feat: IMAP mail sync with thread-to-contact matching (PRD §6.1)

Real IMAP connection via imapflow library:
- Connects to IMAP server (IMAPFlow, TLS on port 993)
- Fetches recent messages (configurable limit, default 20)
- Extracts: from, fromEmail, subject, date, snippet (200 chars)
- Thread-to-contact matching (PRD §6.1):
  1. Match sender email against persons table
  2. If no person match, extract domain and match against company.website
  3. Returns matchedCompany + matchedPerson for each email
- Audit-logged (action: crm.mailsync:imap)
- Zod validated (host, port, user, password, folder, limit)
- 502 on IMAP connection failure with detail
- 400 on validation failure

Tested: invalid creds → 502 'IMAP connection failed', missing host → 400
This commit is contained in:
Z User committed 2026-10-27 22:50:50 +00:00
1 parent 7acc0c5451
commit e45b68bb8b
1089 files changed
+260614

No files matched your search

@@ -0,0 +1,562 @@
---
version: alpha
name: Apple
description: "A photography-first interface that turns marketing into a museum gallery. Edge-to-edge product tiles alternate light and dark canvases, framed by SF Pro Display headlines with negative letter-spacing and a single Action Blue (#0066cc) interactive color. UI chrome recedes so the product can speak — no decorative gradients, no shadows on chrome, only the one signature drop-shadow under product imagery resting on a surface."
colors:
primary: "#0066cc"
primary-focus: "#0071e3"
primary-on-dark: "#2997ff"
ink: "#1d1d1f"
body: "#1d1d1f"
body-on-dark: "#ffffff"
body-muted: "#cccccc"
ink-muted-80: "#333333"
ink-muted-48: "#7a7a7a"
divider-soft: "#f0f0f0"
hairline: "#e0e0e0"
canvas: "#ffffff"
canvas-parchment: "#f5f5f7"
surface-pearl: "#fafafc"
surface-tile-1: "#272729"
surface-tile-2: "#2a2a2c"
surface-tile-3: "#252527"
surface-black: "#000000"
surface-chip-translucent: "#d2d2d7"
on-primary: "#ffffff"
on-dark: "#ffffff"
typography:
hero-display:
fontFamily: "SF Pro Display, system-ui, -apple-system, sans-serif"
fontSize: 56px
fontWeight: 600
lineHeight: 1.07
letterSpacing: -0.28px
display-lg:
fontFamily: "SF Pro Display, system-ui, -apple-system, sans-serif"
fontSize: 40px
fontWeight: 600
lineHeight: 1.1
letterSpacing: 0
display-md:
fontFamily: "SF Pro Text, system-ui, -apple-system, sans-serif"
fontSize: 34px
fontWeight: 600
lineHeight: 1.47
letterSpacing: -0.374px
lead:
fontFamily: "SF Pro Display, system-ui, -apple-system, sans-serif"
fontSize: 28px
fontWeight: 400
lineHeight: 1.14
letterSpacing: 0.196px
lead-airy:
fontFamily: "SF Pro Text, system-ui, -apple-system, sans-serif"
fontSize: 24px
fontWeight: 300
lineHeight: 1.5
letterSpacing: 0
tagline:
fontFamily: "SF Pro Display, system-ui, -apple-system, sans-serif"
fontSize: 21px
fontWeight: 600
lineHeight: 1.19
letterSpacing: 0.231px
body-strong:
fontFamily: "SF Pro Text, system-ui, -apple-system, sans-serif"
fontSize: 17px
fontWeight: 600
lineHeight: 1.24
letterSpacing: -0.374px
body:
fontFamily: "SF Pro Text, system-ui, -apple-system, sans-serif"
fontSize: 17px
fontWeight: 400
lineHeight: 1.47
letterSpacing: -0.374px
dense-link:
fontFamily: "SF Pro Text, system-ui, -apple-system, sans-serif"
fontSize: 17px
fontWeight: 400
lineHeight: 2.41
letterSpacing: 0
caption:
fontFamily: "SF Pro Text, system-ui, -apple-system, sans-serif"
fontSize: 14px
fontWeight: 400
lineHeight: 1.43
letterSpacing: -0.224px
caption-strong:
fontFamily: "SF Pro Text, system-ui, -apple-system, sans-serif"
fontSize: 14px
fontWeight: 600
lineHeight: 1.29
letterSpacing: -0.224px
button-large:
fontFamily: "SF Pro Text, system-ui, -apple-system, sans-serif"
fontSize: 18px
fontWeight: 300
lineHeight: 1.0
letterSpacing: 0
button-utility:
fontFamily: "SF Pro Text, system-ui, -apple-system, sans-serif"
fontSize: 14px
fontWeight: 400
lineHeight: 1.29
letterSpacing: -0.224px
fine-print:
fontFamily: "SF Pro Text, system-ui, -apple-system, sans-serif"
fontSize: 12px
fontWeight: 400
lineHeight: 1.0
letterSpacing: -0.12px
micro-legal:
fontFamily: "SF Pro Text, system-ui, -apple-system, sans-serif"
fontSize: 10px
fontWeight: 400
lineHeight: 1.3
letterSpacing: -0.08px
nav-link:
fontFamily: "SF Pro Text, system-ui, -apple-system, sans-serif"
fontSize: 12px
fontWeight: 400
lineHeight: 1.0
letterSpacing: -0.12px
rounded:
none: 0px
xs: 5px
sm: 8px
md: 11px
lg: 18px
pill: 9999px
full: 9999px
spacing:
xxs: 4px
xs: 8px
sm: 12px
md: 17px
lg: 24px
xl: 32px
xxl: 48px
section: 80px
components:
button-primary:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
typography: "{typography.body}"
rounded: "{rounded.pill}"
padding: 11px 22px
button-primary-focus:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
rounded: "{rounded.pill}"
button-primary-active:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
rounded: "{rounded.pill}"
button-secondary-pill:
backgroundColor: "{colors.canvas}"
textColor: "{colors.primary}"
typography: "{typography.body}"
rounded: "{rounded.pill}"
padding: 11px 22px
button-dark-utility:
backgroundColor: "{colors.ink}"
textColor: "{colors.on-dark}"
typography: "{typography.button-utility}"
rounded: "{rounded.sm}"
padding: 8px 15px
button-pearl-capsule:
backgroundColor: "{colors.surface-pearl}"
textColor: "{colors.ink-muted-80}"
typography: "{typography.caption}"
rounded: "{rounded.md}"
padding: 8px 14px
button-store-hero:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
typography: "{typography.button-large}"
rounded: "{rounded.pill}"
padding: 14px 28px
button-icon-circular:
backgroundColor: "{colors.surface-chip-translucent}"
textColor: "{colors.ink}"
rounded: "{rounded.full}"
size: 44px
text-link:
backgroundColor: transparent
textColor: "{colors.primary}"
typography: "{typography.body}"
text-link-on-dark:
backgroundColor: transparent
textColor: "{colors.primary-on-dark}"
typography: "{typography.body}"
global-nav:
backgroundColor: "{colors.surface-black}"
textColor: "{colors.on-dark}"
typography: "{typography.nav-link}"
height: 44px
sub-nav-frosted:
backgroundColor: "{colors.canvas-parchment}"
textColor: "{colors.ink}"
typography: "{typography.tagline}"
height: 52px
product-tile-light:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.display-lg}"
rounded: "{rounded.none}"
padding: 80px
product-tile-parchment:
backgroundColor: "{colors.canvas-parchment}"
textColor: "{colors.ink}"
typography: "{typography.display-lg}"
rounded: "{rounded.none}"
padding: 80px
product-tile-dark:
backgroundColor: "{colors.surface-tile-1}"
textColor: "{colors.on-dark}"
typography: "{typography.display-lg}"
rounded: "{rounded.none}"
padding: 80px
product-tile-dark-2:
backgroundColor: "{colors.surface-tile-2}"
textColor: "{colors.on-dark}"
rounded: "{rounded.none}"
product-tile-dark-3:
backgroundColor: "{colors.surface-tile-3}"
textColor: "{colors.on-dark}"
rounded: "{rounded.none}"
store-utility-card:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.body-strong}"
rounded: "{rounded.lg}"
padding: 24px
configurator-option-chip:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.caption}"
rounded: "{rounded.pill}"
padding: 12px 16px
configurator-option-chip-selected:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
rounded: "{rounded.pill}"
search-input:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.body}"
rounded: "{rounded.pill}"
padding: 12px 20px
height: 44px
floating-sticky-bar:
backgroundColor: "{colors.canvas-parchment}"
textColor: "{colors.ink}"
typography: "{typography.body}"
height: 64px
padding: 12px 32px
environment-quote-card:
backgroundColor: "{colors.surface-tile-1}"
textColor: "{colors.on-dark}"
typography: "{typography.display-lg}"
rounded: "{rounded.none}"
padding: 80px
footer:
backgroundColor: "{colors.canvas-parchment}"
textColor: "{colors.ink-muted-80}"
typography: "{typography.fine-print}"
padding: 64px
---
## Overview
Apple's web presence is a masterclass in **reverent product photography framed by near-invisible UI**. Every page is a stack of edge-to-edge product "tiles" — alternating light and dark canvases, each centered on a hero headline, a one-line tagline, two tiny blue pill CTAs, and an impossibly crisp product render. Nothing competes with the product. Typography is confident but quiet; color is either pure white, an off-white parchment, or a near-black tile; interactive elements are a single, quiet blue.
Density is unusually low even by contemporary SaaS standards. Each tile occupies roughly one viewport, and there is no decorative chrome — no borders, no gradients, no decorative frames, no shadows on headlines. Elevation appears only when a product image rests on a surface (a single soft `rgba(0, 0, 0, 0.22) 3px 5px 30px` drop for visual weight). The result is a catalog that feels more like a museum gallery: the wall disappears and the artifact takes over.
Store and shop surfaces retain the same chassis but switch modes. The product configurator (iPhone 17 Pro, accessories grid) introduces a tight grid of white utility cards at `{rounded.lg}` (18px) radius with a thin border, paired with a persistent thin sub-nav strip. The environment page leans darker and more editorial. Across all five surfaces the typographic system, spacing rhythm, and the single blue accent are consistent — this is one design language expressed at different volumes.
**Key Characteristics:**
- Photography-first presentation; UI recedes so the product can speak.
- Alternating full-bleed tile sections: white/parchment ↔ near-black, with the color change itself acting as the section divider.
- Single blue accent (`{colors.primary}` — #0066cc) carries every interactive element. No second brand color exists.
- Two button grammars: tiny blue pill CTAs (`{rounded.pill}`) and compact utility rects (`{rounded.sm}`).
- SF Pro Display + SF Pro Text — negative letter-spacing at display sizes for the signature "Apple tight" headline feel.
- Whisper-soft elevation used only when a product image needs to breathe — exactly one drop-shadow in the entire system.
- Tight two-row nav: slim `{component.global-nav}` + product-specific `{component.sub-nav-frosted}` with persistent right-aligned primary CTA.
- Section rhythm across multiple pages: light hero → dark product tile → light utility tile → dark tile → parchment footer — a predictable pulse.
## Colors
> **Source pages analyzed:** homepage, environment, store, iPhone 17 Pro buy page, accessories index. The color system is identical across all five surfaces; only the surface-mode mix differs.
### Brand & Accent
- **Action Blue** (`{colors.primary}` — #0066cc): The single brand-level interactive color. All text links, all blue pill CTAs ("Learn more", "Buy"), and the focus ring root. This is Apple's quiet but universal "click me" signal. Press state shifts to a slightly darker variant via the active scale transform rather than a hex change.
- **Focus Blue** (`{colors.primary-focus}` — #0071e3): A marginally brighter sibling of Action Blue, reserved for the keyboard focus ring on buttons (`outline: 2px solid`).
- **Sky Link Blue** (`{colors.primary-on-dark}` — #2997ff): A brighter blue used on dark surfaces for in-copy links and inline callouts, where Action Blue would disappear against the tile background.
### Surface
- **Pure White** (`{colors.canvas}` — #ffffff): The dominant canvas. Content, utility cards, store tiles, configurator grids.
- **Parchment** (`{colors.canvas-parchment}` — #f5f5f7): The signature Apple off-white. Used for alternating light tiles, footer region, and the default page canvas in store utility sections. Just different enough from white to create rhythm.
- **Pearl Button** (`{colors.surface-pearl}` — #fafafc): A near-white used as the fill for secondary "ghost" buttons — lighter than the parchment canvas so the button still reads as a button against `{colors.canvas-parchment}`.
- **Near-Black Tile 1** (`{colors.surface-tile-1}` — #272729): The primary dark-tile surface on the homepage product grid.
- **Near-Black Tile 2** (`{colors.surface-tile-2}` — #2a2a2c): A micro-step lighter — used where a dark tile sits directly above or below Tile 1 to create the faintest separation.
- **Near-Black Tile 3** (`{colors.surface-tile-3}` — #252527): A micro-step darker — used at the bottom of the stack and in embedded video/player frames.
- **Pure Black** (`{colors.surface-black}` — #000000): Reserved for true void — video player backgrounds, edge-to-edge photographic overlays, the global nav bar background.
- **Translucent Chip Gray** (`{colors.surface-chip-translucent}` — #d2d2d7): The base hex of the translucent gray chip used over photography for circular control buttons. In production, applied at ~64% alpha as `rgba(210, 210, 215, 0.64)`.
### Text
- **Near-Black Ink** (`{colors.ink}` — #1d1d1f): The voice of every headline, every body paragraph, and the dark utility button's fill. Chosen instead of pure black to keep the page feeling photographic rather than printed.
- **Body** (`{colors.body}` — #1d1d1f): Same hex as ink — Apple uses one near-black tone for all text on light surfaces.
- **Body On Dark** (`{colors.body-on-dark}` — #ffffff): All text on dark tiles and on the global nav bar.
- **Body Muted** (`{colors.body-muted}` — #cccccc): Secondary copy on dark tiles where pure white would be too loud.
- **Ink Muted 80** (`{colors.ink-muted-80}` — #333333): Body text on the white Pearl Button surface — slightly softer than pure black.
- **Ink Muted 48** (`{colors.ink-muted-48}` — #7a7a7a): Disabled button text and legal fine-print.
### Hairlines & Borders
- **Divider Soft** (`{colors.divider-soft}` — #f0f0f0): The "border" tone on secondary buttons — functions as a ring shadow rather than a hard line. In production, often applied as `rgba(0, 0, 0, 0.04)`.
- **Hairline** (`{colors.hairline}` — #e0e0e0): The 1px hairline border on store utility cards and configurator chips.
### Brand Gradient
**No decorative gradients.** Atmospheric depth on product photography (the iPhone 17 Pro camera plate, the Apple Watch bands, AirPods reflections) is inherent to the imagery, not a CSS gradient overlay. The environment page's hero uses photographic atmosphere (mountain vista at dawn) but no gradient tokens are defined. Apple is the rare luxury-brand site with zero gradient-based design tokens.
## Typography
### Font Family
- **Display**: `SF Pro Display, system-ui, -apple-system, sans-serif` — Apple's proprietary display face, optimized for sizes ≥ 19px. Defines the voice of every headline.
- **Body / UI**: `SF Pro Text, system-ui, -apple-system, sans-serif` — the text-optimized variant used for body copy, captions, buttons, and links below 20px.
- **OpenType features**: `font-variant-numeric: numerator` is enabled on numeric links (pricing tables, spec sheets). Display sizes rely on tight tracking rather than contextual ligatures.
### Hierarchy
| Token | Size | Weight | Line Height | Letter Spacing | Use |
|---|---|---|---|---|---|
| `{typography.hero-display}` | 56px | 600 | 1.07 | -0.28px | Hero headline; the signature "Apple tight" tracking |
| `{typography.display-lg}` | 40px | 600 | 1.10 | 0 | Tile headlines atop every product tile |
| `{typography.display-md}` | 34px | 600 | 1.47 | -0.374px | Section heads (SF Pro Text at display proportions) |
| `{typography.lead}` | 28px | 400 | 1.14 | 0.196px | Product tile subcopy |
| `{typography.lead-airy}` | 24px | 300 | 1.5 | 0 | Environment-page lead paragraphs (the rare weight 300) |
| `{typography.tagline}` | 21px | 600 | 1.19 | 0.231px | Sub-tile tagline; sub-nav category name |
| `{typography.body-strong}` | 17px | 600 | 1.24 | -0.374px | Inline strong emphasis |
| `{typography.body}` | 17px | 400 | 1.47 | -0.374px | Default paragraph |
| `{typography.dense-link}` | 17px | 400 | 2.41 | 0 | Footer / store utility link lists (relaxed leading) |
| `{typography.caption}` | 14px | 400 | 1.43 | -0.224px | Secondary captions, button text |
| `{typography.caption-strong}` | 14px | 600 | 1.29 | -0.224px | Emphasized captions |
| `{typography.button-large}` | 18px | 300 | 1.0 | 0 | Store hero CTAs (the rare weight 300) |
| `{typography.button-utility}` | 14px | 400 | 1.29 | -0.224px | Utility/nav button labels |
| `{typography.fine-print}` | 12px | 400 | 1.0 | -0.12px | Fine-print, footer body |
| `{typography.micro-legal}` | 10px | 400 | 1.3 | -0.08px | Micro legal disclaimers |
| `{typography.nav-link}` | 12px | 400 | 1.0 | -0.12px | Global nav menu items |
### Principles
- **Negative letter-spacing at display sizes.** Every headline at 17px and up carries a slight tracking tighten (`-0.12 → -0.374px`). This produces the iconic "Apple tight" headline cadence. Never used at 12px or below.
- **Body copy at 17px, not 16px.** Apple breaks the SaaS convention and runs paragraph text at 17px. The extra pixel gives the page an unmistakable "reading, not scanning" pace.
- **Weight 300 is real and rare.** Used deliberately on a handful of large-size reads (`{typography.button-large}` at 18px/300 and `{typography.lead-airy}` at 24px/300). It's not an accident — it's a light-atmosphere cue reserved for moments where the content should feel airy.
- **Weight 600, not 700, for headlines.** Apple's headlines sit at weight 600. Weight 700 is used sparingly for `{typography.tagline}` (21px) when a touch more assertion is needed.
- **Line-height is context-specific.** Display sizes use 1.07–1.19 (tight). Body uses 1.47. Utility link stacks in the footer/store use an unusually relaxed 2.41 (`{typography.dense-link}`). The 2.41 is not a bug — it's how the footer's dense link columns breathe.
- **Weight 500 is deliberately absent.** The ladder is 300 / 400 / 600 / 700. Mid-weight readings always use 600.
### Note on Font Substitutes
SF Pro is Apple's proprietary system font. When building off-system:
- Use `system-ui, -apple-system, BlinkMacSystemFont` as the first stack entry — on macOS/iOS/Safari this resolves to the real SF Pro.
- For non-Apple platforms, **Inter** (Google Fonts, variable) is the closest open-source equivalent. Inter at weight 600 with `font-feature-settings: "ss03"` approximates SF Pro's rounded "a" character.
- Nudge `letter-spacing` down by `-0.01em` on display sizes to re-create the Apple tight feel; Inter's default tracking runs slightly wider than SF Pro.
- For body text, tighten line-height by `0.03` (from 1.47 → 1.44) when substituting Inter — Inter's taller x-height needs less leading.
## Layout
### Spacing System
- **Base unit:** 8px. Sub-base values (2, 4, 5, 6, 7) are used for tight typographic adjustments; structural layout snaps to 8/12/16/20/24.
- **Tokens:** `{spacing.xxs}` 4px · `{spacing.xs}` 8px · `{spacing.sm}` 12px · `{spacing.md}` 17px · `{spacing.lg}` 24px · `{spacing.xl}` 32px · `{spacing.xxl}` 48px · `{spacing.section}` 80px.
- **Section vertical padding:** `{spacing.section}` (80px) inside a product tile; tiles stack edge-to-edge with 0 gap (the color change provides the break).
- **Card padding:** `{spacing.lg}` (24px) inside utility grid cards.
- **Button padding:** 8–11px vertical, 15–22px horizontal.
- **Universal rhythm constants:** the 17px body line-height multiplier (~25px line) and 21px tagline size show up on every analyzed page.
### Grid & Container
- **Max content width:** ~980px on text-heavy sections (environment), ~1440px on product grids (store, accessories), full-bleed for product tiles (homepage).
- **Column patterns:** 3 to 5 column utility card grid on store/accessories; 2-column side-by-side tiles on homepage occasional sections; single-column centered stack on product tile heroes.
- **Gutters:** 20–24px between cards in a utility grid.
### Whitespace Philosophy
Apple's whitespace is the product's pedestal. Every tile begins with at least 64px of air above its headline and 48–64px below. Product renders are never crowded; the nearest content to a product image is at least 40px away. The footer is the only area that breaks this — there, Apple goes deliberately dense to make the full information architecture visible at a glance.
## Elevation & Depth
| Level | Treatment | Use |
|---|---|---|
| Flat | No shadow, no border | Full-bleed tiles, global nav, footer, body sections |
| Soft hairline | 1px `rgba(0, 0, 0, 0.08)` border | Utility cards, sub-nav frosted-glass separator |
| Backdrop blur | `backdrop-filter: blur(N)` on Parchment 80% | Sub-nav and the iPhone buy floating sticky bar |
| Product shadow | `rgba(0, 0, 0, 0.22) 3px 5px 30px 0` | Product renders resting on a surface (the only true "shadow" in the system) |
**Shadow philosophy.** Apple uses **exactly one** drop-shadow, and it is applied to photographic product imagery — never to cards, never to buttons, never to text. Elevation in the UI comes from (a) surface-color change (light tile ↔ dark tile) and (b) backdrop-blur on sticky bars. The single shadow is about giving the product weight, not about UI hierarchy.
### Decorative Depth
- **Atmospheric imagery** on the environment page (photographic vista) supplies mood; no CSS gradient involved.
- **Edge-to-edge tile alternation** creates rhythm without borders or shadows — the color change itself is the divider.
- **Backdrop-filter blur** on `{component.sub-nav-frosted}` and `{component.floating-sticky-bar}` creates a "floating over content" effect that's functional, not decorative.
## Shapes
### Border Radius Scale
| Token | Value | Use |
|---|---|---|
| `{rounded.none}` | 0px | Full-bleed product tiles (no corner rounding) |
| `{rounded.xs}` | 5px | Inline links when styled as subtle chips (rare) |
| `{rounded.sm}` | 8px | Dark utility buttons (Sign In, Bag), inline card imagery |
| `{rounded.md}` | 11px | White Pearl Button capsules |
| `{rounded.lg}` | 18px | Store utility cards, accessories grid cards |
| `{rounded.pill}` | 9999px | Primary blue pill CTAs, sub-nav buy button, configurator option chips, search input — the signature Apple pill |
| `{rounded.full}` | 9999px / 50% | Circular control chips floating over photography |
### Photography Geometry
- **Hero imagery**: full-bleed, 21:9 or taller on the homepage; 16:9 on environment and shop pages. Product renders are photographic-realistic, often shot on a tinted surface that becomes the tile background.
- **Product renders**: PNG/WebP with transparency; rest on a surface tile and pick up the system shadow.
- **Accessory grid**: square 1:1 crops at `{rounded.lg}` (18px) radius, light neutral backgrounds, product centered with 20–40px internal padding.
- **No rounded imagery in hero tiles** — images are full-bleed rectangular. Rounding (`{rounded.sm}`, `{rounded.lg}`) appears only on inline card imagery.
- Lazy-loading via responsive `srcset` and `sizes` across all breakpoints; CDN-optimized WebP.
## Components
### Top Navigation
**`global-nav`** — Persistent, ultra-thin black nav bar pinned to the top of every page. Background `{colors.surface-black}`, height 44px, text `{colors.on-dark}` in `{typography.nav-link}` (12px / 400 / -0.12px tracking). Links are quiet, spaced ~20px apart, running edge-to-edge across the top. Right-aligned cluster: Search, Bag icons — always visible. On mobile, collapses to hamburger at ~834px and the Apple logo centers.
**`sub-nav-frosted`** — Surface-specific nav that sticks below the global nav. Background `{colors.canvas-parchment}` at 80% opacity with backdrop-filter blur, creating a frosted-glass effect. Height 52px. Content on left: product category name ("iPhone", "Store", "Accessories") in `{typography.tagline}` (21px / 600). Content right: inline nav links in `{typography.button-utility}` (14px), ending in a persistent `{component.button-primary}` ("Buy") or a utility link.
### Buttons
**`button-primary`** — The signature Apple action. Background `{colors.primary}` (Action Blue #0066cc), text `{colors.on-primary}` in `{typography.body}` (SF Pro Text 17px / 400), rounded `{rounded.pill}` (full pill — capsule-shaped), padding 11px × 22px. The full-pill radius IS the brand action signal.
- Active state: `{component.button-primary-active}` — `transform: scale(0.95)` (the system-wide micro-interaction).
- Focus state: `{component.button-primary-focus}` — 2px solid `{colors.primary-focus}` outline.
**`button-secondary-pill`** — Used as the second CTA when two blue pills appear together ("Learn more" / "Buy"). Background transparent, text `{colors.primary}`, 1px solid `{colors.primary}` border, rounded `{rounded.pill}`, padding 11px × 22px. Reads as a "ghost pill."
**`button-dark-utility`** — Global nav actions (Sign In, Bag, language selector). Background `{colors.ink}` (#1d1d1f), text `{colors.on-dark}` in `{typography.button-utility}` (14px / 400 / -0.224px tracking), rounded `{rounded.sm}` (8px), padding 8px × 15px. Active state shrinks via `transform: scale(0.95)`.
**`button-pearl-capsule`** — Product-card secondary button. Background `{colors.surface-pearl}` (#fafafc), text `{colors.ink-muted-80}` in `{typography.caption}` (14px), 3px solid `{colors.divider-soft}` border (functions as a soft ring rather than a visible line), rounded `{rounded.md}` (11px), padding 8px × 14px.
**`button-store-hero`** — A larger primary CTA used on store hero surfaces. Same Action Blue + Paper White as `{component.button-primary}`, but with `{typography.button-large}` (18px / 300 — note the rare weight 300) and slightly more padding (14px × 28px). Used sparingly on the store landing.
**`button-icon-circular`** — Floats over photography. 44 × 44px, background `{colors.surface-chip-translucent}` at ~64% alpha, icon in `{colors.ink}`, rounded `{rounded.full}`. Used for carousel controls, close buttons, and in-image controls (product image thumbnails on the iPhone buy page).
**`text-link`** — Inline body links in `{colors.primary}` (Action Blue). Underlined or non-underlined per context.
**`text-link-on-dark`** — Inline body links on dark tiles in `{colors.primary-on-dark}` (Sky Link Blue #2997ff) — Action Blue would disappear against `{colors.surface-tile-1}`.
### Cards & Containers
**`product-tile-light`** — Full-bleed light tile. Background `{colors.canvas}` (white), text `{colors.ink}`, rounded `{rounded.none}` (0 — tiles touch edges), vertical padding `{spacing.section}` (80px). Centered stack: product name in `{typography.display-lg}` (40px / 600) → one-line tagline in `{typography.lead}` (28px / 400) → two `{component.button-primary}` CTAs ("Learn more" / "Buy") → product render resting on the surface with the system shadow.
**`product-tile-parchment`** — Same as `{component.product-tile-light}` but on `{colors.canvas-parchment}` (#f5f5f7). Used to break two consecutive white tiles.
**`product-tile-dark`** — Full-bleed dark tile. Background `{colors.surface-tile-1}` (#272729), text `{colors.on-dark}`, rounded `{rounded.none}`, vertical padding `{spacing.section}` (80px). Same content stack as the light tile but with `{component.text-link-on-dark}` for inline copy and `{component.button-primary}` (Action Blue still works on the dark surface). Used on the homepage product grid as the alternating dark band.
**`product-tile-dark-2`** — Variant on `{colors.surface-tile-2}` (#2a2a2c). Used where a dark tile sits directly above or below `{component.product-tile-dark}` to create the faintest separation through micro-step lightness change.
**`product-tile-dark-3`** — Variant on `{colors.surface-tile-3}` (#252527). Used at the bottom of the stack and in embedded video/player frames.
**`store-utility-card`** — Used in store grid and accessories grid. Background `{colors.canvas}` (white), 1px solid `{colors.hairline}` border, rounded `{rounded.lg}` (18px), padding `{spacing.lg}` (24px). Top: product image (1:1 crop with `{rounded.sm}` (8px) inner image radius). Below: product name in `{typography.body-strong}` (17px / 600), price in `{typography.body}` (17px / 400), and a `{component.text-link}` ("Buy" or "Learn more"). No shadow by default; product render itself carries the system product-shadow.
**`configurator-option-chip`** — Pill-shaped tappable cell used in the iPhone 17 Pro buy page. Background `{colors.canvas}`, text `{colors.ink}` in `{typography.caption}`, rounded `{rounded.pill}`, padding 12px × 16px. Contains a small product thumbnail + label + price delta. Arranged in a grid of 4–5 options per row.
**`configurator-option-chip-selected`** — Selected state. Border upgrades to 2px solid `{colors.primary-focus}`. Same shape, same content.
**`environment-quote-card`** — A photographic-canvas hero specific to the environment page. Dark photographic backdrop (mountain vista at dawn) with `{colors.surface-tile-1}` as the fallback color, centered white-text headline in `{typography.display-lg}` (40px), small green "Apple 2030" pictographic logo above the headline, single `{component.button-primary}` below. Padding `{spacing.section}` (80px).
**`floating-sticky-bar`** — Floats at the bottom of the viewport on the iPhone 17 Pro buy page during scroll. Background `{colors.canvas-parchment}` at 80% opacity with `backdrop-filter: blur(N)`, height 64px, padding 12px × 32px. Left: running price total in `{typography.body}`. Right: `{component.button-primary}` ("Add to Bag").
### Inputs & Forms
**`search-input`** — The accessories search input. Background `{colors.canvas}`, text `{colors.ink}` in `{typography.body}` (17px), 1px solid `rgba(0, 0, 0, 0.08)` border, rounded `{rounded.pill}` (full pill — search is also pill-shaped, matching the CTA grammar), padding 12px × 20px, height 44px. Leading icon: search glyph at 14px, muted tint.
Error and validation states were not surfaced in the analyzed pages.
### Footer
**`footer`** — Background `{colors.canvas-parchment}` (#f5f5f7), text `{colors.ink-muted-80}`. Link columns in `{typography.dense-link}` (17px / 400 / 2.41 line-height — the relaxed leading is what makes the dense columns scannable). Column headings in `{typography.caption-strong}` (14px / 600). Legal row at the very bottom in `{typography.fine-print}` (12px / 400) with `{colors.ink-muted-48}` text. Vertical padding 64px.
## Do's and Don'ts
### Do
- Use `{colors.primary}` (Action Blue #0066cc) for every interactive element — links, pill CTAs, focus signals — and nothing else. The single accent is non-negotiable.
- Set headlines in `{typography.hero-display}` or `{typography.display-lg}` with negative letter-spacing (`-0.28 → -0.374px`) to get the signature "Apple tight" cadence.
- Run body copy at `{typography.body}` (17px / 400 / 1.47 / -0.374px) — not 16px. The extra pixel defines the brand's reading pace.
- Alternate `{component.product-tile-light}` (or parchment) and `{component.product-tile-dark}` for full-bleed section rhythm. The color change IS the divider.
- Reserve `{rounded.pill}` for the primary blue CTA and any other element that should read as an "action" (configurator chips, search input, sticky bar CTA).
- Apply the single product-shadow (`rgba(0, 0, 0, 0.22) 3px 5px 30px`) only to product renders resting on a surface — never on cards, buttons, or text.
- Use `transform: scale(0.95)` as the active/press state on every button — it's the system-wide micro-interaction.
- Keep the global nav `{colors.surface-black}` (true black) — it's the only place pure black appears on most pages.
### Don't
- Don't introduce a second accent color; every "click me" signal is `{colors.primary}` (Action Blue).
- Don't add shadows to cards, buttons, or text — shadow is reserved for product imagery.
- Don't use gradients as decorative backgrounds; atmosphere comes from photography.
- Don't set body copy at weight 500 — Apple's ladder is 300 / 400 / 600 / 700, with 500 deliberately absent. Body is always 400; strong inline is 600; display is 600.
- Don't round full-bleed tiles — tiles are rectangular and edge-to-edge; the color change is the divider.
- Don't tighten line-height below 1.47 for body copy — the editorial leading is part of the brand.
- Don't mix radii grammars — use `{rounded.sm}` for compact utility, `{rounded.lg}` for utility cards, `{rounded.pill}` for pills, and nothing in between (except the rare `{rounded.md}` Pearl Button).
- Don't use `{colors.primary-on-dark}` (Sky Link Blue) on light surfaces — it's the dark-tile-only variant. Action Blue is for light surfaces.
## Responsive Behavior
### Breakpoints
| Name | Width | Key Changes |
|---|---|---|
| Small phone | ≤ 419px | Single-column tiles; sub-nav collapses to category name + primary CTA only; hero typography drops to 28px |
| Phone | 420–640px | Single-column stack; product renders scale to 80% of tile width; hero h1 drops to 34px |
| Large phone | 641–735px | Tiles transition to tighter padding (48px vertical vs 80px); fine-print wraps |
| Tablet portrait | 736–833px | Global nav collapses to hamburger; sub-nav hides category chips, keeps primary CTA |
| Tablet landscape | 834–1023px | Global nav returns fully expanded; 3-column utility grids become 2-column |
| Small desktop | 1024–1068px | Product tiles use 2/3 width with margin gutters; hero h1 stays at 40px |
| Desktop | 1069–1440px | Full layout; 4–5 column store grids; 1440px content max |
| Wide desktop | ≥ 1441px | Content locks at 1440px, margins absorb extra width |
The structural breakpoints that matter for agents: 1440px (content lock), 1068px (small-desktop), 833px (tablet landscape switch), 734px (tablet portrait), 640px (phone), 480px (small phone).
### Touch Targets
- Minimum 44 × 44px. `{component.button-primary}` lands at ~44 × 100px (with the full-pill radius making the visible hit area more generous than the label suggests).
- `{component.button-icon-circular}` is exactly 44 × 44px.
- Global nav utility links are smaller (~32 × 80px) — they deliberately sit at a tighter target because they're precision desktop actions, and the mobile hamburger replaces them at ≤ 833px.
### Collapsing Strategy
- **Global nav**: full horizontal link row on desktop → collapses to Apple logo + hamburger + bag icon at 834px and below.
- **Sub-nav**: category name + inline links + primary CTA → category name + primary CTA only at mobile; inline links move into a hamburger tray.
- **Product tiles**: stack from 2-column to 1-column at 834px; vertical padding tightens from 80px → 48px at small-phone.
- **Utility grids** (store, accessories): 5-col → 4-col (1440px) → 3-col (1068px) → 2-col (834px) → 1-col (640px).
- **Hero typography**: `{typography.hero-display}` (56px) → `{typography.display-lg}` (40px) at 1068px → 34px at 640px → 28px at 419px.
### Image Behavior
- All product imagery uses responsive `srcset` with breakpoint-matched crops.
- Hero photography may switch art direction at mobile (e.g., the environment page's vista crops to a taller aspect ratio on mobile, framing the subject differently).
- Product renders maintain their 1:1 or 4:3 aspect ratios across breakpoints; only scale changes.
- Lazy-loading is default; the above-fold hero loads eagerly.
## Iteration Guide
1. Focus on ONE component at a time. Reference its YAML key directly (`{component.product-tile-dark}`, `{component.search-input}`).
2. Variants of an existing component (`-active`, `-focus`, `-2`, `-3`) live as separate entries in `components:`.
3. Use `{token.refs}` everywhere — never inline hex.
4. Never document hover. Default and Active/Pressed states only.
5. Display headlines stay SF Pro Display 600 with negative letter-spacing. Body stays SF Pro Text 400 at 17px. The boundary is unbreakable.
6. The single drop-shadow (`rgba(0, 0, 0, 0.22) 3px 5px 30px`) is reserved for product photography only.
7. When in doubt about emphasis: alternate surface (light → dark tile) before adding chrome.
## Known Gaps
- Form validation and error states were not surfaced on the analyzed pages; only the neutral search input is documented.
- The homepage's embedded video/player frame uses `{colors.surface-black}`; interior player controls are not documented (they're a platform widget, not a web-design token).
- Some component imagery is dynamic (rotating product hero) and its specific copy varies per surface — component specs name the structure, not the rotating content.
- Dark-mode counterparts for store and accessories utility cards were not surfaced on the analyzed pages; the system documented is the daytime/light-dominant variant Apple ships by default.
- Atmospheric photography (environment page mountain vista) is a content asset, not a design token; the documented `{component.environment-quote-card}` describes the structural surface only.
- The exact backdrop-filter blur radius on `{component.sub-nav-frosted}` and `{component.floating-sticky-bar}` is platform-dependent; production CSS uses `saturate(180%) blur(20px)` as a typical baseline but the value isn't formalized as a token.
@@ -0,0 +1,5 @@
# Apple Inspired Design System
Design system details have been moved to: https://getdesign.md/apple/design-md
You can also view previews, dark mode examples, and download options on getdesign.md.
@@ -0,0 +1,749 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Apple — reference components</title>
<meta
name="description"
content="Reference fixture for design-systems/apple. Every visible
token comes from tokens.css; the page itself follows Apple's
editorial rules — pale-gray feature ladder over white, single
Apple Action Blue accent capped at ≤2 visible uses per screen,
SF Pro display at compressed tracking, and the signature 980px
capsule CTA."
/>
<style>
/* :root paste — sourced verbatim from
design-systems/apple/tokens.css. Keep this block in sync
when tokens.css changes. The agent prompt instructs the
Designer panelist to paste this block as the FIRST thing in
their <style>, then reference everything below via var(...). */
:root {
--bg: #ffffff;
--surface: #f5f5f7;
--surface-warm: #fbfbfd;
--fg: #1d1d1f;
--fg-2: #424245;
--muted: #6e6e73;
--meta: #86868b;
--border: #d2d2d7;
--border-soft: #e8e8ed;
--accent: #0071e3;
--accent-on: #ffffff;
--accent-hover: #0077ed;
--accent-active: #0066cc;
--success: #16a34a;
--warn: #eab308;
--danger: #dc2626;
--font-display:
"SF Pro Display", "SF Pro Icons", "Helvetica Neue", Helvetica, Arial, sans-serif;
--font-body:
"SF Pro Text", "SF Pro Icons", "Helvetica Neue", Helvetica, Arial, sans-serif;
--font-mono:
"SF Mono", ui-monospace, "JetBrains Mono", Menlo, Monaco, Consolas, monospace;
--text-xs: 12px;
--text-sm: 14px;
--text-base: 17px;
--text-lg: 21px;
--text-xl: 28px;
--text-2xl: 40px;
--text-3xl: 56px;
--text-4xl: 80px;
--leading-body: 1.47;
--leading-tight: 1.05;
--tracking-display: -0.015em;
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-12: 48px;
--section-y-desktop: 100px;
--section-y-tablet: 64px;
--section-y-phone: 40px;
--radius-sm: 8px;
--radius-md: 12px;
--radius-lg: 18px;
--radius-pill: 980px;
--elev-flat: none;
--elev-ring: 0 0 0 1px var(--border);
--elev-raised: 0 12px 32px rgba(0, 0, 0, 0.08);
--focus-ring: 0 0 0 4px color-mix(in oklab, var(--accent), transparent 65%);
--motion-fast: 150ms;
--motion-base: 220ms;
--ease-standard: cubic-bezier(0.28, 0, 0.22, 1);
--container-max: 1024px;
--container-gutter-desktop: 22px;
--container-gutter-tablet: 18px;
--container-gutter-phone: 16px;
}
/* ─── Reset (minimal) ───────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
background: var(--bg);
color: var(--fg);
font-family: var(--font-body);
font-size: var(--text-base);
line-height: var(--leading-body);
font-weight: 400;
letter-spacing: -0.022em; /* SF Pro Text body, per DESIGN.md §3 */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* ─── Layout primitives ─────────────────────────────────────── */
.container {
max-width: var(--container-max);
margin-inline: auto;
padding-inline: var(--container-gutter-desktop);
}
section {
padding-block: var(--section-y-desktop);
}
/* Apple uses surface contrast, not borders, to separate chapters
(DESIGN.md §5 — "section transitions rely more on surface
changes than decorative separators"). The .band-* helpers
below switch the chapter canvas while the container stays
constant. */
.band-light { background: var(--bg); color: var(--fg); }
.band-soft { background: var(--surface); color: var(--fg); }
.band-warm { background: var(--surface-warm); color: var(--fg); }
@media (max-width: 1023px) {
.container { padding-inline: var(--container-gutter-tablet); }
section { padding-block: var(--section-y-tablet); }
}
@media (max-width: 639px) {
.container { padding-inline: var(--container-gutter-phone); }
section { padding-block: var(--section-y-phone); }
}
/* ─── Typography ────────────────────────────────────────────── */
h1, h2, h3 {
font-family: var(--font-display);
margin: 0;
color: var(--fg);
}
/* DESIGN.md §3 — Hero Display L (56px / 600 / 1.07). We set
tracking via the display token so all hero copy compresses
consistently. */
h1 {
font-size: var(--text-3xl);
font-weight: 600;
line-height: var(--leading-tight);
letter-spacing: var(--tracking-display);
}
h2 {
font-size: var(--text-2xl);
font-weight: 600;
line-height: 1.1;
letter-spacing: var(--tracking-display);
}
h3 {
font-size: var(--text-xl);
font-weight: 600;
line-height: 1.14;
letter-spacing: -0.007em; /* DESIGN.md §3 — Card/Product Title */
}
p { margin: 0; }
.lead {
font-size: var(--text-lg);
line-height: 1.38;
color: var(--fg-2);
font-weight: 400;
letter-spacing: -0.011em;
}
.body-muted { color: var(--muted); }
.body-meta { color: var(--meta); font-size: var(--text-sm); }
.body-sm { font-size: var(--text-sm); }
/* `.eyebrow` — small uppercase label above hero / section heads.
DESIGN.md §3 has no eyebrow row in the hierarchy table; this
is the agreed pattern for OD reference fixtures and uses the
12px micro-UI tier with positive tracking so the rule reads
as deliberate. */
.eyebrow {
font-family: var(--font-display);
font-size: var(--text-xs);
font-weight: 600;
line-height: 1;
color: var(--accent);
text-transform: uppercase;
letter-spacing: 0.08em;
}
.stack-3 > * + * { margin-block-start: var(--space-3); }
.stack-4 > * + * { margin-block-start: var(--space-4); }
.stack-6 > * + * { margin-block-start: var(--space-6); }
/* ─── Buttons ─────────────────────────────────────────────────
* Apple's CTA family is split across two silhouettes:
* - .btn-pill / .btn-pill-secondary — the signature 980px
* capsule used on every marketing hero and product page.
* - .btn / .btn-primary / .btn-secondary — the 8/12px-radius
* compact controls used in commerce / configurator
* surfaces where the capsule would feel too marketing-y.
*
* Both share base sizing (8/15px padding per DESIGN.md §4) and
* the focus halo. Hover lifts the blue (--accent-hover) rather
* than darkens it — Apple's documented behaviour. Press scales
* the button down 2% per DESIGN.md §4 ("active controls
* commonly reduce scale to indicate physical press"). */
.btn {
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: 8px 16px;
border: 1px solid transparent;
border-radius: var(--radius-sm);
font-family: var(--font-body);
font-weight: 500;
font-size: var(--text-sm);
line-height: 1.2;
cursor: pointer;
text-decoration: none;
transition:
background-color var(--motion-fast) var(--ease-standard),
border-color var(--motion-fast) var(--ease-standard),
transform var(--motion-fast) var(--ease-standard),
box-shadow var(--motion-fast) var(--ease-standard);
}
.btn:focus-visible {
outline: none;
box-shadow: var(--focus-ring);
}
.btn:active { transform: scale(0.98); }
.btn-primary {
background: var(--accent);
color: var(--accent-on);
}
.btn-primary:hover { background: var(--accent-hover); }
.btn-primary:active { background: var(--accent-active); }
.btn-secondary {
background: transparent;
color: var(--fg);
border-color: var(--border);
}
.btn-secondary:hover {
background: var(--surface);
border-color: var(--meta);
}
/* The Apple capsule. --radius-pill is bound to 980px in tokens
(the literal published Apple value); the geometry is the
brand signature and earns its own component. */
.btn-pill {
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: 12px 22px;
border: none;
border-radius: var(--radius-pill);
font-family: var(--font-body);
font-weight: 400;
font-size: var(--text-base);
line-height: 1.2;
letter-spacing: -0.005em;
cursor: pointer;
text-decoration: none;
background: var(--accent);
color: var(--accent-on);
transition:
background-color var(--motion-fast) var(--ease-standard),
transform var(--motion-fast) var(--ease-standard),
box-shadow var(--motion-fast) var(--ease-standard);
}
.btn-pill:hover { background: var(--accent-hover); }
.btn-pill:active { background: var(--accent-active); transform: scale(0.98); }
.btn-pill:focus-visible {
outline: none;
box-shadow: var(--focus-ring);
}
.btn-pill-secondary {
background: transparent;
color: var(--accent);
box-shadow: var(--elev-ring);
}
.btn-pill-secondary:hover {
background: var(--surface);
color: var(--accent-hover);
}
.btn-pill-secondary:active {
color: var(--accent-active);
transform: scale(0.98);
}
/* ─── Inputs ────────────────────────────────────────────────
* Apple's retail inputs are border-led rather than fill-led —
* a hairline #d2d2d7 box on white, dark text, the focus halo
* tightens the border to --accent and adds the blue glow.
* Density stays quiet so device imagery dominates. */
.field {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.field label {
font-size: var(--text-sm);
font-weight: 500;
color: var(--fg);
letter-spacing: -0.016em;
}
.field input {
padding: 12px 14px;
border-radius: var(--radius-sm);
border: 1px solid var(--border);
background: var(--bg);
color: var(--fg);
font-family: var(--font-body);
font-size: var(--text-base);
line-height: 1.2;
outline: none;
transition:
border-color var(--motion-fast) var(--ease-standard),
box-shadow var(--motion-fast) var(--ease-standard);
}
.field input::placeholder { color: var(--muted); }
.field input:hover { border-color: var(--meta); }
.field input:focus-visible {
border-color: var(--accent);
box-shadow: var(--focus-ring);
}
.field-help {
font-size: var(--text-xs);
color: var(--muted);
}
/* ─── Cards ─────────────────────────────────────────────────
* Two intents:
* - .card plain editorial / product card. Lives on
* pale gray (--surface) bands; lifts to
* white (--bg) with a hairline. No shadow
* by default — surface contrast does the
* work.
* - .card-feature featured spotlight. Squircle 18px
* (--radius-lg), the soft Apple shadow on
* hover. Used sparingly — one per band. */
.card {
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
padding: var(--space-6);
display: flex;
flex-direction: column;
gap: var(--space-3);
transition: box-shadow var(--motion-base) var(--ease-standard);
}
.card:hover {
box-shadow: var(--elev-raised);
}
.card-feature {
background: var(--surface-warm);
border: 1px solid var(--border-soft);
border-radius: var(--radius-lg);
padding: var(--space-8) var(--space-6);
display: flex;
flex-direction: column;
gap: var(--space-4);
box-shadow: var(--elev-raised);
}
/* ─── Badges ──────────────────────────────────────────────── */
.badge {
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: 4px var(--space-3);
border-radius: var(--radius-pill);
font-family: var(--font-body);
font-size: var(--text-xs);
font-weight: 500;
line-height: 1.4;
letter-spacing: -0.01em;
}
.badge-success {
color: var(--success);
background: color-mix(in oklab, var(--success), transparent 90%);
}
.badge-muted {
color: var(--muted);
background: color-mix(in oklab, var(--muted), transparent 88%);
}
.badge-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: currentColor;
}
/* ─── Links ─────────────────────────────────────────────────
* Apple's link tone uses Body Link Blue (#0066cc, our
* --accent-active) for inline reading, with the chevron-arrow
* suffix on call-to-action links. The base color is --accent
* for buttons / nav; here we re-bind for the inline reading
* tone via --accent-active. */
a {
color: var(--accent-active);
text-decoration: none;
}
a:hover {
text-decoration: underline;
text-underline-offset: 3px;
}
/* ─── Kbd ─────────────────────────────────────────────────── */
kbd {
font-family: var(--font-mono);
font-size: var(--text-xs);
font-weight: 500;
padding: 2px 6px;
border-radius: var(--radius-sm);
border: 1px solid var(--border);
background: var(--bg);
color: var(--fg-2);
}
/* ─── Distinctive: glass nav strip ──────────────────────────
* DESIGN.md §4 — "Global Marketing Nav: compact dark translucent
* bar with small-type links and restrained iconography." We
* implement the light counterpart: a frosted white strip with
* backdrop-blur, hairline bottom border, and SF Pro Text 14px
* link tier. The blur is what gives Apple chrome its signature
* "atmospheric layering" (DESIGN.md §6). */
.nav {
position: sticky;
top: 0;
z-index: 10;
background: color-mix(in oklab, var(--bg), transparent 20%);
-webkit-backdrop-filter: saturate(180%) blur(20px);
backdrop-filter: saturate(180%) blur(20px);
border-bottom: 1px solid var(--border-soft);
}
.nav-inner {
max-width: var(--container-max);
margin-inline: auto;
padding-inline: var(--container-gutter-desktop);
height: 44px;
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-6);
}
.nav-brand {
font-family: var(--font-display);
font-size: var(--text-base);
font-weight: 500;
color: var(--fg);
letter-spacing: -0.011em;
}
.nav-links {
display: flex;
gap: var(--space-6);
list-style: none;
padding: 0;
margin: 0;
}
.nav-links a {
font-size: var(--text-sm);
font-weight: 400;
color: var(--fg);
letter-spacing: -0.016em;
opacity: 0.8;
transition: opacity var(--motion-fast) var(--ease-standard);
}
.nav-links a:hover {
opacity: 1;
text-decoration: none;
}
@media (max-width: 639px) {
.nav-inner { gap: var(--space-3); padding-inline: var(--container-gutter-phone); }
.nav-links { gap: var(--space-4); }
}
/* ─── Section-specific layout ───────────────────────────── */
.hero-grid {
display: grid;
grid-template-columns: 1.3fr 1fr;
gap: var(--space-12);
align-items: end;
}
@media (max-width: 1023px) {
.hero-grid { grid-template-columns: 1fr; gap: var(--space-8); }
}
.hero-actions {
display: flex;
flex-wrap: wrap;
gap: var(--space-3);
margin-block-start: var(--space-6);
}
.hero-meta {
display: flex;
flex-direction: column;
gap: var(--space-3);
padding: var(--space-5);
border: 1px solid var(--border);
border-radius: var(--radius-md);
background: var(--bg);
}
.features-grid {
display: grid;
grid-template-columns: 1.3fr 1fr 1fr;
gap: var(--space-5);
}
@media (max-width: 1023px) {
.features-grid { grid-template-columns: 1fr 1fr; }
.features-grid > :first-child { grid-column: span 2; }
}
@media (max-width: 639px) {
.features-grid { grid-template-columns: 1fr; }
.features-grid > :first-child { grid-column: auto; }
}
.form-row {
display: grid;
grid-template-columns: 1.3fr 1fr;
gap: var(--space-12);
align-items: start;
}
@media (max-width: 1023px) {
.form-row { grid-template-columns: 1fr; gap: var(--space-8); }
}
.form {
display: flex;
flex-direction: column;
gap: var(--space-4);
max-width: 420px;
}
.form-actions {
display: flex;
flex-wrap: wrap;
gap: var(--space-3);
margin-block-start: var(--space-2);
}
.icon { width: 16px; height: 16px; flex-shrink: 0; }
.row-between {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-3);
}
</style>
</head>
<body>
<!-- ════════════════════════════════════════════════════════════
NAV — Apple's distinctive frosted-glass strip. Sticky to top,
44px tall, SF Pro Text 14px links at 0.8 opacity that
brighten on hover. Backdrop saturate + blur is what gives
Apple chrome its atmospheric layering (DESIGN.md §6).
═══════════════════════════════════════════════════════════════ -->
<header class="nav" data-od-id="nav">
<div class="nav-inner">
<span class="nav-brand">Apple</span>
<nav aria-label="Primary">
<ul class="nav-links">
<li><a href="#hero">Tokens</a></li>
<li><a href="#features">System</a></li>
<li><a href="#form">Contact</a></li>
</ul>
</nav>
</div>
</header>
<main>
<!-- ════════════════════════════════════════════════════════════
HERO — exercises: h1 (56px display, tracking -0.015em),
.lead, .eyebrow, .btn-pill (the signature 980px capsule)
paired with .btn-pill-secondary (ring-edge counterpart),
kbd, .badge-success. Asymmetric grid (1.3:1) so the
composition doesn't read as a generic centered template.
═══════════════════════════════════════════════════════════════ -->
<section class="band-light" data-od-id="hero" id="hero">
<div class="container">
<div class="hero-grid">
<div class="stack-4">
<p class="eyebrow">Reference fixture · Apple</p>
<h1>Quiet chrome. Loud product. One token block.</h1>
<p class="lead" style="max-width: 52ch">
The interface engineered to disappear, distilled into
fifty-six tokens. Pale-gray feature ladder over white,
a single Apple Action Blue, SF Pro at compressed
tracking, and the 980-pixel capsule that has carried
every Buy button for a decade.
</p>
<div class="hero-actions">
<a href="./tokens.css" class="btn-pill">
View tokens
<svg
class="icon"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.75"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="M5 12h14M13 6l6 6-6 6" />
</svg>
</a>
<a href="./DESIGN.md" class="btn-pill btn-pill-secondary">
Read the spec
</a>
</div>
</div>
<aside class="hero-meta" aria-label="System status">
<div class="row-between">
<span class="body-sm">System status</span>
<span class="badge badge-success">
<span class="badge-dot" aria-hidden="true"></span>
Stable
</span>
</div>
<p class="body-sm body-muted">
Last reviewed
<time datetime="2026-05-14">2026-05-14</time> · v0.1
</p>
<p class="body-sm body-muted">
Press <kbd>⌘</kbd> <kbd>K</kbd> to search tokens.
</p>
</aside>
</div>
</div>
</section>
<!-- ════════════════════════════════════════════════════════════
FEATURES — band switches to pale Apple gray (--surface),
cards lift back to white with a hairline. The first card
is .card-feature (squircle, soft Apple shadow), the next
two are plain .card. Each card describes a real property
of this fixture (no "feature one/two/three" filler).
═══════════════════════════════════════════════════════════════ -->
<section class="band-soft" data-od-id="features" id="features">
<div class="container">
<div class="stack-3" style="max-width: 720px">
<p class="eyebrow">What this fixture exercises</p>
<h2>Every component below uses only var(--*).</h2>
<p class="lead body-muted">
Three cards, three real schema decisions worth
inspecting. Rebind the token block and the same shapes
follow.
</p>
</div>
<div class="features-grid" style="margin-block-start: var(--space-12)">
<article class="card-feature">
<p class="eyebrow">Featured</p>
<h3>Surface ladder, three stops, no aliasing.</h3>
<p class="body-muted">
Pure white retail canvas, near-white bridge, pale
Apple gray feature band. Apple's three light tiers
are real, so we keep --surface-warm independent of
--surface instead of collapsing it. Cards on the
gray band lift back to white with a hairline.
</p>
<div>
<a href="./tokens.css" class="btn btn-secondary">
Inspect tokens
</a>
</div>
</article>
<article class="card">
<h3>Accent discipline</h3>
<p class="body-muted body-sm">
--accent appears at most twice on this screen — the
primary capsule CTA and the focus halo. The hero
status uses --success instead, so the page does not
feel mono-blue.
</p>
<a href="./DESIGN.md" class="body-sm">Read the rule →</a>
</article>
<article class="card">
<h3>Type at scale</h3>
<p class="body-muted body-sm">
SF Pro Display for the hero, SF Pro Text for body and
controls, body baseline at 17px (not 16), display
tracking compressed to -0.015em. Hierarchy comes from
size and weight — never a third type face.
</p>
<a href="./tokens.css" class="body-sm">Inspect typography →</a>
</article>
</div>
</div>
</section>
<!-- ════════════════════════════════════════════════════════════
FORM — exercises: .field, input :focus-visible (border
tightens to --accent + the 4px blue halo), .btn-primary
(the compact 8px-radius commerce CTA), .btn-secondary
(border-led counterpart), .field-help. Band switches to
the warm near-white tier so the form reads as a quiet
transactional surface, not a hero.
═══════════════════════════════════════════════════════════════ -->
<section class="band-warm" data-od-id="form" id="form">
<div class="container">
<div class="form-row">
<div class="stack-4">
<p class="eyebrow">Form components</p>
<h2>Inputs inherit the same tokens.</h2>
<p class="lead body-muted" style="max-width: 48ch">
Border-led containment, dark Near-Black Ink text, the
focus halo at four pixels of soft Apple Action Blue.
The submit button reuses the compact .btn-primary —
no new token introduced for this section.
</p>
</div>
<form class="form" onsubmit="event.preventDefault();">
<div class="field">
<label for="email">Apple ID email</label>
<input
id="email"
type="email"
placeholder="you@icloud.com"
autocomplete="email"
required
/>
<p class="field-help">
We'll send the spec PDF and nothing else.
</p>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">
Send the spec
</button>
<button type="button" class="btn btn-secondary">
Skip for now
</button>
</div>
</form>
</div>
</div>
</section>
</main>
</body>
</html>
@@ -0,0 +1,286 @@
/* ─────────────────────────────────────────────────────────────────────────
* design-systems/apple/tokens.css
*
* Structured token bindings for the Apple-inspired design system —
* a precision editorial language built around white-space discipline,
* SF Pro typography, and a single restrained blue accent. This file
* is the *machine-readable* form of the values described in
* `DESIGN.md`. Agents are expected to paste the `:root { … }` block
* verbatim into the first `<style>` of every artifact they generate
* against this design system, then reference everything via
* var(--name) from then on.
*
* Why this file exists:
* DESIGN.md tells humans that Apple uses "Pale Apple Gray (#f5f5f7)
* as the main light surface" and "Apple Action Blue (#0071e3) as the
* primary accent", but agents have to translate those prose names
* into the standard token names the lint enforces (`--surface`,
* `--accent`). That translation step is where token misuse happens.
* This file pre-translates the brand once, so agents copy structure
* instead of inventing it.
*
* Brand-specific schema decisions (non-obvious bindings worth flagging
* for reviewers and downstream brand authors):
* 1. We bind --surface-warm to a real intermediate tier (#fbfbfd),
* NOT an alias of --surface. Apple's surface ladder genuinely has
* three light stops — pure white retail canvas, near-white
* brightness-shifted bands, and pale Apple gray feature fields —
* so collapsing surface-warm would erase a real brand feature.
* 2. We bind --fg-2, --meta, and --border-soft to independent values
* rather than aliases. Apple's neutral text ramp is famously
* four-stop (Near-Black Ink → Utility Dark Gray → Secondary
* Neutral Gray → Mid Border Gray) and the schema's B-slots map
* onto it cleanly.
* 3. --radius-pill is bound to 980px, not 9999px. Apple's signature
* capsule CTA literally uses 980px in published CSS, and the
* number is itself a brand-recognisable detail; we keep it.
* 4. --accent-hover lifts (#0077ed) instead of darkening. Apple's
* live blue buttons brighten slightly on hover rather than mix
* toward black; the schema's default formula would fight that.
* --accent-active darkens to #0066cc — the documented Body Link
* Blue — so the active state aligns with Apple's read-link tone.
* 5. --tracking-display is -0.015em. The DESIGN.md hierarchy lists
* -1.2px on 80px hero (-0.015em); tighter than that breaks at
* smaller display sizes, looser loses Apple's machined feel.
* 6. --section-y-desktop is 100px. Apple's billboard chapters lean
* noticeably more generous than the schema default of 80px — the
* breathing room is what lets product imagery do the talking.
* 7. --ease-standard is cubic-bezier(0.28, 0, 0.22, 1), an Apple-
* flavoured smooth-out instead of the schema default. Apple
* transitions decelerate hard then settle, never bounce.
*
* Contract sources:
* - Standard token names: design-systems/_schema/tokens.schema.ts
* (TOKEN_SCHEMA — every name below appears there or as an
* explicit B-slot alias.)
* - A2 fallback values: design-systems/_schema/defaults.css
* (We override --motion-base, --ease-standard, --elev-raised,
* --focus-ring, --radius-pill; the rest match defaults.)
* - Lint enforcement: apps/daemon/src/lint-artifact.ts
* (raw-hex >12 outside :root → P1; non-token accent → P0)
*
* Keep this file additive: never invent token names not also documented
* in DESIGN.md or the shared schema. New Apple-derived sub-brands
* cloning this template should overwrite values, not rename keys.
* ─────────────────────────────────────────────────────────────────── */
:root {
/* ─── Surface (3 levels) ──────────────────────────────────────────
* Apple's binary section rhythm alternates pure white retail/hero
* canvases with pale Apple gray feature fields. We bind --bg to
* the white canvas (the most common default Apple page background)
* and --surface to the pale gray that cards and feature bands lift
* onto. --surface-warm is bound to a real third tier (#fbfbfd) —
* the near-white brightness shift that appears between hero and
* pale-gray bands on apple.com. Collapsing it to var(--surface)
* would erase a real brand feature, so we keep it independent. */
--bg: #ffffff;
--surface: #f5f5f7;
--surface-warm: #fbfbfd;
/* ─── Foreground ramp (4 levels) ─────────────────────────────────
* Apple's text neutrals are explicitly named in DESIGN.md §2:
* Near-Black Ink (primary), Utility Dark Gray (secondary text /
* dark-neutral surfaces in store contexts), Secondary Neutral Gray
* (helper copy / tertiary metadata), Mid Border Gray (the strongest
* neutral, used for stronger field outlines and the most-restrained
* caption tier). We bind all four — Apple genuinely walks the full
* ramp, so collapsing --fg-2 or --meta to siblings would flatten
* the brand.
*
* Note that none of these are pure black (#000000). #000000 is
* reserved for hero canvases and dark chapters; for body type on
* white, #1d1d1f gives the slight warmth that reads as Apple. */
--fg: #1d1d1f;
--fg-2: #424245;
--muted: #6e6e73;
--meta: #86868b;
/* ─── Border (2 levels) ──────────────────────────────────────────
* Soft Border Gray (#d2d2d7) is Apple's default divider weight and
* card-edge color. --border-soft is bound to a lighter near-neutral
* (#e8e8ed) for inner row separators in dense retail tables and
* configurator option lists, where the d2d2d7 hairline would
* over-compete with the option labels. */
--border: #d2d2d7;
--border-soft: #e8e8ed;
/* ─── Accent ──────────────────────────────────────────────────────
* Apple Action Blue — the system's only persistent chromatic move.
* DESIGN.md §7 ("Don't introduce broad secondary accent palettes
* that compete with Apple blue") makes this a one-color brand for
* action and link semantics; the schema's hard cap of ≤2 visible
* accent uses per screen aligns naturally. */
--accent: #0071e3;
--accent-on: #ffffff; /* white label on the blue fill */
/* ─── Accent states ───────────────────────────────────────────────
* Apple's live primary buttons LIGHTEN on hover (the blue gains
* luminance) and darken on press. The schema's default black-mix
* formula would fight that motion, so we hand-pick both values:
* - hover: #0077ed (≈ 4% brighter than --accent)
* - active: #0066cc (the documented Body Link Blue from DESIGN.md
* §2, which doubles cleanly as the press tone)
*
* Schema rule: every brand provides --accent-hover and
* --accent-active. The binding strategy (formula / hand-picked /
* identity) is brand-decided. Default uses formulas; kami uses
* identity + hand-picked; Apple uses hand-picked in both
* directions. */
--accent-hover: #0077ed;
--accent-active: #0066cc;
/* ─── Semantic ────────────────────────────────────────────────────
* Apple's DESIGN.md §2 explicitly notes "no distinct semantic
* palette was consistently visible in the extracted surface set" —
* so we inherit the schema defaults verbatim. Apple artifacts
* almost never need success / warn / danger; when they do, the
* defaults are restrained enough not to fight the blue accent.
* Reserve under 5% of any surface area regardless. */
--success: #16a34a;
--warn: #eab308;
--danger: #dc2626;
/* ─── Typography ──────────────────────────────────────────────────
* Apple's documented split is two SF Pro families: SF Pro Display
* for hero / merchandising headings, SF Pro Text for navigation,
* controls, and dense commerce copy. We mirror the exact published
* fallback chain (SF Pro Icons → Helvetica Neue → Helvetica → Arial
* → sans-serif) so artifacts rendered on non-macOS clients land on
* the closest practical substitute.
*
* SF Mono leads the monospace stack — Apple's brand mono — with
* the schema fallbacks behind it for portability. */
--font-display:
"SF Pro Display", "SF Pro Icons", "Helvetica Neue", Helvetica, Arial, sans-serif;
--font-body:
"SF Pro Text", "SF Pro Icons", "Helvetica Neue", Helvetica, Arial, sans-serif;
--font-mono:
"SF Mono", ui-monospace, "JetBrains Mono", Menlo, Monaco, Consolas, monospace;
/* Type scale (px) — derived from DESIGN.md §3 hierarchy table.
* Apple's body baseline is 17px (NOT the 16px web norm) because
* SF Pro Text was metrically tuned at 17 for Retina; rebinding
* --text-base to anything else collapses the brand's reading
* texture. The display ceiling is the 80px Hero Display XL. */
--text-xs: 12px; /* Micro UI — fine print, micro labels */
--text-sm: 14px; /* Control Label — buttons, helper labels */
--text-base: 17px; /* Body Primary — Apple's reading baseline */
--text-lg: 21px; /* Link/Action Heading — large promo links */
--text-xl: 28px; /* Card/Product Title — tile-level naming */
--text-2xl: 40px; /* Product Heading — campaign section titles */
--text-3xl: 56px; /* Hero Display L — homepage hero moments */
--text-4xl: 80px; /* Hero Display XL — Environment / store hero */
/* Apple's leading envelope is unusually tight at the top of the
* scale (display sizes ride at 1.00–1.10) and unusually airy in
* the body (1.47, well above the web 1.4 default). Both numbers
* come straight from DESIGN.md §3. */
--leading-body: 1.47; /* SF Pro Text body, 17px */
--leading-tight: 1.05; /* Hero Display XL ceiling */
/* Display tracking compresses to -0.015em — the famous Apple
* machined-headline feel. DESIGN.md §3 lists -1.2px on 80px
* (≈ -0.015em); we bind a single em-value so the same rule applies
* across the display tiers. Body type runs at 0 / -0.374px and is
* left to component-level rules so as not to hurt readability. */
--tracking-display: -0.015em;
/* ─── Spacing ─────────────────────────────────────────────────────
* Apple's underlying grid is 8px (DESIGN.md §5), with utility
* micro-steps (2/4/6/7/8/9/10) for precision alignment. The shared
* schema's 4-8-12-16-20-24-32-48 scale fits cleanly — we inherit
* the defaults. Component-internal values that don't match a token
* (Apple's 14px or 17px utility intervals) stay inline at the
* call site rather than spawning extra spacing tokens. */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-12: 48px;
/* ─── Section rhythm ──────────────────────────────────────────────
* Apple's billboard chapters lean noticeably more generous than the
* schema default of 80px — broad top/bottom breathing room is what
* lets product imagery dominate the page. We bind 100/64/40, a
* slightly wider envelope than default's 80/48/32. */
--section-y-desktop: 100px;
--section-y-tablet: 64px;
--section-y-phone: 40px;
/* ─── Radius ──────────────────────────────────────────────────────
* Apple uses purposeful radius tiers (DESIGN.md §5 §7 — "don't
* flatten all corners to a single radius"). The mapping:
* --radius-sm → 8px compact controls and fields
* --radius-md → 12px standard buttons, configurator chips
* --radius-lg → 18px cards, module frames, commerce panels
* --radius-pill → 980px Apple's signature capsule CTA — we keep
* the literal value rather than collapse
* to 9999px because the number itself is
* a brand-recognisable detail in Apple's
* published CSS.
*
* The 28-36px spotlight tier and the 56px capsule sub-tier are
* component-internal one-offs and stay inline — they do not earn
* their own tokens until a second use appears. */
--radius-sm: 8px;
--radius-md: 12px;
--radius-lg: 18px;
--radius-pill: 980px;
/* ─── Elevation (3 levels) ────────────────────────────────────────
* Apple uses depth sparingly (DESIGN.md §6 — "depth is intentionally
* restrained"). Three sanctioned levels:
* - flat → none (the default; tonal contrast does the work)
* - ring → 0 0 0 1px var(--border) (border-led containment in
* dense retail contexts)
* - raised → 0 12px 32px rgba(0,0,0,0.08) (the soft Apple card
* shadow; rgba 0.08 is the lower bound from DESIGN.md
* §6's "0.08 → 0.22" range, which keeps cards from
* feeling Material-flavoured)
*
* No fourth level — that would be the Material/neumorphism stack
* Apple consciously avoids. */
--elev-flat: none;
--elev-ring: 0 0 0 1px var(--border);
--elev-raised: 0 12px 32px rgba(0, 0, 0, 0.08);
/* ─── Focus ring ──────────────────────────────────────────────────
* Apple's keyboard-focus signal is a soft blue glow at the action
* accent (DESIGN.md §6 — "Blue focus signal (#0071e3) for keyboard
* and selection emphasis"). We use a 4px ring at ~35% accent
* opacity, slightly larger than the schema's 3px default so it
* reads as the deliberate Apple halo rather than a generic outline.
* Implemented as a box-shadow so it layers outside the element
* without affecting layout. */
--focus-ring: 0 0 0 4px color-mix(in oklab, var(--accent), transparent 65%);
/* ─── Motion ──────────────────────────────────────────────────────
* Apple transitions decelerate hard and settle — never bounce,
* never spring past the target. We override the schema default
* easing with cubic-bezier(0.28, 0, 0.22, 1), the curve Apple
* uses on apple.com for hover and section reveals; --motion-base
* is bumped from 200ms → 220ms because Apple's micro-interactions
* carry slightly more cinematic weight than the web default.
* --motion-fast stays at 150ms for true micro-states (hover tints,
* focus, kbd press feedback). */
--motion-fast: 150ms;
--motion-base: 220ms;
--ease-standard: cubic-bezier(0.28, 0, 0.22, 1);
/* ─── Layout ──────────────────────────────────────────────────────
* Apple's marketing core is a constrained readable column with
* generous outer margins (DESIGN.md §5). 1024px max keeps lines
* inside the SF Pro Text comfortable-measure ceiling (~80ch at
* 17px) while leaving the chapter band full-bleed. Gutters step
* 22 → 18 → 16 across desktop / tablet / phone — slightly tighter
* than default to honor Apple's "broad horizontal breathing room
* but column-disciplined content" balance. */
--container-max: 1024px;
--container-gutter-desktop: 22px;
--container-gutter-tablet: 18px;
--container-gutter-phone: 16px;
}