Home Battery Storage Systems | Guardian Elite Series | SunFusion Energy

Advanced Home Battery Storage Systems for 2025

Power Your Future with American-Made Energy Independence

Made in San Diego, USA

16kWh Capacity

15kW Integrated Inverter

99.1% Efficiency

25-Year Warranty

NEMA 3R Rated

Revolutionary Home Energy Storage Solutions

Guardian E2.0 Battery System

Guardian E2.0

  • Professional Grade
  • Scalable Design
  • Advanced BMS
View Details
ECHO Series Battery System

ECHO Series

  • Modular Design
  • Expandable Capacity
  • Flexible Installation
Explore Options

Industry-Leading Technology

Hithium USA Cells

Premium grade battery cells for optimal performance

Advanced BMS

Smart monitoring and management system

UL & NEC Certified

Meeting highest safety standards

100% Recyclable

Environmentally conscious design

Plan Your Energy Future

System Sizing Calculator

Find your perfect system size

Start

Energy Savings Estimator

Calculate your potential savings

Start

ROI Calculator

Evaluate your investment return

Start

Start Your Energy Independence Journey

/* Core Variables */ :root { /* Brand Colors */ --primary-color: #0066CC; --secondary-color: #1E3A8A; --accent-color: #22C55E; --dark: #1F2937; --light: #F3F4F6; /* Typography */ --heading-font: 'Montserrat', sans-serif; --body-font: 'Inter', sans-serif; /* Spacing */ --container-width: 1280px; --section-spacing: 6rem; --element-spacing: 2rem; /* Transitions */ --transition-fast: 0.3s ease; --transition-slow: 0.5s ease; /* Shadows */ --shadow-sm: 0 2px 4px rgba(0,0,0,0.1); --shadow-md: 0 4px 6px rgba(0,0,0,0.1); --shadow-lg: 0 10px 15px rgba(0,0,0,0.1); } /* Reset & Base Styles */ * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: var(--body-font); line-height: 1.6; color: var(--dark); overflow-x: hidden; } /* Typography */ h1, h2, h3, h4, h5, h6 { font-family: var(--heading-font); font-weight: 700; line-height: 1.2; margin-bottom: 1rem; } h1 { font-size: clamp(2.5rem, 5vw, 4rem); } h2 { font-size: clamp(2rem, 4vw, 3rem); } h3 { font-size: clamp(1.5rem, 3vw, 2rem); } /* Layout Components */ .container { max-width: var(--container-width); margin: 0 auto; padding: 0 1rem; } /* Header & Navigation */ .main-header { position: fixed; top: 0; left: 0; right: 0; background: white; box-shadow: var(--shadow-sm); z-index: 1000; } .navbar { display: flex; justify-content: space-between; align-items: center; padding: 1rem var(--element-spacing); max-width: var(--container-width); margin: 0 auto; } .nav-menu { display: flex; gap: 2rem; list-style: none; } /* Hero Section */ .hero { min-height: 100vh; display: flex; align-items: center; background: linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.5)), url('/hero-bg.jpg') center/cover; color: white; padding: var(--section-spacing) 0; margin-top: 4rem; } .hero-content { max-width: 800px; margin: 0 auto; text-align: center; padding: 0 1rem; } /* Buttons */ .btn { display: inline-block; padding: 1rem 2rem; border-radius: 0.5rem; text-decoration: none; font-weight: 600; transition: var(--transition-fast); cursor: pointer; border: none; } .btn-primary { background: var(--primary-color); color: white; } .btn-secondary { background: transparent; border: 2px solid var(--primary-color); color: var(--primary-color); } /* Benefits Banner */ .benefits-banner { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 2rem; padding: var(--element-spacing); background: var(--light); } /* Product Showcase */ .product-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; padding: var(--element-spacing); } .product-card { background: white; border-radius: 1rem; padding: 2rem; box-shadow: var(--shadow-md); transition: var(--transition-fast); } .product-card:hover { transform: translateY(-5px); box-shadow: var(--shadow-lg); } /* Technical Excellence */ .tech-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 2rem; padding: var(--element-spacing); } /* Interactive Tools */ .tools-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; padding: var(--element-spacing); } /* Footer */ .footer-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 3rem; padding: var(--section-spacing) var(--element-spacing); background: var(--dark); color: white; } /* Responsive Design */ @media (max-width: 768px) { .nav-menu { display: none; } .hero-content { padding: 0 1rem; } .benefits-banner { grid-template-columns: 1fr; } } /* Animations */ @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .fade-in { animation: fadeIn 1s ease-in; } /* Forms */ .form-group { margin-bottom: 1rem; } input, textarea { width: 100%; padding: 0.75rem; border: 1px solid #ddd; border-radius: 0.5rem; font-family: var(--body-font); } /* Utility Classes */ .text-center { text-align: center; } .mt-1 { margin-top: 1rem; } .mt-2 { margin-top: 2rem; } .mb-1 { margin-bottom: 1rem; } .mb-2 { margin-bottom: 2rem; } // Main JavaScript File (main.js) // Wait for DOM to be fully loaded document.addEventListener('DOMContentLoaded', function() { // Initialize all components initNavigation(); initSmoothScroll(); initProductCalculator(); initTestimonialCarousel(); initFormValidation(); initAnalytics(); initCookieConsent(); initChatWidget(); }); // Navigation Handler const initNavigation = () => { const header = document.querySelector('.main-header'); const mobileMenuBtn = document.querySelector('.mobile-menu-btn'); const nav = document.querySelector('.nav-menu'); // Sticky Header window.addEventListener('scroll', () => { if (window.scrollY > 100) { header.classList.add('sticky'); } else { header.classList.remove('sticky'); } }); // Mobile Menu Toggle mobileMenuBtn?.addEventListener('click', () => { nav.classList.toggle('active'); }); }; // Smooth Scroll Implementation const initSmoothScroll = () => { document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); target.scrollIntoView({ behavior: 'smooth', block: 'start' }); }); }); }; // Product Calculator const initProductCalculator = () => { const calculator = document.querySelector('.energy-calculator'); if (!calculator) return; const calculateEnergySavings = (usage, rate) => { // Basic calculation logic const dailyUsage = parseFloat(usage); const electricityRate = parseFloat(rate); const annualSavings = dailyUsage * electricityRate * 365 * 0.8; // Assuming 80% efficiency return annualSavings.toFixed(2); }; calculator.addEventListener('submit', (e) => { e.preventDefault(); const usage = document.querySelector('#daily-usage').value; const rate = document.querySelector('#electricity-rate').value; const savings = calculateEnergySavings(usage, rate); document.querySelector('#savings-result').textContent = `Estimated Annual Savings: \$\${savings}`; }); }; // Testimonial Carousel const initTestimonialCarousel = () => { const carousel = document.querySelector('.testimonials-carousel'); if (!carousel) return; let currentSlide = 0; const slides = carousel.querySelectorAll('.testimonial-slide'); const totalSlides = slides.length; const showSlide = (index) => { slides.forEach(slide => slide.style.display = 'none'); slides[index].style.display = 'block'; }; setInterval(() => { currentSlide = (currentSlide + 1) % totalSlides; showSlide(currentSlide); }, 5000); }; // Form Validation const initFormValidation = () => { const forms = document.querySelectorAll('form'); forms.forEach(form => { form.addEventListener('submit', async (e) => { e.preventDefault(); if (validateForm(form)) { try { await submitForm(form); showSuccess(form); } catch (error) { showError(form, error); } } }); }); const validateForm = (form) => { let isValid = true; const inputs = form.querySelectorAll('input, textarea'); inputs.forEach(input => { if (input.hasAttribute('required') && !input.value) { markInvalid(input); isValid = false; } else { markValid(input); } }); return isValid; }; const markInvalid = (input) => { input.classList.add('invalid'); const errorMsg = input.getAttribute('data-error') || 'This field is required'; showInputError(input, errorMsg); }; const markValid = (input) => { input.classList.remove('invalid'); hideInputError(input); }; }; // Analytics Implementation const initAnalytics = () => { // Google Analytics window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'YOUR-GA-ID'); // Track specific events trackPageViews(); trackButtonClicks(); trackFormSubmissions(); }; // Cookie Consent const initCookieConsent = () => { const cookieConsent = document.querySelector('.cookie-consent'); const acceptBtn = cookieConsent?.querySelector('.accept-cookies'); if (!localStorage.getItem('cookieConsent')) { cookieConsent?.classList.add('active'); } acceptBtn?.addEventListener('click', () => { localStorage.setItem('cookieConsent', 'true'); cookieConsent.classList.remove('active'); }); }; // Chat Widget const initChatWidget = () => { const chatWidget = document.querySelector('.chat-widget'); const chatToggle = chatWidget?.querySelector('.chat-toggle'); chatToggle?.addEventListener('click', () => { chatWidget.classList.toggle('active'); }); }; // Utility Functions const debounce = (func, wait) => { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; }; const formatCurrency = (amount) => { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(amount); }; // API Handlers const submitForm = async (form) => { const formData = new FormData(form); try { const response = await fetch('/api/submit-form', { method: 'POST', body: formData }); return await response.json(); } catch (error) { console.error('Form submission error:', error); throw error; } }; // Animation Handlers const initAnimations = () => { const animatedElements = document.querySelectorAll('.animate'); const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('animated'); } }); }); animatedElements.forEach(element => observer.observe(element)); }; // tracking.js // Google Tag Manager (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-XXXXX'); // Facebook Pixel !function(f,b,e,v,n,t,s) {if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)}; if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0]; s.parentNode.insertBefore(t,s)}(window, document,'script', 'https://connect.facebook.net/en_US/fbevents.js'); fbq('init', 'YOUR-PIXEL-ID'); fbq('track', 'PageView'); // tracking.js // Google Tag Manager (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-XXXXX'); // Facebook Pixel !function(f,b,e,v,n,t,s) {if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)}; if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0]; s.parentNode.insertBefore(t,s)}(window, document,'script', 'https://connect.facebook.net/en_US/fbevents.js'); fbq('init', 'YOUR-PIXEL-ID'); fbq('track', 'PageView'); // chat.js class ChatWidget { constructor() { this.messages = []; this.initializeWidget(); } initializeWidget() { // Chat widget initialization code } // Additional chat methods } // api/index.js - Main API Handler const API_BASE_URL = 'https://api.sunfusion.us/v1'; const API_KEY = 'your_api_key'; // Store this securely // API Authentication Handler class APIAuth { static getHeaders() { return { 'Authorization': `Bearer \${API_KEY}`, 'Content-Type': 'application/json' }; } } // Main API Client class APIClient { static async get(endpoint) { try { const response = await fetch(`\${API_BASE_URL}\${endpoint}`, { method: 'GET', headers: APIAuth.getHeaders() }); return await response.json(); } catch (error) { console.error('API Get Error:', error); throw error; } } static async post(endpoint, data) { try { const response = await fetch(`\${API_BASE_URL}\${endpoint}`, { method: 'POST', headers: APIAuth.getHeaders(), body: JSON.stringify(data) }); return await response.json(); } catch (error) { console.error('API Post Error:', error); throw error; } } } // Calculator Service class EnergyCalculator { static async calculateSavings(data) { const endpoint = '/calculator/savings'; return await APIClient.post(endpoint, data); } static async getUtilityRates(zipCode) { const endpoint = `/utility-rates/\${zipCode}`; return await APIClient.get(endpoint); } static async getSolarProduction(location) { const endpoint = '/solar-production'; return await APIClient.post(endpoint, location); } } // Lead Management System class LeadManager { static async submitLead(leadData) { const endpoint = '/leads'; return await APIClient.post(endpoint, leadData); } static async validateEmail(email) { const endpoint = '/validate/email'; return await APIClient.post(endpoint, { email }); } } // Chat System Implementation class ChatSystem { constructor() { this.socket = null; this.messageQueue = []; this.initializeSocket(); } initializeSocket() { this.socket = new WebSocket('wss://chat.sunfusion.us'); this.socket.onopen = () => { console.log('Chat connection established'); this.processMessageQueue(); }; this.socket.onmessage = (event) => { this.handleIncomingMessage(JSON.parse(event.data)); }; this.socket.onclose = () => { console.log('Chat connection closed'); setTimeout(() => this.initializeSocket(), 5000); }; } async sendMessage(message) { if (this.socket.readyState === WebSocket.OPEN) { this.socket.send(JSON.stringify(message)); } else { this.messageQueue.push(message); } } processMessageQueue() { while (this.messageQueue.length > 0) { const message = this.messageQueue.shift(); this.sendMessage(message); } } handleIncomingMessage(message) { // Handle different message types switch (message.type) { case 'chat': this.displayMessage(message); break; case 'status': this.updateStatus(message); break; case 'system': this.handleSystemMessage(message); break; } } } // Analytics Enhancement class AnalyticsEnhanced { static trackEvent(category, action, label = null, value = null) { // Google Analytics gtag('event', action, { 'event_category': category, 'event_label': label, 'value': value }); // Facebook Pixel fbq('trackCustom', action, { category: category, label: label, value: value }); // LinkedIn Insight if (window.lintrk) { window.lintrk('track', { conversion_id: action }); } } static trackPageView(pageTitle, path) { gtag('config', 'GA-TRACKING-ID', { 'page_title': pageTitle, 'page_path': path }); fbq('track', 'PageView'); } static trackConversion(value, currency = 'USD') { gtag('event', 'conversion', { 'send_to': 'AW-CONVERSION-ID/LABEL', 'value': value, 'currency': currency }); fbq('track', 'Purchase', { value: value, currency: currency }); } } // Form Validation Enhancement class FormValidator { static validateField(field) { const value = field.value.trim(); const type = field.getAttribute('data-validate'); switch (type) { case 'email': return this.validateEmail(value); case 'phone': return this.validatePhone(value); case 'zipcode': return this.validateZipCode(value); default: return this.validateRequired(value); } } static validateEmail(email) { const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return regex.test(email); } static validatePhone(phone) { const regex = /^$?([0-9]{3})$?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/; return regex.test(phone); } static validateZipCode(zipCode) { const regex = /(^\d{5}\$)|(^\d{5}-\d{4}$)/; return regex.test(zipCode); } static validateRequired(value) { return value.length > 0; } } // Interactive Product Viewer class ProductViewer { constructor(containerId) { this.container = document.getElementById(containerId); this.currentAngle = 0; this.images = []; this.isLoading = true; this.init(); } async init() { await this.loadImages(); this.setupControls(); this.render(); } async loadImages() { // Load 360-degree product images for (let i = 0; i < 36; i++) { const img = new Image(); img.src = `/assets/product-360/\${i * 10}.jpg`; this.images.push(img); } await Promise.all(this.images.map(img => { return new Promise((resolve) => { img.onload = resolve; }); })); this.isLoading = false; } setupControls() { let isDragging = false; let startX = 0; let startAngle = 0; this.container.addEventListener('mousedown', (e) => { isDragging = true; startX = e.clientX; startAngle = this.currentAngle; }); document.addEventListener('mousemove', (e) => { if (!isDragging) return; const dx = e.clientX - startX; this.currentAngle = startAngle + dx; this.render(); }); document.addEventListener('mouseup', () => { isDragging = false; }); } render() { if (this.isLoading) return; const index = Math.floor(((this.currentAngle % 360) + 360) % 360 / 10); const ctx = this.container.getContext('2d'); ctx.clearRect(0, 0, this.container.width, this.container.height); ctx.drawImage(this.images[index], 0, 0); } } // Initialize all components document.addEventListener('DOMContentLoaded', () => { // Initialize Product Viewer const productViewer = new ProductViewer('product-viewer'); // Initialize Chat System const chatSystem = new ChatSystem(); // Setup Form Validation document.querySelectorAll('form').forEach(form => { form.addEventListener('submit', async (e) => { e.preventDefault(); const isValid = Array.from(form.elements).every(field => FormValidator.validateField(field) ); if (isValid) { const formData = new FormData(form); try { const response = await LeadManager.submitLead( Object.fromEntries(formData) ); AnalyticsEnhanced.trackConversion(response.value); showSuccess(form); } catch (error) { showError(form, error); } } }); }); // Initialize Calculator const calculatorForm = document.querySelector('.calculator-form'); if (calculatorForm) { calculatorForm.addEventListener('submit', async (e) => { e.preventDefault(); const formData = new FormData(calculatorForm); const results = await EnergyCalculator.calculateSavings( Object.fromEntries(formData) ); displayCalculatorResults(results); }); } });
Loading 360° View...

Guardian Elite System

Energy Savings Calculator

Calculate your potential savings with SunFusion

SunFusion Support

Welcome to SunFusion Support! How can we help you today?

Get Your Custom Quote

Compare Our Solutions

Find the perfect energy storage solution for your needs

Features Guardian Elite Guardian E2.0 ECHO Series
/* Component Styles - components.css */ /* Variables and Custom Properties */ :root { /* Brand Colors */ --primary-blue: #0066CC; --secondary-blue: #1E3A8A; --accent-green: #22C55E; --warning: #FFA500; --error: #DC2626; --success: #059669; /* Gradients */ --primary-gradient: linear-gradient(135deg, var(--primary-blue), var(--secondary-blue)); --accent-gradient: linear-gradient(135deg, var(--accent-green), #198754); /* Shadows */ --shadow-sm: 0 2px 4px rgba(0,0,0,0.1); --shadow-md: 0 4px 6px rgba(0,0,0,0.1); --shadow-lg: 0 10px 15px rgba(0,0,0,0.1); --shadow-xl: 0 20px 25px rgba(0,0,0,0.1); /* Animations */ --transition-fast: 0.3s ease; --transition-medium: 0.5s ease; --transition-slow: 0.7s ease; } /* Product Viewer Styles */ .product-viewer-container { position: relative; background: #fff; border-radius: 1rem; box-shadow: var(--shadow-lg); padding: 2rem; margin: 2rem 0; } .product-controls { display: flex; align-items: center; justify-content: space-between; gap: 1rem; } .viewer-canvas { position: relative; width: 100%; height: 600px; background: #f8f9fa; border-radius: 0.5rem; overflow: hidden; } .loading-overlay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(255,255,255,0.9); display: flex; flex-direction: column; align-items: center; justify-content: center; z-index: 10; } .spinner { width: 40px; height: 40px; border: 4px solid #f3f3f3; border-top: 4px solid var(--primary-blue); border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Energy Calculator Styles */ .calculator-widget { background: #fff; border-radius: 1rem; box-shadow: var(--shadow-lg); padding: 2rem; max-width: 600px; margin: 2rem auto; } .calculator-form { display: grid; gap: 1.5rem; margin-top: 2rem; } .form-group { display: flex; flex-direction: column; gap: 0.5rem; } .calculator-results { margin-top: 2rem; padding-top: 2rem; border-top: 2px solid #f3f3f3; } /* Chat Widget Styles */ .chat-widget { position: fixed; bottom: 2rem; right: 2rem; width: 350px; height: 500px; background: #fff; border-radius: 1rem; box-shadow: var(--shadow-xl); display: flex; flex-direction: column; z-index: 1000; transform: translateY(100%); transition: transform var(--transition-medium); } .chat-widget.active { transform: translateY(0); } .chat-header { background: var(--primary-gradient); color: #fff; padding: 1rem; border-radius: 1rem 1rem 0 0; display: flex; justify-content: space-between; align-items: center; } .chat-messages { flex: 1; overflow-y: auto; padding: 1rem; display: flex; flex-direction: column; gap: 1rem; } .message { padding: 0.75rem 1rem; border-radius: 1rem; max-width: 80%; } .message.user { background: var(--primary-blue); color: #fff; align-self: flex-end; border-bottom-right-radius: 0.25rem; } .message.system { background: #f3f3f3; align-self: flex-start; border-bottom-left-radius: 0.25rem; } .chat-input { padding: 1rem; border-top: 1px solid #f3f3f3; } .chat-input form { display: flex; gap: 0.5rem; } /* Lead Capture Form Styles */ .lead-capture-form { background: #fff; border-radius: 1rem; box-shadow: var(--shadow-lg); padding: 2rem; max-width: 500px; margin: 2rem auto; } /* Product Comparison Styles */ .product-comparison { margin: 4rem 0; overflow-x: auto; } .comparison-table { width: 100%; border-collapse: collapse; margin-top: 2rem; } .comparison-table th, .comparison-table td { padding: 1rem; text-align: left; border-bottom: 1px solid #f3f3f3; } .comparison-table th { background: var(--primary-gradient); color: #fff; } /* Notification System Styles */ .notification-system { position: fixed; top: 2rem; right: 2rem; z-index: 1000; display: flex; flex-direction: column; gap: 1rem; } .notification { background: #fff; border-radius: 0.5rem; box-shadow: var(--shadow-lg); padding: 1rem; display: flex; align-items: center; gap: 1rem; min-width: 300px; max-width: 500px; animation: slideIn 0.3s ease; } @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } /* Cookie Consent Styles */ .cookie-consent { position: fixed; bottom: 0; left: 0; right: 0; background: #fff; padding: 1rem; box-shadow: var(--shadow-lg); z-index: 1000; transform: translateY(100%); transition: transform var(--transition-medium); } .cookie-consent.active { transform: translateY(0); } /* Modal Styles */ .modal-container { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 1100; opacity: 0; visibility: hidden; transition: opacity var(--transition-medium); } .modal-container.active { opacity: 1; visibility: visible; } .modal-content { background: #fff; border-radius: 1rem; box-shadow: var(--shadow-xl); width: 90%; max-width: 600px; max-height: 90vh; overflow-y: auto; transform: translateY(-50px); transition: transform var(--transition-medium); } .modal-container.active .modal-content { transform: translateY(0); } /* Responsive Design */ @media (max-width: 768px) { .chat-widget { width: 100%; height: 100%; bottom: 0; right: 0; border-radius: 0; } .product-viewer-container { padding: 1rem; } .comparison-table { font-size: 0.875rem; } .notification { width: 90%; margin: 0 auto; } } /* Accessibility Enhancements */ @media (prefers-reduced-motion: reduce) { * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } } .visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); border: 0; } /* Print Styles */ @media print { .chat-widget, .cookie-consent, .notification-system { display: none !important; } } // main.js - Advanced Component Functionality // Utility Class for Common Functions class Utilities { static debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } static formatCurrency(amount) { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(amount); } static formatNumber(number, decimals = 2) { return new Intl.NumberFormat('en-US', { minimumFractionDigits: decimals, maximumFractionDigits: decimals }).format(number); } } // State Management System class StateManager { constructor() { this.state = {}; this.listeners = new Map(); } setState(key, value) { this.state[key] = value; this.notifyListeners(key); } getState(key) { return this.state[key]; } subscribe(key, callback) { if (!this.listeners.has(key)) { this.listeners.set(key, new Set()); } this.listeners.get(key).add(callback); } notifyListeners(key) { if (this.listeners.has(key)) { this.listeners.get(key).forEach(callback => { callback(this.state[key]); }); } } } // Enhanced Product Viewer class ProductViewer { constructor(containerId) { this.container = document.getElementById(containerId); this.canvas = this.container.querySelector('canvas'); this.ctx = this.canvas.getContext('2d'); this.images = []; this.currentFrame = 0; this.isLoading = true; this.isDragging = false; this.lastX = 0; this.frameCount = 36; // 360 degrees / 10 degree increments this.init(); } async init() { await this.loadImages(); this.setupEventListeners(); this.startAnimation(); } async loadImages() { const loadImage = (index) => { return new Promise((resolve) => { const img = new Image(); img.onload = () => resolve(img); img.src = `/assets/product-360/\${index * 10}.jpg`; }); }; const promises = Array.from({ length: this.frameCount }, (_, i) => loadImage(i)); this.images = await Promise.all(promises); this.isLoading = false; this.container.querySelector('.loading-overlay').style.display = 'none'; } setupEventListeners() { this.container.addEventListener('mousedown', this.handleDragStart.bind(this)); document.addEventListener('mousemove', this.handleDragMove.bind(this)); document.addEventListener('mouseup', this.handleDragEnd.bind(this)); // Touch events this.container.addEventListener('touchstart', this.handleTouchStart.bind(this)); document.addEventListener('touchmove', this.handleTouchMove.bind(this)); document.addEventListener('touchend', this.handleTouchEnd.bind(this)); } handleDragStart(e) { this.isDragging = true; this.lastX = e.clientX; } handleDragMove(e) { if (!this.isDragging) return; const delta = e.clientX - this.lastX; this.currentFrame = (this.currentFrame + Math.sign(delta) + this.frameCount) % this.frameCount; this.render(); this.lastX = e.clientX; } handleDragEnd() { this.isDragging = false; } // Touch event handlers handleTouchStart(e) { this.isDragging = true; this.lastX = e.touches[0].clientX; } handleTouchMove(e) { if (!this.isDragging) return; const delta = e.touches[0].clientX - this.lastX; this.currentFrame = (this.currentFrame + Math.sign(delta) + this.frameCount) % this.frameCount; this.render(); this.lastX = e.touches[0].clientX; } handleTouchEnd() { this.isDragging = false; } render() { if (this.isLoading) return; this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); this.ctx.drawImage(this.images[this.currentFrame], 0, 0); } startAnimation() { let frame = 0; const animate = () => { if (!this.isDragging) { frame = (frame + 1) % this.frameCount; this.currentFrame = frame; this.render(); } requestAnimationFrame(animate); }; animate(); } } // Enhanced Energy Calculator class EnergyCalculator { constructor(formId, resultsId) { this.form = document.getElementById(formId); this.resultsContainer = document.getElementById(resultsId); this.state = new StateManager(); this.init(); } init() { this.form.addEventListener('submit', this.handleSubmit.bind(this)); this.setupRealTimeCalculation(); } setupRealTimeCalculation() { const inputs = this.form.querySelectorAll('input, select'); inputs.forEach(input => { input.addEventListener('input', Utilities.debounce(() => { if (this.form.checkValidity()) { this.calculateSavings(); } }, 500)); }); } async handleSubmit(e) { e.preventDefault(); await this.calculateSavings(); } async calculateSavings() { const formData = new FormData(this.form); const data = Object.fromEntries(formData); try { const response = await fetch('/api/calculate-savings', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); const results = await response.json(); this.displayResults(results); } catch (error) { console.error('Calculation error:', error); this.showError('Unable to calculate savings. Please try again.'); } } displayResults(results) { this.resultsContainer.style.display = 'block'; this.resultsContainer.innerHTML = `

Annual Savings

\${Utilities.formatCurrency(results.annualSavings)}

25-Year Savings

\${Utilities.formatCurrency(results.lifetimeSavings)}

ROI

\${results.roi}%

`; } showError(message) { NotificationSystem.show('error', 'Calculation Error', message); } async requestQuote() { // Implementation for quote request } } // Notification System class NotificationSystem { static show(type, title, message, duration = 5000) { const notification = document.createElement('div'); notification.className = `notification \${type}`; notification.innerHTML = `

\${title}

\${message}

`; document.querySelector('.notification-system').appendChild(notification); notification.querySelector('.notification-close').addEventListener('click', () => { notification.remove(); }); if (duration) { setTimeout(() => { notification.remove(); }, duration); } } static getIcon(type) { const icons = { success: 'check-circle', error: 'exclamation-circle', warning: 'exclamation-triangle', info: 'info-circle' }; return icons[type] || 'info-circle'; } } // Initialize Components document.addEventListener('DOMContentLoaded', () => { // Initialize Product Viewer const productViewer = new ProductViewer('product-viewer'); // Initialize Energy Calculator const calculator = new EnergyCalculator('savings-calculator', 'savings-results'); // Initialize other components as needed });