imitation
← all crawls

Build fast. Run any code fearlessly. · Fly

https://fly.io/
fly.io screenshot

Visuals

Colors

Primary
#281950
Accent
#ca7ff8
Background
#ffffff
Surface
#7c3aed
Text Primary
#281950
Text Secondary
#ffffff

Typography

Aa
Display
Mackinac
64px / w500
Aa
Heading
Mackinac
36px / w500
Aa
Body
Fricolage Grotesque
18px / w325
Aa
Label
Fricolage Grotesque
14.5px / w500
Aa
Mono
Fragment Mono
14px / w400

Spacing

Xs
4px
Sm
8px
Md
12px
Lg
20px
Xl
24px

Radius

Sm
4px
Md
10px
Lg
16px
Pill
9999px

Shadows

Sm
Md
Lg

Mode

Dark mode
Background
Sample text on canvas
Bg#ffffff
Text#281950
Muted#ffffff

Motion

Levelexpressive
Duration
Easingcubic-bezier(0.4, 0, 0.2, 1)

Stack

Frameworktailwind
Iconscustom

Full Palette · 28 tokens

Brand
accent
#ca7ff8
primary
#281950
primary-active
#7c3aed
primary-hover
#6d28d9
Surface
canvas
#ffffff
surface-dark
#191034
surface-elevated
#ffffff
surface-soft
#7c3aed
surface-strong
#f1f2f9
Text
body
#ffffff
ink
#281950
muted
#a39ac1
muted-soft
rgba(40, 25, 80, 0.75)
on-dark
#ffffff
on-primary
#ffffff
on-surface
#281950
Hairlines & Borders
border-gray
#ccd0e0
border-purple-inset
rgba(67, 56, 202, 0.25)
hairline
#e5e6f0
hairline-soft
rgba(255, 255, 255, 0.4)
Semantic
error
#ef4444
info
#3b82f6
link
#7c3aed
link-active
#5b21b6
link-hover
#6d28d9
success
#10b981
warning
#f59e0b
Other
nav-text
#281950

Typography Roles · 11

body-md
Aa
18px / w325
body-sm
Aa
15.5px / w400
button
Aa
15.5px / w450
button-sm
Aa
14.5px / w450
caption
Aa
14.5px / w450
display-lg
Aa
64px / w500
display-xl
Aa
64px / w500
label-md
Aa
14.5px / w500
mono
Aa
14px / w400
title-md
Aa
36px / w500
title-sm
Aa
20px / w400

Components · 29

badge-info
backgroundColortransparent
rounded{rounded.pill}
textColor{colors.info}
badge-success
backgroundColortransparent
rounded{rounded.pill}
textColor{colors.success}
button-ghost
backgroundColortransparent
padding6px 12px
rounded{rounded.pill}
textColor{colors.ink}
typography{typography.caption}
button-primary
backgroundColor{colors.surface-soft}
padding10px 20px
rounded{rounded.pill}
textColor{colors.on-primary}
typography{typography.button}
button-primary-nav
backgroundColor{colors.surface-soft}
height32px
padding0 12px 0 10px
rounded{rounded.asym-right}
textColor{colors.on-primary}
typography{typography.button-sm}
button-secondary
backgroundColortransparent
padding8px 12px
rounded{rounded.DEFAULT}
textColor{colors.link}
typography{typography.label-md}
button-secondary-hover
backgroundColorrgba(124, 58, 237, 0.08)
rounded{rounded.DEFAULT}
textColor{colors.link}
card-default
backgroundColor{colors.canvas}
padding{spacing.xl}
rounded{rounded.lg}
textColor{colors.ink}
typography{typography.body-md}
card-elevated
backgroundColor{colors.surface-elevated}
padding{spacing.xl}
rounded{rounded.lg}
textColor{colors.ink}
code-inline
backgroundColorrgba(40, 25, 80, 0.05)
padding2px 6px
rounded{rounded.sm}
textColor{colors.ink}
typography{typography.mono}
content-section
backgroundColor{colors.canvas}
maxWidth1440px
textColor{colors.ink}
footer-band
backgroundColor{colors.surface-strong}
padding{spacing.section} {spacing.base}
textColor{colors.muted}
typography{typography.body-sm}
hero-band
backgroundColorlinear-gradient(to bottom, #f1f2f9, #ffffff, #ffffff)
minHeight800px
paddingBottom200px
paddingTop70px
textColor{colors.ink}
typography{typography.display-xl}
hero-cta
backgroundColor{colors.surface-soft}
padding14px 20px
rounded{rounded.pill}
textColor{colors.on-primary}
typography{typography.button}
hero-cta-icon
backgroundColortransparent
size16px
textColor{colors.on-primary}
hero-headline
backgroundColortransparent
textColor{colors.ink}
typography{typography.display-lg}
hero-subhead
backgroundColortransparent
textColor{colors.muted-soft}
typography{typography.body-md}
illustration-canvas
backgroundColortransparent
height100%
textColorinherit
width100%
input-focus
backgroundColor{colors.canvas}
rounded{rounded.DEFAULT}
textColor{colors.ink}
input-text
backgroundColor{colors.canvas}
height44px
padding10px 14px
rounded{rounded.DEFAULT}
textColor{colors.ink}
typography{typography.body-md}
link-text
backgroundColortransparent
textColor{colors.link}
typography{typography.body-md}
link-text-hover
backgroundColortransparent
textColor{colors.link-hover}
logo-mark
backgroundColortransparent
size40px
textColor{colors.primary}
menu-toggle
backgroundColortransparent
rounded{rounded.pill}
size40px
textColor{colors.ink}
menu-toggle-open
backgroundColor{colors.canvas}
rounded{rounded.pill}
size40px
textColor{colors.ink}
nav-pill
backgroundColorrgba(255, 255, 255, 0.75)
padding6px 20px
rounded{rounded.pill}
textColor{colors.ink}
typography{typography.button-sm}
nav-pill-gradient
backgroundColorrgba(255, 255, 255, 0.75)
padding{spacing.md} {spacing.xl}
rounded{rounded.pill}
textColor{colors.primary}
typography{typography.button-sm}
top-nav
backgroundColortransparent
height96px
textColor{colors.nav-text}
typography{typography.caption}
top-nav-container
backgroundColortransparent
maxWidth1200px
padding{spacing.base} {spacing.base}
textColor{colors.nav-text}

design.md

Fly.io Design System

Overview

Fly.io's visual identity lives at the intersection of technical precision and creative whimsy. The landing page presents itself as a warm, approachable developer platform — not the cold sterility typical of infrastructure tooling, nor the aggressive neon saturation of Web3 marketing. Instead, it occupies a distinctive middle ground: a soft lavender-washed canvas populated by hand-drawn editorial illustrations, anchored by a confident deep-navy typographic voice, and activated by vibrant violet CTAs that feel both urgent and friendly.

The brand's voltage concentrates in its call-to-action surfaces ({component.button-primary}, {component.hero-cta}) and the gradient-washed navigation pill that floats above the hero illustration. These violet touches — {colors.surface-soft} at #7c3aed and its darker sibling {colors.primary-hover} at #6d28d9 — provide the only saturated color moments against an otherwise restrained palette of near-white surfaces, navy ink ({colors.ink}), and desaturated lavender body text ({colors.muted-soft}). This restraint makes every violet button feel like an invitation rather than a demand.

The defining typographic move is the serif/sans-serif pairing: Mackinac (a custom serif face available in medium weight 500 and bold 700) carries all display and heading roles with elegant negative letter-spacing, while Fricolage Grotesque (a variable geometric sans supporting weights 100–900) handles body text at a deliberately light 325 weight. This creates a visual hierarchy where headlines feel editorial and authoritative, while body copy feels modern and breathable. The {typography.display-lg} at 64px with -2.88px letter-spacing is the system's signature moment — generous, confident, and slightly condensed.

Shape language leans heavily into {rounded.pill} (9999px radius) for all interactive elements — buttons, navigation containers, toggle controls — creating a consistent "soft UI" vocabulary that mirrors the organic curves of the hand-drawn illustrations. Cards and content containers use more conservative {rounded.lg} (16px) or {rounded.md} (10px) radii, maintaining the friendly aesthetic without sacrificing structural clarity.

A notable sub-system is the illustration-first hero architecture: rather than a traditional left-rail headline with right-rail product mockup, Fly.io places a full-width hand-drawn scene behind a centered text column, allowing the illustration to establish mood while the copy delivers message. The gradient wash from {colors.surface-strong} to pure {colors.canvas} creates atmospheric depth beneath the illustration layer.

Key Characteristics

  • Canvas is pure {colors.canvas} (#ffffff) with optional lavender gradient washes ({colors.surface-strong} at #f1f2f9)
  • Brand voltage lives exclusively in violet: {colors.surface-soft} for primary actions, {colors.accent} for decorative accents
  • Headlines use Mackinac serif at weight 500 with aggressive negative letter-spacing ({typography.display-lg})
  • Body text uses Fricolage Grotesque at an ultra-light weight 325, creating high-contrast hierarchy without bolding
  • All CTAs are {rounded.pill}-shaped; navigation uses floating translucent pills with backdrop blur
  • Illustration style is hand-drawn editorial line-art with flat color fills and organic, flowing compositions
  • Shadow system uses subtle purple-tinted shadows ({extensions.shadows.sm}) rather than neutral grays
  • Motion is expressive: scroll-triggered fades, infinite marquee animations, and springy transitions

Colors

Brand & Accent

  • Primary Ink ({colors.primary} — #281950): Deep navy used for headlines, logo marks, and primary text elements. This is the darkest color in the palette — almost black-purple — providing maximum contrast against {colors.canvas}.
  • Primary Active/Violet ({colors.surface-soft} — #7c3aed): The signature brand violet used for all primary buttons ({component.button-primary}, {component.hero-cta}), active states, and key interactive surfaces. This is the most visible expression of the brand.
  • Primary Hover ({colors.primary-hover} — #6d28d9): Darker violet shade for hover states on primary buttons and links.
  • Accent Light Violet ({colors.accent} — #ca7ff8): Soft lavender accent used sparingly for decorative star/sparkle illustrations and tertiary emphasis.

Surface

  • Canvas ({colors.canvas} — #ffffff): Pure white base surface for the entire page background and content areas.
  • Surface Gradient Start ({colors.surface-strong} — #f1f2f9): Cool off-white with slight lavender tint; used as the top-color in the hero band's vertical gradient (linear-gradient(to bottom, #f1f2f9, #ffffff)).
  • Elevated Surface ({colors.surface-elevated} — #ffffff): White surface for cards and panels that sit above the base canvas, often paired with {extensions.shadows.md} elevation.
  • Dark Surface ({colors.surface-dark} — #191034): Near-black purple for inverted contexts (modals, dropdowns, code blocks with dark backgrounds).

Text & Ink

  • Ink ({colors.ink} — #281950): Full-opacity navy for headlines, navigation text, and high-emphasis body copy. Identical hex to {colors.primary}, used semantically as the default text color.
  • Body White ({colors.body} — #ffffff): White text for rendering on dark/violet backgrounds (button labels on {component.button-primary}).
  • Muted Lavender ({colors.muted} — #a39ac1): Desaturated lavender for captions, metadata, timestamps, and secondary interface text.
  • Muted Soft ({colors.muted-soft} — rgba(40, 25, 80, 0.75)): Semi-transparent navy at 75% opacity; used specifically for the hero subheading paragraph ({component.hero-subhead}) to create visual hierarchy beneath the headline.
  • On Primary ({colors.on-primary} — #ffffff): White text guaranteed AA contrast against {colors.surface-soft} (violet); used for all CTA button labels.
  • On Dark ({colors.on-dark} — #ffffff): White text for rendering on any dark surface context.
  • Nav Text ({colors.nav-text} — #281950): Navy for navigation links and header-level UI elements.

Hairlines & Borders

  • Hairline Default ({colors.hairline} — #e5e6f0): Very light gray-lavender for subtle dividers and card borders.
  • Hairline Soft ({colors.hairline-soft} — rgba(255, 255, 255, 0.40)): Semi-transparent white for borders on translucent/glassmorphic elements like {component.nav-pill}.
  • Border Gray ({colors.border-gray} — #ccd0e0): Medium-light gray for visible form field borders and outlined buttons ({component.button-secondary}).
  • Inset Purple Border ({colors.border-purple-inset} — rgba(67, 56, 202, 0.25)): Subtle purple inner glow used as the focus-ring treatment on primary buttons via box-shadow inset.

Semantic

  • Success Green ({colors.success} — #10b981): Emerald green for status indicators, successful deployment badges, and confirmation states.
  • Info Blue ({colors.info} — #3b82f6): Bright blue for informational badges, links to documentation, and neutral status indicators.
  • Warning Amber ({colors.warning} — #f59e0b): Orange-yellow for caution states and attention-requiring notices.
  • Error Red ({colors.error} — #ef4444): Red for error states, failed operations, and destructive action warnings.
  • Link Violet ({colors.link} — #7c3aed): Violet matching the primary brand color for inline text links.
  • Link Hover ({colors.link-hover} — #6d28d9): Darker violet for link hover states.
  • Link Active ({colors.link-active} — #5b21b6): Deepest violet for active/pressed link states.

Typography

Font Family

Fly.io employs a curated three-font family stack, each serving a distinct role in the typographic hierarchy:

Mackinac (serif) serves as the exclusive display and heading face. It is a proprietary webfont loaded from /phx/ui/fonts/mackinac-medium.woff2 (weight 500), mackinac-bold.woff2 (weight 700), plus italic variants for each. It falls back to ui-serif, then Georgia, Cambria, and finally generic serif. Mackinac carries all {typography.display-xl}, {typography.display-lg}, and {typography.title-md} roles — its editorial character (modulated stroke contrast, slightly condensed proportions) gives the platform a publication-quality voice that distinguishes it from competitors' purely technical aesthetics.

Fricolage Grotesque (sans-serif) handles all body text, UI labels, buttons, and interface elements. Loaded as a variable font (fricolage-grotesque.var.woff2) supporting weight range 100–900, it falls back to ui-sans-serif then system fonts. Its geometric construction with open apertures ensures legibility at small sizes, while the variable axis allows precise weight selection — the system notably uses weight 325 for body copy (between Light and Regular), creating a refined low-contrast reading experience that defies the "body text must be 400 or 500" convention.

Fragment Mono (monospace) is loaded for code snippets and technical annotations (fragment-mono-regular.woff2 and -italic.woff2). While no monospace text appears in the hero screenshot, the @font-face declarations confirm its presence for documentation pages and code examples.

Hierarchy

| Token | Size | Weight | Line Height | Letter Spacing | Use | |---|---|---|---|---|---| | {typography.display-xl} | 64px | 500 | 73.6px | -2.88px | Hero H1 (reserved for future oversized displays) | | {typography.display-lg} | 64px | 500 | 73.6px | -2.88px | Hero headline ("Build fast. Run any code fearlessly.") | | {typography.title-md} | 36px | 500 | 47.7px | -0.9px | Section headings (H2 level) | | {typography.title-sm} | 20px | 400 | 28px | 0 | Card titles, feature subtitles | | {typography.body-md} | 18px | 325 | 27px | normal | Hero subhead paragraph, primary body copy | | {typography.body-sm} | 15.5px | 400 | 24px | 0 | Secondary body text, descriptions | | {typography.caption} | 14.5px | 450 | 20px | 0 | Navigation items, metadata, small UI labels | | {typography.button} | 15.5px | 450 | 1.25 (≈19px) | 0 | Primary CTA button labels | | {typography.button-sm} | 14.5px | 450 | 1.2 (≈17px) | 0 | Nav bar button labels | | {typography.label-md} | 14.5px | 500 | 20px | 0 | Form labels, tab labels | | {typography.mono} | 14px | 400 | 20px | 0 | Code snippets, terminal text |

Principles

The typography system trusts size differential and family contrast (serif vs. sans-serif) to carry hierarchical weight, rather than relying on bold weights. Notice that the heaviest weight in regular usage is 500 (medium) for Mackinac headlines — there are no 600, 700, or 800 weights in the body hierarchy. Even the body text sits at a delicate 325, lighter than standard "regular." This creates a sophisticated, airy reading experience where the eye navigates by recognizing which typeface is speaking (Mackinac = important; Fricolage = supporting), not how heavy the strokes are.

Negative letter-spacing is aggressively applied to display sizes: {typography.display-lg} compacts by nearly 3 pixels (-2.88px), and {typography.title-md} by almost a full pixel (-0.9px). This tightening gives large headlines a premium, editorial feel reminiscent of magazine spreads. Body text receives zero letter-spacing adjustment, preserving natural readability.

The color hierarchy reinforces typographic hierarchy: {colors.ink} at full opacity for headlines, {colors.muted-soft} at 75% opacity for body paragraphs. This dual-axis system (size + color value) means even if a user were to resize their browser and collapse the size difference, the opacity difference would still signal importance.

Italic is reserved for Mackinac (the font file mackinac-medium-italic.woff2 exists in the loaded set) and Fragment Mono, likely for emphasized terms within body copy and code variables respectively. No uppercase transformations are observed — the voice is sentence-case throughout, reinforcing approachability over corporate authority.

Note on Font Substitutes

Mackinac is a proprietary Fly.io font with no public Google Fonts equivalent. For development and prototyping purposes, substitute with Playfair Display (Google Fonts) — a transitional serif with similar modulation, slightly condensed proportions, and excellent weight 500 coverage. Define the substitution via CSS variable:

--font-heading: 'Playfair Display', ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif;

Fricolage Grotesque is similarly proprietary. Substitute with DM Sans (Google Fonts) — a low-contrast geometric sans with variable font support and similar open apertures. For the specific weight 325, use DM Sans at weight 300 with slight optical compensation, or fall back to weight 400 with reduced opacity:

--font-body: 'DM Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';

Fragment Mono can be substituted directly with JetBrains Mono or Fira Code, both available on Google Fonts with excellent ligature support for developer-facing content:

--font-mono: 'JetBrains Mono', ui-monospace, monospace;

Layout

Spacing System

  • Base unit: 4px (inferred from the xs: 4px token and the even distribution of spacing values).
  • Tokens: {spacing.xxs} (2px — micro-adjustments, focus ring offsets), {spacing.xs} (4px — icon gaps, internal padding), {spacing.sm} (8px — compact element gaps), {spacing.md} (12px — most common gap, used 78 times in extracted CSS), {spacing.base} (16px — container padding, card internal spacing), {spacing.lg} (20px — button padding, loose gaps), {spacing.xl} (24px — section-internal spacing), {spacing.section-sm} (32px — component group margins), {spacing.section} (80px — major section vertical rhythm), {spacing.section-lg} (120px — hero bottom padding), {spacing.section-xl} (128px — extra-large section breaks).
  • Section padding (vertical): {spacing.section-lg} (120px) for the hero band's bottom padding; {spacing.section} (80px) for standard content sections below the fold.
  • Card internal padding: {spacing.xl} (24px) per {component.card-default} and {component.card-elevated}.
  • Gutters: Header container uses {spacing.base} (16px) horizontal padding scaling responsively to sm: 24px, lg: 32px.

Grid & Container

  • Max content width: 1440px for main content sections (main, section selectors); 1200px for the header/navbar container.
  • Density choice: Editorial density — generous whitespace around each content block, with the hero section consuming 800–1000px of vertical space before the first content section begins. This is not a marketplace or dashboard layout; it's a narrative landing page where breathing room signals confidence.
  • Desktop grid behavior: The hero uses a single centered column (text content max-width constrained implicitly by readability, roughly 700–800px) overlaid on a full-width illustration layer. Below-fold sections likely adopt a 2-column (feature + description) or 3-column (card grid) layout within the 1440px container, though only the hero is visible in the provided viewport.
  • Hero column split: Not a traditional split — the hero centers text horizontally with illustration bleeding edge-to-edge behind it. The text column sits in the lower half of the hero area (pushed down by paddingTop: 70px and illustration dominance).

Whitespace Philosophy

Fly.io embraces editorial airiness. The hero alone reserves ~1000px of vertical real estate (including the 200–268px bottom padding), and the space between the headline and subhead paragraph is substantial. Body text at 18px with 27px line-height creates loose vertical rhythm within paragraphs. This is not whitespace-as-afterthought; whitespace-as-architecture. The hand-drawn illustrations are given room to breathe, and the centered text column never feels cramped against viewport edges.

Header Architecture

┌──────────────────────────────────────────────────────────────────────┐
│ [Logo]              [Products] [Docs] ... [Status]   [Sign In] [Get Started] │
│                      ← centered nav-pill (xl+) →                              │
│  ← 1200px max-width container, 32px horizontal padding →                    │
│  h-24 (96px) tall, transparent background                                   │
└──────────────────────────────────────────────────────────────────────┘

The navigation uses a floating pill architecture on desktop (xl breakpoint+): navigation links are grouped inside a {component.nav-pill} — a translucent white pill (rgba(255, 255, 255, 0.75)) with full rounding, absolutely positioned at horizontal center. The logo sits flush-left within the 1200px container, while the Sign In / Get Started buttons sit flush-right. On smaller breakpoints, this collapses to a hamburger menu ({component.menu-toggle}).

Hero Section

┌──────────────────────────────────────────────────────────────────────┐
│ ┌─ gradient: #f1f2f9 → #ffffff → #ffffff ──────────────────────────┐ │
│ │                                                                   │ │
│ │     ★  ✦  [hand-drawn illustration SVG — full width]  ✦  ★       │ │
│ │         (trees, mountains, boats, characters, sandboxes)           │ │
│ │                                                                   │ │
│ │            Build fast.                                             │ │
│ │        Run any code fearlessly.                                    │ │
│ │                                                                   │ │
│ │     The platform for devs who just want to ship...                 │ │
│ │                                                                   │ │
│ │            [ Deploy your app → ]                                  │ │
│ │                                                                   │ │
│ │  ← 1440px implicit text column, centered →                        │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│                   pb: 200px (lg: 268px)                              │
└──────────────────────────────────────────────────────────────────────┘

Key observations about the hero:

  • Height is responsive: 800px on default, 1000px on lg: breakpoint, with increasing bottom padding
  • The illustration is a single <svg> element positioned absolute/inset, z-indexed beneath the text content
  • Text content is vertically pushed to the lower half (the illustration dominates upper space)
  • The CTA button ({component.hero-cta}) includes a chevron-right icon inline with the label

Elevation & Depth

| Level | Treatment | Use | |---|---|---| | 0 — Flat baseline | No shadow, {colors.canvas} background | Page body, static sections | | 1 — Hairline outline | 1px solid {colors.hairline} or {colors.border-gray} | Card borders, divider lines | | 2 — Soft drop (purple-tinted) | {extensions.shadows.sm} — layered purple shadows (0.1 opacity) | Floating nav-pills, elevated UI chrome | | 3 — Neutral elevation | {extensions.shadows.md} — subtle gray shadow with 1px border | Dropdowns, modals, tooltip containers | | 4 — Focus ring | {extensions.shadows.focus-ring} — purple inset box-shadow | Button focus states, input focus | | 5 — Semantic glow | {extensions.shadows.success-glow} or {extensions.shadows.info-glow} — colored outer glow | Status badges, highlighted cards |

Philosophy: Fly.io uses a layered, color-inflected elevation system rather than neutral grayscale shadows. The primary elevation token ({extensions.shadows.sm}) tints its blur layers with purple (rgba(91, 33, 182, 0.1)), ensuring that even depth cues reinforce brand identity. Focus states avoid the standard outline-offset approach in favor of an inset box-shadow in brand purple — this is unusual and distinctly on-brand. For semantic elements (success checks, info badges), the system graduates to fully colored glow shadows that broadcast their status chromatically.

There is no evidence of hard drop shadows, neumorphism, or dramatic elevation. Everything stays within the "soft UI" idiom — gentle lifts, translucent surfaces, colored glows.

Decorative Depth

The hero section employs a gradient wash as its primary decorative depth technique: linear-gradient(to bottom, #f1f2f9, #ffffff, #ffffff) creates a subtle lavender-to-white transition that grounds the illustration and gives the hero band atmospheric volume without requiring photographic imagery, parallax layers, or complex compositing. The hand-drawn SVG illustration itself provides additional depth through overlapping shapes, varied opacity layers, and foreground/midground/background compositional layering — but these are illustrative techniques, not CSS-driven depth tokens.

Shapes

Border Radius Scale

| Token | Value | Use | |---|---|---| | {rounded.sm} | 4px | Code inline blocks ({component.code-inline}), tiny tags | | {rounded.DEFAULT} | 8px | Secondary buttons, form inputs, small cards | | {rounded.md} | 10px | Standard card corners | | {rounded.lg} | 16px | Feature cards, content panels, image containers | | {rounded.xl} | 20px | Large panel containers (rare) | | {rounded.pill} | 9999px | All primary CTAs, nav pills, toggles, badges | | {rounded.asym-right} | 8px 20px 20px 8px | Nav-bar "Get Started" button (asymmetric pill) | | {rounded.asym-left} | 20px 8px 8px 20px | Mirror of above (unused in current view) |

The asymmetric radius ({rounded.asym-right}) is a signature detail: the "Get Started" button in the navigation has a squircle-like shape with tighter rounding on the left (where it abuts other elements) and fuller rounding on the right (where it terminates freely). This is a deliberate "bookend" shape language that makes the CTA feel like it's emerging from the navigation cluster.

Photography Geometry

No photography is present in the hero section. The site relies entirely on hand-drawn vector illustration (SVG). When imagery is introduced elsewhere (team photos, customer logos, screenshots), the design language suggests it would use {rounded.lg} (16px) corner rounding based on the established card patterns, with possible full-bleed treatments for immersive showcase sections. Avatar shapes would likely be {rounded.pill} or circle, consistent with the dominant roundness vocabulary.

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 workhorse CTA button used for the hero "Deploy your app" action and equivalent conversion points throughout the page. Background {colors.surface-soft} (violet #7c3aed), text {colors.on-primary} (white), type {typography.button} at 15.5px/weight 450, {rounded.pill} geometry, padding 10px 20px. Carries an inset box-shadow focus ring ({extensions.shadows.focus-ring}) using {colors.border-purple-inset}. State variants: see {component.button-primary-nav} for the navigation-sized version with asymmetric rounding.

{component.button-primary-nav} — Compact variant of the primary button used in the top navigation bar's "Get Started" trigger. Same violet background and white text, but sized for the navbar context: {typography.button-sm} at 14.5px, {rounded.asym-right} (8px/20px) creating the signature bookend shape, tighter padding 0 12px 0 10px, fixed height 32px. This is one of the few components breaking the pill symmetry intentionally.

{component.button-secondary} — Outlined/ghost button for secondary actions like "Sign In". Transparent background, text {colors.link} (violet), {typography.label-md} weight 500, {rounded.DEFAULT} (8px), 1px {colors.border-gray} border, padding 8px 12px. Shadow is minimal ({extensions.shadows.lg} — barely-visible neutral lift). State variant {component.button-secondary-hover} introduces a faint violet background tint (rgba(124, 58, 237, 0.08)) and border color shift toward {colors.link-hover}.

{component.button-ghost} — Transparent button for non-CTA interactive elements like text links styled as buttons or filter chips. Background transparent, text {colors.ink}, {typography.caption}, {rounded.pill}, minimal padding. Used for utility actions where a full button would be visually overweight.

{component.menu-toggle} — Mobile hamburger menu control (visible below xl breakpoint). Fully transparent background, {colors.ink} text/icon color, {rounded.pill} (40px square), scales to show white background when menu is open (see {component.menu-toggle-open}). Contains an SVG icon (hamburger → X transform).

{component.hero-cta} — The prominent hero call-to-action ("Deploy your app →"). Larger than {component.button-primary} with padding 14px 20px, same violet background and white text, {rounded.pill}, includes a trailing chevron-right icon ({component.hero-cta-icon}) in white at 16px. This is the highest-conversion-pressure button on the page.

Cards & Containers

{component.card-default} — Standard content card for feature descriptions, testimonials, or documentation previews. Background {colors.canvas}, text {colors.ink}, body type {typography.body-md}, {rounded.lg} (16px), generous internal padding {spacing.xl} (24px). Likely carries {extensions.shadows.sm} or {extensions.shadows.md} when elevated above the base canvas. Used in grid layouts below the fold (not visible in hero viewport).

{component.card-elevated} — Elevated variant of the card for modals, dropdown panels, or highlighted content. Same dimensions and padding as {component.card-default} but with stronger shadow treatment ({extensions.shadows.md}) and potentially a subtle border. Used when the card needs to "float" above other content.

{component.content-section} — Section-level wrapper for all post-hero content blocks. Max-width 1440px, {colors.canvas} background, contains grid layouts for features, pricing, or documentation. Provides horizontal centering and consistent width constraint.

Inputs & Forms

{component.input-text} — Standard text input field. Background {colors.canvas}, text {colors.ink}, body type {typography.body-md}, {rounded.DEFAULT} (8px), padding 10px 14px, fixed height 44px (meets WCAG AAA touch target). Border likely 1px {colors.border-gray} (inferred from button-secondary patterns). State variant {component.input-focus} maintains same geometry with the purple inset focus ring ({extensions.shadows.focus-ring}).

Navigation

{component.top-nav} — The global navigation header. Transparent background (letting the hero gradient show through), height 96px (h-24), contains the logo mark, navigation links, and CTA buttons. Z-indexed at 500 to float above hero illustration. Typography {typography.caption} for nav items.

{component.top-nav-container} — Inner container constraining nav content to 1200px max-width with responsive horizontal padding (16px → 24px → 32px). Centers the nav contents within the viewport.

{component.nav-pill} — The floating translucent pill containing navigation links (Products, Docs, Customers, Pricing, Articles, Community, Status) on desktop. Background rgba(255, 255, 255, 0.75) (75% opaque white) creating a glass effect, text {colors.ink}, {rounded.pill}, padding 6px 20px horizontally. Absolutely positioned at the horizontal center of the nav bar. Likely has backdrop-filter: blur() for frosted-glass effect (implied by the translucency + the gradient overlay classes seen in extracted CSS: bg-gradient-to-r from-pink-200/40 via-viol...).

{component.nav-pill-gradient} — Enhanced variant of the nav pill wrapping the right-side CTAs. Adds a subtle gradient wash over the white base (pink-into-violet at low opacity) to visually separate the action cluster from the navigation links. Same pill geometry, text color shifts to {colors.primary}.

{component.logo-mark} — The Fly.io wordmark and balloon-icon combination. 40px height, transparent background, rendered in {colors.primary} (navy). Positioned flush-left within the nav container.

Signature Components

{component.hero-band} — The full-viewport hero section. Background is a three-stop linear gradient from {colors.surface-strong} (#f1f2f9) down to {colors.canvas} (#ffffff), creating the signature lavender-wash atmosphere. Contains the absolute-positioned SVG illustration layer (full bleed), the centered text column (headline + subhead + CTA), and generous vertical padding (70px top, 200–268px bottom depending on breakpoint). Min-height 800px (lg: 1000px). This is the most architecturally complex component — a layered composition rather than a simple container.

{component.hero-headline} — The H1 headline text block ("Build fast. Run any code fearlessly."). Transparent background, text {colors.ink}, type {typography.display-lg} — Mackinac serif at 64px, weight 500, with aggressive -2.88px letter-spacing. Line height 73.6px. Splits across two visual lines in the screenshot with the word "fearlessly" receiving italic treatment (supported by the loaded Mackinac Italic font).

{component.hero-subhead} — The descriptive paragraph beneath the headline. Text color {colors.muted-soft} (75% opacity navy), type {typography.body-md} — Fricolage Grotesque at 18px, weight 325. Constrained width (roughly 60–70ch) for optimal reading measure.

{component.illustration-canvas} — The full-width SVG illustration occupying the hero's background layer. Contains hand-drawn vector art: trees, mountains, water, boats, anthropomorphic characters, sandbox imagery, stars, clocks, and abstract shapes. Rendered in a limited palette mirroring the brand colors (navy lines, violet/lavender fills, teal accents, peach/coral warmth). Position: absolute, inset: 0, z-index beneath text content.

Utility Components

{component.code-inline} — Inline code or technical term styling. Background rgba(40, 25, 80, 0.05) (5% navy), text {colors.ink}, {typography.mono} (Fragment Mono at 14px), {rounded.sm} (4px), tight padding 2px 6px. Used for referencing API endpoints, package names, or CLI commands within prose.

{component.link-text} — Inline text link. Transparent background, text {colors.link} (violet), inherits surrounding typography (typically {typography.body-md}). Underline likely appears on hover (not documented per no-hover policy).

{component.badge-success} / {component.badge-info} — Small status indicator badges. Transparent background, colored text ({colors.success} green or {colors.info} blue), {rounded.pill} shape. Used for deployment status, region indicators, or feature tags. May carry colored glow shadows ({extensions.shadows.success-glow} / {extensions.shadows.info-glow}) in certain contexts.

{component.footer-band} — Page footer container (inferred from design patterns, not visible in hero screenshot). Background {colors.surface-strong} (#f1f2f9 — the cool off-white), text {colors.muted} (lavender-gray), {typography.body-sm}, generous padding {spacing.section} vertical.

Do's and Don'ts

Do

  • Do use {typography.display-lg} (Mackinac 64px/weight 500) for all H1-level headlines — never substitute a sans-serif or increase the weight beyond 500.
  • Do apply {rounded.pill} (9999px) to every primary CTA button; the circular vocabulary is non-negotiable for brand recognition.
  • Do set body copy to weight 325 in Fricolage Grotesque — the deliberate lightness is a core characteristic, not a mistake.
  • Do use the gradient wash ({colors.surface-strong}{colors.canvas}) for the hero background; flat white loses the atmospheric quality.
  • Do reserve {colors.surface-soft} (#7c3aed violet) exclusively for interactive elements — never use it as decorative background fill on non-clickable surfaces.
  • Do apply the asymmetric radius {rounded.asym-right} to the navigation "Get Started" button; the bookend shape is a signature detail.
  • Do use {colors.muted-soft} (75% opacity navy) for the hero subhead paragraph — this opacity differential is how the system creates hierarchy without reducing font size.
  • Do give the hero band at least 800px of vertical space (1000px on large screens) — compressing it destroys the editorial pacing.
  • Do pair the purple-tinted shadow ({extensions.shadows.sm}) with any floating element (nav-pills, tooltips); neutral grays would break the chromatic cohesion.
  • Do allow hand-drawn illustration to occupy the full hero width behind centered text — do not confine illustrations to a sidebar column.
  • Do use the inset box-shadow focus ring ({extensions.shadows.focus-ring}) for all button and input focus states instead of outline offsets.

Don't

  • Don't bold the display headlines — Mackinac at weight 500 is already the maximum; going to 700 would破坏 the editorial restraint.
  • Don't use black (#000000) for any text — the deepest allowed color is {colors.ink} (#281950), a warm navy that harmonizes with the violet brand palette.
  • Don't apply {rounded.pill} to cards or content containers — that geometry is reserved for interactive elements; cards should use {rounded.lg} (16px) or {rounded.md} (10px).
  • Don't introduce new brand colors beyond the defined palette (violet, navy, lavender, semantic greens/blues/ambers/reds) — the system's coherence depends on chromatic discipline.
  • Don't replace the serif/sans-serif pairing with a single font family — the Mackinac/Fricolage contrast is foundational to the visual voice.
  • Don't add gradients to button backgrounds — primary CTAs are solid {colors.surface-soft}; gradients belong only in the hero wash and nav-pill overlays.
  • Don't reduce the hero headline letter-spacing below -2.88px or remove it entirely — the tightening is what gives the 64px type its premium, magazine-quality feel.
  • Don't use sharp corners (0px radius) anywhere in the interface — even the smallest elements get {rounded.sm} (4px).
  • Don't promote the mobile nav pattern (hamburger menu) to desktop — the floating pill navigation is the intended xl+ experience.
  • Don't place the CTA button above the subhead paragraph — the information hierarchy is Headline → Description → Action, always.
  • Don't use shadows darker than {extensions.shadows.md} — Fly.io's elevation is gentle; heavy drops would violate the soft UI philosophy.

Motion & Animation

Transition Tokens

--transition-fast: color 0.15s cubic-bezier(0.4, 0, 0.2, 1), 
                    background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1), 
                    border-color 0.15s cubic-bezier(0.4, 0, 0.2, 1), 
                    text-decoration-color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
                    
--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), 
                    opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1), 
                    box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1), 
                    transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);

--transition-fade: opacity 0.15s cubic-bezier(0.4, 0, 0.2, 1);
--transition-simple: all 0.2s ease;

The system uses two primary transition durations: 150ms for micro-interactions (color shifts, hover states, link underlines) and 300ms for structural changes (panel reveals, mode switches, transform-based motion). All transitions share the cubic-bezier(0.4, 0, 0.2, 1) easing — the standard "ease-out" curve that feels snappy yet smooth. The comprehensive property lists in --transition-base indicate that the framework (Tailwind) applies transitions holistically to theme-aware components.

Keyframe Animations

The extracted CSS declares 17 distinct @keyframes animations, revealing a motion-rich interface:

  • fpFadeInDown — Entry animation for floating panels or modals (translate Y + fade).
  • ping-badge — Radial pulse for notification dots (scale + opacity ripple).
  • dot-one / dot-two / dot-three — Staggered loading indicator (three-dot typing animation with sequential delays).
  • shimmer — Skeleton loading placeholder sweep (gradient translate-X across element).
  • spin — Continuous rotation for loading spinners (360deg transform).
  • bounce — Vertical oscillation for attention-drawing elements (CTA arrows, scroll prompts).
  • fade — Simple opacity crossfade (0 ↔ 1).
  • slideY — Vertical reveal (translateY + opacity, likely triggered by IntersectionObserver).
  • infinite-scroll — Horizontal marquee/ticker for logo strips or testimonial carousels (continuous translateX loop).
  • ping — Simpler variant of ping-badge for status indicators.
  • pulse — Scale pulse (heartbeat-style breathing animation for live/updating elements).
  • blink-animation — Opacity toggle for cursor/text-caret simulation.
  • subtle-ping — Restrained ping variant for less intrusive status feedback.
  • progress-bar-stripes — Diagonal stripe movement for indeterminate progress bars.
  • indeterminate — Width oscillation for progress bar fill animation.

Interaction Patterns

Based on the declared animations and transition tokens, Fly.io implements these observable interaction patterns:

  1. Scroll-triggered reveals: Sections and cards animate in via {slideY} or {fade} as they enter the viewport (IntersectionObserver-driven). This explains the generous vertical spacing — it gives elements room to "fly in" without colliding with adjacent content.
  2. Floating nav-pill morphing: The navigation pill likely gains additional background opacity or subtle shadow elevation on scroll (triggered by a scroll listener adding a .scrolled class), transitioning via --transition-base.
  3. Mobile menu slide-in: The off-canvas mobile menu uses a 300ms translateX transition (-translate-x-full → translate-x-0) with ease-in-out timing, revealed by toggling a [data-menu-state=on] attribute.
  4. Button press feedback: Primary buttons likely implement a subtle scale-down transform (0.97–0.98) on active/pressed state, rebounding on release, powered by transform 0.3s in the base transition.
  5. Loading states: Forms and async actions use the {shimmer} skeleton animation and/or {dot-one/two/three} typing indicator, providing perceived performance feedback during network requests.
  6. Status badge pulses: Live deployment indicators or connection status dots use {ping-badge} or {subtle-ping} to communicate activity without demanding attention.
  7. Infinite marquees: Customer logo strips or feature tickers scroll horizontally via {infinite-scroll}, creating dynamic energy on otherwise static sections.
  8. Focus ring expansion: The purple inset box-shadow on focused buttons animates in over 150–300ms, creating a "glow spreading from within" sensation rather than a sudden appearance.

Imagery Style

  • Medium: Exclusively hand-drawn vector illustration (SVG), no photography in the hero viewport. Lines have organic, slightly irregular weights suggesting digital brush or pen texture rather than geometric precision.
  • Subject matter: Whimsical, metaphorical scenes combining nature (trees, water, mountains, celestial bodies), human activity (boats, buildings, characters), and computing concepts (sandboxes, boxes with faces, clocks, code symbols). The illustration tells a story about creativity, exploration, and safe experimentation — mapping abstract infrastructure concepts to tactile, playful visuals.
  • Color treatment: Illustration uses a curated subset of the brand palette: navy outlines ({colors.ink}), lavender/purple fills ({colors.accent}, {colors.surface-soft}), teal and aqua accents, warm peach/coral highlights, and yellow/gold for sunlight motifs. Colors are flat (no gradients within the illustration itself) with clean edge definition.
  • Composition: Full-bleed, panoramic format with layered depth (foreground elements overlap midground, midground overlaps background). The illustration wraps around the text column rather than being confined to a sidebar, creating an immersive environment.
  • Line quality: Varied stroke weights (thinner for distant details, bolder for focal characters/objects), occasional texture marks (cross-hatching on wood grain, stippling on ground surfaces). Feels like ink-on-paper translated to vector.
  • Character style: Anthropomorphic objects (a box with a smile, a bird-like creature) rendered with minimal detail — dot eyes, simple curved mouths. Friendly, non-threatening, inviting identification rather than admiration.
  • Role relative to text: Illustration supports and atmospheres; it does not compete with the headline. The text remains fully legible because the illustration uses lighter opacities or avoids placing dense detail behind the text column.
  • Signature technique: Organic, flowing S-curves guide the eye from upper-left (tree/sun motif) through center (mountain/village) to lower-right (sandbox/bird), creating a visual journey that parallels the "build fast → deploy confidently" narrative arc.
  • Decorative elements: Stars and sparkles (✦ ★ shapes in {colors.accent} lavender) float in negative space around the illustration edges, adding magical sparkle without overwhelming the composition.

Icon System

  • Library: Custom SVG icons (no detected third-party library — Tailwind's built-in SVG icon set may be used for basic UI icons, but the illustration elements are bespoke).
  • Specific icons observed:
    • Balloon/logo mark (custom path — the Fly.io brand mark with balloon and string)
    • Chevron-right arrow (within {component.hero-cta})
    • Menu/hamburger icon (three horizontal lines, transforms to X in {component.menu-toggle})
    • Star/sparkle shapes (decorative ✦ ★ in illustration layer)
  • Treatment: Stroke-based for UI icons (menu, chevron) with currentColor inheritance; fill-based for the logo mark and decorative elements. UI icons align centrally with their accompanying text (baseline-aligned for inline icons like the CTA chevron).
  • Size spectrum: Logo mark at 40px ({component.logo-mark}), chevron icon at 16px ({component.hero-cta-icon}), menu icon filling the 40×40px toggle bounds, decorative stars at approximately 24–32px in the illustration.
  • Stroke weight: Consistent 1.5–2px for UI icons (matching the caption text's visual weight), thicker for the brand mark (3–4px for visibility at small sizes).
  • Color: UI icons inherit {colors.ink} or {colors.on-primary} from parent text color via currentColor; decorative illustration icons use explicit fills from the brand palette.

Recommended Frontend Stack

Framework:      Next.js (App Router) or Remix — Fly.io is an Elixir/Phoenix shop 
                (evidenced by /phx/ asset paths), but the frontend consumes this 
                via HTMX/alpine.js hybrid or ships as a static build. For 
                reimplementation: Next.js 14+ with App Router for SSR/SEO needs.
Styling:        Tailwind CSS v3.4+ (confirmed by extracted class names: 
                rounded-full, bg-violet-600, transition-colors, container mx-auto, 
                arbitrary values like [[data-menu-state=on]_&]:bg-white)
Fonts:          Self-hosted WOFF2 files served from /phx/ui/fonts/ (fricolage-grotesque.var.woff2, 
                mackinac-*.woff2, fragment-mono-*.woff2). Google Fonts substitutes 
                for development: Playfair Display (Mackinac), DM Sans (Fricolage), 
                JetBrains Mono (Fragment Mono).
Animation:      Tailwind's built-in animation utilities (animate-ping, animate-spin, 
                animate-bounce) plus custom @keyframes for slideY, shimmer, 
                infinite-scroll. Framer Motion recommended for scroll-triggered 
                reveals if building in React.
Icons:          Inline SVG (custom paths) + Lucide React or Heroicons for 
                standard UI icons (menu, chevron, external-link) where custom 
                marks aren't required.
Component lib:  Headless UI (@headlessui/react) for accessible disclosure patterns 
                (mobile menu, dropdowns) — matches the [data-menu-state=on] 
                attribute pattern observed in extracted HTML.

Responsive Behavior

Breakpoints

| Name | Width | Key Changes | |---|---|---| | Mobile (default) | < 640px | Single column, hamburger menu visible, hero height 800px, CTA full-width | | sm | ≥ 640px | Menu toggle shows white background when open (sm:[[data-menu-state=on]_&]:bg-white), increased horizontal padding | | md | ≥ 768px | Wider container padding, potential 2-column layouts below fold | | lg | ≥ 1024px | Desktop nav links appear (hidden until lg), hero expands to 1000px height, bottom padding increases to 268px, Sign In/Get Started buttons hide from inline nav (become menu items) | | xl | ≥ 1280px | Floating nav-pill appears with centered links, full desktop navigation restored, menu toggle hidden |

Touch Targets

  • {component.hero-cta}: Padding 14px × 20px yields minimum tap area ~48px × 48px (with text height) — exceeds WCAG AAA 44×44 requirement.
  • {component.button-primary-nav}: Fixed 32px height × ~80px width — meets minimum but is compact; adequate for nav-bar context where horizontal space is constrained.
  • {component.button-secondary}: Padding 8px × 12px + text = ~36px height — borderline for WCAG AAA; consider increasing to 44px minimum in implementation.
  • {component.input-text}: Fixed 44px height — meets WCAG AAA exactly.
  • {component.menu-toggle}: 40px × 40px — falls short of 44px recommendation; the invisible hit area should extend to 44px via padding or min-sizing.
  • Nav links inside {component.nav-pill}: Padding 6px × 20px + text ≈ 32px height — relies on the pill's overall clickability rather than individual link targets.

Collapsing Strategy

  1. Navigation: Below xl breakpoint, the floating pill nav collapses to a hamburger menu ({component.menu-toggle}). The off-canvas menu slides in from the right (or left, based on -translate-x-[100vw] classes), overlaying content with a backdrop. Above xl, the pill returns with all links visible.
  2. Hero layout: The centered text column maintains its position across all breakpoints, but the illustration layer may crop differently (SVG viewBox handling). At mobile, the headline font-size may reduce (though 64px is preserved in the extracted CSS — potentially via fluid typography or a sm:text-5xl downward tweak).
  3. CTA positioning: The hero CTA remains inline with text at all sizes; on mobile, it likely stretches to full width or centers with max-width constraint (inferred from max-w-52 classes on nav buttons suggesting width-conscious design).
  4. Vertical spacing: Hero bottom padding scales from 200px (default) to 268px (lg) to accommodate taller viewports, preventing the CTA from sitting too close to the viewport bottom edge on large monitors.
  5. Container width: The 1200px nav container and 1440px content container maintain their max-widths at all breakpoints (they're percentage-based or max-width capped), with horizontal padding adjusting inward (16px → 24px → 32px).
  6. Grid content (below fold): Any card grids or feature columns would collapse from multi-column to single-column below the md/lg threshold (standard responsive pattern, though not visible in hero screenshot).

Image Behavior

  • Hero illustration (SVG): As a scalable vector, the illustration maintains crispness at all viewport widths. Its position: absolute; inset: 0 sizing means it bleeds edge-to-edge regardless of screen width. Critical visual elements (faces, focal characters) should remain within the visible viewport on mobile — the SVG's viewBox and preserveAspectRatio handle cropping, but the art should be composed with a "safe zone" for narrow viewports.
  • Logo mark: The 40px balloon icon likely reduces to 32px on mobile (common pattern), though extracted CSS doesn't show explicit responsive sizing for the logo.
  • Future raster images: If product screenshots or team photos appear below the fold, expect them to use srcSet with 1x/2x/3x variants, lazy loading (loading="lazy"), and possibly <picture> elements with media queries for art-direction crops (portrait on mobile, landscape on desktop).

Iteration Guide

  1. Start with the hero band — Build {component.hero-band} first with its gradient background (linear-gradient(to bottom, #f1f2f9, #ffffff, #ffffff)), full-viewport height (800px mobile, 1000px lg), and the absolute-positioned illustration layer. Get the atmospheric wash correct before adding text content; the gradient is the foundation everything else sits on.
  2. Implement the floating navigation next — The {component.top-nav} with its 96px height, 1200px constrained container, and the {component.nav-pill} (translucent white, {rounded.pill}, centered via absolute positioning + translate-x) is the second-most distinctive architectural element. Ensure the nav-pill has backdrop-filter: blur(8px) or similar for the frosted-glass effect implied by the translucency.
  3. Typography setup is critical — Load the three font families (Mackinac, Fricolage Grotesque, Fragment Mono) via @font-face declarations pointing to the WOFF2 files. If developing locally without access to Fly.io's font assets, substitute with Playfair Display, DM Sans, and JetBrains Mono per the Font Substitutes section. Define CSS custom properties for --font-heading, --font-body, --font-mono.
  4. Apply the headline correctly — Set the H1 to {typography.display-lg}: 64px, weight 500, -2.88px letter-spacing, Mackinac. The negative letter-spacing is easy to overlook but essential for the editorial look. Ensure "fearlessly" renders in italic (Mackinac Italic is loaded).
  5. Body text must be light — Set the subhead paragraph to {typography.body-md} at weight 325 (not 400, not 300). Apply {colors.muted-soft} (rgba(40, 25, 80, 0.75)) for the text color. This combination of light weight + reduced opacity is the system's primary hierarchy mechanism below the fold.
  6. Buttons require precise radius values — The hero CTA gets {rounded.pill} (9999px). The nav "Get Started" gets {rounded.asym-right} (8px 20px 20px 8px) — this asymmetric value is unusual and must be implemented explicitly; it won't happen by accident. All primary buttons get the inset purple box-shadow for focus state.
  7. Motion should be added after static layout — Once the page looks correct without animation, add the transition tokens (150ms for micro-interactions, 300ms for structural changes) and the scroll-triggered entry animations (slideY, fade via IntersectionObserver). Use Tailwind's animate-* utilities for the simpler effects (bounce, pulse, ping) and custom @keyframes for shimmer, infinite-scroll, and dot-loading sequences.
  8. Color discipline is non-negotiable — Only six colors should appear in 95% of your implementation: #281950 (ink/headlines), #7c3aed (violet CTAs), #ffffff (canvas/button-labels), rgba(40, 25, 80, 0.75) (body text), #a39ac1 (muted captions), and #f1f2f9 (gradient start). Reserve the semantic colors (green/blue/red) for status indicators only.
  9. Test the mobile experience early — The hamburger menu, the collapsing navigation, and the hero's vertical compression all interact. Verify that {component.menu-toggle} becomes visible below xl, that the off-canvas menu slides smoothly with translate-x transitions, and that the hero CTA remains tappable at 44px+ height on touch devices.
  10. Run the linter — Execute npx @google/design.md lint DESIGN.md after completing your implementation. Watch for broken-ref errors (indicating you referenced a token that doesn't exist), contrast-ratio warnings (especially on the 75% opacity body text against white), and orphaned-tokens (colors or spacing values defined but never used in components or prose).

Font Setup for Development

If you cannot access Fly.io's self-hosted font files, add these Google Fonts <link> tags to your document <head>:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&family=JetBrains+Mono:ital,wght@0,400..800;1,400..800&family=Playfair+Display:ital,wght@0,400..900;1,400..900&display=swap" rel="stylesheet">

Then define these CSS variables to map to the design tokens:

:root {
  --font-heading: 'Playfair Display', ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif;
  --font-body: 'DM Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
  --font-mono: 'JetBrains Mono', ui-monospace, monospace;
}

When Fricolage Grotesque and Mackinac become available (from Fly.io's open-source releases or purchased licensing), swap the font-family values in these variables — all other token references will resolve automatically.

Known Gaps

  • Hover state styling: Per the no-hover policy, hover backgrounds, border-color shifts, and transform-lifts on buttons/cards are not documented. The extracted CSS shows hover: prefixed Tailwind classes implying hover states exist (e.g., hover:bg-violet-600, hover:border-violet-500/40), but exact values should be inferred from the active/disabled variants and the brand's established color relationships.
  • Loading skeletons: The shimmer keyframe is declared, but the exact skeleton component markup (gradient background animation, border-radius, height variants) is not captured in the hero screenshot.
  • Form validation states beyond focus: Error messages, success checkmarks, disabled-input styling, and helper text typography are not present in the hero viewport and thus undocumented.
  • Authenticated/dashboard surfaces: The screenshot captures only the unauthenticated landing page. Dashboard UI, deployment logs, billing settings, and organization management surfaces may introduce additional color tokens (status-specific backgrounds, data visualization palettes, dark-mode surfaces) not represented here.
  • Dark mode: Despite extensions.mode: "dark" being pre-assigned, the visual evidence strongly indicates a light-mode design (white canvas, navy text). The dark mode token set — if one exists for docs dashboards or developer console — is completely unknown.
  • Sub-brand or regional variants: Enterprise pricing, government/compliance landing pages, or localized versions (e.g., fly.io/jp) may modify the illustration style, color temperature, or typographic voice in ways not detectable from the global homepage.
  • Pixel-exact gradient stops: The hero background gradient's middle stop (via-white) and its transition point (likely 50% or 60% down the band) are approximated from the CSS bg-gradient-to-b from-gray-100 via-white to-white class. Exact color-mix percentages would require inspecting the compiled CSS output.
  • Illustration SVG details: The hand-drawn hero illustration's exact path data, layer ordering, and animation keyframes (if it contains subtle motion like bobbing boats or twinkling stars) are encapsulated in the <svg> element and not decomposed in the extracted CSS. Re-implementing the illustration requires either exporting the original SVG asset or recreating it in a vector editor.
  • Accessibility markup: ARIA roles, focus-management logic, keyboard-navigation handlers, and screen-reader announcements for the mobile menu, dropdown disclosures, and carousel components are behavioral concerns not visible in static CSS extraction. Implement per WCAG 2.2 AA guidelines and the Headless UI library's accessibility patterns.