{
  "$comment": "Fly.io brand tokens. Paths are relative to this site.",
  "site": {
    "name": "Fly.io Brand Guidelines",
    "description": "Logos, color, type & voice for Fly.io, with downloadable assets and a machine-readable API for agents.",
    "officialPage": "https://docs.fly.io/about/brand",
    "url": "https://branding.fly.dev",
    "skillInstall": "npx skills add superfly/skills --skill brand",
    "homepage": "https://fly.io"
  },
  "logos": [
    {
      "id": "logo-landscape",
      "label": "Color Landscape Logo",
      "kind": "logo-landscape",
      "variant": "color",
      "background": "light",
      "svg": "/brand/logo-landscape.svg",
      "png": "/brand/logo-landscape.png",
      "zip": "/brand/logo-landscape.zip"
    },
    {
      "id": "logo-landscape-inverted",
      "label": "Inverted Color Landscape Logo",
      "kind": "logo-landscape",
      "variant": "inverted",
      "background": "dark",
      "svg": "/brand/logo-landscape-inverted.svg",
      "png": "/brand/logo-landscape-inverted.png",
      "zip": "/brand/logo-landscape-inverted.zip"
    },
    {
      "id": "logo-landscape-dark",
      "label": "Dark (Monochrome) Landscape Logo",
      "kind": "logo-landscape",
      "variant": "dark",
      "background": "light",
      "svg": "/brand/logo-landscape-dark.svg",
      "png": "/brand/logo-landscape-dark.png",
      "zip": "/brand/logo-landscape-dark.zip"
    },
    {
      "id": "logo-landscape-light",
      "label": "Light (Monochrome) Landscape Logo",
      "kind": "logo-landscape",
      "variant": "light",
      "background": "dark",
      "svg": "/brand/logo-landscape-light.svg",
      "png": "/brand/logo-landscape-light.png",
      "zip": "/brand/logo-landscape-light.zip"
    },
    {
      "id": "logo-portrait",
      "label": "Color Portrait Logo",
      "kind": "logo-portrait",
      "variant": "color",
      "background": "light",
      "svg": "/brand/logo-portrait.svg",
      "png": "/brand/logo-portrait.png",
      "zip": "/brand/logo-portrait.zip"
    },
    {
      "id": "logo-portrait-inverted",
      "label": "Inverted Color Portrait Logo",
      "kind": "logo-portrait",
      "variant": "inverted",
      "background": "dark",
      "svg": "/brand/logo-portrait-inverted.svg",
      "png": "/brand/logo-portrait-inverted.png",
      "zip": "/brand/logo-portrait-inverted.zip"
    },
    {
      "id": "logo-portrait-dark",
      "label": "Dark (Monochrome) Portrait Logo",
      "kind": "logo-portrait",
      "variant": "dark",
      "background": "light",
      "svg": "/brand/logo-portrait-dark.svg",
      "png": "/brand/logo-portrait-dark.png",
      "zip": "/brand/logo-portrait-dark.zip"
    },
    {
      "id": "logo-portrait-light",
      "label": "Light (Monochrome) Portrait Logo",
      "kind": "logo-portrait",
      "variant": "light",
      "background": "dark",
      "svg": "/brand/logo-portrait-light.svg",
      "png": "/brand/logo-portrait-light.png",
      "zip": "/brand/logo-portrait-light.zip"
    },
    {
      "id": "brandmark",
      "label": "Color Brandmark",
      "kind": "brandmark",
      "variant": "color",
      "background": "light",
      "svg": "/brand/brandmark.svg",
      "png": "/brand/brandmark.png",
      "zip": "/brand/brandmark.zip"
    },
    {
      "id": "brandmark-inverted",
      "label": "Inverted Color Brandmark",
      "kind": "brandmark",
      "variant": "inverted",
      "background": "dark",
      "svg": "/brand/brandmark-inverted.svg",
      "png": "/brand/brandmark-inverted.png",
      "zip": "/brand/brandmark-inverted.zip"
    },
    {
      "id": "brandmark-dark",
      "label": "Dark (Monochrome) Brandmark",
      "kind": "brandmark",
      "variant": "dark",
      "background": "light",
      "svg": "/brand/brandmark-dark.svg",
      "png": "/brand/brandmark-dark.png",
      "zip": "/brand/brandmark-dark.zip"
    },
    {
      "id": "brandmark-light",
      "label": "Light (Monochrome) Brandmark",
      "kind": "brandmark",
      "variant": "light",
      "background": "dark",
      "svg": "/brand/brandmark-light.svg",
      "png": "/brand/brandmark-light.png",
      "zip": "/brand/brandmark-light.zip"
    }
  ],
  "logoKinds": {
    "logo-landscape": {
      "label": "Landscape Logo",
      "summary": "The primary logo. Use it whenever there’s room.",
      "width": 300,
      "height": 89,
      "png": [
        2000,
        593
      ]
    },
    "logo-portrait": {
      "label": "Portrait Logo",
      "summary": "For tall or square spaces where the landscape logo won’t fit.",
      "width": 114,
      "height": 156,
      "png": [
        1461,
        2000
      ]
    },
    "brandmark": {
      "label": "Brandmark",
      "summary": "The balloon on its own. Limited use: app icons, avatars, favicons.",
      "width": 167,
      "height": 151,
      "png": [
        1000,
        904
      ]
    }
  },
  "logoVariants": {
    "color": {
      "label": "Color",
      "suffix": "",
      "background": "light",
      "summary": "Default. Full-color mark with navy wordmark, for light backgrounds."
    },
    "inverted": {
      "label": "Inverted Color",
      "suffix": "-inverted",
      "background": "dark",
      "summary": "Full-color mark with white wordmark, for dark backgrounds."
    },
    "dark": {
      "label": "Dark (Monochrome)",
      "suffix": "-dark",
      "background": "light",
      "summary": "Single-color navy, for light backgrounds where color would clash or print is one-color."
    },
    "light": {
      "label": "Light (Monochrome)",
      "suffix": "-light",
      "background": "dark",
      "summary": "Single-color white, for photos and busy or low-contrast dark backgrounds."
    }
  },
  "logoRules": {
    "clearSpace": "Keep clear space on every side of at least ¼ of the logo’s height. No text, edges or other logos inside it.",
    "minimumSize": [
      {
        "kind": "Landscape Logo",
        "screen": "96 px wide",
        "print": "25 mm wide"
      },
      {
        "kind": "Portrait Logo",
        "screen": "48 px wide",
        "print": "13 mm wide"
      },
      {
        "kind": "Brandmark",
        "screen": "16 px wide",
        "print": "5 mm wide"
      }
    ],
    "dont": [
      "Recolor the logo, or swap its gradient for other colors.",
      "Stretch, squash, skew or rotate it.",
      "Add shadows, outlines, glows or other effects.",
      "Rearrange or resize the balloon relative to the wordmark.",
      "Retype the wordmark in another font.",
      "Place the color logo on busy photos or low-contrast backgrounds. Use a monochrome version."
    ]
  },
  "balloonMark": {
    "title": "Balloon on Its Own",
    "summary": "For square & round spaces where even the brandmark is too busy: social avatars, app & workspace icons.",
    "svg": "/brand/balloon-square.svg",
    "png": "/brand/balloon-square.png",
    "size": 1024,
    "field": "#AD80EF",
    "ink": "#24175B",
    "box": {
      "left": 29.4,
      "top": 19.3,
      "width": 41.1,
      "height": 61.1
    },
    "rules": [
      "Center the balloon in the square. It fills about 60% of the height & 40% of the width.",
      "Keep at least 19% of the square clear above & below the balloon, & 29% on each side.",
      "Use one flat field color. The default is balloon-lilac (#AD80EF), with the balloon in ink & white.",
      "It’s safe in a circular crop: the balloon sits inside the inner 75% of the circle."
    ],
    "dont": [
      "Scale the balloon up until it touches or crowds the edges.",
      "Put it on photos, gradients or busy illustration.",
      "Add the wordmark, a border or a second shape inside the square."
    ]
  },
  "partnerRules": {
    "unit": "x = the height of the Fly.io balloon in the lockup.",
    "spacing": [
      "Separate the two logos by 1x. With a divider, leave ½x on each side of it.",
      "The divider is a 1 px line, 1x tall, in the logo’s own color at 30% opacity (ink on light, white on dark).",
      "Center both logos vertically on the same axis.",
      "Size the partner logo so it looks the same weight as the Fly.io logo: no taller than 1x, & no wider than the Fly.io logo.",
      "Keep ½x of clear space around the whole lockup."
    ],
    "match": "Match formats: full logo next to full logo, symbol next to symbol. Use the brandmark only when every brand in the row is shown as a symbol.",
    "do": [
      "Use the color or monochrome treatment that suits the background, & give the partner the same treatment.",
      "Put Fly.io first (left) on Fly.io’s properties, & follow the partner’s lead on theirs.",
      "Get written approval for any co-branded material (see Usage Terms)."
    ],
    "dont": [
      "Merge the logos into a single mark, or share a letter or shape between them.",
      "Let the partner logo dominate, or shrink Fly.io to fit.",
      "Use “+” or “&” glyphs as separators. Use space or a divider line.",
      "Imply a partnership or endorsement that hasn’t been agreed in writing."
    ]
  },
  "brandKit": {
    "href": "/brand/fly-brand-kit.zip",
    "label": "Fly.io Brand Kit",
    "contents": "All 12 logos & the lone balloon, as SVG & PNG"
  },
  "colors": {
    "logo": [
      {
        "name": "logo-ink",
        "hex": "#24175B",
        "note": "Wordmark & outlines"
      },
      {
        "name": "logo-indigo",
        "hex": "#5046E4",
        "note": "Balloon gradient, start"
      },
      {
        "name": "logo-violet",
        "hex": "#996BEC",
        "note": "Balloon gradient, middle"
      },
      {
        "name": "logo-lilac",
        "hex": "#BA7BF0",
        "note": "Balloon gradient, end"
      }
    ],
    "core": [
      {
        "name": "navy",
        "hex": "#281950",
        "note": "Signature dark"
      },
      {
        "name": "peacoat",
        "hex": "#171434",
        "note": "Deepest background"
      },
      {
        "name": "droplet",
        "hex": "#C9DFFD",
        "note": "Cool highlight"
      },
      {
        "name": "balloon-lilac",
        "hex": "#AD80EF",
        "note": "Field behind the lone balloon"
      }
    ],
    "scales": [
      {
        "name": "navy",
        "description": "Primary text & dark surfaces.",
        "swatches": [
          {
            "name": "navy-50",
            "hex": "#F9F9FD"
          },
          {
            "name": "navy-100",
            "hex": "#F4F3FB"
          },
          {
            "name": "navy-200",
            "hex": "#E7E6F4"
          },
          {
            "name": "navy-300",
            "hex": "#D4CEEA"
          },
          {
            "name": "navy-400",
            "hex": "#A39AC1"
          },
          {
            "name": "navy-500",
            "hex": "#756B93"
          },
          {
            "name": "navy-600",
            "hex": "#564C73"
          },
          {
            "name": "navy-700",
            "hex": "#42385F"
          },
          {
            "name": "navy-800",
            "hex": "#282045"
          },
          {
            "name": "navy-900",
            "hex": "#22183C"
          },
          {
            "name": "navy-950",
            "hex": "#191034"
          }
        ]
      },
      {
        "name": "violet",
        "description": "Accent: links, highlights & calls to action.",
        "swatches": [
          {
            "name": "violet-50",
            "hex": "#F5F3FF"
          },
          {
            "name": "violet-100",
            "hex": "#EDE9FE"
          },
          {
            "name": "violet-200",
            "hex": "#DDD6FE"
          },
          {
            "name": "violet-300",
            "hex": "#C4B5FD"
          },
          {
            "name": "violet-400",
            "hex": "#A78BFA"
          },
          {
            "name": "violet-500",
            "hex": "#8B5CF6"
          },
          {
            "name": "violet-600",
            "hex": "#7C3AED"
          },
          {
            "name": "violet-700",
            "hex": "#6D28D9"
          },
          {
            "name": "violet-800",
            "hex": "#5B21B6"
          },
          {
            "name": "violet-900",
            "hex": "#4C1D95"
          },
          {
            "name": "violet-950",
            "hex": "#2E1065"
          }
        ]
      },
      {
        "name": "purple",
        "description": "Secondary accent, used sparingly.",
        "swatches": [
          {
            "name": "purple-50",
            "hex": "#FAF5FF"
          },
          {
            "name": "purple-100",
            "hex": "#F6E7FF"
          },
          {
            "name": "purple-200",
            "hex": "#EDD4FE"
          },
          {
            "name": "purple-300",
            "hex": "#DFB2FC"
          },
          {
            "name": "purple-400",
            "hex": "#CA7FF8"
          },
          {
            "name": "purple-500",
            "hex": "#B54FF3"
          },
          {
            "name": "purple-600",
            "hex": "#A02BE4"
          },
          {
            "name": "purple-700",
            "hex": "#8919C9"
          },
          {
            "name": "purple-800",
            "hex": "#731CA5"
          },
          {
            "name": "purple-900",
            "hex": "#5D1985"
          }
        ]
      },
      {
        "name": "gray",
        "description": "Cool neutrals for UI chrome, borders & muted text.",
        "swatches": [
          {
            "name": "gray-50",
            "hex": "#F8F9FC"
          },
          {
            "name": "gray-100",
            "hex": "#F1F2F9"
          },
          {
            "name": "gray-200",
            "hex": "#E1E4EF"
          },
          {
            "name": "gray-300",
            "hex": "#CCD0E0"
          },
          {
            "name": "gray-400",
            "hex": "#9698B6"
          },
          {
            "name": "gray-500",
            "hex": "#676B89"
          },
          {
            "name": "gray-600",
            "hex": "#4C4E67"
          },
          {
            "name": "gray-700",
            "hex": "#373953"
          },
          {
            "name": "gray-800",
            "hex": "#202237"
          },
          {
            "name": "gray-900",
            "hex": "#121226"
          }
        ]
      }
    ],
    "status": [
      {
        "name": "success",
        "description": "emerald · done & healthy",
        "swatches": [
          {
            "name": "emerald-50",
            "hex": "#ECFDF5"
          },
          {
            "name": "emerald-100",
            "hex": "#D1FAE5"
          },
          {
            "name": "emerald-200",
            "hex": "#A7F3D0"
          },
          {
            "name": "emerald-300",
            "hex": "#6EE7B7"
          },
          {
            "name": "emerald-400",
            "hex": "#34D399"
          },
          {
            "name": "emerald-500",
            "hex": "#10B981"
          },
          {
            "name": "emerald-600",
            "hex": "#059669"
          },
          {
            "name": "emerald-700",
            "hex": "#047857"
          },
          {
            "name": "emerald-800",
            "hex": "#065F46"
          },
          {
            "name": "emerald-900",
            "hex": "#064E3B"
          },
          {
            "name": "emerald-950",
            "hex": "#022C22"
          }
        ]
      },
      {
        "name": "info",
        "description": "blue · worth knowing",
        "swatches": [
          {
            "name": "blue-50",
            "hex": "#EFF6FF"
          },
          {
            "name": "blue-100",
            "hex": "#DBEAFE"
          },
          {
            "name": "blue-200",
            "hex": "#BFDBFE"
          },
          {
            "name": "blue-300",
            "hex": "#93C5FD"
          },
          {
            "name": "blue-400",
            "hex": "#60A5FA"
          },
          {
            "name": "blue-500",
            "hex": "#3B82F6"
          },
          {
            "name": "blue-600",
            "hex": "#2563EB"
          },
          {
            "name": "blue-700",
            "hex": "#1D4ED8"
          },
          {
            "name": "blue-800",
            "hex": "#1E40AF"
          },
          {
            "name": "blue-900",
            "hex": "#1E3A8A"
          },
          {
            "name": "blue-950",
            "hex": "#172554"
          }
        ]
      },
      {
        "name": "warning",
        "description": "amber · needs attention",
        "swatches": [
          {
            "name": "amber-50",
            "hex": "#FFFBEB"
          },
          {
            "name": "amber-100",
            "hex": "#FEF3C7"
          },
          {
            "name": "amber-200",
            "hex": "#FDE68A"
          },
          {
            "name": "amber-300",
            "hex": "#FCD34D"
          },
          {
            "name": "amber-400",
            "hex": "#FBBF24"
          },
          {
            "name": "amber-500",
            "hex": "#F59E0B"
          },
          {
            "name": "amber-600",
            "hex": "#D97706"
          },
          {
            "name": "amber-700",
            "hex": "#B45309"
          },
          {
            "name": "amber-800",
            "hex": "#92400E"
          },
          {
            "name": "amber-900",
            "hex": "#78350F"
          },
          {
            "name": "amber-950",
            "hex": "#451A03"
          }
        ]
      },
      {
        "name": "error",
        "description": "red · something failed",
        "swatches": [
          {
            "name": "red-50",
            "hex": "#FEF2F2"
          },
          {
            "name": "red-100",
            "hex": "#FEE2E2"
          },
          {
            "name": "red-200",
            "hex": "#FECACA"
          },
          {
            "name": "red-300",
            "hex": "#FCA5A5"
          },
          {
            "name": "red-400",
            "hex": "#F87171"
          },
          {
            "name": "red-500",
            "hex": "#EF4444"
          },
          {
            "name": "red-600",
            "hex": "#DC2626"
          },
          {
            "name": "red-700",
            "hex": "#B91C1C"
          },
          {
            "name": "red-800",
            "hex": "#991B1B"
          },
          {
            "name": "red-900",
            "hex": "#7F1D1D"
          },
          {
            "name": "red-950",
            "hex": "#450A0A"
          }
        ]
      }
    ],
    "pairings": [
      {
        "fg": "#22183C",
        "bg": "#FFFFFF",
        "label": "Body text on white",
        "fgName": "navy-900",
        "bgName": "white",
        "contrast": 16.61
      },
      {
        "fg": "#FFFFFF",
        "bg": "#7C3AED",
        "label": "Button label on violet",
        "fgName": "white",
        "bgName": "violet-600",
        "contrast": 5.7
      },
      {
        "fg": "#6D28D9",
        "bg": "#FFFFFF",
        "label": "Link on white",
        "fgName": "violet-700",
        "bgName": "white",
        "contrast": 7.1
      },
      {
        "fg": "#F4F3FB",
        "bg": "#171434",
        "label": "Body text on peacoat",
        "fgName": "navy-100",
        "bgName": "peacoat",
        "contrast": 16.07
      },
      {
        "fg": "#A78BFA",
        "bg": "#171434",
        "label": "Link on peacoat",
        "fgName": "violet-400",
        "bgName": "peacoat",
        "contrast": 6.51
      },
      {
        "fg": "#676B89",
        "bg": "#F8F9FC",
        "label": "Muted text on gray-50",
        "fgName": "gray-500",
        "bgName": "gray-50",
        "contrast": 4.94
      }
    ]
  },
  "typography": {
    "typefaces": [
      {
        "name": "Mackinac",
        "role": "Display",
        "use": "Headlines & section titles, in Medium (500) with tight tracking. Bold only for rare emphasis.",
        "cssVar": "--font-heading",
        "className": "font-heading",
        "weights": [
          "500",
          "500 italic",
          "700",
          "700 italic"
        ],
        "files": [
          "mackinac-medium.woff2",
          "mackinac-medium-italic.woff2",
          "mackinac-bold.woff2",
          "mackinac-bold-italic.woff2"
        ],
        "license": "Commercial license. Web use on Fly.io properties only; ask the brand team before using it elsewhere.",
        "source": null,
        "sample": "Computers for agents"
      },
      {
        "name": "Fricolage Grotesque",
        "role": "Text",
        "use": "Body copy, UI labels, buttons & navigation. Variable weight 100–900.",
        "cssVar": "--font-sans",
        "className": "font-sans",
        "weights": [
          "100–900"
        ],
        "files": [
          "fricolage-grotesque.var.woff2"
        ],
        "license": "Served as a web font on Fly.io properties. Ask the brand team for desktop files.",
        "source": null,
        "sample": "Run your app close to your users."
      },
      {
        "name": "Fragment Mono",
        "role": "Code",
        "use": "Commands, code, file paths, hex values & technical labels.",
        "cssVar": "--font-mono",
        "className": "font-mono",
        "weights": [
          "400",
          "400 italic"
        ],
        "files": [
          "fragment-mono-regular.woff2",
          "fragment-mono-italic.woff2"
        ],
        "license": "SIL Open Font License. Free to use anywhere.",
        "source": "https://fonts.google.com/specimen/Fragment+Mono",
        "sample": "fly launch && fly deploy"
      }
    ],
    "scale": [
      {
        "token": "6.5xl",
        "size": "4rem",
        "px": 64,
        "lineHeight": 1.25,
        "font": "heading",
        "use": "Hero"
      },
      {
        "token": "5xl",
        "size": "3rem",
        "px": 48,
        "lineHeight": 1.25,
        "font": "heading",
        "use": "Page title"
      },
      {
        "token": "4xl",
        "size": "2.25rem",
        "px": 36,
        "lineHeight": 1.325,
        "font": "heading",
        "use": "Section title"
      },
      {
        "token": "2.5xl",
        "size": "1.625rem",
        "px": 26,
        "lineHeight": 1.325,
        "font": "heading",
        "use": "Subsection"
      },
      {
        "token": "xl",
        "size": "1.28125rem",
        "px": 20.5,
        "lineHeight": 1.6,
        "font": "sans",
        "use": "Lead paragraph"
      },
      {
        "token": "base",
        "size": "1.0625rem",
        "px": 17,
        "lineHeight": 1.6,
        "font": "sans",
        "use": "Body"
      },
      {
        "token": "sm",
        "size": "0.90625rem",
        "px": 14.5,
        "lineHeight": 1.6,
        "font": "sans",
        "use": "UI & captions"
      },
      {
        "token": "xs",
        "size": "0.75rem",
        "px": 12,
        "lineHeight": 1.6,
        "font": "mono",
        "use": "Labels & metadata"
      }
    ],
    "heroTitle": {
      "spec": [
        {
          "part": "Face",
          "value": "Mackinac Medium (500)"
        },
        {
          "part": "Size",
          "value": "48 px on phones, up to 72 px"
        },
        {
          "part": "Tracking",
          "value": "−0.04em"
        },
        {
          "part": "Leading",
          "value": "1.1–1.15"
        },
        {
          "part": "Color",
          "value": "#2e2e2e or navy-900; an optional violet-600 lead line"
        },
        {
          "part": "Underline",
          "value": "12 px tall, the full width of the phrase, sitting on the baseline. Gradient emerald-400 → violet-600, top to bottom."
        }
      ],
      "underline": "/brand/scribble-underline.svg",
      "rules": [
        "Underline the payoff only: the last 1–4 words, the part that makes the claim.",
        "One underline per page, on the hero headline. Never on section titles or body copy.",
        "Wrap the phrase in an inline-block so the underline stretches to exactly its width.",
        "Keep the line short enough not to break; if the payoff wraps, rewrite the headline.",
        "Don’t recolor the gradient, animate it, or swap in a straight CSS underline."
      ]
    },
    "pairings": [
      {
        "id": "hero",
        "title": "Page Hero",
        "use": "Landing pages & the top of any page that needs to sell.",
        "layers": [
          "Mackinac Medium, 48–72 px, tracking −0.04em, leading 1.1",
          "Fricolage Grotesque Regular, 18–20 px, muted",
          "Fricolage Grotesque Medium, 14.5 px, buttons"
        ]
      },
      {
        "id": "section",
        "title": "Section Header",
        "use": "Breaking a long page into chapters.",
        "layers": [
          "Fricolage Grotesque Bold, 13 px, uppercase, tracking +0.05em, violet-600",
          "Mackinac Medium, 26–36 px, tracking −0.025em",
          "Fricolage Grotesque Regular, 17 px, muted"
        ]
      },
      {
        "id": "article",
        "title": "Article",
        "use": "Blog posts & long-form writing.",
        "layers": [
          "Mackinac Medium, 36 px, tracking −0.025em",
          "Fricolage Grotesque Regular, 14.5 px, byline",
          "Fricolage Grotesque Regular, 17 px / 1.6, max 68 characters",
          "Fragment Mono, 0.875 em, inline code"
        ]
      },
      {
        "id": "docs",
        "title": "Docs",
        "use": "Technical documentation, where scanning beats mood.",
        "layers": [
          "Fricolage Grotesque Semibold, 20 px (sans headings in docs)",
          "Fricolage Grotesque Regular, 17 px",
          "Fragment Mono, 13 px, code block"
        ]
      },
      {
        "id": "ui",
        "title": "Product UI",
        "use": "Dashboards, tables & forms. No serif at all.",
        "layers": [
          "Fricolage Grotesque Semibold, 14.5 px, labels",
          "Fricolage Grotesque Medium, 24 px, tabular figures",
          "Fragment Mono, 12 px, IDs & regions"
        ]
      },
      {
        "id": "dark",
        "title": "On Dark",
        "use": "Peacoat & navy surfaces: footers, CTAs, terminals.",
        "layers": [
          "Mackinac Medium, white",
          "Fricolage Grotesque Regular, navy-200",
          "Fragment Mono, emerald-400 prompt"
        ]
      }
    ],
    "rules": [
      {
        "title": "Hierarchy",
        "rules": [
          "Mackinac for headlines, Fricolage Grotesque for everything you read or click, Fragment Mono for anything you type or copy.",
          "One Mackinac headline per block. Use at most two Mackinac sizes in a single view.",
          "In docs & product UI, headings are Fricolage Grotesque Semibold. Mackinac is for marketing & editorial.",
          "Never use more than these three families, & never substitute another one to match a partner."
        ]
      },
      {
        "title": "Weights",
        "rules": [
          "Mackinac: Medium (500) for every headline & section title. Bold (700) only for rare emphasis, & never italic.",
          "Fricolage Grotesque: Regular (400) for body, Medium (500) for buttons & labels, Semibold (600) for emphasis & UI headings.",
          "Fragment Mono: Regular only. Never bold mono; set it apart with color or a background instead."
        ]
      },
      {
        "title": "Size & Measure",
        "rules": [
          "Body text is 17 px at 1.6 line height. Don’t go below 14.5 px for anything people read.",
          "Keep lines between 45 & 75 characters; 68 is the sweet spot.",
          "Headlines get tighter leading: 1.1 at 48 px & up, 1.25–1.3 below.",
          "Mackinac starts at 19 px. Below that, use Fricolage Grotesque."
        ]
      },
      {
        "title": "Case & Tracking",
        "rules": [
          "Title Case for headings & buttons, sentence case for paragraphs & marketing sublines.",
          "Eyebrows & small labels: Fricolage Grotesque Bold, 11–13 px, uppercase, tracked +0.05em, in violet-600 or purple-600. Three words or fewer.",
          "Mackinac headings are tracked −0.025em (+0.025em word spacing) at every size; hero titles go to −0.04em. Never letterspace lowercase text."
        ]
      },
      {
        "title": "Numbers & Code",
        "rules": [
          "Use tabular figures in tables, prices & anything that updates.",
          "Put a non-breaking space between number & unit: 100 GB, 500 ms, 8 vCPU.",
          "Inline code is Fragment Mono at 0.875em with a subtle background. Commands in blocks get a $ prompt that isn’t selectable."
        ]
      },
      {
        "title": "Color",
        "rules": [
          "Headings are navy (#281950) on light & white on dark. Body text is navy-900 on light & navy-100 on dark; secondary text gray-500 or navy-400.",
          "Links are violet-700 (violet-400 on dark) & underlined in running text.",
          "No gradient text, no colored headlines beyond navy & white."
        ]
      },
      {
        "title": "Typesetting",
        "rules": [
          "Curly quotes (“ ”, ’), real ellipses (…), en dashes for ranges (2–4), em dashes sparingly.",
          "Balance headlines & avoid widows: text-wrap: balance for headings, pretty for paragraphs.",
          "Let the browser render real italics & bolds from the font files. Never fake them with transforms or strokes."
        ]
      }
    ]
  },
  "gradients": {
    "named": [
      {
        "name": "Balloon",
        "css": "linear-gradient(135deg, #5046E4, #996BEC 55%, #BA7BF0)",
        "stops": "logo-indigo → logo-violet → logo-lilac",
        "use": "Brand moments: the logo, avatars, a single hero accent. Never behind text."
      },
      {
        "name": "Violet CTA",
        "css": "linear-gradient(to bottom right, #A02BE4, transparent, #4F46E5) #7C3AED",
        "stops": "purple-600 → transparent → indigo-600 over violet-600",
        "use": "The marketing call to action. At most one per page.",
        "text": "#FFFFFF"
      },
      {
        "name": "Violet Dark",
        "css": "linear-gradient(to bottom right, #731CA5, #5B21B6, #4C1D95)",
        "stops": "purple-800 → violet-800 → violet-900",
        "use": "Dark promo blocks & feature panels with white text.",
        "text": "#FFFFFF"
      },
      {
        "name": "Violet Pale",
        "css": "linear-gradient(to bottom right, #FAF5FF, #EDE9FE, rgb(199 210 254 / 0.5))",
        "stops": "purple-50 → violet-100 → indigo-200 at 50%",
        "use": "Light panels & cards with navy text.",
        "text": "#22183C"
      },
      {
        "name": "Pastel Sky",
        "css": "linear-gradient(to right, #7DD3FC, #A5B4FC, #F9A8D4)",
        "stops": "sky-300 → indigo-300 → pink-300",
        "use": "Thin accent lines & dividers. At 10% opacity, a soft section wash. Matches the hero skies."
      },
      {
        "name": "Scrim",
        "css": "linear-gradient(to top, rgb(34 24 60 / 0.9), rgb(34 24 60 / 0.7), rgb(34 24 60 / 0.25))",
        "stops": "navy-900 at 90% → 70% → 25%",
        "use": "Under text on images & illustrations. Rises from the edge the text sits on.",
        "image": true
      }
    ],
    "mesh": [
      {
        "name": "Section",
        "file": "/gradients/section.webp",
        "use": "Large page sections behind navy text",
        "css": "radial-gradient(54% 66% at 5% 10%, #D2FCF3, transparent), radial-gradient(36% 42% at 65% 5%, #E6DCFE, transparent), radial-gradient(42% 54% at 95% 25%, #FED6F4, transparent), radial-gradient(48% 60% at 5% 85%, #FFD3F3, transparent), radial-gradient(30% 36% at 45% 100%, #E8E1FD, transparent), radial-gradient(48% 60% at 98% 80%, #D2FCF3, transparent), #FFFFFF"
      },
      {
        "name": "Machines",
        "file": "/gradients/machines.webp",
        "use": "Product sections, light & airy",
        "css": "radial-gradient(36% 66% at 5% 25%, #C5FFFA, transparent), radial-gradient(26% 36% at 42% 8%, #FDD9E3, transparent), radial-gradient(36% 54% at 82% 15%, #B6E2FE, transparent), radial-gradient(42% 54% at 10% 95%, #B9E5FF, transparent), radial-gradient(26% 36% at 55% 98%, #FDDDE6, transparent), radial-gradient(36% 54% at 95% 75%, #C5FFFA, transparent), #FFFFFF"
      },
      {
        "name": "Support",
        "file": "/gradients/support.webp",
        "use": "Help & support panels",
        "css": "radial-gradient(48% 60% at 15% 12%, #C8EBFF, transparent), radial-gradient(30% 42% at 55% 10%, #F3EDFD, transparent), radial-gradient(42% 54% at 92% 25%, #FFDAE4, transparent), radial-gradient(48% 60% at 5% 88%, #FFD8E2, transparent), radial-gradient(30% 36% at 45% 95%, #F1EEFD, transparent), radial-gradient(48% 60% at 90% 85%, #C8EBFF, transparent), #FFFFFF"
      }
    ],
    "buttons": [
      {
        "name": "Default",
        "spec": "White, navy text, 1 px violet/12% border, inset 0 -3px 6px -2px navy-200; hover navy-50 with violet text"
      },
      {
        "name": "Primary",
        "spec": "Flat violet-600, white text, inset 0 -2px 6px violet-700; hover violet-700"
      },
      {
        "name": "Secondary",
        "spec": "violet-100, violet-600 text, soft violet inset; hover violet-200"
      },
      {
        "name": "CTA",
        "spec": "violet-600 under the Violet CTA gradient, faint light inner ring; one per page, marketing only"
      },
      {
        "name": "Translucent",
        "spec": "Transparent with a white sheen (7.5% → 20%) & white/25 border; for dark & image backgrounds"
      },
      {
        "name": "Shape",
        "spec": "Fully rounded, weight 450, 1 px border. Never a gradient on destructive or secondary buttons"
      }
    ]
  },
  "code": {
    "syntax": [
      {
        "role": "Prompt",
        "token": "emerald-400",
        "hex": "#34D399",
        "example": "$"
      },
      {
        "role": "Command",
        "token": "white",
        "hex": "#FFFFFF",
        "example": "sprite",
        "note": "First word of a command, medium weight"
      },
      {
        "role": "Keyword",
        "token": "violet-300",
        "hex": "#C4B5FD",
        "example": "import"
      },
      {
        "role": "Function & type",
        "token": "sky-300",
        "hex": "#7DD3FC",
        "example": "exec()"
      },
      {
        "role": "String",
        "token": "emerald-300",
        "hex": "#6EE7B7",
        "example": "'my-sprite'"
      },
      {
        "role": "Variable & literal",
        "token": "amber-300",
        "hex": "#FCD34D",
        "example": "$SPRITES_TOKEN"
      },
      {
        "role": "Comment",
        "token": "navy-400",
        "hex": "#A39AC1",
        "example": "# Log in"
      },
      {
        "role": "Plain text",
        "token": "navy-100",
        "hex": "#F4F3FB",
        "example": "-s my-sprite"
      }
    ],
    "terminal": [
      {
        "part": "Surface",
        "value": "navy-900, 12 px radius, 1 px inset ring of white at 10%, small shadow"
      },
      {
        "part": "Title bar",
        "value": "white at 5% with a white/10 bottom border; three 10 px navy-600 dots"
      },
      {
        "part": "Pills",
        "value": "Fragment Mono 10 px, uppercase, tracked; active is emerald-400/15 with emerald-300 text"
      },
      {
        "part": "Type",
        "value": "Fragment Mono 13–14 px, leading 1.6"
      },
      {
        "part": "Comments",
        "value": "Their own line, # in navy-400, never selectable"
      },
      {
        "part": "Commands",
        "value": "emerald-400 $, white first word, navy-100 arguments; the whole line copies"
      },
      {
        "part": "Tabs",
        "value": "Mono uppercase pills above the block; active is violet-600 with white text"
      }
    ],
    "rules": [
      "Terminals & code blocks are always navy-900, even in light mode.",
      "Every command is real & runnable. Don’t abbreviate or fake output.",
      "Explain steps with # comment lines, not prose between blocks.",
      "Make each command copyable on its own, without the $ prompt.",
      "Offer platform variants (macOS / Linux, Windows) when the commands differ.",
      "Only the syntax colors above; no theme-specific highlighting."
    ]
  },
  "imagery": {
    "illustrator": {
      "name": "Annie Ruygt",
      "url": "https://annieruygtillustration.com/"
    },
    "kinds": {
      "hero": {
        "label": "Landing Heroes",
        "summary": "The current fly.io style: pastel skies, clouds & floating machines, with characters at the edges & open sky for headlines. For page heroes & banners."
      },
      "editorial": {
        "label": "Editorial Illustrations",
        "summary": "Full-bleed scenes for blog covers, launches & social cards. Saturated color, visible texture, characters with opinions."
      },
      "spot": {
        "label": "Spot Illustrations",
        "summary": "Single characters or objects on a transparent background. For docs, empty states & feature callouts."
      }
    },
    "illustrations": [
      {
        "id": "ollama-connector",
        "title": "Ollama Connector",
        "kind": "hero",
        "date": "2026-10",
        "width": 1600,
        "height": 404,
        "alt": "Fluffy llamas surf on floating boards through a bright blue sky past white clouds & balloons.",
        "src": "/imagery/ollama-connector.webp",
        "src800": "/imagery/ollama-connector-800.webp"
      },
      {
        "id": "startups",
        "title": "Startups",
        "kind": "hero",
        "date": "2026-10",
        "width": 1600,
        "height": 1300,
        "alt": "A pastel sky over rolling psychedelic hills, trees & a laptop, with a small Fly.io balloon.",
        "openSpace": "top-left",
        "src": "/imagery/startups.webp",
        "src800": "/imagery/startups-800.webp"
      },
      {
        "id": "night-sky",
        "title": "Night Sky",
        "kind": "hero",
        "date": "2026-09",
        "width": 1600,
        "height": 404,
        "alt": "Purple patterned balloons drift past a crescent moon above a dark field & a small pixel creature.",
        "src": "/imagery/night-sky.webp",
        "src800": "/imagery/night-sky-800.webp"
      },
      {
        "id": "benchmark",
        "title": "Benchmark",
        "kind": "hero",
        "date": "2026-09",
        "width": 1600,
        "height": 900,
        "alt": "Winged server towers rise into a violet-to-peach sky, with paper planes overhead & a fox perched on one.",
        "openSpace": "top-left",
        "src": "/imagery/benchmark.webp",
        "src800": "/imagery/benchmark-800.webp"
      },
      {
        "id": "onboarding",
        "title": "Onboarding",
        "kind": "hero",
        "date": "2026-09",
        "width": 1600,
        "height": 933,
        "alt": "A pink sky over colorful hills, trees & a laptop, with a smiling Fly.io balloon.",
        "openSpace": "top-left",
        "src": "/imagery/onboarding.webp",
        "src800": "/imagery/onboarding-800.webp"
      },
      {
        "id": "pricing",
        "title": "Pricing",
        "kind": "hero",
        "date": "2026-09",
        "width": 1600,
        "height": 434,
        "alt": "A smiling server carried by a balloon floats through a light blue sky with clouds.",
        "openSpace": "top-left",
        "src": "/imagery/pricing.webp",
        "src800": "/imagery/pricing-800.webp"
      },
      {
        "id": "default-banner",
        "title": "Default Banner",
        "kind": "hero",
        "date": "2026-08",
        "width": 1600,
        "height": 435,
        "alt": "Hot-air balloons carry servers, a Postgres elephant & a sunglasses-wearing machine through a cloudy sky.",
        "src": "/imagery/default-banner.webp",
        "src800": "/imagery/default-banner-800.webp"
      },
      {
        "id": "computers-compared",
        "title": "Computers Compared",
        "kind": "hero",
        "date": "2026-08",
        "width": 1600,
        "height": 1200,
        "alt": "A smiling server hangs from a balloon in a pale blue sky, scattering bits of data.",
        "openSpace": "top-left",
        "src": "/imagery/computers-compared.webp",
        "src800": "/imagery/computers-compared-800.webp"
      },
      {
        "id": "connectors",
        "title": "Connectors",
        "kind": "hero",
        "date": "2026-08",
        "width": 1600,
        "height": 792,
        "alt": "A band of characters along the bottom: a rocket, a snake, a robot, a ghost & a red planet, on a transparent sky.",
        "src": "/imagery/connectors.webp",
        "src800": "/imagery/connectors-800.webp"
      },
      {
        "id": "run-agent-code",
        "title": "Run Agent Code",
        "kind": "hero",
        "date": "2026-08",
        "width": 1600,
        "height": 308,
        "alt": "A violet space city of glass domes, server towers & spaceships under planets & stars.",
        "src": "/imagery/run-agent-code.webp",
        "src800": "/imagery/run-agent-code-800.webp"
      },
      {
        "id": "homepage",
        "title": "Homepage",
        "kind": "hero",
        "date": "2026-07",
        "width": 1600,
        "height": 1300,
        "alt": "A winged server carries birds & small machines through a pastel sky trailing colorful ribbons.",
        "openSpace": "top-left",
        "src": "/imagery/homepage.webp",
        "src800": "/imagery/homepage-800.webp"
      },
      {
        "id": "early-access-clouds",
        "title": "Clouds",
        "kind": "hero",
        "date": "2026-07",
        "width": 1600,
        "height": 1200,
        "alt": "Soft, painterly clouds in a blue & pink sky.",
        "openSpace": "top-left",
        "src": "/imagery/early-access-clouds.webp",
        "src800": "/imagery/early-access-clouds-800.webp"
      },
      {
        "id": "whack",
        "title": "Whack-a-Mole",
        "kind": "editorial",
        "date": "2026-09",
        "width": 1525,
        "height": 888,
        "alt": "Pink moles pop out of holes in a green field while a wooden mallet swings down.",
        "src": "/imagery/whack.webp",
        "src800": "/imagery/whack-800.webp"
      },
      {
        "id": "swirl",
        "title": "Swirl",
        "kind": "editorial",
        "date": "2026-07",
        "width": 1600,
        "height": 908,
        "alt": "A hot-air balloon drifts over a hilltop town & a compass rose, beneath a starry black circle in a pale mint sky.",
        "src": "/imagery/swirl.webp",
        "src800": "/imagery/swirl-800.webp"
      },
      {
        "id": "toolbox-turnout",
        "title": "Toolbox Turnout",
        "kind": "editorial",
        "date": "2026-07",
        "width": 1525,
        "height": 855,
        "alt": "A green creature and a smiling Fly.io balloon float above the Earth in a pink, cloudy sky.",
        "openSpace": "top-left",
        "src": "/imagery/toolbox-turnout.webp",
        "src800": "/imagery/toolbox-turnout-800.webp"
      },
      {
        "id": "building-agents",
        "title": "Building Agents",
        "kind": "editorial",
        "date": "2026-06",
        "width": 1525,
        "height": 855,
        "alt": "A purple robot with long tentacle arms presses buttons, one labeled delete, on floating islands.",
        "src": "/imagery/building-agents.webp",
        "src800": "/imagery/building-agents-800.webp"
      },
      {
        "id": "local-llm",
        "title": "Local LLM",
        "kind": "editorial",
        "date": "2026-03",
        "width": 1525,
        "height": 855,
        "alt": "Green creatures explore planets, moons & a rocket in a black-and-white comic-style space scene.",
        "src": "/imagery/local-llm.webp",
        "src800": "/imagery/local-llm-800.webp"
      },
      {
        "id": "context-engineering",
        "title": "Context Engineering",
        "kind": "editorial",
        "date": "2026-02",
        "width": 1525,
        "height": 855,
        "alt": "A green creature sits beside a giant book labeled CLAUDE.md on a bright green background.",
        "src": "/imagery/context-engineering.webp",
        "src800": "/imagery/context-engineering-800.webp"
      },
      {
        "id": "agent-swarms",
        "title": "Agent Swarms",
        "kind": "editorial",
        "date": "2026-02",
        "width": 1600,
        "height": 828,
        "alt": "A humanoid robot watches a line of robots, arm in arm & carrying cans, cross a blue landscape.",
        "src": "/imagery/agent-swarms.webp",
        "src800": "/imagery/agent-swarms-800.webp"
      },
      {
        "id": "untrusted",
        "title": "Untrusted",
        "kind": "editorial",
        "date": "2026-02",
        "width": 1459,
        "height": 826,
        "alt": "Green creatures & tiny worlds sealed inside glass domes on a dark background.",
        "src": "/imagery/untrusted.webp",
        "src800": "/imagery/untrusted-800.webp"
      },
      {
        "id": "moltbot",
        "title": "Moltbot",
        "kind": "editorial",
        "date": "2026-01",
        "width": 1525,
        "height": 855,
        "alt": "A red creature naps beside an open laptop & toolboxes in a cozy room.",
        "src": "/imagery/moltbot.webp",
        "src800": "/imagery/moltbot-800.webp"
      },
      {
        "id": "starry-containers",
        "title": "Starry Containers",
        "kind": "editorial",
        "date": "2026-01",
        "width": 1600,
        "height": 827,
        "alt": "A Van Gogh–style swirling night sky with hot-air balloons, a crescent moon & glowing stars over a sleeping town.",
        "src": "/imagery/starry-containers.webp",
        "src800": "/imagery/starry-containers-800.webp"
      },
      {
        "id": "litestream-vfs",
        "title": "Litestream VFS",
        "kind": "editorial",
        "date": "2026-01",
        "width": 1525,
        "height": 855,
        "alt": "A garden hose sprays water at a grinning purple canister under a sunny pink sky.",
        "src": "/imagery/litestream-vfs.webp",
        "src800": "/imagery/litestream-vfs-800.webp"
      },
      {
        "id": "sprites",
        "title": "Sprites",
        "kind": "editorial",
        "date": "2026-01",
        "width": 1525,
        "height": 855,
        "alt": "Green & purple server characters with lightbulb heads stroll together on a pale green background.",
        "src": "/imagery/sprites.webp",
        "src800": "/imagery/sprites-800.webp"
      },
      {
        "id": "startups-runway",
        "title": "Runway",
        "kind": "spot",
        "date": "2026-10",
        "width": 1508,
        "height": 1362,
        "alt": "A ghost & a yellow bird sit on top of a round, rocky hill.",
        "src": "/imagery/startups-runway.webp",
        "src800": "/imagery/startups-runway-800.webp"
      },
      {
        "id": "startups-apply",
        "title": "Apply",
        "kind": "spot",
        "date": "2026-10",
        "width": 1564,
        "height": 1102,
        "alt": "A Fly.io balloon character hugs a filing cabinet connected by cables to laptops & a phone.",
        "src": "/imagery/startups-apply.webp",
        "src800": "/imagery/startups-apply-800.webp"
      },
      {
        "id": "startups-how-it-works",
        "title": "How It Works",
        "kind": "spot",
        "date": "2026-10",
        "width": 1377,
        "height": 1102,
        "alt": "Paper planes made of documents fly up a staircase of steps toward a white bird.",
        "src": "/imagery/startups-how-it-works.webp",
        "src800": "/imagery/startups-how-it-works-800.webp"
      },
      {
        "id": "preferred-cloud",
        "title": "Preferred Cloud",
        "kind": "spot",
        "date": "2026-09",
        "width": 800,
        "height": 712,
        "alt": "A grumpy orange ball scowls next to a cheerful Fly.io balloon.",
        "src": "/imagery/preferred-cloud.webp",
        "src800": "/imagery/preferred-cloud-800.webp"
      },
      {
        "id": "agent-sandboxes",
        "title": "Agent Sandboxes",
        "kind": "spot",
        "date": "2026-08",
        "width": 1377,
        "height": 1102,
        "alt": "A grey computer tower with round glasses chats on the phone while typing on a laptop.",
        "src": "/imagery/agent-sandboxes.webp",
        "src800": "/imagery/agent-sandboxes-800.webp"
      },
      {
        "id": "what-is-a-sandbox",
        "title": "What Is a Sandbox",
        "kind": "spot",
        "date": "2026-08",
        "width": 1537,
        "height": 775,
        "alt": "A small creature sleeps curled up on a fluffy cloud.",
        "src": "/imagery/what-is-a-sandbox.webp",
        "src800": "/imagery/what-is-a-sandbox-800.webp"
      },
      {
        "id": "warm-pool",
        "title": "Warm Pool",
        "kind": "spot",
        "date": "2026-07",
        "width": 1535,
        "height": 1024,
        "alt": "Smiling server cubes relax together in a round hot tub.",
        "src": "/imagery/warm-pool.webp",
        "src800": "/imagery/warm-pool-800.webp"
      },
      {
        "id": "campfire-apps",
        "title": "Campfire Apps",
        "kind": "spot",
        "date": "2026-05",
        "width": 1600,
        "height": 957,
        "alt": "App-block characters sit in camp chairs around a campfire in a forest at night.",
        "src": "/imagery/campfire-apps.webp",
        "src800": "/imagery/campfire-apps-800.webp"
      },
      {
        "id": "hermes",
        "title": "Hermes",
        "kind": "spot",
        "date": "2026-05",
        "width": 1600,
        "height": 611,
        "alt": "A black Greek vase painted with a golden figure, sprouting leafy branches.",
        "src": "/imagery/hermes.webp",
        "src800": "/imagery/hermes-800.webp"
      },
      {
        "id": "open-claw",
        "title": "Open Claw",
        "kind": "spot",
        "date": "2026-04",
        "width": 1600,
        "height": 574,
        "alt": "Three round red bird-like creatures walk in a line, the biggest in front.",
        "src": "/imagery/open-claw.webp",
        "src800": "/imagery/open-claw-800.webp"
      },
      {
        "id": "coding-agents",
        "title": "Coding Agents",
        "kind": "spot",
        "date": "2026-07",
        "width": 600,
        "height": 600,
        "alt": "A rabbit types on a laptop inside a tilted blue box, next to a checklist.",
        "src": "/imagery/coding-agents.webp",
        "src800": "/imagery/coding-agents-800.webp"
      },
      {
        "id": "personal-agents",
        "title": "Personal Agents",
        "kind": "spot",
        "date": "2026-07",
        "width": 600,
        "height": 600,
        "alt": "A small character sleeps in a cozy blue bed.",
        "src": "/imagery/personal-agents.webp",
        "src800": "/imagery/personal-agents-800.webp"
      },
      {
        "id": "mcp-servers",
        "title": "MCP Servers",
        "kind": "spot",
        "date": "2026-07",
        "width": 600,
        "height": 600,
        "alt": "A blue cube, a browser window & a signed document float together.",
        "src": "/imagery/mcp-servers.webp",
        "src800": "/imagery/mcp-servers-800.webp"
      },
      {
        "id": "untrusted-code",
        "title": "Untrusted Code",
        "kind": "spot",
        "date": "2026-07",
        "width": 600,
        "height": 600,
        "alt": "A purple safe with a combination dial.",
        "src": "/imagery/untrusted-code.webp",
        "src800": "/imagery/untrusted-code-800.webp"
      },
      {
        "id": "agent-built-apps",
        "title": "Agent-Built Apps",
        "kind": "spot",
        "date": "2026-07",
        "width": 600,
        "height": 600,
        "alt": "A stone block carved with the letter A, chipped at the base.",
        "src": "/imagery/agent-built-apps.webp",
        "src800": "/imagery/agent-built-apps-800.webp"
      }
    ],
    "zip": "/imagery/fly-imagery.zip",
    "rules": {
      "do": [
        "Use the newest illustrations first, starting with the landing heroes. Older watercolor pieces read as dated.",
        "Put hero headlines in the open sky. The heroes are drawn with characters at the edges to leave room for them.",
        "Let one illustration lead a layout. Pair it with plenty of quiet space & Mackinac headlines.",
        "Crop editorial scenes from the edges, keeping the main character inside the center 80%.",
        "Place spot illustrations on white, navy-50 or peacoat. They’re drawn to sit on flat color.",
        "Write alt text that describes the scene, not the post: who’s doing what, & where."
      ],
      "dont": [
        "Recolor, filter, tint or add effects to an illustration.",
        "Mix illustration styles in one layout, or put illustrations next to stock photos.",
        "Stretch, flip or rotate an illustration, or crop through a character.",
        "Use illustrations to explain architecture. Draw a diagram instead.",
        "Use a scene for a different subject than it was drawn for without checking with the brand team."
      ]
    },
    "textOnImage": {
      "approaches": [
        {
          "id": "beside",
          "title": "Text Beside the Image",
          "summary": "The default. Image & text sit side by side or stacked, so neither fights the other. Works with every illustration."
        },
        {
          "id": "open-space",
          "title": "Text in Open Space",
          "summary": "Only where the scene has a calm area, like an empty sky. Navy text on light areas, white on dark. Never over characters."
        },
        {
          "id": "scrim",
          "title": "Text on a Scrim",
          "summary": "For busy scenes that must carry text. A peacoat gradient rises from the edge the text sits on, & the text goes on the gradient."
        }
      ],
      "rules": [
        "Contrast: at least 4.5:1 for body text & 3:1 for headlines, measured against the busiest part of the image behind the text.",
        "Type: Mackinac Medium for headlines, Fricolage Grotesque for supporting text. Up to 2 lines of headline, 1 of support.",
        "Color: white or navy-900 only. No violet text, outlines or drop shadows on images; use a scrim instead.",
        "Placement: align text to an edge, never centered over the subject. Keep a margin of at least 6% of the image width.",
        "Logo: one corner, with its clear space. Inverted or light logo on dark areas, color or dark logo on light areas.",
        "One message per image. If you need a paragraph, use Text Beside."
      ],
      "scrimCss": ".scrim {\n  position: relative;\n}\n.scrim img {\n  display: block;\n  width: 100%;\n  height: auto;\n}\n/* Gradient over the image, rising from the edge the text sits on */\n.scrim::after {\n  content: \"\";\n  position: absolute;\n  inset: 0;\n  background: linear-gradient(\n    to top,\n    rgb(23 20 52 / 0.92) 0%,   /* peacoat */\n    rgb(23 20 52 / 0.6) 35%,\n    rgb(23 20 52 / 0) 65%\n  );\n}\n/* Text on top of the gradient */\n.scrim-text {\n  position: absolute;\n  z-index: 1;\n  inset-inline: 6%;\n  bottom: 6%;\n  color: #fff;\n}"
    }
  },
  "voice": {
    "principles": [
      {
        "title": "Lead With the Point",
        "body": "Open on a flat claim or a scene, not a preamble. The first sentence should be one a reader could argue with.",
        "do": {
          "text": "Public cloud billing is terrifying.",
          "post": "Accident Forgiveness",
          "date": "2024-08"
        },
        "dont": "In today’s fast-paced cloud landscape, developers face a growing number of challenges."
      },
      {
        "title": "Plain Words, Earned Claims",
        "body": "Say what it does & what it costs. Across 79 posts there’s not one “excited to announce”, “cutting-edge”, “world-class” or “blazing”. If a claim needs an adjective, it needs a number instead.",
        "do": {
          "text": "We just lowered the prices on NVIDIA L40s GPUs to $1.25 per hour.",
          "post": "We’re Cutting L40S Prices In Half",
          "date": "2024-08"
        },
        "dont": "We’re excited to announce blazing-fast, world-class GPU solutions!"
      },
      {
        "title": "Concrete & Clever",
        "body": "Tell the story, then land on specifics: timestamps, commands, numbers, code. Clever openings are welcome as long as they arrive somewhere real.",
        "do": {
          "text": "On September 1, 2024, at 3:30PM EST, a new Fly Machine came up…",
          "post": "Corrosion",
          "date": "2025-10"
        },
        "dont": "Recently, we experienced some issues with parts of our infrastructure."
      },
      {
        "title": "Own It When You’re Wrong",
        "body": "Say “we were wrong” in those words, with the specifics, & say what changes. No euphemisms like “evolving our strategy”.",
        "do": {
          "text": "We were wrong about Javascript edge functions, and I think we were wrong about GPUs.",
          "post": "We Were Wrong About GPUs",
          "date": "2025-02"
        },
        "dont": "We’ve decided to evolve our GPU strategy to better serve our customers."
      },
      {
        "title": "Say When You’re Selling",
        "body": "Readers know a company blog sells things. Name the pitch out loud, then make the argument on its merits.",
        "do": {
          "text": "Obviously, I’m trying to sell you something here. But that doesn’t make me wrong.",
          "post": "Code And Let Live",
          "date": "2026-01"
        },
        "dont": "Fly.io is simply the best choice for every workload."
      },
      {
        "title": "Fair to Competitors, Then Blunt",
        "body": "Give other tools real credit, then give a clear verdict. No sneering at “legacy clouds”.",
        "do": {
          "text": "Consul is fantastic software. Don’t build a global routing system on it.",
          "post": "Corrosion",
          "date": "2025-10"
        },
        "dont": "Unlike clunky legacy clouds, Fly.io actually works."
      },
      {
        "title": "Funny, Scaled to the Stakes",
        "body": "Humor & the occasional swear are house style in bylined posts; the blog’s own rules tell writers to swear. When customers were actually hurt, drop the jokes & say why.",
        "do": {
          "text": "Had this been an impactful attack, we would not be this flippant about it.",
          "post": "Kurt Got Got",
          "date": "2025-10"
        },
        "dont": "Oopsie! Our database took a little nap today 😴"
      },
      {
        "title": "A Person Wrote This",
        "body": "Write in first person under a real byline: “we” for the company, “I” for the author. Use contractions (77 of 79 posts do). In tutorials, bring the reader along.",
        "do": {
          "text": "Let’s implement an API token together.",
          "post": "Macaroons Escalated Quickly",
          "date": "2024-01"
        },
        "dont": "In this article, the implementation of an API token will be demonstrated."
      }
    ],
    "contexts": [
      {
        "context": "Launches",
        "guidance": "Show it working first (a terminal transcript, a screenshot), then argue for it.",
        "quote": {
          "text": "Obviously, I’m trying to sell you something here. But that doesn’t make me wrong.",
          "post": "Code And Let Live",
          "date": "2026-01"
        }
      },
      {
        "context": "Deep Dives",
        "guidance": "Story-driven & specific. Real timestamps, real code, opinions about both.",
        "quote": {
          "text": "Consul is fantastic software. Don’t build a global routing system on it.",
          "post": "Corrosion",
          "date": "2025-10"
        }
      },
      {
        "context": "Bad News & Incidents",
        "guidance": "Ownership first, reassurance in plain words, humor only in proportion to the harm.",
        "quote": {
          "text": "If you’re using Fly GPU Machines, don’t freak out; we’re not getting rid of them.",
          "post": "We Were Wrong About GPUs",
          "date": "2025-02"
        }
      },
      {
        "context": "Pricing",
        "guidance": "The number first, then a candid reason for it.",
        "quote": {
          "text": "Charging you for stuff you didn’t want is bad business.",
          "post": "Accident Forgiveness",
          "date": "2024-08"
        }
      },
      {
        "context": "Docs & Product UI",
        "guidance": "Same plain words, none of the jokes or swearing. Instructions in second person, verbs first, & errors that say how to fix them."
      }
    ],
    "naming": [
      {
        "term": "Fly.io",
        "note": "The company & platform. Capital F, lowercase io, with the dot. Bare “Fly” for the brand is rare; avoid it."
      },
      {
        "term": "Fly Machines",
        "note": "The VM product. Capital M when it means the product (“a Fly Machine”, “Machines”); lowercase only for generic VMs. Never “Fly machine”."
      },
      {
        "term": "Sprites",
        "note": "Persistent Linux computers for agents. Capitalized in prose (“a Sprite”); lowercase only in commands like `sprite create`."
      },
      {
        "term": "Managed Postgres",
        "note": "“Fly Managed Postgres” in product copy, “Managed Postgres” on second reference. “MPG” is fine in technical posts once it’s introduced."
      },
      {
        "term": "flyctl",
        "note": "The CLI’s name, always lowercase. The command you type is `fly`, so write `fly deploy`, not `flyctl deploy`."
      }
    ]
  },
  "usage": {
    "allowed": [
      "Informational articles, blog posts & documentation about Fly.io",
      "Video tutorials, talks & related media",
      "Integration pages & “Deploy on Fly.io” buttons, linking to https://fly.io"
    ],
    "notAllowed": [
      "T-shirts, stickers or any other merchandise, at any time",
      "Anything that implies Fly.io sponsors or endorses you without a written agreement",
      "Anything that could harm Fly.io’s reputation or ties it to illicit activity"
    ],
    "notes": [
      "Use on a web page should link to https://fly.io.",
      "All goodwill from use of the brand accrues to Fly.io, Inc.",
      "Other uses need written authorization from Fly.io."
    ]
  }
}