---
meta:
  name: "Apple"
  version: "1.0.0"
  updated: "2026-04-19"
  description: "Apple Human Interface Guidelines aesthetic — clarity, deference, depth. San Francisco typography, light-first system palette, restrained chrome, generous whitespace."
  inspiration: "apple.com / Apple Human Interface Guidelines"

tokens:
  colors:
    bg: "#FFFFFF"
    surface: "#F5F5F7"
    accent: "#0071E3"
    text: "#1D1D1F"
    border: "#D2D2D7"
    status:
      success: "#30D158"
      warning: "#FF9F0A"
      danger: "#FF3B30"
      info: "#007AFF"

  typography:
    families:
      primary: "SF Pro Text, -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif"
      display: "SF Pro Display, -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif"
      mono: "SF Mono, Menlo, Monaco, 'Courier New', monospace"
    scale:
      - "12px"
      - "14px"
      - "17px"
      - "21px"
      - "28px"
      - "40px"
      - "56px"
      - "80px"
    weights: [400, 500, 600, 700]
    lineHeight:
      tight: "1.1"
      snug: "1.25"
      normal: "1.47"

  spacing:
    - "4px"
    - "8px"
    - "12px"
    - "16px"
    - "22px"
    - "32px"
    - "48px"
    - "80px"
    - "128px"

  radius:
    none: "0px"
    sm: "6px"
    md: "12px"
    lg: "18px"
    xl: "28px"
    full: "9999px"

  shadow:
    sm: "0 1px 2px rgba(0,0,0,0.05)"
    md: "0 4px 12px rgba(0,0,0,0.08)"
    lg: "0 20px 40px rgba(0,0,0,0.10)"

  motion:
    duration:
      fast: "150ms"
      base: "300ms"
      slow: "500ms"
    easing:
      standard: "cubic-bezier(0.25, 0.1, 0.25, 1)"
      emphatic: "cubic-bezier(0.42, 0, 0.12, 1)"

components:
  button:
    radius: full
    paddingX: "22px"
    paddingY: "12px"
    fontWeight: 500
  card:
    radius: lg
    padding: "32px"
    shadow: sm
  input:
    radius: md
    paddingX: "16px"
    paddingY: "12px"
    borderWidth: "1px"

antiPatterns:
  - id: no-side-stripe-borders
    category: layout
    pattern: "border-left:\\s*(?:[3-9]|\\d{2,})px"
    why: "Side-stripe callouts (>= 3px left borders) are an AI tell — they read as generic CMS snippets, not designed surfaces."
    rewrite: "Use a subtle background tint, a top-aligned icon, or a semantic text color instead of a left stripe."
  - id: no-nested-cards
    category: layout
    pattern: "class=\"[^\"]*rounded-(?:xl|2xl|3xl)[^\"]*shadow[^\"]*\"[^>]*>\\s*<[^>]*class=\"[^\"]*rounded-(?:xl|2xl|3xl)[^\"]*shadow"
    why: "A rounded-shadowed card containing another rounded-shadowed card reads as 'I didn't know how to group these'. Flatten."
    rewrite: "Use section-level whitespace and a single card, or swap the outer card for a plain div."
  - id: no-gradient-text
    category: typography
    pattern: "background-clip:\\s*text"
    why: "Gradient text (background-clip: text) is the single strongest AI aesthetic. It reads as try-hard landing-page filler."
    rewrite: "Use a solid color from tokens.colors.text or tokens.colors.accent. Reserve gradients for non-type surfaces."
  - id: no-inter-only
    category: typography
    pattern: "font-family:\\s*['\"]?Inter['\"]?\\s*[,;]?\\s*$"
    why: "Inter as the sole declared font is the AI-default and signals zero type choice was made."
    rewrite: "Declare a primary family with intentional fallbacks (see tokens.typography.families.primary) or pick a distinctive display face."
  - id: no-all-bold-headings
    category: typography
    pattern: "<h[1-3][^>]*class=\"[^\"]*font-black\\b"
    why: "`font-black` on every heading collapses type hierarchy into shouting. Weight differentiates; shouting doesn't."
    rewrite: "Reserve font-black for one hero moment per page; use semibold/bold for most headings."
  - id: no-uppercase-body
    category: typography
    pattern: "<p[^>]*class=\"[^\"]*uppercase\\b"
    why: "ALL-CAPS body text kills readability. Uppercase belongs on labels and eyebrow text only."
    rewrite: "Use tracking-widest or small-caps on short labels; keep body at normal case."
  - id: no-purple-saas-gradient-hero
    category: color
    pattern: "linear-gradient\\([^)]*#[68][0-9a-f]{2}[a-f0-9]f[a-f0-9]"
    why: "Purple→pink hero gradients are the generic SaaS tell."
    rewrite: "Use a single tokens.colors.accent flood or a neutral photograph."
  - id: no-cyan-on-dark
    category: color
    pattern: "color:\\s*#(?:0[0-9a-f]f[0-9a-f]ff|00ffff|22d3ee|06b6d4|0891b2)\\b"
    why: "Bright cyan/electric-teal text on dark backgrounds is the 2015 futuristic-dashboard trope — high chroma, low information density."
    rewrite: "Use a desaturated accent from tokens.colors.accent or a neutral color at reduced alpha."
  - id: no-rainbow-accents
    category: color
    pattern: "(?:text|bg|border)-(?:red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-500[^\"]*\"[^>]*(?:text|bg|border)-(?:red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-500"
    why: "Multiple saturated Tailwind 500-series accents on the same surface reads as 'I couldn't decide'. Commit to one accent."
    rewrite: "Use tokens.colors.accent for primary actions; reserve status colors for semantic contexts only."
  - id: no-bounce-easing
    category: motion
    pattern: "cubic-bezier\\(0\\.68,\\s*-0\\.55"
    why: "Overshoot/bounce easings feel juvenile on UI surfaces."
    rewrite: "Use tokens.motion.easing.standard for UI, emphatic only for hero-level moments."
  - id: no-slow-default
    category: motion
    pattern: "transition(?:-[a-z]+)?:\\s*(?:all|[a-z-]+)\\s+(?:[5-9]\\d{2}|\\d{4,})ms"
    why: "Transitions >= 500ms on UI interactions feel sluggish; users interpret them as jank."
    rewrite: "Keep UI transitions under 280ms (tokens.motion.duration.slow). Reserve 500ms+ for hero entrances only."
  - id: no-permanent-spinner
    category: motion
    pattern: "animation:\\s*spin\\s+\\d+(?:\\.\\d+)?s\\s+linear\\s+infinite"
    why: "A perpetual spinner (`animation: spin … infinite`) left in a mockup for 'loading state' always ships to prod."
    rewrite: "Use discrete loading/empty/error variants side-by-side, or replace with a skeleton."
  - id: no-missing-focus
    category: interaction
    pattern: "<button[^>]*class=\"[^\"]*(?:focus:outline-none|outline-none)[^\"]*\"(?![^>]*focus-visible:)"
    why: "Removing the focus outline without replacing it breaks keyboard accessibility. This is the AI's laziest shortcut."
    rewrite: "Either keep the default outline or replace with `focus-visible:outline-2 focus-visible:outline-offset-2`."
  - id: no-placeholder-names
    category: content
    pattern: "\\b(John|Jane)\\s+Doe\\b"
    why: "John/Jane Doe placeholder strings leak into shipped UI when the AI skips real sample data."
    rewrite: "Use sample data that reflects the actual product (real-looking names, real tasks, real copy)."
  - id: no-lorem-ipsum
    category: content
    pattern: "\\bLorem\\s+ipsum\\s+dolor\\s+sit\\s+amet\\b"
    why: "Lorem ipsum in a shipped mockup means no one thought about what the copy should actually say."
    rewrite: "Write real copy that reflects the feature. If the feature is too early for copy, render a single-word label instead."

inspiration:
  - apple
---

# Apple — design contract

> **Contract:** Apple Human Interface Guidelines aesthetic — clarity, deference, depth. San Francisco type system, warm neutrals, a single blue accent, generous whitespace. The frontmatter above is the source of truth for machine-readable tokens; the sections below are the human-facing narrative.

## 1. Visual Theme

Light-first and typographically driven. The product feels like a well-made physical object photographed under soft daylight — content floats on warm-white surfaces (`bg: #FFFFFF`, `surface: #F5F5F7`) with deliberate negative space between sections. The one blue (`accent: #0071E3`) shows up on the primary action and the active state — nowhere else. Imagery is photographic, never illustrative. Chrome is invisible until touched.

## 2. Color Palette

See `tokens.colors` in the frontmatter for exact values. Narrative rules:

- **Background** is warm white `#FFFFFF`. `surface` is the slightly tinted `#F5F5F7` used for elevated cards, modal sheets, and inline code. Never invert these on the landing surface — dark mode is a separate style pack.
- **Accent** `#0071E3` is Apple blue. It carries the primary action, active navigation state, and link colour. It must NOT tint icons, dividers, or decorative chrome. If `accent` appears more than two times on a page, reduce.
- **Status colours** (`success #30D158`, `warning #FF9F0A`, `danger #FF3B30`, `info #007AFF`) are semantic only — never decorative. Use them for inline validation, system alerts, and real status dots.
- **Text** is `#1D1D1F` (soft black). Pure `#000` is reserved for keyline strokes in photography. Secondary text uses 60% alpha of the same value.

## 3. Typography

See `tokens.typography` in the frontmatter.

- **Display** (`SF Pro Display`) is for page titles and hero moments — sizes ≥ 28px. Below 28px use `primary` (`SF Pro Text`).
- **Primary** tracks tighter on large sizes and wider on small sizes — matching Apple's optical-size guidance. At 12–14px use weight 500 for labels; at 17–21px use weight 400 for body.
- **Mono** (`SF Mono`) is only for code, keyboard shortcut chips (`⌘K`), and file paths.
- Hero numbers on marketing surfaces may use weight 700 but only at ≥ 56px.

## 4. Component Stylings

Token overrides live under `components` in the frontmatter. Narrative rules:

- **Button.** `full` radius pills, `22px` horizontal padding, `12px` vertical, weight 500. Primary uses `accent` on `bg`. Secondary inverts: `surface` background, `text` label, no border. Tertiary is text-only with a `accent` label.
- **Card.** `lg` (18px) radius, `32px` inner padding, `sm` shadow. Cards never nest; they sit side-by-side or stack with `spacing[7]` (48px) between them.
- **Input.** `md` (12px) radius, 1px `border` outline. Focus state: border replaced by a 2px `accent` ring with 0 offset.

## 5. Layout

- 12-column grid at ≥ 1024px; 8-column at 640–1023px; single column below.
- Max content width **980px** for reading surfaces (marketing) and **1440px** for density (tables, code).
- Section padding follows the 8pt scale; prefer `spacing[7]` (48px) and `spacing[8]` (80px) between sections.
- Hero layouts centre a single headline + one CTA with at least `spacing[8]` of vertical space above and below.

## 6. Depth

- `shadow.sm` (`0 1px 2px rgba(0,0,0,0.05)`) for resting cards.
- `shadow.md` for hovered cards and dropdowns.
- `shadow.lg` only for modals and sheets — nothing else.
- Do not stack shadows. One elevation per surface.

## 7. Do's and Don'ts

**Do**
- Use the SF stack everywhere. Fallbacks `-apple-system, BlinkMacSystemFont, 'Segoe UI'` ensure the native feel on every OS.
- Set type in `spacing[4]` (16px) rhythm. Line-height `1.47` for body, `1.25` for hero.
- Write sample data using real Apple product names (`AirPods Pro`, `iPhone 15`, `macOS Sequoia`).
- Treat the accent as precious — one use per view.

**Don't**
- Use any of the `antiPatterns` in the frontmatter. `apt-tools design-lint` will catch them.
- Introduce a secondary accent colour. Apple's palette is a single blue by design.
- Apply gradient fills to type or buttons — the aesthetic is pure solids.
- Use Inter or Arial as the declared primary font. The SF stack is non-negotiable.

## 8. Responsive

- **Narrow** (<640px): single column, full-bleed hero imagery, stacked navigation that collapses into a menu trigger.
- **Medium** (640–1023px): 8-column grid, denser headers, sticky bottom-action bar on forms.
- **Wide** (≥1024px): 12-column grid, persistent top navigation, cards arranged in `spacing[7]` (48px) gutters.
- Touch targets are **44×44px** minimum on narrow viewports (HIG compliance).

## 9. Agent Prompt Guide

Copy-paste starters for `apt:mockup` and ad-hoc generation.

### Build a button

> Render a primary button using `tokens.colors.accent` on `tokens.colors.bg`. Radius from `components.button.radius` (pill). Padding from `components.button.paddingX/paddingY`. Font from `tokens.typography.families.primary`, weight 500. Focus: 2px outline in `tokens.colors.accent`, 0 offset.

### Build a card

> Render a card on `tokens.colors.surface`, 1px `tokens.colors.border` outline, `components.card.radius` corners, `components.card.padding` inner padding, `tokens.shadow.sm` shadow. Headline in `tokens.typography.families.display`, weight 600, at scale[3] (21px). Body in `primary` at scale[2] (17px). No gradient, no nested cards, no decorative rules.

### Build a data table

> Render a dense data table: `tokens.typography.scale[1]` (14px) body size, `tokens.spacing[2]` (12px) row padding, `tokens.colors.border` horizontal row separators only, `tokens.colors.surface` hover state. Numeric columns right-aligned with `mono`, text columns left-aligned with `primary`.

### Reject criteria

Before handing off to `apt:plan`, every generated mockup must pass:

- `apt-tools design-validate DESIGN.md` → exit 0
- `apt-tools design-lint mockups/*.html` → zero violations against `antiPatterns`
- Visual read-through against §7 Do's and Don'ts (single accent, SF stack, warm-white surfaces)
