PageSourceSearch

https://exclusivecuador.netlify.app/app.js

js exclusivecuador.netlify.app collected 2026-10-03 10:42:55 UTC 120,521 bytes, 2,430 lines download raw bytes

1let currentLang = 'es';
2
3// --- DATA DEFINITIONS ---
4const mapLocations = [
5  { name: 'Cultura Manor', coords: [-0.20489229704067102, -78.49774984800666], url: 'https://www.culturamanor.com/' },
6  { name: 'Hacienda Pinsaquí', coords: [0.27985415810021125, -78.23947004800858], url: 'https://www.haciendapinsaqui.com/' },
7  { name: 'Hacienda Abraspungo', coords: [-1.6398183361810093, -78.64071554799848], url: 'https://haciendaabraspungo.com/' },
8  { name: 'Hacienda La Alegría', coords: [-0.4483615847880226, -78.58199848693125], url: 'https://haciendalaalegria.com/web/' },
9  { name: 'Maquipucuna Reserve', coords: [0.12445494728705161, -78.62911537684317], url: 'https://www.maquipucuna.org/' },
10  { name: 'Hamadryade Lodge', coords: [-1.0380095657414963, -77.70886836149693], url: 'https://hamadryade-lodge.com/' },
11  { name: 'Iguana Crossing', coords: [-0.9555366373685902, -90.97136631873319], url: 'https://iguanacrossing.com.ec/' },
12  { name: 'Hacienda La Ciénega', coords: [-0.77196802058979, -78.61955173450916], url: 'https://www.haciendalacienega.com/' }
13];
14
15const tourData = {
16  en: [
17    { nombre: 'QUITO HALF DAY EXPERIENCE', imagen: 'Tour 1.jpg', action: showQuitoHalfDayModal },
18    { nombre: 'QUITO FULL DAY EXPERIENCE', imagen: 'Tour 3.jpg', action: showQuitoFullDayModal },
19    { nombre: 'ANTISANA CONDORS EXPERIENCE', imagen: 'Tour 2.jpg', action: showAntisanaCondorsModal },
20    { nombre: 'COTOPAXI VOLCANO EXPERIENCE', imagen: 'Tour 4.jpg', action: showCotopaxiVolcanoModal },
21    { nombre: 'SURROUNDINGS OF QUITO EXPERIENCE', imagen: 'Tour 5.jpg', action: showSurroundingsOfQuitoModal },
22    { nombre: 'OTAVALO MARKET EXPERIENCE', imagen: 'Tour 6.jpg', action: showOtavaloMarketModal },
23    { nombre: 'HORSE RIDER EXPERIENCE', imagen: 'Tour 7.jpg', action: showHorseRiderModal },
24    { nombre: 'SUMMITS OF THE SUN EXPERIENCE', imagen: 'Tour 8.jpg', action: showSummitsOfTheSunModal }
25  ],
26  es: [
27    { nombre: 'EXPERIENCIA DE MEDIO DÍA EN QUITO', imagen: 'Tour 1.jpg', action: showQuitoHalfDayModal },
28    { nombre: 'EXPERIENCIA DE DÍA COMPLETO EN QUITO', imagen: 'Tour 3.jpg', action: showQuitoFullDayModal },
29    { nombre: 'EXPERIENCIA CÓNDORES ANTISANA', imagen: 'Tour 2.jpg', action: showAntisanaCondorsModal },
30    { nombre: 'EXPERIENCIA VOLCÁN COTOPAXI', imagen: 'Tour 4.jpg', action: showCotopaxiVolcanoModal },
31    { nombre: 'EXPERIENCIA ALREDEDORES DE QUITO', imagen: 'Tour 5.jpg', action: showSurroundingsOfQuitoModal },
32    { nombre: 'EXPERIENCIA MERCADO DE OTAVALO', imagen: 'Tour 6.jpg', action: showOtavaloMarketModal },
33    { nombre: 'EXPERIENCIA CABALGATA', imagen: 'Tour 7.jpg', action: showHorseRiderModal },
34    { nombre: 'EXPERIENCIA CUMBRES DEL SOL', imagen: 'Tour 8.jpg', action: showSummitsOfTheSunModal }
35  ]
36};
37
38const emergencyContacts = {
39  en: [
40    { nombre: 'Police', numero: '911' },
41    { nombre: 'Fire Department', numero: '102' }
42  ],
43  es: [
44    { nombre: 'Policía', numero: '911' },
45    { nombre: 'Bomberos', numero: '102' }
46  ]
47};
48
49const transportData = {
50  flights: {
51    en: [
52      { nombre: 'Mariscal Sucre Airport', sitioWeb: 'https://www.quiport.com/contactenos/?lang=en', pbx: '+(593 2) 395-4200 / +(593 2) 395-4300', direccion: 'Quito-Tababela.' },
53      { nombre: 'Exclusive Air Travel', sitioWeb: 'https://www.instagram.com/exclusiveairtravel?igsh=MTd6MnY0am5zaDV1dw%3D%3D&utm_source=qr' }
54    ],
55    es: [
56      { nombre: 'Aeropuerto Mariscal Sucre', sitioWeb: 'https://www.quiport.com', pbx: '+(593 2) 395-4200 / +(593 2) 395-4300', direccion: 'Parroquia Tababela, vía a Yaruquí.' },
57      { nombre: 'Viajes Aéreos Exclusivos en Helicóptero', sitioWeb: 'https://www.instagram.com/rent4wd?igsh=MXRtM2lseDRxMDUxNw%3D%3D&utm_source=qr' },
58      { nombre: 'Exclusive Air Travel', sitioWeb: 'https://www.instagram.com/exclusiveairtravel?igsh=MTd6MnY0am5zaDV1dw%3D%3D&utm_source=qr' }
59    ]
60  },
61  carRental: {
62    en: [
63      { nombre: 'Rent 4WD Safe hand at the Wheel.<br>CAR RENTAL SERVICE', sitioWeb: 'https://www.rent-4wd.com', backgroundImage: 'Rent 4WD.png' }
64    ],
65    es: [
66      { nombre: 'AVIS Ret a Car', sitioWeb: 'https://www.avis.com/es/locations/ec/quito' }
67    ]
68  }
69};
70
71const sitesData = {
72  'Cultura Manor': {
73    image: '1CMInt.jpg',
74    services: {
75      website: 'https://culturamanor.com/services/',
76      options: [
77        { name: 'Romantic Getaway', icon: 'fa-heart', action: showRomanticModal },
78        { name: 'Restaurant', icon: 'fa-utensils', action: showRestaurantModal },
79        { name: 'Spa & Wellness', icon: 'fa-spa', action: showSpaModal },
80        { name: 'Wedding Planner', icon: 'fa-ring', action: showWeddingPlannerModal },
81        { name: 'Concierge Service', icon: 'fa-whatsapp', url: 'https://api.whatsapp.com/se
81nd/?phone=593994959502&text=Hello%2C+I+need+to+contact+reception&type=phone_number&app_absent=0' }
82      ]
83    }
84  },
85  'Hacienda Pinsaquí': {
86    image: '2HPInt.jpg',
87    services: {
88      options: [
89        { name: 'Restaurant', icon: 'fa-utensils', action: showPinsaquiRestaurantModal },
90        { name: 'Events & Wedding Planner', icon: 'fa-ring', action: showPinsaquiEventsModal },
91        { name: 'Tours', icon: 'fa-route', action: showPinsaquiToursModal },
92        { name: 'Activities', icon: 'fa-puzzle-piece', action: showPinsaquiActivitiesModal },
93        { name: 'Spa', icon: 'fa-spa', action: showPinsaquiSpaModal },
94        { name: 'Concierge Service', icon: 'fa-whatsapp', url: 'https://api.whatsapp.com/send/?phone=593999484819&text&type=phone_number&app_absent=0' }
95      ]
96    }
97  },
98  'Hacienda Abraspungo': {
99    image: '3HAInt.jpg',
100    services: {
101      website: 'https://haciendaabraspungo.com/descubre-abraspungo/',
102      options: [
103        { name: 'Restaurant', icon: 'fa-utensils', action: () => showGenericServiceModal('Restaurant', 'Empieza el día con un variado desayuno, al medío día sabores nacionales e internacionales para compartir en familia o amigos. Y al anochecer, una romántica cena junto a esa persona especial.', 'https://haciendaabraspungo.com/descubre-abraspungo/', true) },
104        { name: 'Eventos', icon: 'fa-calendar-alt', action: () => showGenericServiceModal('Eventos', 'Abraspungo es excelencia en eventos. Entendemos que los detalles marcan la diferencia. ¡Haremos ese día inolvidable!', 'https://haciendaabraspungo.com/descubre-abraspungo/', true) },
105        { name: 'Spa', icon: 'fa-spa', action: () => showGenericServiceModal('Spa', '<b>Masajes de Desbloqueo(60 min):</b> Desbloquea puntos emocionales y son liberados en una Sanación emocional.<br><b>Masaje relajante (60 min):</b> Sus beneficios son calmar dolores de espalda, favorece la circulación sanguínea, reduciendo el estrés.', 'https://haciendaabraspungo.com/descubre-abraspungo/', true) },
106        { name: 'Clases de Pintura', icon: 'fa-paint-brush', action: () => showGenericServiceModal('Clases de Pintura', 'Para grandes o pequeños, disfruta del contacto con la pintura y el lienzo cerca de la naturaleza en nuestros jardines. INCLUYE: Materiales.', 'https://haciendaabraspungo.com/descubre-abraspungo/', true) },
107        { name: 'Horseback Riding', icon: 'fa-horse', action: () => showGenericServiceModal('Horseback Riding', 'Paseo a caballo cubillines (4 horas) Aventura, increíbles paisajes y las mejores fotografías en esta increíble experiencia. Vívela en familia o en pareja, una experiencia que no olvidarán.INCLUYE: Transporte y snacks.', 'https://haciendaabraspungo.com/descubre-abraspungo/', true) },
108        { name: 'Caballos para niños', icon: 'fa-child', action: () => showGenericServiceModal('Caballos para niños', 'Los niños y los caballos tienen una conexión especial, fomenta este vínculo desde pequeños con nuestros dóciles caballos dentro de la hacienda con un guía especilizado.', 'https://haciendaabraspungo.com/descubre-abraspungo/', true) },
109        { name: 'Trekking Cubillines', icon: 'fa-hiking', action: () => showGenericServiceModal('Trekking Cubillines', 'Tus sentidos en pleno contacto con la naturaleza, recorre increíbles rutas llenas de aventura. Te aseguramos paisajes que no olvidarás. INCLUYE: Transporte y Snacks.', 'https://haciendaabraspungo.com/descubre-abraspungo/', true) },
110        { name: 'Romantic Getaway', icon: 'fa-heart', action: () => showGenericServiceModal('Romantic Getaway', 'Por aniversario, cumpleaños o esa ocasión especial; esta noche será inolvidable con una exquisita y romántica cena junto a la chimenea. INCLUYE: Cena de tres tiempos. Copa de Champagne. Copa de vino.', 'https://haciendaabraspungo.com/descubre-abraspungo/', true) },
111        { name: 'Concierge Service', icon: 'fa-whatsapp', url: 'https://api.whatsapp.com/send?phone=593997683450&text=%20' }
112      ]
113    }
114  },
115  'Hacienda La Alegría': {
116    image: '5HLAInt.jpg',
117    services: {
118      options: [
119        { name: 'Horseback Riding', icon: 'fa-horse', action: () => showGenericServiceModal('Horseback Riding', 'We offer day rides for those new to riding, travellers with limited time, or those who just want a brief taste of the fresh mountain air! We also run a program of more adventurous multi-day trips travelling on horseback through the mountains, forests and paramo (high grasslands) of the Andes. Details of some of our rides can be found on the menu on the right. For groups of two or more we are also happy to organize itineraries customized to your requirements.', 'https://haciendalaalegria.com/web/destination/horseback-riding/', true) },
120        { name: 'Ecotourism', icon: 'fa-leaf', action: () => showGenericServiceModal('Ecotourism', 'Explore the various ecotourism options available at Hacienda La Alegría.<br><br><a href="https://haciendalaalegria.com/web/destination/working-farm/" target="_blank" class="btn btn-primary mb-2 w-100">Working Farm</a><a href="https://haciendalaalegria.com/web/destination/things-to-do/" target="_blank" class="btn btn-primary w-100">Tours & Activities</a>', 'https://haciendalaalegria.com/web/destination/working-farm/', true) }
121      ]
122    }
123  },
124  'Maquipucuna Reserve': {
125    image: '6MRLInt.jpg',
126    services: {
127      website: 'https://www.maquipucuna.org/activities',
128      options: [
129        { name: 'EcoTours', icon: 'fa-leaf', action: () => showGenericServiceModal('EcoTours', 'Cloud Forest Discovery Tours, Cloud Forest Birding Tours, Cloud Forest Adventure & Community Tours. Visit the main activities page for more details.', 'https://www.maquipucuna.org/activities', true) },
130        { name: 'ANDEAN SPECTACLED BEARS', icon: 'fa-paw', action: () => showGenericServiceModal('Andean Spectacled Bears', 'A unique opportunity to see the Andean Spectacled Bears. Visit the main activities page for more details.', 'https://www.maquipucuna.org/activities', true) },
131        { name: 'BIRDING PARADISE', icon: 'fa-dove', action: () => showGenericServiceModal('Birding Paradise', 'Explore a paradise for birdwatchers. Visit the main activities page for more details.', 'https://www.maquipucuna.org/activities', true) },
132        { name: 'ORCHIDS & BUTTERFLIES', icon: 'fa-fan', action: () => showGenericServiceModal('Orchids & Butterflies', 'Discover the vibrant world of orchids and butterflies. Visit the main activities page for more details.', 'https://www.maquipucuna.org/activities', true) },
133        { name: 'NIGHT HIKES', icon: 'fa-moon', action: () => showGenericServiceModal('Night Hikes', 'Experience the cloud forest at night. Visit the main activities page for more details.', 'https://www.maquipucuna.org/activities', true) },
134        { name: 'Swimming & Hiking', icon: 'fa-swimmer', action: () => showGenericServiceModal('Swimming & Hiking', 'Enjoy swimming and hiking through beautiful trails. Visit the main activities page for more details.', 'https://www.maquipucuna.org/activities', true) },
135        { name: 'Mindo, Ziplines & Tulipe', icon: 'fa-tree', action: () => showGenericServiceModal('Mindo, Ziplines & Tulipe', 'Adventure awaits with ziplines and cultural visits. Visit the main activities page for more details.', 'https://www.maquipucuna.org/activities', true) },
136        { name: 'WATERFALLS, SWIMMINGHOLES & 32 KM OF TRAILS', icon: 'fa-water', action: () => showGenericServiceModal('Waterfalls & Trails', 'Explore waterfalls, swimming holes, and 32 km of trails. Visit the main activities page for more details.', 'https://www.maquipucuna.org/activities', true) }
137      ]
138    }
139  },
140  'Hamadryade Lodge': {
141    image: '7HLInt.jpg',
142    services: {
143      website: 'https://hamadryade-lodge.com/actividades/',
144      options: [
145        { name: 'Actividades Acuáticas', icon: 'fa-water', action: () => showGenericServiceModal('Actividades Acuáticas', 'Rafting class III, Rafting class IV, Kayak, Tubbing, Cascadas de las latas, Cascada de Umbini, Cascadas de Rumi Yacu.', 'https://hamadryade-lodge.com/actividades/', true) },
146        { name: 'Actividades Culturales', icon: 'fa-landmark', action: () => showGenericServiceModal('Actividades Culturales', 'Pesca tradicional, Visita comunidad Kichwa, Taller chocolate, Taller cacao, Construye tu balsa, Taller de cerámica, Museo Kamak Maki, Visita comunidad Waorani.', 'https://hamadryade-lodge.com/actividades/', true) },
147        { name: 'Actividades de Naturaleza', icon: 'fa-leaf', action: () => showGenericServiceModal('Actividades de Naturaleza', 'Amazónico rescue center, Avistamiento aves, Visita de la chacra, Laguna Paikawe o K
147awana, Visita Ceibo, Observación de saladero de loros, Tour del meliponario.', 'https://hamadryade-lodge.com/actividades/', true) },
148        { name: 'Actividades de Aventura', icon: 'fa-hiking', action: () => showGenericServiceModal('Actividades de Aventura', 'Cavernas de Ponceloma, Caminata Machacu Yacu, Caminata Aitaka, Caminata nocturna, Caminata Jatun Sacha, Tour en avioneta, Rent a bike.', 'https://hamadryade-lodge.com/actividades/', true) },
149        { name: 'Retiros', icon: 'fa-praying-hands', action: () => showGenericServiceModal('Retiros', 'Desde hace más de 13 años, Hamadryade Lodge & Retreat Center acoge retiros transformadores en el corazón de la Amazonía ecuatoriana. Nuestro centro, rodeado por 64 hectáreas de bosque protegido, es un santuario de reconexión profunda con la naturaleza, el cuerpo y el espíritu. En Hamadryade, la naturaleza es maestra y medicina. Cada retiro está cuidadosamente diseñado para que vivas un proceso personal único, en un entorno de privacidad, belleza y contención espiritual.', 'https://hamadryade-lodge.com/retiros/', true) }
150      ]
151    }
152  },
153  'Iguana Crossing': {
154    image: '9ICG.png',
155    services: {
156      website: 'https://iguanacrossing.com.ec/services/',
157      options: [
158        { name: 'Restaurant', icon: 'fa-utensils', action: () => showGenericServiceModal('Restaurant', 'Among the chef\'s exquisite creations, featuring gourmet fusion dishes and our standout specialty: the lava stone barbecue. Experience true culinary artistry with delicacies paired perfectly with organic vegetables and vibrant greens from our highland farm in Isabela. Complement your meal with refreshing, freshly squeezed fruit juices that elevate every bite into a remarkable flavor journey.', 'https://iguanacrossing.com.ec/services/', true) },
159        { name: 'Wedding Planner', icon: 'fa-ring', action: () => showGenericServiceModal('Wedding Planner', 'Celebrate love where nature itself bears witness. Iguana Crossing offers an intimate and breathtaking setting for your special day — from a romantic beachfront ceremony to personalized details that turn your wedding into a once-in-a-lifetime experience.', 'https://iguanacrossing.com.ec/services/', true) },
160        { name: 'Concierge Service', icon: 'fa-whatsapp', url: 'https://wa.link/1swbam' }
161      ]
162    }
163  },
164  'Hacienda La Ciénega': {
165    image: '10 HLc.jpg',
166    services: {
167      options: [
168        { name: 'Rooms', icon: 'fa-bed', action: () => showGenericServiceModal('Rooms', 'Feel the spirit of the colonial era in the 21st century. With pieces from the 17th century, our rooms have a historical touch that recovers the memory of the hacienda, and combines with contemporary nuances to meet the highest standards of hospitality and elegance.', 'https://www.haciendalacienega.com/habitaciones/', true) },
169        { name: 'Restaurant', icon: 'fa-utensils', action: () => showGenericServiceModal('Restaurant', 'Decorated hallways, the warmth of the fire, and old-fashioned dishes. The atmosphere of our dining room provides perfect settings to taste family recipes next to windows overlooking the garden; or if you prefer something more intimate, the lounges are ideal for afternoon gatherings with friends, surrounded by the golden light of a fireplace.', 'https://www.haciendalacienega.com/wp-content/uploads/2025/08/Carta-La-Cienega-2025.pdf', true) }
170      ]
171    }
172  }
173};
174
175const cityWalkVideos = [
176  { name: 'Hotel Cultura Manor - Quito', videoId: 'we8Ol0sqmnQ' },
177  { name: 'Exclusive Hotels & Haciendas of Ecuador', videoId: 'mLzzcfzcWhg' },
178  { name: 'Tunas y Cabras - Imbabura', videoId: 'cS_0b5lAFC8' }
179];
180
181const sponsors = [
182  { name: 'Cultura Manor', logo: 'LOGO_CM-.png', url: 'https://culturamanor.com/' },
183  { name: 'EO Arte & Cultura', logo: 'LOgo Art.png', url: 'https://www.instagram.com/eo.artecultura/' }
184];
185
186const bookingUrls = {
187  'Cultura Manor': 'https://culturamanor.com/book-now/',
188  'Hacienda Pinsaquí': 'https://app.reservationcentric.com/hosteria-hacienda-pinsaqui/book-now#/choose-dates',
189  'Hacienda Abraspungo': 'https://hotels.cloudbeds.com/es/reservation/ekjvTe?widget=1&checkin=2023-03-20&checkout=2023-03-21&currency=usd',
190  'Hacienda La Alegría': 'https://haciendalaalegria.com/web/destination/reservation/',
191  'Maquipucuna Reserve': 'https://www.maquipucuna.org/cloudforest-all-inclusive-packages?lang=es',
192  'Hamadryade Lodge': 'https://hotels.cloudbeds.com/reservation/nTs36P',
193  'Iguana Crossing': 'https://iguanacrossing.com.ec/book-now/',
194  'Hacienda La Ciénega': 'https://www.haciendalacienega.com/'
195};
196
197// --- GLOBAL FUNCTIONS ---
198function toggleLanguage() {
199  currentLang = currentLang === 'en' ? 'es' : 'en';
200  document.getElementById('lang-text').textContent = currentLang === 'en' ? 'ES' : 'EN';
201  
202  const elements = document.querySelectorAll('[data-en], [data-es]');
203  elements.forEach(el => {
204    if (el.hasAttribute(`data-${currentLang}`)) {
205      el.innerHTML = el.getAttribute(`data-${currentLang}`);
206    }
207  });
208  
209  const inputs = document.querySelectorAll('[data-placeholder-en], [data-placeholder-es]');
210  inputs.forEach(input => {
211    if (input.hasAttribute(`data-placeholder-${currentLang}`)) {
212      input.placeholder = input.getAttribute(`data-placeholder-${currentLang}`);
213    }
214  });
215  
216  // Reload dynamic content
217  cargarJourneys();
218  cargarEmergencias();
219  cargarServiciosTransporte();
220  cargarServicios();
221}
222
223function createModal(title, content, extraClasses = '') {
224  const modal = document.createElement('div');
225  modal.classList.add('modal', 'show');
226  if (extraClasses) modal.classList.add(extraClasses);
227  modal.style.display = 'block';
228  modal.innerHTML = `
229    <div class="modal-dialog modal-lg modal-dialog-scrollable">
230      <div class="modal-content">
231        <div class="modal-header">
232          <h5 class="modal-title">${title}</h5>
233          <button type="button" class="btn-close btn-close-white close-modal"></button>
234        </div>
235        <div class="modal-body">${content}</div>
236      </div>
237    </div>
238  `;
239  const closeModalButton = modal.querySelector('.close-modal');
240  closeModalButton.addEventListener('click', () => modal.remove());
241  modal.addEventListener('click', (e) => {
242    if (e.target === modal) modal.remove();
243  });
244  return modal;
245}
246
247// Function to send email notification
248function sendEmailNotification(subject, messageData) {
249  const formspreeUrl = 'https://formspree.io/f/mdayobwe';
250  const emailData = {
251    _subject: subject,
252    ...messageData
253  };
254  
255  console.log('Sending email notification:', subject, emailData);
256  fetch(formspreeUrl, {
257    method: 'POST',
258    headers: { 'Content-Type': 'application/json' },
259    body: JSON.stringify(emailData)
260  })
261  .then(res => {
262    console.log('Email response status:', res.status, res.statusText);
263    if (!res.ok) {
264      console.error('Email error - Status:', res.status, 'StatusText:', res.statusText);
265      return res.text().then(text => {
266        console.error('Email error body:', text);
267        throw new Error(`HTTP ${res.status}: ${text}`);
268      });
269    }
270    return res.json();
271  })
272  .then(data => {
273    console.log('Email sent successfully:', data);
274  })
275  .catch(err => {
276    console.error('Error sending email:', err);
277    alert('Error al enviar email: ' + err.message);
278  });
279}
280
281// Test function to verify Telegram connection
282function testTelegramConnection() {
283  const telegramToken = '8641660748:AAEkXojnvRPk7ZXHmXEwEOBYsm2m2x2-7Y0';
284  const chatId = '1853367208';
285  fetch(`https://api.telegram.org/bot${telegramToken}/sendMessage`, {
286    method: 'POST',
287    headers: { 'Content-Type': 'application/json' },
288    body: JSON.stringify({
289      chat_id: chatId,
290      text: '🧪 Test message from Exclusive Ecuador App - Connection test successful!',
291      parse_mode: 'HTML'
292    })
293  })
294  .then(res => res.json())
295  .then(data => {
296    if(data.ok) {
297      alert('✅ Test message sent successfully! Check your Telegram.');
298    } else {
299      alert('❌ Telegram error: ' + (data.description || data.error_code || 'Unknown'));
300    }
301  })
302  .catch(err => {
303    alert('❌ Connection error: ' + err.message);
304  });
305}
306
307function handleFormSubmit(form, modal) {
308  const button = form.querySelector('button[type="submit"]');
309  button.disabled = true;
310  button.textContent = 'Sending...';
311  
312  const formData = new FormData(form);
313  const subject = formData.get('_subject') || 'New Request';
314  
315  // Build message from form data
316  let message = `<b>${subject}</b>\n`;
317  for (let [key, value] of formData.entries()) {
318    if (!key.startsWith('_') && value) {
319      message += `<b>${key}:</b> ${value}\n`;
320    }
321  }
322  
323  console.log('Mensaje a enviar:', message);
324  
325  // Send to Telegram
326  const telegramToken = '8641660748:AAEkXojnvRPk7ZXHmXEwEOBYsm2m2x2-7Y0';
327  const chatId = '1853367208';
328  const telegramUrl = `https://api.telegram.org/bot${telegramToken}/sendMessage`;
329  console.log('URL de Telegram:', telegramUrl);
330  
331  // Send email notification
332  const emailData = {};
333  for (let [key, value] of formData.entries()) {
334    if (!key.startsWith('_') && value) {
335      emailData[key] = value;
336    }
337  }
338  emailData['_replyto'] = formData.get('Contact') || '';
339  sendEmailNotification(subject, emailData);
340  
341  fetch(telegramUrl, {
342    method: 'POST',
343    headers: { 'Content-Type': 'application/json' },
344    body: JSON.stringify({
345      chat_id: chatId,
346      text: message,
347      parse_mode: 'HTML'
348    })
349  })
350  .then(res => {
351    console.log('Respuesta de Telegram:', res);
352    return res.json();
353  })
354  .then(data => {
355    console.log('Datos de respuesta:', data);
356    if(data.ok) {
357      if(modal) modal.remove();
358      document.body.appendChild(createModal('Request Sent', '<p>Thank you for your request. We will contact you shortly to confirm.</p>'));
359    } else {
360      console.error('Error de Telegram:', data);
361      button.disabled = false;
362      button.textContent = 'Send Request';
363      alert('Error de Telegram: ' + (data.description || data.error_code || 'Unknown error'));
364    }
365  })
366  .catch(err => {
367    console.error('Error en fetch:', err);
368    button.disabled = false;
369    button.textContent = 'Send Request';
370    alert('Error de conexión: ' + err.message);
371  });
372}
373
374// --- MODAL DISPLAY FUNCTIONS ---
375function showGenericServiceModal(title, content, url, useNotification = false) {
376  const buttonText = useNotification ? 'Book Now' : 'Learn More';
377  const buttonClass = useNotification ? 'generic-service-book-btn' : 'generic-service-link';
378  const modalContent = `
379    <p>${content}</p>
380    ${url ? `<div class="text-center my-4"><button class="btn btn-primary ${buttonClass}" data-url="${url}">${buttonText}</button></div>` : ''}
381  `;
382  const modal = createModal(title, modalContent);
383  document.body.appendChild(modal);
384  
385  // Add email notification when clicking button
386  if (url) {
387    const button = modal.querySelector(`.${buttonClass}`);
388    button.addEventListener('click', () => {
389      // Get IP, city and country
390      fetch('https://ipapi.co/json/')
391      .then(res => res.json())
392      .then(data => {
393        const ip = data.ip || 'Unknown';
394        const city = data.city || 'Unknown';
395        const country = data.country_name || 'Unknown';
396        
397        if (useNotification) {
398          // Send both Telegram and Email notifications
399          const telegramToken = '8641660748:AAEkXojnvRPk7ZXHmXEwEOBYsm2m2x2-7Y0';
400          const chatId = '1853367208';
401          const telegramUrl = `https://api.telegram.org/bot${telegramToken}/sendMessage`;
402          const time = new Date().toLocaleString();
403          const message = `🏨 *Service Interest: ${title}*\n` +
404            `👤 Usuario interesado en: ${title}\n` +
405            `📅 Fecha y hora: ${time}\n` +
406            `🌍 Ciudad: ${city}\n` +
407            `🏳️ País: ${country}\n` +
408            `🔗 URL: ${url}`;
409            
410          fetch(telegramUrl, {
411            method: 'POST',
412            headers: { 'Content-Type': 'application/json' },
413            body: JSON.stringify({
414              chat_id: chatId,
415              text: message,
416              parse_mode: 'Markdown'
417            })
418          })
419          .then(res => res.json())
420          .then(data => {
421            sendEmailNotification(`Service Interest: ${title}`, {
422              'Service': title,
423              'URL': url,
424              'Fecha y hora': time,
425              'IP': ip,
426              'Ciudad': city,
427              'País': country
428            });
429            window.open(url, '_blank');
430          })
431          .catch(err => {
432            console.error('Error sending Telegram notification:', err);
433            sendEmailNotification(`Service Interest: ${title}`, {
434              'Service': title,
435              'URL': url,
436              'Fecha y hora': time,
437              'IP': ip,
438              'Ciudad': city,
439              'País': country
440            });
441            window.open(url, '_blank');
442          });
443        } else {
444          // Only send email notification
445          sendEmailNotification(`Service Interest: ${title}`, {
446            'Service': title,
447            'URL': url,
448            'Fecha y hora': new Date().toLocaleString(),
449            'IP': ip,
450            'Ciudad': city,
451            'País': country
452          });
453          window.open(url, '_blank');
454        }
455      })
456      .catch(err => {
457        console.error('Error getting IP info:', err);
458        // Open URL even if IP fetch fails
459        window.open(url, '_blank');
460      });
461    });
462  }
463}
464
465function showPinsaquiRestaurantModal() {
466  const title = 'Hacienda Pinsaquí Restaurants';
467  const content = `
468    <p>Discover our three exclusive restaurants:</p>
469    <div class="d-grid gap-3 mt-4">
470      <button onclick="sendRestaurantClickNotification('Restaurante Pedro Freile', 'https://www.haciendapinsaqui.com/restaurante-pedro-freile.html')" class="btn btn-primary">
471        <i class="fas fa-utensils me-2"></i> Restaurante Pedro Freile
472      </button>
473      <button onclick="sendRestaurantClickNotification('Restaurante Modesto Larrea', 'https://www.haciendapinsaqui.com/restaurante-modesto-larrea.html')" class="btn btn-primary">
474        <i class="fas fa-utensils me-2"></i> Restaurante Modesto Larrea
475      </button>
476      <button onclick="sendRestaurantClickNotification('Restaurante Bar Ecuestre', 'https://www.haciendapinsaqui.com/bar-ecuestre.html')" class="btn btn-primary">
477        <i class="fas fa-glass-cheers me-2"></i> Restaurante Bar Ecuestre
478      </button>
479    </div>
480  `;
481  const modal = createModal(title, content);
482  document.body.appendChild(modal);
483}
484
485function showPinsaquiEventsModal() {
486  const title = 'Events & Wedding Planner';
487  const content = `
488    <p>At Hacienda Pinsaquí we have ample spaces, ideal for that special event that should be unique and, with us, will be unforgettable. And if it comes to corporate events, here you will find the perfect/unique/appropriate environment that your firm has been looking for. Our staff is prepared to provide the exclusive service that great moments require.</p>
489    <div class="text-center my-4">
490      <button onclick="sendEventsClickNotification('https://www.haciendapinsaqui.com/eventos.html')" class="btn btn-primary">Learn More</button>
491    </div>
492  `;
493  const modal = createModal(title, content);
494  document.body.appendChild(modal);
495}
496
497function sendEventsClickNotification(eventsUrl) {
498  const now = new Date();
499  const time = now.toLocaleString();
500  // Get IP, city and country
501  fetch('https://ipapi.co/json/')
502  .then(res => res.json())
503  .then(data => {
504    const ip = data.ip || 'Unknown';
505    const city = data.city || 'Unknown';
506    const country = data.country_name || 'Unknown';
507    
508    // Send to Telegram
509    const telegramToken = '8641660748:AAEkXojnvRPk7ZXHmXEwEOBYsm2m2x2-7Y0';
510    const chatId = '1853367208';
511    const message = `<b>💒 Click en Events & Wedding Planner</b>\n` +
512      `<b>Fecha y hora:</b> ${time}\n` +
513      `<b>IP:</b> ${ip}\n` +
514      `<b>Ciudad:</b> ${city}\n` +
515      `<b>País:</b> ${country}`;
516      
517    fetch(`https://api.telegram.org/bot${telegramToken}/sendMessage`, {
518      method: 'POST',
519      headers: { 'Content-Type': 'application/json' },
520      body: JSON.stringify({
521        chat_id: chatId,
522        text: message,
523        parse_mode: 'HTML'
524      })
525    })
526    .then(res => res.json())
527    .then(data => {
528      // Send email notification
529      sendEmailNotification('Click en Events & Wedding Planner', {
530        'Fecha y hora': time,
531        'IP': ip,
532        'Ciudad': city,
533        'País': country,
534        'URL': eventsUrl
535      });
536      // Close modal and open events URL after sending notification
537      document.querySelector('.modal').remove();
538      window.open(eventsUrl, '_blank');
539    })
540    .catch(err => {
541      console.error('Error sending notification:', err);
542      // Close modal and open events URL even if notification fails
543      document.querySelector('.modal').remove();
544      window.open(eventsUrl, '_blank');
545    });
546  })
547  .catch(err => {
548    console.error('Error getting IP:', err);
549    // Close modal and open events URL even if IP fetch fails
550    document.querySelector('.modal').remove();
551    window.open(eventsUrl, '_blank');
552  });
553}
554
555function showPinsaquiToursModal() {
556  const title = 'Tours';
557  const content = `
558    <p>Horseback riding, trekking, hot springs.</p>
559    <div class="text-center my-4">
560      <button onclick="sendToursClickNotification('https://www.haciendapinsaqui.com/tours.html')" class="btn btn-primary">Learn More</button>
561    </div>
562  `;
563  const modal = createModal(title, content);
564  document.body.appendChild(modal);
565}
566
567function sendToursClickNotification(toursUrl) {
568  const now = new Date();
569  const time = now.toLocaleString();
570  // Get IP, city and country
571  fetch('https://ipapi.co/json/')
572  .then(res => res.json())
573  .then(data => {
574    const ip = data.ip || 'Unknown';
575    const city = data.city || 'Unknown';
576    const country = data.country_name || 'Unknown';
577    
578    // Send to Telegram
579    const telegramToken = '8641660748:AAEkXojnvRPk7ZXHmXEwEOBYsm2m2x2-7Y0';
580    const chatId = '1853367208';
581    const message = `<b>🏔️ Click en Tours</b>\n` +
582      `<b>Fecha y hora:</b> ${time}\n` +
583      `<b>IP:</b> ${ip}\n` +
584      `<b>Ciudad:</b> ${city}\n` +
585      `<b>País:</b> ${country}`;
586      
587    fetch(`https://api.telegram.org/bot${telegramToken}/sendMessage`, {
588      method: 'POST',
589      headers: { 'Content-Type': 'application/json' },
590      body: JSON.stringify({
591        chat_id: chatId,
592        text: message,
593        parse_mode: 'HTML'
594      })
595    })
596    .then(res => res.json())
597    .then(data => {
598      // Send email notification
599      sendEmailNotification('Click en Tours', {
600        'Fecha y hora': time,
601        'IP': ip,
602        'Ciudad': city,
603        'País': country,
604        'URL': toursUrl
605      });
606      // Close modal and open tours URL after sending notification
607      document.querySelector('.modal').remove();
608      window.open(toursUrl, '_blank');
609    })
610    .catch(err => {
611      console.error('Error sending notification:', err);
612      // Close modal and open tours URL even if notification fails
613      document.querySelector('.modal').remove();
614      window.open(toursUrl, '_blank');
615    });
616  })
617  .catch(err => {
618    console.error('Error getting IP:', err);
619    // Close modal and open tours URL even if IP fetch fails
620    document.querySelector('.modal').remove();
621    window.open(toursUrl, '_blank');
622  });
623}
624
625function showPinsaquiActivitiesModal() {
626  const title = 'Activities';
627  const content = `
628    <p>Cooking classes, handicraft classes, music classes.</p>
629    <div class="text-center my-4">
630      <button onclick="sendActivitiesClickNotification('https://www.haciendapinsaqui.com/actividades.html')" class="btn btn-primary">Learn More</button>
631    </div>
632  `;
633  const modal = createModal(title, content);
634  document.body.appendChild(modal);
635}
636
637function sendActivitiesClickNotification(activitiesUrl) {
638  const now = new Date();
639  const time = now.toLocaleString();
640  // Get IP, city and country
641  fetch('https://ipapi.co/json/')
642  .then(res => res.json())
643  .then(data => {
644    const ip = data.ip || 'Unknown';
645    const city = data.city || 'Unknown';
646    const country = data.country_name || 'Unknown';
647    
648    // Send to Telegram
649    const telegramToken = '8641660748:AAEkXojnvRPk7ZXHmXEwEOBYsm2m2x2-7Y0';
650    const chatId = '1853367208';
651    const message = `<b>🧩 Click en Activities</b>\n` +
652      `<b>Fecha y hora:</b> ${time}\n` +
653      `<b>IP:</b> ${ip}\n` +
654      `<b>Ciudad:</b> ${city}\n` +
655      `<b>País:</b> ${country}`;
656      
657    fetch(`https://api.telegram.org/bot${telegramToken}/sendMessage`, {
658      method: 'POST',
659      headers: { 'Content-Type': 'application/json' },
660      body: JSON.stringify({
661        chat_id: chatId,
662        text: message,
663        parse_mode: 'HTML'
664      })
665    })
666    .then(res => res.json())
667    .then(data => {
668      // Send email notification
669      sendEmailNotification('Click en Activities', {
670        'Fecha y hora': time,
671        'IP': ip,
672        'Ciudad': city,
673        'País': country,
674        'URL': activitiesUrl
675      });
676      // Close modal and open activities URL after sending notification
677      document.querySelector('.modal').remove();
678      window.open(activitiesUrl, '_blank');
679    })
680    .catch(err => {
681      console.error('Error sending notification:', err);
682      // Close modal and open activities URL even if notification fails
683      document.querySelector('.modal').remove();
684      window.open(activitiesUrl, '_blank');
685    });
686  })
687  .catch(err => {
688    console.error('Error getting IP:', err);
689    // Close modal and open activities URL even if IP fetch fails
690    document.querySelector('.modal').remove();
691    window.open(activitiesUrl, '_blank');
692  });
693}
694
695function showPinsaquiSpaModal() {
696  const title = 'Spa';
697  const content = `
698    <p>Bathtub baths.</p>
699    <div class="text-center my-4">
700      <button onclick="sendSpaClickNotification('https://www.haciendapinsaqui.com/spa.html')" class="btn btn-primary">Learn More</button>
701    </div>
702  `;
703  const modal = createModal(title, content);
704  document.body.appendChild(modal);
705}
706
707// Hacienda Abraspungo notification functions
708function sendAbraspungoServiceClickNotification(serviceName, serviceUrl) {
709  const now = new Date();
710  const time = now.toLocaleString();
711  // Get IP, city and country
712  fetch('https://ipapi.co/json/')
713  .then(res => res.json())
714  .then(data => {
715    const ip = data.ip || 'Unknown';
716    const city = data.city || 'Unknown';
717    const country = data.country_name || 'Unknown';
718    
719    // Send to Telegram
720    const telegramToken = '8641660748:AAEkXojnvRPk7ZXHmXEwEOBYsm2m2x2-7Y0';
721    const chatId = '1853367208';
722    const telegramUrl = `https://api.telegram.org/bot${telegramToken}/sendMessage`;
723    const message = `🏨 *Hacienda Abraspungo - ${serviceName}*\n` +
724      `👤 Usuario interesado en: ${serviceName}\n` +
725      `📅 Fecha y hora: ${time}\n` +
726      `🌍 Ciudad: ${city}\n` +
727      `🏳️ País: ${country}\n` +
728      `🔗 URL: ${serviceUrl}`;
729      
730    fetch(telegramUrl, {
731      method: 'POST',
732      headers: { 'Content-Type': 'application/json' },
733      body: JSON.stringify({
734        chat_id: chatId,
735        text: message,
736        parse_mode: 'Markdown'
737      })
738    })
739    .then(res => res.json())
740    .then(data => {
741      // Send email notification
742      sendEmailNotification(`Hacienda Abraspungo - ${serviceName}`, {
743        'Sitio': 'Hacienda Abraspungo',
744        'Servicio': serviceName,
745        'URL': serviceUrl,
746        'Fecha y hora': time,
747        'IP': ip,
748        'Ciudad': city,
749        'País': country
750      });
751      // Open service URL
752      window.open(serviceUrl, '_blank');
753    })
754    .catch(err => {
755      console.error('Error sending notification:', err);
756      window.open(serviceUrl, '_blank');
757    });
758  })
759  .catch(err => {
760    console.error('Error getting IP:', err);
761    window.open(serviceUrl, '_blank');
762  });
763}
764
765function sendSpaClickNotification(spaUrl) {
766  const now = new Date();
767  const time = now.toLocaleString();
768  // Get IP, city and country
769  fetch('https://ipapi.co/json/')
770  .then(res => res.json())
771  .then(data => {
772    const ip = data.ip || 'Unknown';
773    const city = data.city || 'Unknown';
774    const country = data.country_name || 'Unknown';
775    
776    // Send to Telegram
777    const telegramToken = '8641660748:AAEkXojnvRPk7ZXHmXEwEOBYsm2m2x2-7Y0';
778    const chatId = '1853367208';
779    const message = `<b>💆 Click en Spa</b>\n` +
780      `<b>Fecha y hora:</b> ${time}\n` +
781      `<b>IP:</b> ${ip}\n` +
782      `<b>Ciudad:</b> ${city}\n` +
783      `<b>País:</b> ${country}`;
784      
785    fetch(`https://api.telegram.org/bot${telegramToken}/sendMessage`, {
786      method: 'POST',
787      headers: { 'Content-Type': 'application/json' },
788      body: JSON.stringify({
789        chat_id: chatId,
790        text: message,
791        parse_mode: 'HTML'
792      })
793    })
794    .then(res => res.json())
795    .then(data => {
796      // Send email notification
797      sendEmailNotification('Click en Spa', {
798        'Fecha y hora': time,
799        'IP': ip,
800        'Ciudad': city,
801        'País': country,
802        'URL': spaUrl
803      });
804      // Close modal and open spa URL after sending notification
805      document.querySelector('.modal').remove();
806      window.open(spaUrl, '_blank');
807    })
808    .catch(err => {
809      console.error('Error sending notification:', err);
810      // Close modal and open spa URL even if notification fails
811      document.querySelector('.modal').remove();
812      window.open(spaUrl, '_blank');
813    });
814  })
815  .catch(err => {
816    console.error('Error getting IP:', err);
817    // Close modal and open spa URL even if IP fetch fails
818    document.querySelector('.modal').remove();
819    window.open(spaUrl, '_blank');
820  });
821}
822
823function sendRestaurantClickNotification(restaurantName, restaurantUrl) {
824  const now = new Date();
825  const time = now.toLocaleString();
826  // Get IP and country
827  fetch('https://ipapi.co/json/')
828  .then(res => res.json())
829  .then(data => {
830    const ip = data.ip || 'Unknown';
831    const country = data.country_name || 'Unknown';
832    
833    // Send to Telegram
834    const telegramToken = '8641660748:AAEkXojnvRPk7ZXHmXEwEOBYsm2m2x2-7Y0';
835    const chatId = '1853367208';
836    const message = `<b>🍽️ Click en Restaurante</b>\n` +
837      `<b>Restaurante:</b> ${restaurantName}\n` +
838      `<b>Hora:</b> ${time}\n` +
839      `<b>IP:</b> ${ip}\n` +
840      `<b>País:</b> ${country}`;
841      
842    fetch(`https://api.telegram.org/bot${telegramToken}/sendMessage`, {
843      method: 'POST',
844      headers: { 'Content-Type': 'application/json' },
845      body: JSON.stringify({
846        chat_id: chatId,
847        text: message,
848        parse_mode: 'HTML'
849      })
850    })
851    .then(res => res.json())
852    .then(data => {
853      // Send email notification
854      sendEmailNotification('Click en Restaurante', {
855        'Restaurante': restaurantName,
856        'Hora': time,
857        'IP': ip,
858        'País': country,
859        'URL': restaurantUrl
860      });
861      // Open restaurant URL after sending notification
862      window.open(restaurantUrl, '_blank');
863    })
864    .catch(err => {
865      console.error('Error sending notification:', err);
866      // Open restaurant URL even if notification fails
867      window.open(restaurantUrl, '_blank');
868    });
869  })
870  .catch(err => {
871    console.error('Error getting IP:', err);
872    // Open restaurant URL even if IP fetch fails
873    window.open(restaurantUrl, '_blank');
874  });
875}
876
877function showRomanticModal() {
878  const title = 'Romantic Getaway';
879  const content = `
880    <p>A magical night in a historic Quito mansion, with every detail designed to celebrate love.</p>
881    <div class="card bg-dark text-white my-3">
882      <div class="card-body">
883        <h5 class="card-title">Special Package for Couples</h5>
884        <ul class="list-unstyled">
885          <li><i class="fas fa-check text-primary me-2"></i>1 night in a romantic suite</li>
886          <li><i class="fas fa-check text-primary me-2"></i>Welcome cocktail</li>
887          <li><i class="fas fa-check text-primary me-2"></i>Intimate dinner for two</li>
888          <li><i class="fas fa-check text-primary me-2"></i>Special details in the room</li>
889          <li><i class="fas fa-check text-primary me-2"></i>Gourmet breakfast</li>
890          <li><i class="fas fa-check text-primary me-2"></i>Warm and exclusive atmosphere</li>
891        </ul>
892      </div>
893    </div>
894    <hr>
895    <h5 class="mb-3">Book Your Getaway</h5>
896    <form id="romantic-booking-form">
897      <input type="hidden" name="_subject" value="New Romantic Getaway Reservation">
898      <input type="hidden" name="Package" value="Romantic Getaway">
899      <div class="row">
900        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Full Name</label><input type="text" name="Full Name" class="form-control" required></div>
901        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Contact (Phone or Email)</label><input type="text" name="Contact" class="form-control" required></div>
902      </div>
903      <div class="mb-3"><label class="form-label fw-bold">Desired Date</label><input type="date" name="Date" class="form-control" required></div>
904      <div class="mb-3"><label class="form-label fw-bold">Message (optional)</label><textarea name="Message" class="form-control" rows="3"></textarea></div>
905      <button type="submit" class="btn btn-primary w-100">Book Now</button>
906    </form>
907  `;
908  const modal = createModal(title, content);
909  document.body.appendChild(modal);
910  modal.querySelector('input[type="date"]').value = new Date().toISOString().split('T')[0];
911  
912  modal.querySelector('#romantic-booking-form').addEventListener('submit', e => {
913    e.preventDefault();
914    const form = e.target;
915    const button = form.querySelector('button[type="submit"]');
916    button.disabled = true;
917    button.textContent = 'Sending...';
918    
919    const formData = new FormData(form);
920    // Send to Telegram
921    const subject = formData.get('_subject') || 'New Romantic Getaway Reservation';
922    let message = `<b>${subject}</b>\n`;
923    for (let [key, value] of formData.entries()) {
924      if (!key.startsWith('_') && value) {
925        message += `<b>${key}:</b> ${value}\n`;
926      }
927    }
928    
929    const telegramToken = '8641660748:AAEkXojnvRPk7ZXHmXEwEOBYsm2m2x2-7Y0';
930    const chatId = '1853367208';
931    fetch(`https://api.telegram.org/bot${telegramToken}/sendMessage`, {
932      method: 'POST',
933      headers: { 'Content-Type': 'application/json' },
934      body: JSON.stringify({
935        chat_id: chatId,
936        text: message,
937        parse_mode: 'HTML'
938      })
939    })
940    .then(res => res.json())
941    .then(data => {
942      // Send email notification
943      const emailData = {};
944      for (let [key, value] of formData.entries()) {
945        if (!key.startsWith('_') && value) {
946          emailData[key] = value;
947        }
948      }
949      emailData['_replyto'] = formData.get('Contact') || '';
950      sendEmailNotification('New Romantic Getaway Reservation', emailData);
951      
952      // Open WhatsApp with form data
953      const fullName = formData.get('Full Name') || '';
954      const contact = formData.get('Contact') || '';
955      const date = formData.get('Date') || '';
956      const messageText = formData.get('Message') || '';
957      const package = formData.get('Package') || 'Romantic Getaway';
958      const whatsappMessage = `Hola, me gustaría reservar el Romantic Getaway:\n` +
959        `Paquete: ${package}\n` +
960        `Nombre: ${fullName}\n` +
961        `Contacto: ${contact}\n` +
962        `Fecha: ${date}\n` +
963        `Mensaje: ${messageText}\n` +
964        `Por favor confirmen disponibilidad. Gracias!`;
965      window.open(`https://wa.me/593992010909?text=${encodeURIComponent(whatsappMessage)}`, '_blank');
966      modal.remove();
967    })
968    .catch(err => {
969      alert('An error occurred while sending your request.');
970      button.disabled = false;
971      button.textContent = 'Book Now';
972    });
973  });
974}
975
976function showRestaurantModal() {
977  const title = 'Restaurant Reservations';
978  const content = `
979    <p>Savor Ecuador’s rich flavors and international inspirations in our refined restaurant. From gourmet breakfasts to elegant dinners, every dish is crafted with fresh, seasonal ingredients and served in an intimate atmosphere.</p>
980    <div class="text-center my-4">
981      <a href="https://drive.google.com/file/d/1GKfxANGjnOe1Xl8Srssu9albg3jsbvww/view?usp=sharing" target="_blank" class="btn btn-primary"><i class="fas fa-cloud-download-alt"></i> Download Menu</a>
982    </div>
983    <hr>
984    <h5 class="mb-3">Make a Reservation</h5>
985    <form id="restaurant-booking-form">
986      <input type="hidden" name="_subject" value="New Restaurant Reservation Request">
987      <div class="row">
988        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Full Name</label><input type="text" name="Full Name" class="form-control" required></div>
989        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Contact (Phone or Email)</label><input type="text" name="Contact" class="form-control" required></div>
990      </div>
991      <div class="row">
992        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Date</label><input type="date" name="Date" class="form-control" required></div>
993        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Time</label><input type="time" name="Time" class="form-control" required></div>
994      </div>
995      <div class="mb-3"><label class="form-label fw-bold">Number of People</label><input type="number" name="Number of People" class="form-control" min="1" required></div>
996      <div class="mb-3"><label class="form-label fw-bold">Special Requests</label><textarea name="Special Requests" class="form-control" rows="3"></textarea></div>
997      <button type="submit" class="btn btn-primary w-100">Send Request</button>
998    </form>
999  `;
1000  const modal = createModal(title, content);
1001  document.body.appendChild(modal);
1002  modal.querySelector('input[type="date"]').value = new Date().toISOString().split('T')[0];
1003  
1004  modal.querySelector('#restaurant-booking-form').addEventListener('submit', e => {
1005    e.preventDefault();
1006    const form = e.target;
1007    const button = form.querySelector('button[type="submit"]');
1008    button.disabled = true;
1009    button.textContent = 'Sending...';
1010    
1011    const formData = new FormData(form);
1012    // Send to Telegram
1013    const subject = formData.get('_subject') || 'New Restaurant Reservation Request';
1014    let message = `<b>${subject}</b>\n`;
1015    for (let [key, value] of formData.entries()) {
1016      if (!key.startsWith('_') && value) {
1017        message += `<b>${key}:</b> ${value}\n`;
1018      }
1019    }
1020    
1021    const telegramToken = '8641660748:AAEkXojnvRPk7ZXHmXEwEOBYsm2m2x2-7Y0';
1022    const chatId = '1853367208';
1023    fetch(`https://api.telegram.org/bot${telegramToken}/sendMessage`, {
1024      method: 'POST',
1025      headers: { 'Content-Type': 'application/json' },
1026      body: JSON.stringify({
1027        chat_id: chatId,
1028        text: message,
1029        parse_mode: 'HTML'
1030      })
1031    })
1032    .then(res => res.json())
1033    .then(data => {
1034      // Send email notification
1035      const emailData = {};
1036      for (let [key, value] of formData.entries()) {
1037        if (!key.startsWith('_') && value) {
1038          emailData[key] = value;
1039        }
1040      }
1041      emailData['_replyto'] = formData.get('Contact') || '';
1042      sendEmailNotification('New Restaurant Reservation Request', emailData);
1043      
1044      // Open WhatsApp with form data
1045      const fullName = formData.get('Full Name') || '';
1046      const contact = formData.get('Contact') || '';
1047      const date = formData.get('Date') || '';
1048      const time = formData.get('Time') || '';
1049      const people = formData.get('Number of People') || '';
1050      const specialRequests = formData.get('Special Requests') || '';
1051      const whatsappMessage = `Hola, me gustaría hacer una reservación en el restaurante:\n` +
1052        `Nombre: ${fullName}\n` +
1053        `Contacto: ${contact}\n` +
1054        `Fecha: ${date}\n` +
1055        `Hora: ${time}\n` +
1056        `Personas: ${people}\n` +
1057        `Solicitudes especiales: ${specialRequests}\n` +
1058        `Por favor confirmen disponibilidad. Gracias!`;
1059      window.open(`https://wa.me/593992010909?text=${encodeURIComponent(whatsappMessage)}`, '_blank');
1060      modal.remove();
1061    })
1062    .catch(err => {
1063      alert('An error occurred while sending your request.');
1064      button.disabled = false;
1065      button.textContent = 'Send Request';
1066    });
1067  });
1068}
1069
1070function showSpaModal() {
1071  const title = 'Spa & Wellness';
1072  const content = `
1073    <p>Book a moment of pure relaxation. Select the services you desire and send us a request.</p>
1074    <form id="spa-booking-form">
1075      <input type="hidden" name="_subject" value="New Spa & Wellness Reservation">
1076      <div class="row">
1077        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Full Name</label><input type="text" name="Full Name" class="form-control" required></div>
1078        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Contact (Phone or Email)</label><input type="text" name="Contact" class="form-control" required></div>
1079      </div>
1080      <div class="row">
1081        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Desired Date</label><input type="date" name="Date" class="form-control" required></div>
1082        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Desired Time</label><input type="time" name="Time" class="form-control" required></div>
1083      </div>
1084      <hr>
1085      <h6>Select Your Services:</h6>
1086      <div class="row">
1087        <div class="col-md-6">
1088          <strong>Spa & Wellness</strong>
1089          <div class="form-check"><input class="form-check-input" type="checkbox" name="Services[]" value="Relaxing Massage (1hr)"><label class="form-check-label">Relaxing Massage (1hr)</label></div>
1090          <div class="form-check"><input class="form-check-input" type="checkbox" name="Services[]" value="Bamboo Massage (1hr)"><label class="form-check-label">Bamboo Massage (1hr)</label></div>
1091          <div class="form-check"><input class="form-check-input" type="checkbox" name="Services[]" value="Relieving Massage (1hr)"><label class="form-check-label">Relieving Massage (1hr)</label></div>
1092          <div class="form-check"><input class="form-check-input" type="checkbox" name="Services[]" value="Hot Stone Massage"><label class="form-check-label">Hot Stone Massage</label></div>
1093          <strong class="mt-3 d-block">Facials</strong>
1094          <div class="form-check"><input class="form-check-input" type="checkbox" name="Services[]" value="Organic Facial (60min)"><label class="form-check-label">Organic Facial (60min)</label></div>
1095          <div class="form-check"><input class="form-check-input" type="checkbox" name="Services[]" value="Renewing Facial (60min)"><label class="form-check-label">Renewing Facial (60min)</label></div>
1096        </div>
1097        <div class="col-md-6">
1098          <strong>Body Wraps</strong>
1099          <div class="form-check"><input class="form-check-input" type="checkbox" name="Services[]" value="Chocolate Wrap (45min)"><label class="form-check-label">Chocolate Wrap (45min)</label></div>
1100          <div class="form-check"><input class="form-check-input" type="checkbox" name="Services[]" value="Clay Wrap (45min)"><label class="form-check-label">Clay Wrap (45min)</label></div>
1101          <strong class="mt-3 d-block">Body Exfoliations</strong>
1102          <div class="form-check"><input class="form-check-input" type="checkbox" name="Services[]" value="Coffee Exfoliation (45min)"><label class="form-check-label">Coffee Exfoliation (45min)</label></div>
1103          <div class="form-check"><input class="form-check-input" type="checkbox" name="Services[]" value="Passion Fruit Scrub (45min)"><label class="form-check-label">Passion Fruit Scrub (45min)</label></div>
1104        </div>
1105      </div>
1106      <hr>
1107      <button type="submit" class="btn btn-primary w-100">Send Request</button>
1108    </form>
1109  `;
1110  const modal = createModal(title, content);
1111  document.body.appendChild(modal);
1112  modal.querySelector('input[type="date"]').value = new Date().toISOString().split('T')[0];
1113  
1114  modal.querySelector('#spa-booking-form').addEventListener('submit', e => {
1115    e.preventDefault();
1116    const form = e.target;
1117    const button = form.querySelector('button[type="submit"]');
1118    button.disabled = true;
1119    button.textContent = 'Sending...';
1120    
1121    const formData = new FormData(form);
1122    // Send to Telegram
1123    const subject = formData.get('_subject') || 'New Spa & Wellness Reservation';
1124    let message = `<b>${subject}</b>\n`;
1125    for (let [key, value] of formData.entries()) {
1126      if (!key.startsWith('_') && value) {
1127        message += `<b>${key}:</b> ${value}\n`;
1128      }
1129    }
1130    
1131    const telegramToken = '8641660748:AAEkXojnvRPk7ZXHmXEwEOBYsm2m2x2-7Y0';
1132    const chatId = '1853367208';
1133    fetch(`https://api.telegram.org/bot${telegramToken}/sendMessage`, {
1134      method: 'POST',
1135      headers: { 'Content-Type': 'application/json' },
1136      body: JSON.stringify({
1137        chat_id: chatId,
1138        text: message,
1139        parse_mode: 'HTML'
1140      })
1141    })
1142    .then(res => res.json())
1143    .then(data => {
1144      // Send email notification
1145      const emailData = {};
1146      for (let [key, value] of formData.entries()) {
1147        if (!key.startsWith('_') && value) {
1148          emailData[key] = value;
1149        }
1150      }
1151      // Get selected services
1152      const services = [];
1153      form.querySelectorAll('input[name="Services[]"]:checked').forEach(checkbox => {
1154        services.push(checkbox.value);
1155      });
1156      emailData['Services'] = services.join(', ') || 'No seleccionados';
1157      emailData['_replyto'] = formData.get('Contact') || '';
1158      sendEmailNotification('New Spa & Wellness Reservation', emailData);
1159      
1160      // Open WhatsApp with form data
1161      const fullName = formData.get('Full Name') || '';
1162      const contact = formData.get('Contact') || '';
1163      const date = formData.get('Date') || '';
1164      const time = formData.get('Time') || '';
1165      const whatsappMessage = `Hola, me gustaría reservar servicios de Spa & Wellness:\n` +
1166        `Nombre: ${fullName}\n` +
1167        `Contacto: ${contact}\n` +
1168        `Fecha: ${date}\n` +
1169        `Hora: ${time}\n` +
1170        `Servicios: ${services.join(', ') || 'No seleccionados'}\n` +
1171        `Por favor confirmen disponibilidad. Gracias!`;
1172      window.open(`https://wa.me/593992010909?text=${encodeURIComponent(whatsappMessage)}`, '_blank');
1173      modal.remove();
1174    })
1175    .catch(err => {
1176      alert('An error occurred while sending your request.');
1177      button.disabled = false;
1178      button.textContent = 'Send Request';
1179    });
1180  });
1181}
1182
1183function showWeddingPlannerModal() {
1184  const title = 'Wedding Planner';
1185  const content = `
1186    <p>Cultura Manor Hotel has qualified staff, infrastructure, equipment, and contacts in churches to host first-class weddings in Quito, Ecuador. Especially, the beautiful Gothic-style Santa Teresita Church, located just one block away, is an ideal option for your ceremony. <a href="https://maps.app.goo.gl/nfzKm53ZZu28nEHP9" target="_blank">Santa Teresita Church</a></p>
1187    <hr>
1188    <h5 class="mb-3">Plan Your Dream Wedding</h5>
1189    <form id="wedding-planner-form">
1190      <input type="hidden" name="_subject" value="New Wedding Planner Inquiry">
1191      <input type="hidden" name="_cc" value="[email protected]">
1192      <div class="row">
1193        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Full Name</label><input type="text" name="Full Name" class="form-control" required></div>
1194        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Contact (Phone or Email)</label><input type="text" name="Contact" class="form-control" required></div>
1195      </div>
1196      <div class="row">
1197        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Wedding Date</label><input type="date" name="Wedding Date" class="form-control" required></div>
1198        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Approximate Number of Guests</label><input type="number" name="Number of Guests" class="form-control" min="1"></div>
1199      </div>
1200      <div class="mb-3">
1201        <label class="form-label fw-bold">Requirements:</label>
1202        <div class="form-check"><input class="form-check-input" type="checkbox" name="Requirements[]" value="Catering"><label class="form-check-label">Catering</label></div>
1203        <div class="form-check"><input class="form-check-input" type="checkbox" name="Requirements[]" value="Artistic Show"><label class="form-check-label">Artistic Show</label></div>
1204        <div class="form-check"><input class="form-check-input" type="checkbox" name="Requirements[]" value="Live Music"><label class="form-check-label">Live Music</label></div>
1205        <div class="form-check"><input class="form-check-input" type="checkbox" name="Requirements[]" value="Santa Teresa Church"><label class="form-check-label">Santa Teresa Church</label></div>
1206        <div class="form-check"><input class="form-check-input" type="checkbox" name="Requirements[]" value="Reception"><label class="form-check-label">Reception</label></div>
1207        <div class="form-check"><input class="form-check-input" type="checkbox" name="Requirements[]" value="Master of Ceremonies"><label class="form-check-label">Master of Ceremonies</label></div>
1208        <div class="form-check"><input class="form-check-input" type="checkbox" name="Requirements[]" value="Floral Arrangements"><label class="form-check-label">Floral Arrangements</label></div>
1209      </div>
1210      <div class="mb-3"><label class="form-label fw-bold">Additional Message</label><textarea name="Additional Message" class="form-control" rows="3"></textarea></div>
1211      <hr>
1212      <div class="d-flex justify-content-between align-items-center">
1213        <button type="submit" class="btn btn-primary">Send Inquiry</button>
1214        <a href="https://api.whatsapp.com/send?phone=593994959503&text=Hello, I need information about wedding planning" target="_blank" class="modal-whatsapp-btn"><i class="fab fa-whatsapp"></i></a>
1215      </div>
1216    </form>
1217  `;
1218  const modal = createModal(title, content);
1219  document.body.appendChild(modal);
1220  modal.querySelector('input[type="date"]').value = new Date().toISOString().split('T')[0];
1221  
1222  modal.querySelector('#wedding-planner-form').addEventListener('submit', e => {
1223    e.preventDefault();
1224    const form = e.target;
1225    const button = form.querySelector('button[type="submit"]');
1226    button.disabled = true;
1227    button.textContent = 'Sending...';
1228    
1229    const formData = new FormData(form);
1230    // Send to Telegram
1231    const subject = formData.get('_subject') || 'New Wedding Planner Inquiry';
1232    let message = `<b>${subject}</b>\n`;
1233    for (let [key, value] of formData.entries()) {
1234      if (!key.startsWith('_') && value) {
1235        message += `<b>${key}:</b> ${value}\n`;
1236      }
1237    }
1238    
1239    const telegramToken = '8641660748:AAEkXojnvRPk7ZXHmXEwEOBYsm2m2x2-7Y0';
1240    const chatId = '1853367208';
1241    fetch(`https://api.telegram.org/bot${telegramToken}/sendMessage`, {
1242      method: 'POST',
1243      headers: { 'Content-Type': 'application/json' },
1244      body: JSON.stringify({
1245        chat_id: chatId,
1246        text: message,
1247        parse_mode: 'HTML'
1248      })
1249    })
1250    .then(res => res.json())
1251    .then(data => {
1252      // Send email notification
1253      const emailData = {};
1254      for (let [key, value] of formData.entries()) {
1255        if (!key.startsWith('_') && value) {
1256          emailData[key] = value;
1257        }
1258      }
1259      // Get selected requirements
1260      const requirements = [];
1261      form.querySelectorAll('input[name="Requirements[]"]:checked').forEach(checkbox => {
1262        requirements.push(checkbox.value);
1263      });
1264      emailData['Requirements'] = requirements.join(', ') || 'No seleccionados';
1265      emailData['_replyto'] = formData.get('Contact') || '';
1266      sendEmailNotification('New Wedding Planner Inquiry', emailData);
1267      
1268      // Open WhatsApp with form data
1269      const fullName = formData.get('Full Name') || '';
1270      const contact = formData.get('Contact') || '';
1271      const weddingDate = formData.get('Wedding Date') || '';
1272      const guests = formData.get('Number of Guests') || '';
1273      const additionalMessage = formData.get('Additional Message') || '';
1274      const whatsappMessage = `Hola, me gustaría información sobre Wedding Planner:\n` +
1275        `Nombre: ${fullName}\n` +
1276        `Contacto: ${contact}\n` +
1277        `Fecha de boda: ${weddingDate}\n` +
1278        `Número de invitados: ${guests}\n` +
1279        `Requisitos: ${requirements.join(', ') || 'No seleccionados'}\n` +
1280        `Mensaje adicional: ${additionalMessage}\n` +
1281        `Por favor envíenme información. Gracias!`;
1282      window.open(`https://wa.me/593992010909?text=${encodeURIComponent(whatsappMessage)}`, '_blank');
1283      modal.remove();
1284    })
1285    .catch(err => {
1286      alert('An error occurred while sending your request.');
1287      button.disabled = false;
1288      button.textContent = 'Send Inquiry';
1289    });
1290  });
1291}
1292
1293function showQuitoHalfDayModal() {
1294  const title = 'Quito Half Day Tour Details';
1295  const content = `
1296    <h5>Rates per group:</h5>
1297    <ul>
1298      <li>1 - 2 people: $130</li>
1299      <li>3 people: $150</li>
1300      <li>4 people: $220</li>
1301      <li>5 people: $250</li>
1302      <li>6 people: $300</li>
1303    </ul>
1304    <hr>
1305    <h5 class="mb-3">Book Your Tour</h5>
1306    <form id="quito-half-day-form">
1307      <input type="hidden" name="_subject" value="New Quito Half Day Tour Reservation">
1308      <input type="hidden" name="_cc" value="[email protected]">
1309      <div class="row">
1310        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Full Name</label><input type="text" name="Full Name" class="form-control" required></div>
1311        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Phone or Email</label><input type="text" name="Contact" class="form-control" required></div>
1312      </div>
1313      <div class="row">
1314        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Desired Tour Date</label><input type="date" name="Date" class="form-control" required></div>
1315        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Number of People</label><input type="number" name="Number of People" class="form-control" min="1" required></div>
1316      </div>
1317      <div class="mb-3">
1318        <label class="form-label fw-bold">Choose one option:</label>
1319        <select class="form-select" name="Tour Option" required>
1320          <option value="Option 1: Equator Line (Intiñan Museum) + Photos with llamas + Empanadas & ice cream.">Option 1: Equator Line (Intiñan Museum) + Photos with llamas + Empanadas & ice cream.</option>
1321          <option value="Option 2: Quito's Historic Center + Panecillo Viewpoint.">Option 2: Quito's Historic Center + Panecillo Viewpoint.</option>
1322          <option value="Option 3: Quito's Historic Center + Chocolate Tour.">Option 3: Quito's Historic Center + Chocolate Tour.</option>
1323          <option value="Option 4: Vegetable Market + Shamanic Cleansing + Gastronomic Tour.">Option 4: Vegetable Market + Shamanic Cleansing + Gastronomic Tour.</option>
1324          <option value="Option 5: Full Gastronomic Tour (breakfast, brunch, lunch, and dinner).">Option 5: Full Gastronomic Tour (breakfast, brunch, lunch, and dinner).</option>
1325          <option value="Option 6: Exclusive Galleries (Olga Fisch, Alpaca Collection) or Artisan Market.">Option 6: Exclusive Galleries (Olga Fisch, Alpaca Collection) or Artisan Market.</option>
1326          <option value="Option 7: Guayasamín Museum, National Museum, or Botanical Garden.">Option 7: Guayasamín Museum, National Museum, or Botanical Garden.</option>
1327          <option value="Option 8: Cable Car + Swing + Gastronomic Tour (Monday to Friday; weekends require 1-hour wait).">Option 8: Cable Car + Swing + Gastronomic Tour (Monday to Friday; weekends require 1-hour wait).</option>
1328          <option value="Option 9: Archaeological Site (Quitu-Cara Rumipamba Museum or Rumicucho Ruins).">Option 9: Archaeological Site (Quitu-Cara Rumipamba Museum or Rumicucho Ruins).</option>
1329          <option value="Option 10: Craft Beer Tour (visit to local microbreweries).">Option 10: Craft Beer Tour (visit to local microbreweries).</option>
1330        </select>
1331      </div>
1332      <div class="d-flex justify-content-between align-items-center">
1333        <button type="submit" class="btn btn-primary">Send Request</button>
1334        <a href="https://wa.me/593992010909?text=Hola, me gustaría reservar el Quito Half Day Tour" target="_blank" class="modal-whatsapp-btn"><i class="fab fa-whatsapp"></i></a>
1335      </div>
1336    </form>
1337  `;
1338  const modal = createModal(title, content);
1339  document.body.appendChild(modal);
1340  modal.querySelector('input[type="date"]').value = new Date().toISOString().split('T')[0];
1341  modal.querySelector('#quito-half-day-form').addEventListener('submit', e => {
1342    e.preventDefault();
1343    handleFormSubmit(e.target, modal);
1344  });
1345}
1346
1347function showQuitoFullDayModal() {
1348  const title = 'Quito Full Day Tour Details';
1349  const content = `
1350    <h5>Rates per group:</h5>
1351    <ul>
1352      <li>1 - 2 people: $210</li>
1353      <li>3 people: $250</li>
1354      <li>4 people: $300</li>
1355      <li>5 people: $350</li>
1356      <li>6 people: $400</li>
1357    </ul>
1358    <hr>
1359    <h5 class="mb-3">Book Your Tour</h5>
1360    <form id="quito-full-day-form">
1361      <input type="hidden" name="_subject" value="New Quito Full Day Tour Reservation">
1362      <input type="hidden" name="_cc" value="[email protected]">
1363      <div class="row">
1364        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Full Name</label><input type="text" name="Full Name" class="form-control" required></div>
1365        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Phone or Email</label><input type="text" name="Contact" class="form-control" required></div>
1366      </div>
1367      <div class="row">
1368        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Desired Tour Date</label><input type="date" name="Date" class="form-control" required></div>
1369        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Number of People</label><input type="number" name="Number of People" class="form-control" min="1" required></div>
1370      </div>
1371      <div class="mb-3">
1372        <label class="form-label fw-bold">Choose 4 options:</label>
1373        <div class="form-check"><input class="form-check-input" type="checkbox" name="Tour Options[]" value="Dome Tour (2 hours)."><label class="form-check-label">Dome Tour (2 hours).</label></div>
1374        <div class="form-check"><input class="form-check-input" type="checkbox" name="Tour Options[]" value="Quito's Historic Center (3 hours)."><label class="form-check-label">Quito's Historic Center (3 hours).</label></div>
1375        <div class="form-check"><input class="form-check-input" type="checkbox" name="Tour Options[]" value="Panecillo Viewpoint (1 hour)."><label class="form-check-label">
1375Panecillo Viewpoint (1 hour).</label></div>
1376        <div class="form-check"><input class="form-check-input" type="checkbox" name="Tour Options[]" value="Cable Car + Swing (2h30 min)."><label class="form-check-label">Cable Car + Swing (2h30 min).</label></div>
1377        <div class="form-check"><input class="form-check-input" type="checkbox" name="Tour Options[]" value="Shamanic Cleansing (5 min per person)."><label class="form-check-label">Shamanic Cleansing (5 min per person).</label></div>
1378        <div class="form-check"><input class="form-check-input" type="checkbox" name="Tour Options[]" value="Vegetable Market (1 hour)."><label class="form-check-label">Vegetable Market (1 hour).</label></div>
1379        <div class="form-check"><input class="form-check-input" type="checkbox" name="Tour Options[]" value="Quito Gastronomic Tour (1 - 3 hours)."><label class="form-check-label">Quito Gastronomic Tour (1 - 3 hours).</label></div>
1380        <div class="form-check"><input class="form-check-input" type="checkbox" name="Tour Options[]" value="Street Food Tour (1 - 2 hours)."><label class="form-check-label">Street Food Tour (1 - 2 hours).</label></div>
1381        <div class="form-check"><input class="form-check-input" type="checkbox" name="Tour Options[]" value="Intiñan Museum + Photos with llamas."><label class="form-check-label">Intiñan Museum + Photos with llamas.</label></div>
1382        <div class="form-check"><input class="form-check-input" type="checkbox" name="Tour Options[]" value="Pululahua Crater (1 hour)."><label class="form-check-label">Pululahua Crater (1 hour).</label></div>
1383        <div class="form-check"><input class="form-check-input" type="checkbox" name="Tour Options[]" value="Guayasamín Museum (3 hours)."><label class="form-check-label">Guayasamín Museum (3 hours).</label></div>
1384        <div class="form-check"><input class="form-check-input" type="checkbox" name="Tour Options[]" value="Artisan Market (1 - 2 hours)."><label class="form-check-label">Artisan Market (1 - 2 hours).</label></div>
1385        <div class="form-check"><input class="form-check-input" type="checkbox" name="Tour Options[]" value="Chocolate Tour (Pacari) (1 - 2 hours)."><label class="form-check-label">Chocolate Tour (Pacari) (1 - 2 hours).</label></div>
1386      </div>
1387      <div class="d-flex justify-content-between align-items-center">
1388        <button type="submit" class="btn btn-primary">Send Request</button>
1389        <a href="https://wa.me/593992010909?text=Hola, me gustaría reservar el Quito Full Day Tour" target="_blank" class="modal-whatsapp-btn"><i class="fab fa-whatsapp"></i></a>
1390      </div>
1391    </form>
1392  `;
1393  const modal = createModal(title, content);
1394  document.body.appendChild(modal);
1395  modal.querySelector('input[type="date"]').value = new Date().toISOString().split('T')[0];
1396  modal.querySelector('#quito-full-day-form').addEventListener('submit', e => {
1397    e.preventDefault();
1398    handleFormSubmit(e.target, modal);
1399  });
1400}
1401
1402function showAntisanaCondorsModal() {
1403  const title = 'Condors in Antisana Tour Details';
1404  const content = `
1405    <h5>Rates per group:</h5>
1406    <ul>
1407      <li>1 - 2 people: $250</li>
1408      <li>3 people: $300</li>
1409      <li>4 people: $350</li>
1410      <li>5 people: $400</li>
1411      <li>6 people: $500</li>
1412    </ul>
1413    <hr>
1414    <h5>Includes:</h5>
1415    <p>Andean wildlife observation: condors, hummingbirds, deer, hawks, eagles, and more.<br>Optional lunch: Fresh trout from the natural lake.</p>
1416    <hr>
1417    <h5 class="mb-3">Book Your Tour</h5>
1418    <form id="antisana-condors-form">
1419      <input type="hidden" name="_subject" value="New Condors in Antisana Tour Reservation">
1420      <input type="hidden" name="_cc" value="[email protected]">
1421      <div class="row">
1422        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Full Name</label><input type="text" name="Full Name" class="form-control" required></div>
1423        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Phone or Email</label><input type="text" name="Contact" class="form-control" required></div>
1424      </div>
1425      <div class="row">
1426        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Desired Tour Date</label><input type="date" name="Date" class="form-control" required></div>
1427        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Number of People</label><input type="number" name="Number of People" class="form-control" min="1" required></div>
1428      </div>
1429      <div class="mb-3">
1430        <label class="form-label fw-bold">Optional Additional Activities:</label>
1431        <div class="form-check">
1432          <input class="form-check-input" type="checkbox" name="Additional Activities[]" value="Mountain Biking (+$35 pp)">
1433          <label class="form-check-label">Mountain Biking (+$35 pp)</label>
1434        </div>
1435        <div class="form-check">
1436          <input class="form-check-input" type="checkbox" name="Additional Activities[]" value="Horseback Riding (+$35 pp)">
1437          <label class="form-check-label">Horseback Riding (+$35 pp)</label>
1438        </div>
1439      </div>
1440      <div class="d-flex justify-content-between align-items-center">
1441        <button type="submit" class="btn btn-primary">Send Request</button>
1442        <a href="https://wa.me/593992010909?text=Hola, me gustaría reservar el Condors in Antisana Tour" target="_blank" class="modal-whatsapp-btn"><i class="fab fa-whatsapp"></i></a>
1443      </div>
1444    </form>
1445  `;
1446  const modal = createModal(title, content);
1447  document.body.appendChild(modal);
1448  modal.querySelector('input[type="date"]').value = new Date().toISOString().split('T')[0];
1449  modal.querySelector('#antisana-condors-form').addEventListener('submit', e => {
1450    e.preventDefault();
1451    handleFormSubmit(e.target, modal);
1452  });
1453}
1454
1455function showCotopaxiVolcanoModal() {
1456  const title = 'Cotopaxi Volcano Tour Details';
1457  const content = `
1458    <h5>Rates per group:</h5>
1459    <ul>
1460      <li>1 - 2 people: $270</li>
1461      <li>3 people: $350</li>
1462      <li>4 people: $400</li>
1463      <li>5 people: $500</li>
1464      <li>6 people: $600</li>
1465    </ul>
1466    <hr>
1467    <h5>Experience options:</h5>
1468    <ul>
1469      <li>
1469Cotopaxi National Park.</li>
1470      <li>Inca Hacienda (llama feeding and photos).</li>
1471      <li>Hot tea in a cozy fireplace lounge.</li>
1472      <li>Lunch at the hacienda (reservation required, $35 - $50 per person).</li>
1473    </ul>
1474    <hr>
1475    <h5 class="mb-3">Book Your Tour</h5>
1476    <form id="cotopaxi-volcano-form">
1477      <input type="hidden" name="_subject" value="New Cotopaxi Volcano Tour Reservation">
1478      <input type="hidden" name="_cc" value="[email protected]">
1479      <div class="row">
1480        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Full Name</label><input type="text" name="Full Name" class="form-control" required></div>
1481        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Phone or Email</label><input type="text" name="Contact" class="form-control" required></div>
1482      </div>
1483      <div class="row">
1484        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Desired Tour Date</label><input type="date" name="Date" class="form-control" required></div>
1485        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Number of People</label><input type="number" name="Number of People" class="form-control" min="1" required></div>
1486      </div>
1487      <div class="d-flex justify-content-between align-items-center">
1488        <button type="submit" class="btn btn-primary">Send Request</button>
1489        <a href="https://wa.me/593992010909?text=Hola, me gustaría reservar el Cotopaxi Volcano Tour" target="_blank" class="modal-whatsapp-btn"><i class="fab fa-whatsapp"></i></a>
1490      </div>
1491    </form>
1492  `;
1493  const modal = createModal(title, content);
1494  document.body.appendChild(modal);
1495  modal.querySelector('input[type="date"]').value = new Date().toISOString().split('T')[0];
1496  modal.querySelector('#cotopaxi-volcano-form').addEventListener('submit', e => {
1497    e.preventDefault();
1498    handleFormSubmit(e.target, modal);
1499  });
1500}
1501
1502function showSurroundingsOfQuitoModal() {
1503  const title = 'Outside of Quito (Full Day) Tour Details';
1504  const content = `
1505    <h5>Rates per group:</h5>
1506    <ul>
1507      <li>1 - 2 people: $250</li>
1508      <li>3 people: $300</li>
1509      <li>4 people: $350</li>
1510      <li>5 people: $400</li>
1511      <li>6 people: $500</li>
1512    </ul>
1513    <hr>
1514    <h5 class="mb-3">Book Your Tour</h5>
1515    <form id="surroundings-of-quito-form">
1516      <input type="hidden" name="_subject" value="New Outside of Quito (Full Day) Tour Reservation">
1517      <input type="hidden" name="_cc" value="[email protected]">
1518      <div class="row">
1519        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Full Name</label><input type="text" name="Full Name" class="form-control" required></div>
1520        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Phone or Email</label><input type="text" name="Contact" class="form-control" required></div>
1521      </div>
1522      <div class="row">
1523        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Desired Tour Date</label><input type="date" name="Date" class="form-control" required></div>
1524        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Number of People</label><input type="number" name="Number of People" class="form-control" min="1" required></div>
1525      </div>
1526      <div class="mb-3">
1527        <label class="form-label fw-bold">Available Destinations:</label>
1528        <div class="form-check">
1529          <input class="form-check-input" type="checkbox" name="Destinations[]" value="Papallacta.">
1530          <label class="form-check-label">Papallacta.</label>
1531        </div>
1532        <div class="form-check">
1533          <input class="form-check-input" type="checkbox" name="Destinations[]" value="Otavalo Indigenous Market.">
1534          <label class="form-check-label">Otavalo Indigenous Market.</label>
1535        </div>
1536        <div class="form-check">
1537          <input class="form-check-input" type="checkbox" name="Destinations[]" value="Mindo Cloud Forest.">
1538          <label class="form-check-label">Mindo Cloud Forest.</label>
1539        </div>
1540        <div class="form-check">
1541          <input class="form-check-input" type="checkbox" name="Destinations[]" value="Horseback Riding Day (+$50 per horse).">
1542          <label class="form-check-label">Horseback Riding Day (+$50 per horse).</label>
1543        </div>
1544        <div class="form-check">
1545          <input class="form-check-input" type="checkbox" name="Destinations[]" value="Mountain Biking (+$35 per bike and equipment).">
1546          <label class="form-check-label">Mountain Biking (+$35 per bike and equipment).</label>
1547        </div>
1548        <div class="form-check">
1549          <input class="form-check-input" type="checkbox" name="Destinations[]" value="Cochasquí Pyramids + Photos with llamas.">
1550          <label class="form-check-label">Cochasquí Pyramids + Photos with llamas.</label>
1551        </div>
1552        <div class="form-check">
1553          <input class="form-check-input" type="checkbox" name="Destinations[]" value="Rose Farm + Hacienda La Ciénega.">
1554          <label class="form-check-label">Rose Farm + Hacienda La Ciénega.</label>
1555        </div>
1556      </div>
1557      <div class="d-flex justify-content-between align-items-center">
1558        <button type="submit" class="btn btn-primary">Send Request</button>
1559        <a href="https://wa.me/593992010909?text=Hola, me gustaría reservar el Outside of Quito (Full Day) Tour" target="_blank" class="modal-whatsapp-btn"><i class="fab fa-whatsapp"></i></a>
1560      </div>
1561    </form>
1562  `;
1563  const modal = createModal(title, content);
1564  document.body.appendChild(modal);
1565  modal.querySelector('input[type="date"]').value = new Date().toISOString().split('T')[0];
1566  modal.querySelector('#surroundings-of-quito-form').addEventListener('submit', e => {
1567    e.preventDefault();
1568    handleFormSubmit(e.target, modal);
1569  });
1570}
1571
1572function showOtavaloMarketModal() {
1573  const title = 'Otavalo Market Tour Details';
1574  const content = `
1575    <p>Explore the Ecuadorian Andes with visits to emblematic sites and unique cultural experiences.</p>
1576    <hr>
1577    <h5 class="mb-3">Book Your Tour</h5>
1578    <form id="otavalo-market-form">
1579      <input type="hidden" name="_subject" value="New Otavalo Market Tour Reservation">
1580      <input type="hidden" name="_cc" value="[email protected]">
1581      <div class="row">
1582        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Full Name</label><input type="text" name="Full Name" class="form-control" required></div>
1583        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Phone or Email</label><input type="text" name="Contact" class="form-control" required></div>
1584      </div>
1585      <div class="row">
1586        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Desired Tour Date</label><input type="date" name="Date" class="form-control" required></div>
1587        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Number of People</label><input type="number" id="otavalo-people" name="Number of People" class="form-control" min="1" required></div>
1588      </div>
1589      <div class="mb-3">
1590        <label class="form-label fw-bold">Choose one food option (mandatory):</label>
1591        <div class="form-check">
1592          <input class="form-check-input food-option" type="radio" name="Food Option" value="Lunch at Hacienda Pinsaquí ($25 - $35 per person)" data-cost-min="25" data-cost-max="35" required>
1593          <label class="form-check-label">Lunch at Hacienda Pinsaquí ($25 - $35 per person)</label>
1594        </div>
1595        <div class="form-check">
1596          <input class="form-check-input food-option" type="radio" name="Food Option" value="Traditional food (roasted guinea pig, $22)" data-cost-min="22" data-cost-max="22">
1597          <label class="form-check-label">Traditional food (roasted guinea pig, $22)</label>
1598        </div>
1599        <div class="form-check">
1600          <input class="form-check-input food-option" type="radio" name="Food Option" value="Lunch at an Otavalo family home ($25 per person)" data-cost-min="25" data-cost-max="25">
1601          <label class="form-check-label">Lunch at an Otavalo family home ($25 per person)</label>
1602        </div>
1603      </div>
1604      <div class="mb-3">
1605        <label class="form-label fw-bold">Choose two additional options (mandatory, no extra cost):</label>
1606        <div class="form-check"><input class="form-check-input additional-option" type="checkbox" name="Additional Options[]" value="Quitsato (Middle of the World in Cayambe)."><label class="form-check-label">Quitsato (Middle of the World in Cayambe).</label></div>
1607        <div class="form-check"><input class="form-check-input additional-option" type="checkbox" name="Additional Options[]" value="Cochasquí Pyramids."><label class="form-check-label">Cochasquí Pyramids.</label></div>
1608        <div class="form-check"><input class="form-check-input additional-option" type="checkbox" name="Additional Options[]" value="Otavalo artisan market."><label class="form-check-label">Otavalo artisan market.</label></div>
1609        <div class="form-check"><input class="form-check-input additional-option" type="checkbox" name="Additional Options[]" value="Alpaca weaving workshops."><label class="form-check-label">Alpaca weaving workshops.</label></div>
1610        <div class="form-check"><input class="form-check-input additional-option" type="checkbox" name="Additional Options[]" value="Live Andean musicians."><label class="form-check-label">Live Andean musicians.</label></div>
1611        <div class="form-check"><input class="form-check-input additional-option" type="checkbox" name="Additional Options[]" value="Cotacachi (leather city)."><label class="form-check-label">Cotacachi (leather city).</label></div>
1612        <div class="form-check"><input class="form-check-input additional-option" type="checkbox" name="Additional Options[]" value="Peguche (waterfall and sacred tree viewpoint)."><label class="form-check-label">Peguche (waterfall and sacred tree viewpoint).</label></div>
1613        <div class="form-check"><input class="form-check-input additional-option" type="checkbox" name="Additional Options[]" value="Condor Park (raptor rescue)."><label class="form-check-label">Condor Park (raptor rescue).</label></div>
1614      </div>
1615      <div class="mb-3">
1616        <label class="form-label fw-bold">Optional paid activities:</label>
1617        <div class="form-check">
1618          <input class="form-check-input paid-option" type="checkbox" name="Paid Activities[]" value="Cuicocha Lagoon (optional walk, $15)" data-cost="15">
1619          <label class="form-check-label">Cuicocha Lagoon (optional walk, $15)</label>
1620        </div>
1621        <div class="form-check">
1622          <input class="form-check-input paid-option" type="checkbox" name="Paid Activities[]" value="Cockfights (Saturdays from 2 pm, $5)" data-cost="5">
1623          <label class="form-check-label">Cockfights (Saturdays from 2 pm, $5)</label>
1624        </div>
1625        <div class="form-check">
1626          <input class="form-check-input paid-option" type="checkbox" name="Paid Activities[]" value="Horseback riding at hacienda ($35 per person)" data-cost="35">
1627          <label class="form-check-label">Horseback riding at hacienda ($35 per person)</label>
1628        </div>
1629      </div>
1630      <hr>
1631      <h5 class="mb-3">Total Estimated Cost: $<span id="otavalo-total-cost">0</span></h5>
1632      <div class="d-flex justify-content-between align-items-center">
1633        <button type="submit" class="btn btn-primary">Send Request</button>
1634        <a href="https://wa.me/593992010909?text=Hola, me gustaría reservar el Otavalo Market Tour" target="_blank" class="modal-whatsapp-btn"><i class="fab fa-whatsapp"></i></a>
1635      </div>
1636    </form>
1637  `;
1638  const modal = createModal(title, content);
1639  document.body.appendChild(modal);
1640  modal.querySelector('input[type="date"]').value = new Date().toISOString().split('T')[0];
1641  
1642  const form = modal.querySelector('#otavalo-market-form');
1643  const totalCostEl = modal.querySelector('#otavalo-total-cost');
1644  const peopleInput = modal.querySelector('#otavalo-people');
1645  
1646  function calculateTotal() {
1647    let total = 0;
1648    const numPeople = parseInt(peopleInput.value) || 0;
1649    const foodOption = form.querySelector('.food-option:checked');
1650    if (foodOption) {
1651      const minCost = parseFloat(foodOption.dataset.costMin) || 0;
1652      // For simplicity, we'll use the minimum cost for the range
1653      total += minCost * numPeople;
1654    }
1655    form.querySelectorAll('.paid-option:checked').forEach(option => {
1656      const cost = parseFloat(option.dataset.cost) || 0;
1657      if (option.value.includes('per person')) {
1658        total += cost * numPeople;
1659      } else {
1660        total += cost;
1661      }
1662    });
1663    totalCostEl.textContent = total.toFixed(2);
1664  }
1665  
1666  form.addEventListener('change', calculateTotal);
1667  peopleInput.addEventListener('input', calculateTotal);
1668  
1669  form.addEventListener('submit', e => {
1670    const additionalOptions = form.querySelectorAll('.additional-option:checked');
1671    if (additionalOptions.length !== 2) {
1672      e.preventDefault();
1673      alert('Please choose exactly two additional options.');
1674      return;
1675    }
1676    e.preventDefault();
1677    handleFormSubmit(e.target, modal);
1678  });
1679}
1680
1681function showHorseRiderModal() {
1682  const title = 'Horse Rider Experience Details';
1683  const content = `
1684    <h5>Rates per group:</h5>
1685    <ul>
1686      <li>1 - 2 people: $280</li>
1687      <li>3 people: $350</li>
1688      <li>4 people: $450</li>
1689      <li>5 people: $550</li>
1690      <li>6 people: $650</li>
1691    </ul>
1692    <hr>
1693    <h5 class="mb-3">Book Your Tour</h5>
1694    <form id="horse-rider-form">
1695      <input type="hidden" name="_subject" value="New Horse Rider Experience Reservation">
1696      <div class="row">
1697        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Full Name</label><input type="text" name="Full Name" class="form-control" required></div>
1698        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Phone or Email</label><input type="text" name="Contact" class="form-control" required></div>
1699      </div>
1700      <div class="row">
1701        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Desired Tour Date</label><input type="date" name="Date" class="form-control" required></div>
1702        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Number of People</label><input type="number" id="horse-rider-people" name="Number of People" class="form-control" min="1" required></div>
1703      </div>
1704      <div class="mb-3">
1705        <label class="form-label fw-bold">Choose 2 activities (mandatory):</label>
1706        <div class="form-check">
1707          <input class="form-check-input activity-option" type="checkbox" name="Activities[]" value="Rafting ($40, 3 hours)" data-cost="40">
1708          <label class="form-check-label">Rafting ($40, 3 hours)</label>
1709        </div>
1710        <div class="form-check">
1711          <input class="form-check-input activity-option" type="checkbox" name="Activities[]" value="Rappel ($40, 3 hours)" data-cost="40">
1712          <label class="form-check-label">Rappel ($40, 3 hours)</label>
1713        </div>
1714        <div class="form-check">
1715          <input class="form-check-input activity-option" type="checkbox" name="Activities[]" value="Casa del Árbol y columpio ($2)" data-cost="2">
1716          <label class="form-check-label">Casa del Árbol y columpio ($2)</label>
1717        </div>
1718        <div class="form-check">
1719          <input class="form-check-input activity-option" type="checkbox" name="Activities[]" value="Caminata (2 hours)" data-cost="0">
1720          <label class="form-check-label">Caminata (2 hours)</label>
1721        </div>
1722        <div class="form-check">
1723          <input class="form-check-input activity-option" type="checkbox" name="Activities[]" value="Ruta de las cascadas + Pailón del Diablo ($5)" data-cost="5">
1724          <label class="form-check-label">Ruta de las cascadas + Pailón del Diablo ($5)</label>
1725        </div>
1726        <div class="form-check">
1727          <input class="form-check-input activity-option" type="checkbox" name="Activities[]" value="Taller de tejidos nativos (1 hour)" data-cost="0">
1728          <label class="form-check-label">Taller de tejidos nativos (1 hour)</label>
1729        </div>
1730      </div>
1731      <hr>
1732      <h5 class="mb-3">Total Activities Cost: $<span id="horse-rider-total-cost">0</span></h5>
1733      <div class="d-flex justify-content-between align-items-center">
1734        <button type="submit" class="btn btn-primary">Send Re
1734quest</button>
1735        <a href="https://wa.me/593992010909?text=Hola, me gustaría reservar el Horse Rider Experience" target="_blank" class="modal-whatsapp-btn"><i class="fab fa-whatsapp"></i></a>
1736      </div>
1737    </form>
1738  `;
1739  const modal = createModal(title, content);
1740  document.body.appendChild(modal);
1741  modal.querySelector('input[type="date"]').value = new Date().toISOString().split('T')[0];
1742  
1743  const form = modal.querySelector('#horse-rider-form');
1744  const totalCostEl = modal.querySelector('#horse-rider-total-cost');
1745  
1746  function calculateTotal() {
1747    let total = 0;
1748    form.querySelectorAll('.activity-option:checked').forEach(option => {
1749      total += parseFloat(option.dataset.cost) || 0;
1750    });
1751    totalCostEl.textContent = total.toFixed(2);
1752  }
1753  
1754  form.addEventListener('change', calculateTotal);
1755  form.addEventListener('submit', e => {
1756    const activityOptions = form.querySelectorAll('.activity-option:checked');
1757    if (activityOptions.length !== 2) {
1758      e.preventDefault();
1759      alert('Please choose exactly two activities.');
1760      return;
1761    }
1762    e.preventDefault();
1763    handleFormSubmit(e.target, modal);
1764  });
1765}
1766
1767function showSummitsOfTheSunModal() {
1768  const title = 'Summits of the Sun – Ecuador 10 Days';
1769  const content = `
1770    <p>This 10-day expedition in Ecuador is a meticulously planned journey that blends high-altitude mountaineering with luxurious stays in exclusive boutique hotels and historic haciendas. The itinerary is strategically designed for optimal acclimatization, allowing adventurers to safely tackle some of the Andes' most iconic peaks.</p>
1771    <p>The tour begins in Quito (2,850 m), where guests settle into the elegant Cultura Manor Boutique Hotel. The first two days are dedicated to acclimatization and cultural immersion. This includes exploring Quito's UNESCO World Heritage historic center, with visits to landmarks like the Compañía de Jesús Church and San Francisco Square, as well as a trip to the Middle of the World Monument to stand on the equatorial line.</p>
1772    <p>The physical challenge begins on Day 3 with an ascent of Rucu Pichincha (4,696 m), the volcano that overlooks Quito, offering breathtaking views and serving as a crucial acclimatization climb. This is followed on Day 4 by a more demanding trek in the Antisana Ecological Reserve, with the goal of hiking on the glaciers or summiting Antisana (5,704 m), depending on conditions.</p>
1773    <p>Next, the journey moves north. Guests will visit the vibrant indigenous handicraft market in Otavalo and take a scenic walk around the stunning turquoise crater lake, Cuicocha Lagoon. The accommodation for this leg is the historic Hacienda Pinsaquí, an 18th-century colonial estate. From here, the team undertakes a midnight ascent of Cayambe (5,790 m), the only major volcano located directly on the equator, renowned for its spectacular glaciers.</p>
1774    <p>The expedition then travels south towards the "Avenue of the Volcanoes." After an acclimatization walk at Limpiopungo Lagoon at the foot of Cotopaxi, guests will check into Hacienda La Ciénega, one of Ecuador's oldest and most storied estates. The pinnacle of the trip is the pre-dawn climb of the legendary Cotopaxi (5,897 m), aiming to reach its perfectly symmetrical, snow-capped summit at sunrise for a once-in-a-lifetime experience.</p>
1775    <p>The final leg of the tour takes travelers to Riobamba, "the city of mountains." Here, they will visit the Chimborazo Wildlife Reserve, home to wild vicuñas, llamas, and alpacas, all while admiring the immense peak of Chimborazo. The journey concludes with a restful evening at Hacienda Abraspungo, blending traditional Andean architecture with modern comfort, before departure.</p>
1776    <hr>
1777    <h5 class="mb-3">Book Your Expedition</h5>
1778    <form id="summits-sun-form">
1779      <input type="hidden" name="_subject" value="New Summits of the Sun Expedition Reservation">
1780      <input type="hidden" name="_cc" value="[email protected]">
1781      <div class="row">
1782        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Full Name</label><input type="text" name="Full Name" class="form-control" required></div>
1783        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Phone or Email</label><input type="text" name="Contact" class="form-control" required></div>
1784      </div>
1785      <div class="row">
1786        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Desired Start Date</label><input type="date" name="Date" class="form-control" required></div>
1787        <div class="col-md-6 mb-3"><label class="form-label fw-bold">Number of People</label><input type="number" name="Number of People" class="form-control" min="1" required></div>
1788      </div>
1789      <div class="mb-3">
1790        <label class="form-label fw-bold">Experience Level</label>
1791        <select class="form-select" name="Experience Level" required>
1792          <option value="Beginner">Beginner</option>
1793          <option value="Intermediate">Intermediate</option>
1794          <option value="Advanced">Advanced</option>
1795          <option value="Expert">Expert</option>
1796        </select>
1797      </div>
1798      <div class="d-flex justify-content-between align-items-center">
1799        <button type="submit" class="btn btn-primary">Send Request</button>
1800        <a href="https://wa.me/593992010909?text=Hola, me gustaría reservar el Summits of the Sun – Ecuador 10 Days" target="_blank" class="modal-whatsapp-btn"><i class="fab fa-whatsapp"></i></a>
1801      </div>
1802    </form>
1803    <hr>
1804    <div class="text-center my-4">
1805      <a href="SUMMITS ECUADOR.pdf" target="_blank" class="btn btn-primary me-2"><i class="fas fa-download"></i> Detailed Itinerary</a>
1806    </div>
1807  `;
1808  const modal = createModal(title, content);
1809  document.body.appendChild(modal);
1810  modal.querySelector('input[type="date"]').value = new Date().toISOString().split('T')[0];
1811  modal.querySelector('#summits-sun-form').addEventListener('submit', e => {
1812    e.preventDefault();
1813    handleFormSubmit(e.target, modal);
1814  });
1815}
1816
1817function showSiteServicesModal(siteName) {
1818  const site = sitesData[siteName];
1819  if (!site) return;
1820  
1821  let serviceButtonsHTML = '';
1822  site.services.options.forEach((service, index) => {
1823    const uniqueId = `${siteName.replace(/\s+/g, '-')}-service-${index}`;
1824    if (service.url) {
1825      serviceButtonsHTML += `
1826        <a href="${service.url}" target="_blank" class="list-group-item list-group-item-action service-url-link" data-service="${service.name}" data-url="${service.url}">
1827          <i class="fab ${service.icon}"></i> ${service.name}
1828        </a>`;
1829    } else {
1830      serviceButtonsHTML += `
1831        <button type="button" id="${uniqueId}" class="list-group-item list-group-item-action">
1832          <i class="fas ${service.icon}"></i> ${service.name}
1833        </button>`;
1834    }
1835  });
1836  
1837  const content = `
1838    ${site.services.website ? `<a href="${site.services.website}" target="_blank" class="services-website-link"><i class="fas fa-globe"></i> Visit our Services Page</a>` : ''}
1839    <div class="list-group service-modal-body">
1840      ${serviceButtonsHTML}
1841    </div>
1842  `;
1843  
1844  const modal = createModal(`${siteName} Services`, content, 'service-modal');
1845  document.body.appendChild(modal);
1846  
1847  // Add email notification for URL links
1848  modal.querySelectorAll('.service-url-link').forEach(link => {
1849    link.addEventListener('click', () => {
1850      const serviceName = link.dataset.service;
1851      const serviceUrl = link.dataset.url;
1852      // Get IP, city and country
1853      fetch('https://ipapi.co/json/')
1854      .then(res => res.json())
1855      .then(data => {
1856        const ip = data.ip || 'Unknown';
1857        const city = data.city || 'Unknown';
1858        const country = data.country_name || 'Unknown';
1859        sendEmailNotification(`Service Click: ${siteName} - ${serviceName}`, {
1860          'Site': siteName,
1861          'Service': serviceName,
1862          'URL': serviceUrl,
1863          'Fecha y hora': new Date().toLocaleString(),
1864          'IP': ip,
1865          'Ciudad': city,
1866          'País': country
1867        });
1868      })
1869      .catch(err => {
1870        console.error('Error getting IP info:', err);
1871        // Send email without IP info if fetch fails
1872        sendEmailNotification(`Service Click: ${siteName} - ${serviceName}`, {
1873          'Site': siteName,
1874          'Service': serviceName,
1875          'URL': serviceUrl,
1876          'Fecha y hora': new Date().toLocaleString(),
1877          'IP': 'Unknown',
1878          'Ciudad': 'Unknown',
1879          'País': 'Unknown'
1880        });
1881      });
1882    });
1883  });
1884  
1885  site.services.options.forEach((service, index) => {
1886    if (service.action) {
1887      const uniqueId = `${siteName.replace(/\s+/g, '-')}-service-${index}`;
1888      modal.querySelector(`#${uniqueId}`).addEventListener('click', () => {
1889        modal.remove();
1890        service.action();
1891      });
1892    }
1893  });
1894}
1895
1896// --- DYNAMIC CONTENT LOADERS ---
1897function cargarServicios() {
1898  const container = document.getElementById('service-categories-container');
1899  if (!container) return;
1900  container.innerHTML = '';
1901  
1902  Object.keys(sitesData).forEach(siteName => {
1903    const site = sitesData[siteName];
1904    const card = document.createElement('div');
1905    card.className = 'col-md-6 col-lg-4 mb-4';
1906    let style = `background-image: url('${site.image}');`;
1907    if (siteName === 'Hacienda La Alegría') {
1908      style += ' background-position: top;';
1909    } else if (siteName === 'Maquipucuna Reserve') {
1910      style += ' background-position: center 30%;';
1911    }
1912    card.innerHTML = `
1913      <div class="site-service-card" style="${style}">
1914        <h4>${siteName}</h4>
1915      </div>
1916    `;
1917    card.querySelector('.site-service-card').addEventListener('click', () => showSiteServicesModal(siteName));
1918    container.appendChild(card);
1919  });
1920}
1921
1922function cargarJourneys() {
1923  const container = document.getElementById('journey-options');
1924  if (!container) return;
1925  container.innerHTML = '';
1926  
1927  tourData[currentLang].forEach(tour => {
1928    const item = document.createElement('div');
1929    item.className = 'tour-item';
1930    item.style.backgroundImage = `url('${tour.imagen}')`;
1931    item.innerHTML = `<div class="tour-item-overlay"></div><div class="tour-item-title">${tour.nombre}</div>`;
1932    if (tour.action) {
1933      item.addEventListener('click', tour.action);
1934      container.appendChild(item);
1935    } else {
1936      const link = document.createElement('a');
1937      link.href = `https://api.whatsapp.com/send?phone=593994959503&text=Book ${tour.nombre}`;
1938      link.target = '_blank';
1939      link.appendChild(item);
1940      container.appendChild(link);
1941    }
1942  });
1943}
1944
1945function cargarEmergencias() {
1946  const list = document.getElementById('emergency-contacts');
1947  if (!list) return;
1948  list.innerHTML = '';
1949  
1950  emergencyContacts[currentLang].forEach(c => {
1951    const item = document.createElement('li');
1952    item.className = 'list-group-item d-flex justify-content-between align-items-center bg-transparent text-white';
1953    item.innerHTML = `<span><strong>${c.nombre}</strong></span><span class="emergency-number">${c.numero}</span>`;
1954    list.appendChild(item);
1955  });
1956}
1957
1958function cargarServiciosTransporte() {
1959  const container = document.getElementById('transport-info');
1960  if (!container) return;
1961  container.innerHTML = '';
1962  
1963  const names = {
1964    en: { flights: 'Flights', taxi: 'Taxi Services', carRental: 'Car Rental' },
1965    es: { flights: 'Vuelos', taxi: 'Servicios de Taxi', carRental: 'Alquiler de Vehículos' }
1966  };
1967  
1968  Object.entries(transportData).forEach(([cat, data]) => {
1969    const categoryDiv = document.createElement('div');
1970    categoryDiv.className = 'transport-category mb-4';
1971    let itemsHTML = '';
1972    
1973    data[currentLang].forEach(srv => {
1974      const nameHTML = srv.sitioWeb ? `<h5><a href="${srv.sitioWeb}" target="_blank" class="transport-name-link">${srv.nombre}</a></h5>` : `<h5>${srv.nombre}</h5>`;
1975      let pbxHTML = srv.pbx ? `<p><i class="fas fa-phone"></i> ${srv.pbx}</p>` : '';
1976      let direccionHTML = srv.direccion ? `<p><i class="fas fa-map-marker-alt"></i> ${srv.direccion}</p>` : '';
1977      let style = '';
1978      if (srv.backgroundImage) {
1979        style = `style="background-image: linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.5)), url('${srv.backgroundImage}'); background-size: cover; background-position: center;"`;
1980      }
1981      itemsHTML += `
1982        <div class="transport-item-new" ${style}>
1983          ${nameHTML}
1984          ${direccionHTML}
1985          ${pbxHTML}
1986        </div>
1987      `;
1988    });
1989    
1990    categoryDiv.innerHTML = `
1991      <h4 class="transport-title">${names[currentLang][cat]}</h4>
1992      <div class="transport-grid">
1993        ${itemsHTML}
1994      </div>
1995    `;
1996    container.appendChild(categoryDiv);
1997  });
1998}
1999
2000function showCityWalkModal() {
2001  const menuItems = cityWalkVideos.map((video, index) =>
2002    `<li class="list-group-item" data-video-id="${video.videoId}">${video.name}</li>`
2003  ).join('');
2004  
2005  const sponsorItems = sponsors.map(sponsor =>
2006    `<a href="${sponsor.url}" target="_blank" class="sponsor-item"><img src="${sponsor.logo}" alt="${sponsor.name}"></a>`
2007  ).join('');
2008  
2009  const modalElement = document.createElement('div');
2010  modalElement.className = 'city-walk-modal';
2011  modalElement.innerHTML = `
2012    <button class="city-walk-close"><i class="fas fa-arrow-left"></i></button>
2013    <div class="city-walk-video-container">
2014      <iframe id="city-walk-iframe" src="https://www.youtube.com/embed/${cityWalkVideos[0].videoId}?autoplay=1&mute=1&controls=1&rel=0" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
2015    </div>
2016    <div class="city-walk-bottom-bar">
2017      <div class="menus-container">
2018        <div class="city-walk-menu">
2019          <ul class="list-group list-group-horizontal">
2020            ${menuItems}
2021          </ul>
2022        </div>
2023        <div class="sponsors-menu">
2024          ${sponsorItems}
2025        </div>
2026      </div>
2027      <div class="bottom-bar-buttons">
2028        <button class="menu-toggle-btn"><i class="fas fa-bars"></i> Destinations</button>
2029        <button class="sponsors-toggle-btn"><i class="fas fa-star"></i> Sponsors</button>
2030        <a href="https://api.whatsapp.com/send?phone=593994959503&text=Hello, I need information about Cultura Manor services" target="_blank" class="contact-toggle-btn"><i class="fab fa-whatsapp"></i> Contact us</a>
2031      </div>
2032    </div>
2033  `;
2034  
2035  document.body.appendChild(modalElement);
2036  document.body.style.overflow = 'hidden';
2037  
2038  const iframe = modalElement.querySelector('#city-walk-iframe');
2039  const menuLinks = modalElement.querySelectorAll('.city-walk-menu .list-group-item');
2040  const cityWalkMenu = modalElement.querySelector('.city-walk-menu');
2041  const sponsorsMenu = modalElement.querySelector('.sponsors-menu');
2042  
2043  if (menuLinks.length > 0) menuLinks[0].classList.add('active');
2044  
2045  menuLinks.forEach(link => {
2046    link.addEventListener('click', function() {
2047      menuLinks.forEach(l => l.classList.remove('active'));
2048      this.classList.add('active');
2049      const videoId = this.getAttribute('data-video-id');
2050      iframe.src = `https://www.youtube.com/embed/${videoId}?autoplay=1&mute=1&controls=1&rel=0`;
2051    });
2052  });
2053  
2054  modalElement.querySelector('.menu-toggle-btn').addEventListener('click', () => {
2055    cityWalkMenu.classList.toggle('open');
2056    sponsorsMenu.classList.remove('open');
2057  });
2058  
2059  modalElement.querySelector('.sponsors-toggle-btn').addEventListener('click', () => {
2060    sponsorsMenu.classList.toggle('open');
2061    cityWalkMenu.classList.remove('open');
2062  });
2063  
2064  modalElement.querySelector('.city-walk-close').addEventListener('click', () => {
2065    modalElement.remove();
2066    document.body.style.overflow = 'auto';
2067  });
2068}
2069
2070// --- DOMContentLoaded EVENT LISTENER ---
2071document.addEventListener('DOMContentLoaded', () => {
2072  // Initialize map
2073  const map = L.map('hotel-map', { minZoom: 6 }).setView([-1.0, -83.5], 6);
2074  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
2075  
2076  const smallIcon = L.icon({
2077    iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png',
2078    iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon-2x.png',
2079    shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png',
2080    iconSize: [15, 25], iconAnchor: [7, 25], popupAnchor: [1, -20]
2081  });
2082  
2083  mapLocations.forEach(location => {
2084    L.marker(location.coords, { icon: smallIcon }).addTo(map)
2085      .bindPopup(`<strong>${location.name}</strong><br><a href="${location.url}" target="_blank">Visitar sitio web</a>`);
2086  });
2087  
2088  // Set initial date
2089  const today = new Date().toISOString().split('T')[0];
2090  const checkDateInput = document.getElementById('check-date');
2091  if (checkDateInput) checkDateInput.value = today;
2092  
2093  document.getElementById('check-inout-form').addEventListener('submit', function(e) {
2094    e.preventDefault();
2095    const form = e.target;
2096    const button = form.querySelector('button[type="submit"]');
2097    button.disabled = true;
2098    button.textContent = 'Sending...';
2099    
2100    const formData = new FormData(form);
2101    // Send to Telegram
2102    const subject = formData.get('_subject') || 'New Booking Request';
2103    let message = `<b>${subject}</b>\n`;
2104    for (let [key, value] of formData.entries()) {
2105      if (!key.startsWith('_') && value) {
2106        message += `<b>${key}:</b> ${value}\n`;
2107      }
2108    }
2109    
2110    const telegramToken = '8641660748:AAEkXojnvRPk7ZXHmXEwEOBYsm2m2x2-7Y0';
2111    const chatId = '1853367208';
2112    fetch(`https://api.telegram.org/bot${telegramToken}/sendMessage`, {
2113      method: 'POST',
2114      headers: { 'Content-Type': 'application/json' },
2115      body: JSON.stringify({
2116        chat_id: chatId,
2117        text: message,
2118        parse_mode: 'HTML'
2119      })
2120    })
2121    .then(res => res.json())
2122    .then(data => {
2123      // Send email notification
2124      const emailData = {};
2125      for (let [key, value] of formData.entries()) {
2126        if (!key.startsWith('_') && value) {
2127          emailData[key] = value;
2128        }
2129      }
2130      emailData['_replyto'] = formData.get('Contact') || '';
2131      sendEmailNotification('New Booking Request', emailData);
2132      
2133      // Open WhatsApp with form data
2134      const fullName = formData.get('Full Name') || '';
2135      const contact = formData.get('Contact') || '';
2136      const date = formData.get('Date') || '';
2137      const adults = formData.get('Number of Adults') || '';
2138      const children = formData.get('Number of Children') || '0';
2139      const experience = formData.get('Selected Experience') || '';
2140      const whatsappMessage = `Hola, me gustaría hacer una reserva:\n` +
2141        `Experiencia: ${experience}\n` +
2142        `Nombre: ${fullName}\n` +
2143        `Contacto: ${contact}\n` +
2144        `Fecha: ${date}\n` +
2145        `Adultos: ${adults}\n` +
2146        `Niños: ${children}\n` +
2147        `Por favor confirmen disponibilidad. Gracias!`;
2148      window.open(`https://wa.me/593992010909?text=${encodeURIComponent(whatsappMessage)}`, '_blank');
2149      
2150      button.disabled = false;
2151      button.textContent = 'Confirm';
2152      form.reset();
2153    })
2154    .catch(err => {
2155      alert('An error occurred while sending your request.');
2156      button.disabled = false;
2157      button.textContent = 'Confirm';
2158    });
2159  });
2160  
2161  // Members Only functionality
2162  document.getElementById('members-only-btn').addEventListener('click', showMemberLogin);
2163  
2164  function showMemberLogin() {
2165    const loginContent = `
2166      <div class="text-center">
2167        <h5><i class="fas fa-lock"></i> Member Authentication</h5>
2168        <p class="mb-4">Please enter your email address to access your member dashboard</p>
2169        <form id="member-login-form">
2170          <div class="mb-3">
2171            <label for="member-email" class="form-label fw-bold">Email Address</label>
2172            <input type="email" class="form-control" id="member-email" placeholder="[email protected]" required>
2173          </div>
2174          <button type="submit" class="btn btn-primary w-100">
2175            <i class="fas fa-sign-in-alt"></i> Access My Account
2176          </button>
2177        </form>
2178      </div>
2179    `;
2180    const modal = createModal('Member Login', loginContent);
2181    document.body.appendChild(modal);
2182    modal.querySelector('#member-login-form').addEventListener('submit', handleMemberLogin);
2183  }
2184  
2185  async function handleMemberLogin(e) {
2186    e.preventDefault();
2187    const email = e.target.querySelector('#member-email').value;
2188    const button = e.target.querySelector('button[type="submit"]');
2189    const originalText = button.innerHTML;
2190    
2191    button.disabled = true;
2192    button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Verifying...';
2193    
2194    try {
2195      // Fetch member data from Google Sheets
2196      const response = await fetch(`https://docs.google.com/spreadsheets/d/e/2PACX-1vQSFgiUWYtndIwhbahcYozYPgGLQDKUyvps0DEsbEjo4kwj3WD7m_rsNrKEn1X6PEc4UnvGI83RhbTW/pubhtml`);
2197      // Since we can't directly fetch from published HTML, we'll use a proxy service
2198      // For now, let's simulate the data structure
2199      const members = await fetchMemberData();
2200      const member = members.find(m => m.email.toLowerCase() === email.toLowerCase());
2201      
2202      if (member) {
2203        showMemberDashboard(member);
2204        e.target.closest('.modal').remove();
2205      } else {
2206        showNotRegisteredError();
2207      }
2208    } catch (error) {
2209      console.error('Error fetching member data:', error);
2210      showNotRegisteredError();
2211    } finally {
2212      button.disabled = false;
2213      button.innerHTML = originalText;
2214    }
2215  }
2216  
2217  async function fetchMemberData() {
2218    try {
2219      // Try published CSV first
2220      const csvUrl = 'https://docs.google.com/spreadsheets/d/e/2PACX-1vQSFgiUWYtndIwhbahcYozYPgGLQDKUyvps0DEsbEjo4kwj3WD7m_rsNrKEn1X6PEc4UnvGI83RhbTW/pub?output=csv';
2221      let response = await fetch(csvUrl);
2222      if (response.ok) {
2223        const csvText = await response.text();
2224        return parseCSVData(csvText);
2225      }
2226      throw new Error('CSV fetch failed');
2227    } catch (error) {
2228      console.error('Error fetching Google Sheet data:', error);
2229      console.log('Using fallback data - Google Sheets not accessible');
2230      // Fallback data that works
2231      return [
2232        {
2233          email: '[email protected]',
2234          name: 'Test Member',
2235          memberNumber: 'EHHEC-TEST-001',
2236          balance: '$1,000.00',
2237          estado: 'Active',
2238          qrCode: 'EHHEC-TEST-001-TESTMEMBER'
2239        },
2240        {
2241          email: '[email protected]',
2242          name: 'Demo User',
2243          memberNumber: 'EHHEC-DEMO-002',
2244          balance: '$2,500.00',
2245          estado: 'Active',
2246          qrCode: 'EHHEC-DEMO-002-DEMOUSER'
2247        }
2248      ];
2249    }
2250  }
2251  
2252  function parseCSVData(csvText) {
2253    const rows = csvText.split('\n').filter(row => row.trim());
2254    const members = [];
2255    console.log('CSV Data received:', csvText.substring(0, 400)); // Debug first 400 chars
2256    
2257    for (let i = 1; i < rows.length; i++) {
2258      const columns = rows[i].split(',').map(col => col.trim().replace(/"/g, ''));
2259      console.log(`Row ${i}:`, columns); // Debug each row
2260      console.log(`Column count: ${columns.length}`);
2261      
2262      // Expected columns: Email, Name, MemberNumber, Balance, Estado
2263      // Try to find Estado column by looking for common status values
2264      let estado = 'Active';
2265      for (let j = 0; j < columns.length; j++) {
2266        const col = columns[j].toLowerCase();
2267        if (col.includes('active') || col.includes('inactive') || col.includes('pending') || col.includes('suspended')) {
2268          estado = columns[j];
2269          console.log(`Found Estado in column ${j}: ${estado}`);
2270          break;
2271        }
2272      }
2273      
2274      if (columns.length >= 4 && columns[0]) {
2275        members.push({
2276          email: columns[0],
2277          name: columns[1] || 'Unknown',
2278          memberNumber: columns[2] || 'N/A',
2279          balance: columns[3] || '$0.00',
2280          estado: estado,
2281          qrCode: `${columns[2] || 'UNKNOWN'}-${columns[1] || 'UNKNOWN'}`.replace(/\s+/g, '').toUpperCase()
2282        });
2283      }
2284    }
2285    console.log('Parsed members:', members); // Debug final result
2286    return members;
2287  }
2288  
2289  function showMemberDashboard(member) {
2290    // Generate timestamp for QR code
2291    const timestamp = new Date().toISOString();
2292    // Create comprehensive QR data with card number
2293    const qrData = JSON.stringify({
2294      name: member.name,
2295      cardNumber: member.memberNumber,
2296      timestamp: timestamp,
2297      type: 'EHHEC_MEMBER'
2298    });
2299    
2300    const dashboardContent = `
2301      <div class="text-center member-dashboard">
2302        <div class="member-header mb-3">
2303          <h4 class="mb-2"><i class="fas fa-user-circle text-primary"></i> Exclusive Member</h4>
2304          <p class="text-muted mb-0">Welcome back, ${member.name}!</p>
2305        </div>
2306        <div class="member-info-grid mb-3">
2307          <div class="info-card">
2308            <div class="info-icon">
2309              <i class="fas fa-user"></i>
2310            </div>
2311            <div class="info-content">
2312              <small class="text-muted">Name</small>
2313              <p class="mb-0 fw-bold">${member.name}</p>
2314            </div>
2315          </div>
2316          <div class="info-card">
2317            <div class="info-icon">
2318              <i class="fas fa-credit-card"></i>
2319            </div>
2320            <div class="info-content">
2321              <small class="text-muted">Card Number</small>
2322              <p class="mb-0 fw-bold">${member.memberNumber}</p>
2323            </div>
2324          </div>
2325          <div class="info-card" style="text-align: center;">
2326            <div class="info-icon">
2327              <i class="fas fa-info-circle"></i>
2328            </div>
2329            <div class="info-content">
2330              <small class="text-muted">Status</small>
2331              <p class="mb-0 fw-bold ${member.estado === 'Active' ? 'text-success' : 'text-warning'}">${member.estado}</p>
2332            </div>
2333          </div>
2334        </div>
2335        <div class="qr-section text-center mb-3">
2336          <div class="info-card qr-card-large">
2337            <div class="info-icon">
2338              <i class="fas fa-qrcode"></i>
2339            </div>
2340            <div class="info-content">
2341              <div class="qr-code-wrapper-large">
2342                <img src="https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(qrData)}"
2343                     alt="Member QR Code"
2344                     class="qr-code-img-large">
2345              </div>
2346            </div>
2347          </div>
2348        </div>
2349        <div class="alert alert-gold py-2 mb-3">
2350          <small><i class="fas fa-qrcode"></i> QR code with your card number</small>
2351        </div>
2352        <div class="d-grid gap-2 mb-3">
2353          <a href="https://ehhec.com/wp-content/uploads/2025/10/exclusive-travel-card.pdf" target="_blank" class="btn btn-outline-primary">
2354            <i class="fas fa-file-pdf"></i> Member Information
2355          </a>
2356        </div>
2357      </div>
2358    `;
2359    const modal = createModal('Dashboard', dashboardContent, 'modal-md');
2360    document.body.appendChild(modal);
2361  }
2362  
2363  function refreshMemberDashboard(email) {
2364    const refreshBtn = document.querySelector('.btn-refresh-dashboard');
2365    const originalIcon = refreshBtn.innerHTML;
2366    
2367    // Show loading state
2368    refreshBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
2369    refreshBtn.disabled = true;
2370    
2371    // Fetch fresh member data
2372    fetchMemberData().then(members => {
2373      const member = members.find(m => m.email.toLowerCase() === email.toLowerCase());
2374      if (member) {
2375        // Close current modal and reopen with fresh data
2376        document.querySelector('.modal').remove();
2377        showMemberDashboard(member);
2378        
2379        // Show success feedback
2380        setTimeout(() => {
2381          const successToast = document.createElement('div');
2382          successToast.className = 'position-fixed top-0 end-0 p-3';
2383          successToast.style.zIndex = '9999';
2384          successToast.innerHTML = `
2385            <div class="toast show" role="alert">
2386              <div class="toast-body">
2387                <i class="fas fa-check-circle text-success me-2"></i>
2388                Data refreshed successfully
2389              </div>
2390            </div>
2391          `;
2392          document.body.appendChild(successToast);
2393          setTimeout(() => successToast.remove(), 3000);
2394        }, 100);
2395      } else {
2396        // Member not found anymore
2397        document.querySelector('.modal').remove();
2398        showNotRegisteredError();
2399      }
2400    }).catch(error => {
2401      console.error('Error refreshing data:', error);
2402      refreshBtn.innerHTML = originalIcon;
2403      refreshBtn.disabled = false;
2404    });
2405  }
2406  
2407  function showNotRegisteredError() {
2408    const errorContent = `
2409      <div class="text-center">
2410        <div class="alert alert-warning">
2411          <i class="fas fa-exclamation-triangle fa-2x mb-3"></i>
2412          <h5>Member Not Found</h5>
2413          <p class="mb-3">We couldn't find your email in our member database.</p>
2414          <p class="mb-4">Please contact our technical support for assistance.</p>
2415          <a href="https://wa.link/6zal29" target="_blank" class="btn btn-success">
2416            <i class="fab fa-whatsapp"></i> Contact Technical Support
2417          </a>
2418        </div>
2419        <button class="btn btn-secondary mt-3" onclick="this.closest('.modal').remove()">
2420          <i class="fas fa-arrow-left"></i> Try Again
2421        </button>
2422      </div>
2423    `;
2424    const modal = createModal('Authentication Failed', errorContent);
2425    document.body.appendChild(modal);
2426  }
2427  
2428  // Initial content load
2429  toggleLanguage(); // This will call all cargar... functions
2430});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.