项目文件夹

文件
wehub-resource-sync 070959e133
landing-page-staging / Deploy landing page to staging (push) Has been skipped
landing-page-ci / Validate landing page (push) Failing after 4s
visual-baseline / Capture visual baselines (push) Has been cancelled
bake-plugin-previews / Bake plugin previews (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:00:47 +08:00

750 行
28 KiB
HTML

<!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>