🍌 855+ Nano Banana Prompts
精選圖像生成提示詞庫,即複即用 → 點擊探索
正在確認會員權限…
Sentinel AI
置頂SkyElite Private Jets
置頂AI Designer Portfolio
置頂Asme
置頂Email Landing Page
置頂3D Jack Portfolio
置頂Securify Data Security
置頂👥 已分享Aetheris Voyage
置頂Skill- -grill me
Skill - grill - me
grill me
Skill - find-lead-to-gmail
Skill - zoom-meeting-minutes
Skill - youtube-to-social-media-270
Nexto 404
Nexto 404
Build a 404 "Page Not Found" hero page as a single full-viewport (100vh, no scroll) React + Vite + Tailwind CSS application using the DM Sans font and Google Material Symbols Rounded icons. The page must match the following specification exactly: --- ## Fonts & External Resources - **Google Font:** DM Sans (all weights, variable: `opsz 9..40, wght 100..1000`) - **Google Material Symbols Rounded:** `opsz,wght,FILL,GRAD@24,400,1,0` - **Logo image:** `https://pub-f170a2592d2c4a1485466404c36807be.r2.dev/Tests/logoipsum-415.svg` (rendered with `filter: brightness(0)` to make it black, height 28px) - **Background spaceship image:** `https://pub-e68758f43067417dba612b2371819aa1.r2.dev/viktor-components/alien-spaceship.png` --- ## Layout The entire page is exactly `100vh` with `overflow: hidden` on html, body, and `#root`. No scrolling. The body uses `display: flex; flex-direction: column`. The `#root` div also uses `height: 100vh; display: flex; flex-direction: column; overflow: hidden`. --- ## Background Body has a layered background: 1. The spaceship PNG centered at `center 40%`, sized with `background-size: contain` 2. A `linear-gradient(to top left, #F5F5F5, #F7F7F7)` covering the full page Both are `background-attachment: fixed` and `no-repeat`. --- ## Color Variables (CSS custom properties) ``` --text-main: #1a1a1a --text-secondary: #888888 --bg-page: #F5F5F5 --card-bg: #ffffff ``` --- ## Navbar - Max-width `1100px`, centered, padding `28px 40px` - Has a dashed bottom border made with `background-image: linear-gradient(to right, rgba(0,0,0,0.08) 2px, transparent 2px); background-size: 6px 1px` on a `::after` pseudo-element - **Left:** Logo (the SVG image + the text "nexto." in 20px bold, -0.3px letter-spacing, color #111, flex with 9px gap) - **Center:** Nav links ("Our Team", "Solutions" with a dropdown arrow character, "Showcase", "News") - 14px, weight 400, opacity 0.65, hover to opacity 1, gap 36px - **Right:** CTA button "Let's Connect" - dark gradient button (`linear-gradient(180deg, #2c2c2c 0%, #111111 100%)`), white text 13px weight 500, border-radius 40px, padding `5px 16px 5px 5px`. Has a white circular arrow icon (24px circle) on the LEFT side with a chevron SVG inside. Box-shadow `0 4px 15px rgba(0,0,0,0.15)`. On hover: translateY(-1px), stronger shadow, brightness(1.1). - **Hamburger (mobile only):** 3 spans, 24px wide, 2px height, animates to X when active. Hidden on desktop, shown on mobile (`display: flex` at max-width 768px). --- ## Mobile Navigation - Fixed full-screen overlay, slides in from right with `transform: translateX(100%)` -> `translateX(0)`, cubic-bezier(0.77, 0, 0.175, 1) transition - On mobile: left-aligned, large links (38px, weight 800, letter-spacing -1.5px), each with bottom border, padding 24px 0 - Last link is the CTA button styled same as navbar but with 32px arrow circle --- ## Main Content Area - `flex: 1`, centered both ways (`align-items: center; justify-content: center`), max-width 700px, padding `20px 20px 30px` - **Lost text:** "Seems you've wandered off..." - 15px, color `--text-secondary`, weight 400, margin-bottom 12px - **Title wrapper:** `position: relative; display: inline-block; margin-bottom: 14px` - **Cloud decoration:** Material Symbols "cloud" icon, positioned `top: -18px; left: -24px`, font-size 42px, with gradient text fill (`linear-gradient(to bottom, #F7B2FB 50%, #786EF1 80%, #5588FB 100%)` using `-webkit-background-clip: text; -webkit-text-fill-color: transparent`), white drop-shadow outline, `floatSlow` animation (5s, 0.3s delay) - **Heart decoration:** Material Symbols "favorite" icon, positioned `bottom: -15px; right: 20px`, font-size 32px, same gradient fill, white drop-shadow outline, `floatSlow` animation (4.5s, 1s delay) - **Title:** "Whoops! Nothing here yet" - `font-size: clamp(34px, 5vw, 52px)`, weight 500, letter-spacing -1.5px, line-height 1.08, color #0f0f0f - **Subtext:** "Grab a 30-minute `chat` to explore your ideas, scope, and vision. We'll find common ground, sync and `define` a clear roadmap." - 14px, color `--text-secondary`, line-height 1.7, max-width 470px, margin-bottom 28px. The words "chat" and "define" are in highlighted tags (inline-flex, background #E0E2E7, 12.5px, weight 600, padding 2px 12px, border-radius 6px) --- ## Navigation Cards - Flex column, gap 12px, max-width 460px, positioned at bottom with `margin-top: auto` - **Card 1 "Main Page":** House SVG icon (path: `M3 9.5L12 3l9 6.5V20a1 1 0 01-1 1H5a1 1 0 01-1-1V9.5z` with door `M9 21V12h6v9` in white). Subtitle: "Back where it all begins..." - **Card 2 "Showcase":** Circle-dot SVG icon (circle r=9 filled, inner circle r=3.5 white). Subtitle: "Where we walk the walk" - Each card: white background, border-radius 18px, padding 18px 22px, flex between, 1px border rgba(0,0,0,0.05), shadow `0 2px 12px rgba(0,0,0,0.04)`. On hover: translateY(-3px), shadow `0 8px 28px rgba(0,0,0,0.08)`. - Icon container: 48px circle, background #eaecf0, scales 1.05 on card hover - Right chevron arrow (rsaquo character, 21px), translateX(6px) on hover - Card title: 15px weight 600, subtitle: 12px color `--text-secondary` --- ## Animations ```css @keyframes floatSlow { 0%, 100% { transform: translateY(0px) rotate(0deg); } 50% { transform: translateY(-10px) rotate(3deg); } } ``` --- ## Responsive Breakpoints **768px and below:** - Hide nav-links and desktop CTA button, show hamburger - Background-size: 90%, position: center 45% - Navbar padding: 20px - Title: 30px, decorations smaller - Cards: full width, gap 10px, smaller padding/icons **480px and below:** - Title: 26px - Background-size: 100% - Decorations even smaller ---
Modern Agency
Modern Agency
Build a React + Vite + Tailwind CSS landing page for "Axion Studio" - a design agency site. Use the `shaders` package (npm: `shaders`) for the hero background, `lucide-react` for icons. The page has 3 sections. Match every detail exactly: --- ## SECTION 1: HERO (Full viewport height) **Background:** Light gray `#EFEFEF` with a full-screen animated shader overlay (positioned absolute, inset-0, z-10, pointer-events-none). The shader stack uses components from `shaders/react`: - `Swirl` - colorA: `#ffffff`, colorB: `#f0f0f0`, detail: 1.7 - `ChromaFlow` - baseColor: `#ffffff`, downColor/leftColor/rightColor/upColor: `#ff5f03`, momentum: 13, radius: 3.5 - `FlutedGlass` - aberration: 0.61, angle: 31, frequency: 8, highlight: 0.12, highlightSoftness: 0, lightAngle: -90, refraction: 4, shape: "rounded", softness: 1, speed: 0.15 - `FilmGrain` - strength: 0.05 **Navigation (z-20, relative):** A pill-shaped white navbar (`bg-white rounded-full`) with 5px padding, inside a max-w-[1440px] container with p-2 sm:p-3. - LEFT: Dark circle logo (w-9 h-9 sm:w-10 sm:h-10, bg-gray-900, rounded-full) with white text "AX" (10px/11px, font-bold, tracking-tight). Next to it (hidden on mobile, shown md+): nav links "Projects", "Studio", "Journal", "Connect" - 14px, text-gray-900, hover:text-gray-500, transition-colors duration-300, gap-6. - RIGHT (hidden on mobile, shown md+): - Text "Taking on projects for Q1 2026" (13px, text-gray-600, hidden below lg) - Clock icon (lucide, size 14) + live London time "{HH:MM} in London" (13px, text-gray-600) - CTA button: bg-gray-900, text-white, 13px font-medium, rounded-full, pl-5 pr-2 py-2. Text "Book a strategy call" with a HOVER TEXT ROLL animation: the text is duplicated inside a flex-col container with overflow-hidden h-[20px], on group-hover it translates -50% vertically (duration-500, ease cubic-bezier(0.25,0.1,0.25,1)). Arrow icon in a white circle (w-6 h-6) that rotates -45deg on hover (same easing). - MOBILE: A "Menu"/"Close" toggle button (md:hidden), bg-gray-900, rounded-full, with Menu/X icons from lucide-react. **Mobile Menu Overlay:** Fixed inset-0, z-50. Black/60 backdrop. A white bottom sheet (rounded-2xl, mx-3 mb-3) that slides up (translate-y-full to translate-y-0, duration-500, ease cubic-bezier(0.32,0.72,0,1)). Contains: time badge, nav links (28px/32px font-medium), and a "Start a project" button with arrow. **Hero Content (z-20):** Positioned at the bottom of the viewport using flexbox (flex-1 spacer above). Max-w-[1440px], px-5 sm:px-8 lg:px-12, pb-14 sm:pb-16 lg:pb-20. - Small label: "Axion Studio" (13px/14px, text-gray-900, tracking-wide, mb-5 sm:mb-8) - Headline h1: "We craft digital experiences / for brands ready to dominate / their category online." - clamp(1.75rem,7vw,4.2rem) on mobile, clamp(2.5rem,5vw,4.2rem) on sm+. font-medium, leading-[1.08], tracking-[-0.03em], text-gray-900. Line breaks hidden on mobile (uses `<br className="hidden sm:block" />` with `<span className="sm:hidden"> </span>` fallback spaces). - CTA row (mt-8 sm:mt-12, flex-col sm:flex-row, gap-4 sm:gap-5): - Orange button: bg-[#F26522], hover:bg-[#e05a1a], text-white, 13px/14px, rounded-full, pl-5 sm:pl-6 pr-2 py-2. Same text-roll hover animation for "Start a project". White circle (w-7 h-7 sm:w-8 sm:h-8) with orange ArrowRight that rotates -45deg on hover. - Partner badge: White pill with subtle shadow (0_2px_8px_rgba(0,0,0,0.08)), hover shadow (0_4px_16px_rgba(0,0,0,0.12)), rounded-[4px]. Contains an inline SVG icon (the starburst/compass shape below, w-5 h-5 sm:w-6 sm:h-6, fill-current text-[#E8704E]), text "Certified Partner" (13px/14px font-medium), and a dark badge "Featured" (10px/11px, bg-gray-900, text-white, px-1.5 sm:px-2 py-0.5, rounded). **SVG Icon for partner badge:** ```svg <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="m19.6 66.5 19.7-11 .3-1-.3-.5h-1l-3.3-.2-11.2-.3L14 53l-9.5-.5-2.4-.5L0 49l.2-1.5 2-1.3 2.9.2 6.3.5 9.5.6 6.9.4L38 49.1h1.6l.2-.7-.5-.4-.4-.4L29 41l-10.6-7-5.6-4.1-3-2-1.5-2-.6-4.2 2.7-3 3.7.3.9.2 3.7 2.9 8 6.1L37 36l1.5 1.2.6-.4.1-.3-.7-1.1L33 25l-6-10.4-2.7-4.3-.7-2.6c-.3-1-.4-2-.4-3l3-4.2L28 0l4.2.6L33.8 2l2.6 6 4.1 9.3L47 29.9l2 3.8 1 3.4.3 1h.7v-.5l.5-7.2 1-8.7 1-11.2.3-3.2 1.6-3.8 3-2L61 2.6l2 2.9-.3 1.8-1.1 7.7L59 27.1l-1.5 8.2h.9l1-1.1 4.1-5.4 6.9-8.6 3-3.5L77 13l2.3-1.8h4.3l3.1 4.7-1.4 4.9-4.4 5.6-3.7 4.7-5.3 7.1-3.2 5.7.3.4h.7l12-2.6 6.4-1.1 7.6-1.3 3.5 1.6.4 1.6-1.4 3.4-8.2 2-9.6 2-14.3 3.3-.2.1.2.3 6.4.6 2.8.2h6.8l12.6 1 3.3 2 1.9 2.7-.3 2-5.1 2.6-6.8-1.6-16-3.8-5.4-1.3h-.8v.4l4.6 4.5 8.3 7.5L89 80.1l.5 2.4-1.3 2-1.4-.2-9.2-7-3.6-3-8-6.8h-.5v.7l1.8 2.7 9.8 14.7.5 4.5-.7 1.4-2.6 1-2.7-.6-5.8-8-6-9-4.7-8.2-.5.4-2.9 30.2-1.3 1.5-3 1.2-2.5-2-1.4-3 1.4-6.2 1.6-8 1.3-6.4 1.2-7.9.7-2.6v-.2H49L43 72l-9 12.3-7.2 7.6-1.7.7-3-1.5.3-2.8L24 86l10-12.8 6-7.9 4-4.6-.1-.5h-.3L17.2 77.4l-4.7.6-2-2 .2-3 1-1 8-5.5Z"/></svg> ``` --- ## SECTION 2: ABOUT (White background) `bg-white`, pt-16 sm:pt-20 lg:pt-32, pb-12 sm:pb-16 lg:pb-24, overflow-hidden. Max-w-[1440px] container. **Badge row:** px-5 sm:px-8 lg:px-12, flex items-center gap-3, mb-6 sm:mb-8. - Numbered circle: w-6 h-6 sm:w-7 sm:h-7, rounded-full, bg-gray-900, text-white, 11px/12px font-semibold. Shows "1". - Pill label: "Introducing Axion" - 12px/13px, font-medium, border border-gray-200, rounded-full, px-3 sm:px-4 py-1 sm:py-1.5. **Heading h2:** "Strategy-led creatives, delivering / results in digital and beyond." - clamp(1.5rem,4vw,3.2rem), font-medium, leading-[1.12], tracking-[-0.02em], text-gray-900, mb-12 sm:mb-16 lg:mb-28. **Content area (responsive):** - MOBILE/TABLET (lg:hidden): Stacked - paragraph + button, then images. - Paragraph: "Through research, creative thinking and iteration we help growing brands realize their digital full potential." - 15px/17px, leading-[1.6], font-medium, text-gray-900. - Button: "About our studio" - orange (#F26522), same text-roll animation, white arrow circle rotates -45deg. - Two images: flex-col sm:flex-row, gap-4 sm:gap-5. First: sm:w-[45%] aspect-[438/346]. Second: sm:w-[55%] aspect-[900/600]. Both rounded-xl sm:rounded-2xl, object-cover. - DESKTOP (hidden lg:grid): `grid-cols-[26%_1fr_48%] items-end gap-6 xl:gap-8`. - Left column (self-end): Small image, aspect-[438/346], rounded-2xl. - Center column (self-start, flex justify-end): Paragraph (16px/18px, leading-[1.65], whitespace-nowrap, with `<br/>` between lines) + orange button. - Right column (self-end): Large image, aspect-[3/2], rounded-2xl. **Image URLs:** - Small image: `https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260516_090123_74be96d4-9c1b-40cf-932a-96f4f4babed3.png&w=1280&q=85` - Large image: `https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260516_090133_c157d30b-a99a-4477-bec1-a446149ec3f2.png&w=1280&q=85` --- ## SECTION 3: CASE STUDIES (Light gray background) `bg-[#F5F5F5]`, pt-16 sm:pt-20 lg:pt-28, pb-16 sm:pb-20 lg:pb-28. Max-w-[1440px] container. **Badge row:** Same pattern as Section 2, but number is "2", label is "Featured client work", border-gray-300. **Heading h2:** "Our projects" - same clamp sizing as hero headline (clamp(1.75rem,7vw,4.2rem) / clamp(2.5rem,5vw,4.2rem)), font-medium, leading-[1.08], tracking-[-0.03em], mb-10 sm:mb-14 lg:mb-16. **Cards Grid:** `grid grid-cols-1 md:grid-cols-2 gap-5 sm:gap-6 lg:gap-7`, px-5 sm:px-8 lg:px-12. **Card 1 (Narrativ):** - Video container: aspect-[329/246], rounded-2xl, overflow-hidden, bg-[#1a1d2e], group, cursor-pointer. - Video: `src="https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260516_122702_390f5305-8719-41d5-ae80-d23ab3796c28.mp4"`, autoPlay, muted, loop, playsInline, w-full h-full object-cover. - Hover button (absolute bottom-4 left-4): A white circle (h-9 w-9) that expands to w-[148px] on group-hover (transition-all duration-300 ease-in-out). Contains "Learn more" text (13px, font-medium, opacity-0 to opacity-100 on hover with delay-100) and a link/chain SVG icon (14x14, -rotate-45 to rotate-0 on hover). The SVG is the lucide "link" icon drawn manually with two arc paths. - Description: "Winner of Site of the Month 2025 - an interactive 3D showcase driving record engagement" - 13px/14px, text-gray-600, mt-4, leading-relaxed. - Title: "Narrativ" - 14px/15px, font-semibold, text-gray-900, mt-1. **Card 2 (Luminar):** - Video container: aspect-square, rounded-2xl, overflow-hidden, bg-[#6b6b6b], group, cursor-pointer. - Video: `src="https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260516_123323_f909c2b8-ff6c-4edf-882b-8ebcdbe389b5.mp4"`, autoPlay, muted, loop, playsInline, w-full h-full object-cover. - Hover button (absolute bottom-4 left-4): A DARK circle (bg-gray-900, h-9 w-9) that expands to w-[168px] on group-hover. Contains "View case study" text (13px, font-medium, text-white) and a white ArrowRight icon (size 14) that transitions from -rotate-45 to rotate-0 on hover. - Description: "Transforming a dated platform into a conversion-focused brand experience" - 13px/14px, text-gray-600, mt-4, leading-relaxed. - Title: "Luminar" - 14px/15px, font-semibold, text-gray-900, mt-1. --- ## GLOBAL STYLES (index.css): Standard Tailwind directives plus two utility classes (not actively used in current layout but defined): - `.liquid-glass`: rgba(255,255,255,0.01) bg, backdrop-filter blur(4px), inset box-shadow, pseudo-element gradient border using mask-composite. - `.liquid-glass-strong`: Same but blur(50px), no pseudo-element. --- ## TECHNICAL DETAILS: - **Framework:** React 18 + TypeScript + Vite - **Styling:** Tailwind CSS 3.4 (default config, no custom theme extensions) - **Packages:** `shaders` (for Shader, ChromaFlow, FilmGrain, FlutedGlass, Swirl from `shaders/react`), `lucide-react` (ArrowRight, Clock, Menu, X) - **Font:** System default (no custom font loaded) - **All animations use:** `duration-500 ease-[cubic-bezier(0.25,0.1,0.25,1)]` unless noted otherwise - **Max content width:** 1440px, centered with mx-auto - **Responsive breakpoints:** Default Tailwind (sm: 640px, md: 768px, lg: 1024px, xl: 1280px) - **Live clock:** Updates every second, shows London timezone in HH:MM format
Creative Studio
Creative Studio
Build a full-screen hero section using React, Tailwind CSS, Framer Motion, and Lucide React icons. Use the Inter font. The page is fully mobile-responsive. Here are the exact specifications: --- **BACKGROUND:** - A full-screen autoplaying, looping, muted video covering the entire viewport as a background. - Video URL: `https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260517_222138_3e3205be-3364-417b-a64a-bfe087acbec4.mp4` - The video is positioned absolute, inset-0, with `object-cover` to fill the viewport. --- **COLOR:** - Accent color: `#5E0ED7` (deep purple). Used for the logo dot, the "+" symbols in stats, and the CTA link text. - All body text is black (#000). --- **FONT:** - Font family: `'Inter', sans-serif` applied to the root container. - All text is uppercase with wide letter-spacing (`tracking-widest` or `tracking-wide`). - Font weights: 600 (semibold) throughout. --- **LAYOUT (flex column, min-h-screen):** The page is a flex column with three vertical sections: 1. **Nav** (top, fixed height) 2. **Stats row** (flex-1, vertically centered, right-aligned) 3. **Bottom content** (pinned to bottom with padding) --- **NAVIGATION BAR:** - Horizontal flex, items centered, justified between. Padding: `px-5 sm:px-8 md:px-12 pt-5 md:pt-6`. - **Left:** A circular logo — 32px round div with 2px border in accent color, containing a 10px solid circle in accent color. - **Center (hidden on mobile, visible md+):** Four nav links: "Story", "Expertise", "Studios", "Feedback". Text: 14px, font-semibold, tracking-widest, uppercase, black. - **Right:** A 36px round black button with three horizontal white lines (hamburger icon — three `span` elements, each `w-4 h-0.5 bg-white` with `gap-1`). This opens the mobile menu on click. --- **MOBILE MENU OVERLAY:** - Triggered by hamburger click. Fixed, full-screen, z-50, white background. - Top row: same logo (left) and a 36px round black close button with an X icon (right). - Below: vertical list of the 4 nav links at `text-3xl`, font-semibold, tracking-widest, uppercase, with `gap-8` and `mt-16`. - Bottom (mt-auto): "Work With Us" CTA in accent color with ArrowUpRight icon, `text-xl`. --- **STATS ROW (middle section):** - Container: `flex-1 flex items-center justify-end`, with same horizontal padding. `py-8 md:py-0`. - Three stat items in a horizontal row with `gap-5 sm:gap-8 md:gap-10`, each right-aligned: - **+300** / CRAFTED BRANDS - **+200** / DIGITAL PRODUCTS - **+100** / VENTURES FUNDED - Number styling: `fontSize: clamp(1.5rem, 5vw, 3.5rem)`, weight 600. The "+" is rendered separately in accent color at 0.5em size. The number is black. - Label: `text-[10px] sm:text-xs md:text-sm`, font-semibold, tracking-widest, uppercase, black, `whitespace-pre-line leading-tight` (each label has a line break between the two words). --- **BOTTOM SECTION:** - Padding: `px-5 sm:px-8 md:px-12 pb-8 md:pb-12`. Flex column with `gap-6 md:gap-12`. **Row A (tagline + CTA):** - Flex row, items-center, justify-between, gap-4. - **Left:** Small uppercase tagline paragraph: "Shaping Bold / Visions Into Power / For Your Tribe" (with `<br />` line breaks). Text: `text-[10px] sm:text-xs md:text-sm`, font-semibold, tracking-widest, max-width `130px sm:160px md:max-w-xs`. - **Right:** CTA link "Work With Us" with ArrowUpRight icon. Text: `text-base sm:text-xl md:text-2xl`, accent color, weight 600, `whitespace-nowrap`. Icon: 18px on mobile, 22px on sm+. **Row B (description + main heading):** - Flex row, `items-end`, justify-between, `gap-3 sm:gap-4`. - **Left:** A fixed-width container (`w-[120px] sm:w-[180px] md:w-[280px]`, shrink-0) containing a paragraph: "Creative Studios Built Around Elevating Your Vision Into Striking Reality". Text: `text-[9px] sm:text-xs md:text-sm`, font-semibold, tracking-widest, uppercase, `text-left md:text-right`. - **Right:** The main heading — three words stacked vertically: "Fearless", "Vision", "Delivered". Each word in its own `overflow-hidden` wrapper. Text: `fontSize: clamp(2rem, 9vw, 9rem)`, `lineHeight: 0.88`, weight 600, uppercase, black, text-right. --- **ANIMATIONS (Framer Motion):** All animations fire on page load (initial -> animate). 1. **fadeDown variant** (nav elements): - From: `{ opacity: 0, y: -20 }` - To: `{ opacity: 1, y: 0 }` - Each element has a custom stagger index. Delay: `index * 0.1s`. Duration: 0.5s. Ease: `[0.22, 1, 0.36, 1]`. - Applied to: logo (custom=0), each nav link (custom=1-4), hamburger (custom=5). 2. **fadeUp variant** (stats + bottom content): - From: `{ opacity: 0, y: 32 }` - To: `{ opacity: 1, y: 0 }` - Delay: `index * 0.12s`. Duration: 0.6s. Ease: `[0.22, 1, 0.36, 1]`. - Applied to: each stat card (custom=2,3,4), tagline paragraph (custom=5), CTA link (custom=6), description block (custom=7). 3. **Heading slide-up** (main heading words): - Each word slides up from `y: "110%"` to `y: 0` within its overflow-hidden parent (clip reveal effect). - Delay: `0.4 + wordIndex * 0.14` (so 0.4s, 0.54s, 0.68s). Duration: 0.7s. Ease: `[0.22, 1, 0.36, 1]`. --- **RESPONSIVE BREAKPOINTS:** - Mobile-first. Three tiers: default (mobile), `sm:` (640px), `md:` (768px). - Nav links hidden on mobile, shown md+. - Spacing, font sizes, and widths scale up at each breakpoint. - Mobile menu provides full navigation on small screens. --- **DEPENDENCIES:** - React 18 - Tailwind CSS 3 - framer-motion - lucide-react (ArrowUpRight, X icons)
VaultShield
VaultShield
Create a fullscreen hero section for a password manager app called "VaultShield" using React, TypeScript, Tailwind CSS, Framer Motion, and Lucide React icons. --- ## Fonts - **Heading font:** `Helvetica Now Display Bold` loaded from `https://db.onlinewebfonts.com/c/04e6981992c0e2e7642af2074ebe3901?family=Helvetica+Now+Display+Bold` (add as a `<link>` in `index.html`) - **Body font:** `Inter` (weights 300-900) loaded from Google Fonts: `https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap` (imported in CSS) ## CSS Variables ```css :root { --font-heading: 'Helvetica Now Display Bold', sans-serif; --font-body: 'Inter', sans-serif; --color-text: #192837; --color-accent: #7342E2; --color-login-bg: #F2F2EE; } ``` ## Background Video Full-screen background video covering the entire viewport (`absolute inset-0, object-cover`): ``` https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260518_003132_8b7edcb6-c64d-4a52-a9ca-879942e122ad.mp4 ``` Attributes: `autoPlay`, `muted`, `loop`, `playsInline` ## Layout Structure 1. **Container:** `relative w-full min-h-screen`, font-family from `--font-body`, color from `--color-text` 2. **Navbar:** max-width 1280px, centered, z-10, `px-5 sm:px-8 py-4 sm:py-5`, flex with items centered and space-between 3. **Hero content:** max-width 1280px centered container with `paddingTop: clamp(40px, 8vw, 72px)`, content block capped at `max-width: 560px` ## Logo (SVG) Custom SVG logo, 32x32, fill `#192837`, geometric angular shape: ```svg <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none" overflow="visible" viewBox="0 0 256 256"> <path d="M 64 128 L 64.5 128 L 32 95 L 0 64 L 0 0 L 64 0 L 128 64 L 128 64.5 L 161 32 L 192 0 L 256 0 L 256 64 L 192 128 L 128 128 L 128 192 L 96 223 L 63.5 256 L 0 256 L 0 192 Z M 256 192 L 224 223 L 191.5 256 L 128 256 L 128 192 L 192 128 L 256 128 Z" fill="#192837"/> </svg> ``` ## Navbar Elements - **Left:** Logo - **Center (desktop only, `hidden md:flex`):** 5 links — `['Vault', 'Plans', 'Install', 'News', 'Help']`, text-sm font-medium, opacity hover effect - **Right (desktop only):** - "Start For Free" button — `background: #7342E2`, white text, rounded-full, `px-5 py-2.5` - "Sign In" button — `background: #F2F2EE`, dark text, rounded-full, `px-5 py-2.5` - **Mobile:** Hamburger icon (Menu/X from lucide-react), opens a right-side slide-in sheet ## Mobile Menu Sheet (AnimatePresence + Framer Motion) - **Backdrop:** fixed inset-0, `rgba(25,40,55,0.35)` background with `blur(4px)` backdrop-filter - **Sheet:** fixed right-0 top-0, width `min(88vw, 360px)`, height `100dvh`, background `#CFC8C5`, box-shadow `-12px 0 48px rgba(25,40,55,0.18)` - **Sheet animation:** slides from `x: '100%'` to `x: 0`, ease `[0.22, 1, 0.36, 1]`, duration 0.45s - **Sheet content:** Logo + close button header, 1px divider, staggered nav links (delay `0.18 + i * 0.07`), bottom CTA buttons matching desktop style ## Hero Heading - Font: `var(--font-heading)` - Size: `clamp(1.65rem, 5vw, 3rem)` - Line-height: `1.05` - Letter-spacing: `-0.01em` - Color: `#192837` - Margin-bottom: `24px` - Contains inline Lucide icons (Zap, LockKeyhole, Fingerprint) at 24px, color `#192837`, vertically aligned middle, positioned `top: -2px` - Text: "Lock Down Your Passwords with Ironclad Security" - Zap icon before "Lock" - LockKeyhole icon between "Passwords" and "with" - Fingerprint icon after "Security" ## Hero Subtext - Font: `var(--font-body)` - Size: `clamp(0.9rem, 2.5vw, 1.1rem)` - Line-height: `1.65` - Opacity: `0.8` - Max-width: `560px` - Text: "Zero stress, total control. VaultShield keeps you covered with unbreakable storage, one-tap access, and pro-grade tools for your non-stop world." ## CTA Button - Background: `#7342E2` - Color: white - Border-radius: `50px` - Padding: `17px 24px` - Font: `var(--font-body)`, font-weight semibold - Size: `clamp(0.9rem, 2vw, 1rem)` - Box-shadow: `0 4px 24px rgba(115,66,226,0.28)` - Min-width: `210px` - Flex with space-between, gap `32px` - Text: "Get It Free" with ArrowRightCircle icon (20px) on the right - Hover: `scale(1.04)` + `brightness(1.1)` - Tap: `scale(0.96)` ## Animations (Framer Motion) **fadeUp variant** applied to heading (delay 0), subtext (delay 0.15s), and CTA button (delay 0.30s): ```js hidden: { opacity: 0, y: 28 } visible: { opacity: 1, y: 0, transition: { delay: i * 0.15, duration: 0.6, ease: [0.22, 1, 0.36, 1] } } ``` ## Dependencies - `react`, `react-dom` - `framer-motion` - `lucide-react` (icons: ArrowRightCircle, Zap, LockKeyhole, Fingerprint, Menu, X) - Tailwind CSS --- That is every detail needed to reproduce the hero section exactly as built.
3D Collectible Hero
3D Collectible Hero
Build a single full-viewport hero section in React + TypeScript + Vite + Tailwind CSS, using `lucide-react` for icons. The component is a character-figurine carousel called "TOONHUB". **Fonts (load in `index.html` head):** ```html <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link href="https://fonts.googleapis.com/css2?family=Anton&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" /> ``` Body font: `'Inter', sans-serif`. Display font (huge ghost text + bottom-right link): `'Anton', sans-serif`. **Image data (4 items, exact URLs and colors):** ```ts const IMAGES = [ { src: 'https://fifth-gentle-45902158.figma.site/_components/v2/4de492f6d9cf8244ad5293233e5c6f52407d42fc/1.02464a56.png', bg: '#F4845F', panel: '#F79B7F' }, { src: 'https://fifth-gentle-45902158.figma.site/_components/v2/4de492f6d9cf8244ad5293233e5c6f52407d42fc/2.b977faab.png', bg: '#6BBF7A', panel: '#85CC92' }, { src: 'https://fifth-gentle-45902158.figma.site/_components/v2/4de492f6d9cf8244ad5293233e5c6f52407d42fc/3.4df853b4.png', bg: '#E882B4', panel: '#ED9DC4' }, { src: 'https://fifth-gentle-45902158.figma.site/_components/v2/4de492f6d9cf8244ad5293233e5c6f52407d42fc/4.4457fbce.png', bg: '#6EB5FF', panel: '#8DC4FF' }, ]; ``` Preload all 4 images on mount via `new Image()`. **State & logic:** - `activeIndex` (0–3), `isAnimating` boolean lock, `isMobile` (`window.innerWidth < 640`, updated on resize). - `navigate('next' | 'prev')`: ignore if animating; set `isAnimating=true`; bump `activeIndex` `(prev+1)%4` or `(prev+3)%4`; release lock after `650ms`. - Roles derived from activeIndex: `center=activeIndex`, `left=(activeIndex+3)%4`, `right=(activeIndex+1)%4`, `back=(activeIndex+2)%4`. **Layout structure:** Outer `<div>` has `backgroundColor: IMAGES[activeIndex].bg`, transition `background-color 650ms cubic-bezier(0.4,0,0.2,1)`, `fontFamily: 'Inter, sans-serif'`, `relative w-full overflow-hidden`. Inside, a `relative w-full` div with `height: 100vh; overflow: hidden`. 1. **Grain overlay** (`absolute inset-0 pointer-events-none`, zIndex 50): SVG fractalNoise data URI, `baseFrequency=0.9`, `numOctaves=4`, opacity 0.08 inside SVG, container `opacity: 0.4`, `backgroundSize: 200px 200px`, repeat. 2. **Giant ghost text "3D SHAPE"** (`absolute inset-x-0 flex items-center justify-center pointer-events-none select-none`, zIndex 2, `top: 18%`): font Anton, `fontSize: clamp(90px, 28vw, 380px)`, weight 900, color white, opacity 1, lineHeight 1, uppercase, letterSpacing `-0.02em`, whiteSpace nowrap. 3. **Top-left brand label "TOONHUB"** (`absolute top-6 left-4 sm:left-8`, zIndex 60): `text-xs font-semibold uppercase`, white, opacity 0.9, letterSpacing `0.18em`. 4. **Carousel** (`absolute inset-0`, zIndex 3): map all 4 IMAGES; each item is `position:absolute`, `aspectRatio: '0.6 / 1'`, with role-based styles below. Inside, an `<img>` `width:100%; height:100%; objectFit:contain; objectPosition:bottom center; draggable=false`. Per-role style: - **center**: `transform: translateX(-50%) scale(${isMobile?1.25:1.68})`, no blur, opacity 1, zIndex 20, `left:50%`, `height: isMobile?'60%':'92%'`, `bottom: isMobile?'22%':0`. - **left**: `translateX(-50%) scale(1)`, blur 2px, opacity 0.85, zIndex 10, `left: isMobile?'20%':'30%'`, `height: isMobile?'16%':'28%'`, `bottom: isMobile?'32%':'12%'`. - **right**: same as left but `left: isMobile?'80%':'70%'`. - **back**: `translateX(-50%) scale(1)`, blur 4px, opacity 1, zIndex 5, `left:50%`, `height: isMobile?'13%':'22%'`, `bottom: isMobile?'32%':'12%'`. Transition on each item: `transform 650ms cubic-bezier(0.4,0,0.2,1), filter 650ms ..., opacity 650ms ..., left 650ms ...`. `willChange: transform, filter, opacity`. 5. **Bottom-left text + nav buttons** (`absolute bottom-6 left-4 sm:bottom-20 sm:left-24`, zIndex 60, `maxWidth:320px`): - `<p>` "TOONHUB FIGURINES" — bold uppercase, tracking-widest, `mb-2 sm:mb-3 text-base sm:text-[22px]`, white, opacity 0.95, letterSpacing `0.02em`. - `<p>` (hidden on mobile, `hidden sm:block`): "The artwork is stunning, shipped fully prepared. The finish is a vision, the 3D craft is flawless. Many thanks! Wishing you the win. Order now." — `text-xs sm:text-sm`, white, opacity 0.85, lineHeight 1.6, `mb-4 sm:mb-5`. - Two circular buttons (`w-12 h-12 sm:w-16 sm:h-16`, transparent bg, 2px white border, white icon): `ArrowLeft` and `ArrowRight` from lucide-react, size 26, strokeWidth 2.25. On hover: scale 1.08 + bg `rgba(255,255,255,0.12)`. Transition `transform 150ms, background-color 150ms`. Click triggers `navigate('prev')` / `navigate('next')`. 6. **Bottom-right link "DISCOVER IT"** (`absolute bottom-6 right-4 sm:bottom-20 sm:right-10`, zIndex 60): `<a>` flex items-center, font Anton, `fontSize: clamp(20px, 4vw, 56px)`, weight 400, white, opacity 0.95→1 on hover (200ms), letterSpacing `-0.02em`, lineHeight 1, uppercase, no underline. Followed by `ArrowRight` (`w-5 h-5 sm:w-8 sm:h-8`, strokeWidth 2.25). **Behavior summary:** clicking arrows rotates roles; background color, image positions, scales, blurs, and opacities all crossfade simultaneously over 650ms with `cubic-bezier(0.4,0,0.2,1)`. The character images sit at the bottom of the screen overlapping the giant "3D SHAPE" text behind them.
Cybersecurity Hero
Cybersecurity Hero
Build a **single-page React + TypeScript (Vite)** landing hero for a product called **"Xero"** that recreates the following section exactly. Use the **Inter** Google Font (weights 300, 400, 500, 600, 700, 800). Do not use Tailwind utility classes for the hero — write plain CSS in a global stylesheet. No purple/indigo branding outside the specified pink-magenta gradient arc. ## Layout & Structure Render three top-level blocks centered on a black page (`#0a0a0f`), each constrained to `max-width: 1600px`, in this vertical order: 1. **`<nav>`** — sticky-style top bar (not actually sticky, just at top) 2. **`<section class="hero-card">`** — the rounded dark hero card with the animated icon pipeline 3. **`<div class="brands">`** — a row of 5 monochrome brand logos The body uses `display: flex; flex-direction: column; align-items: center; padding: 14px;` and `font-family: 'Inter', sans-serif;`. ### CSS Variables (on `:root`) ``` --bg: #0a0a0f; --surface: #111118; --text: #f0f0f5; --text-muted: #8888a8; --accent: #c8a0e0; --accent-pink: #b04090; --border: rgba(255, 255, 255, 0.08); ``` ## NAVBAR - Grid layout: `grid-template-columns: 1fr auto 1fr; padding: 12px 24px; margin-bottom: 14px;` - **Left**: `<span class="nav-logo">Xero</span>` — `font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em;` - **Center**: `<ul class="nav-links">` with three `<a>` items: **Method**, **Pricing**, **Docs**. Color `--text-muted`, `font-size: 0.85rem`, gap 32px, hover transitions to `--text` over 0.2s. - **Right**: `<div class="nav-actions">` containing two pill buttons: - `.btn-login` — `rgba(255,255,255,0.06)` bg, 1px border `--border`, white text, padding `7px 18px`, `border-radius: 999px`, `font-size: 0.82rem`, `font-weight: 500`. Hover: bg `rgba(255,255,255,0.12)`. - `.btn-signup` — solid white bg, black `#0a0a0f` text, same dimensions, `font-weight: 600`. Hover: `opacity: 0.88`. - The `.nav-menu` wrapper uses `display: contents` on desktop so the `ul` and actions become direct grid children. ### Mobile (≤ 768px) - Nav becomes flex with space-between. - A `.menu-toggle` hamburger appears: 24×14 button with two 2px-tall white spans. When `.active`, span 1 rotates `translateY(6px) rotate(45deg)` and span 2 rotates `translateY(-6px) rotate(-45deg)` to form an X. - `.nav-menu.active` slides in from `right: -100%` to `right: 0` over 0.4s `cubic-bezier(0.4, 0, 0.2, 1)` as a full-screen `var(--bg)` overlay with column-stacked links and full-width buttons. - Toggling sets `document.body.style.overflow = 'hidden'`. ## HERO CARD Outer `.hero-card` styles: - `width: 100%; max-width: 1600px; border-radius: 20px; border: 1px solid rgba(255,255,255,0.07); overflow: hidden; position: relative; background: #0d0b12; padding: 80px 40px 70px; min-height: 640px;` - `display: flex; flex-direction: column; align-items: center; text-align: center;` ### `::before` Gradient Arc (the signature visual) A radial gradient positioned at `50% -70%` with **many manually-tuned stops** producing a smooth dark→pink→white arc near the top: ``` background: radial-gradient(circle at 50% -70%, transparent 60%, rgba(176,48,136,0.03) 63%, rgba(176,48,136,0.08) 65%, rgba(176,48,136,0.16) 67%, rgba(176,48,136,0.28) 69%, rgba(176,48,136,0.40) 71%, rgba(176,48,136,0.52) 73%, rgba(176,48,136,0.64) 75%, rgba(176,48,136,0.74) 77%, rgba(176,48,136,0.82) 79%, rgba(210,70,175,0.92) 85%, rgba(240,110,210,0.88) 87%, rgba(255,205,250,0.92) 91%, rgba(255,240,255,0.98) 93%, #ffffff 95%), radial-gradient(circle at 50% 35%, rgba(120,40,180,0.08) 0%, transparent 50%); z-index: 0; pointer-events: none; ``` ### `.hero-grid` Overlay A separate absolutely-positioned div with crosshatch grid: ``` background-image: linear-gradient(rgba(255,255,255,0.07) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.07) 1px, transparent 1px); background-size: 40px 40px; mask-image: radial-gradient(circle at 50% -70%, transparent 60%, black 78%); ``` This makes the grid only visible inside the arc area. ## ICON PIPELINE (the animated centerpiece) Container `.icon-pipeline`: `position: relative; display: flex; align-items: center; justify-content: center; max-width: 700px; margin-bottom: 52px; z-index: 1;` Children in this exact order: 1. **`<svg class="beam-svg">`** — absolutely-positioned over the whole pipeline (`overflow: visible`), containing: - A `<filter id="glow">` with `feGaussianBlur stdDeviation="2"` then `feComposite ... operator="over"`. - A `<linearGradient id="beam-gradient" gradientUnits="userSpaceOnUse">` with stops: - `0%` `#b04090` opacity 0 - `20%` `#b04090` opacity 0.8 - `50%` `#fff` opacity 1 - `80%` `#c8a0e0` opacity 0.8 - `100%` `#c8a0e0` opacity 0 - Two `<path>` elements both stroked with `url(#beam-gradient)`: - Glow path: `stroke-width="2"`, `filter="url(#glow)"`, `opacity: 0.6`. - Core path: `stroke-width="0.8"`. 2. **Left node** `.icon-node.node-light-right` (id `node-stack`) — Lucide-style **layers** SVG (3 stacked diamonds): `<polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/>`. 3. **`.pipeline-line`** — `width: 160px; height: 1px;` linear gradient `90deg, rgba(255,255,255,0.15), rgba(255,255,255,0.07)`. 4. **Center wrapper** with `position: relative;` containing: - **`.splash`** — 100×100 absolutely centered, `border-radius: 50%`, `background: radial-gradient(circle, rgba(255,77,200,0.6) 0%, transparent 70%)`, initial `opacity: 0; transform: scale(0.4); z-index: 2;` - **`.icon-node-center`** (id `node-x`) — 64×64 round, `background: #1e1e2c`, neumorphic shadow (see below), containing the **Xero "X" logoipsum** SVG (`viewBox="0 0 40 40"`) — the multi-cut path provided in the source. 5. **`.pipeline-line.right`** — same 160×1 line, gradient reversed. 6. **Right node** `.icon-node.node-light-left` (id `node-shield`) — Lucide-style **shield-check** SVG: `<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><polyline points="9 12 11 14 15 10"/>`. ### Side Node Styling `.icon-node`: 46×46 round, `background: #1a1a24`, `cursor: pointer`, `z-index: 3`, with **neumorphic** shadow stack: ``` box-shadow: 6px 6px 12px rgba(0,0,0,0.4), -4px -4px 10px rgba(255,255,255,0.03), inset 1px 1px 1px rgba(255,255,255,0.05), inset 4px 4px 8px rgba(0,0,0,0.4); ``` Plus an `::after` dotted outer ring at `inset: -7px` (`border: 1px dotted #1a1a24`). Hover: `translateY(-1px)` and stronger shadows. Active: inset-only shadows. Inner SVG: 20×20, stroke `rgba(255,255,255,0.7)`, `stroke-width: 1.5`, fill none, round caps. ### Center Node Styling `.icon-node-center`: 64×64, `background: #1e1e2c`, similar but stronger neumorphic shadow: ``` 8px 8px 16px rgba(0,0,0,0.5), -6px -6px 14px rgba(255,255,255,0.04), inset 1px 1px 2px rgba(255,255,255,0.06), inset 6px 6px 12px rgba(0,0,0,0.5); ``` Inner Xero SVG: 28×28, `fill: white`. ### Side-Light Glows - `.node-light-right::before` — half-circle radial glow on the right side: `radial-gradient(circle at right, rgba(200,200,200,0.45) 0%, transparent 70%)`, `opacity: 0` default, `opacity: 1` when `.active` (300ms transition). - `.node-light-left::before` — same but on left, color `rgba(200,100,255,0.5)`. ### Splash Keyframe ``` @keyframes splash-anim { 0% { transform: scale(0.4); opacity: 0.8; } 40% { opacity: 0.6; } 100% { transform: scale(1.4); opacity: 0; } } ``` Triggered by adding `.animate` (0.8s ease-out forwards). ## BEAM ANIMATION (JavaScript / requestAnimationFrame) Implement a state machine with four phases. On mount and on every window `resize`, recompute the SVG path: ``` const pRect = pipeline.getBoundingClientRect(); const sRect = nodeStack.getBoundingClientRect(); const xRect = nodeX.getBoundingClientRect(); const shRect = nodeShield.getBoundingClientRect(); const startX = sRect.left + sRect.width/2 - pRect.left; const startY = sRect.top + sRect.height/2 - pRect.top; // midX/midY from nodeX, endX/endY from nodeShield const d = `M ${startX},${startY} L ${midX},${midY} L ${endX},${endY}`; ``` Set this `d` on **both** beam paths. The gradient is animated by mutating `x1` / `x2` of `#beam-gradient` (in `userSpaceOnUse`) so the bright window slides along. Use `halfWidth = 5` (percentage units), `center = percentage * 100`: ``` gradient.x1 = (center - 5) + '%' gradient.x2 = (center + 5) + '%' y1 = y2 = '0%' ``` State machine in a `requestAnimationFrame` loop, tracking `lastStateChange` timestamp: | State | Duration | Behavior | |---|---|---| | **`p1`** | 800 ms | `percentage` interpolates `0 → 0.5`. While `p < 0.4`, add `.active` to `node-stack`; remove after. At end: switch to `splash`, hide both beam paths (`opacity: 0`), add `.animate` to splash. | | **`splash`** | 800 ms | Wait. After elapsed: switch to `p2`, remove `.animate`, restore `opacity: 1` on both beam paths. | | **`p2`** | 800 ms | `percentage` interpolates `0.5 → 1.0`. While `p > 0.6`, add `.active` to `node-shield`. At end: remove `.active`, switch to `idle`. | | **`idle`** | 1000 ms | Wait, then loop back to `p1`. | Total cycle ≈ 3.4 seconds, infinite. ## HERO TEXT `.hero-content` `max-width: 620px; z-index: 1;` ```html <h1 class="hero-heading"> The simple way <strong>encryption your data</strong> </h1> <p class="hero-sub"> Fully managed data encrypting service and annotation<br> platform for teams of all industries. </p> <a href="#" class="btn-cta">Get Started</a> ``` - `.hero-heading`: `font-size: clamp(2.4rem, 5.5vw, 4rem); font-weight: 300; line-height: 1.1; letter-spacing: -0.02em;` - `.hero-heading strong`: `display: block; font-weight: 400; margin-top: 4px;` with `background: linear-gradient(to right, #ffffff, #a98597); -webkit-background-clip: text; -webkit-text-fill-color: transparent;` - `.hero-sub`: 0.9rem, `rgba(255,255,255,0.4)`, `max-width: 440px`, `margin: 0 auto 36px`. - `.btn-cta`: white pill, black text, `padding: 12px 32px; border-radius: 999px; font-weight: 600;`. Hover: `opacity: 0.9; translateY(-1px)`. ## BRANDS ROW `.brands`: flex row, `gap: 64px; padding: 32px 24px 10px; flex-wrap: wrap; justify-content: center;` Five `.brand-item` blocks (each: flex, gap 10, color `rgba(255,255,255,0.35)`, font-size 1.1rem, font-weight 500, white-space nowrap, with a 22×22 SVG): 1. **Expedia** — `<circle cx=12 cy=12 r=10 fill=current /><path fill="var(--bg)" d="M8 9h8v2H8zm0 4h6v2H8z"/>` then text `Expedia`. 2. **asana** — three filled circles: `(12,7,r=4)`, `(5,16,r=3.5)`, `(19,16,r=3.5)`, text `asana`. 3. **zenefits** — three stroked horizontal polylines (lengths 16/8/16) at y=8/12/16, text `zenefits`. 4. **HubSpot** — small filled circle `(15.5,8.5,r=2.5)`, stroked circle `(8.5,8.5,r=2)`, paths connecting them; text `HubSp<span class="hubspot-dot"></span>t` where `.hubspot-dot` is a 6×6 round superscript dot. 5. **loom** — circle `(12,12,r=9)` plus vertical/horizontal/diagonal stroke lines forming a globe-with-X, text `loom`. ## Responsive Breakpoints - `≤ 860px`: pipeline `gap: 0; margin-bottom: 40px;` `.pipeline-line { width: 80px }`. - `≤ 768px`: enable mobile hamburger menu, `.icon-node` shrinks to 38×38, `.icon-node-center` to 52×52, `.hero-card { padding: 60px 20px 60px; min-height: auto }`, `.brands { gap: 32px }`. - `≤ 480px`: `.hero-card { border-radius: 16px }`, `.brands { gap: 24px }`. ## Z-Index Stack (critical for splash/beam layering) - `0` — gradient arc + grid overlay - `1` — pipeline container, hero text - `2` — beam SVG, splash - `3` — all icon nodes - `4` — node side-light glows - `1000-1001` — mobile nav overlay and toggle Implement all of the above exactly. Use `useRef` for the pipeline, the three nodes, both beam paths, the gradient, and the splash. Use one `useEffect` to set up the resize listener and the `requestAnimationFrame` loop, and clean both up on unmount.
Neo Museum
Neo Museum
Project Setup Stack: React 19 + Vite 6 + Tailwind CSS 4 + Motion (Framer Motion) + Lucide React icons + TypeScript package.json dependencies: - `react`, `react-dom` ^19.0.1 - `vite` ^6.2.3 - `@tailwindcss/vite` ^4.1.14, `tailwindcss` ^4.1.14 - `motion` ^12.23.24 - `lucide-react` ^0.546.0 - `@vitejs/plugin-react` ^5.0.4 - `typescript` ~5.8.2 Fonts (loaded via Google Fonts in `index.css`): - Sans: Inter (weights: 300, 400, 500, 600) - Mono: JetBrains Mono (weights: 400, 500) ```css /* index.css */ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@400;500&display=swap'); @import "tailwindcss"; @theme { --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif; --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, monospace; } @layer utilities { .text-mega { font-size: 21vw; line-height: 0.75; letter-spacing: -0.04em; } } ``` Global styling: Background `#fcfcfc`, text `#111`, selection color `bg-black text-white`, `overflow-x-hidden`, `font-sans` (Inter). --- DATA ```tsx const chaptersData = [ { name: "Age of Dinosaurs", image: "https://res.cloudinary.com/dsdxaxkiz/image/upload/v1779624247/01_udnber.png" }, { name: "Fossils of Ancient Life", image: "https://res.cloudinary.com/dsdxaxkiz/image/upload/v1779624374/02_pmvxxl.png" }, { name: "Reptiles of the Mesozoic", image: "https://res.cloudinary.com/dsdxaxkiz/image/upload/v1779624236/03_hcp3jc.png" }, { name: "Marine Fossil Gallery", image: "https://res.cloudinary.com/dsdxaxkiz/image/upload/v1779624256/04_get63z.png" }, { name: "Prehistoric Giants", image: "https://res.cloudinary.com/dsdxaxkiz/image/upload/v1779624251/05_kz1tyu.png" } ]; ``` --- STATE ```tsx const [showVideo, setShowVideo] = useState(false); const [activeChapter, setActiveChapter] = useState(2); // starts at "Reptiles of the Mesozoic" const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); ``` - `showVideo` flips to `true` after a 2800ms delay (setTimeout) - `activeChapter` auto-cycles every 3500ms via setInterval, wrapping `(prev + 1) % 5` --- ANIMATION VARIANTS ```tsx const fadeUp = { initial: { opacity: 0, y: 20 }, animate: { opacity: 1, y: 0 }, }; const letterBlock = { initial: { y: 120, opacity: 0 }, animate: { y: 0, opacity: 1, transition: { duration: 1.2, ease: [0.16, 1, 0.3, 1] } } }; ``` --- SECTION 1: HERO (full viewport height) Container: `relative w-full min-h-screen flex flex-col overflow-hidden` 1A. HEADER (NHM Logo) - `motion.header` with `staggerChildren: 0.1, delayChildren: 0.1` - Padding: `pt-6 px-6 md:px-16`, `z-20` - The "NHM" logo is a custom inline SVG with `viewBox="0 0 840 100"`, `fill-[#111]`, full width - The SVG is wrapped in `motion.h1` with `variants` that animate from `scale: 1.03` to `scale: 1` with `staggerChildren: 0.06, delayChildren: 0.1` - Each polygon of each letter uses the `letterBlock` variant (slides up from `y: 120`) - Letter N (translate 0,0): Three polygons -- left vertical `0,0 14,0 14,100 0,100`, right vertical `200,0 214,0 214,100 200,100`, diagonal `0,0 33,0 214,100 181,100` - Letter H (translate 280,0): Three polygons -- left vertical `0,0 14,0 14,100 0,100`, right vertical `200,0 214,0 214,100 200,100`, crossbar `14,43 200,43 200,57 14,57` - Letter M (translate 560,0): Four polygons -- left vertical `0,0 14,0 14,100 0,100`, right vertical `266,0 280,0 280,100 266,100`, left diagonal `0,0 26,0 153,100 127,100`, right diagonal `254,0 280,0 153,100 127,100` 1B. SUB-NAV BAR - Below the SVG logo, `flex justify-between items-start mt-8` - Font: `text-[10px] md:text-[11px] font-mono tracking-[0.2em] uppercase` - Uses `fadeUp` variant with `duration: 0.8, ease: "easeOut"` Left column (15% width): Three lines -- "Natura" / "History" / "Museum" Arrow separator (5% width, hidden on mobile): `ArrowRight` from lucide, size 14, strokeWidth 1, `text-gray-400` Center column (flex-1 on mobile, 30% on desktop): "Exploring the story of life on earth through science, discovery and wonder." -- Split differently on desktop (3 lines) vs mobile (4 lines). `text-gray-800 leading-relaxed font-mono` Arrow separator (5% width, hidden on mobile): Same as above Right column (15% width, hidden on mobile): Nav links list -- Visit, Exhibitions, Discover, Learn, About. `text-gray-800`, `hover:text-black hover:underline` Hamburger button (far right, z-60): Two horizontal lines (`w-8 h-[1.5px] bg-black`), `gap-[6px]`. Hover: first line shrinks to `w-6`, second expands to `w-10`. When open: first rotates 45deg + translateY, second rotates -45deg + translateY (forming an X). Transition: `duration-300`. 1C. MOBILE MENU OVERLAY - `AnimatePresence` wrapping a `motion.div` - Appears below the header, slides in from `y: -20`, `opacity: 0` to `y: 0, opacity: 1` - `bg-[#fcfcfc] border-b border-gray-200 shadow-xl`, only visible on `md:hidden` - Contains the same nav links as the desktop version, `text-sm font-mono tracking-[0.2em] uppercase`, `space-y-6` 1D. BACKGROUND VIDEO - Appears after 2800ms delay (controlled by `showVideo` state) - `absolute top-0 left-0 w-full h-full pointer-events-none z-0` - Video: `autoPlay loop muted playsInline`, `w-full h-full object-cover` - Video URL: `https://res.cloudinary.com/dsdxaxkiz/video/upload/v1779624998/magnific_use-img-2-as-the-exact-ba_Piu3X0W42C_wnrc8f.mp4` 1E. LEFT SIDEBAR CONTENT - `motion.div` with `staggerChildren: 0.15, delayChildren: 0.6` - Position: `px-10 md:px-16`, `mt-20 sm:mt-28 md:mt-32`, `w-[320px]`, `z-10` Section indicator: `01` + horizontal line (`w-16 h-[1.5px] bg-black/20`), `text-xs font-mono` Headline: "TIMELESS WONDERS" -- `text-[3.5rem] md:text-[5rem] font-normal tracking-tight leading-[1]`. Line break between "TIMELESS" and "WONDERS". Description: "Step into the natural world and / discover the stories written / millions of years ago." -- `text-[13px] md:text-[14px] text-gray-700 w-[240px] leading-[1.6]` CTA Button ("Explore Now"): - Container: `bg-[#1a1a1a] px-6 py-3.5 border border-[#1a1a1a] rounded-md shadow-sm` - Hover: slides up 0.5px, adds `shadow-[3px_3px_0px_rgba(17,17,17,0.5)]` - Active: resets translate and shadow - Has a sliding background panel: `bg-[#fcfcfc]` that slides from `-translate-x-[101%]` to `translate-x-0` on hover, `duration-700 ease-[cubic-bezier(0.16,1,0.3,1)]` - Icon: Custom SVG leaf/plant shape (4 paths forming a stylized leaf), white by default, turns `#111` on hover with `scale-110 -rotate-12 -translate-y-1` transform - Text: "Explore Now", `text-[15px] font-medium`, white turning to `#111` on hover 1F. RIGHT SIDEBAR (hidden on mobile) - `motion.div` with `staggerChildren: 0.15, delayChildren: 0.9` - Position: `w-[200px] mt-12 md:mt-20`, `hidden md:flex` Specimen info: "Tyrannosaurus Rex" heading (`text-[10px] font-bold font-mono tracking-widest uppercase`), subtext "Late Cretaceous period / 68-66 million years ago" (`text-[12px] text-gray-600 leading-[1.6]`) Stats: "Length" label + "12.3 m" value, "Height" label + "4.0 m" value. Labels: `text-[10px] font-mono tracking-widest uppercase text-gray-500`. Values: `text-[13px] font-medium`. View Details button: Circle (`w-10 h-10 rounded-full border border-gray-400`) with `Plus` icon (size 16, strokeWidth 1.5), text "View Details" (`text-[10px] font-mono uppercase tracking-widest font-bold`). Hover: circle gets `border-black bg-[#111]`, icon turns white. 1G. BOTTOM-LEFT "SCROLL TO EXPLORE" - `absolute bottom-10 left-[2.5rem] md:left-[4rem]`, `hidden md:flex` - Fade up animation: `delay: 1.2` - Circle (`w-12 h-12 rounded-full border border-gray-300`) containing two thin vertical lines (`w-[1px] h-[12px] bg-gray-600`, `gap-[4px]`) representing a pause icon - Text: "Scroll to explore" -- `text-[10px] font-mono tracking-widest uppercase text-gray-500 font-semibold` --- SECTION 2: "EXPLORE OUR WORLD" Container: `relative w-full min-h-[75vh] md:min-h-screen bg-[#fcfcfc]`, flex column centered, `pt-24 md:pt-32 pb-0 z-20` 2A. SECTION LABEL `[ 02 ] Explore Our World` -- `text-[10px] md:text-[11px] font-mono tracking-[0.2em]`, `mb-12`. "02" in `text-gray-500`, "Explore Our World" in `text-gray-900 font-bold uppercase`. 2B. MAIN HEADING "Unearth the stories of our planet's past through fossils, minerals, and ancient wonders." -- `text-[2.2rem] md:text-[3.5rem] lg:text-[4.2rem] leading-[1.1] font-medium tracking-tight text-[#111]`, max-width 1000px, text-center. Line break on desktop after "past". Animates with `whileInView` from `y: 40, opacity: 0` to `y: 0, opacity: 1`, `once: true`, margin `-100px`. 2C. ACTION PILLS Five pill buttons in a flex-wrap row, `gap-3 md:gap-4`, `mb-10 md:mb-24`. Staggered reveal animation (`staggerChildren: 0.1, delayChildren: 0.3`). Each pill: `rounded-full border border-gray-300 text-[11px] font-medium uppercase tracking-wider bg-white/50 backdrop-blur-sm text-gray-800`. Hover: `border-black bg-black text-white`. Icons from lucide (size 14, strokeWidth 2): 1. `Bone` + "Dinosaurs" 2. `Dna` + "Ancient Life" 3. `Gem` + "Minerals" 4. `Leaf` + "Fossils" 5. `BookOpen` + "Learn More" 2D. SPACER `min-h-[220px] md:min-h-[450px]` -- provides room for the pterodactyl image from Section 3 to overlap upward. 2E. BOTTOM TEXT Absolute positioned at bottom, `px-8 md:px-16 pb-8 md:pb-12`, `pointer-events-none`. Two text elements at `justify-between`: - Left: "WE DON'T JUST TELL STORIES." - Right: "PALEONTOLOGY (C) 2026" - Both: `text-[10px] font-mono tracking-widest uppercase text-gray-500 font-medium`, hidden on mobile. --- SECTION 3: "ANCIENT COLLECTION" (Dark Section) Container: `relative w-full bg-[#0a0a0a] text-white flex flex-col z-30` 3A. PTERODACTYL IMAGE (Overlapping) - Absolute positioned at top, centered horizontally (`left-1/2 -translate-x-1/2`) - Width: `w-[160vw] md:w-[1100px]` - Image URL: `https://res.cloudinary.com/dsdxaxkiz/image/upload/v1779625001/ChatGPT_Image_May_23_2026_12_24_44_PM_1_lv1dne.png` - Animates with `whileInView` from `y: "-65%", opacity: 0` to `y: "-78%", opacity: 1`, `duration: 1.4, ease: "easeOut"`, viewport margin `100px` - `pointer-events-none z-0`, `mix-blend` not applied here 3B. HEADING AREA - Padding: `px-8 md:px-16 pt-32 md:pt-48 mb-16`, `z-10` - Two-column layout on xl (`flex-col xl:flex-row justify-between`) Left -- Main heading: "Curated from millions of years of wonder [3 circle icons] & discovery." -- `text-[1.8rem] md:text-[3rem] lg:text-[3.8rem] xl:text-[4rem] leading-[1.15] font-medium tracking-tight text-white`. The three circle icons are inline (`inline-flex gap-2 md:gap-3 align-middle mx-2 md:mx-4 translate-y-[-4px]`), each `w-10 h-10 md:w-14 md:h-14 rounded-full border border-gray-600 bg-black text-gray-400`. Hover: `bg-white text-black border-white`. Icons: `Bone`, `Dna`, `Leaf` (size 22). Right -- Tagline + pills: - Tagline: "WE DON'T JUST DISPLAY FOSSILS / WE SHARE EARTH'S STORY" -- `text-[9px] md:text-[10px] font-mono tracking-widest text-gray-400 uppercase mb-6 leading-relaxed` - Three pills: "Educational", "Authentic", "Inspiring" -- `px-5 py-2 rounded-full border border-gray-600 text-[9px] font-mono tracking-widest uppercase text-gray-300`. Hover: `bg-white text-black border-white`. 3C. TWO-COLUMN PANEL Separated by `h-[1px] bg-gray-800` line. Flex row on desktop, column on mobile. Left panel (35% width): - `border-r border-gray-800` on desktop, `border-b` on mobile - `min-h-[400px] md:min-h-[500px]` - Top: `***` text (`text-gray-500 text-xl tracking-[0.3em]`) - Center: Chapter image using `SandTransitionImage` component (SVG filter-based sand/dissolve transition). Image: `absolute inset-0 w-[80%] h-[80%] m-auto object-contain mix-blend-lighten`. Uses `AnimatePresence mode="wait"`. - Bottom: Chapter counter `01 / 05` style, with animated number (`motion.div` slides vertically). `text-[10px] font-mono tracking-widest text-[#888] uppercase`. Counter numeral color `#888`, divider `text-[#333]`. Right panel (65% width): - Top bar: "Explore the past. Understand the present." + animated "Chapter 0X" label. `border-b border-gray-800 p-8 text-[10px] font-mono text-gray-400 tracking-widest`. - Chapter list: 5 items, each `border-b border-gray-800/80 py-8`. Active: `text-white`, inactive: `text-[#444] hover:text-[#999]`. Chapter name: `text-2xl md:text-[2rem] font-medium tracking-tight`. Active item shows `ArrowUpRight` icon (size 22, strokeWidth 1, `text-gray-400`) that animates in/out. - Clicking a chapter sets `activeChapter`. 3D. BOTTOM FOOTER - `h-[1px] bg-gray-800` divider - Text: "DIGGING INTO OUR PLANET'S PAST" -- `px-8 py-8 text-[10px] font-mono tracking-widest text-gray-500 uppercase bg-[#0a0a0a]` --- SandTransitionImage COMPONENT A custom component that creates a sand/particle dissolve effect using SVG filters: ```tsx function SandTransitionImage({ src, alt, className }) { // Uses usePresence() from motion/react for AnimatePresence awareness // Unique filterId per instance via useRef // requestAnimationFrame loop over 900ms // Easing: entering = quartic ease-out (1 - Math.pow(1-t, 4)), exiting = cubic (Math.pow(t, 3)) // SVG filter chain: // 1. feTurbulence: fractalNoise, baseFrequency 1.8, numOctaves 4 // 2. feDisplacementMap: scale up to 150 based on progress // 3. feOffset: dy up to -80 (enter) or 120 (exit), dx up to -30/+30 // 4. feGaussianBlur: up to 6px // 5. feColorMatrix: opacity fades (1 - progress * 1.2) // Image has crossOrigin="anonymous" and referrerPolicy="no-referrer" } ``` --- ALL EXTERNAL ASSET URLs Video: - `https://res.cloudinary.com/dsdxaxkiz/video/upload/v1779624998/magnific_use-img-2-as-the-exact-ba_Piu3X0W42C_wnrc8f.mp4` Images: - Chapter 1: `https://res.cloudinary.com/dsdxaxkiz/image/upload/v1779624247/01_udnber.png` - Chapter 2: `https://res.cloudinary.com/dsdxaxkiz/image/upload/v1779624374/02_pmvxxl.png` - Chapter 3: `https://res.cloudinary.com/dsdxaxkiz/image/upload/v1779624236/03_hcp3jc.png` - Chapter 4: `https://res.cloudinary.com/dsdxaxkiz/image/upload/v1779624256/04_get63z.png` - Chapter 5: `https://res.cloudinary.com/dsdxaxkiz/image/upload/v1779624251/05_kz1tyu.png` - Pterodactyl: `https://res.cloudinary.com/dsdxaxkiz/image/upload/v1779625001/ChatGPT_Image_May_23_2026_12_24_44_PM_1_lv1dne.png` (Note: these are Cloudinary URLs, not CloudFront. The project uses Cloudinary for all hosted media assets.) --- KEY DESIGN DETAILS - Color palette: `#fcfcfc` (off-white bg), `#111` / `#1a1a1a` (near-black), `#0a0a0a` (dark section bg). Gray scale via Tailwind: `gray-300` through `gray-800`. - No purple/indigo anywhere. Strictly monochrome black/white/gray. - Typography hierarchy: Large display headings (3.5-5rem), mono labels (10-11px), body text (13-14px). - Spacing: 8px base system throughout. - Transitions: Most hover transitions 300-700ms. Button slide effect uses `cubic-bezier(0.16, 1, 0.3, 1)`. Letter animations use same cubic bezier. - The page is entirely a single `App.tsx` component plus the `SandTransitionImage` helper function in the same file.
AI Workflow Hero
AI Workflow Hero
### Stack - **Vite** + **React 18** + **TypeScript** - **Tailwind CSS 3.4** - **lucide-react** for icons (`LogIn`, `UserPlus`, `Play`, `Sparkles`, `Menu`, `X`) - No Framer Motion -- all animations are CSS `transition-*` classes --- ### Fonts (loaded in `index.html`) ```html <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet" /> <link href="https://db.onlinewebfonts.com/c/6e47ef470dd19698c911332a9b4d1cf4?family=Neue+Haas+Grotesk+Text+Pro" rel="stylesheet" /> <link href="https://db.onlinewebfonts.com/c/dec0d9b4e22ca588dc20e1e2e09a59b5?family=Neue+Haas+Grotesk+Display+Pro+55+Roman" rel="stylesheet" /> ``` Body/root font stack (in `index.css`): ```css html, body, #root { height: 100%; margin: 0; font-family: 'Neue Haas Grotesk Display Pro 55 Roman', 'Neue Haas Grotesk Text Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; } ``` --- ### Video URL (CloudFront) ``` https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260511_131941_d136af49-e243-493a-be14-6ff3f24e09e6.mp4 ``` --- ### Color Palette | Token | Hex | |-------|-----| | Dark green (text, buttons) | `#1f2a1d` | | Medium dark green | `#2d3a2a` | | Button hover | `#2a3827` | | Body text green | `#4b5b47` | | Heading primary | `#336443` | | Heading accent | `#85AB8B` | | Bottom-left text | `#3d5638` | | Bottom-left button bg | `#3d5638`, hover `#2d4228` | --- ### Architecture Two files: 1. **`BoomerangVideoBg.tsx`** -- captures video frames into canvas, then plays them forward/backward in a seamless boomerang loop at 30fps (960px max capture width). 2. **`App.tsx`** -- the full hero section. --- ### `BoomerangVideoBg.tsx` (exact) ```tsx import { useEffect, useRef, useState } from 'react'; type Props = { src: string; className?: string; }; export default function BoomerangVideoBg({ src, className }: Props) { const videoRef = useRef<HTMLVideoElement>(null); const displayCanvasRef = useRef<HTMLCanvasElement>(null); const [framesReady, setFramesReady] = useState(false); const framesRef = useRef<HTMLCanvasElement[]>([]); useEffect(() => { const video = videoRef.current; if (!video) return; const frames: HTMLCanvasElement[] = []; let capturing = true; let lastTime = -1; const MAX_WIDTH = 960; const captureFrame = () => { if (!capturing || video.readyState < 2) return; if (video.currentTime === lastTime) return; lastTime = video.currentTime; const vw = video.videoWidth; const vh = video.videoHeight; if (!vw || !vh) return; const scale = Math.min(1, MAX_WIDTH / vw); const w = Math.round(vw * scale); const h = Math.round(vh * scale); const canvas = document.createElement('canvas'); canvas.width = w; canvas.height = h; const ctx = canvas.getContext('2d'); if (!ctx) return; ctx.drawImage(video, 0, 0, w, h); frames.push(canvas); }; type VFCVideo = HTMLVideoElement & { requestVideoFrameCallback?: (cb: () => void) => number; }; const vfcVideo = video as VFCVideo; const hasVFC = typeof vfcVideo.requestVideoFrameCallback === 'function'; let rafId = 0; const rafLoop = () => { captureFrame(); if (capturing) rafId = requestAnimationFrame(rafLoop); }; const vfcLoop = () => { captureFrame(); if (capturing && vfcVideo.requestVideoFrameCallback) { vfcVideo.requestVideoFrameCallback(vfcLoop); } }; const onEnded = () => { capturing = false; if (frames.length > 0) { framesRef.current = frames; setFramesReady(true); } }; const onLoaded = () => { video.play().catch(() => {}); if (hasVFC) { vfcVideo.requestVideoFrameCallback!(vfcLoop); } else { rafId = requestAnimationFrame(rafLoop); } }; video.addEventListener('loadedmetadata', onLoaded); video.addEventListener('ended', onEnded); if (video.readyState >= 1) onLoaded(); return () => { capturing = false; cancelAnimationFrame(rafId); video.removeEventListener('loadedmetadata', onLoaded); video.removeEventListener('ended', onEnded); }; }, [src]); useEffect(() => { if (!framesReady) return; const canvas = displayCanvasRef.current; if (!canvas) return; const ctx = canvas.getContext('2d'); if (!ctx) return; const frames = framesRef.current; if (frames.length === 0) return; const first = frames[0]; canvas.width = first.width; canvas.height = first.height; let index = 0; let direction = 1; let last = performance.now(); const interval = 1000 / 30; let rafId = 0; const render = (now: number) => { if (now - last >= interval) { last = now; ctx.drawImage(frames[index], 0, 0); index += direction; if (index >= frames.length - 1) { index = frames.length - 1; direction = -1; } else if (index <= 0) { index = 0; direction = 1; } } rafId = requestAnimationFrame(render); }; rafId = requestAnimationFrame(render); return () => cancelAnimationFrame(rafId); }, [framesReady]); return ( <div className={className ?? 'absolute inset-0 w-full h-full'}> <video ref={videoRef} src={src} className="w-full h-full object-cover" style={{ display: framesReady ? 'none' : 'block' }} muted playsInline preload="auto" crossOrigin="anonymous" /> <canvas ref={displayCanvasRef} className="w-full h-full object-cover" style={{ display: framesReady ? 'block' : 'none' }} /> </div> ); } ``` --- ### `App.tsx` (exact) ```tsx import { useState, useEffect } from 'react'; import { LogIn, UserPlus, Play, Sparkles, Menu, X } from 'lucide-react'; import BoomerangVideoBg from './BoomerangVideoBg'; const BG_VIDEO = 'https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260511_131941_d136af49-e243-493a-be14-6ff3f24e09e6.mp4'; function App() { const [menuOpen, setMenuOpen] = useState(false); useEffect(() => { if (menuOpen) { document.body.style.overflow = 'hidden'; } else { document.body.style.overflow = ''; } return () => { document.body.style.overflow = ''; }; }, [menuOpen]); const navLinks = [ { href: '#mission', label: 'Purpose' }, { href: '#how', label: 'The Process' }, { href: '#pricing', label: 'Tariffs' }, ]; return ( <section className="relative w-full min-h-screen sm:h-screen overflow-hidden"> <BoomerangVideoBg src={BG_VIDEO} className="absolute inset-0 w-full h-full" /> <nav className="absolute top-0 left-0 right-0 z-30 flex items-center justify-between px-4 sm:px-6 md:px-10 py-4 sm:py-6"> <div className="flex items-center gap-2 text-[#2d3a2a]"> <span className="text-lg sm:text-xl md:text-2xl font-semibold tracking-tight"> LinkFlow<sup className="text-[10px] sm:text-xs font-medium">TM</sup> </span> </div> <div className="hidden lg:flex items-center gap-1 bg-white/70 backdrop-blur-md rounded-full pl-6 pr-1 py-1 shadow-sm border border-white/60"> {navLinks.map((link, i) => ( <a key={link.href} href={link.href} className={`text-sm px-3 py-2 transition-colors ${ i === 0 ? 'font-semibold text-[#1f2a1d]' : 'font-medium text-[#4b5b47] hover:text-[#1f2a1d]' }`} > {link.label} </a> ))} <button className="ml-2 bg-[#1f2a1d] hover:bg-[#2a3827] text-white text-sm font-medium px-5 py-2.5 rounded-full transition-colors"> Try it Live </button> </div> <div className="flex items-center gap-3 sm:gap-6 text-[#2d3a2a]"> <a href="#signup" className="hidden sm:flex items-center gap-2 text-sm font-medium hover:opacity-80 transition-opacity"> <UserPlus className="w-4 h-4" /> Sign Me Up! </a> <a href="#login" className="hidden sm:flex items-center gap-2 text-sm font-medium hover:opacity-80 transition-opacity"> <LogIn className="w-4 h-4" /> Enter </a> <button onClick={() => setMenuOpen((v) => !v)} className="lg:hidden relative flex items-center justify-center w-10 h-10 rounded-full bg-white/70 backdrop-blur-md border border-white/60 text-[#1f2a1d] transition-all duration-300 hover:bg-white/90" aria-label={menuOpen ? 'Close menu' : 'Open menu'} aria-expanded={menuOpen} > <Menu className={`w-5 h-5 absolute transition-all duration-300 ${ menuOpen ? 'opacity-0 rotate-90 scale-50' : 'opacity-100 rotate-0 scale-100' }`} /> <X className={`w-5 h-5 absolute transition-all duration-300 ${ menuOpen ? 'opacity-100 rotate-0 scale-100' : 'opacity-0 -rotate-90 scale-50' }`} /> </button> </div> </nav> {/* Mobile menu overlay */} <div className={`lg:hidden fixed inset-0 z-20 transition-opacity duration-300 ${ menuOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none' }`} onClick={() => setMenuOpen(false)} > <div className="absolute inset-0 bg-[#1f2a1d]/40 backdrop-blur-sm" /> </div> {/* Mobile menu drawer */} <div className={`lg:hidden fixed top-0 right-0 bottom-0 z-20 w-[85%] max-w-sm bg-white/95 backdrop-blur-xl shadow-2xl transition-transform duration-500 ease-[cubic-bezier(0.22,1,0.36,1)] ${ menuOpen ? 'translate-x-0' : 'translate-x-full' }`} > <div className="flex flex-col h-full pt-24 px-8 pb-8"> <div className="flex flex-col gap-1"> {navLinks.map((link, i) => ( <a key={link.href} href={link.href} onClick={() => setMenuOpen(false)} className={`text-2xl font-semibold text-[#1f2a1d] py-4 border-b border-[#1f2a1d]/10 transition-all duration-500 ${ menuOpen ? 'translate-x-0 opacity-100' : 'translate-x-8 opacity-0' }`} style={{ transitionDelay: menuOpen ? `${150 + i * 70}ms` : '0ms' }} > {link.label} </a> ))} </div> <div className={`mt-8 flex flex-col gap-4 transition-all duration-500 ${ menuOpen ? 'translate-x-0 opacity-100' : 'translate-x-8 opacity-0' }`} style={{ transitionDelay: menuOpen ? '400ms' : '0ms' }} > <a href="#signup" className="flex items-center gap-2 text-sm font-medium text-[#2d3a2a] sm:hidden"> <UserPlus className="w-4 h-4" /> Sign Me Up! </a> <a href="#login" className="flex items-center gap-2 text-sm font-medium text-[#2d3a2a] sm:hidden"> <LogIn className="w-4 h-4" /> Enter </a> <button className="mt-2 bg-[#1f2a1d] hover:bg-[#2a3827] text-white text-sm font-semibold px-5 py-3 rounded-full transition-colors"> Try it Live </button> </div> </div> </div> {/* Hero copy */} <div className="relative z-10 flex flex-col items-center text-center pt-24 sm:pt-28 md:pt-32 px-4 sm:px-6"> <h1 className="font-normal leading-[0.95] text-[#336443] text-[2rem] sm:text-4xl md:text-5xl lg:text-[4.75rem] xl:text-[5.25rem] max-w-5xl" style={{ fontFamily: '"Neue Haas Grotesk Display Pro 55 Roman", "Neue Haas Grotesk Text Pro", "Helvetica Neue", Helvetica, Arial, sans-serif', letterSpacing: '-0.035em' }} > Close the rift{' '} <span className="text-[#85AB8B]"> linking <br className="hidden sm:block" /> signals and action </span> </h1> <p className="mt-6 sm:mt-8 text-[#4b5b47] text-sm sm:text-base md:text-lg leading-relaxed max-w-md px-2"> Shape scattered signals into meaningful outcomes via AI-driven workflows. </p> </div> {/* Bottom-left CTA block */} <div className="absolute left-4 right-4 sm:right-auto sm:left-6 md:left-10 bottom-6 sm:bottom-8 md:bottom-10 z-10 max-w-sm"> <div className="flex items-center gap-2 text-[#3d5638] sm:text-white/95 mb-3"> <Sparkles className="w-4 h-4" /> <span className="text-sm font-semibold sm:font-medium"> FluxEngine<sup className="text-[10px]">TM</sup> </span> </div> <p className="text-[#3d5638]/90 sm:text-white/85 text-xs leading-relaxed mb-6 max-w-xs font-medium sm:font-normal"> LinkFlow smoothly unites your company systems, streamlining data paths between services without having to write custom scripts. </p> <div className="flex items-center gap-4 flex-wrap"> <button className="bg-[#3d5638] sm:bg-white hover:bg-[#2d4228] sm:hover:bg-white/90 text-white sm:text-[#1f2a1d] text-sm font-semibold px-5 sm:px-6 py-2.5 sm:py-3 rounded-full transition-colors shadow-sm"> Try it Live </button> <button className="text-[#3d5638] sm:text-white text-sm font-semibold sm:font-medium hover:opacity-80 transition-opacity"> Know More. </button> </div> </div> {/* Bottom-right video link */} <div className="hidden sm:flex absolute right-6 md:right-10 bottom-8 md:bottom-10 z-10 items-center gap-2 text-white/90 text-sm"> <button className="flex items-center justify-center w-6 h-6 rounded-full bg-white/20 backdrop-blur-sm hover:bg-white/30 transition-colors"> <Play className="w-3 h-3 fill-white text-white ml-0.5" /> </button> <span className="font-medium">How we build?</span> <span className="text-white/60">1:35</span> </div> </section> ); } export default App; ``` --- ### Animation Details (all CSS, no Framer Motion) | Element | Property | Values | |---------|----------|--------| | Hamburger Menu/X icon swap | `transition-all duration-300` | Open: Menu gets `opacity-0 rotate-90 scale-50`, X gets `opacity-100 rotate-0 scale-100`. Closed: reverse. | | Mobile overlay backdrop | `transition-opacity duration-300` | Open: `opacity-100 pointer-events-auto`. Closed: `opacity-0 pointer-events-none`. | | Mobile drawer slide | `transition-transform duration-500 ease-[cubic-bezier(0.22,1,0.36,1)]` | Open: `translate-x-0`. Closed: `translate-x-full`. | | Mobile nav links stagger | `transition-all duration-500` | Open: `translate-x-0 opacity-100`, delay per item: `150ms + i * 70ms`. Closed: `translate-x-8 opacity-0`, delay `0ms`. | | Mobile CTA group | `transition-all duration-500` | Open: `translate-x-0 opacity-100`, delay `400ms`. Closed: `translate-x-8 opacity-0`, delay `0ms`. | | Nav buttons | `transition-colors` | Default Tailwind duration (150ms). | | Opacity links | `transition-opacity` | `hover:opacity-80`. | --- ### Key Layout/Spacing Notes - Root section: `relative w-full min-h-screen sm:h-screen overflow-hidden` - Navbar padding: `px-4 sm:px-6 md:px-10 py-4 sm:py-6` - Desktop pill nav: `bg-white/70 backdrop-blur-md rounded-full pl-6 pr-1 py-1 shadow-sm border border-white/60` - Hero heading: `pt-24 sm:pt-28 md:pt-32`, font sizes `text-[2rem] sm:text-4xl md:text-5xl lg:text-[4.75rem] xl:text-[5.25rem]`, `leading-[0.95]`, `letterSpacing: '-0.035em'` - Bottom-left block: `absolute left-4 right-4 sm:right-auto sm:left-6 md:left-10 bottom-6 sm:bottom-8 md:bottom-10` - Bottom-right video: `absolute right-6 md:right-10 bottom-8 md:bottom-10` --- ### Dependencies (package.json) ```json { "dependencies": { "lucide-react": "^0.344.0", "react": "^18.3.1", "react-dom": "^18.3.1" }, "devDependencies": { "@vitejs/plugin-react": "^4.3.1", "autoprefixer": "^10.4.18", "postcss": "^8.4.35", "tailwindcss": "^3.4.1", "typescript": "^5.5.3", "vite": "^5.4.2" } } ```
Blog Showcase
Blog Showcase
Build a "Behind the Lens" photography blog section with the following exact specifications: **Layout and Structure:** - White background page, max-width 1200px, centered, 60px vertical padding, 20px horizontal padding - Header with: a small grey "Blog" badge (bg #f4f4f4, 8px border-radius), a large heading "Behind the lens" (64px, Outfit font, weight 500, letter-spacing -2.5px), a subtitle paragraph and a "View all posts" button side by side - Subtitle: "Thoughts, insights, and stories from my photography journey. Take a peek into my creative process and recent projects." (max-width 480px, #666 color, 18px, weight 500, opacity 0.8) - "View all posts" button: black bg, white text, 40px border-radius pill shape, 14px font, weight 600, scales 1.02 on hover **Featured Post (full-width card):** - 2-column grid (1fr 1fr), 20px border-radius, 1px solid #f0f0f0 border, min-height 520px, bg #fcfcfc - Left side: autoplaying looped muted video, object-fit cover, fills the entire area - Right side: 60px padding, contains a black "Must Read" pill badge (12px font, 20px border-radius), title in Outfit font 48px weight 500 (letter-spacing -1.5px), description in #666 at 17px, and a footer with author name and colored category badge pushed to the bottom via margin-top auto - Featured post data: title "Full-Frame vs. Crop Sensor: Which for Photography?", description "An honest look at the real-world differences between these camera systems to help you choose what's actually right for your photography needs.", author "By August Renner (c)", category "Gear" with color #7d1a4a - Featured video URL: `https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260507_155500_808e6fdd-761f-4acd-b3be-cb7e6e700def.mp4` **Blog Grid (3 standard cards):** - 3-column grid, 25px gap, below the featured post - Each card: video with 16/10 aspect ratio, 20px border-radius, title below (Outfit 17px weight 600) with a colored category badge aligned right - Card 1: "Finding Natural Light in Unexpected Places", category "Lighting" (#2c4c34), video: `https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260506_030111_a9e15665-d379-4a7f-8116-695bbe452ad1.mp4` - Card 2: "My Approach to Editing: Creating a Consistent Photography Style", category "Editing" (#a63e2d), video: `https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260508_064122_c4750c0e-7476-4b44-94a2-a85a65c63bf2.mp4` - Card 3: "Pricing Your Photography: Strategies That Work", category "Business" (#1a2b8c), video: `https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260507_154232_f8809bd2-a6c3-4a38-908d-2005e5b3cb3e.mp4` **Hover Interactions (on all video containers):** - Videos scale to 1.08 on hover with cubic-bezier(0.33, 1, 0.68, 1) over 0.5s - A dark overlay (rgba(0,0,0,0.25)) fades in over 0.4s on hover - A centered "+" icon inside a 70px circle (rgba(255,255,255,0.2) bg) scales from 0.7 to 1.0 on hover over 0.3s - White "L-shaped" corner brackets (12px, 1.5px border) in all 4 corners of each video, 15px inset from edges **Category Badges:** - Pill shape (20px border-radius), white text, 11px font, weight 600, 4px 12px padding, capitalized, background color matches each post's assigned color **Fonts:** - Google Fonts: Inter (400, 500, 600) for body text, Outfit (500, 600, 700) for headings and titles **Responsive:** - At 1024px: featured post becomes single column, grid becomes 2 columns, featured content padding 40px - At 768px: heading drops to 48px, header-bottom stacks vertically, grid becomes 1 column, featured title drops to 32px **Data Source:** - Store all blog post data (type, badge, title, description, author, category, category_color, image/video URL, display_order) in a Supabase `blog_posts` table - Fetch and render dynamically, ordered by display_order ascending - Enable RLS with public read access for anon and authenticated users **Tech Stack:** - React + TypeScript + Vite + Tailwind CSS (for base resets only, use custom CSS for the blog styles) - Supabase JS client for data fetching - All videos use autoPlay, loop, muted, playsInline attributes
No-Code Waitlist
No-Code Waitlist
Build a full-screen dark hero section landing page in React + Vite + Tailwind CSS v4 + Motion (framer-motion) + Lucide React icons + hls.js. The page should be a single screen (100vh, no scroll) with a black background, a fullscreen background video, a glassmorphism navbar, and a centered hero with an email capture CTA. > > **Dependencies:** `react`, `react-dom`, `motion`, `hls.js`, `lucide-react`, `tailwindcss` v4 with `@tailwindcss/vite`, `@vitejs/plugin-react` > > **Fonts:** Import Google Fonts: > - `Inter` (weights 300, 400, 500, 600) -- used as the base sans-serif font > - `Instrument Serif` (regular and italic) -- used for the hero heading > > **CSS (`index.css`):** > - Import both Google Font URLs, then `@import "tailwindcss";` > - Set `@theme { --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif; }` > - `:root` variables: `--background: #000000; --foreground: #ffffff;` > - `body`: background-color var(--background), color var(--foreground), font-family var(--font-sans), `-webkit-font-smoothing: antialiased`, `letter-spacing: -0.01em` > - `.liquid-glass` class: `background: rgba(255,255,255,0.01)`, `background-blend-mode: luminosity`, `backdrop-filter: blur(4px)`, `-webkit-backdrop-filter: blur(4px)`, `border: none`, `box-shadow: inset 0 1px 1px rgba(255,255,255,0.1)`, `position: relative`, `overflow: hidden`. It has a `::before` pseudo-element for a gradient border effect: `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) 40%, rgba(255,255,255,0) 60%, rgba(255,255,255,0.15) 80%, rgba(255,255,255,0.45) 100%)`, masked with `-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)` and `-webkit-mask-composite: xor; mask-composite: exclude;` > - `.glass-pill` class: `background: rgba(255,255,255,0.04)`, `backdrop-filter: blur(16px) saturate(180%)`, `border-radius: 9999px`, `box-shadow: none !important` > > **Background Video component:** > - Renders an absolutely positioned `<div>` covering the full parent (`absolute inset-0 overflow-hidden pointer-events-none`) > - Contains a `<video>` element: `autoPlay`, `muted`, `loop`, `playsInline`, classes `w-full h-full object-cover opacity-100` > - Video source URL: `https://stream.mux.com/kimF2ha9zLrX64H00UgLGPflCzNtl1T0215MlAmeOztv8.m3u8` (this is an HLS stream from Mux, NOT CloudFront) > - Uses `hls.js`: if the browser natively supports HLS (`video.canPlayType("application/vnd.apple.mpegurl")`), set `video.src` directly; otherwise instantiate `new Hls()`, `loadSource`, `attachMedia` > > **Navbar component:** > - Animates in with `motion.nav`: `initial={{ y: -20, opacity: 0 }}`, `animate={{ y: 0, opacity: 1 }}` > - Classes: `relative z-20 px-6 py-6 w-full` > - Inner container: `liquid-glass rounded-full px-6 py-3 flex items-center justify-between max-w-5xl mx-auto` > - Left side (`flex items-center gap-8`): > - Logo: `Globe` icon from lucide-react (w-6 h-6 text-white) + "Asme" text (`text-white font-semibold text-lg`), in a `flex items-center gap-2` wrapper > - Nav links: "Features", "Pricing", "About" -- hidden on mobile (`hidden md:flex`), `items-center gap-8 text-white/80 text-sm font-medium`, each link has `hover:text-white transition-colors duration-300` > - Right side (`flex items-center gap-4`): > - "Sign Up" plain text button: `text-white hover:text-white/80 transition-colors text-sm font-medium cursor-pointer` > - "Login" glassmorphism button: `liquid-glass rounded-full px-6 py-2 text-sm font-medium text-white hover:opacity-90 transition-opacity cursor-pointer` > > **Hero component:** > - `<section>` with `relative flex-1 flex flex-col items-center justify-center px-6` > - Content wrapper: `relative z-10 text-center max-w-5xl mx-auto flex flex-col items-center justify-center w-full gap-12` > - **Tagline** (motion.p): text "BUILD A NO-CODE AI APP IN MINUTES", `text-white/80 text-[10px] md:text-[11px] font-medium tracking-[0.2em] uppercase mb-4`, animates `initial={{ opacity: 0, y: 10 }}`, `animate={{ opacity: 1, y: 0 }}`, `transition={{ delay: 0.1 }}` > - **Heading** (motion.h1): text "A new way to think and create with computers" (with `<br className="hidden md:block" />` after "create"), `fontFamily: "'Instrument Serif', serif"` set via inline style, classes `text-4xl md:text-[64px] font-medium tracking-[-0.01em] leading-[1.1] mb-6 bg-gradient-to-b from-white via-white/95 to-white/70 bg-clip-text text-transparent max-w-4xl`, animates `initial={{ opacity: 0, y: 20 }}`, `animate={{ opacity: 1, y: 0 }}`, `transition={{ duration: 1, ease: [0.16, 1, 0.3, 1] }}` > - **CTA area** (motion.div): `min-h-[50px] mt-2`, animates with `delay: 0.4`. Uses `AnimatePresence mode="wait"` to toggle between: > - **Button state**: "Get early access" -- `px-10 py-3 text-[14px] font-medium border border-white/10 rounded-full hover:border-white/30 hover:bg-white/[0.02] transition-all duration-300 text-white/90 backdrop-blur-sm cursor-pointer`. On click, switches to email form. > - **Email form state**: a `<form>` with `flex items-center gap-2 pl-5 pr-1.5 py-1.5 text-[14px] font-medium border border-white/20 rounded-full bg-white/[0.02] backdrop-blur-sm w-full max-w-[320px] focus-within:border-white/40 transition-colors duration-300`. Contains an email `<input>` (transparent background, white text, `placeholder-white/45`, `autoFocus`) and a submit button with either `ArrowRight` icon (default) or `Check` icon (after submit). Both states animate scale 0.95 to 1 with 0.2s duration. > - **Typewriter placeholder**: when the email form opens, the placeholder text "Enter Your Email Here For Early Access" types in character by character at 60ms intervals. After submission, it types "You Will Receive Notifications By Email" instead. After 4 seconds, it resets back to the button state. > - **"Play Video Demo"** link below (motion.div with `delay: 0.8` fade-in): `text-white/80 hover:text-white/40 transition-colors duration-300 text-[13px] font-medium tracking-wide` > > **App root layout:** > - `<main>` with `relative bg-black h-screen w-screen flex flex-col overflow-hidden selection:bg-white selection:text-black shrink-0` > - Render order: `BackgroundVideo`, `Navbar`, `Hero` > - Text selection is styled white bg with black text --- Key clarification: The video URL is **not** from CloudFront. It is an HLS stream hosted on **Mux**: `https://stream.mux.com/kimF2ha9zLrX64H00UgLGPflCzNtl1T0215MlAmeOztv8.m3u8`. The `.m3u8` format requires hls.js for non-Safari browsers.
