mikeschlottig commited on
Commit
2917b05
·
verified ·
1 Parent(s): 1652593

Built out the Services, Projects and Contact Page. Ensure that the links in the footer work and are properly routed.

Browse files
Files changed (3) hide show
  1. index.html +174 -44
  2. script.js +40 -9
  3. style.css +20 -2
index.html CHANGED
@@ -112,14 +112,14 @@
112
  <h1 class="text-5xl md:text-7xl font-extrabold mb-6 leading-tight">Safe & Professional Tree Removal</h1>
113
  <p class="text-xl md:text-2xl mb-8 text-gray-200">Expert care for your property. Precision cutting, stump grinding, and 24/7 emergency storm services.</p>
114
  <div class="flex flex-col sm:flex-row gap-4 justify-center">
115
- <a href="#contact" onclick="router.navigate('contact')" class="bg-secondary-600 hover:bg-secondary-700 text-white font-bold py-4 px-8 rounded-lg shadow-lg transition transform hover:-translate-y-1">
116
  Get Free Estimate
117
  </a>
118
- <a href="#services" onclick="router.navigate('services')" class="bg-white/10 hover:bg-white/20 backdrop-blur-md text-white font-bold py-4 px-8 rounded-lg border border-white/30 transition">
119
  Our Services
120
  </a>
121
  </div>
122
- </div>
123
  </div>
124
 
125
  <!-- Trust Indicators -->
@@ -168,8 +168,8 @@
168
  </div>
169
  <h4 class="text-xl font-bold mb-2">Tree Removal</h4>
170
  <p class="text-gray-600 mb-4">Safe, strategic removal of dangerous or unwanted trees with minimal impact on your landscape.</p>
171
- <a href="#services" onclick="router.navigate('services')" class="text-secondary-600 font-bold hover:text-secondary-800 inline-flex items-center">Learn More <i data-feather="arrow-right" class="w-4 h-4 ml-1"></i></a>
172
- </div>
173
  </div>
174
  <!-- Service Card 2 -->
175
  <div class="bg-white rounded-xl shadow-lg overflow-hidden hover:shadow-2xl transition duration-300 group">
@@ -182,8 +182,8 @@
182
  </div>
183
  <h4 class="text-xl font-bold mb-2">Stump Grinding</h4>
184
  <p class="text-gray-600 mb-4">Professional grinding equipment to remove unsightly stumps and prevent regrowth or pest issues.</p>
185
- <a href="#services" onclick="router.navigate('services')" class="text-secondary-600 font-bold hover:text-secondary-800 inline-flex items-center">Learn More <i data-feather="arrow-right" class="w-4 h-4 ml-1"></i></a>
186
- </div>
187
  </div>
188
  <!-- Service Card 3 -->
189
  <div class="bg-white rounded-xl shadow-lg overflow-hidden hover:shadow-2xl transition duration-300 group">
@@ -196,8 +196,8 @@
196
  </div>
197
  <h4 class="text-xl font-bold mb-2">Trimming & Pruning</h4>
198
  <p class="text-gray-600 mb-4">Expert cutting to improve tree health, aesthetics, and safety around power lines and structures.</p>
199
- <a href="#services" onclick="router.navigate('services')" class="text-secondary-600 font-bold hover:text-secondary-800 inline-flex items-center">Learn More <i data-feather="arrow-right" class="w-4 h-4 ml-1"></i></a>
200
- </div>
201
  </div>
202
  </div>
203
  </div>
@@ -320,7 +320,6 @@
320
 
321
  <!-- Footer Component -->
322
  <custom-footer></custom-footer>
323
-
324
  <!-- Web Components Scripts -->
325
  <script>
326
  // HEADER COMPONENT
@@ -354,6 +353,7 @@
354
  display: flex;
355
  align-items: center;
356
  gap: 0.5rem;
 
357
  }
358
  .nav-desktop {
359
  display: none;
@@ -383,6 +383,7 @@
383
  font-weight: 600;
384
  text-decoration: none;
385
  transition: background-color 0.2s;
 
386
  }
387
  .btn-cta:hover {
388
  background-color: #b45309;
@@ -420,39 +421,92 @@
420
  text-decoration: none;
421
  font-weight: 600;
422
  border-bottom: 1px solid #f1f5f9;
 
 
 
 
423
  }
424
  </style>
425
  <header>
426
  <div class="container">
427
- <a href="#home" class="logo" onclick="window.router.navigate('home')">
428
- <i data-feather="box" style="fill: #059669;"></i> TimberTitan
429
- </a>
 
430
 
431
  <nav class="nav-desktop">
432
- <a onclick="window.router.navigate('home')" class="nav-link active" data-target="home">Home</a>
433
- <a onclick="window.router.navigate('services')" class="nav-link" data-target="services">Services</a>
434
- <a onclick="window.router.navigate('projects')" class="nav-link" data-target="projects">Projects</a>
435
- <a onclick="window.router.navigate('contact')" class="nav-link" data-target="contact">Contact</a>
436
- <a onclick="window.router.navigate('contact')" class="btn-cta">Get Quote</a>
437
  </nav>
438
 
439
- <button class="mobile-menu-btn" onclick="document.querySelector('.mobile-menu').classList.toggle('open')">
440
- <i data-feather="menu"></i>
441
  </button>
442
  </div>
443
  <div class="mobile-menu">
444
- <a onclick="window.router.navigate('home')" class="mobile-link">Home</a>
445
- <a onclick="window.router.navigate('services')" class="mobile-link">Services</a>
446
- <a onclick="window.router.navigate('projects')" class="mobile-link">Projects</a>
447
- <a onclick="window.router.navigate('contact')" class="mobile-link">Contact</a>
448
  </div>
449
  </header>
450
  `;
451
- feather.replace();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
452
  }
453
  }
454
  customElements.define('custom-header', CustomHeader);
455
-
456
  // FOOTER COMPONENT
457
  class CustomFooter extends HTMLElement {
458
  connectedCallback() {
@@ -491,14 +545,27 @@
491
  .footer-links li {
492
  margin-bottom: 0.75rem;
493
  }
494
- .footer-links a {
495
  color: #94a3b8;
496
- text-decoration: none;
497
  transition: color 0.2s;
 
498
  }
499
- .footer-links a:hover {
500
  color: white;
501
  }
 
 
 
 
 
 
 
 
 
 
 
 
502
  .copyright {
503
  text-align: center;
504
  border-top: 1px solid #334155;
@@ -506,49 +573,112 @@
506
  padding-top: 2rem;
507
  font-size: 0.875rem;
508
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
509
  </style>
510
  <footer>
511
  <div class="footer-grid">
512
  <div class="footer-col">
513
  <h3>TimberTitan</h3>
514
  <p>Professional tree care services dedicated to safety, quality, and customer satisfaction. Serving the community since 1995.</p>
 
 
 
 
 
 
 
 
 
 
 
515
  </div>
516
  <div class="footer-col">
517
  <h3>Services</h3>
518
  <ul class="footer-links">
519
- <li><a href="#" onclick="window.router.navigate('services')">Tree Removal</a></li>
520
- <li><a href="#" onclick="window.router.navigate('services')">Stump Grinding</a></li>
521
- <li><a href="#" onclick="window.router.navigate('services')">Emergency Services</a></li>
522
- <li><a href="#" onclick="window.router.navigate('services')">Land Clearing</a></li>
 
 
523
  </ul>
524
  </div>
525
  <div class="footer-col">
526
  <h3>Quick Links</h3>
527
  <ul class="footer-links">
528
- <li><a href="#" onclick="window.router.navigate('home')">About Us</a></li>
529
- <li><a href="#" onclick="window.router.navigate('projects')">Recent Projects</a></li>
530
- <li><a href="#" onclick="window.router.navigate('contact')">Contact Us</a></li>
531
- <li><a href="#">Privacy Policy</a></li>
 
532
  </ul>
533
  </div>
534
  <div class="footer-col">
535
- <h3>Contact</h3>
536
- <ul class="footer-links">
537
- <li>(555) 123-4567</li>
538
- <li>help@timbertitan.com</li>
539
- <li>123 Forest Drive, CA</li>
 
 
 
 
 
 
 
 
 
 
 
 
 
540
  </ul>
541
  </div>
542
  </div>
543
  <div class="copyright">
544
- <p>&copy; 2023 TimberTitan Services. All rights reserved.</p>
545
  </div>
546
  </footer>
547
  `;
 
 
 
 
 
 
 
 
 
 
 
 
 
548
  }
549
  }
550
  customElements.define('custom-footer', CustomFooter);
551
- </script>
552
 
553
  <!-- Main Logic Script -->
554
  <script src="script.js"></script>
 
112
  <h1 class="text-5xl md:text-7xl font-extrabold mb-6 leading-tight">Safe & Professional Tree Removal</h1>
113
  <p class="text-xl md:text-2xl mb-8 text-gray-200">Expert care for your property. Precision cutting, stump grinding, and 24/7 emergency storm services.</p>
114
  <div class="flex flex-col sm:flex-row gap-4 justify-center">
115
+ <a href="javascript:void(0)" onclick="window.router.navigate('contact')" class="bg-secondary-600 hover:bg-secondary-700 text-white font-bold py-4 px-8 rounded-lg shadow-lg transition transform hover:-translate-y-1 cursor-pointer">
116
  Get Free Estimate
117
  </a>
118
+ <a href="javascript:void(0)" onclick="window.router.navigate('services')" class="bg-white/10 hover:bg-white/20 backdrop-blur-md text-white font-bold py-4 px-8 rounded-lg border border-white/30 transition cursor-pointer">
119
  Our Services
120
  </a>
121
  </div>
122
+ </div>
123
  </div>
124
 
125
  <!-- Trust Indicators -->
 
168
  </div>
169
  <h4 class="text-xl font-bold mb-2">Tree Removal</h4>
170
  <p class="text-gray-600 mb-4">Safe, strategic removal of dangerous or unwanted trees with minimal impact on your landscape.</p>
171
+ <a href="javascript:void(0)" onclick="window.router.navigate('services')" class="text-secondary-600 font-bold hover:text-secondary-800 inline-flex items-center cursor-pointer">Learn More <i data-feather="arrow-right" class="w-4 h-4 ml-1"></i></a>
172
+ </div>
173
  </div>
174
  <!-- Service Card 2 -->
175
  <div class="bg-white rounded-xl shadow-lg overflow-hidden hover:shadow-2xl transition duration-300 group">
 
182
  </div>
183
  <h4 class="text-xl font-bold mb-2">Stump Grinding</h4>
184
  <p class="text-gray-600 mb-4">Professional grinding equipment to remove unsightly stumps and prevent regrowth or pest issues.</p>
185
+ <a href="javascript:void(0)" onclick="window.router.navigate('services')" class="text-secondary-600 font-bold hover:text-secondary-800 inline-flex items-center cursor-pointer">Learn More <i data-feather="arrow-right" class="w-4 h-4 ml-1"></i></a>
186
+ </div>
187
  </div>
188
  <!-- Service Card 3 -->
189
  <div class="bg-white rounded-xl shadow-lg overflow-hidden hover:shadow-2xl transition duration-300 group">
 
196
  </div>
197
  <h4 class="text-xl font-bold mb-2">Trimming & Pruning</h4>
198
  <p class="text-gray-600 mb-4">Expert cutting to improve tree health, aesthetics, and safety around power lines and structures.</p>
199
+ <a href="javascript:void(0)" onclick="window.router.navigate('services')" class="text-secondary-600 font-bold hover:text-secondary-800 inline-flex items-center cursor-pointer">Learn More <i data-feather="arrow-right" class="w-4 h-4 ml-1"></i></a>
200
+ </div>
201
  </div>
202
  </div>
203
  </div>
 
320
 
321
  <!-- Footer Component -->
322
  <custom-footer></custom-footer>
 
323
  <!-- Web Components Scripts -->
324
  <script>
325
  // HEADER COMPONENT
 
353
  display: flex;
354
  align-items: center;
355
  gap: 0.5rem;
356
+ cursor: pointer;
357
  }
358
  .nav-desktop {
359
  display: none;
 
383
  font-weight: 600;
384
  text-decoration: none;
385
  transition: background-color 0.2s;
386
+ cursor: pointer;
387
  }
388
  .btn-cta:hover {
389
  background-color: #b45309;
 
421
  text-decoration: none;
422
  font-weight: 600;
423
  border-bottom: 1px solid #f1f5f9;
424
+ cursor: pointer;
425
+ }
426
+ .mobile-link:hover {
427
+ color: #059669;
428
  }
429
  </style>
430
  <header>
431
  <div class="container">
432
+ <div class="logo" data-navigate="home">
433
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#059669" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg>
434
+ TimberTitan
435
+ </div>
436
 
437
  <nav class="nav-desktop">
438
+ <span class="nav-link active" data-target="home">Home</span>
439
+ <span class="nav-link" data-target="services">Services</span>
440
+ <span class="nav-link" data-target="projects">Projects</span>
441
+ <span class="nav-link" data-target="contact">Contact</span>
442
+ <span class="btn-cta" data-navigate="contact">Get Quote</span>
443
  </nav>
444
 
445
+ <button class="mobile-menu-btn">
446
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
447
  </button>
448
  </div>
449
  <div class="mobile-menu">
450
+ <span class="mobile-link" data-navigate="home">Home</span>
451
+ <span class="mobile-link" data-navigate="services">Services</span>
452
+ <span class="mobile-link" data-navigate="projects">Projects</span>
453
+ <span class="mobile-link" data-navigate="contact">Contact</span>
454
  </div>
455
  </header>
456
  `;
457
+
458
+ // Add click handlers after DOM is ready
459
+ setTimeout(() => {
460
+ const logo = this.shadowRoot.querySelector('.logo');
461
+ const navLinks = this.shadowRoot.querySelectorAll('.nav-link');
462
+ const mobileLinks = this.shadowRoot.querySelectorAll('.mobile-link');
463
+ const ctaBtn = this.shadowRoot.querySelector('.btn-cta');
464
+ const menuBtn = this.shadowRoot.querySelector('.mobile-menu-btn');
465
+ const mobileMenu = this.shadowRoot.querySelector('.mobile-menu');
466
+
467
+ // Logo click
468
+ if (logo) {
469
+ logo.addEventListener('click', () => {
470
+ if (window.router) window.router.navigate('home');
471
+ });
472
+ }
473
+
474
+ // Nav links
475
+ navLinks.forEach(link => {
476
+ link.addEventListener('click', () => {
477
+ const target = link.getAttribute('data-target');
478
+ if (window.router) window.router.navigate(target);
479
+ });
480
+ });
481
+
482
+ // Mobile links
483
+ mobileLinks.forEach(link => {
484
+ link.addEventListener('click', () => {
485
+ const target = link.getAttribute('data-navigate');
486
+ if (window.router) {
487
+ window.router.navigate(target);
488
+ mobileMenu.classList.remove('open');
489
+ }
490
+ });
491
+ });
492
+
493
+ // CTA button
494
+ if (ctaBtn && ctaBtn.getAttribute('data-navigate')) {
495
+ ctaBtn.addEventListener('click', () => {
496
+ if (window.router) window.router.navigate('contact');
497
+ });
498
+ }
499
+
500
+ // Mobile menu toggle
501
+ if (menuBtn && mobileMenu) {
502
+ menuBtn.addEventListener('click', () => {
503
+ mobileMenu.classList.toggle('open');
504
+ });
505
+ }
506
+ }, 0);
507
  }
508
  }
509
  customElements.define('custom-header', CustomHeader);
 
510
  // FOOTER COMPONENT
511
  class CustomFooter extends HTMLElement {
512
  connectedCallback() {
 
545
  .footer-links li {
546
  margin-bottom: 0.75rem;
547
  }
548
+ .footer-link {
549
  color: #94a3b8;
550
+ cursor: pointer;
551
  transition: color 0.2s;
552
+ display: inline-block;
553
  }
554
+ .footer-link:hover {
555
  color: white;
556
  }
557
+ .contact-info {
558
+ list-style: none;
559
+ padding: 0;
560
+ margin: 0;
561
+ }
562
+ .contact-info li {
563
+ margin-bottom: 0.75rem;
564
+ color: #94a3b8;
565
+ display: flex;
566
+ align-items: center;
567
+ gap: 0.5rem;
568
+ }
569
  .copyright {
570
  text-align: center;
571
  border-top: 1px solid #334155;
 
573
  padding-top: 2rem;
574
  font-size: 0.875rem;
575
  }
576
+ .social-links {
577
+ display: flex;
578
+ gap: 1rem;
579
+ margin-top: 1rem;
580
+ }
581
+ .social-link {
582
+ width: 40px;
583
+ height: 40px;
584
+ background-color: #334155;
585
+ border-radius: 50%;
586
+ display: flex;
587
+ align-items: center;
588
+ justify-content: center;
589
+ cursor: pointer;
590
+ transition: background-color 0.2s;
591
+ }
592
+ .social-link:hover {
593
+ background-color: #d97706;
594
+ }
595
+ .social-link svg {
596
+ width: 18px;
597
+ height: 18px;
598
+ }
599
  </style>
600
  <footer>
601
  <div class="footer-grid">
602
  <div class="footer-col">
603
  <h3>TimberTitan</h3>
604
  <p>Professional tree care services dedicated to safety, quality, and customer satisfaction. Serving the community since 1995.</p>
605
+ <div class="social-links">
606
+ <div class="social-link">
607
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"/></svg>
608
+ </div>
609
+ <div class="social-link">
610
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="20" rx="5" ry="5"/><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/><line x1="17.5" y1="6.5" x2="17.51" y2="6.5"/></svg>
611
+ </div>
612
+ <div class="social-link">
613
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"/></svg>
614
+ </div>
615
+ </div>
616
  </div>
617
  <div class="footer-col">
618
  <h3>Services</h3>
619
  <ul class="footer-links">
620
+ <li><span class="footer-link" data-navigate="services">Tree Removal</span></li>
621
+ <li><span class="footer-link" data-navigate="services">Stump Grinding</span></li>
622
+ <li><span class="footer-link" data-navigate="services">Emergency Services</span></li>
623
+ <li><span class="footer-link" data-navigate="services">Land Clearing</span></li>
624
+ <li><span class="footer-link" data-navigate="services">Tree Pruning</span></li>
625
+ <li><span class="footer-link" data-navigate="services">Cabling & Bracing</span></li>
626
  </ul>
627
  </div>
628
  <div class="footer-col">
629
  <h3>Quick Links</h3>
630
  <ul class="footer-links">
631
+ <li><span class="footer-link" data-navigate="home">Home</span></li>
632
+ <li><span class="footer-link" data-navigate="services">All Services</span></li>
633
+ <li><span class="footer-link" data-navigate="projects">Recent Projects</span></li>
634
+ <li><span class="footer-link" data-navigate="contact">Get Free Quote</span></li>
635
+ <li><span class="footer-link">Privacy Policy</span></li>
636
  </ul>
637
  </div>
638
  <div class="footer-col">
639
+ <h3>Contact Us</h3>
640
+ <ul class="contact-info">
641
+ <li>
642
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
643
+ (555) 123-4567
644
+ </li>
645
+ <li>
646
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
647
+ help@timbertitan.com
648
+ </li>
649
+ <li>
650
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
651
+ 123 Forest Drive, Woodland Hills, CA
652
+ </li>
653
+ <li>
654
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
655
+ Mon - Sat: 7AM - 6PM
656
+ </li>
657
  </ul>
658
  </div>
659
  </div>
660
  <div class="copyright">
661
+ <p>&copy; 2023 TimberTitan Services. All rights reserved. | Licensed & Insured | Lic# 123456</p>
662
  </div>
663
  </footer>
664
  `;
665
+
666
+ // Add click handlers
667
+ setTimeout(() => {
668
+ const footerLinks = this.shadowRoot.querySelectorAll('.footer-link');
669
+ footerLinks.forEach(link => {
670
+ link.addEventListener('click', () => {
671
+ const target = link.getAttribute('data-navigate');
672
+ if (window.router && target) {
673
+ window.router.navigate(target);
674
+ }
675
+ });
676
+ });
677
+ }, 0);
678
  }
679
  }
680
  customElements.define('custom-footer', CustomFooter);
681
+ </script>
682
 
683
  <!-- Main Logic Script -->
684
  <script src="script.js"></script>
script.js CHANGED
@@ -57,7 +57,6 @@ const projectsData = [
57
  { title: "Hazardous Limb Removal", location: "Suburbia", img: "http://static.photos/nature/640x360/14" },
58
  { title: "Commercial Clearing", location: "Industrial Park", img: "http://static.photos/nature/640x360/15" },
59
  ];
60
-
61
  class Router {
62
  constructor() {
63
  this.routes = ['home', 'services', 'projects', 'contact'];
@@ -107,6 +106,9 @@ class Router {
107
  // Load specific page data if needed
108
  if (pageId === 'services') this.loadServices();
109
  if (pageId === 'projects') this.loadProjects();
 
 
 
110
  }
111
 
112
  updateNavState(activeId) {
@@ -123,9 +125,21 @@ class Router {
123
  });
124
  }
125
  }
 
 
 
 
 
 
 
 
 
 
126
 
127
  async loadServices() {
128
  const grid = document.getElementById('services-grid');
 
 
129
  // Check if already loaded to prevent re-render
130
  if (grid.children.length > 1 && !grid.querySelector('.spinner')) return;
131
 
@@ -141,22 +155,38 @@ class Router {
141
  </div>
142
  <div class="p-8 flex-grow flex flex-col">
143
  <div class="w-12 h-12 bg-primary-100 rounded-lg flex items-center justify-center text-primary-600 mb-4">
144
- <i data-feather="${service.icon}"></i>
 
 
145
  </div>
146
  <h4 class="text-xl font-bold mb-2">${service.title}</h4>
147
  <p class="text-gray-600 mb-4 flex-grow">${service.desc}</p>
148
- <a href="#contact" onclick="window.router.navigate('contact')" class="text-secondary-600 font-bold hover:text-secondary-800 inline-flex items-center self-start">
149
- Request Service <i data-feather="arrow-right" class="w-4 h-4 ml-1"></i>
150
- </a>
 
151
  </div>
152
  </div>
153
  `).join('');
154
- feather.replace();
155
  }, 600);
156
  }
 
 
 
 
 
 
 
 
 
 
 
 
157
 
158
  loadProjects() {
159
  const grid = document.getElementById('gallery-grid');
 
 
160
  if (grid.children.length > 0) return;
161
 
162
  const html = projectsData.map(proj => `
@@ -164,15 +194,16 @@ class Router {
164
  <img src="${proj.img}" alt="${proj.title}" class="w-full h-full object-cover transition duration-500 group-hover:scale-110">
165
  <div class="absolute inset-0 bg-gradient-to-t from-black/80 to-transparent opacity-0 group-hover:opacity-100 transition duration-300 flex flex-col justify-end p-6">
166
  <h4 class="text-white font-bold text-xl">${proj.title}</h4>
167
- <p class="text-gray-300 text-sm"><i data-feather="map-pin" class="w-3 h-3 inline"></i> ${proj.location}</p>
 
 
 
168
  </div>
169
  </div>
170
  `).join('');
171
  grid.innerHTML = html;
172
- feather.replace();
173
  }
174
  }
175
-
176
  // Initialize Router when DOM is ready
177
  let router;
178
  document.addEventListener('DOMContentLoaded', () => {
 
57
  { title: "Hazardous Limb Removal", location: "Suburbia", img: "http://static.photos/nature/640x360/14" },
58
  { title: "Commercial Clearing", location: "Industrial Park", img: "http://static.photos/nature/640x360/15" },
59
  ];
 
60
  class Router {
61
  constructor() {
62
  this.routes = ['home', 'services', 'projects', 'contact'];
 
106
  // Load specific page data if needed
107
  if (pageId === 'services') this.loadServices();
108
  if (pageId === 'projects') this.loadProjects();
109
+
110
+ // Close mobile menu if open
111
+ this.closeMobileMenu();
112
  }
113
 
114
  updateNavState(activeId) {
 
125
  });
126
  }
127
  }
128
+
129
+ closeMobileMenu() {
130
+ const header = document.querySelector('custom-header');
131
+ if (header && header.shadowRoot) {
132
+ const mobileMenu = header.shadowRoot.querySelector('.mobile-menu');
133
+ if (mobileMenu) {
134
+ mobileMenu.classList.remove('open');
135
+ }
136
+ }
137
+ }
138
 
139
  async loadServices() {
140
  const grid = document.getElementById('services-grid');
141
+ if (!grid) return;
142
+
143
  // Check if already loaded to prevent re-render
144
  if (grid.children.length > 1 && !grid.querySelector('.spinner')) return;
145
 
 
155
  </div>
156
  <div class="p-8 flex-grow flex flex-col">
157
  <div class="w-12 h-12 bg-primary-100 rounded-lg flex items-center justify-center text-primary-600 mb-4">
158
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
159
+ ${this.getIconPath(service.icon)}
160
+ </svg>
161
  </div>
162
  <h4 class="text-xl font-bold mb-2">${service.title}</h4>
163
  <p class="text-gray-600 mb-4 flex-grow">${service.desc}</p>
164
+ <button onclick="window.router.navigate('contact')" class="text-secondary-600 font-bold hover:text-secondary-800 inline-flex items-center self-start cursor-pointer bg-transparent border-0 p-0">
165
+ Request Service
166
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="ml-1"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
167
+ </button>
168
  </div>
169
  </div>
170
  `).join('');
 
171
  }, 600);
172
  }
173
+
174
+ getIconPath(iconName) {
175
+ const icons = {
176
+ 'log-out': '<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/>',
177
+ 'disc': '<circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/>',
178
+ 'scissors': '<circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><line x1="20" y1="4" x2="8.12" y2="15.88"/><line x1="14.47" y1="14.48" x2="20" y2="20"/><line x1="8.12" y1="8.12" x2="12" y2="12"/>',
179
+ 'alert-triangle': '<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>',
180
+ 'map': '<polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/>',
181
+ 'anchor': '<circle cx="12" cy="5" r="3"/><line x1="12" y1="22" x2="12" y2="8"/><path d="M5 12H2a10 10 0 0 0 20 0h-3"/>'
182
+ };
183
+ return icons[iconName] || icons['log-out'];
184
+ }
185
 
186
  loadProjects() {
187
  const grid = document.getElementById('gallery-grid');
188
+ if (!grid) return;
189
+
190
  if (grid.children.length > 0) return;
191
 
192
  const html = projectsData.map(proj => `
 
194
  <img src="${proj.img}" alt="${proj.title}" class="w-full h-full object-cover transition duration-500 group-hover:scale-110">
195
  <div class="absolute inset-0 bg-gradient-to-t from-black/80 to-transparent opacity-0 group-hover:opacity-100 transition duration-300 flex flex-col justify-end p-6">
196
  <h4 class="text-white font-bold text-xl">${proj.title}</h4>
197
+ <p class="text-gray-300 text-sm flex items-center">
198
+ <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-1"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
199
+ ${proj.location}
200
+ </p>
201
  </div>
202
  </div>
203
  `).join('');
204
  grid.innerHTML = html;
 
205
  }
206
  }
 
207
  // Initialize Router when DOM is ready
208
  let router;
209
  document.addEventListener('DOMContentLoaded', () => {
style.css CHANGED
@@ -46,8 +46,26 @@ body {
46
  .nav-link.active::after {
47
  width: 100%;
48
  }
49
-
50
  /* Utility for shadow root link handling (if needed) */
51
  a {
52
  text-decoration: none;
53
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  .nav-link.active::after {
47
  width: 100%;
48
  }
 
49
  /* Utility for shadow root link handling (if needed) */
50
  a {
51
  text-decoration: none;
52
+ }
53
+
54
+ /* Button reset for inline-flex buttons */
55
+ button.bg-transparent {
56
+ background: transparent;
57
+ border: none;
58
+ padding: 0;
59
+ margin: 0;
60
+ font: inherit;
61
+ color: inherit;
62
+ cursor: pointer;
63
+ }
64
+
65
+ button.bg-transparent:hover {
66
+ text-decoration: none;
67
+ }
68
+
69
+ button.bg-transparent svg {
70
+ pointer-events: none;
71
+ }