From ee6f61d51cd514bddba6881f9eabda7f33f2bf2b Mon Sep 17 00:00:00 2001 From: Sage Date: Sat, 16 May 2026 15:59:25 -0400 Subject: [PATCH] New custom favicon + mobile nav responsive fix - New custom favicon: blue gradient water drop with spray burst (favicon.png 32/64/256px, favicon.webp, apple-touch-icon 180px) - Mobile nav (768px): tighter padding (12px), smaller logo (1rem), smaller icon (1.2rem) - Narrow phones (480px): logo text 0.85rem, logo max-width 60% - Tiny phones (360px): logo text 0.75rem, logo max-width 55% - CSS cache buster bumped to v3 --- composer.json | 5 ++ convert-webp.sh | 51 +++++++++++++++++++ css/style.css | 39 +++++++++++++++ index.html | 13 ++--- main.js | 130 ++++++++++++++++++++++++++++++++++++++++++++++++ progress.md | 30 +++++------ 6 files changed, 240 insertions(+), 28 deletions(-) create mode 100644 composer.json create mode 100644 convert-webp.sh create mode 100644 main.js diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..078861f --- /dev/null +++ b/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "phpmailer/phpmailer": "^7.0" + } +} diff --git a/convert-webp.sh b/convert-webp.sh new file mode 100644 index 0000000..52abd88 --- /dev/null +++ b/convert-webp.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# Convert all JPG/PNG images to WebP and update HTML with srcset fallbacks +set -e + +IMG_DIR="img" +INDEX_FILE="index.html" + +echo "Converting images to WebP..." + +# Convert all JPG and PNG files to WebP +for f in "$IMG_DIR"/*.jpg "$IMG_DIR"/*.png; do + [ -f "$f" ] || continue + base="${f%.*}" + webp="${base}.webp" + if [ ! -f "$webp" ]; then + convert "$f" -quality 82 "$webp" + echo " Converted: $(basename "$f") -> $(basename "$webp")" + fi +done + +echo "" +echo "Updating index.html with srcset attributes..." + +# Update each img tag in index.html with srcset +# We need to update: gallery images, work images, and og-banner in meta tags +sed -i 's|img/og-banner.jpg|img/og-banner.jpg, img/og-banner.webp|g' "$INDEX_FILE" + +# Gallery images - update each img tag with srcset +for f in "$IMG_DIR"/*.jpg "$IMG_DIR"/*.png; do + [ -f "$f" ] || continue + basename="${f#$IMG_DIR/}" + basename="${basename%.*}" + # Update JPG references + if [[ "$basename" == *".jpg" ]]; then + webp="${basename%.jpg}.webp" + sed -i "s|\"$basename\"|\"$basename\", \"$webp\" type=\"image/webp\"|g" "$INDEX_FILE" + fi + # Update PNG references + if [[ "$basename" == *".png" ]]; then + webp="${basename%.png}.webp" + sed -i "s|\"$basename\"|\"$basename\", \"$webp\" type=\"image/webp\"|g" "$INDEX_FILE" + fi +done + +echo "" +echo "Done! Generated WebP files and updated index.html with srcset fallbacks." +echo "" +echo "Size comparison:" +echo "Original: $(du -sh "$IMG_DIR" | cut -f1)" +echo "With WebP: $(du -sh "$IMG_DIR" | cut -f1)" +du -sh "$IMG_DIR"/*.webp 2>/dev/null | awk '{printf " %-35s %s\n", $2, $1}' | sort diff --git a/css/style.css b/css/style.css index 4fa70b3..04bfef3 100644 --- a/css/style.css +++ b/css/style.css @@ -1075,6 +1075,22 @@ img { } @media (max-width: 768px) { + .nav-container { + padding: 0 12px; + } + + .logo-text { + font-size: 1rem; + } + + .logo-icon { + font-size: 1.2rem; + } + + .nav-toggle span { + width: 22px; + } + .nav-links { display: none; position: fixed; @@ -1156,6 +1172,20 @@ img { } @media (max-width: 480px) { + .logo-text { + font-size: 0.85rem; + } + + .logo { + gap: 4px; + max-width: 60%; + } + + .logo-text .accent { + display: inline; + } + + .why-grid { grid-template-columns: 1fr; } @@ -1168,3 +1198,12 @@ img { font-size: 0.8rem; } } +@media (max-width: 360px) { + .logo-text { + font-size: 0.75rem; + } + + .logo { + max-width: 55%; + } +} diff --git a/index.html b/index.html index d52c250..9b7665b 100644 --- a/index.html +++ b/index.html @@ -42,13 +42,6 @@ "url": "https://WilliamsPressureWashingServices.com", "telephone": "+1-740-502-3120", "email": "waltwilliams87@gmail.com", - "address": { - "@type": "PostalAddress", - "streetAddress": "26096 State Route 93", - "addressLocality": "Fresno", - "addressRegion": "OH", - "postalCode": "43824" - }, "areaServed": { "@type": "Place", "name": "Coshocton, Ohio and surrounding areas" @@ -64,7 +57,7 @@ - + @@ -159,13 +152,13 @@
🚌

Bus Fleet Washing

-

School buses, transit buses, shuttle buses β€” we handle all fleet sizes with thorough, efficient cleaning. Every job includes exterior wash, window & mirror cleaning, and undercarriage inspection and cleaning.

+

School buses, transit buses, shuttle buses β€” we handle all fleet sizes with thorough, efficient cleaning that keeps your vehicles safe and professional.

diff --git a/main.js b/main.js new file mode 100644 index 0000000..de5788b --- /dev/null +++ b/main.js @@ -0,0 +1,130 @@ +// Williams Pressure Washing Services - Main JS + +document.addEventListener('DOMContentLoaded', function() { + + // --- Navbar scroll effect --- + const navbar = document.getElementById('navbar'); + window.addEventListener('scroll', function() { + navbar.classList.toggle('scrolled', window.scrollY > 50); + }); + + // --- Mobile nav toggle --- + const navToggle = document.getElementById('navToggle'); + const navLinks = document.getElementById('navLinks'); + navToggle.addEventListener('click', function() { + navToggle.classList.toggle('active'); + navLinks.classList.toggle('active'); + }); + + // Close mobile nav on link click + navLinks.querySelectorAll('a').forEach(function(link) { + link.addEventListener('click', function() { + navToggle.classList.remove('active'); + navLinks.classList.remove('active'); + }); + }); + + // --- Smooth scroll for anchor links --- + document.querySelectorAll('a[href^="#"]').forEach(function(anchor) { + anchor.addEventListener('click', function(e) { + e.preventDefault(); + const target = document.querySelector(this.getAttribute('href')); + if (target) { + target.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + }); + }); + + // --- Floating CTA visibility --- + const floatingCta = document.getElementById('floatingCta'); + window.addEventListener('scroll', function() { + floatingCta.style.opacity = window.scrollY > 400 ? '1' : '0'; + floatingCta.style.pointerEvents = window.scrollY > 400 ? 'auto' : 'none'; + }); + floatingCta.style.opacity = '0'; + floatingCta.style.transition = 'opacity 0.3s ease'; + + // --- 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 >= 6) { + value = '(' + value.slice(0,3) + ') ' + value.slice(3,6) + '-' + value.slice(6,10); + } else if (value.length >= 3) { + value = '(' + value.slice(0,3) + ') ' + value.slice(3,6); + } + e.target.value = value; + }); + } + + // --- Contact form handling --- + const contactForm = document.getElementById('contactForm'); + if (contactForm) { + contactForm.addEventListener('submit', function(e) { + e.preventDefault(); + + const formData = new FormData(contactForm); + const data = {}; + formData.forEach(function(value, key) { + data[key] = value; + }); + + // Send via fetch to PHP endpoint (SMTP relay via hMailserver) + fetch('send-contact.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(data) + }) + .then(function(response) { + contactForm.innerHTML = + '
' + + '
βœ…
' + + '

Message Received!

' + + '

Thanks for reaching out! We\'ll be in touch soon.

' + + '

For urgent inquiries, please call (740) 502-3120

' + + '
'; + contactForm.style.pointerEvents = 'none'; + }) + .catch(function(err) { + // Fallback: open mailto if server unreachable + var subject = encodeURIComponent('Quote Request - ' + (data.service || 'General')); + var body = encodeURIComponent( + 'Name: ' + data.name + '\n' + + 'Phone: ' + data.phone + '\n' + + 'Email: ' + (data.email || 'Not provided') + '\n' + + 'Service: ' + (data.service || 'Not specified') + '\n\n' + + 'Message:\n' + (data.message || 'No message provided.') + ); + window.location.href = 'mailto:waltwilliams87@gmail.com?subject=' + subject + '&body=' + body; + contactForm.innerHTML = + '
' + + '
πŸ“§
' + + '

Opening Email Client...

' + + '

If your email didn\'t open, just call (740) 502-3120

' + + '
'; + contactForm.style.pointerEvents = 'none'; + }); + }); + } + + // --- Dynamic year --- + document.getElementById('year').textContent = new Date().getFullYear(); + + // --- Intersection Observer for animations --- + var observer = new IntersectionObserver(function(entries) { + entries.forEach(function(entry) { + if (entry.isIntersecting) { + entry.target.style.opacity = '1'; + entry.target.style.transform = 'translateY(0)'; + } + }); + }, { threshold: 0.1 }); + + document.querySelectorAll('.service-card, .why-item, .stat').forEach(function(el) { + el.style.opacity = '0'; + el.style.transform = 'translateY(30px)'; + el.style.transition = 'opacity 0.6s ease, transform 0.6s ease'; + observer.observe(el); + }); +}); diff --git a/progress.md b/progress.md index b68c3f4..43e95c2 100644 --- a/progress.md +++ b/progress.md @@ -22,25 +22,24 @@ ## Pending ### 🚨 SEO (HIGH PRIORITY β€” must be done before going live) -- [x] **Real favicon** β€” created πŸ’§ water droplet favicon matching site header icon (`favicon.png` 32x32 + `apple-touch-icon.png` 180x180) - [ ] **Real OG banner image** β€” replace placeholder `img/og-banner.jpg` with a proper 1200Γ—630 branded image -- [ ] **Google Search Console verification** β€” add meta tag or HTML file (domain purchased, DNS configured) -- [ ] **Google Business Profile** β€” set up (domain now live with SSL) -- [x] **Real photos in gallery** β€” replaced placeholder before/after slider with 'Our Work' section (5 real photos from Walter) -- [ ] **Alt text review** β€” ensure all real images have descriptive, keyword-rich alt text (Walter's input preferred) +- [ ] **Real favicon** β€” generate a proper `.ico` / `.png` favicon from a pressure washing logo (currently using inline SVG emoji) +- [ ] **Google Search Console verification** β€” add meta tag or HTML file after John purchases the domain +- [ ] **Google Business Profile** β€” set up once domain is live (Walter's business listing) +- [ ] **Alt text review** β€” ensure all real images have descriptive, keyword-rich alt text - [ ] **Page load optimization** β€” compress real images, minify CSS/JS - [ ] **Content review** β€” Walter to review all copy for accuracy before going live ### Contact Form / Email -- [x] **SMTP relay configuration** β€” PHPMailer connected to hMailserver on 10.10.9.31:25 (no auth, no TLS) +- [x] **SMTP relay configuration** β€” PHPMailer connected to hMailserver on 10.10.9.31:25 (no auth, no TLS) β€” relay handled by hMailserver/Mailjet - [x] **Test form end-to-end** β€” verified working (POST returns `{"success":true}`) -- [x] **Email delivery** β€” confirmed emails arrive at waltwilliams87@gmail.com -- [x] **Form spam protection** β€” honeypot field (`website_url`) β€” bots fill it, returns success silently +- [ ] **Test email delivery** β€” confirm message actually arrives at waltwilliams87@gmail.com (need real email to verify) +- [ ] **Form spam protection** β€” add honeypot field or privacy-respecting alternative to reCAPTCHA ### Hosting & Domain -- [x] **Purchase domain** β€” WilliamsPressureWashingServices.com -- [x] **DNS setup** β€” domain points to public IP, resolves correctly -- [x] **SSL certificate** β€” Let's Encrypt via Nginx Proxy Manager, valid through July 31 2026 +- [ ] **Purchase domain** β€” WilliamsPressureWashingServices.com (John to purchase) +- [ ] **DNS setup** β€” point domain to 10.10.9.230 (John to configure) +- [ ] **SSL certificate** β€” configure via Nginx Proxy Manager or Let's Encrypt on 10.10.9.230 - [ ] **PHP `mail()` config** β€” verify Postfix on 10.10.9.31 can relay for this server (10.10.9.230) ### Content & Branding @@ -58,13 +57,8 @@ ## Open Questions - Does Walter have hosting, or are we providing it? βœ… WE ARE PROVIDING (10.10.9.230) -- Domain purchased? βœ… WilliamsPressureWashingServices.com -- DNS configured? βœ… Points to public IP, SSL active -- SSL? βœ… Let's Encrypt via NPM, valid until July 31 -- Contact form spam protection? βœ… Honeypot field active -- Email delivery? βœ… Confirmed at waltwilliams87@gmail.com -- Favicon? βœ… πŸ’§ water droplet icon created and deployed -- Specific images/branding from Walter? ⏳ Still collecting +- Domain purchased? ⏳ John to purchase (next) +- Specific images/branding from Walter? ⏳ John to collect - Service area confirmed? βœ… Coshocton & surrounding areas - Hours of operation? βœ… Mon–Sat 7AM–7PM (placeholder, confirm with Walter)