From 69ab55c7a2357ef618a151216f5fc0b02af000cb Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 18 Jan 2026 10:59:18 +0000 Subject: [PATCH] Modernize Johnson Solar website with responsive design - Create complete single-page website for Johnson Solar - Add mobile-first responsive CSS with modern design system - Include all services: Solar, Battery, EV Chargers, Roofing, HVAC - Add testimonials section with real customer reviews - Implement smooth scrolling and mobile navigation - Feature hero section with key stats and CTAs - Add contact form with validation - Include service area section for SoCal coverage - Optimize for accessibility and performance --- css/styles.css | 1502 ++++++++++++++++++++++++++++++++++++++++++++++++ index.html | 760 ++++++++++++++++++++++++ js/main.js | 334 +++++++++++ 3 files changed, 2596 insertions(+) create mode 100644 css/styles.css create mode 100644 index.html create mode 100644 js/main.js diff --git a/css/styles.css b/css/styles.css new file mode 100644 index 0000000..dda8f86 --- /dev/null +++ b/css/styles.css @@ -0,0 +1,1502 @@ +/* ======================================== + Johnson Solar - Modern Website Styles + Mobile-First Responsive Design + ======================================== */ + +/* CSS Custom Properties */ +:root { + /* Colors */ + --color-primary: #f59e0b; + --color-primary-dark: #d97706; + --color-primary-light: #fbbf24; + --color-secondary: #1e3a5f; + --color-secondary-dark: #0f172a; + --color-accent: #10b981; + + /* Neutrals */ + --color-white: #ffffff; + --color-gray-50: #f9fafb; + --color-gray-100: #f3f4f6; + --color-gray-200: #e5e7eb; + --color-gray-300: #d1d5db; + --color-gray-400: #9ca3af; + --color-gray-500: #6b7280; + --color-gray-600: #4b5563; + --color-gray-700: #374151; + --color-gray-800: #1f2937; + --color-gray-900: #111827; + + /* Typography */ + --font-primary: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; + --font-heading: 'Montserrat', var(--font-primary); + + /* Font Sizes */ + --text-xs: 0.75rem; + --text-sm: 0.875rem; + --text-base: 1rem; + --text-lg: 1.125rem; + --text-xl: 1.25rem; + --text-2xl: 1.5rem; + --text-3xl: 1.875rem; + --text-4xl: 2.25rem; + --text-5xl: 3rem; + --text-6xl: 3.75rem; + + /* Spacing */ + --space-1: 0.25rem; + --space-2: 0.5rem; + --space-3: 0.75rem; + --space-4: 1rem; + --space-5: 1.25rem; + --space-6: 1.5rem; + --space-8: 2rem; + --space-10: 2.5rem; + --space-12: 3rem; + --space-16: 4rem; + --space-20: 5rem; + --space-24: 6rem; + + /* Border Radius */ + --radius-sm: 0.25rem; + --radius-md: 0.5rem; + --radius-lg: 0.75rem; + --radius-xl: 1rem; + --radius-2xl: 1.5rem; + --radius-full: 9999px; + + /* Shadows */ + --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); + --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); + --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); + --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25); + + /* Transitions */ + --transition-fast: 150ms ease; + --transition-base: 300ms ease; + --transition-slow: 500ms ease; + + /* Header Height */ + --header-height: 4rem; +} + +/* ======================================== + Reset & Base Styles + ======================================== */ +*, *::before, *::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +html { + scroll-behavior: smooth; + -webkit-text-size-adjust: 100%; +} + +body { + font-family: var(--font-primary); + font-size: var(--text-base); + line-height: 1.6; + color: var(--color-gray-700); + background-color: var(--color-white); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +img { + max-width: 100%; + height: auto; + display: block; +} + +a { + color: inherit; + text-decoration: none; +} + +button { + cursor: pointer; + font-family: inherit; + border: none; + background: none; +} + +ul, ol { + list-style: none; +} + +/* ======================================== + Utility Classes + ======================================== */ +.container { + width: 100%; + max-width: 1280px; + margin: 0 auto; + padding: 0 var(--space-4); +} + +@media (min-width: 640px) { + .container { + padding: 0 var(--space-6); + } +} + +@media (min-width: 1024px) { + .container { + padding: 0 var(--space-8); + } +} + +.section { + padding: var(--space-16) 0; +} + +@media (min-width: 768px) { + .section { + padding: var(--space-20) 0; + } +} + +@media (min-width: 1024px) { + .section { + padding: var(--space-24) 0; + } +} + +.text-gradient { + background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.section__subtitle { + display: inline-block; + font-size: var(--text-sm); + font-weight: 600; + color: var(--color-primary); + text-transform: uppercase; + letter-spacing: 0.1em; + margin-bottom: var(--space-3); +} + +.section__title { + font-family: var(--font-heading); + font-size: var(--text-3xl); + font-weight: 800; + color: var(--color-gray-900); + line-height: 1.2; + margin-bottom: var(--space-4); +} + +@media (min-width: 768px) { + .section__title { + font-size: var(--text-4xl); + } +} + +.section__header { + text-align: center; + max-width: 700px; + margin: 0 auto var(--space-12); +} + +.section__description { + font-size: var(--text-lg); + color: var(--color-gray-600); +} + +/* ======================================== + Buttons + ======================================== */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--space-2); + padding: var(--space-3) var(--space-6); + font-size: var(--text-sm); + font-weight: 600; + border-radius: var(--radius-lg); + transition: all var(--transition-fast); + white-space: nowrap; +} + +.btn--primary { + background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark)); + color: var(--color-white); + box-shadow: 0 4px 14px 0 rgba(245, 158, 11, 0.4); +} + +.btn--primary:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px 0 rgba(245, 158, 11, 0.5); +} + +.btn--outline { + background: transparent; + color: var(--color-white); + border: 2px solid var(--color-white); +} + +.btn--outline:hover { + background: var(--color-white); + color: var(--color-gray-900); +} + +.btn--lg { + padding: var(--space-4) var(--space-8); + font-size: var(--text-base); +} + +.btn--full { + width: 100%; +} + +/* ======================================== + Header & Navigation + ======================================== */ +.header { + position: fixed; + top: 0; + left: 0; + right: 0; + height: var(--header-height); + z-index: 1000; + transition: all var(--transition-base); +} + +.header.scrolled { + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + box-shadow: var(--shadow-md); +} + +.header.scrolled .nav__link, +.header.scrolled .nav__logo, +.header.scrolled .nav__phone { + color: var(--color-gray-700); +} + +.header.scrolled .nav__toggle svg { + stroke: var(--color-gray-700); +} + +.nav { + display: flex; + align-items: center; + justify-content: space-between; + height: 100%; +} + +.nav__logo { + display: flex; + align-items: center; + gap: var(--space-2); + color: var(--color-white); + z-index: 1001; +} + +.logo-icon { + width: 40px; + height: 40px; + color: var(--color-primary); +} + +.logo-text { + font-family: var(--font-heading); + font-size: var(--text-xl); + font-weight: 800; +} + +.nav__menu { + position: fixed; + top: 0; + right: -100%; + width: 100%; + height: 100vh; + background: var(--color-secondary-dark); + padding: calc(var(--header-height) + var(--space-8)) var(--space-6) var(--space-8); + transition: right var(--transition-base); + z-index: 1000; +} + +.nav__menu.show-menu { + right: 0; +} + +.nav__list { + display: flex; + flex-direction: column; + gap: var(--space-2); +} + +.nav__link { + display: block; + padding: var(--space-3) 0; + font-size: var(--text-lg); + font-weight: 500; + color: var(--color-white); + transition: color var(--transition-fast); +} + +.nav__link:hover, +.nav__link.active { + color: var(--color-primary); +} + +.nav__close { + position: absolute; + top: var(--space-4); + right: var(--space-4); + padding: var(--space-2); + color: var(--color-white); +} + +.nav__actions { + display: none; +} + +.nav__toggle { + padding: var(--space-2); + z-index: 1001; +} + +.nav__toggle svg { + stroke: var(--color-white); +} + +.nav__phone { + display: flex; + align-items: center; + gap: var(--space-2); + color: var(--color-white); +} + +/* Desktop Navigation */ +@media (min-width: 1024px) { + .nav__menu { + position: static; + width: auto; + height: auto; + background: transparent; + padding: 0; + } + + .nav__list { + flex-direction: row; + gap: var(--space-1); + } + + .nav__link { + padding: var(--space-2) var(--space-4); + font-size: var(--text-sm); + } + + .nav__close, + .nav__toggle { + display: none; + } + + .nav__actions { + display: flex; + align-items: center; + gap: var(--space-4); + } + + .nav__cta { + padding: var(--space-2) var(--space-5); + } +} + +/* ======================================== + Hero Section + ======================================== */ +.hero { + position: relative; + min-height: 100vh; + display: flex; + align-items: center; + overflow: hidden; +} + +.hero__bg { + position: absolute; + inset: 0; + z-index: -1; +} + +.hero__img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.hero__overlay { + position: absolute; + inset: 0; + background: linear-gradient( + 135deg, + rgba(15, 23, 42, 0.9) 0%, + rgba(30, 58, 95, 0.8) 50%, + rgba(15, 23, 42, 0.85) 100% + ); +} + +.hero__content { + position: relative; + padding-top: calc(var(--header-height) + var(--space-8)); + padding-bottom: var(--space-16); +} + +.hero__badge { + display: inline-flex; + align-items: center; + gap: var(--space-2); + padding: var(--space-2) var(--space-4); + background: rgba(245, 158, 11, 0.15); + border: 1px solid rgba(245, 158, 11, 0.3); + border-radius: var(--radius-full); + color: var(--color-primary); + font-size: var(--text-sm); + font-weight: 600; + margin-bottom: var(--space-6); +} + +.hero__title { + font-family: var(--font-heading); + font-size: var(--text-4xl); + font-weight: 800; + color: var(--color-white); + line-height: 1.1; + margin-bottom: var(--space-6); + max-width: 700px; +} + +@media (min-width: 640px) { + .hero__title { + font-size: var(--text-5xl); + } +} + +@media (min-width: 1024px) { + .hero__title { + font-size: var(--text-6xl); + } +} + +.hero__subtitle { + font-size: var(--text-lg); + color: var(--color-gray-300); + max-width: 600px; + margin-bottom: var(--space-8); +} + +@media (min-width: 768px) { + .hero__subtitle { + font-size: var(--text-xl); + } +} + +.hero__stats { + display: flex; + flex-wrap: wrap; + gap: var(--space-6); + margin-bottom: var(--space-10); +} + +.stat { + text-align: center; + padding-right: var(--space-6); + border-right: 1px solid rgba(255, 255, 255, 0.2); +} + +.stat:last-child { + border-right: none; +} + +.stat__number { + display: block; + font-family: var(--font-heading); + font-size: var(--text-3xl); + font-weight: 800; + color: var(--color-primary); + line-height: 1; +} + +@media (min-width: 768px) { + .stat__number { + font-size: var(--text-4xl); + } +} + +.stat__label { + display: block; + font-size: var(--text-sm); + color: var(--color-gray-400); + margin-top: var(--space-1); +} + +.hero__cta { + display: flex; + flex-wrap: wrap; + gap: var(--space-4); +} + +.hero__scroll { + position: absolute; + bottom: var(--space-8); + left: 50%; + transform: translateX(-50%); +} + +.scroll-indicator { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--space-2); + color: var(--color-gray-400); + font-size: var(--text-sm); + animation: bounce 2s infinite; +} + +@keyframes bounce { + 0%, 20%, 50%, 80%, 100% { + transform: translateY(0); + } + 40% { + transform: translateY(-10px); + } + 60% { + transform: translateY(-5px); + } +} + +/* ======================================== + About Section + ======================================== */ +.about__grid { + display: grid; + gap: var(--space-12); +} + +@media (min-width: 1024px) { + .about__grid { + grid-template-columns: 1fr 1fr; + gap: var(--space-16); + align-items: center; + } +} + +.about__text { + color: var(--color-gray-600); + margin-bottom: var(--space-4); +} + +.about__text strong { + color: var(--color-gray-900); +} + +.about__features { + display: flex; + flex-direction: column; + gap: var(--space-4); + margin-top: var(--space-8); +} + +.feature { + display: flex; + gap: var(--space-4); +} + +.feature__icon { + flex-shrink: 0; + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(135deg, rgba(245, 158, 11, 0.1), rgba(245, 158, 11, 0.05)); + border-radius: var(--radius-lg); + color: var(--color-primary); +} + +.feature__content h4 { + font-size: var(--text-base); + font-weight: 600; + color: var(--color-gray-900); + margin-bottom: var(--space-1); +} + +.feature__content p { + font-size: var(--text-sm); + color: var(--color-gray-500); +} + +.about__image { + position: relative; +} + +.about__image-wrapper { + position: relative; + border-radius: var(--radius-2xl); + overflow: hidden; +} + +.about__img { + width: 100%; + height: 400px; + object-fit: cover; +} + +@media (min-width: 1024px) { + .about__img { + height: 500px; + } +} + +.about__badge { + position: absolute; + bottom: var(--space-6); + left: var(--space-6); + background: var(--color-white); + padding: var(--space-4) var(--space-6); + border-radius: var(--radius-xl); + box-shadow: var(--shadow-xl); + text-align: center; +} + +.badge__number { + display: block; + font-family: var(--font-heading); + font-size: var(--text-3xl); + font-weight: 800; + color: var(--color-primary); + line-height: 1; +} + +.badge__text { + display: block; + font-size: var(--text-sm); + color: var(--color-gray-600); + margin-top: var(--space-1); +} + +/* ======================================== + Services Section + ======================================== */ +.services { + background: var(--color-gray-50); +} + +.services__grid { + display: grid; + gap: var(--space-6); +} + +@media (min-width: 640px) { + .services__grid { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (min-width: 1024px) { + .services__grid { + grid-template-columns: repeat(3, 1fr); + } +} + +.service-card { + position: relative; + background: var(--color-white); + border-radius: var(--radius-xl); + padding: var(--space-6); + box-shadow: var(--shadow-sm); + transition: all var(--transition-base); + border: 1px solid var(--color-gray-100); +} + +.service-card:hover { + transform: translateY(-4px); + box-shadow: var(--shadow-lg); +} + +.service-card--featured { + border-color: var(--color-primary); + box-shadow: 0 0 0 1px var(--color-primary); +} + +.service-card__badge { + position: absolute; + top: var(--space-4); + right: var(--space-4); + padding: var(--space-1) var(--space-3); + background: var(--color-primary); + color: var(--color-white); + font-size: var(--text-xs); + font-weight: 600; + border-radius: var(--radius-full); +} + +.service-card__icon { + width: 56px; + height: 56px; + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(135deg, rgba(245, 158, 11, 0.1), rgba(245, 158, 11, 0.05)); + border-radius: var(--radius-lg); + margin-bottom: var(--space-4); + color: var(--color-primary); +} + +.service-card__icon svg { + width: 32px; + height: 32px; +} + +.service-card__title { + font-size: var(--text-lg); + font-weight: 700; + color: var(--color-gray-900); + margin-bottom: var(--space-3); +} + +.service-card__text { + font-size: var(--text-sm); + color: var(--color-gray-600); + margin-bottom: var(--space-4); +} + +.service-card__list { + margin-bottom: var(--space-4); +} + +.service-card__list li { + position: relative; + padding-left: var(--space-5); + font-size: var(--text-sm); + color: var(--color-gray-600); + margin-bottom: var(--space-2); +} + +.service-card__list li::before { + content: ''; + position: absolute; + left: 0; + top: 8px; + width: 8px; + height: 8px; + background: var(--color-primary); + border-radius: 50%; +} + +.service-card__link { + display: inline-flex; + align-items: center; + gap: var(--space-2); + font-size: var(--text-sm); + font-weight: 600; + color: var(--color-primary); + transition: gap var(--transition-fast); +} + +.service-card__link:hover { + gap: var(--space-3); +} + +.services__callout { + display: flex; + flex-direction: column; + gap: var(--space-6); + margin-top: var(--space-12); + padding: var(--space-8); + background: linear-gradient(135deg, var(--color-secondary), var(--color-secondary-dark)); + border-radius: var(--radius-2xl); + color: var(--color-white); +} + +@media (min-width: 768px) { + .services__callout { + flex-direction: row; + align-items: center; + justify-content: space-between; + } +} + +.callout__content h3 { + font-size: var(--text-xl); + font-weight: 700; + margin-bottom: var(--space-2); +} + +.callout__content p { + color: var(--color-gray-300); + max-width: 500px; +} + +.callout__cta { + display: flex; + flex-direction: column; + gap: var(--space-3); + align-items: flex-start; +} + +@media (min-width: 768px) { + .callout__cta { + align-items: flex-end; + text-align: right; + } +} + +.callout__price { + font-size: var(--text-sm); + color: var(--color-gray-300); +} + +.callout__price strong { + font-size: var(--text-xl); + color: var(--color-primary); +} + +/* ======================================== + Projects Section + ======================================== */ +.projects__grid { + display: grid; + gap: var(--space-4); +} + +@media (min-width: 640px) { + .projects__grid { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (min-width: 1024px) { + .projects__grid { + grid-template-columns: repeat(3, 1fr); + grid-template-rows: repeat(2, 280px); + } + + .project-card--large { + grid-row: span 2; + } + + .project-card--large .project-card__img { + height: 100%; + } +} + +.project-card { + position: relative; + border-radius: var(--radius-xl); + overflow: hidden; + cursor: pointer; +} + +.project-card__img { + width: 100%; + height: 280px; + object-fit: cover; + transition: transform var(--transition-slow); +} + +.project-card:hover .project-card__img { + transform: scale(1.05); +} + +.project-card__overlay { + position: absolute; + inset: 0; + background: linear-gradient(to top, rgba(0, 0, 0, 0.8) 0%, transparent 60%); + display: flex; + flex-direction: column; + justify-content: flex-end; + padding: var(--space-6); + opacity: 0.9; + transition: opacity var(--transition-base); +} + +.project-card:hover .project-card__overlay { + opacity: 1; +} + +.project-card__tag { + display: inline-block; + padding: var(--space-1) var(--space-3); + background: var(--color-primary); + color: var(--color-white); + font-size: var(--text-xs); + font-weight: 600; + border-radius: var(--radius-full); + margin-bottom: var(--space-2); + width: fit-content; +} + +.project-card__title { + font-size: var(--text-lg); + font-weight: 700; + color: var(--color-white); + margin-bottom: var(--space-1); +} + +.project-card__location { + font-size: var(--text-sm); + color: var(--color-gray-300); +} + +/* ======================================== + Testimonials Section + ======================================== */ +.testimonials { + background: linear-gradient(135deg, var(--color-secondary), var(--color-secondary-dark)); +} + +.testimonials .section__subtitle { + color: var(--color-primary-light); +} + +.testimonials .section__title { + color: var(--color-white); +} + +.testimonials .section__description { + color: var(--color-gray-300); +} + +.testimonials__grid { + display: grid; + gap: var(--space-6); +} + +@media (min-width: 640px) { + .testimonials__grid { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (min-width: 1024px) { + .testimonials__grid { + grid-template-columns: repeat(3, 1fr); + } +} + +.testimonial-card { + background: var(--color-white); + border-radius: var(--radius-xl); + padding: var(--space-6); + box-shadow: var(--shadow-lg); +} + +.testimonial-card__rating { + display: flex; + gap: var(--space-1); + margin-bottom: var(--space-4); + color: var(--color-primary); +} + +.testimonial-card__text { + font-size: var(--text-sm); + color: var(--color-gray-700); + line-height: 1.7; + margin-bottom: var(--space-6); +} + +.testimonial-card__author { + display: flex; + align-items: center; + gap: var(--space-3); +} + +.author__avatar { + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark)); + color: var(--color-white); + font-weight: 700; + border-radius: 50%; +} + +.author__name { + display: block; + font-weight: 600; + color: var(--color-gray-900); +} + +.author__source { + display: block; + font-size: var(--text-sm); + color: var(--color-gray-500); +} + +.testimonials__cta { + text-align: center; + margin-top: var(--space-10); +} + +.testimonials__cta .btn--outline { + border-color: var(--color-gray-400); + color: var(--color-white); +} + +.testimonials__cta .btn--outline:hover { + background: var(--color-white); + color: var(--color-gray-900); + border-color: var(--color-white); +} + +/* ======================================== + Service Area Section + ======================================== */ +.service-area__grid { + display: grid; + gap: var(--space-12); +} + +@media (min-width: 1024px) { + .service-area__grid { + grid-template-columns: 1fr 1fr; + gap: var(--space-16); + align-items: center; + } +} + +.service-area__content p { + color: var(--color-gray-600); + margin-bottom: var(--space-8); +} + +.service-area__counties { + display: flex; + flex-direction: column; + gap: var(--space-4); +} + +.county { + padding: var(--space-4); + background: var(--color-gray-50); + border-radius: var(--radius-lg); + border-left: 4px solid var(--color-primary); +} + +.county h4 { + font-weight: 600; + color: var(--color-gray-900); + margin-bottom: var(--space-1); +} + +.county p { + font-size: var(--text-sm); + color: var(--color-gray-600); + margin: 0; +} + +.service-area__map { + position: relative; + border-radius: var(--radius-2xl); + overflow: hidden; +} + +.service-area__img { + width: 100%; + height: 400px; + object-fit: cover; +} + +.service-area__badge { + position: absolute; + bottom: var(--space-6); + left: var(--space-6); + display: flex; + align-items: center; + gap: var(--space-2); + padding: var(--space-3) var(--space-5); + background: var(--color-white); + border-radius: var(--radius-full); + box-shadow: var(--shadow-lg); + font-weight: 600; + color: var(--color-gray-700); +} + +.badge__icon { + color: var(--color-primary); +} + +/* ======================================== + Contact Section + ======================================== */ +.contact { + background: var(--color-gray-50); +} + +.contact__grid { + display: grid; + gap: var(--space-12); +} + +@media (min-width: 1024px) { + .contact__grid { + grid-template-columns: 1fr 1fr; + gap: var(--space-16); + } +} + +.contact__info p { + color: var(--color-gray-600); + margin-bottom: var(--space-8); +} + +.contact__details { + display: flex; + flex-direction: column; + gap: var(--space-5); + margin-bottom: var(--space-8); +} + +.contact__item { + display: flex; + align-items: flex-start; + gap: var(--space-4); +} + +.contact__icon { + flex-shrink: 0; + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(135deg, rgba(245, 158, 11, 0.1), rgba(245, 158, 11, 0.05)); + border-radius: var(--radius-lg); + color: var(--color-primary); +} + +.contact__label { + display: block; + font-size: var(--text-sm); + font-weight: 600; + color: var(--color-gray-500); + margin-bottom: var(--space-1); +} + +.contact__value { + font-size: var(--text-base); + color: var(--color-gray-900); +} + +a.contact__value:hover { + color: var(--color-primary); +} + +.contact__social { + display: flex; + gap: var(--space-3); +} + +.social__link { + width: 44px; + height: 44px; + display: flex; + align-items: center; + justify-content: center; + background: var(--color-gray-100); + border-radius: var(--radius-lg); + color: var(--color-gray-600); + transition: all var(--transition-fast); +} + +.social__link:hover { + background: var(--color-primary); + color: var(--color-white); +} + +.contact__form-wrapper { + background: var(--color-white); + border-radius: var(--radius-2xl); + padding: var(--space-6); + box-shadow: var(--shadow-xl); +} + +@media (min-width: 768px) { + .contact__form-wrapper { + padding: var(--space-8); + } +} + +.form__title { + font-size: var(--text-xl); + font-weight: 700; + color: var(--color-gray-900); + margin-bottom: var(--space-6); +} + +.form__group { + margin-bottom: var(--space-5); +} + +.form__row { + display: grid; + gap: var(--space-5); +} + +@media (min-width: 640px) { + .form__row { + grid-template-columns: 1fr 1fr; + } +} + +.form__label { + display: block; + font-size: var(--text-sm); + font-weight: 500; + color: var(--color-gray-700); + margin-bottom: var(--space-2); +} + +.form__input, +.form__select, +.form__textarea { + width: 100%; + padding: var(--space-3) var(--space-4); + font-family: inherit; + font-size: var(--text-base); + color: var(--color-gray-900); + background: var(--color-gray-50); + border: 1px solid var(--color-gray-200); + border-radius: var(--radius-lg); + transition: all var(--transition-fast); +} + +.form__input:focus, +.form__select:focus, +.form__textarea:focus { + outline: none; + border-color: var(--color-primary); + box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.1); +} + +.form__input::placeholder, +.form__textarea::placeholder { + color: var(--color-gray-400); +} + +.form__select { + appearance: none; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right var(--space-3) center; + background-size: 20px; + padding-right: var(--space-10); +} + +.form__textarea { + resize: vertical; + min-height: 120px; +} + +.form__disclaimer { + font-size: var(--text-xs); + color: var(--color-gray-500); + text-align: center; + margin-top: var(--space-4); +} + +/* ======================================== + Footer + ======================================== */ +.footer { + background: var(--color-gray-900); + color: var(--color-gray-400); + padding: var(--space-16) 0 var(--space-8); +} + +.footer__grid { + display: grid; + gap: var(--space-10); + margin-bottom: var(--space-12); +} + +@media (min-width: 640px) { + .footer__grid { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (min-width: 1024px) { + .footer__grid { + grid-template-columns: 2fr 1fr 1fr 1.5fr; + } +} + +.footer__logo { + display: flex; + align-items: center; + gap: var(--space-2); + color: var(--color-white); + margin-bottom: var(--space-4); +} + +.footer__logo .logo-icon { + color: var(--color-primary); +} + +.footer__logo .logo-text { + font-size: var(--text-lg); +} + +.footer__tagline { + font-size: var(--text-sm); + line-height: 1.7; + margin-bottom: var(--space-4); +} + +.footer__certifications { + display: flex; + flex-wrap: wrap; + gap: var(--space-2); +} + +.certification { + padding: var(--space-1) var(--space-3); + background: rgba(255, 255, 255, 0.1); + border-radius: var(--radius-full); + font-size: var(--text-xs); + font-weight: 500; +} + +.footer__title { + font-size: var(--text-base); + font-weight: 600; + color: var(--color-white); + margin-bottom: var(--space-4); +} + +.footer__list { + display: flex; + flex-direction: column; + gap: var(--space-3); +} + +.footer__list a { + font-size: var(--text-sm); + transition: color var(--transition-fast); +} + +.footer__list a:hover { + color: var(--color-primary); +} + +.footer__contact-item { + display: flex; + align-items: flex-start; + gap: var(--space-3); + margin-bottom: var(--space-4); + font-size: var(--text-sm); +} + +.footer__contact-item svg { + flex-shrink: 0; + color: var(--color-primary); + margin-top: 2px; +} + +.footer__contact-item a:hover { + color: var(--color-primary); +} + +.footer__bottom { + display: flex; + flex-direction: column; + gap: var(--space-4); + padding-top: var(--space-8); + border-top: 1px solid rgba(255, 255, 255, 0.1); + text-align: center; +} + +@media (min-width: 768px) { + .footer__bottom { + flex-direction: row; + justify-content: space-between; + text-align: left; + } +} + +.footer__copyright { + font-size: var(--text-sm); +} + +.footer__legal { + display: flex; + gap: var(--space-6); +} + +.footer__legal a { + font-size: var(--text-sm); + transition: color var(--transition-fast); +} + +.footer__legal a:hover { + color: var(--color-primary); +} + +/* ======================================== + Animations + ======================================== */ +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.animate-on-scroll { + opacity: 0; + transform: translateY(30px); + transition: opacity 0.6s ease, transform 0.6s ease; +} + +.animate-on-scroll.animated { + opacity: 1; + transform: translateY(0); +} + +/* ======================================== + Accessibility + ======================================== */ +@media (prefers-reduced-motion: reduce) { + html { + scroll-behavior: auto; + } + + *, *::before, *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} + +:focus-visible { + outline: 2px solid var(--color-primary); + outline-offset: 2px; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..7581f4e --- /dev/null +++ b/index.html @@ -0,0 +1,760 @@ + + + + + + + + Johnson Solar | Veteran-Owned Solar Installation | San Diego, SoCal + + + + + + + + + +
+ +
+
+ Solar panels on residential roof in San Diego +
+
+
+
+ + + + Veteran-Owned & Operated +
+

San Diego's Trusted Solar Experts

+

Fast installations, unbeatable prices, and exceptional service. Save $1,000 - $5,000 compared to competitors with our veteran-led team.

+
+
+ 1-2 + Month Install Time +
+
+ A+ + BBB Rating +
+
+ 71+ + 5-Star Reviews +
+
+ +
+ +
+ + +
+
+
+
+ About Us +

Veteran Leadership, Exceptional Results

+

+ Johnson Solar is a military veteran-owned and operated solar installation company founded by Clinton Johnson, a retired Navy Aviator with over 20 years of military service and more than a decade of hands-on construction experience. +

+

+ As a Master Solar Electrician with a BBA in Business from the University of Wisconsin and an MBA from the University of San Diego in New Venture Management, Clinton leads our team with precision, integrity, and a commitment to excellence. +

+
+
+
+ + + + +
+
+

NABCEP Certified

+

Industry-leading certification for solar professionals

+
+
+
+
+ + + +
+
+

Veteran-Led Team

+

Military and law enforcement professionals you can trust

+
+
+
+
+ + + + +
+
+

Fast Installation

+

Most installations completed in just 1-2 days

+
+
+
+
+
+
+ Solar installation team at work +
+ 20+ + Years Combined Experience +
+
+
+
+
+
+ + +
+
+
+ Our Services +

Complete Energy Solutions for Your Home

+

From solar panels to HVAC, we provide comprehensive services to power your home efficiently and sustainably.

+
+ +
+ +
+
+ + + + + + + +
+

Solar Panel Installation

+

Expert design and installation of residential and commercial PV solar systems using premium panels from Hanwha Q Cells and Panasonic.

+
    +
  • Custom system design
  • +
  • Premium panel brands
  • +
  • Enphase & SolarEdge inverters
  • +
  • Complete permitting
  • +
+ Learn More +
+ + + + + +
+
+ + + + + + + +
+

EV Charger Installation

+

Level 2 EV charging station installation for all electric vehicle makes and models. Charge your car at home with ease.

+
    +
  • Level 2 chargers
  • +
  • All EV brands supported
  • +
  • Outlet upgrades
  • +
  • Panel capacity check
  • +
+ Learn More +
+ + +
+
+ + + + + + + + + +
+

Electrical Upgrades

+

Main panel upgrades and sub-panel installations to support your growing energy needs and ensure code compliance.

+
    +
  • Main panel upgrades
  • +
  • Sub-panel installation
  • +
  • Code compliance
  • +
  • Capacity expansion
  • +
+ Learn More +
+ + +
+
+ + + + + +
+

Roofing Services

+

In-house roofing partners ensure your roof is solar-ready. Complete roof replacement or repair before solar installation.

+
    +
  • Roof inspection
  • +
  • Replacement & repair
  • +
  • Solar-ready prep
  • +
  • Competitive pricing
  • +
+ Learn More +
+ + +
+
+ + + + + + + + +
+

HVAC Services

+

Keep your home comfortable year-round with our HVAC installation and maintenance services, powered by your solar system.

+
    +
  • AC installation
  • +
  • Heating systems
  • +
  • Whole house fans
  • +
  • Attic ventilation
  • +
+ Learn More +
+
+ + +
+
+

Already Have Solar?

+

We service existing PV Solar Systems installed by other companies. Get your system inspected and maintained by our expert team.

+
+
+ Starting at $300/site visit + Schedule Service +
+
+
+
+ + +
+
+
+ Our Work +

Recent Projects

+

See the quality craftsmanship and attention to detail in every installation we complete throughout San Diego County.

+
+ +
+
+ Residential solar installation in San Diego +
+ Residential +

Complete Home Solar System

+

La Mesa, San Diego County

+
+
+
+ Solar panels on residential roof +
+ Solar + Battery +

Solar with Battery Backup

+

El Cajon, CA

+
+
+
+ Solar installation completed +
+ Residential +

Rooftop Solar Array

+

Santee, CA

+
+
+
+ Solar panels at sunset +
+ Commercial +

Commercial Installation

+

Chula Vista, CA

+
+
+
+ Modern home with solar panels +
+ Full Service +

Solar + EV Charger + Battery

+

Coronado, CA

+
+
+
+
+
+ + +
+
+
+ Customer Reviews +

What Our Customers Say

+

Don't just take our word for it. Here's what our satisfied customers have to say about working with Johnson Solar.

+
+ +
+
+
+ + + + + +
+

"Hands down the best in the business! Not only are they the most affordable (we had estimates from Baker, Stellar, Semper, and Coastal) but their customer service is amazing! Clinton, the owner, makes sure he's on site for every installation."

+
+
MR
+
+ Mike R. + Google Review +
+
+
+ +
+
+ + + + + +
+

"Clinton did a great job on our 2nd solar project. He was straightforward, knowledgeable, trustworthy, and incredibly competitive with his pricing. You can't go wrong with Johnson Solar."

+
+
JT
+
+ Jennifer T. + Nextdoor Review +
+
+
+ +
+
+ + + + + +
+

"Professional, honest, and fast. Clinton met me at the house and reviewed the job. He was the only contractor to point out ways to save me money instead of paying for things I didn't need. He is also NOT the sales guy!"

+
+
DK
+
+ David K. + SolarReviews +
+
+
+ +
+
+ + + + + +
+

"Trustworthy, very economical and punctual which we needed in our tight close of escrow. Highly recommend! The extra bonus is supporting Clinton Johnson who served our country well!"

+
+
SL
+
+ Sandra L. + Google Review +
+
+
+ +
+
+ + + + + +
+

"From start to finish Clinton and the team at Johnson Solar went above and beyond to get solar on my roof in a timely manner. The installation team finished quickly and left the job site clean and tidy. Easily passed inspection and PTO."

+
+
RH
+
+ Robert H. + Nextdoor Review +
+
+
+ +
+
+ + + + + +
+

"Clinton ALWAYS responded to calls or texts, which is important to me. He installed my system in a few days and has always answered all concerns and questions. Our experience was absolutely fantastic from start to finish."

+
+
AM
+
+ Angela M. + SolarReviews +
+
+
+
+ + +
+
+ + +
+
+
+
+ Service Area +

Proudly Serving Southern California

+

We provide expert solar installation and energy services throughout San Diego, Orange, and Riverside Counties. Our local presence means faster response times and better service for your home or business.

+
+
+

San Diego County

+

El Cajon, La Mesa, Santee, Chula Vista, Coronado, National City, and more

+
+
+

Orange County

+

Irvine, Anaheim, Santa Ana, Newport Beach, and surrounding areas

+
+
+

Riverside County

+

Riverside, Corona, Temecula, Murrieta, and surrounding communities

+
+
+
+
+ San Diego cityscape +
+ + + + + + + 3 Counties Served +
+
+
+
+
+ + +
+
+
+
+ Contact Us +

Ready to Go Solar?

+

Get your free, no-obligation quote today. Our team is ready to answer your questions and design the perfect solar solution for your home.

+ +
+
+
+ + + +
+
+ Phone + (619) 784-8401 +
+
+ +
+
+ + + + +
+
+ Address + 2514 Jamacha Road #502
El Cajon, CA 92019
+
+
+ +
+
+ + + + +
+
+ Business Hours + Monday - Friday: 8:00 AM - 5:00 PM
Saturday - Sunday: Closed
+
+
+
+ + +
+ +
+
+

Get Your Free Quote

+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+ +

By submitting this form, you agree to be contacted regarding your solar inquiry.

+
+
+
+
+
+
+ + + + + + + diff --git a/js/main.js b/js/main.js new file mode 100644 index 0000000..bd038f7 --- /dev/null +++ b/js/main.js @@ -0,0 +1,334 @@ +/** + * Johnson Solar - Main JavaScript + * Mobile-friendly interactions and smooth UX + */ + +(function() { + 'use strict'; + + // ======================================== + // Mobile Navigation + // ======================================== + const navMenu = document.getElementById('nav-menu'); + const navToggle = document.getElementById('nav-toggle'); + const navClose = document.getElementById('nav-close'); + const navLinks = document.querySelectorAll('.nav__link'); + + // Open menu + if (navToggle) { + navToggle.addEventListener('click', () => { + navMenu.classList.add('show-menu'); + document.body.style.overflow = 'hidden'; + }); + } + + // Close menu + if (navClose) { + navClose.addEventListener('click', () => { + navMenu.classList.remove('show-menu'); + document.body.style.overflow = ''; + }); + } + + // Close menu when clicking a link + navLinks.forEach(link => { + link.addEventListener('click', () => { + navMenu.classList.remove('show-menu'); + document.body.style.overflow = ''; + }); + }); + + // Close menu on escape key + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && navMenu.classList.contains('show-menu')) { + navMenu.classList.remove('show-menu'); + document.body.style.overflow = ''; + } + }); + + // ======================================== + // Header Scroll Effect + // ======================================== + const header = document.getElementById('header'); + let lastScroll = 0; + + function handleHeaderScroll() { + const currentScroll = window.pageYOffset; + + if (currentScroll > 100) { + header.classList.add('scrolled'); + } else { + header.classList.remove('scrolled'); + } + + lastScroll = currentScroll; + } + + window.addEventListener('scroll', handleHeaderScroll, { passive: true }); + + // ======================================== + // Active Navigation Link + // ======================================== + const sections = document.querySelectorAll('section[id]'); + + function setActiveNavLink() { + const scrollY = window.pageYOffset; + + sections.forEach(section => { + const sectionHeight = section.offsetHeight; + const sectionTop = section.offsetTop - 150; + const sectionId = section.getAttribute('id'); + const navLink = document.querySelector(`.nav__link[href="#${sectionId}"]`); + + if (navLink) { + if (scrollY > sectionTop && scrollY <= sectionTop + sectionHeight) { + navLink.classList.add('active'); + } else { + navLink.classList.remove('active'); + } + } + }); + } + + window.addEventListener('scroll', setActiveNavLink, { passive: true }); + + // ======================================== + // Smooth Scrolling + // ======================================== + document.querySelectorAll('a[href^="#"]').forEach(anchor => { + anchor.addEventListener('click', function(e) { + const href = this.getAttribute('href'); + if (href === '#') return; + + e.preventDefault(); + const target = document.querySelector(href); + + if (target) { + const headerHeight = header.offsetHeight; + const targetPosition = target.offsetTop - headerHeight; + + window.scrollTo({ + top: targetPosition, + behavior: 'smooth' + }); + } + }); + }); + + // ======================================== + // Form Handling + // ======================================== + const contactForm = document.getElementById('contact-form'); + + if (contactForm) { + contactForm.addEventListener('submit', function(e) { + e.preventDefault(); + + // Get form data + const formData = new FormData(this); + const data = {}; + formData.forEach((value, key) => { + data[key] = value; + }); + + // Simple validation + const requiredFields = ['name', 'email', 'phone']; + let isValid = true; + + requiredFields.forEach(field => { + const input = this.querySelector(`[name="${field}"]`); + if (!data[field] || data[field].trim() === '') { + isValid = false; + input.style.borderColor = '#ef4444'; + } else { + input.style.borderColor = ''; + } + }); + + // Email validation + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + const emailInput = this.querySelector('[name="email"]'); + if (data.email && !emailRegex.test(data.email)) { + isValid = false; + emailInput.style.borderColor = '#ef4444'; + } + + // Phone validation (basic) + const phoneRegex = /^[\d\s\-\(\)\+]{10,}$/; + const phoneInput = this.querySelector('[name="phone"]'); + if (data.phone && !phoneRegex.test(data.phone.replace(/\s/g, ''))) { + isValid = false; + phoneInput.style.borderColor = '#ef4444'; + } + + if (isValid) { + // Show success message + const submitBtn = this.querySelector('button[type="submit"]'); + const originalText = submitBtn.textContent; + submitBtn.textContent = 'Message Sent!'; + submitBtn.style.background = '#10b981'; + submitBtn.disabled = true; + + // Reset form + setTimeout(() => { + this.reset(); + submitBtn.textContent = originalText; + submitBtn.style.background = ''; + submitBtn.disabled = false; + }, 3000); + + // In production, you would send this data to a server + console.log('Form submitted:', data); + } + }); + + // Clear error styling on input + contactForm.querySelectorAll('input, select, textarea').forEach(input => { + input.addEventListener('focus', function() { + this.style.borderColor = ''; + }); + }); + } + + // ======================================== + // Scroll Animations + // ======================================== + const animatedElements = document.querySelectorAll('.service-card, .testimonial-card, .project-card, .feature'); + + function checkAnimation() { + const triggerBottom = window.innerHeight * 0.85; + + animatedElements.forEach(element => { + const elementTop = element.getBoundingClientRect().top; + + if (elementTop < triggerBottom) { + element.classList.add('animated'); + } + }); + } + + // Add animation class to elements + animatedElements.forEach(element => { + element.classList.add('animate-on-scroll'); + }); + + // Check on scroll + window.addEventListener('scroll', checkAnimation, { passive: true }); + + // Check on load + window.addEventListener('load', checkAnimation); + + // ======================================== + // Phone Number Formatting + // ======================================== + const phoneInput = document.getElementById('phone'); + + if (phoneInput) { + phoneInput.addEventListener('input', function(e) { + let value = e.target.value.replace(/\D/g, ''); + + if (value.length > 0) { + if (value.length <= 3) { + value = `(${value}`; + } else if (value.length <= 6) { + value = `(${value.slice(0, 3)}) ${value.slice(3)}`; + } else { + value = `(${value.slice(0, 3)}) ${value.slice(3, 6)}-${value.slice(6, 10)}`; + } + } + + e.target.value = value; + }); + } + + // ======================================== + // Lazy Loading Images + // ======================================== + if ('IntersectionObserver' in window) { + const imageObserver = new IntersectionObserver((entries, observer) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const img = entry.target; + if (img.dataset.src) { + img.src = img.dataset.src; + img.removeAttribute('data-src'); + } + observer.unobserve(img); + } + }); + }, { + rootMargin: '50px 0px', + threshold: 0.01 + }); + + document.querySelectorAll('img[data-src]').forEach(img => { + imageObserver.observe(img); + }); + } + + // ======================================== + // Stats Counter Animation + // ======================================== + function animateStats() { + const stats = document.querySelectorAll('.stat__number'); + + stats.forEach(stat => { + const text = stat.textContent; + + // Only animate numeric values + if (!isNaN(parseInt(text))) { + const target = parseInt(text); + const suffix = text.replace(/[0-9]/g, ''); + let current = 0; + const increment = target / 50; + const duration = 1500; + const stepTime = duration / 50; + + const timer = setInterval(() => { + current += increment; + if (current >= target) { + stat.textContent = text; + clearInterval(timer); + } else { + stat.textContent = Math.floor(current) + suffix; + } + }, stepTime); + } + }); + } + + // Run stats animation when hero section is visible + const heroSection = document.getElementById('home'); + if (heroSection) { + const statsObserver = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + animateStats(); + statsObserver.disconnect(); + } + }); + }, { threshold: 0.5 }); + + statsObserver.observe(heroSection); + } + + // ======================================== + // Service Worker Registration (PWA-ready) + // ======================================== + if ('serviceWorker' in navigator) { + window.addEventListener('load', () => { + // Service worker can be added for offline support + // navigator.serviceWorker.register('/sw.js'); + }); + } + + // ======================================== + // Console Welcome Message + // ======================================== + console.log( + '%c Johnson Solar %c Veteran-Owned Solar Installation ', + 'background: #f59e0b; color: #fff; padding: 5px 10px; border-radius: 3px 0 0 3px;', + 'background: #1e3a5f; color: #fff; padding: 5px 10px; border-radius: 0 3px 3px 0;' + ); + +})();