# Astro — Marketing site Design Spec

> Source: astro.build (live DOM, computed styles), 2026-07-19.
> Coverage: home / framework landing. No logged-in surface exists.
> Note: the page also publishes an `--ec-*` token set from **Expressive Code** (the code-block component library used in Astro's docs). Those are component tokens, recorded separately in &sect;2 rather than treated as brand chrome.

## 1. Visual Theme & Atmosphere

Astro is a dark, deep-navy framework page — canvas `#0c0f19` over `#060913` — with a genuinely unusual typographic setup: the display face **Obviously** is used across an extreme weight range, from **700 at 48px down to 300 at 36px**, so the hero headline and the sentence beneath it are the same family at opposite ends of the scale. Body copy runs Inter at weight **200**, which is lighter than almost anything else in this library. Colour arrives as a family of **angled two-stop gradients** — indigo&rarr;violet, red&rarr;magenta, mint&rarr;blue, yellow&rarr;coral — each also published as a 15-25% alpha wash for card grounds, so the same gradient appears twice at two intensities. Chrome itself is nearly monochrome: translucent gray pills on the navy. Feels: deep, spacey, gradient-lit, technical.

## 2. Color Palette & Roles

### Surfaces

| Token | Hex | Role / usage |
|---|---|---|
| `canvas` | `#0c0f19` | Page ground (deep navy) |
| `canvas-2` | `#0d0f14` | Secondary ground |
| `deep` | `#060913` | Deepest ground |
| `deep-alpha` | `rgba(5,9,18,0.55)` | Translucent chip ground |
| `panel` | `#17191e` | Code / panel fill |
| `panel-2` | `#23262d` | Tab bar fill |
| `surface` | `#343841` | Raised chrome, scrollbar thumb |
| `glass` | `rgba(43,43,43,0.30)` | Secondary button fill |
| `glass-2` | `rgba(44,44,44,0.50)` | Tertiary button fill |
| `glass-3` | `rgba(14,16,20,0.50)` | Faint panel |
| `white` | `#ffffff` | Primary button fill, headings |

### Text

| Token | Hex | Role / usage |
|---|---|---|
| `text` | `#f2f6fa` | Headlines |
| `text-2` | `#eef0f9` | Code foreground / bright text |
| `body` | `#bfc1c9` | Body copy (most common) |
| `muted` | `#858b98` | Meta, secondary labels |
| `on-accent` | `#030712` | Text on a bright accent fill |

### Borders

`border` `rgba(135,140,150,0.20)` &middot; `border-2` `rgba(132,139,152,0.30)` &middot; `border-strong` `rgb(84,88,100)`

### Accents (used as text/highlight, not fills)

| Token | Hex | Role / usage |
|---|---|---|
| `blue` | `#54b9ff` | Link / highlight |
| `mint` | `#4bf3c8` | Highlight, code selection foreground |
| `periwinkle` | `#acafff` | Highlight |
| `sand` | `#ffd493` | Highlight |
| `red` | `#d83333` | Brand red, gradient stop |
| `cyan-react` | `#61dafb` | Framework-demo accent (React) |

### Signature gradient family

Each is published both as a solid two-stop gradient **and** as a low-alpha wash for the card behind it:

| Name | Gradient | Wash |
|---|---|---|
| Indigo&rarr;violet | `linear-gradient(83.21deg, rgb(50,69,255) 0%, rgb(184,69,237) 100%)` | `linear-gradient(to right bottom, rgba(50,69,255,.25), rgba(74,242,200,.25))` |
| Deep indigo&rarr;purple | `linear-gradient(to right top, rgb(19,33,172), rgb(136,26,189))` | — |
| Red&rarr;magenta | `linear-gradient(66.77deg, rgb(216,51,51) 0%, rgb(240,65,255) 100%)` | `linear-gradient(to right bottom, rgba(216,51,51,.2), rgba(240,65,255,.2))` |
| Mint&rarr;blue | `linear-gradient(247.23deg, rgb(74,242,200) 0%, rgb(47,76,179) 100%)` | — |
| Yellow&rarr;coral | `linear-gradient(266.93deg, rgb(248,228,46) 0%, rgb(255,125,84) 100%)` | `linear-gradient(to right bottom, rgba(248,228,46,.15), rgba(255,125,84,.15))` |

### Expressive Code component tokens (`--ec-*`, docs code blocks)

`codeBg #17191e` &middot; `codeFg #eef0f9` &middot; `codeSelBg #3d4dfff0` &middot; `brdCol rgb(84,88,100)` &middot; `gtrFg #686c76` &middot; `gtrBrdCol #686c7633` &middot; `gtrHlFg #858b98f9` &middot; `uiSelBg #094771` &middot; `uiSelFg #4bf3c8` &middot; `focusBrd #00daef` &middot; `sbThumbCol #343841` &middot; `sbThumbHoverCol #555965` &middot; `tm-markBg #264a8980` / `markBrdCol #5570b3d0` &middot; `tm-insBg #26561c80` / `insBrdCol #4e7e41d0` / `insDiffIndCol #7eb070d0` &middot; `tm-delBg #81322b80` / `delBrdCol #ae594fd0` / `delDiffIndCol #e68a7ed0` &middot; `frm-edActTabBg #17191e` &middot; `frm-edTabBarBg #23262d` &middot; `frm-trmTtbFg #cccccc`

**Rules.** Chrome is monochrome — translucent gray pills on navy. The gradients are for cards, badges and illustration, never for buttons. Accent hexes (blue, mint, periwinkle, sand) appear as text and highlights, not as fills.

## 3. Typography Rules

- Display: `Obviously, obviously-fallback` — worked across an extreme weight range
- Body: `Inter, inter-fallback`
- UI: `ui-sans-serif, system-ui`

| Role | Family | Size/Line | Weight |
|---|---|---|---|
| Hero h1 | Obviously | 48/52.8 | **700** |
| Lead h2 | Obviously | 36/40 | **300** |
| Section h2 | Obviously | 30/36 | 400 |
| Card label h2 | ui-sans-serif | 16/24 | 600 |
| Product label h2 | ui-sans-serif | 16/24 | 500 (`#858b98`) |
| Lead paragraph | Inter | 18/27 | **200** |
| Body | ui-sans-serif | 16/24 | 300 |
| Button label | ui-sans-serif | 16 | 400 (600 on skip link) |

Patterns: the display family spans **300 to 700** with no settled mid-weight — the hero at 700 sits directly above a 300-weight line in the same face, which is the page's signature typographic contrast. Body copy at Inter **200** is exceptionally light. Tracking is `normal` at every size. Sentence case; no uppercase eyebrows.

## 4. Component Stylings

**Nav** — translucent over the navy ground.

**Buttons** — almost everything is a **9999px pill** at 40-42px:

| Variant | Fill | Text | Border | Radius | Height | Padding | Type |
|---|---|---|---|---|---|---|---|
| Primary | `#ffffff` | `#f2f6fa` | 1px none | 9999px | 42px | 8px 16px | 16/400 |
| Secondary | `rgba(43,43,43,0.30)` | `#bfc1c9` | 1px `rgba(132,139,152,0.30)` | 9999px | 42px | 8px 16px | 16/400 |
| Tertiary | `rgba(44,44,44,0.50)` | `#bfc1c9` | 1px `rgba(132,139,152,0.30)` | 9999px | 42px | 8px 16px | 16/400 |
| Filter (active) | `#ffffff` | `#f2f6fa` | none | 9999px | 40px | 8px 24px | 16/400 |
| Filter (rest) | `rgba(43,43,43,0.30)` | `#f2f6fa` | none | 9999px | 40px | 8px 24px | 16/400 |
| Version chip | `rgba(5,9,18,0.55)` | `#f2f6fa` | none | 9999px | 36px | 0 16px | 16/400 |
| Demo (React) | `#61dafb` | `#030712` | none | **8px** | 40px | 8px 16px | 16/400 |
| Skip link | `#0c0f19` | `#ffffff` | 1px `rgba(135,140,150,0.20)` | 9999px | 42px | 8px 16px | 16/600 |

The 8px "Add to cart" button belongs to an embedded framework demo, not to Astro's own chrome — the one non-pill.

**Gradient card** — a card whose ground is the low-alpha wash and whose badge or heading carries the matching full-strength gradient; this pairing is the page's main compositional move.

**Code block (Expressive Code)** — `#17191e` body, `#23262d` tab bar, `rgb(84,88,100)` border, gutter `#686c76`, selection `#3d4dfff0`, focus `#00daef`, with published ins/del/mark diff tokens.

**Inputs** — not captured (no exposed form fields).

## 5. Layout Principles

A dark stack: hero (700-weight headline over a 300-weight line, then a pill CTA pair and a version chip), a logo wall, then feature and showcase grids built from gradient-wash cards, with filter pills above the showcase. Radius scale is bimodal — `8px` for the embedded demo and code panels, `9999px` for essentially all chrome.

## 6. Depth &amp; Elevation

Radius: `8px` (panels, demo button) and `9999px` (all chrome pills), plus intermediate values in the census.

Shadow use is minimal — the Expressive Code frame publishes `--ec-frm-shdCol: #ffffff00` (fully transparent), and no meaningful drop-shadow recipe was resolved for chrome. Depth is the surface ladder `#060913` &rarr; `#0c0f19` &rarr; `#17191e` &rarr; `#23262d` &rarr; `#343841` plus translucent glass fills and `rgba(...)` hairlines.

## 7. Motion

Transition census resolved only generic values; specific durations and easings are **not captured**.

## 8. Backgrounds, Effects &amp; WebGL

The gradient family in &sect;2 is the entire effect layer — angled two-stop linear gradients at full strength for badges and headings, and the same pairs at 15-25% alpha as card grounds. No WebGL, no canvas, no backdrop-filter, no grain.

## 9. Do's and Don'ts

### Do
- Ground the page in deep navy (`#0c0f19` over `#060913`), not neutral black.
- Set the hero in Obviously at **700** and put a **300**-weight line of the same face directly beneath it.
- Run body copy in Inter at weight **200**.
- Make every chrome control a 9999px pill at 40-42px on translucent gray.
- Pair each gradient with its own low-alpha wash: full strength on the badge, 15-25% on the card ground.
- Keep accent hexes (`#54b9ff`, `#4bf3c8`, `#acafff`, `#ffd493`) as text and highlights.

### Don't
- Don't put a gradient on a button — chrome stays monochrome.
- Don't settle the display face at a mid weight; the 700/300 contrast is the point.
- Don't use heavy body copy — Inter sits at 200.
- Don't give chrome controls a small radius; only embedded demos and code panels use 8px.
- Don't treat the `--ec-*` values as brand tokens — they belong to the code-block component.
- Don't add drop shadows; depth is the surface ladder and glass fills.

## 10. Responsive Behavior

Not captured — no media-query census was resolved from the accessible stylesheets.

## 11. Agent Prompt Guide

- Canvas `#0c0f19` · Deep `#060913` · Panel `#17191e` · Text `#f2f6fa` · Body `#bfc1c9` · Muted `#858b98` · Border `rgba(135,140,150,.20)` · Accents `#54b9ff` / `#4bf3c8` / `#acafff` / `#ffd493`
- Font: Obviously 700/400/300 (display), Inter 200 (body), ui-sans-serif 300-600 (UI) · Body: 18/27 lead, 16/24 · Radius: 9999px chrome / 8px panel · Control height: 40-42px
- Focus: `#00daef` (Expressive Code) · Hover: not captured · Motion: not captured

<astro_design_language>
A deep-navy framework page — #0c0f19 over #060913, never neutral black — stepping up through #17191e panels, #23262d tab bars and #343841 raised chrome, with text at #f2f6fa, body #bfc1c9 and muted #858b98. The signature typographic move is extreme weight contrast within one display family: Obviously set at 700 for the 48/52.8 hero sitting directly above a 300-weight 36/40 line of the same face, with section headings at 400 and body copy in Inter at an exceptionally light weight 200 (18/27). Tracking is normal at every size and nothing is uppercase. Colour arrives entirely through a family of angled two-stop gradients — indigo-to-violet linear-gradient(83.21deg, #3245ff, #b845ed), red-to-magenta (66.77deg, #d83333, #f041ff), mint-to-blue (247.23deg, #4af2c8, #2f4cb3) and yellow-to-coral (266.93deg, #f8e42e, #ff7d54) — each also published as a 15-25% alpha wash, so the same gradient appears twice: full strength on a badge or heading, and diluted as the ground of the card behind it. Chrome itself stays monochrome: nearly every control is a 9999px pill at 40-42px on translucent gray (rgba(43,43,43,.30) or rgba(44,44,44,.50)) with rgba(132,139,152,.30) hairlines, and the only 8px radius belongs to embedded framework demos and code panels. Accent hexes #54b9ff, #4bf3c8, #acafff and #ffd493 are text and highlight colours, never fills. Depth is the surface ladder plus glass, with no meaningful drop shadow, no WebGL, canvas or backdrop-filter. Feels: deep, spacey, gradient-lit, technical. Avoid: gradients on buttons, settling the display face at a mid weight, heavy body copy, small-radius chrome, and treating the Expressive Code --ec-* token set as brand colour.
</astro_design_language>
