Notliable666's picture
I would like a clone app of Neutralframes.com
4b38d82 verified
Raw
History Blame Contribute Delete
41 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Neutralframes — Minimal Framing for Modern Spaces</title>
<script src="https://cdn.tailwindcss.com"></script>
<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&family=Playfair+Display:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
neutral: {
50: '#FAFAF8',
100: '#F5F5F0',
200: '#E8E8E0',
300: '#D4D4C8',
400: '#A8A898',
500: '#787868',
600: '#585848',
700: '#404038',
800: '#282820',
900: '#181810',
},
cream: '#F5F0EB',
warm: '#E8DFD0',
sand: '#C4B89A',
charcoal: '#2C2C28',
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
display: ['Playfair Display', 'serif'],
}
}
}
}
</script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
body { font-family: 'Inter', sans-serif; background: #FAFAF8; color: #2C2C28; }
/* Custom scrollbar */
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: #F5F5F0; }
::-webkit-scrollbar-thumb { background: #A8A898; border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: #787868; }
/* Animations */
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(30px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slideInLeft {
from { opacity: 0; transform: translateX(-40px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes slideInRight {
from { opacity: 0; transform: translateX(40px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes scaleIn {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
@keyframes float {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-8px); }
}
.animate-fade-in-up { animation: fadeInUp 0.8s ease-out forwards; }
.animate-fade-in { animation: fadeIn 0.6s ease-out forwards; }
.animate-slide-left { animation: slideInLeft 0.8s ease-out forwards; }
.animate-slide-right { animation: slideInRight 0.8s ease-out forwards; }
.animate-scale-in { animation: scaleIn 0.6s ease-out forwards; }
.animate-float { animation: float 4s ease-in-out infinite; }
.delay-100 { animation-delay: 0.1s; }
.delay-200 { animation-delay: 0.2s; }
.delay-300 { animation-delay: 0.3s; }
.delay-400 { animation-delay: 0.4s; }
.delay-500 { animation-delay: 0.5s; }
.delay-600 { animation-delay: 0.6s; }
/* Scroll reveal */
.reveal { opacity: 0; transform: translateY(30px); transition: all 0.8s cubic-bezier(0.16, 1, 0.3, 1); }
.reveal.visible { opacity: 1; transform: translateY(0); }
/* Frame hover effect */
.frame-card { position: relative; overflow: hidden; }
.frame-card::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(to top, rgba(44,44,40,0.4), transparent 50%);
opacity: 0;
transition: opacity 0.4s ease;
}
.frame-card:hover::after { opacity: 1; }
.frame-card .overlay-content {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 1.5rem;
z-index: 2;
transform: translateY(10px);
opacity: 0;
transition: all 0.4s ease;
}
.frame-card:hover .overlay-content { transform: translateY(0); opacity: 1; }
/* Nav blur */
.nav-blur { backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); }
/* Marquee */
@keyframes marquee {
0% { transform: translateX(0); }
100% { transform: translateX(-50%); }
}
.marquee-track { animation: marquee 30s linear infinite; }
.marquee-track:hover { animation-play-state: paused; }
/* Mobile menu */
.mobile-menu { transform: translateX(100%); transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1); }
.mobile-menu.open { transform: translateX(0); }
/* Product grid hover */
.product-item img { transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1); }
.product-item:hover img { transform: scale(1.05); }
/* Selection color */
::selection { background: #C4B89A; color: #2C2C28; }
/* Cursor dot */
.cursor-dot {
width: 8px; height: 8px;
background: #2C2C28;
border-radius: 50%;
position: fixed;
pointer-events: none;
z-index: 9999;
transition: transform 0.15s ease;
mix-blend-mode: difference;
background: white;
}
/* Tabs */
.tab-btn.active { color: #2C2C28; border-color: #2C2C28; }
.tab-btn { color: #A8A898; border-color: transparent; }
/* Toast */
.toast {
transform: translateY(100px);
opacity: 0;
transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.toast.show {
transform: translateY(0);
opacity: 1;
}
</style>
</head>
<body class="overflow-x-hidden">
<!-- Navigation -->
<nav id="navbar" class="fixed top-0 left-0 right-0 z-50 nav-blur bg-neutral-50/80 transition-all duration-300">
<div class="max-w-7xl mx-auto px-6 lg:px-8">
<div class="flex items-center justify-between h-16 lg:h-20">
<!-- Logo -->
<a href="#" class="flex items-center gap-2 group">
<div class="w-8 h-8 border-2 border-charcoal flex items-center justify-center group-hover:bg-charcoal transition-all duration-300">
<div class="w-3 h-3 border border-charcoal group-hover:border-white transition-all duration-300"></div>
</div>
<span class="font-display text-xl font-semibold tracking-tight">neutralframes</span>
</a>
<!-- Desktop Menu -->
<div class="hidden md:flex items-center gap-8">
<a href="#collections" class="text-sm font-medium text-neutral-600 hover:text-charcoal transition-colors duration-200">Collections</a>
<a href="#frames" class="text-sm font-medium text-neutral-600 hover:text-charcoal transition-colors duration-200">Frames</a>
<a href="#about" class="text-sm font-medium text-neutral-600 hover:text-charcoal transition-colors duration-200">About</a>
<a href="#journal" class="text-sm font-medium text-neutral-600 hover:text-charcoal transition-colors duration-200">Journal</a>
</div>
<!-- Right actions -->
<div class="flex items-center gap-4">
<button class="hidden md:flex items-center gap-2 text-sm font-medium text-neutral-600 hover:text-charcoal transition-colors" id="searchBtn">
<i data-lucide="search" class="w-4 h-4"></i>
</button>
<button class="hidden md:flex items-center gap-2 text-sm font-medium text-neutral-600 hover:text-charcoal transition-colors relative" id="cartBtn">
<i data-lucide="shopping-bag" class="w-4 h-4"></i>
<span class="absolute -top-1.5 -right-1.5 w-4 h-4 bg-charcoal text-white text-[10px] flex items-center justify-center rounded-full" id="cartCount">0</span>
</button>
<button class="md:hidden" id="menuToggle">
<i data-lucide="menu" class="w-5 h-5"></i>
</button>
</div>
</div>
</div>
</nav>
<!-- Mobile Menu -->
<div class="mobile-menu fixed inset-0 z-50 bg-neutral-50" id="mobileMenu">
<div class="flex items-center justify-between px-6 h-16">
<a href="#" class="flex items-center gap-2">
<div class="w-8 h-8 border-2 border-charcoal flex items-center justify-center">
<div class="w-3 h-3 border border-charcoal"></div>
</div>
<span class="font-display text-xl font-semibold tracking-tight">neutralframes</span>
</a>
<button id="menuClose">
<i data-lucide="x" class="w-5 h-5"></i>
</button>
</div>
<div class="flex flex-col items-center justify-center h-[calc(100%-4rem)] gap-8">
<a href="#collections" class="font-display text-3xl font-medium text-charcoal mobile-link">Collections</a>
<a href="#frames" class="font-display text-3xl font-medium text-charcoal mobile-link">Frames</a>
<a href="#about" class="font-display text-3xl font-medium text-charcoal mobile-link">About</a>
<a href="#journal" class="font-display text-3xl font-medium text-charcoal mobile-link">Journal</a>
<button class="mt-4 px-8 py-3 bg-charcoal text-white text-sm font-medium rounded-none hover:bg-neutral-800 transition-colors">
Shop Now
</button>
</div>
</div>
<!-- Search Modal -->
<div id="searchModal" class="fixed inset-0 z-50 bg-neutral-50/95 nav-blur hidden items-center justify-center">
<div class="w-full max-w-2xl px-6">
<div class="flex items-center justify-between mb-8">
<span class="text-sm text-neutral-400 uppercase tracking-widest">Search</span>
<button id="searchClose"><i data-lucide="x" class="w-5 h-5"></i></button>
</div>
<input type="text" placeholder="What are you looking for?" class="w-full text-3xl md:text-5xl font-display bg-transparent border-b-2 border-charcoal pb-4 outline-none placeholder:text-neutral-300" id="searchInput">
<div class="mt-8">
<p class="text-sm text-neutral-400 uppercase tracking-widest mb-4">Popular Searches</p>
<div class="flex flex-wrap gap-3">
<span class="px-4 py-2 border border-neutral-200 text-sm text-neutral-600 cursor-pointer hover:bg-charcoal hover:text-white hover:border-charcoal transition-all">Oak Frames</span>
<span class="px-4 py-2 border border-neutral-200 text-sm text-neutral-600 cursor-pointer hover:bg-charcoal hover:text-white hover:border-charcoal transition-all">Minimal Poster</span>
<span class="px-4 py-2 border border-neutral-200 text-sm text-neutral-600 cursor-pointer hover:bg-charcoal hover:text-white hover:border-charcoal transition-all">Black Metal</span>
<span class="px-4 py-2 border border-neutral-200 text-sm text-neutral-600 cursor-pointer hover:bg-charcoal hover:text-white hover:border-charcoal transition-all">Gallery Wall</span>
<span class="px-4 py-2 border border-neutral-200 text-sm text-neutral-600 cursor-pointer hover:bg-charcoal hover:text-white hover:border-charcoal transition-all">Floating Frame</span>
</div>
</div>
</div>
</div>
<!-- Hero Section -->
<section class="min-h-screen flex items-center pt-20">
<div class="max-w-7xl mx-auto px-6 lg:px-8 w-full">
<div class="grid lg:grid-cols-2 gap-12 lg:gap-20 items-center">
<!-- Left content -->
<div class="order-2 lg:order-1">
<div class="animate-fade-in-up">
<p class="text-sm uppercase tracking-[0.3em] text-neutral-500 mb-6">Framing since 2018</p>
</div>
<h1 class="font-display text-5xl md:text-6xl lg:text-7xl xl:text-8xl font-medium leading-[0.95] mb-8 animate-fade-in-up delay-100">
Frames<br>
<span class="italic text-neutral-400">for living</span><br>
spaces
</h1>
<p class="text-lg text-neutral-500 leading-relaxed max-w-md mb-10 animate-fade-in-up delay-200">
Handcrafted frames designed to complement your art. Minimal, timeless, and made to last a lifetime.
</p>
<div class="flex flex-wrap gap-4 animate-fade-in-up delay-300">
<a href="#collections" class="group inline-flex items-center gap-3 px-8 py-4 bg-charcoal text-white text-sm font-medium hover:bg-neutral-700 transition-all duration-300">
Shop Collections
<i data-lucide="arrow-right" class="w-4 h-4 group-hover:translate-x-1 transition-transform duration-300"></i>
</a>
<a href="#about" class="inline-flex items-center gap-3 px-8 py-4 border border-charcoal text-charcoal text-sm font-medium hover:bg-charcoal hover:text-white transition-all duration-300">
Our Story
</a>
</div>
<!-- Stats -->
<div class="flex gap-12 mt-16 animate-fade-in-up delay-400">
<div>
<p class="font-display text-3xl font-semibold">12k+</p>
<p class="text-sm text-neutral-400 mt-1">Happy Customers</p>
</div>
<div>
<p class="font-display text-3xl font-semibold">50+</p>
<p class="text-sm text-neutral-400 mt-1">Frame Styles</p>
</div>
<div>
<p class="font-display text-3xl font-semibold">4.9</p>
<p class="text-sm text-neutral-400 mt-1">Average Rating</p>
</div>
</div>
</div>
<!-- Right image -->
<div class="order-1 lg:order-2 animate-fade-in delay-200">
<div class="relative">
<div class="absolute -top-6 -left-6 w-full h-full border-2 border-sand/40"></div>
<img src="http://static.photos/minimal/640x360/42" alt="Minimal frame display" class="w-full aspect-[4/5] object-cover relative z-10">
<div class="absolute -bottom-4 -right-4 bg-cream px-6 py-4 z-20">
<p class="font-display text-sm italic">"Less is more"</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Marquee -->
<section class="py-12 border-y border-neutral-200 overflow-hidden bg-white">
<div class="flex whitespace-nowrap">
<div class="marquee-track flex items-center gap-8">
<span class="font-display text-2xl text-neutral-300">Oak Collection</span>
<span class="text-sand"></span>
<span class="font-display text-2xl text-neutral-300">Black Metal Series</span>
<span class="text-sand"></span>
<span class="font-display text-2xl text-neutral-300">White Minimal</span>
<span class="text-sand"></span>
<span class="font-display text-2xl text-neutral-300">Walnut Frames</span>
<span class="text-sand"></span>
<span class="font-display text-2xl text-neutral-300">Gallery Sets</span>
<span class="text-sand"></span>
<span class="font-display text-2xl text-neutral-300">Floating Frames</span>
<span class="text-sand"></span>
<span class="font-display text-2xl text-neutral-300">Oak Collection</span>
<span class="text-sand"></span>
<span class="font-display text-2xl text-neutral-300">Black Metal Series</span>
<span class="text-sand"></span>
<span class="font-display text-2xl text-neutral-300">White Minimal</span>
<span class="text-sand"></span>
<span class="font-display text-2xl text-neutral-300">Walnut Frames</span>
<span class="text-sand"></span>
<span class="font-display text-2xl text-neutral-300">Gallery Sets</span>
<span class="text-sand"></span>
<span class="font-display text-2xl text-neutral-300">Floating Frames</span>
<span class="text-sand"></span>
</div>
</div>
</section>
<!-- Collections Section -->
<section id="collections" class="py-24 lg:py-32">
<div class="max-w-7xl mx-auto px-6 lg:px-8">
<div class="flex flex-col md:flex-row md:items-end justify-between mb-16 reveal">
<div>
<p class="text-sm uppercase tracking-[0.3em] text-neutral-400 mb-4">Curated</p>
<h2 class="font-display text-4xl md:text-5xl lg:text-6xl font-medium">Collections</h2>
</div>
<a href="#" class="group inline-flex items-center gap-2 text-sm font-medium text-neutral-500 hover:text-charcoal mt-4 md:mt-0 transition-colors">
View All
<i data-lucide="arrow-right" class="w-4 h-4 group-hover:translate-x-1 transition-transform duration-300"></i>
</a>
</div>
<!-- Collection Grid -->
<div class="grid md:grid-cols-3 gap-4 lg:gap-6">
<div class="frame-card md:col-span-2 md:row-span-2 group cursor-pointer reveal">
<img src="http://static.photos/nature/640x360/15" alt="Oak Collection" class="w-full h-full object-cover min-h-[400px] md:min-h-full">
<div class="overlay-content">
<p class="text-white/70 text-sm uppercase tracking-widest mb-1">18 Styles</p>
<h3 class="font-display text-2xl text-white font-medium">Oak Collection</h3>
</div>
</div>
<div class="frame-card group cursor-pointer reveal">
<img src="http://static.photos/minimal/320x240/22" alt="Black Metal" class="w-full h-full object-cover min-h-[200px]">
<div class="overlay-content">
<p class="text-white/70 text-sm uppercase tracking-widest mb-1">12 Styles</p>
<h3 class="font-display text-xl text-white font-medium">Black Metal</h3>
</div>
</div>
<div class="frame-card group cursor-pointer reveal">
<img src="http://static.photos/white/320x240/88" alt="White Minimal" class="w-full h-full object-cover min-h-[200px]">
<div class="overlay-content">
<p class="text-white/70 text-sm uppercase tracking-widest mb-1">8 Styles</p>
<h3 class="font-display text-xl text-white font-medium">White Minimal</h3>
</div>
</div>
</div>
</div>
</section>
<!-- Products / Frames Section -->
<section id="frames" class="py-24 lg:py-32 bg-white">
<div class="max-w-7xl mx-auto px-6 lg:px-8">
<div class="text-center mb-16 reveal">
<p class="text-sm uppercase tracking-[0.3em] text-neutral-400 mb-4">Handcrafted</p>
<h2 class="font-display text-4xl md:text-5xl lg:text-6xl font-medium">Best Sellers</h2>
</div>
<!-- Filter Tabs -->
<div class="flex justify-center gap-4 mb-12 reveal">
<button class="tab-btn active text-sm font-medium border-b-2 pb-2 px-2 transition-all duration-200" data-filter="all">All</button>
<button class="tab-btn text-sm font-medium border-b-2 pb-2 px-2 transition-all duration-200" data-filter="wood">Wood</button>
<button class="tab-btn text-sm font-medium border-b-2 pb-2 px-2 transition-all duration-200" data-filter="metal">Metal</button>
<button class="tab-btn text-sm font-medium border-b-2 pb-2 px-2 transition-all duration-200" data-filter="float">Float</button>
</div>
<!-- Product Grid -->
<div class="grid grid-cols-2 lg:grid-cols-4 gap-4 lg:gap-6" id="productGrid">
<!-- Products will be inserted by JS -->
</div>
</div>
</section>
<!-- Features Section -->
<section class="py-24 lg:py-32 bg-charcoal text-white">
<div class="max-w-7xl mx-auto px-6 lg:px-8">
<div class="text-center mb-20 reveal">
<p class="text-sm uppercase tracking-[0.3em] text-neutral-400 mb-4">Why Neutralframes</p>
<h2 class="font-display text-4xl md:text-5xl lg:text-6xl font-medium">Built on<br><span class="italic text-neutral-400">principles</span></h2>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-8 lg:gap-12">
<div class="reveal">
<div class="w-12 h-12 border border-neutral-500 flex items-center justify-center mb-6">
<i data-lucide="tree-pine" class="w-5 h-5 text-sand"></i>
</div>
<h3 class="font-display text-xl font-medium mb-3">Sustainable Wood</h3>
<p class="text-neutral-400 text-sm leading-relaxed">All our wooden frames are crafted from FSC-certified sustainable forests. Quality that cares.</p>
</div>
<div class="reveal">
<div class="w-12 h-12 border border-neutral-500 flex items-center justify-center mb-6">
<i data-lucide="hand" class="w-5 h-5 text-sand"></i>
</div>
<h3 class="font-display text-xl font-medium mb-3">Handcrafted</h3>
<p class="text-neutral-400 text-sm leading-relaxed">Each frame is meticulously assembled by skilled artisans who take pride in their craft.</p>
</div>
<div class="reveal">
<div class="w-12 h-12 border border-neutral-500 flex items-center justify-center mb-6">
<i data-lucide="shield-check" class="w-5 h-5 text-sand"></i>
</div>
<h3 class="font-display text-xl font-medium mb-3">UV Protection</h3>
<p class="text-neutral-400 text-sm leading-relaxed">Premium acrylic glazing with 92% UV protection keeps your artwork safe from fading.</p>
</div>
<div class="reveal">
<div class="w-12 h-12 border border-neutral-500 flex items-center justify-center mb-6">
<i data-lucide="package" class="w-5 h-5 text-sand"></i>
</div>
<h3 class="font-display text-xl font-medium mb-3">Safe Shipping</h3>
<p class="text-neutral-400 text-sm leading-relaxed">Custom packaging ensures your frames arrive in perfect condition. Free returns within 30 days.</p>
</div>
</div>
</div>
</section>
<!-- About / Story Section -->
<section id="about" class="py-24 lg:py-32">
<div class="max-w-7xl mx-auto px-6 lg:px-8">
<div class="grid lg:grid-cols-2 gap-16 items-center">
<div class="reveal">
<div class="grid grid-cols-2 gap-4">
<img src="http://static.photos/craft/320x240/55" alt="Crafting process" class="w-full object-cover aspect-square">
<img src="http://static.photos/indoor/320x240/33" alt="Workshop" class="w-full object-cover aspect-square mt-8">
</div>
</div>
<div class="reveal">
<p class="text-sm uppercase tracking-[0.3em] text-neutral-400 mb-6">Our Story</p>
<h2 class="font-display text-4xl md:text-5xl font-medium mb-8 leading-tight">
Framing is<br><span class="italic text-neutral-400">an art form</span>
</h2>
<p class="text-neutral-500 leading-relaxed mb-6">
Founded in 2018 in a small workshop in Copenhagen, Neutralframes started with a simple idea: frames should disappear into the space, letting the art speak for itself.
</p>
<p class="text-neutral-500 leading-relaxed mb-10">
Today, we continue that tradition — creating minimal, high-quality frames that complement without competing. Every joint, every edge, every finish is considered with the same care an artist gives their work.
</p>
<a href="#" class="group inline-flex items-center gap-3 text-sm font-medium border-b-2 border-charcoal pb-1 hover:border-sand transition-colors duration-300">
Read Our Full Story
<i data-lucide="arrow-right" class="w-4 h-4 group-hover:translate-x-1 transition-transform duration-300"></i>
</a>
</div>
</div>
</div>
</section>
<!-- Gallery Wall Section -->
<section class="py-24 lg:py-32 bg-cream">
<div class="max-w-7xl mx-auto px-6 lg:px-8">
<div class="text-center mb-16 reveal">
<p class="text-sm uppercase tracking-[0.3em] text-neutral-400 mb-4">Inspiration</p>
<h2 class="font-display text-4xl md:text-5xl lg:text-6xl font-medium">Gallery Walls</h2>
<p class="text-neutral-500 mt-4 max-w-lg mx-auto">Curated arrangements to transform any wall into a personal gallery.</p>
</div>
<!-- Gallery wall preview -->
<div class="grid grid-cols-2 md:grid-cols-4 gap-3 lg:gap-4 reveal">
<div class="col-span-2 row-span-2">
<img src="http://static.photos/indoor/640x360/77" alt="Gallery wall" class="w-full h-full object-cover">
</div>
<div>
<img src="http://static.photos/minimal/320x240/11" alt="Wall detail" class="w-full h-full object-cover">
</div>
<div>
<img src="http://static.photos/white/320x240/44" alt="Wall detail" class="w-full h-full object-cover">
</div>
<div>
<img src="http://static.photos/workspace/320x240/66" alt="Wall detail" class="w-full h-full object-cover">
</div>
<div>
<img src="http://static.photos/vintage/320x240/99" alt="Wall detail" class="w-full h-full object-cover">
</div>
</div>
</div>
</section>
<!-- Testimonials -->
<section class="py-24 lg:py-32">
<div class="max-w-7xl mx-auto px-6 lg:px-8">
<div class="text-center mb-16 reveal">
<p class="text-sm uppercase tracking-[0.3em] text-neutral-400 mb-4">Testimonials</p>
<h2 class="font-display text-4xl md:text-5xl lg:text-6xl font-medium">What people<br><span class="italic text-neutral-400">are saying</span></h2>
</div>
<div class="grid md:grid-cols-3 gap-8" id="testimonialGrid">
<!-- Testimonials inserted by JS -->
</div>
</div>
</section>
<!-- Journal / Blog Section -->
<section id="journal" class="py-24 lg:py-32 bg-white">
<div class="max-w-7xl mx-auto px-6 lg:px-8">
<div class="flex flex-col md:flex-row md:items-end justify-between mb-16 reveal">
<div>
<p class="text-sm uppercase tracking-[0.3em] text-neutral-400 mb-4">Journal</p>
<h2 class="font-display text-4xl md:text-5xl lg:text-6xl font-medium">Latest Stories</h2>
</div>
<a href="#" class="group inline-flex items-center gap-2 text-sm font-medium text-neutral-500 hover:text-charcoal mt-4 md:mt-0 transition-colors">
All Articles
<i data-lucide="arrow-right" class="w-4 h-4 group-hover:translate-x-1 transition-transform duration-300"></i>
</a>
</div>
<div class="grid md:grid-cols-3 gap-8" id="journalGrid">
<!-- Journal entries inserted by JS -->
</div>
</div>
</section>
<!-- Newsletter -->
<section class="py-24 lg:py-32 bg-charcoal text-white">
<div class="max-w-2xl mx-auto px-6 lg:px-8 text-center">
<div class="reveal">
<p class="text-sm uppercase tracking-[0.3em] text-neutral-400 mb-6">Stay Updated</p>
<h2 class="font-display text-3xl md:text-4xl lg:text-5xl font-medium mb-6">Join the <span class="italic text-sand">frame lovers</span></h2>
<p class="text-neutral-400 mb-10">Get early access to new collections, framing tips, and exclusive offers. No spam, unsubscribe anytime.</p>
<form id="newsletterForm" class="flex flex-col sm:flex-row gap-3">
<input type="email" placeholder="Your email address" required class="flex-1 px-6 py-4 bg-neutral-800 border border-neutral-600 text-white placeholder:text-neutral-500 outline-none focus:border-sand transition-colors text-sm" id="emailInput">
<button type="submit" class="px-8 py-4 bg-sand text-charcoal text-sm font-medium hover:bg-warm transition-colors duration-300 whitespace-nowrap">
Subscribe
</button>
</form>
<p class="text-xs text-neutral-500 mt-4">By subscribing you agree to our Privacy Policy</p>
</div>
</div>
</section>
<!-- Footer -->
<footer class="py-20 bg-neutral-900 text-white">
<div class="max-w-7xl mx-auto px-6 lg:px-8">
<div class="grid grid-cols-2 md:grid-cols-4 gap-10 mb-16">
<div class="col-span-2 md:col-span-1">
<a href="#" class="flex items-center gap-2 mb-6">
<div class="w-8 h-8 border-2 border-sand flex items-center justify-center">
<div class="w-3 h-3 border border-sand"></div>
</div>
<span class="font-display text-lg font-semibold">neutralframes</span>
</a>
<p class="text-sm text-neutral-400 leading-relaxed">Minimal frames for modern living. Handcrafted with care in Copenhagen.</p>
</div>
<div>
<h4 class="text-sm font-medium uppercase tracking-wider mb-6">Shop</h4>
<ul class="space-y-3">
<li><a href="#" class="text-sm text-neutral-400 hover:text-white transition-colors">All Frames</a></li>
<li><a href="#" class="text-sm text-neutral-400 hover:text-white transition-colors">Oak Collection</a></li>
<li><a href="#" class="text-sm text-neutral-400 hover:text-white transition-colors">Black Metal</a></li>
<li><a href="#" class="text-sm text-neutral-400 hover:text-white transition-colors">White Minimal</a></li>
<li><a href="#" class="text-sm text-neutral-400 hover:text-white transition-colors">Gallery Sets</a></li>
</ul>
</div>
<div>
<h4 class="text-sm font-medium uppercase tracking-wider mb-6">Company</h4>
<ul class="space-y-3">
<li><a href="#" class="text-sm text-neutral-400 hover:text-white transition-colors">About Us</a></li>
<li><a href="#" class="text-sm text-neutral-400 hover:text-white transition-colors">Journal</a></li>
<li><a href="#" class="text-sm text-neutral-400 hover:text-white transition-colors">Careers</a></li>
<li><a href="#" class="text-sm text-neutral-400 hover:text-white transition-colors">Press</a></li>
</ul>
</div>
<div>
<h4 class="text-sm font-medium uppercase tracking-wider mb-6">Support</h4>
<ul class="space-y-3">
<li><a href="#" class="text-sm text-neutral-400 hover:text-white transition-colors">Help Center</a></li>
<li><a href="#" class="text-sm text-neutral-400 hover:text-white transition-colors">Shipping Info</a></li>
<li><a href="#" class="text-sm text-neutral-400 hover:text-white transition-colors">Returns</a></li>
<li><a href="#" class="text-sm text-neutral-400 hover:text-white transition-colors">Size Guide</a></li>
<li><a href="#" class="text-sm text-neutral-400 hover:text-white transition-colors">Contact</a></li>
</ul>
</div>
</div>
<div class="flex flex-col md:flex-row items-center justify-between pt-8 border-t border-neutral-700">
<p class="text-xs text-neutral-500">© 2024 Neutralframes. All rights reserved.</p>
<div class="flex gap-6 mt-4 md:mt-0">
<a href="#" class="text-neutral-500 hover:text-white transition-colors"><i data-lucide="instagram" class="w-4 h-4"></i></a>
<a href="#" class="text-neutral-500 hover:text-white transition-colors"><i data-lucide="twitter" class="w-4 h-4"></i></a>
<a href="#" class="text-neutral-500 hover:text-white transition-colors"><i data-lucide="facebook" class="w-4 h-4"></i></a>
<a href="#" class="text-neutral-500 hover:text-white transition-colors"><i data-lucide="linkedin" class="w-4 h-4"></i></a>
</div>
</div>
</div>
</footer>
<!-- Toast notification -->
<div id="toast" class="toast fixed bottom-6 right-6 z-50 bg-charcoal text-white px-6 py-4 flex items-center gap-3 shadow-lg">
<i data-lucide="check-circle" class="w-5 h-5 text-sand"></i>
<span class="text-sm" id="toastMessage">Item added to cart</span>
</div>
<script src="https://unpkg.com/lucide@latest"></script>
<script>
// ===== DATA =====
const products = [
{ id: 1, name: 'Oak Thin Frame', price: 49, category: 'wood', image: 'http://static.photos/nature/320x240/10', sizes: ['A4', 'A3', 'A2'] },
{ id: 2, name: 'Black Metal Frame', price: 59, category: 'metal', image: 'http://static.photos/black/320x240/20', sizes: ['A4', 'A3', 'A2'] },
{ id: 3, name: 'White Float Frame', price: 69, category: 'float', image: 'http://static.photos/white/320x240/30', sizes: ['A4', 'A3'] },
{ id: 4, name: 'Walnut Classic', price: 55, category: 'wood', image: 'http://static.photos/vintage/320x240/40', sizes: ['A4', 'A3', 'A2'] },
{ id: 5, name: 'Brass Minimal', price: 79, category: 'metal', image: 'http://static.photos/gold/320x240/50', sizes: ['A3', 'A2', 'A1'] },
{ id: 6, name: 'Natural Oak Float', price: 65, category: 'float', image: 'http://static.photos/nature/320x240/60', sizes: ['A4', 'A3'] },
{ id: 7, name: 'Matte Black', price: 52, category: 'metal', image: 'http://static.photos/black/320x240/70', sizes: ['A4', 'A3', 'A2'] },
{ id: 8, name: 'Ash Wood Frame', price: 58, category: 'wood', image: 'http://static.photos/nature/320x240/80', sizes: ['A4', 'A3', 'A2'] },
];
const testimonials = [
{ name: 'Sarah M.', location: 'London', text: 'The quality is exceptional. The oak frame perfectly complements my print without overwhelming it. Exactly what I was looking for.', rating: 5 },
{ name: 'Thomas K.', location: 'Berlin', text: 'I\'ve ordered 6 frames now and each one has been perfect. The floating frames give such a clean, modern look to my gallery wall.', rating: 5 },
{ name: 'Emily R.', location: 'New York', text: 'Beautiful craftsmanship and fast shipping. The black metal frame is sleek and minimal. My art has never looked better.', rating: 5 },
];
const journalEntries = [
{ title: 'How to Create the Perfect Gallery Wall', date: 'Dec 12, 2024', category: 'Guide', image: 'http://static.photos/indoor/320x240/90', readTime: '5 min read' },
{ title: 'Choosing the Right Frame for Your Art', date: 'Nov 28, 2024', category: 'Tips', image: 'http://static.photos/minimal/320x240/85', readTime: '4 min read' },
{ title: 'Sustainable Framing: Our Commitment', date: 'Nov 15, 2024', category: 'Story', image: 'http://static.photos/nature/320x240/75', readTime: '6 min read' },
];
// ===== CART STATE =====
let cart = [];
// ===== RENDER PRODUCTS =====
function renderProducts(filter = 'all') {
const grid = document.getElementById('productGrid');
const filtered = filter === 'all' ? products : products.filter(p => p.category === filter);
grid.innerHTML = filtered.map((product, i) => `
<div class="product-item group reveal visible" style="animation-delay: ${i * 0.05}s">
<div class="relative overflow-hidden bg-neutral-100 mb-4">
<img src="${product.image}" alt="${product.name}" class="w-full aspect-[3/4] object-cover">
<button onclick="addToCart(${product.id})" class="absolute bottom-0 left-0 right-0 bg-charcoal text-white text-sm font-medium py-3 translate-y-full group-hover:translate-y-0 transition-transform duration-300 flex items-center justify-center gap-2">
<i data-lucide="shopping-bag" class="w-4 h-4"></i>
Add to Cart
</button>
</div>
<h3 class="text-sm font-medium mb-1">${product.name}</h3>
<p class="text-sm text-neutral-400">From $${product.price}</p>
</div>
`).join('');
lucide.createIcons();
}
// ===== RENDER TESTIMONIALS =====
function renderTestimonials() {
const grid = document.getElementById('testimonialGrid');
grid.innerHTML = testimonials.map((t, i) => `
<div class="p-8 bg-neutral-50 reveal">
<div class="flex gap-1 mb-4">
${Array(t.rating).fill('<i data-lucide="star" class="w-4 h-4 fill-sand text-sand"></i>').join('')}
</div>
<p class="text-neutral-600 leading-relaxed mb-6 text-sm">"${t.text}"</p>
<div>
<p class="font-medium text-sm">${t.name}</p>
<p class="text-xs text-neutral-400">${t.location}</p>
</div>
</div>
`).join('');
lucide.createIcons();
}
// ===== RENDER JOURNAL =====
function renderJournal() {
const grid = document.getElementById('journalGrid');
grid.innerHTML = journalEntries.map((j, i) => `
<a href="#" class="group reveal">
<div class="overflow-hidden mb-4">
<img src="${j.image}" alt="${j.title}" class="w-full aspect-[4/3] object-cover group-hover:scale-105 transition-transform duration-500">
</div>
<div class="flex items-center gap-3 mb-3">
<span class="text-xs uppercase tracking-widest text-neutral-400">${j.category}</span>
<span class="text-xs text-neutral-300">·</span>
<span class="text-xs text-neutral-400">${j.readTime}</span>
</div>
<h3 class="font-display text-lg font-medium group-hover:text-neutral-500 transition-colors">${j.title}</h3>
<p class="text-xs text-neutral-400 mt-2">${j.date}</p>
</a>
`).join('');
}
// ===== ADD TO CART =====
function addToCart(productId) {
const product = products.find(p => p.id === productId);
if (product) {
cart.push(product);
document.getElementById('cartCount').textContent = cart.length;
showToast(`${product.name} added to cart`);
}
}
// ===== TOAST =====
function showToast(message) {
const toast = document.getElementById('toast');
const toastMsg = document.getElementById('toastMessage');
toastMsg.textContent = message;
toast.classList.add('show');
setTimeout(() => toast.classList.remove('show'), 3000);
}
// ===== TABS =====
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
renderProducts(btn.dataset.filter);
});
});
// ===== MOBILE MENU =====
document.getElementById('menuToggle').addEventListener('click', () => {
document.getElementById('mobileMenu').classList.add('open');
document.body.style.overflow = 'hidden';
});
document.getElementById('menuClose').addEventListener('click', () => {
document.getElementById('mobileMenu').classList.remove('open');
document.body.style.overflow = '';
});
document.querySelectorAll('.mobile-link').forEach(link => {
link.addEventListener('click', () => {
document.getElementById('mobileMenu').classList.remove('open');
document.body.style.overflow = '';
});
});
// ===== SEARCH MODAL =====
document.getElementById('searchBtn').addEventListener('click', () => {
const modal = document.getElementById('searchModal');
modal.classList.remove('hidden');
modal.classList.add('flex');
setTimeout(() => document.getElementById('searchInput').focus(), 100);
});
document.getElementById('searchClose').addEventListener('click', () => {
const modal = document.getElementById('searchModal');
modal.classList.add('hidden');
modal.classList.remove('flex');
});
// ===== NEWSLETTER =====
document.getElementById('newsletterForm').addEventListener('submit', (e) => {
e.preventDefault();
const email = document.getElementById('emailInput').value;
if (email) {
showToast('Welcome! You\'ve been subscribed 🎉');
document.getElementById('emailInput').value = '';
}
});
// ===== SCROLL REVEAL =====
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
}
});
}, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' });
function observeReveals() {
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
}
// ===== NAVBAR SCROLL =====
let lastScroll = 0;
window.addEventListener('scroll', () => {
const navbar = document.getElementById('navbar');
const currentScroll = window.pageYOffset;
if (currentScroll > 100) {
navbar.style.borderBottom = '1px solid rgba(0,0,0,0.05)';
} else {
navbar.style.borderBottom = 'none';
}
if (currentScroll > lastScroll && currentScroll > 200) {
navbar.style.transform = 'translateY(-100%)';
} else {
navbar.style.transform = 'translateY(0)';
}
navbar.style.transition = 'transform 0.3s ease, border-bottom 0.3s ease';
lastScroll = currentScroll;
});
// ===== SMOOTH ANCHOR SCROLLING =====
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', (e) => {
e.preventDefault();
const target = document.querySelector(anchor.getAttribute('href'));
if (target) {
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
});
});
// ===== INIT =====
document.addEventListener('DOMContentLoaded', () => {
lucide.createIcons();
renderProducts();
renderTestimonials();
renderJournal();
observeReveals();
});
</script>
<script src="https://deepsite.hf.co/deepsite-badge.js"></script>
</body>
</html>