{
  "schemaVersion": 2,
  "generatedAt": "2026-05-11T14:00:00+08:00",
  "title": "Design System: AI零售柜",
  "extensions": {
    "colorMeta": {
      "primary-yellow": {
        "role": "primary",
        "displayName": "Brand Yellow",
        "canonical": "#FFC107",
        "tonalRamp": [
          "#FFF8E1", "#FFECB3", "#FFE082", "#FFD54F",
          "#FFC107", "#FFB300", "#FFA000", "#FF8F00"
        ]
      },
      "neutral-ink": {
        "role": "neutral",
        "displayName": "Ink",
        "canonical": "#2C2C2C",
        "tonalRamp": [
          "#0A0A0A", "#1A1A1A", "#2C2C2C", "#404040",
          "#555555", "#8C8C8C", "#BDBDBD", "#EEEEEE"
        ]
      },
      "neutral-cream": {
        "role": "neutral",
        "displayName": "Cream",
        "canonical": "#FAFAFA",
        "tonalRamp": [
          "#E8E8E8", "#EEEEEE", "#F0F0F0", "#F5F5F5",
          "#FAFAFA", "#FCFCFC", "#FEFEFE", "#FFFFFF"
        ]
      }
    },
    "shadows": [
      { "name": "ambient", "value": "0 2rpx 8rpx rgba(0,0,0,0.04)", "purpose": "Subtle card grounding at rest." },
      { "name": "low", "value": "0 4rpx 16rpx rgba(0,0,0,0.06)", "purpose": "Default card elevation above cream background." },
      { "name": "mid", "value": "0 8rpx 32rpx rgba(0,0,0,0.08)", "purpose": "Elevated surfaces: login card, active modal." },
      { "name": "brand-glow", "value": "0 8rpx 24rpx rgba(255,193,7,0.25)", "purpose": "Scan button halo. The only colored shadow." }
    ],
    "motion": [
      { "name": "ease-fast", "value": "cubic-bezier(0.25, 0.1, 0.25, 1)", "purpose": "Micro-interactions, button state changes (150ms)." },
      { "name": "ease-standard", "value": "cubic-bezier(0.42, 0, 0.58, 1)", "purpose": "Page transitions, card entrances (300ms)." },
      { "name": "ease-enter", "value": "cubic-bezier(0, 0, 0.2, 1)", "purpose": "Slide-up entrances for modals and drawers." }
    ],
    "breakpoints": []
  },
  "components": [
    {
      "name": "Scan Button",
      "kind": "button",
      "refersTo": "button-primary",
      "description": "The hero button on the home page. 400rpx circle with Brand Yellow gradient, pulsing ripple, and brand-glow shadow.",
      "html": "<button class=\"ds-btn-scan\"><span class=\"ds-btn-scan-icon\">📷</span><span class=\"ds-btn-scan-text\">扫码开门</span></button>",
      "css": ".ds-btn-scan { width: 400rpx; height: 400rpx; border-radius: 50%; background: linear-gradient(135deg, #FFE082, #FFC107); border: none; box-shadow: 0 8rpx 24rpx rgba(255,193,7,0.25); display: flex; flex-direction: column; align-items: center; justify-content: center; cursor: pointer; transition: transform 0.3s cubic-bezier(0.25,0.1,0.25,1), box-shadow 0.3s ease; } .ds-btn-scan:active { transform: scale(0.95); box-shadow: 0 4rpx 16rpx rgba(255,193,7,0.3); } .ds-btn-scan-icon { font-size: 80rpx; margin-bottom: 4rpx; } .ds-btn-scan-text { font-size: 40rpx; font-weight: 600; color: #1A1A1A; letter-spacing: 4rpx; }"
    },
    {
      "name": "Primary Action Button",
      "kind": "button",
      "refersTo": "button-primary",
      "description": "Full-width pill button for primary actions like '开门购物' or '立即开通'.",
      "html": "<button class=\"ds-btn-primary\">开门购物</button>",
      "css": ".ds-btn-primary { width: 100%; height: 108rpx; background: linear-gradient(135deg, #FFD700, #FFC107, #FFB300); border: none; border-radius: 54rpx; color: #1A1A1A; font-size: 36rpx; font-weight: 600; letter-spacing: 8rpx; box-shadow: 0 12rpx 40rpx rgba(255,193,7,0.35), 0 4rpx 16rpx rgba(255,193,7,0.2); transition: transform 0.3s cubic-bezier(0.25,0.1,0.25,1), box-shadow 0.3s ease; } .ds-btn-primary:active { transform: translateY(-4rpx) scale(1.02); box-shadow: 0 16rpx 48rpx rgba(255,193,7,0.45); }"
    },
    {
      "name": "Ghost Button",
      "kind": "button",
      "refersTo": "button-ghost",
      "description": "Secondary action alongside primary. White fill, light border, used for '返回' and cancel actions.",
      "html": "<button class=\"ds-btn-ghost\">返回</button>",
      "css": ".ds-btn-ghost { background: #FFFFFF; border: 2rpx solid #EEEEEE; border-radius: 32rpx; color: #8C8C8C; font-size: 28rpx; font-weight: 500; padding: 16rpx 32rpx; transition: background 0.15s ease; } .ds-btn-ghost:active { background: #FAFAFA; }"
    },
    {
      "name": "Menu Item",
      "kind": "custom",
      "refersTo": "menu-item",
      "description": "List row with icon, label, optional badge, and right-facing chevron. Used in 我的 and settings screens.",
      "html": "<div class=\"ds-menu-item\"><span class=\"ds-menu-icon\">📋</span><span class=\"ds-menu-label\">我的订单</span><span class=\"ds-menu-arrow\"></span></div>",
      "css": ".ds-menu-item { display: flex; align-items: center; padding: 24rpx 32rpx; background: #FFFFFF; border-bottom: 1rpx solid #EEEEEE; transition: background 0.15s ease; } .ds-menu-item:active { background: #FAFAFA; } .ds-menu-item:last-child { border-bottom: none; } .ds-menu-icon { width: 40rpx; height: 40rpx; margin-right: 24rpx; } .ds-menu-label { flex: 1; font-size: 28rpx; color: #2C2C2C; } .ds-menu-arrow { width: 16rpx; height: 16rpx; border-top: 2rpx solid #BDBDBD; border-right: 2rpx solid #BDBDBD; transform: rotate(45deg); }"
    },
    {
      "name": "Status Card",
      "kind": "card",
      "refersTo": "card-default",
      "description": "Card with status icon, title, and description. Used in shopping flow for door-open, shopping-done, and error states.",
      "html": "<div class=\"ds-status-card\"><div class=\"ds-status-icon success\">✓</div><div class=\"ds-status-title\">结算完成</div><div class=\"ds-status-desc\">您已成功购买以下商品</div></div>",
      "css": ".ds-status-card { background: #FFFFFF; border-radius: 24rpx; padding: 32rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); text-align: center; } .ds-status-icon { width: 56rpx; height: 56rpx; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 20rpx; font-size: 32rpx; color: #FFFFFF; font-weight: bold; } .ds-status-icon.success { background: linear-gradient(135deg, #00CC66, #00B359); box-shadow: 0 4rpx 12rpx rgba(0,204,102,0.3); } .ds-status-title { font-size: 34rpx; font-weight: 700; color: #2C2C2C; margin-bottom: 8rpx; } .ds-status-desc { font-size: 24rpx; color: #8C8C8C; }"
    },
    {
      "name": "Product Card",
      "kind": "card",
      "refersTo": "card-default",
      "description": "Product display card with image, name, price, and stock info. Used in cabinet product listing and order detail.",
      "html": "<div class=\"ds-product-card\"><div class=\"ds-product-img\">🥤</div><div class=\"ds-product-info\"><div class=\"ds-product-name\">可口可乐 330ml</div><div class=\"ds-product-price\">¥3.50</div></div></div>",
      "css": ".ds-product-card { display: flex; padding: 20rpx 24rpx; background: #FFFFFF; border-bottom: 1rpx solid #F5F5F5; } .ds-product-card:last-child { border-bottom: none; } .ds-product-img { width: 140rpx; height: 140rpx; background: #F5F5F5; border-radius: 12rpx; display: flex; align-items: center; justify-content: center; font-size: 52rpx; margin-right: 20rpx; flex-shrink: 0; } .ds-product-info { flex: 1; display: flex; flex-direction: column; justify-content: center; } .ds-product-name { font-size: 28rpx; color: #2C2C2C; font-weight: 500; line-height: 1.4; margin-bottom: 8rpx; } .ds-product-price { font-size: 32rpx; color: #F44336; font-weight: 700; }"
    }
  ],
  "narrative": {
    "northStar": "The Yellow Mark",
    "overview": "AI零售柜 is a consumer mini-program where the yellow accent works like a brand marker — instantly recognizable, like 美团's yellow or 闲鱼's yellow. The surface is clean and white, the yellow appears with purpose: a scan button, a selected state, a price. Its presence signals action; its absence signals rest. The system is built on restraint, not because less is more, but because every element must justify itself against the physical context: a user standing in front of a cabinet under bright office lights.",
    "keyCharacteristics": [
      "Yellow as brand marker, not surface decoration",
      "White-dominant backgrounds with warm tint",
      "Precision over abundance — every pixel is intentional",
      "Fast transitions that feel mechanical, not theatrical",
      "Physical-digital coherence: the phone UI mirrors the cabinet interaction"
    ],
    "rules": [
      {
        "name": "The One Yellow Rule",
        "body": "Brand Yellow appears on at most 30-40% of any given screen. It is the brand marker, not the brand blanket. When everything is yellow, nothing is.",
        "section": "colors"
      },
      {
        "name": "The White Canvas Rule",
        "body": "White (#FFFFFF) is the default card surface; Cream (#FAFAFA) is the default page background. The difference is subtle but structural — cards float on cream; content that belongs to the page sits directly on cream.",
        "section": "colors"
      },
      {
        "name": "The Scale Jump Rule",
        "body": "Adjacent text sizes differ by at least 1.25x. No 28rpx next to 30rpx; the scale skips intentionally: 22 → 24 → 28 → 32 → 36 → 48 → 56.",
        "section": "typography"
      },
      {
        "name": "The Shadow Has a Job Rule",
        "body": "Never use a shadow without answering: what does this elevation communicate? If the answer is 'looks nice,' remove it.",
        "section": "elevation"
      },
      {
        "name": "The Flat-By-Default Rule",
        "body": "Menu items, list rows, and non-interactive surfaces carry no shadow. Shadow = affordance, not decoration.",
        "section": "elevation"
      }
    ],
    "dos": [
      "Use Brand Yellow (#FFC107) exclusively for interactive elements: buttons, selected states, brand marks, and active indicators.",
      "Use White (#FFFFFF) for cards and Cream (#FAFAFA) for page backgrounds. The distinction creates structure without borders.",
      "Maintain at least 32rpx of breathing room around primary CTAs.",
      "Use the Shadow vocabulary intentionally: Ambient for at-rest cards, Brand Glow only for the primary CTA.",
      "Cap body text at 65-75 characters per line on the widest screen."
    ],
    "donts": [
      "Don't use Brand Yellow as a background fill on text-heavy surfaces. Yellow's job is signaling action, not hosting reading.",
      "Don't introduce a second accent color. Green, orange, red, and blue are functional signals; they are not decorative accents.",
      "Don't use nested cards. A card inside a card is always wrong.",
      "Don't use side-stripe borders (border-left/border-right > 1px) as colored accents.",
      "Don't use gradient text (background-clip: text). Solid colors only.",
      "Don't use glassmorphism, decorative blurs, or translucent overlays as a default aesthetic.",
      "Don't let the interface feel like a discount retail mini-program: no red flash-sale badges, no banner carousels, no cluttered grids of same-sized product cards."
    ]
  }
}
