# Carbon

> **Category:** Landing Page
> **Effect:** A dual-direction carbon-fibre weave is traversed by a slow radial light while a graphite wordmark and electric-blue structural seam hold the composition.
> **Platform:** cmd-code (`openrouter`)
> **Model:** `stealth/space-bunny-alpha` — Space Bunny Alpha (stealth/space-bunny-alpha)
> **License:** Free / MIT — copy, paste, ship.
> **Self-contained:** yes — one `index.html`, no build step, no external media.

---

## 🎬 Live demo

Open [`public/demos/carbon/index.html`](../public/demos/carbon/index.html) — generated by the model
above from the prompt below, with no human edits to the markup.

## ✅ Verification

<!-- VERIFICATION:START -->
_Pending — this block is written by `tools/verify.mjs` after the build run._
<!-- VERIFICATION:END -->

## 📋 Prompt

```text
A. WHAT IS BEING BUILT

Build one complete, standalone index.html for a cinematic single-viewport landing page named “CARBON”. The document language is lang="en", the document title is exactly “CARBON — Woven Composites”, and the page is a real document containing one header, one main landmark, one footer, one nav landmark, exactly one h1, and no duplicate page-level headings. The visible product claim is: “Engineered fibre. Quietly radical.” The company is a fictional composites manufacturer; do not add product checkout, shopping-cart behaviour, customer accounts, external links, cookie controls, or secondary pages.

At viewport widths of 901px and above, html and body must use width: 100%; height: 100dvh; margin: 0; overflow: hidden. The stage must use width: 100%; height: 100dvh; min-height: 680px; overflow: hidden. At widths of 900px and below, the document may scroll vertically, but it must retain width: 100% and must never scroll horizontally. Support 390x844, 768x1024, 1440x900, and 1920x1080 without clipped controls or horizontal overflow.

Do NOT build a video background, GIF, raster image, remote image, base64 image, Lottie file, WebGL scene, SVG illustration, framework, component library, utility framework, animation library, or third-party CDN asset. Do not build a dashboard, configurator, ecommerce flow, multi-page navigation, modal, cookie banner, or mobile drawer. Do not use more than one h1. Do not use text generated inside canvas. Do not add horizontal overflow. Do not run continuous layout measurement. Do not animate background-position, background-size, width, height, top, left, filter, box-shadow, or colour values. Do not call getBoundingClientRect inside the animation loop.

B. THE BACKDROP

Build one full-stage backdrop with these elements:

1. One .backdrop fixed to the stage at inset: 0, z-index: 0.
2. One .backdrop-base at inset: 0. Its background colour is #080a0d.
3. Two pseudo-elements on .backdrop-base, ::before and ::after, each absolute at inset: -80px. Together they form the carbon-fibre weave. The element counts are two pseudo-elements for the base weave and one separate highlight layer.
4. The warp uses repeating-linear-gradient(90deg, #11151a 0, #11151a 12px, #050608 12px, #050608 24px, #1c2229 24px, #1c2229 36px, #080a0d 36px, #080a0d 48px). The fill uses repeating-linear-gradient(0deg, rgba(255,255,255,0) 0, rgba(255,255,255,0) 14px, rgba(0,0,0,0.48) 14px, rgba(0,0,0,0.48) 24px, rgba(255,255,255,0.035) 24px, rgba(255,255,255,0.035) 34px, rgba(0,0,0,0.18) 34px, rgba(0,0,0,0.18) 44px). Offset the horizontal fill by 12px and the vertical warp by -12px so their 12px half-period offset creates an over/under impression. Keep the gradients stationary; animate only transforms and opacity.
5. One .backdrop-vignette at inset: 0 with background: radial-gradient(ellipse 78% 72% at 50% 46%, rgba(8,10,13,0) 0%, rgba(8,10,13,0.16) 48%, rgba(8,10,13,0.76) 100%). It darkens all four corners and protects text contrast.
6. One .backdrop-light at inset: -180px; z-index: 2. Its background is rgba(226,232,240,0.13). Apply mask-image: radial-gradient(circle 360px at 50% 50%, #000 0%, rgba(0,0,0,0.94) 20%, rgba(0,0,0,0.62) 43%, rgba(0,0,0,0.18) 67%, transparent 82%); add -webkit-mask-image with the identical value. The mask reveals a light veil; it does not regenerate or repaint the weave gradients. The layer is 150% by 150%, translated through six keyframe positions, and uses will-change: transform, opacity.
7. One .blue-seam at left: 63%; top: -12%; width: 1px; height: 124%; z-index: 3. Its linear-gradient is transparent 0%, rgba(59,130,246,0.12) 13%, #60a5fa 43%, #93c5fd 55%, rgba(59,130,246,0.16) 87%, transparent 100%. Add box-shadow: 0 0 12px rgba(96,165,250,0.16). Keep the seam visible over the weave but below all typography.
8. One .grain at inset: 0; z-index: 4; opacity: 0.13; pointer-events: none. Construct it only from a 4px by 4px conic-gradient with alternating transparent and rgba(255,255,255,0.045) quadrants. Do not load image data.

The drift periods are 18s for the weave highlight, 26s for the seam pulse, and 7.5s for the grain translation. The highlight and seam use compositor-only transform animation. The grain may translate by 4px increments, but it must not animate opacity. No canvas is used, so no canvas-resolution trick, context filter, shadow blur, or per-item compositing cost applies. The per-frame budget is fewer than 3 active animated layers, zero geometry reads, zero geometry writes, zero style writes from JavaScript, and a target of 20 or more animation frames during any 1.2-second sample at 1440x900. The main rAF callback only increments window.__DEMO__.frames.

C. THE LAYER STACK

Build the stage in this exact back-to-front order:

1. .backdrop, position: fixed/absolute stage child, z-index: 0.
2. .backdrop-base and its two gradient pseudo-elements, z-index: 1 within the backdrop stacking context.
3. .backdrop-light, z-index: 2 within the backdrop stacking context.
4. .blue-seam, z-index: 3 within the backdrop stacking context.
5. .grain, z-index: 4 within the backdrop stacking context.
6. header.site-header, z-index: 20.
7. main.hero, z-index: 30.
8. div.hero-seam-label, z-index: 35.
9. footer.site-footer, z-index: 20.
10. div.edge-index at z-index: 40 for non-interactive edition metadata.

The stage establishes position: relative and isolation: isolate. All full-bleed background layers use pointer-events: none. The header, main, footer, and metadata remain keyboard reachable. Do not place a full-size transparent element over the page because it would block controls.

D. TOKEN TABLE

Define every recurring size and colour in :root with these exact values:

--font-sans: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
--font-mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
--page-x: 48px;
--page-y: 34px;
--header-height: 46px;
--footer-height: 42px;
--content-width: 1280px;
--content-max: 1680px;
--hero-top: 50%;
--hero-width: min(1120px, 78vw);
--h1-size: clamp(92px, 15.4vw, 296px);
--h1-weight: 680;
--h1-letter: -0.078em;
--h1-line: 0.78;
--eyebrow-size: 11px;
--eyebrow-letter: 0.22em;
--claim-size: clamp(20px, 1.8vw, 32px);
--claim-line: 1.18;
--body-size: 14px;
--body-line: 1.55;
--meta-size: 10px;
--meta-letter: 0.18em;
--nav-size: 11px;
--nav-letter: 0.16em;
--button-height: 46px;
--button-pad-x: 22px;
--button-radius: 999px;
--button-border: 1px;
--rule: 1px;
--seam-width: 1px;
--backdrop-grain-size: 4px;
--backdrop-weave-unit: 48px;
--motion-fast: 420ms;
--motion-medium: 820ms;
--motion-slow: 1200ms;
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
--color-void: #080a0d;
--color-carbon: #11151a;
--color-carbon-light: #1c2229;
--color-white: #f8fafc;
--color-slate: #94a3b8;
--color-slate-dark: #64748b;
--color-line: rgba(148,163,184,0.24);
--color-line-strong: rgba(148,163,184,0.46);
--color-accent: #60a5fa;
--color-accent-soft: rgba(96,165,250,0.16);
--focus-ring: #93c5fd;
--text-shadow: 0 8px 32px rgba(0,0,0,0.72), 0 1px 2px rgba(0,0,0,0.92);
--z-backdrop: 0;
--z-header: 20;
--z-main: 30;
--z-label: 35;
--z-footer: 20;
--z-meta: 40;

E. THE COMPOSITION

Header: position: absolute; top: 0; left: 0; right: 0; height: 46px; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; padding: 0 48px; border-bottom: 1px solid rgba(148,163,184,0.12); z-index: 20. The left brand is an anchor with href="#top", accessible name “CARBON home”, and exact visible copy “CARBON / 01”. Style it as 11px monospace, weight 600, letter-spacing 0.16em, color #f8fafc. The center nav contains exactly two anchors, “Materials” and “Process”, styled 11px uppercase with 0.16em tracking and 28px gap. The right header action is an anchor with href="#contact", exact copy “Start a project”, height 46px, and display: inline-flex; align-items: center; justify-self: end.

Hero: main.hero has id="top", position: absolute; inset: 46px 0 42px; display: grid; grid-template-columns: 1fr 1120px 1fr; align-items: center; padding: 0 48px; z-index: 30. The central .hero-copy has width: min(1120px, 78vw); justify-self: center. The .eyebrow reads exactly “COMPOSITE SYSTEMS / EST. 2016”. The only h1 reads exactly “CARBON” and uses the tokenized fluid type. Beneath it, insert a 1px rule with width: min(720px, 64vw), margin: 34px 0 26px, and background: linear-gradient(90deg, rgba(148,163,184,0.58), rgba(148,163,184,0.06)). The claim reads exactly “Engineered fibre. Quietly radical.” The body reads exactly “We build high-performance composite structures where low weight, exceptional stiffness, and precise finishing meet.” Place one primary anchor after the body: href="#contact", exact copy “Explore the material”, with a right-arrow glyph “→” inside an aria-hidden span. Place one secondary text link beside it: href="#process", exact copy “Our process”. The body content is constrained to 480px; no text may extend behind the 63% seam without the vignette preserving contrast.

A vertical .hero-seam-label is position: absolute; left: calc(63% + 18px); top: 50%; transform: translateY(-50%); writing-mode: vertical-rl; text-orientation: mixed; color: #93c5fd; font: 10px/1 var(--font-mono); letter-spacing: 0.18em; opacity: 0.74. Its exact copy is “TOW 6K / 2x2 TWILL / 220 GSM”.

Footer: position: absolute; left: 0; right: 0; bottom: 0; height: 42px; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; padding: 0 48px; border-top: 1px solid rgba(148,163,184,0.12); color: #94a3b8; z-index: 20. The left copy is exactly “PRECISION IN EVERY LAYER”. The center coordinates read exactly “51.5072° N / 0.1276° W”. The right copy is exactly “ISO 9001 / MATERIAL 06”, justify-self: end.

.edge-index is position: absolute; right: 17px; top: 50%; transform: translateY(-50%) rotate(180deg); writing-mode: vertical-rl; font: 9px/1 var(--font-mono); letter-spacing: 0.22em; color: rgba(148,163,184,0.5). Its exact copy is “MONOFILAMENT STUDY / 04”. It is non-interactive.

The anchor targets #contact and #process must resolve to existing visible or programmatically focusable page landmarks. Give main id="process". Put id="contact" on the primary action wrapper and tabindex="-1" so the header target remains valid without introducing a duplicate control.

F. THE UI LANGUAGE

Primary button treatment: height 46px; padding 0 22px; border: 1px solid rgba(248,250,252,0.22); border-radius: 999px; background: linear-gradient(135deg, #f8fafc 0%, #cbd5e1 100%); color: #080a0d; display: inline-flex; align-items: center; gap: 18px; font-size: 11px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase. On hover, transform: translateY(-2px); background: linear-gradient(135deg, #ffffff 0%, #94a3b8 100%); box-shadow: 0 10px 30px rgba(0,0,0,0.28). The arrow span is font-size: 16px; line-height: 1; transition: transform 420ms var(--ease-out). On hover the arrow translates 4px on the x-axis.

Secondary link: height 46px; padding: 0 4px; color: #cbd5e1; border-bottom: 1px solid rgba(148,163,184,0.42); display inline-flex; align-items: center; font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase. On hover, color: #f8fafc; border-color: #60a5fa.

Header brand and nav links have no permanent pill. Their hover colour is #f8fafc, and their underline pseudo-element scales from 0 to 1 on the x-axis. Every visible control has a 2px solid #93c5fd focus-visible outline with 4px outline offset and border-radius inherited from the control. Do not suppress focus rings. Ensure minimum target dimensions of 44px by 44px for the project link, nav links, primary action, and secondary link.

G. MOTION

Use CSS only for entrance animation. The wordmark starts at opacity 0, transform: translate3d(0, 34px, 0), and runs for 1100ms with cubic-bezier(0.16,1,0.3,1). The eyebrow, rule, claim, body, and actions use 760ms, 860ms, 920ms, 980ms, and 1040ms respectively. Do not leave any content below opacity 1.

Exact stagger table:

.site-header -> opacity 0 to 1 and translate3d(0,-12px,0) to 0 -> 0ms, duration 700ms.
.hero .eyebrow -> opacity 0 to 1 and translate3d(0,14px,0) to 0 -> 180ms, duration 680ms.
.hero h1 -> opacity 0 to 1, scale(0.985), and translate3d(0,34px,0) to 0 -> 300ms, duration 1100ms.
.hero-rule -> opacity 0 to 1 and scaleX(0.2) to 1 -> 560ms, duration 860ms.
.hero .claim -> opacity 0 to 1 and translate3d(0,18px,0) to 0 -> 640ms, duration 780ms.
.hero .body-copy -> opacity 0 to 1 and translate3d(0,14px,0) to 0 -> 740ms, duration 760ms.
.hero-actions -> opacity 0 to 1 and translate3d(0,12px,0) to 0 -> 840ms, duration 740ms.
.site-footer -> opacity 0 to 1 and translate3d(0,10px,0) to 0 -> 920ms, duration 700ms.
.edge-index -> opacity 0 to 1 -> 1100ms, duration 700ms.
.backdrop-light -> lightSweep -> 0ms, duration 18000ms, iteration-count infinite.
.blue-seam -> seamPulse -> 0ms, duration 26000ms, iteration-count infinite.
.grain -> grainShift -> 0ms, duration 7500ms, iteration-count infinite.

Named keyframes:

@keyframes reveal-up { from { opacity: 0; transform: translate3d(0, var(--enter-y, 18px), 0); } to { opacity: 1; transform: translate3d(0,0,0); } }
@keyframes reveal-title { from { opacity: 0; transform: translate3d(0,34px,0) scale(0.985); } to { opacity: 1; transform: translate3d(0,0,0) scale(1); } }
@keyframes reveal-rule { from { opacity: 0; transform: scaleX(0.2); } to { opacity: 1; transform: scaleX(1); } }
@keyframes lightSweep { 0% { transform: translate3d(-26%, -10%, 0); opacity: 0.46; } 24% { opacity: 0.82; } 50% { transform: translate3d(22%, 4%, 0); opacity: 0.64; } 76% { opacity: 0.88; } 100% { transform: translate3d(30%, 18%, 0); opacity: 0.46; } }
@keyframes seamPulse { 0%,100% { transform: translate3d(0,-7px,0); opacity: 0.28; } 50% { transform: translate3d(0,7px,0); opacity: 0.76; } }
@keyframes grainShift { 0% { transform: translate3d(0,0,0); } 25% { transform: translate3d(-4px,4px,0); } 50% { transform: translate3d(4px,-4px,0); } 75% { transform: translate3d(-2px,-2px,0); } 100% { transform: translate3d(0,0,0); } }

Set animation-fill-mode: both for entrance animations. Set will-change: transform, opacity only on the three continuously animated backdrop layers. Never animate box-shadow or filter.

H. RESPONSIVE TABLE

At 1440x900, retain the base tokens: 48px page padding, 1120px hero width, 15.4vw h1 size, 46px header, 42px footer. At 1920x1080, override --page-x: 72px; --page-y: 46px; --content-max: 1680px; --hero-width: min(1240px, 72vw); --h1-size: 296px; --claim-size: 32px. The seam remains at 63% and the h1 remains optically left of centre through the central grid column.

At 768x1024, set --page-x: 32px; --page-y: 26px; --header-height: 58px; --footer-height: 52px; --hero-width: min(680px, 82vw); --h1-size: clamp(112px, 21vw, 176px); --claim-size: 24px; --body-size: 14px. Use body height: auto; min-height: 100dvh; overflow-x: hidden. Stage min-height: 100dvh; height: auto; overflow: visible. Header becomes sticky at top with z-index 20. Hero becomes position: relative; inset: auto; min-height: calc(100dvh - 58px - 52px); padding: 112px 32px 120px; display: grid; grid-template-columns: 1fr; align-content: center. Footer remains relative. Hide the center header nav below 901px. Keep the blue seam fixed at 63%. Set the vertical seam label to display: none only in the compact layout because its 10px text is not a control and would crowd the body. The edge-index remains visible.

At 390x844, set --page-x: 20px; --page-y: 18px; --header-height: 58px; --footer-height: 64px; --hero-width: 100%; --h1-size: clamp(72px, 25vw, 104px); --h1-letter: -0.072em; --claim-size: 22px; --body-size: 13px; --button-height: 48px; --button-pad-x: 18px. Header grid becomes 1fr auto. Hero padding is 92px 20px 112px. Footer grid becomes 1fr auto; the center coordinates are display:none. Hero actions use flex-direction: column; align-items: flex-start; gap: 12px. The primary action remains 48px high. The claim max-width is 330px and body max-width is 340px. Hide the edge-index. Keep the seam at 58% on mobile so it passes through the right side of the h1. The seam label is already display:none.

At max-height: 760px and min-width: 901px, set --page-y: 20px; --header-height: 42px; --footer-height: 36px; --h1-size: clamp(84px, 14vw, 188px); --claim-size: 19px; --body-size: 12px. Hero inset becomes 42px 0 36px. The body copy max-width is 430px. Hero rule margins become 22px 0 18px.

At max-height: 700px and min-width: 901px, set --page-x: 32px; --header-height: 38px; --footer-height: 34px; --h1-size: clamp(72px, 12.5vw, 152px); --claim-size: 17px; --body-size: 11px. Hero inset becomes 38px 0 34px. The h1 line-height becomes 0.8. The rule width becomes 560px and margins become 16px 0 14px. Header project link height becomes 38px. Footer height becomes 34px.

I. FAILURE GUARDS

All animated content must have opacity: 1 and transform: none as its resting state in CSS. Animation-delay may hold an element at opacity 0 for at most 1100ms. The script must not overwrite opacity or transform on content. Use two requestAnimationFrame callbacks: the first schedules the second; the second marks telemetry ready after the browser has completed one paint opportunity. Add a 1200ms timeout fallback that also marks ready once, so a throttled background tab cannot leave ready false. The runtime must never emit console output. Catch script errors through a window error listener and append error.message strings to telemetry.

Under prefers-reduced-motion: reduce, stop entrance animation, lightSweep, seamPulse, and grainShift with animation: none !important. Keep all foreground elements at opacity: 1 and transform: none. Keep .backdrop-light at a static transform: translate3d(-8%, 0, 0) and opacity: 0.66. Keep the seam at opacity: 0.56. Do not disable the telemetry rAF counter because telemetry readiness is a runtime requirement; its callback must still perform only frames += 1. Do not use matchMedia listeners that change document structure.

J. THE EXACT JS

Place this script as the final direct child of body. It performs no DOM measurement and no style mutation:

    <script>
    (function () {
      var telemetry = {
        name: 'carbon',
        ready: false,
        frames: 0,
        effects: [
          'header-reveal',
          'eyebrow-reveal',
          'title-reveal',
          'rule-reveal',
          'claim-reveal',
          'body-reveal',
          'actions-reveal',
          'footer-reveal',
          'metadata-reveal',
          'backdrop-light',
          'blue-seam',
          'film-grain'
        ],
        errors: []
      };
      window.__DEMO__ = telemetry;

      window.addEventListener('error', function (event) {
        telemetry.errors.push(String(event.message || 'Unknown runtime error'));
      });

      var readyMarked = false;
      function markReady() {
        if (readyMarked) return;
        readyMarked = true;
        telemetry.ready = true;
      }

      requestAnimationFrame(function () {
        requestAnimationFrame(markReady);
      });

      window.setTimeout(markReady, 1200);

      function countFrame() {
        telemetry.frames += 1;
        requestAnimationFrame(countFrame);
      }
      requestAnimationFrame(countFrame);
    }());
    </script>

The full HTML must use semantic landmarks exactly once: header.site-header containing nav, main#top.hero, and footer.site-footer. Use aria-label="Primary navigation" on nav. The visible arrow span inside the primary action must be aria-hidden="true". Do not add aria-live regions. Preserve normal document order. Set background: #080a0d on html. Set body margin: 0. Set *, *::before, and *::after with box-sizing: border-box. Set button, a with font: inherit where applicable. Ensure document.documentElement.scrollWidth is not greater than document.documentElement.clientWidth at all four target viewport sizes. Keep the complete file below 90 KB and contain no console statement.

---

TECHNICAL CONTRACT (non-negotiable):

1. Deliver ONE single file: a complete, valid `index.html`. No build step, no bundler,
   no framework, no package install. It must open correctly by double-clicking the file
   and also over http://.
2. Vanilla only. No React, no Tailwind CDN, no GSAP, no Three.js, no jQuery, no Lottie.
   Plain HTML + CSS + modern JavaScript in <style> and <script> tags.
3. NO external media. No .mp4, no .webm, no .gif, no remote images, no base64 blobs of
   photos. Every visual must be generated procedurally with CSS gradients, SVG, or
   <canvas>. This keeps the page free to host and impossible to break with a dead link.
4. Google Fonts is the ONLY permitted network request, and it must be declared with a
   <link rel="preconnect"> plus a system-font fallback stack so the page still looks
   intentional offline. If you prefer, skip it and use a pure system stack.
5. Responsive and correct at 390x844 (phone), 768x1024 (tablet) and 1440x900 (desktop).
   No horizontal scrollbar at any of those widths. Nothing may overflow its container.
6. Accessibility: exactly one <h1>; real <header>/<main>/<footer>/<nav> landmarks; every
   interactive element is a <button> or <a> with an accessible name; visible :focus-visible
   ring; body text contrast ratio >= 4.5:1 against its background.
7. Motion safety: wrap all continuous motion in
   `@media (prefers-reduced-motion: reduce)` rules that reduce it to a static or
   near-static state. The page must remain fully readable and usable with motion off.
8. Performance: no layout thrash. Cache DOM reads, batch writes inside a single
   requestAnimationFrame loop, use transform/opacity for animation, and never allocate
   inside the hot loop. Target 60fps on a 2019 laptop. Total file under 90 KB.
9. Runtime telemetry hook (used by the automated verifier — implement it exactly):
   at the top of your script define
     window.__DEMO__ = { name: '<slug>', ready: false, frames: 0, effects: [], errors: [] };
   then set `ready = true` after the first paint of your main effect, increment
   `frames` once per animation frame inside your rAF loop, and push the name of each
   implemented effect into `effects`. Add a `window.addEventListener('error', ...)`
   handler that pushes messages into `errors`. Do not rename these fields.
10. Zero console output in the happy path. No console.log left behind. No uncaught
    exceptions, no failed network requests.

RESPONSE FORMAT:
Return ONLY the raw HTML inside a single ```html fenced code block. No explanation, no
preamble, no commentary before or after the fence. The file must be complete and
immediately runnable — never truncate, never write "// rest of code here".
```

---

*LandingPagePrompts Prompt Library — free, verified, model-attributed.*
