Skip to content
VibeFather
Join

2 cases built from this template

Same prompt, different [VARIABLES]. Click one to preview it above.

About this template

A bright, airy landing page for a B2B software product, built around a hero that feels alive: a soft mesh gradient in apricot, lilac, glacier blue, butter and seafoam drifts slowly behind a big dark headline and leans toward the cursor as it moves. The gradient is one hand-written fragment shader running on the small OGL library, with a CSS fallback for browsers without WebGL and for visitors who prefer reduced motion.

Beside the headline, three glassy product panels drawn entirely in code (a close-progress card, a cash chart and a match notification) sit at different depths in a tilted 3D stack. They float in on load, tilt gently with the pointer and drift apart at different speeds as you scroll. Below the hero come a marquee of invented customer wordmarks, a counting metrics band, a four-tab feature walkthrough whose panels slide in on an auto-advancing timer, a bento of integration, API and security cards, a draggable testimonial carousel, three-tier pricing with a monthly and yearly switch, an FAQ and a closing call to action that reuses the gradient.

The default content is Fernway, a month-end close tool for finance teams, so the panels show reconciliations, checklists and variance charts with believable numbers. The layout suits founders and indie hackers launching a fintech, developer tool or any B2B product that should look polished without photography: there are no bitmaps at all, so the build stays light.

To adapt it, change the brand, slug, product and audience. The builder rewrites every headline, panel label and data point to match while keeping the four panel types, the palette and the motion. The five gradient colors live in one file, so shifting the mood toward cooler or warmer hues is a one-line change.

The template prompt

The live demo was built from exactly this text — nothing added. The other cases only change the values of the [VARIABLES].

# WebGL Gradient SaaS Landing Page

Build this website exactly as described below. Replace the [VARIABLES] with your own values; keep everything else.

## Brief
A single-page marketing site for [BRAND], [PRODUCT] for [AUDIENCE]. Light and premium: an off-white canvas, a full-bleed hand-written WebGL mesh gradient hero that flows slowly and bends toward the cursor, glassy product panels drawn in code floating at different depths beside the headline, then an invented-customer logo marquee, a metrics band, a tabbed feature walkthrough, a platform bento, a testimonial carousel, three-tier pricing, an FAQ, a closing call to action on a second gradient and a dense footer.

- Audience: [AUDIENCE] evaluating a new tool: controllers, finance leads and CFOs at 50 to 1,000 person companies who compare vendors on trust, clarity and price. Secondary: founders and marketers who want to launch their own B2B product with this look.
- Goal: Get the visitor to start a free trial or book a demo. The hero states the promise, the floating panels show the product working, the metrics and testimonials prove it, and pricing plus FAQ remove the last doubts. Every call to action is an in-page anchor; nothing submits.
- Tone: Calm, confident, specific. Short declarative sentences, concrete numbers, no hype words, no exclamation marks, no emoji. Reads like software made by people who have run a month-end close themselves.

## Stack
- Framework: Vite 5 + React 18 + TypeScript
- Styling: Tailwind CSS 3.4
- Libraries: react 18 (MIT), react-dom 18 (MIT), ogl (WebGL renderer for the mesh gradient) (Unlicense), motion (motion.dev, import from 'motion/react') (MIT), lucide-react (ISC), @fontsource-variable/instrument-sans (OFL-1.1), @fontsource-variable/inter (OFL-1.1), @fontsource-variable/jetbrains-mono (OFL-1.1), tailwindcss 3.4 + postcss + autoprefixer (MIT), vite 5 + @vitejs/plugin-react (MIT), typescript (Apache-2.0), webgl-noise 3D simplex noise snippet by Ian McEwan and Stefan Gustavson (pasted GLSL, not a package) (MIT)
- Build: `npm run build` → static files in `dist/`. No backend, no server code, no external APIs.
- Setup:
  - Scaffold with npm create vite@latest using the react-ts template. One page: index.html at the project root with entry src/main.tsx. Use vite ^5, react ^18.3, react-dom ^18.3, tailwindcss ^3.4, ogl ^1.0, and the current releases of motion and lucide-react.
  - vite.config.ts: base './', plugins [react()], build { outDir 'dist', sourcemap false, emptyOutDir true }. Do not copy src/ into dist/. package.json scripts: dev = vite, build = tsc -b && vite build, preview = vite preview.
  - Tailwind 3.4 through PostCSS (tailwindcss + autoprefixer), content ['./index.html', './src/**/*.{ts,tsx}']. In tailwind.config.ts extend colors with every Design color under kebab-case keys (canvas, surface, mist, line, ink, ink-soft, muted, logo-gray, iris, iris-tint, positive, positive-tint, caution, caution-tint, negative, negative-tint, g-cream, g-apricot, g-lilac, g-glacier, g-butter, g-seafoam). fontFamily: display ['"Instrument Sans Variable"', 'system-ui', 'sans-serif'], sans ['"Inter Variable"', 'system-ui', 'sans-serif'], mono ['"JetBrains Mono Variable"', 'ui-monospace', 'monospace']. maxWidth { container: '1200px' }. borderRadius { panel: '20px', frame: '28px', cta: '32px' }.
  - Also in tailwind.config.ts boxShadow: panel = '0 1px 2px rgba(14,21,37,0.06), 0 12px 32px -8px rgba(14,21,37,0.16), 0 40px 80px -24px rgba(76,56,160,0.22)'; lift = '0 2px 4px rgba(14,21,37,0.05), 0 24px 48px -12px rgba(14,21,37,0.18)'; card = '0 1px 2px rgba(14,21,37,0.04), 0 8px 24px -12px rgba(14,21,37,0.10)'.
  - Import the fonts once at the top of src/main.tsx: import '@fontsource-variable/instrument-sans'; import '@fontsource-variable/inter'; import '@fontsource-variable/jetbrains-mono'. Vite bundles the woff2 files into dist/assets.
  - Files: src/content.ts (every string and every data point on the page, typed), src/App.tsx, src/sections/ (Header, Hero, LogoStrip, Metrics, FeatureTabs, Platform, Testimonials, Pricing, Faq, FinalCta, Footer), src/components/MeshGradient.tsx, src/gl/noise.ts (simplex noise GLSL string), src/gl/mesh.ts (vertex and fragment shader strings), src/components/panels/ (HeroClosePanel, CashPanel, MatchToast, ReconcilePanel, ChecklistPanel, FluxPanel, AuditPanel, CodeCard), src/components/Logo.tsx, src/components/Wordmarks.tsx.
  - src/index.css: @tailwind base/components/utilities; body { background #FBFAF8; color #3A4458; font-family Inter Variable; -webkit-font-smoothing antialiased; font-feature-settings 'cv11' } ; .tnum { font-variant-numeric: tabular-nums } ; ::selection { background rgba(179,157,255,0.4) } ; section[id] { scroll-margin-top: 88px } ; html { scroll-behavior: smooth } only inside @media (prefers-reduced-motion: no-preference). Keyframes here: marquee (translateX(0) to translateX(-50%)), bob (translateY(0) -> translateY(-6px) -> translateY(0)), pulse-dot (box-shadow 0 0 0 0 rgba(18,162,107,0.45) -> 0 0 0 6px rgba(18,162,107,0)).
  - Wrap the app in <MotionConfig reducedMotion="user">. Read useReducedMotion() once in App and pass it down: when true, the shader is replaced by its CSS fallback, the marquee stops, panels do not parallax, tilt or bob, tabs and carousel do not auto-advance, and counters show final values.
  - src/gl/noise.ts: paste the 3D simplex noise function snoise(vec3) from the webgl-noise project by Ian McEwan and Stefan Gustavson (https://github.com/stegu/webgl-noise, MIT), keeping its license comment, as an exported GLSL string. This is the only third-party code inside the shader; everything else in mesh.ts is written fresh as specified in the Hero section.
  - index.html: <link rel="icon" type="image/svg+xml" href="./favicon.svg">, file in public/favicon.svg. No other head tags beyond charset, viewport, theme-color #FBFAF8 and <title>.

## Variables
- [BRAND] — Product or company name (default: "Fernway"). Shown in the header wordmark, hero subline, code sample, pricing, footer and <title>. One or two words.
- [BRAND_SLUG] — Lowercase slug for code and email (default: "fernway"). Used for the SDK package name (@[BRAND_SLUG]/sdk), the API key env var ([BRAND_SLUG] upper-cased with underscores + _API_KEY), the client variable and hello@[BRAND_SLUG].com.
- [PRODUCT] — What the product is (default: "month-end close automation"). Lower-case noun phrase used inside sentences. Drives the headline, all four feature tabs and every panel's data.
- [AUDIENCE] — Who it is for (default: "finance teams at growing companies"). Lower-case plural phrase. Drives the subline, testimonial roles, pricing seat names and metrics wording.
- [CREDIT] — keep a small "Template by VibeFather" link to https://vibefather.ai/t/webgl-gradient-saas-landing-page in the footer (default: yes; delete this line to remove it)

The copy under Pages & Sections is written for the default values. If your values differ, rewrite every headline, paragraph, label and image for them — same length, tone and structure. Layout, colors, type and motion stay as described.
Keep all copy, image paths and links in one content file (for example `src/content.ts`), keyed by section, so the content can be swapped later without touching components.

## Design
### Colors
- Canvas `#FBFAF8` — Page background, header background after scroll (at 78% opacity), footer
- Surface `#FFFFFF` — Cards, pricing cards, active tab card, solid panel backgrounds
- Mist `#F3F1EE` — Testimonials band background and the feature-tab panel stage
- Line `#E6E2DC` — Hairlines, card rings, dividers, outlined buttons
- Ink `#0E1525` — Headlines, primary pill buttons, code card background
- Ink Soft `#3A4458` — Body text, nav links
- Muted `#6B7487` — Secondary text, inactive tab titles, captions
- Logo Gray `#8A92A3` — Customer wordmarks in the logo strip
- Iris `#5B4BFF` — Single UI accent: eyebrows, text links, chart lines, check icons, focus ring base
- Iris Tint `#EEEBFF` — Chip backgrounds with Iris text
- Positive `#12A26B` — Done states, positive deltas, status dot
- Positive Tint `#E6F6EE` — Positive chip backgrounds
- Caution `#D98B06` — In-review states, flagged variance, needs-receipt
- Caution Tint `#FFF4DB` — Caution chip backgrounds
- Negative `#E5484D` — Blocked states only
- Negative Tint `#FDECEC` — Blocked chip background
- Gradient Cream `#FFF1E4` — Shader base color and CSS fallback base
- Gradient Apricot `#FF9E7A` — Mesh gradient hue 1; progress arcs start
- Gradient Lilac `#B39DFF` — Mesh gradient hue 2; chart area fills
- Gradient Glacier `#8FD3FF` — Mesh gradient hue 3
- Gradient Butter `#FFE08A` — Mesh gradient hue 4
- Gradient Seafoam `#9EECD0` — Mesh gradient hue 5

### Typography
- Display: H1, H2, prices, big numbers, tab titles, quotes (Instrument Sans Variable). H1 600 clamp(44px, 6vw, 84px)/1.02, letter-spacing -0.035em. H2 600 clamp(34px, 4vw, 56px)/1.06, -0.03em. H3 600 22px/1.25, -0.015em.: Instrument Sans (OFL), weights 500/600
- Text: body 17px/1.6 400, UI 15px 500, buttons 15.5px 600, eyebrows 13px 600 uppercase with 0.08em tracking in Iris (Inter Variable with cv11): Inter (OFL), weights 400/500/600/700
- Mono: amounts and IDs in panels (tabular), code card 13px/1.7, step numbers 12px, timestamps (JetBrains Mono Variable): JetBrains Mono (OFL), weights 400/500/600

### Layout & motion
- Spacing: 8px base. Container max-width 1200px, side padding 24px (20px under 640px). 12-column grid, 24px gutter. Sections: padding-block 128px desktop, 88px under 768px. Header 72px tall. Card padding 32px desktop / 24px mobile. Panel inner padding 20px.
- Radius: Pill (9999px) for all buttons, chips, toggles and tabs on mobile. 20px for floating product panels and small cards. 28px for bento cards, pricing cards and the tab panel stage. 32px for the final CTA frame. 12px for small tiles inside panels, 6px for table status chips.
- Motion: Two easings only: entrance [0.16, 1, 0.3, 1] (expo out) for reveals and load-in, swap [0.22, 1, 0.36, 1] for tab, carousel and price changes.
- Motion: Section reveal: every section's header block and its main grid fade and rise from opacity 0, y 24px to 1, 0 over 0.7s when 20% enters the viewport (whileInView, viewport once). Grid children stagger 0.06s.
- Motion: Hover: cards lift y -4px with shadow-card -> shadow-lift over 0.25s; primary buttons darken to #1F2940 and lift 1px; arrow icons inside links slide 3px right.
- Motion: Hero gradient flows continuously and slowly (one full visual cycle takes about 40 seconds) and bends toward the cursor with eased lag; it pauses whenever the hero is off screen or the tab is hidden.
- Motion: Floating panels: load-in with stagger, idle bob 6px, pointer tilt on a spring, scroll parallax at three different speeds (details in Hero).
- Motion: Logo marquee 38s linear loop, pauses on hover. Metrics count up once over 1.4s.
- Motion: prefers-reduced-motion: CSS gradient instead of the shader, no parallax, tilt, bob, marquee, count-up or auto-advance; reveals become a plain 0.2s opacity fade.
- Imagery: No photographs and no bitmap files at all. Everything visual is drawn in code: the WebGL mesh gradient (with a CSS radial-gradient fallback), glass product panels built from HTML and inline SVG with invented data, SVG charts and progress rings, code-drawn customer wordmarks, gradient initials avatars (no faces) and Lucide icons. The look comes from soft pastel color, frosted white glass, crisp near-black type and layered shadows.

## Pages & Sections
### Home (`index.html`)
1. **Document and shared header** — <title>[BRAND] · [PRODUCT] for [AUDIENCE]</title> with the first letter of PRODUCT capitalized ('Fernway · Month-end close automation for finance teams at growing companies'). lang 'en'. public/favicon.svg is the logo mark: 32×32 viewBox, rounded square rx 9 filled with a linearGradient at 135deg #FF9E7A -> #B39DFF -> #8FD3FF, a white stroke path 'M9 19 C 12 13, 16 11, 23 10' (stroke-width 2.6, round caps) and a white circle r 2 at (22, 21). Logo.tsx renders the same mark at 28px followed by the wordmark '[BRAND]' in Instrument Sans 600 20px, letter-spacing -0.02em, Ink, 10px gap. All copy and data come from src/content.ts. When the variable values differ from the defaults, rewrite every headline, subline, panel label, panel data point, metric, testimonial, plan and FAQ for the new [PRODUCT] and [AUDIENCE], keeping the same lengths, structure, number formats and tone. Header nav links: 'Product' (#product), 'Platform' (#platform), 'Customers' (#stories), 'Pricing' (#pricing), 'FAQ' (#faq). Right side: text link 'Sign in' (#start) and primary pill 'Book a demo' with lucide ArrowRight 16px (#start). The logo links to #top.
   Layout: DOM order in <body>: header (fixed), main > section#top (hero), section#customers (logo strip), section#metrics, section#product (feature tabs), section#platform, section#stories (testimonials), section#pricing, section#faq, section#start (final CTA), then footer. Header: position fixed, top 0, full width, z 50, height 72px; inner container 1200px, flex, logo left, nav centered (gap 32px, Inter 500 15px, Ink Soft, hover Ink), actions right (gap 20px). 'Book a demo' is the primary pill at 40px height, 18px horizontal padding, Inter 600 14.5px, white on Ink. At scrollY 0 the header is transparent over the gradient; after 24px it transitions (0.3s) to background rgba(251,250,248,0.78), backdrop-filter blur(14px) saturate(140%), and a 1px bottom border rgba(14,21,37,0.06). Under 1024px the nav and 'Sign in' collapse into a 40px round menu button (lucide Menu, toggles to X). It opens a sheet directly under the header: background rgba(251,250,248,0.96) with blur, links stacked at Instrument Sans 600 24px with 20px gaps, a full-width 'Book a demo' pill at the bottom, 24px padding. Selecting a link closes the sheet. Escape closes it; body scroll is locked while open.
   Motion: Sheet opens with height 0 -> auto and opacity 0 -> 1 over 0.3s (swap easing); links stagger in 0.04s from y 8px. Header background change is a CSS transition on background-color, border-color and backdrop-filter.
2. **Hero with mesh gradient and floating product panels** — Eyebrow chip (glass pill: background rgba(255,255,255,0.55), 1px border rgba(255,255,255,0.8), blur 12px, height 32px, padding 0 14px 0 6px, Inter 500 13.5px Ink): a small Ink pill 'New' (white text, 11.5px 600, 20px tall, 8px padding) + 'Intercompany eliminations, now automated' + lucide ArrowRight 14px; links to #product. H1 on two lines on desktop: 'Close the books in days,' / 'not weeks.' (Instrument Sans 600, clamp(44px, 6vw, 84px)/1.02, -0.035em, Ink, max-width 620px). Subline (Inter 400 19px/1.6, Ink Soft, max-width 520px): '[BRAND] is [PRODUCT] for [AUDIENCE]. Match every transaction, chase every receipt and hand your auditors a clean ledger, all from one calm workspace.' CTA row (gap 20px): primary pill 'Start free trial' (48px tall, 22px padding, lucide ArrowRight 16px) to #pricing; text link 'Book a 20-minute demo' + ArrowRight in Ink 600 15.5px to #start. Trust row (Inter 500 13.5px, Ink Soft, separated by 4px Muted dots): '14-day free trial' · 'No credit card' · 'SOC 2 Type II'. PANEL A 'Close overview' (width 440px, solid glass): top row has an 8px Positive dot + 'October close' (Inter 600 15px Ink) and on the right a chip 'Day 2 of 3' (Iris on Iris Tint, 12px 600). Below, a 64px SVG progress ring (stroke 6, track #EEEAF6, arc with linearGradient #FF9E7A -> #B39DFF, 86% filled, round cap) with '86%' in Instrument Sans 600 18px centered; to its right '34 of 39 tasks done' (Inter 600 15px Ink) over 'Sign-off expected in 26 hours' (13px Muted). A 1px Line divider, then four 40px task rows (13.5px Ink): lucide CircleCheck in Positive + 'Bank reconciliations · 12 accounts' + right 'Done' (12px Muted) + 22px initials avatar 'PN'; CircleCheck Positive + 'Accruals and prepaids' + 'Done' + 'SR'; CircleDot Caution + 'Intercompany eliminations' + 'In review' + 'LK'; Circle Muted + 'Revenue recognition' + 'Assigned' + 'OH'. PANEL B 'Cash position' (width 250px): label 'Cash position' (12.5px Muted), value '$4.82M' (Instrument Sans 600 28px, -0.02em, Ink, tnum) with a chip '+3.4%' (Positive on Positive Tint, lucide TrendingUp 12px) on the same line, then an SVG area chart 218×84 of twelve points [3.10, 3.28, 3.21, 3.56, 3.49, 3.88, 3.97, 3.81, 4.18, 4.39, 4.61, 4.82] (y domain 3.0 to 5.0): 2px Iris line with smooth monotone curve, area filled with linearGradient rgba(179,157,255,0.35) -> rgba(179,157,255,0), last point a 4px Iris dot with a 2px white ring; tiny labels 'May' at left and 'Oct' at right (11px Muted). PANEL C 'Match toast' (width 300px): 36px circle in Positive Tint holding lucide Check 18px Positive; text 'Matched 1,284 transactions' (Inter 600 14px Ink) over 'Operating ••4417 and Payroll ••0921 · just now' (12.5px Muted); a 'View' link in Iris 13px 600 at the right. Initials avatars everywhere: circle filled with a 135deg linear gradient of two palette hues (PN Apricot->Butter, SR Lilac->Glacier, LK Glacier->Seafoam, OH Butter->Apricot, DM Seafoam->Lilac), initials Inter 600 at 45% of the diameter in Ink.
   Layout: section#top: position relative, overflow hidden, min-height 880px on desktop (760px under 1024px with the stack below the text), padding-top 152px (120px mobile). The MeshGradient fills the whole section behind everything (z 0). Soft-curved bottom edge: an absolutely positioned inline SVG at the bottom of the section, full width, height 160px (72px under 768px), viewBox 0 0 1440 160, preserveAspectRatio none, path 'M0 56 C 360 150, 1080 150, 1440 56 L1440 160 L0 160 Z' filled Canvas #FBFAF8, so the gradient ends in a gentle downward bow (a curve, never a straight diagonal). Content (z 10) sits in the 1200px container on a 12-column grid: text in columns 1-6, vertically starting at the top padding; the panel stack in columns 7-12. Panel stack: a wrapper with perspective 1800px and height 540px; inside it a group with transform-style preserve-3d and transform rotateX(10deg) rotateY(-16deg) rotateZ(2deg) (plus the spring and scroll offsets). Panel A at left 6%, top 96px, translateZ(0); Panel B at right 0, top 24px, translateZ(70px); Panel C at left 0, top 392px, translateZ(130px). All three panels: background rgba(255,255,255,0.72), backdrop-filter blur(18px) saturate(160%), 1px border rgba(255,255,255,0.7), outer ring 0 0 0 1px rgba(14,21,37,0.06), shadow-panel, radius 20px, padding 20px. Under 1024px: single column, text first, then the stack centered with max-width 420px, height 440px, transform scale(0.82) from top center, tilt reduced to rotateX(6deg) rotateY(-8deg) rotateZ(0). Under 768px the H1 drops the forced line break, CTA row stacks with the primary pill full width.
   Motion: MESH GRADIENT (src/components/MeshGradient.tsx, props { seed: number; className?: string }). OGL setup: new Renderer({ dpr: Math.min(window.devicePixelRatio, 1.5) (1 under 768px), alpha: false, antialias: false }); geometry new Triangle(gl); one Program; one Mesh; canvas absolutely fills the parent (inset 0, width and height 100%). Resize with a ResizeObserver on the parent -> renderer.setSize(w, h) and update uRes. Uniforms: uTime (seconds), uRes (vec2 px), uMouse (vec2, 0..1 in uv space, y up), uStrength (float 0..1), uSeed (float), uBase #FFF1E4, uC0 #FF9E7A, uC1 #B39DFF, uC2 #8FD3FF, uC3 #FFE08A, uC4 #9EECD0 (convert hex to vec3 0..1 in mesh.ts from one exported palette array so colors change in one place). Vertex shader: pass uv as vUv, gl_Position = vec4(position, 0.0, 1.0). Fragment shader (write it this way, after the pasted snoise): float aspect = uRes.x / uRes.y; vec2 p = vec2(vUv.x * aspect, vUv.y); vec2 m = vec2(uMouse.x * aspect, uMouse.y); vec2 d = p - m; float fall = exp(-dot(d, d) * 3.2) * uStrength; p -= d * fall * 0.24; float t = uTime * 0.035 + uSeed; vec2 q = vec2(snoise(vec3(p * 0.9, t)), snoise(vec3(p * 0.9 + 4.7, t + 1.3))); vec2 w = p + q * 0.55; float n0 = snoise(vec3(w * 1.10, t * 1.2)); float n1 = snoise(vec3(w * 1.40 + 9.1, t * 0.9)); float n2 = snoise(vec3(w * 0.80 - 3.3, t * 1.1)); float n3 = snoise(vec3(w * 1.70 + 2.2, t * 0.7)); float n4 = snoise(vec3(w * 1.25 - 7.4, t * 0.8)); vec3 col = uBase; col = mix(col, uC0, smoothstep(-0.35, 0.65, n0)); col = mix(col, uC1, smoothstep(-0.10, 0.80, n1) * 0.90); col = mix(col, uC2, smoothstep(0.00, 0.85, n2) * 0.85); col = mix(col, uC3, smoothstep(0.15, 0.95, n3) * 0.70); col = mix(col, uC4, smoothstep(0.25, 1.00, n4) * 0.55); col += vec3(fall * 0.07); col = mix(col, vec3(1.0), 0.16 * (1.0 - smoothstep(0.0, 0.55, vUv.x))); float g = fract(sin(dot(gl_FragCoord.xy + fract(uTime) * 61.0, vec2(12.9898, 78.233))) * 43758.5453); col += (g - 0.5) * 0.018; gl_FragColor = vec4(col, 1.0); The swell (fall) is the 'bends toward the cursor' effect: the color field is pulled toward the pointer and brightened slightly around it. Pointer: listen to pointermove on window; target = pointer position relative to the gradient's parent rect, x = (clientX - left) / width, y = 1 - (clientY - top) / height. Each frame: mouse += (target - mouse) * 0.045; strength eases toward 1 while the pointer is inside the parent and toward 0 when it leaves (same 0.045 factor). Start with mouse at (0.7, 0.6) and strength 0. Touch or no fine pointer (matchMedia('(pointer: fine)') false): no listeners; the mouse target drifts on a slow Lissajous path, x = 0.5 + 0.28 * sin(time * 0.21), y = 0.55 + 0.2 * sin(time * 0.17), strength 0.6. Loop with requestAnimationFrame; pause when an IntersectionObserver reports the parent off screen or document.hidden is true; on unmount cancel the frame, disconnect observers and call gl.getExtension('WEBGL_lose_context')?.loseContext(). Fallback: if reduced motion is set, or creating the Renderer throws, or gl is null, render instead a div with background-color #FFF1E4 and background-image: radial-gradient(60% 70% at 18% 30%, #FF9E7A 0%, transparent 60%), radial-gradient(55% 65% at 62% 18%, #B39DFF 0%, transparent 62%), radial-gradient(60% 70% at 90% 62%, #8FD3FF 0%, transparent 60%), radial-gradient(50% 60% at 38% 88%, #FFE08A 0%, transparent 60%), radial-gradient(45% 55% at 76% 96%, #9EECD0 0%, transparent 60%), plus a left white veil linear-gradient(90deg, rgba(255,255,255,0.18), transparent 55%). The canvas fades in from opacity 0 to 1 over 0.8s on its first rendered frame so there is no flash; the fallback div sits underneath as the background until then. HERO TEXT on load (motion, entrance easing): eyebrow chip, H1, subline, CTA row and trust row each go opacity 0, y 20 -> 1, 0, duration 0.8s, delays 0.05 / 0.12 / 0.24 / 0.32 / 0.40s. PANEL STACK: load-in per panel from opacity 0, y 80px, scale 0.96 to 1, 0, 1 over 1.0s, delays A 0.20s, B 0.45s, C 0.65s. Pointer tilt: on pointermove over the hero compute nx, ny in -0.5..0.5 from the hero rect; group rotateY = -16deg + nx * 6deg and rotateX = 10deg - ny * 4deg through useSpring({ stiffness: 90, damping: 18 }). Scroll: useScroll({ target: heroRef, offset: ['start start', 'end start'] }); panel translateY maps progress 0 -> 1 to A 0 -> -60px, B 0 -> -150px, C 0 -> -220px, and the group's extra rotateX 0 -> 8deg, so the stack separates and tips back as the page scrolls. Idle bob: an inner wrapper of each panel runs the bob keyframe (A 7s, B 6s, C 8s, ease-in-out, infinite, delays 0 / 1.2 / 2.4s) so it never fights the motion transforms. Under reduced motion: no tilt, no parallax, no bob; panels just fade in.
3. **Customer logo strip** — Caption centered (Inter 500 14px, Muted): 'Trusted by 2,400+ finance teams, from seed-stage startups to public companies'. Eight invented customer wordmarks, each a small inline SVG glyph (20px tall) plus the name, all filled Logo Gray #8A92A3: 1 'Halcyon Freight': two stacked chevrons, Instrument Sans 600 19px, -0.01em. 2 'orbitlab' (lower case): a 14px circle with a tilted ellipse orbit around it, Inter 700 20px, -0.03em. 3 'Pinecrest Health': a triangle sitting on a short bar, Instrument Sans 500 18px. 4 'MOONMILK': a crescent, Inter 700 15px uppercase, 0.12em tracking. 5 'Tallow & Co.': a square rotated 45deg, JetBrains Mono 600 16px. 6 'Quarrystone': three offset stacked rectangles, Instrument Sans 600 18px. 7 'brisa foods' (lower case): a two-hump wave path, Inter 500 19px. 8 'KETTLE SUPPLY': a half circle with a small handle arc, Instrument Sans 600 15px uppercase, 0.06em tracking. These are invented companies; never use a real company's name or mark.
   Layout: section#customers sits on Canvas directly under the hero curve: padding-top 16px, padding-bottom 80px. Caption, then 32px gap, then a full-width (container width) marquee row 56px tall with mask-image linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent). The track holds the eight wordmarks twice in a row (aria-hidden on the duplicate set), items vertically centered, gap 72px. Under 768px gap 48px and wordmarks scale to 85%.
   Motion: Track animates with the marquee keyframe, 38s linear infinite; hovering the row sets animation-play-state paused and the hovered wordmark transitions to Ink over 0.2s. Reduced motion: no animation, a single set wraps centered with 40px row gap and 56px column gap.
4. **Metrics band** — Four stats (number in display type, then label, then note): '3.1 days' / 'Median time to close' / 'Down from 11.4 days before [BRAND]'. '96%' / 'Transactions matched automatically' / 'Across 38M bank lines last quarter'. '41 hrs' / 'Saved per accountant each month' / 'Self-reported by 610 customers'. '120+' / 'Bank, ERP and payroll integrations' / 'Read-only, connected in minutes'.
   Layout: section#metrics: container 1200px, padding-block 56px, 1px Line border on top and bottom of an inner wrapper. Four equal columns separated by 1px Line vertical rules, each column padding 0 32px (first column 0 left). Number: Instrument Sans 600 clamp(40px, 4.4vw, 60px), -0.03em, Ink, tnum; the unit suffix (' days', '%', ' hrs', '+') at 60% of the number size in Muted. Label Inter 500 16px Ink, 8px below. Note Inter 400 13.5px Muted, 4px below, max-width 220px. Under 768px: 2×2 grid, rules become a horizontal divider between rows, 32px gap.
   Motion: When the band is 40% in view, each number counts up from 0 to its value over 1.4s (ease-out cubic, one decimal for '3.1'), columns staggered 0.1s. Runs once. Reduced motion: final values immediately.
5. **Tabbed feature walkthrough** — Header centered, max-width 720px: eyebrow 'The platform', H2 'Everything the close needs, in the order you do it.', sub (Inter 18px Ink Soft) 'Four connected tools that share one ledger, one checklist and one audit trail.' Four tabs, each with number, title, description, three bullets and one panel: 01 'Reconcile' — title 'Match thousands of transactions before coffee.' desc 'Rules and learned patterns pair bank lines with ledger entries the moment feeds sync. You only review the exceptions.' bullets 'Auto-match on amount, reference and counterparty' / 'Split and group matches for batched payouts' / 'Receipt requests go straight to the cardholder'. Panel: card header 'Operating account ••4417' (Inter 600 15px) + chip '1,284 matched · 18 to review' (Iris on Iris Tint). Table with columns Description | Amount | Matched to | Status (header row 12px Muted uppercase 0.04em). Rows (13.5px, 44px tall, 1px Line separators; amounts JetBrains Mono tnum right-aligned): 'Cloud hosting, October' | '−$18,240.00' | 'JE-10482' | Matched; 'Customer payment, Alderline Co.' | '+$64,500.00' | 'INV-2291' | Matched; 'Payroll run #42' | '−$212,880.16' | 'JE-10477' | Matched; 'Office lease, 40 Harbor St.' | '−$22,000.00' | 'JE-10490 (suggested)' | Suggested; 'Card spend, team offsite' | '−$3,418.72' | '—' | Needs receipt. Status chips 6px radius 12px 600: Matched Positive/Positive Tint, Suggested Iris/Iris Tint, Needs receipt Caution/Caution Tint. Floating chip: 'Rule applied: payroll provider → 6010 Wages'. 02 'Checklist' — title 'A close checklist that runs itself.' desc 'Recurring tasks roll forward each month with owners, due days and dependencies already set.' bullets 'Dependencies unlock the next task automatically' / 'One-click reviewer sign-off' / 'Live progress for the controller and CFO'. Panel: three group rows with label, count and a 6px progress bar (gradient Apricot->Lilac fill on #EEEAF6 track): 'Cash' 4/4, 'Revenue' 3/5, 'Reporting' 0/4. Below, five task rows with avatar, title, due chip and state: 'Reconcile operating accounts' PN 'Day 1' Done; 'Review deferred revenue roll-forward' SR 'Day 2' In review; 'Post intercompany eliminations' LK 'Day 2' Blocked (Negative chip 'Waiting on FX rates'); 'Draft flux commentary' OH 'Day 3' To do; 'CFO sign-off' DM 'Day 3' To do. Floating chip: 'Unlocked: Draft flux commentary'. 03 'Flux analysis' — title 'Explain every swing before anyone asks.' desc '[BRAND] compares each account month over month, flags variances above your threshold and drafts a first explanation for review.' bullets 'Thresholds by account, percent or amount' / 'Drafted explanations you edit and approve' / 'Commentary flows into the board pack'. Panel: legend 'Sep' (Line #D9D5CE swatch) and 'Oct' (Iris swatch) and a note 'Threshold ±10% or $10K' (12px Muted). Five accounts as paired horizontal bars (10px tall, 4px radius, widths proportional to the larger value per row), with value labels in mono and a delta on the right: 'Software subscriptions' $48.2K -> $66.5K '+38%' (Caution, row tinted Caution Tint); 'Contractors' $120.4K -> $112.9K '−6%'; 'Travel' $18.7K -> $21.0K '+12%' (Caution); 'Payroll' $640.1K -> $652.3K '+2%'; 'Marketing' $92.0K -> $90.4K '−2%'. Overlay card (translateZ 60px, bottom right, width 280px): 'Software subscriptions +38%' (600 14px) over 'Draft: Annual renewal of the design suite posted in October. Spread over 12 months from November.' (13px Ink Soft) and two small buttons 'Accept' (Ink pill 30px) and 'Edit' (outlined). 04 'Audit trail' — title 'Hand auditors a trail, not a scavenger hunt.' desc 'Every match, edit and sign-off is time-stamped, attributed and linked to its support, ready to export.' bullets 'Immutable activity log per account' / 'Support files attached to every entry' / 'One-click PBC package export'. Panel: vertical timeline (1px Line spine, 8px dots in Iris) with six entries, time in JetBrains Mono 12px Muted on the left: '09:14' PN 'matched 212 lines on Operating ••4417'; '09:32' SR 'updated rule Payroll provider (v3 → v4)'; '10:05' LK 'attached 3 support files to JE-10490'; '11:47' OH 'requested review on Revenue recognition'; '13:20' DM 'approved Bank reconciliations'; '14:02' DM 'exported PBC package (48 files)'. Bottom: outlined pill 'Export PBC package' with lucide Download 16px. Floating chip: 'Every change signed and time-stamped'. When [PRODUCT] changes, keep the four panel archetypes (data table with status chips, grouped checklist with progress bars, paired bar comparison with a flagged row and overlay card, activity timeline with an export button) and rewrite tab names, titles, bullets and all data for the new product.
   Layout: section#product on Canvas. Header block, 64px gap, then a 12-column grid: tab list in columns 1-5, panel stage in columns 6-12, aligned top. Tab list: role tablist, vertical, gap 8px. Each tab is a button, full width, padding 20px 24px, radius 20px, text-left. Row 1: number in JetBrains Mono 12px Muted + 12px gap + title in Instrument Sans 600 20px. Inactive: transparent background, title Muted, hover title Ink Soft. Active: Surface background, 1px Line ring, shadow-card, title Ink, and below the title the description (Inter 16px/1.6 Ink Soft, 8px top margin) and three bullets (lucide Check 16px Iris, 15px Ink Soft, 8px gap). A 2px progress bar runs along the inside bottom of the active card (inset 0 24px 12px, track #EEEAF6, fill linear-gradient(90deg, #FF9E7A, #B39DFF, #8FD3FF)). Panel stage: role tabpanel, height 540px, radius 28px, overflow hidden, background Mist with three soft blobs drawn as radial gradients (rgba(255,158,122,0.40) at 15% 10%, rgba(179,157,255,0.35) at 95% 40%, rgba(143,211,255,0.35) at 40% 100%, each fading to transparent at 45%). Inside, perspective 1600px; the active panel is a glass card (same glass recipe as the hero panels, but background rgba(255,255,255,0.82)), width 88%, centered, rotateX(4deg) rotateY(-6deg). Each panel's floating chip is a small glass pill (Inter 600 12.5px Ink, lucide Sparkles 14px Iris) positioned top-right outside the card edge at translateZ(60px). Under 1024px: the tab list becomes a horizontal, scroll-snapping row of pill chips (height 40px, Inter 600 14px; active chip Ink with white text) above the stage; the active tab's description and bullets render under the chips; stage height 420px, no tilt, panel width 94%, tables drop the Matched to column.
   Motion: Auto-advance every 7s: the active tab's progress bar fills from 0 to 100% linearly over 7s, then the next tab activates (loops). Hovering or focusing anything inside the section pauses the timer and the bar; clicking a tab selects it and pauses auto-advance for 15s. Arrow Up/Down (Left/Right on mobile) move between tabs. Panel swap: AnimatePresence mode 'popLayout'; entering panel from opacity 0, x 32px, rotateY -14deg to its resting tilt; exiting panel to opacity 0, x -24px; 0.5s swap easing. Panel rows stagger in 0.04s from y 8px. Description and bullets of the active tab expand with height 0 -> auto over 0.35s. The floating chip bobs (6s). Reduced motion: no auto-advance, bar hidden, panels crossfade only.
6. **Platform bento** — Header left-aligned (max-width 640px): eyebrow 'Built to fit', H2 'Fits the stack you already run.', sub 'Connect bank feeds, your ERP and payroll in an afternoon. Everything stays read-only until you say otherwise.' Card 1 'Integrations': title (H3) '120+ read-only integrations', text 'Bank feeds, card programs, payroll, billing and ERPs sync every 15 minutes. CSV and SFTP for everything else.' and a 6×2 grid of 56px tiles (radius 16px, Surface, 1px Line ring, shadow-card), each holding a lucide icon 24px in Ink Soft with a 11.5px Muted label under the tile: Landmark 'Banks', CreditCard 'Cards', Users 'Payroll', Receipt 'Billing', Building2 'ERP', FileSpreadsheet 'CSV', Wallet 'Wallets', Globe 'FX rates', Banknote 'Payouts', Database 'Warehouse', Calculator 'Tax', Lock 'SFTP'. Generic labels only, never real company names or logos. Card 2 'Developer API' (dark): title 'An API for everything in the UI' (white), text 'REST endpoints and webhooks for every object, with typed SDKs.' (rgba(255,255,255,0.7)), then a code window: top bar with three 10px dots (#3A4458), a tab label 'sync.ts' (JetBrains Mono 12px, rgba(255,255,255,0.6)) and a copy button (lucide Copy 16px, swaps to Check for 1.6s after copying; wrap navigator.clipboard in try/catch). Code (JetBrains Mono 13px/1.7), for the defaults: line 1 '// Start a reconciliation from your own tools' ; line 2 'import { Fernway } from "@fernway/sdk";' ; line 3 blank ; line 4 'const fernway = new Fernway({ apiKey: process.env.FERNWAY_API_KEY });' ; line 5 blank ; line 6 'const run = await fernway.reconciliations.create({' ; line 7 '  account: "operating-4417",' ; line 8 '  autoMatch: true,' ; line 9 '});' ; line 10 blank ; line 11 'console.log(run.matched, run.needsReview); // 1284 18'. Build the class name from [BRAND] in PascalCase without spaces, the package from '@[BRAND_SLUG]/sdk', the env var from [BRAND_SLUG] upper-cased with hyphens turned into underscores + '_API_KEY', and the client variable from [BRAND_SLUG] in camelCase; rewrite the resource, method, fields and comment for [PRODUCT]. Token colors: comments #6B7487, keywords (import, from, const, new, await) #C4B5FD, strings #FFD49A, properties and functions #8FD3FF, numbers and booleans #FF9E7A, plain #E8EAF0. Under the code: '99.98% API uptime over the last 90 days' (12.5px rgba(255,255,255,0.6)) with a pulsing 6px Positive dot. Card 3 'Security': title 'Controls your auditors will like', text 'Granular roles, approvals and a full log of who changed what, with data kept in the region you choose.' and six chips in a 2×3 grid (Surface, 1px Line, pill, 40px tall, lucide ShieldCheck 16px Positive + Inter 500 14px Ink): 'SOC 2 Type II', 'SSO, SAML and SCIM', 'Role-based approvals', 'AES-256 at rest', 'US or EU data residency', 'Read-only bank access'.
   Layout: section#platform on Canvas. Header, 56px gap, then a 12-column grid with 24px gap and two rows: Card 1 columns 1-7 row 1; Card 2 columns 8-12 spanning rows 1-2; Card 3 columns 1-7 row 2. Cards 1 and 3: Surface, radius 28px, 1px Line ring, shadow-card, padding 32px. Card 2: background Ink #0E1525, radius 28px, padding 32px, the code window inside with background #151D30, 1px border rgba(255,255,255,0.08), radius 16px, padding 20px, overflow-x auto. Card 1 tile grid sits below the text with 28px top margin, 6 columns, 16px gap. Card 3 is two columns inside: text left, chip grid right. Under 1024px every card spans the full width in order 1, 2, 3; Card 1 tiles become 4 columns; Card 3 stacks.
   Motion: Cards hover-lift (y -4px, shadow-lift). Integration tiles float with the bob keyframe at 6s, each delayed by its index × 0.35s, amplitude 4px (use a variant of bob with -4px). Code lines reveal once in view: each line fades from opacity 0, x -6px with 0.05s stagger. Reduced motion: no tile float, code shows immediately.
7. **Testimonial carousel** — Header centered: eyebrow 'Customers', H2 'Finance teams close calmer with [BRAND].' Four slides (quote, avatar initials, name, role and company, metric chip): 1 Dana Okafor (DO), VP Finance, Halcyon Freight: 'We used to lose the first week of every month to spreadsheets. Now the bank side is done before our Monday stand-up, and we spend the time on the numbers that actually moved.' chip 'Close: 12 → 4 days'. 2 Marcus Lindqvist (ML), Corporate Controller, Pinecrest Health: 'Our auditors asked for the PBC list and I sent them one link. They finished fieldwork two weeks early, and their only question was which tool we were using.' chip 'Audit fieldwork: 2 weeks faster'. 3 Ines Carvalho (IC), CFO, Moonmilk: 'Three entities, two currencies, one accountant. Intercompany used to take her two days. It now takes an hour, and I can see exactly where the close stands from my phone.' chip 'Intercompany: 2 days → 1 hour'. 4 Theo Barnes (TB), Senior Accountant, Kettle Supply: 'The receipt chasing alone paid for it. People get a nudge the day the card swipes, not three weeks later when nobody remembers the lunch.' chip 'Missing receipts: −81%'. Avatar gradients: DO Apricot->Butter, ML Lilac->Glacier, IC Seafoam->Glacier, TB Butter->Lilac; initials in Ink. Counter '01 / 04' in JetBrains Mono 13px Muted.
   Layout: section#stories: full-bleed Mist #F3F1EE background, padding-block 128px. Header, 56px gap, then a carousel frame max-width 880px centered, overflow hidden. Slide: a code-drawn quote mark (two 18×24px rounded shapes filled with linear-gradient #FF9E7A -> #B39DFF) on top, 24px gap, quote in Instrument Sans 500 clamp(24px, 2.8vw, 36px)/1.3, -0.02em, Ink; 40px gap; bottom row: 48px initials avatar + name (Inter 600 16px Ink) over role and company (Inter 400 14px Muted), and on the right the metric chip (pill, 36px tall, Surface background, 1.5px gradient border made with the padding-box/border-box background trick using linear-gradient(135deg, #FF9E7A, #B39DFF, #8FD3FF), Inter 600 13.5px Ink, tnum). Controls row 48px below the slide: left the dots (8px circles in #D9D5CE; the active one widens to a 24px pill filled with the Apricot->Lilac gradient) and the counter; right two 44px round buttons (Surface, 1px Line ring, lucide ArrowLeft and ArrowRight 18px Ink, hover Ink background with white icon). Under 768px the metric chip moves under the name row and the quote is 22px.
   Motion: Slides change with AnimatePresence and a direction value: entering slide from x ±80px, opacity 0 to x 0, opacity 1; exiting to x ∓80px, opacity 0; 0.55s swap easing. The slide is draggable on x (motion drag='x', dragConstraints {left: 0, right: 0}, dragElastic 0.18): onDragEnd, offset.x < -80 or velocity.x < -400 goes next, the mirror goes previous. Auto-advance every 9s, paused while hovered, focused or dragging. Left/Right arrow keys work when the carousel has focus (tabIndex 0, aria-roledescription 'carousel', each slide aria-label 'n of 4'). Reduced motion: no auto-advance, slides crossfade.
8. **Pricing** — Header centered: eyebrow 'Pricing', H2 'Simple plans that grow with your team.', sub 'Every plan includes unlimited transactions and a 14-day free trial.' Billing toggle: segmented pill with 'Monthly' and 'Yearly' and, next to 'Yearly', a chip 'Save 20%' (Positive #0E7A50 text on #DDF7EC). Default Monthly. Starter: 'For lean teams running their first automated close.' Monthly '$290' /mo, sub 'Billed monthly'; Yearly '$232' /mo, sub 'Billed $2,784 yearly'. CTA 'Start free trial' (outlined). Features: 'Up to 3 finance seats', '5 bank and card feeds', 'Auto-matching rules', 'Close checklist templates', 'Receipt requests by email', 'Email support, 1 business day'. Growth (highlighted, chip 'Most popular'): 'For teams closing multiple entities every month.' Monthly '$790' /mo 'Billed monthly'; Yearly '$632' /mo 'Billed $7,584 yearly'. CTA 'Start free trial' (primary Ink). Features: 'Up to 15 finance seats', 'Unlimited bank and card feeds', 'Multi-entity and intercompany', 'Flux analysis with drafted explanations', 'Approval workflows and sign-offs', 'Priority support, 4-hour response'. Enterprise: 'For public and pre-IPO companies with audit-grade needs.' Price 'Custom' with sub 'Annual agreement' in both modes. CTA 'Talk to sales' (outlined). Features: 'Unlimited seats and entities', 'SSO, SAML and SCIM', 'Custom ERP connectors', 'Dedicated close specialist', '99.9% uptime SLA', 'US or EU data residency'. Footnote centered under the cards (Inter 14px Muted): 'Prices in USD. Nonprofits get 30% off any plan.' All CTAs link to #start.
   Layout: section#pricing on Canvas. Header, 32px gap, toggle centered (height 44px, padding 4px, Surface background, 1px Line ring, radius pill; options Inter 600 14.5px; the active option sits on an Ink thumb with white text, inactive Ink Soft), 48px gap, then three equal cards in a row, gap 24px, align stretch. Card: Surface, radius 28px, 1px Line ring, shadow-card, padding 32px, flex column. Plan name Instrument Sans 600 22px Ink; description 15px Ink Soft (min-height 48px); 28px gap; price Instrument Sans 600 52px, -0.03em, Ink, tnum, with '/mo' in Inter 500 16px Muted; billing sub 13.5px Muted; 24px gap; CTA full width 48px pill; 28px gap; 1px Line divider; feature list 15px Ink Soft with lucide Check 16px Iris, 14px gap; list grows so CTAs align. Growth card: translateY(-12px) on desktop, shadow-lift, 1.5px gradient border (background: linear-gradient(#fff, #fff) padding-box, linear-gradient(135deg, #FF9E7A, #B39DFF, #8FD3FF) border-box; border 1.5px solid transparent), and the 'Most popular' chip at top-right inside the card (pill 26px tall, the same three-stop gradient as background, Ink text Inter 600 12px). Under 1024px: cards stack in one column, max-width 480px centered, same order, Growth card without the translate.
   Motion: Toggle thumb slides between options with a shared layoutId (spring stiffness 400, damping 32). Price numbers and billing subs swap with AnimatePresence: old value exits y -12px opacity 0, new enters from y 12px, 0.25s swap easing. Cards reveal with the standard section reveal, stagger 0.08s, and hover-lift.
9. **FAQ** — Left: H2 'Questions, answered.' and text (Inter 16px Ink Soft) 'Can't find what you need? Email hello@[BRAND_SLUG].com and an accountant on our team replies within one business day.' with the address as an Iris mailto link. Right, five items: 'How long does setup take?' — 'Most teams connect bank feeds and their ERP in an afternoon. Our onboarding team imports your existing checklist and matching rules, so your first close in [BRAND] is usually the next one on the calendar.' 'Which banks and ERPs do you support?' — '[BRAND] connects to more than 120 banks, card programs, payroll providers and ERPs through read-only feeds. If a source isn't listed, upload a CSV or schedule an SFTP drop and it syncs the same way.' 'Will our auditors accept the records?' — 'Every match, edit and sign-off is time-stamped and attributed to a person. You can export a PBC package with reconciliations, support files and the full activity log as one PDF and spreadsheet bundle.' 'How is our data protected?' — '[BRAND] is SOC 2 Type II audited, encrypts data with AES-256 at rest and TLS 1.3 in transit, and keeps it in the US or EU region you choose. Bank connections are read-only.' 'Can we change or cancel our plan?' — 'Yes. Plans are month to month unless you pick yearly billing. Upgrades are prorated right away, and downgrades take effect at the end of the billing period.'
   Layout: section#faq on Canvas. 12-column grid: heading block in columns 1-4 (sticky top 120px on desktop), accordion in columns 6-12. Accordion items separated by 1px Line (top border on the first item too). Each item: a button row, padding 24px 0, question Instrument Sans 600 19px Ink, lucide Plus 20px Ink Soft at the right inside a 36px round Surface button with a 1px Line ring; answer Inter 16px/1.65 Ink Soft, max-width 600px, padding-bottom 24px. Only one item open at a time; the first is open on load. Buttons use aria-expanded and aria-controls. Under 1024px the heading block sits above the accordion and is not sticky.
   Motion: Answer height animates 0 -> auto with opacity over 0.3s (swap easing); the Plus icon rotates 45deg into an X over 0.25s.
10. **Final call to action** — H2 'Make next month your fastest close yet.' Sub (Inter 18px Ink Soft, max-width 520px) 'Start a 14-day trial with your own bank feeds. Most teams see their first automatic matches within an hour.' Buttons: primary Ink pill 'Start free trial' + ArrowRight (to #pricing) and a glass pill 'Book a demo' (background rgba(255,255,255,0.6), blur 12px, 1px border rgba(255,255,255,0.8), Ink text) linking to #faq. Small line under the buttons (Inter 500 13.5px Ink Soft): '14-day trial · Setup in an afternoon · Cancel anytime'. Two small floating glass chips drawn in code: top-right 'Auto-matched 96%' with lucide Sparkles 14px Iris; bottom-left 'October close complete · Day 3' with lucide CircleCheck 14px Positive.
   Layout: section#start: container 1200px, padding-block 96px. Inside, a frame with radius 32px, overflow hidden, position relative, min-height 440px (380px mobile), 1px ring rgba(14,21,37,0.06). A second MeshGradient instance with seed 7.0 fills the frame (its pointer tracking is relative to the frame) with the same CSS fallback. Content centered horizontally and vertically, text-align center, padding 64px 24px: H2 in Instrument Sans 600 clamp(36px, 4.6vw, 64px)/1.05, -0.03em, Ink, max-width 760px; 20px gap to sub; 32px gap to buttons (gap 12px; stacked full-width under 640px); 16px to the small line. Chips: absolute, top 32px right 40px and bottom 32px left 40px (hidden under 768px), same glass recipe as the hero panels at radius 9999px, height 38px, padding 0 14px, Inter 600 13px Ink.
   Motion: The frame reveals with scale 0.98 -> 1 and opacity 0 -> 1 over 0.8s when 25% in view. Chips bob (6s and 7s). The gradient only animates while the frame is on screen.
11. **Footer** — Brand column: logo, then '[BRAND] is [PRODUCT] for [AUDIENCE].' (Inter 15px Ink Soft, max-width 300px), a status chip (Surface, 1px Line, pill, 30px tall: 8px Positive dot with the pulse-dot animation + 'All systems normal' Inter 500 13px Ink), and the address '220 Larkspur Avenue, Suite 400, Portland, OR 97209' (13px Muted). Columns: Product ('Reconcile', 'Close checklist', 'Flux analysis', 'Audit trail', 'Integrations', 'Pricing'); Company ('About', 'Customers', 'Careers' with a small chip 'Hiring' in Iris on Iris Tint, 'Press', 'Contact'); Resources ('Docs', 'API reference', 'Close playbook', 'Changelog', 'Status'); Legal ('Privacy', 'Terms', 'Security', 'DPA', 'Subprocessors'). Links that match a section go to its anchor (Reconcile, Close checklist, Flux analysis, Audit trail -> #product; Integrations, API reference, Security -> #platform; Customers -> #stories; Pricing -> #pricing; Contact -> #faq); every other link points to ./index.html. Bottom bar: left '© [BRAND] Inc. All rights reserved.' (13px Muted); right the optional [CREDIT] link (13px Muted, hover Ink), omitted entirely when CREDIT is empty.
   Layout: footer on Canvas with a 1px Line top border, padding 80px 0 40px. 12-column grid: brand column in columns 1-4 (stacked, 20px gaps), then four link columns of 2 columns each. Column headings Inter 600 13px uppercase, 0.06em tracking, Ink, 20px below them the links (Inter 400 14.5px Ink Soft, hover Ink, 12px vertical gap). Bottom bar 64px below, separated by 1px Line, padding-top 24px, flex space-between. Under 1024px: brand column full width, link columns in a 2×2 grid; under 640px the bottom bar stacks.
   Motion: Link color transitions over 0.15s. The status dot pulses every 2s (none under reduced motion).

## Assets
- font: Self-hosted with Fontsource npm packages, imported once in src/main.tsx: @fontsource-variable/instrument-sans (display), @fontsource-variable/inter (text), @fontsource-variable/jetbrains-mono (mono). All OFL-1.1. Vite bundles the woff2 files into dist/assets.
- icon: lucide-react (ISC), imported per icon: ArrowRight, ArrowLeft, Check, CircleCheck, CircleDot, Circle, TrendingUp, Sparkles, Menu, X, Plus, Copy, Download, ShieldCheck, Lock, Landmark, CreditCard, Users, Receipt, Building2, FileSpreadsheet, Wallet, Globe, Banknote, Database, Calculator. No brand icons and no Simple Icons.
- image: Everything is drawn in code, no image files are downloaded: the mesh gradient (OGL fragment shader, CSS radial-gradient fallback), the logo mark and public/favicon.svg (hand-written SVG as specified), the eight customer wordmarks (inline SVG glyph + text), all product panels, progress rings, area and bar charts (HTML + inline SVG with invented data), initials avatars (CSS gradients), quote marks and the hero's curved bottom edge (inline SVG). No photographs, screenshots, stock images or placeholder services.
- image: Write ASSETS.md at the project root listing every third-party item with source and license: Instrument Sans, Inter and JetBrains Mono via Fontsource (https://fontsource.org, OFL-1.1); lucide-react icons (https://lucide.dev, ISC); OGL (https://github.com/oframe/ogl, Unlicense); motion (https://motion.dev, MIT); 3D simplex noise GLSL from webgl-noise by Ian McEwan and Stefan Gustavson (https://github.com/stegu/webgl-noise, MIT), pasted in src/gl/noise.ts. State that there are no third-party images and that all customer names, people and figures are invented.

## Don'ts
- No backend of any kind: no server code, API routes, databases, auth, analytics or third-party API calls. No forms or email inputs; every call to action is an in-page anchor and the only outbound links are the mailto link and the optional [CREDIT] link.
- Do not load fonts from fonts.googleapis.com, fonts.gstatic.com, Adobe Fonts or any CDN. Fontsource packages only.
- No CDN <script> or <link> tags. ogl, motion and lucide-react are installed from npm and bundled.
- Production build: build.sourcemap false, no src/ copied into dist/, Vite base './' so every asset path is relative. Internal links point to in-page anchors or ./index.html, never to a bare directory.
- Do not change the stack (Vite 5 + React 18 + TypeScript, Tailwind CSS 3.4, OGL, Motion, Lucide) unless the user asks. No three.js, no other WebGL or shader library, no UI kit. The gradient is one hand-written fragment shader as specified; only the simplex noise function is pasted from webgl-noise (MIT).
- No real payments or SaaS company's logo, wordmark, product names or brand name anywhere, including the well-known fintech homepage this gradient style is associated with. Never call the site a clone or name a real company as its source.
- Do not reuse that company's gradient palette (no hot magenta, electric purple, saturated orange set), shader code, skewed straight-diagonal hero edge or its hero geometry, and no globe or signature illustration assets. Use only the pastel hues and the soft curved bottom edge specified here.
- No marketing copy, slogans or taglines from any real SaaS site. Write all copy fresh from this prompt.
- Every logo in the customer strip is an invented, code-drawn wordmark. No real customer logos, no Simple Icons, no brand icons. No real bank, card network, ERP or payroll brand names in panels, integration tiles or FAQ answers.
- No commercial or proprietary fonts (for example Söhne, Camphor or any custom brand typeface). Use only Instrument Sans, Inter and JetBrains Mono.
- No screenshots of real product dashboards. All UI panels are built in code with the invented data given here.
- No code from Aceternity UI, Tailwind Plus / Tailwind UI or purchased Framer or ThemeForest templates for the gradient, glass panels or floating-card effects; write every effect from scratch. Every dependency must be MIT, ISC, BSD, Apache-2.0, 0BSD, CC0, Unlicense or OFL-1.1 (fonts).
- No photographs, stock images, placeholder-image services or faces. People appear only as gradient initials avatars.
- Respect prefers-reduced-motion exactly as described (CSS gradient instead of the shader, no parallax, tilt, bob, marquee, count-up or auto-advance). Pause the shader when off screen or the tab is hidden, and release the WebGL context on unmount.
- Must work at 1440×900 and 390×844 with zero console errors and no horizontal scrollbar. Every interactive element is reachable by keyboard with a visible focus ring (3px rgba(91,75,255,0.45), 2px offset). Body text keeps at least 4.5:1 contrast over the gradient and glass.
- Keep dist/ under 20 MB (this build should be well under 2 MB). No bitmaps.
- Keep all copy and data in src/content.ts. When the variable values differ from the defaults, rewrite every headline, panel label, data point, metric, testimonial, plan and FAQ for the new product and audience while keeping lengths, structure and number formats. No lorem ipsum. Build package names, env vars and client names in the code sample from [BRAND] and [BRAND_SLUG], never hard-coded.
- No dark-mode toggle, cookie banner, chat widget, pop-up, newsletter modal or sound.
- No mention of the template source inside the site except the optional [CREDIT] link in the footer.

---
— Prompt by VibeFather · https://vibefather.ai/t/webgl-gradient-saas-landing-page · CC BY-NC 4.0 (non-commercial; commercial use needs a VibeFather Pro license) · Request removal: https://vibefather.ai/takedown

Free for personal projects under CC BY-NC 4.0. Commercial use comes with Pro.

DESIGN.md

The design system on its own — colors, type, spacing and motion. Apply this look to a project you already have.

---
name: "WebGL Gradient SaaS Landing Page"
colors:
  canvas: "#FBFAF8"
  surface: "#FFFFFF"
  mist: "#F3F1EE"
  line: "#E6E2DC"
  ink: "#0E1525"
  ink_soft: "#3A4458"
  muted: "#6B7487"
  logo_gray: "#8A92A3"
  iris: "#5B4BFF"
  iris_tint: "#EEEBFF"
  positive: "#12A26B"
  positive_tint: "#E6F6EE"
  caution: "#D98B06"
  caution_tint: "#FFF4DB"
  negative: "#E5484D"
  negative_tint: "#FDECEC"
  gradient_cream: "#FFF1E4"
  gradient_apricot: "#FF9E7A"
  gradient_lilac: "#B39DFF"
  gradient_glacier: "#8FD3FF"
  gradient_butter: "#FFE08A"
  gradient_seafoam: "#9EECD0"
typography:
  display_h1_h2_prices_big_numbers_tab_titles_quotes_instrument_sans_variable_h1_600_clamp_44px_6vw_84px_1_02_letter_spacing_0_035em_h2_600_clamp_34px_4vw_56px_1_06_0_03em_h3_600_22px_1_25_0_015em: { family: "Instrument Sans", weights: [500, 600] }
  text_body_17px_1_6_400_ui_15px_500_buttons_15_5px_600_eyebrows_13px_600_uppercase_with_0_08em_tracking_in_iris_inter_variable_with_cv11: { family: "Inter", weights: [400, 500, 600, 700] }
  mono_amounts_and_ids_in_panels_tabular_code_card_13px_1_7_step_numbers_12px_timestamps_jetbrains_mono_variable: { family: "JetBrains Mono", weights: [400, 500, 600] }
spacing: "8px base. Container max-width 1200px, side padding 24px (20px under 640px). 12-column grid, 24px gutter. Sections: padding-block 128px desktop, 88px under 768px. Header 72px tall. Card padding 32px desktop / 24px mobile. Panel inner padding 20px."
radius: "Pill (9999px) for all buttons, chips, toggles and tabs on mobile. 20px for floating product panels and small cards. 28px for bento cards, pricing cards and the tab panel stage. 32px for the final CTA frame. 12px for small tiles inside panels, 6px for table status chips."
---

# WebGL Gradient SaaS Landing Page — Design System

Apply this design system to an existing project. It describes the look and feel only; for the full site, use prompt.md.

## Colors
- **Canvas** `#FBFAF8` — Page background, header background after scroll (at 78% opacity), footer
- **Surface** `#FFFFFF` — Cards, pricing cards, active tab card, solid panel backgrounds
- **Mist** `#F3F1EE` — Testimonials band background and the feature-tab panel stage
- **Line** `#E6E2DC` — Hairlines, card rings, dividers, outlined buttons
- **Ink** `#0E1525` — Headlines, primary pill buttons, code card background
- **Ink Soft** `#3A4458` — Body text, nav links
- **Muted** `#6B7487` — Secondary text, inactive tab titles, captions
- **Logo Gray** `#8A92A3` — Customer wordmarks in the logo strip
- **Iris** `#5B4BFF` — Single UI accent: eyebrows, text links, chart lines, check icons, focus ring base
- **Iris Tint** `#EEEBFF` — Chip backgrounds with Iris text
- **Positive** `#12A26B` — Done states, positive deltas, status dot
- **Positive Tint** `#E6F6EE` — Positive chip backgrounds
- **Caution** `#D98B06` — In-review states, flagged variance, needs-receipt
- **Caution Tint** `#FFF4DB` — Caution chip backgrounds
- **Negative** `#E5484D` — Blocked states only
- **Negative Tint** `#FDECEC` — Blocked chip background
- **Gradient Cream** `#FFF1E4` — Shader base color and CSS fallback base
- **Gradient Apricot** `#FF9E7A` — Mesh gradient hue 1; progress arcs start
- **Gradient Lilac** `#B39DFF` — Mesh gradient hue 2; chart area fills
- **Gradient Glacier** `#8FD3FF` — Mesh gradient hue 3
- **Gradient Butter** `#FFE08A` — Mesh gradient hue 4
- **Gradient Seafoam** `#9EECD0` — Mesh gradient hue 5

## Typography
- **Display: H1, H2, prices, big numbers, tab titles, quotes (Instrument Sans Variable). H1 600 clamp(44px, 6vw, 84px)/1.02, letter-spacing -0.035em. H2 600 clamp(34px, 4vw, 56px)/1.06, -0.03em. H3 600 22px/1.25, -0.015em.** — Instrument Sans (OFL), weights 500/600. Self-host the font files.
- **Text: body 17px/1.6 400, UI 15px 500, buttons 15.5px 600, eyebrows 13px 600 uppercase with 0.08em tracking in Iris (Inter Variable with cv11)** — Inter (OFL), weights 400/500/600/700. Self-host the font files.
- **Mono: amounts and IDs in panels (tabular), code card 13px/1.7, step numbers 12px, timestamps (JetBrains Mono Variable)** — JetBrains Mono (OFL), weights 400/500/600. Self-host the font files.

## Spacing & shape
- Spacing: 8px base. Container max-width 1200px, side padding 24px (20px under 640px). 12-column grid, 24px gutter. Sections: padding-block 128px desktop, 88px under 768px. Header 72px tall. Card padding 32px desktop / 24px mobile. Panel inner padding 20px.
- Radius: Pill (9999px) for all buttons, chips, toggles and tabs on mobile. 20px for floating product panels and small cards. 28px for bento cards, pricing cards and the tab panel stage. 32px for the final CTA frame. 12px for small tiles inside panels, 6px for table status chips.

## Motion
- Two easings only: entrance [0.16, 1, 0.3, 1] (expo out) for reveals and load-in, swap [0.22, 1, 0.36, 1] for tab, carousel and price changes.
- Section reveal: every section's header block and its main grid fade and rise from opacity 0, y 24px to 1, 0 over 0.7s when 20% enters the viewport (whileInView, viewport once). Grid children stagger 0.06s.
- Hover: cards lift y -4px with shadow-card -> shadow-lift over 0.25s; primary buttons darken to #1F2940 and lift 1px; arrow icons inside links slide 3px right.
- Hero gradient flows continuously and slowly (one full visual cycle takes about 40 seconds) and bends toward the cursor with eased lag; it pauses whenever the hero is off screen or the tab is hidden.
- Floating panels: load-in with stagger, idle bob 6px, pointer tilt on a spring, scroll parallax at three different speeds (details in Hero).
- Logo marquee 38s linear loop, pauses on hover. Metrics count up once over 1.4s.
- prefers-reduced-motion: CSS gradient instead of the shader, no parallax, tilt, bob, marquee, count-up or auto-advance; reveals become a plain 0.2s opacity fade.

## Imagery
No photographs and no bitmap files at all. Everything visual is drawn in code: the WebGL mesh gradient (with a CSS radial-gradient fallback), glass product panels built from HTML and inline SVG with invented data, SVG charts and progress rings, code-drawn customer wordmarks, gradient initials avatars (no faces) and Lucide icons. The look comes from soft pastel color, frosted white glass, crisp near-black type and layered shadows.

## Tone
Calm, confident, specific. Short declarative sentences, concrete numbers, no hype words, no exclamation marks, no emoji. Reads like software made by people who have run a month-end close themselves.

---
— Prompt by VibeFather · https://vibefather.ai/t/webgl-gradient-saas-landing-page · CC BY-NC 4.0 (non-commercial; commercial use needs a VibeFather Pro license) · Request removal: https://vibefather.ai/takedown