Skip to content
LandingPagePrompts
Landing PageMiniMaxAI/MiniMax-M3partial cross-check

Chrome Bloom

A liquid-chrome metaball bloom drifts behind a conic-sheen italic wordmark

The exact prompt

Build one complete, self-contained `index.html` for **Bloom** — a generative brand studio landing page. Document title: `Bloom — Generative Brand Studio`. `<html lang="en">`. ONE file only: plain HTML + CSS + JS in `<style>`/`<script>`. No frameworks, no bundlers, no external media of any kind (no images, no video, no fonts other than Google Fonts, no CDN scripts). Every visual pixel is generated by CSS gradients, inline SVG, and absolutely-positioned CSS circles composited through a `filter: blur() contrast()` chain. No `<canvas>`, no WebGL, no Three.js.

**Viewport rule:** on viewports `>= 901px` wide the page is a single frame: `html, body { height:100%; overflow:hidden }` and `.page { height:100dvh; overflow:hidden }`. NO SCROLL on desktop. On viewports `<= 900px` the page may scroll vertically. No horizontal overflow at any width.

**Do NOT build:** no `<canvas>`, no WebGL, no Three.js, no Lottie, no GSAP, no jQuery, no Tailwind, no React, no images (remote or base64), no audio, no forms, no pricing tables, no testimonials, no extra sections beyond the specified header / hero / footer, no more than 3 nav links, no more than 3 footer items, no cookie banner, no scroll indicator, no hamburger menu on desktop (menu only on `<=900px`).

---

## A. WHAT IS BEING BUILT

A single-viewport landing page for a generative brand studio called **Bloom**. Behind a large italic serif wordmark sits a liquid-chrome form: exactly **6 circles** on independent orbital paths, blurred and composited through a single `filter: blur(28px) contrast(18)` chain so they read as ONE metaball mass rather than 6 separate blobs. The wordmark itself is a serif italic at large size with a conic-gradient chrome sheen applied via `background-clip: text`. A fine SVG grain overlay sits on top. A slow ~40-second hue drift rotates the chrome's tint. The frame is moody, expensive, liquid-metal — the studio calls itself a brand foundry and the page should feel like one. Header: small wordmark + 3 nav links. Hero: eyebrow chip, italic wordmark, single muted lede, one CTA. Footer: a three-item strip.

---

## B. THE BACKDROP — the chrome bloom (the ONLY animated visual besides the grain jitter)

The chrome bloom is a fixed-size composited layer, NOT a full-viewport element. It is one `<div class="bloom">` at `position:fixed; left:50%; top:50%; width: min(82vw, 1180px); height: min(82vw, 1180px); transform: translate(-50%, -50%); z-index: 1; pointer-events: none; filter: blur(28px) contrast(18); mix-blend-mode: screen; will-change: transform; contain: paint;`. Its transform is animated by JS; the **filter is set once in CSS and never re-applied per frame**. Because the bloom sits over a near-black field, the `contrast(18)` amplifies blurred edges into hard chrome rims and the adjacent circles merge into one body.

**The 6 circles.** Inside `.bloom`, six `<span class="orb orb--N">` elements where N = 1..6. Each is `position:absolute; left:50%; top:50%; width: var(--orb-size, 38%); height: var(--orb-size, 38%); margin-left: calc(var(--orb-size)/-2); margin-top: calc(var(--orb-size)/-2); border-radius: 50%;`. Each circle is filled with a **radial-gradient chrome body** so even before compositing it looks like a polished bead. The gradient (the same family for every orb, different stop offsets) is:

```
background:
  radial-gradient(circle at 32% 30%,
    #ffffff 0%,
    #f6f0e1 8%,
    #e9d8a6 18%,
    #b08a3a 38%,
    #2a1d0a 62%,
    #0a0703 88%,
    #000000 100%);
```

The 6 orbs have these sizes and starting offsets (orb-size is a percentage of the bloom container; x/y are the centerpoint offset as a percentage of container width/height; the JS orbit path will then add to these):

```
orb--1  size 42%  x -18%  y  -8%   (large, upper-left mass)
orb--2  size 34%  x  22%  y -14%   (mid, upper-right)
orb--3  size 30%  x  10%  y  18%   (mid, lower-centre)
orb--4  size 26%  x -24%  y  14%   (small, lower-left)
orb--5  size 22%  x  26%  y   6%   (small, right)
orb--6  size 18%  x  -6%  y -22%   (tiny, top-centre)
```

**Orbits.** JS reads `--t` (seconds since start) and sets each orb's `transform` to `translate(calc(baseX + r * cos(theta)), calc(baseY + r * sin(theta)))` once per animation frame. The baseX / baseY are the offsets above; the radius `r` is a per-orb percentage of container size (so the path is responsive). The angle `theta = omega * t + phase`. Six named per-orb motion rules, each fully independent:

```
orb--1  r 9%   omega 0.105 rad/s   phase 0.00
orb--2  r 7%   omega 0.146 rad/s   phase 1.10
orb--3  r 6%   omega 0.182 rad/s   phase 2.31
orb--4  r 5%   omega 0.218 rad/s   phase 3.47
orb--5  r 4.5% omega 0.260 rad/s   phase 4.62
orb--6  r 4%   omega 0.314 rad/s   phase 5.78
```

Frequencies are deliberately non-commensurate so the bloom never visibly repeats. Each orb is also given a faint `filter: brightness(0.92..1.08)` via its inline `--bri` custom property, set once in CSS and varied per orb to break perfect symmetry.

**Performance budget for the filter.** The `filter: blur(28px) contrast(18)` chain is expensive; therefore the bloom container is:
- a fixed pixel size that does NOT re-flow on scroll or resize-recalc,
- promoted to its own composited layer via `will-change: transform`,
- has `contain: paint`,
- the filter is declared in CSS **once** — the rAF loop animates `transform` on the `.bloom` container (a slow 40s hue-rotation drift) and per-orb `transform` (the orbit positions). Filter is never re-applied per frame.
- on `<= 900px` the bloom is shrunk: `width: min(120vw, 720px); height: min(120vw, 720px);` and `filter: blur(22px) contrast(16)` to keep mobile paint under budget.

**Hue drift.** A second slow animation is applied to the `.bloom` container itself: `animation: hue-drift 40s linear infinite` where `hue-drift` keyframes go `0% { filter: blur(28px) contrast(18) hue-rotate(0deg); } 50% { filter: blur(28px) contrast(18) hue-rotate(-14deg); } 100% { filter: blur(28px) contrast(18) hue-rotate(0deg); }`. The hue-rotate sits at the end of the filter chain so the chrome mass subtly tints warmer / cooler without changing position. The filter is set in keyframes, not per frame, so the compositor can keep caching it.

**Grain overlay.** A `.grain` element: `position:fixed; inset:-50%; width:200%; height:200%; pointer-events:none; z-index:5; opacity:0.07; mix-blend-mode: overlay;`. Background is an inline SVG `feTurbulence` rendered as a data-URI: `<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.92' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>`, `background-size: 180px 180px;`. Animation: `grain 1.1s steps(4) infinite` with keyframes jittering `transform: translate` among `(0,0) (-2%,1%) (1.5%,-2%) (-1%,2%)`. This is the second effect layer.

---

## C. LAYER STACK (back → front)

1. `html, body` — near-black `#0a0a0c`, forced twice (see Failure Guards).
2. `.vignette` — z-index 0, `position:fixed; inset:0; pointer-events:none;`, `background: radial-gradient(ellipse at 50% 50%, rgba(10,10,12,0) 0%, rgba(10,10,12,0) 55%, rgba(0,0,0,0.55) 90%, rgba(0,0,0,0.85) 100%);` — a deep edge falloff so the chrome bloom appears to float in a void.
3. `.bloom` — z-index 1, the 6-orb liquid-chrome composited layer (per Section B).
4. `.scrim` — z-index 2, a fixed `linear-gradient(180deg, rgba(10,10,12,0.55) 0%, rgba(10,10,12,0.12) 28%, rgba(10,10,12,0.10) 58%, rgba(10,10,12,0.78) 100%)` guaranteeing text contrast at the top and bottom of the frame.
5. `.page` — z-index 3, `position:relative; display:grid; grid-template-rows: auto 1fr auto; min-height:100dvh` (height:100dvh inside the desktop lock).
6. `.wordmark` sheen — z-index 4, the conic-gradient chrome sheen applied via `background-clip: text` on the h1 (described in section E).
7. `.grain` — z-index 5, the SVG feTurbulence overlay.

---

## D. TOKEN TABLE (defaults at ~1440px)

```
--bg:            #0a0a0c
--bg-2:          #14141a
--text:          #f4ecdc
--text-soft:     #d6c9a8
--muted:         #8b8474
--dim:           #56524a
--accent:        #e9d8a6
--accent-warm:   #f6e2a0
--accent-deep:   #a07a2a
--line:          rgba(244,236,220,0.16)
--line-soft:     rgba(244,236,220,0.08)
--chrome-hi:     #ffffff
--chrome-mid:    #e9d8a6
--chrome-lo:     #2a1d0a
--logo:          15px
--nav:           13.5px
--nav-h:         36px
--btn:           13.5px
--btn-h:         44px
--eyebrow:       12px
--h1:            clamp(64px, 9.4vw, 156px)
--h1-min:        44px
--h1-max:        168px
--lede:          17px
--foot:          12.5px
--header-y:      26px
--header-x:      44px
--hero-x:        44px
--hero-y:        48px
--copy-max:      1080px
--lede-max:      560px
--radius-pill:   999px
--radius-soft:   14px
--focus-w:       2px
--focus-offset:  4px
--bloom-blur:    28px
--bloom-contrast:18
--orb-1:         42%
--orb-2:         34%
--orb-3:         30%
--orb-4:         26%
--orb-5:         22%
--orb-6:         18%
--ease-out:      cubic-bezier(0.16,1,0.3,1)
--enter-dur:     0.95s
--soft-dur:      1.15s
--drift-dur:     40s
--grain-dur:     1.1s
--serif:         "Cormorant Garamond", "EB Garamond", Georgia, "Times New Roman", serif
--sans:          "Inter", system-ui, -apple-system, "Segoe UI", sans-serif
```

Fonts (Google Fonts ONLY, with the fallbacks listed): `Cormorant+Garamond:ital,wght@1,400;1,500;1,600` and `Inter:wght@400;500;600`, loaded with one `<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>` and one stylesheet link with `display=swap`.

---

## E. THE COMPOSITION — exact build order

**.page** is the grid container with three rows: `<header>`, `<main>`, `<footer>`.

**HEADER** — `padding: var(--header-y) var(--header-x) 0; display:flex; align-items:center; justify-content:space-between; gap:24px`.

- Left: `a.brand` (href `#`, accessible name "Bloom home"). It contains an inline SVG monogram 22×22 — a small chrome droplet: `<svg viewBox="0 0 22 22" width="22" height="22" aria-hidden="true"><defs><radialGradient id="bm" cx="35%" cy="30%" r="70%"><stop offset="0%" stop-color="#ffffff"/><stop offset="22%" stop-color="#f6e2a0"/><stop offset="55%" stop-color="#a07a2a"/><stop offset="100%" stop-color="#0a0703"/></radialGradient></defs><circle cx="11" cy="11" r="9" fill="url(#bm)"/></svg>` — followed by the wordmark text `bloom` in `var(--serif)`, italic, `font-size: var(--logo); font-weight:500; color: var(--text); letter-spacing:0.01em; font-style: italic`.
- Centre: `nav` with exactly 3 links: `work`, `studio`, `journal`. Each `href="#"`, `var(--sans)`, `font-size: var(--nav); color: var(--muted); font-weight:500; letter-spacing: 0.02em;`. Height `var(--nav-h)`, `display:flex; align-items:center; gap: 32px;`. Hover: `color: var(--text); transition: color 0.22s var(--ease-out);`.
- Right: `a.cta` (href `#`, accessible name "Start a project"), text `Start a project`. Style: `display:inline-flex; align-items:center; height: var(--btn-h); padding: 0 22px; border-radius: var(--radius-pill); font-family: var(--sans); font-size: var(--btn); font-weight: 500; letter-spacing: 0.01em; color: #14110a; background: linear-gradient(180deg, #fbf2cf 0%, var(--accent) 48%, var(--accent-deep) 100%); border: 1px solid rgba(255,255,255,0.18); box-shadow: 0 18px 44px rgba(233,216,166,0.18), inset 0 1px 0 rgba(255,255,255,0.55);`. Hover: `transform: translateY(-1px); box-shadow: 0 22px 56px rgba(233,216,166,0.26), inset 0 1px 0 rgba(255,255,255,0.7); background: linear-gradient(180deg, #ffffff 0%, #f6e2a0 50%, #c89a3a 100%);` over 0.24s `var(--ease-out)`.

**MAIN (hero)** — `display:flex; flex-direction:column; justify-content:center; align-items:center; padding: var(--hero-y) var(--hero-x) calc(var(--hero-y) + 24px); width:100%; max-width: var(--copy-max); margin: 0 auto; text-align:center; min-width:0;`. Vertically centred within the 1fr row.

1. `.eyebrow` — `var(--sans)`, `font-size: var(--eyebrow); color: var(--accent); letter-spacing: 0.22em; text-transform: uppercase; font-weight: 500; margin: 0;`. Exact copy: `Generative Brand Foundry · Est. 2024`. The middle dot is `color: var(--dim)`.
2. `h1` — EXACTLY ONE `<h1>`, `var(--serif)`, italic, `font-weight: 500; font-size: var(--h1); line-height: 0.96; letter-spacing: -0.025em; color: var(--text); margin: 24px 0 0; text-wrap: balance;`. The conic-gradient chrome sheen is applied to the h1 element via `background: conic-gradient(from 220deg at 50% 50%, #fbf2cf 0deg, #e9d8a6 70deg, #b08a3a 140deg, #f6e2a0 220deg, #ffffff 290deg, #a07a2a 340deg, #fbf2cf 360deg); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent;`. The text is also given `text-shadow: 0 1px 0 rgba(0,0,0,0.35);` for legibility on bright bloom moments. The conic gradient is slowly rotated via `@keyframes sheen { from { background-position: 50% 50%; } to { background-position: 50% 50%; } }` — the sheen does NOT visibly animate (the wordmark stays reading as a single chrome surface); rotation is implicit because the conic is drawn around the text bounding box, not the viewport. Exact copy, a single line, max 2 lines on narrow screens: `Brands, in liquid metal.`
3. `.lede` — `var(--sans)`, single paragraph, `font-size: var(--lede); line-height: 1.55; color: var(--text-soft); margin: 22px auto 0; max-width: var(--lede-max); font-weight: 400; letter-spacing: 0.002em;`. Exact copy: `Bloom designs living identity systems — marks, type, motion and chrome — for studios that ship faster than the brand book can keep up.`

**FOOTER** — `padding: 18px var(--header-x) 22px; display:flex; align-items:center; justify-content:space-between; gap: 20px; border-top: 1px solid var(--line-soft); background: linear-gradient(180deg, rgba(10,10,12,0) 0%, rgba(10,10,12,0.55) 100%);`.

- Left: mono-styled `var(--foot)`, `color: var(--muted); font-family: var(--sans); font-weight: 500; letter-spacing: 0.01em;`. Exact copy: `© 2026 Bloom Studio`.
- Centre: a single `span.foot-mark` — `color: var(--muted); font-size: var(--foot); font-family: var(--sans); font-weight: 500;` with a 6×6 `display:inline-block; border-radius: 50%; background: var(--accent); box-shadow: 0 0 10px rgba(233,216,166,0.55); margin-right: 8px; vertical-align: 1px;` and the text `Now booking · Q2 2026`.
- Right: exactly 3 links `dribbble`, `instagram`, `are.na`. `var(--sans)`, `var(--foot)`, `color: var(--muted); font-weight: 500; letter-spacing: 0.01em;`, `gap: 22px`, `href="#"`. Hover: `color: var(--text); transition: color 0.22s var(--ease-out);`.

---

## F. THE UI LANGUAGE

There is exactly ONE button style in the page (the header CTA) — the chrome-pill: 999px radius, 1px `rgba(255,255,255,0.18)` border, a 3-stop linear gradient `#fbf2cf → #e9d8a6 → #a07a2a`, dark text `#14110a`, outer accent glow, inner top highlight. Hover: lift -1px, swap to a brighter gradient, deepen the glow over 0.24s `var(--ease-out)`. Nav links are plain sans text — no pills, no backgrounds, no underline ever; hover swaps colour to `var(--text)`. Footer links: same treatment in `var(--foot)`. Eyebrow is a tracking-heavy small-caps accent line. Selection: `::selection { background: rgba(233,216,166,0.30); color: #14110a; }`. Every interactive element gets `:focus-visible { outline: var(--focus-w) solid var(--accent); outline-offset: var(--focus-offset); border-radius: 6px; }`. No element on the page ever shows a default blue focus ring or a text underline.

---

## G. MOTION — entrance stagger + named keyframes

All entrance animations: `animation-duration: var(--enter-dur); animation-fill-mode: both; animation-timing-function: var(--ease-out); animation-delay: var(--d, 0.08s)`. The `.appear` class is applied to each animated element with a modifier class selecting keyframes and an inline `--d`.

Stagger table (element → modifier → --d):
```
brand             appear--fade   0.08s
nav link 1 work   appear--fade   0.16s
nav link 2 studio appear--fade   0.22s
nav link 3 journal appear--fade  0.28s
header cta        appear--lift   0.34s
eyebrow           appear--soft   0.50s
h1                appear--bloom  0.66s   (duration 1.20s)
lede              appear--soft   0.96s   (duration 1.10s)
footer left       appear--fade   1.18s
footer centre     appear--fade   1.24s
footer right      appear--fade   1.30s
```

Named keyframes (all end at opacity 1 / identity transform):
```
in-fade   from { opacity: 0 }                                            to { opacity: 1 }
in-soft   from { opacity: 0; transform: translateY(12px) }               to { opacity: 1; transform: none }
in-lift   from { opacity: 0; transform: translateY(10px) scale(0.97) }   to { opacity: 1; transform: none }
in-bloom  from { opacity: 0; transform: translateY(18px) scale(0.985); filter: blur(6px); }
           to  { opacity: 1; transform: none; filter: blur(0); }
```

The H1 `in-bloom` rise mirrors the way a molten form settles — the type enters with a faint blur that resolves into the chrome sheen. The CTA `in-lift` carries the only transform:translateY + scale on a button.

Continuous keyframes:
- `hue-drift` — see Section B. 40s, linear, infinite. Sits on `.bloom`. The filter is declared in keyframes (so it is cached by the compositor), not re-applied by JS.
- `grain` — see Section B. 1.1s, steps(4), infinite. Sits on `.grain`. Only `transform` is animated.
- `sheen` — declared on the h1 so the conic gradient's `background-position` is animated; in practice the conic is fixed relative to the text bounding box so the visible effect is a stable chrome surface with a barely-perceptible highlight drift. `0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } ` over 18s linear infinite. If this risks distracting from the wordmark it may be removed; the wordmark still reads as chrome without it.

The orb orbits, the hue-drift, the grain, and the sheen run continuously, independent of the entrance stagger. The orb orbit positions are written by JS per rAF tick (see Section J).

---

## H. RESPONSIVE TABLE — exact token overrides per breakpoint

```
>= 1600px:
  --h1-max: 188px  --logo: 16px  --nav: 14px  --nav-h: 38px
  --btn: 14px  --btn-h: 46px  --lede: 18px  --foot: 13px
  --header-y: 32px  --header-x: 60px  --hero-x: 60px
  --copy-max: 1240px  --lede-max: 620px

>= 1920px:
  --h1-max: 220px  --header-x: 76px  --hero-x: 76px
  --copy-max: 1380px  --header-y: 38px  --lede: 19px

1280px – 1599px:
  --h1-max: 168px  --header-x: 48px  --hero-x: 48px
  --copy-max: 1120px

901px – 1279px:
  --h1-min: 56px  --h1-max: 132px  --nav-h: 34px
  --header-x: 32px  --hero-x: 32px
  --copy-max: 920px  --lede: 16px  --lede-max: 520px

>= 901px AND max-height 850px:
  --h1-min: 52px  --h1-max: 120px  --hero-y: 28px
  --header-y: 18px  --lede: 15px  (h1 margin-top 16px, lede margin-top 16px)

>= 901px AND max-height 720px:
  --h1-min: 44px  --h1-max: 96px  --hero-y: 18px
  --header-y: 14px  --eyebrow: 11px  --lede: 13.5px  --btn-h: 38px

>= 901px (desktop lock, all heights):
  html, body { height:100%; overflow:hidden }  .page { height:100dvh; overflow:hidden }
  .bloom { width: min(82vw, 1180px); height: min(82vw, 1180px);
           filter: blur(28px) contrast(18); }

<= 900px:
  no vh lock; page may scroll; nav becomes a full-viewport overlay menu:
  - header keeps brand + burger button (<button class="burger" aria-label="Open navigation" aria-expanded="false">, three 18×1.5px bars in var(--text), gap 5px)
  - .menu { position:fixed; inset:0; z-index:50; background: rgba(10,10,12,0.94);
            backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
            display:flex; flex-direction:column; align-items:flex-start; justify-content:center;
            padding: 0 32px; gap: 26px;
            transform: translateY(-100%); transition: transform 0.45s var(--ease-out); }
  - .menu.open { transform: none }
  - menu shows the 3 nav links stacked at --nav: 22px plus the CTA pill
  - Escape key, link click, and resize >900px all close it
  --h1-min: 44px  --h1-max: 96px  --header-x: 24px  --hero-x: 24px
  --copy-max: 100%  --lede: 16px
  .bloom { width: min(120vw, 720px); height: min(120vw, 720px);
           filter: blur(22px) contrast(16); }
  .bloom { top: 56%; }   /* bias bloom down so wordmark reads on top of it */

<= 560px:
  --h1-min: 38px  --h1-max: 80px  --eyebrow: 11px
  --lede: 15px  --header-x: 20px  --hero-x: 20px
  footer becomes flex-direction:column; align-items:flex-start; gap:10px
  header CTA is hidden (it lives inside the menu on mobile)
  .bloom { width: min(160vw, 560px); height: min(160vw, 560px);
           filter: blur(20px) contrast(15); }
```

The orb sizes and orbital radii are CSS custom properties on the `.bloom` container; on <=900px they shrink to `--orb-1: 36%, --orb-2: 30%, --orb-3: 26%, --orb-4: 22%, --orb-5: 18%, --orb-6: 16%` and the JS orbit radii are divided by 1.3 so the metaball mass stays compact.

---

## I. FAILURE GUARDS — the page is never blank, never broken

1. **Black-first:** the FIRST CSS rule is `html, body { background:#0a0a0c !important; color:#f4ecdc }`; the body tag carries `style="background:#0a0a0c;color:#f4ecdc"`; a later rule restates `html, body { background:#0a0a0c; background: var(--bg, #0a0a0c) }`.
2. **Resting opacity is 1:** every `.appear` element's un-animated computed style is its final state (opacity 1, no transform). Animations use `fill-mode: both` only to hold the FROM state during the delay. If CSS animations fail or JS never runs, the page renders complete and readable. The 6 orbs sit at their base offsets in CSS (no animation needed) and JS only adjusts `transform`. If JS never runs, the bloom is still visible.
3. **rAF entrance fallback:** after two `requestAnimationFrame` ticks, for every `.appear` element check `el.getAnimations({ subtree: false })`; if none has `playState` `"running"` or `"finished"`, add `.is-in` to every `.appear` element. `.is-in { animation: none !important; opacity: 1 !important; transform: none !important; filter: none !important; clip-path: none !important }`. If the browser lacks `getAnimations`, perform the same `.is-in` fallback after the two rAFs.
4. **Bloom fallback (no filter support):** if `CSS.supports('filter', 'blur(28px) contrast(18)')` returns false, JS adds `.no-bloom` to `<html>`. CSS must then show 6 absolutely-positioned CSS circles (no blur/contrast) with `opacity: 0.85; background: var(--accent-deep); border-radius: 50%;` so the wordmark still sits on a recognisable warm form. Page remains readable; telemetry `errors` receives a short string.
5. **Reduced motion:** inside `@media (prefers-reduced-motion: reduce)`: `*, *::before, *::after { transition: none !important; animation: none !important; }`; force `.appear` to `opacity:1 !important; transform: none !important; filter: none !important; clip-path: none !important`; the JS orbit loop still runs once (paints the initial frame, sets `ready = true`, increments `frames` by 1) and then `cancelAnimationFrame`s itself; the `.bloom` filter keyframe `hue-drift` is disabled by the universal rule; the grain animation is hidden. The static frame must still show the 6 orbs at their base offsets so the page reads as designed.
6. **No console output** in the happy path: no `console.log`, no thrown exceptions; every filter and animation property read is guarded.

---

## J. THE EXACT JS (only this, vanilla, one IIFE at end of body)

1. **Telemetry first, before anything else:**
   `window.__DEMO__ = { name: 'chrome-bloom', ready: false, frames: 0, effects: [], errors: [] };`
   Push `'liquid-chrome'`, `'conic-sheen'`, `'hue-drift'`, `'grain-texture'`, and `'mobile-menu'` into `effects` once implemented (in that order). Add `window.addEventListener('error', e => window.__DEMO__.errors.push(String(e.message || e)))`.
2. **Cache DOM references once:** `document.documentElement`, `.bloom`, all 6 `.orb` nodes (in order), `.grain`, `.burger`, `.menu`, all `.menu` links, and the result of `matchMedia('(prefers-reduced-motion: reduce)')`. Never call `getBoundingClientRect` inside the rAF loop. Cache the bloom container's `clientWidth` / `clientHeight` once at startup and recompute on resize only.
3. **Orbit data table** (read-only constant in JS): an array of 6 objects `{ baseXPct, baseYPct, radiusPct, omega, phase, sizePct }` matching the orb sizes and starting offsets in Section B. On resize, divide every `radiusPct` by the orb size factor appropriate to the current breakpoint (1.0 desktop, 1.3 mobile) so the metaball mass stays compact.
4. **rAF loop:** `requestAnimationFrame` reads `t = performance.now() / 1000`; for each of the 6 orbs, compute `x = baseX + radius * Math.cos(omega * t + phase)` and `y = baseY + radius * Math.sin(omega * t + phase)`; assign `orb.style.transform = `translate(${x.toFixed(2)}%, ${y.toFixed(2)}%)``. The bloom container transform is left to CSS keyframes. On the FIRST completed paint, set `window.__DEMO__.ready = true`. Increment `window.__DEMO__.frames` by exactly 1 each rAF tick. If `document.hidden`, skip the assignment and the paint, but keep the rAF alive. If `prefersReduced.matches`, paint exactly one frame then `cancelAnimationFrame` and return.
5. **Resize handler:** one `resizeQueued` boolean; on `window.resize` set the flag and call `requestAnimationFrame` once; in the rAF callback recompute the cached bloom `clientWidth` / `clientHeight`, recompute breakpoint, update orb radius factors. No timers, no `getBoundingClientRect` per frame.
6. **Entrance fallback:** after two nested `requestAnimationFrame` callbacks following `DOMContentLoaded`, iterate every `.appear` and check `el.getAnimations`; if no animation is running or finished, add `.is-in` to every `.appear`. If `getAnimations` is missing, add `.is-in` to every `.appear` after the same two rAFs.
7. **Mobile menu:** burger click toggles `.menu.open` and `aria-expanded`; `Escape` key closes; any menu link click closes; `window.resize` to width > 900px closes and clears `aria-expanded`.
8. **Feature support check:** at startup, if `CSS.supports('filter', 'blur(28px) contrast(18)')` is false, add `.no-bloom` to `<html>` and skip the rAF loop entirely; push a string into `errors` like `'filter-blur-contrast-unsupported'`.

No other JS. No libraries. No console calls. No `setTimeout` / `setInterval`. All motion is `requestAnimationFrame` or CSS keyframes.

---

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".

Acceptance criteria (15)

  1. exactly one <h1> with the exact text 'Brands, in liquid metal.' rendered in an italic serif (Cormorant Garamond) with a conic-gradient chrome sheen via background-clip: text
  2. a fixed .bloom container holds exactly 6 absolutely-positioned .orb circles whose transforms are updated per rAF; the container applies filter: blur(28px) contrast(18) once in CSS and is animated with transform only
  3. window.__DEMO__ is initialized with name 'chrome-bloom', ready becomes true after the first painted orbit frame, frames increments once per rAF tick, effects contains 'liquid-chrome', 'conic-sheen', 'hue-drift', 'grain-texture', and 'mobile-menu', and errors stays empty in the happy path
  4. exactly 3 nav links, 1 CTA, 1 lede paragraph and 3 footer items exist with accessible names; every anchor and button has a visible :focus-visible ring and the page is single-viewport (height:100dvh; overflow:hidden) at >=901px
  5. no horizontal overflow at 390px, 768px, 1440px, or 1920px; the prefers-reduced-motion reduce block keeps the page readable and static; the entire index.html is under 90 KB and uses Google Fonts as the only network request
  6. window.__DEMO__.ready becomes true within 5s
  7. window.__DEMO__.frames advances (>= 20 frames in 1.2s)
  8. window.__DEMO__.errors is empty
  9. zero console errors and zero page errors
  10. zero failed network requests
  11. exactly one <h1> with non-empty text
  12. header, main, footer landmarks present
  13. no horizontal overflow at 390 / 768 / 1440 widths
  14. no horizontal overflow after 2s of animation
  15. prefers-reduced-motion: reduce leaves the page usable and errors empty

More landing page prompts