← Back to library

Landing Page

Lead Capture System

Photo-hero service page with an italic serif headline, three-offer strip and an async-only sales model.

2 tools★ 82
#serif#offers#service
ClaudeLovable

The prompt

Prompt
# Lead Capture System

## What you're building
A photographic, full-bleed service page for `{{brand}}` — a solo operator who builds lead-capture, follow-up and light-automation systems for founders, creators, coaches and small service businesses. The audience is people drowning in manual follow-up who have been burned by agencies and by software they never finished configuring. The distinctive idea is **async-only sales**: the page never asks for a call. Every CTA resolves into a form, an email or a recorded walkthrough, and that constraint is stated as a *feature* in the hero, which is exactly what disqualifies the wrong buyers and converts the right ones.

## Art direction
Mood: warm editorial luxury over a bright photograph — a soft-white serif headline on tropical daylight, one antique-gold accent, and dark glass panels that float over the image without hiding it.

| Token | Hex | Use |
|---|---|---|
| `--ink` | `#0C0C0E` | Page ground below the hero; the most-painted surface |
| `--scrim` | `#000000` @ 50% | Layer 1 of the hero contrast stack, full-cover |
| `--glass` | `#FFFFFF` @ 3.5% | Offer-strip fill over the photo |
| `--glass-2` | `#FFFFFF` @ 3% | Secondary panels, form-field fills |
| `--glass-3` | `#FFFFFF` @ 5% | Hover state on glass surfaces |
| `--gold-wash` | `#C8A97E` @ 10% | Accent panel fills, eyebrow pill background, primary-button fill |
| `--gold-wash-2` | `#C8A97E` @ 8% | Card borders at rest |
| `--cream` | `#F5F0EA` | Headings and primary text — the dominant foreground |
| `--cream-soft` | `#F5F0EA` @ 88% | Secondary body copy; **the minimum for any text over the photograph** |
| `--white` | `#FFFCF8` | Hero deck copy over the photograph only |
| `--gold` | `#C8A97E` | The italic accent phrase, section eyebrows, rules, CTA borders |
| `--gold-70` | `#C8A97E` @ 72% | Card eyebrows, focused form labels |
| `--gold-50` | `#C8A97E` @ 50% | Hairlines, dividers, button borders — **rules and borders only, never text** |
| `--muted` | `#FFFFFF` @ 55% | Labels, captions, meta — **on `--ink` only** |

**Two corrections to values you may find measured on a live build.** They are contrast failures, not design intent, and reproducing them reproduces the bug:

- `--muted` at 40% white composites to `rgb(109,109,110)` on `--ink` and measures **3.79:1** — below the 4.5:1 body/label minimum. It is specified here at **55%**, which composites to `rgb(145,145,146)` and measures **6.23:1** against `#0C0C0E`.
- `--gold-50` reads **2.9:1** on `--ink` and must never carry text. Disabled controls use `--muted` at 55% with `aria-disabled`, not faded gold.

Verified ratios you can rely on, all against `--ink` `#0C0C0E`: `--cream` **17.4:1**, `--cream-soft` **13.3:1**, `--gold` **9.8:1**, `--muted` **6.2:1**.

**Type stack — the mixed treatment, spelled out.** Two families do three jobs, and the split is the brand signature.

- **`"Playfair Display", serif` 700, upright** — the H1's main clause and every H2. H1: `clamp(2.5rem, 1.3rem + 4.8vw, 4.5rem)`, `line-height: 1.1`, `letter-spacing: normal` — do not tighten Playfair, its own fit is correct. Colour `--cream`. H2: `1.5rem`, `line-height: 1.25`, `--cream`.
- **`"Playfair Display", serif` 700, `font-style: italic`** — **exactly one phrase in the H1**: the final qualifying clause, set in `--gold`, same size and weight as the upright text so it reads as emphasis rather than a second heading. It is a genuine `<em>` inside the `<h1>`, not a styled `<span>`, and it falls on its own line at every width. **The real italic face is required.** Load `Playfair Display` italic 700 as its own file and set `font-synthesis: none` on the `<h1>` so a missing italic fails visibly in review instead of shipping as a machine-sheared oblique — a synthesised slant on a didone reads as a rendering fault, and this phrase is the page's single most important piece of typography. Nothing else on the page is italic.
- **`Inter, sans-serif` 400** — all body copy. Hero deck: `1.25rem` / `1.6`, colour `--white`, `max-width: 46ch`, centred. Body elsewhere: `1rem` / `1.7`, `--cream-soft`.
- **`Inter, sans-serif` 600** — every eyebrow and label: `0.6875rem`, `letter-spacing: 0.18em`, uppercase, colour `--gold-70`. Card headlines inside the offer strip are also Inter 600 at `0.9375rem` / `1.5` in `--cream` — the serif never appears inside a small panel.

So: **serif upright for the promise, serif italic gold for the qualifier, sans for everything that explains or asks.** Do not introduce a fourth treatment.

**H1 fit, checked against the supplied copy.** At 1440px the clamp resolves to `1.3rem + 4.8vw = 89.9px`, so the `4.5rem` cap applies: **72px**. Give the H1 `max-width: 62rem` (992px) inside the 1120px container. Playfair Display 700 averages ≈0.47em per character across mixed-case English including spaces, so at 72px a character costs ≈34px. The three supplied lines measure: line 1 (24 chars) ≈812px, line 2 (21) ≈710px, line 3 (17) ≈575px — all inside 992px, so the headline renders on **exactly three lines**. The same arithmetic at 1024px (clamp = 70.0px, available 976px) and 768px (57.7px, available 720px) still gives three lines. Below 400px the clamp floor of `2.5rem` engages; at 375px the italic line measures ≈320px against 335px of available width, so it holds on one line — if your rendering pushes it over, let the `<em>` wrap internally but keep the hard break that puts it on its own line.

Shape: `border-radius: 10px` on all buttons and form fields; `14px` on the glass panels; nothing fully rounded except the eyebrow pill. Buttons are transparent with a 1px `--gold-50` border; the primary is distinguished by a `--gold-wash` fill. There are no solid-fill buttons on this page.

**Text over photography — resolved, not left to judgement.** The hero media sits under a three-layer stack, all three shipped by default:

1. A full-cover `--scrim` at 50%.
2. A vertical `linear-gradient(180deg, rgb(0 0 0 / 0.55) 0%, rgb(0 0 0 / 0.25) 42%, rgb(0 0 0 / 0.7) 100%)`.
3. A **copy plate** behind the centred copy column only: `radial-gradient(ellipse 120% 90% at 50% 42%, rgb(0 0 0 / 0.62) 0%, rgb(0 0 0 / 0.30) 62%, transparent 100%)`, sized to the copy column plus a 15% bleed.

That stack transmits roughly 12% of the underlying image where the H1 and deck sit. Against a near-white sky (relative luminance ≈0.78) the composited ground lands at ≈0.095, which gives `--gold` (luminance 0.478) **3.6:1** and the `--white` deck **7.1:1**. Requirements: **body and label text over the photo ≥4.5:1, display H1 ≥3:1.** Verify against the *brightest frame of the video*, not the poster — sample the three lightest regions each text run crosses.

If a sampled region still fails, there is exactly one remedy and it is not typographic: **swap the media for a darker crop.** Do not lighten the gold, do not shrink the plate's coverage, and do not add a `text-shadow` — a shadow is a supplement to a contrast strategy, never the strategy.

## Copy

Every string the page renders, verbatim. Placeholders name a real business, person, tool, project, price or commitment and must be supplied — everything around them is written here. **Never invent a client name, a tool name, a figure, or a testimonial.**

Placeholders used: `{{brand}}`, `{{brand-initials}}`, `{{email}}`, `{{year}}`, `{{response-window}}`, `{{integrations.<group>[]}}`, `{{work-0N-name}}`, `{{work-0N-description}}`, `{{work-0N-url}}`, `{{budget-band-1..3}}`, `{{reference_id}}`.

### Chrome

| Slot | String |
|---|---|
| Skip link (first focusable element) | `Skip to the inquiry form` |
| `↗` glyph, visually-hidden companion text | `(opens in a new tab)` |

There is no navigation bar. The page's only wayfinding is CTA repetition, and that is part of its argument.

### 1 · Hero

| Slot | String |
|---|---|
| Eyebrow pill | `SOLO-BUILT AI SYSTEMS` |
| H1, line 1 (upright, `--cream`) | `Lead Capture, Follow-Up,` |
| H1, line 2 (upright, `--cream`) | `and Simple Automation` |
| H1, line 3 (`<em>`, italic, `--gold`) | `Without the Bloat` |
| Deck | `I build focused systems for founders, creators, coaches, consultants, and small service businesses that need follow-up to happen whether or not anyone remembers to do it.` |

Three-offer strip. Each statement is ≤90 characters, which is what holds it to three lines in the 213px column the 3-up grid produces at 800px.

| Column label | Statement |
|---|---|
| `PRIMARY OFFER` | `A lead capture and follow-up system, built around your tools and handed over running.` |
| `FALLBACK OFFER` | `An async teardown of the funnel you already have, delivered as a recorded walkthrough.` |
| `SALES MODEL` | `No calls. Email, forms and recorded video — including the part where we decide.` |

| Slot | String |
|---|---|
| Strip caption (full width, inside the panel) | `Entry engagements start at pilot scope: one bottleneck, one system, one handover.` |
| Hero secondary button | `View Selected Work` |
| Capsule line (gold dot, centred) | `Systems that follow up so you don't have to.` |

### 2 · Inquiry form card (begins inside the hero)

| Slot | String |
|---|---|
| H2 (serif) | `Start Your System` |
| Qualifier line beneath the H2 | `Best fit if enquiries already reach you and go cold. If you need traffic first, say so — I will point you somewhere useful instead.` |

Fields, in render order. Four are required.

| # | Field | Label | Required | Detail |
|---|---|---|---|---|
| 1 | Request type | `What are you asking for?` | **yes** | Radio group, `<fieldset>` + `<legend>`: `A system build` · `An async teardown` |
| 2 | Name | `Your name` | **yes** | Placeholder `First and last` |
| 3 | Email | `Email` | **yes** | Placeholder `you@company.com` |
| 4 | Business or role | `Business or role` | no | Placeholder `e.g. two-person design studio` |
| 5 | Bottleneck | `Where the breakdown is happening` | **yes** | `<textarea rows="4">`, placeholder `Enquiries come in through three places and nobody answers them until Monday.` |
| 6 | Budget | `Budget range` | no | Select: `Not sure yet` · `{{budget-band-1}}` · `{{budget-band-2}}` · `{{budget-band-3}}` · `Tell me what it should be` |
| — | Submit | `Send Inquiry` | — | — |
| — | Line beneath submit | `Goes to one inbox, read by one person. Reply within {{response-window}}.` | — | — |

Form states. Every string is supplied; nothing is generated at runtime.

| State | String |
|---|---|
| Submit disabled — request type missing | `Pick what you're asking for to send this.` |
| Submit disabled — name missing | `Add your name to send this.` |
| Submit disabled — email missing | `Add your email to send this.` |
| Submit disabled — bottleneck missing | `Add the bottleneck to send this.` |
| Field error — request type | `Pick one so I know which reply to send.` |
| Field error — name | `Add your name so I know who I'm replying to.` |
| Field error — email | `That email address didn't parse. Everything else you typed is still here.` |
| Field error — bottleneck | `Tell me where the breakdown is happening — a sentence is enough.` |
| Submitting — button label | `Sending…` |
| Success — H2 | `Received.` |
| Success — body | `Reference {{reference_id}}. One person reads this and replies within {{response-window}} to the address you gave.` |
| Success — link | `View Selected Work` |
| Error — banner | `That didn't send. Nothing you typed was lost — try again, or email {{email}} directly.` |
| Error — retry button | `Try again` |
| Duplicate / rate limited | `Already received — I have your first message and I'll reply to that thread.` |
| Offline | `You're offline. Your message is still here; send it when you reconnect.` |

The disabled hint names the **first** required field still missing, in the form's own top-to-bottom order. There are four possible strings and all four are above.

### 3 · What I Build

| Slot | String |
|---|---|
| Eyebrow | `WHAT I BUILD` |
| H2, line 1 (hard break, no trailing space) | `Custom systems for content, follow-up,` |
| H2, line 2 | `websites, and operations` |
| Deck | `Built around your workflow, tools, and business model instead of forcing you into a template.` |

**Six cards.** All six are written out; none is a template to extend. Each card is a name, a description, and three verifiable outcomes.

| # | Card name | Description | Outcomes |
|---|---|---|---|
| 01 | `Lead Capture + Follow-Up` | `A tight intake form, a routing rule, and a follow-up sequence that runs on its own. Every enquiry gets a first reply the same day, whether or not you are at a desk.` | `Every enquiry answered the same day` · `One inbox instead of four` · `A record of who was told what, and when` |
| 02 | `Content Systems` | `A repeatable pipeline from idea to published piece. The drafting, formatting and scheduling steps are automated; the judgement calls stay with you.` | `A publishing cadence you can actually hold` · `Drafts waiting for you, not a blank page` · `One place where every piece lives` |
| 03 | `Websites That Convert` | `A small site built around a single decision, not a brochure. Structure and copy first, then design, then speed — so the page loads fast and asks for one thing.` | `One page, one decision, one form` · `A load time you can measure` · `Copy you can edit without a developer` |
| 04 | `Intake + Qualification` | `A front door that sorts serious enquiries from tyre-kickers before they reach you, using rules you wrote and can read back in plain language.` | `Unqualified enquiries answered without your time` · `Rules written in plain language, not code` · `A weekly list of who is worth a real reply` |
| 05 | `Operations Automation` | `The small repeated jobs that eat a week: moving records between tools, chasing a missing field, sending the same three emails. Automated once, then monitored.` | `Hours back that you can name` · `Fewer things typed twice` · `An alert when something stops working` |
| 06 | `Handover + Documentation` | `Every build ships with a written walkthrough of how it works and how to change it. You own it. Nothing here is rented back to you.` | `A written map of every moving part` · `Access in your accounts, not mine` · `A change you can make yourself in ten minutes` |

### 4 · The Process

| Slot | String |
|---|---|
| Eyebrow | `THE PROCESS` |
| H2 | `From bottleneck to working system` |
| Monogram mark | `{{brand-initials}}` |

| # | Step title | Explanation |
|---|---|---|
| 1 | `Point to the bottleneck` | `Tell me where the breakdown is happening: no leads, weak follow-up, messy intake, or a site that is not converting. You do not need to know the fix.` |
| 2 | `I scope it in writing` | `You get a written scope naming the one system I would build first, what it will and will not do, and what it costs. Nothing starts until you reply to it.` |
| 3 | `I build it and show you` | `You get a recorded walkthrough at the halfway point and again at the end. You comment in writing; there is no meeting to schedule.` |
| 4 | `You receive it running` | `You get the working system inside your own accounts, a written map of how it runs, and two weeks of adjustments included.` |

Beneath step 4, the low-commitment offer:

| Slot | String |
|---|---|
| Lead-in line | `Not ready to name a budget? Ask for a teardown of what you already have instead.` |
| Button | `Request Async Teardown` |

### 5 · Ambient band

| Slot | String |
|---|---|
| Centred serif line (the band's only copy) | `Quiet systems, running while you sleep.` |

### 6 · How It Connects

| Slot | String |
|---|---|
| Eyebrow | `HOW IT CONNECTS` |
| H2, line 1 (hard break, no trailing space) | `Built to fit the tools and channels` |
| H2, line 2 | `you already use` |
| Deck | `Connect the channels, apps, and tools you already rely on without rebuilding your workflow from scratch.` |
| Grid label above the three panels | `PLATFORM INTEGRATIONS` |

Three category panels, each with a written explanation and up to six chips.

| Category name | Explanation |
|---|---|
| `Content & Publishing` | `Where the work goes out: your site, your feeds, your newsletter.` |
| `Messaging & Email` | `Where enquiries land and where the follow-up leaves from.` |
| `Data & Operations` | `Where the record lives once a lead becomes a job.` |

Chips are `{{integrations.content[]}}`, `{{integrations.messaging[]}}`, `{{integrations.operations[]}}` — real product names supplied by the operator, six per group at most. **Never invent a tool name to fill a row.** If a group supplies fewer than six, render only what is supplied; the chips wrap and no layout depends on the count. If a group supplies none, omit that panel entirely rather than shipping an empty one.

### 7 · Selected Work

| Slot | String |
|---|---|
| Eyebrow | `SELECTED WORK` |
| H2 | `Real projects and systems I've already built` |
| Deck | `No inflated claims. Just a clearer picture of the kinds of websites, product flows, and automations I can build for you.` |
| Status tag — live work | `Live Project` |
| Status tag — pilot work | `Pilot Build` |
| Per-card control (pilot cards only) | `View Pilot Build` |

Three cards. `{{work-0N-name}}` and `{{work-0N-description}}` describe real deployed work and must be supplied — writing them here would be fabrication. The description is **one or two sentences, ≤32 characters short of overflowing two lines at `1rem`/1.7 in the card**, and it says what the system *does*, never what it earned. Sample shape, **not to be shipped**: *"A booking flow that answers the price question before it asks for a date."*

**Card control rules.** A card whose status is `Pilot Build` renders the `View Pilot Build` control pointing at `{{work-0N-url}}`, `target="_blank" rel="noopener noreferrer"`. A card whose status is `Live Project` renders **no control at all** — the whole card is the link, with a `↗` glyph top-right and an accessible name equal to `{{work-0N-name}}`. If a card has no `{{work-0N-url}}`, it is not a link and shows no control: no `href="#"`, no disabled button. A dead control on a page arguing "here is real running work" is the worst defect available.

### 8 · Closing band and footer

| Slot | String |
|---|---|
| H2 (serif, one line) | `One system. One bottleneck. Start there.` |
| Primary button | `Send Inquiry` |
| Secondary button | `Request Async Teardown` |
| Footer wordmark | `{{brand}}` |
| Footer contact (real `mailto:`) | `{{email}}` |
| Footer legal line | `© {{year}} {{brand}}. Built and run by one person.` |

### Alt text and non-visible labels

The page renders **no content images**. Every visual is either the hero media or a decorative glyph, so the accessibility work here is aria-labelling rather than alt text.

| Element | Treatment |
|---|---|
| Hero video | `aria-hidden="true"`, not focusable, no controls — it is decoration |
| Hero poster image | `alt=""` — the H1 already carries the meaning; a described photo would duplicate it |
| Ambient canvas (§5) | `aria-hidden="true"`, `tabindex="-1"` |
| Gold dot on the capsule | `aria-hidden="true"` |
| `↗` glyph on every off-site control | `aria-hidden="true"`, followed by visually-hidden `(opens in a new tab)` |
| Gold hairline bullets in §3 cards | `aria-hidden="true"`; the outcome list is a real `<ul>` |
| Form submit spinner | `aria-hidden="true"`; state is carried by `aria-busy` and the `Sending…` label |
| Vertical gold rule in §4 | `aria-hidden="true"` |
| `{{brand-initials}}` monogram | `role="img"`, `aria-label="{{brand}}"` |

## Layout
Six bands, roughly **six screens** at 1080px — a sanity figure, not a target. Never pad whitespace to hit it. What matters is the proportion: **What I Build is the longest read on the page**, the hero runs about one and a half viewports because the form starts inside it, and the ambient band is the one place that gets height for its own sake. Container `max-width: 1120px`, gutter `4vw`. No nav bar.

**Every anchor destination on the page** — there are no others, and nothing links to `#`:

| Control | Target |
|---|---|
| Skip link | `#inquiry` |
| `View Selected Work` (hero, and the success-state link) | `#selected-work` |
| `Request Async Teardown` (after §4, and closing band) | `#inquiry`, and it pre-selects the `An async teardown` radio |
| `Send Inquiry` (closing band) | `#inquiry`, focus moves to the first field |
| `Send Inquiry` (inside the form) | not an anchor — it submits |
| `View Pilot Build` | `{{work-0N-url}}`, new tab; omitted when absent |
| Footer `{{email}}` | `mailto:{{email}}` |

1. **Hero.** Full-bleed autoplaying muted looping video (or a static photograph at the same crop) under the three-layer scrim stack. Flex column, centred, in order: eyebrow pill on `--gold-wash`; H1 over three hard-broken lines with the italic gold clause last; deck; the three-offer strip — one `--glass` panel with `backdrop-filter: blur(12px)` and a 14px radius, containing a 3-column grid at 20px gap with the full-width caption line beneath; the `View Selected Work` button; the gold-dot capsule; then the inquiry form card (`--glass-2`, 14px radius, `max-width: 33rem`) which begins inside the hero and runs past the fold. The third offer column is the async-only constraint stated as an offer, not an apology.
2. **What I Build.** On `--ink`. Gold eyebrow, serif H2 over two hard-broken lines, deck. Then a 2-column card grid of **six** cards, each `--glass-2` with a `--gold-wash-2` border: card name in Inter 600 `--cream`, description in `--cream-soft`, and a three-item outcome list with gold hairline bullets. Cards run tall; this is the page's longest read, so it must be scannable by card name alone.
3. **The Process.** Eyebrow, serif H2, the `{{brand-initials}}` monogram mark, then four numbered steps in a single column with a 1px `--gold-50` vertical rule through the number gutter. Numerals are gold, set in Inter 600 — there is no monospace face on this page. Beneath step 4: the teardown lead-in line and its button.
4. **Ambient band.** The page's one visual indulgence: a full-width interactive canvas on `--ink` — a slow gold-on-black particle flow field — carrying one centred serif line and no CTA. Its job is to give the long page a breath between the explanatory sections and the proof sections. **It is entirely optional**: render a static gold-on-black gradient if WebGL is unavailable, if `navigator.deviceMemory < 4`, under `prefers-reduced-motion`, or below 768px.
5. **How It Connects.** Eyebrow, serif H2 over two hard-broken lines, deck, the `PLATFORM INTEGRATIONS` label, then three category panels: category name in Inter 600, the one-line explanation, and a wrapped row of tool chips in `--muted` on `--glass-2`. This section dissolves "I'd have to change my stack" using nothing but names.
6. **Selected Work.** Eyebrow, serif H2, the disclaiming deck line, then three project cards in a row (one column on mobile): status tag, project name in serif at `1.25rem`, the description, and — on pilot cards only — the `View Pilot Build` control. Then the closing band on `--gold-wash`: serif H2 and the two buttons side by side. Footer beneath: wordmark, `mailto:` address, legal line.

## Conversion architecture
- **Hook:** the H1 names three specific pains in sequence and then, in gold italic, removes the thing the reader fears most about fixing them. The italic phrase *is* the differentiator — it earns its typographic separation because it is the only clause that isn't a commodity.
- **Mechanism:** *disqualification as trust*. A solo operator can't win on capacity, so this page wins on fit. The three-offer strip declares the primary offer, the fallback offer, and the sales model in the first screen — a reader who wants a big agency, a phone call, or a retainer they can't scope leaves immediately, and everyone who stays is pre-qualified. The inquiry form sits inside the hero because the page's job is finished by the end of screen one for the right reader.
- **Proof / credibility devices, in order:** the `SOLO-BUILT AI SYSTEMS` eyebrow (owning the limitation before it is used against you); the pilot-scope caption (a small first commitment); named integrations in §5 (competence shown, not claimed); §7's status tags separating live work from pilots; and §7's deck line disclaiming inflated results — the single highest-trust sentence on the page. No testimonials, no logos, no revenue claims. If `{{brand}}` gets real client quotes later they belong in §7, never in the hero.
- **Objection handling, in page order:** *"Who is this for?"* → hero deck, by role. *"What do I actually get?"* → offer strip, then §3's cards. *"Will I have to sit through calls?"* → `SALES MODEL`, stated as a benefit. *"Is this a big commitment?"* → pilot-scope caption plus §4 step 1. *"Will it fit my tools?"* → §5, entirely. *"Has this ever worked?"* → §7, with its own honesty disclaimer. *"How do I start?"* → the form, already open, already visible.
- **CTA cadence:** four distinct labels — `Send Inquiry` (primary; hero form and closing band), `View Selected Work` (hero secondary), `Request Async Teardown` (after §4 and in the closing band), `View Pilot Build` (per pilot card). Something actionable is on screen roughly every screen and a half. All four are transparent 10px-radius gold-bordered buttons; the primary is distinguished by placement and its `--gold-wash` fill, never by a different shape.
- **Single next action:** send the inquiry. The teardown request exists to catch readers who aren't ready to name a budget, and it feeds the same form and the same inbox.

## Interaction & states
**Hero video:** `autoplay muted loop playsinline preload="metadata"`, with a `poster` that is the exact first frame so there is no flash. If the video fails, if `prefers-reduced-motion: reduce` is set, if `connection.saveData` is true, or below 768px, render the poster only — the three-layer scrim and every contrast ratio hold identically in both cases. No play/pause chrome: it is decoration, so `aria-hidden="true"` and out of the tab order.

**Inquiry form** — the page's only interactive system. Copy for every state is in **Copy**.
- *Empty:* every field has a visible `<label>` above it in Inter 600 `--muted`; placeholders are examples, never the label. Field fill `--glass-2`, border 1px `--gold-50`. Submit is disabled with the visible hint naming the first missing required field, `aria-disabled="true"`, reason exposed via `aria-describedby` rather than a tooltip.
- *Focused:* border → `--gold`, plus a 3px `--gold-wash` ring. Label brightens to `--gold-70`. Focus is never removed.
- *Invalid — on blur, never on keystroke:* border and message in a warm red measured at ≥4.5:1 against `--glass-2` over `--ink`, tied by `aria-describedby`, plus a warning glyph so colour is not the only signal.
- *Submitting:* button label → `Sending…`, a 16px gold spinner placed **before** the label so the button width does not change, `aria-busy="true"`, fields locked but text at full contrast.
- *Success:* the form card cross-fades to the confirmation at the same height — serif H2, the reference line, and the `View Selected Work` link. Focus moves to the confirmation heading; announced via `aria-live="polite"`.
- *Error:* an inline banner above the fields, `aria-live="assertive"`, the plain-language line, a `Try again` button, and `{{email}}` as a guaranteed fallback path. Every entered value preserved.
- *Duplicate / rate limited:* the same email inside an hour gets the neutral confirmation, not an error. Never punish an eager buyer with a failure screen.
- *Offline:* `navigator.onLine === false` disables submit with the offline hint; an `online` listener re-enables it and clears the hint. Nothing is discarded.

**Ambient canvas (§4):** pointer movement influences the field with heavy damping (lerp 0.06, cursor→field displacement is **positive**: the field drifts *toward* the pointer). The animation pauses via `IntersectionObserver` when the section is off-screen and on `visibilitychange`. `aria-hidden`, non-focusable. Bail permanently to the static gradient if the rolling 60-frame average drops below 45fps for two consecutive seconds.

**Cards and buttons:** cards lift `translateY(-3px)` and their border goes `--gold-wash-2` → `--gold-50` on hover; buttons fill to `--gold-wash` and their border to `--gold`; active resets the transform instantly. `:focus-visible` reproduces the hover treatment plus a 2px offset ring at ≥3:1 against its backdrop.

## Motion
- Section reveal: `opacity 0→1` + `translateY(24px→0)`, `640ms cubic-bezier(0.22, 1, 0.36, 1)`, at 15% intersection, `once: true`. Children stagger 70ms, capped at six.
- H1 on load: the upright clause fades up over `700ms`; the italic gold phrase follows at `+180ms` on the same curve. That single beat of delay is the page's only choreographed moment — do not add a second.
- Offer strip: the three columns stagger in at 90ms intervals after the deck.
- Process rule (§4): the gold vertical line draws top-to-bottom via `scaleY` over `900ms ease-out` when the section enters.
- Buttons and cards: `border-color`, `background`, `transform` at `180ms ease-out`.
- Canvas: continuous but slow — nothing in it completes a visible cycle in under 20 seconds.
- **`prefers-reduced-motion: reduce` resolves to one behaviour: scroll-triggered reveals are removed entirely, not shortened.** Every section renders at `opacity: 1` in its final position from first paint, and the reveal `IntersectionObserver` is never constructed. The H1 has no staged entrance. The process rule is drawn at full height. The hero video is replaced by its poster. The canvas renders its static gradient. Hover *colour* changes stay — they are state feedback, not motion; hover *transforms* do not.

Subscribe to the preference, do not read it once:

```js
const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
const [reduced, setReduced] = useState(mq.matches);
useEffect(() => {
  const onChange = () => setReduced(mq.matches);
  mq.addEventListener("change", onChange);
  return () => mq.removeEventListener("change", onChange);
}, []);
```

An empty-dependency `useEffect` that reads `mq.matches` once never re-runs when the user flips the OS setting with the page open.

## Build notes
- **Stack** — React + Tailwind. Tokens as CSS custom properties on `:root`, mapped into `tailwind.config`. Dark page: `color-scheme: dark`, and paint `body` with `--ink` explicitly so the area below the hero never borrows a light system background. No animation library, no scroll library — `IntersectionObserver` for reveals, CSS keyframes for the rest, plain component state for the form.
- **Assets** — this clause is as strict as the no-invented-client clause. The page renders **one media box** and nothing else:

  | Asset | Count | Aspect | Intrinsic size | Default when not supplied |
  |---|---|---|---|---|
  | Hero poster | 1 | 16:9 | 1920 × 1080 | A `--ink` block with the three-layer scrim stack still applied, so contrast and layout are identical |
  | Hero video | 1 | 16:9 | 1920 × 1080 | **Omit the `<video>` entirely** and render the poster; add it only when `{{hero_video}}` is supplied |

  The hero box reserves its space from CSS alone — `width: 100%`, `aspect-ratio: 16 / 9`, `object-fit: cover` inside a `min-height: 100svh` hero — so CLS is 0 with no media present at all. When a real file is supplied the `<img>` keeps that rule *and* carries matching `width`/`height` attributes.

  There are **no other images**: no project screenshots, no logos, no illustrations. §7's cards are type and a status tag. Do not substitute inline-SVG wireframes, stock photography, generated UI mockups, or anything that could be mistaken for a real client's product. Every remaining visual is either the §4 canvas or an inline glyph, and each glyph is described in **Copy → Alt text**: a filled gold dot 6px across on the capsule; a 12px downward chevron on the budget select; a 16px circular spinner arc, 270° in `--gold`; a 14px triangular warning mark beside field errors; and a 12px `↗` north-east arrow on off-site controls.
- **Fonts** — no font files ship with this prompt, so do not write an `@font-face` block pointing at files you do not have. Load Playfair Display 700 **normal and italic** and Inter 400/600 from Google Fonts with `display=swap`. In a plain Vite or HTML build that is a `<link>` to `fonts.googleapis.com` plus `<link rel="preconnect">` to `fonts.gstatic.com`. In **Next.js**, use `next/font/google` (`Playfair_Display` with `style: ["normal", "italic"]`, `Inter`) — it self-hosts at build time, needs no preconnect, and `@next/next/no-page-custom-font` lints the hand-written link anyway. Set `font-synthesis: none` on the `<h1>`.

  Georgia is the closest visual fallback for Playfair but is **not** metrically compatible — expect a reflow on swap. Reserve the headline's box with `min-height: calc(3 * 1.1em)` on the `<h1>` so the reflow costs no layout shift, and if you need the reflow gone entirely, wrap Georgia in an `@font-face` with `size-adjust` tuned to your build rather than claiming a match that isn't there.
- **Hero media** — serve the video as H.264 MP4 + WebM, ≤2.5MB, ≤1600px wide. Ship the poster as an AVIF/WebP pair sized to the hero. The poster is the LCP element: preload it with `fetchpriority="high"`. The video is never preloaded beyond metadata.
- **Form handling** — a native `<form>` posting to a server action or API route, so the page works with JavaScript disabled. Validate on blur and on submit; require request type, name, email and the bottleneck; validate email with a permissive pattern, not a strict RFC regex. Honeypot field plus a server-side timing check for spam — no CAPTCHA. Rate limit server-side per IP and per email.
- **Deferred work** — exactly one thing is deferred, and it is deferred because it is genuinely large: the §4 canvas module, dynamically imported once the section is within one viewport. Nothing else on this page is big enough for a split to be worth measuring, and §7's cards contain no imagery to defer.
- **Performance budget, with the strategy that meets it** — LCP < 2.5s on 4G with the video present (poster preloaded at high priority, video at `preload="metadata"`); CLS < 0.02 (hero box reserved by `aspect-ratio`, form card reserved by `min-height` before its content mounts, H1 box reserved against font swap); total JS < 140KB gzipped excluding the canvas chunk. The canvas holds under 6ms/frame by construction, not by hope: a fixed budget of 900 particles in two `Float32Array`s allocated once on resize, a 32×32 flow-field grid **precomputed on resize** with only its phase offset advancing per frame, zero object allocation inside the loop, `devicePixelRatio` capped at 1.5, and one batched fill per frame rather than a `beginPath` per particle. The particle positions are the only per-frame recomputation; the field, the grid and the colour ramp are all static between resizes.
- **Accessibility must-haves**
  - The H1's italic phrase is a semantic `<em>` so it is announced as emphasis, not merely styled.
  - Every form field has a visible `<label>`; every error is linked by `aria-describedby`; the radio group is a real `<fieldset>` + `<legend>` over `<input type="radio">`, arrow-key navigable.
  - Submission outcome announces via `aria-live`; on success focus moves to the confirmation heading.
  - The hero video and the §4 canvas are `aria-hidden="true"` and out of the tab order — both are decorative.
  - Pilot cards' controls and Live Project card-links have accessible names equal to the project name, never "view" or "read more".
  - `{{email}}` is present as a `mailto:` no-JS fallback for the entire form.
  - **Verify text-over-photo contrast against the brightest video frame**, not the poster, and re-verify after any media swap.
  - The skip link is the first focusable element, since the page has no navigation.
  - Error colour is always paired with a glyph and message text.
- **Breakpoints** — `1120px` (container caps), `1024px` (What I Build 2→1, integrations 3→2), `768px` (offer strip 3→1, video → poster, canvas → static gradient, work cards 3→1), `480px` (form full-bleed). The offer strip holds 3-up down to 768px because at 800px viewport the three columns resolve to ≈213px each, which fits every supplied statement in three lines at `0.9375rem`/1.5; below that they would go to four.
- **Mobile behaviour**
  - The offer strip becomes one column with order preserved — primary, fallback, sales model. The sales-model column is never the one that gets truncated.
  - The H1 keeps its three hard-broken lines down to 400px, below which the clamp floor of `2.5rem` engages and the italic phrase may wrap internally while still starting on its own line.
  - Below 768px the hero video is replaced by its poster; the scrim stack and every contrast ratio stay identical.
  - The inquiry form card goes full-bleed with 20px gutters and `font-size: 16px` inputs.
  - §3's cards and §5's integration groups stack to one column; tool chips wrap rather than scroll.
  - §4's canvas is the static gradient below 768px — it is never worth the battery on a phone.
  - Buttons go full width at 48px tall, stacked with 12px gaps in the closing band. All targets ≥44px.

## Acceptance checks
- The H1 renders in Playfair Display 700 at 72px at 1440px, on exactly three lines, with the final clause in a **real italic face** inside an `<em>` in `--gold` and isolated on its own line. Disable the italic file and confirm the phrase fails to render as a slanted upright — `font-synthesis: none` is in force.
- Sampling the three brightest regions the hero text crosses, on the lightest frame of the video, returns ≥4.5:1 for the deck and ≥3:1 for the H1 with all three scrim layers applied. The same sampling passes with the video absent and only the poster showing.
- No text anywhere uses `--gold-50`, and no label or caption uses white below 55% alpha.
- The three-offer strip shows exactly three labelled columns, the third of which states the async-only sales model, and collapses to one column below 768px in the same order.
- §3 renders exactly six cards, each with three outcome items, and every one of those strings comes from **Copy**.
- Submitting with a missing required field flags only that field on blur, announces the error, preserves every other value, and the disabled-state hint names the first missing field in form order.
- A forced submission failure surfaces the `{{email}}` fallback, and the form still submits with JavaScript disabled.
- With `prefers-reduced-motion: reduce`, every section is at full opacity in its final position from first paint, no reveal observer is constructed, the hero shows the poster, the H1 has no staged entrance, and §4 renders as a static gradient. Toggling the OS setting with the page open changes the behaviour without a reload.
- The page contains no navigation bar and exactly four distinct **conversion** CTA labels — `Send Inquiry`, `View Selected Work`, `Request Async Teardown`, `View Pilot Build` — each a transparent 10px-radius gold-bordered button. In-form controls (`Try again`) and the theme-free chrome are not counted; they are not conversion points.
- No control on the page links to `#` or to a destination outside the anchor table under **Layout**. A `Live Project` card with no `{{work-0N-url}}` renders no link and no control rather than a dead one.
- Keyboard-only traversal starts at the skip link and reaches every field, card and button with a visible focus ring at ≥3:1 against its backdrop.
- The page renders exactly one media box. Throttle to slow 3G with no media files present and CLS stays under 0.02.
- Every string the page renders comes from **Copy**, or is one of the listed placeholders. The only builder-authored content on the page is the three `{{work-0N-*}}` values and the `{{integrations.*}}` tool names, all of which must be real.

More like this