{
  "version": "2.1.0",
  "components": [
    {
      "id": "accordion",
      "name": "Accordion",
      "category": "navigation",
      "description": "折りたたみ式コンテンツ。aria-expanded必須。",
      "docPath": "components/accordion.md",
      "anatomy": [
        "container",
        "item",
        "trigger",
        "icon",
        "panel"
      ],
      "variants": [
        {
          "name": "single",
          "class": "border border-slate-200 rounded-lg divide-y divide-slate-200",
          "tailwind": "border border-slate-200 rounded-lg divide-y divide-slate-200"
        },
        {
          "name": "multiple",
          "class": "border border-slate-200 rounded-lg divide-y divide-slate-200",
          "tailwind": "border border-slate-200 rounded-lg divide-y divide-slate-200"
        }
      ],
      "sizes": [],
      "states": [
        "default",
        "expanded",
        "collapsed",
        "hover",
        "focus"
      ],
      "appStatus": "planned",
      "accessibility": {
        "role": "button (trigger)",
        "required": [
          "aria-expanded",
          "aria-controls"
        ],
        "focusRing": "focus-visible:ring-2 focus-visible:ring-primary-500/50"
      },
      "prohibited": [],
      "htmlSample": "<div class=\"border border-slate-200 rounded-lg divide-y divide-slate-200\"><button class=\"w-full flex items-center justify-between py-4 px-6 text-left text-base font-medium text-slate-900 hover:bg-gray-50\" aria-expanded=\"false\" aria-controls=\"panel-1\"><span>セクション</span></button><div id=\"panel-1\" class=\"hidden py-4 px-6 text-body\">内容</div></div>"
    },
    {
      "id": "action-sheet",
      "name": "ActionSheet",
      "category": "feedback",
      "description": "画面下から出るアクション/選択リスト。web の select / dropdown を APP に adapted 変換する際の受け皿（構造的 P0）。destructive アクションは色で区別しラベルでも伝える。",
      "docPath": "components/action-sheet.md",
      "anatomy": [
        "overlay",
        "sheet",
        "title?",
        "action",
        "cancelAction"
      ],
      "variants": [
        {
          "name": "default",
          "class": "",
          "tailwind": ""
        }
      ],
      "sizes": [],
      "states": [
        "default"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "action-sheet",
          "platform": "app",
          "contractVersion": "0.1.0",
          "description": "RN 実装（src/components/ActionSheet.tsx）の具象レシピ（styleRefs 形式）。RN core Modal（transparent + slide）+ 下端 sheet。actions は縦積み（区切り線 border-default）、cancel は下に分離した独立ブロック。destructive アクションは actionTextStyle の色を destructiveColor に差し替える。sheet の下余白は SafeArea を実装が加算する。overlay の黒 50% は token 外の literal（modal と同じ）。",
          "variants": {
            "default": {
              "overlayStyle": {
                "flex": 1,
                "backgroundColor": "rgba(0,0,0,0.5)",
                "justifyContent": "flex-end",
                "padding": {
                  "token": "spacing.2"
                }
              },
              "sheetStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderRadius": {
                  "token": "radius.lg"
                },
                "overflow": "hidden"
              },
              "titleStyle": {
                "fontSize": {
                  "token": "typography.fontSize.sm"
                },
                "color": {
                  "token": "color.semantic.light.text-muted"
                },
                "textAlign": "center",
                "paddingVertical": {
                  "token": "spacing.3"
                }
              },
              "actionStyle": {
                "paddingVertical": {
                  "token": "spacing.4"
                },
                "alignItems": "center",
                "borderTopWidth": 1,
                "borderTopColor": {
                  "token": "color.semantic.light.border-default"
                }
              },
              "actionTextStyle": {
                "fontSize": {
                  "token": "typography.fontSize.lg"
                },
                "color": {
                  "token": "color.primary.500"
                }
              },
              "destructiveTextStyle": {
                "fontSize": {
                  "token": "typography.fontSize.lg"
                },
                "color": {
                  "token": "color.status.danger.base"
                }
              },
              "cancelStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderRadius": {
                  "token": "radius.lg"
                },
                "marginTop": {
                  "token": "spacing.2"
                },
                "paddingVertical": {
                  "token": "spacing.4"
                },
                "alignItems": "center"
              },
              "cancelTextStyle": {
                "fontSize": {
                  "token": "typography.fontSize.lg"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.semibold"
                },
                "color": {
                  "token": "color.primary.500"
                }
              }
            }
          },
          "sizes": {},
          "states": {}
        }
      },
      "accessibility": {
        "role": "dialog",
        "required": [
          "開いている間は背後を操作不可にする（RN: Modal の accessibilityViewIsModal）",
          "閉じる手段を複数持つ（cancelAction 必須 + overlay tap + Android back）",
          "destructive は色だけでなくラベル文言でも破壊的操作と分かるようにする"
        ],
        "focusRing": "N/A"
      },
      "prohibited": [],
      "htmlSample": ""
    },
    {
      "id": "alert",
      "name": "Alert",
      "category": "feedback",
      "description": "インラインアラート通知。Info / Success / Warning / Error の4タイプ。",
      "docPath": "components/alert.md",
      "anatomy": [
        "container",
        "icon",
        "title?",
        "message",
        "closeButton?"
      ],
      "variants": [
        {
          "name": "info",
          "class": "bg-primary-50 border border-primary-200 text-primary-800 rounded-lg p-4",
          "tailwind": "bg-primary-50 border border-primary-200 text-primary-800 rounded-lg p-4"
        },
        {
          "name": "success",
          "class": "bg-emerald-50 border border-emerald-200 text-emerald-800 rounded-lg p-4",
          "tailwind": "bg-emerald-50 border border-emerald-200 text-emerald-800 rounded-lg p-4"
        },
        {
          "name": "warning",
          "class": "bg-amber-50 border border-amber-200 text-amber-800 rounded-lg p-4",
          "tailwind": "bg-amber-50 border border-amber-200 text-amber-800 rounded-lg p-4"
        },
        {
          "name": "error",
          "class": "bg-red-50 border border-red-200 text-red-800 rounded-lg p-4",
          "tailwind": "bg-red-50 border border-red-200 text-red-800 rounded-lg p-4"
        }
      ],
      "sizes": [],
      "states": [
        "default",
        "dismissing"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "alert",
          "platform": "app",
          "contractVersion": "2.0.0",
          "description": "RN 実装（src/components/Alert.tsx）の具象レシピ（styleRefs 形式）。variant = 通知タイプ4種。RN では border を持たず bg subtle + text 色で表現する（status token に border 用の中間色が無いため。COLOR_ONLY_FORBIDDEN は title/message のテキストと icon slot で担保）。dark mode は実装 resolver が status.*.subtle-dark / text-dark 側を解決する（info のみ primary 固定 = dark token が無い既知の割り切り、web と同じ）。icon は ReactNode slot（EmptyState 前例。Icon を差すなら melta-app/icons を利用者が opt-in）。",
          "variants": {
            "info": {
              "containerStyle": {
                "backgroundColor": {
                  "token": "color.primary.50"
                },
                "borderRadius": {
                  "token": "radius.md"
                },
                "padding": {
                  "token": "spacing.4"
                },
                "flexDirection": "row",
                "alignItems": "flex-start",
                "gap": {
                  "token": "spacing.3"
                }
              },
              "titleStyle": {
                "color": {
                  "token": "color.primary.800"
                },
                "fontSize": {
                  "token": "typography.fontSize.base"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.medium"
                }
              },
              "messageStyle": {
                "color": {
                  "token": "color.primary.800"
                },
                "fontSize": {
                  "token": "typography.fontSize.sm"
                }
              }
            },
            "success": {
              "containerStyle": {
                "backgroundColor": {
                  "token": "color.status.success.subtle-light"
                },
                "borderRadius": {
                  "token": "radius.md"
                },
                "padding": {
                  "token": "spacing.4"
                },
                "flexDirection": "row",
                "alignItems": "flex-start",
                "gap": {
                  "token": "spacing.3"
                }
              },
              "titleStyle": {
                "color": {
                  "token": "color.status.success.text-light"
                },
                "fontSize": {
                  "token": "typography.fontSize.base"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.medium"
                }
              },
              "messageStyle": {
                "color": {
                  "token": "color.status.success.text-light"
                },
                "fontSize": {
                  "token": "typography.fontSize.sm"
                }
              }
            },
            "warning": {
              "containerStyle": {
                "backgroundColor": {
                  "token": "color.status.warning.subtle-light"
                },
                "borderRadius": {
                  "token": "radius.md"
                },
                "padding": {
                  "token": "spacing.4"
                },
                "flexDirection": "row",
                "alignItems": "flex-start",
                "gap": {
                  "token": "spacing.3"
                }
              },
              "titleStyle": {
                "color": {
                  "token": "color.status.warning.text-light"
                },
                "fontSize": {
                  "token": "typography.fontSize.base"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.medium"
                }
              },
              "messageStyle": {
                "color": {
                  "token": "color.status.warning.text-light"
                },
                "fontSize": {
                  "token": "typography.fontSize.sm"
                }
              }
            },
            "error": {
              "containerStyle": {
                "backgroundColor": {
                  "token": "color.status.danger.subtle-light"
                },
                "borderRadius": {
                  "token": "radius.md"
                },
                "padding": {
                  "token": "spacing.4"
                },
                "flexDirection": "row",
                "alignItems": "flex-start",
                "gap": {
                  "token": "spacing.3"
                }
              },
              "titleStyle": {
                "color": {
                  "token": "color.status.danger.text-light"
                },
                "fontSize": {
                  "token": "typography.fontSize.base"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.medium"
                }
              },
              "messageStyle": {
                "color": {
                  "token": "color.status.danger.text-light"
                },
                "fontSize": {
                  "token": "typography.fontSize.sm"
                }
              }
            }
          },
          "sizes": {},
          "states": {}
        }
      },
      "accessibility": {
        "role": "alert (error/warning) / status (info/success)",
        "required": [
          "aria-live"
        ],
        "focusRing": "N/A"
      },
      "prohibited": [
        "色だけで情報伝達すると色覚多様性への非対応になる",
        "Alert含め全コンポーネントで禁止",
        "AI生成UIの典型パターン。装飾過剰で汎用性が低い"
      ],
      "htmlSample": "<div role=\"alert\" aria-live=\"assertive\" class=\"bg-red-50 border border-red-200 text-red-800 rounded-lg p-4 flex items-start gap-3\"><div><h3 class=\"font-medium\">エラー</h3><p class=\"text-sm mt-1\">もう一度お試しください</p></div></div>"
    },
    {
      "id": "avatar",
      "name": "Avatar",
      "category": "data-display",
      "description": "ユーザーアバター。Image / Initials / Status / Group。",
      "docPath": "components/avatar.md",
      "anatomy": [
        "container",
        "image?",
        "initials?",
        "statusDot?"
      ],
      "variants": [
        {
          "name": "image",
          "class": "w-10 h-10 rounded-full object-cover",
          "tailwind": "w-10 h-10 rounded-full object-cover"
        },
        {
          "name": "initials",
          "class": "w-10 h-10 rounded-full bg-primary-50 text-primary-600 font-medium inline-flex items-center justify-center text-sm",
          "tailwind": "w-10 h-10 rounded-full bg-primary-50 text-primary-600 font-medium inline-flex items-center justify-center text-sm"
        },
        {
          "name": "group",
          "class": "flex -space-x-2",
          "tailwind": "flex -space-x-2"
        }
      ],
      "sizes": [
        {
          "name": "small",
          "class": "w-8 h-8",
          "tailwind": "w-8 h-8",
          "height": "32px"
        },
        {
          "name": "medium",
          "class": "w-10 h-10",
          "tailwind": "w-10 h-10",
          "height": "40px"
        },
        {
          "name": "large",
          "class": "w-12 h-12",
          "tailwind": "w-12 h-12",
          "height": "48px"
        }
      ],
      "states": [
        "default",
        "online",
        "away",
        "offline"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "avatar",
          "platform": "app",
          "contractVersion": "2.0.0",
          "description": "RN 実装（src/components/Avatar.tsx）の具象レシピ（styleRefs 形式）。variant=image は RN Image を radius.full で clip、variant=initials は bg primary.50 + text primary.600（fontSize は sizes 軸で xs/sm/base に段階）、variant=group は AvatarGroup（2枚目以降を overlapStyle の負 margin = -spacing.2 相当で重ねる。負値 token が無いため literal -8）。states の online/away/offline は statusDot（右下配置、bg-surface の ring）で表現し、dot 径は sizes 軸の dotSize。",
          "variants": {
            "image": {
              "style": {
                "borderRadius": {
                  "token": "radius.full"
                },
                "overflow": "hidden"
              }
            },
            "initials": {
              "style": {
                "borderRadius": {
                  "token": "radius.full"
                },
                "backgroundColor": {
                  "token": "color.primary.50"
                },
                "alignItems": "center",
                "justifyContent": "center"
              },
              "textStyle": {
                "color": {
                  "token": "color.primary.600"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.medium"
                }
              }
            },
            "group": {
              "style": {
                "flexDirection": "row"
              },
              "overlapStyle": {
                "marginLeft": -8
              }
            }
          },
          "sizes": {
            "small": {
              "style": {
                "width": 32,
                "height": 32
              },
              "textStyle": {
                "fontSize": {
                  "token": "typography.fontSize.xs"
                }
              },
              "dotSize": 8
            },
            "medium": {
              "style": {
                "width": 40,
                "height": 40
              },
              "textStyle": {
                "fontSize": {
                  "token": "typography.fontSize.sm"
                }
              },
              "dotSize": 10
            },
            "large": {
              "style": {
                "width": 48,
                "height": 48
              },
              "textStyle": {
                "fontSize": {
                  "token": "typography.fontSize.base"
                }
              },
              "dotSize": 12
            }
          },
          "states": {
            "online": {
              "dotStyle": {
                "backgroundColor": {
                  "token": "color.status.success.base"
                },
                "borderColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderWidth": 2
              }
            },
            "away": {
              "dotStyle": {
                "backgroundColor": {
                  "token": "color.status.warning.base"
                },
                "borderColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderWidth": 2
              }
            },
            "offline": {
              "dotStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.border-strong"
                },
                "borderColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderWidth": 2
              }
            }
          }
        }
      },
      "accessibility": {
        "role": "img",
        "required": [
          "aria-label=\"名前\""
        ],
        "focusRing": "N/A"
      },
      "prohibited": [],
      "htmlSample": "<div class=\"w-10 h-10 rounded-full bg-primary-50 text-primary-600 font-medium inline-flex items-center justify-center text-sm\" role=\"img\" aria-label=\"田中太郎\">田中</div>"
    },
    {
      "id": "badge",
      "name": "Badge",
      "category": "data-display",
      "description": "ステータス・カウント表示。Status / Dot / Count / Outline の4バリエーション。",
      "docPath": "components/badge.md",
      "anatomy": [
        "container",
        "dotIndicator?",
        "label"
      ],
      "variants": [
        {
          "name": "neutral",
          "class": "inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium bg-slate-100 text-slate-700",
          "tailwind": "inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium bg-slate-100 text-slate-700"
        },
        {
          "name": "success",
          "class": "inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium bg-emerald-50 text-emerald-700",
          "tailwind": "inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium bg-emerald-50 text-emerald-700"
        },
        {
          "name": "warning",
          "class": "inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium bg-amber-50 text-amber-700",
          "tailwind": "inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium bg-amber-50 text-amber-700"
        },
        {
          "name": "danger",
          "class": "inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium bg-red-50 text-red-700",
          "tailwind": "inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium bg-red-50 text-red-700"
        },
        {
          "name": "accent",
          "class": "inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium bg-primary-50 text-primary-700",
          "tailwind": "inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium bg-primary-50 text-primary-700"
        }
      ],
      "sizes": [],
      "states": [
        "default"
      ],
      "appStatus": "planned",
      "accessibility": {
        "role": "status",
        "required": [],
        "focusRing": "N/A"
      },
      "prohibited": [
        "色だけで情報伝達すると色覚多様性への非対応になる",
        "Badge はステータス表示、Tag はユーザー管理メタデータ"
      ],
      "htmlSample": "<span class=\"inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium bg-slate-100 text-slate-700\">未着手</span>"
    },
    {
      "id": "bottom-sheet",
      "name": "BottomSheet",
      "category": "feedback",
      "description": "画面下から出る汎用シート container（content は自由 slot）。フィルタ・詳細・複雑な選択 UI の受け皿。ActionSheet がリスト特化なのに対しこちらは容器。",
      "docPath": "components/bottom-sheet.md",
      "anatomy": [
        "overlay",
        "sheet",
        "grabber",
        "title?",
        "content"
      ],
      "variants": [
        {
          "name": "default",
          "class": "",
          "tailwind": ""
        }
      ],
      "sizes": [],
      "states": [
        "default"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "bottom-sheet",
          "platform": "app",
          "contractVersion": "0.1.0",
          "description": "RN 実装（src/components/BottomSheet.tsx）の具象レシピ（styleRefs 形式）。RN core Modal（transparent + slide）+ 下端 sheet（上角のみ radius）。grabber は装飾バー（a11y ツリーから除外）。content は自由 slot で padding のみ供給。スワイプで閉じるジェスチャは Phase 外（overlay tap + Android back で閉じる）。sheet の下余白は SafeArea を実装が加算する。",
          "variants": {
            "default": {
              "overlayStyle": {
                "flex": 1,
                "backgroundColor": "rgba(0,0,0,0.5)",
                "justifyContent": "flex-end"
              },
              "sheetStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderTopLeftRadius": {
                  "token": "radius.lg"
                },
                "borderTopRightRadius": {
                  "token": "radius.lg"
                }
              },
              "grabberStyle": {
                "width": 36,
                "height": 4,
                "borderRadius": {
                  "token": "radius.full"
                },
                "backgroundColor": {
                  "token": "color.semantic.light.border-strong"
                },
                "alignSelf": "center",
                "marginTop": {
                  "token": "spacing.2"
                }
              },
              "titleStyle": {
                "fontSize": {
                  "token": "typography.fontSize.lg"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.bold"
                },
                "color": {
                  "token": "color.semantic.light.text-heading"
                },
                "paddingHorizontal": {
                  "token": "spacing.4"
                },
                "paddingTop": {
                  "token": "spacing.4"
                }
              },
              "contentStyle": {
                "padding": {
                  "token": "spacing.4"
                }
              }
            }
          },
          "sizes": {},
          "states": {}
        }
      },
      "accessibility": {
        "role": "dialog",
        "required": [
          "開いている間は背後を操作不可にする（RN: Modal の accessibilityViewIsModal）",
          "閉じる手段を複数持つ（overlay tap + Android back。title があれば閉じるボタンを推奨）"
        ],
        "focusRing": "N/A"
      },
      "prohibited": [],
      "htmlSample": ""
    },
    {
      "id": "breadcrumb",
      "name": "Breadcrumb",
      "category": "navigation",
      "description": "階層パスナビゲーション。ol要素で構造化。",
      "docPath": "components/breadcrumb.md",
      "anatomy": [
        "nav",
        "orderedList",
        "linkItem",
        "separator",
        "currentPage",
        "ellipsis?",
        "homeIcon?"
      ],
      "variants": [
        {
          "name": "text-separator",
          "class": "flex items-center gap-2 text-sm",
          "tailwind": "flex items-center gap-2 text-sm"
        },
        {
          "name": "chevron-separator",
          "class": "flex items-center gap-2 text-sm",
          "tailwind": "flex items-center gap-2 text-sm"
        }
      ],
      "sizes": [],
      "states": [
        "default",
        "hover"
      ],
      "appStatus": "not-planned",
      "appNote": "RN 主要ライブラリ提供 0/5。Apple HIG が multisegment breadcrumb を明示的に否定。back ボタン + nav bar タイトルで代替",
      "accessibility": {
        "role": "navigation",
        "required": [
          "aria-label=\"パンくずリスト\"",
          "aria-current=\"page\""
        ],
        "focusRing": "focus:ring-2 focus:ring-primary-500/50"
      },
      "prohibited": [
        "スクリーンリーダーが現在ページを識別できない",
        "<nav>（および role=\"navigation\"）にアクセシブルネームが無いと、スクリーンリーダーのランドマーク一覧で複数のナビゲーションを区別できない。nav が 1 つしか無い画面でも、後から増えたときに無名ランドマークが並ぶため常に付与する"
      ],
      "htmlSample": "<nav aria-label=\"パンくずリスト\"><ol class=\"flex items-center gap-2 text-sm\"><li><a href=\"#\" class=\"text-slate-500 hover:text-slate-700\">ホーム</a></li><li class=\"text-slate-500\">/</li><li><span class=\"text-slate-900 font-medium\" aria-current=\"page\">詳細</span></li></ol></nav>"
    },
    {
      "id": "button",
      "name": "Button",
      "category": "form-input",
      "description": "CTA / secondary / icon button。3階層ヒエラルキー。",
      "docPath": "components/button.md",
      "anatomy": [
        "leadingIcon?",
        "label",
        "trailingIcon?"
      ],
      "variants": [
        {
          "name": "contained",
          "class": "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 focus:outline-none focus:ring-2 focus:ring-primary-500/50 transition-colors cursor-pointer",
          "tailwind": "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 focus:outline-none focus:ring-2 focus:ring-primary-500/50 transition-colors cursor-pointer"
        },
        {
          "name": "outlined",
          "class": "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 focus:outline-none focus:ring-2 focus:ring-primary-500/50 transition-colors cursor-pointer",
          "tailwind": "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 focus:outline-none focus:ring-2 focus:ring-primary-500/50 transition-colors cursor-pointer"
        },
        {
          "name": "brand-outline",
          "class": "inline-flex items-center justify-center gap-2 h-10 px-4 text-[1rem] font-medium text-primary-500 bg-white border border-primary-500 rounded-lg hover:bg-primary-50 focus:outline-none focus:ring-2 focus:ring-primary-500/50 transition-colors cursor-pointer",
          "tailwind": "inline-flex items-center justify-center gap-2 h-10 px-4 text-[1rem] font-medium text-primary-500 bg-white border border-primary-500 rounded-lg hover:bg-primary-50 focus:outline-none focus:ring-2 focus:ring-primary-500/50 transition-colors cursor-pointer"
        },
        {
          "name": "neutral",
          "class": "inline-flex items-center justify-center gap-2 h-10 px-4 text-[1rem] font-medium bg-slate-100 text-slate-700 rounded-lg hover:bg-slate-200 transition-colors cursor-pointer",
          "tailwind": "inline-flex items-center justify-center gap-2 h-10 px-4 text-[1rem] font-medium bg-slate-100 text-slate-700 rounded-lg hover:bg-slate-200 transition-colors cursor-pointer"
        },
        {
          "name": "lighted",
          "class": "inline-flex items-center justify-center gap-2 h-10 px-4 text-[1rem] font-medium bg-primary-50 text-primary-600 rounded-lg hover:bg-primary-100 transition-colors cursor-pointer",
          "tailwind": "inline-flex items-center justify-center gap-2 h-10 px-4 text-[1rem] font-medium bg-primary-50 text-primary-600 rounded-lg hover:bg-primary-100 transition-colors cursor-pointer"
        },
        {
          "name": "danger",
          "class": "inline-flex items-center justify-center gap-2 h-10 px-4 text-[1rem] font-medium bg-red-600 text-white rounded-lg hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-600/50 transition-colors cursor-pointer",
          "tailwind": "inline-flex items-center justify-center gap-2 h-10 px-4 text-[1rem] font-medium bg-red-600 text-white rounded-lg hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-600/50 transition-colors cursor-pointer"
        },
        {
          "name": "subtle",
          "class": "inline-flex items-center justify-center gap-2 h-10 px-4 text-[1rem] font-medium text-slate-700 rounded-lg hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-primary-500/50 transition-colors cursor-pointer",
          "tailwind": "inline-flex items-center justify-center gap-2 h-10 px-4 text-[1rem] font-medium text-slate-700 rounded-lg hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-primary-500/50 transition-colors cursor-pointer"
        }
      ],
      "sizes": [
        {
          "name": "small",
          "class": "h-8 px-3 text-[0.875rem] relative after:absolute after:inset-x-0 after:top-1/2 after:h-11 after:-translate-y-1/2",
          "tailwind": "h-8 px-3 text-[0.875rem] relative after:absolute after:inset-x-0 after:top-1/2 after:h-11 after:-translate-y-1/2",
          "height": "32px"
        },
        {
          "name": "medium",
          "class": "h-10 px-4 text-[1rem] relative after:absolute after:inset-x-0 after:top-1/2 after:h-11 after:-translate-y-1/2",
          "tailwind": "h-10 px-4 text-[1rem] relative after:absolute after:inset-x-0 after:top-1/2 after:h-11 after:-translate-y-1/2",
          "height": "40px"
        },
        {
          "name": "large",
          "class": "h-12 px-6 text-[1rem]",
          "tailwind": "h-12 px-6 text-[1rem]",
          "height": "48px"
        }
      ],
      "iconButton": [
        {
          "name": "small",
          "class": "w-8 h-8",
          "tailwind": "w-8 h-8",
          "icon": "w-4 h-4"
        },
        {
          "name": "medium",
          "class": "w-10 h-10",
          "tailwind": "w-10 h-10",
          "icon": "w-5 h-5"
        },
        {
          "name": "large",
          "class": "w-12 h-12",
          "tailwind": "w-12 h-12",
          "icon": "w-5 h-5"
        }
      ],
      "iconTextPadding": [
        {
          "name": "small",
          "class": "pl-2.5 pr-3",
          "tailwind": "pl-2.5 pr-3"
        },
        {
          "name": "medium",
          "class": "pl-3 pr-4",
          "tailwind": "pl-3 pr-4"
        },
        {
          "name": "large",
          "class": "pl-5 pr-6",
          "tailwind": "pl-5 pr-6"
        }
      ],
      "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 は効かせない。",
          "class": "opacity-50 cursor-not-allowed pointer-events-none"
        },
        "loading": {
          "description": "非同期処理中。全 variant 共通。",
          "tailwind": "opacity-70 cursor-wait pointer-events-none",
          "ariaChanges": "aria-busy=\"true\" + disabled。",
          "htmlNote": "label 前にスピナーを prepend（スピナーのクラスは htmlSample/anatomy 側で表現。htmlNote は prose でリンタ非対象）。",
          "class": "opacity-70 cursor-wait pointer-events-none"
        }
      },
      "platformSemantics": {
        "hover": "web のみ。app には hover が存在せず pressed が対応する（recipes/app の pressedStyle が写像先）",
        "elevation": "web は box-shadow、app は iOS shadow* + Android elevation に分解される。トークン（elevation.*）は共有",
        "touchTarget": "app はタッチターゲット最小 44pt を size 側で保証する。web も after: 擬似要素拡張で実効タップ領域 44px を保証する（見た目の高さは h-8/h-10 のまま。BTN_MIN_TAP_TARGET が検知）。縦積みで gap-2（8px）以下の隣接は判定が重なるため拡張を外してよい（DOM 後勝ち）。icon-only は幅拡張が別式のため第一弾対象外",
        "focus": "web は focus ring クラス、app は FocusRing overlay コンポーネント（キーボード/TV フォーカス時）"
      },
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "button",
          "platform": "app",
          "contractVersion": "2.1.0",
          "description": "RN 実装（src/primitives/Button.tsx）の具象レシピ（styleRefs 形式）。pressedStyle は Pressable pressed 時差分（web hover 対応）。contained/brand-outline 以外の pressedBg は contract に native token が無いため実装が hover tailwind と同値のトークンで近似したもの。focus は FocusRing overlay（絶対配置 inset -3 / borderWidth 2 / color.primary.500 / borderRadius = radius.md + 3）で表現し element style には現れない。gap は icon-label 間（spacing.2）。ラベル付きの sizes は height ではなく minHeight（RN の fontScale でテキストが拡大したときにラベルがクリップされないための下限。視覚寸法は既定 fontScale=1 で従来と同じ）。iconOnly 時は paddingHorizontal の代わりに iconOnlyWidth × iconOnlyHeight の固定正方形（ラベルを持たないので拡大不要。minHeight にすると縦だけ伸びて正方形が崩れる）。",
          "variants": {
            "contained": {
              "style": {
                "backgroundColor": {
                  "token": "color.primary.500"
                },
                "borderRadius": {
                  "token": "radius.md"
                },
                "gap": {
                  "token": "spacing.2"
                }
              },
              "pressedStyle": {
                "backgroundColor": {
                  "token": "color.primary.700"
                }
              },
              "textStyle": {
                "color": {
                  "token": "color.semantic.light.text-on-accent"
                }
              }
            },
            "outlined": {
              "style": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderWidth": 1,
                "borderColor": {
                  "token": "color.semantic.light.border-default"
                },
                "borderRadius": {
                  "token": "radius.md"
                },
                "gap": {
                  "token": "spacing.2"
                }
              },
              "pressedStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface-alt"
                }
              },
              "textStyle": {
                "color": {
                  "token": "color.semantic.light.text-default"
                }
              }
            },
            "brand-outline": {
              "style": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderWidth": 1,
                "borderColor": {
                  "token": "color.primary.500"
                },
                "borderRadius": {
                  "token": "radius.md"
                },
                "gap": {
                  "token": "spacing.2"
                }
              },
              "pressedStyle": {
                "backgroundColor": {
                  "token": "color.primary.50"
                }
              },
              "textStyle": {
                "color": {
                  "token": "color.primary.500"
                }
              }
            },
            "neutral": {
              "style": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface-alt"
                },
                "borderRadius": {
                  "token": "radius.md"
                },
                "gap": {
                  "token": "spacing.2"
                }
              },
              "pressedStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.border-default"
                }
              },
              "textStyle": {
                "color": {
                  "token": "color.semantic.light.text-default"
                }
              }
            },
            "lighted": {
              "style": {
                "backgroundColor": {
                  "token": "color.primary.50"
                },
                "borderRadius": {
                  "token": "radius.md"
                },
                "gap": {
                  "token": "spacing.2"
                }
              },
              "pressedStyle": {
                "backgroundColor": {
                  "token": "color.primary.100"
                }
              },
              "textStyle": {
                "color": {
                  "token": "color.primary.600"
                }
              }
            },
            "danger": {
              "style": {
                "backgroundColor": {
                  "token": "color.status.danger.base"
                },
                "borderRadius": {
                  "token": "radius.md"
                },
                "gap": {
                  "token": "spacing.2"
                }
              },
              "pressedStyle": {
                "backgroundColor": {
                  "token": "color.status.danger.text-light"
                }
              },
              "textStyle": {
                "color": {
                  "token": "color.semantic.light.text-on-accent"
                }
              }
            },
            "subtle": {
              "style": {
                "backgroundColor": "transparent",
                "borderRadius": {
                  "token": "radius.md"
                },
                "gap": {
                  "token": "spacing.2"
                }
              },
              "pressedStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface-alt"
                }
              },
              "textStyle": {
                "color": {
                  "token": "color.semantic.light.text-default"
                }
              }
            }
          },
          "sizes": {
            "small": {
              "minHeight": 32,
              "paddingHorizontal": {
                "token": "spacing.3"
              },
              "fontSize": {
                "token": "typography.fontSize.sm"
              },
              "iconOnlyWidth": 32,
              "iconOnlyHeight": 32
            },
            "medium": {
              "minHeight": 40,
              "paddingHorizontal": {
                "token": "spacing.4"
              },
              "fontSize": {
                "token": "typography.fontSize.base"
              },
              "iconOnlyWidth": 40,
              "iconOnlyHeight": 40
            },
            "large": {
              "minHeight": 48,
              "paddingHorizontal": {
                "token": "spacing.6"
              },
              "fontSize": {
                "token": "typography.fontSize.base"
              },
              "iconOnlyWidth": 48,
              "iconOnlyHeight": 48
            }
          },
          "states": {
            "disabled": {
              "style": {
                "opacity": 0.5
              }
            },
            "loading": {
              "style": {
                "opacity": 0.5
              }
            },
            "focus": {
              "style": {
                "borderWidth": 2,
                "borderColor": {
                  "token": "color.primary.500"
                }
              }
            }
          }
        }
      },
      "accessibility": {
        "role": "button",
        "required": [
          "type attribute",
          "focus-visible ring",
          "aria-label for icon-only"
        ],
        "focusRing": "focus:ring-2 focus:ring-primary-500/50"
      },
      "prohibited": [
        "タップターゲットが小さすぎる",
        "操作内容がスクリーンリーダーに伝わらない",
        "高さ 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）実装形",
        "重要度の区別がつかない（Neutralのみ例外）",
        "トグル状態の対比がないと意味不明"
      ],
      "htmlSample": {
        "contained": "<button class=\"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 focus:outline-none focus:ring-2 focus:ring-primary-500/50 transition-colors cursor-pointer relative after:absolute after:inset-x-0 after:top-1/2 after:h-11 after:-translate-y-1/2\">保存</button>",
        "outlined": "<button class=\"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 focus:outline-none focus:ring-2 focus:ring-primary-500/50 transition-colors cursor-pointer relative after:absolute after:inset-x-0 after:top-1/2 after:h-11 after:-translate-y-1/2\">キャンセル</button>",
        "brand-outline": "<button class=\"inline-flex items-center justify-center gap-2 h-10 px-4 text-[1rem] font-medium text-primary-500 bg-white border border-primary-500 rounded-lg hover:bg-primary-50 focus:outline-none focus:ring-2 focus:ring-primary-500/50 transition-colors cursor-pointer relative after:absolute after:inset-x-0 after:top-1/2 after:h-11 after:-translate-y-1/2\">フォロー</button>",
        "iconOnly": "<button class=\"w-10 h-10 inline-flex items-center justify-center rounded-lg hover:bg-gray-50 cursor-pointer\" aria-label=\"閉じる\"><svg class=\"w-5 h-5 fill-current text-body\" viewBox=\"0 0 24 24\"><use href=\"assets/icons/Close.svg#icon\"/></svg></button>"
      }
    },
    {
      "id": "card",
      "name": "Card",
      "category": "data-display",
      "description": "コンテンツコンテナ。Basic / Metrics / Media / Action / Link の5バリエーション。",
      "docPath": "components/card.md",
      "anatomy": [
        "header?",
        "body",
        "footer?",
        "media?"
      ],
      "variants": [
        {
          "name": "basic",
          "class": "bg-white rounded-xl border border-slate-200 p-6 shadow-sm",
          "tailwind": "bg-white rounded-xl border border-slate-200 p-6 shadow-sm"
        },
        {
          "name": "media",
          "class": "bg-white rounded-xl border border-slate-200 overflow-hidden shadow-sm",
          "tailwind": "bg-white rounded-xl border border-slate-200 overflow-hidden shadow-sm"
        },
        {
          "name": "action",
          "class": "bg-white rounded-xl border border-slate-200 p-6 shadow-sm hover:shadow-md transition-shadow",
          "tailwind": "bg-white rounded-xl border border-slate-200 p-6 shadow-sm hover:shadow-md transition-shadow"
        },
        {
          "name": "link",
          "class": "bg-white rounded-xl border border-slate-200 p-6 shadow-sm hover:border-primary-300 transition-all",
          "tailwind": "bg-white rounded-xl border border-slate-200 p-6 shadow-sm hover:border-primary-300 transition-all"
        }
      ],
      "sizes": [],
      "states": [
        "default",
        "hover",
        "focus-within"
      ],
      "platformSemantics": {
        "elevation": "APP は製品テーマに合わせて影なしを明示選択できる。省略時は従来の影を維持する。影なし時は押下中も elevation.none のみを読み、sm/md を参照しない。影で押下を表せないため、action/link の押下は枠を primary-300 に変えて表す（web では link の hover に使う色。APP の影なしでは action の押下にも使う。recipe の elevationOptions.none.pressedStyle）。背景・余白と primaryAction の操作契約は維持する。"
      },
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "card",
          "platform": "app",
          "contractVersion": "2.1.0",
          "description": "RN 実装（src/components/Card.tsx）の具象レシピ（styleRefs 形式）。elevation は iOS shadow* + Android elevation の複合トークン（theme.elevation[key] を spread）。action/link は Pressable で pressed 時に elevation sm→md（contract hover → pressed mapping）。media は iOS の影と overflow:hidden の同居不可のため外枠に overflow を付けず、内側 clip View（borderRadius radius.lg + overflow hidden）でクリップし body のみ bodyStyle の padding を持つ。focus ring は Card では描かず、フォーカスを受ける primaryAction 側が持つ。contract の focus-within は RN 非サポートとして Phase1 drop 済みのため states は空。 elevation prop は default（省略時）または none。none は全状態で elevation.none を使う。合成順は variant の style → variant の pressedStyle → elevationOptions の style / pressedStyle（後勝ち）。elevationOptions の pressedStyle は pressedStyle を持つ variant（action/link）にだけ適用する。",
          "variants": {
            "basic": {
              "style": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderRadius": {
                  "token": "radius.lg"
                },
                "borderWidth": 1,
                "borderColor": {
                  "token": "color.semantic.light.border-default"
                },
                "padding": {
                  "token": "spacing.6"
                },
                "elevation": {
                  "token": "elevation.sm"
                }
              }
            },
            "media": {
              "style": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderRadius": {
                  "token": "radius.lg"
                },
                "borderWidth": 1,
                "borderColor": {
                  "token": "color.semantic.light.border-default"
                },
                "elevation": {
                  "token": "elevation.sm"
                }
              },
              "bodyStyle": {
                "padding": {
                  "token": "spacing.6"
                }
              }
            },
            "action": {
              "style": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderRadius": {
                  "token": "radius.lg"
                },
                "borderWidth": 1,
                "borderColor": {
                  "token": "color.semantic.light.border-default"
                },
                "padding": {
                  "token": "spacing.6"
                },
                "elevation": {
                  "token": "elevation.sm"
                }
              },
              "pressedStyle": {
                "elevation": {
                  "token": "elevation.md"
                }
              }
            },
            "link": {
              "style": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderRadius": {
                  "token": "radius.lg"
                },
                "borderWidth": 1,
                "borderColor": {
                  "token": "color.semantic.light.border-default"
                },
                "padding": {
                  "token": "spacing.6"
                },
                "elevation": {
                  "token": "elevation.sm"
                }
              },
              "pressedStyle": {
                "elevation": {
                  "token": "elevation.md"
                }
              }
            }
          },
          "sizes": {},
          "states": {},
          "elevationOptions": {
            "default": {
              "description": "既存variant/stateのelevationを維持"
            },
            "none": {
              "description": "影なし。action/link の押下は影の代わりに枠を primary-300 へ変えて表す（web の link hover と同じ色。Dark では bg-surface に対し 8.46:1 と focus ring の primary-500 より目立つが、web の hover と同値にそろえる）",
              "style": {
                "elevation": {
                  "token": "elevation.none"
                }
              },
              "pressedStyle": {
                "elevation": {
                  "token": "elevation.none"
                },
                "borderColor": {
                  "token": "color.primary.300"
                }
              }
            }
          }
        }
      },
      "accessibility": {
        "role": "article",
        "required": [
          "action / link は主アクションの操作要素（button / a）を内包する。カード面自体を操作要素にしない（RN: 面に accessibilityRole=\"button\" を付けない）",
          "面のクリック・タップはポインタ向けの近道。キーボード / スクリーンリーダーからの到達は内包した操作要素が担う",
          "内包する操作要素が2つ以上ある場合、面のクリックはそのうち1つ（主アクション）と同じ遷移先にする"
        ],
        "focusRing": "focus-within:ring-2 focus-within:ring-primary-500/50"
      },
      "prohibited": [
        "UIの統一感を損なう",
        "影が強すぎてノイズになる",
        "影が強すぎてノイズになる",
        "コンテンツが窮屈になる",
        "AI生成UIの典型パターン。装飾過剰で汎用性が低い",
        "Alert含め全コンポーネントで禁止"
      ],
      "htmlSample": {
        "basic": "<div class=\"bg-white rounded-xl border border-slate-200 p-6 shadow-sm\"><h3 class=\"text-lg font-bold text-slate-900\">タイトル</h3><p class=\"text-base text-body mt-2\">内容</p></div>",
        "media": "<div class=\"bg-white rounded-xl border border-slate-200 overflow-hidden shadow-sm\"><img src=\"...\" alt=\"\" class=\"w-full h-48 object-cover\"><div class=\"p-6\"><h3 class=\"text-lg font-bold text-slate-900\">タイトル</h3></div></div>"
      }
    },
    {
      "id": "checkbox",
      "name": "Checkbox",
      "category": "form-input",
      "description": "複数選択フォームコントロール。CSS 18px サイズ。",
      "docPath": "components/checkbox.md",
      "anatomy": [
        "box",
        "checkmark?",
        "indeterminateMark?",
        "label",
        "groupLabel?",
        "helperText?",
        "errorText?"
      ],
      "variants": [
        {
          "name": "default",
          "class": "w-4 h-4 accent-primary-500 cursor-pointer",
          "tailwind": "w-4 h-4 accent-primary-500 cursor-pointer"
        },
        {
          "name": "disabled",
          "class": "w-4 h-4 opacity-50 cursor-not-allowed",
          "tailwind": "w-4 h-4 opacity-50 cursor-not-allowed"
        },
        {
          "name": "indeterminate",
          "class": "w-4 h-4 accent-primary-500 cursor-pointer",
          "tailwind": "w-4 h-4 accent-primary-500 cursor-pointer"
        }
      ],
      "sizes": [],
      "states": [
        "default",
        "checked",
        "unchecked",
        "indeterminate",
        "disabled",
        "error",
        "focus"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "checkbox",
          "platform": "app",
          "contractVersion": "2.0.0",
          "description": "RN 実装（src/components/Checkbox.tsx）の具象レシピ（styleRefs 形式）。RN にネイティブ checkbox が無いため Pressable + 描画で実装する。checkmark は rotate した View の L 字 border（react-native-svg 非依存 = 本体エントリの依存ゼロ維持）、indeterminate variant は横棒。box は 20px（web の 16px より大きいのはタッチ前提、実タッチ標的は行の minHeight で 44 を確保 — 行は背景を持たないため hitSlop でなく寸法で満たす。A11Y_MIN_TAP_TARGET_44 / 縦積みの隣接行と当たり判定が重ならない）。checked/error は state 差分、labelStyle は variant 非依存の共通部として default にのみ載せる。markColor は checked 時の checkmark / indeterminate の横棒の色。",
          "variants": {
            "default": {
              "boxStyle": {
                "width": 20,
                "height": 20,
                "borderWidth": 2,
                "borderColor": {
                  "token": "color.semantic.light.border-strong"
                },
                "borderRadius": {
                  "token": "radius.sm"
                },
                "backgroundColor": {
                  "token": "color.semantic.light.input-bg"
                }
              },
              "labelStyle": {
                "fontSize": {
                  "token": "typography.fontSize.base"
                },
                "color": {
                  "token": "color.semantic.light.text-default"
                }
              },
              "gap": {
                "token": "spacing.2"
              }
            },
            "indeterminate": {
              "boxStyle": {
                "width": 20,
                "height": 20,
                "borderWidth": 2,
                "borderColor": {
                  "token": "color.primary.500"
                },
                "borderRadius": {
                  "token": "radius.sm"
                },
                "backgroundColor": {
                  "token": "color.primary.500"
                }
              }
            },
            "disabled": {
              "style": {
                "opacity": 0.5
              }
            }
          },
          "sizes": {},
          "states": {
            "checked": {
              "boxStyle": {
                "backgroundColor": {
                  "token": "color.primary.500"
                },
                "borderColor": {
                  "token": "color.primary.500"
                }
              },
              "markColor": {
                "token": "color.semantic.light.text-on-accent"
              }
            },
            "unchecked": {},
            "error": {
              "boxStyle": {
                "borderColor": {
                  "token": "color.status.danger.base"
                }
              }
            }
          }
        }
      },
      "accessibility": {
        "role": "checkbox (native <input type=\"checkbox\">)",
        "required": [
          "label association"
        ],
        "focusRing": "focus:ring-2 focus:ring-primary-500/50"
      },
      "prohibited": [
        "スクリーンリーダーが目的を読み上げられない"
      ],
      "htmlSample": "<label class=\"flex items-center gap-2 cursor-pointer\"><input type=\"checkbox\" class=\"w-4 h-4 accent-primary-500\"><span class=\"text-base text-body\">同意します</span></label>"
    },
    {
      "id": "copy-button",
      "name": "CopyButton",
      "category": "feedback",
      "description": "クリップボードコピー + pop アニメーション付きアイコンボタン。",
      "docPath": "components/copy-button.md",
      "anatomy": [
        "container",
        "copyIcon",
        "checkIcon"
      ],
      "variants": [
        {
          "name": "outlined",
          "class": "bg-white border border-slate-200 inline-flex items-center justify-center cursor-pointer",
          "tailwind": "bg-white border border-slate-200 inline-flex items-center justify-center cursor-pointer"
        },
        {
          "name": "subtle",
          "class": "bg-transparent inline-flex items-center justify-center cursor-pointer hover:bg-gray-50",
          "tailwind": "bg-transparent inline-flex items-center justify-center cursor-pointer hover:bg-gray-50"
        }
      ],
      "sizes": [
        {
          "name": "large",
          "class": "w-12 h-12 p-3 rounded-2xl",
          "tailwind": "w-12 h-12 p-3 rounded-2xl",
          "height": "48px"
        },
        {
          "name": "medium",
          "class": "w-10 h-10 p-2.5 rounded-xl",
          "tailwind": "w-10 h-10 p-2.5 rounded-xl",
          "height": "40px"
        },
        {
          "name": "small",
          "class": "w-8 h-8 p-2 rounded-lg",
          "tailwind": "w-8 h-8 p-2 rounded-lg",
          "height": "32px"
        }
      ],
      "states": [
        "default",
        "hover",
        "active",
        "copied",
        "focus"
      ],
      "appStatus": "not-planned",
      "appNote": "DS プリミティブでなくアプリ層のコンポジット（button + clipboard + toast）",
      "accessibility": {
        "role": "button",
        "required": [
          "aria-label=\"コピー\"",
          "aria-label update on copied"
        ],
        "focusRing": "focus-visible:ring-2 focus-visible:ring-primary-500/50"
      },
      "prohibited": [
        "操作内容がスクリーンリーダーに伝わらない"
      ],
      "htmlSample": "<button class=\"copy-button\" aria-label=\"コピー\"><svg class=\"cb-icon cb-icon-copy w-5 h-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"3\" y=\"3\" width=\"13\" height=\"13\" rx=\"2.5\"/><path d=\"M8 21h11a2 2 0 0 0 2-2v-11\"/></svg><svg class=\"cb-icon cb-icon-check w-5 h-5\" viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"11\" fill=\"currentColor\" opacity=\"0.15\"/><polyline points=\"7 12.5 10.5 16 17 9\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg></button>"
    },
    {
      "id": "datepicker",
      "name": "DatePicker",
      "category": "form-input",
      "description": "日付選択コンポーネント。カレンダーポップアップ + キーボードナビ。",
      "docPath": "components/datepicker.md",
      "anatomy": [
        "trigger",
        "hiddenInput",
        "calendarPopup",
        "monthHeader",
        "dayOfWeekHeader",
        "dayGrid",
        "todayButton?"
      ],
      "variants": [
        {
          "name": "trigger",
          "class": "w-full flex items-center gap-2 rounded-lg border border-slate-300 bg-white px-3 py-2 text-base",
          "tailwind": "w-full flex items-center gap-2 rounded-lg border border-slate-300 bg-white px-3 py-2 text-base"
        },
        {
          "name": "calendar",
          "class": "absolute mt-1 w-[320px] bg-white rounded-xl border border-slate-200 shadow-md z-20 p-4",
          "tailwind": "absolute mt-1 w-[320px] bg-white rounded-xl border border-slate-200 shadow-md z-20 p-4"
        },
        {
          "name": "day-cell",
          "class": "w-10 h-10 inline-flex items-center justify-center text-sm rounded-lg",
          "tailwind": "w-10 h-10 inline-flex items-center justify-center text-sm rounded-lg"
        }
      ],
      "sizes": [],
      "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 で隠す。",
          "class": ""
        },
        "selected": {
          "description": "選択済み日セル。day-cell 基底への overlay 差分。",
          "tailwind": "bg-primary-500 text-white hover:bg-primary-600",
          "ariaChanges": "当該 day セルに aria-selected=\"true\"。",
          "class": "bg-primary-500 text-white hover:bg-primary-600"
        },
        "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 色を継承。",
          "class": "font-semibold ring-1 ring-inset ring-primary-300"
        },
        "error": {
          "description": "不正入力。trigger 基底への overlay 差分。",
          "tailwind": "border-red-600",
          "ariaChanges": "トリガーに aria-invalid=\"true\" + aria-describedby でエラーメッセージ参照。",
          "class": "border-red-600"
        },
        "disabled": {
          "description": "操作不可。全 variant 共通。",
          "tailwind": "opacity-50 cursor-not-allowed pointer-events-none",
          "ariaChanges": "トリガーに disabled 属性 + aria-disabled=\"true\"。カレンダーを開けない。",
          "class": "opacity-50 cursor-not-allowed pointer-events-none"
        }
      },
      "appStatus": "planned",
      "appMapping": "adapted",
      "appNote": "カレンダー自作はしない。OS 標準の日付ピッカー（@react-native-community/datetimepicker 等）への委譲でトークンのみ供給",
      "accessibility": {
        "role": "dialog (popup)",
        "required": [
          "aria-label=\"カレンダーを開く\"",
          "aria-selected (day)",
          "keyboard navigation"
        ],
        "focusRing": "focus:ring-2 focus:ring-primary-500/50"
      },
      "prohibited": [
        "ブラウザ間で表示が不統一",
        "影が強すぎてノイズになる（datepicker コンテキスト。汎用は SPACE_NO_SHADOW_LG で検出）",
        "Dropdown レイヤーの統一が崩れる",
        "色覚多様性への非対応",
        "キーボードユーザーが操作不可",
        "日付の曜日が判別できない"
      ],
      "htmlSample": "<button class=\"w-full flex items-center gap-2 rounded-lg border border-slate-300 bg-white px-3 py-2 text-base focus:ring-2 focus:ring-primary-500/50\" aria-label=\"カレンダーを開く\"><span>日付を選択</span></button>"
    },
    {
      "id": "divider",
      "name": "Divider",
      "category": "layout",
      "description": "セクション間の視覚的区切り。水平 / テキスト付き / 垂直の3パターン。",
      "docPath": "components/divider.md",
      "anatomy": [
        "line",
        "label?",
        "container?"
      ],
      "variants": [
        {
          "name": "horizontal",
          "class": "border-t border-slate-200",
          "tailwind": "border-t border-slate-200"
        },
        {
          "name": "with-text",
          "class": "flex items-center gap-4",
          "tailwind": "flex items-center gap-4"
        },
        {
          "name": "vertical",
          "class": "border-l border-slate-200 self-stretch",
          "tailwind": "border-l border-slate-200 self-stretch"
        }
      ],
      "sizes": [],
      "states": [
        "default"
      ],
      "appStatus": "planned",
      "accessibility": {
        "role": "separator",
        "required": [
          "role=\"separator\" (non-hr)",
          "aria-orientation=\"vertical\" (vertical)"
        ],
        "focusRing": "N/A"
      },
      "prohibited": [
        "セマンティクス違反。支援技術が区切りを認識できない",
        "薄すぎて境界が見えない",
        "線が強すぎてノイズになる"
      ],
      "htmlSample": "<hr class=\"border-t border-slate-200 my-6\">"
    },
    {
      "id": "dropdown",
      "name": "Dropdown",
      "category": "navigation",
      "description": "ドロップダウンメニュー。キーボードナビゲーション対応。",
      "docPath": "components/dropdown.md",
      "anatomy": [
        "triggerButton",
        "menuContainer",
        "menuItem",
        "leadingIcon?",
        "separator?",
        "menuGroupLabel?"
      ],
      "variants": [
        {
          "name": "basic",
          "class": "absolute top-full mt-1 w-48 bg-white rounded-lg border border-slate-200 shadow-md z-20 py-1",
          "tailwind": "absolute top-full mt-1 w-48 bg-white rounded-lg border border-slate-200 shadow-md z-20 py-1"
        },
        {
          "name": "with-icons",
          "class": "absolute top-full mt-1 w-48 bg-white rounded-lg border border-slate-200 shadow-md z-20 py-1",
          "tailwind": "absolute top-full mt-1 w-48 bg-white rounded-lg border border-slate-200 shadow-md z-20 py-1"
        },
        {
          "name": "with-separator",
          "class": "absolute top-full mt-1 w-48 bg-white rounded-lg border border-slate-200 shadow-md z-20 py-1",
          "tailwind": "absolute top-full mt-1 w-48 bg-white rounded-lg border border-slate-200 shadow-md z-20 py-1"
        }
      ],
      "sizes": [],
      "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 で隠す。",
          "class": ""
        },
        "destructive": {
          "description": "破壊的アクションの menuItem。menuItem 基底への overlay 差分。",
          "tailwind": "text-red-700 hover:bg-red-50",
          "htmlNote": "「削除」等の危険操作項目に適用。アイコンも text-red-600 に揃える。",
          "class": "text-red-700 hover:bg-red-50"
        },
        "disabled": {
          "description": "操作不可。全 variant 共通。",
          "tailwind": "opacity-50 cursor-not-allowed pointer-events-none",
          "ariaChanges": "トリガーに aria-disabled=\"true\"。開けない（aria-expanded は false のまま）。",
          "class": "opacity-50 cursor-not-allowed pointer-events-none"
        }
      },
      "appStatus": "planned",
      "appMapping": "adapted",
      "appNote": "hover 起動は存在しない。タップ起動の Menu（アンカー付き）or ActionSheet に変換",
      "accessibility": {
        "role": "menu",
        "required": [
          "role=\"menuitem\" on items",
          "aria-haspopup on trigger"
        ],
        "focusRing": "focus-visible:ring-2 focus-visible:ring-primary-500/50"
      },
      "prohibited": [],
      "htmlSample": "<div class=\"relative inline-block\"><button aria-haspopup=\"menu\" class=\"h-10 px-4 bg-white border border-slate-200 rounded-lg hover:bg-gray-50\">メニュー</button><div role=\"menu\" class=\"absolute top-full mt-1 w-48 bg-white rounded-lg border border-slate-200 shadow-md z-20 py-1\"><a role=\"menuitem\" class=\"flex items-center gap-3 px-4 py-2 text-sm text-body hover:bg-gray-50\">編集</a></div></div>"
    },
    {
      "id": "empty-state",
      "name": "EmptyState",
      "category": "feedback",
      "description": "データ無し時のプレースホルダー（アイコン + タイトル + 説明 + 任意のアクション）。Text + Button の compose。",
      "docPath": "components/empty-state.md",
      "anatomy": [
        "icon?",
        "title",
        "description?",
        "actionButton?"
      ],
      "variants": [
        {
          "name": "default",
          "class": "",
          "tailwind": ""
        }
      ],
      "sizes": [],
      "states": [
        "default"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "empty-state",
          "platform": "app",
          "contractVersion": "0.1.0",
          "description": "RN 実装（src/components/EmptyState.tsx）の具象レシピ（styleRefs 形式）。中央寄せコンテナ + title（Text lg / semibold / heading role / text-heading）+ description（Text sm / text-muted）+ 任意 action（Button contained を内部 compose、marginTop spacing.2）。titleStyle / descriptionStyle は compose する Text primitive へ渡す値。",
          "variants": {
            "default": {
              "style": {
                "alignItems": "center",
                "justifyContent": "center",
                "padding": {
                  "token": "spacing.8"
                },
                "gap": {
                  "token": "spacing.3"
                }
              },
              "titleStyle": {
                "fontSize": {
                  "token": "typography.fontSize.lg"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.semibold"
                },
                "color": {
                  "token": "color.semantic.light.text-heading"
                },
                "textAlign": "center"
              },
              "descriptionStyle": {
                "fontSize": {
                  "token": "typography.fontSize.sm"
                },
                "color": {
                  "token": "color.semantic.light.text-muted"
                },
                "textAlign": "center"
              },
              "actionStyle": {
                "marginTop": {
                  "token": "spacing.2"
                }
              }
            }
          },
          "sizes": {},
          "states": {}
        }
      },
      "accessibility": {
        "role": "none",
        "required": [
          "title は見出しとして読み上げる"
        ],
        "focusRing": "N/A"
      },
      "prohibited": [],
      "htmlSample": ""
    },
    {
      "id": "header",
      "name": "Header",
      "category": "layout",
      "description": "画面ヘッダー。defaultは左寄せ見出し、actionsは可視タイトルなしの操作バー、centered/navigationは中央タイトル。配置・寸法・文字組みはHeaderが所有し、画面の操作内容とnavigationは利用側が渡す。",
      "docPath": "components/header.md",
      "anatomy": [
        "container",
        "title",
        "leading?",
        "trailing?"
      ],
      "variants": [
        {
          "name": "default",
          "class": "",
          "tailwind": ""
        },
        {
          "name": "actions",
          "class": "",
          "tailwind": ""
        },
        {
          "name": "centered",
          "class": "",
          "tailwind": ""
        },
        {
          "name": "navigation",
          "class": "",
          "tailwind": ""
        }
      ],
      "sizes": [],
      "states": [
        "default"
      ],
      "appStatus": "implemented",
      "appNote": "melta-app に実装済みなのは default / actions のみ。centered / navigation は契約だけが先行している。melta-app の型は melta-app 内に生成済みの契約型（header 0.2.0）から取るため、melta-app が新しい契約で型を再生成して公開するまでは型エラーになる。再生成後も実装が入るまでは default と同じ描画になる。使う前に melta-app 側の実装を待つこと",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "header",
          "platform": "app",
          "contractVersion": "0.3.0",
          "description": "RN 実装（src/components/Header.tsx）の具象レシピ（styleRefs 形式）。title は melta の Text を compose するため titleStyle は持たない（typography は text recipe が正）。default/actions は variant=\"xl\" weight=\"bold\" color=\"text-heading\" role=\"heading\"。default の横並び・外側余白・下線・titleWrapStyle の flex:1 を actions も保ち、中央spacer前後のgapだけspacing.1に抑え、hiddenTitleStyleでa11y見出しを視覚的に隠す。centered/navigation は Text variant=\"lg\" を既定、長い動的タイトルは \"base\" とし、独立した見出しgroupに置く。等幅の左右slotと縮小可能なタイトル領域を持ち、最小高44でフォント拡大を許す。navigation の borderBottomWidth:1 は密度1での値で、実機ではStyleSheet.hairlineWidthをresolverへ渡す。centered は下線を持たず横余白は親が持つ。",
          "variants": {
            "default": {
              "containerStyle": {
                "flexDirection": "row",
                "alignItems": "center",
                "gap": {
                  "token": "spacing.3"
                },
                "paddingHorizontal": {
                  "token": "spacing.4"
                },
                "paddingVertical": {
                  "token": "spacing.3"
                },
                "backgroundColor": {
                  "token": "color.semantic.light.bg-page"
                },
                "borderBottomWidth": 1,
                "borderBottomColor": {
                  "token": "color.semantic.light.border-default"
                }
              },
              "titleWrapStyle": {
                "flex": 1
              }
            },
            "actions": {
              "containerStyle": {
                "flexDirection": "row",
                "alignItems": "center",
                "gap": {
                  "token": "spacing.1"
                },
                "paddingHorizontal": {
                  "token": "spacing.4"
                },
                "paddingVertical": {
                  "token": "spacing.3"
                },
                "backgroundColor": {
                  "token": "color.semantic.light.bg-page"
                },
                "borderBottomWidth": 1,
                "borderBottomColor": {
                  "token": "color.semantic.light.border-default"
                }
              },
              "titleWrapStyle": {
                "flex": 1
              },
              "hiddenTitleStyle": {
                "position": "absolute",
                "width": 1,
                "height": 1,
                "overflow": "hidden"
              }
            },
            "centered": {
              "containerStyle": {
                "flexDirection": "row",
                "alignItems": "center",
                "minHeight": 44
              },
              "titleWrapStyle": {
                "flexShrink": 1,
                "minWidth": 0
              },
              "leadingStyle": {
                "flex": 1,
                "minWidth": 44,
                "flexDirection": "row",
                "justifyContent": "flex-start"
              },
              "trailingStyle": {
                "flex": 1,
                "minWidth": 44,
                "flexDirection": "row",
                "justifyContent": "flex-end"
              }
            },
            "navigation": {
              "containerStyle": {
                "flexDirection": "row",
                "alignItems": "center",
                "minHeight": 44,
                "paddingHorizontal": {
                  "token": "spacing.4"
                },
                "borderBottomWidth": 1,
                "borderBottomColor": {
                  "token": "color.semantic.light.border-default"
                }
              },
              "titleWrapStyle": {
                "flexShrink": 1,
                "minWidth": 0
              },
              "leadingStyle": {
                "flex": 1,
                "minWidth": 44,
                "flexDirection": "row",
                "justifyContent": "flex-start"
              },
              "trailingStyle": {
                "flex": 1,
                "minWidth": 44,
                "flexDirection": "row",
                "justifyContent": "flex-end"
              }
            }
          },
          "sizes": {},
          "states": {}
        }
      },
      "accessibility": {
        "role": "banner",
        "required": [
          "titleは空でない画面名。default/centered/navigationでは可視heading、actionsでは視覚的に隠したheading（RN: accessibilityRole=\"header\"）として読み上げる。スクロールによるタイトル切替で見えない場合は、利用側wrapperで読み上げ対象からも外す",
          "container全体を単一のaccessible要素にまとめない。leading/trailingの操作は独立してフォーカス・読み上げ・操作できる",
          "centered/navigationの左右slotに入れる操作は44pt以上の標的を持たせる。固定高でフォント拡大を切らず、最小高で確保する"
        ],
        "focusRing": "N/A"
      },
      "prohibited": [],
      "htmlSample": ""
    },
    {
      "id": "icon",
      "name": "Icon",
      "category": "data-display",
      "description": "統一アイコン primitive。name prop でグリフを選択し（グリフ集合は実装側の公開面 = assets/icons の Charcoal セット由来）、色は semantic token キー限定の prop（default text-default）。絵文字・生 Text 代用を置き換える（dogfood 不足-2）。",
      "docPath": "components/icon.md",
      "anatomy": [
        "glyph"
      ],
      "variants": [
        {
          "name": "default",
          "class": "",
          "tailwind": ""
        }
      ],
      "sizes": [
        {
          "name": "sm",
          "class": "",
          "tailwind": "",
          "height": "16px"
        },
        {
          "name": "md",
          "class": "",
          "tailwind": "",
          "height": "20px"
        },
        {
          "name": "lg",
          "class": "",
          "tailwind": "",
          "height": "24px"
        }
      ],
      "states": [
        "default"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "icon",
          "platform": "app",
          "contractVersion": "0.1.0",
          "description": "RN 実装（src/primitives/Icon.tsx）の具象レシピ（styleRefs 形式）。グリフは melta-ui assets/icons（Charcoal）から codegen した Path データを src に同梱し、react-native-svg（optional peer）で描画する。color は prop（semantic token キー限定、default color.semantic.light.text-default = variants.default.style.color）。size prop は sizes 軸（sm/md/lg、width=height の正方形）。",
          "variants": {
            "default": {
              "style": {
                "color": {
                  "token": "color.semantic.light.text-default"
                }
              }
            }
          },
          "sizes": {
            "sm": {
              "style": {
                "width": 16,
                "height": 16
              }
            },
            "md": {
              "style": {
                "width": 20,
                "height": 20
              }
            },
            "lg": {
              "style": {
                "width": 24,
                "height": 24
              }
            }
          },
          "states": {}
        }
      },
      "accessibility": {
        "role": "img",
        "required": [
          "意味を持つ icon は accessibilityLabel（web: aria-label）必須",
          "装飾 icon は accessibility ツリーから除外する（RN: importantForAccessibility=\"no-hide-descendants\" / web: aria-hidden）"
        ],
        "focusRing": "N/A"
      },
      "prohibited": [],
      "htmlSample": ""
    },
    {
      "id": "image",
      "name": "Image",
      "category": "data-display",
      "description": "画像表示 primitive。aspectRatio / radius / contentFit / onError fallback を持つ。Phase1 は RN コア Image、expo-image は Phase2。",
      "docPath": "components/image.md",
      "anatomy": [
        "image",
        "fallback?"
      ],
      "variants": [
        {
          "name": "default",
          "class": "",
          "tailwind": ""
        }
      ],
      "sizes": [],
      "states": [
        "default",
        "error"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "image",
          "platform": "app",
          "contractVersion": "0.1.0",
          "description": "RN 実装（src/components/Image.tsx）の具象レシピ（styleRefs 形式）。radius は prop（radius.* token キー、指定時のみ borderRadius + overflow:hidden を適用）で、実装にデフォルト radius は無い（contract default variant の tokenRefs radius=radius.md とは食い違い、レシピは実装準拠で空）。contentFit(cover|contain) → RN resizeMode に変換、aspectRatio は literal prop。states.error は onError 時に fallback ReactNode へ差し替え（同一 shape、style 差分なし）。",
          "variants": {
            "default": {
              "style": {}
            }
          },
          "sizes": {},
          "states": {
            "error": {
              "style": {}
            }
          }
        }
      },
      "accessibility": {
        "role": "image",
        "required": [
          "情報を持つ画像は accessibilityLabel 必須",
          "装飾画像は読み上げ対象から外す"
        ],
        "focusRing": "N/A"
      },
      "prohibited": [],
      "htmlSample": ""
    },
    {
      "id": "list",
      "name": "List",
      "category": "data-display",
      "description": "リストアイテム。Link / Information / Action / Toggle / Selection の6タイプ。",
      "docPath": "components/list.md",
      "anatomy": [
        "container",
        "primaryText",
        "secondaryText?",
        "leftIcon?",
        "leftImage?",
        "rightIcon?",
        "rightImage?",
        "action?",
        "border?"
      ],
      "variants": [
        {
          "name": "link",
          "class": "flex items-center gap-3 px-4 py-3 text-body hover:bg-gray-50 border-b border-slate-200 transition-colors",
          "tailwind": "flex items-center gap-3 px-4 py-3 text-body hover:bg-gray-50 border-b border-slate-200 transition-colors"
        },
        {
          "name": "information",
          "class": "flex items-center gap-3 px-4 py-3 text-body border-b border-slate-200",
          "tailwind": "flex items-center gap-3 px-4 py-3 text-body border-b border-slate-200"
        },
        {
          "name": "action",
          "class": "flex items-center justify-between px-4 py-3 text-body hover:bg-gray-50 border-b border-slate-200",
          "tailwind": "flex items-center justify-between px-4 py-3 text-body hover:bg-gray-50 border-b border-slate-200"
        }
      ],
      "sizes": [],
      "states": [
        "default",
        "hover",
        "active",
        "selected",
        "focus"
      ],
      "appStatus": "planned",
      "accessibility": {
        "role": "listitem",
        "required": [
          "role=\"button\" (clickable items)"
        ],
        "focusRing": "focus-visible:ring-2 focus-visible:ring-primary-500/50"
      },
      "prohibited": [
        "テキストが切れる or 余白が不均等",
        "色覚多様性への非対応",
        "キーボード/スクリーンリーダーで操作不可",
        "情報の断絶を誤解させる"
      ],
      "htmlSample": "<ul class=\"divide-y divide-slate-200\"><li class=\"flex items-center justify-between px-4 py-3 hover:bg-gray-50\"><div><h4 class=\"text-base font-medium text-slate-900\">アイテム</h4><p class=\"text-sm text-slate-500\">説明</p></div></li></ul>"
    },
    {
      "id": "metric",
      "name": "Metric",
      "category": "data-display",
      "description": "数値 + 単位 + ラベルの指標表示 primitive（距離 / 時間 / 獲得標高 等の走行サマリー表示）。tabular-nums で桁揃え。sizes の height は数値テキストの想定行高(px)で、実 fontSize は実装側が token から解決する。",
      "docPath": "components/metric.md",
      "anatomy": [
        "value",
        "unit?",
        "label?"
      ],
      "variants": [
        {
          "name": "default",
          "class": "",
          "tailwind": ""
        }
      ],
      "sizes": [
        {
          "name": "sm",
          "class": "",
          "tailwind": "",
          "height": "26px"
        },
        {
          "name": "md",
          "class": "",
          "tailwind": "",
          "height": "36px"
        },
        {
          "name": "lg",
          "class": "",
          "tailwind": "",
          "height": "45px"
        }
      ],
      "states": [
        "default"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "metric",
          "platform": "app",
          "contractVersion": "0.1.0",
          "description": "RN 実装（src/primitives/Metric.tsx）の具象レシピ（styleRefs 形式）。value は tabular-nums（literal、token 外）で桁揃え + bold + text-heading。unit は value の1段下の fontSize でベースライン揃え（medium / text-muted / marginLeft spacing.1）。label は sm / text-muted。sizes は value / unit の fontSize token マッピング（contract sizes の height は想定行高で、実 fontSize はここで解決）。",
          "variants": {
            "default": {
              "valueStyle": {
                "fontWeight": {
                  "token": "typography.fontWeight.bold"
                },
                "color": {
                  "token": "color.semantic.light.text-heading"
                },
                "fontVariant": [
                  "tabular-nums"
                ]
              },
              "unitStyle": {
                "fontWeight": {
                  "token": "typography.fontWeight.medium"
                },
                "color": {
                  "token": "color.semantic.light.text-muted"
                },
                "marginLeft": {
                  "token": "spacing.1"
                }
              },
              "labelStyle": {
                "fontSize": {
                  "token": "typography.fontSize.sm"
                },
                "color": {
                  "token": "color.semantic.light.text-muted"
                }
              }
            }
          },
          "sizes": {
            "sm": {
              "valueFontSize": {
                "token": "typography.fontSize.lg"
              },
              "unitFontSize": {
                "token": "typography.fontSize.base"
              }
            },
            "md": {
              "valueFontSize": {
                "token": "typography.fontSize.2xl"
              },
              "unitFontSize": {
                "token": "typography.fontSize.lg"
              }
            },
            "lg": {
              "valueFontSize": {
                "token": "typography.fontSize.3xl"
              },
              "unitFontSize": {
                "token": "typography.fontSize.xl"
              }
            }
          },
          "states": {}
        }
      },
      "accessibility": {
        "role": "text",
        "required": [
          "value + unit + label を1つの accessibilityLabel に合成して読み上げる"
        ],
        "focusRing": "N/A"
      },
      "prohibited": [],
      "htmlSample": ""
    },
    {
      "id": "modal",
      "name": "Modal",
      "category": "feedback",
      "description": "フォーカストラップとバックドロップを備えたモーダルダイアログ。",
      "docPath": "components/modal.md",
      "anatomy": {
        "overlay": {
          "description": "背景バックドロップ。クリックで閉じる。MODAL_OVERLAY_REQUIRED。",
          "element": "div",
          "tailwind": "bg-black/50 absolute inset-0",
          "class": "bg-black/50 absolute inset-0"
        },
        "container": {
          "description": "ダイアログ本体。フォーカストラップ範囲。",
          "element": "div",
          "roles": "role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"modal-title\"",
          "tailwind": "bg-white rounded-xl p-6 shadow-xl relative z-10",
          "class": "bg-white rounded-xl p-6 shadow-xl relative z-10"
        },
        "header": {
          "description": "タイトル。aria-labelledby 参照先。",
          "element": "h2",
          "roles": "id=\"modal-title\"",
          "tailwind": "text-2xl font-bold text-slate-900",
          "class": "text-2xl font-bold text-slate-900"
        },
        "body": {
          "description": "本文。",
          "element": "div",
          "tailwind": "text-body mt-2",
          "class": "text-body mt-2"
        },
        "footer": {
          "description": "アクション群(任意)。",
          "element": "div",
          "tailwind": "flex justify-end gap-3 mt-6",
          "class": "flex justify-end gap-3 mt-6"
        },
        "closeButton": {
          "description": "閉じるボタン。MODAL_CLOSE_REQUIRED。アイコンのみなら aria-label 必須。",
          "element": "button",
          "roles": "aria-label=\"閉じる\""
        }
      },
      "variants": [
        {
          "name": "confirmation",
          "class": "fixed inset-0 flex items-center justify-center z-50",
          "tailwind": "fixed inset-0 flex items-center justify-center z-50"
        },
        {
          "name": "form",
          "class": "fixed inset-0 flex items-center justify-center z-50",
          "tailwind": "fixed inset-0 flex items-center justify-center z-50"
        },
        {
          "name": "alert",
          "class": "fixed inset-0 flex items-center justify-center z-50",
          "tailwind": "fixed inset-0 flex items-center justify-center z-50"
        }
      ],
      "sizes": [
        {
          "name": "small",
          "class": "w-96",
          "tailwind": "w-96",
          "height": "0px"
        },
        {
          "name": "medium",
          "class": "w-[32rem]",
          "tailwind": "w-[32rem]",
          "height": "0px"
        },
        {
          "name": "large",
          "class": "w-[48rem]",
          "tailwind": "w-[48rem]",
          "height": "0px"
        }
      ],
      "states": [
        "default",
        "open",
        "closing"
      ],
      "stateSpecs": {
        "default": {
          "description": "閉。DOM 上 hidden。",
          "tailwind": "hidden",
          "ariaChanges": "aria-hidden=\"true\"。",
          "class": "hidden"
        },
        "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 基底＝差分なし。",
          "class": ""
        },
        "closing": {
          "description": "閉アニメ中。完了後 hidden に戻し focus 復帰。",
          "tailwind": "opacity-0 transition-opacity duration-150",
          "htmlNote": "トランジション終了で default(hidden) へ。",
          "class": "opacity-0 transition-opacity duration-150"
        }
      },
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "modal",
          "platform": "app",
          "contractVersion": "2.0.0",
          "description": "RN 実装（src/components/Modal.tsx）の具象レシピ（styleRefs 形式）。RN core Modal（transparent + animationType fade）に overlay（Pressable、tap で onClose）+ panel を載せる。variant（confirmation/form/alert）は意味分類で style は共通（契約と同じ）。sizes はタブレット以上で効く maxWidth（モバイルは width 100% - overlay padding が先に効く）。契約の open/closing state は RN Modal の visible prop + animationType に委譲するため states は空で宣言。focus trap は RN Modal の accessibilityViewIsModal、Escape は Android back（onRequestClose）が対応物。overlay の黒 50% は token 外の literal（web も bg-black/50）。",
          "variants": {
            "confirmation": {
              "overlayStyle": {
                "flex": 1,
                "backgroundColor": "rgba(0,0,0,0.5)",
                "justifyContent": "center",
                "alignItems": "center",
                "padding": {
                  "token": "spacing.4"
                }
              },
              "panelStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderRadius": {
                  "token": "radius.lg"
                },
                "padding": {
                  "token": "spacing.6"
                },
                "width": "100%",
                "elevation": {
                  "token": "elevation.overlay"
                }
              },
              "titleStyle": {
                "fontSize": {
                  "token": "typography.fontSize.2xl"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.bold"
                },
                "color": {
                  "token": "color.semantic.light.text-heading"
                }
              },
              "bodyStyle": {
                "marginTop": {
                  "token": "spacing.2"
                }
              },
              "footerStyle": {
                "flexDirection": "row",
                "justifyContent": "flex-end",
                "gap": {
                  "token": "spacing.3"
                },
                "marginTop": {
                  "token": "spacing.6"
                }
              }
            },
            "form": {
              "overlayStyle": {
                "flex": 1,
                "backgroundColor": "rgba(0,0,0,0.5)",
                "justifyContent": "center",
                "alignItems": "center",
                "padding": {
                  "token": "spacing.4"
                }
              },
              "panelStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderRadius": {
                  "token": "radius.lg"
                },
                "padding": {
                  "token": "spacing.6"
                },
                "width": "100%",
                "elevation": {
                  "token": "elevation.overlay"
                }
              },
              "titleStyle": {
                "fontSize": {
                  "token": "typography.fontSize.2xl"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.bold"
                },
                "color": {
                  "token": "color.semantic.light.text-heading"
                }
              },
              "bodyStyle": {
                "marginTop": {
                  "token": "spacing.2"
                }
              },
              "footerStyle": {
                "flexDirection": "row",
                "justifyContent": "flex-end",
                "gap": {
                  "token": "spacing.3"
                },
                "marginTop": {
                  "token": "spacing.6"
                }
              }
            },
            "alert": {
              "overlayStyle": {
                "flex": 1,
                "backgroundColor": "rgba(0,0,0,0.5)",
                "justifyContent": "center",
                "alignItems": "center",
                "padding": {
                  "token": "spacing.4"
                }
              },
              "panelStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderRadius": {
                  "token": "radius.lg"
                },
                "padding": {
                  "token": "spacing.6"
                },
                "width": "100%",
                "elevation": {
                  "token": "elevation.overlay"
                }
              },
              "titleStyle": {
                "fontSize": {
                  "token": "typography.fontSize.2xl"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.bold"
                },
                "color": {
                  "token": "color.semantic.light.text-heading"
                }
              },
              "bodyStyle": {
                "marginTop": {
                  "token": "spacing.2"
                }
              },
              "footerStyle": {
                "flexDirection": "row",
                "justifyContent": "flex-end",
                "gap": {
                  "token": "spacing.3"
                },
                "marginTop": {
                  "token": "spacing.6"
                }
              }
            }
          },
          "sizes": {
            "small": {
              "panelStyle": {
                "maxWidth": 384
              }
            },
            "medium": {
              "panelStyle": {
                "maxWidth": 512
              }
            },
            "large": {
              "panelStyle": {
                "maxWidth": 768
              }
            }
          },
          "states": {}
        }
      },
      "accessibility": {
        "role": "dialog",
        "required": [
          "aria-labelledby",
          "aria-modal=\"true\"",
          "focus trap"
        ],
        "focusRing": "focus trap required"
      },
      "prohibited": [
        "キーボードユーザーがモーダル外に出てしまう",
        "ユーザーが脱出できない",
        "ユーザーが操作を中断できない",
        "スクリーンリーダーがモーダルを認識できない",
        "背景との分離が不明確",
        "モーダルの中にモーダルを開くとUXが複雑になりすぎる。合法な部品だけで構成しても合成として崩壊する"
      ],
      "htmlSample": {
        "confirmation": "<div role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"modal-title\" class=\"fixed inset-0 flex items-center justify-center z-50\"><div class=\"bg-black/50 absolute inset-0\"></div><div class=\"bg-white rounded-xl p-6 w-96 shadow-xl relative z-10\"><h2 id=\"modal-title\" class=\"text-2xl font-bold text-slate-900\">確認</h2><p class=\"text-body mt-2\">この操作を実行しますか？</p><div class=\"flex justify-end gap-3 mt-6\"><button class=\"inline-flex items-center justify-center 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 relative after:absolute after:inset-x-0 after:top-1/2 after:h-11 after:-translate-y-1/2\">キャンセル</button><button class=\"inline-flex items-center justify-center h-10 px-4 text-[1rem] font-medium bg-primary-500 text-white rounded-lg hover:bg-primary-700 cursor-pointer relative after:absolute after:inset-x-0 after:top-1/2 after:h-11 after:-translate-y-1/2\">実行</button></div></div></div>"
      }
    },
    {
      "id": "pagination",
      "name": "Pagination",
      "category": "navigation",
      "description": "ページ送りナビゲーション。w-10 h-10タップターゲット。",
      "docPath": "components/pagination.md",
      "anatomy": [
        "navContainer",
        "pageButton",
        "prevButton",
        "nextButton",
        "ellipsis?"
      ],
      "variants": [
        {
          "name": "active",
          "class": "w-10 h-10 inline-flex items-center justify-center text-base font-medium text-white bg-primary-500 rounded-lg",
          "tailwind": "w-10 h-10 inline-flex items-center justify-center text-base font-medium text-white bg-primary-500 rounded-lg"
        },
        {
          "name": "inactive",
          "class": "w-10 h-10 inline-flex items-center justify-center text-base font-medium text-slate-700 bg-white border border-slate-200 rounded-lg hover:bg-gray-50 transition-colors",
          "tailwind": "w-10 h-10 inline-flex items-center justify-center text-base font-medium text-slate-700 bg-white border border-slate-200 rounded-lg hover:bg-gray-50 transition-colors"
        },
        {
          "name": "disabled",
          "class": "w-10 h-10 inline-flex items-center justify-center text-slate-300 cursor-not-allowed",
          "tailwind": "w-10 h-10 inline-flex items-center justify-center text-slate-300 cursor-not-allowed"
        }
      ],
      "sizes": [],
      "states": [
        "default",
        "active",
        "disabled",
        "hover",
        "focus"
      ],
      "appStatus": "not-planned",
      "appNote": "モバイルは無限スクロール（FlatList onEndReached）で代替。カルーセル文脈は PageControl の領分",
      "accessibility": {
        "role": "navigation",
        "required": [
          "aria-label=\"ページネーション\"",
          "aria-current=\"page\"",
          "aria-label per button"
        ],
        "focusRing": "focus:ring-2 focus:ring-primary-500/50"
      },
      "prohibited": [
        "高さ 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）実装形",
        "<nav>（および role=\"navigation\"）にアクセシブルネームが無いと、スクリーンリーダーのランドマーク一覧で複数のナビゲーションを区別できない。nav が 1 つしか無い画面でも、後から増えたときに無名ランドマークが並ぶため常に付与する"
      ],
      "htmlSample": "<nav aria-label=\"ページネーション\"><ul class=\"flex items-center gap-1\"><li><button class=\"w-10 h-10 inline-flex items-center justify-center text-base font-medium text-white bg-primary-500 rounded-lg\" aria-current=\"page\" aria-label=\"ページ 1\">1</button></li></ul></nav>"
    },
    {
      "id": "progress",
      "name": "Progress",
      "category": "feedback",
      "description": "リニアプログレスバー。aria-valuenow/min/max必須。",
      "docPath": "components/progress.md",
      "anatomy": [
        "track",
        "fill",
        "label?",
        "percentage?"
      ],
      "variants": [
        {
          "name": "primary",
          "class": "bg-slate-200 rounded-full h-2",
          "tailwind": "bg-slate-200 rounded-full h-2"
        },
        {
          "name": "success",
          "class": "bg-slate-200 rounded-full h-2",
          "tailwind": "bg-slate-200 rounded-full h-2"
        },
        {
          "name": "indeterminate",
          "class": "bg-slate-200 rounded-full h-2 overflow-hidden",
          "tailwind": "bg-slate-200 rounded-full h-2 overflow-hidden"
        }
      ],
      "sizes": [],
      "states": [
        "default",
        "determinate",
        "indeterminate",
        "complete"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "progress",
          "platform": "app",
          "contractVersion": "2.0.0",
          "description": "RN 実装（src/components/Progress.tsx）の具象レシピ（styleRefs 形式）。track（高さ8 = web h-2）の中を fill が value%（determinate）または往復アニメ（indeterminate variant、AccessibilityInfo.isReduceMotionEnabled で静止 = MOTION_REDUCED_MOTION_REQUIRED の RN 写像）で埋める。a11y: accessibilityRole=\"progressbar\" + accessibilityValue {min:0, max:100, now}（indeterminate は now を渡さない）。fill の幅は実装が value から算出する（recipe は色と形のみ）。",
          "variants": {
            "primary": {
              "trackStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.border-default"
                },
                "borderRadius": {
                  "token": "radius.full"
                },
                "height": 8,
                "overflow": "hidden"
              },
              "fillStyle": {
                "backgroundColor": {
                  "token": "color.primary.500"
                },
                "borderRadius": {
                  "token": "radius.full"
                },
                "height": 8
              }
            },
            "success": {
              "trackStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.border-default"
                },
                "borderRadius": {
                  "token": "radius.full"
                },
                "height": 8,
                "overflow": "hidden"
              },
              "fillStyle": {
                "backgroundColor": {
                  "token": "color.status.success.base"
                },
                "borderRadius": {
                  "token": "radius.full"
                },
                "height": 8
              }
            },
            "indeterminate": {
              "trackStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.border-default"
                },
                "borderRadius": {
                  "token": "radius.full"
                },
                "height": 8,
                "overflow": "hidden"
              },
              "fillStyle": {
                "backgroundColor": {
                  "token": "color.primary.500"
                },
                "borderRadius": {
                  "token": "radius.full"
                },
                "height": 8
              }
            }
          },
          "sizes": {},
          "states": {}
        }
      },
      "accessibility": {
        "role": "progressbar",
        "required": [
          "aria-valuenow",
          "aria-valuemin=\"0\"",
          "aria-valuemax=\"100\"",
          "aria-label"
        ],
        "focusRing": "N/A"
      },
      "prohibited": [
        "prefers-reduced-motion 無視はアクセシビリティ違反"
      ],
      "htmlSample": "<div class=\"bg-slate-200 rounded-full h-2\" role=\"progressbar\" aria-valuenow=\"65\" aria-valuemin=\"0\" aria-valuemax=\"100\" aria-label=\"進捗\"><div class=\"bg-primary-500 rounded-full h-2\" style=\"width:65%\"></div></div>"
    },
    {
      "id": "radio",
      "name": "Radio",
      "category": "form-input",
      "description": "単一選択フォームコントロール。fieldsetラッパー必須。",
      "docPath": "components/radio.md",
      "anatomy": [
        "radioCircle",
        "selectedIndicator?",
        "label",
        "groupLabel",
        "description?",
        "helperText?",
        "errorText?"
      ],
      "variants": [
        {
          "name": "vertical",
          "class": "flex flex-col gap-3",
          "tailwind": "flex flex-col gap-3"
        },
        {
          "name": "horizontal",
          "class": "flex gap-4",
          "tailwind": "flex gap-4"
        },
        {
          "name": "card-style",
          "class": "grid grid-cols-2 gap-4",
          "tailwind": "grid grid-cols-2 gap-4"
        }
      ],
      "sizes": [],
      "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）を表示。",
          "class": "border-primary-500"
        },
        "unselected": {
          "description": "未選択（radioCircle の基底状態）。default の resting と同義＝差分なし。",
          "tailwind": "",
          "ariaChanges": "aria-checked=\"false\"。selectedIndicator は非表示。",
          "class": ""
        },
        "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 を優先（選択済みでもエラーなら赤枠）。",
          "class": "border-red-600"
        },
        "disabled": {
          "description": "操作不可。全 variant 共通。",
          "tailwind": "opacity-50 cursor-not-allowed pointer-events-none",
          "ariaChanges": "各 <input type=\"radio\"> に disabled + aria-disabled=\"true\"。",
          "class": "opacity-50 cursor-not-allowed pointer-events-none"
        }
      },
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "radio",
          "platform": "app",
          "contractVersion": "2.0.0",
          "description": "RN 実装（src/components/RadioGroup.tsx）の具象レシピ（styleRefs 形式）。契約どおり fieldset 相当の RadioGroup（groupLabel 必須）として実装し、variant はレイアウト（vertical/horizontal/card-style）。circleStyle/dotStyle/groupLabelStyle は variant 非依存の共通部として vertical にのみ載せる。card-style は各 option を枠付きカードにする（web の grid 2col は RN では縦積みに読み替え）。selected/error は state 差分（selected の dot 表示は実装、error は circle と card の border に適用）。",
          "variants": {
            "vertical": {
              "containerStyle": {
                "flexDirection": "column",
                "gap": {
                  "token": "spacing.3"
                }
              },
              "circleStyle": {
                "width": 20,
                "height": 20,
                "borderWidth": 2,
                "borderColor": {
                  "token": "color.semantic.light.border-strong"
                },
                "borderRadius": {
                  "token": "radius.full"
                },
                "alignItems": "center",
                "justifyContent": "center"
              },
              "dotStyle": {
                "width": 10,
                "height": 10,
                "borderRadius": {
                  "token": "radius.full"
                },
                "backgroundColor": {
                  "token": "color.primary.500"
                }
              },
              "labelStyle": {
                "fontSize": {
                  "token": "typography.fontSize.base"
                },
                "color": {
                  "token": "color.semantic.light.text-default"
                }
              },
              "groupLabelStyle": {
                "fontSize": {
                  "token": "typography.fontSize.sm"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.medium"
                },
                "color": {
                  "token": "color.semantic.light.text-heading"
                },
                "marginBottom": {
                  "token": "spacing.3"
                }
              },
              "optionGap": {
                "token": "spacing.2"
              }
            },
            "horizontal": {
              "containerStyle": {
                "flexDirection": "row",
                "flexWrap": "wrap",
                "gap": {
                  "token": "spacing.4"
                }
              }
            },
            "card-style": {
              "containerStyle": {
                "flexDirection": "column",
                "gap": {
                  "token": "spacing.3"
                }
              },
              "cardStyle": {
                "borderWidth": 1,
                "borderColor": {
                  "token": "color.semantic.light.border-default"
                },
                "borderRadius": {
                  "token": "radius.md"
                },
                "padding": {
                  "token": "spacing.4"
                }
              },
              "cardSelectedStyle": {
                "borderColor": {
                  "token": "color.primary.500"
                },
                "backgroundColor": {
                  "token": "color.primary.50"
                }
              }
            }
          },
          "sizes": {},
          "states": {
            "selected": {
              "circleStyle": {
                "borderColor": {
                  "token": "color.primary.500"
                }
              }
            },
            "unselected": {},
            "disabled": {
              "style": {
                "opacity": 0.5
              }
            },
            "error": {
              "circleStyle": {
                "borderColor": {
                  "token": "color.status.danger.base"
                }
              },
              "errorTextStyle": {
                "fontSize": {
                  "token": "typography.fontSize.xs"
                },
                "color": {
                  "token": "color.status.danger.text-light"
                },
                "marginTop": {
                  "token": "spacing.2"
                }
              }
            }
          }
        }
      },
      "accessibility": {
        "role": "radio (native <input type=\"radio\">)",
        "required": [
          "fieldset wrapper",
          "label association"
        ],
        "focusRing": "focus:ring-2 focus:ring-primary-500/50"
      },
      "prohibited": [
        "グループの目的が伝わらない",
        "スクリーンリーダーが目的を読み上げられない"
      ],
      "htmlSample": "<fieldset><legend class=\"text-sm font-medium text-slate-900 mb-3\">配送方法</legend><div class=\"flex flex-col gap-3\"><label class=\"flex items-center gap-2 cursor-pointer\"><input type=\"radio\" name=\"delivery\" class=\"w-4 h-4 accent-primary-500\"><span class=\"text-base text-body\">標準配送</span></label></div></fieldset>"
    },
    {
      "id": "row",
      "name": "Row",
      "category": "layout",
      "description": "子要素を横に並べる layout primitive。gap は spacing token キー限定の prop。折返し（wrap）と主軸配置（justify）を持ち、タグ列・メトリクス列・ヘッダー行の生 flexbox 手書きを置き換える（dogfood 不足-1）。",
      "docPath": "components/row.md",
      "anatomy": [
        "container"
      ],
      "variants": [
        {
          "name": "default",
          "class": "",
          "tailwind": ""
        }
      ],
      "sizes": [],
      "states": [
        "default"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "row",
          "platform": "app",
          "contractVersion": "0.1.0",
          "description": "RN 実装（src/primitives/Row.tsx）の具象レシピ（styleRefs 形式）。横並び View。gap は prop（spacing token キー限定、省略時は出力しない）、align は prop（start|center|end|baseline|stretch → alignItems、default center）、justify は prop（start|center|end|between → justifyContent、default start = style 出力なし）、wrap は prop（true で flexWrap: \"wrap\"）。",
          "variants": {
            "default": {
              "style": {
                "flexDirection": "row",
                "alignItems": "center"
              }
            }
          },
          "sizes": {},
          "states": {}
        }
      },
      "accessibility": {
        "role": "none",
        "required": [],
        "focusRing": "N/A"
      },
      "prohibited": [],
      "htmlSample": ""
    },
    {
      "id": "screen",
      "name": "Screen",
      "category": "layout",
      "description": "画面骨格 primitive（SafeArea + bg-page + content padding）。header slot を scroll 外に固定し、毎画面手書きされる SafeAreaView + ScrollView + ヘッダーの定型を置き換える（dogfood 不足-3）。",
      "docPath": "components/screen.md",
      "anatomy": [
        "safeArea",
        "header?",
        "content"
      ],
      "variants": [
        {
          "name": "fixed",
          "class": "",
          "tailwind": ""
        },
        {
          "name": "scroll",
          "class": "",
          "tailwind": ""
        }
      ],
      "sizes": [],
      "states": [
        "default"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "screen",
          "platform": "app",
          "contractVersion": "0.1.0",
          "description": "RN 実装（src/components/Screen.tsx）の具象レシピ（styleRefs 形式）。safeAreaStyle は SafeAreaView（flex:1 + bg-page）、contentStyle は variant=fixed の View / variant=scroll の ScrollView contentContainerStyle に適用。padding は prop（spacing token キー限定 | \"none\"、default spacing.4 = ここに焼く）。header slot は scroll 外（SafeArea 直下）に固定する。",
          "variants": {
            "fixed": {
              "safeAreaStyle": {
                "flex": 1,
                "backgroundColor": {
                  "token": "color.semantic.light.bg-page"
                }
              },
              "contentStyle": {
                "flex": 1,
                "padding": {
                  "token": "spacing.4"
                }
              }
            },
            "scroll": {
              "safeAreaStyle": {
                "flex": 1,
                "backgroundColor": {
                  "token": "color.semantic.light.bg-page"
                }
              },
              "contentStyle": {
                "padding": {
                  "token": "spacing.4"
                }
              }
            }
          },
          "sizes": {},
          "states": {}
        }
      },
      "accessibility": {
        "role": "none",
        "required": [],
        "focusRing": "N/A"
      },
      "prohibited": [],
      "htmlSample": ""
    },
    {
      "id": "select",
      "name": "Select",
      "category": "form-input",
      "description": "ドロップダウン選択。appearance-none + カスタムSVGシェブロン必須。",
      "docPath": "components/select.md",
      "anatomy": [
        "label",
        "wrapper",
        "select",
        "chevronIcon"
      ],
      "variants": [
        {
          "name": "default",
          "class": "appearance-none w-full px-3 py-2 text-base border border-slate-300 rounded-lg focus:ring-2 focus:ring-primary-500/50 pr-10",
          "tailwind": "appearance-none w-full px-3 py-2 text-base border border-slate-300 rounded-lg focus:ring-2 focus:ring-primary-500/50 pr-10"
        },
        {
          "name": "error",
          "class": "appearance-none w-full px-3 py-2 text-base border border-red-300 rounded-lg focus:ring-2 focus:ring-red-600/50 bg-red-50 pr-10",
          "tailwind": "appearance-none w-full px-3 py-2 text-base border border-red-300 rounded-lg focus:ring-2 focus:ring-red-600/50 bg-red-50 pr-10"
        },
        {
          "name": "disabled",
          "class": "appearance-none w-full px-3 py-2 text-base border border-slate-200 rounded-lg bg-slate-100 text-slate-400 cursor-not-allowed pr-10",
          "tailwind": "appearance-none w-full px-3 py-2 text-base border border-slate-200 rounded-lg bg-slate-100 text-slate-400 cursor-not-allowed pr-10"
        }
      ],
      "sizes": [],
      "states": [
        "default",
        "hover",
        "focus",
        "error",
        "disabled"
      ],
      "appStatus": "planned",
      "appMapping": "adapted",
      "appNote": "web のドロップリストは持ち込まない。ActionSheet / BottomSheet / OS Picker で開く選択 UI に変換（gluestack/Tamagui も native では Sheet 化）",
      "accessibility": {
        "role": "combobox (native <select>)",
        "required": [
          "label association"
        ],
        "focusRing": "focus:ring-2 focus:ring-primary-500/50"
      },
      "prohibited": [
        "ネイティブ矢印はブラウザ間で位置・余白が不安定",
        "スクリーンリーダーが目的を読み上げられない"
      ],
      "htmlSample": {
        "default": "<div class=\"leading-normal\"><label class=\"block text-sm font-medium text-slate-900 mb-1.5\">カテゴリ</label><div class=\"relative\"><select class=\"appearance-none w-full px-3 py-2 text-base border border-slate-300 rounded-lg focus:ring-2 focus:ring-primary-500/50 pr-10\"><option>選択してください</option></select><svg class=\"absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-400 pointer-events-none\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\"/></svg></div></div>"
      }
    },
    {
      "id": "sidebar",
      "name": "Sidebar",
      "category": "navigation",
      "description": "メインナビゲーション用サイドバー。Standard / Compact / Drawer の3バリエーション。",
      "docPath": "components/sidebar.md",
      "anatomy": [
        "header",
        "nav",
        "navItem",
        "footer"
      ],
      "variants": [
        {
          "name": "standard",
          "class": "w-64 bg-white border-r border-slate-200 flex-shrink-0 flex flex-col h-screen",
          "tailwind": "w-64 bg-white border-r border-slate-200 flex-shrink-0 flex flex-col h-screen"
        },
        {
          "name": "compact",
          "class": "w-16 bg-white border-r border-slate-200 flex-shrink-0 flex flex-col items-center h-screen",
          "tailwind": "w-16 bg-white border-r border-slate-200 flex-shrink-0 flex flex-col items-center h-screen"
        },
        {
          "name": "drawer",
          "class": "fixed left-0 top-0 h-screen w-64 bg-white shadow-xl z-50 flex flex-col",
          "tailwind": "fixed left-0 top-0 h-screen w-64 bg-white shadow-xl z-50 flex flex-col"
        }
      ],
      "sizes": [
        {
          "name": "standard",
          "class": "w-64",
          "tailwind": "w-64",
          "height": "0px"
        },
        {
          "name": "compact",
          "class": "w-16",
          "tailwind": "w-16",
          "height": "0px"
        }
      ],
      "states": [
        "default",
        "collapsed",
        "drawer-open"
      ],
      "appStatus": "not-planned",
      "appNote": "Navigation Drawer の領分＝react-navigation 側の責務。DS はトークン供給のみ",
      "accessibility": {
        "role": "navigation",
        "required": [
          "aria-label=\"メインナビゲーション\"",
          "aria-current=\"page\" on active item"
        ],
        "focusRing": "focus-visible:ring-2 focus-visible:ring-primary-500/50"
      },
      "prohibited": [
        "実装ごとにバラつきが出る",
        "メインコンテンツとのコントラストが強すぎる",
        "ボタン等他コンポーネントとの一貫性を損なう",
        "DS標準アイコンサイズからの逸脱",
        "スクリーンリーダーが現在ページを識別できない",
        "キーボードユーザーが背面要素を操作してしまう",
        "<nav>（および role=\"navigation\"）にアクセシブルネームが無いと、スクリーンリーダーのランドマーク一覧で複数のナビゲーションを区別できない。nav が 1 つしか無い画面でも、後から増えたときに無名ランドマークが並ぶため常に付与する"
      ],
      "htmlSample": {
        "standard": "<div class=\"w-64 bg-white border-r border-slate-200 flex-shrink-0 flex flex-col h-screen\"><div class=\"p-4 border-b border-slate-200\"><span class=\"text-lg font-bold text-slate-900\">App</span></div><nav aria-label=\"メインナビゲーション\" class=\"flex-1 px-3 py-4\"><a href=\"#\" class=\"flex items-center gap-3 px-4 py-2.5 text-sm font-medium text-primary-600 bg-primary-50 rounded-lg\" aria-current=\"page\">ダッシュボード</a><a href=\"#\" class=\"flex items-center gap-3 px-4 py-2.5 text-sm font-medium text-body hover:bg-gray-50 rounded-lg transition-colors\">設定</a></nav><div class=\"mt-auto p-4 border-t border-slate-200\"><span class=\"text-sm text-slate-500\">v1.0</span></div></div>"
      }
    },
    {
      "id": "skeleton",
      "name": "Skeleton",
      "category": "feedback",
      "description": "ローディングプレースホルダー。aria-busy=\"true\"必須。",
      "docPath": "components/skeleton.md",
      "anatomy": [
        "container",
        "circle?",
        "bar",
        "srOnlyText"
      ],
      "variants": [
        {
          "name": "text",
          "class": "bg-slate-200 rounded-md h-4 w-full skeleton-pulse",
          "tailwind": "bg-slate-200 rounded-md h-4 w-full skeleton-pulse"
        },
        {
          "name": "card",
          "class": "bg-white rounded-xl border border-slate-200 p-6 shadow-sm",
          "tailwind": "bg-white rounded-xl border border-slate-200 p-6 shadow-sm"
        },
        {
          "name": "circle",
          "class": "bg-slate-200 rounded-full w-10 h-10 skeleton-pulse",
          "tailwind": "bg-slate-200 rounded-full w-10 h-10 skeleton-pulse"
        }
      ],
      "sizes": [],
      "states": [
        "default",
        "loading",
        "loaded"
      ],
      "platformSemantics": {
        "elevation": "APP は製品テーマに合わせて影なしを明示選択できる。省略時は従来の影を維持する。影なし時は押下中も elevation.none のみを読み、sm/md を参照しない。Skeleton の text/circle はカードの elevation を参照しない。"
      },
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "skeleton",
          "platform": "app",
          "contractVersion": "2.0.0",
          "description": "RN 実装（src/components/Skeleton.tsx）の具象レシピ（styleRefs 形式）。text は行バー（複数行時は行間 gap spacing.2、最終行のみ width 70%）。circle は 40x40 固定。card は Surface 土台（bg-surface / radius.lg / elevation.sm / padding spacing.6 + borderWidth 1 border-default）の上に border-default のバー（height 12 / radius.sm）とアバター円（40x40）を gap spacing.3 / spacing.2 で構成。バー寸法（14 / 12 / 40 / %幅）は token に対応が無く literal。states.loading は pulse アニメーション（opacity 1↔0.4 を motion.duration.slow で loop、reduce-motion ON 時は完全停止で opacity 1 固定 + busy 維持）。loaded は Skeleton 自体をアンマウント（style 差分なし）。 elevation prop は default（省略時）または none。none は全状態で elevation.none を使う。",
          "variants": {
            "text": {
              "style": {
                "height": 14,
                "borderRadius": {
                  "token": "radius.sm"
                },
                "backgroundColor": {
                  "token": "color.semantic.light.border-default"
                },
                "gap": {
                  "token": "spacing.2"
                }
              }
            },
            "circle": {
              "style": {
                "width": 40,
                "height": 40,
                "borderRadius": {
                  "token": "radius.full"
                },
                "backgroundColor": {
                  "token": "color.semantic.light.border-default"
                }
              }
            },
            "card": {
              "style": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderRadius": {
                  "token": "radius.lg"
                },
                "borderWidth": 1,
                "borderColor": {
                  "token": "color.semantic.light.border-default"
                },
                "padding": {
                  "token": "spacing.6"
                },
                "elevation": {
                  "token": "elevation.sm"
                }
              },
              "barStyle": {
                "height": 12,
                "borderRadius": {
                  "token": "radius.sm"
                },
                "backgroundColor": {
                  "token": "color.semantic.light.border-default"
                }
              }
            }
          },
          "sizes": {},
          "states": {
            "loading": {
              "style": {
                "opacity": 0.4
              },
              "animation": {
                "opacityFrom": 1,
                "opacityTo": 0.4,
                "duration": {
                  "token": "motion.duration.slow"
                }
              }
            },
            "loaded": {
              "style": {}
            }
          },
          "elevationOptions": {
            "default": {
              "description": "既存variant/stateのelevationを維持"
            },
            "none": {
              "style": {
                "elevation": {
                  "token": "elevation.none"
                }
              }
            }
          }
        }
      },
      "accessibility": {
        "role": "status",
        "required": [
          "aria-busy=\"true\"",
          "aria-label=\"読み込み中\""
        ],
        "focusRing": "N/A"
      },
      "prohibited": [
        "スクリーンリーダーがローディング状態を認識できない",
        "ローディング完了が伝わらない",
        "DS統一から外れる",
        "進捗が伝わらず不安を与える",
        "prefers-reduced-motion 無視はアクセシビリティ違反"
      ],
      "htmlSample": "<div aria-busy=\"true\" role=\"status\" aria-label=\"読み込み中\" class=\"bg-slate-200 rounded-md h-4 w-full skeleton-pulse\"></div>"
    },
    {
      "id": "stack",
      "name": "Stack",
      "category": "layout",
      "description": "子要素を縦に積む layout primitive。gap は spacing token キー限定の prop（省略時 gap なし）。画面の縦リズムを生 flexbox 手書きから置き換える（dogfood 不足-1）。",
      "docPath": "components/stack.md",
      "anatomy": [
        "container"
      ],
      "variants": [
        {
          "name": "default",
          "class": "",
          "tailwind": ""
        }
      ],
      "sizes": [],
      "states": [
        "default"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "stack",
          "platform": "app",
          "contractVersion": "0.1.0",
          "description": "RN 実装（src/primitives/Stack.tsx）の具象レシピ（styleRefs 形式）。縦積み View。gap は prop（spacing token キー限定、省略時は gap を出力しない）、align は prop（start|center|end|stretch → alignItems、default stretch = style 出力なし）。token 依存の固定値を持たないため style は flexDirection のみ。",
          "variants": {
            "default": {
              "style": {
                "flexDirection": "column"
              }
            }
          },
          "sizes": {},
          "states": {}
        }
      },
      "accessibility": {
        "role": "none",
        "required": [],
        "focusRing": "N/A"
      },
      "prohibited": [],
      "htmlSample": ""
    },
    {
      "id": "stepper",
      "name": "Stepper",
      "category": "navigation",
      "description": "マルチステッププロセスの進捗表示。Completed / Active / Upcoming の3状態。",
      "docPath": "components/stepper.md",
      "anatomy": [
        "container",
        "step",
        "indicator",
        "label",
        "description?",
        "connector"
      ],
      "variants": [
        {
          "name": "horizontal",
          "class": "flex items-center",
          "tailwind": "flex items-center"
        },
        {
          "name": "vertical",
          "class": "space-y-0",
          "tailwind": "space-y-0"
        }
      ],
      "sizes": [
        {
          "name": "standard",
          "class": "w-8 h-8 text-sm",
          "tailwind": "w-8 h-8 text-sm",
          "height": "32px"
        },
        {
          "name": "compact",
          "class": "w-6 h-6 text-xs",
          "tailwind": "w-6 h-6 text-xs",
          "height": "24px"
        }
      ],
      "states": [
        "completed",
        "active",
        "upcoming"
      ],
      "appStatus": "planned",
      "accessibility": {
        "role": "list",
        "required": [
          "role=\"listitem\" per step",
          "aria-current=\"step\" (active)"
        ],
        "focusRing": "N/A"
      },
      "prohibited": [
        "色覚多様性への非対応",
        "スクリーンリーダーが現在ステップを識別できない",
        "タップターゲットが小さすぎる",
        "線が強すぎてノイズになる"
      ],
      "htmlSample": "<div role=\"list\" class=\"flex items-center\"><div role=\"listitem\" class=\"flex items-center\"><div class=\"w-8 h-8 rounded-full bg-primary-500 text-white inline-flex items-center justify-center text-sm\"><span class=\"sr-only\">完了:</span><svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" stroke-width=\"2\" aria-hidden=\"true\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M5 13l4 4L19 7\"/></svg></div></div><div class=\"flex-1 h-0.5 mx-3 bg-primary-500\"></div><div role=\"listitem\"><div class=\"w-8 h-8 rounded-full border-2 border-primary-500 bg-white text-primary-500 font-semibold inline-flex items-center justify-center text-sm\" aria-current=\"step\">2</div></div></div>"
    },
    {
      "id": "surface",
      "name": "Surface",
      "category": "layout",
      "description": "Card / Skeleton / EmptyState の共通土台となる箱 primitive（bg / radius / elevation / padding）。melta-app では internal（未 export）。",
      "docPath": "components/surface.md",
      "anatomy": [
        "container"
      ],
      "variants": [
        {
          "name": "default",
          "class": "",
          "tailwind": ""
        }
      ],
      "sizes": [],
      "states": [
        "default"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "surface",
          "platform": "app",
          "contractVersion": "0.1.0",
          "description": "RN 実装（src/components/Surface.tsx）の具象レシピ（styleRefs 形式）。melta-app 内部専用（未 export）。default variant の値は prop デフォルト（bg=bg-surface / radius=lg / elevation=none、padding はデフォルト無し）。props は token キー限定で上書き可能（bg: SemanticColors キー / radius: radius.* / elevation: elevation.* / padding: spacing.*）。elevation は iOS shadow* + Android elevation の複合トークン。",
          "variants": {
            "default": {
              "style": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderRadius": {
                  "token": "radius.lg"
                },
                "elevation": {
                  "token": "elevation.none"
                }
              }
            }
          },
          "sizes": {},
          "states": {}
        }
      },
      "accessibility": {
        "role": "none",
        "required": [],
        "focusRing": "N/A"
      },
      "prohibited": [],
      "htmlSample": ""
    },
    {
      "id": "table",
      "name": "Table",
      "category": "data-display",
      "description": "データテーブル。th scope=\"col\"必須。",
      "docPath": "components/table.md",
      "anatomy": {
        "wrapper": {
          "description": "角丸ボーダーのコンテナ。",
          "element": "div",
          "tailwind": "bg-white rounded-xl border border-slate-200 overflow-hidden",
          "class": "bg-white rounded-xl border border-slate-200 overflow-hidden"
        },
        "caption": {
          "description": "テーブル説明(推奨)。SR 向け。",
          "element": "caption"
        },
        "th": {
          "description": "列見出し。scope=\"col\" 必須(TABLE_TH_SCOPE_REQUIRED)。sortable variant では aria-sort=\"none|ascending|descending\" を付与しクリック/Enter でトグル、ラベル+方向アイコンを inline-flex。",
          "element": "th",
          "roles": "scope=\"col\"",
          "tailwind": "text-left py-3 px-4 text-xs font-medium text-slate-500 uppercase tracking-wider",
          "class": "text-left py-3 px-4 text-xs font-medium text-slate-500 uppercase tracking-wider"
        },
        "row": {
          "description": "tbody 行。hover ハイライト。",
          "element": "tr",
          "tailwind": "hover:bg-gray-50 transition-colors",
          "class": "hover:bg-gray-50 transition-colors"
        },
        "td": {
          "description": "データセル。",
          "element": "td",
          "tailwind": "py-3 px-4 text-sm text-slate-900",
          "class": "py-3 px-4 text-sm text-slate-900"
        }
      },
      "variants": [
        {
          "name": "basic",
          "class": "w-full",
          "tailwind": "w-full"
        },
        {
          "name": "sortable",
          "class": "w-full",
          "tailwind": "w-full"
        }
      ],
      "sizes": [],
      "states": [
        "default",
        "hover",
        "empty"
      ],
      "stateSpecs": {
        "empty": {
          "description": "0件。空状態行を表示。全 variant 共通。",
          "tailwind": "",
          "htmlNote": "<tbody> 内に colspan 全列結合の1行で中央寄せ「データがありません」。",
          "class": ""
        }
      },
      "appStatus": "not-planned",
      "appNote": "モバイルは単列リスト / Card への再構成が定石（M3 に data table なし）。list + metric で分解表現する",
      "accessibility": {
        "role": "table",
        "required": [
          "<th scope=\"col\">",
          "caption (recommended)"
        ],
        "focusRing": "focus-visible:ring-2 focus-visible:ring-primary-500/50"
      },
      "prohibited": [
        "ヘッダーとデータの関係が不明確",
        "セマンティクス違反"
      ],
      "htmlSample": {
        "basic": "<div class=\"bg-white rounded-xl border border-slate-200 overflow-hidden\"><table class=\"w-full\"><thead class=\"border-b border-slate-200 bg-gray-50\"><tr><th scope=\"col\" class=\"text-left py-3 px-4 text-xs font-medium text-slate-500 uppercase tracking-wider\">名前</th></tr></thead><tbody><tr class=\"hover:bg-gray-50 transition-colors\"><td class=\"py-3 px-4 text-sm text-slate-900\">値</td></tr></tbody></table></div>"
      }
    },
    {
      "id": "tabs",
      "name": "Tabs",
      "category": "navigation",
      "description": "コンテンツ切り替えタブ。underline（下線）/ bar（丸角バー）の2バリアント。キーボードナビ対応。",
      "docPath": "components/tabs.md",
      "anatomy": [
        "tabList",
        "tab",
        "tabPanel",
        "indicator"
      ],
      "variants": [
        {
          "name": "underline-active",
          "class": "px-4 py-2.5 text-sm font-semibold text-primary-500 border-b-2 border-primary-500 cursor-default",
          "tailwind": "px-4 py-2.5 text-sm font-semibold text-primary-500 border-b-2 border-primary-500 cursor-default"
        },
        {
          "name": "underline-inactive",
          "class": "px-4 py-2.5 text-sm font-medium text-slate-500 border-b-2 border-transparent hover:text-slate-700 cursor-pointer",
          "tailwind": "px-4 py-2.5 text-sm font-medium text-slate-500 border-b-2 border-transparent hover:text-slate-700 cursor-pointer"
        },
        {
          "name": "bar-active",
          "class": "flex-1 relative flex items-center justify-center py-4 text-sm font-semibold text-slate-900 hover:bg-slate-100 cursor-pointer",
          "tailwind": "flex-1 relative flex items-center justify-center py-4 text-sm font-semibold text-slate-900 hover:bg-slate-100 cursor-pointer"
        },
        {
          "name": "bar-inactive",
          "class": "flex-1 relative flex items-center justify-center py-4 text-sm font-medium text-slate-400 hover:text-slate-600 hover:bg-slate-100 cursor-pointer",
          "tailwind": "flex-1 relative flex items-center justify-center py-4 text-sm font-medium text-slate-400 hover:text-slate-600 hover:bg-slate-100 cursor-pointer"
        }
      ],
      "sizes": [],
      "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\"（フォーカス・選択不可）。",
          "class": "opacity-50 cursor-not-allowed pointer-events-none"
        }
      },
      "appStatus": "planned",
      "appMapping": "adapted",
      "appNote": "トップタブ / SegmentedControl 型として実装（web の下線タブ意味論を M3 segmented / iOS UISegmentedControl に写像）",
      "accessibility": {
        "role": "tab / tablist / tabpanel",
        "required": [
          "aria-selected",
          "aria-controls",
          "tabindex management"
        ],
        "focusRing": "focus-visible:ring-2 focus-visible:ring-primary-500/50"
      },
      "prohibited": [],
      "htmlSample": {
        "underline": "<div role=\"tablist\" class=\"flex border-b border-slate-200\"><button role=\"tab\" aria-selected=\"true\" class=\"px-4 py-2.5 text-sm font-semibold text-primary-500 border-b-2 border-primary-500\">タブ1</button><button role=\"tab\" aria-selected=\"false\" tabindex=\"-1\" class=\"px-4 py-2.5 text-sm font-medium text-slate-500 border-b-2 border-transparent hover:text-slate-700\">タブ2</button></div>",
        "bar": "<div role=\"tablist\" class=\"flex border-b border-slate-200\"><button role=\"tab\" aria-selected=\"true\" class=\"flex-1 relative flex items-center justify-center py-4 text-sm font-semibold text-slate-900 hover:bg-slate-100 cursor-pointer\">タブ1<span style=\"position:absolute;bottom:0;left:50%;transform:translateX(-50%);width:56px;height:4px;background:var(--color-primary-500);border-radius:2px\"></span></button><button role=\"tab\" aria-selected=\"false\" tabindex=\"-1\" class=\"flex-1 relative flex items-center justify-center py-4 text-sm font-medium text-slate-400 hover:text-slate-600 hover:bg-slate-100 cursor-pointer\">タブ2</button></div>"
      }
    },
    {
      "id": "tag",
      "name": "Tag",
      "category": "data-display",
      "description": "削除可能なタグ / フィルターチップ。",
      "docPath": "components/tag.md",
      "anatomy": [
        "container",
        "labelText",
        "removeButton?",
        "checkmarkIcon?"
      ],
      "variants": [
        {
          "name": "basic",
          "class": "inline-flex items-center gap-1 px-3 py-1 rounded-full text-xs font-medium bg-slate-100 text-slate-700",
          "tailwind": "inline-flex items-center gap-1 px-3 py-1 rounded-full text-xs font-medium bg-slate-100 text-slate-700"
        },
        {
          "name": "removable",
          "class": "inline-flex items-center gap-1 px-3 py-1 rounded-full text-xs font-medium bg-slate-100 text-slate-700",
          "tailwind": "inline-flex items-center gap-1 px-3 py-1 rounded-full text-xs font-medium bg-slate-100 text-slate-700"
        },
        {
          "name": "filter-chip",
          "class": "inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-sm border border-slate-200 cursor-pointer bg-white text-slate-700",
          "tailwind": "inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-sm border border-slate-200 cursor-pointer bg-white text-slate-700"
        }
      ],
      "sizes": [],
      "states": [
        "default",
        "active",
        "inactive",
        "hover",
        "focus"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "tag",
          "platform": "app",
          "contractVersion": "2.0.0",
          "description": "RN 実装（src/primitives/Tag.tsx）の具象レシピ（styleRefs 形式）。states.active / inactive は filter-chip variant のみに適用（contract states active/inactive → prop selected:boolean）。inactive は filter-chip の variant style そのまま（差分なし）。removable の削除ボタンは text-muted の xs テキスト + minWidth/minHeight 24 + hitSlop 10（最小タップターゲット確保、literal）。focus は FocusRing overlay（borderWidth 2 / color.primary.500 / inset -3、filter-chip と removable の削除ボタンのみ）。",
          "variants": {
            "basic": {
              "style": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-page-alt"
                },
                "paddingHorizontal": {
                  "token": "spacing.3"
                },
                "paddingVertical": {
                  "token": "spacing.1"
                },
                "gap": {
                  "token": "spacing.1"
                },
                "borderRadius": {
                  "token": "radius.full"
                }
              },
              "textStyle": {
                "fontSize": {
                  "token": "typography.fontSize.xs"
                },
                "color": {
                  "token": "color.semantic.light.text-default"
                }
              }
            },
            "removable": {
              "style": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-page-alt"
                },
                "paddingHorizontal": {
                  "token": "spacing.3"
                },
                "paddingVertical": {
                  "token": "spacing.1"
                },
                "gap": {
                  "token": "spacing.1"
                },
                "borderRadius": {
                  "token": "radius.full"
                }
              },
              "textStyle": {
                "fontSize": {
                  "token": "typography.fontSize.xs"
                },
                "color": {
                  "token": "color.semantic.light.text-default"
                }
              }
            },
            "filter-chip": {
              "style": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderWidth": 1,
                "borderColor": {
                  "token": "color.semantic.light.border-default"
                },
                "paddingHorizontal": {
                  "token": "spacing.3"
                },
                "paddingVertical": {
                  "token": "spacing.1"
                },
                "gap": {
                  "token": "spacing.1"
                },
                "borderRadius": {
                  "token": "radius.full"
                }
              },
              "textStyle": {
                "fontSize": {
                  "token": "typography.fontSize.sm"
                },
                "color": {
                  "token": "color.semantic.light.text-default"
                }
              }
            }
          },
          "sizes": {},
          "states": {
            "active": {
              "style": {
                "backgroundColor": {
                  "token": "color.primary.50"
                },
                "borderColor": {
                  "token": "color.primary.200"
                }
              },
              "textStyle": {
                "color": {
                  "token": "color.primary.700"
                }
              }
            },
            "inactive": {
              "style": {}
            },
            "focus": {
              "style": {
                "borderWidth": 2,
                "borderColor": {
                  "token": "color.primary.500"
                }
              }
            }
          }
        }
      },
      "accessibility": {
        "role": "button (removable)",
        "required": [
          "aria-label (remove button)",
          "aria-selected (filter chip)"
        ],
        "focusRing": "focus:ring-2 focus:ring-primary-500/50"
      },
      "prohibited": [
        "スクリーンリーダーがボタンの目的を読み上げられない",
        "キーボードのみでは削除操作を発見できない",
        "モバイルで誤タップが頻発する。横断方針は A11Y_MIN_TAP_TARGET_44 が正。本ルールはその web（tag の × ボタン）実装形",
        "選択状態がスクリーンリーダーに伝わらない",
        "Badge はステータス表示、Tag はユーザー管理メタデータ"
      ],
      "htmlSample": "<div class=\"inline-flex items-center gap-1 px-3 py-1 rounded-full text-xs font-medium bg-slate-100 text-slate-700\"><span>タグ</span><button aria-label=\"削除\" class=\"text-slate-500 hover:text-slate-700\">×</button></div>"
    },
    {
      "id": "text",
      "name": "Text",
      "category": "data-display",
      "description": "本文・見出し・キャプションの基本テキスト primitive。fontSize variant と semantic color、heading/body で letterSpacing を切替。",
      "docPath": "components/text.md",
      "anatomy": [
        "textNode"
      ],
      "variants": [
        {
          "name": "xxs",
          "class": "",
          "tailwind": ""
        },
        {
          "name": "xs",
          "class": "",
          "tailwind": ""
        },
        {
          "name": "sm",
          "class": "",
          "tailwind": ""
        },
        {
          "name": "base",
          "class": "",
          "tailwind": ""
        },
        {
          "name": "lg",
          "class": "",
          "tailwind": ""
        },
        {
          "name": "xl",
          "class": "",
          "tailwind": ""
        },
        {
          "name": "2xl",
          "class": "",
          "tailwind": ""
        },
        {
          "name": "3xl",
          "class": "",
          "tailwind": ""
        }
      ],
      "sizes": [],
      "states": [
        "default"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "text",
          "platform": "app",
          "contractVersion": "0.2.0",
          "description": "RN 実装（src/primitives/Text.tsx）の具象レシピ（styleRefs 形式）。variant = fontSize 段階。fontSize token は fontSize/lineHeight の複合値として解決する。letterSpacing は typography.letterSpacing.{heading|body}（em 比率）を fontSize から pt 換算して適用（role prop で切替、default body）。文字色は prop（semantic token キー限定、default color.semantic.light.text-default）、weight も prop（typography.fontWeight.* キー限定）で、variant には依存しない。",
          "variants": {
            "xxs": {
              "style": {
                "fontSize": {
                  "token": "typography.fontSize.xxs"
                },
                "letterSpacing": {
                  "token": "typography.letterSpacing.body"
                }
              }
            },
            "xs": {
              "style": {
                "fontSize": {
                  "token": "typography.fontSize.xs"
                },
                "letterSpacing": {
                  "token": "typography.letterSpacing.body"
                }
              }
            },
            "sm": {
              "style": {
                "fontSize": {
                  "token": "typography.fontSize.sm"
                },
                "letterSpacing": {
                  "token": "typography.letterSpacing.body"
                }
              }
            },
            "base": {
              "style": {
                "fontSize": {
                  "token": "typography.fontSize.base"
                },
                "letterSpacing": {
                  "token": "typography.letterSpacing.body"
                }
              }
            },
            "lg": {
              "style": {
                "fontSize": {
                  "token": "typography.fontSize.lg"
                },
                "letterSpacing": {
                  "token": "typography.letterSpacing.body"
                }
              }
            },
            "xl": {
              "style": {
                "fontSize": {
                  "token": "typography.fontSize.xl"
                },
                "letterSpacing": {
                  "token": "typography.letterSpacing.body"
                }
              }
            },
            "2xl": {
              "style": {
                "fontSize": {
                  "token": "typography.fontSize.2xl"
                },
                "letterSpacing": {
                  "token": "typography.letterSpacing.body"
                }
              }
            },
            "3xl": {
              "style": {
                "fontSize": {
                  "token": "typography.fontSize.3xl"
                },
                "letterSpacing": {
                  "token": "typography.letterSpacing.body"
                }
              }
            }
          },
          "sizes": {},
          "states": {}
        }
      },
      "accessibility": {
        "role": "text",
        "required": [
          "見出しは heading role（RN: accessibilityRole=\"header\"）を付与する"
        ],
        "focusRing": "N/A"
      },
      "prohibited": [],
      "htmlSample": ""
    },
    {
      "id": "textfield",
      "name": "TextField",
      "category": "form-input",
      "description": "テキスト入力フィールド。Default / Error / Disabled / Success の4状態。",
      "docPath": "components/textfield.md",
      "anatomy": [
        "label",
        "input",
        "helperText?",
        "errorMessage?"
      ],
      "variants": [
        {
          "name": "default",
          "class": "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",
          "tailwind": "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"
        },
        {
          "name": "error",
          "class": "w-full px-3 py-2 text-base border border-red-300 rounded-lg focus:ring-2 focus:ring-red-600/50 bg-red-50",
          "tailwind": "w-full px-3 py-2 text-base border border-red-300 rounded-lg focus:ring-2 focus:ring-red-600/50 bg-red-50"
        },
        {
          "name": "disabled",
          "class": "w-full px-3 py-2 text-base border border-slate-200 rounded-lg bg-slate-100 text-slate-400 cursor-not-allowed",
          "tailwind": "w-full px-3 py-2 text-base border border-slate-200 rounded-lg bg-slate-100 text-slate-400 cursor-not-allowed"
        },
        {
          "name": "success",
          "class": "w-full px-3 py-2 text-base border border-emerald-300 rounded-lg focus:ring-2 focus:ring-emerald-500/50",
          "tailwind": "w-full px-3 py-2 text-base border border-emerald-300 rounded-lg focus:ring-2 focus:ring-emerald-500/50"
        }
      ],
      "sizes": [
        {
          "name": "small",
          "class": "px-3 py-1.5 text-sm",
          "tailwind": "px-3 py-1.5 text-sm",
          "height": "36px"
        },
        {
          "name": "medium",
          "class": "px-3 py-2 text-base",
          "tailwind": "px-3 py-2 text-base",
          "height": "42px"
        },
        {
          "name": "large",
          "class": "px-3 py-2.5 text-lg",
          "tailwind": "px-3 py-2.5 text-lg",
          "height": "48px"
        }
      ],
      "states": [
        "default",
        "hover",
        "focus",
        "error",
        "disabled",
        "success"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "textfield",
          "platform": "app",
          "contractVersion": "2.0.0",
          "description": "RN 実装（src/components/TextField.tsx）の具象レシピ（styleRefs 形式）。variant は入力の検証状態（default/error/success/disabled = 契約の variant 語彙）。labelStyle/helperTextStyle/errorTextStyle は variant 非依存の共通部として default にのみ載せる（実装 resolver は全 variant で同じものを返す）。focus は state 差分（borderColor のみ。web の ring は RN 非対応、border 幅を変えるとレイアウトシフトするため色だけ）。disabled のテキスト色は text-muted（実装は editable=false + accessibilityState.disabled）。sizes の縦寸法は height ではなく minHeight（RN の fontScale で入力テキストが拡大したときに 1 行がクリップされないための下限。視覚寸法は既定 fontScale=1 で従来と同じ）。",
          "variants": {
            "default": {
              "inputStyle": {
                "borderWidth": 1,
                "borderColor": {
                  "token": "color.semantic.light.input-border"
                },
                "backgroundColor": {
                  "token": "color.semantic.light.input-bg"
                },
                "borderRadius": {
                  "token": "radius.md"
                }
              },
              "labelStyle": {
                "fontSize": {
                  "token": "typography.fontSize.sm"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.medium"
                },
                "color": {
                  "token": "color.semantic.light.text-heading"
                },
                "marginBottom": {
                  "token": "spacing.2"
                }
              },
              "helperTextStyle": {
                "fontSize": {
                  "token": "typography.fontSize.xs"
                },
                "color": {
                  "token": "color.semantic.light.text-muted"
                },
                "marginTop": {
                  "token": "spacing.1"
                }
              },
              "errorTextStyle": {
                "fontSize": {
                  "token": "typography.fontSize.xs"
                },
                "color": {
                  "token": "color.status.danger.text-light"
                },
                "marginTop": {
                  "token": "spacing.1"
                }
              }
            },
            "error": {
              "inputStyle": {
                "borderWidth": 1,
                "borderColor": {
                  "token": "color.status.danger.base"
                },
                "backgroundColor": {
                  "token": "color.status.danger.subtle-light"
                },
                "borderRadius": {
                  "token": "radius.md"
                }
              }
            },
            "success": {
              "inputStyle": {
                "borderWidth": 1,
                "borderColor": {
                  "token": "color.status.success.base"
                },
                "backgroundColor": {
                  "token": "color.semantic.light.input-bg"
                },
                "borderRadius": {
                  "token": "radius.md"
                }
              }
            },
            "disabled": {
              "inputStyle": {
                "borderWidth": 1,
                "borderColor": {
                  "token": "color.semantic.light.border-default"
                },
                "backgroundColor": {
                  "token": "color.semantic.light.bg-page-alt"
                },
                "borderRadius": {
                  "token": "radius.md"
                }
              }
            }
          },
          "sizes": {
            "small": {
              "inputStyle": {
                "minHeight": 36,
                "paddingHorizontal": {
                  "token": "spacing.3"
                },
                "fontSize": {
                  "token": "typography.fontSize.sm"
                }
              }
            },
            "medium": {
              "inputStyle": {
                "minHeight": 42,
                "paddingHorizontal": {
                  "token": "spacing.3"
                },
                "fontSize": {
                  "token": "typography.fontSize.base"
                }
              }
            },
            "large": {
              "inputStyle": {
                "minHeight": 48,
                "paddingHorizontal": {
                  "token": "spacing.3"
                },
                "fontSize": {
                  "token": "typography.fontSize.lg"
                }
              }
            }
          },
          "states": {
            "focus": {
              "inputStyle": {
                "borderColor": {
                  "token": "color.primary.500"
                }
              }
            }
          }
        }
      },
      "accessibility": {
        "role": "textbox",
        "required": [
          "label association",
          "aria-invalid (error state)",
          "aria-describedby (error message)"
        ],
        "focusRing": "focus:ring-2 focus:ring-primary-500/50"
      },
      "prohibited": [
        "入力開始で消え、目的がわからなくなる",
        "スクリーンリーダーが目的を読み上げられない",
        "色覚多様性への非対応",
        "フィールドとの対応がわからない"
      ],
      "htmlSample": {
        "default": "<div class=\"leading-normal\"><label class=\"block text-sm font-medium text-slate-900 mb-1.5\">メール</label><input type=\"email\" class=\"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\" placeholder=\"user@example.com\"></div>",
        "error": "<div class=\"leading-normal\"><label class=\"block text-sm font-medium text-slate-900 mb-1.5\">メール</label><input type=\"email\" aria-invalid=\"true\" aria-describedby=\"email-error\" class=\"w-full px-3 py-2 text-base border border-red-300 rounded-lg focus:ring-2 focus:ring-red-600/50 bg-red-50\"><p id=\"email-error\" class=\"text-sm text-red-600 mt-1\">有効なメールアドレスを入力してください</p></div>"
      }
    },
    {
      "id": "toast",
      "name": "Toast",
      "category": "feedback",
      "description": "一時的な通知メッセージ。4タイプ（success/error/warning/info）。",
      "docPath": "components/toast.md",
      "anatomy": [
        "container",
        "statusIcon",
        "message",
        "description?",
        "closeButton",
        "actionButton?",
        "progressBar?"
      ],
      "variants": [
        {
          "name": "success",
          "class": "flex items-center gap-3 bg-emerald-50 border border-emerald-200 text-emerald-800 rounded-lg p-4",
          "tailwind": "flex items-center gap-3 bg-emerald-50 border border-emerald-200 text-emerald-800 rounded-lg p-4"
        },
        {
          "name": "error",
          "class": "flex items-center gap-3 bg-red-50 border border-red-200 text-red-800 rounded-lg p-4",
          "tailwind": "flex items-center gap-3 bg-red-50 border border-red-200 text-red-800 rounded-lg p-4"
        },
        {
          "name": "warning",
          "class": "flex items-center gap-3 bg-amber-50 border border-amber-200 text-amber-800 rounded-lg p-4",
          "tailwind": "flex items-center gap-3 bg-amber-50 border border-amber-200 text-amber-800 rounded-lg p-4"
        },
        {
          "name": "info",
          "class": "flex items-center gap-3 bg-primary-50 border border-primary-200 text-primary-800 rounded-lg p-4",
          "tailwind": "flex items-center gap-3 bg-primary-50 border border-primary-200 text-primary-800 rounded-lg p-4"
        }
      ],
      "sizes": [],
      "states": [
        "default",
        "entering",
        "visible",
        "dismissing",
        "hover"
      ],
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "toast",
          "platform": "app",
          "contractVersion": "2.0.0",
          "description": "RN 実装（src/components/Toast.tsx）の具象レシピ（styleRefs 形式）。Alert と同系の bg subtle + text 色に elevation.sm を重ねる（浮いている通知）。表示位置・キュー・自動消滅はアプリ層の責務（presentational component として実装し、entering/visible/dismissing のアニメ state は Phase 外 = states 空で宣言。hover は RN 非対応）。closeButton は Pressable + テキスト ×（accessibilityLabel=\"閉じる\" 必須）。dark mode は resolver が subtle-dark / text-dark を解決（info のみ primary 固定、alert と同じ割り切り）。",
          "variants": {
            "success": {
              "containerStyle": {
                "backgroundColor": {
                  "token": "color.status.success.subtle-light"
                },
                "borderRadius": {
                  "token": "radius.md"
                },
                "padding": {
                  "token": "spacing.4"
                },
                "flexDirection": "row",
                "alignItems": "center",
                "gap": {
                  "token": "spacing.3"
                },
                "elevation": {
                  "token": "elevation.sm"
                }
              },
              "messageStyle": {
                "color": {
                  "token": "color.status.success.text-light"
                },
                "fontSize": {
                  "token": "typography.fontSize.sm"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.medium"
                }
              }
            },
            "error": {
              "containerStyle": {
                "backgroundColor": {
                  "token": "color.status.danger.subtle-light"
                },
                "borderRadius": {
                  "token": "radius.md"
                },
                "padding": {
                  "token": "spacing.4"
                },
                "flexDirection": "row",
                "alignItems": "center",
                "gap": {
                  "token": "spacing.3"
                },
                "elevation": {
                  "token": "elevation.sm"
                }
              },
              "messageStyle": {
                "color": {
                  "token": "color.status.danger.text-light"
                },
                "fontSize": {
                  "token": "typography.fontSize.sm"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.medium"
                }
              }
            },
            "warning": {
              "containerStyle": {
                "backgroundColor": {
                  "token": "color.status.warning.subtle-light"
                },
                "borderRadius": {
                  "token": "radius.md"
                },
                "padding": {
                  "token": "spacing.4"
                },
                "flexDirection": "row",
                "alignItems": "center",
                "gap": {
                  "token": "spacing.3"
                },
                "elevation": {
                  "token": "elevation.sm"
                }
              },
              "messageStyle": {
                "color": {
                  "token": "color.status.warning.text-light"
                },
                "fontSize": {
                  "token": "typography.fontSize.sm"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.medium"
                }
              }
            },
            "info": {
              "containerStyle": {
                "backgroundColor": {
                  "token": "color.primary.50"
                },
                "borderRadius": {
                  "token": "radius.md"
                },
                "padding": {
                  "token": "spacing.4"
                },
                "flexDirection": "row",
                "alignItems": "center",
                "gap": {
                  "token": "spacing.3"
                },
                "elevation": {
                  "token": "elevation.sm"
                }
              },
              "messageStyle": {
                "color": {
                  "token": "color.primary.800"
                },
                "fontSize": {
                  "token": "typography.fontSize.sm"
                },
                "fontWeight": {
                  "token": "typography.fontWeight.medium"
                }
              }
            }
          },
          "sizes": {},
          "states": {}
        }
      },
      "accessibility": {
        "role": "status",
        "required": [
          "aria-live=\"polite\"",
          "aria-atomic=\"true\""
        ],
        "focusRing": "N/A"
      },
      "prohibited": [],
      "htmlSample": "<div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" class=\"flex items-center gap-3 bg-emerald-50 border border-emerald-200 text-emerald-800 rounded-lg p-4\"><span class=\"text-sm font-medium\">保存しました</span></div>"
    },
    {
      "id": "toggle",
      "name": "Toggle",
      "category": "form-input",
      "description": "ON/OFFスイッチコンポーネント。role=\"switch\"必須。",
      "docPath": "components/toggle.md",
      "anatomy": [
        "track",
        "thumb",
        "label",
        "description?",
        "statusText?"
      ],
      "variants": [
        {
          "name": "off",
          "class": "relative inline-flex h-6 w-11 items-center rounded-full bg-slate-300",
          "tailwind": "relative inline-flex h-6 w-11 items-center rounded-full bg-slate-300"
        },
        {
          "name": "on",
          "class": "relative inline-flex h-6 w-11 items-center rounded-full bg-primary-500",
          "tailwind": "relative inline-flex h-6 w-11 items-center rounded-full bg-primary-500"
        }
      ],
      "sizes": [
        {
          "name": "medium",
          "class": "h-6 w-11",
          "tailwind": "h-6 w-11",
          "height": "24px"
        },
        {
          "name": "large",
          "class": "h-7 w-14",
          "tailwind": "h-7 w-14",
          "height": "28px"
        }
      ],
      "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 は現状態を保持。",
          "class": "opacity-50 cursor-not-allowed pointer-events-none"
        }
      },
      "appStatus": "implemented",
      "recipes": {
        "app": {
          "$schema": "../../../schemas/recipe.schema.json",
          "id": "toggle",
          "platform": "app",
          "contractVersion": "2.0.0",
          "description": "RN 実装（src/components/Toggle.tsx）の具象レシピ（styleRefs 形式）。RN Switch は token 制御（track/thumb 色 + サイズ段階）が弱いため custom（Pressable の track + 内側 thumb）で実装する。variant = variantModeledStates（off/on）。thumb は track 内で thumbOffset(2) 浮かせ、on 時は右端へ寄せる（left = trackWidth - thumbSize - thumbOffset）。disabled は state 差分（opacity、accessibilityState.disabled）。a11y: accessibilityRole=\"switch\" + accessibilityState.checked。",
          "variants": {
            "off": {
              "trackStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.border-strong"
                },
                "borderRadius": {
                  "token": "radius.full"
                }
              },
              "thumbStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderRadius": {
                  "token": "radius.full"
                }
              }
            },
            "on": {
              "trackStyle": {
                "backgroundColor": {
                  "token": "color.primary.500"
                },
                "borderRadius": {
                  "token": "radius.full"
                }
              },
              "thumbStyle": {
                "backgroundColor": {
                  "token": "color.semantic.light.bg-surface"
                },
                "borderRadius": {
                  "token": "radius.full"
                }
              }
            }
          },
          "sizes": {
            "medium": {
              "trackStyle": {
                "width": 44,
                "height": 24
              },
              "thumbStyle": {
                "width": 20,
                "height": 20
              },
              "thumbOffset": 2
            },
            "large": {
              "trackStyle": {
                "width": 56,
                "height": 28
              },
              "thumbStyle": {
                "width": 24,
                "height": 24
              },
              "thumbOffset": 2
            }
          },
          "states": {
            "disabled": {
              "style": {
                "opacity": 0.5
              }
            }
          }
        }
      },
      "accessibility": {
        "role": "switch",
        "required": [
          "aria-checked",
          "label association"
        ],
        "focusRing": "focus:ring-2 focus:ring-primary-500/50"
      },
      "prohibited": [],
      "htmlSample": "<label class=\"flex items-center gap-3 cursor-pointer\"><div role=\"switch\" aria-checked=\"false\" class=\"relative inline-flex h-6 w-11 items-center rounded-full bg-slate-300\"><span class=\"inline-block h-5 w-5 transform rounded-full bg-white transition\"></span></div><span class=\"text-base text-body\">通知</span></label>"
    },
    {
      "id": "tooltip",
      "name": "Tooltip",
      "category": "feedback",
      "description": "ホバー/フォーカスで表示される補足情報。max-width: 20rem。",
      "docPath": "components/tooltip.md",
      "anatomy": [
        "container",
        "text"
      ],
      "variants": [
        {
          "name": "top",
          "class": "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 bg-slate-600 text-white text-sm rounded-lg shadow-sm px-3 py-2 max-w-xs",
          "tailwind": "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 bg-slate-600 text-white text-sm rounded-lg shadow-sm px-3 py-2 max-w-xs"
        },
        {
          "name": "bottom",
          "class": "absolute top-full left-1/2 -translate-x-1/2 mt-2 bg-slate-600 text-white text-sm rounded-lg shadow-sm px-3 py-2 max-w-xs",
          "tailwind": "absolute top-full left-1/2 -translate-x-1/2 mt-2 bg-slate-600 text-white text-sm rounded-lg shadow-sm px-3 py-2 max-w-xs"
        },
        {
          "name": "left",
          "class": "absolute right-full top-1/2 -translate-y-1/2 mr-2 bg-slate-600 text-white text-sm rounded-lg shadow-sm px-3 py-2 max-w-xs",
          "tailwind": "absolute right-full top-1/2 -translate-y-1/2 mr-2 bg-slate-600 text-white text-sm rounded-lg shadow-sm px-3 py-2 max-w-xs"
        },
        {
          "name": "right",
          "class": "absolute left-full top-1/2 -translate-y-1/2 ml-2 bg-slate-600 text-white text-sm rounded-lg shadow-sm px-3 py-2 max-w-xs",
          "tailwind": "absolute left-full top-1/2 -translate-y-1/2 ml-2 bg-slate-600 text-white text-sm rounded-lg shadow-sm px-3 py-2 max-w-xs"
        }
      ],
      "sizes": [],
      "states": [
        "default",
        "visible",
        "hidden"
      ],
      "appStatus": "not-planned",
      "appNote": "hover 前提のため。iPhone HIG に tooltip 概念なし。必要になれば長押し Hint として別契約を切る",
      "accessibility": {
        "role": "tooltip",
        "required": [
          "aria-describedby on trigger",
          "id on tooltip"
        ],
        "focusRing": "N/A"
      },
      "prohibited": [],
      "htmlSample": "<div class=\"relative inline-block\"><button aria-describedby=\"tip-1\">?</button><div id=\"tip-1\" role=\"tooltip\" class=\"absolute bottom-full left-1/2 -translate-x-1/2 mb-2 bg-slate-600 text-white text-sm rounded-lg shadow-sm px-3 py-2 max-w-xs\">補足情報</div></div>"
    }
  ]
}
