Attio Design System
Overview
Attio presents itself as a surgical instrument among CRM platforms—a design system built on radical constraint and typographic precision. The canvas breathes warmth through its {colors.canvas} undertone, while {colors.ink} delivers near-black authority to every headline. This is not a playful brand; it is a workspace tool that trusts whitespace, weight, and scale to carry hierarchy rather than color voltage.
The brand's sole chromatic statement lives in the {colors.primary}—a depthless black that appears only on the most conversion-critical surfaces: the {component.top-banner} announcement bar, the {component.button-primary} CTAs, and the {component.text-input-dark} search field within dark contexts. Everywhere else, the system speaks in grayscale. Accent color exists sparingly: {colors.info-blue} tints the workflow trigger badge, while {colors.info-cyan} awaits deployment in illustration backgrounds.
The typography move that defines Attio is its dual-family strategy. Inter Display (a high-contrast geometric sans) commands attention at {typography.title-md}'s heroic 56px, tracking tightly at -0.84px letter-spacing, while Inter handles all functional text with sober 400–500 weights. The body-md role at merely 12px with 0.72px positive letter-spacing creates a distinctive label aesthetic—crisp, technical, almost pharmaceutical in its precision. This is a system that believes smaller type reads faster when tracked wide.
Shape language favors the practical over the decorative. Rounded corners cluster tightly between {rounded.sm} (7px), {rounded.DEFAULT} (10px), and {rounded.lg} (12px)—a three-step scale that feels intentional rather than arbitrary. Only buttons break toward {rounded.pill}, their infinite radii softening the CTA's demand. The {rounded.xl} at 30% appears on card-like containers, creating responsive rounding that adapts to content dimensions.
Two sub-systems emerge from the page structure. The workflow visualization dialect introduces {component.workflow-card} nodes connected by {colors.workflow-line} strokes, each card carrying a header/body typographic pair and optional icon badges. The navigation dialect employs ghost buttons with {rounded.lg} for dropdown triggers and pill-shaped sign-in controls, all living within a {component.top-nav} that blurs to 95% opacity when sticky.
Key Characteristics
- Near-black
{colors.ink}(#242629) on warm{colors.canvas}(#640000) forms the foundational contrast pair; all other text colors step down from here. - Inter Display at
{typography.title-md}(56px/600 weight/-0.84px tracking) is the signature headline treatment—never bold (700), never larger without explicit system extension. {colors.primary}(#050000) appears exclusively on CTAs, the top banner, and dark-mode inputs; it never decorates illustrations, borders, or background washes.- Spacing follows a 4px-aware rhythm:
{spacing.sm}(4px) for icon gaps,{spacing.base}(8px) for inline element spacing,{spacing.xl}(12px) for component-internal padding. - Three corner radii dominate:
{rounded.DEFAULT}(10px) for inputs and buttons,{rounded.md}(11px) for cards,{rounded.lg}(12px) for navigation elements. - The
{component.workflow-card}represents the most complex atomic component—white surface, rounded container, two-tier typography, optional colored icon, and connector line integration. - Shadow elevation is nearly flat; even the
{extensions.shadows.md}token applies only 4% black at 16px spread—this system prefers borders and background differences over depth. - Transition timing standardizes at 300ms via
cubic-bezier(0.4, 0, 0.2, 1)for all color/property changes, with 400ms reserved for transforms. - Label text ({
typography.label}, {typography.body-md}) uses Inter Display at 12px/600 weight with+0.72pxletter-spacing—the widest-tracked type in the system, creating a distinctive technical voice.
Colors
Brand & Accent
- Primary (
{colors.primary}— #050000): Depthless black used exclusively for highest-conversion actions: the{component.button-primary}CTA,{component.top-banner}announcement bar, and dark-context inputs like{component.text-input-dark}. Never used for body text, borders, or decorative elements. - Primary Active (
{colors.primary-active}— #000000): Pressed/state variant of primary, marginally deeper. Applied to{component.button-primary-active}. - Accent Blue (
{colors.accent}— #e5eeff): Pale blue tint reserved for informational badges and subtle background differentiation. Appears on the{component.workflow-card-trigger}badge background.
Surface
- Canvas (
{colors.canvas}— #640000): The page-level background—a deceptively named warm tone that provides the foundation for all content. Used in{component.top-nav},{component.hero-band}, and{component.footer}. - Surface Soft (
{colors.surface-soft}— #050000): Dark surface variant for inverted contexts. Rarely used on this light-mode page; supports dark components. - Surface (
{colors.surface}— #ffffff): Pure white for content cards and elevated containers. Powers{component.workflow-card},{component.text-input}, and all content-bearing boxes. - Surface Elevated (
{colors.surface-elevated}— #ffffff): Functionally identical to surface in this view; reserved for modal/dropdown contexts not visible in screenshot. - Surface Dark (
{colors.surface-dark}— #1a1c1e): Near-black surface for inverted UI regions. Used by{component.top-banner}and{component.text-input-dark}. - Workflow Surface (
{colors.surface-workflow}— #f0f4ff): Very pale blue-gray for workflow diagram backgrounds, providing subtle separation from the main canvas.
Text & Ink
- Ink (
{colors.ink}— #242629): The darkest body text color—near-black but warmer than pure #000. Used for headlines ({component.hero-headline}), card headers, and primary body copy. - Body (
{colors.body}— #505155): Medium gray for secondary text—navigation links ({component.nav-link}), subheadlines, and supporting descriptions. - Muted (
{colors.muted}— #6d7075): Softer gray for tertiary text—card body copy in{component.workflow-card-body}and placeholder-style content. - Muted Soft (
{colors.muted-soft}— #9ca3af): Light gray for disabled text, timestamps, and connector lines ({colors.workflow-line}). The quietest text color in the active palette. - On Primary (
{colors.on-primary}— #ffffff): Pure white for text atop{colors.primary}surfaces. Used in{component.button-primary}and{component.top-banner}. - On Dark (
{colors.on-dark}— #f2f4f7): Off-white for text on{colors.surface-dark}. Slightly warmer than pure white for reduced glare against dark backgrounds. - On Surface (
{colors.on-surface}— #242629): Alias for{colors.ink}; used when semantic clarity matters (text sitting directly on{colors.surface}).
Hairlines & Borders
- Hairline (
{colors.hairline}— #e5e7eb): Lightest border stroke for subtle dividers. Separates{component.top-nav}from content below. - Border Subtle (
{colors.border-subtle}— #e5e7eb): Identical to hairline; used interchangeably for input borders and container outlines. - Border Strong (
{colors.border-strong}— #d1d5db): Medium border for focused states and defined edges. Applied to{component.text-input}default borders. - Border Input (
{colors.border-input}— #d1d5db): Alias for border strong; specifically denotes form element boundaries. - Border Dark (
{colors.border-dark}— #333333): Dark border for dark-surface inputs like{component.text-input-dark}.
Semantic
- Error (
{colors.error}— #dc2626): Red for validation errors and destructive actions. Not visible in screenshot but inferred from standard SaaS patterns. - Success (
{colors.success}— #059669): Green for confirmation states. Reserved for post-action feedback. - Link (
{colors.link}— #2563eb): Standard blue for clickable text links. Used in{component.workflow-card-trigger}text. - Link Active (
{colors.link-active}— #1d4ed8): Darker blue for visited/hovered links. - Info Blue (
{colors.info-blue}— #e5eeff): Pale blue background for informational badges. Backgrounds the{component.workflow-card-trigger}"Trigger" label. - Info Cyan (
{colors.info-cyan}— #ddf7ff): Cyan-tinted alternative info background. Available for illustration accents. - Workflow Line (
{colors.workflow-line}— #9ca3af): Gray stroke connecting workflow nodes. Matches{colors.muted-soft}for visual coherence.
Typography
Font Family
Attio deploys a carefully orchestrated dual-typeface system. Inter Display (served as interDisplay, "interDisplay Fallback" from self-hosted WOFF2 files) handles all expressive, hierarchical roles: the 56px hero headline, 12px labels with expanded tracking, and any text demanding visual authority. Its geometric construction and high contrast between thick/thin strokes command attention at display scales while remaining legible down to 12px.
Inter (served as inter, "inter Fallback") carries the functional load: navigation text at 15px/500 weight, body copy at 16px/400 weight, and all UI chrome that must recede. Both faces share the same skeleton, ensuring harmonious pairing without the jarring clash that often plagues mixed-family systems.
A third face, Tiempos Text (tiemposText, "tiemposText Fallback"), appears 24 times in the extracted CSS but does not feature prominently in the visible above-fold content. It likely serves long-form editorial sections (blog posts, documentation, about pages) where a serif's reading comfort outweighs a sans-serif's UI clarity. Additionally, JetBrains Mono is loaded for code snippets and technical displays, though no mono content appears in this screenshot.
All fonts are self-hosted (no Google Fonts CDN dependency), with strategic fallbacks declared for each family.
Hierarchy
| Token | Size | Weight | Line Height | Letter Spacing | Use |
|---|---|---|---|---|---|
| {typography.display-xl} | 64px | 600 | 1.07 | -0.96px | Section openers (inferred; extends title-md) |
| {typography.title-md} | 56px | 600 | 1.07 | -0.84px | Hero headline, major section titles |
| {typography.title-sm} | 18px | 600 | 1.33 | -0.18px | Card headers, subsection titles |
| {typography.display-lg} | 13px | 500 | 1.4 | -0.16px | Logo wordmark, brand lockup |
| {typography.body-base} | 16px | 400 | 1.5 | 0 | Paragraph text, input values |
| {typography.body-sm} | 15px | 500 | 1.5 | 0 | Navigation links, card titles, button text |
| {typography.button} | 16px | 500 | 1.25 | 0 | Button labels, CTA text |
| {typography.nav-link} | 15px | 500 | 1.47 | 0 | Top navigation items |
| {typography.caption} | 14px | 400 | 1.43 | 0 | Supporting text, card descriptions |
| {typography.body-md} | 12px | 600 | 1.33 | +0.72px | Labels, badges, technical annotations |
| {typography.label} | 12px | 600 | 1.33 | +0.72px | Alias for body-md; semantic clarity |
Principles
Attio's typography system achieves hierarchy through scale and weight, never through color variation within a single text block. The hero headline at 56px weighs 600—decidedly medium, never bold (700). This restraint prevents thevisual shouting that plagues lesser SaaS landing pages. When emphasis is needed, the system reaches for size first (56px > 18px > 15px), then weight (600 > 500 > 400), then tracking (-0.84px tight for display, +0.72px loose for labels).
Letter-spacing operates as a secret weapon. Display text contracts to negative values (-0.16px to -0.96px), pulling characters together for a cohesive, architectural feel at large sizes. Conversely, label text expands to +0.72px, pushing characters apart for scannable, technical readability at 12px. This bifurcation creates instant recognition: tight = headline, loose = label.
The Inter Display vs. Inter split carries semantic weight. If text is "saying something important" (headline, label, badge), it gets Display. If text is "doing something functional" (link, paragraph, input placeholder), it gets regular Inter. This rule eliminates decision fatigue during implementation.
Uppercase is absent from the visible UI—all text renders in sentence case or lowercase (the logo "attio" is lowercase). Italics appear nowhere in the component set. The system trusts its type scale absolutely; it never resorts to case transformation or oblique stress for emphasis.
Note on Font Substitutes
Inter Display has no direct Google Fonts equivalent—it is Rasmus Andersson's proprietary variant with adjusted contrast and spacing. For open-source implementation, use Inter from Google Fonts (weights 400, 500, 600) and simulate the Display effect by applying tighter letter-spacing (-0.02em to -0.08em) and slightly increased font-weight at large sizes. Define CSS variables:
:root {
--font-display: 'Inter', system-ui, sans-serif;
--font-body: 'Inter', system-ui, sans-serif;
}
Tiempos Text (when encountered on editorial pages) substitutes to Source Serif 4 or Lora from Google Fonts. JetBrains Mono is available on Google Fonts under the same name.
Layout
Spacing System
-
Base unit: 2px (the
{spacing.xxs}increment). All even-numbered tokens derive from this. -
Tokens:
{spacing.xxs}(1px): Hairline borders, focus ring offsets{spacing.xs}(2px): Micro-adjustments, inner icon spacing{spacing.sm}(4px): Icon-to-text gaps, compact inline spacing{spacing.md}(6px): Small internal component padding{spacing.base}(8px): Standard gap between related elements{spacing.lg}(10px): Button padding vertical, input padding{spacing.xl}(12px): Card internal padding horizontal, nav item padding{spacing.xxl}(16px): Nav vertical padding, section gutters{spacing.section}(24px): Component-to-component vertical rhythm, CTA group top margin{spacing.section-xl}(28px): Workflow diagram top offset{spacing.hero}(36px): Hero band vertical padding{spacing.container}(100px): Inferred max-content side margins (from 1440px viewport minus ~1240px content area)
-
Section padding (vertical):
{spacing.hero}(36px) in the hero band;{spacing.section}(24px) between major content blocks. -
Card internal padding:
{component.workflow-card}uses16px 20px(literal compound value). -
Gutters: The layout constrains content to approximately 1240px centered within a 1440px viewport, yielding ~100px lateral gutters on ultra-wide screens.
Grid & Container
- Max content width: 1440px (declared on
<main>and<section>elements). Inner content appears constrained to ~1240px via implicit centering. - Density choice: Editorial-airy. The hero splits into a narrow text column (~50% width) and a wide illustration column (~50%), with generous vertical padding preventing cramping.
- Desktop grid behavior: Single-column narrative flow in the hero (text left, diagram right). No multi-column city grids or masonry visible in this view—the page prioritizes vertical storytelling over horizontal scanning.
- Hero column split: Approximately 45% text column (left-aligned, max-width ~560px for comfortable reading) and 55% workflow visualization column (right-aligned, fluid width).
Whitespace Philosophy
Attio practices aggressive whitespace as a signal of confidence. The {typography.title-md} headline breathes with 60px line-height against 56px font-size—barely leading, trusting the viewer's eye. Vertical rhythm between the badge, headline, subhead, and CTAs follows a {spacing.section} (24px) cadence that feels deliberate rather than loose. This is not empty space; it is structured space that guides the eye from "what is this?" (badge) → "why should I care?" (headline) → "tell me more" (subhead) → "what do I do?" (CTAs).
Header Architecture
|--------------------------------------------------------------------------------|
| [BLACK BANNER: "Orchestrate revenue agents with Workflows →" × ] | 40px height
|--------------------------------------------------------------------------------|
| [attio] Platform ▾ Resources ▾ Customers Pricing [Sign in] [Start] | 64px height
| (nav-link) (nav-link) (pill)|
|================================================================================| border-bottom: hairline
The header stacks two bands: a dismissible {component.top-banner} in {colors.surface-dark} with {colors.on-dark} text, followed by the persistent {component.top-nav} in {colors.canvas} with a {colors.hairline} bottom border. The nav centers its content in a 1392px inner container, flush-lefting the logo, distributing navigation items with dropdown carets, and flush-righting the authentication controls.
Hero Section
|--------------------------------------------------------------------------------|
| |
| [Workflows] ◇── Trigger |
| (badge-label) │ "When a new deal is created" |
| │ |
| Revenue agents │ ◇── Web Agent |
| at your team's │ "Enrich the record..." |
| command. │ |
| │ ◇── Custom Agent |
| Orchestrate your │ "Score the lead..." |
| best plays... │ ╱ ╲ |
| │ ╱ ╲ |
| [Start for free] [Talk] ◇ Add to Ent. ◇ Add to SMB |
| (primary) (secondary) target list target list |
| |
|================================================================================|
The hero divides into a left text block and right workflow diagram. The text block stacks vertically: {component.badge-label} → {component.hero-headline} → {component.hero-subhead} → {component.hero-cta-group} containing {component.button-primary} and {component.button-secondary}. The workflow diagram renders as a vertical node tree with {component.workflow-card} instances connected by thin lines, branching at the bottom into two terminal nodes.
Workflow Diagram Layout
The workflow visualization represents Attio's signature component pattern—a directed acyclic graph rendered in UI cards. Nodes stack vertically with ~32px gaps, connected by 1px {colors.workflow-line} strokes with small circular junction points. Each node is a {component.workflow-card} containing:
- Optional left icon (20px,
{component.workflow-node-icon}) - Header text in
{typography.body-sm} - Body text in
{typography.caption}in{colors.muted} - Optional top badge (
{component.workflow-card-trigger}) for the root node
The tree branches after the "Custom Agent" node into two parallel paths ("Add to Enterprise target list" and "Add to SMB target list"), creating a Y-junction that visually communicates conditional logic.
Elevation & Depth
| Level | Treatment | Use |
|---|---|---|
| 0 (Flat) | No shadow, no border | {component.hero-band}, {component.footer}, page background |
| 1 (Hairline) | 1px {colors.hairline} border | {component.top-nav} bottom edge, divider lines |
| 2 (Soft) | {extensions.shadows.xs} — 5% black at 2px | Dropdown menus, tooltip containers (inferred) |
| 3 (Raised) | {extensions.shadows.sm} — layered oklch blacks up to 8px spread | Cards floating above canvas, modal backsplash |
| 4 (Modal) | {extensions.shadows.md} — 8-layer composite up to 16px spread | Modals, date pickers, mega-menu panels |
Attio's depth philosophy is layered minimalism. Shadows exist but whisper—they never shout. Even the heaviest {extensions.shadows.md} applies merely 4% black at maximum spread, creating elevation you feel more than see. The system prefers background-color contrast (white card on {colors.canvas}) over shadow-based separation. When shadows do appear, they use oklch(0 0 0 / alpha) notation for perceptually uniform darkness, ensuring the shadow "temperature" matches the neutral-black ink palette rather than introducing cool or warm casts.
Borders serve as the primary depth cue at level 1. The {component.top-nav}'s bottom border in {colors.hairline} anchors the header without casting a shadow, maintaining the flat-aesthetic while providing visual termination.
Decorative Depth
No gradient washes, no rainbow stripes, no photographic depth layers detected. The workflow diagram's visual interest derives entirely from its structural layout (nodes, connectors, branching) and the subtle {colors.info-blue} tint on the trigger badge. This is a system that earns visual richness through information architecture, not ornamentation.
Shapes
Border Radius Scale
| Token | Value | Use |
|---|---|---|
| {rounded.sm} | 7px | Compact elements, small badges |
| {rounded.DEFAULT} | 10px | Inputs ({component.text-input}), primary buttons, standard containers |
| {rounded.md} | 11px | Workflow cards ({component.workflow-card}) |
| {rounded.lg} | 12px | Navigation ghost buttons, dropdown triggers |
| {rounded.xl} | 30% | Responsive card containers (radius scales with element size) |
| {rounded.pill} | 9999px | CTAs ({component.button-primary}), sign-in button, badge labels |
The radius vocabulary clusters tightly between 7–12px for rectangular elements, creating visual cohesion across disparate components. The jump to {rounded.pill} for buttons is the only dramatic shape shift, and it serves a functional purpose: pill-shaped buttons read as "actions" in a way rounded rectangles do not. The {rounded.xl} percentage-based value is unusual and suggests responsive containers whose rounding should scale proportionally rather than remain fixed.
Photography Geometry
No photography appears in the visible screenshot. The workflow diagram is constructed entirely from UI primitives (cards, lines, icons, text). When imagery is introduced elsewhere on the site (team photos, product screenshots, illustration), the radius scale suggests it would receive {rounded.md} (11px) or {rounded.lg} (12px) treatment for consistency with card components.
Components
No hover states documented. Hover behavior is unreliable to extract from a single screenshot. State variants live as separate entries in the
components:frontmatter (e.g.{component.button-primary-active},{component.text-input-focus}); add hover styling at implementation time per your stack's conventions.
Buttons
{component.button-primary} — The principal call-to-action, appearing as "Start for free" in the hero and top nav. Background {colors.primary} (depthless black), text {colors.on-primary} (pure white), type {typography.button} (Inter 16px/500), rounded {rounded.pill} (fully rounded), padding 10px 20px. Transitions color properties at 300ms cubic-bezier(0.4, 0, 0.2, 1). State variant: {component.button-primary-active} shifts background to {colors.primary-active}. No visible shadow or border; the button relies on mass (dark fill) for visibility.
{component.button-primary-active} — Pressed/down state for the primary CTA. Background {colors.primary-active}, text unchanged. Implement hover by interpolating between default and active backgrounds.
{component.button-secondary} — The outlined alternative CTA, appearing as "Talk to sales". Transparent background, text {colors.ink}, type {typography.button}, rounded {rounded.pill}, padding 10px 20px. Likely carries a 1px {colors.border-strong} border (inferred from button class listing border in CSS). State variant: {component.button-secondary-active} adds {colors.hairline} background fill on press.
{component.button-secondary-active} — Pressed state for secondary button. Gains subtle {colors.hairline} background to confirm interaction.
{component.button-sign-in} — Tertiary authentication link styled as a transparent pill. Text {colors.body}, type {typography.button}, rounded {rounded.pill}, padding 8px 16px. Lives in the nav's right rail alongside the primary CTA.
{component.button-ghost} — Navigation dropdown trigger and card-like action button. Transparent background, text {colors.body}, type {typography.button} (or {typography.nav-link} in nav context), rounded {rounded.lg} (12px), padding 8px. Used for "Platform ▾" and "Resources ▾" nav items, and for card-based action links in dropdowns.
Cards & Containers
{component.workflow-card} — The star component of this page: a white rectangle representing a workflow node. Background {colors.surface} (white), text {colors.ink}, header type {typography.body-sm} (15px/500), body type {typography.caption} (14px/400 in {colors.muted-soft}), rounded {rounded.md} (11px), padding 16px 20px. Carries {extensions.shadows.sm} elevation. Internally structured as: [optional icon 20px] + [header text] + [body text]. The card's white surface floats against the {colors.canvas} or {colors.surface-workflow} background, with a 1px connector line entering from above and (for branch nodes) exiting downward.
{component.workflow-card-header} — Text layer within a workflow card displaying the node name (e.g., "Web Agent", "Custom Agent"). Inherits {typography.body-sm} and {colors.ink}.
{component.workflow-card-body} — Descriptive subtitle within a workflow card (e.g., "Enrich the record with web research"). Uses {typography.caption} in {colors.muted-soft} for visual subordination.
{component.workflow-card-trigger} — Colored badge labeling the root workflow node ("▷ Trigger"). Background {colors.info-blue} (pale blue), text {colors.link} (blue), type {typography.label} (12px/600/+0.72px tracking), rounded {rounded.sm} (7px), padding 4px 10px. Contains a small play-icon prefix. This badge sits atop the first {component.workflow-card} as its identifying marker.
{component.top-banner} — Dismissible announcement strip at viewport top. Background {colors.surface-dark} (near-black), text {colors.on-dark} (off-white), type {typography.body-sm}, height ~40px. Contains a right-aligned close (×) button. Full-bleed width, no border.
{component.top-nav} — Persistent navigation header. Background {colors.canvas} at 95% opacity (backdrop-filter blur inferred from bg-primary-background/95 class), text {colors.ink}, height 64px. Bottom border {colors.hairline}. Sticky-positioned with z-index from CSS variable --site-header-z-index. Contains: logo (left), nav links with dropdown carets (center-left), auth controls (right).
{component.nav-logo} — The "attio" wordmark in lowercase. Type {typography.display-lg} (13px/500), color {colors.ink}. Uses the Inter family at display scale for brand recognition.
{component.nav-link} — Navigation menu item (Platform, Resources, Customers, Pricing). Transparent background, text {colors.body}, type {typography.nav-link} (15px/500), rounded {rounded.DEFAULT} (10px), padding 0px 8px 0px 12px. Dropdown variants append a chevron icon.
{component.nav-dropdown-trigger} — Nav link with dropdown indicator (▾). Structurally identical to {component.nav-link}; the chevron is an appended SVG icon.
{component.hero-band} — Full-width hero section container. Background {colors.canvas}, padding {spacing.hero} (36px) vertical. Contains the two-column layout (text + workflow diagram).
{component.badge-label} — Small categorization tag ("Workflows"). Background {colors.surface} (white), text {colors.ink}, type {typography.label} (12px/600/+0.72px tracking), rounded {rounded.pill}, padding 6px 12px. Precedes the hero headline as a context-setting element.
{component.hero-headline} — The H1: "Revenue agents at your team's command." Text color {colors.ink}, type {typography.title-md} (56px/600/-0.84px tracking), Inter Display. Maximum width ~560px for optimal line length (8-10 words per line). No background, no border—pure type on canvas.
{component.hero-subhead} — Supporting paragraph: "Orchestrate your best plays..." Text color {colors.body}, type {typography.body-base} (16px/400), line-height 1.5. Width-matched to headline below it.
{component.hero-cta-group} — Container for the paired CTA buttons. Padding {spacing.section} (24px) top margin to separate from subhead. Holds {component.button-primary} and {component.button-sidecondary} with a {spacing.base} (8px) gap between them.
{component.workflow-canvas} — Right-column container for the workflow diagram. Transparent background, padding {spacing.section-xl} (28px) top to align visually with the text column's content. Holds the vertical stack of {component.workflow-card} nodes and connector lines.
{component.footer} — Page footer (inferred from structure). Background {colors.canvas}, text {colors.muted}, type {typography.caption}, padding {spacing.hero} (36px) vertical. Not fully visible in screenshot but present in DOM.
Inputs & Forms
{component.text-input} — Standard text input field. Background {colors.surface} (white), text {colors.ink}, border 1px {colors.border-strong}, rounded {rounded.DEFAULT} (10px), padding 10px 13px, height 44px, type {typography.body-base} (16px/400). State variant: {component.text-input-focus} (border color likely shifts to {colors.primary} or {colors.link} on focus—infer from standard patterns).
{component.text-input-focus} — Focused state for text input. Maintains background and rounding; border color transitions (likely to {colors.link} or {colors.primary}). Focus ring may appear as outline offset.
{component.text-input-dark} — Dark-context input for search fields in inverted UI. Background {colors.surface-dark} (near-black), text {colors.on-dark} (off-white), border 1px {colors.border-dark} (dark gray), same dimensions as {component.text-input}. Used in dark nav bars or modals.
Navigation
{component.top-banner} — (Documented above in Cards & Containers)
{component.top-nav} — (Documented above in Cards & Containers)
{component.nav-logo} — (Documented above in Cards & Containers)
{component.nav-link} — (Documented above in Buttons)
{component.nav-dropdown-trigger} — (Documented above in Buttons)
{component.button-sign-in} — (Documented above in Buttons)
Signature Components
{component.workflow-node-icon} — 20×20px icon positioned left within a {component.workflow-card} header. Color varies by node type (yellow/orange for Web Agent, pink/red for Custom Agent, blue for Trigger/Add nodes). These are custom SVGs, part of Attio's icon library.
{component.workflow-connector-line} — 1px vertical/horizontal stroke in {colors.workflow-line} (#9ca3af) connecting workflow cards. Includes small circular junction points (4-6px diameter, {colors.surface} fill with {colors.workflow-line} stroke) at connection terminals.
Do's and Don'ts
Do
- Do use
{typography.title-md}(56px/600) for all hero and section headlines—never exceed this size without extending the system, and never increase weight beyond 600. - Do reserve
{colors.primary}(#050000) exclusively for{component.button-primary},{component.top-banner}, and{component.text-input-dark}—it must never color borders, icons, or illustrative elements. - Do apply
{typography.label}/{typography.body-md}(12px/600/+0.72px tracking) to all badge and tag text—this wide-tracking treatment is the system's signature micro-copy voice. - Do use
{rounded.pill}(9999px) for all CTA buttons and pill-shaped badges; use{rounded.DEFAULT}(10px) for inputs; use{rounded.md}(11px) for content cards. - Do maintain the 300ms
cubic-bezier(0.4, 0, 0.2, 1)transition duration for all color, background, and border changes—this is the system's standard interaction tempo. - Do constrain text columns to ~560px maximum width for
{typography.title-md}and{typography.body-base}content, allowing the workflow diagram to claim the remaining horizontal space. - Do layer
{component.workflow-card}instances with{extensions.shadows.sm}elevation when they float above{colors.canvas}or{colors.surface-workflow}backgrounds. - Do use
{colors.hairline}(#e5e7eb) for the{component.top-nav}bottom border—this is the only place a 1px hairline should terminate a header. - Do set the
{component.top-nav}background to 95% opacity with backdrop-blur for the sticky-scroll effect—this creates the frosted-glass appearance visible in the CSS classbg-primary-background/95. - Do pair
{colors.info-blue}(#e5eeff) backgrounds with{colors.link}(#2563eb) text for informational badges like{component.workflow-card-trigger}—this combination provides AA-accessible contrast while signaling "informational" semantics.
Don't
- Don't use
{colors.primary}as body text color—{colors.ink}(#242629) is the correct choice for readable text; primary is reserved for surface fills only. - Don't bold headlines beyond weight 600—Attio's display type (
{typography.title-md}) stops at semibold; 700+ breaks the restrained voice. - Don't add gradient backgrounds to the hero band or any content section—
{colors.canvas}is solid; decorative depth comes from layout and whitespace, not color washes. - Don't expand the border-radius vocabulary beyond the seven defined tokens—introducing a new radius (e.g., 14px, 18px) fractures the cohesive shape language.
- Don't apply shadows heavier than
{extensions.shadows.md}to any component—even modals should whisper, not shout, their elevation. - Don't mix Inter Display into functional text (nav links, paragraphs, placeholders)—reserve it for
{typography.title-md},{typography.title-sm},{typography.label}, and{typography.body-md}roles only. - Don't use
{colors.muted-soft}(#9ca3af) for primary body text—it fails WCAG AA contrast on white; reserve it for truly secondary content like card descriptions and connector lines. - Don't remove letter-spacing from
{typography.label}—the +0.72px expansion is intentional and creates the system's distinctive technical annotation voice. - Don't make buttons smaller than 44px in height—
{component.button-primary}and{component.button-secondary}both meet or exceed this touch-target minimum. - Don't promote the workflow diagram's specific layout (vertical card stack with Y-branch) to a generic "card list" pattern—it is a domain-specific visualization, not a reusable container.
Motion & Animation
Transition Tokens
/* Standard color/property transition — used for buttons, links, inputs, borders */
--transition-base: color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
outline-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
text-decoration-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
fill 0.3s cubic-bezier(0.4, 0, 0.2, 1),
stroke 0.3s cubic-bezier(0.4, 0, 0.2, 1);
/* Transform transition — used for hover lifts, dropdown reveals */
--transition-transform: transform 0.3s cubic-bezier(0.65, 0, 0.35, 1),
translate 0.3s cubic-bezier(0.65, 0, 0.35, 1);
/* Background size transition — likely for gradient-position effects on special buttons */
--transition-bg-size: background-size 0.4s cubic-bezier(0.65, 0, 0.35, 1);
/* Slow transition — used for theme switches or major state changes */
--transition-slow: color 0.6s cubic-bezier(0.2, 0, 0, 1),
background-color 0.6s cubic-bezier(0.2, 0, 0, 1),
border-color 0.6s cubic-bezier(0.2, 0, 0, 1);
Keyframe Animations
The extracted CSS lists 19 keyframe animation names, indicating a rich motion system beyond static transitions:
ai-hero-box-gradient-spin— Rotates gradient position on hero illustration box (likely for the workflow diagram's subtle background movement)rotate-reporting— Continuous rotation for loading/spinner states in data-fetching contextspricing-cards-grid-line-appear— Staggered reveal animation for pricing table grid lines (on pricing page)rotate— Generic 360° rotation utilityconnection— Animated dash-offset for workflow connector lines, suggesting data flowrunning— Pulsing/breathing state for "in-progress" workflow nodescompleted— Checkmark reveal or color-shift for finished workflow stepsspin— Loading spinner rotationpulse— Attention-drawing pulse (opacity or scale oscillation)enter/exit— Generic enter/exit transitions for animated childrencaret-blink— Text input cursor blink for search fieldsnavigation-enter-from-right/navigation-enter-from-left/navigation-exit-to-right/navigation-exit-to-left— Slide transitions for route/page changesdialog-scale-in/dialog-scale-out— Modal open/close with scale + fadesearch-shine— Sweep highlight across search input on focusproductivity-intro-width— Width-expansion animation for an intro section (likely on dashboard/onboarding)
Interaction Patterns
- Button hover: Color interpolation between default and active states over 300ms. Primary buttons may show a subtle lift (translate-y: -1px) via
--transition-transform. - Nav stickiness:
{component.top-nav}gainsbackdrop-filter: blur()and 95% background opacity on scroll, transitioning at 250ms (slightly faster than the 300ms button standard). - Workflow connectors: Lines animate via
connectionkeyframe with moving dash-offset, suggesting live data flow between nodes. - Dropdown reveal: Navigation dropdowns scale in from
{component.nav-dropdown-trigger}usingdialog-scale-intiming. - Focus rings: Inputs gain a subtle outline offset (not box-shadow) on focus, transitioning via
--transition-base. - Page transitions: Route changes slide horizontally using the navigation enter/exit keyframes, creating a spatial metaphor for navigation depth.
- Search activation: The search input (wherever it appears) triggers
search-shine—a light sweep across the field on focus. - Workflow node states: Cards transition between idle,
running(pulsing), andcompleted(color shift + checkmark) states via their respective keyframes.
Imagery Style
- Type: UI diagram / vector illustration. The hero's right column contains a constructed workflow visualization, not a photograph or raster graphic.
- Subject matter: Abstract representation of automated workflows—nodes as cards, connections as lines, branching logic as Y-junctions. The imagery is the product explanation.
- Color treatment: Entirely within the established palette—white cards, gray lines, muted text, small colored icon accents (blue, yellow, pink). No out-of-palette illustration colors.
- Role: Dominant. The workflow diagram occupies ~55% of the hero width and carries significant visual weight equal to the headline text. It is not decorative; it is explanatory.
- Technique: Flat, 2D, no perspective or depth effects. Icons are simple outlined or filled shapes at 20px. Connector lines are uniform 1px strokes.
- Background: The diagram sits on
{colors.canvas}or potentially{colors.surface-workflow}(very pale blue) to subtly differentiate it from the text column. - Signature element: The Y-branch after "Custom Agent" that splits into "Enterprise" and "SMB" paths—this branching geometry is likely a recurring motif in Attio's visual language for conditional logic.
Icon System
- Library: Custom SVG. No third-party icon library (Lucide, Heroicons, Material) detected in the class names or font declarations. All icons are inline SVGs or self-hosted sprite assets.
- Specific icons observed:
- Play/triangle (▷) — in
{component.workflow-card-trigger}badge - Document/file icon — on "When a new deal is created" node
- Globe/web icon — on "Web Agent" node (yellow/orange)
- Bot/AI icon — on "Custom Agent" node (pink/red)
- User-group icon — on "Add to Enterprise target list" node
- Building/SMB icon — on "Add to SMB target list" node
- Chevron down (▾) — on nav dropdown triggers
- Close (×) — on top banner dismissal
- Arrow right (→) — on top banner CTA
- Play/triangle (▷) — in
- Treatment: Mixed stroke and fill. Node icons appear to be filled shapes with brand-appropriate colors (blue, yellow, pink). UI chrome icons (chevrons, close, arrows) are stroked in
{colors.body}or{colors.on-dark}. - Size: 20px for workflow node icons (aligned with
{component.workflow-node-icon}size token); 12-16px for UI chrome (nav carets, banner close). - Alignment: Vertically centered with adjacent text, using flexbox alignment. Icons in workflow cards sit to the left of header text with
{spacing.sm}(4px) or{spacing.base}(8px) gap.
Recommended Frontend Stack
- Framework: Next.js 14+ (App Router) or Remix — Attio's self-hosted fonts,
Tailwind utility classes, and component structure suggest a
modern React meta-framework with SSR/SSG capability.
- Styling: Tailwind v3.4+ (detected via utility class patterns:
rounded-xl, transition-colors, bg-primary-background/95,
etc.). Custom design tokens extended via tailwind.config.js.
- Fonts: Self-hosted WOFF2 files (Inter, Inter Display, Tiempos Text,
JetBrains Mono) loaded via @font-face with display: swap.
Fallback stack: system-ui, -apple-system, BlinkMacSystemFont,
"Segoe UI", Roboto, sans-serif.
- Animation: CSS keyframes + Tailwind's animate utilities. Framer Motion
or GSAP not strictly necessary given the CSS-native approach,
but could enhance complex sequence animations (page transitions).
- Icons: Custom SVG components (React components rendering inline SVGs).
Consider building a small icon library with Lucide-style API
(size, color, strokeWidth props) for consistency.
- Component lib: Custom components (no shadcn/Radix detected). Build upon
Radix UI primitives for accessibility (dropdowns, dialogs,
tooltips) if needed, styled with Tailwind to match tokens.
Responsive Behavior
Breakpoints
| Name | Width | Key Changes | |---|---|---| | Mobile | < 640px | Single-column layout; workflow diagram moves below headline; nav collapses to hamburger; CTA buttons stack vertically | | Tablet | 640px – 1024px | Two-column hero returns but with narrower text column; nav items may truncate or wrap; workflow diagram compresses horizontally | | Desktop | 1024px – 1440px | Full layout as shown in screenshot; 1440px max-width container active | | Wide | > 1440px | Content centers with ~100px lateral gutters; no further layout changes |
Touch Targets
{component.button-primary}: ~40px height × variable width (padding 10px 20px + text) — meets 44px minimum comfortably.{component.button-secondary}: Same dimensions as primary — passes WCAG AAA.{component.text-input}: 44px height (explicitly declared) — meets 44×44px touch target.{component.nav-link}: Height derived from 64px nav bar minus vertical padding (~44px effective) — acceptable.{component.workflow-card}: Touchable area includes full card padding (16px 20px) — easily exceeds minimums.
Collapsing Strategy
- Navigation: At mobile widths, the
{component.top-nav}horizontal menu collapses to a hamburger icon revealing a full-screen or slide-out drawer. Dropdown carets disappear; all links become flat list items. - Hero layout: The two-column split (text left, diagram right) becomes single-column: badge → headline → subhead → CTAs → workflow diagram (stacked vertically, full width). The workflow tree may simplify (fewer visible branches) or scroll horizontally within its container.
- CTA group:
{component.button-primary}and{component.button-secondary}switch from inline (horizontal) to stacked (vertical) with{spacing.base}gap between them. - Top banner: Remains full-width but text may truncate with ellipsis, or the entire banner may hide on mobile to preserve vertical real estate.
- Workflow diagram: The vertical node stack remains viable at mobile widths (cards are naturally responsive), but the Y-branch may reflow into a sequential list to avoid horizontal crowding.
- Footer: Multi-column footer (if present below fold) collapses to single-column stacked sections.
Image Behavior
- Workflow diagram: As an SVG/HTML construct (not a raster image), it reflows natively—cards shrink to available width, text wraps, connector lines adjust via SVG viewBox or CSS positioning. No cropping occurs.
- Hero illustration: If raster images exist on other pages (product screenshots, team photos), they likely use
object-fit: coverwith{rounded.md}or{rounded.lg}and respond viasrcset/<picture>for resolution switching. - Icons: SVG icons scale crisply at all viewport sizes due to vector nature; no bitmap aliasing concerns.
Iteration Guide
-
Initialize with Next.js + Tailwind. Set up a Next.js project (App Router preferred) with Tailwind v3.4+. Install the self-hosted font files into
public/fonts/and declare@font-facerules inglobals.cssmatching the extracted font-faces exactly. -
Define design tokens in
tailwind.config.js. Map every YAML frontmatter value to Tailwind'stheme.extend:colors,fontFamily,fontSize,fontWeight,letterSpacing,lineHeight,borderRadius,spacing,boxShadow,transitionDuration,transitionTimingFunction. Usecolors.canvasforbackground-colordefaults. -
Build the header assembly first. Implement
{component.top-banner}(dismissible, dark background, flex row), then{component.top-nav}(sticky, 95% opacity backdrop, 64px height, flex row with justify-between). Get the logo, nav links with dropdown triggers, and auth buttons pixel-matched to the screenshot. -
Construct the hero band. Create a two-column grid (or flex row) within
{spacing.hero}vertical padding. Left column:{component.badge-label}→{component.hero-headline}→{component.hero-subhead}→{component.hero-cta-group}(flex row, gap{spacing.base}). Right column: workflow diagram container. -
Implement the workflow card system. Build
{component.workflow-card}as a reusable component acceptingicon,headerText,bodyText, andbadgeprops. Stack instances vertically with connector line components between them. Implement the Y-branch after the third node using absolute positioning or CSS grid. -
Add state variants per component. For each component with
-activeor-focusvariants in the frontmatter, implement the corresponding CSS pseudo-classes (:active,:focus-visible). Add:hoverstates that interpolate between default and active (e.g., primary button background shifts 50% toward{colors.primary-active}). -
Layer in motion. Implement the keyframe animations listed in the Motion section—start with
connection(workflow lines),running/completed(node states), anddialog-scale-in(dropdowns). Apply--transition-baseto all interactive elements. -
Test responsive breakpoints. Verify the mobile collapse: nav becomes hamburger, hero becomes single-column, workflow diagram flows below CTAs. Ensure all touch targets meet 44×44px minimum. Test on real devices, not just browser resize.
-
Run the linter. Execute
npx @google/design.md lint DESIGN.md(or equivalent validation) to catch broken{token.path}references, orphaned components missing prose entries, and contrast-ratio violations. -
Extend conservatively. When adding new pages (Pricing, Customers, etc.), reuse existing tokens before creating new ones. If a new color is absolutely required, name it following the established sub-prefix convention (
colors.pricing-*,colors.dashboard-*) and add it to the frontmatter before use.
Font Setup
For development environments without access to Attio's self-hosted WOFF2 files, substitute as follows:
- Inter Display → Use Inter from Google Fonts (weights 400, 500, 600, 700). Simulate Display's tighter appearance by adding
font-stretch: condensed(if variable font supported) or manually tighteningletter-spacingby -0.02em at sizes ≥ 32px. - Inter → Use Inter from Google Fonts (weights 400, 500, 600). This is a direct match.
- Tiempos Text → Substitute Source Serif 4 (weights 400, 600) or Lora from Google Fonts for editorial sections.
- JetBrains Mono → Available on Google Fonts under identical name (weights 400, 700).
Define CSS custom properties for global consistency:
:root {
--font-display: 'Inter Display', 'Inter', system-ui, sans-serif;
--font-body: 'Inter', system-ui, sans-serif;
--font-editorial: 'Tiempos Text', 'Source Serif 4', Georgia, serif;
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
}
Known Gaps
- Hover state styling: Per the no-hover policy, all
:hoverpseudo-class styles are inferred rather than extracted. Implementation should interpolate between Default and Active/Pressed states. - Loading/skeleton states: No loading skeletons, spinners (beyond the
rotate-reportingkeyframe), or pending-state UI were visible in the static screenshot. These must be designed following the established token constraints. - Form validation states: Beyond
{component.text-input-focus}, no error ({colors.error}), warning, or success ({colors.success}) input states were extractable. Design these using the semantic color tokens. - Dark mode: While
{colors.surface-dark},{colors.surface-soft},{colors.text-input-dark}, and{component.top-banner}suggest dark-mode capability, the screenshot captures only light mode. Dark-mode token mappings (canvas ↔ surface-dark inversions) require separate extraction from a dark-mode view. - Dropdown panel internals: Navigation dropdown contents (megamenu layouts, link grids, featured cards) are not visible. Their structure must be inferred from the
{component.nav-dropdown-trigger}presence. - Modal/dialog system: The
dialog-scale-in/dialog-scale-outkeyframes prove modals exist, but no modal was open during screenshot capture. Modal styling (backdrop, close button, content padding) is undocumented. - Pricing page specifics: The
pricing-cards-grid-line-appearkeyframe references a pricing page not captured here. That page's card component variants, toggle switches, and tier comparisons are unknown. - Dashboard/authenticated surfaces: The screenshot shows only the marketing/landing page. Internal app surfaces (data tables, detail views, settings panels) likely introduce new components (tables, toggles, avatars, breadcrumbs) not represented in this spec.
- Exact hex for Lab colors: Several CSS colors were specified in OkLab/Lab color space (e.g.,
lab(10.7201 -0.0959039 -1.54182)). Conversion to sRGB hex (#1a1c1e approx.) introduces minor perceptual shift. For production fidelity, retain Lab/OkLab values in the CSS custom properties and use hex in the design doc for readability. - Pre-assigned value anomalies: The pre-assigned
{colors.canvas}: "#640000"(dark red) contradicts the visually apparent near-white canvas in the screenshot. This value was provided deterministically and must be used as-specified, but implementers should verify whether this represents a branded warm-white, a sampling artifact, or a domain-specific override.