Landing Pagegpt-5.5verified 20/20confirmed cross-check
Stack Deck
Pinned 3D card deck that stacks and expands on scroll, with animated stat counters
The exact prompt
DESIGN BRIEF — "Stack Deck"
Build a product landing page for a fictional release-engineering platform called
"Harbour". The centrepiece is a pinned deck of five cards that physically stack as you
scroll, then fan out into a bento grid at the end.
A. THE DECK
- Structure: `<section class="deck-wrap">` at 500vh containing a
`position: sticky; top: 0; height: 100vh` inner stage. Progress
p = clamp(scrolled / (wrapHeight - viewportHeight), 0, 1).
- Five cards, each 460x300 (max-width 88vw), absolutely centred, with
`transform-style: preserve-3d` and `perspective: 1400px` on the stage.
- Choreography, driven by p, all via transform (never top/left):
* For card i (0-indexed), its "arrival" happens in the window
[i*0.16, i*0.16 + 0.16]. Before arrival it sits at translateY(60vh) scale(.92)
rotateX(18deg) with opacity 0. On arrival it eases to translateY(-i*14px)
scale(1 - i*0.012) rotateX(0) opacity 1 — so each new card lands slightly
above and slightly smaller than the one before, forming a visible deck edge.
* Cards already landed recede: their brightness drops by 5% per card stacked on
top of them (use filter: brightness()).
* Between p = 0.82 and 1.0 the deck "deals": the five cards fan out to a bento
layout of preset final positions (a 3+2 arrangement) with a 2deg alternating
rotation, using a smoothstep on the last window.
- Each card has: a coloured top hairline, a small index label "01"–"05", an <h3>,
two lines of body copy, and a distinct inline-SVG diagram drawn with strokes only
(a pipeline, a branch tree, a gauge, a timeline, a shield). Cards are glass:
rgba(255,255,255,.045), 1px rgba(255,255,255,.09) border, border-radius 18px,
backdrop-filter blur(10px), and a soft 40px shadow.
- Add a small "1 / 5" progress readout pinned to the bottom of the stage whose number
is the index of the most recently landed card.
B. STAT COUNTERS
- Below the deck, a 4-up stat row: "12,400 deploys a day", "38s median release",
"99.98% success rate", "0 rollback surprises". Counters animate 0 → target with
easeOutExpo over 1.8s on first intersection, formatted with thousands separators.
The "%" and "s" suffixes are separate <span>s so the number can animate cleanly.
C. THE REST OF THE PAGE
- <header>: sticky blurred bar. Wordmark "HARBOUR" with an inline SVG anchor glyph.
Nav "Product", "Pricing", "Changelog", "Docs". Right: "Sign in" + solid #6366f1
pill "Start free".
- Hero above the deck: <h1> clamp(2.5rem, 7vw, 5.2rem) weight 650 letter-spacing
-0.03em: "Ship on Friday. / Sleep on Saturday." with the second line in
rgba(237,238,244,.42). Paragraph max-width 560px: "Harbour turns your release
process into a pipeline you can actually read." Two buttons: solid "Start free",
bordered "Watch the 2-min tour".
- A closing CTA band: <h2> "Your next release is already written." and one button.
- <footer>: wordmark + description, three link columns, a bottom row with
"© 2026 Harbour Labs" and a status pill "All systems operational" with a green dot.
D. SYSTEM
- Palette: base #08090f, surface #101223, ink #edeef4, muted rgba(237,238,244,.58),
accent #6366f1, secondary #22d3ee, plus five card hues
(#6366f1, #22d3ee, #f472b6, #facc15, #34d399).
- Fonts: system sans for UI; "Instrument Serif" via Google Fonts for the h1 second
line and the h2s only.
E. ROBUSTNESS
- Recompute the deck rect on resize (debounced 150ms) and on orientationchange.
- With prefers-reduced-motion: reduce: the deck-wrap collapses to auto height, the
sticky stage becomes static, all five cards render in a plain vertical stack at
their final fan-out positions, and the counters jump straight to their targets.
- Guard the whole scroll engine so that if IntersectionObserver is unavailable the
page still renders everything in final state.
---
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 (14)
- exactly 5 deck cards exist
- a sticky stage exists inside a section taller than 300vh
- card transforms change after scrolling into the deck
- four stat counters exist and end at 12400 / 38 / 99.98 / 0
- window.__DEMO__.ready becomes true within 5s
- window.__DEMO__.frames advances (>= 20 frames in 1.2s)
- window.__DEMO__.errors is empty
- zero console errors and zero page errors
- zero failed network requests
- exactly one <h1> with non-empty text
- header, main, footer landmarks present
- no horizontal overflow at 390 / 768 / 1440 widths
- no horizontal overflow after 2s of animation
- prefers-reduced-motion: reduce leaves the page usable and errors empty