editorial · serif · sans · mono · structured · cool

Fly.io

Mackinac display + Fragment Mono on a violet-saturated canvas — a PaaS that dresses like a small-press magazine.

By webdesignhot · fly.io
$ npx design-md add fly-io
Learn more about the CLI
Compare to…
try on →
1440 × 900
mobile · 390 × 844
Tokens design.md/v1.5
  • bg #24175b
  • bg-deep #15103d
  • bg-cream #fbf2e4
  • bg-elev-1 #1f1748
  • bg-elev-2 #2a1f6b
  • surface #1f1748
  • surface-cream #f4ead7
  • surface-cream-deep #ede0c4
  • brand — · 2.7 #7c3aed
  • brand-hover #9061f5
  • brand-pressed #6929d4
  • brand-deep #5b21b6
  • brand-glow #7c3aed33
  • on-brand #ffffff
  • accent #a78bfa
  • accent-hover #c4b5fd
  • accent-warm #f59e0b
  • accent-warm-soft #fbbf24
  • accent-soft #7c3aed1f
  • link #a78bfa
  • link-hover #c4b5fd
  • link-visited #8b6cd9
  • link-cream #5b21b6
  • selected #7c3aed26
  • disabled #3a2f5f
  • disabled-text #6b5d8a
  • text AAA · 14.0 #fbf2e4
  • text-ink #15103d
  • text-heading #fbf2e4
  • text-muted #a89dc8
  • text-soft #867aa8
  • text-faint — · 2.2 #5b537a
  • text-disabled #6b5d8a
  • text-cream-heading #15103d
  • text-cream-body #2a1f4d
  • text-cream-muted #5b507a
  • border #ffffff1a
  • border-soft #ffffff0d
  • border-strong #ffffff33
  • border-ink #15103d33
  • border-ink-strong #15103d4d
  • border-brand #7c3aed66
  • shadow-ambient rgba(0,0,0,0.25)
  • shadow-standard rgba(15,16,61,0.4)
  • shadow-elevated rgba(15,16,61,0.55)
  • shadow-glow rgba(124,58,237,0.3)
  • success #34d399
  • success-bg #0f3a2a
  • warning #f59e0b
  • warning-bg #3a2710
  • danger #f87171
  • danger-bg #3a1818
  • info #a78bfa
  • info-bg #1f1748
Typography
Ship faster than ever.
display-hero Mackinac 96px w500 -0.03em
Ship faster than ever.
display-large Mackinac 72px w500 -0.025em
Ship faster than ever.
h1 Mackinac 56px w500 -0.022em
Built for teams that ship.
h2 Mackinac 42px w500 -0.02em
A complete kit
h3 Mackinac 28px w500 -0.01em
The quick brown fox jumps over the lazy dog.
quote Mackinac 24px w400 -0.005em
The quick brown fox jumps over the lazy dog.
h4 Mackinac 22px w500 -0.005em
The quick brown fox jumps over the lazy dog.
body-large "Fricolage Grotesque" 19px w400 0
The quick brown fox jumps over the lazy dog.
body "Fricolage Grotesque" 17px w400 0
The quick brown fox jumps over the lazy dog.
link "Fricolage Grotesque" 17px w500 0
The quick brown fox jumps over the lazy dog.
button "Fricolage Grotesque" 16px w500 0
The quick brown fox jumps over the lazy dog.
body-small "Fricolage Grotesque" 15px w400 0
The quick brown fox jumps over the lazy dog.
button-small "Fricolage Grotesque" 14px w500 0
OUR DESIGN SYSTEM
caption "Fricolage Grotesque" 14px w400 0
npx design-md add linear
code-body "Fragment Mono" 14px w400 0
npx design-md add linear
code-bold "Fragment Mono" 14px w700 0
OUR DESIGN SYSTEM
label-mono "Fragment Mono" 13px w400 0.04em
OUR DESIGN SYSTEM
caption-small "Fricolage Grotesque" 13px w400 0
The quick brown fox jumps over the lazy dog.
micro "Fricolage Grotesque" 12px w500 0.06em
OUR DESIGN SYSTEM
code-label "Fragment Mono" 12px w400 0.05em
Spacing
  • step-0 2px
  • step-1 4px
  • step-2 8px
  • step-3 12px
  • step-4 16px
  • step-5 20px
  • step-6 24px
  • step-7 32px
  • step-8 40px
  • step-9 48px
  • step-10 64px
  • step-11 80px
  • step-12 96px
  • step-13 128px
  • step-14 160px
Radius
  • micro 2px
  • sm 4px
  • md 6px
  • lg 10px
  • xl 14px
  • featured 18px
  • pill 9999px
Components
Text link →
Card preview A complete kit — everything your product needs. Hero, pricing, FAQ, dashboard, docs — every layout your product needs.
New Stable v1.0
Lineage & influences

Fly.io is the only major PaaS that runs a wedge-serif display face. **Mackinac** — by Production Type — is a high-contrast 21st-century serif most commonly seen on small-press book covers and design- journal mastheads. Pairing it with **Fricolage Grotesque** (a geometric sans with rounded terminals) and **Fragment Mono** (an angular variable-width monospace) gives Fly.io a typographic palette that has more in common with The Browser Company's Arc memos and Plain's editorial restraint than with any AWS-class infrastructure brand. The chromatic identity is a violet-saturated near-black `#24175b` that fades into cream `#fbf2e4` reading panels — a high- contrast tonal flip borrowed from magazine spread design. Action sits on the brand violet `#7c3aed`. Where Railway uses eggplant and Render uses CMYK violet, Fly leans into the saturated indigo-violet of Plex's older "Plex Indigo" colour-way, modernised toward Tailwind's `violet-600`. Buttons are 6px — tighter than the 8px PaaS norm — reinforcing the editorial-print feel.

Export 4 formats · paste-ready
Tailwind

theme.extend block for tailwind.config.js

tailwind.config.js
CSS variables

:root { --bg, --text, --brand, … } you can paste anywhere

design.css
DTCG JSON

W3C Design Tokens Community Group format

design.tokens.json
Figma Variables

Importable into Figma → Variables → Import

figma-variables.json
The file
---
name: Fly.io
tagline: 'Mackinac display + Fragment Mono on a violet-saturated canvas — a PaaS that dresses like a small-press magazine.'
author: webdesignhot
source_url: https://fly.io
spec: design.md/v1.5
quality: curated
featured: false
categories: [dev-tools, saas]
tags: [editorial, serif, sans, mono, structured, cool]
preview_swatch: ['#24175b', '#7c3aed', '#fbf2e4']
related: [railway, vercel, supabase]
description: 'Fly.io is the rare infrastructure brand that uses **Mackinac** as its display face — a high-contrast wedge-serif normally found in editorial magazines — paired with **Fricolage Grotesque** for body and **Fragment Mono** for code. The chromatic identity is a violet-saturated near-black canvas that fades into a creamy off-white reading panel; the result is a PaaS that reads like a literary quarterly with a deploy command.'

colors:
  # Primary
  bg: '#24175b'                  # deep violet hero band
  bg-deep: '#15103d'             # near-black violet
  bg-cream: '#fbf2e4'            # creamy off-white reading panel
  bg-elev-1: '#1f1748'           # tinted purple panel
  bg-elev-2: '#2a1f6b'           # mid-tone purple
  surface: '#1f1748'             # tinted purple panel
  surface-cream: '#f4ead7'       # cream variant
  surface-cream-deep: '#ede0c4'  # deeper cream

  # Brand & Dark
  brand: '#7c3aed'               # violet primary action — Fly's signature
  brand-hover: '#9061f5'         # hover (lighter)
  brand-pressed: '#6929d4'       # pressed (deeper)
  brand-deep: '#5b21b6'          # deepest violet
  brand-glow: '#7c3aed33'        # 20% violet wash
  on-brand: '#ffffff'            # white text on violet

  # Accent
  accent: '#a78bfa'              # lighter violet
  accent-hover: '#c4b5fd'        # accent hover
  accent-warm: '#f59e0b'         # amber counterpoint
  accent-warm-soft: '#fbbf24'    # softer amber
  accent-soft: '#7c3aed1f'       # 12% violet wash

  # Interactive
  link: '#a78bfa'                # links use lighter violet
  link-hover: '#c4b5fd'          # link hover
  link-visited: '#8b6cd9'        # visited
  link-cream: '#5b21b6'          # link on cream panels (darker)
  selected: '#7c3aed26'          # 15% violet selection
  disabled: '#3a2f5f'            # disabled bg
  disabled-text: '#6b5d8a'       # disabled text

  # Neutral Scale
  text: '#fbf2e4'                # cream on dark
  text-ink: '#15103d'            # near-black violet on cream
  text-heading: '#fbf2e4'        # headline cream
  text-muted: '#a89dc8'          # muted lavender on dark
  text-soft: '#867aa8'           # softer lavender
  text-faint: '#5b537a'          # quaternary
  text-disabled: '#6b5d8a'

  # On-cream neutrals
  text-cream-heading: '#15103d'  # near-black violet on cream
  text-cream-body: '#2a1f4d'     # mid-violet on cream
  text-cream-muted: '#5b507a'    # muted on cream

  # Surface & Borders
  border: '#ffffff1a'            # 10% white hairline on dark
  border-soft: '#ffffff0d'       # 5% white
  border-strong: '#ffffff33'     # 20% white emphasized
  border-ink: '#15103d33'        # 20% violet ink on cream
  border-ink-strong: '#15103d4d' # 30% ink emphasized
  border-brand: '#7c3aed66'      # 40% brand on focus

  # Shadow
  shadow-ambient: 'rgba(0,0,0,0.25)'      # low ambient
  shadow-standard: 'rgba(15,16,61,0.4)'   # ink-tinted standard
  shadow-elevated: 'rgba(15,16,61,0.55)'  # deep elevated
  shadow-glow: 'rgba(124,58,237,0.3)'     # violet focus glow

  # Semantic
  success: '#34d399'             # mint green
  success-bg: '#0f3a2a'          # success surface
  warning: '#f59e0b'             # amber (also brand counterpoint)
  warning-bg: '#3a2710'          # warning surface
  danger: '#f87171'              # coral red
  danger-bg: '#3a1818'           # danger surface
  info: '#a78bfa'                # info uses lighter violet
  info-bg: '#1f1748'             # info surface

typography:
  display:
    family: 'Mackinac, ui-serif, Georgia, "Times New Roman", serif'
    weights: [400, 500, 700]
    opentype-features: ['liga', 'dlig', 'kern']
  body:
    family: '"Fricolage Grotesque", Inter, -apple-system, "system-ui", "Segoe UI", Roboto, "Helvetica Neue", sans-serif'
    weights: [400, 500, 600]
    opentype-features: ['ss01', 'kern']
  mono:
    family: '"Fragment Mono", ui-monospace, SFMono-Regular, Menlo, monospace'
    weights: [400]
    opentype-features: ['zero', 'tnum']
  scale:
    display-hero:   { size: 96, weight: 500, lineHeight: 1.0,  tracking: '-0.03em',  family: display, opentype: 'liga, dlig' }
    display-large:  { size: 72, weight: 500, lineHeight: 1.05, tracking: '-0.025em', family: display, opentype: 'liga' }
    h1:             { size: 56, weight: 500, lineHeight: 1.08, tracking: '-0.022em', family: display, opentype: 'liga' }
    h2:             { size: 42, weight: 500, lineHeight: 1.12, tracking: '-0.02em',  family: display }
    h3:             { size: 28, weight: 500, lineHeight: 1.25, tracking: '-0.01em',  family: display }
    h4:             { size: 22, weight: 500, lineHeight: 1.3,  tracking: '-0.005em', family: display }
    body-large:     { size: 19, weight: 400, lineHeight: 1.55, tracking: '0',         family: body }
    body:           { size: 17, weight: 400, lineHeight: 1.55, tracking: '0',         family: body }
    body-small:     { size: 15, weight: 400, lineHeight: 1.5,  tracking: '0',         family: body }
    label-mono:     { size: 13, weight: 400, lineHeight: 1.3,  tracking: '0.04em',    family: mono, opentype: 'zero, tnum' }
    button:         { size: 16, weight: 500, lineHeight: 1.0,  tracking: '0',         family: body }
    button-small:   { size: 14, weight: 500, lineHeight: 1.0,  tracking: '0',         family: body }
    link:           { size: 17, weight: 500, lineHeight: 1.55, tracking: '0',         family: body }
    quote:          { size: 24, weight: 400, lineHeight: 1.35, tracking: '-0.005em',  family: display }
    caption:        { size: 14, weight: 400, lineHeight: 1.4,  tracking: '0',         family: body }
    caption-small:  { size: 13, weight: 400, lineHeight: 1.35, tracking: '0',         family: body }
    micro:          { size: 12, weight: 500, lineHeight: 1.3,  tracking: '0.06em',    family: body }
    code-body:      { size: 14, weight: 400, lineHeight: 1.6,  tracking: '0',         family: mono, opentype: 'zero' }
    code-bold:      { size: 14, weight: 700, lineHeight: 1.6,  tracking: '0',         family: mono, opentype: 'zero' }
    code-label:     { size: 12, weight: 400, lineHeight: 1.3,  tracking: '0.05em',    family: mono, opentype: 'zero, tnum' }

radius:
  micro: 2
  sm: 4
  md: 6           # button — tighter than 8px PaaS norm
  lg: 10          # card
  xl: 14          # hero shell
  featured: 18    # signature panels
  pill: 9999

spacing:
  base: 4
  scale: [2, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 96, 128, 160]
  xxs: 2
  xs: 4
  sm: 8
  md: 16
  lg: 24
  xl: 32
  xxl: 48
  section-sm: 80
  section: 120
  section-lg: 160

layout:
  page-width: 1200
  prose-width: 680
  header-height: 64

motion:
  ease-standard: 'cubic-bezier(0.4, 0, 0.2, 1)'
  ease-emphasized: 'cubic-bezier(0.2, 0, 0, 1)'
  ease-decelerate: 'cubic-bezier(0, 0, 0.2, 1)'
  duration-fast: 120
  duration-standard: 240
  duration-slow: 400
  reduced-motion: 'respects prefers-reduced-motion: reduce — panel transitions reduce to opacity-only, hover scale removed, decorative floats disabled.'

breakpoints:
  mobile: 640
  tablet: 1024
  desktop: 1200
  wide: 1536

shadows:
  ambient: 'rgba(0,0,0,0.25) 0 1px 3px'
  standard: 'rgba(15,16,61,0.4) 0 8px 24px -4px'
  elevated: 'rgba(15,16,61,0.55) 0 18px 36px -12px, rgba(0,0,0,0.3) 0 4px 8px'
  deep: 'rgba(15,16,61,0.7) 0 30px 60px -16px'
  ring: '0 0 0 3px rgba(124,58,237,0.4)'
  glow: '0 0 32px rgba(124,58,237,0.35)'

accessibility:
  contrast-text-on-bg: 11.6         # AAA — cream on deep violet
  contrast-text-on-brand: 5.2       # AA — white on #7c3aed
  contrast-ink-on-cream: 14.8       # AAA — #15103d on #fbf2e4
  contrast-link-on-bg: 7.4          # AAA — light violet link on dark canvas
  contrast-muted-on-bg: 5.8         # AA at body sizes
  focus-ring: '3px solid rgba(124,58,237,0.4), 0 offset'
  reduced-motion-honored: true
  keyboard-nav: 'standard tab order; violet focus ring on dark, brand-deep on cream'

components:
  button-primary:
    bg: '#7c3aed'
    text: '#ffffff'
    padding: '10px 18px'
    radius: 6
    font: 'button (16/500)'
    border: 'none'
    hover: 'bg → #9061f5; subtle 1.005 scale'
    active: 'bg → #6929d4'
    use: 'primary CTA — Sign up, Deploy, Try Fly'
  button-ghost:
    bg: 'transparent'
    text: '#fbf2e4'
    padding: '10px 18px'
    radius: 6
    font: 'button (16/500)'
    border: '1px solid rgba(255,255,255,0.2)'
    hover: 'border → rgba(255,255,255,0.35); bg → rgba(255,255,255,0.05)'
    use: 'secondary action on dark'
  button-cream:
    bg: '#fbf2e4'
    text: '#15103d'
    padding: '10px 18px'
    radius: 6
    font: 'button (16/500)'
    border: 'none'
    hover: 'bg → #f4ead7'
    use: 'inverted CTA on dark canvas'
  card:
    bg: '#1f1748'
    text: '#fbf2e4'
    padding: '24px'
    radius: 10
    border: '1px solid rgba(255,255,255,0.1)'
    shadow: 'rgba(0,0,0,0.25) 0 1px 3px'
    use: 'feature card on dark'
  card-cream:
    bg: '#fbf2e4'
    text: '#15103d'
    padding: '24px'
    radius: 10
    border: '1px solid rgba(15,16,61,0.15)'
    use: 'reading panel — body content, blog'
  input:
    bg: '#15103d'
    text: '#fbf2e4'
    placeholder: '#867aa8'
    padding: '10px 14px'
    radius: 6
    border: '1px solid rgba(255,255,255,0.15)'
    focus: 'border → #7c3aed; ring 3px solid rgba(124,58,237,0.4)'
    use: 'text input, search'
  badge:
    bg: '#1f1748'
    text: '#a78bfa'
    padding: '2px 10px'
    radius: 9999
    font: 'micro (12/500)'
    use: 'tag, status, region label'
  nav-link:
    bg: 'transparent'
    text: '#a89dc8'
    padding: '8px 12px'
    font: 'body-small (15/500)'
    hover: 'text → #fbf2e4'
    active: 'text → #a78bfa'
    use: 'top nav, sidebar'

lineage:
  summary: |
    Fly.io is the only major PaaS that runs a wedge-serif display face.
    **Mackinac** — by Production Type — is a high-contrast 21st-century
    serif most commonly seen on small-press book covers and design-
    journal mastheads. Pairing it with **Fricolage Grotesque** (a
    geometric sans with rounded terminals) and **Fragment Mono** (an
    angular variable-width monospace) gives Fly.io a typographic palette
    that has more in common with The Browser Company's Arc memos and
    Plain's editorial restraint than with any AWS-class infrastructure
    brand. The chromatic identity is a violet-saturated near-black
    `#24175b` that fades into cream `#fbf2e4` reading panels — a high-
    contrast tonal flip borrowed from magazine spread design. Action
    sits on the brand violet `#7c3aed`. Where Railway uses eggplant and
    Render uses CMYK violet, Fly leans into the saturated indigo-violet
    of Plex's older "Plex Indigo" colour-way, modernised toward Tailwind's
    `violet-600`. Buttons are 6px — tighter than the 8px PaaS norm —
    reinforcing the editorial-print feel.
  influences:
    - name: 'Mackinac (Production Type)'
      role: 'The wedge-serif display face that sets Fly.io apart from every Inter-based PaaS.'
      url: https://productiontype.com
    - name: 'Plain'
      role: 'Editorial cream panels, restrained type-driven layouts, mono accents as voice.'
      url: https://plain.com
    - name: 'The Browser Company / Arc'
      role: 'Cream-on-violet tonal flips, magazine-spread layout rhythm, mono pull-quotes.'
      url: https://arc.net
    - name: 'Velvetyne (Fricolage Grotesque)'
      role: 'Geometric sans with rounded terminals — softer than Inter, less institutional than Geist.'
      url: https://velvetyne.fr

dark-mode: native    # Fly's primary canvas is the violet-dark; cream panels are inversions, not a dark-mode toggle
---

## 1. Visual Theme & Atmosphere

Fly.io's home page opens with a Mackinac headline at roughly 72–96px on a
deep violet (`#24175b`) field — a treatment that reads more like the
cover of a design-quarterly than a deploy-platform landing. Mackinac's
high contrast and wedge-shaped terminals give the type a hand-cut feel
no Inter or Geist headline can replicate. The first impression is
**editorial PaaS** — a small-press literary magazine that happens to
run global edge infrastructure.

The page rhythms alternate between dark violet panels and creamy
`#fbf2e4` reading bands — a magazine-spread tonal flip. Fragment Mono
appears in pull-quotes, deploy commands, and the navigation tags,
giving the technical voice a typeset rather than terminal-y character.
The brand violet `#7c3aed` carries every primary action; the amber
`#f59e0b` is a single counterpoint accent used sparingly for highlights
and warmth.

The chromatic palette is unusually rich for infrastructure. The hero
canvas (`#24175b`) sits between Tailwind violet-900 and Plex Indigo —
saturated enough to feel chromatic, dark enough to read as evening
sky. The cream panel `#fbf2e4` flips the entire tonal relationship:
ink (`#15103d`) on cream, body type set in Fricolage Grotesque, with
Fragment Mono pull-quotes that read like typeset broadside fragments.

The mood is **deploy-platform-as-craft**. Where AWS feels industrial
and Vercel feels minimalist, Fly.io feels considered — the
infrastructure equivalent of a hand-bound book. Every typographic
decision (the wedge-serif display, the rounded-sans body, the angular
mono) reinforces the brief: deployment as a small-press act, not an
enterprise transaction.

**Key Characteristics**

- Deep violet canvas (`#24175b`) alternating with cream reading panels (`#fbf2e4`) — magazine tonal flip
- Mackinac wedge-serif for display — the only major PaaS with serif headlines
- Fricolage Grotesque body sans + Fragment Mono for code/quotes
- Brand violet `#7c3aed` (Tailwind violet-600) for primary action
- Amber `#f59e0b` as the sole counterpoint accent
- 6px button radius (tighter than 8px PaaS norm) — reinforces print feel
- 10px card radius, 14px hero shell — slightly tighter than industry default
- Generous vertical rhythm with magazine-spread cadence
- Pull-quotes set in Mackinac at 24px italic-feeling
- Mono labels for region tags, deploy commands, technical metadata

## 2. Color Palette & Roles

### Primary

- **Background** (`#24175b`) [→ `--fly-bg`]: deep violet hero canvas — the brand's defining surface
- **Background Deep** (`#15103d`): near-black violet — used for footer and full-bleed panels
- **Background Cream** (`#fbf2e4`): creamy off-white reading panel — Fly's tonal flip
- **Primary Text on Dark** (`#fbf2e4`): cream optical-white
- **Primary Text on Cream** (`#15103d`): near-black violet ink
- **Primary CTA Fill** (`#7c3aed`): brand violet

### Brand & Dark

- **Brand Violet** (`#7c3aed`) [Tailwind violet-600]: primary action
- **Brand Hover** (`#9061f5`): lighter on hover
- **Brand Pressed** (`#6929d4`): pressed state
- **Brand Deep** (`#5b21b6`): deepest violet — icon strokes, links on cream
- **Brand Glow** (`#7c3aed33`): 20% violet wash

### Accent

- **Lighter Violet** (`#a78bfa`): secondary emphasis, links on dark
- **Accent Hover** (`#c4b5fd`): hover state
- **Amber** (`#f59e0b`) [→ `--fly-accent-warm`]: warm counterpoint — the only non-violet brand colour
- **Amber Soft** (`#fbbf24`): softer amber
- **Brand Soft** (`#7c3aed1f`): 12% wash

### Interactive

- **Link on Dark** (`#a78bfa`): lighter violet
- **Link on Cream** (`#5b21b6`): deep violet
- **Link Hover** (`#c4b5fd`): brightened
- **Link Visited** (`#8b6cd9`): muted
- **Selected** (`#7c3aed26`): 15% violet wash
- **Disabled** (`#3a2f5f`)
- **Disabled Text** (`#6b5d8a`)

### Neutral Scale

#### On dark canvas

- **Text Heading** (`#fbf2e4`): cream optical-white
- **Text Body** (`#fbf2e4`): same cream
- **Text Muted** (`#a89dc8`): muted lavender
- **Text Soft** (`#867aa8`): softer lavender
- **Text Faint** (`#5b537a`): quaternary

#### On cream panel

- **Text Heading** (`#15103d`): near-black violet ink
- **Text Body** (`#2a1f4d`): mid-violet
- **Text Muted** (`#5b507a`): muted violet-grey

### Surface & Borders

- **Surface (dark)** (`#1f1748`): tinted purple panel
- **Surface (cream)** (`#fbf2e4`): same as bg-cream (cards float on cream)
- **Surface Cream Deep** (`#ede0c4`): nested cream panel
- **Border on Dark** (`#ffffff1a`): 10% white hairline
- **Border Soft on Dark** (`#ffffff0d`): 5% white
- **Border Strong on Dark** (`#ffffff33`): 20% emphasized
- **Border on Cream** (`#15103d33`): 20% violet ink
- **Border Brand** (`#7c3aed66`): 40% on focus

### Shadow Colors

Shadows are ink-tinted (using `#15103d`) at varying alpha — the violet undertone keeps depth chromatically continuous with the brand:

- **Ambient** (`rgba(0,0,0,0.25)`): low resting
- **Standard** (`rgba(15,16,61,0.4)`): card hover, ink-tinted
- **Elevated** (`rgba(15,16,61,0.55)`): popover, dropdown
- **Deep** (`rgba(15,16,61,0.7)`): modal
- **Glow** (`rgba(124,58,237,0.35)`): violet focus glow

### Semantic

- **Success** (`#34d399`): mint green
- **Success Bg** (`#0f3a2a`): dark mint surface
- **Warning** (`#f59e0b`): amber (also brand counterpoint)
- **Warning Bg** (`#3a2710`): dark amber surface
- **Danger** (`#f87171`): coral red
- **Danger Bg** (`#3a1818`)
- **Info** (`#a78bfa`): info uses lighter violet
- **Info Bg** (`#1f1748`)

## 3. Typography Rules

### Font Family

- **Display**: Mackinac (Production Type) — high-contrast wedge-serif, the brand's typographic spine
- **Body**: Fricolage Grotesque (Velvetyne) — geometric sans with rounded terminals
- **Mono**: Fragment Mono — angular variable-width monospace
- **OpenType**: `liga` and `dlig` enabled on Mackinac for typographic ligatures (ff, ffl, ct); `kern` enabled throughout; `tnum` and `zero` on Fragment Mono for technical alignment

### Hierarchy

| Role | Font | Size | Weight | Line Height | Letter Spacing | OT Features | Notes |
|------|------|------|--------|-------------|----------------|-------------|-------|
| display-hero | display | 96 | 500 | 1.0 | -0.03em | liga, dlig | hero only |
| display-large | display | 72 | 500 | 1.05 | -0.025em | liga | section opener |
| h1 | display | 56 | 500 | 1.08 | -0.022em | liga | page title |
| h2 | display | 42 | 500 | 1.12 | -0.02em | — | feature heading |
| h3 | display | 28 | 500 | 1.25 | -0.01em | — | sub-feature |
| h4 | display | 22 | 500 | 1.3 | -0.005em | — | card title |
| body-large | body | 19 | 400 | 1.55 | 0 | — | hero supporting |
| body | body | 17 | 400 | 1.55 | 0 | — | default — slightly larger than usual 16 |
| body-small | body | 15 | 400 | 1.5 | 0 | — | dense feature blocks |
| label-mono | mono | 13 | 400 | 1.3 | 0.04em | zero, tnum | eyebrow, region tag |
| button | body | 16 | 500 | 1.0 | 0 | — | primary/ghost |
| button-small | body | 14 | 500 | 1.0 | 0 | — | dense controls |
| link | body | 17 | 500 | 1.55 | 0 | — | inline link |
| quote | display | 24 | 400 | 1.35 | -0.005em | — | pull-quote in Mackinac |
| caption | body | 14 | 400 | 1.4 | 0 | — | image caption |
| caption-small | body | 13 | 400 | 1.35 | 0 | — | metadata |
| micro | body | 12 | 500 | 1.3 | 0.06em | — | badge label |
| code-body | mono | 14 | 400 | 1.6 | 0 | zero | inline + block code |
| code-bold | mono | 14 | 700 | 1.6 | 0 | zero | emphasized identifiers |
| code-label | mono | 12 | 400 | 1.3 | 0.05em | zero, tnum | deploy slugs |

### Principles

- **Mackinac is non-negotiable**: the wedge-serif is the brand's typographic spine — every display-level headline must use it
- **Weight discipline**: Mackinac stays at 500 (not 700) — keeps the display calm and editorial
- **Body 17px, not 16px**: Fly's body size is one step larger than the PaaS norm — matches the editorial reading rhythm
- **Tracking philosophy**: tight negative tracking (-0.02em to -0.03em) on display; neutral on body; positive (`0.04em` to `0.06em`) on mono labels
- **Three-family discipline**: Mackinac (serif display) + Fricolage (sans body) + Fragment Mono (mono) — never substitute any one of them
- **Pull-quotes in Mackinac**: 24px display-set quotes for blog and feature copy — typeset, not screen-read
- **Tabular numerals on metrics**: Fragment Mono with `tnum` for region pricing, latency, machine counts
- **OpenType ligatures**: `liga` and `dlig` on Mackinac for ff, fi, ct, st — these are part of the editorial feel

## 4. Component Stylings

### Buttons

**button-primary** — Violet
- Background: `#7c3aed`
- Text: `#ffffff` at 16/500 Fricolage
- Padding: 10px 18px
- Radius: 6 (tighter than 8px PaaS norm)
- Border: none
- Hover: bg → `#9061f5`, subtle 1.005× scale
- Active: bg → `#6929d4`
- Focus: 3px solid rgba(124,58,237,0.4) ring
- Use: primary CTA — "Sign up", "Deploy", "Try Fly"

**button-ghost** — Outlined on dark
- Background: transparent
- Text: `#fbf2e4` at 16/500
- Padding: 10px 18px
- Radius: 6
- Border: 1px solid rgba(255,255,255,0.2)
- Hover: border → rgba(255,255,255,0.35), bg → rgba(255,255,255,0.05)
- Use: secondary action on dark canvas

**button-cream** — Inverted CTA on dark
- Background: `#fbf2e4`
- Text: `#15103d` at 16/500
- Padding: 10px 18px
- Radius: 6
- Border: none
- Hover: bg → `#f4ead7`
- Use: alternative primary on dark — "Read the docs", "View pricing"

**button-danger**
- Background: transparent
- Text: `#f87171` at 16/500
- Padding: 10px 18px
- Radius: 6
- Border: 1px solid rgba(248,113,113,0.4)
- Hover: bg → rgba(248,113,113,0.08)
- Use: destructive action

### Cards

**card-dark** — On violet canvas
- Background: `#1f1748`
- Padding: 24px
- Radius: 10
- Border: 1px solid rgba(255,255,255,0.1)
- Shadow: ambient
- Use: feature card on dark sections

**card-cream** — On cream reading panel
- Background: `#fbf2e4`
- Padding: 24px
- Radius: 10
- Border: 1px solid rgba(15,16,61,0.15)
- Use: blog card, doc card, pricing tier

### Badges / Tags / Pills

**badge-tag-dark**
- Background: `#1f1748`
- Text: `#a78bfa` at 12/500 micro
- Padding: 2px 10px
- Radius: pill
- Use: tag, region label, status

**badge-mono** — Deploy region
- Background: transparent
- Text: `#a78bfa` at 12/400 mono
- Border: 1px solid rgba(255,255,255,0.15)
- Padding: 2px 8px
- Radius: 4
- Use: region pills (`iad`, `lhr`, `nrt`)

### Inputs / Forms

**input-text-dark**
- Background: `#15103d`
- Text: `#fbf2e4` at 17/400 Fricolage
- Placeholder: `#867aa8`
- Padding: 10px 14px
- Radius: 6
- Border: 1px solid rgba(255,255,255,0.15)
- Focus: border → `#7c3aed`, ring 3px solid rgba(124,58,237,0.4)

### Navigation

**nav-link**
- Background: transparent
- Text: `#a89dc8` at 15/500 Fricolage
- Padding: 8px 12px
- Hover: text → `#fbf2e4`
- Active: text → `#a78bfa`

### Decorative

**pull-quote**
- Set in Mackinac at 24px / 400, line-height 1.35
- Optional 4px violet `#7c3aed` left-border at 16px gap
- Used inside cream reading panels for editorial emphasis

**code-block-dark**
- Background: `#15103d`
- Text: `#fbf2e4` at code-body (14/400 Fragment Mono)
- Padding: 16px 20px
- Radius: 8
- Border: 1px solid rgba(255,255,255,0.08)
- Inline backticks render in `#a78bfa` on rgba(124,58,237,0.15) wash

## 5. Layout Principles

### Spacing System

- **Base unit**: 4px
- **Scale**: 2, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 96, 128, 160
- **Density observation**: Fly's grid is **editorial** — sections are separated by 120–160px (more than typical PaaS), feature blocks within sections at 32–48px

### Grid & Container

- **Page width**: 1200px max
- **Prose width**: 680px (blog, documentation, marketing body — narrow for editorial reading)
- **Hero treatment**: full-bleed violet canvas, content constrained to ~960px
- **Feature grid**: 3-col at desktop, 2-col at tablet, 1-col at mobile

### Whitespace Philosophy

- Whitespace functions as breathing room between editorial moments
- Section gaps are generous (120–160px) to support magazine-spread cadence
- Cream panels function as reading-rest — a tonal break between dense violet sections

### Section Cadence

- Hero (deep violet) → feature grid (dark surface) → testimonial (cream panel) → product detail (violet) → cream blog teaser → footer (deep violet)
- The violet/cream alternation is the layout signature
- Cream panels never share a section with violet panels — they take the whole section

## 6. Shapes & Radius Scale

| Tier | Px | Use |
|------|----|----|
| Micro | 2 | inline pills, mono region tags |
| Standard | 4 | small badges |
| Comfortable | 6 | buttons (Fly's tight default) |
| Relaxed | 10 | cards |
| Featured | 14 | hero shells, feature blocks |
| Large | 18 | signature illustrative panels |
| Pill | 9999 | status pills, avatars |

The 6px button radius is a deliberate departure from the 8px PaaS default — it pulls the controls toward print/typeset feel.

## 7. Depth & Elevation

| Level | Treatment | Use |
|-------|-----------|----|
| 0 | flat | hero copy on canvas |
| 1 | 1px translucent hairline | inline cards, code blocks |
| 2 | 1px hairline + ambient shadow | feature cards |
| 3 | standard shadow, ink-tinted | hover state |
| 4 | elevated ink-tinted | popover, dropdown |
| 5 | deep + violet ring glow | modal, command palette |

**Shadow Philosophy**: Fly's shadows tilt **ink-tinted** — using `#15103d` (the deepest violet) at varying alpha rather than pure black. This keeps the chromatic story continuous into the depth layer. Multi-layer shadows are used at level 4+ to soften edges. Depth is more often **panel-to-panel** (tonal contrast between violet and cream sections) than card-to-card; shadows are reserved for floating UI elements.

## 8. Interaction & Motion

### Easing

- **Standard**: `cubic-bezier(0.4, 0, 0.2, 1)` — default
- **Emphasized**: `cubic-bezier(0.2, 0, 0, 1)` — page transitions, modal enter
- **Decelerate**: `cubic-bezier(0, 0, 0.2, 1)` — tooltips

### Durations

- **Fast** (120ms): hover, focus
- **Standard** (240ms): card lift, button press
- **Slow** (400ms): modal enter, page transition

### Per-Component Recipes

- **Button hover**: bg colour transitions over 240ms standard ease; 1.005× scale via transform
- **Card hover**: shadow ambient → standard, border opacity 0.1 → 0.2, over 240ms
- **Link hover**: underline grows 0 → 1px over 120ms; text colour fades to brighter accent
- **Pull-quote enter**: opacity 0 → 1 + translateY 16px → 0 over 400ms emphasized when scrolled into view
- **Section transitions**: cream panel entry uses scaleY 0.98 → 1 + opacity 0 → 1 over 400ms emphasized

### Page Transitions

- Default: opacity 0 → 1 + translateY 12px → 0 over 400ms emphasized

### Reduced Motion

When `prefers-reduced-motion: reduce` is set:

- Section entry animations reduce to opacity-only fade
- Card hover scale removed
- Pull-quote scroll-triggered enter becomes instant
- Page enter translate removed

## 9. Accessibility & A11y

### Contrast Pairs

- **Cream `#fbf2e4` on `#24175b`**: 11.6:1 (AAA, all sizes)
- **Cream on `#15103d`**: 14.4:1 (AAA)
- **Ink `#15103d` on cream `#fbf2e4`**: 14.8:1 (AAA)
- **White on `#7c3aed`**: 5.2:1 (AA at body sizes)
- **Light violet `#a78bfa` link on dark canvas**: 7.4:1 (AAA)
- **Muted lavender `#a89dc8` on `#24175b`**: 5.8:1 (AA)
- **Brand-deep `#5b21b6` link on cream**: 8.6:1 (AAA)

### Focus Indicators

- Default on dark: 3px solid rgba(124,58,237,0.4) ring, no offset
- Default on cream: 3px solid rgba(124,58,237,0.5) ring, 2px offset
- Always visible

### ARIA Patterns

- **Combobox**: standard listbox pattern
- **Dialog**: aria-labelledby + aria-describedby; trap focus; ESC to close
- **Region pills**: aria-label spelling out the airport code (e.g., "Region: Frankfurt — fra")
- **Pull-quotes**: use `<blockquote>` with optional cite attribute

### Keyboard Navigation

- Tab order follows visual order
- Skip-link at page top
- Enter activates buttons; Enter on links
- Cmd/Ctrl+K for command palette (when present)
- Escape closes modals

### Screen Reader Hints

- Status pills always paired with aria-label
- Decorative pull-quote borders are `aria-hidden`
- Mono code uses `<code>` semantic; `<pre>` for blocks

### Reduced Motion

`prefers-reduced-motion: reduce` honored throughout — see §8.

## 10. Responsive Behavior

### Breakpoints

| Name | Min Width | Use |
|------|-----------|----|
| Mobile | — | default |
| Tablet | 640 | enlarged grids |
| Desktop | 1024 | full feature grid |
| Wide | 1200 | max page width |
| Ultra | 1536 | hero only |

### Touch Targets

- Minimum 44×44px for primary buttons
- Region mono pills expand hit-area to 32×24px

### Collapsing Strategy

- **Nav**: collapses to hamburger ≤ 768px
- **Feature grid**: 3-col → 2-col @ 1024 → 1-col @ 640
- **Hero**: display-hero (96px) reduces to 56px @ 640
- **Pull-quotes**: maintain Mackinac display but reduce 24 → 20 @ 640

### Image Behavior

- Hero illustrations + map visuals use SVG
- Logos lock at intrinsic size
- Region maps respond fluidly with viewport

## 11. Content & Voice

### Tone

Considered, slightly literary, technical-but-warm. Fly.io's marketing copy reads more like a craft-publication than a SaaS landing — sentences are full, verbs are precise, occasional turns toward the witty. The brand explicitly avoids both corporate jargon and dev-bro hype.

### Microcopy Patterns

- **Button verbs**: "Sign up", "Deploy", "Try Fly", "Read more", "Get started" — direct but unembellished
- **Error message recipe**: "[noun] [failed]: [reason]. [actionable next step]" — full sentences, not jargon-fragments
- **Success confirmations**: "[noun] [verb-past] in [region]" — "App deployed in iad"
- **Empty states**: short editorial sentences — "Nothing here yet. Spin up an app to see it here."

### CTA Verb Conventions

- Top-level: "Sign up" or "Get started"
- Product: "Deploy now" or "Try [feature]"
- Documentation: "Read the docs"
- Blog/editorial: "Read more"
- Sales: "Talk to us"

## 12. Dark Mode & Theming

Fly.io is **dark-as-default** — the violet canvas is the brand's primary surface, and the cream panels are an inversion within the same brand, not a separate "light mode." There is no light-mode toggle for the marketing site; the dashboard product runs the same chromatic palette throughout.

The cream `#fbf2e4` reading panels function as **inverted moments** within the dark brand:
- Page sections alternate violet → cream → violet (magazine-spread tonal flip)
- Cards and content within cream panels use the cream sub-token map (`text-cream-heading`, `text-cream-body`)
- The brand violet `#7c3aed` works on both surfaces; the deep violet `#5b21b6` is preferred for links on cream for contrast

If a true light-only mode were needed: hold `text-cream-heading` (`#15103d`) as primary text on `#fbf2e4` background, swap brand to `brand-deep` (`#5b21b6`) for primary CTAs.

## 13. Lineage & Influences

Fly.io is the only major PaaS that runs a wedge-serif display face. **Mackinac** by Production Type — a high-contrast 21st-century serif most commonly seen on small-press book covers and design-journal mastheads — is paired with **Fricolage Grotesque** (a geometric sans with rounded terminals) and **Fragment Mono** (an angular variable-width monospace). The chromatic identity is a violet-saturated near-black canvas that fades into cream reading panels — a high-contrast tonal flip borrowed from magazine spread design.

Where Railway uses eggplant and Render uses CMYK violet, Fly leans into the saturated indigo-violet of Plex's older "Plex Indigo" colour-way, modernised toward Tailwind's `violet-600`. The 6px button radius — tighter than the 8px PaaS norm — reinforces the editorial-print feel. The amber `#f59e0b` is a single counterpoint accent borrowed from sunlight-warmth gradient palettes.

- **Mackinac (Production Type)** — https://productiontype.com — wedge-serif display
- **Plain** — https://plain.com — editorial cream panels, restrained type-driven layouts
- **The Browser Company / Arc** — https://arc.net — cream-on-violet tonal flips, magazine cadence
- **Velvetyne (Fricolage Grotesque)** — https://velvetyne.fr — geometric sans with rounded terminals

## 14. Do's and Don'ts

### Do

- **Do** use Mackinac for every display headline — it is the brand's typographic spine
- **Do** alternate violet and cream panels for section transitions; that tonal flip is the layout signature
- **Do** set technical labels and deploy commands in Fragment Mono — it ties the developer copy to the editorial voice
- **Do** keep button radius at 6px (not 8px) — the tighter geometry is part of the print feel
- **Do** use 17px body (not 16px) — the slightly larger reading size matches the editorial rhythm
- **Do** use Mackinac for pull-quotes at 24px — typeset emphasis in editorial copy
- **Do** ink-tint shadows with `#15103d` — keeps depth chromatically continuous
- **Do** anchor body copy at `#fbf2e4` cream optical-white on dark, `#15103d` on cream
- **Do** use the amber `#f59e0b` as the only counterpoint accent
- **Do** honor `prefers-reduced-motion` — disable scroll-triggered enters

### Don't

- **Don't** swap Mackinac for any other serif (Lyon, Plex Serif, Source Serif) — Mackinac's wedge terminals are non-negotiable
- **Don't** pair the brand violet with cool blues or magentas; the warm amber `#f59e0b` is the only counterpoint
- **Don't** apply drop shadows to cards on cream panels; depth there is hairline-bordered, never elevation-shadow
- **Don't** use Inter for display headlines — Inter collapses Fly's voice into generic-PaaS register
- **Don't** flip to a light-only marketing site; the violet canvas is the brand
- **Don't** use 8px button radius — Fly is 6px
- **Don't** over-apply the cream — it functions as reading-rest, not as a primary surface
- **Don't** layer mono on long-form copy — Fragment Mono is for technical labels and pull-quote fragments
- **Don't** add italic to Mackinac — the brand's italic-feeling effect comes from optical adjustment, not style toggle
- **Don't** use 700 weight on Mackinac display — 500 is the calm editorial weight

## 15. Agent Prompt Guide

### Quick Color Reference

```
bg: #24175b
bg-deep: #15103d
bg-cream: #fbf2e4
text-on-dark: #fbf2e4
text-on-cream: #15103d
brand: #7c3aed
brand-hover: #9061f5
accent: #a78bfa
accent-warm: #f59e0b
border-on-dark: rgba(255,255,255,0.1)
on-brand: #ffffff
```

### Example Component Prompts

1. "Create a hero section: deep violet `#24175b` background, a 96px Mackinac display headline at 500 weight in `#fbf2e4` cream with -0.03em tracking and `liga, dlig` ligatures enabled, body-large 19px Fricolage subhead in `#a89dc8`. Add a primary violet button (`#7c3aed` fill, white text, 6px radius, 10px 18px padding) saying 'Sign up' and a ghost button 'Read the docs' (transparent, white text, 1px rgba(255,255,255,0.2) border)."

2. "Design a magazine-spread layout: section 1 deep violet (`#24175b`) with feature grid, section 2 cream `#fbf2e4` reading panel with 3 blog cards (cream `#fbf2e4` bg, 24px padding, 10px radius, 1px rgba(15,16,61,0.15) border, ink `#15103d` headlines in Mackinac at 28px, body in Fricolage 17px `#2a1f4d`)."

3. "Build a pull-quote component for a cream reading panel: Mackinac display at 24px, 400 weight, line-height 1.35, ink `#15103d` text, optional 4px `#7c3aed` violet left-border at 16px gap. Pull-quote text reads typeset rather than screen-read."

4. "Create a code block on dark canvas: `#15103d` background, 14px Fragment Mono `#fbf2e4` body text with `zero` slashed-zero feature, 16px 20px padding, 8px radius, 1px rgba(255,255,255,0.08) border. Inline backticks render in `#a78bfa` on a rgba(124,58,237,0.15) wash."

5. "Design a region pill: 1px rgba(255,255,255,0.15) border, 4px radius, 2px 8px padding, 12px Fragment Mono in `#a78bfa`. Add aria-label spelling the full region (e.g., 'Region: Frankfurt — fra')."

6. "Build a top navigation: deep violet `#24175b` background, Fly.io wordmark in cream Mackinac, nav links in Fricolage 15px at 500 weight in `#a89dc8` (hover `#fbf2e4`), right-side ghost 'Sign in' and primary 'Sign up' violet button at 6px radius."

### Iteration Guide

1. **Start with Mackinac** — if your display isn't a wedge-serif, you're not on Fly. Substitute Mackinac is a non-starter
2. **Layer the magazine cadence** — alternate deep violet sections with cream panels for the editorial rhythm
3. **Tighten button radius** — 6px, not 8px; this single detail pulls everything toward print
4. **Set body at 17px** — slightly larger reading size matches the literary voice
5. **Reserve amber** — `#f59e0b` is the single warm accent; never mix with red, magenta, or other warm hues
6. **Pull-quotes in Mackinac** — 24px display-set quotes inside cream panels for editorial emphasis
7. **Mono with `zero`** — Fragment Mono with slashed zero for region labels, deploy commands, technical metadata
8. **Ink-tint shadows** — `rgba(15,16,61,X)` not `rgba(0,0,0,X)`; the violet undertone is part of the chromatic story
Prose

1. Visual Theme & Atmosphere

Fly.io’s home page opens with a Mackinac headline at roughly 72–96px on a deep violet (#24175b) field — a treatment that reads more like the cover of a design-quarterly than a deploy-platform landing. Mackinac’s high contrast and wedge-shaped terminals give the type a hand-cut feel no Inter or Geist headline can replicate. The first impression is editorial PaaS — a small-press literary magazine that happens to run global edge infrastructure.

The page rhythms alternate between dark violet panels and creamy #fbf2e4 reading bands — a magazine-spread tonal flip. Fragment Mono appears in pull-quotes, deploy commands, and the navigation tags, giving the technical voice a typeset rather than terminal-y character. The brand violet #7c3aed carries every primary action; the amber #f59e0b is a single counterpoint accent used sparingly for highlights and warmth.

The chromatic palette is unusually rich for infrastructure. The hero canvas (#24175b) sits between Tailwind violet-900 and Plex Indigo — saturated enough to feel chromatic, dark enough to read as evening sky. The cream panel #fbf2e4 flips the entire tonal relationship: ink (#15103d) on cream, body type set in Fricolage Grotesque, with Fragment Mono pull-quotes that read like typeset broadside fragments.

The mood is deploy-platform-as-craft. Where AWS feels industrial and Vercel feels minimalist, Fly.io feels considered — the infrastructure equivalent of a hand-bound book. Every typographic decision (the wedge-serif display, the rounded-sans body, the angular mono) reinforces the brief: deployment as a small-press act, not an enterprise transaction.

Key Characteristics

  • Deep violet canvas (#24175b) alternating with cream reading panels (#fbf2e4) — magazine tonal flip
  • Mackinac wedge-serif for display — the only major PaaS with serif headlines
  • Fricolage Grotesque body sans + Fragment Mono for code/quotes
  • Brand violet #7c3aed (Tailwind violet-600) for primary action
  • Amber #f59e0b as the sole counterpoint accent
  • 6px button radius (tighter than 8px PaaS norm) — reinforces print feel
  • 10px card radius, 14px hero shell — slightly tighter than industry default
  • Generous vertical rhythm with magazine-spread cadence
  • Pull-quotes set in Mackinac at 24px italic-feeling
  • Mono labels for region tags, deploy commands, technical metadata

2. Color Palette & Roles

Primary

  • Background (#24175b) [→ --fly-bg]: deep violet hero canvas — the brand’s defining surface
  • Background Deep (#15103d): near-black violet — used for footer and full-bleed panels
  • Background Cream (#fbf2e4): creamy off-white reading panel — Fly’s tonal flip
  • Primary Text on Dark (#fbf2e4): cream optical-white
  • Primary Text on Cream (#15103d): near-black violet ink
  • Primary CTA Fill (#7c3aed): brand violet

Brand & Dark

  • Brand Violet (#7c3aed) [Tailwind violet-600]: primary action
  • Brand Hover (#9061f5): lighter on hover
  • Brand Pressed (#6929d4): pressed state
  • Brand Deep (#5b21b6): deepest violet — icon strokes, links on cream
  • Brand Glow (#7c3aed33): 20% violet wash

Accent

  • Lighter Violet (#a78bfa): secondary emphasis, links on dark
  • Accent Hover (#c4b5fd): hover state
  • Amber (#f59e0b) [→ --fly-accent-warm]: warm counterpoint — the only non-violet brand colour
  • Amber Soft (#fbbf24): softer amber
  • Brand Soft (#7c3aed1f): 12% wash

Interactive

  • Link on Dark (#a78bfa): lighter violet
  • Link on Cream (#5b21b6): deep violet
  • Link Hover (#c4b5fd): brightened
  • Link Visited (#8b6cd9): muted
  • Selected (#7c3aed26): 15% violet wash
  • Disabled (#3a2f5f)
  • Disabled Text (#6b5d8a)

Neutral Scale

On dark canvas

  • Text Heading (#fbf2e4): cream optical-white
  • Text Body (#fbf2e4): same cream
  • Text Muted (#a89dc8): muted lavender
  • Text Soft (#867aa8): softer lavender
  • Text Faint (#5b537a): quaternary

On cream panel

  • Text Heading (#15103d): near-black violet ink
  • Text Body (#2a1f4d): mid-violet
  • Text Muted (#5b507a): muted violet-grey

Surface & Borders

  • Surface (dark) (#1f1748): tinted purple panel
  • Surface (cream) (#fbf2e4): same as bg-cream (cards float on cream)
  • Surface Cream Deep (#ede0c4): nested cream panel
  • Border on Dark (#ffffff1a): 10% white hairline
  • Border Soft on Dark (#ffffff0d): 5% white
  • Border Strong on Dark (#ffffff33): 20% emphasized
  • Border on Cream (#15103d33): 20% violet ink
  • Border Brand (#7c3aed66): 40% on focus

Shadow Colors

Shadows are ink-tinted (using #15103d) at varying alpha — the violet undertone keeps depth chromatically continuous with the brand:

  • Ambient (rgba(0,0,0,0.25)): low resting
  • Standard (rgba(15,16,61,0.4)): card hover, ink-tinted
  • Elevated (rgba(15,16,61,0.55)): popover, dropdown
  • Deep (rgba(15,16,61,0.7)): modal
  • Glow (rgba(124,58,237,0.35)): violet focus glow

Semantic

  • Success (#34d399): mint green
  • Success Bg (#0f3a2a): dark mint surface
  • Warning (#f59e0b): amber (also brand counterpoint)
  • Warning Bg (#3a2710): dark amber surface
  • Danger (#f87171): coral red
  • Danger Bg (#3a1818)
  • Info (#a78bfa): info uses lighter violet
  • Info Bg (#1f1748)

3. Typography Rules

Font Family

  • Display: Mackinac (Production Type) — high-contrast wedge-serif, the brand’s typographic spine
  • Body: Fricolage Grotesque (Velvetyne) — geometric sans with rounded terminals
  • Mono: Fragment Mono — angular variable-width monospace
  • OpenType: liga and dlig enabled on Mackinac for typographic ligatures (ff, ffl, ct); kern enabled throughout; tnum and zero on Fragment Mono for technical alignment

Hierarchy

RoleFontSizeWeightLine HeightLetter SpacingOT FeaturesNotes
display-herodisplay965001.0-0.03emliga, dlighero only
display-largedisplay725001.05-0.025emligasection opener
h1display565001.08-0.022emligapage title
h2display425001.12-0.02emfeature heading
h3display285001.25-0.01emsub-feature
h4display225001.3-0.005emcard title
body-largebody194001.550hero supporting
bodybody174001.550default — slightly larger than usual 16
body-smallbody154001.50dense feature blocks
label-monomono134001.30.04emzero, tnumeyebrow, region tag
buttonbody165001.00primary/ghost
button-smallbody145001.00dense controls
linkbody175001.550inline link
quotedisplay244001.35-0.005empull-quote in Mackinac
captionbody144001.40image caption
caption-smallbody134001.350metadata
microbody125001.30.06embadge label
code-bodymono144001.60zeroinline + block code
code-boldmono147001.60zeroemphasized identifiers
code-labelmono124001.30.05emzero, tnumdeploy slugs

Principles

  • Mackinac is non-negotiable: the wedge-serif is the brand’s typographic spine — every display-level headline must use it
  • Weight discipline: Mackinac stays at 500 (not 700) — keeps the display calm and editorial
  • Body 17px, not 16px: Fly’s body size is one step larger than the PaaS norm — matches the editorial reading rhythm
  • Tracking philosophy: tight negative tracking (-0.02em to -0.03em) on display; neutral on body; positive (0.04em to 0.06em) on mono labels
  • Three-family discipline: Mackinac (serif display) + Fricolage (sans body) + Fragment Mono (mono) — never substitute any one of them
  • Pull-quotes in Mackinac: 24px display-set quotes for blog and feature copy — typeset, not screen-read
  • Tabular numerals on metrics: Fragment Mono with tnum for region pricing, latency, machine counts
  • OpenType ligatures: liga and dlig on Mackinac for ff, fi, ct, st — these are part of the editorial feel

4. Component Stylings

Buttons

button-primary — Violet

  • Background: #7c3aed
  • Text: #ffffff at 16/500 Fricolage
  • Padding: 10px 18px
  • Radius: 6 (tighter than 8px PaaS norm)
  • Border: none
  • Hover: bg → #9061f5, subtle 1.005× scale
  • Active: bg → #6929d4
  • Focus: 3px solid rgba(124,58,237,0.4) ring
  • Use: primary CTA — “Sign up”, “Deploy”, “Try Fly”

button-ghost — Outlined on dark

  • Background: transparent
  • Text: #fbf2e4 at 16/500
  • Padding: 10px 18px
  • Radius: 6
  • Border: 1px solid rgba(255,255,255,0.2)
  • Hover: border → rgba(255,255,255,0.35), bg → rgba(255,255,255,0.05)
  • Use: secondary action on dark canvas

button-cream — Inverted CTA on dark

  • Background: #fbf2e4
  • Text: #15103d at 16/500
  • Padding: 10px 18px
  • Radius: 6
  • Border: none
  • Hover: bg → #f4ead7
  • Use: alternative primary on dark — “Read the docs”, “View pricing”

button-danger

  • Background: transparent
  • Text: #f87171 at 16/500
  • Padding: 10px 18px
  • Radius: 6
  • Border: 1px solid rgba(248,113,113,0.4)
  • Hover: bg → rgba(248,113,113,0.08)
  • Use: destructive action

Cards

card-dark — On violet canvas

  • Background: #1f1748
  • Padding: 24px
  • Radius: 10
  • Border: 1px solid rgba(255,255,255,0.1)
  • Shadow: ambient
  • Use: feature card on dark sections

card-cream — On cream reading panel

  • Background: #fbf2e4
  • Padding: 24px
  • Radius: 10
  • Border: 1px solid rgba(15,16,61,0.15)
  • Use: blog card, doc card, pricing tier

Badges / Tags / Pills

badge-tag-dark

  • Background: #1f1748
  • Text: #a78bfa at 12/500 micro
  • Padding: 2px 10px
  • Radius: pill
  • Use: tag, region label, status

badge-mono — Deploy region

  • Background: transparent
  • Text: #a78bfa at 12/400 mono
  • Border: 1px solid rgba(255,255,255,0.15)
  • Padding: 2px 8px
  • Radius: 4
  • Use: region pills (iad, lhr, nrt)

Inputs / Forms

input-text-dark

  • Background: #15103d
  • Text: #fbf2e4 at 17/400 Fricolage
  • Placeholder: #867aa8
  • Padding: 10px 14px
  • Radius: 6
  • Border: 1px solid rgba(255,255,255,0.15)
  • Focus: border → #7c3aed, ring 3px solid rgba(124,58,237,0.4)

nav-link

  • Background: transparent
  • Text: #a89dc8 at 15/500 Fricolage
  • Padding: 8px 12px
  • Hover: text → #fbf2e4
  • Active: text → #a78bfa

Decorative

pull-quote

  • Set in Mackinac at 24px / 400, line-height 1.35
  • Optional 4px violet #7c3aed left-border at 16px gap
  • Used inside cream reading panels for editorial emphasis

code-block-dark

  • Background: #15103d
  • Text: #fbf2e4 at code-body (14/400 Fragment Mono)
  • Padding: 16px 20px
  • Radius: 8
  • Border: 1px solid rgba(255,255,255,0.08)
  • Inline backticks render in #a78bfa on rgba(124,58,237,0.15) wash

5. Layout Principles

Spacing System

  • Base unit: 4px
  • Scale: 2, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 96, 128, 160
  • Density observation: Fly’s grid is editorial — sections are separated by 120–160px (more than typical PaaS), feature blocks within sections at 32–48px

Grid & Container

  • Page width: 1200px max
  • Prose width: 680px (blog, documentation, marketing body — narrow for editorial reading)
  • Hero treatment: full-bleed violet canvas, content constrained to ~960px
  • Feature grid: 3-col at desktop, 2-col at tablet, 1-col at mobile

Whitespace Philosophy

  • Whitespace functions as breathing room between editorial moments
  • Section gaps are generous (120–160px) to support magazine-spread cadence
  • Cream panels function as reading-rest — a tonal break between dense violet sections

Section Cadence

  • Hero (deep violet) → feature grid (dark surface) → testimonial (cream panel) → product detail (violet) → cream blog teaser → footer (deep violet)
  • The violet/cream alternation is the layout signature
  • Cream panels never share a section with violet panels — they take the whole section

6. Shapes & Radius Scale

TierPxUse
Micro2inline pills, mono region tags
Standard4small badges
Comfortable6buttons (Fly’s tight default)
Relaxed10cards
Featured14hero shells, feature blocks
Large18signature illustrative panels
Pill9999status pills, avatars

The 6px button radius is a deliberate departure from the 8px PaaS default — it pulls the controls toward print/typeset feel.

7. Depth & Elevation

LevelTreatmentUse
0flathero copy on canvas
11px translucent hairlineinline cards, code blocks
21px hairline + ambient shadowfeature cards
3standard shadow, ink-tintedhover state
4elevated ink-tintedpopover, dropdown
5deep + violet ring glowmodal, command palette

Shadow Philosophy: Fly’s shadows tilt ink-tinted — using #15103d (the deepest violet) at varying alpha rather than pure black. This keeps the chromatic story continuous into the depth layer. Multi-layer shadows are used at level 4+ to soften edges. Depth is more often panel-to-panel (tonal contrast between violet and cream sections) than card-to-card; shadows are reserved for floating UI elements.

8. Interaction & Motion

Easing

  • Standard: cubic-bezier(0.4, 0, 0.2, 1) — default
  • Emphasized: cubic-bezier(0.2, 0, 0, 1) — page transitions, modal enter
  • Decelerate: cubic-bezier(0, 0, 0.2, 1) — tooltips

Durations

  • Fast (120ms): hover, focus
  • Standard (240ms): card lift, button press
  • Slow (400ms): modal enter, page transition

Per-Component Recipes

  • Button hover: bg colour transitions over 240ms standard ease; 1.005× scale via transform
  • Card hover: shadow ambient → standard, border opacity 0.1 → 0.2, over 240ms
  • Link hover: underline grows 0 → 1px over 120ms; text colour fades to brighter accent
  • Pull-quote enter: opacity 0 → 1 + translateY 16px → 0 over 400ms emphasized when scrolled into view
  • Section transitions: cream panel entry uses scaleY 0.98 → 1 + opacity 0 → 1 over 400ms emphasized

Page Transitions

  • Default: opacity 0 → 1 + translateY 12px → 0 over 400ms emphasized

Reduced Motion

When prefers-reduced-motion: reduce is set:

  • Section entry animations reduce to opacity-only fade
  • Card hover scale removed
  • Pull-quote scroll-triggered enter becomes instant
  • Page enter translate removed

9. Accessibility & A11y

Contrast Pairs

  • Cream #fbf2e4 on #24175b: 11.6:1 (AAA, all sizes)
  • Cream on #15103d: 14.4:1 (AAA)
  • Ink #15103d on cream #fbf2e4: 14.8:1 (AAA)
  • White on #7c3aed: 5.2:1 (AA at body sizes)
  • Light violet #a78bfa link on dark canvas: 7.4:1 (AAA)
  • Muted lavender #a89dc8 on #24175b: 5.8:1 (AA)
  • Brand-deep #5b21b6 link on cream: 8.6:1 (AAA)

Focus Indicators

  • Default on dark: 3px solid rgba(124,58,237,0.4) ring, no offset
  • Default on cream: 3px solid rgba(124,58,237,0.5) ring, 2px offset
  • Always visible

ARIA Patterns

  • Combobox: standard listbox pattern
  • Dialog: aria-labelledby + aria-describedby; trap focus; ESC to close
  • Region pills: aria-label spelling out the airport code (e.g., “Region: Frankfurt — fra”)
  • Pull-quotes: use <blockquote> with optional cite attribute

Keyboard Navigation

  • Tab order follows visual order
  • Skip-link at page top
  • Enter activates buttons; Enter on links
  • Cmd/Ctrl+K for command palette (when present)
  • Escape closes modals

Screen Reader Hints

  • Status pills always paired with aria-label
  • Decorative pull-quote borders are aria-hidden
  • Mono code uses <code> semantic; <pre> for blocks

Reduced Motion

prefers-reduced-motion: reduce honored throughout — see §8.

10. Responsive Behavior

Breakpoints

NameMin WidthUse
Mobiledefault
Tablet640enlarged grids
Desktop1024full feature grid
Wide1200max page width
Ultra1536hero only

Touch Targets

  • Minimum 44×44px for primary buttons
  • Region mono pills expand hit-area to 32×24px

Collapsing Strategy

  • Nav: collapses to hamburger ≤ 768px
  • Feature grid: 3-col → 2-col @ 1024 → 1-col @ 640
  • Hero: display-hero (96px) reduces to 56px @ 640
  • Pull-quotes: maintain Mackinac display but reduce 24 → 20 @ 640

Image Behavior

  • Hero illustrations + map visuals use SVG
  • Logos lock at intrinsic size
  • Region maps respond fluidly with viewport

11. Content & Voice

Tone

Considered, slightly literary, technical-but-warm. Fly.io’s marketing copy reads more like a craft-publication than a SaaS landing — sentences are full, verbs are precise, occasional turns toward the witty. The brand explicitly avoids both corporate jargon and dev-bro hype.

Microcopy Patterns

  • Button verbs: “Sign up”, “Deploy”, “Try Fly”, “Read more”, “Get started” — direct but unembellished
  • Error message recipe: “[noun] [failed]: [reason]. [actionable next step]” — full sentences, not jargon-fragments
  • Success confirmations: “[noun] [verb-past] in [region]” — “App deployed in iad”
  • Empty states: short editorial sentences — “Nothing here yet. Spin up an app to see it here.”

CTA Verb Conventions

  • Top-level: “Sign up” or “Get started”
  • Product: “Deploy now” or “Try [feature]”
  • Documentation: “Read the docs”
  • Blog/editorial: “Read more”
  • Sales: “Talk to us”

12. Dark Mode & Theming

Fly.io is dark-as-default — the violet canvas is the brand’s primary surface, and the cream panels are an inversion within the same brand, not a separate “light mode.” There is no light-mode toggle for the marketing site; the dashboard product runs the same chromatic palette throughout.

The cream #fbf2e4 reading panels function as inverted moments within the dark brand:

  • Page sections alternate violet → cream → violet (magazine-spread tonal flip)
  • Cards and content within cream panels use the cream sub-token map (text-cream-heading, text-cream-body)
  • The brand violet #7c3aed works on both surfaces; the deep violet #5b21b6 is preferred for links on cream for contrast

If a true light-only mode were needed: hold text-cream-heading (#15103d) as primary text on #fbf2e4 background, swap brand to brand-deep (#5b21b6) for primary CTAs.

13. Lineage & Influences

Fly.io is the only major PaaS that runs a wedge-serif display face. Mackinac by Production Type — a high-contrast 21st-century serif most commonly seen on small-press book covers and design-journal mastheads — is paired with Fricolage Grotesque (a geometric sans with rounded terminals) and Fragment Mono (an angular variable-width monospace). The chromatic identity is a violet-saturated near-black canvas that fades into cream reading panels — a high-contrast tonal flip borrowed from magazine spread design.

Where Railway uses eggplant and Render uses CMYK violet, Fly leans into the saturated indigo-violet of Plex’s older “Plex Indigo” colour-way, modernised toward Tailwind’s violet-600. The 6px button radius — tighter than the 8px PaaS norm — reinforces the editorial-print feel. The amber #f59e0b is a single counterpoint accent borrowed from sunlight-warmth gradient palettes.

14. Do’s and Don’ts

Do

  • Do use Mackinac for every display headline — it is the brand’s typographic spine
  • Do alternate violet and cream panels for section transitions; that tonal flip is the layout signature
  • Do set technical labels and deploy commands in Fragment Mono — it ties the developer copy to the editorial voice
  • Do keep button radius at 6px (not 8px) — the tighter geometry is part of the print feel
  • Do use 17px body (not 16px) — the slightly larger reading size matches the editorial rhythm
  • Do use Mackinac for pull-quotes at 24px — typeset emphasis in editorial copy
  • Do ink-tint shadows with #15103d — keeps depth chromatically continuous
  • Do anchor body copy at #fbf2e4 cream optical-white on dark, #15103d on cream
  • Do use the amber #f59e0b as the only counterpoint accent
  • Do honor prefers-reduced-motion — disable scroll-triggered enters

Don’t

  • Don’t swap Mackinac for any other serif (Lyon, Plex Serif, Source Serif) — Mackinac’s wedge terminals are non-negotiable
  • Don’t pair the brand violet with cool blues or magentas; the warm amber #f59e0b is the only counterpoint
  • Don’t apply drop shadows to cards on cream panels; depth there is hairline-bordered, never elevation-shadow
  • Don’t use Inter for display headlines — Inter collapses Fly’s voice into generic-PaaS register
  • Don’t flip to a light-only marketing site; the violet canvas is the brand
  • Don’t use 8px button radius — Fly is 6px
  • Don’t over-apply the cream — it functions as reading-rest, not as a primary surface
  • Don’t layer mono on long-form copy — Fragment Mono is for technical labels and pull-quote fragments
  • Don’t add italic to Mackinac — the brand’s italic-feeling effect comes from optical adjustment, not style toggle
  • Don’t use 700 weight on Mackinac display — 500 is the calm editorial weight

15. Agent Prompt Guide

Quick Color Reference

bg: #24175b
bg-deep: #15103d
bg-cream: #fbf2e4
text-on-dark: #fbf2e4
text-on-cream: #15103d
brand: #7c3aed
brand-hover: #9061f5
accent: #a78bfa
accent-warm: #f59e0b
border-on-dark: rgba(255,255,255,0.1)
on-brand: #ffffff

Example Component Prompts

  1. “Create a hero section: deep violet #24175b background, a 96px Mackinac display headline at 500 weight in #fbf2e4 cream with -0.03em tracking and liga, dlig ligatures enabled, body-large 19px Fricolage subhead in #a89dc8. Add a primary violet button (#7c3aed fill, white text, 6px radius, 10px 18px padding) saying ‘Sign up’ and a ghost button ‘Read the docs’ (transparent, white text, 1px rgba(255,255,255,0.2) border).”

  2. “Design a magazine-spread layout: section 1 deep violet (#24175b) with feature grid, section 2 cream #fbf2e4 reading panel with 3 blog cards (cream #fbf2e4 bg, 24px padding, 10px radius, 1px rgba(15,16,61,0.15) border, ink #15103d headlines in Mackinac at 28px, body in Fricolage 17px #2a1f4d).”

  3. “Build a pull-quote component for a cream reading panel: Mackinac display at 24px, 400 weight, line-height 1.35, ink #15103d text, optional 4px #7c3aed violet left-border at 16px gap. Pull-quote text reads typeset rather than screen-read.”

  4. “Create a code block on dark canvas: #15103d background, 14px Fragment Mono #fbf2e4 body text with zero slashed-zero feature, 16px 20px padding, 8px radius, 1px rgba(255,255,255,0.08) border. Inline backticks render in #a78bfa on a rgba(124,58,237,0.15) wash.”

  5. “Design a region pill: 1px rgba(255,255,255,0.15) border, 4px radius, 2px 8px padding, 12px Fragment Mono in #a78bfa. Add aria-label spelling the full region (e.g., ‘Region: Frankfurt — fra’).”

  6. “Build a top navigation: deep violet #24175b background, Fly.io wordmark in cream Mackinac, nav links in Fricolage 15px at 500 weight in #a89dc8 (hover #fbf2e4), right-side ghost ‘Sign in’ and primary ‘Sign up’ violet button at 6px radius.”

Iteration Guide

  1. Start with Mackinac — if your display isn’t a wedge-serif, you’re not on Fly. Substitute Mackinac is a non-starter
  2. Layer the magazine cadence — alternate deep violet sections with cream panels for the editorial rhythm
  3. Tighten button radius — 6px, not 8px; this single detail pulls everything toward print
  4. Set body at 17px — slightly larger reading size matches the literary voice
  5. Reserve amber#f59e0b is the single warm accent; never mix with red, magenta, or other warm hues
  6. Pull-quotes in Mackinac — 24px display-set quotes inside cream panels for editorial emphasis
  7. Mono with zero — Fragment Mono with slashed zero for region labels, deploy commands, technical metadata
  8. Ink-tint shadowsrgba(15,16,61,X) not rgba(0,0,0,X); the violet undertone is part of the chromatic story
Ship with this

Drop fly-io into your project, then ship the actual sections in an afternoon.

1 · install design
npx design-md add fly-io
2 · ship landing page
npx agentkit init --design fly-io
How AgentKit reads DESIGN.md
You might also like