Exploring the world of digital galleries can be both inspiring and educational. In this article, we present ten stunning gallery examples that showcase the best in design and functionality.
From minimalist layouts to vibrant, interactive displays, these galleries offer a glimpse into the creative possibilities available today. Let's dive into these exemplary designs and discover what makes each one unique.
CODE1
Here's the code:
CODETEXT1
CODE2
Here's the code:
CODETEXT2
CODE3
Here's the code:
CODETEXT3
CODE4
Here's the code:
CODETEXT4
CODE5
Here's the code:
CODETEXT5
Designers and developers, elevate your gallery creations with Subframe's drag-and-drop interface and intuitive, responsive canvas. Achieve pixel-perfect UI effortlessly, every time.
Loved by professionals across the industry, Subframe makes stunning design accessible to all. Start for free today!
CODE6
Here's the code:
CODETEXT6
CODE7
Here's the code:
CODETEXT7
CODE8
Here's the code:
CODETEXT8
CODE9
Here's the code:
CODETEXT9
CODE10
Here's the code:
CODETEXT10
Ready to elevate your UI designs? With Subframe, you can create pixel-perfect galleries and interfaces in minutes. Our drag-and-drop editor and beautifully crafted components make the process efficient and enjoyable.
Don't wait to bring your vision to life. Start for free and begin designing stunning UIs today!
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Chronos Gallery</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Cormorant Garamond', serif; } body { background-color: #f8f7f5; color: #333; overflow-x: hidden; padding: 20px; max-width: 700px; max-height: 700px; overflow-y: auto; margin: 0 auto; } header { margin-bottom: 30px; padding-bottom: 15px; border-bottom: 1px solid #e0dcd5; } h1 { font-size: 32px; font-weight: 300; letter-spacing: 1.2px; margin-bottom: 10px; color: #343434; } .subtitle { font-size: 16px; color: #777; font-style: italic; margin-bottom: 20px; } .filters { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 20px; } .filter-btn { background-color: transparent; border: 1px solid #c7c1b5; padding: 8px 16px; cursor: pointer; transition: all 0.3s ease; font-size: 14px; border-radius: 2px; color: #555; } .filter-btn:hover { background-color: #edebe7; } .filter-btn.active { background-color: #e0dcd5; color: #333; font-weight: 500; } .gallery-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 20px; margin-top: 30px; } .artwork-item { position: relative; overflow: hidden; cursor: pointer; border-radius: 2px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); height: 280px; transform-origin: center; transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .artwork-item:hover { transform: scale(1.03); z-index: 10; } .artwork-image { width: 100%; height: 100%; object-fit: cover; transition: all 0.5s ease; } .artwork-item:hover .artwork-image { filter: brightness(0.8); } .artwork-details { position: absolute; bottom: 0; left: 0; width: 100%; background: linear-gradient(to top, rgba(0, 0, 0, 0.8), transparent); padding: 20px; transform: translateY(100%); transition: transform 0.4s cubic-bezier(0.19, 1, 0.22, 1); color: #fff; } .artwork-item:hover .artwork-details { transform: translateY(0); } .artwork-title { font-size: 18px; margin-bottom: 5px; font-weight: 500; } .artwork-artist { font-size: 14px; font-style: italic; margin-bottom: 8px; opacity: 0.9; } .artwork-meta { display: flex; font-size: 12px; opacity: 0.8; justify-content: space-between; } .artwork-year { color: #e0dcd5; } .artwork-medium { text-transform: uppercase; letter-spacing: 1px; font-size: 11px; } .no-results { grid-column: 1 / -1; padding: 40px; text-align: center; color: #777; font-style: italic; } /* Special animation for featured piece */ .featured-badge { position: absolute; top: 10px; right: 10px; background: rgba(210, 180, 140, 0.9); color: white; padding: 5px 10px; font-size: 11px; border-radius: 2px; letter-spacing: 1px; transform: translateY(-40px); opacity: 0; transition: all 0.4s ease; } .artwork-item:hover .featured-badge { transform: translateY(0); opacity: 1; } .curator-note { font-size: 12px; line-height: 1.4; margin-top: 8px; max-height: 0; overflow: hidden; transition: max-height 0.4s ease; } .artwork-item:hover .curator-note { max-height: 100px; } @media (max-width: 600px) { .gallery-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 15px; } .artwork-item { height: 220px; } h1 { font-size: 24px; } .filter-btn { padding: 6px 12px; font-size: 12px; } } /* Loading animation */ .loader { display: none; justify-content: center; align-items: center; height: 100px; } .loader-dot { width: 10px; height: 10px; margin: 0 5px; background-color: #c7c1b5; border-radius: 50%; animation: bounce 1.4s infinite ease-in-out both; } .loader-dot:nth-child(1) { animation-delay: -0.32s; } .loader-dot:nth-child(2) { animation-delay: -0.16s; } @keyframes bounce { 0%, 80%, 100% { transform: scale(0); } 40% { transform: scale(1); } } </style> </head> <body> <header> <h1>Chronos Gallery</h1> <p class="subtitle">Evolution of Form: Exploring Artistic Movements From 1800-2020</p> <div class="filters"> <button class="filter-btn active" data-filter="all">All Works</button> <button class="filter-btn" data-filter="painting">Painting</button> <button class="filter-btn" data-filter="sculpture">Sculpture</button> <button class="filter-btn" data-filter="photography">Photography</button> <button class="filter-btn" data-filter="digital">Digital</button> <button class="filter-btn" data-period="19">19th Century</button> <button class="filter-btn" data-period="20">20th Century</button> <button class="filter-btn" data-period="21">21st Century</button> </div> </header> <div class="loader"> <div class="loader-dot"></div> <div class="loader-dot"></div> <div class="loader-dot"></div> </div> <div class="gallery-grid" id="gallery"> <!-- Content will be populated by JavaScript --> </div> <script> // Artwork data const artworks = [ { id: 1, title: "Chromatic Reverie", artist: "Eliza Thornfield", year: 1887, period: "19", medium: "painting", image: "https://images.unsplash.com/photo-1579783928621-7a13d66a62d1?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2340&q=80", featured: true, note: "A rare example of pre-impressionist color theory experimentation." }, { id: 2, title: "Urban Fragment #7", artist: "Terrence Holloway", year: 1932, period: "20", medium: "photography", image: "https://images.unsplash.com/photo-1577083552762-c47bc83e8749?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2340&q=80", featured: false, note: "" }, { id: 3, title: "Dissected Form", artist: "Maria Scultura", year: 1965, period: "20", medium: "sculpture", image: "https://images.unsplash.com/photo-1571331627305-b3711675c042?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2149&q=80", featured: true, note: "Part of Scultura's groundbreaking series on decomposition." }, { id: 4, title: "Neo-Expressionist Study", artist: "Jean-Michel Fornier", year: 1978, period: "20", medium: "painting", image: "https://images.unsplash.com/photo-1547826039-bfc35e0f1ea8?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1972&q=80", featured: false, note: "" }, { id: 5, title: "Digital Decay 2.0", artist: "Alex Zhang", year: 2019, period: "21", medium: "digital", image: "https://images.unsplash.com/photo-1633658578580-0124fc2e7783?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80", featured: false, note: "" }, { id: 6, title: "Conversation with Silence", artist: "Hiroshi Tanaka", year: 2008, period: "21", medium: "sculpture", image: "https://images.unsplash.com/photo-1550684376-efcbd6e3f031?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2340&q=80", featured: true, note: "Created during Tanaka's solitary mountain retreat." }, { id: 7, title: "Impressions of Morning", artist: "Claude Monette", year: 1872, period: "19", medium: "painting", image: "https://images.unsplash.com/photo-1581343109297-b0723710832c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2090&q=80", featured: false, note: "" }, { id: 8, title: "Post-Human Landscape", artist: "Sophia Rivers", year: 2017, period: "21", medium: "digital", image: "https://images.unsplash.com/photo-1642427749670-f20e2e76ed8c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2160&q=80", featured: true, note: "Commissioned for the International Climate Summit." }, { id: 9, title: "Documentary Series #12", artist: "Henri Cartessi", year: 1948, period: "20", medium: "photography", image: "https://images.unsplash.com/photo-1534278854415-d08fd9e5406f?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2340&q=80", featured: false, note: "" } ]; // DOM manipulation after page load document.addEventListener('DOMContentLoaded', function() { const gallery = document.getElementById('gallery'); const filterButtons = document.querySelectorAll('.filter-btn'); const loader = document.querySelector('.loader'); let currentFilter = 'all'; let currentPeriod = null; // Render gallery items function renderGallery(items) { // Show loader and clear gallery gallery.style.display = 'none'; loader.style.display = 'flex'; setTimeout(() => { gallery.innerHTML = ''; if (items.length === 0) { const noResults = document.createElement('div'); noResults.className = 'no-results'; noResults.textContent = 'No artworks match your current filters. Try adjusting your selection.'; gallery.appendChild(noResults); } else { items.forEach(artwork => { const artworkItem = document.createElement('div'); artworkItem.className = 'artwork-item'; artworkItem.setAttribute('data-medium', artwork.medium); artworkItem.setAttribute('data-period', artwork.period); artworkItem.innerHTML = ` <img src="${artwork.image}" alt="${artwork.title}" class="artwork-image"> ${artwork.featured ? '<span class="featured-badge">FEATURED</span>' : ''} <div class="artwork-details"> <h3 class="artwork-title">${artwork.title}</h3> <p class="artwork-artist">${artwork.artist}</p> <div class="artwork-meta"> <span class="artwork-year">${artwork.year}</span> <span class="artwork-medium">${artwork.medium}</span> </div> ${artwork.note ? `<p class="curator-note">${artwork.note}</p>` : ''} </div> `; gallery.appendChild(artworkItem); }); } // Hide loader and show gallery loader.style.display = 'none'; gallery.style.display = 'grid'; }, 600); // Simulate loading time } // Filter artworks function filterArtworks() { let filteredArtworks = [...artworks]; if (currentFilter !== 'all') { filteredArtworks = filteredArtworks.filter(artwork => artwork.medium === currentFilter); } if (currentPeriod) { filteredArtworks = filteredArtworks.filter(artwork => artwork.period === currentPeriod); } renderGallery(filteredArtworks); } // Initialize gallery renderGallery(artworks); // Filter button click events filterButtons.forEach(button => { button.addEventListener('click', function() { // Remove active class from all buttons filterButtons.forEach(btn => btn.classList.remove('active')); // Add active class to clicked button this.classList.add('active'); // Set current filter based on button data if (this.hasAttribute('data-filter')) { currentFilter = this.getAttribute('data-filter'); // If clicking a medium filter, reset period filter if (currentPeriod) { currentPeriod = null; // Remove active class from period buttons document.querySelectorAll('[data-period]').forEach(btn => { if (!btn.hasAttribute('data-filter')) { btn.classList.remove('active'); } }); } } else if (this.hasAttribute('data-period')) { currentPeriod = this.getAttribute('data-period'); // If clicking a period filter, reset medium filter if (currentFilter !== 'all') { currentFilter = 'all'; // Remove active class from medium buttons document.querySelectorAll('[data-filter]').forEach(btn => { if (!btn.hasAttribute('data-period')) { btn.classList.remove('active'); } }); // Add active class to "All Works" button document.querySelector('[data-filter="all"]').classList.add('active'); } } filterArtworks(); }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Boutique Active E-commerce Gallery</title> <style> @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap'); :root { --primary: #2a6b8f; --secondary: #f27a54; --accent: #e9c46a; --light: #f4f7f9; --dark: #2b3743; --bg-gradient: linear-gradient(135deg, #f4f7f9 0%, #e3f0f5 100%); --card-shadow: 0 8px 20px rgba(42, 107, 143, 0.1); --hover-shadow: 0 12px 30px rgba(42, 107, 143, 0.2); --anim-timing: cubic-bezier(0.34, 1.56, 0.64, 1); } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Poppins', sans-serif; background: var(--bg-gradient); color: var(--dark); height: 100%; width: 100%; overflow-x: hidden; padding: 20px; } .container { max-width: 700px; margin: 0 auto; height: 100%; } header { text-align: center; margin-bottom: 20px; } h1 { font-size: 1.8rem; font-weight: 600; color: var(--primary); margin-bottom: 8px; position: relative; display: inline-block; } h1::after { content: ''; position: absolute; bottom: -5px; left: 50%; transform: translateX(-50%); width: 60%; height: 3px; background: var(--secondary); border-radius: 2px; } .subtitle { font-size: 0.9rem; color: var(--dark); opacity: 0.8; margin-bottom: 5px; } .filter-controls { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; flex-wrap: wrap; } .filter-buttons { display: flex; gap: 10px; flex-wrap: wrap; } .filter-btn { background: transparent; border: 1px solid var(--primary); color: var(--primary); padding: 6px 12px; border-radius: 20px; font-size: 0.85rem; cursor: pointer; transition: all 0.3s var(--anim-timing); } .filter-btn:hover, .filter-btn.active { background: var(--primary); color: white; transform: translateY(-2px); } .sort-dropdown { position: relative; } .sort-dropdown select { appearance: none; background: transparent; border: 1px solid var(--primary); padding: 6px 30px 6px 12px; border-radius: 20px; font-size: 0.85rem; color: var(--primary); cursor: pointer; outline: none; } .sort-dropdown::after { content: '▼'; font-size: 0.7rem; color: var(--primary); position: absolute; right: 12px; top: 50%; transform: translateY(-50%); pointer-events: none; } .product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 20px; margin-bottom: 20px; } .product-card { background: white; border-radius: 12px; overflow: hidden; position: relative; transition: all 0.4s var(--anim-timing); box-shadow: var(--card-shadow); height: 100%; display: flex; flex-direction: column; transform-origin: center; } .product-card:hover { transform: translateY(-5px); box-shadow: var(--hover-shadow); } .product-image { position: relative; overflow: hidden; padding-top: 100%; /* 1:1 Aspect ratio */ } .product-image img { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s ease; } .product-card:hover .product-image img { transform: scale(1.1); } .product-badge { position: absolute; top: 10px; left: 10px; background: var(--secondary); color: white; padding: 4px 8px; font-size: 0.75rem; font-weight: 500; border-radius: 4px; z-index: 2; opacity: 1; transition: opacity 0.3s, transform 0.3s; } .product-badge.sale { background: var(--secondary); } .product-badge.new { background: var(--accent); color: var(--dark); } .product-badge.eco { background: #3da87e; } .quick-actions { position: absolute; bottom: 0; left: 0; right: 0; display: flex; justify-content: center; padding: 10px; background: rgba(255, 255, 255, 0.9); transform: translateY(100%); transition: transform 0.3s ease; z-index: 2; gap: 8px; } .product-card:hover .quick-actions { transform: translateY(0); } .action-btn { background: var(--primary); color: white; border: none; width: 32px; height: 32px; border-radius: 50%; font-size: 0.9rem; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.3s; } .action-btn:hover { background: var(--secondary); transform: scale(1.1); } .action-btn.add-to-cart { width: auto; padding: 0 12px; border-radius: 16px; } .product-info { padding: 15px; flex-grow: 1; display: flex; flex-direction: column; } .product-title { font-size: 0.95rem; font-weight: 500; margin-bottom: 5px; transition: color 0.3s; line-height: 1.3; } .product-card:hover .product-title { color: var(--primary); } .product-meta { display: flex; justify-content: space-between; align-items: center; margin-top: auto; } .product-price { font-weight: 600; color: var(--primary); display: flex; flex-direction: column; } .regular-price { text-decoration: line-through; font-size: 0.75rem; color: #999; font-weight: 400; } .sale-price { color: var(--secondary); } .product-rating { display: flex; align-items: center; font-size: 0.8rem; gap: 4px; } .stars { color: var(--accent); } .review-count { color: #888; } .product-desc { font-size: 0.8rem; color: #666; margin: 5px 0 10px; line-height: 1.4; max-height: 0; overflow: hidden; transition: max-height 0.4s ease, margin 0.4s ease; } .product-card:hover .product-desc { max-height: 60px; margin: 8px 0 12px; } .pagination { display: flex; justify-content: center; gap: 5px; margin-top: 20px; } .page-btn { width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; border: 1px solid var(--primary); border-radius: 4px; background: transparent; color: var(--primary); cursor: pointer; transition: all 0.3s; } .page-btn:hover, .page-btn.active { background: var(--primary); color: white; } .quick-view-modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(43, 55, 67, 0.8); display: flex; align-items: center; justify-content: center; z-index: 1000; opacity: 0; visibility: hidden; transition: opacity 0.3s, visibility 0.3s; } .quick-view-modal.active { opacity: 1; visibility: visible; } .modal-content { background: white; border-radius: 12px; width: 90%; max-width: 600px; max-height: 80vh; overflow: auto; padding: 20px; position: relative; transform: translateY(30px); opacity: 0; transition: transform 0.4s var(--anim-timing), opacity 0.4s; } .quick-view-modal.active .modal-content { transform: translateY(0); opacity: 1; } .close-modal { position: absolute; top: 15px; right: 15px; background: none; border: none; font-size: 1.2rem; color: var(--dark); cursor: pointer; transition: transform 0.3s; } .close-modal:hover { transform: rotate(90deg); } .modal-product { display: flex; flex-direction: column; gap: 20px; } @media (min-width: 480px) { .modal-product { flex-direction: row; } } .modal-product-img { flex: 1; border-radius: 8px; overflow: hidden; } .modal-product-img img { width: 100%; height: auto; object-fit: cover; } .modal-product-details { flex: 1; display: flex; flex-direction: column; } .modal-title { font-size: 1.2rem; color: var(--dark); margin-bottom: 5px; } .modal-price { font-size: 1.1rem; font-weight: 600; color: var(--primary); margin-bottom: 15px; } .modal-desc { font-size: 0.9rem; line-height: 1.5; color: #555; margin-bottom: 20px; } .modal-actions { display: flex; gap: 10px; margin-top: auto; } .modal-btn { flex: 1; padding: 10px 15px; border: none; border-radius: 6px; font-weight: 500; cursor: pointer; transition: all 0.3s; } .add-cart-btn { background: var(--primary); color: white; } .add-cart-btn:hover { background: #1d5a7a; } .wishlist-btn { background: #f0f0f0; color: var(--dark); } .wishlist-btn:hover { background: #e0e0e0; } .color-options { display: flex; gap: 8px; margin-bottom: 15px; } .color-option { width: 25px; height: 25px; border-radius: 50%; cursor: pointer; position: relative; transition: transform 0.3s; } .color-option:hover { transform: scale(1.1); } .color-option.selected::after { content: ''; position: absolute; top: -3px; left: -3px; right: -3px; bottom: -3px; border: 2px solid var(--primary); border-radius: 50%; } .empty-indicator { height: 2px; background: #e0e0e0; position: relative; margin: 15px 0; border-radius: 2px; overflow: hidden; } .empty-indicator::after { content: ''; position: absolute; top: 0; left: 0; width: 70%; height: 100%; background: var(--secondary); border-radius: 2px; } .stock-text { font-size: 0.8rem; color: #777; margin-bottom: 15px; } /* Loading shimmer effect */ @keyframes shimmer { 0% { background-position: -468px 0; } 100% { background-position: 468px 0; } } .shimmer { animation: shimmer 1.5s infinite linear; background: linear-gradient(to right, #f6f7f8 8%, #edeef1 18%, #f6f7f8 33%); background-size: 800px 104px; } /* Add a subtle pattern to the background */ .bg-pattern { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; opacity: 0.03; background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23000000' fill-opacity='1'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); } /* Responsive adjustments */ @media (max-width: 600px) { .product-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 15px; } h1 { font-size: 1.5rem; } .subtitle { font-size: 0.8rem; } .filter-controls { flex-direction: column; align-items: flex-start; gap: 10px; } .sort-dropdown { align-self: flex-end; } } </style> </head> <body> <div class="bg-pattern"></div> <div class="container"> <header> <h1>Boutique Active</h1> <p class="subtitle">Premium activewear for your active lifestyle</p> </header> <div class="filter-controls"> <div class="filter-buttons"> <button class="filter-btn active" data-filter="all">All</button> <button class="filter-btn" data-filter="new">New Arrivals</button> <button class="filter-btn" data-filter="sale">On Sale</button> <button class="filter-btn" data-filter="eco">Eco-Friendly</button> </div> <div class="sort-dropdown"> <select id="sort-select"> <option value="popularity">Popularity</option> <option value="price-asc">Price: Low to High</option> <option value="price-desc">Price: High to Low</option> <option value="newest">Newest First</option> </select> </div> </div> <div class="product-grid"> <!-- Product 1 --> <div class="product-card" data-category="new"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1613645695025-20e3f38de4a4?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80" alt="Flow Yoga Top"> <div class="product-badge new">New</div> <div class="quick-actions"> <button class="action-btn quick-view" data-id="1"><i class="fas fa-eye"></i></button> <button class="action-btn add-to-cart">Add to Cart</button> <button class="action-btn"><i class="fas fa-heart"></i></button> </div> </div> <div class="product-info"> <h3 class="product-title">Flow Yoga Top</h3> <p class="product-desc">Breathable 4-way stretch fabric perfect for hot yoga sessions.</p> <div class="product-meta"> <div class="product-price">$48.00</div> <div class="product-rating"> <span class="stars">★★★★★</span> <span class="review-count">(42)</span> </div> </div> </div> </div> <!-- Product 2 --> <div class="product-card" data-category="sale"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1545127398-14699f92334b?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80" alt="Pulse Runner Shorts"> <div class="product-badge sale">Sale -20%</div> <div class="quick-actions"> <button class="action-btn quick-view" data-id="2"><i class="fas fa-eye"></i></button> <button class="action-btn add-to-cart">Add to Cart</button> <button class="action-btn"><i class="fas fa-heart"></i></button> </div> </div> <div class="product-info"> <h3 class="product-title">Pulse Runner Shorts</h3> <p class="product-desc">Lightweight shorts with hidden pocket for your essentials.</p> <div class="product-meta"> <div class="product-price"> <span class="regular-price">$55.00</span> <span class="sale-price">$44.00</span> </div> <div class="product-rating"> <span class="stars">★★★★☆</span> <span class="review-count">(29)</span> </div> </div> </div> </div> <!-- Product 3 --> <div class="product-card" data-category="eco"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1616486338812-3dadae4b4ace?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80" alt="Terra Eco Leggings"> <div class="product-badge eco">Eco</div> <div class="quick-actions"> <button class="action-btn quick-view" data-id="3"><i class="fas fa-eye"></i></button> <button class="action-btn add-to-cart">Add to Cart</button> <button class="action-btn"><i class="fas fa-heart"></i></button> </div> </div> <div class="product-info"> <h3 class="product-title">Terra Eco Leggings</h3> <p class="product-desc">Made from recycled ocean plastic with flattering high waist.</p> <div class="product-meta"> <div class="product-price">$65.00</div> <div class="product-rating"> <span class="stars">★★★★★</span> <span class="review-count">(67)</span> </div> </div> </div> </div> <!-- Product 4 --> <div class="product-card" data-category="new"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1556306535-0f09a537f0a3?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80" alt="Flex Training Jacket"> <div class="product-badge new">New</div> <div class="quick-actions"> <button class="action-btn quick-view" data-id="4"><i class="fas fa-eye"></i></button> <button class="action-btn add-to-cart">Add to Cart</button> <button class="action-btn"><i class="fas fa-heart"></i></button> </div> </div> <div class="product-info"> <h3 class="product-title">Flex Training Jacket</h3> <p class="product-desc">Performance jacket with thermal regulation for all weather.</p> <div class="product-meta"> <div class="product-price">$89.00</div> <div class="product-rating"> <span class="stars">★★★★☆</span> <span class="review-count">(31)</span> </div> </div> </div> </div> <!-- Product 5 --> <div class="product-card" data-category="sale"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1490481651871-ab68de25d43d?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80" alt="Summit Hiking Tee"> <div class="product-badge sale">Sale -15%</div> <div class="quick-actions"> <button class="action-btn quick-view" data-id="5"><i class="fas fa-eye"></i></button> <button class="action-btn add-to-cart">Add to Cart</button> <button class="action-btn"><i class="fas fa-heart"></i></button> </div> </div> <div class="product-info"> <h3 class="product-title">Summit Hiking Tee</h3> <p class="product-desc">Moisture-wicking tee that keeps you dry on the trails.</p> <div class="product-meta"> <div class="product-price"> <span class="regular-price">$42.00</span> <span class="sale-price">$35.70</span> </div> <div class="product-rating"> <span class="stars">★★★★☆</span> <span class="review-count">(24)</span> </div> </div> </div> </div> <!-- Product 6 --> <div class="product-card" data-category="eco"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1434682881908-b43d0467b798?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80" alt="Orbit Bamboo Tank"> <div class="product-badge eco">Eco</div> <div class="quick-actions"> <button class="action-btn quick-view" data-id="6"><i class="fas fa-eye"></i></button> <button class="action-btn add-to-cart">Add to Cart</button> <button class="action-btn"><i class="fas fa-heart"></i></button> </div> </div> <div class="product-info"> <h3 class="product-title">Orbit Bamboo Tank</h3> <p class="product-desc">Sustainable bamboo fabric with natural anti-odor properties.</p> <div class="product-meta"> <div class="product-price">$38.00</div> <div class="product-rating"> <span class="stars">★★★★★</span> <span class="review-count">(52)</span> </div> </div> </div> </div> </div> <div class="pagination"> <button class="page-btn active">1</button> <button class="page-btn">2</button> <button class="page-btn">3</button> <button class="page-btn">></button> </div> </div> <!-- Quick View Modal --> <div class="quick-view-modal" id="quickViewModal"> <div class="modal-content"> <button class="close-modal">×</button> <div class="modal-product"> <div class="modal-product-img"> <img src="" alt="Product" id="modalProductImg"> </div> <div class="modal-product-details"> <h2 class="modal-title" id="modalTitle"></h2> <div class="modal-price" id="modalPrice"></div> <div class="color-options"> <div class="color-option selected" style="background-color: #3a6b8f;"></div> <div class="color-option" style="background-color: #d43c4e;"></div> <div class="color-option" style="background-color: #333333;"></div> <div class="color-option" style="background-color: #e9c46a;"></div> </div> <p class="modal-desc" id="modalDesc"></p> <div class="stock-text">Item in stock - Usually ships within 24 hours</div> <div class="empty-indicator"></div> <div class="modal-actions"> <button class="modal-btn add-cart-btn">Add to Cart</button> <button class="modal-btn wishlist-btn">Save for Later</button> </div> </div> </div> </div> </div> <script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script> <script> document.addEventListener('DOMContentLoaded', function() { // Font Awesome fallback if(typeof FontAwesome === 'undefined') { const icons = { 'fa-eye': '👁️', 'fa-heart': '❤️', 'fa-shopping-cart': '🛒' }; document.querySelectorAll('.fas').forEach(icon => { const classes = Array.from(icon.classList); for (const cls of classes) { if (icons[cls]) { icon.textContent = icons[cls]; break; } } }); } // Filter functionality const filterButtons = document.querySelectorAll('.filter-btn'); const productCards = document.querySelectorAll('.product-card'); filterButtons.forEach(button => { button.addEventListener('click', () => { // Remove active class from all buttons filterButtons.forEach(btn => btn.classList.remove('active')); // Add active class to clicked button button.classList.add('active'); const filter = button.dataset.filter; // Filter products productCards.forEach(card => { if (filter === 'all' || card.dataset.category === filter) { card.style.display = 'flex'; } else { card.style.display = 'none'; } }); }); }); // Sort functionality const sortSelect = document.getElementById('sort-select'); sortSelect.addEventListener('change', () => { const sortBy = sortSelect.value; const productGrid = document.querySelector('.product-grid'); const products = Array.from(productCards); products.sort((a, b) => { const aPrice = parseFloat(a.querySelector('.product-price').innerText.replace('$', '')); const bPrice = parseFloat(b.querySelector('.product-price').innerText.replace('$', '')); if (sortBy === 'price-asc') { return aPrice - bPrice; } else if (sortBy === 'price-desc') { return bPrice - aPrice; } else { // For other sort options, just randomize for demo return Math.random() - 0.5; } }); // Reorder elements products.forEach(product => { productGrid.appendChild(product); }); }); // Pagination functionality const pageButtons = document.querySelectorAll('.page-btn'); pageButtons.forEach(button => { button.addEventListener('click', () => { pageButtons.forEach(btn => btn.classList.remove('active')); button.classList.add('active'); // In a real app, load the next page data here // For demo, just scroll to top of grid document.querySelector('.product-grid').scrollIntoView({ behavior: 'smooth' }); }); }); // Quick view modal functionality const quickViewButtons = document.querySelectorAll('.quick-view'); const modal = document.getElementById('quickViewModal'); const closeModal = document.querySelector('.close-modal'); // Product data for quick view const productData = { 1: { title: 'Flow Yoga Top', price: '$48.00', image: 'https://images.unsplash.com/photo-1613645695025-20e3f38de4a4?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', desc: 'Our most versatile yoga top crafted with breathable 4-way stretch fabric. Features flatlock seams to prevent chafing and a built-in shelf bra for light support. Perfect for hot yoga sessions or any workout that brings the heat.' }, 2: { title: 'Pulse Runner Shorts', price: '$44.00', image: 'https://images.unsplash.com/photo-1545127398-14699f92334b?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', desc: 'Engineered for speed and comfort, these lightweight running shorts feature a hidden pocket perfect for storing your essentials. The sweat-wicking fabric keeps you dry while reflective details enhance visibility in low light.' }, 3: { title: 'Terra Eco Leggings', price: '$65.00', image: 'https://images.unsplash.com/photo-1616486338812-3dadae4b4ace?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', desc: 'Eco-friendly performance leggings crafted from recycled ocean plastic. Features a flattering high waist, smartphone pocket, and compression fit that supports your muscles during intense workouts. Each pair helps remove plastic from our oceans.' }, 4: { title: 'Flex Training Jacket', price: '$89.00', image: 'https://images.unsplash.com/photo-1556306535-0f09a537f0a3?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', desc: 'The ultimate performance jacket with thermal regulation technology adapts to your body temperature. Breathable panels release excess heat while insulated areas retain warmth where needed. Perfect for outdoor training in variable conditions.' }, 5: { title: 'Summit Hiking Tee', price: '$35.70', image: 'https://images.unsplash.com/photo-1490481651871-ab68de25d43d?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', desc: 'Hit the trails with confidence in our moisture-wicking summit tee. The antimicrobial treatment prevents odor-causing bacteria, while UPF 50+ offers sun protection. Seamless underarm construction eliminates chafing on longer hikes.' }, 6: { title: 'Orbit Bamboo Tank', price: '$38.00', image: 'https://images.unsplash.com/photo-1434682881908-b43d0467b798?ixlib=rb-4.0.3&auto=format&fit=crop&w=400&q=80', desc: 'Sustainably made from bamboo fabric with natural anti-odor properties, this tank offers exceptional comfort for yoga and studio workouts. The bamboo fibers create a silky-soft feel against the skin while providing excellent breathability.' } }; quickViewButtons.forEach(button => { button.addEventListener('click', (e) => { e.preventDefault(); const productId = button.dataset.id; const product = productData[productId]; // Update modal content document.getElementById('modalProductImg').src = product.image; document.getElementById('modalTitle').textContent = product.title; document.getElementById('modalPrice').textContent = product.price; document.getElementById('modalDesc').textContent = product.desc; // Show modal with animation modal.classList.add('active'); document.body.style.overflow = 'hidden'; // Prevent scrolling }); }); closeModal.addEventListener('click', () => { modal.classList.remove('active'); document.body.style.overflow = ''; // Re-enable scrolling }); // Close modal when clicking outside content modal.addEventListener('click', (e) => { if (e.target === modal) { modal.classList.remove('active'); document.body.style.overflow = ''; } }); // Color options in modal const colorOptions = document.querySelectorAll('.color-option'); colorOptions.forEach(option => { option.addEventListener('click', () => { colorOptions.forEach(opt => opt.classList.remove('selected')); option.classList.add('selected'); }); }); // Add to cart button interactions const addToCartButtons = document.querySelectorAll('.add-to-cart, .add-cart-btn'); addToCartButtons.forEach(button => { button.addEventListener('click', (e) => { e.preventDefault(); // Add animation feedback button.innerHTML = '✓ Added'; button.style.background = '#3da87e'; // Reset after a delay setTimeout(() => { if (button.classList.contains('add-to-cart')) { button.innerHTML = 'Add to Cart'; button.style.background = ''; } else { button.innerHTML = 'Add to Cart'; button.style.background = ''; } }, 1
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Hidden Gems of Southeast Asia</title> <style> /* Base Styles */ * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Montserrat', sans-serif; } body { overflow-x: hidden; background-color: #0a0a0a; color: #fff; height: 100%; width: 100%; } .container { width: 100%; height: 100vh; overflow-y: auto; overflow-x: hidden; perspective: 1px; scroll-behavior: smooth; } /* Typography */ h1 { font-size: 3rem; font-weight: 800; letter-spacing: 1px; margin-bottom: 1rem; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); } h2 { font-size: 2rem; font-weight: 600; margin-bottom: 0.5rem; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); } p { font-size: 1rem; line-height: 1.6; margin-bottom: 1rem; max-width: 600px; } /* Navigation */ .nav { position: fixed; top: 0; width: 100%; padding: 1rem; display: flex; justify-content: space-between; align-items: center; z-index: 1000; transition: background-color 0.3s ease; } .nav.scrolled { background-color: rgba(0, 0, 0, 0.8); backdrop-filter: blur(10px); } .logo { font-size: 1.5rem; font-weight: 700; color: #fff; text-decoration: none; display: flex; align-items: center; } .logo svg { margin-right: 8px; fill: #fff; } .nav-links { display: flex; gap: 1.5rem; } .nav-link { color: #fff; text-decoration: none; position: relative; font-weight: 500; transition: color 0.3s; } .nav-link:after { content: ''; position: absolute; width: 0; height: 2px; bottom: -4px; left: 0; background: linear-gradient(90deg, #ff7e5f, #feb47b); transition: width 0.3s ease; } .nav-link:hover { color: #feb47b; } .nav-link:hover:after { width: 100%; } /* Hero Section */ .hero { position: relative; height: 100vh; display: flex; align-items: center; justify-content: center; transform-style: preserve-3d; z-index: -1; } .hero-bg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-image: url('https://images.unsplash.com/photo-1528127269322-539801943592'); background-size: cover; background-position: center; transform: translateZ(-1px) scale(2); z-index: -1; } .hero-content { text-align: center; padding: 2rem; position: relative; transform: translateZ(0); z-index: 1; } .hero-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(to bottom, rgba(0,0,0,0.4) 0%, rgba(0,0,0,0.7) 100%); z-index: -1; } .hero-tagline { font-size: 1.2rem; font-weight: 400; margin-bottom: 2rem; opacity: 0; transform: translateY(20px); animation: fadeUp 1s forwards 0.5s; } .cta-button { display: inline-block; padding: 1rem 2rem; background: linear-gradient(90deg, #ff7e5f, #feb47b); color: white; text-decoration: none; border-radius: 50px; font-weight: 600; transition: transform 0.3s, box-shadow 0.3s; box-shadow: 0 4px 15px rgba(255, 126, 95, 0.4); opacity: 0; transform: translateY(20px); animation: fadeUp 1s forwards 0.8s; } .cta-button:hover { transform: translateY(-5px); box-shadow: 0 10px 20px rgba(255, 126, 95, 0.6); } /* Destinations Section */ .destinations { padding: 4rem 1rem; background-color: #0a0a0a; } .section-header { text-align: center; margin-bottom: 3rem; } .section-title { display: inline-block; font-size: 2.5rem; margin-bottom: 1rem; background: linear-gradient(90deg, #ff7e5f, #feb47b); -webkit-background-clip: text; -webkit-text-fill-color: transparent; position: relative; } .destination-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; max-width: 1200px; margin: 0 auto; } .destination-card { position: relative; height: 400px; border-radius: 16px; overflow: hidden; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); transition: transform 0.5s ease, box-shadow 0.5s ease; cursor: pointer; } .destination-card:hover { transform: translateY(-10px); box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4); } .destination-card:before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(to bottom, rgba(0,0,0,0) 0%, rgba(0,0,0,0.8) 100%); z-index: 1; opacity: 0.7; transition: opacity 0.5s ease; } .destination-card:hover:before { opacity: 0.9; } .destination-image { width: 100%; height: 100%; object-fit: cover; transform: scale(1); transition: transform 2s ease; } .destination-card:hover .destination-image { transform: scale(1.1); } .destination-content { position: absolute; bottom: 0; left: 0; width: 100%; padding: 2rem; z-index: 2; transform: translateY(20px); opacity: 0.8; transition: transform 0.5s ease, opacity 0.5s ease; } .destination-card:hover .destination-content { transform: translateY(0); opacity: 1; } .destination-title { font-size: 1.8rem; margin-bottom: 0.5rem; position: relative; } .destination-title:after { content: ''; position: absolute; bottom: -8px; left: 0; width: 50px; height: 3px; background: linear-gradient(90deg, #ff7e5f, #feb47b); transition: width 0.5s ease; } .destination-card:hover .destination-title:after { width: 80px; } .destination-desc { font-size: 0.9rem; margin-bottom: 1rem; max-width: 100%; } .location-tag { display: inline-flex; align-items: center; padding: 0.4rem 0.8rem; background-color: rgba(255, 255, 255, 0.1); border-radius: 50px; font-size: 0.8rem; margin-right: 0.5rem; backdrop-filter: blur(5px); } .location-tag svg { margin-right: 5px; fill: #ff7e5f; } /* Interactive Map */ .map-section { padding: 4rem 1rem; background-color: #0f0f0f; } .map-container { position: relative; width: 100%; height: 400px; max-width: 1200px; margin: 0 auto; overflow: hidden; border-radius: 16px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); } .map-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(10, 10, 10, 0.4); display: flex; align-items: center; justify-content: center; z-index: 2; } .map-cta { padding: 1rem 2rem; background: linear-gradient(90deg, #ff7e5f, #feb47b); color: white; border: none; border-radius: 50px; font-weight: 600; cursor: pointer; transition: transform 0.3s, box-shadow 0.3s; box-shadow: 0 4px 15px rgba(255, 126, 95, 0.4); } .map-cta:hover { transform: translateY(-5px); box-shadow: 0 10px 20px rgba(255, 126, 95, 0.6); } .map-placeholder { width: 100%; height: 100%; background-image: url('https://images.unsplash.com/photo-1524661135-423995f22d0b'); background-size: cover; background-position: center; filter: blur(2px); } #map { width: 100%; height: 100%; opacity: 0; transition: opacity 1s ease; } .location-marker { position: absolute; width: 20px; height: 20px; background-color: #ff7e5f; border-radius: 50%; transform: translate(-50%, -50%); z-index: 3; cursor: pointer; box-shadow: 0 0 0 rgba(255, 126, 95, 0.4); animation: pulse 2s infinite; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(255, 126, 95, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(255, 126, 95, 0); } 100% { box-shadow: 0 0 0 0 rgba(255, 126, 95, 0); } } .location-marker:after { content: ''; position: absolute; top: 100%; left: 50%; transform: translateX(-50%); width: 0; height: 0; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 7px solid #ff7e5f; } .location-info { position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); width: 200px; padding: 0.8rem; background-color: rgba(15, 15, 15, 0.9); color: white; border-radius: 8px; font-size: 0.8rem; opacity: 0; pointer-events: none; transition: opacity 0.3s ease, transform 0.3s ease; transform: translateY(10px) translateX(-50%); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); z-index: 4; } .location-marker:hover .location-info { opacity: 1; transform: translateY(0) translateX(-50%); } /* Footer */ .footer { padding: 2rem 1rem; background-color: #0a0a0a; text-align: center; } .footer-links { display: flex; justify-content: center; gap: 1.5rem; margin-bottom: 1rem; } .footer-link { color: #fff; text-decoration: none; transition: color 0.3s; } .footer-link:hover { color: #ff7e5f; } .social-links { display: flex; justify-content: center; gap: 1rem; margin-bottom: 1rem; } .social-link { display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; background-color: rgba(255, 255, 255, 0.1); border-radius: 50%; transition: background-color 0.3s; } .social-link:hover { background-color: rgba(255, 126, 95, 0.8); } .social-link svg { width: 20px; height: 20px; fill: white; } .copyright { font-size: 0.8rem; color: rgba(255, 255, 255, 0.6); } /* Modal */ .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.8); display: flex; align-items: center; justify-content: center; z-index: 1000; opacity: 0; pointer-events: none; transition: opacity 0.3s ease; } .modal.active { opacity: 1; pointer-events: auto; } .modal-content { position: relative; width: 90%; max-width: 900px; background-color: #0f0f0f; border-radius: 16px; padding: 2rem; max-height: 80vh; overflow-y: auto; } .modal-close { position: absolute; top: 1rem; right: 1rem; background: none; border: none; color: white; font-size: 1.5rem; cursor: pointer; transition: color 0.3s; } .modal-close:hover { color: #ff7e5f; } .modal-image { width: 100%; height: 300px; object-fit: cover; border-radius: 8px; margin-bottom: 1.5rem; } .modal-title { font-size: 2rem; margin-bottom: 1rem; } .modal-desc { margin-bottom: 1.5rem; line-height: 1.8; } .modal-facts { margin-bottom: 1.5rem; } .fact-item { display: flex; align-items: flex-start; margin-bottom: 0.8rem; } .fact-icon { margin-right: 10px; font-size: 1.2rem; color: #ff7e5f; } /* Animations */ @keyframes fadeUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } /* Responsive */ @media (max-width: 768px) { h1 { font-size: 2.5rem; } h2 { font-size: 1.8rem; } .nav-links { display: none; } .destination-grid { grid-template-columns: 1fr; } .destination-card { height: 350px; } .modal-content { padding: 1.5rem; } .modal-image { height: 200px; } } @media (max-width: 480px) { h1 { font-size: 2rem; } .hero-tagline { font-size: 1rem; } .section-title { font-size: 2rem; } .destination-card { height: 300px; } } </style> </head> <body> <div class="container"> <nav class="nav"> <a href="#" class="logo"> <svg width="24" height="24" viewBox="0 0 24 24"> <path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/> </svg> HiddenAsia </a> <div class="nav-links"> <a href="#destinations" class="nav-link">Destinations</a> <a href="#map-section" class="nav-link">Map</a> <a href="#" class="nav-link">Stories</a> <a href="#" class="nav-link">Travel Tips</a> </div> </nav> <section class="hero"> <div class="hero-bg"></div> <div class="hero-overlay"></div> <div class="hero-content"> <h1>Discover Southeast Asia's Hidden Gems</h1> <p class="hero-tagline">Venture beyond the tourist trails and immerse yourself in authentic cultural experiences</p> <a href="#destinations" class="cta-button">Begin Your Journey</a> </div> </section> <section id="destinations" class="destinations"> <div class="section-header"> <h2 class="section-title">Secret Destinations</h2> <p>Escape the crowds and discover these lesser-known but equally breathtaking locations</p> </div> <div class="destination-grid"> <div class="destination-card" data-id="bagan"> <img src="https://images.unsplash.com/photo-1514282401047-d79a71a590e8" alt="Bagan, Myanmar" class="destination-image"> <div class="destination-content"> <h3 class="destination-title">Bagan, Myanmar</h3> <p class="destination-desc">Ancient temples pepper the landscape where sunrise balloon rides reveal the true majesty of this historical wonder.</p> <div class="location-tags"> <span class="location-tag"> <svg width="12" height="12" viewBox="0 0 24 24"> <path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/> </svg> Mandalay Region </span> </div> </div> </div> <div class="destination-card" data-id="phong-nha"> <img src="https://images.unsplash.com/photo-1540244838170-e5e64790d160" alt="Phong Nha, Vietnam" class="destination-image"> <div class="destination-content"> <h3 class="destination-title">Phong Nha, Vietnam</h3> <p class="destination-desc">Home to the world's largest cave systems, this natural wonder offers jungle trekking, underground rivers, and pristine forests.</p> <div class="location-tags"> <span class="location-tag"> <svg width="12" height="12" viewBox="0 0 24 24"> <path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/> </svg> Quảng Bình Province </span> </div> </div> </div> <div class="destination-card" data-id="koh-rong"> <img src="https://images.unsplash.com/photo-1517783999520-f068d7431a60" alt="Koh Rong, Cambodia" class="destination-image"> <div class="destination-content"> <h3 class="destination-title">Koh Rong, Cambodia</h3> <p class="destination-desc">Unspoiled white sand beaches, bioluminescent waters, and rustic island life far from the crowds of Thailand's islands.</p> <div class="location-tags"> <span class="location-tag"> <svg width="12" height="12" viewBox="0 0 24 24"> <path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/> </svg> Sihanoukville Province </span> </div> </div> </div> </div> </section> <section id="map-section" class="map-section"> <div class="section-header"> <h2 class="section-title">Explore the Region</h2> <p>Navigate our interactive map to discover the locations of Southeast Asia's best-kept secrets</p> </div> <div class="map-container"> <div class="map-placeholder"></div> <div id="map"></div> <div class="map-overlay"> <button class="map-cta" id="load-map">Explore Map</button> </div> <!-- Location markers positioned absolutely --> <div class="location-marker" style="top: 30%; left: 35%;"> <div class="location-info"> <strong>Bagan, Myanmar</strong> <p>Ancient temple complex dating back to the 9th century</p> </div> </div> <div class="location-marker" style="top: 60%; left: 55%;"> <div class="location-info"> <strong>Phong Nha, Vietnam</strong> <p>Underground river systems and massive caves</p> </div> </div> <div class="location-marker" style="top: 70%; left: 40%;"> <div class="location-info"> <strong>Koh Rong, Cambodia</strong> <p>Pristine beaches and bioluminescent waters</p> </div> </div> </div> </section> <footer class="footer"> <div class="footer-links"> <a href="#" class="footer-link">About</a> <a href="#" class="footer-link">Contact</a> <a href="#" class="footer-link">Privacy</a> <a href="#" class="footer-link">Terms</a> </div> <div class="social-links"> <a href="#" class="social-link"> <svg viewBox="0 0 24 24"> <path d="M12 2.04C6.5 2.04 2 6.53 2 12.06C2 17.06 5.66 21.21 10.44 21.96V14.96H7.9V12.06H10.44V9.85C10.44 7.34 11.93 5.96 14.22 5.96C15.31 5.96 16.45 6.15 16.45 6.15V8.62H15.19C13.95 8.62 13.56 9.39 13.56 10.18V12.06H16.34L15.89 14.96H13.56V21.96A10 10 0 0 0 22 12.06C22 6.53 17.5 2.04 12 2.04Z" /> </svg> </a> <a href="#" class="social-link"> <svg viewBox="0 0 24 24"> <path d="M22.46,6C21.69,6.35 20.86,6.58 20,6.69C20.88,6.16 21.56,5.32 21.88,4.31C21.05,4.81 20.13,5.16 19.16,5.36C18.37,4.5 17.26,4 16,4C13.65,4 11.73,5.92 11.73,8.29C11.73,8.63 11.77,8.96 11.84,9.27C8.28,9.09 5.11,7.38 3,4.79C2.63,5.42 2.42,6.16 2.42,6.94C2.42,8.43 3.17,9.75 4.33,10.5C3.62,10.5 2.96,10.3 2.38,10C2.38,10 2.38,10 2.38,10.03C2.38,12.11 3.86,13.85 5.82,14.24C5.46,14.34 5.08,14.39 4.69,14.39C4.42,14.39 4.15,14.36 3.89,14.31C4.43,16 6,17.26 7.89,17.29C6.43,18.45 4.58,19.13 2.56,19.13C2.22,19.13 1.88,19.11 1.54,19.07C3.44,20.29 5.7,21 8.12,21C16,21 20.33,14.46 20.33,8.79C20.33,8.6 20.33,8.42 20.32,8.23C21.16,7.63 21.88,6.87 22.46,6Z" /> </svg> </a> <a href="#" class="social-link"> <svg viewBox="0 0 24 24"> <path d="M7.8,2H16.2C19.4,2 22,4.6 22,7.8V16.2A5.8,5.8 0 0,1 16.2,22H7.8C4.6,22 2,19.4 2,16.2V7.8A5.8,5.8 0 0,1 7.8,2M7.6,4A3.6,3.6 0 0,0 4,7.6V16.4C4,18.39 5.61,20 7.6,20H16.4A3.6,3.6 0 0,0 20,16.4V7.6C20,5.61 18.39,4 16.4,4H7.6M17.25,5.5A1.25,1.25 0 0,1 18.5,6.75A1.25,1.25 0 0,1 17.25,8A1.25,1.25 0 0,1 16,6.75A1.25,1.25 0 0,1 17.25,5.5M12,7A5,5 0 0,1 17,12A5,5 0 0,1 12,17A5,5 0 0,1 7,12A5,5 0 0,1 12,7M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9Z" /> </svg> </a> </div> <p class="copyright">© 2023 HiddenAsia. All rights reserved.</p> </footer> <!-- Modal --> <div class="modal" id="destination-modal"> <div class="modal-content"> <button class="modal-close">×</button> <img src="" alt="" class="modal-image"> <h2 class="modal-title"></h2> <p class="modal-desc"></p> <div class="modal-facts"> <h3>Quick Facts</h3> <div class="fact-item"> <span class="fact-icon">🌍</span> <span class="fact-text"></span> </div> <div class="fact-item"> <span class="fact-icon">🕰️</span> <span class="fact-text"></span> </div> <div class="fact-item"> <span class="fact-icon">🔍</span> <span class="fact-text"></span> </div> </div> </div> </div> </div> <script> // Destination data const destinations = { "bagan": { title: "Bagan, Myanmar", image: "https://images.unsplash.com/photo-1514282401047-d79a71a590e8", description: "Bagan is an ancient city in central Myanmar that was the capital of the Pagan Kingdom from the 9th to the 13th centuries. During this time, over 10,000 Buddhist temples, pagodas, and monasteries were built on the Bagan plains. Today, there are still more than 2,200 temples and pagodas standing.<br><br>The best way to experience Bagan is at sunrise, when hot air balloons float above the misty plain dotted with thousands of ancient stupas. Or rent an e-bike to explore the lesser-visited temples away from the main areas, where you might find yourself completely alone in a 1,000-year-old structure.", facts: [ "Located in Mandalay Region, Myanmar, approximately 290 km southwest of Mandalay city", "Best visited between November and February when temperatures are cooler and skies are clear", "Temple architecture varies widely, from massive structures like Ananda Temple to smaller, more intimate shrines" ] }, "phong-nha": { title: "Phong Nha, Vietnam", image: "https://images.unsplash.com/photo-1540244838170-e5e64790d160", description: "Phong Nha-Ke Bang National Park is home to the oldest karst mountains in Asia, formed approximately 400 million years ago. Its cave systems are truly spectacular, including Son Doong, the world's largest cave, which is so massive it contains its own river, jungle, and climate.<br><br>While Son Doong requires advanced booking and costs thousands of dollars to explore, there are many other accessible options. Paradise Cave stretches for 31 km underground with breathtaking formations, while Phong Nha Cave can be explored by boat along an underground river. The area also offers jungle trekking, rural homestays, and swimming in the crystal-clear Chay River.", facts: [ "Located in the Quảng Bình Province of North-Central Vietnam, about 500 km south of Hanoi", "The caves were largely unknown to the outside world until the 1990s, with some major discoveries made as recently as 2009", "The national park is also home to over 100 types of mammals, including endangered langurs and the rare saola (Asian unicorn)" ] }, "koh-rong": { title: "Koh Rong, Cambodia", image: "https://images.unsplash.com/photo-1517783999520-f068d7431a60", description: "While Cambodia is famous for Angkor Wat, its islands remain relatively undiscovered. Koh Rong is the second-largest island in Cambodia, featuring 43 km of beach coastline. Its pristine white sand beaches rival any in Thailand, but with a fraction of the development and crowds.<br><br>The island's most magical feature appears after dark - swim in the sea at night to witness bioluminescent plankton that light up like blue stars with every movement. During the day, hike through the island's interior jungle, snorkel around coral reefs, or simply relax on secluded beaches like Long Set (4K) Beach or Coconut Beach where development remains minimal and electricity still runs on generators in many areas.", facts: [ "Located in the Gulf of Thailand, 25 km off the coast from Sihanoukville", "Despite growing development, the island has no roads, ATMs are scarce, and many areas have limited electricity", "Marine life is abundant, with opportunities to see seahorses, parrotfish, blue spotted rays, and occasionally phosphorescent plankton at night" ] } }; // Modal functionality const modal = document.getElementById('destination-modal'); const destinationCards = document.querySelectorAll('.destination-card'); const modalClose = document.querySelector('.modal-close'); destinationCards.forEach(card => { card.addEventListener('click', () => { const destination = destinations[card.dataset.id]; if (destination) { document.querySelector('.modal-image').src = destination.image; document.querySelector('.modal-image').alt = destination.title; document.querySelector('.modal-title').textContent = destination.title; document.querySelector('.modal-desc').innerHTML = destination.description; const factTexts = document.querySelectorAll('.fact-text'); destination.facts.forEach((fact, i) => { if (factTexts[i]) { factTexts[i].textContent = fact; } }); modal.classList.add('active'); document.body.style.overflow = 'hidden'; } }); }); modalClose.addEventListener('click', () => { modal.classList.remove('active'); document.body.style.overflow = ''; }); // Close modal when clicking outside content modal.addEventListener('click', (e) => { if (e.target === modal) { modal.classList.remove('active'); document.body.style.overflow = ''; } }); // Map functionality const mapCta = document.getElementById('load-map'); const mapOverlay = document.querySelector('.map-overlay'); mapCta.addEventListener('click', () => { // In a real scenario, this would load a proper map API mapOverlay.style.opacity =
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Interactive Mood Board Gallery</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } :root { --primary: #6366f1; --primary-light: #818cf8; --dark: #1f2937; --light: #f9fafb; --gray: #e5e7eb; --gray-dark: #6b7280; --success: #10b981; --warning: #f59e0b; --accent: #ec4899; --accent-light: #f9a8d4; } body { background-color: var(--light); color: var(--dark); height: 100%; overflow: hidden; user-select: none; position: relative; } .app-container { width: 100%; height: 700px; max-width: 700px; margin: 0 auto; display: flex; flex-direction: column; overflow: hidden; position: relative; background-color: #fff; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); border-radius: 12px; } .header { display: flex; justify-content: space-between; align-items: center; padding: 1rem; border-bottom: 1px solid var(--gray); background: #fff; z-index: 10; } .header h1 { font-size: 1.25rem; font-weight: 600; color: var(--dark); margin: 0; } .controls { display: flex; gap: 0.5rem; } .control-btn { background: none; border: none; cursor: pointer; border-radius: 6px; padding: 0.5rem; display: flex; align-items: center; justify-content: center; transition: all 0.2s ease; color: var(--gray-dark); } .control-btn:hover { background-color: var(--gray); color: var(--dark); } .control-btn i { font-size: 1.25rem; } .sidebar { position: absolute; right: -280px; top: 0; bottom: 0; width: 280px; background: #fff; box-shadow: -2px 0 15px rgba(0, 0, 0, 0.1); z-index: 20; transition: right 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55); padding: 1rem; display: flex; flex-direction: column; overflow-y: auto; } .sidebar.open { right: 0; } .sidebar-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; } .sidebar-header h2 { font-size: 1rem; font-weight: 600; } .close-sidebar { background: none; border: none; cursor: pointer; font-size: 1.25rem; color: var(--gray-dark); } .sidebar-content { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.5rem; margin-bottom: 1rem; } .asset-item { border-radius: 6px; overflow: hidden; cursor: grab; position: relative; transition: transform 0.2s ease; } .asset-item:hover { transform: scale(1.05); } .asset-item img { width: 100%; height: 100%; object-fit: cover; display: block; } .asset-categories { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1rem; } .category-pill { padding: 0.25rem 0.75rem; border-radius: 20px; font-size: 0.75rem; cursor: pointer; transition: all 0.2s ease; background-color: var(--gray); color: var(--gray-dark); } .category-pill:hover, .category-pill.active { background-color: var(--primary); color: white; } .board-container { position: relative; flex: 1; overflow: hidden; background-color: #f5f5f5; background-image: linear-gradient(45deg, #ececec 25%, transparent 25%), linear-gradient(-45deg, #ececec 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #ececec 75%), linear-gradient(-45deg, transparent 75%, #ececec 75%); background-size: 20px 20px; background-position: 0 0, 0 10px, 10px -10px, -10px 0px; } .board { position: absolute; width: 100%; height: 100%; overflow: auto; padding: 1.5rem; } .mood-item { position: absolute; cursor: grab; user-select: none; z-index: 1; transition: box-shadow 0.2s ease, transform 0.2s ease; border-radius: 6px; overflow: hidden; background-color: #fff; } .mood-item.grabbing { cursor: grabbing; z-index: 10; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2); transform: scale(1.02); } .mood-item img { width: 100%; height: 100%; object-fit: cover; pointer-events: none; } .mood-item .controls { position: absolute; bottom: 0; left: 0; right: 0; background: rgba(0, 0, 0, 0.5); padding: 0.5rem; display: flex; justify-content: flex-end; opacity: 0; transition: opacity 0.2s ease; } .mood-item:hover .controls { opacity: 1; } .item-control { background: rgba(255, 255, 255, 0.3); border: none; border-radius: 4px; color: white; width: 28px; height: 28px; margin-left: 0.25rem; cursor: pointer; transition: all 0.2s ease; display: flex; align-items: center; justify-content: center; } .item-control:hover { background: rgba(255, 255, 255, 0.5); } .tooltip { position: absolute; background: var(--dark); color: white; padding: 0.5rem 0.75rem; border-radius: 4px; font-size: 0.75rem; z-index: 100; opacity: 0; transition: opacity 0.2s ease; pointer-events: none; } .tooltip.visible { opacity: 1; } .actions { display: flex; position: absolute; bottom: 1rem; right: 1rem; gap: 0.5rem; z-index: 5; } .action-btn { padding: 0.5rem 1rem; border-radius: 6px; font-weight: 500; font-size: 0.875rem; cursor: pointer; transition: all 0.2s ease; display: flex; align-items: center; gap: 0.5rem; border: none; } .btn-primary { background-color: var(--primary); color: white; box-shadow: 0 2px 5px rgba(99, 102, 241, 0.3); } .btn-primary:hover { background-color: var(--primary-light); transform: translateY(-2px); box-shadow: 0 4px 8px rgba(99, 102, 241, 0.4); } .btn-ghost { background-color: transparent; color: var(--gray-dark); box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); border: 1px solid var(--gray); } .btn-ghost:hover { background-color: var(--gray); color: var(--dark); transform: translateY(-2px); } .notification { position: absolute; bottom: -60px; left: 50%; transform: translateX(-50%); background: var(--dark); color: white; padding: 0.75rem 1.25rem; border-radius: 6px; font-size: 0.875rem; transition: all 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); z-index: 50; } .notification.show { bottom: 20px; } @media (max-width: 600px) { .header h1 { font-size: 1rem; } .board { padding: 1rem; } .action-btn { padding: 0.4rem 0.8rem; font-size: 0.8rem; } } /* Overlay for when sidebar is open */ .overlay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.3); z-index: 15; opacity: 0; visibility: hidden; transition: opacity 0.3s ease; } .overlay.active { opacity: 1; visibility: visible; } /* Additional animations */ @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } .pulse { animation: pulse 2s infinite; } .add-notice { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; color: var(--gray-dark); padding: 1rem; border-radius: 8px; background: rgba(255, 255, 255, 0.7); transition: opacity 0.3s ease; } .add-notice.hidden { opacity: 0; } .dropzone-indicator { position: absolute; border: 2px dashed var(--primary); background: rgba(99, 102, 241, 0.1); border-radius: 6px; z-index: 0; display: none; } .dropzone-indicator.active { display: block; } /* Loading spinner for saved effect */ .spinner { width: 18px; height: 18px; border: 2px solid rgba(255, 255, 255, 0.3); border-radius: 50%; border-top-color: #fff; animation: spin 0.8s linear infinite; display: inline-block; } @keyframes spin { to { transform: rotate(360deg); } } /* For Font Awesome alternative */ .icon { display: inline-block; width: 1em; height: 1em; stroke-width: 0; stroke: currentColor; fill: currentColor; } </style> </head> <body> <div class="app-container"> <div class="header"> <h1>Patchwork Inspiration Board</h1> <div class="controls"> <button class="control-btn" id="undo-btn" title="Undo"> <svg class="icon" viewBox="0 0 24 24"> <path d="M12.5,8C9.85,8 7.45,9 5.6,10.6L2,7V16H11L7.38,12.38C8.77,11.22 10.54,10.5 12.5,10.5C16.04,10.5 19.05,12.81 20.1,16L22.47,15.22C21.08,11.03 17.15,8 12.5,8Z"></path> </svg> </button> <button class="control-btn" id="redo-btn" title="Redo"> <svg class="icon" viewBox="0 0 24 24"> <path d="M18.4,10.6C16.55,9 14.15,8 11.5,8C6.85,8 2.92,11.03 1.54,15.22L3.9,16C4.95,12.81 7.95,10.5 11.5,10.5C13.45,10.5 15.23,11.22 16.62,12.38L13,16H22V7L18.4,10.6Z"></path> </svg> </button> <button class="control-btn" id="zoom-in-btn" title="Zoom In"> <svg class="icon" viewBox="0 0 24 24"> <path d="M15.5,14L20.5,19L19,20.5L14,15.5V14.71L13.73,14.43C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.43,13.73L14.71,14H15.5M9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14M12,10H10V12H9V10H7V9H9V7H10V9H12V10Z"></path> </svg> </button> <button class="control-btn" id="zoom-out-btn" title="Zoom Out"> <svg class="icon" viewBox="0 0 24 24"> <path d="M15.5,14H14.71L14.43,13.73C15.41,12.59 16,11.11 16,9.5A6.5,6.5 0 0,0 9.5,3A6.5,6.5 0 0,0 3,9.5A6.5,6.5 0 0,0 9.5,16C11.11,16 12.59,15.41 13.73,14.43L14,14.71V15.5L19,20.5L20.5,19L15.5,14M9.5,14C7,14 5,12 5,9.5C5,7 7,5 9.5,5C12,5 14,7 14,9.5C14,12 12,14 9.5,14M7,9H12V10H7V9Z"></path> </svg> </button> <button class="control-btn" id="open-assets-btn" title="Asset Library"> <svg class="icon" viewBox="0 0 24 24"> <path d="M19,20H4C2.89,20 2,19.1 2,18V6C2,4.89 2.89,4 4,4H10L12,6H19A2,2 0 0,1 21,8H21L4,8V18L6.14,10H23.21L20.93,18.5C20.7,19.37 19.92,20 19,20Z"></path> </svg> </button> </div> </div> <div class="board-container"> <div class="board" id="mood-board"> <div class="add-notice" id="add-notice"> <p>Drag images from the Asset Library to start creating</p> <p>Click the folder icon in the top right to open assets</p> </div> </div> <div class="dropzone-indicator" id="dropzone"></div> </div> <div class="sidebar" id="sidebar"> <div class="sidebar-header"> <h2>Asset Library</h2> <button class="close-sidebar" id="close-sidebar"> <svg class="icon" viewBox="0 0 24 24"> <path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"></path> </svg> </button> </div> <div class="asset-categories"> <div class="category-pill active" data-category="all">All</div> <div class="category-pill" data-category="texture">Textures</div> <div class="category-pill" data-category="color">Colors</div> <div class="category-pill" data-category="pattern">Patterns</div> <div class="category-pill" data-category="photo">Photos</div> </div> <div class="sidebar-content" id="assets"> <!-- Assets will be dynamically loaded here --> </div> </div> <div class="overlay" id="overlay"></div> <div class="actions"> <button class="action-btn btn-ghost" id="clear-btn"> <svg class="icon" viewBox="0 0 24 24" style="width: 16px; height: 16px;"> <path d="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z"></path> </svg> Clear </button> <button class="action-btn btn-primary" id="save-btn"> <svg class="icon" viewBox="0 0 24 24" style="width: 16px; height: 16px;"> <path d="M15,9H5V5H15M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M17,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3Z"></path> </svg> Save Board </button> </div> <div class="notification" id="notification">Your mood board has been saved!</div> <div class="tooltip" id="tooltip"></div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Initialize variables const board = document.getElementById('mood-board'); const sidebar = document.getElementById('sidebar'); const overlay = document.getElementById('overlay'); const openAssetsBtn = document.getElementById('open-assets-btn'); const closeSidebarBtn = document.getElementById('close-sidebar'); const assetsContainer = document.getElementById('assets'); const notification = document.getElementById('notification'); const saveBtn = document.getElementById('save-btn'); const clearBtn = document.getElementById('clear-btn'); const tooltipEl = document.getElementById('tooltip'); const addNotice = document.getElementById('add-notice'); const categoryPills = document.querySelectorAll('.category-pill'); const dropzoneIndicator = document.getElementById('dropzone'); const undoBtn = document.getElementById('undo-btn'); const redoBtn = document.getElementById('redo-btn'); const zoomInBtn = document.getElementById('zoom-in-btn'); const zoomOutBtn = document.getElementById('zoom-out-btn'); let activeItem = null; let initialX = 0; let initialY = 0; let xOffset = 0; let yOffset = 0; let scale = 1; let historyStack = []; let historyIndex = -1; let isDragging = false; let currentDropzone = null; // Sample assets data const assets = [ { id: 'asset1', src: 'https://images.unsplash.com/photo-1558244661-d248897f7bc4?w=600&auto=format', type: 'texture', width: 150, height: 150 }, { id: 'asset2', src: 'https://images.unsplash.com/photo-1535376472810-5d229c65da09?w=600&auto=format', type: 'texture', width: 150, height: 200 }, { id: 'asset3', src: 'https://images.unsplash.com/photo-1491895200222-0fc4a4c35e18?w=600&auto=format', type: 'color', width: 200, height: 150 }, { id: 'asset4', src: 'https://images.unsplash.com/photo-1517816428104-797678c7cf0c?w=600&auto=format', type: 'pattern', width: 180, height: 180 }, { id: 'asset5', src: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=600&auto=format', type: 'photo', width: 180, height: 240 }, { id: 'asset6', src: 'https://images.unsplash.com/photo-1533038590840-1cde6e668a91?w=600&auto=format', type: 'photo', width: 240, height: 180 }, { id: 'asset7', src: 'https://images.unsplash.com/photo-1506259091721-347e791bab0f?w=600&auto=format', type: 'color', width: 160, height: 160 }, { id: 'asset8', src: 'https://images.unsplash.com/photo-1525909002-1b05e0c869d8?w=600&auto=format', type: 'pattern', width: 200, height: 150 }, { id: 'asset9', src: 'https://images.unsplash.com/photo-1519751138087-5bf79df62d5b?w=600&auto=format', type: 'texture', width: 180, height: 180 }, { id: 'asset10', src: 'https://images.unsplash.com/photo-1520052205864-92d242b3a76b?w=600&auto=format', type: 'photo', width: 240, height: 160 }, ]; // Initial state of the board let items = []; // Load assets function loadAssets(filter = 'all') { assetsContainer.innerHTML = ''; const filteredAssets = filter === 'all' ? assets : assets.filter(asset => asset.type === filter); filteredAssets.forEach(asset => { const assetEl = document.createElement('div'); assetEl.classList.add('asset-item'); assetEl.setAttribute('draggable', 'true'); assetEl.innerHTML = `<img src="${asset.src}" alt="Asset" data-id="${asset.id}" data-width="${asset.width}" data-height="${asset.height}">`; assetEl.addEventListener('dragstart', handleAssetDragStart); assetContainer.appendChild(assetEl); }); } // Initialize assets loadAssets(); // Event listeners for category filters categoryPills.forEach(pill => { pill.addEventListener('click', () => { categoryPills.forEach(p => p.classList.remove('active')); pill.classList.add('active'); loadAssets(pill.dataset.category); }); }); // Handle drag start for assets function handleAssetDragStart(e) { const img = e.target.querySelector('img') || e.target; const assetId = img.dataset.id; const asset = assets.find(a => a.id === assetId); if (!asset) return; e.dataTransfer.setData('text/plain', JSON.stringify({ id: assetId, src: asset.src, width: img.dataset.width, height: img.dataset.height })); // Create a custom drag image const dragIcon = img.cloneNode(true); dragIcon.style.width = '100px'; dragIcon.style.height = 'auto'; dragIcon.style.opacity = '0.7'; document.body.appendChild(dragIcon); e.dataTransfer.setDragImage(dragIcon, 50, 50); // Remove the clone after drag starts setTimeout(() => { document.body.removeChild(dragIcon); }, 0); } // Setup drag and drop for the board board.addEventListener('dragover', (e) => { e.preventDefault(); showDropzoneIndicator(e.clientX, e.clientY); }); board.addEventListener('dragleave', () => { hideDropzoneIndicator(); }); board.addEventListener('drop', handleDrop); function showDropzoneIndicator(x, y) { const rect = board.getBoundingClientRect(); const boardX = x - rect.left; const boardY = y - rect.top; dropzoneIndicator.style.left = (boardX - 100) + 'px'; dropzoneIndicator.style.top = (boardY - 75) + 'px'; dropzoneIndicator.style.width = '200px'; dropzoneIndicator.style.height = '150px'; dropzoneIndicator.classList.add('active'); } function hideDropzoneIndicator() { dropzoneIndicator.classList.remove('active'); } function handleDrop(e) { e.preventDefault(); hideDropzoneIndicator(); try { const data = JSON.parse(e.dataTransfer.getData('text/plain')); if (!data.id || !data.src) return; const rect = board.getBoundingClientRect(); const x = e.clientX - rect.left - (data.width / 2); const y = e.clientY - rect.top - (data.height / 2); addItemToBoard(data.id, data.src, x, y, parseInt(data.width), parseInt(data.height)); } catch (err) { console.error("Error processing drop:", err); } } function addItemToBoard(id, src, x, y, width, height) { // Hide the add notice when items are added if (items.length === 0) { addNotice.classList.add('hidden'); } const uid = 'item_' + Date.now() + '_' + Math.floor(Math.random() * 1000); const itemEl = document.createElement('div'); itemEl.classList.add('mood-item'); itemEl.setAttribute('data-id', uid); itemEl.style.width = width + 'px'; itemEl.style.height = height + 'px'; itemEl.style.left = x + 'px'; itemEl.style.top = y + 'px'; itemEl.innerHTML = ` <img src="${src}" alt="Mood item"> <div class="controls"> <button class="item-control rotate-btn" title="Rotate"> <svg class="icon" viewBox="0 0 24 24"> <path d="M12,5V1L7,6L12,11V7A6,6 0 0,1 18,13A6,6 0 0,1 12,19A6,6 0 0,1 6,13H4A8,8 0 0,0 12,21A8,8 0 0,0 20,13A8,8 0 0,0 12,5Z"></path> </svg> </button> <button class="item-control resize-btn" title="Resize"> <svg class="icon" viewBox="0 0 24 24"> <path d="M10,21V19H6.41L10.91,14.5L9.5,13.09L5,17.59V14H3V21H10M14.5,10.91L19,6.41V10H21V3H14V5H17.59L13.09,9.5L14.5,10.91Z"></path> </svg> </button> <button class="item-control delete-btn" title="Delete"> <svg class="icon" viewBox="0 0 24 24"> <path d="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z"></path> </svg> </button> </div> `; board.appendChild(itemEl); // Save item to internal state items.push({ id: uid, src, x, y, width, height, rotation: 0 }); // Save state to history saveToHistory(); // Setup event listeners for this item setupItemEvents(itemEl); // Add animation for new items itemEl.style.transform = 'scale(0.8)'; itemEl.style.opacity = '0'; setTimeout(() => { itemEl.style.transform = 'scale(1)'; itemEl.style.opacity = '1'; itemEl.style.transition = 'transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0.3s ease'; }, 10); } function setupItemEvents(itemEl) { // Mouse down event for dragging itemEl.addEventListener('mousedown', dragStart); // Button event listeners const deleteBtn = itemEl.querySelector('.delete-btn'); const rotateBtn = itemEl.querySelector('.rotate-btn'); const resizeBtn = itemEl.querySelector('.resize-btn'); deleteBtn.addEventListener('click', (e) => { e.stopPropagation(); deleteItem(itemEl.dataset.id); }); rotateBtn.addEventListener('click', (e) => { e.stopPropagation(); rotateItem(itemEl.dataset.id); }); resizeBtn.addEventListener('click', (e) => { e.stopPropagation(); toggleResizeMode(itemEl.dataset.id); }); // Double click to bring to front itemEl.addEventListener('dblclick', () => { bringToFront(itemEl); }); } function dragStart(e) { if (e.target.classList.contains('item-control')) return; const item = e.target.closest('.mood-item'); if (!item) return; e.preventDefault(); activeItem = item; activeItem.classList.add('grabbing'); const transform = getComputedStyle(activeItem).transform; const matrix = new DOMMatrix(transform); const rotation = Math.atan2(matrix.b, matrix.a) * (180 / Math.PI); initialX = e.clientX; initialY = e.clientY; const rect = activeItem.getBoundingClientRect(); xOffset = rect.left + rect.width / 2 - initialX; yOffset = rect.top + rect.height / 2 - initialY; // Set up move and end event listeners document.addEventListener('mousemove', drag); document.addEventListener('mouseup', dragEnd); // Bring active item to front bringToFront(activeItem); } function drag(e) { if (!activeItem) return; e.preventDefault(); const boardRect = board.getBoundingClientRect(); const x = e.clientX - boardRect.left + xOffset; const y = e.clientY - boardRect.top + yOffset; // Update position with rotation preserved const item = items.find(i => i.id === activeItem.dataset.id); if (item) { item.x = x - (item.width / 2); item.y = y - (item.height / 2); updateItemPosition(activeItem, item); } } function dragEnd() { if (!activeItem) return; // Save state to history saveToHistory(); activeItem.classList.remove('grabbing'); activeItem = null; document.removeEventListener('mousemove', drag); document.removeEventListener('mouseup', dragEnd); } function updateItemPosition(itemEl, itemData) { itemEl.style.left = itemData.x + 'px'; itemEl.style.top = itemData.y + 'px'; itemEl.style.transform = `rotate(${itemData.rotation}deg)`; } function bringToFront(itemEl) { // Get all items and find max z-index const allItems = document.querySelectorAll('.mood-item'); let maxZ = 0; allItems.forEach(item => { const z = parseInt(getComputedStyle(item).zIndex) || 1; maxZ = Math.max(maxZ, z); }); // Set this item's z-index higher itemEl.style.zIndex = (maxZ + 1).toString(); } function deleteItem(id) { const itemIndex = items.findIndex(item => item.id === id); if (itemIndex === -1) return; // Remove from DOM const itemEl = document.querySelector(`.mood-item[data-id="${id}"]`); // Animate removal itemEl.style.transition = 'transform 0.3s ease, opacity 0.3s ease'; itemEl.style.transform = 'scale(0.8) rotate(10deg)'; itemEl.style.opacity = '0'; setTimeout(() => { if (itemEl && itemEl.parentNode) { itemEl.parentNode.removeChild(itemEl); } // Remove from state items.splice(itemIndex, 1); // Save state to history saveToHistory(); // Show add notice if no items left if (items.length === 0) { addNotice.classList.remove('hidden'); } }, 300); } function rotateItem(id) { const item = items.find(item => item.id === id); if (!item) return; // Rotate by 15 degrees item.rotation = (item.rotation + 15) % 360; // Update DOM const itemEl = document.querySelector(`.mood-item[data-id="${id}"]`); itemEl.style.transform = `rotate(${item.rotation}deg)`; // Save state to history saveToHistory(); } function toggleResizeMode(id) { const item = items.find(item => item.id === id); if (!item) return; // Increase size by 20% item.width = Math.round(item.width * 1.2); item.height = Math.round(item.height * 1.2); // Update DOM const itemEl = document.querySelector(`.mood-item[data-id="${id}"]`); itemEl.style.width = item.width + 'px'; itemEl.style.height = item.height + 'px'; // Save state to history saveToHistory(); } // Sidebar open/close openAssetsBtn.addEventListener('click', () => { sidebar.classList.add('open'); overlay
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>TechVision 2024 Showcase</title> <style> :root { --primary: #2962ff; --primary-light: #768fff; --primary-dark: #0039cb; --secondary: #ff3d00; --secondary-light: #ff7539; --secondary-dark: #c30000; --dark: #212121; --light: #f5f5f5; --gray: #9e9e9e; --success: #00c853; --warning: #ffd600; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', 'Segoe UI', sans-serif; } body { background-color: var(--light); color: var(--dark); overflow-x: hidden; max-width: 700px; max-height: 700px; overflow-y: auto; scrollbar-width: thin; } body::-webkit-scrollbar { width: 5px; } body::-webkit-scrollbar-track { background: var(--light); } body::-webkit-scrollbar-thumb { background-color: var(--gray); border-radius: 6px; } .container { max-width: 700px; margin: 0 auto; padding: 20px; } header { text-align: center; margin-bottom: 30px; position: relative; } .header-content { position: relative; z-index: 2; } .bg-pattern { position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0.05; z-index: 1; background-image: radial-gradient(var(--primary) 2px, transparent 2px); background-size: 30px 30px; } h1 { font-size: 2.5rem; margin-bottom: 10px; background: linear-gradient(90deg, var(--primary), var(--secondary)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; display: inline-block; } .tagline { font-size: 1.1rem; color: var(--gray); margin-bottom: 20px; } .filter-tabs { display: flex; justify-content: center; gap: 15px; margin-bottom: 30px; flex-wrap: wrap; } .filter-btn { background: none; border: none; padding: 8px 15px; font-size: 0.9rem; cursor: pointer; border-radius: 20px; transition: all 0.3s ease; position: relative; color: var(--dark); } .filter-btn::after { content: ''; position: absolute; bottom: 0; left: 50%; transform: translateX(-50%); width: 0; height: 2px; background: var(--primary); transition: width 0.3s ease; } .filter-btn:hover::after, .filter-btn.active::after { width: 80%; } .filter-btn.active { color: var(--primary); font-weight: 600; } .product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 25px; margin-bottom: 30px; } .product-card { background: white; border-radius: 15px; overflow: hidden; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05); transition: transform 0.3s ease, box-shadow 0.3s ease; position: relative; height: 280px; display: flex; flex-direction: column; } .product-card:hover { transform: translateY(-10px); box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1); } .product-image { height: 150px; overflow: hidden; position: relative; } .product-image img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s ease; } .product-card:hover .product-image img { transform: scale(1.1); } .product-badge { position: absolute; top: 10px; right: 10px; background: var(--primary); color: white; font-size: 0.7rem; padding: 4px 8px; border-radius: 10px; font-weight: 600; z-index: 10; } .new-release .product-badge { background: var(--secondary); } .exclusive .product-badge { background: var(--success); } .limited .product-badge { background: var(--warning); color: var(--dark); } .product-info { padding: 15px; display: flex; flex-direction: column; flex-grow: 1; position: relative; z-index: 1; } .product-name { font-weight: 700; margin-bottom: 5px; font-size: 1rem; } .product-category { font-size: 0.8rem; color: var(--gray); margin-bottom: 10px; } .product-price { margin-top: auto; font-weight: 700; color: var(--primary); display: flex; justify-content: space-between; align-items: center; } .cta-btn { background-color: var(--light); border: none; color: var(--dark); width: 36px; height: 36px; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.3s ease; } .cta-btn:hover { background-color: var(--primary); color: white; } .cta-btn i { font-size: 1.2rem; } .product-specs { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(255, 255, 255, 0.95); padding: 20px; display: flex; flex-direction: column; opacity: 0; transform: translateY(10px); pointer-events: none; transition: all 0.3s ease; z-index: 5; } .product-card:hover .product-specs { opacity: 1; transform: translateY(0); pointer-events: auto; } .spec-title { font-weight: 700; margin-bottom: 15px; color: var(--primary); font-size: 1rem; } .spec-list { list-style: none; margin-bottom: 15px; } .spec-item { display: flex; margin-bottom: 8px; font-size: 0.85rem; line-height: 1.4; } .spec-item-icon { color: var(--primary); margin-right: 8px; flex-shrink: 0; } .spec-actions { margin-top: auto; display: flex; justify-content: space-between; } .spec-btn { padding: 8px 15px; border: none; border-radius: 5px; font-size: 0.85rem; cursor: pointer; transition: all 0.2s ease; font-weight: 600; } .view-btn { background-color: var(--primary); color: white; } .view-btn:hover { background-color: var(--primary-dark); } .compare-btn { background-color: var(--light); color: var(--dark); } .compare-btn:hover { background-color: var(--gray); color: white; } footer { text-align: center; margin-top: 30px; padding-top: 20px; border-top: 1px solid #e0e0e0; color: var(--gray); font-size: 0.8rem; } .tooltip { position: absolute; background: var(--dark); color: white; padding: 5px 10px; border-radius: 5px; font-size: 0.8rem; pointer-events: none; opacity: 0; transition: opacity 0.2s; z-index: 100; width: max-content; max-width: 200px; } @media (max-width: 600px) { .product-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 15px; } h1 { font-size: 2rem; } .product-card { height: 250px; } .product-image { height: 120px; } } @media (max-width: 400px) { .product-grid { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); } .container { padding: 15px 10px; } h1 { font-size: 1.8rem; } } /* Special features and animations */ .animate-pulse { animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } .loader { display: none; justify-content: center; align-items: center; height: 100px; } .dot { width: 10px; height: 10px; background: var(--primary); border-radius: 50%; margin: 0 5px; animation: dot-animation 1.4s infinite ease-in-out both; } .dot:nth-child(1) { animation-delay: -0.32s; } .dot:nth-child(2) { animation-delay: -0.16s; } @keyframes dot-animation { 0%, 80%, 100% { transform: scale(0); } 40% { transform: scale(1); } } /* Animation for new items */ .new-item { animation: highlight 1.5s ease-out; } @keyframes highlight { from { box-shadow: 0 0 0 3px var(--secondary); } to { box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05); } } /* Custom iconography */ .icon { width: 16px; height: 16px; display: inline-block; position: relative; } .icon svg { width: 100%; height: 100%; } </style> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> </head> <body> <div class="container"> <header> <div class="bg-pattern"></div> <div class="header-content"> <h1>TechVision 2024</h1> <p class="tagline">Experience tomorrow's technology today with our flagship products</p> </div> </header> <div class="filter-tabs"> <button class="filter-btn active" data-filter="all">All Products</button> <button class="filter-btn" data-filter="smartphones">Smartphones</button> <button class="filter-btn" data-filter="wearables">Wearables</button> <button class="filter-btn" data-filter="audio">Audio</button> <button class="filter-btn" data-filter="computing">Computing</button> </div> <div class="product-grid"> <!-- Smartphones --> <div class="product-card new-release" data-category="smartphones"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1592899677977-9c10ca588bbd?ixlib=rb-4.0.3&auto=format&fit=crop&w=500&q=80" alt="NeoPhone X1"> <div class="product-badge">NEW</div> </div> <div class="product-info"> <h3 class="product-name">NeoPhone X1</h3> <p class="product-category">Smartphone</p> <div class="product-price"> <span>$899</span> <button class="cta-btn" aria-label="View details"><i class="fas fa-info"></i></button> </div> </div> <div class="product-specs"> <h4 class="spec-title">NeoPhone X1</h4> <ul class="spec-list"> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-microchip"></i></span> <span>5nm Quantum Processor, 12GB RAM</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-camera"></i></span> <span>50MP main camera with AI enhancement</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-battery-full"></i></span> <span>5000mAh battery, 65W fast charging</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-mobile-alt"></i></span> <span>6.7" AMOLED 120Hz display</span> </li> </ul> <div class="spec-actions"> <button class="spec-btn view-btn" aria-label="View product">View Details</button> <button class="spec-btn compare-btn" aria-label="Add to compare">Compare</button> </div> </div> </div> <div class="product-card" data-category="smartphones"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1598327105666-5b89351aff97?ixlib=rb-4.0.3&auto=format&fit=crop&w=500&q=80" alt="Flux Pro"> </div> <div class="product-info"> <h3 class="product-name">Flux Pro</h3> <p class="product-category">Smartphone</p> <div class="product-price"> <span>$699</span> <button class="cta-btn" aria-label="View details"><i class="fas fa-info"></i></button> </div> </div> <div class="product-specs"> <h4 class="spec-title">Flux Pro</h4> <ul class="spec-list"> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-microchip"></i></span> <span>6nm Octa-core processor, 8GB RAM</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-camera"></i></span> <span>48MP triple camera system</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-battery-full"></i></span> <span>4500mAh battery, 45W charging</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-mobile-alt"></i></span> <span>6.4" 90Hz OLED display</span> </li> </ul> <div class="spec-actions"> <button class="spec-btn view-btn" aria-label="View product">View Details</button> <button class="spec-btn compare-btn" aria-label="Add to compare">Compare</button> </div> </div> </div> <!-- Wearables --> <div class="product-card exclusive" data-category="wearables"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1579586337278-3befd40fd17a?ixlib=rb-4.0.3&auto=format&fit=crop&w=500&q=80" alt="QuantumWatch Series 5"> <div class="product-badge">EXCLUSIVE</div> </div> <div class="product-info"> <h3 class="product-name">QuantumWatch S5</h3> <p class="product-category">Smartwatch</p> <div class="product-price"> <span>$349</span> <button class="cta-btn" aria-label="View details"><i class="fas fa-info"></i></button> </div> </div> <div class="product-specs"> <h4 class="spec-title">QuantumWatch Series 5</h4> <ul class="spec-list"> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-heart"></i></span> <span>Advanced ECG & blood oxygen monitoring</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-battery-full"></i></span> <span>7-day battery life, magnetic charging</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-tint"></i></span> <span>5ATM water resistance, titanium case</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-running"></i></span> <span>30+ sport modes with AI coaching</span> </li> </ul> <div class="spec-actions"> <button class="spec-btn view-btn" aria-label="View product">View Details</button> <button class="spec-btn compare-btn" aria-label="Add to compare">Compare</button> </div> </div> </div> <div class="product-card" data-category="wearables"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1575311373937-040b8e1fd6b0?ixlib=rb-4.0.3&auto=format&fit=crop&w=500&q=80" alt="FitBand Ultra"> </div> <div class="product-info"> <h3 class="product-name">FitBand Ultra</h3> <p class="product-category">Fitness Tracker</p> <div class="product-price"> <span>$129</span> <button class="cta-btn" aria-label="View details"><i class="fas fa-info"></i></button> </div> </div> <div class="product-specs"> <h4 class="spec-title">FitBand Ultra</h4> <ul class="spec-list"> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-heart"></i></span> <span>24/7 heart rate & sleep tracking</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-battery-full"></i></span> <span>14-day battery life on single charge</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-swimming-pool"></i></span> <span>50m water resistance, swim tracking</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-bell"></i></span> <span>Smart notifications & stress monitoring</span> </li> </ul> <div class="spec-actions"> <button class="spec-btn view-btn" aria-label="View product">View Details</button> <button class="spec-btn compare-btn" aria-label="Add to compare">Compare</button> </div> </div> </div> <!-- Audio --> <div class="product-card limited" data-category="audio"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1545127398-14699f92334b?ixlib=rb-4.0.3&auto=format&fit=crop&w=500&q=80" alt="SonicPods Pro"> <div class="product-badge">LIMITED</div> </div> <div class="product-info"> <h3 class="product-name">SonicPods Pro</h3> <p class="product-category">Wireless Earbuds</p> <div class="product-price"> <span>$199</span> <button class="cta-btn" aria-label="View details"><i class="fas fa-info"></i></button> </div> </div> <div class="product-specs"> <h4 class="spec-title">SonicPods Pro</h4> <ul class="spec-list"> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-volume-up"></i></span> <span>Adaptive sound EQ with spatial audio</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-wind"></i></span> <span>Active noise cancellation & transparency</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-battery-full"></i></span> <span>8hr playback, 24hr with case</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-tint"></i></span> <span>IPX7 sweat & water resistant</span> </li> </ul> <div class="spec-actions"> <button class="spec-btn view-btn" aria-label="View product">View Details</button> <button class="spec-btn compare-btn" aria-label="Add to compare">Compare</button> </div> </div> </div> <div class="product-card" data-category="audio"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1505740420928-5e560c06d30e?ixlib=rb-4.0.3&auto=format&fit=crop&w=500&q=80" alt="AudioSphere X2"> </div> <div class="product-info"> <h3 class="product-name">AudioSphere X2</h3> <p class="product-category">Headphones</p> <div class="product-price"> <span>$249</span> <button class="cta-btn" aria-label="View details"><i class="fas fa-info"></i></button> </div> </div> <div class="product-specs"> <h4 class="spec-title">AudioSphere X2</h4> <ul class="spec-list"> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-volume-up"></i></span> <span>40mm custom drivers with Hi-Res certification</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-wind"></i></span> <span>Adaptive ANC with ambient awareness</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-battery-full"></i></span> <span>30hr battery life, fast charge (5hr in 10min)</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-wifi"></i></span> <span>Dual device connection, touch controls</span> </li> </ul> <div class="spec-actions"> <button class="spec-btn view-btn" aria-label="View product">View Details</button> <button class="spec-btn compare-btn" aria-label="Add to compare">Compare</button> </div> </div> </div> <!-- Computing --> <div class="product-card new-release" data-category="computing"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1611186871348-b1ce696e52c9?ixlib=rb-4.0.3&auto=format&fit=crop&w=500&q=80" alt="UltraBook Slim"> <div class="product-badge">NEW</div> </div> <div class="product-info"> <h3 class="product-name">UltraBook Slim</h3> <p class="product-category">Laptop</p> <div class="product-price"> <span>$1,299</span> <button class="cta-btn" aria-label="View details"><i class="fas fa-info"></i></button> </div> </div> <div class="product-specs"> <h4 class="spec-title">UltraBook Slim</h4> <ul class="spec-list"> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-microchip"></i></span> <span>12th Gen Core i7, 16GB DDR5 RAM</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-hdd"></i></span> <span>1TB NVMe SSD, PCIe 4.0</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-desktop"></i></span> <span>14" 2.8K OLED, 90Hz, 400 nits</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-battery-full"></i></span> <span>18hr battery, 65W USB-C charging</span> </li> </ul> <div class="spec-actions"> <button class="spec-btn view-btn" aria-label="View product">View Details</button> <button class="spec-btn compare-btn" aria-label="Add to compare">Compare</button> </div> </div> </div> <div class="product-card" data-category="computing"> <div class="product-image"> <img src="https://images.unsplash.com/photo-1527443224154-c4a3942d3acf?ixlib=rb-4.0.3&auto=format&fit=crop&w=500&q=80" alt="CreatorTab Pro"> </div> <div class="product-info"> <h3 class="product-name">CreatorTab Pro</h3> <p class="product-category">Tablet</p> <div class="product-price"> <span>$749</span> <button class="cta-btn" aria-label="View details"><i class="fas fa-info"></i></button> </div> </div> <div class="product-specs"> <h4 class="spec-title">CreatorTab Pro</h4> <ul class="spec-list"> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-microchip"></i></span> <span>Octa-core processor, 8GB RAM</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-pencil-alt"></i></span> <span>Pressure-sensitive stylus included</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-desktop"></i></span> <span>12.4" 2800x1752 AMOLED, 120Hz</span> </li> <li class="spec-item"> <span class="spec-item-icon"><i class="fas fa-camera"></i></span> <span>13MP rear + 8MP front camera</span> </li> </ul> <div class="spec-actions"> <button class="spec-btn view-btn" aria-label="View product">View Details</button> <button class="spec-btn compare-btn" aria-label="Add to compare">Compare</button> </div> </div> </div> </div> <div class="loader"> <div class="dot"></div> <div class="dot"></div> <div class="dot"></div> </div> <footer> <p>TechVision 2024 Showcase — Experience the Next Generation of Innovation</p> </footer> </div> <div class="tooltip" id="tooltip"></div> <script> document.addEventListener('DOMContentLoaded', function() { const filterButtons = document.querySelectorAll('.filter-btn'); const productCards = document.querySelectorAll('.product-card'); const tooltip = document.getElementById('tooltip'); const loader = document.querySelector('.loader'); // Filter functionality filterButtons.forEach(button => { button.addEventListener('click', () => { // Remove active class from all buttons filterButtons.forEach(btn => btn.classList.remove('active')); // Add active class to clicked button button.classList.add('active'); // Show loader document.querySelector('.product-grid').style.display = 'none'; loader.style.display = 'flex'; // Get filter value const filter = button.getAttribute('data-filter'); // Delay to show loading effect setTimeout(() => { // Hide loader and show grid loader.style.display = 'none'; document.querySelector('.product-grid').style.display = 'grid'; // Filter products productCards.forEach(card => { if (filter === 'all' || card.getAttribute('data-category') === filter) { card.style.display = 'flex'; } else { card.style.display = 'none'; } }); }, 500); }); }); // Tooltip functionality for buttons document.querySelectorAll('.cta-btn, .spec-btn').forEach(btn => { btn.addEventListener('mouseenter', (e) => { const rect = e.target.getBoundingClientRect(); tooltip.style.top = `${rect.bottom + 5}px`; tooltip.style.left = `${rect.left + rect.width / 2}px`; tooltip.textContent = e.target.getAttribute('aria-label'); tooltip.style.opacity = '1'; }); btn.addEventListener('mouseleave', () => { tooltip.style.opacity = '0'; }); }); // Add event listener for action buttons to prevent form submission document.querySelectorAll('.view-btn, .compare-btn').forEach(btn => { btn.addEventListener('click', (e) => { e.preventDefault(); // Show feedback const rect = e.target.getBoundingClientRect(); tooltip.style.top = `${rect.bottom + 5}px`; tooltip.style.left = `${rect.left + rect.width / 2}px`; if (e.target.classList.contains('view-btn')) { tooltip.textContent = 'Details view coming soon!'; } else { tooltip.textContent = 'Added to compare list!'; } tooltip.style.opacity = '1'; setTimeout(() => { tooltip.style.opacity = '0'; }, 1500); }); }); // Make badge for limited items pulse document.querySelectorAll('.limited .product-badge').forEach(badge => { badge.classList.add('animate-pulse'); }); // Responsive hover effect for touch devices document.querySelectorAll('.product-card').forEach(card => { card.addEventListener('touchstart', function() { // Remove hover effect from all cards first document.querySelectorAll('.product-card').forEach(c => { c.classList.remove('touch-hover'); }); // Add hover effect to this card this.classList.add('touch-hover'); }); }); // Handle window resize for proper positioning window.addEventListener('resize', () => { tooltip.style.opacity = '0'; }); // Simulate new items arriving periodically (for demo purposes) setTimeout(() => { document.querySelectorAll('.product-card').forEach((card, index) => { if (index % 3 === 0) { card.classList.add('new-item'); setTimeout(() => { card.classList.remove('new-item'); }, 1500); } }); }, 3000); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Earthtones - Nature Photography Gallery</title> <style> @import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@300;400;500;600&family=Montserrat:wght@300;400;500&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; } :root { --moss-green: #8A9A5B; --earth-brown: #9C7A54; --sand-beige: #F2E8C6; --forest-green: #3A5F0B; --dusk-purple: #6C5B7B; --dawn-orange: #F8B195; --night-blue: #0F2C59; --water-blue: #5D8CAE; --easing: cubic-bezier(0.25, 0.1, 0.25, 1); } body { font-family: 'Montserrat', sans-serif; background-color: #FAF7F2; color: #333; overflow-x: hidden; height: 100vh; display: flex; flex-direction: column; } h1, h2, h3, h4, h5 { font-family: 'Cormorant Garamond', serif; font-weight: 500; } .container { max-width: 700px; width: 100%; height: 100%; margin: 0 auto; padding: 0; display: flex; flex-direction: column; overflow: hidden; } header { display: flex; justify-content: space-between; align-items: center; padding: 1.2rem; background-color: transparent; position: relative; z-index: 10; } .logo { display: flex; align-items: center; } .logo-icon { position: relative; width: 32px; height: 32px; margin-right: 10px; } .logo-circle { position: absolute; border-radius: 50%; opacity: 0.8; } .circle1 { width: 32px; height: 32px; background-color: var(--moss-green); z-index: 1; } .circle2 { width: 24px; height: 24px; background-color: var(--earth-brown); top: 4px; left: 4px; z-index: 2; } .circle3 { width: 16px; height: 16px; background-color: var(--sand-beige); top: 8px; left: 8px; z-index: 3; } .logo-text { font-size: 1.5rem; letter-spacing: 1px; background: linear-gradient(to right, var(--moss-green), var(--forest-green)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; font-weight: 600; } nav { position: relative; } .menu-toggle { background: none; border: none; cursor: pointer; display: flex; flex-direction: column; height: 20px; justify-content: space-between; width: 25px; z-index: 15; } .menu-toggle span { background-color: var(--forest-green); border-radius: 3px; height: 2px; transition: all 0.3s var(--easing); width: 100%; } .menu-toggle.active span:nth-child(1) { transform: translateY(9px) rotate(45deg); } .menu-toggle.active span:nth-child(2) { opacity: 0; } .menu-toggle.active span:nth-child(3) { transform: translateY(-9px) rotate(-45deg); } .menu { background-color: rgba(250, 247, 242, 0.96); border-radius: 12px; box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1); height: 0; opacity: 0; overflow: hidden; padding: 0; position: absolute; right: 0; top: 40px; transition: all 0.3s var(--easing); width: 180px; visibility: hidden; z-index: 10; } .menu.active { height: auto; opacity: 1; padding: 15px; visibility: visible; } .menu li { list-style: none; opacity: 0; transform: translateY(10px); transition: all 0.3s var(--easing); } .menu.active li { opacity: 1; transform: translateY(0); transition-delay: calc(0.1s * var(--i)); } .menu a { color: #444; display: block; font-size: 0.95rem; padding: 8px 5px; text-decoration: none; transition: color 0.2s var(--easing); } .menu a:hover { color: var(--moss-green); } .filter-tabs { display: flex; margin: 0.8rem 1.2rem; gap: 10px; overflow-x: auto; scrollbar-width: none; } .filter-tabs::-webkit-scrollbar { display: none; } .tab { border: none; border-radius: 20px; padding: 6px 16px; font-size: 0.85rem; background-color: #f0ebe3; color: #666; cursor: pointer; white-space: nowrap; transition: all 0.3s var(--easing); } .tab:hover { background-color: #e7e1d5; } .tab.active { background-color: var(--moss-green); color: white; } .tab[data-category="forests"] { border-bottom: 2px solid var(--forest-green); } .tab[data-category="deserts"] { border-bottom: 2px solid var(--earth-brown); } .tab[data-category="oceans"] { border-bottom: 2px solid var(--water-blue); } .tab[data-category="mountains"] { border-bottom: 2px solid #8B4513; } .tab[data-category="dusk"] { border-bottom: 2px solid var(--dusk-purple); } .tab[data-category="dawn"] { border-bottom: 2px solid var(--dawn-orange); } .tab[data-category="night"] { border-bottom: 2px solid var(--night-blue); } main { flex: 1; overflow-y: auto; padding: 0 1.2rem 1.2rem; scrollbar-width: thin; scrollbar-color: #ccc #f5f5f5; } main::-webkit-scrollbar { width: 6px; } main::-webkit-scrollbar-track { background: #f5f5f5; border-radius: 3px; } main::-webkit-scrollbar-thumb { background: #ccc; border-radius: 3px; } .gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 15px; margin-top: 10px; } .photo-item { position: relative; border-radius: 16px; overflow: hidden; aspect-ratio: 1 / 1; cursor: pointer; transform: translateY(30px); opacity: 0; box-shadow: 0 5px 15px rgba(0,0,0,0.07); transition: all 0.5s var(--easing); } .photo-item.visible { transform: translateY(0); opacity: 1; } .photo-item img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s var(--easing); } .photo-item:hover img { transform: scale(1.05); } .photo-overlay { position: absolute; bottom: 0; left: 0; right: 0; padding: 15px 10px; background: linear-gradient(transparent, rgba(0,0,0,0.7)); color: white; opacity: 0; transform: translateY(20px); transition: all 0.3s var(--easing); } .photo-item:hover .photo-overlay { opacity: 1; transform: translateY(0); } .photo-title { font-size: 0.95rem; margin-bottom: 4px; font-weight: 500; } .photo-info { font-size: 0.75rem; opacity: 0.8; display: flex; justify-content: space-between; margin-top: 4px; } .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.9); display: flex; justify-content: center; align-items: center; z-index: 100; opacity: 0; visibility: hidden; transition: all 0.3s var(--easing); } .modal.active { opacity: 1; visibility: visible; } .modal-content { position: relative; max-width: 90%; max-height: 80%; transition: all 0.3s var(--easing); transform: scale(0.9); opacity: 0; } .modal.active .modal-content { opacity: 1; transform: scale(1); } .modal-image { max-width: 100%; max-height: 100%; border-radius: 4px; box-shadow: 0 5px 25px rgba(0,0,0,0.2); } .modal-close { position: absolute; top: -30px; right: 0; background: none; border: none; color: white; font-size: 24px; cursor: pointer; } .modal-info { position: absolute; bottom: -60px; left: 0; width: 100%; color: white; } .modal-title { font-size: 1.2rem; margin-bottom: 5px; } .modal-description { font-size: 0.9rem; opacity: 0.8; } .empty-state { display: none; flex-direction: column; align-items: center; justify-content: center; text-align: center; height: 300px; opacity: 0; transform: translateY(20px); transition: all 0.3s var(--easing); } .empty-state.visible { display: flex; opacity: 1; transform: translateY(0); } .empty-state-icon { font-size: 3rem; margin-bottom: 15px; color: #ccc; } .empty-state-text { font-size: 1.1rem; margin-bottom: 10px; color: #777; } .empty-state-subtext { font-size: 0.9rem; color: #999; max-width: 300px; } .intro-card { background: linear-gradient(135deg, var(--sand-beige), #FAF7F2); border-radius: 16px; padding: 20px; margin-bottom: 20px; box-shadow: 0 5px 15px rgba(0,0,0,0.05); opacity: 0; transform: translateY(20px); transition: all 0.5s var(--easing); } .intro-card.visible { opacity: 1; transform: translateY(0); } .intro-card h2 { color: var(--forest-green); margin-bottom: 10px; font-size: 1.4rem; } .intro-card p { font-size: 0.9rem; line-height: 1.5; margin-bottom: 15px; } .featured-image { position: relative; border-radius: 12px; overflow: hidden; height: 180px; margin-top: 15px; } .featured-image img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s var(--easing); } .featured-image:hover img { transform: scale(1.05); } .intro-card-stats { display: flex; justify-content: space-between; margin-top: 15px; font-size: 0.8rem; color: #777; } .intro-stat { display: flex; align-items: center; } .intro-stat i { margin-right: 5px; font-size: 1rem; } /* Decorative leaf shapes */ .leaf { position: fixed; z-index: -1; opacity: 0.06; pointer-events: none; } .leaf-1 { top: 10%; left: 5%; width: 150px; height: 150px; border-radius: 50% 0 50% 50%; background-color: var(--moss-green); transform: rotate(45deg); } .leaf-2 { bottom: 10%; right: 5%; width: 180px; height: 180px; border-radius: 50% 50% 0 50%; background-color: var(--forest-green); transform: rotate(-60deg); } .leaf-3 { bottom: 30%; left: 15%; width: 120px; height: 120px; border-radius: 50% 50% 50% 0; background-color: var(--earth-brown); transform: rotate(30deg); } /* For smaller screens */ @media (max-width: 500px) { .gallery { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 10px; } .intro-card h2 { font-size: 1.2rem; } .featured-image { height: 140px; } .menu { width: 150px; } } /* Animations */ @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } .hidden { display: none !important; } </style> </head> <body> <div class="leaf leaf-1"></div> <div class="leaf leaf-2"></div> <div class="leaf leaf-3"></div> <div class="container"> <header> <div class="logo"> <div class="logo-icon"> <div class="logo-circle circle1"></div> <div class="logo-circle circle2"></div> <div class="logo-circle circle3"></div> </div> <div class="logo-text">Earthtones</div> </div> <nav> <button class="menu-toggle"> <span></span> <span></span> <span></span> </button> <ul class="menu"> <li style="--i:1;"><a href="#">Home</a></li> <li style="--i:2;"><a href="#">Featured Artists</a></li> <li style="--i:3;"><a href="#">Submit Photos</a></li> <li style="--i:4;"><a href="#">About Us</a></li> <li style="--i:5;"><a href="#">Contact</a></li> </ul> </nav> </header> <div class="filter-tabs"> <button class="tab active" data-category="all">All</button> <button class="tab" data-category="forests">Forests</button> <button class="tab" data-category="deserts">Deserts</button> <button class="tab" data-category="oceans">Oceans</button> <button class="tab" data-category="mountains">Mountains</button> <button class="tab" data-category="dawn">Dawn</button> <button class="tab" data-category="dusk">Dusk</button> <button class="tab" data-category="night">Night</button> </div> <main> <div class="intro-card"> <h2>The Poetry of Wilderness</h2> <p>Discover the untamed beauty of Earth's most pristine landscapes through the lenses of renowned photographers who've braved the elements to capture extraordinary moments of natural harmony.</p> <div class="featured-image"> <img src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1574&q=80" alt="Featured landscape"> </div> <div class="intro-card-stats"> <div class="intro-stat"> <i>🌿</i> 217 photographs </div> <div class="intro-stat"> <i>📸</i> 42 photographers </div> <div class="intro-stat"> <i>🌎</i> 28 countries </div> </div> </div> <div class="gallery"> <!-- Each photo item has data-category attributes for filtering --> <div class="photo-item" data-category="forests"> <img src="https://images.unsplash.com/photo-1448375240586-882707db888b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1500&q=80" alt="Redwood Forest"> <div class="photo-overlay"> <div class="photo-title">Ancient Redwoods</div> <div class="photo-info"> <span>Oregon, USA</span> <span>Elena Karpova</span> </div> </div> </div> <div class="photo-item" data-category="mountains dusk"> <img src="https://images.unsplash.com/photo-1519681393784-d120267933ba?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1500&q=80" alt="Mountain Twilight"> <div class="photo-overlay"> <div class="photo-title">Alpine Twilight</div> <div class="photo-info"> <span>Swiss Alps</span> <span>Thomas Riel</span> </div> </div> </div> <div class="photo-item" data-category="deserts"> <img src="https://images.unsplash.com/photo-1682686581854-5e71f58e7e3f?ixlib=rb-4.0.3&ixid=M3wxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1500&q=80" alt="Desert Dunes"> <div class="photo-overlay"> <div class="photo-title">Saharan Waves</div> <div class="photo-info"> <span>Morocco</span> <span>Aisha El-Mansour</span> </div> </div> </div> <div class="photo-item" data-category="oceans dawn"> <img src="https://images.unsplash.com/photo-1505118380757-91f5f5632de0?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1626&q=80" alt="Ocean Sunrise"> <div class="photo-overlay"> <div class="photo-title">Pacific Awakening</div> <div class="photo-info"> <span>Big Sur, CA</span> <span>James Wong</span> </div> </div> </div> <div class="photo-item" data-category="forests night"> <img src="https://images.unsplash.com/photo-1478724141773-c3a0b396d08c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1500&q=80" alt="Mystic Forest"> <div class="photo-overlay"> <div class="photo-title">Moonlit Pines</div> <div class="photo-info"> <span>Bavaria, Germany</span> <span>Klaus Schneider</span> </div> </div> </div> <div class="photo-item" data-category="oceans"> <img src="https://images.unsplash.com/photo-1509316785289-025f5b846b35?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1476&q=80" alt="Ocean Deep"> <div class="photo-overlay"> <div class="photo-title">Cerulean Depths</div> <div class="photo-info"> <span>Great Barrier Reef</span> <span>Sophia Chen</span> </div> </div> </div> <div class="photo-item" data-category="mountains dawn"> <img src="https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1500&q=80" alt="Mountain Dawn"> <div class="photo-overlay"> <div class="photo-title">Himalayan Sunrise</div> <div class="photo-info"> <span>Nepal</span> <span>Raj Patel</span> </div> </div> </div> <div class="photo-item" data-category="deserts dusk"> <img src="https://images.unsplash.com/photo-1604537466608-109fa2f16c3b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1469&q=80" alt="Desert Sunset"> <div class="photo-overlay"> <div class="photo-title">Sonoran Afterglow</div> <div class="photo-info"> <span>Arizona, USA</span> <span>Maria Rodriguez</span> </div> </div> </div> </div> <div class="empty-state"> <div class="empty-state-icon">🌿</div> <div class="empty-state-text">No photographs found</div> <div class="empty-state-subtext">Try selecting a different category or check back later for new additions.</div> </div> </main> </div> <div class="modal"> <div class="modal-content"> <button class="modal-close">×</button> <img class="modal-image" src="" alt=""> <div class="modal-info"> <h3 class="modal-title"></h3> <p class="modal-description"></p> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Menu toggle const menuToggle = document.querySelector('.menu-toggle'); const menu = document.querySelector('.menu'); menuToggle.addEventListener('click', function() { menuToggle.classList.toggle('active'); menu.classList.toggle('active'); }); // Close menu when clicking outside document.addEventListener('click', function(event) { if (!event.target.closest('nav') && menu.classList.contains('active')) { menuToggle.classList.remove('active'); menu.classList.remove('active'); } }); // Initialize elements with animations const introCard = document.querySelector('.intro-card'); introCard.classList.add('visible'); const photoItems = document.querySelectorAll('.photo-item'); // Set initial animations with delays photoItems.forEach((item, index) => { setTimeout(() => { item.classList.add('visible'); }, 100 + (index * 100)); }); // Category filtering const filterTabs = document.querySelectorAll('.tab'); const emptyState = document.querySelector('.empty-state'); filterTabs.forEach(tab => { tab.addEventListener('click', function() { // Remove active class from all tabs filterTabs.forEach(t => t.classList.remove('active')); // Add active class to clicked tab this.classList.add('active'); const category = this.getAttribute('data-category'); // Hide all photos first photoItems.forEach(item => { item.classList.remove('visible'); setTimeout(() => { if (category === 'all' || item.getAttribute('data-category').includes(category)) { item.classList.remove('hidden'); setTimeout(() => { item.classList.add('visible'); }, 50); } else { item.classList.add('hidden'); } }, 300); }); // Show empty state if no photos match the filter setTimeout(() => { const visiblePhotos = document.querySelectorAll('.photo-item:not(.hidden)'); if (visiblePhotos.length === 0) { emptyState.classList.add('visible'); } else { emptyState.classList.remove('visible'); } }, 400); }); }); // Modal functionality const modal = document.querySelector('.modal'); const modalImage = document.querySelector('.modal-image'); const modalTitle = document.querySelector('.modal-title'); const modalDescription = document.querySelector('.modal-description'); const modalClose = document.querySelector('.modal-close'); photoItems.forEach(item => { item.addEventListener('click', function() { const img = this.querySelector('img'); const title = this.querySelector('.photo-title').textContent; const info = this.querySelector('.photo-info').textContent; modalImage.src = img.src; modalTitle.textContent = title; modalDescription.textContent = info; modal.classList.add('active'); document.body.style.overflow = 'hidden'; }); }); modalClose.addEventListener('click', function() { modal.classList.remove('active'); document.body.style.overflow = ''; }); // Close modal when clicking outside the content modal.addEventListener('click', function(event) { if (event.target === modal) { modal.classList.remove('active'); document.body.style.overflow = ''; } }); // Smooth scrolling const main = document.querySelector('main'); let isScrolling = false; main.addEventListener('scroll', function() { if (!isScrolling) { isScrolling = true; // Animate photos as they come into view photoItems.forEach(item => { if (!item.classList.contains('visible') && !item.classList.contains('hidden')) { const rect = item.getBoundingClientRect(); if (rect.top < window.innerHeight) { item.classList.add('visible'); } } }); setTimeout(() => { isScrolling = false; }, 100); } }); // Randomize leaf animations const leaves = document.querySelectorAll('.leaf'); leaves.forEach(leaf => { leaf.style.animation = `pulse ${5 + Math.random() * 5}s infinite`; }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Architectural Design Gallery</title> <style> /* Core styles */ :root { --primary: #e63946; --secondary: #3a86ff; --accent: #ffbe0b; --dark: #212121; --light: #f8f9fa; --grid-line: rgba(33, 33, 33, 0.1); --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } body { background-color: var(--light); color: var(--dark); overflow-x: hidden; position: relative; width: 100%; height: 100vh; } .container { width: 100%; height: 100%; max-width: 700px; max-height: 700px; margin: 0 auto; padding: 1rem; position: relative; overflow: hidden; } /* Grid system */ .grid-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; } .grid-x, .grid-y { position: absolute; background-color: var(--grid-line); } .grid-x { width: 100%; height: 1px; } .grid-y { height: 100%; width: 1px; } /* Header */ header { display: flex; justify-content: space-between; align-items: center; padding: 1.5rem 0; border-bottom: 2px solid var(--dark); margin-bottom: 1.5rem; position: relative; z-index: 2; } .logo { font-size: 1.2rem; font-weight: 700; letter-spacing: -0.5px; display: flex; align-items: center; } .logo-square { width: 12px; height: 12px; background-color: var(--primary); margin-right: 8px; transform: rotate(45deg); transition: var(--transition); } .logo:hover .logo-square { transform: rotate(225deg); } nav { display: flex; gap: 1.5rem; } .nav-link { text-decoration: none; color: var(--dark); font-size: 0.9rem; font-weight: 500; position: relative; padding: 0.2rem 0; transition: var(--transition); } .nav-link:after { content: ''; position: absolute; bottom: 0; left: 0; width: 0; height: 2px; background-color: var(--primary); transition: var(--transition); } .nav-link:hover:after { width: 100%; } .nav-link:hover { color: var(--primary); } /* Main gallery */ .gallery { display: grid; grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(2, 1fr); gap: 1rem; height: calc(100% - 12rem); position: relative; z-index: 2; } .gallery-item { position: relative; overflow: hidden; border: 1px solid var(--grid-line); transition: var(--transition); cursor: pointer; background-color: var(--light); } .gallery-item:hover { transform: translateY(-5px); box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1); } .gallery-item:nth-child(1):before { content: ''; position: absolute; top: 0; left: 0; height: 4px; width: 40%; background-color: var(--primary); } .gallery-item:nth-child(2):before { content: ''; position: absolute; top: 0; right: 0; height: 4px; width: 40%; background-color: var(--secondary); } .gallery-item:nth-child(3):before { content: ''; position: absolute; bottom: 0; left: 0; height: 4px; width: 40%; background-color: var(--accent); } .gallery-item:nth-child(4):before { content: ''; position: absolute; bottom: 0; right: 0; height: 4px; width: 40%; background-color: var(--dark); } .gallery-image { width: 100%; height: 70%; object-fit: cover; filter: grayscale(100%); transition: var(--transition); } .gallery-item:hover .gallery-image { filter: grayscale(0%); } .gallery-info { padding: 0.75rem; height: 30%; display: flex; flex-direction: column; justify-content: space-between; } .gallery-title { font-size: 0.95rem; font-weight: 600; margin-bottom: 0.25rem; } .gallery-meta { display: flex; justify-content: space-between; align-items: center; font-size: 0.75rem; color: #666; } /* Detail view */ .detail-view { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: var(--light); z-index: 10; padding: 2rem; transform: translateY(100%); transition: transform 0.5s cubic-bezier(0.7, 0, 0.3, 1); display: flex; flex-direction: column; } .detail-view.active { transform: translateY(0); } .detail-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; } .detail-title { font-size: 1.5rem; font-weight: 700; } .close-btn { background: none; border: none; cursor: pointer; width: 32px; height: 32px; position: relative; } .close-btn:before, .close-btn:after { content: ''; position: absolute; width: 100%; height: 2px; background-color: var(--dark); top: 50%; left: 0; transition: var(--transition); } .close-btn:before { transform: rotate(45deg); } .close-btn:after { transform: rotate(-45deg); } .close-btn:hover:before, .close-btn:hover:after { background-color: var(--primary); } .blueprint-container { position: relative; flex-grow: 1; background-color: #f0f0f0; overflow: hidden; } .blueprint { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; background-color: #f0f4f8; background-image: linear-gradient(var(--grid-line) 1px, transparent 1px), linear-gradient(90deg, var(--grid-line) 1px, transparent 1px); background-size: 20px 20px; } .blueprint svg { width: 80%; height: 80%; } .hotspot { position: absolute; width: 20px; height: 20px; border-radius: 50%; background-color: var(--primary); transform: translate(-50%, -50%); cursor: pointer; transition: var(--transition); z-index: 2; } .hotspot:hover { transform: translate(-50%, -50%) scale(1.3); } .hotspot-tooltip { position: absolute; background-color: white; padding: 0.75rem; border-radius: 4px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); width: 200px; top: calc(100% + 10px); left: 50%; transform: translateX(-50%); opacity: 0; pointer-events: none; transition: var(--transition); z-index: 3; } .hotspot:hover .hotspot-tooltip { opacity: 1; } .detail-tabs { display: flex; margin-top: 1rem; border-bottom: 1px solid var(--grid-line); } .detail-tab { padding: 0.5rem 1rem; border: none; background: none; font-size: 0.9rem; cursor: pointer; position: relative; transition: var(--transition); } .detail-tab.active:after { content: ''; position: absolute; bottom: -1px; left: 0; width: 100%; height: 2px; background-color: var(--primary); } .detail-tab-content { padding: 1rem 0; } .detail-info { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem; } .detail-info-item { display: flex; flex-direction: column; } .detail-info-label { font-size: 0.75rem; color: #666; margin-bottom: 0.25rem; } .detail-info-value { font-size: 0.9rem; font-weight: 500; } /* Tools and utilities */ .tools { display: flex; align-items: center; justify-content: flex-start; margin-bottom: 1.5rem; gap: 0.5rem; position: relative; z-index: 2; } .tool-btn { padding: 0.5rem; background: none; border: 1px solid var(--grid-line); cursor: pointer; transition: var(--transition); display: flex; align-items: center; justify-content: center; width: 34px; height: 34px; } .tool-btn:hover { border-color: var(--dark); } .tool-btn.active { background-color: var(--dark); color: var(--light); } .tool-btn svg { width: 16px; height: 16px; } .search-tool { flex-grow: 1; position: relative; margin-left: auto; } .search-input { width: 100%; padding: 0.5rem 1rem; border: 1px solid var(--grid-line); background: none; font-size: 0.9rem; transition: var(--transition); } .search-input:focus { outline: none; border-color: var(--dark); } /* Responsive */ @media (max-width: 600px) { .gallery { grid-template-columns: 1fr; grid-template-rows: repeat(4, 1fr); } nav { gap: 1rem; } .detail-info { grid-template-columns: 1fr; } } /* Animation */ @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes slideInUp { from { transform: translateY(10px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } .fadeIn { animation: fadeIn 0.6s ease-out forwards; } .slideInUp { opacity: 0; animation: slideInUp 0.6s ease-out forwards; } .delay-1 { animation-delay: 0.1s; } .delay-2 { animation-delay: 0.2s; } .delay-3 { animation-delay: 0.3s; } .delay-4 { animation-delay: 0.4s; } </style> </head> <body> <div class="container"> <!-- Grid overlay --> <div class="grid-overlay" id="gridOverlay"></div> <!-- Header --> <header class="fadeIn"> <div class="logo"> <div class="logo-square"></div> <span>ARCHIGRID</span> </div> <nav> <a href="#" class="nav-link">PROJECTS</a> <a href="#" class="nav-link">ARCHITECTS</a> <a href="#" class="nav-link">ABOUT</a> </nav> </header> <!-- Tools --> <div class="tools fadeIn delay-1"> <button class="tool-btn active" title="Grid view"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="3" width="7" height="7"></rect> <rect x="14" y="3" width="7" height="7"></rect> <rect x="14" y="14" width="7" height="7"></rect> <rect x="3" y="14" width="7" height="7"></rect> </svg> </button> <button class="tool-btn" title="Toggle grid lines"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect> <line x1="3" y1="9" x2="21" y2="9"></line> <line x1="3" y1="15" x2="21" y2="15"></line> <line x1="9" y1="3" x2="9" y2="21"></line> <line x1="15" y1="3" x2="15" y2="21"></line> </svg> </button> <div class="search-tool"> <input type="text" class="search-input" placeholder="Search projects..."> </div> </div> <!-- Gallery --> <div class="gallery"> <div class="gallery-item slideInUp delay-1"> <img src="https://images.unsplash.com/photo-1487958449943-2429e8be8625?ixlib=rb-1.2.1&auto=format&fit=crop&w=400&h=300&q=80" alt="Cantilever House" class="gallery-image"> <div class="gallery-info"> <h3 class="gallery-title">Cantilever House</h3> <div class="gallery-meta"> <span>Urban Modern</span> <span>2023</span> </div> </div> </div> <div class="gallery-item slideInUp delay-2"> <img src="https://images.unsplash.com/photo-1600607687644-c7f34c52d363?ixlib=rb-1.2.1&auto=format&fit=crop&w=400&h=300&q=80" alt="Skyline Tower" class="gallery-image"> <div class="gallery-info"> <h3 class="gallery-title">Skyline Tower</h3> <div class="gallery-meta"> <span>High-rise</span> <span>2021</span> </div> </div> </div> <div class="gallery-item slideInUp delay-3"> <img src="https://images.unsplash.com/photo-1600585152220-90363fe7e115?ixlib=rb-1.2.1&auto=format&fit=crop&w=400&h=300&q=80" alt="Geometric Pavilion" class="gallery-image"> <div class="gallery-info"> <h3 class="gallery-title">Geometric Pavilion</h3> <div class="gallery-meta"> <span>Minimalist</span> <span>2022</span> </div> </div> </div> <div class="gallery-item slideInUp delay-4"> <img src="https://images.unsplash.com/photo-1572120360610-d971b9d7767c?ixlib=rb-1.2.1&auto=format&fit=crop&w=400&h=300&q=80" alt="Glass House" class="gallery-image"> <div class="gallery-info"> <h3 class="gallery-title">Glass House</h3> <div class="gallery-meta"> <span>Sustainable</span> <span>2023</span> </div> </div> </div> </div> <!-- Detail view --> <div class="detail-view" id="detailView"> <div class="detail-header"> <h2 class="detail-title" id="detailTitle">Cantilever House</h2> <button class="close-btn" id="closeDetail"></button> </div> <div class="blueprint-container"> <div class="blueprint" id="blueprint"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500" fill="none" stroke="#333" stroke-width="1"> <!-- Blueprint outlines for a house --> <rect x="100" y="100" width="300" height="300" /> <line x1="100" y1="250" x2="400" y2="250" /> <line x1="250" y1="100" x2="250" y2="400" /> <rect x="270" y="120" width="80" height="110" /> <rect x="150" y="120" width="80" height="110" /> <rect x="150" y="270" width="180" height="110" /> <path d="M100,250 L50,250 L50,350 L100,350 Z" /> <circle cx="330" cy="320" r="30" /> <!-- Additional details --> <line x1="100" y1="170" x2="150" y2="170" stroke-dasharray="5,5" /> <line x1="350" y1="170" x2="400" y2="170" stroke-dasharray="5,5" /> <line x1="150" y1="320" x2="170" y2="320" stroke-dasharray="5,5" /> <line x1="210" y1="320" x2="230" y2="320" stroke-dasharray="5,5" /> </svg> <!-- Hotspots --> <div class="hotspot" style="top: 30%; left: 35%;"> <div class="hotspot-tooltip"> <strong>Main Living Space</strong> <p>Open concept design with 23' ceilings and floor-to-ceiling windows.</p> </div> </div> <div class="hotspot" style="top: 65%; left: 65%;"> <div class="hotspot-tooltip"> <strong>Cantilever Section</strong> <p>12.5' extension supported by steel beam structure, creating dramatic visual interest.</p> </div> </div> <div class="hotspot" style="top: 35%; left: 75%;"> <div class="hotspot-tooltip"> <strong>Green Roof</strong> <p>Sedum plantings for thermal insulation and stormwater management.</p> </div> </div> </div> </div> <div class="detail-tabs"> <button class="detail-tab active">Overview</button> <button class="detail-tab">Specifications</button> <button class="detail-tab">Materials</button> </div> <div class="detail-tab-content"> <div class="detail-info"> <div class="detail-info-item"> <span class="detail-info-label">ARCHITECT</span> <span class="detail-info-value">Miyamoto & Associates</span> </div> <div class="detail-info-item"> <span class="detail-info-label">LOCATION</span> <span class="detail-info-value">Portland, Oregon</span> </div> <div class="detail-info-item"> <span class="detail-info-label">AREA</span> <span class="detail-info-value">3,240 sq ft</span> </div> <div class="detail-info-item"> <span class="detail-info-label">YEAR</span> <span class="detail-info-value">2023</span> </div> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Create grid const gridOverlay = document.getElementById('gridOverlay'); const gridSize = 25; for (let i = 0; i < window.innerHeight / gridSize; i++) { const gridLineX = document.createElement('div'); gridLineX.classList.add('grid-x'); gridLineX.style.top = (i * gridSize) + 'px'; gridOverlay.appendChild(gridLineX); } for (let i = 0; i < window.innerWidth / gridSize; i++) { const gridLineY = document.createElement('div'); gridLineY.classList.add('grid-y'); gridLineY.style.left = (i * gridSize) + 'px'; gridOverlay.appendChild(gridLineY); } // Toggle grid button const gridToggleBtn = document.querySelectorAll('.tool-btn')[1]; gridToggleBtn.addEventListener('click', function() { this.classList.toggle('active'); gridOverlay.style.display = gridOverlay.style.display === 'none' ? 'block' : 'none'; }); // Gallery items const galleryItems = document.querySelectorAll('.gallery-item'); const detailView = document.getElementById('detailView'); const detailTitle = document.getElementById('detailTitle'); const closeDetailBtn = document.getElementById('closeDetail'); galleryItems.forEach(item => { item.addEventListener('click', function() { const title = this.querySelector('.gallery-title').textContent; detailTitle.textContent = title; detailView.classList.add('active'); }); }); closeDetailBtn.addEventListener('click', function() { detailView.classList.remove('active'); }); // Detail tabs const detailTabs = document.querySelectorAll('.detail-tab'); detailTabs.forEach(tab => { tab.addEventListener('click', function() { detailTabs.forEach(t => t.classList.remove('active')); this.classList.add('active'); // In a real app, we would switch content here }); }); // Hotspots interactivity const hotspots = document.querySelectorAll('.hotspot'); hotspots.forEach(hotspot => { hotspot.addEventListener('mouseenter', function() { const tooltip = this.querySelector('.hotspot-tooltip'); const rect = tooltip.getBoundingClientRect(); // Adjust position if tooltip goes outside viewport if (rect.right > window.innerWidth) { tooltip.style.left = 'auto'; tooltip.style.right = '0'; tooltip.style.transform = 'none'; } }); }); // Search functionality placeholder const searchInput = document.querySelector('.search-input'); searchInput.addEventListener('focus', function() { this.placeholder = ''; }); searchInput.addEventListener('blur', function() { this.placeholder = 'Search projects...'; }); // Add drag to pan functionality for blueprint const blueprint = document.getElementById('blueprint'); let isDragging = false; let startX, startY, scrollLeft, scrollTop; blueprint.addEventListener('mousedown', function(e) { isDragging = true; startX = e.pageX - blueprint.offsetLeft; startY = e.pageY - blueprint.offsetTop; scrollLeft = blueprint.scrollLeft; scrollTop = blueprint.scrollTop; blueprint.style.cursor = 'grabbing'; }); blueprint.addEventListener('mouseleave', function() { isDragging = false; blueprint.style.cursor = 'grab'; }); blueprint.addEventListener('mouseup', function() { isDragging = false; blueprint.style.cursor = 'grab'; }); blueprint.addEventListener('mousemove', function(e) { if (!isDragging) return; e.preventDefault(); const x = e.pageX - blueprint.offsetLeft; const y = e.pageY - blueprint.offsetTop; const walkX = (x - startX) * 1; const walkY = (y - startY) * 1; blueprint.scrollLeft = scrollLeft - walkX; blueprint.scrollTop = scrollTop - walkY; }); // Set initial cursor for blueprint blueprint.style.cursor = 'grab'; }); </script> </body> </html>
<html> <head> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } body { background-color: #0d0d0d; color: #fff; height: 700px; width: 100%; max-width: 700px; margin: 0 auto; overflow: hidden; position: relative; } .container { width: 100%; height: 100%; padding: 20px; display: flex; flex-direction: column; } header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; } h1 { font-size: 1.8rem; font-weight: 800; background: linear-gradient(90deg, #FF6B6B, #FFD166, #06D6A0); -webkit-background-clip: text; background-clip: text; color: transparent; transform: translateZ(0); } .controls { display: flex; gap: 12px; margin-bottom: 1.5rem; overflow-x: auto; padding-bottom: 8px; -ms-overflow-style: none; scrollbar-width: none; } .controls::-webkit-scrollbar { display: none; } .genre-btn { background: rgba(255, 255, 255, 0.08); border: none; color: white; padding: 8px 16px; border-radius: 50px; font-size: 0.85rem; cursor: pointer; transition: all 0.3s ease; white-space: nowrap; } .genre-btn.active { background: #FF6B6B; box-shadow: 0 0 15px rgba(255, 107, 107, 0.5); } .album-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 20px; overflow-y: auto; padding-right: 10px; margin-bottom: 20px; flex: 1; -ms-overflow-style: none; scrollbar-width: none; } .album-grid::-webkit-scrollbar { width: 4px; } .album-grid::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.2); border-radius: 4px; } .album { position: relative; border-radius: 8px; overflow: hidden; aspect-ratio: 1/1; cursor: pointer; transform-style: preserve-3d; transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); } .album:hover { transform: translateY(-8px) scale(1.05); z-index: 10; } .album-cover { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s ease; } .album:hover .album-cover { transform: scale(1.05); } .album-info { position: absolute; bottom: 0; left: 0; width: 100%; padding: 60px 12px 12px; background: linear-gradient(to top, rgba(0, 0, 0, 0.9), transparent); opacity: 0; transform: translateY(20px); transition: all 0.4s ease; } .album:hover .album-info { opacity: 1; transform: translateY(0); } .album-title { font-size: 0.9rem; font-weight: 700; margin-bottom: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .album-artist { font-size: 0.8rem; opacity: 0.8; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .album-detail { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.9); display: flex; align-items: center; justify-content: center; z-index: 100; opacity: 0; pointer-events: none; transition: opacity 0.5s ease; backdrop-filter: blur(8px); } .album-detail.active { opacity: 1; pointer-events: all; } .detail-container { display: flex; max-width: 90%; max-height: 90%; border-radius: 12px; overflow: hidden; box-shadow: 0 25px 50px rgba(0, 0, 0, 0.25); background: linear-gradient(135deg, #1e1e1e, #121212); transform: scale(0.9); opacity: 0; transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .album-detail.active .detail-container { transform: scale(1); opacity: 1; } .detail-cover { width: 280px; height: 280px; object-fit: cover; } .detail-info { padding: 25px; display: flex; flex-direction: column; justify-content: center; min-width: 280px; } .detail-title { font-size: 1.8rem; font-weight: 800; margin-bottom: 8px; } .detail-artist { font-size: 1.1rem; opacity: 0.8; margin-bottom: 12px; } .detail-release, .detail-tracks { font-size: 0.9rem; opacity: 0.6; margin-bottom: 6px; } .detail-genre { display: inline-block; background: rgba(255, 107, 107, 0.2); color: #FF6B6B; padding: 4px 10px; border-radius: 50px; font-size: 0.8rem; margin-top: 12px; margin-bottom: 20px; } .detail-desc { font-size: 0.9rem; line-height: 1.5; opacity: 0.8; margin-bottom: 20px; max-height: 120px; overflow-y: auto; } .close-btn { position: absolute; top: 20px; right: 20px; width: 40px; height: 40px; border-radius: 50%; background: rgba(255, 255, 255, 0.1); border: none; color: white; font-size: 1.2rem; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; } .close-btn:hover { background: rgba(255, 255, 255, 0.2); transform: rotate(90deg); } .visualizer { position: absolute; bottom: 0; left: 0; width: 100%; height: 40px; display: flex; align-items: flex-end; justify-content: center; padding: 0 20px; z-index: -1; } .bar { width: 4px; height: 5px; margin: 0 2px; background: linear-gradient(to top, #FF6B6B, #FFD166); border-radius: 2px 2px 0 0; transition: height 0.2s ease; } @media (max-width: 500px) { .album-grid { grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 15px; } .detail-container { flex-direction: column; width: 85%; } .detail-cover { width: 100%; height: auto; } h1 { font-size: 1.5rem; } } .loading { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: #0d0d0d; display: flex; flex-direction: column; align-items: center; justify-content: center; z-index: 1000; transition: opacity 0.5s ease, visibility 0.5s ease; } .loading.hidden { opacity: 0; visibility: hidden; } .loading-bars { display: flex; align-items: flex-end; height: 50px; margin-bottom: 20px; } .loading-bar { width: 6px; height: 20px; margin: 0 3px; background: linear-gradient(to top, #FF6B6B, #FFD166); border-radius: 3px; animation: equalize 1s infinite alternate; } .loading-bar:nth-child(1) { animation-delay: -1.2s; } .loading-bar:nth-child(2) { animation-delay: -1.1s; } .loading-bar:nth-child(3) { animation-delay: -1.0s; } .loading-bar:nth-child(4) { animation-delay: -0.9s; } .loading-bar:nth-child(5) { animation-delay: -0.8s; } .loading-bar:nth-child(6) { animation-delay: -0.7s; } .loading-bar:nth-child(7) { animation-delay: -0.6s; } @keyframes equalize { 0% { height: 10px; } 100% { height: 40px; } } .loading-text { font-size: 1rem; font-weight: 600; background: linear-gradient(90deg, #FF6B6B, #FFD166, #06D6A0); -webkit-background-clip: text; background-clip: text; color: transparent; } .now-playing { position: fixed; bottom: 20px; left: 20px; right: 20px; background: rgba(30, 30, 30, 0.8); backdrop-filter: blur(10px); border-radius: 10px; padding: 12px; display: flex; align-items: center; transform: translateY(100px); opacity: 0; transition: all 0.4s ease; z-index: 90; } .now-playing.active { transform: translateY(0); opacity: 1; } .now-playing-img { width: 50px; height: 50px; border-radius: 4px; margin-right: 12px; } .now-playing-info { flex: 1; } .now-playing-title { font-size: 0.9rem; font-weight: 600; margin-bottom: 4px; } .now-playing-artist { font-size: 0.8rem; opacity: 0.7; } .now-playing-controls { display: flex; align-items: center; gap: 8px; } .control-btn { background: none; border: none; color: white; width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s ease; } .control-btn:hover { background: rgba(255, 255, 255, 0.1); } .play-btn { background: #FF6B6B; width: 36px; height: 36px; } .play-btn:hover { background: #ff5252; transform: scale(1.05); } </style> </head> <body> <div class="loading"> <div class="loading-bars"> <div class="loading-bar"></div> <div class="loading-bar"></div> <div class="loading-bar"></div> <div class="loading-bar"></div> <div class="loading-bar"></div> <div class="loading-bar"></div> <div class="loading-bar"></div> </div> <div class="loading-text">Loading the rhythm...</div> </div> <div class="container"> <header> <h1>Rhythm Archive</h1> </header> <div class="controls"> <button class="genre-btn active" data-genre="all">All Genres</button> <button class="genre-btn" data-genre="rock">Rock</button> <button class="genre-btn" data-genre="electronic">Electronic</button> <button class="genre-btn" data-genre="hiphop">Hip-Hop</button> <button class="genre-btn" data-genre="jazz">Jazz</button> <button class="genre-btn" data-genre="indie">Indie</button> </div> <div class="album-grid"> <!-- Albums will be inserted here by JS --> </div> </div> <div class="album-detail"> <div class="detail-container"> <img class="detail-cover" src="" alt="Album Cover"> <div class="detail-info"> <h2 class="detail-title"></h2> <p class="detail-artist"></p> <span class="detail-genre"></span> <p class="detail-release"></p> <p class="detail-tracks"></p> <p class="detail-desc"></p> </div> </div> <button class="close-btn">✕</button> </div> <div class="now-playing"> <img class="now-playing-img" src="" alt="Now Playing"> <div class="now-playing-info"> <div class="now-playing-title"></div> <div class="now-playing-artist"></div> </div> <div class="now-playing-controls"> <button class="control-btn"> <svg width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M4 4a.5.5 0 0 1 1 0v3.248l6.267-3.636c.52-.302 1.233.043 1.233.696v7.384c0 .653-.713.998-1.233.696L5 8.752V12a.5.5 0 0 1-1 0V4z"/> </svg> </button> <button class="control-btn play-btn"> <svg width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="m11.596 8.697-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393z"/> </svg> </button> <button class="control-btn"> <svg width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M12.5 4a.5.5 0 0 0-1 0v3.248L5.233 3.612C4.713 3.31 4 3.655 4 4.308v7.384c0 .653.713.998 1.233.696L11.5 8.752V12a.5.5 0 0 0 1 0V4z"/> </svg> </button> </div> </div> <div class="visualizer"> <!-- Audio visualizer bars will be added here by JS --> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Simulate loading setTimeout(() => { document.querySelector('.loading').classList.add('hidden'); }, 1500); // Album data const albums = [ { id: 1, title: "Chromatic Pulse", artist: "Neon Cascade", genre: "electronic", cover: "https://images.unsplash.com/photo-1614149162883-504ce4d13909?w=400&q=80", releaseYear: 2023, tracks: 12, description: "A journey through future bass and synth-wave, creating an immersive landscape of digital textures and rhythmic patterns that push the boundaries of electronic music." }, { id: 2, title: "Echoes of Entropy", artist: "Quantum Collective", genre: "rock", cover: "https://images.unsplash.com/photo-1493225457124-a3eb161ffa5f?w=400&q=80", releaseYear: 2022, tracks: 10, description: "A powerful rock album that combines hard-hitting guitar riffs with introspective lyrics about chaos and order in modern life. Features the hit single 'Dimensional Drift'." }, { id: 3, title: "Velvet Horizon", artist: "Lunar Theory", genre: "indie", cover: "https://images.unsplash.com/photo-1528459801416-a9e53bbf4e17?w=400&q=80", releaseYear: 2022, tracks: 9, description: "An indie masterpiece that blends folk-inspired melodies with experimental production techniques, creating a dreamlike atmosphere that transports listeners to another world." }, { id: 4, title: "Metro Rhapsody", artist: "Urban Cipher", genre: "hiphop", cover: "https://images.unsplash.com/photo-1581905764498-f1b60bae941a?w=400&q=80", releaseYear: 2023, tracks: 14, description: "A groundbreaking hip-hop album that captures city life through sharp lyrical storytelling, innovative beats, and collaborations with underground artists from across the globe." }, { id: 5, title: "Blue Metamorphosis", artist: "Midnight Quartet", genre: "jazz", cover: "https://images.unsplash.com/photo-1511671782779-c97d3d27a1d4?w=400&q=80", releaseYear: 2021, tracks: 8, description: "Contemporary jazz that honors tradition while pushing into new territory, featuring complex improvisations and unexpected harmonic shifts that showcase each musician's virtuosity." }, { id: 6, title: "Prismatic Shadows", artist: "Aurora Veil", genre: "electronic", cover: "https://images.unsplash.com/photo-1603126857599-f6e157fa2fe6?w=400&q=80", releaseYear: 2023, tracks: 11, description: "A mesmerizing blend of ambient electronic soundscapes and pulsing dance rhythms, creating an emotional journey through light and darkness." }, { id: 7, title: "Concrete & Sky", artist: "The Resonant", genre: "rock", cover: "https://images.unsplash.com/photo-1496293455970-f8581aae0e3b?w=400&q=80", releaseYear: 2022, tracks: 10, description: "An anthemic rock album exploring the contrast between urban grit and human aspiration, delivered with passionate vocals and arena-sized choruses." }, { id: 8, title: "Nostalgic Futures", artist: "Retro Synthetics", genre: "electronic", cover: "https://images.unsplash.com/photo-1605348863400-c21ea557333e?w=400&q=80", releaseYear: 2021, tracks: 12, description: "A retro-futuristic electronic odyssey that reimagines 80s synth sounds with cutting-edge production techniques and cinematic arrangements." }, { id: 9, title: "Verdant Whispers", artist: "Sylvan Echo", genre: "indie", cover: "https://images.unsplash.com/photo-1452639608291-23cd58f6864c?w=400&q=80", releaseYear: 2022, tracks: 10, description: "Folk-inspired indie music with lush vocal harmonies and organic instrumentation that evokes the tranquility and mystery of deep forests." }, { id: 10, title: "Cloud Theory", artist: "Altitude", genre: "electronic", cover: "https://images.unsplash.com/photo-1615247001958-f4bc92fa6a4a?w=400&q=80", releaseYear: 2023, tracks: 9, description: "Ethereal electronic compositions that float between ambient, downtempo, and experimental genres, creating an immersive atmosphere for deep listening." }, { id: 11, title: "Flow State", artist: "Onyx Currents", genre: "hiphop", cover: "https://images.unsplash.com/photo-1484876065684-b683cf17d276?w=400&q=80", releaseYear: 2022, tracks: 13, description: "Progressive hip-hop that combines conscious lyrics with jazz-influenced production and live instrumentation, challenging genre conventions." }, { id: 12, title: "Modal Mutations", artist: "The Improvisers", genre: "jazz", cover: "https://images.unsplash.com/photo-1516280440614-37939bbacd81?w=400&q=80", releaseYear: 2021, tracks: 7, description: "A showcase of modern jazz innovation, featuring complex time signatures, extended techniques, and a fearless approach to improvisation and composition." } ]; const albumGrid = document.querySelector('.album-grid'); const albumDetail = document.querySelector('.album-detail'); const genreBtns = document.querySelectorAll('.genre-btn'); const closeBtn = document.querySelector('.close-btn'); const nowPlaying = document.querySelector('.now-playing'); const visualizer = document.querySelector('.visualizer'); // Create visualizer bars for (let i = 0; i < 30; i++) { const bar = document.createElement('div'); bar.classList.add('bar'); visualizer.appendChild(bar); } // Animate visualizer function animateVisualizer() { const bars = document.querySelectorAll('.bar'); bars.forEach(bar => { const height = Math.floor(Math.random() * 30) + 5; bar.style.height = `${height}px`; }); } setInterval(animateVisualizer, 100); // Render albums function renderAlbums(filteredAlbums = albums) { albumGrid.innerHTML = ''; filteredAlbums.forEach(album => { const albumEl = document.createElement('div'); albumEl.classList.add('album'); albumEl.dataset.id = album.id; albumEl.innerHTML = ` <img class="album-cover" src="${album.cover}" alt="${album.title}"> <div class="album-info"> <h3 class="album-title">${album.title}</h3> <p class="album-artist">${album.artist}</p> </div> `; albumGrid.appendChild(albumEl); // Add slight delay for staggered animation effect setTimeout(() => { albumEl.style.opacity = 1; albumEl.style.transform = 'translateY(0)'; }, 50 * albumGrid.children.length); }); } // Initial render renderAlbums(); // Filter albums by genre genreBtns.forEach(btn => { btn.addEventListener('click', () => { genreBtns.forEach(b => b.classList.remove('active')); btn.classList.add('active'); const genre = btn.dataset.genre; let filteredAlbums; if (genre === 'all') { filteredAlbums = albums; } else { filteredAlbums = albums.filter(album => album.genre === genre); } renderAlbums(filteredAlbums); }); }); // Show album details albumGrid.addEventListener('click', (e) => { const albumEl = e.target.closest('.album'); if (!albumEl) return; const albumId = parseInt(albumEl.dataset.id); const album = albums.find(a => a.id === albumId); if (album) { const detailCover = document.querySelector('.detail-cover'); const detailTitle = document.querySelector('.detail-title'); const detailArtist = document.querySelector('.detail-artist'); const detailGenre = document.querySelector('.detail-genre'); const detailRelease = document.querySelector('.detail-release'); const detailTracks = document.querySelector('.detail-tracks'); const detailDesc = document.querySelector('.detail-desc'); detailCover.src = album.cover; detailTitle.textContent = album.title; detailArtist.textContent = album.artist; detailGenre.textContent = album.genre.charAt(0).toUpperCase() + album.genre.slice(1); detailRelease.textContent = `Released: ${album.releaseYear}`; detailTracks.textContent = `Tracks: ${album.tracks}`; detailDesc.textContent = album.description; albumDetail.classList.add('active'); // Show now playing setTimeout(() => { const nowPlayingImg = document.querySelector('.now-playing-img'); const nowPlayingTitle = document.querySelector('.now-playing-title'); const nowPlayingArtist = document.querySelector('.now-playing-artist'); nowPlayingImg.src = album.cover; nowPlayingTitle.textContent = album.title; nowPlayingArtist.textContent = album.artist; nowPlaying.classList.add('active'); }, 1000); } }); // Close album details closeBtn.addEventListener('click', () => { albumDetail.classList.remove('active'); nowPlaying.classList.remove('active'); }); // Playback controls interaction (visual only) const playBtn = document.querySelector('.play-btn'); playBtn.addEventListener('click', function() { this.innerHTML = this.innerHTML.includes('m11.596') ? '<svg width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M5.5 3.5A1.5 1.5 0 0 1 7 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5zm5 0A1.5 1.5 0 0 1 12 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5z"/></svg>' : '<svg width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="m11.596 8.697-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393z"/></svg>'; // Toggle more intense visualizer animation if (this.innerHTML.includes('M5.5')) { visualizer.classList.add('active'); setInterval(animateVisualizer, 80); } else { visualizer.classList.remove('active'); setInterval(animateVisualizer, 200); } }); }); </script> </body> </html>
<html> <head> <style> @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700;900&family=Press+Start+2P&family=Rajdhani:wght@300;400;500;600;700&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; } :root { --neon-pink: #ff2a6d; --neon-blue: #05d9e8; --neon-purple: #9d4edd; --dark-bg: #0f0f1a; --cyber-yellow: #ffd23f; --grid-size: 20px; } body { font-family: 'Rajdhani', sans-serif; background-color: var(--dark-bg); color: white; overflow-x: hidden; height: 100vh; display: flex; flex-direction: column; position: relative; } /* CRT Effect */ body::before { content: ""; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.2) 50%); background-size: 100% 4px; z-index: 100; pointer-events: none; opacity: 0.3; } /* Cyberpunk Grid */ body::after { content: ''; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(var(--dark-bg) 95%, var(--neon-blue) 95%, var(--dark-bg) 100%), linear-gradient(90deg, var(--dark-bg) 95%, var(--neon-blue) 95%, var(--dark-bg) 100%); background-size: var(--grid-size) var(--grid-size); opacity: 0.1; pointer-events: none; z-index: -1; } header { padding: 1.5rem; text-align: center; position: relative; z-index: 1; } h1 { font-family: 'Orbitron', sans-serif; font-weight: 900; font-size: 2.5rem; text-transform: uppercase; letter-spacing: 4px; margin-bottom: 0.5rem; background-image: linear-gradient(90deg, var(--neon-pink), var(--neon-blue)); -webkit-background-clip: text; background-clip: text; color: transparent; text-shadow: 0 0 15px rgba(255, 42, 109, 0.5); position: relative; animation: titlePulse 2s infinite alternate; } .subtitle { font-family: 'Press Start 2P', cursive; font-size: 0.7rem; color: var(--cyber-yellow); margin-bottom: 1.5rem; letter-spacing: 1px; } main { padding: 0 1rem; overflow-y: auto; flex: 1; max-width: 100%; } .gallery { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.5rem; padding-bottom: 2rem; } .game-card { background: rgba(10, 10, 20, 0.8); border: 2px solid transparent; border-radius: 8px; overflow: hidden; position: relative; transition: all 0.3s ease; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); height: 300px; cursor: pointer; } .game-card::before { content: ''; position: absolute; top: -2px; left: -2px; right: -2px; bottom: -2px; background: linear-gradient(45deg, var(--neon-pink), var(--neon-blue), var(--neon-purple), var(--cyber-yellow)); z-index: -1; border-radius: 10px; animation: border-glow 3s linear infinite; opacity: 0; transition: opacity 0.3s ease; } .game-card:hover::before { opacity: 1; } .game-card:hover { transform: translateY(-5px); box-shadow: 0 15px 25px rgba(0, 0, 0, 0.6); } .card-image { height: 65%; overflow: hidden; position: relative; background-size: cover; background-position: center; transition: all 0.5s ease; } .card-image::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(to bottom, transparent 50%, rgba(15, 15, 26, 0.8) 100%); } .game-card:hover .card-image { height: 30%; } .card-content { padding: 1rem; position: relative; z-index: 1; transition: all 0.5s ease; } .game-card:hover .card-content { transform: translateY(-65%); } .card-title { font-family: 'Orbitron', sans-serif; font-weight: 700; font-size: 1.2rem; margin-bottom: 0.5rem; } .card-genre { font-size: 0.8rem; background: var(--neon-purple); display: inline-block; padding: 3px 10px; border-radius: 12px; margin-bottom: 0.5rem; } .card-lore { max-height: 0; overflow: hidden; opacity: 0; transition: all 0.5s ease; font-size: 0.9rem; line-height: 1.4; } .game-card:hover .card-lore { max-height: 500px; opacity: 1; margin-top: 1rem; } /* Pixel art character gallery */ .pixel-characters { display: flex; justify-content: center; margin: 1.5rem 0; overflow-x: auto; padding: 1rem 0; gap: 1.5rem; } .pixel-character { width: 64px; height: 64px; image-rendering: pixelated; background-size: contain; background-repeat: no-repeat; background-position: center; transform: scale(1); transition: transform 0.2s ease; position: relative; cursor: pointer; } .pixel-character:hover { transform: scale(1.5); z-index: 10; } .pixel-character:hover::after { content: attr(data-name); position: absolute; bottom: -20px; left: 50%; transform: translateX(-50%); white-space: nowrap; font-size: 0.8rem; font-family: 'Press Start 2P', cursive; color: var(--cyber-yellow); text-shadow: 0 0 5px rgba(0, 0, 0, 0.8); } .neon-button { background: transparent; border: 2px solid var(--neon-blue); color: var(--neon-blue); padding: 0.5rem 1.5rem; font-family: 'Orbitron', sans-serif; font-size: 1rem; text-transform: uppercase; letter-spacing: 2px; border-radius: 4px; cursor: pointer; position: relative; overflow: hidden; transition: all 0.3s ease; z-index: 1; margin-top: 1rem; display: inline-block; } .neon-button::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(5, 217, 232, 0.2), transparent); transition: all 0.6s ease; z-index: -1; } .neon-button:hover { color: white; box-shadow: 0 0 10px var(--neon-blue), 0 0 20px var(--neon-blue); } .neon-button:hover::before { left: 100%; } .cta-container { text-align: center; margin: 1rem 0; } footer { text-align: center; padding: 1rem; font-size: 0.8rem; color: rgba(255, 255, 255, 0.6); position: relative; z-index: 1; } @keyframes border-glow { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @keyframes titlePulse { 0% { text-shadow: 0 0 5px rgba(255, 42, 109, 0.5); } 100% { text-shadow: 0 0 15px rgba(255, 42, 109, 0.8), 0 0 20px rgba(5, 217, 232, 0.6); } } /* Scanlines effect */ .scanlines { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: repeating-linear-gradient( to bottom, transparent 0px, transparent 2px, rgba(0, 0, 0, 0.1) 2px, rgba(0, 0, 0, 0.1) 4px ); pointer-events: none; z-index: 99; opacity: 0.3; } .noise { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 98; opacity: 0.05; pointer-events: none; } /* Responsive adjustments */ @media (max-width: 700px) { h1 { font-size: 2rem; } .gallery { grid-template-columns: 1fr; } .pixel-character { width: 48px; height: 48px; } .game-card { height: 280px; } } @media (max-width: 500px) { h1 { font-size: 1.5rem; } .subtitle { font-size: 0.6rem; } } @media (min-width: 701px) and (max-width: 1024px) { .gallery { grid-template-columns: repeat(2, 1fr); } } /* Virtual console at bottom */ .virtual-console { background: rgba(5, 5, 15, 0.9); border-top: 2px solid var(--neon-blue); padding: 0.8rem; margin-top: auto; display: flex; align-items: center; justify-content: space-between; } .console-text { font-family: 'Press Start 2P', cursive; font-size: 0.6rem; color: var(--neon-blue); overflow: hidden; white-space: nowrap; width: 100%; position: relative; } .console-cursor { display: inline-block; width: 8px; height: 15px; background-color: var(--neon-blue); animation: blink 1s infinite; margin-left: 5px; vertical-align: middle; } @keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } } /* Tooltip system */ .tooltip { position: absolute; background: rgba(10, 10, 20, 0.95); border: 1px solid var(--neon-blue); border-radius: 4px; padding: 1rem; max-width: 300px; z-index: 100; pointer-events: none; opacity: 0; transition: opacity 0.3s ease; transform: translateY(10px); box-shadow: 0 0 15px rgba(5, 217, 232, 0.3); } .tooltip-visible { opacity: 1; transform: translateY(0); } .tooltip h4 { font-family: 'Orbitron', sans-serif; color: var(--cyber-yellow); margin-bottom: 0.5rem; } .tooltip p { font-size: 0.9rem; line-height: 1.4; } </style> </head> <body> <div class="scanlines"></div> <div class="noise" id="noise"></div> <header> <h1>PIXEL NEXUS</h1> <p class="subtitle">INTERACTIVE GAMING ART GALLERY</p> </header> <div class="pixel-characters"> <div class="pixel-character" style="background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEOklEQVRYhbWXTWxUVRTHf+e+N2/a6ZSWtrTQQhGLUDACiYbEYExcsDCyceHChTFx48aVK+PChTFx48KYEBY1JsaVH4kfARIREg1gRKAULKXQr2k77cybe+49LuZNO52ZToXqSW7eu/Pu+Z//Peeee58opXjQZozJxL2i1vKkqqovgY1ABGSBPJABGkAVuApcB66IyJlQ1X2gCgTAn8aYezbkngDGmFVAFtimqtuBp4FhwC0jt8A4cElEzoYQjiRJ8ldW9Wtf7waQAp4BXgM2A32L+C0HCoCWwjrAH8BnIvJN6mv3LLIlwKhS6h1gO9C/hNBSsoB5IKq17gOeBV4G3lVKbQD2G2OuxnF8PYoi7wbYzwBvAa/+j+AoikhTBxkRRGtEBJ8mKK0Rpeid+y43KvXmda31EPAS8E6tVjs0MzMzZZIkMcaYQWPMx8Ar7QVXWkMSL1TcQWIFnkYoSGJcc3Y3TYQkmicIbUppHQJbgLeBQ9Z1XTzPe98Ys76z6FqpkV/nSeuLGZJahGvPEyYeB0UrtGt2XRnXUrgCrrOWJEmo1+tHgT2u0WgMKqV2AtvaVtbaNaZ7h73rCacj3FgBPWJCmDERJl+kn4ZCR4JoTRoEJEGA1iqYnp5+EXjSiMgLwFPdRJVWuLaJtREuqkJjGk3YjgOFCIPWDJx6nL6z35MkCXGSECcpre8l9jyUUk8BO4wxG4BH7jIHOFxzBldjj7TuQRp3dNAOItrQd/YwPWdP4Ps+jThBRBARROZ/azc/fwSYRyn1yELnQuJrxs56JJEQQmfTjKwfFFo51JVv6Tn1E34Q4HkeSZrSM7qRdPgxbL6IJAmIYP2Ayr27wlVKbQJyMh8JYyNnPPxpQbRCa9W1iDJ/2YT1B4TKsVMkYYjv+/i+T5okDL+1j8LD6wE4vOdFRs8dY+L4YbxGbcG/ZT5PAo/Z+bUgnjKY6QSpd7YS8ZdCSNOMHPmB6cmr+EFA4Pv4QYDWmscPHCLYsp2RU8cYO3mEsdNHcKKwbAGRCz9kVNW3NLKKVsfWRiiVz5Mv9JLNF8j3FMnm88RRxK2R30jjBtPlS/jVaYLAJ/B9fN/HcRxWbN3B6v0fcnl6huLWbbj5HkqlyzzKvANqHcCyR7IROF4RD15YSe+KlRSKRXr7+sj1FMnmcrz540kADu14mhtjl6iPX8WvTuN5Hp7r4nkeSikcxyEIAuI4xvM9ii+9jluaIIvdCr7nKIZGJkgbDSr3MRFNVS8zfvYn3MoUrusupg9u3oaxER8dfIP1G58A4PDel7l27gRXTh3HSjrfZGQdLx1ARMjkcmSyObJBQO/AEMW+PgZXrebx0TGetRnGzx8nCcPFmadpiijF1OQkvr/MkS0iJMD3DcvvyFGUAieUUofuZr5UVynxA8B/4KBiBYnWCLcAAAAASUVORK5CYII=')" data-name="Knight"></div> <div class="pixel-character" style="background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEJUlEQVRYhbWXW2gcVRjHf2dmZ3azm2Q3m002rUnUxt60VitCxQsIXh5EfNAHQZ980CcFn0TwQcQHwSdBEF8UfBAUwQtUECrWtGpbmzZpYtMke8lmk93sZi8zc46Pk8xOJruTjYkfDMycM+f7f9//O985s0JKyf2WEMIXmxXPsJ2TUso3gX1ACuSBABAHGoANlIFV4DpwFfiuWav9BtQBF/hJCLHpRDYlIIRYC3jAcSnlCeAlYD9g9HG3gCvAFSHE5Vq9fjkUCv1aKpVcgGazuR7AboAQMAq8DRwFdvT52Ugp09baGzW9fxVcIpEE9gJvCSHeE0I8AXwrhCimaVrUNM3fBXAQOAu8McBkG0kppYfnge77GeDU7Ozst6lUahzYC7wVCARmS6XS7Vqt5nYDHAFOAq/1GlyaJvV6HcMwUBSl89e6vNXqeE1rnQGOAR8AX5mmGc3n8yeEELs2O9onh7WOMvxer2UjMgGflBI3+1fP4FJKVFXtAowDR6WUX5qmaZRKpY+Aw/0WlFJSq9WQUvaGaLlLpcLz3CWA9s8CPgVOB4PBkZmZmXeAp6PtVhMQQvSE0DQNx3E2Ba0LgM8BznZpRMk/UF3X8TyvA9SyrE53NE3DdV0cx8F1XTzPI51OB4LB4EOGEOIg8HDfyTZRq9HA87wNIK2Wj6IoxGKxTtdM0yQcDgOQy+UM4BEhxB6ggGj1rKOqai/AbqqqsrS0BEA8Hu/AJBIJAoEAjuNQrVbDwC5gGKhY/QCi0ei27v2WZWGaJpFIpJNJRVGIxWL+0UADBgW+rQrV27L8bK4HAYadwcZXxgA+/EwK3a+2ZCASiXSmDwQCrK6u+kkhpZSLQNc6NgM4jrONNf5X/tkVi0UIhUI0Gg3q9brfUAuoBmWgZ2+EEJs+4w8CTdMoFouk02kymQwrKyt+oAb8BZQMn9B13a6LzWp+fl7++OWnlG/fQk0kkDqkm5JgKEwwFGLZDDJ6r8bEI/sIxZL8/N03zM3N0Wg0iEajxONxdF3fAKOq6iJwA5i0gMvAs+0LzWYT0zRxHJvlpSVsKcjs30PiX40DvsRkc5mUPZVff5hianKKVqtFNptlZGSEeDy+YVFqmrYEnDNsOz8yOjoecRwsyyKVSqHrOrZtU61WWVleplqpUCmXKZdK4LlQKQLQfPpZ0g89jO04VCoVlpeXKRQKmKZJPp8nk8mQTCbRNA1N0/yK58xarfaHValUyOVyuK5LsVhkYWGBQqFAo9HAtu1OOVfLJaRtI1sO5vE3kMlduK6L4zhUq1VKpRLz8/M4joOu65xbXJzZadv5Wdd1m41GwwDI5XKkUimSySSJRIJYLIamaYTDYUKhELqu+3uHb8Kk0Wj8XSgUfm82mxbQAJwNX8fvtwT0NmLrLwI5qwIrP8IWAAAAAElFTkSuQmCC')" data-name="Mage"></div> <div class="pixel-character" style="background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAD20lEQVRYhcWXXWhcRRTHf3Nn7t3N7ibZzX6kaWKT1KQ1sWkVP1CpWkWKCFJ98MFCQR988sWnCj5YEHwoCIIP4oNvioJCEaH4UFFKsVZMLdFYTdMm2WQ3+5HsbnbvnTnHh92b3GR3sxtT/MPAzJ0z5/znzDkzZ4SUkvstIYQvG5U5Hvi0lPJV4DAwBhQAE0gBKaAD1IAycBO4Dvwci8d/AZqAB1wUQnRN5K4EhBBDgA8cllK+ADwDHAT0PuEucA24JoS46jjOpWQy+UcmkwkA2u12J4DvAQQwDnwAvAgc6BO8m1wpZbS19m5N4mEh8ISUUpNSHgKeF0K8I4R4HPhOCJENw7Coqqq/C+AAcAZ4qd/g/SQl4AEudIJKKWm1WpHOAM4BxxcWFr7K5/OzwEHg/UQiMZfJZO7UarW2H+AIcAI4ttvgXTb8lSsBVA9wgL3AUeCzfD6vtVqtj4BH+g0qpWR9Y0MppXK5omvCYcMYAVD4d79lxN8BTiYSieG5ubn3gCc6te7E8zwajQaGYaAoSscmGo0GGxsb+J7XS63kYXbP00cbjcZGPp9/E3iqZxd9xPd9arUa7XYbIQSKohCNRqOO6/LN6WeZPHSI8clJ1IiG4waEYdj5bTQanSmNAk8Cf3UROG5aJmCQSqU6YL7v02w2aTQamKZJqVwm9Dx+OHuGxz74GKsZ8uZjh1hds0mlkhSLJaanpzEMA8MwqNfrpNNpNE2LWpZ1AHgEuKAFQXBw39790c3QCkgmk9i2jeu62LZNuVymUi5TLpWo1+uEzSbO0y+A3uqEbts2s7OzrK6uUqlUsG0b13XJ5XKkUin/6tWrVwzDUMrl8kHgu84S7BmfKBYajQbVahXbtmlubt5zArbboDnd5WoYBoqioKoq+Xye4eFhDMPA9/0o8IBpFOmZAMMjIwwl08QQmKZBJpNldHSUXC5HdihLfnycB0dHGTs0xVAshmEYhGFIu93GdV1c16XRaFCr1QBCYBl4yNCDYIbNNiRjMYbTadKZDJlMhkKhQH50lPGB9nXkxRcYiEYjPSLtPyDXde9Y4zgu6+vrVCoV3zsaRn4EsO+WAIqiUCwWSSaTvcH/S1PqPqBpmvJnvbaqAB7QvmsCQggymQy6rt8xgWKxiOd5RLRIBagaQRAAlHeL0L+8V7qmb4wA1MnJ/XuGh4eW9uzZc8P3/U6Q7/tUq1Vs22ZpaYnlO3cW/CDYNIJgJQp8F4vFVlKp1NzKykpnCV3XpdVqUavVCALv9vWFhc+DIGgb9XqdVCqFaZpomkYsFkPXdVRVRQiBpmnR24hhmkajsXzr1q0rrutWgQDwur6O77eE73TFPvgHvJJzzBB0JKAAAAAASUVORK5CYII=')" data-name="Rogue"></div> <div class="pixel-character" style="background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEGElEQVRYha2XXWgcVRTHf3dmZ2Yzm91kN5vdbGLTpCZNY6I2Rkur9QMLKhQVRUVf8sWTDwrFBx988UkQH/RBEPTFBx980odSqA9FKAhFbIxWa0zTJk2zm939mJ2d/Tx+mOxmNruTrI0XLszcuef8z/+ce+65V0gpudsyDMMXG1W3cJ2jUspXgMPANFAELCAJJIEeUAWuAzeAX2Px+C9AA/CBq4ZhdCRyRwJCiHHABg5LKZ8DngYOAGafcBv4A7humMY113WvJBKJP7LZrAfQbrfXAfwAEMAU8D7wAnCgT/BechVC4vV0SxXZKaaSUpIcGeHyxYtomob6KJVK1Go1/x/AWeD43Nzc14VCYRbYD7ybSCRms9nsrVqt1vECh4CTwNHtBu8tKSUffvAhZ86cwdSF+pZAwLJtGk6ZpdVVnJCF43Zcmg1cPTLOH2NTvFapVLB0fQI4YQLPA0f6RCXYJk5yZJTnnjtGzLJ4/dQpXnjpJZqtFsVikUqlgm3b9DrTYKmgMaHXKDt10CSqQKrI0qYXBbKPpQfn8H7H8Tm0SFtF0wRPbHH9cg2lVtMxLQvLsvA8D9/3O3r+qrDrLFXW2J00lbUODAzBM/AYQHoiZjEai5O0bMrVGqXyGk7NRQhBuVymVCoRhmH3HBvEpjGawOdAUwGWgL/7OWiatuXN2Z0F9g2Pq7zXarVYXFykVqupObAsC13X0XUd0zSxbRvbtlG5uWVA24gE3rEsa2J+fv5N4PGB6xaJsHtvgV25UaLRKIZhKCJra2usr6/TbDZpNBrhWq3WzeAdHXjNNE1teXn5FPBUZwz7DZPQDfLZcdLxJLppEY/HOX/+PFEU0W636XQ6+L6P53ndyK9Wq9SdDdzOhm1bwOOapp2RUn5pGMbDwGP9kzZoOmWS8RQApmlimiYnTpyg2Wziui5BENBuKzJhGFFvuNQbLk7VYa3hUqs7FDJCCHFIBzLApkxfT0brnlK5zGq1ir2tZS8UCgwPD3cJALRaLZUc5Qrt+pPV/lsIfVnXa6k2UqFQYHx8vC8BkI3pEIjGMGMxZCSJRDGiiAQSK2Yx4g6RcPgsmUzy6/nzHaqBtlO/s9B14vH4Q0JRcDzKzRpDWoQhIopDYFgkyWkm1yoOXrO5g4CGVK5gZXySeqWM73kwahHFRpHf+bFH0i1yHEEi2ITPAI7zHJQNQ+hGYltM3OZ2Zk6N46Z6Uxi0sGjUIooipOzSuQa0olJKv43jmFaSXG6c+qM2K39fwY7Z244OQ7EMXyeXm0DGgCiiJQAMQwtKlQDPE3S6bXcGO8IY8Tqs3Jq75nleEAQBWJZKMtM00TStyzmKIorLNXnhwq/HDh06HQEhwNK8OcDr6QmCYK6QtP+5evXaNc/zfKDdYyv+vwUsBfz9QHl6XnDmn9ZtAAAAAElFTkSuQmCC')" data-name="Archer"></div> <div class="pixel-character" style="background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEGElEQVRYhbWXTWhcVRTHf/e+92Ymk8xkMpNJJpOYNKlJrTaNNdFWKyoUFfGjUBcuxIVdKIILceHChQtBcOFCBLtRXLlxUaRQ0EJBEcGPWKu1Jjb5aPORZDKZj5f33r3HxXszL5PJZEz1wOXde+4957//c849514hpeR+Swjhy3rFHerzoJTyNeAosAsYB1LAEJAChgAH8IB54CZwHfgumUr9AJQBH7gshKjryF0JCCHGgARwREr5AvAUsB9QG6hbwB/AVSHElVKp9F0mlfozn8+7AJVKZRXADwABTAIfAC8C+zcI3k3+Pj8BhTNHjz0NHBZCvC2EeAL4SgiR98PCjKqqgd4BjgPndhq8kzzfI6uWFAUcx6HkFMm7eQxN38Kz5BzwXiqVmlxYWHgfeCyUekOtpRqLxQiFQhGgn1Etn0/iSYlb8WgBSdOkWCxSLBb/M04CJ1Op1GfpdPo4MNnTQQhBNBoNAhiGEajsRVKCpqqEw+HFREKJAvtMYKZ+lpsT2GphWwgEEALeAqaBw/Tfd/WIgpXw9MnH0TQNTVVxXa/7b83AE8BR4O2azcpLJKW/6AwEgkAIgaqqKIoAxUeGvPWAUsrXhRCvCiHeEUJ8IoS4JIQYWr+q/uLUo1Oe71P2PJaXCywuLrHiFDfSHAFeBobD/WrApgSklMsOhRCPCCFeFUK8J4Q4A3y5vqKUklwux/KdO5TLHmE9wpPpwywslbkyew3P88Pmtf