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:
1 parent
7acc0c5451
commit
e45b68bb8b
1089 files changed
+260614
No files matched your search
@@ -0,0 +1,516 @@
|
||||
---
|
||||
version: alpha
|
||||
name: Shopify
|
||||
description: "An inspired interpretation of Shopify's design language — a cinematic commerce platform that runs two parallel design tracks. The marketing-hero and product-narrative pages live on near-black canvases with full-bleed photography of merchants, giant Neue Haas Grotesk display type at thin weights, and a single black-pill CTA stroked in white. The transactional pages (pricing, signup, dashboards) flip to a cream-mint canvas with pastel aloe and pistachio greens, the same pill button vocabulary, and Inter for UI body. The two tracks share typographic DNA but diverge sharply in canvas polarity — and that choice is the brand."
|
||||
|
||||
colors:
|
||||
primary: "#000000"
|
||||
ink: "#000000"
|
||||
on-primary: "#ffffff"
|
||||
on-dark: "#ffffff"
|
||||
canvas-night: "#000000"
|
||||
canvas-night-elevated: "#0a0a0a"
|
||||
canvas-light: "#ffffff"
|
||||
canvas-cream: "#fbfbf5"
|
||||
surface-elevated-dark: "#1e2c31"
|
||||
shade-30: "#d4d4d8"
|
||||
shade-40: "#a1a1aa"
|
||||
shade-50: "#71717a"
|
||||
shade-60: "#52525b"
|
||||
shade-70: "#3f3f46"
|
||||
hairline-light: "#e4e4e7"
|
||||
hairline-dark: "#1e2c31"
|
||||
aloe-10: "#c1fbd4"
|
||||
pistachio-10: "#d4f9e0"
|
||||
link-cool-1: "#9dabad"
|
||||
link-cool-2: "#9797a2"
|
||||
link-cool-3: "#bdbdca"
|
||||
link-mint: "#99b3ad"
|
||||
|
||||
typography:
|
||||
display-xxl:
|
||||
fontFamily: "NeueHaasGrotesk Display, Helvetica, Arial, sans-serif"
|
||||
fontSize: 96px
|
||||
fontWeight: 330
|
||||
lineHeight: 1.0
|
||||
letterSpacing: 2.4px
|
||||
fontFeature: ss03
|
||||
display-xl:
|
||||
fontFamily: "NeueHaasGrotesk Display, Helvetica, Arial, sans-serif"
|
||||
fontSize: 70px
|
||||
fontWeight: 330
|
||||
lineHeight: 1.0
|
||||
letterSpacing: 0
|
||||
fontFeature: ss03
|
||||
display-lg:
|
||||
fontFamily: "NeueHaasGrotesk Display, Helvetica, Arial, sans-serif"
|
||||
fontSize: 55px
|
||||
fontWeight: 330
|
||||
lineHeight: 1.16
|
||||
letterSpacing: 0
|
||||
fontFeature: ss03
|
||||
display-md:
|
||||
fontFamily: "NeueHaasGrotesk Display, Helvetica, Arial, sans-serif"
|
||||
fontSize: 48px
|
||||
fontWeight: 330
|
||||
lineHeight: 1.14
|
||||
letterSpacing: 0
|
||||
fontFeature: ss03
|
||||
heading-xl:
|
||||
fontFamily: "NeueHaasGrotesk Display, Helvetica, Arial, sans-serif"
|
||||
fontSize: 28px
|
||||
fontWeight: 500
|
||||
lineHeight: 1.28
|
||||
letterSpacing: 0.42px
|
||||
fontFeature: ss03
|
||||
heading-lg:
|
||||
fontFamily: "NeueHaasGrotesk Display, Helvetica, Arial, sans-serif"
|
||||
fontSize: 24px
|
||||
fontWeight: 400
|
||||
lineHeight: 1.14
|
||||
letterSpacing: 0.36px
|
||||
fontFeature: ss03
|
||||
heading-md:
|
||||
fontFamily: "NeueHaasGrotesk Display, Helvetica, Arial, sans-serif"
|
||||
fontSize: 20px
|
||||
fontWeight: 500
|
||||
lineHeight: 1.4
|
||||
letterSpacing: 0.3px
|
||||
fontFeature: ss03
|
||||
heading-sm:
|
||||
fontFamily: "NeueHaasGrotesk Display, Helvetica, Arial, sans-serif"
|
||||
fontSize: 18px
|
||||
fontWeight: 500
|
||||
lineHeight: 1.25
|
||||
letterSpacing: 0.72px
|
||||
fontFeature: ss03
|
||||
body-lg:
|
||||
fontFamily: "Inter Variable, Inter, Helvetica, Arial, sans-serif"
|
||||
fontSize: 18px
|
||||
fontWeight: 550
|
||||
lineHeight: 1.56
|
||||
letterSpacing: 0
|
||||
fontFeature: ss03
|
||||
body-md:
|
||||
fontFamily: "Inter Variable, Inter, Helvetica, Arial, sans-serif"
|
||||
fontSize: 16px
|
||||
fontWeight: 420
|
||||
lineHeight: 1.5
|
||||
letterSpacing: 0
|
||||
fontFeature: ss03
|
||||
body-strong:
|
||||
fontFamily: "Inter Variable, Inter, Helvetica, Arial, sans-serif"
|
||||
fontSize: 16px
|
||||
fontWeight: 550
|
||||
lineHeight: 1.5
|
||||
letterSpacing: 0
|
||||
fontFeature: ss03
|
||||
caption:
|
||||
fontFamily: "Inter Variable, Inter, Helvetica, Arial, sans-serif"
|
||||
fontSize: 14px
|
||||
fontWeight: 500
|
||||
lineHeight: 1.49
|
||||
letterSpacing: 0.28px
|
||||
fontFeature: ss03
|
||||
micro:
|
||||
fontFamily: "Inter Variable, Inter, Helvetica, Arial, sans-serif"
|
||||
fontSize: 13px
|
||||
fontWeight: 500
|
||||
lineHeight: 1.5
|
||||
letterSpacing: -0.13px
|
||||
fontFeature: ss03
|
||||
eyebrow-cap:
|
||||
fontFamily: "Inter Variable, Inter, Helvetica, Arial, sans-serif"
|
||||
fontSize: 12px
|
||||
fontWeight: 400
|
||||
lineHeight: 1.2
|
||||
letterSpacing: 0.72px
|
||||
fontFeature: ss03
|
||||
code:
|
||||
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace"
|
||||
fontSize: 16px
|
||||
fontWeight: 400
|
||||
lineHeight: 1.5
|
||||
letterSpacing: 0
|
||||
fontFeature: ss03
|
||||
|
||||
rounded:
|
||||
xs: 4px
|
||||
sm: 5px
|
||||
md: 8px
|
||||
lg: 12px
|
||||
xl: 20px
|
||||
pill: 9999px
|
||||
|
||||
spacing:
|
||||
xxs: 2px
|
||||
xs: 4px
|
||||
sm: 8px
|
||||
md: 12px
|
||||
lg: 16px
|
||||
xl: 24px
|
||||
xxl: 32px
|
||||
huge: 64px
|
||||
|
||||
components:
|
||||
button-primary-pill:
|
||||
backgroundColor: "{colors.primary}"
|
||||
textColor: "{colors.on-primary}"
|
||||
typography: "{typography.body-md}"
|
||||
rounded: "{rounded.pill}"
|
||||
padding: 12px 24px
|
||||
button-primary-pill-pressed:
|
||||
backgroundColor: "{colors.shade-70}"
|
||||
textColor: "{colors.on-primary}"
|
||||
typography: "{typography.body-md}"
|
||||
rounded: "{rounded.pill}"
|
||||
padding: 12px 24px
|
||||
button-outline-on-dark:
|
||||
backgroundColor: "{colors.canvas-night}"
|
||||
textColor: "{colors.on-primary}"
|
||||
typography: "{typography.body-md}"
|
||||
rounded: "{rounded.pill}"
|
||||
padding: 12px 26px
|
||||
button-outline-on-light:
|
||||
backgroundColor: "{colors.canvas-light}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body-md}"
|
||||
rounded: "{rounded.pill}"
|
||||
padding: 12px 24px
|
||||
button-aloe-pill:
|
||||
backgroundColor: "{colors.aloe-10}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body-md}"
|
||||
rounded: "{rounded.pill}"
|
||||
padding: 12px 24px
|
||||
text-input:
|
||||
backgroundColor: "{colors.canvas-light}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body-md}"
|
||||
rounded: "{rounded.md}"
|
||||
padding: 10px 12px
|
||||
card-pricing:
|
||||
backgroundColor: "{colors.canvas-light}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body-md}"
|
||||
rounded: "{rounded.lg}"
|
||||
padding: 32px
|
||||
card-pricing-featured:
|
||||
backgroundColor: "{colors.aloe-10}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body-md}"
|
||||
rounded: "{rounded.lg}"
|
||||
padding: 32px
|
||||
card-feature-cinematic:
|
||||
backgroundColor: "{colors.canvas-night-elevated}"
|
||||
textColor: "{colors.on-primary}"
|
||||
typography: "{typography.body-lg}"
|
||||
rounded: "{rounded.lg}"
|
||||
padding: 32px
|
||||
card-pistachio-band:
|
||||
backgroundColor: "{colors.pistachio-10}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body-md}"
|
||||
rounded: "{rounded.lg}"
|
||||
padding: 32px
|
||||
card-photo-frame:
|
||||
backgroundColor: "{colors.canvas-night}"
|
||||
textColor: "{colors.on-primary}"
|
||||
typography: "{typography.body-md}"
|
||||
rounded: "{rounded.xl}"
|
||||
padding: 0px
|
||||
pill-tag-mint:
|
||||
backgroundColor: "{colors.aloe-10}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.eyebrow-cap}"
|
||||
rounded: "{rounded.pill}"
|
||||
padding: 4px 12px
|
||||
pill-tag-shade:
|
||||
backgroundColor: "{colors.shade-30}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.eyebrow-cap}"
|
||||
rounded: "{rounded.pill}"
|
||||
padding: 4px 12px
|
||||
nav-bar-light:
|
||||
backgroundColor: "{colors.canvas-light}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.body-md}"
|
||||
rounded: "{rounded.xs}"
|
||||
padding: 16px 24px
|
||||
nav-bar-dark:
|
||||
backgroundColor: "{colors.canvas-night}"
|
||||
textColor: "{colors.on-primary}"
|
||||
typography: "{typography.body-md}"
|
||||
rounded: "{rounded.xs}"
|
||||
padding: 16px 24px
|
||||
link-on-dark:
|
||||
backgroundColor: "{colors.canvas-night}"
|
||||
textColor: "{colors.on-primary}"
|
||||
typography: "{typography.body-md}"
|
||||
rounded: "{rounded.xs}"
|
||||
padding: 0px
|
||||
footer-dark:
|
||||
backgroundColor: "{colors.canvas-night}"
|
||||
textColor: "{colors.on-primary}"
|
||||
typography: "{typography.caption}"
|
||||
rounded: "{rounded.xs}"
|
||||
padding: 64px 24px
|
||||
footer-light:
|
||||
backgroundColor: "{colors.canvas-light}"
|
||||
textColor: "{colors.ink}"
|
||||
typography: "{typography.caption}"
|
||||
rounded: "{rounded.xs}"
|
||||
padding: 64px 24px
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Shopify runs two parallel design tracks that share typographic DNA and a single button vocabulary, but diverge in canvas polarity. The marketing track lives on `{colors.canvas-night}` (`#000000`) — full-bleed cinematic photography of merchants, giant `{typography.display-xxl}` headlines in Neue Haas Grotesk Display set at weight 330 (a thin, almost editorial cut), and a single CTA: a white-stroked black pill with the form `button-outline-on-dark`. The pages read like the spread of a high-end print magazine: lots of black, lots of negative space, photography that doesn't compete with text, and one and only one action per band.
|
||||
|
||||
The transactional track flips to `{colors.canvas-light}` and `{colors.canvas-cream}` (an off-white that's barely warmer than pure white). Pricing tiers, comparison tables, and signup flows sit on this lighter canvas, with the same pill button system but in inverse polarity (a solid black pill with white text, or a `{colors.aloe-10}` mint pill for the featured / "Start free trial" tier). The accents — `{colors.aloe-10}` mint and `{colors.pistachio-10}` pistachio — show up only on the light track, never on the cinematic dark hero pages.
|
||||
|
||||
Typography is split across three families. **Neue Haas Grotesk Display** at thin weights (330–500) handles every display, headline, and editorial moment — the brand's identity is that thin display cut. **Inter Variable** at 420–550 weights handles every UI body, button label, caption, and form field — utility text that doesn't fight the display. **ui-monospace** appears only in code blocks and rare technical eyebrows. Across all three families, the OpenType `ss03` stylistic set is enabled — it's the brand's character-level signature, applied universally.
|
||||
|
||||
**Key Characteristics:**
|
||||
- Two-canvas system: `{colors.canvas-night}` for cinematic marketing, `{colors.canvas-light}` / `{colors.canvas-cream}` for transactional surfaces — never blended.
|
||||
- Pill-shape (`{rounded.pill}`) is the only button shape across both tracks; rounded rectangles do not exist for buttons.
|
||||
- Thin-weight (330) display typography is the signature; `{typography.display-xxl}` at 96px / weight 330 is the brand's loudest visual.
|
||||
- Aloe and pistachio greens (`{colors.aloe-10}`, `{colors.pistachio-10}`) are reserved for the light track — they signal commerce, growth, transactional success.
|
||||
- Photography is full-bleed, edge-to-edge, never inset in cards on the cinematic track; merchants and storefront imagery do the heavy visual lifting that gradients and illustrations would do elsewhere.
|
||||
- The OpenType `ss03` stylistic set is enabled across every text role — a character-level unifier that tracks across both tracks.
|
||||
- Tight letter-spacing on display sizes (2.4px positive tracking on 96px display) gives the thin weight extra optical air.
|
||||
|
||||
## Colors
|
||||
|
||||
> **Source pages:** home (`/`), `/start`, `/website/builder`, `/pricing`.
|
||||
|
||||
### Brand & Accent
|
||||
- **Aloe** (`{colors.aloe-10}` — `#c1fbd4`): The featured-tier and "growth" accent. Used as a pill button background on light surfaces and as a feature-card fill in the pricing comparison band.
|
||||
- **Pistachio** (`{colors.pistachio-10}` — `#d4f9e0`): Softer than aloe; used as a wide section band fill on the light track to signal a different category of feature without leaving the green family.
|
||||
- **Cool Link Tones** (`{colors.link-cool-1}` `#9dabad`, `{colors.link-cool-2}` `#9797a2`, `{colors.link-cool-3}` `#bdbdca`, `{colors.link-mint}` `#99b3ad`): Muted footer / tertiary link colors used on dark surfaces to create a quiet hierarchy below the primary white type.
|
||||
|
||||
### Surface
|
||||
- **Canvas Night** (`{colors.canvas-night}` — `#000000`): Pure black hero, cinematic feature pages, footer.
|
||||
- **Canvas Night Elevated** (`{colors.canvas-night-elevated}` — `#0a0a0a`): Cards on cinematic surfaces, video frames.
|
||||
- **Surface Elevated Dark** (`{colors.surface-elevated-dark}` — `#1e2c31`): Dark teal-shifted surface used on a small subset of dark cards to introduce subtle depth without breaking the black.
|
||||
- **Canvas Light** (`{colors.canvas-light}` — `#ffffff`): Pricing, signup, comparison tables.
|
||||
- **Canvas Cream** (`{colors.canvas-cream}` — `#fbfbf5`): Slightly warm off-white used on the pricing-page background canvas — invisibly different from `#ffffff` but adds editorial warmth.
|
||||
- **Hairline Light** (`{colors.hairline-light}` — `#e4e4e7`): 1px borders on light cards, table dividers.
|
||||
- **Hairline Dark** (`{colors.hairline-dark}` — `#1e2c31`): 1px borders on the rare dark cards that have visible chrome.
|
||||
|
||||
### Shade Ladder
|
||||
- **Shade-30** (`{colors.shade-30}` — `#d4d4d8`): Tag / chip background on light, footer hairline on dark.
|
||||
- **Shade-40** (`{colors.shade-40}` — `#a1a1aa`): Tertiary text on light, secondary text on dark.
|
||||
- **Shade-50** (`{colors.shade-50}` — `#71717a`): Secondary text on light.
|
||||
- **Shade-60** (`{colors.shade-60}` — `#52525b`): Tertiary text on light, deep on dark.
|
||||
- **Shade-70** (`{colors.shade-70}` — `#3f3f46`): Pressed-state of the primary pill button; deep dark surface accent.
|
||||
|
||||
### Text
|
||||
- **Ink** (`{colors.ink}` — `#000000`): All text on light canvas.
|
||||
- **On Primary** (`{colors.on-primary}` — `#ffffff`): All text on dark canvas + filled-pill labels.
|
||||
|
||||
## Typography
|
||||
|
||||
### Font Family
|
||||
|
||||
The display tier is **Neue Haas Grotesk Display** at thin weights (330–500). When unavailable, fall back to **Helvetica** at light weight, then Arial. The thin-weight cut is the brand — no substitution should default to weight 400+.
|
||||
|
||||
The UI tier is **Inter Variable** at 420–550 — a variable font with sub-weight precision that lets the system span body (420), strong (550), and caption (500) without jumping to heavier tiers. Inter is open-source via Google Fonts.
|
||||
|
||||
The code tier is **ui-monospace**, the system mono — preferred over a webfont mono to avoid unnecessary downloads.
|
||||
|
||||
The OpenType `ss03` stylistic set is enabled across every role. It alters specific glyph forms (lowercase `a`, `g`, single-story numerals) for a slightly more geometric character. Apply via `font-feature-settings: "ss03"` on the body element or root.
|
||||
|
||||
### Hierarchy
|
||||
|
||||
| Token | Size | Weight | Line Height | Letter Spacing | Use |
|
||||
|---|---|---|---|---|---|
|
||||
| `{typography.display-xxl}` | 96px | 330 | 1.0 | 2.4px | Cinematic hero headline |
|
||||
| `{typography.display-xl}` | 70px | 330 | 1.0 | 0 | Section opener on cinematic pages |
|
||||
| `{typography.display-lg}` | 55px | 330 | 1.16 | 0 | Pricing-page page title |
|
||||
| `{typography.display-md}` | 48px | 330 | 1.14 | 0 | Sub-section headline on light track |
|
||||
| `{typography.heading-xl}` | 28px | 500 | 1.28 | 0.42px | Card title / pricing tier name |
|
||||
| `{typography.heading-lg}` | 24px | 400 | 1.14 | 0.36px | Compact card title |
|
||||
| `{typography.heading-md}` | 20px | 500 | 1.4 | 0.3px | Section sub-heading |
|
||||
| `{typography.heading-sm}` | 18px | 500 | 1.25 | 0.72px | Eyebrow / mini-section label |
|
||||
| `{typography.body-lg}` | 18px | 550 | 1.56 | 0 | Marketing body lead, large body |
|
||||
| `{typography.body-md}` | 16px | 420 | 1.5 | 0 | Default UI body, pill-button labels |
|
||||
| `{typography.body-strong}` | 16px | 550 | 1.5 | 0 | Emphasized body run |
|
||||
| `{typography.caption}` | 14px | 500 | 1.49 | 0.28px | Helper copy, footnotes |
|
||||
| `{typography.micro}` | 13px | 500 | 1.5 | -0.13px | Pricing fine print |
|
||||
| `{typography.eyebrow-cap}` | 12px | 400 | 1.2 | 0.72px | All-caps eyebrow above large headlines |
|
||||
| `{typography.code}` | 16px | 400 | 1.5 | 0 | Code blocks |
|
||||
|
||||
### Principles
|
||||
- **Display thinness is the brand.** Always render display sizes at weight 330 — never 400+. The thinness is a deliberate editorial choice that makes the giant size feel quiet.
|
||||
- **Display in NHGD, body in Inter.** Don't push body roles up to NHGD; don't push display roles down to Inter.
|
||||
- **Tracking lifts on display.** The 96px hero gets +2.4px positive tracking — the thin glyphs need air. At 70px and below, tracking returns to 0.
|
||||
|
||||
### Note on Font Substitutes
|
||||
Open substitutes for Neue Haas Grotesk Display: **Helvetica Now Display** (proprietary) or **Inter Display** at light weights (open-source) are the closest matches. Avoid Helvetica Neue at default weight — it's too heavy for the brand's thin tier. **Inter Variable** is open-source via Google Fonts and is the canonical body face — no substitute needed.
|
||||
|
||||
## Layout
|
||||
|
||||
### Spacing System
|
||||
- **Base unit**: 8px (with denser sub-units 1, 2, 3, 4 for fine work).
|
||||
- **Tokens**: `{spacing.xxs}` 2px · `{spacing.xs}` 4px · `{spacing.sm}` 8px · `{spacing.md}` 12px · `{spacing.lg}` 16px · `{spacing.xl}` 24px · `{spacing.xxl}` 32px · `{spacing.huge}` 64px.
|
||||
- **Section padding**: `{spacing.huge}` 64–128px on cinematic marketing pages (extreme negative space is the point); collapses to ~48px on transactional pages where density takes priority.
|
||||
- **Card internal padding**: `{spacing.xxl}` 32px on pricing cards; `{spacing.xl}` 24px on compact tag rows.
|
||||
|
||||
### Grid & Container
|
||||
- Cinematic hero pages use a wide max-width container (~1440–1600px) with edge-bleeding photography that escapes the container.
|
||||
- Pricing collapses through 4-up → 2-up → 1-up tiers based on viewport.
|
||||
- Body content centers in a ~720–840px reading column on long-form pages.
|
||||
|
||||
### Whitespace Philosophy
|
||||
The cinematic track treats whitespace as the brand's most valuable asset — sections often have 128–192px of vertical air between content blocks, with photography filling the rest. The transactional track tightens to ~48–64px between bands because users are scanning, comparing, and acting. The contrast between the two whitespace philosophies is part of the brand voice.
|
||||
|
||||
## Elevation & Depth
|
||||
|
||||
| Level | Treatment | Use |
|
||||
|---|---|---|
|
||||
| 0 | Flat, no shadow | Default surface |
|
||||
| 1 | `0 1px 2px rgba(255,255,255,0.05), inset 0 1px 0 rgba(255,255,255,0.04)` | Subtle inset highlight on dark cards (a top-edge sheen) |
|
||||
| 2 | `0 0 0 1px rgba(255,255,255,0.08), 0 1px 3px rgba(0,0,0,0.3), 0 5px 10px rgba(0,0,0,0.2)` | Dark elevated cards with hairline + drop shadow stack |
|
||||
| 3 | `0 8px 8px rgba(0,0,0,0.1), 0 4px 4px rgba(0,0,0,0.1), 0 2px 2px rgba(0,0,0,0.1), 0 0 0 1px rgba(0,0,0,0.1)` | Stacked-shadow card on light surfaces; layered tiny shadows produce a soft halo |
|
||||
| 4 | `0 25px 50px -12px rgba(0,0,0,0.25)` | Modal / floating panel on light |
|
||||
|
||||
### Decorative Depth
|
||||
On the cinematic track, depth comes from photography — full-bleed merchant imagery layered behind cards, with subtle inset top-edge highlights creating the illusion of light hitting a glass surface. On the light track, the layered tiny-shadow stack (Level 3) produces a soft, paper-like halo around pricing cards — depth without harshness.
|
||||
|
||||
## Shapes
|
||||
|
||||
### Border Radius Scale
|
||||
|
||||
| Token | Value | Use |
|
||||
|---|---|---|
|
||||
| `{rounded.xs}` | 4px | Inputs, hairline tags |
|
||||
| `{rounded.sm}` | 5px | Image containers (small) |
|
||||
| `{rounded.md}` | 8px | Form inputs, video frames, smaller cards |
|
||||
| `{rounded.lg}` | 12px | Pricing cards, feature cards |
|
||||
| `{rounded.xl}` | 20px (top-only on some asymmetric cards) | Hero photo frames, cinematic card chrome |
|
||||
| `{rounded.pill}` | 9999px | All buttons, pill tags, mint chips |
|
||||
|
||||
### Photography Geometry
|
||||
Photography is full-bleed with no border. On cinematic pages it escapes the container entirely; on transactional pages it sits inside `{rounded.lg}` containers with no shadow. Avatar treatments in customer-logo strips are simple greyscale wordmarks at uniform height (~24–32px), aligned in a single horizontal strip.
|
||||
|
||||
## Components
|
||||
|
||||
### Buttons
|
||||
|
||||
**`button-primary-pill`** — the dominant CTA across the system.
|
||||
- Background `{colors.primary}` (black), text `{colors.on-primary}`, type `{typography.body-md}`, padding `{spacing.md} {spacing.xl}` (12px 24px), rounded `{rounded.pill}` 9999px.
|
||||
- Pressed state `button-primary-pill-pressed`: background lifts to `{colors.shade-70}`.
|
||||
|
||||
**`button-outline-on-dark`** — the cinematic hero CTA.
|
||||
- Background `{colors.canvas-night}` (transparent on the canvas), 2px solid `{colors.on-primary}` border, text `{colors.on-primary}`, same pill geometry.
|
||||
|
||||
**`button-outline-on-light`** — the light-track equivalent.
|
||||
- Background `{colors.canvas-light}`, 1px solid `{colors.ink}` border, text `{colors.ink}`, same pill geometry.
|
||||
|
||||
**`button-aloe-pill`** — the featured CTA on pricing pages.
|
||||
- Background `{colors.aloe-10}`, text `{colors.ink}`, same pill geometry. Used for the "Start free trial" tier.
|
||||
|
||||
### Cards & Containers
|
||||
|
||||
**`card-pricing`** — the standard tier card on the pricing page.
|
||||
- Background `{colors.canvas-light}`, padding `{spacing.xxl}`, rounded `{rounded.lg}` 12px, 1px `{colors.hairline-light}` border. Title in `{typography.heading-xl}`, price in `{typography.display-md}`, body in `{typography.body-md}`, CTA pinned to the bottom as `button-primary-pill`.
|
||||
|
||||
**`card-pricing-featured`** — the highlighted pricing tier.
|
||||
- Background `{colors.aloe-10}`, otherwise identical to `card-pricing`. The mint fill (rather than a brand-color border) is the brand's distinctive featured-tier choice.
|
||||
|
||||
**`card-feature-cinematic`** — feature card on the cinematic track.
|
||||
- Background `{colors.canvas-night-elevated}`, text `{colors.on-primary}`, rounded `{rounded.lg}`, often with a top-edge inset highlight (Level 1 elevation). Holds full-bleed photography or a single large statement.
|
||||
|
||||
**`card-pistachio-band`** — wide horizontal band card used to highlight a category of features on the light track.
|
||||
- Background `{colors.pistachio-10}`, text `{colors.ink}`, rounded `{rounded.lg}` 12px, padding `{spacing.xxl}`.
|
||||
|
||||
**`card-photo-frame`** — full-bleed photography container on cinematic pages.
|
||||
- Background `{colors.canvas-night}`, padding 0, rounded `{rounded.xl}` 20px (often top-only). The photo IS the content; no inner padding, no overlay text inside the card.
|
||||
|
||||
### Inputs & Forms
|
||||
|
||||
**`text-input`** — standard text input on light surfaces.
|
||||
- Background `{colors.canvas-light}`, text `{colors.ink}`, type `{typography.body-md}`, padding `{spacing.sm}+ {spacing.md}` (10px 12px), rounded `{rounded.md}` 8px, 1px `{colors.hairline-light}` border.
|
||||
|
||||
### Navigation
|
||||
|
||||
**`nav-bar-light`** — top nav on light pages.
|
||||
- Background `{colors.canvas-light}`, text `{colors.ink}`, padding `{spacing.lg} {spacing.xl}`. Logo wordmark on the left, nav items center, two pill buttons on the right (`button-outline-on-light` for "Log in", `button-primary-pill` for "Start free trial").
|
||||
|
||||
**`nav-bar-dark`** — top nav on cinematic pages.
|
||||
- Background `{colors.canvas-night}`, text `{colors.on-primary}`, otherwise identical structure. Two pill buttons on the right (`button-outline-on-dark` for both, with the rightmost subtly more prominent via type weight).
|
||||
|
||||
### Pills, Tags, and Chips
|
||||
|
||||
**`pill-tag-mint`** — small tag on light surfaces, signaling a feature category.
|
||||
- Background `{colors.aloe-10}`, text `{colors.ink}`, type `{typography.eyebrow-cap}`, padding `{spacing.xs} {spacing.md}`, rounded `{rounded.pill}`.
|
||||
|
||||
**`pill-tag-shade`** — neutral tag on light surfaces.
|
||||
- Background `{colors.shade-30}`, text `{colors.ink}`, otherwise same shape as `pill-tag-mint`.
|
||||
|
||||
### Signature Components
|
||||
|
||||
**Cinematic Photography Layer** — full-bleed merchant photos on the hero. No overlay scrim, no text-on-image; instead, the type sits in clean negative space above or below the photo. The brand treats photography as an editorial spread, not as decoration.
|
||||
|
||||
**Stacked Tiny Shadows (Level 3 Elevation)** — pricing cards on the light track use 4 stacked tiny drop shadows (each 1–8px Y offset, 10% black) to produce a soft, layered paper halo. This is the brand's distinctive depth on light.
|
||||
|
||||
**`link-on-dark`** — inline link on cinematic pages.
|
||||
- Color `{colors.on-primary}`, no underline by default (links rely on context); for tertiary footer links, color shifts to one of the cool muted tones (`{colors.link-cool-1}` etc.) with a persistent underline.
|
||||
|
||||
**`footer-dark`** — full-page-width footer on the cinematic track.
|
||||
- Background `{colors.canvas-night}`, text `{colors.on-primary}`, type `{typography.caption}`, padding `{spacing.huge} {spacing.xl}`. Contains 4–5 columns of muted-tone link groups, social icons, and a small legal row.
|
||||
|
||||
**`footer-light`** — equivalent on the transactional track.
|
||||
- Background `{colors.canvas-light}`, text `{colors.ink}`, otherwise same structure.
|
||||
|
||||
## Do's and Don'ts
|
||||
|
||||
### Do
|
||||
- Reserve `{colors.aloe-10}` and `{colors.pistachio-10}` for the light track only — they don't appear on cinematic black pages.
|
||||
- Always use `{rounded.pill}` for buttons; never `{rounded.md}` or `{rounded.lg}`.
|
||||
- Render display tiers at weight 330; bumping to 400 or 500 breaks the brand's thin-display signature.
|
||||
- Use full-bleed photography on cinematic pages — let it escape the container.
|
||||
- Apply `font-feature-settings: "ss03"` globally; the stylistic set is the brand's typographic signature.
|
||||
- Pair black canvas with white type and white-stroked outline pills; pair light canvas with black type and filled-black pills.
|
||||
|
||||
### Don't
|
||||
- Don't introduce a third canvas color — stick to black or light/cream. Greys, beiges, and blues are not in the system.
|
||||
- Don't add drop shadows on cinematic dark cards beyond the subtle inset top-highlight; the cinematic track wants flat blackness.
|
||||
- Don't shrink display tiers below `{typography.display-md}` (48px) on hero surfaces; below that they read as section heads, not display.
|
||||
- Don't put aloe / pistachio greens behind type — they're surface fills, not text colors.
|
||||
- Don't replace the pill shape with a rounded-rectangle button anywhere.
|
||||
|
||||
## Responsive Behavior
|
||||
|
||||
### Breakpoints
|
||||
|
||||
| Name | Width | Key Changes |
|
||||
|---|---|---|
|
||||
| Wide | ≥ 1440px | Full cinematic hero with edge-bleeding photography; pricing 4-up |
|
||||
| Desktop | 1024–1440px | Default content max-width; pricing 4-up tightens |
|
||||
| Tablet | 768–1023px | Pricing 2-up; cinematic hero photography crops |
|
||||
| Mobile | < 768px | Pricing 1-up; hamburger nav; display-xxl drops to ~56–64px |
|
||||
|
||||
### Touch Targets
|
||||
- Pill buttons hit ≥ 44×44px on mobile via 12px vertical padding × 16px line-height. WCAG AAA compliant.
|
||||
- Form fields stay at the 44px minimum height across all breakpoints.
|
||||
|
||||
### Collapsing Strategy
|
||||
- Display sizes scale down through the breakpoint stair: 96 → 70 → 55 → 48 → 36px on mobile.
|
||||
- Cinematic photography crops aggressively at smaller widths, prioritizing focal subject over edge-bleed.
|
||||
- Pricing tiers stair-step 4-up → 2-up → 1-up; the featured aloe tier stays visually distinguished at every step.
|
||||
- Top nav collapses to hamburger below 768px; menu inherits canvas polarity.
|
||||
|
||||
### Image Behavior
|
||||
Photography uses responsive `srcset` with art-direction crops at major breakpoints. Mobile crops favor close subjects; wide crops favor environmental / storefront context.
|
||||
|
||||
## Iteration Guide
|
||||
|
||||
1. Focus on ONE component at a time.
|
||||
2. Reference component names and tokens directly (`{colors.aloe-10}`, `{button-primary-pill}-pressed`, `{rounded.pill}`).
|
||||
3. Run `npx @google/design.md lint DESIGN.md` after edits.
|
||||
4. Add new variants as separate entries.
|
||||
5. Default body to `{typography.body-md}`; reserve `{typography.body-lg}` for marketing leads.
|
||||
6. Keep the two canvas tracks separated — when designing a new page, choose cinematic OR transactional, not both.
|
||||
7. The pill shape is non-negotiable; new button variants vary in fill / border / canvas, never in shape.
|
||||
@@ -0,0 +1,5 @@
|
||||
# Shopify Inspired Design System
|
||||
|
||||
Design system details have been moved to: https://getdesign.md/shopify/design-md
|
||||
|
||||
You can also view previews, dark mode examples, and download options on getdesign.md.
|
||||
@@ -0,0 +1,342 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Shopify — reference components</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Reference fixture for design-systems/shopify. Every visible
|
||||
value comes from tokens.css. Shopify's signature moves: dark-first
|
||||
cinematic (void black canvas), NeueHaasGrotesk ultra-light display,
|
||||
full-pill CTAs, neon green (#36F4A4) focus rings only."
|
||||
/>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--bg: #000000;
|
||||
--surface: #02090a;
|
||||
--surface-warm: #061a1c;
|
||||
|
||||
--fg: #ffffff;
|
||||
--fg-2: #ffffff;
|
||||
--muted: #a1a1aa;
|
||||
--meta: #71717a;
|
||||
|
||||
--border: #1e2c31;
|
||||
--border-soft: #3f3f46;
|
||||
|
||||
--accent: #36f4a4;
|
||||
--accent-on: #000000;
|
||||
--accent-hover: #2de097;
|
||||
--accent-active: color-mix(in oklab, var(--accent), black 14%);
|
||||
|
||||
--success: #36f4a4;
|
||||
--warn: #eab308;
|
||||
--danger: #dc2626;
|
||||
|
||||
--font-display: "NeueHaasGrotesk", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
--font-body: "Inter Variable", "Inter", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
|
||||
--text-xs: 12px;
|
||||
--text-sm: 14px;
|
||||
--text-base: 18px;
|
||||
--text-lg: 20px;
|
||||
--text-xl: 32px;
|
||||
--text-2xl: 48px;
|
||||
--text-3xl: 70px;
|
||||
--text-4xl: 96px;
|
||||
|
||||
--leading-body: 1.56;
|
||||
--leading-tight: 1.00;
|
||||
--tracking-display: 0em;
|
||||
|
||||
--space-1: 4px;
|
||||
--space-2: 8px;
|
||||
--space-3: 12px;
|
||||
--space-4: 16px;
|
||||
--space-5: 24px;
|
||||
--space-6: 28px;
|
||||
--space-8: 36px;
|
||||
--space-12: 64px;
|
||||
|
||||
--section-y-desktop: 96px;
|
||||
--section-y-tablet: 64px;
|
||||
--section-y-phone: 40px;
|
||||
|
||||
--radius-sm: 9999px;
|
||||
--radius-md: 8px;
|
||||
--radius-lg: 12px;
|
||||
--radius-pill: 9999px;
|
||||
|
||||
--elev-flat: none;
|
||||
--elev-ring: 0 0 0 1px var(--border);
|
||||
--elev-raised:
|
||||
rgba(0, 0, 0, 0.1) 0px 0px 0px 1px,
|
||||
rgba(0, 0, 0, 0.1) 0px 2px 2px,
|
||||
rgba(0, 0, 0, 0.1) 0px 4px 4px,
|
||||
rgba(0, 0, 0, 0.1) 0px 8px 8px,
|
||||
rgba(255, 255, 255, 0.03) 0px 1px 0px inset;
|
||||
|
||||
--focus-ring: 0 0 0 2px #36f4a4;
|
||||
|
||||
--motion-fast: 150ms;
|
||||
--motion-base: 200ms;
|
||||
--ease-standard: ease;
|
||||
|
||||
--container-max: 1280px;
|
||||
--container-gutter-desktop: 64px;
|
||||
--container-gutter-tablet: 32px;
|
||||
--container-gutter-phone: 16px;
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
html, body { margin: 0; padding: 0; }
|
||||
body {
|
||||
background: var(--bg);
|
||||
color: var(--muted);
|
||||
font-family: var(--font-body);
|
||||
font-size: var(--text-base);
|
||||
line-height: var(--leading-body);
|
||||
/* ss03 on all text per brand spec. */
|
||||
font-feature-settings: "ss03";
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: var(--container-max);
|
||||
margin-inline: auto;
|
||||
padding-inline: var(--container-gutter-desktop);
|
||||
}
|
||||
section { padding-block: var(--section-y-desktop); }
|
||||
section + section { border-top: 1px solid var(--border); }
|
||||
@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);
|
||||
font-weight: 330; /* ultra-light — the Shopify signature */
|
||||
margin: 0;
|
||||
color: var(--fg);
|
||||
font-feature-settings: "ss03";
|
||||
line-height: var(--leading-tight);
|
||||
}
|
||||
h1 {
|
||||
font-size: var(--text-4xl);
|
||||
/* 96px display: weight 330, line-height 1.00. */
|
||||
}
|
||||
h2 {
|
||||
font-size: var(--text-3xl);
|
||||
/* 70px heading 1: line-height 1.00. */
|
||||
}
|
||||
h3 {
|
||||
font-size: var(--text-xl);
|
||||
/* 32px heading 4: line-height 1.14, tracking 0.32px (positive).
|
||||
Overrides the shared 1.00 set above. */
|
||||
line-height: 1.14;
|
||||
letter-spacing: 0.32px;
|
||||
font-weight: 360;
|
||||
}
|
||||
p { margin: 0; }
|
||||
.lead {
|
||||
font-size: var(--text-lg);
|
||||
line-height: 1.40;
|
||||
color: var(--muted);
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
.body-muted { color: var(--muted); }
|
||||
.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 — full pill for all CTAs. ──── */
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
padding: 12px 26px 12px 16px;
|
||||
border-radius: var(--radius-sm); /* 9999px full pill */
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--text-base);
|
||||
font-weight: 400;
|
||||
font-feature-settings: "ss03";
|
||||
line-height: 1.5;
|
||||
cursor: pointer;
|
||||
border: 2px solid transparent;
|
||||
transition: all var(--motion-base) var(--ease-standard);
|
||||
text-decoration: none;
|
||||
}
|
||||
.btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
|
||||
.btn-primary {
|
||||
background: var(--fg);
|
||||
color: var(--bg);
|
||||
border-color: transparent;
|
||||
}
|
||||
.btn-primary:hover { opacity: 0.9; }
|
||||
.btn-ghost {
|
||||
background: transparent;
|
||||
color: var(--fg);
|
||||
border-color: var(--fg);
|
||||
}
|
||||
.btn-ghost:hover { background: var(--fg); color: var(--bg); }
|
||||
|
||||
/* ─── Cards ──────────────────────────────── */
|
||||
.card {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-md);
|
||||
padding: var(--space-6);
|
||||
box-shadow: var(--elev-raised);
|
||||
transition: box-shadow var(--motion-base) var(--ease-standard);
|
||||
}
|
||||
|
||||
/* ─── Stats ──────────────────────────────── */
|
||||
.stat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-2);
|
||||
}
|
||||
.stat-number {
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--text-3xl);
|
||||
font-weight: 750;
|
||||
color: var(--fg);
|
||||
font-feature-settings: "ss03";
|
||||
line-height: 1.00;
|
||||
}
|
||||
|
||||
/* ─── Inputs ─────────────────────────────── */
|
||||
.field { display: flex; flex-direction: column; gap: var(--space-2); }
|
||||
.field label { font-size: var(--text-sm); font-weight: 500; color: var(--muted); }
|
||||
.field input {
|
||||
background: var(--surface-warm);
|
||||
color: var(--fg);
|
||||
border: 1px solid var(--border-soft);
|
||||
border-radius: var(--radius-md);
|
||||
padding: 12px 16px;
|
||||
font-family: var(--font-body);
|
||||
font-size: var(--text-base);
|
||||
outline: none;
|
||||
transition: border-color var(--motion-fast) var(--ease-standard),
|
||||
box-shadow var(--motion-fast) var(--ease-standard);
|
||||
}
|
||||
.field input::placeholder { color: var(--meta); }
|
||||
.field input:focus {
|
||||
border-color: var(--accent);
|
||||
box-shadow: var(--focus-ring);
|
||||
}
|
||||
|
||||
/* ─── Layout ─────────────────────────────── */
|
||||
.hero-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: var(--space-12);
|
||||
align-items: center;
|
||||
}
|
||||
@media (max-width: 1023px) { .hero-grid { grid-template-columns: 1fr; } }
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: var(--space-8);
|
||||
}
|
||||
@media (max-width: 639px) { .stats-grid { grid-template-columns: 1fr; } }
|
||||
.hero-actions { display: flex; gap: var(--space-4); margin-block-start: var(--space-8); flex-wrap: wrap; }
|
||||
.icon { width: 16px; height: 16px; flex-shrink: 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="container">
|
||||
<!-- HERO -->
|
||||
<section data-od-id="hero">
|
||||
<div class="hero-grid">
|
||||
<div class="stack-6">
|
||||
<h1>Commerce is yours to own.</h1>
|
||||
<p class="lead" style="max-width:46ch">
|
||||
Start, run, and grow your business. Shopify's cinematic dark canvas
|
||||
stages commerce like a product keynote. Ultra-light NeueHaasGrotesk
|
||||
at 96px. Every value from tokens.css.
|
||||
</p>
|
||||
<div class="hero-actions">
|
||||
<a href="./tokens.css" class="btn btn-primary">
|
||||
Start for free
|
||||
<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 btn-ghost">Read the spec</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside>
|
||||
<div class="card">
|
||||
<p style="font-size:var(--text-sm);color:var(--meta);margin-bottom:var(--space-4)">Commerce data</p>
|
||||
<div class="stats-grid" style="grid-template-columns:1fr 1fr">
|
||||
<div class="stat">
|
||||
<span class="stat-number">150M+</span>
|
||||
<span style="font-size:var(--text-sm);color:var(--muted)">buyers served</span>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<span class="stat-number">15+</span>
|
||||
<span style="font-size:var(--text-sm);color:var(--muted)">years in commerce</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- FEATURES -->
|
||||
<section data-od-id="features" style="background:var(--surface-warm);margin-inline:calc(var(--container-gutter-desktop)*-1);padding-inline:var(--container-gutter-desktop)">
|
||||
<h2 style="max-width:24ch;margin-bottom:var(--space-8)">Built for scale.</h2>
|
||||
|
||||
<div class="stats-grid">
|
||||
<div class="stat">
|
||||
<span style="font-family:var(--font-display);font-size:var(--text-3xl);font-weight:750;color:var(--fg);font-feature-settings:'ss03';line-height:1">96px</span>
|
||||
<span style="font-size:var(--text-sm);color:var(--muted);margin-top:var(--space-2)">Display XL, weight 330 — featherweight monumental type</span>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<span style="font-family:var(--font-display);font-size:var(--text-3xl);font-weight:750;color:var(--accent);font-feature-settings:'ss03';line-height:1">#36F4A4</span>
|
||||
<span style="font-size:var(--text-sm);color:var(--muted);margin-top:var(--space-2)">Neon Green — focus rings only, never fills large surfaces</span>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<span style="font-family:var(--font-display);font-size:var(--text-3xl);font-weight:750;color:var(--fg);font-feature-settings:'ss03';line-height:1">9999px</span>
|
||||
<span style="font-size:var(--text-sm);color:var(--muted);margin-top:var(--space-2)">Full pill for all primary CTAs — non-negotiable brand rule</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- FORM -->
|
||||
<section data-od-id="form">
|
||||
<div style="display:grid;grid-template-columns:1.2fr 1fr;gap:var(--space-12);align-items:start">
|
||||
<div class="stack-4">
|
||||
<h3>Start your free trial.</h3>
|
||||
<p style="font-size:var(--text-base);color:var(--muted);line-height:var(--leading-body);margin-top:var(--space-3)">
|
||||
Dark input surfaces. Border: 1px solid #3f3f46 at rest.
|
||||
Focus: 2px solid neon green. 8px radius on inputs.
|
||||
</p>
|
||||
</div>
|
||||
<form style="display:flex;flex-direction:column;gap:var(--space-4);max-width:400px"
|
||||
onsubmit="event.preventDefault()">
|
||||
<div class="field">
|
||||
<label for="email">Email address</label>
|
||||
<input id="email" type="email" placeholder="you@store.com" />
|
||||
</div>
|
||||
<div style="margin-top:var(--space-2)">
|
||||
<button type="submit" class="btn btn-primary">Start for free</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,141 @@
|
||||
/* ─────────────────────────────────────────────────────────────────────────
|
||||
* design-systems/shopify/tokens.css
|
||||
*
|
||||
* Structured token bindings for the "Shopify" brand — dark-first cinematic,
|
||||
* ethereal ultra-light display type, neon green accent.
|
||||
*
|
||||
* Brand identity in three sentences:
|
||||
* 1. Darkness as theatre — deep forest-teal surfaces (not pure black:
|
||||
* #000000 root, #02090A cards, #061A1C sections, #102620 elevated)
|
||||
* create a nocturnal keynote atmosphere, staged like a product reveal.
|
||||
* 2. NeueHaasGrotesk variable at monumental scale (96px) with impossible
|
||||
* lightness (weight 330–400, OpenType ss03); Inter Variable handles
|
||||
* body at unusual weights (420/450/550); combined they feel etched.
|
||||
* 3. Neon Green (#36F4A4) is the singular high-energy accent — pulsing
|
||||
* like a bioluminescent signal exclusively for focus rings and accent
|
||||
* highlights; white is the only text color on dark.
|
||||
*
|
||||
* Schema decisions:
|
||||
* - --bg: #000000 (void — root page background, true black).
|
||||
* - --surface: #02090A (deep teal — card surfaces).
|
||||
* - --surface-warm: #061A1C (dark forest — section backgrounds).
|
||||
* - --fg: #ffffff (white — the only text color on dark).
|
||||
* - --fg-2: #ffffff (same; no secondary ink split on dark canvas).
|
||||
* - --muted: #a1a1aa (muted zinc — secondary text, descriptions).
|
||||
* - --meta: #71717a (shade-50 — timestamps, tertiary info).
|
||||
* - --border: #1e2c31 (dark card border); --border-soft: #3f3f46.
|
||||
* - --accent: #36F4A4 (neon green — focus/accent only, not bg).
|
||||
* - --accent-on: #000000 (black text on neon green).
|
||||
* - --tracking-display: 0em (NeueHaasGrotesk at 96px tracks neutral).
|
||||
* - --leading-tight: 1.00 (display XL line-height at 96px).
|
||||
* - --radius-sm: 9999px (full pill for all CTAs per brand identity).
|
||||
* ─────────────────────────────────────────────────────────────────── */
|
||||
|
||||
:root {
|
||||
/* ─── Surface ──────────────────────────────────────────────────── */
|
||||
--bg: #000000; /* void — true black root */
|
||||
--surface: #02090a; /* deep teal — card surfaces */
|
||||
--surface-warm: #061a1c; /* dark forest — section backgrounds */
|
||||
|
||||
/* ─── Foreground ───────────────────────────────────────────────── */
|
||||
--fg: #ffffff; /* white — only text color on dark */
|
||||
--fg-2: #ffffff; /* same; no secondary ink split */
|
||||
--muted: #a1a1aa; /* muted zinc — secondary text */
|
||||
--meta: #71717a; /* shade-50 — timestamps, tertiary */
|
||||
|
||||
/* ─── Border ───────────────────────────────────────────────────── */
|
||||
--border: #1e2c31; /* dark card border */
|
||||
--border-soft: #3f3f46; /* shade-70 — subtle dividers */
|
||||
|
||||
/* ─── Accent ───────────────────────────────────────────────────── */
|
||||
/* Neon Green is precious — focus rings and critical accent highlights only.
|
||||
It never fills large surfaces. --accent-on is black for contrast. */
|
||||
--accent: #36f4a4; /* neon green */
|
||||
--accent-on: #000000;
|
||||
--accent-hover: #2de097; /* slightly darker neon on hover */
|
||||
--accent-active: color-mix(in oklab, var(--accent), black 14%);
|
||||
|
||||
/* ─── Semantic ─────────────────────────────────────────────────── */
|
||||
--success: #36f4a4; /* neon green — success state */
|
||||
--warn: #eab308;
|
||||
--danger: #dc2626;
|
||||
|
||||
/* ─── Typography ───────────────────────────────────────────────── */
|
||||
--font-display: "NeueHaasGrotesk", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
--font-body: "Inter Variable", "Inter", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
|
||||
/* Type scale — DESIGN.md §Typography Hierarchy.
|
||||
* NeueHaasGrotesk from 96px (display XL) to 24px (heading 6).
|
||||
* Inter Variable from 20px (body large) to 12px (label).
|
||||
* Schema spine maps the key stops. */
|
||||
--text-xs: 12px; /* label — uppercase, wide-tracked */
|
||||
--text-sm: 14px; /* caption — metadata */
|
||||
--text-base: 18px; /* body — standard Inter reading */
|
||||
--text-lg: 20px; /* body large — lead paragraphs */
|
||||
--text-xl: 32px; /* heading 4 — card headings */
|
||||
--text-2xl: 48px; /* heading 3 — feature titles */
|
||||
--text-3xl: 70px; /* heading 1 — section titles */
|
||||
--text-4xl: 96px; /* display XL — cinematic hero */
|
||||
|
||||
/* Leading + tracking.
|
||||
* --leading-tight=1.00: display XL at 96px.
|
||||
* h2 (70px) → 1.00; h3 (48px) → 1.14 per DESIGN.md.
|
||||
* --tracking-display: 0em (NeueHaasGrotesk tracks neutral at display).
|
||||
* NB: positive tracking (0.32px–2.4px) exists at smaller NeueHaas sizes
|
||||
* and is set inline in components.html. */
|
||||
--leading-body: 1.56;
|
||||
--leading-tight: 1.00;
|
||||
--tracking-display: 0em;
|
||||
|
||||
/* ─── Spacing ──────────────────────────────────────────────────── */
|
||||
/* 8px base unit per DESIGN.md §Spacing System. */
|
||||
--space-1: 4px;
|
||||
--space-2: 8px;
|
||||
--space-3: 12px;
|
||||
--space-4: 16px;
|
||||
--space-5: 24px;
|
||||
--space-6: 28px;
|
||||
--space-8: 36px;
|
||||
--space-12: 64px;
|
||||
|
||||
/* Section rhythm — theatrical pacing: vast dark expanse between sections. */
|
||||
--section-y-desktop: 96px;
|
||||
--section-y-tablet: 64px;
|
||||
--section-y-phone: 40px;
|
||||
|
||||
/* ─── Radius ───────────────────────────────────────────────────── */
|
||||
/* Full pill for all primary CTAs — non-negotiable brand identity.
|
||||
Cards: 8px standard, 12px featured. */
|
||||
--radius-sm: 9999px; /* full pill — all CTA buttons */
|
||||
--radius-md: 8px; /* standard cards, inputs */
|
||||
--radius-lg: 12px; /* featured cards */
|
||||
--radius-pill: 9999px;
|
||||
|
||||
/* ─── Elevation ────────────────────────────────────────────────── */
|
||||
/* Multi-layered shadow: 1px ring + progressive blur + inset white glow.
|
||||
Shadows are "ambient occlusion" on dark surfaces, not traditional lift. */
|
||||
--elev-flat: none;
|
||||
--elev-ring: 0 0 0 1px var(--border);
|
||||
--elev-raised:
|
||||
rgba(0, 0, 0, 0.1) 0px 0px 0px 1px,
|
||||
rgba(0, 0, 0, 0.1) 0px 2px 2px,
|
||||
rgba(0, 0, 0, 0.1) 0px 4px 4px,
|
||||
rgba(0, 0, 0, 0.1) 0px 8px 8px,
|
||||
rgba(255, 255, 255, 0.03) 0px 1px 0px inset;
|
||||
|
||||
/* ─── Focus ────────────────────────────────────────────────────── */
|
||||
/* Neon Green focus ring — 2px ring, brand signature. */
|
||||
--focus-ring: 0 0 0 2px #36f4a4;
|
||||
|
||||
/* ─── Motion ───────────────────────────────────────────────────── */
|
||||
--motion-fast: 150ms;
|
||||
--motion-base: 200ms;
|
||||
--ease-standard: ease;
|
||||
|
||||
/* ─── Layout ───────────────────────────────────────────────────── */
|
||||
--container-max: 1280px;
|
||||
--container-gutter-desktop: 64px;
|
||||
--container-gutter-tablet: 32px;
|
||||
--container-gutter-phone: 16px;
|
||||
}
|
||||
Reference in new issue
Block a user