<aside> ⭐
Hi, my name is Shana and I made this notion page just for you. Make sure to follow me @reinesana.ai on Instagram for more tech content
Steps:
To use this prompt**:** Send 4 images alongside the prompt.
All four can be the same image if you only have one.
To customize
Aether in the navbar, hero badge, and footer['Services', 'Work', 'Process', 'Pricing'] in Navbar.tsxpartners array in IntroSection.tsxfillText lines in ParticleTitle.tsxcards array in FeaturesSection.tsx and steps array in HowItWorksSection.tsx<aside> ⚡
Recommended Workflow
**Aether — Complete Site Recreation Prompt**
Build a single-page cinematic landing page for "Aether," an AI-powered web design agency. Stack: React + Vite + TypeScript + Tailwind CSS v4, Framer Motion, Lucide React. Pure black background. Surreal, cinematic, pastel-futurist aesthetic. No videos. No iframes. All section backgrounds use the images I am attaching to this message.
**IMAGES I AM SENDING WITH THIS PROMPT (attach them alongside this text):**
• Image 1 — Hero background: flower meadow with tulips, wide sky, warm golden hour. Save as `/public/hero-bg.jpg`.
• Image 2 — Intro section background: abstract or nature texture. Save as `/public/intro-bg.jpg`.
• Image 3 — Features section background: abstract/dark nature texture. Save as `/public/features-bg.jpg`.
Use each image exactly where specified below. Do not generate placeholder images or fetch stock images.
**DEPENDENCIES**
`framer-motionlucide-react`
Google Fonts in index.css:
`@import url('<https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@1&family=Barlow:wght@300;400;500;600&display=swap>');`
**index.css — FULL FILE**
`@import url('<https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@1&family=Barlow:wght@300;400;500;600&display=swap>');@import "tailwindcss";@theme inline { --font-heading: 'Instrument Serif', serif; --font-body: 'Barlow', sans-serif; --font-sans: 'Barlow', sans-serif; --color-background: hsl(var(--background)); --color-foreground: hsl(var(--foreground)); --color-border: hsl(var(--border)); --color-input: hsl(var(--input)); --color-ring: hsl(var(--ring)); --color-card: hsl(var(--card)); --color-card-foreground: hsl(var(--card-foreground)); --color-popover: hsl(var(--popover)); --color-popover-foreground: hsl(var(--popover-foreground)); --color-primary: hsl(var(--primary)); --color-primary-foreground: hsl(var(--primary-foreground)); --color-secondary: hsl(var(--secondary)); --color-secondary-foreground: hsl(var(--secondary-foreground)); --color-muted: hsl(var(--muted)); --color-muted-foreground: hsl(var(--muted-foreground)); --color-accent: hsl(var(--accent)); --color-accent-foreground: hsl(var(--accent-foreground)); --color-destructive: hsl(var(--destructive)); --color-destructive-foreground: hsl(var(--destructive-foreground));}:root { --background: 0 0% 0%; --foreground: 0 0% 100%; --muted-foreground: 0 0% 100%; --primary: 0 0% 100%; --primary-foreground: 0 0% 0%; --border: 0 0% 100% / 0.2; --card: 0 0% 5%; --card-foreground: 0 0% 100%; --popover: 0 0% 0%; --popover-foreground: 0 0% 100%; --secondary: 0 0% 12%; --secondary-foreground: 0 0% 100%; --muted: 0 0% 8%; --accent: 0 0% 12%; --accent-foreground: 0 0% 100%; --destructive: 0 70% 60%; --destructive-foreground: 0 0% 100%; --input: 0 0% 100%; --ring: 0 0% 100%; --radius: 9999px;}@layer base { * { box-sizing: border-box; border-color: transparent; } body { font-family: 'Barlow', sans-serif; font-weight: 300; color: white; background: black; overflow-x: hidden; margin: 0; padding: 0; }}/* Liquid glass base */.liquid-glass { background: rgba(255,255,255,0.04); background-blend-mode: luminosity; backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); box-shadow: inset 0 1px 1px rgba(255,255,255,0.10); position: relative; overflow: hidden;}.liquid-glass::before { content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 1.4px; background: linear-gradient(180deg, rgba(255,255,255,0.45) 0%, rgba(255,255,255,0.15) 20%, rgba(255,255,255,0.00) 40%, rgba(255,255,255,0.00) 60%, rgba(255,255,255,0.15) 80%, rgba(255,255,255,0.45) 100% ); -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask-composite: xor; mask-composite: exclude; pointer-events: none;}/* Stronger blur glass (used on primary CTA buttons) */.liquid-glass-strong { background: rgba(255,255,255,0.04); background-blend-mode: luminosity; backdrop-filter: blur(50px); -webkit-backdrop-filter: blur(50px); box-shadow: 4px 4px 4px rgba(0,0,0,0.05), inset 0 1px 1px rgba(255,255,255,0.15); position: relative; overflow: hidden;}.liquid-glass-strong::before { content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 1.4px; background: linear-gradient(180deg, rgba(255,255,255,0.50) 0%, rgba(255,255,255,0.20) 20%, rgba(255,255,255,0.00) 40%, rgba(255,255,255,0.00) 60%, rgba(255,255,255,0.20) 80%, rgba(255,255,255,0.50) 100% ); -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask-composite: xor; mask-composite: exclude; pointer-events: none;}/* Section pill badges */.section-badge { display: inline-block; font-family: 'Barlow', sans-serif; font-size: 0.75rem; font-weight: 500; color: white; margin-bottom: 1rem; padding: 0.25rem 0.875rem; border-radius: 9999px; border: 1px solid rgba(255,255,255,0.18); background: rgba(255,255,255,0.06);}/* Fixed grain overlay — subtle film texture over the whole page */.grain-overlay { position: fixed; inset: 0; pointer-events: none; z-index: 100; opacity: 0.025; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='<http://www.w3.org/2000/svg>'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='1'/%3E%3C/svg%3E"); background-size: 128px 128px;}/* Hero canvas: breathing brightness/saturation like dappled sunlight */@keyframes hero-glow { 0% { filter: brightness(1.00) saturate(1.00); } 25% { filter: brightness(1.06) saturate(1.12); } 55% { filter: brightness(1.02) saturate(1.05); } 78% { filter: brightness(1.08) saturate(1.15); } 100% { filter: brightness(1.00) saturate(1.00); }}.hero-glow { animation: hero-glow 9s ease-in-out infinite; will-change: filter; }`
**App.tsx**
`import Navbar from './components/Navbar';import PageLoader from './components/PageLoader';import HeroSection from './components/HeroSection';import IntroSection from './components/IntroSection';import FeaturesSection from './components/FeaturesSection';import CTASection from './components/CTASection';import Footer from './components/Footer';export default function App() { return ( <> <div className="grain-overlay" /> <PageLoader /> <Navbar /> <HeroSection /> <IntroSection /> <FeaturesSection /> <CTASection /> <Footer /> </> );}`
**PageLoader.tsx**
Black overlay that fades out over 1.4s (starts at 0.5s), removed from DOM at 2.2s. Creates the cinematic page-load bloom entrance.
`import { useState, useEffect } from 'react';import { motion, AnimatePresence } from 'framer-motion';export default function PageLoader() { const [visible, setVisible] = useState(true); useEffect(() => { const t = setTimeout(() => setVisible(false), 2200); return () => clearTimeout(t); }, []); return ( <AnimatePresence> {visible && ( <motion.div key="loader" initial={{ opacity: 1 }} animate={{ opacity: 0 }} transition={{ duration: 1.4, delay: 0.5, ease: [0.4, 0, 0.2, 1] }} style={{ position: 'fixed', inset: 0, background: 'black', zIndex: 9999, pointerEvents: 'none' }} /> )} </AnimatePresence> );}`
**Navbar.tsx**
Fixed pill navbar at top. `liquid-glass` pill, slides in from above at 0.9s delay. Logo = "Aether" in Instrument Serif italic. Links: Services, Work, Process, Pricing. White "Get Started" button on right. Box-shadow deepens on scroll.
**SwayCanvas.tsx — WebGL animated hero background**
This component renders hero-bg.jpg as a WebGL canvas with:
• **Foreground tulips/flowers (lower ~62% of image)**: cluster-based sway driven by multi-frequency wind gusts. Each flower cluster has an independent phase so they never move in sync. Amplitude scales with depth (foreground moves more than background).
• **Sky zone (upper ~38%)**: very slow radial zoom from top-center (clouds appear to slowly approach the viewer) plus subtle lateral drift.
• Falls back to Canvas 2D strip-based sway if WebGL is unavailable.
• The canvas has CSS class `hero-glow` so it breathes with the 9s brightness/saturation animation.
`import { useEffect, useRef } from 'react';const VERT = ` attribute vec2 a_pos; varying vec2 v_uv; void main() { v_uv = vec2(a_pos.x * 0.5 + 0.5, -a_pos.y * 0.5 + 0.5); gl_Position = vec4(a_pos, 0.0, 1.0); }`;const FRAG = ` precision mediump float; uniform sampler2D u_tex; uniform float u_time; varying vec2 v_uv; void main() { float skyLine = 0.62; // ── CLOUD ZONE ────────────────────────────────────────────────────────── float inSky = smoothstep(skyLine - 0.04, skyLine + 0.06, v_uv.y); vec2 skyCenter = vec2(0.5, 1.0); // Slow radial zoom — clouds approach the viewer float creep = fract(u_time * 0.00060 / 0.05) * 0.05; float zoomFactor = 1.0 - (sin(u_time * 0.018) * 0.022 + creep) * inSky; vec2 zoomedSkyUV = skyCenter + (v_uv - skyCenter) * zoomFactor; vec2 skyUV = mix(v_uv, zoomedSkyUV, inSky); float cloudDx = inSky * ( sin(u_time * 0.045 + v_uv.x * 1.5) * 0.009 + sin(u_time * 0.070 + v_uv.x * 0.8) * 0.005 ); float cloudDy = (skyUV.y - v_uv.y); // ── PLANT ZONE ────────────────────────────────────────────────────────── float inPlant = 1.0 - smoothstep(skyLine - 0.07, skyLine + 0.02, v_uv.y); float depth = clamp((skyLine - v_uv.y) / skyLine, 0.0, 1.0); // Multi-frequency wind gusts — organic, not metronomic float gust = sin(u_time * 0.38) * 0.50 + sin(u_time * 0.61) * 0.30 + sin(u_time * 0.97) * 0.20; // Cluster phase — 8 clusters per row width, irregular spacing float clusterPhase = v_uv.x * 8.0 + sin(v_uv.x * 3.5) * 2.0 + v_uv.y * 2.0; float clusterSway = sin(u_time * 1.10 + clusterPhase) * 0.65 + sin(u_time * 1.80 + clusterPhase * 0.8 + 1.8) * 0.35; // Amplitude: foreground large, background tiny float plantAmp = pow(depth, 0.55) * 0.0058 * inPlant; float plantDx = (gust * 0.58 + clusterSway * 0.42) * plantAmp; float plantDy = sin(u_time * 0.75 + clusterPhase + 3.0) * plantAmp * 0.14; // ── COMBINE ───────────────────────────────────────────────────────────── float totalCloudDx = (skyUV.x - v_uv.x) + cloudDx; vec2 displaced = clamp(v_uv + vec2(plantDx + totalCloudDx, plantDy + cloudDy), 0.0, 1.0); gl_FragColor = texture2D(u_tex, displaced); }`;function compileShader(gl: WebGLRenderingContext, type: number, src: string) { const s = gl.createShader(type)!; gl.shaderSource(s, src); gl.compileShader(s); return s;}export default function SwayCanvas() { const canvasRef = useRef<HTMLCanvasElement>(null); useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const img = new Image(); img.src = '/hero-bg.jpg'; img.onload = () => { const gl = ( canvas.getContext('webgl', { preserveDrawingBuffer: true }) ?? canvas.getContext('experimental-webgl', { preserveDrawingBuffer: true }) ) as WebGLRenderingContext | null; if (!gl) return; // add 2D fallback if needed canvas.width = canvas.offsetWidth || 1280; canvas.height = canvas.offsetHeight || 720; gl.viewport(0, 0, canvas.width, canvas.height); const prog = gl.createProgram()!; gl.attachShader(prog, compileShader(gl, gl.VERTEX_SHADER, VERT)); gl.attachShader(prog, compileShader(gl, gl.FRAGMENT_SHADER, FRAG)); gl.linkProgram(prog); gl.useProgram(prog); const buf = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buf); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1, 1,-1, -1,1, -1,1, 1,-1, 1,1]), gl.STATIC_DRAW); const aPos = gl.getAttribLocation(prog, 'a_pos'); gl.enableVertexAttribArray(aPos); gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0); const uTime = gl.getUniformLocation(prog, 'u_time'); gl.uniform1i(gl.getUniformLocation(prog, 'u_tex'), 0); const tex = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img); let animId: number; function loop(ts: number) { gl!.uniform1f(uTime, ts / 1000); gl!.drawArrays(gl!.TRIANGLES, 0, 6); animId = requestAnimationFrame(loop); } animId = requestAnimationFrame(loop); const ro = new ResizeObserver(() => { canvas.width = canvas.offsetWidth || 1280; canvas.height = canvas.offsetHeight || 720; gl!.viewport(0, 0, canvas.width, canvas.height); }); ro.observe(canvas); (canvas as any).__glCleanup = () => { cancelAnimationFrame(animId); ro.disconnect(); gl.deleteProgram(prog); gl.deleteTexture(tex); gl.deleteBuffer(buf); }; }; return () => { (canvas as any).__glCleanup?.(); }; }, []); return ( <canvas ref={canvasRef} className="hero-glow" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', display: 'block' }} /> );}`
**AtmosphereCanvas.tsx — 200 floating ambient motes**
Full-canvas shimmer of 200 tiny drifting particles. Each is a radial gradient dot with independent twinkle speed. They drift slowly upward and wrap at edges. zIndex: 2.
• `r`: random 0.4–1.8px
• `opacity`: random 0.18–0.63, modulated by sin twinkle
• Bloom radius = r * 2.4
• Color: white (`rgba(255,255,255,opacity)`) fading to transparent
• Speed: speedX ±0.07, speedY −0.04 to −0.22 (upward drift)
• 55% of motes spawn in upper 60% of canvas; rest spread below
**ParticleCanvas.tsx — 60 pollen particles at flower tips**
Spawns tiny pollen in a narrow band at 55–68% of canvas height (right at the flower tips). They drift gently upward and fade out as they rise above the flower zone.
• Count: 60 particles
• `r`: 0.1–0.8px (very small, like pollen)
• `baseOpacity`: 0.08–0.53, pulse with sin(phase)
• Bloom radius = r * 2.2
• `speedY`: −0.05 to −0.27 upward
• Reset back into flower-tip band when risen past 44% height
• Fade out between 50–60% height using `heightFactor`
• zIndex: 2
**ParticleTitle.tsx — Interactive particle-based heading**
Renders the hero heading "The Website Your Brand / Deserves" as particles assembled from canvas pixel sampling. Mouse proximity repels particles (radius 110px, strength 10), they spring back (SPRING=0.055, FRICTION=0.80). Settled particles breathe with tiny sine drift. Particles near cursor glow.
The canvas is 230px tall, full-width. Font: `italic 80px 'Instrument Serif'`, centered, two lines. Particles are sampled every 3px from the text mask. Each particle starts off-canvas top or bottom, then springs to its target position.
**HeroSection.tsx — FULL STRUCTURE**
`<section style={{ height: '100vh', background: 'black', overflow: 'hidden', position: 'relative' }}> {/* Background layer */} <div style={{ position: 'absolute', inset: 0, zIndex: 0, overflow: 'hidden' }}> {/* WebGL animated meadow — fades in at 0.4s over 1.8s */} <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 1.8, delay: 0.4, ease: [0.25,0.46,0.45,0.94] }} style={{ position: 'absolute', inset: 0 }}> <SwayCanvas /> </motion.div> {/* Top gradient: sky blends into navbar */} black 0% → rgba(0,0,0,0.20) 28% → transparent 52% {/* AMBIENT LIGHT ORB 1 — Sun, top-right, warm golden */} motion.div animate x:[0,38,-18,30,0] y:[0,-22,14,-10,0] opacity:[0.75,1,0.8,1,0.75] duration:10s, position: top:-8%, right:4%, 560×560px radial-gradient golden rgba(255,215,90,0.42) → rgba(255,150,30,0.14) → transparent filter:blur(60px), mixBlendMode:screen {/* AMBIENT LIGHT ORB 2 — Sky, cool blue, upper band */} motion.div animate x:[0,70,-40,50,0] y:[0,18,-12,8,0] opacity:[0.55,0.9,0.6,0.88,0.55] duration:14s delay:1.5s, position: top:-6%, left:10%, 750×280px radial-gradient rgba(120,200,255,0.22) → transparent filter:blur(55px), mixBlendMode:screen {/* AMBIENT LIGHT ORB 3 — Meadow, warm green-gold, bottom */} motion.div animate x:[-20,30,-10,40,-20] y:[0,-28,10,-18,0] opacity:[0.5,0.88,0.55,0.9,0.5] duration:12s delay:0.5s, position: bottom:-12%, left:15%, 680×420px radial-gradient rgba(155,215,100,0.22) → rgba(200,235,80,0.06) → transparent filter:blur(65px), mixBlendMode:screen {/* AMBIENT LIGHT ORB 4 — Left warm rim */} motion.div animate x:[0,22,-14,18,0] y:[0,-35,20,-25,0] opacity:[0.4,0.72,0.45,0.68,0.4] duration:16s delay:3s, position: top:20%, left:-6%, 380×560px radial-gradient rgba(255,195,100,0.18) → transparent filter:blur(55px), mixBlendMode:screen {/* Edge vignette — darkens corners */} radial-gradient ellipse 82% 82% at 50% 50%: transparent 32% → rgba(0,0,0,0.32) 66% → rgba(0,0,0,0.70) 100% {/* Global legibility wash */} rgba(0,0,0,0.32) flat overlay {/* Dark radial halo behind title text */} radial-gradient ellipse 55% 35% at 50% 40%: rgba(0,0,0,0.48) 0% → transparent 75% </div> {/* Atmosphere + pollen layers (zIndex:2) */} <AtmosphereCanvas /> <ParticleCanvas /> {/* Hero content — parallax scrolls up 45px and fades to 0 by 60% scroll */} <motion.div style={{ y, opacity, position:'relative', zIndex:10, ... padding:'170px 1.5rem 0' }}> {/* Badge — slides up at delay 1.1s */} <motion.div initial={{y:20,opacity:0}} animate={{y:0,opacity:1}} transition={{delay:1.1}}> liquid-glass pill: "New" white badge + "Introducing AI-powered web design." text </motion.div> {/* Particle title — maxWidth 960px */} <ParticleTitle /> {/* Subtext — blurs in at delay 1.6s */} <motion.p initial={{opacity:0, filter:'blur(8px)'}} animate={{opacity:1, filter:'blur(0px)'}} transition={{delay:1.6}}> "Stunning design. Blazing performance. Built by AI, refined by experts. This is web design, wildly reimagined." </motion.p> {/* CTAs — rise up at delay 1.9s */} liquid-glass-strong "Get Started" button + ghost "Watch the Film" button </motion.div> {/* Bottom fade — 360px gradient into black */} transparent 0% → rgba(0,0,0,0.45) 40% → rgba(0,0,0,0.85) 75% → black 100%</section>`
**IntroSection.tsx — "Design that feels like a world"**
`background: blackpadding: 10rem 1.5rem 14remposition: relative, overflow: hidden`
**Background image** (replaces video):
`<img src="/intro-bg.jpg" style={{ position:'absolute', inset:0, width:'100%', height:'100%', objectFit:'cover', zIndex:0, pointerEvents:'none', opacity:0.5 }}/>`
Top/bottom gradient fade: `black 0% → transparent 18% → transparent 82% → black 100%` Dark wash: `rgba(0,0,0,0.28)` overlay. Also renders `<ParticleCanvas />` (floating dust).
**Content** (maxWidth 48rem, centered, zIndex 3):
• `.section-badge` → "Trusted by modern brands"
• `h2` Instrument Serif italic: *"Design that feels like / a world, not a template."* fontSize: clamp(2.5rem, 6vw, 4.5rem), letterSpacing: -0.04em, lineHeight: 0.92
• `p` Barlow 300: *"We build web experiences that transcend the ordinary — / immersive, cinematic, and unmistakably yours."*
• Partner row: Luminary · Celestia · Vaulted · Prism · Aura · Nocturne font: Barlow 300, 0.875rem, letterSpacing 0.12em, uppercase, color rgba(255,255,255,0.42)
All elements use `fadeUp` Framer Motion variant (y:28→0, staggered 0.12s delay), triggered `useInView` with margin -80px.
**FeaturesSection.tsx — "Built with beauty and performance in balance."**
`background: blackpadding: 7rem 1.5rem 9remposition: relative, overflow: hidden`
**Background image** (replaces video):
`<img src="/features-bg.jpg" style={{ position:'absolute', inset:0, width:'100%', height:'100%', objectFit:'cover', zIndex:0, pointerEvents:'none', opacity:0.6 }}/>`
Top/bottom gradient fade: `black 0% → transparent 18% → transparent 82% → black 100%` Dark wash: `rgba(0,0,0,0.30)` overlay.
**Content** (maxWidth 56rem, centered, zIndex 2):
• `.section-badge` → "Capabilities"
• `h2` Instrument Serif italic: *"Built with beauty / and performance in balance."*
**Cards grid** — 4 cards in `repeat(auto-fit, minmax(280px, 1fr))`, maxWidth 48rem: Each card:
• `borderRadius:1.5rem, padding:1.75rem`
• `background: linear-gradient(145deg, rgba(255,255,255,0.06), rgba(255,255,255,0.02))`
• `backdropFilter: blur(40px)`
• `border: 1px solid rgba(255,255,255,0.09)`
• `boxShadow: 0 1px 0 rgba(255,255,255,0.08) inset, 0 20px 60px rgba(0,0,0,0.5)`
• Top shimmer line (1px gradient across top edge)
• Number `01–04` at top-right, Barlow 300, rgba(255,255,255,0.20)
• Icon box: 2.75rem square, rounded-xl, gradient background, lucide icon
• Title: Barlow 500, 0.95rem, white
• Description: Barlow 300, 0.85rem, rgba(255,255,255,0.45)
• `whileHover={{ y: -6 }}`
Cards:
1. Eye icon — "Cinematic Visual Systems" — "Immersive layouts, motion, and atmosphere that feel authored, not assembled. Every pixel placed with intent."
2. Sparkles icon — "AI-Led Creative Direction" — "We turn prompts, references, and brand signals into cohesive visual experiences that feel unmistakably yours."
3. Zap icon — "Fast Iteration" — "Explore ambitious directions quickly without losing polish. Rapid cycles, high fidelity, always."
4. Package icon — "Production-Ready Output" — "Refined front-end builds designed for responsiveness, clarity, and launch. No handoff headaches."
**CTASection.tsx — "Your next website starts here."**
`background: blackpadding: 7rem 1.5rem 10rem`
Centered, maxWidth 48rem:
• `.section-badge` → "Begin"
• `h2` Instrument Serif italic, clamp(2.75rem,7vw,4.75rem): *"Your next website / starts here."*
• `p` Barlow 300: *"Book a free strategy call and explore what AI-powered design can become."*
• Two buttons:
◦ `liquid-glass-strong` pill: "Book a Call" + ArrowUpRight icon
◦ `liquid-glass` pill: "View Pricing" + ChevronRight icon
**Navbar.tsx**
Fixed pill at top, slides in from y:-18 at delay 0.9s.
• `liquid-glass` rounded-full pill, height 3.5rem, maxWidth 56rem, centered
• Left: "Aether" in Instrument Serif italic
• Center: nav links — Services, Work, Process, Pricing — Barlow 400, 0.875rem, rgba(255,255,255,0.75)
• Right: white solid pill button "Get Started" with ArrowUpRight
• Box-shadow deepens when window.scrollY > 30
**Footer.tsx**
Simple centered footer, black background, Barlow 300, small text:
• "Aether" brand name in Instrument Serif italic
• Tagline: "AI-powered web design for the extraordinary."
• Copyright: "© 2025 Aether. All rights reserved."
**ANIMATION SYSTEM**
All sections use the same `fadeUp` Framer Motion variant:
`const fadeUp = { hidden: { opacity: 0, y: 28 }, visible: (i: number) => ({ opacity: 1, y: 0, transition: { duration: 0.7, delay: i * 0.12, ease: [0.16, 1, 0.3, 1] }, }),};`
Triggered by `useInView(ref, { once: true, margin: '-80px' })`.
Hero parallax: `useScroll` + `useTransform` — content translates y 0→45px and fades 1→0 over 60% scroll.
**RESULT**
The page should feel:
• Cinematic and immersive
• Like a real living scene (WebGL animated tulips/sky, floating particles)
• High-end agency quality
• Black and minimal outside the hero
• Every section entry is a smooth, staggered fade-upBuild a single-page cinematic landing page for "Aether," an AI-powered web design agency. Stack: React + Vite + TypeScript + Tailwind CSS v4, Framer Motion, Lucide React. Pure black background. Surreal, cinematic, pastel-futurist aesthetic. No videos. No iframes. All section backgrounds use the images I am attaching to this message.
**IMAGES I AM SENDING WITH THIS PROMPT (attach them alongside this text):**
• Image 1 — Hero background: flower meadow with tulips, wide sky, warm golden hour. Save as `/public/hero-bg.jpg`.
• Image 2 — Section 3 background: misty lake or forest scene, wide and cinematic. Save as `/public/section3-bg.jpg`.
• Image 3 — Intro section background: abstract or nature texture. Save as `/public/intro-bg.jpg`.
• Image 4 — Features section background: abstract/dark nature texture. Save as `/public/features-bg.jpg`.
Use each image exactly where specified below. Do not generate placeholder images or fetch stock images.
**DEPENDENCIES**
`framer-motionlucide-react`
Google Fonts in index.css:
`@import url('<https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@1&family=Barlow:wght@300;400;500;600&display=swap>');`
**index.css — FULL FILE**
`@import url('<https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@1&family=Barlow:wght@300;400;500;600&display=swap>');@import "tailwindcss";@theme inline { --font-heading: 'Instrument Serif', serif; --font-body: 'Barlow', sans-serif; --font-sans: 'Barlow', sans-serif; --color-background: hsl(var(--background)); --color-foreground: hsl(var(--foreground)); --color-border: hsl(var(--border)); --color-input: hsl(var(--input)); --color-ring: hsl(var(--ring)); --color-card: hsl(var(--card)); --color-card-foreground: hsl(var(--card-foreground)); --color-popover: hsl(var(--popover)); --color-popover-foreground: hsl(var(--popover-foreground)); --color-primary: hsl(var(--primary)); --color-primary-foreground: hsl(var(--primary-foreground)); --color-secondary: hsl(var(--secondary)); --color-secondary-foreground: hsl(var(--secondary-foreground)); --color-muted: hsl(var(--muted)); --color-muted-foreground: hsl(var(--muted-foreground)); --color-accent: hsl(var(--accent)); --color-accent-foreground: hsl(var(--accent-foreground)); --color-destructive: hsl(var(--destructive)); --color-destructive-foreground: hsl(var(--destructive-foreground));}:root { --background: 0 0% 0%; --foreground: 0 0% 100%; --muted-foreground: 0 0% 100%; --primary: 0 0% 100%; --primary-foreground: 0 0% 0%; --border: 0 0% 100% / 0.2; --card: 0 0% 5%; --card-foreground: 0 0% 100%; --popover: 0 0% 0%; --popover-foreground: 0 0% 100%; --secondary: 0 0% 12%; --secondary-foreground: 0 0% 100%; --muted: 0 0% 8%; --accent: 0 0% 12%; --accent-foreground: 0 0% 100%; --destructive: 0 70% 60%; --destructive-foreground: 0 0% 100%; --input: 0 0% 100%; --ring: 0 0% 100%; --radius: 9999px;}@layer base { * { box-sizing: border-box; border-color: transparent; } body { font-family: 'Barlow', sans-serif; font-weight: 300; color: white; background: black; overflow-x: hidden; margin: 0; padding: 0; }}/* Liquid glass base */.liquid-glass { background: rgba(255,255,255,0.04); background-blend-mode: luminosity; backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); box-shadow: inset 0 1px 1px rgba(255,255,255,0.10); position: relative; overflow: hidden;}.liquid-glass::before { content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 1.4px; background: linear-gradient(180deg, rgba(255,255,255,0.45) 0%, rgba(255,255,255,0.15) 20%, rgba(255,255,255,0.00) 40%, rgba(255,255,255,0.00) 60%, rgba(255,255,255,0.15) 80%, rgba(255,255,255,0.45) 100% ); -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask-composite: xor; mask-composite: exclude; pointer-events: none;}/* Stronger blur glass (used on primary CTA buttons) */.liquid-glass-strong { background: rgba(255,255,255,0.04); background-blend-mode: luminosity; backdrop-filter: blur(50px); -webkit-backdrop-filter: blur(50px); box-shadow: 4px 4px 4px rgba(0,0,0,0.05), inset 0 1px 1px rgba(255,255,255,0.15); position: relative; overflow: hidden;}.liquid-glass-strong::before { content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 1.4px; background: linear-gradient(180deg, rgba(255,255,255,0.50) 0%, rgba(255,255,255,0.20) 20%, rgba(255,255,255,0.00) 40%, rgba(255,255,255,0.00) 60%, rgba(255,255,255,0.20) 80%, rgba(255,255,255,0.50) 100% ); -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask-composite: xor; mask-composite: exclude; pointer-events: none;}/* Section pill badges */.section-badge { display: inline-block; font-family: 'Barlow', sans-serif; font-size: 0.75rem; font-weight: 500; color: white; margin-bottom: 1rem; padding: 0.25rem 0.875rem; border-radius: 9999px; border: 1px solid rgba(255,255,255,0.18); background: rgba(255,255,255,0.06);}/* Fixed grain overlay — subtle film texture over the whole page */.grain-overlay { position: fixed; inset: 0; pointer-events: none; z-index: 100; opacity: 0.025; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='<http://www.w3.org/2000/svg>'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='1'/%3E%3C/svg%3E"); background-size: 128px 128px;}/* Hero canvas: breathing brightness/saturation like dappled sunlight */@keyframes hero-glow { 0% { filter: brightness(1.00) saturate(1.00); } 25% { filter: brightness(1.06) saturate(1.12); } 55% { filter: brightness(1.02) saturate(1.05); } 78% { filter: brightness(1.08) saturate(1.15); } 100% { filter: brightness(1.00) saturate(1.00); }}.hero-glow { animation: hero-glow 9s ease-in-out infinite; will-change: filter; }`
**App.tsx**
`import Navbar from './components/Navbar';import PageLoader from './components/PageLoader';import HeroSection from './components/HeroSection';import IntroSection from './components/IntroSection';import HowItWorksSection from './components/HowItWorksSection';import FeaturesSection from './components/FeaturesSection';import CTASection from './components/CTASection';import Footer from './components/Footer';export default function App() { return ( <> <div className="grain-overlay" /> <PageLoader /> <Navbar /> <HeroSection /> <IntroSection /> <HowItWorksSection /> <FeaturesSection /> <CTASection /> <Footer /> </> );}`
**PageLoader.tsx**
Black overlay that fades out over 1.4s (starts at 0.5s), removed from DOM at 2.2s. Creates the cinematic page-load bloom entrance.
`import { useState, useEffect } from 'react';import { motion, AnimatePresence } from 'framer-motion';export default function PageLoader() { const [visible, setVisible] = useState(true); useEffect(() => { const t = setTimeout(() => setVisible(false), 2200); return () => clearTimeout(t); }, []); return ( <AnimatePresence> {visible && ( <motion.div key="loader" initial={{ opacity: 1 }} animate={{ opacity: 0 }} transition={{ duration: 1.4, delay: 0.5, ease: [0.4, 0, 0.2, 1] }} style={{ position: 'fixed', inset: 0, background: 'black', zIndex: 9999, pointerEvents: 'none' }} /> )} </AnimatePresence> );}`
**Navbar.tsx**
Fixed pill navbar at top. `liquid-glass` pill, slides in from above at 0.9s delay. Logo = "Aether" in Instrument Serif italic. Links: Services, Work, Process, Pricing. White "Get Started" button on right. Box-shadow deepens on scroll.
**SwayCanvas.tsx — WebGL animated hero background**
This component renders hero-bg.jpg as a WebGL canvas with:
• **Foreground tulips/flowers (lower ~62% of image)**: cluster-based sway driven by multi-frequency wind gusts. Each flower cluster has an independent phase so they never move in sync. Amplitude scales with depth (foreground moves more than background).
• **Sky zone (upper ~38%)**: very slow radial zoom from top-center (clouds appear to slowly approach the viewer) plus subtle lateral drift.
• Falls back to Canvas 2D strip-based sway if WebGL is unavailable.
• The canvas has CSS class `hero-glow` so it breathes with the 9s brightness/saturation animation.
`import { useEffect, useRef } from 'react';const VERT = ` attribute vec2 a_pos; varying vec2 v_uv; void main() { v_uv = vec2(a_pos.x * 0.5 + 0.5, -a_pos.y * 0.5 + 0.5); gl_Position = vec4(a_pos, 0.0, 1.0); }`;const FRAG = ` precision mediump float; uniform sampler2D u_tex; uniform float u_time; varying vec2 v_uv; void main() { float skyLine = 0.62; // ── CLOUD ZONE ────────────────────────────────────────────────────────── float inSky = smoothstep(skyLine - 0.04, skyLine + 0.06, v_uv.y); vec2 skyCenter = vec2(0.5, 1.0); // Slow radial zoom — clouds approach the viewer float creep = fract(u_time * 0.00060 / 0.05) * 0.05; float zoomFactor = 1.0 - (sin(u_time * 0.018) * 0.022 + creep) * inSky; vec2 zoomedSkyUV = skyCenter + (v_uv - skyCenter) * zoomFactor; vec2 skyUV = mix(v_uv, zoomedSkyUV, inSky); float cloudDx = inSky * ( sin(u_time * 0.045 + v_uv.x * 1.5) * 0.009 + sin(u_time * 0.070 + v_uv.x * 0.8) * 0.005 ); float cloudDy = (skyUV.y - v_uv.y); // ── PLANT ZONE ────────────────────────────────────────────────────────── float inPlant = 1.0 - smoothstep(skyLine - 0.07, skyLine + 0.02, v_uv.y); float depth = clamp((skyLine - v_uv.y) / skyLine, 0.0, 1.0); // Multi-frequency wind gusts — organic, not metronomic float gust = sin(u_time * 0.38) * 0.50 + sin(u_time * 0.61) * 0.30 + sin(u_time * 0.97) * 0.20; // Cluster phase — 8 clusters per row width, irregular spacing float clusterPhase = v_uv.x * 8.0 + sin(v_uv.x * 3.5) * 2.0 + v_uv.y * 2.0; float clusterSway = sin(u_time * 1.10 + clusterPhase) * 0.65 + sin(u_time * 1.80 + clusterPhase * 0.8 + 1.8) * 0.35; // Amplitude: foreground large, background tiny float plantAmp = pow(depth, 0.55) * 0.0058 * inPlant; float plantDx = (gust * 0.58 + clusterSway * 0.42) * plantAmp; float plantDy = sin(u_time * 0.75 + clusterPhase + 3.0) * plantAmp * 0.14; // ── COMBINE ───────────────────────────────────────────────────────────── float totalCloudDx = (skyUV.x - v_uv.x) + cloudDx; vec2 displaced = clamp(v_uv + vec2(plantDx + totalCloudDx, plantDy + cloudDy), 0.0, 1.0); gl_FragColor = texture2D(u_tex, displaced); }`;function compileShader(gl: WebGLRenderingContext, type: number, src: string) { const s = gl.createShader(type)!; gl.shaderSource(s, src); gl.compileShader(s); return s;}export default function SwayCanvas() { const canvasRef = useRef<HTMLCanvasElement>(null); useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const img = new Image(); img.src = '/hero-bg.jpg'; img.onload = () => { const gl = ( canvas.getContext('webgl', { preserveDrawingBuffer: true }) ?? canvas.getContext('experimental-webgl', { preserveDrawingBuffer: true }) ) as WebGLRenderingContext | null; if (!gl) return; // add 2D fallback if needed canvas.width = canvas.offsetWidth || 1280; canvas.height = canvas.offsetHeight || 720; gl.viewport(0, 0, canvas.width, canvas.height); const prog = gl.createProgram()!; gl.attachShader(prog, compileShader(gl, gl.VERTEX_SHADER, VERT)); gl.attachShader(prog, compileShader(gl, gl.FRAGMENT_SHADER, FRAG)); gl.linkProgram(prog); gl.useProgram(prog); const buf = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buf); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1, 1,-1, -1,1, -1,1, 1,-1, 1,1]), gl.STATIC_DRAW); const aPos = gl.getAttribLocation(prog, 'a_pos'); gl.enableVertexAttribArray(aPos); gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0); const uTime = gl.getUniformLocation(prog, 'u_time'); gl.uniform1i(gl.getUniformLocation(prog, 'u_tex'), 0); const tex = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img); let animId: number; function loop(ts: number) { gl!.uniform1f(uTime, ts / 1000); gl!.drawArrays(gl!.TRIANGLES, 0, 6); animId = requestAnimationFrame(loop); } animId = requestAnimationFrame(loop); const ro = new ResizeObserver(() => { canvas.width = canvas.offsetWidth || 1280; canvas.height = canvas.offsetHeight || 720; gl!.viewport(0, 0, canvas.width, canvas.height); }); ro.observe(canvas); (canvas as any).__glCleanup = () => { cancelAnimationFrame(animId); ro.disconnect(); gl.deleteProgram(prog); gl.deleteTexture(tex); gl.deleteBuffer(buf); }; }; return () => { (canvas as any).__glCleanup?.(); }; }, []); return ( <canvas ref={canvasRef} className="hero-glow" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', display: 'block' }} /> );}`
**AtmosphereCanvas.tsx — 200 floating ambient motes**
Full-canvas shimmer of 200 tiny drifting particles. Each is a radial gradient dot with independent twinkle speed. They drift slowly upward and wrap at edges. zIndex: 2.
• `r`: random 0.4–1.8px
• `opacity`: random 0.18–0.63, modulated by sin twinkle
• Bloom radius = r * 2.4
• Color: white (`rgba(255,255,255,opacity)`) fading to transparent
• Speed: speedX ±0.07, speedY −0.04 to −0.22 (upward drift)
• 55% of motes spawn in upper 60% of canvas; rest spread below
**ParticleCanvas.tsx — 60 pollen particles at flower tips**
Spawns tiny pollen in a narrow band at 55–68% of canvas height (right at the flower tips). They drift gently upward and fade out as they rise above the flower zone.
• Count: 60 particles
• `r`: 0.1–0.8px (very small, like pollen)
• `baseOpacity`: 0.08–0.53, pulse with sin(phase)
• Bloom radius = r * 2.2
• `speedY`: −0.05 to −0.27 upward
• Reset back into flower-tip band when risen past 44% height
• Fade out between 50–60% height using `heightFactor`
• zIndex: 2
**ParticleTitle.tsx — Interactive particle-based heading**
Renders the hero heading "The Website Your Brand / Deserves" as particles assembled from canvas pixel sampling. Mouse proximity repels particles (radius 110px, strength 10), they spring back (SPRING=0.055, FRICTION=0.80). Settled particles breathe with tiny sine drift. Particles near cursor glow.
The canvas is 230px tall, full-width. Font: `italic 80px 'Instrument Serif'`, centered, two lines. Particles are sampled every 3px from the text mask. Each particle starts off-canvas top or bottom, then springs to its target position.
**HeroSection.tsx — FULL STRUCTURE**
`<section style={{ height: '100vh', background: 'black', overflow: 'hidden', position: 'relative' }}> {/* Background layer */} <div style={{ position: 'absolute', inset: 0, zIndex: 0, overflow: 'hidden' }}> {/* WebGL animated meadow — fades in at 0.4s over 1.8s */} <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 1.8, delay: 0.4, ease: [0.25,0.46,0.45,0.94] }} style={{ position: 'absolute', inset: 0 }}> <SwayCanvas /> </motion.div> {/* Top gradient: sky blends into navbar */} black 0% → rgba(0,0,0,0.20) 28% → transparent 52% {/* AMBIENT LIGHT ORB 1 — Sun, top-right, warm golden */} motion.div animate x:[0,38,-18,30,0] y:[0,-22,14,-10,0] opacity:[0.75,1,0.8,1,0.75] duration:10s, position: top:-8%, right:4%, 560×560px radial-gradient golden rgba(255,215,90,0.42) → rgba(255,150,30,0.14) → transparent filter:blur(60px), mixBlendMode:screen {/* AMBIENT LIGHT ORB 2 — Sky, cool blue, upper band */} motion.div animate x:[0,70,-40,50,0] y:[0,18,-12,8,0] opacity:[0.55,0.9,0.6,0.88,0.55] duration:14s delay:1.5s, position: top:-6%, left:10%, 750×280px radial-gradient rgba(120,200,255,0.22) → transparent filter:blur(55px), mixBlendMode:screen {/* AMBIENT LIGHT ORB 3 — Meadow, warm green-gold, bottom */} motion.div animate x:[-20,30,-10,40,-20] y:[0,-28,10,-18,0] opacity:[0.5,0.88,0.55,0.9,0.5] duration:12s delay:0.5s, position: bottom:-12%, left:15%, 680×420px radial-gradient rgba(155,215,100,0.22) → rgba(200,235,80,0.06) → transparent filter:blur(65px), mixBlendMode:screen {/* AMBIENT LIGHT ORB 4 — Left warm rim */} motion.div animate x:[0,22,-14,18,0] y:[0,-35,20,-25,0] opacity:[0.4,0.72,0.45,0.68,0.4] duration:16s delay:3s, position: top:20%, left:-6%, 380×560px radial-gradient rgba(255,195,100,0.18) → transparent filter:blur(55px), mixBlendMode:screen {/* Edge vignette — darkens corners */} radial-gradient ellipse 82% 82% at 50% 50%: transparent 32% → rgba(0,0,0,0.32) 66% → rgba(0,0,0,0.70) 100% {/* Global legibility wash */} rgba(0,0,0,0.32) flat overlay {/* Dark radial halo behind title text */} radial-gradient ellipse 55% 35% at 50% 40%: rgba(0,0,0,0.48) 0% → transparent 75% </div> {/* Atmosphere + pollen layers (zIndex:2) */} <AtmosphereCanvas /> <ParticleCanvas /> {/* Hero content — parallax scrolls up 45px and fades to 0 by 60% scroll */} <motion.div style={{ y, opacity, position:'relative', zIndex:10, ... padding:'170px 1.5rem 0' }}> {/* Badge — slides up at delay 1.1s */} <motion.div initial={{y:20,opacity:0}} animate={{y:0,opacity:1}} transition={{delay:1.1}}> liquid-glass pill: "New" white badge + "Introducing AI-powered web design." text </motion.div> {/* Particle title — maxWidth 960px */} <ParticleTitle /> {/* Subtext — blurs in at delay 1.6s */} <motion.p initial={{opacity:0, filter:'blur(8px)'}} animate={{opacity:1, filter:'blur(0px)'}} transition={{delay:1.6}}> "Stunning design. Blazing performance. Built by AI, refined by experts. This is web design, wildly reimagined." </motion.p> {/* CTAs — rise up at delay 1.9s */} liquid-glass-strong "Get Started" button + ghost "Watch the Film" button </motion.div> {/* Bottom fade — 360px gradient into black */} transparent 0% → rgba(0,0,0,0.45) 40% → rgba(0,0,0,0.85) 75% → black 100%</section>`
**IntroSection.tsx — "Design that feels like a world"**
`background: blackpadding: 10rem 1.5rem 14remposition: relative, overflow: hidden`
**Background image** (replaces video):
`<img src="/intro-bg.jpg" style={{ position:'absolute', inset:0, width:'100%', height:'100%', objectFit:'cover', zIndex:0, pointerEvents:'none', opacity:0.5 }}/>`
Top/bottom gradient fade: `black 0% → transparent 18% → transparent 82% → black 100%` Dark wash: `rgba(0,0,0,0.28)` overlay. Also renders `<ParticleCanvas />` (floating dust).
**Content** (maxWidth 48rem, centered, zIndex 3):
• `.section-badge` → "Trusted by modern brands"
• `h2` Instrument Serif italic: *"Design that feels like / a world, not a template."* fontSize: clamp(2.5rem, 6vw, 4.5rem), letterSpacing: -0.04em, lineHeight: 0.92
• `p` Barlow 300: *"We build web experiences that transcend the ordinary — / immersive, cinematic, and unmistakably yours."*
• Partner row: Luminary · Celestia · Vaulted · Prism · Aura · Nocturne font: Barlow 300, 0.875rem, letterSpacing 0.12em, uppercase, color rgba(255,255,255,0.42)
All elements use `fadeUp` Framer Motion variant (y:28→0, staggered 0.12s delay), triggered `useInView` with margin -80px.
**HowItWorksSection.tsx — "You imagine it. We shape it."**
`background: blackpadding: 10rem 1.5rem 14remposition: relative, overflow: hidden`
**Background image** — Ken Burns animation:
`<motion.img src="/section3-bg.jpg" animate={{ scale: [1.06, 1.12, 1.06], x: ['0%', '-2%', '0%'], y: ['0%', '-1.5%', '0%'], }} transition={{ duration: 14, repeat: Infinity, ease: 'easeInOut' }} style={{ position:'absolute', inset:0, width:'100%', height:'100%', objectFit:'cover', objectPosition:'center center', transformOrigin:'center center', zIndex:0 }}/>`
**Overlays**:
• Top/bottom gradient (7-stop): `black 0% → rgba(0,0,0,0.75) 10% → rgba(0,0,0,0.4) 20% → transparent 38% → transparent 72% → rgba(0,0,0,0.6) 88% → black 100%`
• Side vignette: `black 0% → transparent 18% → transparent 82% → black 100%` (left to right)
• Dark wash: `rgba(0,0,0,0.38)`
**Content** (maxWidth 64rem, centered, zIndex 2):
• `.section-badge` → "How It Works"
• `h2` Instrument Serif italic: *"You imagine it. / We shape it."*
• `p` Barlow 300: *"From concept to launch, our AI-guided process turns direction into a site that feels polished, cinematic, and alive."*
**FeaturesSection.tsx — "Built with beauty and performance in balance."**
`background: blackpadding: 7rem 1.5rem 9remposition: relative, overflow: hidden`
**Background image** (replaces video):
`<img src="/features-bg.jpg" style={{ position:'absolute', inset:0, width:'100%', height:'100%', objectFit:'cover', zIndex:0, pointerEvents:'none', opacity:0.6 }}/>`
Top/bottom gradient fade: `black 0% → transparent 18% → transparent 82% → black 100%` Dark wash: `rgba(0,0,0,0.30)` overlay.
**Content** (maxWidth 56rem, centered, zIndex 2):
• `.section-badge` → "Capabilities"
• `h2` Instrument Serif italic: *"Built with beauty / and performance in balance."*
**Cards grid** — 4 cards in `repeat(auto-fit, minmax(280px, 1fr))`, maxWidth 48rem: Each card:
• `borderRadius:1.5rem, padding:1.75rem`
• `background: linear-gradient(145deg, rgba(255,255,255,0.06), rgba(255,255,255,0.02))`
• `backdropFilter: blur(40px)`
• `border: 1px solid rgba(255,255,255,0.09)`
• `boxShadow: 0 1px 0 rgba(255,255,255,0.08) inset, 0 20px 60px rgba(0,0,0,0.5)`
• Top shimmer line (1px gradient across top edge)
• Number `01–04` at top-right, Barlow 300, rgba(255,255,255,0.20)
• Icon box: 2.75rem square, rounded-xl, gradient background, lucide icon
• Title: Barlow 500, 0.95rem, white
• Description: Barlow 300, 0.85rem, rgba(255,255,255,0.45)
• `whileHover={{ y: -6 }}`
Cards:
1. Eye icon — "Cinematic Visual Systems" — "Immersive layouts, motion, and atmosphere that feel authored, not assembled. Every pixel placed with intent."
2. Sparkles icon — "AI-Led Creative Direction" — "We turn prompts, references, and brand signals into cohesive visual experiences that feel unmistakably yours."
3. Zap icon — "Fast Iteration" — "Explore ambitious directions quickly without losing polish. Rapid cycles, high fidelity, always."
4. Package icon — "Production-Ready Output" — "Refined front-end builds designed for responsiveness, clarity, and launch. No handoff headaches."
**CTASection.tsx — "Your next website starts here."**
`background: blackpadding: 7rem 1.5rem 10rem`
Centered, maxWidth 48rem:
• `.section-badge` → "Begin"
• `h2` Instrument Serif italic, clamp(2.75rem,7vw,4.75rem): *"Your next website / starts here."*
• `p` Barlow 300: *"Book a free strategy call and explore what AI-powered design can become."*
• Two buttons:
◦ `liquid-glass-strong` pill: "Book a Call" + ArrowUpRight icon
◦ `liquid-glass` pill: "View Pricing" + ChevronRight icon
**Navbar.tsx**
Fixed pill at top, slides in from y:-18 at delay 0.9s.
• `liquid-glass` rounded-full pill, height 3.5rem, maxWidth 56rem, centered
• Left: "Aether" in Instrument Serif italic
• Center: nav links — Services, Work, Process, Pricing — Barlow 400, 0.875rem, rgba(255,255,255,0.75)
• Right: white solid pill button "Get Started" with ArrowUpRight
• Box-shadow deepens when window.scrollY > 30
**Footer.tsx**
Simple centered footer, black background, Barlow 300, small text:
• "Aether" brand name in Instrument Serif italic
• Tagline: "AI-powered web design for the extraordinary."
• Copyright: "© 2025 Aether. All rights reserved."
**ANIMATION SYSTEM**
All sections use the same `fadeUp` Framer Motion variant:
`const fadeUp = { hidden: { opacity: 0, y: 28 }, visible: (i: number) => ({ opacity: 1, y: 0, transition: { duration: 0.7, delay: i * 0.12, ease: [0.16, 1, 0.3, 1] }, }),};`
Triggered by `useInView(ref, { once: true, margin: '-80px' })`.
Hero parallax: `useScroll` + `useTransform` — content translates y 0→45px and fades 1→0 over 60% scroll.
**RESULT**
The page should feel:
• Cinematic and immersive
• Like a real living scene (WebGL animated tulips/sky, floating particles)
• High-end agency quality
• Black and minimal outside the hero
• Every section entry is a smooth, staggered fade-upBuild a single-page landing page for "Aether," an AI-powered web design agency, using React + Vite + TypeScript + Tailwind CSS v4. Pure black background on all sections below the hero. Surreal, cinematic, pastel-futurist aesthetic.
FONTS & DESIGN SYSTEM
Google Fonts import in index.css:
• Instrument Serif (italic weight) — headings
• Barlow (300, 400, 500, 600) — body
CSS Variables (:root):
--background: 0 0% 0%;
--foreground: 0 0% 100%;
--muted-foreground: 0 0% 100%;
--primary: 0 0% 100%;
--primary-foreground: 0 0% 0%;
--border: 0 0% 100% / 0.2;
--card: 0 0% 5%;
--card-foreground: 0 0% 100%;
--popover: 0 0% 0%;
--popover-foreground: 0 0% 100%;
--secondary: 0 0% 12%;
--secondary-foreground: 0 0% 100%;
--muted: 0 0% 8%;
--accent: 0 0% 12%;
--accent-foreground: 0 0% 100%;
--destructive: 0 70% 60%;
--destructive-foreground: 0 0% 100%;
--input: 0 0% 100%;
--ring: 0 0% 100%;
--radius: 9999px;
@theme inline maps --font-heading, --font-body, --font-sans all to Barlow/Instrument Serif.
@layer base: * { box-sizing: border-box; border-color: transparent; } — this prevents Tailwind v4's preflight from rendering faint white lines at section boundaries.
body uses font-family: Barlow, sans-serif; font-weight: 300; color: white; background: black; overflow-x: hidden;
LIQUID GLASS CSS
Two classes — .liquid-glass (subtle) and .liquid-glass-strong (heavier):
.liquid-glass:
background: rgba(255,255,255,0.04);
background-blend-mode: luminosity;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
box-shadow: inset 0 1px 1px rgba(255,255,255,0.10);
position: relative;
overflow: hidden;
::before — gradient border mask:
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
padding: 1.4px;
background: linear-gradient(180deg,
rgba(255,255,255,0.45) 0%, rgba(255,255,255,0.15) 20%,
rgba(255,255,255,0.00) 40%, rgba(255,255,255,0.00) 60%,
rgba(255,255,255,0.15) 80%, rgba(255,255,255,0.45) 100%);
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
.liquid-glass-strong: Same but backdrop-filter: blur(50px), box-shadow: 4px 4px 4px rgba(0,0,0,0.05), inset 0 1px 1px rgba(255,255,255,0.15), and gradient stops at 0.50/0.20 instead of 0.45/0.15.
.section-badge:
display: inline-block;
font-family: Barlow;
font-size: 0.75rem;
font-weight: 500;
color: white;
margin-bottom: 1rem;
padding: 0.25rem 0.875rem;
border-radius: 9999px;
.grain-overlay:
position: fixed;
inset: 0;
pointer-events: none;
z-index: 100;
opacity: 0.025;
— SVG fractalNoise data URI, background-size: 128px 128px.
Two drift keyframe animations (drift, drift2) for cloud blobs — .cloud-drift-1 at 18s, .cloud-drift-2 at 22s.
PARTICLE CANVAS (floating dust, hero only)
Canvas component ParticleCanvas — position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 2.
90 particles, each with r: random * 1.6 + 0.2, baseOpacity: random * 0.55 + 0.08, speed: random * 0.35 + 0.08, drift: (random - 0.5) * 0.25, phase: random * Math.PI * 2.
Each frame: y -= speed; x += drift; phase += 0.012. Wrap at canvas edges.
Draw as radial gradient from rgba(255,255,255,opacity) center to transparent at r * 2.5.
Opacity pulses via baseOpacity * (0.65 + 0.35 * sin(phase)).
PARTICLE TITLE (canvas typography)
Component ParticleTitle — canvas element, width: 100%; height: 230px; cursor: none; background: transparent.
Logic:
1. Wait for document.fonts.load("italic 80px 'Instrument Serif'").
2. Size canvas to offsetWidth × 230. fontSize = min(offsetWidth * 0.086, 90).
3. Render two lines of text to an offscreen canvas: "The Website Your Brand" and "Deserves", both centered at H/2 ± leading * 0.5. Leading = fontSize * 1.08.
4. Sample pixels at 3px stride — any pixel with alpha > 100 becomes a target point.
5. Each particle starts at a random x, and either above or below the canvas. Has tx, ty (target), vx, vy, r: random * 0.85 + 0.45, opacity: 0, phase.
6. Physics each frame: cursor repulsion within REPEL_RADIUS = 90, REPEL_STRENGTH = 7; spring back to target with SPRING = 0.055; friction FRICTION = 0.82.
When settled (within 2px of target), add gentle sine/cosine breathing drift. Opacity increments by +0.022 per frame up to 1.
7. Near cursor: draw a white radial glow at r * 4 radius, opacity scaled by nearFactor.
8. Draw solid white circle at radius r.
9. Mouse events: mousemove updates cursor position relative to canvas rect; mouseleave sends cursor to {-9999, -9999}.
NAVBAR
Wrap with a plain div for fixed positioning — position: fixed; top: 1rem; left: 50%; transform: translateX(-50%); width: calc(100% - 2rem); max-width: 56rem; z-index: 50.
Apply Framer Motion fade-in (y: -18 → 0, opacity: 0 → 1, duration: 1.1) to the inner pill only, not the positioning wrapper.
Inner pill: liquid-glass, border-radius: 9999px, px-5 h-14, display: flex; align-items: center;, adds deeper shadow on scroll (triggers after 30px).
• Left (flex: 1): "Aether" in Instrument Serif italic, text-white, text-xl, tracking-tight.
• Center (flex-shrink, auto): ["Services", "Work", "Process", "Pricing"] as anchor links — text-sm, text-white/75, hover:text-white, font-weight 400.
• Right (flex: 1, justify-end): solid white button — bg-white, text-black, rounded-full, px-5 py-1.5, text-sm, font-medium — "Get Started" + ArrowUpRight w-3.5 h-3.5.
HERO SECTION
height: 100vh; min-height: 600px; background: black; overflow: hidden.
Uses useScroll + useTransform for parallax: content y goes 0→45px, opacity 1→0 over scroll progress 0→0.6.
Video background — Cloudinary iframe, position: absolute; top: 0; left: 0; width: 100%; height: 56.25vw; border: none; pointer-events: none; z-index: 0.
URL: <https://player.cloudinary.com/embed/?cloud_name=dgqsqiucd&public_id=Untitled_design_ydxlbl&autoplay=true&loop=true&muted=true&controls=false&showLogo=false&showJumpControls=false&hideContextMenu=true>
Subtle darkening overlay: absolute inset-0 z-1 rgba(0,0,0,0.05).
<ParticleCanvas /> at z-index: 2.
Hero content — z-10, paddingTop: 110px, centered column:
• Badge: liquid-glass inline-flex items-center gap-2 rounded-full px-4 py-2 — "New" tag in white bg, black text, xs semibold; "Introducing AI-powered web design." in text-white/75 text-[0.82rem]. Animates from y:20, opacity:0 at delay 0.1s.
• <ParticleTitle /> in a maxWidth: 960px wrapper.
• Subtext motion.p: "Stunning design. Blazing performance. Built by AI, refined by experts. This is web design, wildly reimagined." — Barlow font-weight:300 text-[1rem] text-white/65, blur 8px→0 at delay 0.8s.
• Two CTAs at delay 1.1s: liquid-glass-strong rounded-full px-7 py-3 "Get Started" + ArrowUpRight; plain rounded-full px-5 py-3 text-white/60 "Watch the Film" + Play icon.
Bottom fade: position: absolute; z-index: 5; top: calc(56.25vw - 280px); height: 280px;
background: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,0.5) 45%, rgba(0,0,0,0.9) 80%, black 100%).
SECTION 2 — INTRO (IntroSection)
background: black; py-28 md:py-36 px-6; text-center; overflow: hidden.
Video background — <video autoPlay loop muted playsInline> direct MP4, absolutely centered at top:50% left:50% width:70% height:70% translate(-50%,-50%), z-index: 0,
radial mask: radial-gradient(ellipse 80% 80% at 50% 50%, black 20%, transparent 75%), objectFit: contain.
URL: <https://res.cloudinary.com/dgqsqiucd/video/upload/v1773990554/14967453_1920_1080_30fps_nrgzdo.mp4>
Content (max-w-3xl mx-auto z-2, staggered fade-up on scroll):
• Badge: <span className="section-badge">Trusted by modern brands</span>
• H2: "Design that feels like / a world, not a template." — Instrument Serif italic tracking-[-0.04em] leading-[0.92] text-5xl md:text-6xl lg:text-7xl.
• P: "We build web experiences that transcend the ordinary — / immersive, cinematic, and unmistakably yours." — Barlow font-weight:300 text-white/72 text-[1.05rem].
• Partners row: ["Luminary", "Celestia", "Vaulted", "Prism", "Aura", "Nocturne"] — text-sm tracking-widest uppercase Barlow font-weight:300 text-white/42 gap-8 md:gap-12.
Bottom fade: absolute bottom-0 left-0 right-0 z-3 height:300px linear-gradient(to bottom, transparent, black).
SECTION 3 — HOW IT WORKS (HowItWorksSection)
background: black. Inner div: relative overflow-hidden py-40 md:py-56 px-6.
Video background — Cloudinary iframe, position: absolute; top: -12%; left: 0; width: 100%; height: 124%; border: none; pointer-events: none; z-index: 0.
URL: <https://player.cloudinary.com/embed/?cloud_name=dgqsqiucd&public_id=Untitled_design_2_elcyul&autoplay=true&loop=true&muted=true&controls=false&showLogo=false&showJumpControls=false&hideContextMenu=true>
Top+bottom fade overlay: absolute inset-0 z-1 background: linear-gradient(to bottom, black 0%, transparent 45%, transparent 55%, black 100%).
Content (max-w-5xl mx-auto text-center z-2, staggered fade-up):
• Badge: "How It Works"
• H2: "You imagine it. / We shape it." — same heading style.
• P: "From concept to launch, our AI-guided process turns direction into a site that feels polished, cinematic, and alive." — Barlow font-weight:300 text-white/70 text-[1.05rem] max-w-xl mx-auto.
SECTION 4 — FEATURES (FeaturesSection)
background: black; py-28 md:py-36 px-6; overflow: hidden.
Video background — same MP4 as Section 2, but <video> with objectFit: cover, position: absolute; top:50% left:50% width:60% height:60% translate(-50%,-50%) z-0,
radial mask: radial-gradient(ellipse 80% 80% at 50% 50%, black 15%, transparent 72%).
Content (max-w-4xl mx-auto z-1):
• Header (centered, mb-14): badge "Capabilities", H2 "Built with beauty / and performance in balance." — same heading style.
• Cards grid: grid md:grid-cols-2 gap-5 max-w-3xl mx-auto.
4 cards, each motion.div — fade-up on scroll, delay: i * 0.1, whileHover: { y: -6 }.
Style: rounded-3xl p-7 relative overflow-hidden, background linear-gradient(145deg, rgba(255,255,255,0.06), rgba(255,255,255,0.02)), backdropFilter: blur(40px),
border: 1px solid rgba(255,255,255,0.09), boxShadow: 0 1px 0 rgba(255,255,255,0.08) inset, 0 20px 60px rgba(0,0,0,0.5).
Each card contains:
• Shimmer line: absolute top-0 left-6 right-6 h-px background: linear-gradient(to right, transparent, rgba(255,255,255,0.18), transparent).
• Hover glow: absolute inset-0 opacity-0 group-hover:opacity-100 duration-700 — radial-gradient white at top-left.
• Number: absolute top-6 right-7 — "01" through "04", Barlow font-weight:300 text-white/20 text-xs tracking-[0.05em].
• Icon container: w-11 h-11 rounded-2xl mb-5, background linear-gradient(135deg, rgba(255,255,255,0.09), rgba(255,255,255,0.03)), border: 1px solid rgba(255,255,255,0.12), color: rgba(255,255,255,0.75).
• Title: Barlow font-medium text-[0.95rem] text-white mb-2.5 tracking-[-0.01em].
• Description: Barlow font-weight:300 text-[0.85rem] text-white/45 leading-relaxed.
Card data (use lucide-react icons — Eye, Sparkles, Zap, Package):
1. Eye — "Cinematic Visual Systems" — "Immersive layouts, motion, and atmosphere that feel authored, not assembled. Every pixel placed with intent."
2. Sparkles — "AI-Led Creative Direction" — "We turn prompts, references, and brand signals into cohesive visual experiences that feel unmistakably yours."
3. Zap — "Fast Iteration" — "Explore ambitious directions quickly without losing polish. Rapid cycles, high fidelity, always."
4. Package — "Production-Ready Output" — "Refined front-end builds designed for responsiveness, clarity, and launch. No handoff headaches."
CTA SECTION
background: black; py-28 md:py-40 px-6.
max-w-3xl mx-auto text-center, staggered fade-up.
• Badge: "Begin"
• H2: "Your next website / starts here." — Instrument Serif italic tracking-[-0.04em] leading-[0.9] text-5xl md:text-6xl lg:text-7xl.
• P: "Book a free strategy call and explore what AI-powered design can become." — Barlow font-weight:300 text-white/70 text-[1.05rem] max-w-md mx-auto mb-10.
• Two buttons: liquid-glass-strong rounded-full px-8 py-3.5 "Book a Call" + ArrowUpRight; liquid-glass rounded-full px-8 py-3.5 text-white/80 font-light "View Pricing" + ChevronRight.
FOOTER
background: black; px-6 pb-10.
max-w-5xl mx-auto.
Horizontal rule: h-px w-full mb-8; background: rgba(255,255,255,0.12).
Two-column row: flex flex-col md:flex-row items-center justify-between gap-4.
• Left: "© 2026 Aether Design. All rights reserved." — Barlow font-weight:300 text-white/38 text-xs.
• Right: ["Privacy", "Terms", "Contact"] as <a href="#"> links — flex items-center gap-6; Barlow font-weight:300 text-xs color: rgba(255,255,255,0.38); hover:text-white/70 transition-colors duration-200.