Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a new dedicated landing page for the EchoKit Gift Version product, presenting a premium, customizable AI companion device designed specifically for gifting. The page features a modern, visually-rich design with interactive elements including audio samples, image galleries, and detailed product information sections.
Key Changes
- New standalone gift version product page with comprehensive sections covering experience, features, creator studio, unboxing, pricing, and timeline
- Interactive audio player implementation with custom controls for voice sample demonstrations
- Responsive gallery showcasing device capabilities through images and functional audio samples
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <h3>Emotional Connection</h3> | ||
| <p>It’s not just a speaker; it’s a time capsule. Without the distraction of a touchscreen, the <strong>Voice-Only Interface</strong> encourages deeper, more natural conversations.</p> | ||
| </div> | ||
| </div> |
There was a problem hiding this comment.
Incomplete feature display: The features grid is incomplete. The closing div tag for the features-grid is missing, and only 2 feature boxes are included when the grid layout suggests space for more features.
| </div> | |
| <div class="feature-box"> | |
| <div class="feature-icon" style="color: var(--accent-cool);"><i class="fas fa-microchip"></i></div> | |
| <h3>Private & Secure</h3> | |
| <p>Your data never leaves your hands. All training and voice data are processed securely, and the device operates offline for maximum privacy.</p> | |
| </div> | |
| </div> |
echokit-gift.html
Outdated
| <div style="display: inline-block; padding: 6px 16px; background: #fef3c7; color: #b45309; border-radius: 20px; font-weight: 600; font-size: 0.8rem; margin-bottom: 24px;"> | ||
| <i class="fas fa-star"></i> The Perfect Gift 2025 | ||
| </div> | ||
| <h1> | ||
| Unwrap AI with <span class="serif-highlight">Heart</span> | ||
| </h1> | ||
| <p style="font-size: 1.25rem; margin: 30px 0; color: var(--text-muted);"> | ||
| EchoKit Gift Version: A bespoke AI companion living inside a stunning box. | ||
| </p> | ||
| <div style="display: flex; gap: 15px;"> | ||
| <a href="https://form.jotform.com/253442751110042" class="btn btn-primary">Build your Own</a> | ||
| <a href="#gallery" class="btn btn-outline"><i class="fas fa-play"></i> Watch Demo</a> | ||
| </div> | ||
| </div> | ||
|
|
||
| <!-- Visual Side (Abstract Device) --> | ||
| <div class="hero-visual"> | ||
| <img src="./assets/hero-2.jpeg" alt="EchoKit Device" style="width: 100%; height: 100%; object-fit: cover;"> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </header> | ||
|
|
||
| <!-- 2. GALLERY SECTION (Images + Functional Audio) --> | ||
| <section id="gallery" class="section-padding" style="padding-top: 0;"> | ||
|
|
||
| <style> | ||
| .visual-mode-item { | ||
| position: relative; | ||
| border-radius: 16px; | ||
| overflow: hidden; | ||
| aspect-ratio: 1/1; | ||
| border: 1px solid rgba(255,255,255,0.15); | ||
| cursor: default; | ||
| } | ||
| .visual-mode-img { | ||
| width: 100%; | ||
| height: 100%; | ||
| object-fit: cover; | ||
| transition: transform 0.6s cubic-bezier(0.25, 1, 0.5, 1); | ||
| } | ||
| .visual-mode-item:hover .visual-mode-img { | ||
| transform: scale(1.1); | ||
| } | ||
| .visual-overlay { | ||
| position: absolute; | ||
| bottom: 0; left: 0; right: 0; | ||
| background: linear-gradient(to top, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0) 100%); | ||
| padding: 20px 15px 15px; | ||
| display: flex; | ||
| flex-direction: column; | ||
| justify-content: flex-end; | ||
| } | ||
| </style> | ||
|
|
||
| <div class="container"> | ||
| <div class="gallery-section"> | ||
| <div class="text-center gallery-header"> | ||
| <h2 style="color: white;">The <span class="serif-highlight" style="color:white; border-color:white;">Experience</span></h2> | ||
| <p>More than a gadget. It's your voice, your memories. Living on a pure black OLED canvas.</p> | ||
| </div> | ||
|
|
||
| <div class="gallery-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 40px; margin-top: 60px;"> | ||
|
|
||
| <!-- LEFT: 4 Visual Modes (Images) --> | ||
| <div class="gallery-card"> | ||
| <h3 style="color: white; margin-bottom: 20px;">Examples</h3> | ||
|
|
||
| <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> | ||
|
|
||
| <!-- Image 1: Birthday --> | ||
| <div class="visual-mode-item"> | ||
| <img src="./assets/showcase-01.jpeg" class="visual-mode-img" alt="Birthday Cake"> | ||
| <div class="visual-overlay"> | ||
| <i class="fas fa-birthday-cake" style="color: white; margin-bottom: 5px;"></i> | ||
| <span style="color: white; font-size: 0.8rem; font-weight: 500;">Birthday Mode</span> | ||
| </div> | ||
| </div> | ||
|
|
||
| <!-- Image 2: Stories (Book/Cozy) --> | ||
| <div class="visual-mode-item"> | ||
| <img src="./assets/showcase-02.jpeg" class="visual-mode-img" alt="Reading"> | ||
| <div class="visual-overlay"> | ||
| <i class="fas fa-book-open" style="color: white; margin-bottom: 5px;"></i> | ||
| <span style="color: white; font-size: 0.8rem; font-weight: 500;">Storytelling</span> | ||
| </div> | ||
| </div> | ||
|
|
||
| <!-- Image 3: Now Playing (Abstract/Music) --> | ||
| <div class="visual-mode-item"> | ||
| <img src="./assets/showcase-03.jpeg" class="visual-mode-img" alt="Music Waves"> | ||
| <div class="visual-overlay"> | ||
| <i class="fas fa-music" style="color: white; margin-bottom: 5px;"></i> | ||
| <span style="color: white; font-size: 0.8rem; font-weight: 500;">Now Playing</span> | ||
| </div> | ||
| </div> | ||
|
|
||
| <!-- Image 4: Photo Frame (Family) --> | ||
| <div class="visual-mode-item"> | ||
| <img src="./assets/showcase-04.jpeg" class="visual-mode-img" alt="Family Photo"> | ||
| <div class="visual-overlay"> | ||
| <i class="fas fa-image" style="color: white; margin-bottom: 5px;"></i> | ||
| <span style="color: white; font-size: 0.8rem; font-weight: 500;">Digital Frame</span> | ||
| </div> | ||
| </div> | ||
|
|
||
| </div> | ||
| </div> | ||
|
|
||
| <!-- RIGHT: 2 Audio Samples (Kept the functional audio) --> | ||
| <div style="display: flex; flex-direction: column; gap: 20px;"> | ||
|
|
||
| <!-- Audio Sample 1 --> | ||
| <div class="gallery-card"> | ||
| <h3 style="color: white; margin-bottom: 5px;">Grandma's Recipe</h3> | ||
| <p style="font-size: 0.85rem; opacity: 0.6; color: white;">Cloned from old cassette tapes.</p> | ||
|
|
||
| <div style="margin-top: 20px;"> | ||
| <div class="audio-player-ui" style="background: white; border-radius: 50px; padding: 10px 15px; display: flex; align-items: center; gap: 15px;"> | ||
| <div class="play-btn-circle" onclick="toggleAudio('audio1', this)" style="width: 35px; height: 35px; background: var(--text-main); border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer;"> | ||
| <i class="fas fa-play" style="color: white; font-size: 0.8rem;"></i> | ||
| </div> | ||
| <div style="height: 4px; background: #e4e4e7; flex-grow: 1; border-radius: 2px; overflow: hidden;"> | ||
| <div id="progress1" style="width: 0%; height: 100%; background: var(--accent-tech); transition: width 0.2s;"></div> | ||
| </div> | ||
| <span style="color: #18181b; font-size: 0.8rem; font-weight: 600;">0:12</span> | ||
| </div> | ||
| <audio id="audio1" src="./assets/grandma.mp3" ontimeupdate="updateProgress('audio1', 'progress1')" onended="resetPlayer('audio1', this)"></audio> | ||
| </div> | ||
| <p style="font-size: 0.85rem; margin-top:15px; opacity: 0.7; font-style: italic; color: white;">"Don't forget the cinnamon pinch..."</p> | ||
| </div> | ||
|
|
||
| <!-- Audio Sample 2 --> | ||
| <div class="gallery-card"> | ||
| <h3 style="color: #a5b4fc; margin-bottom: 5px;">AI Twin</h3> | ||
| <p style="font-size: 0.85rem; opacity: 0.6; color: white;">Your personal tone & style.</p> | ||
|
|
||
| <div style="margin-top: 20px;"> | ||
| <div class="audio-player-ui" style="background: white; border-radius: 50px; padding: 10px 15px; display: flex; align-items: center; gap: 15px;"> | ||
| <div class="play-btn-circle" onclick="toggleAudio('audio2', this)" style="width: 35px; height: 35px; background: var(--accent-tech); border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer;"> | ||
| <i class="fas fa-play" style="color: white; font-size: 0.8rem;"></i> | ||
| </div> | ||
| <div style="height: 4px; background: #e4e4e7; flex-grow: 1; border-radius: 2px; overflow: hidden;"> | ||
| <div id="progress2" style="width: 0%; height: 100%; background: var(--accent-tech); transition: width 0.2s;"></div> | ||
| </div> | ||
| <span style="color: #18181b; font-size: 0.8rem; font-weight: 600;">0:08</span> | ||
| </div> | ||
| <audio id="audio2" src="./assets/girl.mp3" ontimeupdate="updateProgress('audio2', 'progress2')" onended="resetPlayer('audio2', this)"></audio> | ||
| </div> | ||
| <p style="font-size: 0.85rem; margin-top:15px; opacity: 0.7; font-style: italic; color: white;">"I'm the digital twin of Emma..."</p> | ||
| </div> | ||
|
|
||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </section> | ||
|
|
||
| <script> | ||
| // Store currently playing audio to handle switching | ||
| let currentAudio = null; | ||
| let currentBtn = null; | ||
|
|
||
| function toggleAudio(audioId, btnElement) { | ||
| const audio = document.getElementById(audioId); | ||
| const icon = btnElement.querySelector('i'); | ||
|
|
||
| // If clicking a different audio while one is playing | ||
| if (currentAudio && currentAudio !== audio) { | ||
| currentAudio.pause(); | ||
| currentAudio.currentTime = 0; | ||
| // Reset the other button icon | ||
| if (currentBtn) { | ||
| currentBtn.querySelector('i').classList.remove('fa-pause'); | ||
| currentBtn.querySelector('i').classList.add('fa-play'); | ||
| } | ||
| } | ||
|
|
||
| if (audio.paused) { | ||
| audio.play(); | ||
| icon.classList.remove('fa-play'); | ||
| icon.classList.add('fa-pause'); | ||
| currentAudio = audio; | ||
| currentBtn = btnElement; | ||
| } else { | ||
| audio.pause(); | ||
| icon.classList.remove('fa-pause'); | ||
| icon.classList.add('fa-play'); | ||
| currentAudio = null; | ||
| currentBtn = null; | ||
| } | ||
| } | ||
|
|
||
| function updateProgress(audioId, progressId) { | ||
| const audio = document.getElementById(audioId); | ||
| const progressBar = document.getElementById(progressId); | ||
| if (audio.duration) { | ||
| const percentage = (audio.currentTime / audio.duration) * 100; | ||
| progressBar.style.width = percentage + '%'; | ||
| } | ||
| } | ||
|
|
||
| function resetPlayer(audioId, audioEl) { | ||
| // Find the button associated with this audio (traverse up to container then find button) | ||
| // Or simpler: verify if this is the current playing one | ||
| if (currentAudio === audioEl) { | ||
| const icon = currentBtn.querySelector('i'); | ||
| icon.classList.remove('fa-pause'); | ||
| icon.classList.add('fa-play'); | ||
| currentAudio = null; | ||
| // Reset progress bar visually | ||
| const progressBarId = audioId === 'audio1' ? 'progress1' : 'progress2'; | ||
| document.getElementById(progressBarId).style.width = '0%'; | ||
| } | ||
| } | ||
| </script> | ||
|
|
||
| <!-- 3. FEATURES --> | ||
| <section id="features" class="section-padding" style="background: white;"> | ||
| <div class="container"> | ||
| <div class="text-center"> | ||
| <h2>Why it feels <span class="serif-highlight">Magic</span></h2> | ||
| </div> | ||
| <div class="features-grid"> | ||
| <div class="feature-box"> | ||
| <div class="feature-icon"><i class="fas fa-wand-magic-sparkles"></i></div> | ||
| <h3>Ultimate Customization</h3> | ||
| <p>Every EchoKit is unique. We manually deploy a custom AI model trained specifically on your provided stories and voice data, ensuring the response style is exclusively yours.</p> | ||
| </div> | ||
| <div class="feature-box"> | ||
| <div class="feature-icon" style="color: var(--accent-warm);"><i class="fas fa-heart"></i></div> | ||
| <h3>Emotional Connection</h3> | ||
| <p>It’s not just a speaker; it’s a time capsule. Without the distraction of a touchscreen, the <strong>Voice-Only Interface</strong> encourages deeper, more natural conversations.</p> | ||
| </div> | ||
| </div> | ||
| </section> | ||
|
|
||
| <!-- 4. STUDIO (Dashboard Layout) --> | ||
| <section id="studio" class="section-padding"> | ||
| <div class="container"> | ||
| <div class="text-center"> | ||
| <h2>The <span class="serif-highlight">Creator Studio</span></h2> | ||
| <p>Before we ship the box, you craft the soul.</p> | ||
| </div> | ||
|
|
||
| <div class="studio-layout"> | ||
| <!-- Left: Steps --> | ||
| <div class="step-list"> | ||
| <div class="step-item active"> | ||
| <div class="step-num">1</div> | ||
| <div> | ||
| <h4>Voice Lab</h4> | ||
| <p style="font-size: 0.9rem;">Upload 3 minutes of audio to clone a voice.</p> | ||
| </div> | ||
| </div> | ||
| <div class="step-item"> | ||
| <div class="step-num">2</div> | ||
| <div> | ||
| <h4>Personality</h4> | ||
| <p style="font-size: 0.9rem;">Customize the tone, style and behavior.</p> | ||
| </div> | ||
| </div> | ||
| <div class="step-item"> | ||
| <div class="step-num">3</div> | ||
| <div> | ||
| <h4>Knowledge Base</h4> | ||
| <p style="font-size: 0.9rem;">Type inside knowlaedge and jokes.</p> | ||
| </div> | ||
| </div> | ||
| </div> | ||
|
|
||
| <!-- Right: Mockup --> | ||
| <div class="studio-mockup"> | ||
| <div class="mockup-header"> | ||
| <span style="font-weight: 700;">Project: Grandma's 80th</span> | ||
| <span style="background: #dcfce7; color: #166534; padding: 2px 10px; border-radius: 10px; font-size: 0.8rem;">Drafting</span> | ||
| </div> | ||
| <div style="background: #f8fafc; border: 2px dashed #cbd5e1; border-radius: 12px; height: 200px; display: flex; align-items: center; justify-content: center; color: #94a3b8; flex-direction: column; gap: 10px;"> | ||
| <i class="fas fa-cloud-upload-alt" style="font-size: 2rem;"></i> | ||
| <span>Drag & Drop Audio Files Here</span> | ||
| </div> | ||
| <div style="text-align: center; margin-top: 30px;"> | ||
| <button class="btn btn-primary">Enter Studio & Start</button> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </section> | ||
|
|
||
| <!-- 5. UNBOXING (Bento Grid) --> | ||
| <section id="unboxing" class="section-padding bento-section"> | ||
| <div class="container"> | ||
| <div class="text-center" style="margin-bottom: 50px;"> | ||
| <h2>Premium <span class="serif-highlight">Unboxing</span></h2> | ||
| <p>Designed to be gifted.</p> | ||
| </div> | ||
|
|
||
| <div class="bento-grid"> | ||
| <!-- Main Item: Device --> | ||
| <div class="bento-item bento-main"> | ||
| <div style="position: relative; z-index: 2;"> | ||
| <h3 style="color: white; font-size: 2rem;">EchoKit Device</h3> | ||
| <p style="color: #a1a1aa;">A talking device in your design. Pre-loaded with your custom AI.</p> | ||
| <ul style="margin-top: 20px; color: #d4d4d8;"> | ||
| <li><i class="fas fa-check"></i> 2.4-inch OLED Screen</li> | ||
| <li><i class="fas fa-check"></i> WiFi 2.4 GHz, Bluetooth 5.0 LE</li> | ||
| </ul> | ||
| </div> | ||
| <i class="fas fa-tv bento-icon-lg" style="color: white;"></i> | ||
| </div> | ||
|
|
||
| <!-- Item 2: Gift Card --> | ||
| <div class="bento-item bento-card"> | ||
| <div style="position: relative; z-index: 2;"> | ||
| <h4 style="color: #3730a3;">Voice Pass</h4> | ||
| <p style="font-size: 0.9rem; color: #4338ca;">Comes with 2 hours of AI conversation monthly on us.</p> | ||
| </div> | ||
| <i class="fas fa-qrcode bento-icon-lg" style="color: #4338ca;"></i> | ||
| </div> | ||
|
|
||
| <!-- Item 3: Accessories --> | ||
| <div class="bento-item bento-acc"> | ||
| <div style="position: relative; z-index: 2;"> | ||
| <h4 style="color: #9a3412;">Accessories</h4> | ||
| <p style="font-size: 0.9rem; color: #c2410c;">Premium braided cable & power bank included.</p> | ||
| </div> | ||
| <i class="fas fa-plug bento-icon-lg" style="color: #c2410c;"></i> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </section> | ||
|
|
||
| <!-- PRICING --> | ||
| <section id="pricing" class="section-padding" style="background: white;"> | ||
| <div class="container"> | ||
| <div class="text-center" style="margin-bottom: 50px;"> | ||
| <h2>Gift Editions</h2> | ||
| </div> | ||
|
|
||
| <div class="pricing-grid"> | ||
| <!-- Starter --> | ||
| <div class="price-card"> | ||
| <h3 style="font-family: var(--font-serif);">Starter Gift</h3> | ||
| <div style="font-size: 2.5rem; font-weight: 800; margin: 10px 0;">$89</div> | ||
| <p style="font-size: 0.9rem; margin-bottom: 20px;">Perfect for visual storytelling.</p> | ||
| <a href="#studio" class="btn btn-outline">Select Starter</a> | ||
| <ul style="margin-top: 30px; font-size: 0.9rem; display: flex; flex-direction: column; gap: 10px;"> | ||
| <li><i class="fas fa-check" style="color: var(--text-main);"></i> Custom Bootscreen</li> | ||
| <li><i class="fas fa-check" style="color: var(--text-main);"></i> Custom Welcome Voice</li> | ||
| <li><i class="fas fa-check" style="color: var(--text-main);"></i> Choose Any pre-trained Voice</li> | ||
| <li><i class="fas fa-check" style="color: var(--text-main);"></i> Customize Personality via System Prompt</li> | ||
| </ul> | ||
| </div> | ||
|
|
||
| <!-- Advanced --> | ||
| <div class="price-card featured"> | ||
| <div class="popular-badge">Most Gifted</div> | ||
| <h3 style="font-family: var(--font-serif);">Advanced Edition</h3> | ||
| <div style="font-size: 2.5rem; font-weight: 800; margin: 10px 0;">$199</div> | ||
| <p style="font-size: 0.9rem; margin-bottom: 20px;">Deep customization with voice cloning.</p> | ||
| <a href="#studio" class="btn btn-primary">Craft This Gift</a> | ||
| <ul style="margin-top: 30px; font-size: 0.9rem; display: flex; flex-direction: column; gap: 10px;"> | ||
| <li><i class="fas fa-check" style="color: var(--accent-tech);"></i> <strong>Everything in Starter</strong></li> | ||
| <li><i class="fas fa-check" style="color: var(--accent-tech);"></i> Voice Cloning</li> | ||
| <li><i class="fas fa-check" style="color: var(--accent-tech);"></i> Long Memory Vector</li> | ||
| <li><i class="fas fa-check" style="color: var(--accent-tech);"></i> MCP Tools</li> | ||
| </ul> | ||
| </div> | ||
|
|
||
| <!-- Corporate --> | ||
| <div class="price-card"> | ||
| <h3 style="font-family: var(--font-serif);">Corporate Box</h3> | ||
| <div style="font-size: 2.5rem; font-weight: 800; margin: 10px 0;">Custom</div> | ||
| <p style="font-size: 0.9rem; margin-bottom: 20px;">High-end gifts for VIP clients.</p> | ||
| <a href="#" class="btn btn-outline">Contact Sales</a> | ||
| <ul style="margin-top: 30px; font-size: 0.9rem; display: flex; flex-direction: column; gap: 10px;"> | ||
| <li><i class="fas fa-check" style="color: var(--text-main);"></i> Self-hosted Server</li> | ||
| <li><i class="fas fa-check" style="color: var(--text-main);"></i> Bulk Management</li> | ||
| </ul> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </section> | ||
|
|
||
| <!-- PROCESS (Timeline) --> | ||
| <section class="section-padding"> | ||
| <div class="container"> | ||
| <h3 class="text-center" style="margin-bottom: 40px;">Timeline</h3> | ||
| <div style="display: flex; flex-wrap: wrap; gap: 20px; justify-content: center; text-align: center;"> | ||
| <div style="flex: 1; min-width: 200px;"> | ||
| <div style="font-weight: 700; margin-bottom: 5px;">1. Prepare the data</div> | ||
| <p style="font-size: 0.85rem;">Upload materials (1 days)</p> | ||
| </div> | ||
| <div style="font-size: 1.5rem; color: #e4e4e7;">→</div> | ||
| <div style="flex: 1; min-width: 200px;"> | ||
| <div style="font-weight: 700; margin-bottom: 5px;">2. Training</div> | ||
| <p style="font-size: 0.85rem;">AI Model Training (5 days)</p> | ||
| </div> | ||
| <div style="font-size: 1.5rem; color: #e4e4e7;">→</div> | ||
| <div style="flex: 1; min-width: 200px;"> | ||
| <div style="font-weight: 700; margin-bottom: 5px;">3. Delivery</div> | ||
| <p style="font-size: 0.85rem;">World global Shipping</p> |
There was a problem hiding this comment.
Best practices violation: Inline styles are extensively used throughout the HTML instead of using CSS classes. This makes the code harder to maintain and reuse. For example, lines 279, 285, 288, 337, and many others contain inline style attributes that should be moved to CSS classes.
| <img src="./assets/showcase-01.jpeg" class="visual-mode-img" alt="Birthday Cake"> | ||
| <div class="visual-overlay"> | ||
| <i class="fas fa-birthday-cake" style="color: white; margin-bottom: 5px;"></i> | ||
| <span style="color: white; font-size: 0.8rem; font-weight: 500;">Birthday Mode</span> | ||
| </div> | ||
| </div> | ||
|
|
||
| <!-- Image 2: Stories (Book/Cozy) --> | ||
| <div class="visual-mode-item"> | ||
| <img src="./assets/showcase-02.jpeg" class="visual-mode-img" alt="Reading"> | ||
| <div class="visual-overlay"> | ||
| <i class="fas fa-book-open" style="color: white; margin-bottom: 5px;"></i> | ||
| <span style="color: white; font-size: 0.8rem; font-weight: 500;">Storytelling</span> | ||
| </div> | ||
| </div> | ||
|
|
||
| <!-- Image 3: Now Playing (Abstract/Music) --> | ||
| <div class="visual-mode-item"> | ||
| <img src="./assets/showcase-03.jpeg" class="visual-mode-img" alt="Music Waves"> | ||
| <div class="visual-overlay"> | ||
| <i class="fas fa-music" style="color: white; margin-bottom: 5px;"></i> | ||
| <span style="color: white; font-size: 0.8rem; font-weight: 500;">Now Playing</span> | ||
| </div> | ||
| </div> | ||
|
|
||
| <!-- Image 4: Photo Frame (Family) --> | ||
| <div class="visual-mode-item"> | ||
| <img src="./assets/showcase-04.jpeg" class="visual-mode-img" alt="Family Photo"> | ||
| <div class="visual-overlay"> | ||
| <i class="fas fa-image" style="color: white; margin-bottom: 5px;"></i> | ||
| <span style="color: white; font-size: 0.8rem; font-weight: 500;">Digital Frame</span> | ||
| </div> | ||
| </div> |
There was a problem hiding this comment.
Accessibility issue: All images in the gallery section lack alt text. The img tags should have descriptive alt attributes for screen readers to understand the visual content being displayed.
| <div class="audio-player-ui" style="background: white; border-radius: 50px; padding: 10px 15px; display: flex; align-items: center; gap: 15px;"> | ||
| <div class="play-btn-circle" onclick="toggleAudio('audio1', this)" style="width: 35px; height: 35px; background: var(--text-main); border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer;"> | ||
| <i class="fas fa-play" style="color: white; font-size: 0.8rem;"></i> | ||
| </div> | ||
| <div style="height: 4px; background: #e4e4e7; flex-grow: 1; border-radius: 2px; overflow: hidden;"> | ||
| <div id="progress1" style="width: 0%; height: 100%; background: var(--accent-tech); transition: width 0.2s;"></div> | ||
| </div> | ||
| <span style="color: #18181b; font-size: 0.8rem; font-weight: 600;">0:12</span> | ||
| </div> | ||
| <audio id="audio1" src="./assets/grandma.mp3" ontimeupdate="updateProgress('audio1', 'progress1')" onended="resetPlayer('audio1', this)"></audio> | ||
| </div> | ||
| <p style="font-size: 0.85rem; margin-top:15px; opacity: 0.7; font-style: italic; color: white;">"Don't forget the cinnamon pinch..."</p> | ||
| </div> | ||
|
|
||
| <!-- Audio Sample 2 --> | ||
| <div class="gallery-card"> | ||
| <h3 style="color: #a5b4fc; margin-bottom: 5px;">AI Twin</h3> | ||
| <p style="font-size: 0.85rem; opacity: 0.6; color: white;">Your personal tone & style.</p> | ||
|
|
||
| <div style="margin-top: 20px;"> | ||
| <div class="audio-player-ui" style="background: white; border-radius: 50px; padding: 10px 15px; display: flex; align-items: center; gap: 15px;"> | ||
| <div class="play-btn-circle" onclick="toggleAudio('audio2', this)" style="width: 35px; height: 35px; background: var(--accent-tech); border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer;"> | ||
| <i class="fas fa-play" style="color: white; font-size: 0.8rem;"></i> | ||
| </div> | ||
| <div style="height: 4px; background: #e4e4e7; flex-grow: 1; border-radius: 2px; overflow: hidden;"> | ||
| <div id="progress2" style="width: 0%; height: 100%; background: var(--accent-tech); transition: width 0.2s;"></div> | ||
| </div> | ||
| <span style="color: #18181b; font-size: 0.8rem; font-weight: 600;">0:08</span> | ||
| </div> | ||
| <audio id="audio2" src="./assets/girl.mp3" ontimeupdate="updateProgress('audio2', 'progress2')" onended="resetPlayer('audio2', this)"></audio> |
There was a problem hiding this comment.
Accessibility issue: The audio players lack proper ARIA labels and keyboard navigation support. The play buttons should have aria-label attributes to describe their function, and the custom audio controls should be keyboard accessible with appropriate event handlers for Enter/Space keys.
| </p> | ||
| <div style="display: flex; gap: 15px;"> | ||
| <a href="https://form.jotform.com/253442751110042" class="btn btn-primary">Build your Own</a> | ||
| <a href="#gallery" class="btn btn-outline"><i class="fas fa-play"></i> Watch Demo</a> |
There was a problem hiding this comment.
Accessibility issue: Multiple buttons and links lack descriptive text for screen readers. For example, the "Watch Demo" link icon should have sr-only text, and navigation links should have clearer context when read by screen readers.
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | ||
| <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700&family=Playfair+Display:ital,wght@0,500;0,600;1,400&display=swap" rel="stylesheet"> | ||
| <!-- Font Awesome --> | ||
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
There was a problem hiding this comment.
Security concern: External resources are loaded from CDNs (Google Fonts, cdnjs) without Subresource Integrity (SRI) attributes. This exposes users to potential supply chain attacks if these CDNs are compromised. Consider adding integrity and crossorigin attributes to the link tags.
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-papm6H1Qb6QwQK4Q1r5l6QwO5jM90+hCbGyF/F7fs/3Gzdh0dX8GZFODdgNpTiFqouBZfyqCk41sJLbvOjFh1w==" crossorigin="anonymous"> |
| <div class="play-btn-circle" onclick="toggleAudio('audio1', this)" style="width: 35px; height: 35px; background: var(--text-main); border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer;"> | ||
| <i class="fas fa-play" style="color: white; font-size: 0.8rem;"></i> | ||
| </div> | ||
| <div style="height: 4px; background: #e4e4e7; flex-grow: 1; border-radius: 2px; overflow: hidden;"> | ||
| <div id="progress1" style="width: 0%; height: 100%; background: var(--accent-tech); transition: width 0.2s;"></div> | ||
| </div> | ||
| <span style="color: #18181b; font-size: 0.8rem; font-weight: 600;">0:12</span> | ||
| </div> | ||
| <audio id="audio1" src="./assets/grandma.mp3" ontimeupdate="updateProgress('audio1', 'progress1')" onended="resetPlayer('audio1', this)"></audio> | ||
| </div> | ||
| <p style="font-size: 0.85rem; margin-top:15px; opacity: 0.7; font-style: italic; color: white;">"Don't forget the cinnamon pinch..."</p> | ||
| </div> | ||
|
|
||
| <!-- Audio Sample 2 --> | ||
| <div class="gallery-card"> | ||
| <h3 style="color: #a5b4fc; margin-bottom: 5px;">AI Twin</h3> | ||
| <p style="font-size: 0.85rem; opacity: 0.6; color: white;">Your personal tone & style.</p> | ||
|
|
||
| <div style="margin-top: 20px;"> | ||
| <div class="audio-player-ui" style="background: white; border-radius: 50px; padding: 10px 15px; display: flex; align-items: center; gap: 15px;"> | ||
| <div class="play-btn-circle" onclick="toggleAudio('audio2', this)" style="width: 35px; height: 35px; background: var(--accent-tech); border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer;"> |
There was a problem hiding this comment.
Accessibility issue: Interactive elements that use onclick handlers (lines 398, 418) should also be keyboard accessible. Add tabindex="0" and handle keyboard events (keydown with Enter/Space) to ensure users can interact with these elements using keyboard only.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Michael Yuan <michael@secondstate.io>
No description provided.