<div class="trip-overview-raw" style="display: none;"> <script> (function(){ try { var mapData = {"summary":{"title":"21-Day Portugal Family Trip","dates":"August 2026","travelers":"4 Travelers"},"weather":{"desc":"Warm and sunny with occasional coastal breezes","temp":"25-35°C"},"security":{"status":"Low Risk","tip":"Portugal is generally safe for families; stay aware of your surroundings."},"budget":{"total":"€845–€1,415","items":[{"label":"Accommodations","val":"€420–€790"},{"label":"Transport","val":"€50–€75"},{"label":"Activities & Food","val":"€375–€550"}]},"map":{"waypoints":[{"name":"Lisbon","lat":38.7223,"lon":-9.1393,"days":"Day 1-7","desc":"Explore the vibrant capital with family-friendly activities.","photo":"","highlights":["Tagus River Sunset","Historic Tram 28"]},{"name":"Lagos","lat":37.1028,"lon":-8.6747,"days":"Day 8-14","desc":"Enjoy beautiful beaches and sea adventures.","photo":"","highlights":["Ponta da Piedade","Zoomarine Algarve"]},{"name":"Porto","lat":41.1496,"lon":-8.6109,"days":"Day 15-21","desc":"Discover the charm of Porto and its riverside attractions.","photo":"","highlights":["Livraria Lello","Douro Valley"]}],"route":[0,1,2]},"days":[{"day_index":1,"day_title":"Arrival in Lisbon","image_query":"Lisbon Alfama Portugal","html_placeholder":"[DAY_IMAGE_01]"},{"day_index":2,"day_title":"Discovering Lisbon’s Old Quarters","image_query":"Lisbon Tram Adventure Portugal","html_placeholder":"[DAY_IMAGE_02]"},{"day_index":3,"day_title":"Oceanarium & Parque das Nações","image_query":"Lisbon Oceanarium Portugal","html_placeholder":"[DAY_IMAGE_03]"},{"day_index":4,"day_title":"Day Trip to Sintra","image_query":"Sintra Pena Palace Portugal","html_placeholder":"[DAY_IMAGE_04]"},{"day_index":5,"day_title":"Belém & Maritime Discoveries","image_query":"Lisbon Belém Portugal","html_placeholder":"[DAY_IMAGE_05]"},{"day_index":6,"day_title":"Beach Day at Costa da Caparica","image_query":"Costa da Caparica beach Portugal","html_placeholder":"[DAY_IMAGE_06]"},{"day_index":7,"day_title":"Free/Rest Day in Lisbon","image_query":"Lisbon Chiado Portugal","html_placeholder":"[DAY_IMAGE_07]"},{"day_index":8,"day_title":"Lisbon to Algarve (Lagos/Albufeira)","image_query":"Lagos Portugal","html_placeholder":"[DAY_IMAGE_08]"},{"day_index":9,"day_title":"Beaches & Sea Caves","image_query":"Lagos caves Portugal","html_placeholder":"[DAY_IMAGE_09]"},{"day_index":10,"day_title":"Family Adventure Park","image_query":"Lagos waterpark Portugal","html_placeholder":"[DAY_IMAGE_10]"},{"day_index":11,"day_title":"Cliffs & Villages","image_query":"Sagres Portugal","html_placeholder":"[DAY_IMAGE_11]"},{"day_index":12,"day_title":"Market & Cooking Class","image_query":"Lagos market Portugal","html_placeholder":"[DAY_IMAGE_12]"},{"day_index":13,"day_title":"Free/Rest Day","image_query":"Lagos Portugal","html_placeholder":"[DAY_IMAGE_13]"},{"day_index":14,"day_title":"Dolphin Watching & Farewell to Algarve","image_query":"Lagos dolphin watching Portugal","html_placeholder":"[DAY_IMAGE_14]"},{"day_index":15,"day_title":"Algarve to Porto (by train or flight)","image_query":"Porto Ribeira Portugal","html_placeholder":"[DAY_IMAGE_15]"},{"day_index":16,"day_title":"Porto City Discovery","image_query":"Porto Livraria Lello Portugal","html_placeholder":"[DAY_IMAGE_16]"},{"day_index":17,"day_title":"Douro Valley Day Trip","image_query":"Douro Valley vineyards Portugal","html_placeholder":"[DAY_IMAGE_17]"},{"day_index":18,"day_title":"Porto Parks & Play","image_query":"Porto City Park Portugal","html_placeholder":"[DAY_IMAGE_18]"},{"day_index":19,"day_title":"Day Trip to Guimarães","image_query":"Guimarães castle Portugal","html_placeholder":"[DAY_IMAGE_19]"},{"day_index":20,"day_title":"Free/Rest Day in Porto","image_query":"Porto Foz Portugal","html_placeholder":"[DAY_IMAGE_20]"},{"day_index":21,"day_title":"Departure from Porto","image_query":"Porto Airport Portugal","html_placeholder":"[DAY_IMAGE_21]"}]}; var dayImagesRaw = [{"day_index":1,"day_title":"Arrival in Lisbon","placeholder":"[DAY_IMAGE_01]","day_image_url":"https://images.unsplash.com/photo-1616971693099-a1b43ae7108b?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMaXNib24lMjBBbGZhbWElMjBQb3J0dWdhbHxlbnwwfDB8fHwxNzY5NzAyMTIwfDA&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1616971693099-a1b43ae7108b?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMaXNib24lMjBBbGZhbWElMjBQb3J0dWdhbHxlbnwwfDB8fHwxNzY5NzAyMTIwfDA&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Arrival in Lisbon\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":2,"day_title":"Discovering Lisbon’s Old Quarters","placeholder":"[DAY_IMAGE_02]","day_image_url":"https://images.unsplash.com/photo-1755114113169-2f86a86f9f8d?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMaXNib24lMjBUcmFtJTIwQWR2ZW50dXJlJTIwUG9ydHVnYWx8ZW58MHwwfHx8MTc2OTcwMjEyMHww&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1755114113169-2f86a86f9f8d?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMaXNib24lMjBUcmFtJTIwQWR2ZW50dXJlJTIwUG9ydHVnYWx8ZW58MHwwfHx8MTc2OTcwMjEyMHww&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Discovering Lisbon’s Old Quarters\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":3,"day_title":"Oceanarium & Parque das Nações","placeholder":"[DAY_IMAGE_03]","day_image_url":"https://images.unsplash.com/photo-1584203968150-fe113b69ecbe?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMaXNib24lMjBPY2VhbmFyaXVtJTIwUG9ydHVnYWx8ZW58MHwwfHx8MTc2OTcwMjEyMXww&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1584203968150-fe113b69ecbe?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMaXNib24lMjBPY2VhbmFyaXVtJTIwUG9ydHVnYWx8ZW58MHwwfHx8MTc2OTcwMjEyMXww&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Oceanarium & Parque das Nações\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":4,"day_title":"Day Trip to Sintra","placeholder":"[DAY_IMAGE_04]","day_image_url":"https://images.unsplash.com/photo-1734812787881-de6960ac74d1?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxTaW50cmElMjBQZW5hJTIwUGFsYWNlJTIwUG9ydHVnYWx8ZW58MHwwfHx8MTc2OTcwMjEyMXww&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1734812787881-de6960ac74d1?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxTaW50cmElMjBQZW5hJTIwUGFsYWNlJTIwUG9ydHVnYWx8ZW58MHwwfHx8MTc2OTcwMjEyMXww&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Day Trip to Sintra\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":5,"day_title":"Belém & Maritime Discoveries","placeholder":"[DAY_IMAGE_05]","day_image_url":"https://images.unsplash.com/photo-1697633533011-8be9343ef38a?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMaXNib24lMjBCZWwlQzMlQTltJTIwUG9ydHVnYWx8ZW58MHwwfHx8MTc2OTcwMjEyMnww&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1697633533011-8be9343ef38a?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMaXNib24lMjBCZWwlQzMlQTltJTIwUG9ydHVnYWx8ZW58MHwwfHx8MTc2OTcwMjEyMnww&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Belém & Maritime Discoveries\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":6,"day_title":"Beach Day at Costa da Caparica","placeholder":"[DAY_IMAGE_06]","day_image_url":"https://images.unsplash.com/photo-1632500347726-2b7a4508d121?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxDb3N0YSUyMGRhJTIwQ2FwYXJpY2ElMjBiZWFjaCUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk3MDIxMjJ8MA&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1632500347726-2b7a4508d121?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxDb3N0YSUyMGRhJTIwQ2FwYXJpY2ElMjBiZWFjaCUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk3MDIxMjJ8MA&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Beach Day at Costa da Caparica\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":7,"day_title":"Free/Rest Day in Lisbon","placeholder":"[DAY_IMAGE_07]","day_image_url":"https://images.unsplash.com/photo-1768501362063-17082efa1682?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMaXNib24lMjBDaGlhZG8lMjBQb3J0dWdhbHxlbnwwfDB8fHwxNzY5NzAyMTIzfDA&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1768501362063-17082efa1682?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMaXNib24lMjBDaGlhZG8lMjBQb3J0dWdhbHxlbnwwfDB8fHwxNzY5NzAyMTIzfDA&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Free/Rest Day in Lisbon\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":8,"day_title":"Lisbon to Algarve (Lagos/Albufeira)","placeholder":"[DAY_IMAGE_08]","day_image_url":"https://images.unsplash.com/photo-1627826676942-576ea238e0cc?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMYWdvcyUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk2ODY5MTB8MA&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1627826676942-576ea238e0cc?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMYWdvcyUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk2ODY5MTB8MA&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Lisbon to Algarve (Lagos/Albufeira)\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":9,"day_title":"Beaches & Sea Caves","placeholder":"[DAY_IMAGE_09]","day_image_url":"https://images.unsplash.com/photo-1635619608146-0e24519dad42?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMYWdvcyUyMGNhdmVzJTIwUG9ydHVnYWx8ZW58MHwwfHx8MTc2OTcwMjEyM3ww&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1635619608146-0e24519dad42?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMYWdvcyUyMGNhdmVzJTIwUG9ydHVnYWx8ZW58MHwwfHx8MTc2OTcwMjEyM3ww&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Beaches & Sea Caves\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":10,"day_title":"Family Adventure Park","placeholder":"[DAY_IMAGE_10]","day_image_url":"https://images.unsplash.com/photo-1608750330768-9dcd0b258109?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwyfHxQb3J0dWdhbCUyMHRyYXZlbCUyMGxhbmRzY2FwZXxlbnwwfDB8fHwxNzY5NjE0Mjg2fDA&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1608750330768-9dcd0b258109?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwyfHxQb3J0dWdhbCUyMHRyYXZlbCUyMGxhbmRzY2FwZXxlbnwwfDB8fHwxNzY5NjE0Mjg2fDA&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Family Adventure Park\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":11,"day_title":"Cliffs & Villages","placeholder":"[DAY_IMAGE_11]","day_image_url":"https://images.unsplash.com/photo-1695199858472-c81a7444789d?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxTYWdyZXMlMjBQb3J0dWdhbHxlbnwwfDB8fHwxNzY5Njg2OTEwfDA&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1695199858472-c81a7444789d?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxTYWdyZXMlMjBQb3J0dWdhbHxlbnwwfDB8fHwxNzY5Njg2OTEwfDA&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Cliffs & Villages\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":12,"day_title":"Market & Cooking Class","placeholder":"[DAY_IMAGE_12]","day_image_url":"https://images.unsplash.com/photo-1646076930249-e4e0b3d03678?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMYWdvcyUyMG1hcmtldCUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk3MDIxMjR8MA&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1646076930249-e4e0b3d03678?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMYWdvcyUyMG1hcmtldCUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk3MDIxMjR8MA&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Market & Cooking Class\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":13,"day_title":"Free/Rest Day","placeholder":"[DAY_IMAGE_13]","day_image_url":"https://images.unsplash.com/photo-1627826676942-576ea238e0cc?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMYWdvcyUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk2ODY5MTB8MA&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1627826676942-576ea238e0cc?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMYWdvcyUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk2ODY5MTB8MA&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Free/Rest Day\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":14,"day_title":"Dolphin Watching & Farewell to Algarve","placeholder":"[DAY_IMAGE_14]","day_image_url":"https://images.unsplash.com/photo-1568807090201-842cc3075dec?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMYWdvcyUyMGRvbHBoaW4lMjB3YXRjaGluZyUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk3MDIxMjR8MA&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1568807090201-842cc3075dec?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxMYWdvcyUyMGRvbHBoaW4lMjB3YXRjaGluZyUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk3MDIxMjR8MA&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Dolphin Watching & Farewell to Algarve\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":15,"day_title":"Algarve to Porto (by train or flight)","placeholder":"[DAY_IMAGE_15]","day_image_url":"https://images.unsplash.com/photo-1646921414314-aad689d55b4e?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxQb3J0byUyMFJpYmVpcmElMjBQb3J0dWdhbHxlbnwwfDB8fHwxNzY5NzAyMTI1fDA&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1646921414314-aad689d55b4e?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxQb3J0byUyMFJpYmVpcmElMjBQb3J0dWdhbHxlbnwwfDB8fHwxNzY5NzAyMTI1fDA&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Algarve to Porto (by train or flight)\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":16,"day_title":"Porto City Discovery","placeholder":"[DAY_IMAGE_16]","day_image_url":"https://images.unsplash.com/photo-1648670086311-fca5a49d4dee?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxQb3J0byUyMExpdnJhcmlhJTIwTGVsbG8lMjBQb3J0dWdhbHxlbnwwfDB8fHwxNzY5NzAyMTI1fDA&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1648670086311-fca5a49d4dee?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxQb3J0byUyMExpdnJhcmlhJTIwTGVsbG8lMjBQb3J0dWdhbHxlbnwwfDB8fHwxNzY5NzAyMTI1fDA&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Porto City Discovery\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":17,"day_title":"Douro Valley Day Trip","placeholder":"[DAY_IMAGE_17]","day_image_url":"https://images.unsplash.com/photo-1677477242420-44217efa1534?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxEb3VybyUyMFZhbGxleSUyMHZpbmV5YXJkcyUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk3MDIxMjV8MA&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1677477242420-44217efa1534?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxEb3VybyUyMFZhbGxleSUyMHZpbmV5YXJkcyUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk3MDIxMjV8MA&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Douro Valley Day Trip\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":18,"day_title":"Porto Parks & Play","placeholder":"[DAY_IMAGE_18]","day_image_url":"https://images.unsplash.com/photo-1762294486679-d5067439c19f?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxQb3J0byUyMENpdHklMjBQYXJrJTIwUG9ydHVnYWx8ZW58MHwwfHx8MTc2OTcwMjEyNnww&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1762294486679-d5067439c19f?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxQb3J0byUyMENpdHklMjBQYXJrJTIwUG9ydHVnYWx8ZW58MHwwfHx8MTc2OTcwMjEyNnww&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Porto Parks & Play\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":19,"day_title":"Day Trip to Guimarães","placeholder":"[DAY_IMAGE_19]","day_image_url":"https://images.unsplash.com/photo-1662149191062-68917c79bbd6?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxHdWltYXIlQzMlQTNlcyUyMGNhc3RsZSUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk3MDIxMjZ8MA&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1662149191062-68917c79bbd6?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxHdWltYXIlQzMlQTNlcyUyMGNhc3RsZSUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk3MDIxMjZ8MA&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Day Trip to Guimarães\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":20,"day_title":"Free/Rest Day in Porto","placeholder":"[DAY_IMAGE_20]","day_image_url":"https://images.unsplash.com/photo-1731336477469-c6dbb4211102?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxQb3J0byUyMEZveiUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk3MDIxMjZ8MA&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1731336477469-c6dbb4211102?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwxfHxQb3J0byUyMEZveiUyMFBvcnR1Z2FsfGVufDB8MHx8fDE3Njk3MDIxMjZ8MA&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Free/Rest Day in Porto\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}, {"day_index":21,"day_title":"Departure from Porto","placeholder":"[DAY_IMAGE_21]","day_image_url":"https://images.unsplash.com/photo-1608750330768-9dcd0b258109?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwyfHxQb3J0dWdhbCUyMHRyYXZlbCUyMGxhbmRzY2FwZXxlbnwwfDB8fHwxNzY5NjE0Mjg2fDA&ixlib=rb-4.1.0&q=80&w=1080","day_image_html":"<img src=\"https://images.unsplash.com/photo-1608750330768-9dcd0b258109?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w4NjAxNDN8MHwxfHNlYXJjaHwyfHxQb3J0dWdhbCUyMHRyYXZlbCUyMGxhbmRzY2FwZXxlbnwwfDB8fHwxNzY5NjE0Mjg2fDA&ixlib=rb-4.1.0&q=80&w=1080\" width=\"640\" alt=\"Departure from Porto\" style=\"display:block;margin:20px auto;border-radius:8px;\">"}]; var dayImages = Array.isArray(dayImagesRaw) ? dayImagesRaw : (dayImagesRaw ? [dayImagesRaw] : []); var travelerName = "Hakim"; var destination = "Portugal"; function extractDays(dayRange) { if (!dayRange) return []; var match = dayRange.toString().match(/Day\s+(\d+)(?:-(\d+))?/); if (!match) return []; var start = parseInt(match[1]); var end = match[2] ? parseInt(match[2]) : start; var days = []; for (var i = start; i <= end; i++) { days.push(i); } return days; } function findImageForWaypoint(waypoint, dayImages) { var days = extractDays(waypoint.days); if (days.length === 0) return null; var firstDay = days[0]; for (var i = 0; i < dayImages.length; i++) { if (dayImages[i].day_index === firstDay) { return dayImages[i].day_image_url; } } return null; } if (mapData && mapData.map && mapData.map.waypoints) { for (var i = 0; i < mapData.map.waypoints.length; i++) { var wp = mapData.map.waypoints[i]; var imageUrl = findImageForWaypoint(wp, dayImages); if (imageUrl) { wp.photo = imageUrl; } } } window.TD_MAP_DATA_ENRICHED = mapData; window.travelerName = travelerName; window.destination = destination; } catch(e) { console.error('Error enriching map data:', e); window.TD_MAP_DATA_ENRICHED = {"summary":{"title":"21-Day Portugal Family Trip","dates":"August 2026","travelers":"4 Travelers"},"weather":{"desc":"Warm and sunny with occasional coastal breezes","temp":"25-35°C"},"security":{"status":"Low Risk","tip":"Portugal is generally safe for families; stay aware of your surroundings."},"budget":{"total":"€845–€1,415","items":[{"label":"Accommodations","val":"€420–€790"},{"label":"Transport","val":"€50–€75"},{"label":"Activities & Food","val":"€375–€550"}]},"map":{"waypoints":[{"name":"Lisbon","lat":38.7223,"lon":-9.1393,"days":"Day 1-7","desc":"Explore the vibrant capital with family-friendly activities.","photo":"","highlights":["Tagus River Sunset","Historic Tram 28"]},{"name":"Lagos","lat":37.1028,"lon":-8.6747,"days":"Day 8-14","desc":"Enjoy beautiful beaches and sea adventures.","photo":"","highlights":["Ponta da Piedade","Zoomarine Algarve"]},{"name":"Porto","lat":41.1496,"lon":-8.6109,"days":"Day 15-21","desc":"Discover the charm of Porto and its riverside attractions.","photo":"","highlights":["Livraria Lello","Douro Valley"]}],"route":[0,1,2]},"days":[{"day_index":1,"day_title":"Arrival in Lisbon","image_query":"Lisbon Alfama Portugal","html_placeholder":"[DAY_IMAGE_01]"},{"day_index":2,"day_title":"Discovering Lisbon’s Old Quarters","image_query":"Lisbon Tram Adventure Portugal","html_placeholder":"[DAY_IMAGE_02]"},{"day_index":3,"day_title":"Oceanarium & Parque das Nações","image_query":"Lisbon Oceanarium Portugal","html_placeholder":"[DAY_IMAGE_03]"},{"day_index":4,"day_title":"Day Trip to Sintra","image_query":"Sintra Pena Palace Portugal","html_placeholder":"[DAY_IMAGE_04]"},{"day_index":5,"day_title":"Belém & Maritime Discoveries","image_query":"Lisbon Belém Portugal","html_placeholder":"[DAY_IMAGE_05]"},{"day_index":6,"day_title":"Beach Day at Costa da Caparica","image_query":"Costa da Caparica beach Portugal","html_placeholder":"[DAY_IMAGE_06]"},{"day_index":7,"day_title":"Free/Rest Day in Lisbon","image_query":"Lisbon Chiado Portugal","html_placeholder":"[DAY_IMAGE_07]"},{"day_index":8,"day_title":"Lisbon to Algarve (Lagos/Albufeira)","image_query":"Lagos Portugal","html_placeholder":"[DAY_IMAGE_08]"},{"day_index":9,"day_title":"Beaches & Sea Caves","image_query":"Lagos caves Portugal","html_placeholder":"[DAY_IMAGE_09]"},{"day_index":10,"day_title":"Family Adventure Park","image_query":"Lagos waterpark Portugal","html_placeholder":"[DAY_IMAGE_10]"},{"day_index":11,"day_title":"Cliffs & Villages","image_query":"Sagres Portugal","html_placeholder":"[DAY_IMAGE_11]"},{"day_index":12,"day_title":"Market & Cooking Class","image_query":"Lagos market Portugal","html_placeholder":"[DAY_IMAGE_12]"},{"day_index":13,"day_title":"Free/Rest Day","image_query":"Lagos Portugal","html_placeholder":"[DAY_IMAGE_13]"},{"day_index":14,"day_title":"Dolphin Watching & Farewell to Algarve","image_query":"Lagos dolphin watching Portugal","html_placeholder":"[DAY_IMAGE_14]"},{"day_index":15,"day_title":"Algarve to Porto (by train or flight)","image_query":"Porto Ribeira Portugal","html_placeholder":"[DAY_IMAGE_15]"},{"day_index":16,"day_title":"Porto City Discovery","image_query":"Porto Livraria Lello Portugal","html_placeholder":"[DAY_IMAGE_16]"},{"day_index":17,"day_title":"Douro Valley Day Trip","image_query":"Douro Valley vineyards Portugal","html_placeholder":"[DAY_IMAGE_17]"},{"day_index":18,"day_title":"Porto Parks & Play","image_query":"Porto City Park Portugal","html_placeholder":"[DAY_IMAGE_18]"},{"day_index":19,"day_title":"Day Trip to Guimarães","image_query":"Guimarães castle Portugal","html_placeholder":"[DAY_IMAGE_19]"},{"day_index":20,"day_title":"Free/Rest Day in Porto","image_query":"Porto Foz Portugal","html_placeholder":"[DAY_IMAGE_20]"},{"day_index":21,"day_title":"Departure from Porto","image_query":"Porto Airport Portugal","html_placeholder":"[DAY_IMAGE_21]"}]} || {}; window.travelerName = "Hakim"; window.destination = "Portugal"; } })(); </script> </div> <script> (function () { 'use strict'; console.log('[TD Map V8] Initializing...'); function loadLeaflet(callback) { if (typeof L !== 'undefined') { callback(); return; } console.log('[TD Map V8] Loading Leaflet libraries...'); var link = document.createElement('link'); link.rel = 'stylesheet'; link.href = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css'; document.head.appendChild(link); var script = document.createElement('script'); script.src = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js'; script.onload = function () { console.log('[TD Map V8] Leaflet loaded!'); callback(); }; script.onerror = function () { console.error('[TD Map V8] Failed to load Leaflet.'); var container = document.getElementById('td-map-v8-container'); if (container) container.innerHTML = 'Map Error: Could not load libraries.'; }; document.head.appendChild(script); } function decodeHTML(str) { var txt = document.createElement('textarea'); var decoded = str; var max = 5, i = 0; while ((decoded.includes('<') || decoded.includes('&')) && i < max) { txt.innerHTML = decoded; decoded = txt.value; i++; } return decoded; } function extractMapData(content) { var startMarkers = ['var mapData=', 'var mapData =', 'mapData=']; for (var m = 0; m < startMarkers.length; m++) { var startIdx = content.indexOf(startMarkers[m]); if (startIdx !== -1) { var braceStart = content.indexOf('{', startIdx); if (braceStart === -1) continue; var depth = 0, braceEnd = -1; for (var i = braceStart; i < content.length; i++) { if (content[i] === '{') depth++; if (content[i] === '}') depth--; if (depth === 0) { braceEnd = i; break; } } if (braceEnd !== -1) { var jsonStr = content.substring(braceStart, braceEnd + 1); try { return JSON.parse(jsonStr); } catch (e) { jsonStr = jsonStr.replace(/&/g, '&').replace(/\\"/g, '"'); try { return JSON.parse(jsonStr); } catch (e2) { } } } } } return null; } function extractVariable(content, varName) { var match = content.match(new RegExp('var\\s+' + varName + '\\s*=\\s*["\']([^"\']+)["\']')); return match ? match[1] : null; } function initMap() { var mapData = window.TD_MAP_DATA_ENRICHED; var travelerName = window.travelerName || 'Traveler'; var destination = window.destination || 'Destination'; if (!mapData) { var rawEl = document.querySelector('.trip-overview-raw') || document.querySelector('#trip-overview-raw'); if (!rawEl) { console.warn('[TD Map V8] No data element found.'); return; } var content = decodeHTML(rawEl.innerHTML || rawEl.textContent); rawEl.style.display = 'none'; mapData = extractMapData(content); if (!mapData) { console.error('[TD Map V8] JSON extraction failed.'); return; } travelerName = extractVariable(content, 'travelerName') || travelerName; destination = extractVariable(content, 'destination') || destination; } var container = document.getElementById('td-map-v8-container'); if (!container) { container = document.createElement('div'); container.id = 'td-map-v8-container'; container.style.width = '100%'; container.style.display = 'flex'; container.style.flexDirection = 'column'; var rawEl = document.querySelector('.trip-overview-raw'); if (rawEl && rawEl.parentNode) { rawEl.parentNode.insertBefore(container, rawEl.nextSibling); } else { document.body.appendChild(container); } } container.innerHTML = ''; buildMapUI(container, mapData, travelerName, destination); } function buildMapUI(container, mapData, travelerName, destination) { var waypoints = mapData.map.waypoints || []; if (waypoints.length === 0) return; // Préparer les données pour la STATS BAR var weatherTemp = mapData.weather ? mapData.weather.temp : ''; var weatherDesc = mapData.weather ? mapData.weather.desc : ''; var securityStatus = mapData.security ? mapData.security.status : ''; var securityTip = mapData.security ? mapData.security.tip : ''; var budgetTotal = mapData.budget ? mapData.budget.total : ''; container.innerHTML = '<div id="td-map-v8" style="font-family: \'Inter\', sans-serif; width: 100%; background: #fff; border-radius: 0.75rem; overflow: hidden; box-shadow: 0 4px 20px rgba(0,0,0,0.08);"><div style="background: #001427; padding: 1.1rem 1.5rem;"><div style="display: flex; justify-content: space-between; align-items: center;"><div><h2 style="margin: 0; font-family: \'Poppins\', sans-serif; font-size: 1.1rem; font-weight: 600; color: white;">' + travelerName + '\'s Journey</h2><p style="margin: 0.25rem 0 0; font-size: 0.8rem; color: rgba(255,255,255,0.7);">' + (mapData.summary ? mapData.summary.dates : '') + ' • ' + (mapData.summary ? mapData.summary.travelers : '') + '</p></div><div style="text-align: right;"><span style="display: block; font-size: 0.7rem; text-transform: uppercase; color: rgba(255,255,255,0.5); letter-spacing: 1px; font-weight: 600;">Est. Budget</span><span style="font-size: 1rem; font-weight: 700; color: #E98A15;">' + budgetTotal + '</span></div></div></div><div style="display: grid; grid-template-columns: 1fr 1fr; background: #f8f9fa; border-left: 1px solid #eef0f2; border-right: 1px solid #eef0f2; padding: 0.9rem 1.5rem;"><div style="border-right: 1px solid #eef0f2; padding-right: 0.9rem;"><span style="display: block; font-size: 0.65rem; text-transform: uppercase; color: #8898aa; font-weight: 700; letter-spacing: 0.5px; margin-bottom: 0.25rem;">Weather</span><div style="display: flex; align-items: center; gap: 0.5rem;"><span style="font-size: 1.1rem;">☀️</span><div><span style="display: block; font-size: 0.8rem; font-weight: 600; color: #001427;">' + weatherTemp + '</span><span style="display: block; font-size: 0.7rem; color: #525f7f;">' + weatherDesc + '</span></div></div></div><div style="padding-left: 0.9rem;"><span style="display: block; font-size: 0.65rem; text-transform: uppercase; color: #8898aa; font-weight: 700; letter-spacing: 0.5px; margin-bottom: 0.25rem;">Safety</span><div style="display: flex; align-items: center; gap: 0.5rem;"><span style="font-size: 1.1rem;">🛡️</span><div><span style="display: block; font-size: 0.8rem; font-weight: 600; color: #001427;">' + securityStatus + '</span><span style="display: block; font-size: 0.7rem; color: #525f7f; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 120px;">' + securityTip + '</span></div></div></div></div><div id="leaflet-map-v8" style="width: 100%; height: 25rem; background: #e7e0da; z-index: 1;"></div><div id="timeline-v8" style="background: #f8f9fa; padding: 1rem 1.25rem; border-top: 3px solid #e98a15; overflow-x: auto; white-space: nowrap; -webkit-overflow-scrolling: touch;"><div style="display: inline-flex; gap: 0.5rem; padding-bottom: 5px;"></div></div><div style="display: flex; justify-content: center; gap: 1.5rem; padding: 0.8rem; font-size: 0.75rem; color: #001427; font-weight: 500; border-top: 1px solid #eee;"><span style="display: flex; align-items: center; gap: 0.4rem;"><span style="width: 0.6rem; height: 0.6rem; background: #e98a15; border-radius: 50%;"></span> ' + destination + '</span><span style="display: flex; align-items: center; gap: 0.4rem;"><span>📷</span> Click markers for photos</span></div></div><style>.leaflet-popup-content-wrapper { border-radius: 0.75rem !important; padding: 0 !important; overflow: hidden; box-shadow: 0 10px 25px rgba(0,0,0,0.15) !important; }.leaflet-popup-content { margin: 0 !important; width: 280px !important; }.leaflet-container { font-family: \'Inter\', sans-serif !important; }.timeline-item-v8 { display: inline-flex; flex-direction: column; align-items: center; cursor: pointer; padding: 0.5rem 0.75rem; border-radius: 0.5rem; min-width: 4.5rem; transition: all 0.2s ease; border: 1px solid transparent; }.timeline-item-v8:hover { background: #fff; border-color: #ddd; transform: translateY(-2px); }.timeline-item-v8.active { background: #e98a15; color: white !important; box-shadow: 0 4px 12px rgba(233, 138, 21, 0.4); }.timeline-item-v8.active span { color: white !important; }#timeline-v8::-webkit-scrollbar { height: 6px; }#timeline-v8::-webkit-scrollbar-track { background: transparent; }#timeline-v8::-webkit-scrollbar-thumb { background: #ddd; border-radius: 10px; }#timeline-v8::-webkit-scrollbar-thumb:hover { background: #ccc; }</style>'; var map = L.map('leaflet-map-v8', { scrollWheelZoom: true, zoomControl: true }).setView([0, 0], 2); L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png', { maxZoom: 19, attribution: '© <a href="https://carto.com/">CARTO</a>' }).addTo(map); var markers = []; waypoints.forEach(function(wp, i) { var dayLabelRaw = wp.days ? wp.days.toString() : ""; var dayLabelClean = dayLabelRaw.split('-')[0]; var iconHtml = '<div style="background: linear-gradient(135deg, #e98a15, #d47710); color: white; width: 2.2rem; height: 2.2rem; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 700; border: 3px solid white; box-shadow: 0 4px 15px rgba(233,138,21,0.5); font-size: 0.9rem;">' + (i + 1) + '</div>'; var icon = L.divIcon({ html: iconHtml, className: 'td-marker-v8', iconSize: [36, 36], iconAnchor: [18, 18], popupAnchor: [0, -24] }); var popupContent = '<div style="font-family: \'Inter\', sans-serif;"><div style="width: 100%; height: 9rem; background: #eee; overflow: hidden; position: relative;"><img src="' + (wp.photo || '') + '" style="width: 100%; height: 100%; object-fit: cover; display: block;" onerror="this.parentElement.style.display=\'none\'"></div><div style="padding: 1rem;"><span style="background: rgba(233,138,21,0.1); color: #d47710; padding: 0.25rem 0.6rem; border-radius: 2rem; font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;">' + wp.days + '</span><h4 style="margin: 0.5rem 0 0.25rem; font-size: 1rem; color: #001427; font-weight: 700; line-height: 1.3;">' + wp.name + '</h4><p style="font-size: 0.8rem; color: #666; margin: 0; line-height: 1.4;">' + (wp.desc || '') + '</p></div></div>'; var marker = L.marker([wp.lat, wp.lon], { icon: icon }).bindPopup(popupContent).addTo(map); markers.push(marker); var tlItem = document.createElement('div'); tlItem.className = 'timeline-item-v8'; var timelineDayText = dayLabelClean; if (/^\d+$/.test(timelineDayText.trim())) { timelineDayText = "Day " + timelineDayText; } tlItem.innerHTML = '<span style="font-size: 0.65rem; color: #999; font-weight: 600; text-transform: uppercase;">' + timelineDayText + '</span><span style="font-size: 0.8rem; font-weight: 700; color: #001427;">' + wp.name + '</span>'; tlItem.onclick = function() { map.setView([wp.lat, wp.lon], 11, { animate: true }); marker.openPopup(); var allItems = document.querySelectorAll('.timeline-item-v8'); for (var j = 0; j < allItems.length; j++) { allItems[j].classList.remove('active'); } tlItem.classList.add('active'); tlItem.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' }); }; marker.on('click', function() { var allItems = document.querySelectorAll('.timeline-item-v8'); for (var j = 0; j < allItems.length; j++) { allItems[j].classList.remove('active'); } tlItem.classList.add('active'); tlItem.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' }); }); document.querySelector('#timeline-v8 > div').appendChild(tlItem); }); var route = waypoints.map(function(wp) { return [wp.lat, wp.lon]; }); L.polyline(route, { color: '#e98a15', weight: 4, dashArray: '10, 10', opacity: 0.8, lineCap: 'round' }).addTo(map); if (markers.length > 0) { map.fitBounds(L.latLngBounds(waypoints.map(function(wp) { return [wp.lat, wp.lon]; })).pad(0.1)); } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function() { loadLeaflet(initMap); }); } else { loadLeaflet(initMap); } })(); </script>