Home Battery Storage Systems | Guardian Elite Series | SunFusion Energy
Advanced Home Battery Storage Systems for 2025
Power Your Future with American-Made Energy Independence
16kWh Capacity
15kW Integrated Inverter
99.1% Efficiency
25-Year Warranty
NEMA 3R Rated
Revolutionary Home Energy Storage Solutions
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
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);
});
}
});
Features |
Guardian Elite |
Guardian E2.0 |
ECHO Series |
We use cookies to enhance your experience. By continuing to visit this site you agree to our use of cookies.
/* 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)}
`;
}
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 = `
`;
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
});