The mock can now work several trips at once: a trip picker in the topbar, per-trip state in localStorage (edits + version history survive switching), and a per-trip router key so each trip routes on its own OSRM extract. Colombia (Cartagena -> Santa Marta, 8 days) becomes the default working trip, inside a new walking-profile OSRM instance: - scripts/crop_pbf.py: streaming 3-pass PBF cropper (no PBF library; the country file is too big for osmium extract -s complete_ways on this box). Framing validated against osmium test fixtures and osrm-extract. Drops relations (foot profile ignores restrictions). - scripts/setup-osrm-colombia.sh: download -> crop (~4.6 MB) -> extract/partition/customize with the official foot.lua -> serve :5003. Verified: Getsemaní -> Castillo San Felipe 7.98 km / 96 min. - server.js: ROUTERS map, ?router=colombia|northeast on /route, /table, /router-status (per-router probe points). - app.js: legs touching a transit stop are fixed (flight/taxi/bus via M.multimodal), never re-routed; distance-0 router answers (both points on one node) read as adjacent stops, not out-of-coverage. - multi-hotel fix: day-scope map fit uses the stays covering THAT day, so a two-city trip no longer fits the whole country per day. Also: pre-cache-tiles.sh (Cartagena+Santa Marta z14-16, 2560 tiles), tile cache write fix (Node rejects flags:'x'; buffer-then-write), favicon, renderHotelMks load-order guard, tests updated for the new default trip (all four puppeteer suites green, zero console errors).
992 lines
67 KiB
JavaScript
992 lines
67 KiB
JavaScript
// Fake data layer — same shapes the real API will return.
|
||
// Each stop: day, slot (mutual-exclusion group), state: planned | maybe | alt.
|
||
// Only one `planned` stop per slot per day; `alt`/`maybe` don't count against
|
||
// the day's time budget.
|
||
//
|
||
// Two demo cities: Florence (rich itinerary demo) and Boston (inside the
|
||
// local OSRM extract, so legs are routed on the real road network — see
|
||
// server.js /route proxy and app.js routeClient). ?city=florence|boston
|
||
const FLORENCE = {
|
||
trip: {
|
||
id: 'trip-2026-09',
|
||
version: 1,
|
||
title: 'Florence 12–15 Sep',
|
||
// stays, not a single hotel: {hotel, place, checkIn, checkOut, state}.
|
||
// Days resolve their anchor per date; >1 candidate stay covering the
|
||
// same nights → worst-case anchoring for those nights.
|
||
// Multi-city trips = more stays, each anchoring its own dates.
|
||
stays: [
|
||
{ id: 'ST1', name: 'Hotel Palagio', at: [43.7684, 11.2566], place: 'Florence',
|
||
checkIn: '2026-09-12', checkOut: '2026-09-15', state: 'booked', price: 180 },
|
||
],
|
||
places: [
|
||
{ id: 'PL1', name: 'Florence', bbox: [43.73, 11.21, 43.80, 11.29],
|
||
center: [43.769, 11.255], vibe: 'art + food, relaxed pace',
|
||
dates: ['2026-09-12', '2026-09-15'] }
|
||
],
|
||
bookings: [
|
||
{ type: 'hotel', name: 'Hotel Palagio', ref: 'H-77821',
|
||
dates: '12–15 Sep', where: [43.7684, 11.2566],
|
||
status: 'booked', source: 'user_booking' },
|
||
{ type: 'train', name: 'Frecciarossa 9512', ref: 'F-55812',
|
||
from: 'Firenze SMN', to: 'Pisa Centrale', date: '2026-09-15',
|
||
depart: '09:12', arrive: '09:58', status: 'booked', source: 'user_booking',
|
||
stations: { from: [43.7726, 11.2597], to: [43.7157, 10.3922] } }
|
||
]
|
||
},
|
||
|
||
days: [
|
||
{ id: 'D1', date: '2026-09-12', label: 'Day 1 · Fri 12',
|
||
startMin: 8 * 60, wakingHours: 11,
|
||
base: { name: 'Hotel Palagio', at: [43.7684, 11.2566] },
|
||
legs: [],
|
||
stops: [
|
||
{ id: 'S1', name: 'Breakfast at the hotel', kind: 'meal', mealKind: 'breakfast',
|
||
slot: 'breakfast', state: 'planned',
|
||
at: [43.7684, 11.2566], dur: 30, durConf: 3,
|
||
suggested: { value: 30, conf: 2, src: 'triptadvisor.com' } },
|
||
{ id: 'S2', name: 'Palazzo Pitti', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://www.palazzopittiturin.it',
|
||
at: [43.7639, 11.2518], dur: 60, durConf: 5, // user override (sticky)
|
||
suggested: { value: 150, conf: 2, src: 'wikivoyage.org' },
|
||
price: { amount: 14, cur: '€', conf: 2, src: 'uffizi.it' },
|
||
note: 'guides suggest 2–3 h', img: ['🏛️', 'Palazzo Pitti', 'linear-gradient(135deg,#b5533c,#7a3a2c)',
|
||
'https://thumb.wikimedia.org/wikipedia/commons/thumb/7/72/Palacio_Pitti%2C_Florencia%2C_Italia%2C_2022-09-18%2C_DD_197.jpg/1280px-Palacio_Pitti%2C_Florencia%2C_Italia%2C_2022-09-18%2C_DD_197.jpg'],
|
||
detail: {
|
||
summary: 'The Medici family’s riverside palazzo: the Galleria Palatina (Portraiture, the 500 Room) and the modern-art Galleria d’Arte Moderna. Rooms are small and crowded in peak season — the apartments alone run 1.5–2 h if you linger, ~1 h for the highlights. September afternoons are the sweet spot: light is good for photos and lines thin after 16:00.',
|
||
links: [
|
||
{ label: 'Official site', href: 'https://www.palazzopittiturin.it' },
|
||
{ label: 'Tickets', href: 'https://www.uffizi.it/en/visit/tickets' },
|
||
{ label: 'TripAdvisor', href: 'https://www.tripadvisor.com/Attraction_Review-g187791-d183726-Reviews-Palazzo_Pitti-Florence_Tuscany.html' },
|
||
{ label: 'Reddit r/Florence', href: 'https://www.reddit.com/r/Florence/search/?q=palazzo+pitti&restrict_sr=1' }
|
||
] } },
|
||
{ id: 'S4', name: 'Lunch — Trattoria Mario', kind: 'meal', mealKind: 'lunch',
|
||
slot: 'lunch', state: 'planned', url: 'https://www.trattoriamario.it',
|
||
at: [43.7667, 11.2544], dur: 45, durConf: 3,
|
||
suggested: { value: 90, conf: 2, src: 'trattoriamario.it' },
|
||
price: { amount: 25, cur: '€', conf: 2, src: 'trattoriamario.it' },
|
||
img: ['🍝', 'Trattoria Mario', 'linear-gradient(135deg,#d08b3c,#9c5f1e)',
|
||
'https://upload.wikimedia.org/wikipedia/commons/1/12/Bistecca_alla_fiorentina-01.jpg'],
|
||
detail: {
|
||
summary: 'A no-frills Florentine kitchen on Via dei Neri, open since 1954. Counter seating, short menu (bistecca, lampredotto, tripe soup), and the queue is real — arriving as lunch opens (12:00) is the difference between 10 minutes and 40. Budget ~1 h including eating.',
|
||
links: [
|
||
{ label: 'Official site', href: 'https://www.trattoriamario.it' },
|
||
{ label: 'Menu', href: 'https://www.trattoriamario.it/menu' },
|
||
{ label: 'TripAdvisor', href: 'https://www.tripadvisor.com/Restaurant_Review-g187791-d310951-Reviews-Trattoria_Mario-Florence_Tuscany.html' },
|
||
{ label: 'Reddit r/food', href: 'https://www.reddit.com/r/food/search/?q=trattoria+mario+florence&restrict_sr=1' }
|
||
] } },
|
||
{ id: 'S5', name: 'Boboli Gardens', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://www.boboli.it',
|
||
at: [43.7579, 11.2463], dur: 120, durConf: 3,
|
||
suggested: { value: 120, conf: 2, src: 'boboli.it' },
|
||
price: { amount: 10, cur: '€', conf: 2, src: 'uffizi.it' },
|
||
img: ['🌿', 'Boboli Gardens', 'linear-gradient(135deg,#4f9e63,#2c6b40)',
|
||
'https://thumb.wikimedia.org/wikipedia/commons/thumb/d/d2/Obelisco%2C_Boboli_Gardens%2C_Florence_%2826408174180%29.jpg/1280px-Obelisco%2C_Boboli_Gardens%2C_Florence_%2826408174180%29.jpg'],
|
||
detail: {
|
||
summary: 'The Medici’s formal garden behind Pitti — statues, the Apollo fountain, a hilltop view over the city. The full loop with the Accademia annex runs 2 h; the upper terraces alone are a fine 45-minute pace-break. Pairs naturally with Pitti: the entrance is the courtyard behind it.',
|
||
links: [
|
||
{ label: 'Official site', href: 'https://www.boboli.it' },
|
||
{ label: 'Tickets', href: 'https://www.uffizi.it/en/visit/tickets' },
|
||
{ label: 'TripAdvisor', href: 'https://www.tripadvisor.com/Attraction_Review-g187791-d183872-Reviews-Giardini_Di_Boboli-Florence_Tuscany.html' },
|
||
{ label: 'Reddit r/Florence', href: 'https://www.reddit.com/r/Florence/search/?q=boboli&restrict_sr=1' }
|
||
] } },
|
||
{ id: 'S6', name: 'Gelato — Vivoli', kind: 'meal', mealKind: 'snack',
|
||
slot: 'snack', state: 'planned',
|
||
at: [43.7680, 11.2537], dur: 20, durConf: 3,
|
||
suggested: { value: 20, conf: 1, src: null },
|
||
price: null,
|
||
img: ['🍦', 'Vivoli gelato', 'linear-gradient(135deg,#e0a5c0,#a56a92)'] },
|
||
{ id: 'S7', name: 'Lunch — Ristorante Santini', kind: 'meal', mealKind: 'lunch',
|
||
slot: 'lunch', state: 'alt', url: 'https://www.santini.it',
|
||
at: [43.7646, 11.2528], dur: 75, durConf: 3,
|
||
suggested: { value: 90, conf: 2, src: 'santini.it' },
|
||
price: { amount: 45, cur: '€', conf: 2, src: 'santini.it' },
|
||
img: ['🍷', 'Ristorante Santini', 'linear-gradient(135deg,#7a4a5c,#4c2b3a)',
|
||
'https://thumb.wikimedia.org/wikipedia/commons/thumb/c/c0/View_from_Giotto%27s_Bell_Tower_-_Florence.jpg/1280px-View_from_Giotto%27s_Bell_Tower_-_Florence.jpg'],
|
||
detail: {
|
||
summary: 'A classic Florentine restaurant in a 16th-century building on the Arno — the terrace looks across to Pitti. Set tables, longer menus, lunch from 12:30. The step-up option: worth holding if Mario’s queue looks long, or if the day goes well and you want to mark it.',
|
||
links: [
|
||
{ label: 'Official site', href: 'https://www.santini.it' },
|
||
{ label: 'Menu', href: 'https://www.santini.it/en/menu' },
|
||
{ label: 'TripAdvisor', href: 'https://www.tripadvisor.com/Restaurant_Review-g187791-d1442007-Reviews-Ristorante_Santini-Florence_Tuscany.html' },
|
||
{ label: 'Reddit r/food', href: 'https://www.reddit.com/r/food/search/?q=santini+florence&restrict_sr=1' }
|
||
] } }
|
||
]
|
||
},
|
||
{ id: 'D2', date: '2026-09-13', label: 'Day 2 · Sat 13',
|
||
startMin: 8 * 60 + 30, wakingHours: 11,
|
||
base: { name: 'Hotel Palagio', at: [43.7684, 11.2566] },
|
||
legs: [],
|
||
stops: [
|
||
{ id: 'S8', name: 'Breakfast at the hotel', kind: 'meal', mealKind: 'breakfast',
|
||
slot: 'breakfast', state: 'planned',
|
||
at: [43.7684, 11.2566], dur: 30, durConf: 3,
|
||
suggested: { value: 30, conf: 2, src: 'tripadvisor.com' } },
|
||
{ id: 'S9', name: 'Galleria dell’Accademia (David)', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://www.galleriaaccademia.firenze.it',
|
||
at: [43.7734, 11.2628], dur: 90, durConf: 3,
|
||
suggested: { value: 120, conf: 2, src: 'wikivoyage.org' },
|
||
price: { amount: 16, cur: '€', conf: 2, src: 'galleriaaccademia.firenze.it' },
|
||
img: ['🗿', 'Accademia', 'linear-gradient(135deg,#6b7280,#3f4650)'],
|
||
detail: {
|
||
summary: 'Home of the original David plus Donatello’s Prigione. Timed-entry tickets, and the David room moves in batches — a 09:30 slot is noticeably calmer than midday. Allow ~90 min; 2 h if you do the whole collection.',
|
||
links: [
|
||
{ label: 'Official site', href: 'https://www.galleriaaccademia.firenze.it' },
|
||
{ label: 'Tickets', href: 'https://www.galleriaaccademia.firenze.it/en/tickets' },
|
||
{ label: 'TripAdvisor', href: 'https://www.tripadvisor.com/Attraction_Review-g187791-d183692-Reviews-Galleria_dell_Accademia-Florence_Tuscany.html' },
|
||
{ label: 'Reddit r/Florence', href: 'https://www.reddit.com/r/Florence/search/?q=accademia+david&restrict_sr=1' }
|
||
] } },
|
||
{ id: 'S10', name: 'Lunch — Trattoria Sostanza', kind: 'meal', mealKind: 'lunch',
|
||
slot: 'lunch', state: 'planned', url: 'https://www.sostanza.it',
|
||
at: [43.7609, 11.2469], dur: 75, durConf: 3,
|
||
suggested: { value: 90, conf: 2, src: 'tripadvisor.com' },
|
||
price: { amount: 35, cur: '€', conf: 2, src: 'tripadvisor.com' },
|
||
img: ['🍕', 'Trattoria Sostanza', 'linear-gradient(135deg,#b0563c,#7a3a2c)'],
|
||
detail: {
|
||
summary: 'Oltrarno kitchen a short walk across the Arno from the Accademia: Florentine classics, a proper wine list, and a roomy back — the kind of lunch that runs long. Reservations recommended on Saturdays.',
|
||
links: [
|
||
{ label: 'Official site', href: 'https://www.sostanza.it' },
|
||
{ label: 'Menu', href: 'https://www.sostanza.it/menu' },
|
||
{ label: 'TripAdvisor', href: 'https://www.tripadvisor.com/Restaurant_Review-g187791-d559983-Reviews-Trattoria_Sostanza-Florence_Tuscany.html' },
|
||
{ label: 'Reddit r/food', href: 'https://www.reddit.com/r/food/search/?q=sostanza+florence&restrict_sr=1' }
|
||
] } },
|
||
{ id: 'S11', name: 'Oltrarno stroll · San Niccolò', kind: 'visit', slot: 'visit', state: 'planned',
|
||
at: [43.7613, 11.2497], dur: 60, durConf: 3,
|
||
suggested: { value: 60, conf: 1, src: null },
|
||
price: null,
|
||
img: ['⛪', 'Oltrarno', 'linear-gradient(135deg,#8f7a4f,#5c4d2e)'] }
|
||
]
|
||
},
|
||
{ id: 'D3', date: '2026-09-14', label: 'Day 3 · Sun 14',
|
||
startMin: 9 * 60, wakingHours: 11,
|
||
base: { name: 'Hotel Palagio', at: [43.7684, 11.2566] },
|
||
legs: [],
|
||
stops: [
|
||
{ id: 'S12', name: 'Breakfast at the hotel', kind: 'meal', mealKind: 'breakfast',
|
||
slot: 'breakfast', state: 'planned',
|
||
at: [43.7684, 11.2566], dur: 30, durConf: 3,
|
||
suggested: { value: 30, conf: 2, src: 'tripadvisor.com' } },
|
||
{ id: 'S13', name: 'San Marco & cloister', kind: 'visit', slot: 'visit', state: 'planned',
|
||
at: [43.7723, 11.2597], dur: 45, durConf: 3,
|
||
suggested: { value: 45, conf: 1, src: null },
|
||
price: { amount: 8, cur: '€', conf: 1, src: null },
|
||
img: ['🖼️', 'San Marco', 'linear-gradient(135deg,#7a6a4f,#4d422e)'] },
|
||
{ id: 'S14', name: 'Aperitivo — Il Latte', kind: 'meal', mealKind: 'dinner',
|
||
slot: 'dinner', state: 'maybe',
|
||
url: 'https://www.illatte.it',
|
||
at: [43.7700, 11.2560], dur: 60, durConf: 3,
|
||
suggested: { value: 60, conf: 1, src: null },
|
||
price: { amount: 12, cur: '€', conf: 2, src: 'tripadvisor.com' },
|
||
img: ['🥂', 'Il Latte', 'linear-gradient(135deg,#c9a13c,#8f6f1e)'] }
|
||
]
|
||
},
|
||
{ id: 'D4', date: '2026-09-15', label: 'Day 4 · Mon 15', isDeparture: true,
|
||
startMin: 8 * 60, wakingHours: 11,
|
||
base: { name: 'Hotel Palagio', at: [43.7684, 11.2566] },
|
||
legs: [],
|
||
stops: [
|
||
{ id: 'S15', name: 'Breakfast & check-out', kind: 'meal', mealKind: 'breakfast',
|
||
slot: 'breakfast', state: 'planned',
|
||
at: [43.7684, 11.2566], dur: 30, durConf: 3,
|
||
suggested: { value: 30, conf: 2, src: 'tripadvisor.com' } },
|
||
{ id: 'S16', name: 'Train → Pisa Centrale', kind: 'transit', slot: 'transit', state: 'planned',
|
||
at: [43.7726, 11.2597], dur: 30, durConf: 4,
|
||
transit: { name: 'Frecciarossa 9512', ref: 'F-55812',
|
||
from: 'Firenze SMN', to: 'Pisa Centrale',
|
||
depart: '09:12', arrive: '09:58', arriveBy: '08:42',
|
||
buffer: '30 min before departure' },
|
||
suggested: null,
|
||
price: { amount: 45, cur: '€', conf: 4, src: 'booking' },
|
||
img: ['🚄', 'Frecciarossa 9512', 'linear-gradient(135deg,#274b8f,#16294d)'] }
|
||
]
|
||
}
|
||
],
|
||
|
||
// focus-mode candidate pools (what a slot search returns)
|
||
candidates: {
|
||
hotel: [
|
||
{ id: 'H1', name: 'Hotel Palagio', at: [43.7684, 11.2566], price: 180, dur: null,
|
||
tags: ['central', 'quiet', 'refundable'], pitch: 'Where you are now — refundable until the 8th.', url: null },
|
||
{ id: 'H2', name: 'Hotel Savoy', at: [43.7726, 11.2565], price: 210, dur: null,
|
||
tags: ['near SMN', 'grand', 'rooftop'], pitch: 'Grand hotel by the station — handy for the 15th, 10 min from the centre.', url: null },
|
||
{ id: 'H3', name: 'Residenza Oltrarno', at: [43.7604, 11.2510], price: 140, dur: null,
|
||
tags: ['oltrarno', 'small', 'value'], pitch: 'Six rooms above a bookshop — cheaper, and puts you on the south side.', url: null },
|
||
],
|
||
lunch: [
|
||
{ id: 'C1', name: 'Trattoria Mario', at: [43.7667, 11.2544], price: 25, dur: 90,
|
||
tags: ['counter', 'local', 'queue'], pitch: 'No-frills counter since 1954 — the queue is the point.',
|
||
url: 'https://www.trattoriamario.it', img: ['🍝', 'Trattoria Mario', 'linear-gradient(135deg,#d08b3c,#9c5f1e)', 'https://upload.wikimedia.org/wikipedia/commons/1/12/Bistecca_alla_fiorentina-01.jpg'] },
|
||
{ id: 'C2', name: 'Ristorante Santini', at: [43.7646, 11.2528], price: 45, dur: 90,
|
||
tags: ['views', 'terrace', 'splurge'], pitch: '16th-century set tables on the Arno, terrace across from Pitti.',
|
||
url: 'https://www.santini.it', img: ['🍷', 'Santini', 'linear-gradient(135deg,#7a4a5c,#4c2b3a)'] },
|
||
{ id: 'C3', name: 'Trattoria Sostanza', at: [43.7609, 11.2469], price: 35, dur: 90,
|
||
tags: ['oltrarno', 'roomy', 'wine'], pitch: 'Oltrarno kitchen, proper wine list, a roomy back — runs long.',
|
||
url: 'https://www.sostanza.it', img: ['🍕', 'Sostanza', 'linear-gradient(135deg,#b0563c,#7a3a2c)'] },
|
||
{ id: 'C4', name: 'Vendemmia', at: [43.7735, 11.2585], price: 30, dur: 75,
|
||
tags: ['vegetarian', 'garden', 'near SMN'], pitch: 'Garden terrace by SMN, strong vegetarian menu, calmer pace.',
|
||
url: 'https://www.vendemmia.it', img: ['🥗', 'Vendemmia', 'linear-gradient(135deg,#5f9e6b,#33613c)'] },
|
||
{ id: 'C5', name: 'La Cantina di San Niccolò', at: [43.7615, 11.2490], price: 22, dur: 75,
|
||
tags: ['cellar', 'cozy', 'oltrarno'], pitch: 'Stone cellar, candlelight, short honest menu — book ahead.',
|
||
url: 'https://www.lacantina.it', img: ['🕯️', 'La Cantina', 'linear-gradient(135deg,#8f7a4f,#5c4d2e)'] },
|
||
{ id: 'C6', name: 'Buonami Pizza', at: [43.7680, 11.2550], price: 15, dur: 45,
|
||
tags: ['fast', 'casual', 'near hotel'], pitch: 'Two-stop, fast, good — the reset-button lunch.',
|
||
url: 'https://www.buonami.it', img: ['🍕', 'Buonami', 'linear-gradient(135deg,#c98a2c,#8a5f1a)'] }
|
||
],
|
||
visit: [
|
||
{ id: 'V1', name: 'Piazzale Michelangelo', at: [43.7669, 11.2455], price: 0, dur: 60,
|
||
tags: ['views', 'sunset', 'free'], pitch: 'The postcard view — best from 17:00 as the light warms.',
|
||
url: 'https://en.wikipedia.org/wiki/Piazzale_Michelangelo', img: ['🌇', 'Piazzale Michelangelo', 'linear-gradient(135deg,#c97a3c,#8a4f1a)'] },
|
||
{ id: 'V2', name: 'San Miniato al Monte', at: [43.7620, 11.2521], price: 4, dur: 60,
|
||
tags: ['views', 'romanesque', 'calm'], pitch: 'Romanesque basilica on the hill — quiet, cool in the afternoon.',
|
||
url: 'https://en.wikipedia.org/wiki/San_Miniato_al_Monte', img: ['⛪', 'San Miniato', 'linear-gradient(135deg,#8f9a7a,#5c644d)'] },
|
||
{ id: 'V3', name: 'Santo Spirito square', at: [43.7603, 11.2496], price: 0, dur: 45,
|
||
tags: ['square', 'lazier', 'market'], pitch: 'Oltrarno’s lazy square; Saturday’s market is the event.',
|
||
url: 'https://en.wikipedia.org/wiki/Santo_Spirito,_Florence', img: ['☕', 'Santo Spirito', 'linear-gradient(135deg,#a58a6a,#6d5840)'] },
|
||
{ id: 'V4', name: 'Terme di Caracalla (ruins)', at: [43.7589, 11.2707], price: 10, dur: 75,
|
||
tags: ['ruins', 'open', 'afternoon'], pitch: 'Third-century baths in open fields — cool, empty, odd.',
|
||
url: 'https://en.wikipedia.org/wiki/Baths_of_Caracalla', img: ['🏛️', 'Terme di Caracalla', 'linear-gradient(135deg,#b0a58a,#756a4f)'] }
|
||
]
|
||
},
|
||
|
||
nudges: {
|
||
D1: [
|
||
{ id: 'N1', title: 'Lunch may be a little tight',
|
||
body: '45 min at Trattoria Mario — a meal there usually runs <b>~90 min</b> <i>(web)</i>, and the local queue adds to that.',
|
||
fix: { label: 'Extend to ~90 min', stop: 'S4', dur: 90,
|
||
msg: 'Lunch extended to 90 min — everything after it slides later; the day still fits.' } },
|
||
{ id: 'N2', title: 'Pitti: 1 h (you) vs ~2.5 h usually',
|
||
body: 'Guides suggest 2–3 h for the full complex. We kept your 1 h — no need to change anything.',
|
||
fix: { label: 'Keep as is' } }
|
||
],
|
||
D2: [],
|
||
D3: [
|
||
{ id: 'N3', title: 'Dinner is still an idea',
|
||
body: 'Il Latte is an option, not a plan — worth deciding by this evening so there’s a fallback if it’s full.',
|
||
fix: { label: 'Keep as is' } }
|
||
]
|
||
},
|
||
multimodal: [
|
||
{ into: 'S5', dur: 18, sub: [{ mode: 'foot', dur: 6 }, { mode: 'tram', dur: 12 }] }
|
||
],
|
||
vibes: [
|
||
{ id: 'v1', label: 'art & food · relaxed pace' },
|
||
{ id: 'v2', label: 'gardens & walking' },
|
||
{ id: 'v3', label: 'day trip · Fiesole' },
|
||
{ id: 'v4', label: 'views & aperitivo' }
|
||
],
|
||
|
||
suggestions: [
|
||
{ stop: 'S2', pitch: 'The Palazzo Medici’s private apartments — less crowded than the Uffizi, opens right at 9:30.',
|
||
enrich: 'open 09:30–19:30 · skip-the-line available' },
|
||
{ stop: 'S4', pitch: 'No-frills Florentine kitchen the locals queue for. Expect a wait without a reservation.',
|
||
enrich: 'lunch 12:00–14:30 · dinner from 19:30 · ~1 h typically' },
|
||
{ stop: 'S5', pitch: 'Renaissance gardens behind Pitti — a good pace-break in the heat; ~2 h is the sweet spot.',
|
||
enrich: 'open 08:15–19:30 · last entry 18:15' },
|
||
{ stop: 'S7', pitch: 'The step-up lunch: set tables on the Arno, terrace across from Pitti. Worth holding if Mario’s queue looks long.',
|
||
enrich: 'lunch from 12:30 · book ahead in season' }
|
||
]
|
||
};
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Boston — same shapes, but INSIDE the local OSRM extract (NE-US), so the
|
||
// routeClient upgrades legs to real road-network times + geometry.
|
||
// ---------------------------------------------------------------------------
|
||
const BOSTON = {
|
||
trip: {
|
||
id: 'trip-2026-09-b',
|
||
version: 1,
|
||
title: 'Boston 14–16 Sep',
|
||
stays: [
|
||
{ id: 'ST1', name: 'Hotel Commonwealth', at: [42.3495, -71.0960], place: 'Boston',
|
||
checkIn: '2026-09-14', checkOut: '2026-09-16', state: 'booked', price: 165 },
|
||
],
|
||
places: [
|
||
{ id: 'PL1', name: 'Boston', bbox: [42.33, -71.12, 42.375, -71.04],
|
||
center: [42.357, -71.063], vibe: 'history + harbor, food-first',
|
||
dates: ['2026-09-14', '2026-09-16'] }
|
||
],
|
||
bookings: [
|
||
{ type: 'hotel', name: 'Hotel Commonwealth', ref: 'H-55210',
|
||
dates: '14–16 Sep', where: [42.3495, -71.0960], status: 'booked', source: 'user_booking' },
|
||
{ type: 'train', name: 'Amtrak 700', ref: 'A-33421',
|
||
from: 'Back Bay', to: 'Penn Station, NYC', date: '2026-09-16',
|
||
depart: '17:00', arrive: '19:40', status: 'booked', source: 'user_booking',
|
||
stations: { from: [42.3519, -71.0654], to: [40.7506, -73.9935] } }
|
||
]
|
||
},
|
||
days: [
|
||
{ id: 'D1', date: '2026-09-14', label: 'Day 1 · Mon 14',
|
||
startMin: 8 * 60, wakingHours: 11,
|
||
base: { name: 'Hotel Commonwealth', at: [42.3495, -71.0960] },
|
||
legs: [],
|
||
stops: [
|
||
{ id: 'S1', name: 'Breakfast at the hotel', kind: 'meal', mealKind: 'breakfast',
|
||
slot: 'breakfast', state: 'planned',
|
||
at: [42.3495, -71.0960], dur: 30, durConf: 3,
|
||
suggested: { value: 30, conf: 2, src: 'tripadvisor.com' } },
|
||
{ id: 'S2', name: 'Museum of Fine Arts', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://www.mfa.org',
|
||
at: [42.3394, -71.0949], dur: 120, durConf: 3,
|
||
suggested: { value: 150, conf: 2, src: 'mfa.org' },
|
||
price: { amount: 25, cur: '$', conf: 2, src: 'mfa.org' },
|
||
img: ['🖼️', 'MFA Boston', 'linear-gradient(135deg,#7a4a5c,#4c2b3a)',
|
||
'https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/MFA%2C_Boston%2C_MA.jpg/1280px-MFA%2C_Boston%2C_MA.jpg'],
|
||
detail: {
|
||
summary: 'One of the largest art museums in the US, next to the hotel. The Impressionist wing and the Asian galleries are the anchors — allow 2 h for highlights, 3 h if you linger in the Japanese scroll wing. Thursday/Friday the light in the skylit atrium is the best.',
|
||
links: [
|
||
{ label: 'Official site', href: 'https://www.mfa.org' },
|
||
{ label: 'Tickets', href: 'https://www.mfa.org/visit/tickets' },
|
||
{ label: 'TripAdvisor', href: 'https://www.tripadvisor.com/Attraction_Review-g1146335-d183805-Reviews-Museum_of_Fine_Arts-Boston_MA.html' }
|
||
] } },
|
||
{ id: 'S4', name: 'Lunch — State Street Fare', kind: 'meal', mealKind: 'lunch',
|
||
slot: 'lunch', state: 'planned', url: 'https://www.statestreetfare.com',
|
||
at: [42.3410, -71.0935], dur: 60, durConf: 3,
|
||
suggested: { value: 75, conf: 2, src: 'statestreetfare.com' },
|
||
price: { amount: 30, cur: '$', conf: 2, src: 'statestreetfare.com' },
|
||
img: ['🍽️', 'State Street Fare', 'linear-gradient(135deg,#d08b3c,#9c5f1e)'],
|
||
detail: {
|
||
summary: 'The MFA’s own café with a garden terrace — New England seasonal plates. It’s the sensible choice after a museum morning; the terrace gets crowded by 13:00 on weekends.',
|
||
links: [
|
||
{ label: 'Official site', href: 'https://www.statestreetfare.com' },
|
||
{ label: 'Menu', href: 'https://www.statestreetfare.com/menu' }
|
||
] } },
|
||
{ id: 'S5', name: 'Boston Public Library (Coppa Wing)', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://www.bpl.org',
|
||
at: [42.3499, -71.0769], dur: 60, durConf: 3,
|
||
suggested: { value: 60, conf: 2, src: 'bpl.org' },
|
||
price: { amount: 0, cur: '$', conf: 2, src: 'bpl.org' },
|
||
img: ['📚', 'BPL', 'linear-gradient(135deg,#5f7a4f,#3a4f2c)'],
|
||
detail: {
|
||
summary: 'The Beaux-Arts free reading room and the Domitian & Apollo statues in the courtyard. A good 45–60 min breather on the walk toward the North End — the architecture alone is worth it.',
|
||
links: [
|
||
{ label: 'Official site', href: 'https://www.bpl.org' }
|
||
] } },
|
||
{ id: 'S6', name: 'Faneuil Hall & Quincy Market', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://www.boston.gov/departments/parks/faneuil-hall',
|
||
at: [42.3601, -71.0555], dur: 90, durConf: 3,
|
||
suggested: { value: 90, conf: 2, src: 'boston.gov' },
|
||
price: null,
|
||
img: ['🏛️', 'Faneuil Hall', 'linear-gradient(135deg,#b5533c,#7a3a2c)'],
|
||
detail: {
|
||
summary: 'The “Cradle of Liberty” and the covered food market. Best worked top-down: the market stalls first (clam chowder, lemonade), then the hall’s free exhibits. Weekends are busy — September afternoons are kinder.',
|
||
links: [
|
||
{ label: 'Official site', href: 'https://www.boston.gov/departments/parks/faneuil-hall' },
|
||
{ label: 'Quincy Market', href: 'https://www.quincymarket.com' }
|
||
] } }
|
||
]
|
||
},
|
||
{ id: 'D2', date: '2026-09-15', label: 'Day 2 · Tue 15',
|
||
startMin: 8 * 60 + 30, wakingHours: 11,
|
||
base: { name: 'Hotel Commonwealth', at: [42.3495, -71.0960] },
|
||
legs: [],
|
||
stops: [
|
||
{ id: 'S8', name: 'Breakfast at the hotel', kind: 'meal', mealKind: 'breakfast',
|
||
slot: 'breakfast', state: 'planned',
|
||
at: [42.3495, -71.0960], dur: 30, durConf: 3,
|
||
suggested: { value: 30, conf: 2, src: 'tripadvisor.com' } },
|
||
{ id: 'S9', name: 'Paul Revere House', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://www.boston.gov/departments/parks/paul-revere-house',
|
||
at: [42.3616, -71.0631], dur: 45, durConf: 3,
|
||
suggested: { value: 45, conf: 2, src: 'boston.gov' },
|
||
price: { amount: 10, cur: '$', conf: 2, src: 'boston.gov' },
|
||
img: ['🏠', 'Paul Revere House', 'linear-gradient(135deg,#8f7a4f,#5c4d2e)'],
|
||
detail: {
|
||
summary: 'The oldest house in Boston, a tight 30–45 min with the resident docent. Timed entry; the North End around it is the walk.',
|
||
links: [
|
||
{ label: 'Official site', href: 'https://www.boston.gov/departments/parks/paul-revere-house' }
|
||
] } },
|
||
{ id: 'S10', name: 'Lunch — Union Oyster House', kind: 'meal', mealKind: 'lunch',
|
||
slot: 'lunch', state: 'planned', url: 'https://www.unionoysterhouse.com',
|
||
at: [42.3621, -71.0604], dur: 60, durConf: 3,
|
||
suggested: { value: 75, conf: 2, src: 'unionoysterhouse.com' },
|
||
price: { amount: 40, cur: '$', conf: 2, src: 'unionoysterhouse.com' },
|
||
img: ['🦪', 'Union Oyster House', 'linear-gradient(135deg,#4f7a9e,#2c4f6b)'],
|
||
detail: {
|
||
summary: 'Claimed oldest restaurant in the US (1826). Clam chowder and a short, serious menu. Book ahead for the lunch hour — the room is small.',
|
||
links: [
|
||
{ label: 'Official site', href: 'https://www.unionoysterhouse.com' }
|
||
] } },
|
||
{ id: 'S11', name: 'New England Aquarium', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://neaq.org',
|
||
at: [42.3598, -71.0483], dur: 120, durConf: 3,
|
||
suggested: { value: 120, conf: 2, src: 'neaq.org' },
|
||
price: { amount: 35, cur: '$', conf: 2, src: 'neaq.org' },
|
||
img: ['🐋', 'NE Aquarium', 'linear-gradient(135deg,#2f6fd6,#1d4f9c)'],
|
||
detail: {
|
||
summary: 'The whale tank and the Harborwalk beyond it. September is a good time — the new whale migration is winding down but the penguin and jelly exhibits are year-round. Allow 2 h.',
|
||
links: [
|
||
{ label: 'Official site', href: 'https://neaq.org' }
|
||
] } }
|
||
]
|
||
},
|
||
{ id: 'D3', date: '2026-09-16', label: 'Day 3 · Wed 16', isDeparture: true,
|
||
startMin: 8 * 60, wakingHours: 11,
|
||
base: { name: 'Hotel Commonwealth', at: [42.3495, -71.0960] },
|
||
legs: [],
|
||
stops: [
|
||
{ id: 'S15', name: 'Breakfast & check-out', kind: 'meal', mealKind: 'breakfast',
|
||
slot: 'breakfast', state: 'planned',
|
||
at: [42.3495, -71.0960], dur: 30, durConf: 3,
|
||
suggested: { value: 30, conf: 2, src: 'tripadvisor.com' } },
|
||
{ id: 'S12', name: 'Boston Common & Public Garden', kind: 'visit', slot: 'visit', state: 'planned',
|
||
at: [42.3547, -71.0717], dur: 45, durConf: 3,
|
||
suggested: { value: 45, conf: 1, src: null },
|
||
price: null,
|
||
img: ['🌳', 'Public Garden', 'linear-gradient(135deg,#4f9e63,#2c6b40)'] },
|
||
{ id: 'S16', name: 'Train → Penn Station NYC', kind: 'transit', slot: 'transit', state: 'planned',
|
||
at: [42.3519, -71.0654], dur: 30, durConf: 4,
|
||
transit: { name: 'Amtrak 700', ref: 'A-33421',
|
||
from: 'Back Bay', to: 'Penn Station, NYC',
|
||
depart: '17:00', arrive: '19:40', arriveBy: '16:30',
|
||
buffer: '30 min before departure' },
|
||
suggested: null,
|
||
price: { amount: 65, cur: '$', conf: 4, src: 'booking' },
|
||
img: ['🚄', 'Amtrak 700', 'linear-gradient(135deg,#274b8f,#16294d)'] }
|
||
]
|
||
}
|
||
],
|
||
candidates: {
|
||
hotel: [
|
||
{ id: 'H1', name: 'Hotel Commonwealth', at: [42.3495, -71.0960], price: 165, dur: null,
|
||
tags: ['by the mfa', 'quiet', 'refundable'], pitch: 'Where you are now — one block from the MFA, refundable until the 12th.', url: null },
|
||
{ id: 'H2', name: 'The Liberty Hotel', at: [42.3580, -71.0530], price: 240, dur: null,
|
||
tags: ['north end', 'rooftop', 'grand'], pitch: 'Rooftop bar over the North End — closer to the food, pricier.', url: null },
|
||
{ id: 'H3', name: 'Haven Guest House', at: [42.3470, -71.0900], price: 120, dur: null,
|
||
tags: ['value', 'small', 'near mfa'], pitch: 'Six rooms off the MFA’s garden — cheaper, a short walk to everything.', url: null }
|
||
],
|
||
lunch: [
|
||
{ id: 'C1', name: 'State Street Fare', at: [42.3410, -71.0935], price: 30, dur: 75,
|
||
tags: ['by the mfa', 'garden', 'seasonal'], pitch: 'The MFA’s café — garden terrace, New England seasonal plates.',
|
||
url: 'https://www.statestreetfare.com', img: ['🍽️', 'State Street Fare', 'linear-gradient(135deg,#d08b3c,#9c5f1e)'] },
|
||
{ id: 'C2', name: 'Union Oyster House', at: [42.3621, -71.0604], price: 40, dur: 75,
|
||
tags: ['historic', 'oysters', 'book ahead'], pitch: 'Claimed oldest restaurant in the US — clam chowder, a short serious menu.',
|
||
url: 'https://www.unionoysterhouse.com', img: ['🦪', 'Union Oyster', 'linear-gradient(135deg,#4f7a9e,#2c4f6b)'] },
|
||
{ id: 'C3', name: 'Eataly Boston', at: [42.3595, -71.0540], price: 35, dur: 60,
|
||
tags: ['market', 'fast', 'central'], pitch: 'The food-hall option — a dozen kitchens, grab and go, by Quincy Market.',
|
||
url: 'https://boston.eataly.net', img: ['🍕', 'Eataly', 'linear-gradient(135deg,#b0563c,#7a3a2c)'] },
|
||
{ id: 'C4', name: 'Kazuo', at: [42.3540, -71.0620], price: 32, dur: 60,
|
||
tags: ['japanese', 'counter', 'near the common'], pitch: 'Japanese counter near the Common — quiet, good, a little pricier.',
|
||
url: 'https://kazooboston.com', img: ['🍣', 'Kazuo', 'linear-gradient(135deg,#5f6b7a,#3a434f)'] }
|
||
],
|
||
visit: [
|
||
{ id: 'V1', name: 'John F. Kennedy Presidential Library', at: [42.3599, -71.0590], price: 15, dur: 90,
|
||
tags: ['history', 'harbor view', 'indoor'], pitch: 'The JFK archives with a harbor view — a good 90 min, indoor if it turns.',
|
||
url: 'https://www.jfklibrary.org', img: ['🎙️', 'JFK Library', 'linear-gradient(135deg,#4a5a78,#2f3a50)'] },
|
||
{ id: 'V2', name: 'Harborwalk', at: [42.3590, -71.0420], price: 0, dur: 60,
|
||
tags: ['outdoor', 'harbor', 'walk'], pitch: 'The esplanade along the harbor — sunset is the point in September.',
|
||
url: 'https://www.boston.gov/departments/parks/harborwalk', img: ['🌅', 'Harborwalk', 'linear-gradient(135deg,#c97a3c,#8a4f1a)'] },
|
||
{ id: 'V3', name: 'T. F. Green Memorial', at: [42.3530, -71.0470], price: 0, dur: 45,
|
||
tags: ['views', 'free', 'calm'], pitch: 'The memorial at the harbor’s edge — a quiet, photo-friendly 30–45 min.',
|
||
url: 'https://www.boston.gov', img: ['⛵', 'T. F. Green', 'linear-gradient(135deg,#7a8a9e,#4f5a6b)'] },
|
||
{ id: 'V4', name: 'Boston Tea Party Ships & Museum', at: [42.3555, -71.0535], price: 30, dur: 75,
|
||
tags: ['history', 'interactive', 'harbor'], pitch: 'A 75-min interactive re-enactment on the harbor — fun, a little kitsch.',
|
||
url: 'https://www.bostonteachallenge.org', img: ['🫖', 'Tea Party', 'linear-gradient(135deg,#8f4f4f,#5c2f2f)'] }
|
||
]
|
||
},
|
||
nudges: {
|
||
D1: [
|
||
{ id: 'N1', title: 'Lunch may be a little tight',
|
||
body: '60 min at State Street Fare — the terrace lunch usually runs <b>~75 min</b> <i>(web)</i>, and it crowds by 13:00.',
|
||
fix: { label: 'Extend to ~75 min', stop: 'S4', dur: 75,
|
||
msg: 'Lunch extended to 75 min — the afternoon slides a little later; the day still fits.' } },
|
||
{ id: 'N2', title: 'MFA: 2 h (you) vs ~2.5 h usually',
|
||
body: 'Guides suggest 2.5–3 h for the highlights. We kept your 2 h — the Impressionist wing alone runs that long.',
|
||
fix: { label: 'Keep as is' } }
|
||
],
|
||
D2: [
|
||
{ id: 'N3', title: 'Union Oyster House at the lunch hour',
|
||
body: 'The room is small and booked solid 12:00–13:30 — a 12:00 seat beats a 12:30 walk-in.',
|
||
fix: { label: 'Keep as is' } }
|
||
],
|
||
D3: []
|
||
},
|
||
multimodal: [],
|
||
vibes: [
|
||
{ id: 'v1', label: 'history & harbor · relaxed pace' },
|
||
{ id: 'v2', label: 'museums & art' },
|
||
{ id: 'v3', label: 'food-first, North End' },
|
||
{ id: 'v4', label: 'views & sunset walk' }
|
||
],
|
||
suggestions: [
|
||
{ stop: 'S2', pitch: 'The MFA’s Impressionist wing and the Japanese scroll room — 2 h for highlights, 3 h if you linger.',
|
||
enrich: 'open 10:00–17:00 · free first Thu 4–9 · one block from the hotel' },
|
||
{ stop: 'S4', pitch: 'The MFA’s own café — the garden terrace gets crowded by 13:00 on weekends.',
|
||
enrich: 'lunch 12:00–15:00 · ~1 h · terrace seats' },
|
||
{ stop: 'S5', pitch: 'The Beaux-Arts free reading room and the courtyard’s Domitian & Apollo — a good breather toward the North End.',
|
||
enrich: 'open 10:00–18:00 · free · ~45 min' },
|
||
{ stop: 'S6', pitch: 'Work the market stalls first (chowder, lemonade), then the free hall exhibits — weekends are busy.',
|
||
enrich: 'stalls 10:00–17:00 · hall free · ~90 min' }
|
||
]
|
||
};
|
||
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// COLOMBIA · Cartagena → Santa Marta — the working trip. Inside the local
|
||
// walking-profile OSRM extract (:5003, `colombia`), so every on-foot leg
|
||
// upgrades to real road-network times + geometry; the flights are fixed.
|
||
const COLOMBIA = {
|
||
id: 'colombia',
|
||
router: 'colombia',
|
||
trip: {
|
||
id: 'trip-2026-09-col',
|
||
version: 1,
|
||
title: 'Colombia · Cartagena → Santa Marta 21–28 Sep',
|
||
stays: [
|
||
{ id: 'ST1', name: 'Hotel Casa San Antonio', at: [10.3952, -75.5522], place: 'Getsemaní, Cartagena',
|
||
checkIn: '2026-09-21', checkOut: '2026-09-24', state: 'booked', price: 120 },
|
||
{ id: 'ST2', name: 'Hotel Muelle de Bolívar', at: [11.2390, -74.2130], place: 'Centro, Santa Marta',
|
||
checkIn: '2026-09-25', checkOut: '2026-09-28', state: 'booked', price: 150 },
|
||
],
|
||
places: [
|
||
{ id: 'PL1', name: 'Cartagena', bbox: [10.36, -75.62, 10.48, -75.42],
|
||
center: [10.42, -75.52], vibe: 'forts, old town & Caribbean sea',
|
||
dates: ['2026-09-21', '2026-09-25'] },
|
||
{ id: 'PL2', name: 'Santa Marta', bbox: [11.08, -74.27, 11.28, -74.13],
|
||
center: [11.18, -74.20], vibe: 'malecón, muelle & Tayrona',
|
||
dates: ['2026-09-25', '2026-09-28'] },
|
||
],
|
||
bookings: [
|
||
{ type: 'hotel', name: 'Hotel Casa San Antonio', ref: 'C-20117',
|
||
dates: '21–25 Sep', where: [10.3952, -75.5522], status: 'booked', source: 'user_booking' },
|
||
{ type: 'hotel', name: 'Hotel Muelle de Bolívar', ref: 'C-20118',
|
||
dates: '25–28 Sep', where: [11.2390, -74.2130], status: 'booked', source: 'user_booking' },
|
||
{ type: 'flight', name: 'AV 1351', ref: 'AV-88213',
|
||
from: 'Rafael Núñez (CTG)', to: 'Simón Bolívar (SMR)', date: '2026-09-25',
|
||
depart: '08:40', arrive: '09:25', status: 'booked', source: 'user_booking',
|
||
stations: { from: [10.4622, -75.4385], to: [11.1165, -74.2330] } },
|
||
{ type: 'flight', name: 'AV 1352', ref: 'AV-88214',
|
||
from: 'Simón Bolívar (SMR)', to: 'Bogotá (BOG)', date: '2026-09-28',
|
||
depart: '15:10', arrive: '15:55', status: 'booked', source: 'user_booking',
|
||
stations: { from: [11.1165, -74.2330], to: [4.7016, -74.1469] } },
|
||
]
|
||
},
|
||
days: [
|
||
{ id: 'D1', date: '2026-09-21', label: 'Day 1 · Mon 21',
|
||
startMin: 9 * 60, wakingHours: 12,
|
||
base: { name: 'Hotel Casa San Antonio', at: [10.3952, -75.5522] },
|
||
legs: [],
|
||
stops: [
|
||
{ id: 'S1', name: 'Breakfast at the hotel', kind: 'meal', mealKind: 'breakfast',
|
||
slot: 'breakfast', state: 'planned',
|
||
at: [10.3952, -75.5522], dur: 30, durConf: 3,
|
||
suggested: { value: 30, conf: 2, src: 'tripadvisor.com' } },
|
||
{ id: 'S2', name: 'Getsemaní street-art walk', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://en.wikipedia.org/wiki/Getseman%C3%AD,_Cartagena',
|
||
at: [10.3932, -75.5520], dur: 60, durConf: 3,
|
||
suggested: { value: 60, conf: 2, src: 'cartagenatourism.com' },
|
||
price: null,
|
||
img: ['🎨', 'Getsemaní street art', 'linear-gradient(135deg,#c98a3c,#8a5c24)'],
|
||
detail: {
|
||
summary: 'The former port neighbourhood — a hundred walls of murals between narrow lanes. Start at Plaza de los Coches and wander south to the market; mornings are cool and the lanes are empty before 10:00.',
|
||
links: [ { label: 'Getsemaní', href: 'https://en.wikipedia.org/wiki/Getseman%C3%AD,_Cartagena' } ] } },
|
||
{ id: 'S3', name: 'Lunch — La Casona de San Diego', kind: 'meal', mealKind: 'lunch',
|
||
slot: 'lunch', state: 'planned', url: 'https://www.tripadvisor.com',
|
||
at: [10.3940, -75.5545], dur: 75, durConf: 3,
|
||
suggested: { value: 75, conf: 2, src: 'tripadvisor.com' },
|
||
price: { amount: 18, cur: '$', conf: 2, src: 'tripadvisor.com' },
|
||
img: ['🍲', 'La Casona de San Diego', 'linear-gradient(135deg,#3c8f6b,#1f5c44)'],
|
||
detail: {
|
||
summary: 'Caribbean home cooking in a whitewashed casona — sancocho de pescado, mango con arepa. Cash only; the line moves fast at 12:30.',
|
||
links: [ { label: 'TripAdvisor', href: 'https://www.tripadvisor.com' } ] } },
|
||
{ id: 'S4', name: 'Mercado de Getsemaní', kind: 'visit', slot: 'visit', state: 'planned',
|
||
at: [10.3945, -75.5530], dur: 45, durConf: 3,
|
||
suggested: { value: 45, conf: 2, src: null },
|
||
price: null,
|
||
img: ['🥭', 'Mercado de Getsemaní', 'linear-gradient(135deg,#8f6b3c,#5c441f)'],
|
||
detail: {
|
||
summary: 'Fish, fruit and dried herbs stacked to the ceiling — the market the neighbourhood actually uses. A coconut and a fresh juice while you look at the catch is the correct way to spend 45 minutes here.',
|
||
links: [ { label: 'Cartagena tourism', href: 'https://www.cartagenatourism.com' } ] } },
|
||
{ id: 'S5', name: 'Plaza de la Aduana & Cathedral', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://en.wikipedia.org/wiki/Cartagena_Cathedral',
|
||
at: [10.4615, -75.5550], dur: 60, durConf: 3,
|
||
suggested: { value: 60, conf: 2, src: 'cartagenatourism.com' },
|
||
price: null,
|
||
img: ['⛪', 'Catedral de Cartagena', 'linear-gradient(135deg,#8f3c5c,#5c1f3a)'],
|
||
detail: {
|
||
summary: 'The 1594 cathedral is the oldest in Colombia and sits on the square where the old city’s life happens. Golden hour: the facade turns pink and the plaza fills with musicians. Entry is cheap; the belfry stairs are the view.',
|
||
links: [ { label: 'Cartagena Cathedral', href: 'https://en.wikipedia.org/wiki/Cartagena_Cathedral' } ] } }
|
||
]
|
||
},
|
||
{ id: 'D2', date: '2026-09-22', label: 'Day 2 · Tue 22',
|
||
startMin: 8 * 60 + 30, wakingHours: 12,
|
||
base: { name: 'Hotel Casa San Antonio', at: [10.3952, -75.5522] },
|
||
legs: [],
|
||
stops: [
|
||
{ id: 'S6', name: 'Breakfast at the hotel', kind: 'meal', mealKind: 'breakfast',
|
||
slot: 'breakfast', state: 'planned',
|
||
at: [10.3952, -75.5522], dur: 30, durConf: 3,
|
||
suggested: { value: 30, conf: 2, src: 'tripadvisor.com' } },
|
||
{ id: 'S7', name: 'Casa de la Moneda', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://en.wikipedia.org/wiki/Casa_de_la_Moneda_(Cartagena)',
|
||
at: [10.4619, -75.5544], dur: 45, durConf: 3,
|
||
suggested: { value: 45, conf: 2, src: 'cartagenatourism.com' },
|
||
price: { amount: 5, cur: '$', conf: 2, src: 'cartagenatourism.com' },
|
||
img: ['🪙', 'Casa de la Moneda', 'linear-gradient(135deg,#8f8a3c,#5c571f)'],
|
||
detail: {
|
||
summary: 'The colonial mint — the coin-moulding room and the courtyard where the galleons’ silver was counted. Small, cool and fast: 45 minutes is exactly right.',
|
||
links: [ { label: 'Casa de la Moneda', href: 'https://en.wikipedia.org/wiki/Casa_de_la_Moneda_(Cartagena)' } ] } },
|
||
{ id: 'S8', name: 'Palacio de la Inquisición', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://en.wikipedia.org/wiki/Palacio_de_la_Inquisici%C3%B3n_(Cartagena)',
|
||
at: [10.4604, -75.5561], dur: 60, durConf: 3,
|
||
suggested: { value: 60, conf: 2, src: 'cartagenatourism.com' },
|
||
price: { amount: 7, cur: '$', conf: 2, src: 'cartagenatourism.com' },
|
||
img: ['🏛️', 'Palacio de la Inquisición', 'linear-gradient(135deg,#3c5c8f,#1f3a5c)'],
|
||
detail: {
|
||
summary: 'The Inquisition’s 16th-century house — the courtyard fountain, the old interrogation rooms and the museum’s quiet gold room. The 23:00 evening slot with the plaza lit by candles is the famous one; daytime is calm.',
|
||
links: [ { label: 'Palacio de la Inquisición', href: 'https://en.wikipedia.org/wiki/Palacio_de_la_Inquisici%C3%B3n_(Cartagena)' } ] } },
|
||
{ id: 'S9', name: 'San Pedro Claver', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://en.wikipedia.org/wiki/San_Pedro_Claver_Church',
|
||
at: [10.4645, -75.5557], dur: 45, durConf: 3,
|
||
suggested: { value: 45, conf: 2, src: null },
|
||
price: null,
|
||
img: ['🕊️', 'San Pedro Claver', 'linear-gradient(135deg,#7a7a8f,#4f4f61)'],
|
||
detail: {
|
||
summary: 'The whitest church in the old city — and the resting place of Pedro Claver, “apostle of the negroes”. Free, quiet, and the Plaza del Chopo behind it is where the old town’s afternoon slows down.',
|
||
links: [ { label: 'San Pedro Claver', href: 'https://en.wikipedia.org/wiki/San_Pedro_Claver_Church' } ] } },
|
||
{ id: 'S10', name: 'Lunch — La Loma de San Diego', kind: 'meal', mealKind: 'lunch',
|
||
slot: 'lunch', state: 'planned', url: 'https://www.tripadvisor.com',
|
||
at: [10.4590, -75.5530], dur: 75, durConf: 3,
|
||
suggested: { value: 75, conf: 2, src: 'tripadvisor.com' },
|
||
price: { amount: 25, cur: '$', conf: 2, src: 'tripadvisor.com' },
|
||
img: ['🥘', 'La Loma de San Diego', 'linear-gradient(135deg,#c93c3c,#8a1f1f)'],
|
||
detail: {
|
||
summary: 'The old-town institution for arroz con coco and grilled fish — a big table under the patio, and the kitchen is part of the show. Go at 12:15 to skip the tour-group wave.',
|
||
links: [ { label: 'TripAdvisor', href: 'https://www.tripadvisor.com' } ] } },
|
||
{ id: 'S11', name: 'Cerro La Popa — sunset', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://en.wikipedia.org/wiki/Cerro_de_La_Popa',
|
||
at: [10.4257, -75.5523], dur: 75, durConf: 3,
|
||
suggested: { value: 90, conf: 2, src: 'cartagenatourism.com' },
|
||
price: { amount: 10, cur: '$', conf: 2, src: 'cartagenatourism.com' },
|
||
img: ['🌅', 'Cerro La Popa', 'linear-gradient(135deg,#c95c3c,#8a3a1f)'],
|
||
detail: {
|
||
summary: 'The hilltop hermitage over the city — the panoramic terrace is the best single view in Cartagena: the fort, the old town’s pink walls, the Gulf and Bocagrande in one frame. Be up 45 min before sunset or the terrace is elbow to elbow.',
|
||
links: [ { label: 'Cerro La Popa', href: 'https://en.wikipedia.org/wiki/Cerro_de_La_Popa' } ] } }
|
||
]
|
||
},
|
||
{ id: 'D3', date: '2026-09-23', label: 'Day 3 · Wed 23',
|
||
startMin: 8 * 60, wakingHours: 12,
|
||
base: { name: 'Hotel Casa San Antonio', at: [10.3952, -75.5522] },
|
||
legs: [],
|
||
stops: [
|
||
{ id: 'S12', name: 'Breakfast at the hotel', kind: 'meal', mealKind: 'breakfast',
|
||
slot: 'breakfast', state: 'planned',
|
||
at: [10.3952, -75.5522], dur: 30, durConf: 3,
|
||
suggested: { value: 30, conf: 2, src: 'tripadvisor.com' } },
|
||
{ id: 'S13', name: 'Castillo San Felipe', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://www.castillosanfelipe.gov.co',
|
||
at: [10.3930, -75.5565], dur: 90, durConf: 3,
|
||
suggested: { value: 120, conf: 2, src: 'castillosanfelipe.gov.co' },
|
||
price: { amount: 15, cur: '$', conf: 2, src: 'castillosanfelipe.gov.co' },
|
||
img: ['🏰', 'Castillo San Felipe', 'linear-gradient(135deg,#8a8f3c,#565b24)'],
|
||
detail: {
|
||
summary: 'The largest Spanish fort in the Americas — five levels of ramparts, tunnels and cannon lines around the whole peninsula. A full loop takes 2 h; 90 min gets the tunnels and the sea terrace. Go at opening (08:30) for the cold tunnels and no tour buses.',
|
||
links: [
|
||
{ label: 'Castillo San Felipe', href: 'https://www.castillosanfelipe.gov.co' },
|
||
{ label: 'Tickets', href: 'https://www.castillosanfelipe.gov.co/visita' }
|
||
] } },
|
||
{ id: 'S14', name: 'Castillo San Diego', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://en.wikipedia.org/wiki/Castillo_San_Diego',
|
||
at: [10.4247, -75.5512], dur: 75, durConf: 3,
|
||
suggested: { value: 75, conf: 2, src: 'cartagenatourism.com' },
|
||
price: { amount: 8, cur: '$', conf: 2, src: 'cartagenatourism.com' },
|
||
img: ['⚓', 'Castillo San Diego', 'linear-gradient(135deg,#3c8f8a,#1f5c59)'],
|
||
detail: {
|
||
summary: 'The smaller fort guarding the harbour mouth from the other side — the 4th-floor terrace looks straight across to San Felipe. Pairs well as the afternoon half of a fort day.',
|
||
links: [ { label: 'Castillo San Diego', href: 'https://en.wikipedia.org/wiki/Castillo_San_Diego' } ] } },
|
||
{ id: 'S15', name: 'Lunch — Club El Boat', kind: 'meal', mealKind: 'lunch',
|
||
slot: 'lunch', state: 'planned', url: 'https://www.tripadvisor.com',
|
||
at: [10.4355, -75.5375], dur: 75, durConf: 3,
|
||
suggested: { value: 75, conf: 2, src: 'tripadvisor.com' },
|
||
price: { amount: 20, cur: '$', conf: 2, src: 'tripadvisor.com' },
|
||
img: ['🦐', 'Club El Boat', 'linear-gradient(135deg,#3c6b8f,#1f445c)'],
|
||
detail: {
|
||
summary: 'Seafood on the Bocagrande malecón — the langosta is the plate, the sunset the side order. Arrive 12:45 for the table with the water view before the 14:00 heat makes the terrace empty.',
|
||
links: [ { label: 'TripAdvisor', href: 'https://www.tripadvisor.com' } ] } },
|
||
{ id: 'S16', name: 'Malecón de Bocagrande', kind: 'visit', slot: 'visit', state: 'planned',
|
||
at: [10.4365, -75.5390], dur: 60, durConf: 3,
|
||
suggested: { value: 60, conf: 2, src: null },
|
||
price: null,
|
||
img: ['🌊', 'Malecón de Bocagrande', 'linear-gradient(135deg,#4f9ea0,#2c6b6d)'],
|
||
detail: {
|
||
summary: 'The 5 km seawall walk around the Caribbean — the long straight boardwalk is the city’s living room. An hour south of the malecón covers the best stretch without getting sweaty.',
|
||
links: [ { label: 'Bocagrande', href: 'https://en.wikipedia.org/wiki/Bocagrande' } ] } }
|
||
]
|
||
},
|
||
{ id: 'D4', date: '2026-09-24', label: 'Day 4 · Thu 24',
|
||
startMin: 9 * 60, wakingHours: 12,
|
||
base: { name: 'Hotel Casa San Antonio', at: [10.3952, -75.5522] },
|
||
legs: [],
|
||
stops: [
|
||
{ id: 'S17', name: 'Breakfast at the hotel', kind: 'meal', mealKind: 'breakfast',
|
||
slot: 'breakfast', state: 'planned',
|
||
at: [10.3952, -75.5522], dur: 30, durConf: 3,
|
||
suggested: { value: 30, conf: 2, src: 'tripadvisor.com' } },
|
||
{ id: 'S18', name: 'Punta Canoa', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://en.wikipedia.org/wiki/Punta_Canoa',
|
||
at: [10.4185, -75.5255], dur: 90, durConf: 3,
|
||
suggested: { value: 90, conf: 2, src: 'cartagenatourism.com' },
|
||
price: null,
|
||
img: ['🏖️', 'Punta Canoa', 'linear-gradient(135deg,#3cb5c9,#1f7a8a)'],
|
||
detail: {
|
||
summary: 'The old fishermen’s point — beach, hammocks and the best cheap seafood on a bench in the city. September mornings are calm; the water is flat glass before the wind comes off the gulf.',
|
||
links: [ { label: 'Punta Canoa', href: 'https://en.wikipedia.org/wiki/Punta_Canoa' } ] } },
|
||
{ id: 'S19', name: 'Lunch — beachside at Punta Canoa', kind: 'meal', mealKind: 'lunch',
|
||
slot: 'lunch', state: 'planned', url: 'https://www.tripadvisor.com',
|
||
at: [10.4190, -75.5245], dur: 75, durConf: 3,
|
||
suggested: { value: 75, conf: 2, src: 'tripadvisor.com' },
|
||
price: { amount: 15, cur: '$', conf: 2, src: 'tripadvisor.com' },
|
||
img: ['🍤', 'Punta Canoa beach', 'linear-gradient(135deg,#c9803c,#8a541f)'],
|
||
detail: {
|
||
summary: 'Whatever the boat landed this morning — fried whole, with coconut rice and yuca. Point to a table, the price is on the chalkboard, and the sea is the view.',
|
||
links: [ { label: 'TripAdvisor', href: 'https://www.tripadvisor.com' } ] } },
|
||
{ id: 'S20', name: 'Plaza del Chopo — farewell stroll', kind: 'visit', slot: 'visit', state: 'planned',
|
||
at: [10.4638, -75.5560], dur: 60, durConf: 3,
|
||
suggested: { value: 45, conf: 2, src: null },
|
||
price: null,
|
||
img: ['🌇', 'Plaza del Chopo', 'linear-gradient(135deg,#8f3c5c,#5c241f)'],
|
||
detail: {
|
||
summary: 'The old city’s quietest square — a last loop past San Pedro Claver with the light going gold, and one more arepa con queso from the corner stall.',
|
||
links: [ { label: 'Cartagena old town', href: 'https://en.wikipedia.org/wiki/Cartagena' } ] } }
|
||
]
|
||
},
|
||
{ id: 'D5', date: '2026-09-25', label: 'Day 5 · Fri 25',
|
||
startMin: 7 * 60, wakingHours: 11,
|
||
base: { name: 'Hotel Muelle de Bolívar', at: [11.2390, -74.2130] },
|
||
legs: [],
|
||
stops: [
|
||
{ id: 'S21', name: 'Breakfast & check-out', kind: 'meal', mealKind: 'breakfast',
|
||
slot: 'breakfast', state: 'planned',
|
||
at: [10.3952, -75.5522], dur: 45, durConf: 3,
|
||
suggested: { value: 45, conf: 2, src: 'tripadvisor.com' } },
|
||
{ id: 'S22', name: 'Vuelo CTG → SMR', kind: 'transit', slot: 'transit', state: 'planned',
|
||
at: [10.4622, -75.4385], dur: 45, durConf: 4,
|
||
transit: { name: 'AV 1351', ref: 'AV-88213',
|
||
from: 'Rafael Núñez (CTG)', to: 'Simón Bolívar (SMR)',
|
||
depart: '08:40', arrive: '09:25', arriveBy: '07:40',
|
||
buffer: '1 h before departure' },
|
||
suggested: null,
|
||
price: { amount: 89, cur: '$', conf: 4, src: 'booking' },
|
||
img: ['✈️', 'AV 1351', 'linear-gradient(135deg,#274b8f,#16294d)'] },
|
||
{ id: 'S23', name: 'Malecón & Plaza Colesio, Santa Marta', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://en.wikipedia.org/wiki/Santa_Marta',
|
||
at: [11.2425, -74.2140], dur: 60, durConf: 3,
|
||
suggested: { value: 60, conf: 2, src: 'santamarta.gov.co' },
|
||
price: null,
|
||
img: ['🏙️', 'Malecón de Santa Marta', 'linear-gradient(135deg,#3c8f6b,#1f5c44)'],
|
||
detail: {
|
||
summary: 'The city Bolívar died in — the malecón runs from the muelle past Plaza Colesio under the palms. Check in, drop the bags, and walk the sea wall to shake the flight: the Caribbean here is warmer and emptier than Cartagena’s.',
|
||
links: [ { label: 'Santa Marta', href: 'https://en.wikipedia.org/wiki/Santa_Marta' } ] } },
|
||
{ id: 'S24', name: 'Basílica de la Virgen del Perpetuo Socorro', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://en.wikipedia.org/wiki/Bas%C3%ADlica_de_la_Virgen_del_Perpetuo_Socorro',
|
||
at: [11.2420, -74.2152], dur: 30, durConf: 3,
|
||
suggested: { value: 30, conf: 2, src: null },
|
||
price: null,
|
||
img: ['⛪', 'Basílica del Perpetuo Socorro', 'linear-gradient(135deg,#8f8a3c,#5c441f)'],
|
||
detail: {
|
||
summary: 'The city’s most venerated image — the small baroque church on Plaza de la Aduana where the candles never stop. Ten minutes of quiet is enough; the plaza around it is the evening spot.',
|
||
links: [ { label: 'Basílica', href: 'https://en.wikipedia.org/wiki/Bas%C3%ADlica_de_la_Virgen_del_Perpetuo_Socorro' } ] } }
|
||
]
|
||
},
|
||
{ id: 'D6', date: '2026-09-26', label: 'Day 6 · Sat 26',
|
||
startMin: 8 * 60 + 30, wakingHours: 11,
|
||
base: { name: 'Hotel Muelle de Bolívar', at: [11.2390, -74.2130] },
|
||
legs: [],
|
||
stops: [
|
||
{ id: 'S25', name: 'Breakfast at the hotel', kind: 'meal', mealKind: 'breakfast',
|
||
slot: 'breakfast', state: 'planned',
|
||
at: [11.2390, -74.2130], dur: 30, durConf: 3,
|
||
suggested: { value: 30, conf: 2, src: 'tripadvisor.com' } },
|
||
{ id: 'S26', name: 'Casa de Raquel', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://en.wikipedia.org/wiki/Casa_de_Raquel',
|
||
at: [11.2418, -74.2118], dur: 45, durConf: 3,
|
||
suggested: { value: 45, conf: 2, src: 'santamarta.gov.co' },
|
||
price: { amount: 4, cur: '$', conf: 2, src: 'santamarta.gov.co' },
|
||
img: ['📜', 'Casa de Raquel', 'linear-gradient(135deg,#7a5c8f,#4f3a5c)'],
|
||
detail: {
|
||
summary: 'The house of Raquel Méndez — the girl whose love letters made Bolívar’s last years. The small museum upstairs has the original letters; the courtyard is the photo.',
|
||
links: [ { label: 'Casa de Raquel', href: 'https://en.wikipedia.org/wiki/Casa_de_Raquel' } ] } },
|
||
{ id: 'S27', name: 'Lunch — La Terraza del Muelle', kind: 'meal', mealKind: 'lunch',
|
||
slot: 'lunch', state: 'planned', url: 'https://www.tripadvisor.com',
|
||
at: [11.2375, -74.2140], dur: 75, durConf: 3,
|
||
suggested: { value: 75, conf: 2, src: 'tripadvisor.com' },
|
||
price: { amount: 20, cur: '$', conf: 2, src: 'tripadvisor.com' },
|
||
img: ['🐟', 'La Terraza del Muelle', 'linear-gradient(135deg,#3c6b8f,#1f445c)'],
|
||
detail: {
|
||
summary: 'Grilled fish on the terrace over the working harbour — the boats come in around noon and the menu follows the catch. The shrimp ceviche is the safe first order.',
|
||
links: [ { label: 'TripAdvisor', href: 'https://www.tripadvisor.com' } ] } },
|
||
{ id: 'S28', name: 'El Muelle & fish market', kind: 'visit', slot: 'visit', state: 'planned',
|
||
at: [11.2360, -74.2150], dur: 45, durConf: 3,
|
||
suggested: { value: 45, conf: 2, src: null },
|
||
price: null,
|
||
img: ['⚓', 'El Muelle de Santa Marta', 'linear-gradient(135deg,#5c6b8f,#3a445c)'],
|
||
detail: {
|
||
summary: 'The 19th-century stone pier and the market behind it — ice, line-caught fish, and the same crews who have run these boats for a century. The best 45 minutes in the city if you like to watch work happen.',
|
||
links: [ { label: 'El Muelle', href: 'https://en.wikipedia.org/wiki/El_Muelle_(Santa_Marta)' } ] } },
|
||
{ id: 'S29', name: 'Parque de los Novios', kind: 'visit', slot: 'visit', state: 'planned',
|
||
at: [11.2395, -74.2085], dur: 45, durConf: 3,
|
||
suggested: { value: 45, conf: 2, src: 'santamarta.gov.co' },
|
||
price: null,
|
||
img: ['💑', 'Parque de los Novios', 'linear-gradient(135deg,#6b8f4f,#445c2c)'],
|
||
detail: {
|
||
summary: 'The lakeside park where the city goes at dusk — the lagoon, the couples (it is in the name), and the walk back along the water to the hotel.',
|
||
links: [ { label: 'Santa Marta parks', href: 'https://santamarta.gov.co' } ] } }
|
||
]
|
||
},
|
||
{ id: 'D7', date: '2026-09-27', label: 'Day 7 · Sun 27',
|
||
startMin: 7 * 60 + 30, wakingHours: 12,
|
||
base: { name: 'Hotel Muelle de Bolívar', at: [11.2390, -74.2130] },
|
||
legs: [],
|
||
stops: [
|
||
{ id: 'S30', name: 'Breakfast at the hotel', kind: 'meal', mealKind: 'breakfast',
|
||
slot: 'breakfast', state: 'planned',
|
||
at: [11.2390, -74.2130], dur: 30, durConf: 3,
|
||
suggested: { value: 30, conf: 2, src: 'tripadvisor.com' } },
|
||
{ id: 'S31', name: 'Bus → Tayrona (El Croado)', kind: 'transit', slot: 'transit', state: 'planned',
|
||
at: [11.1975, -74.1760], dur: 40, durConf: 3,
|
||
transit: { name: 'Bus Centro → El Croado', ref: 'TAY-01',
|
||
from: 'Santa Marta Centro', to: 'Parque Tayrona, El Croado',
|
||
depart: '08:30', arrive: '09:10', arriveBy: '08:30',
|
||
buffer: 'park gate opens 08:00' },
|
||
suggested: null,
|
||
price: { amount: 4, cur: '$', conf: 3, src: 'parquetayrona.gov.co' },
|
||
img: ['🚌', 'Bus to Tayrona', 'linear-gradient(135deg,#8f6b3c,#5c441f)'] },
|
||
{ id: 'S32', name: 'Playa Cangrejos', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://parquetayrona.gov.co',
|
||
at: [11.1765, -74.1690], dur: 60, durConf: 3,
|
||
suggested: { value: 60, conf: 2, src: 'parquetayrona.gov.co' },
|
||
price: { amount: 15, cur: '$', conf: 3, src: 'parquetayrona.gov.co' },
|
||
img: ['🌴', 'Playa Cangrejos', 'linear-gradient(135deg,#3cb5c9,#1f5c44)'],
|
||
detail: {
|
||
summary: 'The first beach on the park walk — jungle right up to the sand line, and the water so clear it looks edited. Two hours here is a long, correct rest after the walk in.',
|
||
links: [ { label: 'Parque Tayrona', href: 'https://parquetayrona.gov.co' } ] } },
|
||
{ id: 'S33', name: 'Cabo San Juan', kind: 'visit', slot: 'visit', state: 'planned',
|
||
url: 'https://parquetayrona.gov.co',
|
||
at: [11.1390, -74.1455], dur: 120, durConf: 3,
|
||
suggested: { value: 120, conf: 2, src: 'parquetayrona.gov.co' },
|
||
price: null,
|
||
img: ['🏝️', 'Cabo San Juan', 'linear-gradient(135deg,#c95c8a,#8a1f5c)'],
|
||
detail: {
|
||
summary: 'The park’s far tip — the 2.5 km beach walk from Cangrejos is the trail: sand underfoot, jungle walls, the headland where the Caribbean hits the Sierra Nevada. September crowd levels are thin; the last boats out run 15:30, so turn around by 14:00.',
|
||
links: [ { label: 'Parque Tayrona', href: 'https://parquetayrona.gov.co' } ] } }
|
||
]
|
||
},
|
||
{ id: 'D8', date: '2026-09-28', label: 'Day 8 · Mon 28', isDeparture: true,
|
||
startMin: 9 * 60, wakingHours: 6,
|
||
base: { name: 'Hotel Muelle de Bolívar', at: [11.2390, -74.2130] },
|
||
legs: [],
|
||
stops: [
|
||
{ id: 'S34', name: 'Breakfast & check-out', kind: 'meal', mealKind: 'breakfast',
|
||
slot: 'breakfast', state: 'planned',
|
||
at: [11.2390, -74.2130], dur: 45, durConf: 3,
|
||
suggested: { value: 45, conf: 2, src: 'tripadvisor.com' } },
|
||
{ id: 'S35', name: 'Vuelo SMR → BOG', kind: 'transit', slot: 'transit', state: 'planned',
|
||
at: [11.1165, -74.2330], dur: 45, durConf: 4,
|
||
transit: { name: 'AV 1352', ref: 'AV-88214',
|
||
from: 'Simón Bolívar (SMR)', to: 'Bogotá (BOG)',
|
||
depart: '15:10', arrive: '15:55', arriveBy: '14:10',
|
||
buffer: '1 h before departure' },
|
||
suggested: null,
|
||
price: { amount: 95, cur: '$', conf: 4, src: 'booking' },
|
||
img: ['✈️', 'AV 1352', 'linear-gradient(135deg,#274b8f,#16294d)'] }
|
||
]
|
||
}
|
||
],
|
||
candidates: {
|
||
hotel: [
|
||
{ id: 'H1', name: 'Hotel Casa San Antonio', at: [10.3952, -75.5522], price: 120, dur: null,
|
||
tags: ['Getsemaní', 'colonial casona', 'roof terrace'], pitch: 'Where you are now — a whitewashed casona in Getsemaní with a terrace over the murals.', url: 'https://www.tripadvisor.com' },
|
||
{ id: 'H2', name: 'Hotel Casa 1800', at: [10.4606, -75.5547], price: 260, dur: null,
|
||
tags: ['old town', 'design', 'pool'], pitch: 'In the old town instead — the 19th-century palace turned design hotel; pricier, but you skip the walk entirely.', url: 'https://www.casa1800.com' },
|
||
{ id: 'H3', name: 'Villa El Banderito', at: [10.4340, -75.5365], price: 140, dur: null,
|
||
tags: ['Bocagrande', 'beachfront', 'quiet'], pitch: 'On the Bocagrande sand — wake up at the water; a 15-min tuktuk from Getsemaní.', url: 'https://www.tripadvisor.com' }
|
||
],
|
||
lunch: [
|
||
{ id: 'C1', name: 'La Casona de San Diego', at: [10.3940, -75.5545], price: 18, dur: 75,
|
||
tags: ['caribbean', 'getsemaní', 'cash only'], pitch: 'Sancocho and mango con arepa in a whitewashed casona — the neighbourhood’s own lunch.',
|
||
url: 'https://www.tripadvisor.com', img: ['🍲', 'La Casona', 'linear-gradient(135deg,#3c8f6b,#1f5c44)'] },
|
||
{ id: 'C2', name: 'La Loma de San Diego', at: [10.4590, -75.5530], price: 25, dur: 75,
|
||
tags: ['old town', 'arroz con coco', 'institution'], pitch: 'The old-town classic — big patio table, kitchen as theatre, go at 12:15.',
|
||
url: 'https://www.tripadvisor.com', img: ['🥘', 'La Loma', 'linear-gradient(135deg,#c93c3c,#8a1f1f)'] },
|
||
{ id: 'C3', name: 'Club El Boat', at: [10.4355, -75.5375], price: 20, dur: 90,
|
||
tags: ['bocagrande', 'seafood', 'sunset'], pitch: 'Langosta on the malecón — the sunset is the side order.',
|
||
url: 'https://www.tripadvisor.com', img: ['🦐', 'El Boat', 'linear-gradient(135deg,#3c6b8f,#1f445c)'] },
|
||
{ id: 'C4', name: 'La Terraza del Muelle', at: [11.2375, -74.2140], price: 20, dur: 75,
|
||
tags: ['santa marta', 'harbour', 'catch of the day'], pitch: 'Grilled fish over the working pier — the boats set the menu.',
|
||
url: 'https://www.tripadvisor.com', img: ['🐟', 'Terraza del Muelle', 'linear-gradient(135deg,#3c6b8f,#1f445c)'] }
|
||
],
|
||
visit: [
|
||
{ id: 'V1', name: 'Playa Bocagrande', at: [10.4330, -75.5340], price: 0, dur: 90,
|
||
tags: ['beach', 'free', 'swim'], pitch: 'The city beach — a proper swim and a hammock, ten minutes from the old town by tuktuk.',
|
||
url: 'https://en.wikipedia.org/wiki/Bocagrande', img: ['🏖️', 'Bocagrande', 'linear-gradient(135deg,#3cb5c9,#1f7a8a)'] },
|
||
{ id: 'V2', name: 'Plaza Peñol', at: [10.4632, -75.5570], price: 0, dur: 30,
|
||
tags: ['free', 'old town', 'shades'], pitch: 'The old town’s leafy pause — the black umbrellas and the shade are the whole point.',
|
||
url: 'https://en.wikipedia.org/wiki/Cartagena', img: ['☂️', 'Plaza Peñol', 'linear-gradient(135deg,#4f7a4f,#2c4f2c)'] },
|
||
{ id: 'V3', name: 'Iglesia de la Popa', at: [10.4253, -75.5530], price: 10, dur: 30,
|
||
tags: ['view', 'hilltop', 'sunset'], pitch: 'The church itself in 15 min — the terrace does the rest.',
|
||
url: 'https://en.wikipedia.org/wiki/Cerro_de_La_Popa', img: ['⛪', 'Iglesia de la Popa', 'linear-gradient(135deg,#7a7a8f,#4f4f61)'] },
|
||
{ id: 'V4', name: 'Playa Cocal, Tayrona', at: [11.1650, -74.1620], price: 0, dur: 60,
|
||
tags: ['tayrona', 'beach', 'jungle'], pitch: 'The quieter of the two main Tayrona beaches — the jungle wall is closer to the sand here.',
|
||
url: 'https://parquetayrona.gov.co', img: ['🌴', 'Playa Cocal', 'linear-gradient(135deg,#4f9e63,#2c6b40)'] },
|
||
{ id: 'V5', name: 'Cerro de La Popa (Santa Marta)', at: [11.2460, -74.2020], price: 2, dur: 60,
|
||
tags: ['view', 'santa marta', 'sunset'], pitch: 'The hilltop over Santa Marta — city, gulf and the Sierra Nevada in one frame.',
|
||
url: 'https://en.wikipedia.org/wiki/Santa_Marta', img: ['🌄', 'Cerro La Popa', 'linear-gradient(135deg,#c95c3c,#8a3a1f)'] }
|
||
]
|
||
},
|
||
nudges: {
|
||
D1: [
|
||
{ id: 'N1', title: 'Getsemaní is best before 10:00',
|
||
body: 'The street-art lanes fill with tour groups by late morning. Your 09:30 start is the right call — keep it.',
|
||
fix: { label: 'Keep as is' } }
|
||
],
|
||
D3: [
|
||
{ id: 'N2', title: 'Two forts in a day is a lot of stairs',
|
||
body: 'Castillo San Diego runs <b>~75 min</b> for the terrace-and-bastion loop <i>(web)</b>; 90 min if you take the rampart walk. As is, you’ll be tight but fine.',
|
||
fix: { label: 'Extend to ~90 min', stop: 'S14', dur: 90,
|
||
msg: 'San Diego extended to 90 min — the malecón stroll slides a little later; the day still fits.' } }
|
||
],
|
||
D7: [
|
||
{ id: 'N3', title: 'Tayrona: water, sunscreen, and the 15:30 boats',
|
||
body: 'The Cangrejos → Cabo San Juan stretch is <b>2.5 km of beach, no shade and no vendors</b>. The last boats out run 15:30 — your 14:00 turnaround is correct.',
|
||
fix: { label: 'Keep as is' } }
|
||
],
|
||
D4: [], D5: [], D6: [], D8: []
|
||
},
|
||
multimodal: [
|
||
{ into: 'S22', dur: 30, sub: [ { mode: 'car', dur: 25 } ] }, // taxi Getsemaní → CTG airport
|
||
{ into: 'S23', dur: 25, sub: [ { mode: 'car', dur: 20 } ] }, // taxi SMR → hotel
|
||
{ into: 'S31', dur: 40, sub: [ { mode: 'bus', dur: 35 } ] }, // bus Centro → Tayrona
|
||
{ into: 'S35', dur: 25, sub: [ { mode: 'car', dur: 20 } ] } // taxi hotel → SMR
|
||
],
|
||
vibes: [
|
||
{ id: 'v1', label: 'forts & old town' },
|
||
{ id: 'v2', label: 'Caribbean beaches & malecón' },
|
||
{ id: 'v3', label: 'street art (Getsemaní)' },
|
||
{ id: 'v4', label: 'Tayrona day trip' },
|
||
{ id: 'v5', label: 'Caribbean food' }
|
||
],
|
||
suggestions: [
|
||
{ stop: 'S2', pitch: 'A hundred walls of murals between narrow lanes — start at Plaza de los Coches and wander to the market.',
|
||
enrich: 'free · best before 10:00 · ~60 min' },
|
||
{ stop: 'S13', pitch: 'Five levels of ramparts, tunnels and cannon lines — go at opening (08:30) for the cold tunnels and no tour buses.',
|
||
enrich: 'open 08:30 · ~$15 · 90–120 min' },
|
||
{ stop: 'S11', pitch: 'The best single view in Cartagena — be on the terrace 45 min before sunset.',
|
||
enrich: 'open 09:00–18:00 · ~$10' },
|
||
{ stop: 'S33', pitch: 'Sand underfoot, jungle walls, the headland where the Caribbean hits the Sierra Nevada. Last boats out 15:30.',
|
||
enrich: 'park 08:00–16:00 · entry ~$15 · 2.5 km beach walk' }
|
||
]
|
||
};
|
||
// ---------------- trip registry (multi-trip) ----------------
|
||
// Each trip is a full dataset. The app keeps per-trip state in
|
||
// localStorage (see app.js), so several trips can be worked on in parallel.
|
||
window.TRIPS = {
|
||
colombia: Object.assign({}, COLOMBIA),
|
||
boston: Object.assign({ id: 'boston' }, BOSTON),
|
||
florence: Object.assign({ id: 'florence' }, FLORENCE),
|
||
};
|
||
// ?trip= (legacy: ?city=) picks the starting trip; default: the one you're working on
|
||
const _city = ((new URLSearchParams(location.search).get('trip'))
|
||
|| (new URLSearchParams(location.search).get('city'))
|
||
|| 'colombia').toLowerCase();
|
||
window.MOCK = window.TRIPS[_city] || window.TRIPS.colombia;
|
||
window.MOCK_CITY = window.MOCK.id;
|