SPB Git

spb/voyage2026

Public

chore(retrait cluster): synchro copie du nœud M3U96b + README « URL live hors fonction » (2026-09-04)

Simon-Pierre Boucher committed (Sep 4, 2026) Browse files

4 changed files +728 −0

added .gitignore +10 −0
@@ -0,0 +1,10 @@
1+node_modules/
2+.next/
3+dist/
4+.env
5+.env.*
6+!.env.example
7+*.db*
8+*.log
9+.DS_Store
10+data/models/
added README.md +4 −0
@@ -0,0 +1,4 @@
1+> ⚠️ **URL live hors fonction pour le moment.** L'application a été retirée du cluster MacLustr le 2026-09-04 (processus arrêtés, copie du nœud supprimée). Ce dépôt spbgit est désormais la seule source de vérité du projet. Ancienne URL : https://www.voyage2026toronto.com
2+
3+# voyage2026
4+
added itineraire-toronto-2026.html +662 −0
@@ -0,0 +1,662 @@
1+<!DOCTYPE html>
2+<html lang="fr">
3+<head>
4+<meta charset="UTF-8">
5+<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+<title>Erika ♥ SP · Road Trip Québec → Toronto · Ed Sheeran LOOP Tour · 17–24 août 2026</title>
7+<meta name="description" content="Itinéraire complet du road trip Québec–Toronto pour le Ed Sheeran LOOP Tour au Rogers Centre, 17 au 24 août 2026.">
8+<link rel="preconnect" href="https://fonts.googleapis.com">
9+<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10+<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;600;700&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
11+<style>
12+ :root {
13+ --bg: #0b0d14;
14+ --bg-2: #11141f;
15+ --card: #161a28;
16+ --card-2: #1c2133;
17+ --ink: #f2f4fa;
18+ --ink-soft: #9aa3ba;
19+ --line: rgba(255,255,255,.08);
20+ --orange: #ff6b2c;
21+ --pink: #ff2e88;
22+ --violet: #7c4dff;
23+ --teal: #2dd4bf;
24+ --grad: linear-gradient(100deg, #ff6b2c, #ff2e88 45%, #7c4dff);
25+ --radius: 22px;
26+ }
27+ * { margin: 0; padding: 0; box-sizing: border-box; }
28+ html { scroll-behavior: smooth; }
29+ body {
30+ font-family: "Inter", -apple-system, sans-serif;
31+ background: var(--bg);
32+ color: var(--ink);
33+ line-height: 1.65;
34+ overflow-x: hidden;
35+ }
36+ h1, h2, h3, .num, .cd-num { font-family: "Space Grotesk", "Inter", sans-serif; }
37+ .wrap { max-width: 1020px; margin: 0 auto; padding: 0 24px; }
38+
39+ /* ---------- STICKY NAV ---------- */
40+ .nav {
41+ position: fixed; top: 0; left: 0; right: 0; z-index: 50;
42+ background: rgba(11,13,20,.72); backdrop-filter: blur(14px);
43+ border-bottom: 1px solid var(--line);
44+ }
45+ .nav-inner {
46+ max-width: 1020px; margin: 0 auto; padding: 12px 24px;
47+ display: flex; align-items: center; gap: 16px;
48+ }
49+ .nav .logo { font-weight: 800; font-size: 15px; letter-spacing: .02em; white-space: nowrap; }
50+ .nav .logo span { background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; }
51+ .nav-days { display: flex; gap: 4px; margin-left: auto; overflow-x: auto; scrollbar-width: none; }
52+ .nav-days::-webkit-scrollbar { display: none; }
53+ .nav-days a {
54+ color: var(--ink-soft); text-decoration: none; font-size: 13px; font-weight: 600;
55+ padding: 6px 12px; border-radius: 999px; white-space: nowrap; transition: all .2s;
56+ }
57+ .nav-days a:hover { color: #fff; background: rgba(255,255,255,.08); }
58+ .nav-days a.hot { color: #fff; background: linear-gradient(100deg, #ff6b2c, #ff2e88); }
59+
60+ /* ---------- HERO ---------- */
61+ .hero {
62+ position: relative; min-height: 92vh;
63+ display: flex; align-items: flex-end;
64+ isolation: isolate; overflow: hidden;
65+ }
66+ .hero-bg {
67+ position: absolute; inset: -6%;
68+ background: url("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3c/Sunset_Toronto_Skyline_Panorama_Crop_from_Snake_Island.jpg/1920px-Sunset_Toronto_Skyline_Panorama_Crop_from_Snake_Island.jpg") center 62% / cover no-repeat;
69+ z-index: -2; animation: kenburns 26s ease-in-out infinite alternate;
70+ }
71+ @keyframes kenburns { from { transform: scale(1); } to { transform: scale(1.09) translateY(-1.5%); } }
72+ .hero::after {
73+ content: ""; position: absolute; inset: 0; z-index: -1;
74+ background:
75+ radial-gradient(120% 70% at 70% 10%, transparent 40%, rgba(11,13,20,.55) 100%),
76+ linear-gradient(180deg, rgba(11,13,20,.45) 0%, rgba(11,13,20,.35) 45%, var(--bg) 100%);
77+ }
78+ .hero-inner { position: relative; width: 100%; max-width: 1020px; margin: 0 auto; padding: 140px 24px 72px; }
79+ .kicker {
80+ display: inline-flex; align-items: center; gap: 10px;
81+ text-transform: uppercase; letter-spacing: .3em; font-size: 12px; font-weight: 700;
82+ color: #ffd9c4; margin-bottom: 18px;
83+ }
84+ .kicker::before { content: ""; width: 34px; height: 2px; background: var(--grad); border-radius: 2px; }
85+ .hero h1 {
86+ font-size: clamp(40px, 7.5vw, 84px); font-weight: 700; line-height: 1.02;
87+ letter-spacing: -.02em; margin-bottom: 14px;
88+ }
89+ .hero h1 .grad {
90+ background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent;
91+ background-size: 200% 100%; animation: shine 6s linear infinite;
92+ }
93+ @keyframes shine { to { background-position: 200% 0; } }
94+ .hero .sub { font-size: clamp(16px, 2.2vw, 20px); color: #d5daea; max-width: 640px; }
95+ .badges { margin-top: 26px; display: flex; flex-wrap: wrap; gap: 10px; }
96+ .badge {
97+ background: rgba(255,255,255,.08); backdrop-filter: blur(8px);
98+ border: 1px solid rgba(255,255,255,.18); border-radius: 999px;
99+ padding: 8px 18px; font-size: 14px; font-weight: 600;
100+ }
101+ .badge.hot { background: linear-gradient(100deg, rgba(255,107,44,.9), rgba(255,46,136,.9)); border-color: transparent; }
102+
103+ /* ---------- ERIKA + SP ---------- */
104+ .lovers {
105+ display: inline-flex; align-items: center; gap: 12px;
106+ margin: 6px 0 16px;
107+ font-family: "Space Grotesk", "Inter", sans-serif;
108+ font-size: clamp(19px, 2.8vw, 26px); font-weight: 700; letter-spacing: .01em;
109+ }
110+ .lovers .name { background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; }
111+ .lovers .heart {
112+ display: inline-block; color: #ff2e88; font-size: 1.15em; line-height: 1;
113+ animation: heartbeat 1.5s ease-in-out infinite;
114+ filter: drop-shadow(0 0 10px rgba(255,46,136,.55));
115+ }
116+ @keyframes heartbeat {
117+ 0%, 100% { transform: scale(1); }
118+ 14% { transform: scale(1.3); }
119+ 28% { transform: scale(1); }
120+ 42% { transform: scale(1.22); }
121+ 56% { transform: scale(1); }
122+ }
123+
124+ /* ---------- COUNTDOWN ---------- */
125+ .countdown { margin-top: 34px; display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
126+ .cd-label { font-size: 13px; text-transform: uppercase; letter-spacing: .18em; color: #ffd9c4; font-weight: 700; width: 100%; }
127+ .cd-box {
128+ min-width: 86px; text-align: center; padding: 14px 10px 10px;
129+ background: rgba(255,255,255,.07); backdrop-filter: blur(10px);
130+ border: 1px solid rgba(255,255,255,.16); border-radius: 16px;
131+ }
132+ .cd-num { font-size: 34px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
133+ .cd-unit { font-size: 11px; text-transform: uppercase; letter-spacing: .14em; color: var(--ink-soft); margin-top: 6px; }
134+
135+ /* ---------- STATS ---------- */
136+ .stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-top: -10px; position: relative; z-index: 2; }
137+ .stat {
138+ background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
139+ padding: 20px; text-align: center; transition: transform .25s, border-color .25s;
140+ }
141+ .stat:hover { transform: translateY(-4px); border-color: rgba(255,107,44,.5); }
142+ .stat .num { font-size: 28px; font-weight: 700; background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; }
143+ .stat .lbl { font-size: 12px; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .1em; margin-top: 2px; }
144+
145+ /* ---------- ROUTE STRIP ---------- */
146+ .route-strip {
147+ margin: 30px 0 0; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
148+ padding: 22px 26px; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; justify-content: center;
149+ font-weight: 700; font-size: 15px;
150+ }
151+ .route-strip .city { color: var(--ink); }
152+ .route-strip .leg { color: var(--ink-soft); font-weight: 500; font-size: 12.5px; padding: 0 8px; position: relative; }
153+
154+ /* ---------- SECTIONS ---------- */
155+ h2.section {
156+ font-size: clamp(24px, 3.4vw, 34px); font-weight: 700; letter-spacing: -.01em;
157+ margin: 72px 0 8px; display: flex; align-items: center; gap: 14px;
158+ }
159+ h2.section::after { content: ""; flex: 1; height: 1px; background: linear-gradient(90deg, rgba(255,107,44,.6), transparent); }
160+ .section-sub { color: var(--ink-soft); margin-bottom: 30px; max-width: 720px; }
161+
162+ /* ---------- DAY CARDS ---------- */
163+ .day {
164+ background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
165+ overflow: hidden; margin-bottom: 40px; scroll-margin-top: 90px;
166+ transition: border-color .3s;
167+ }
168+ .day:hover { border-color: rgba(255,255,255,.2); }
169+ .day-photo { height: 340px; overflow: hidden; position: relative; }
170+ .day-photo .img {
171+ position: absolute; inset: 0; background-size: cover; background-position: center;
172+ transition: transform .8s cubic-bezier(.2,.6,.2,1);
173+ }
174+ .day:hover .day-photo .img { transform: scale(1.06); }
175+ .day-photo::after {
176+ content: ""; position: absolute; inset: 0;
177+ background: linear-gradient(180deg, rgba(11,13,20,.15), transparent 35%, transparent 70%, rgba(22,26,40,.9));
178+ pointer-events: none;
179+ }
180+ .day-photo .tag {
181+ position: absolute; top: 18px; left: 18px; z-index: 2;
182+ background: rgba(11,13,20,.7); backdrop-filter: blur(8px); color: #fff;
183+ border: 1px solid rgba(255,255,255,.2);
184+ padding: 8px 18px; border-radius: 999px; font-size: 13px; font-weight: 800; letter-spacing: .08em;
185+ }
186+ .day-photo .drive {
187+ position: absolute; bottom: 18px; right: 18px; z-index: 2;
188+ background: rgba(255,255,255,.92); color: #10131d;
189+ padding: 8px 16px; border-radius: 999px; font-size: 13px; font-weight: 700;
190+ }
191+ .day-body { padding: 30px 34px 34px; }
192+ .day-body h3 { font-size: 24px; font-weight: 700; letter-spacing: -.01em; margin-bottom: 2px; }
193+ .day-body .date {
194+ color: var(--orange); font-weight: 800; font-size: 13px;
195+ text-transform: uppercase; letter-spacing: .14em; margin-bottom: 16px;
196+ }
197+ .timeline { list-style: none; margin: 14px 0 4px; }
198+ .timeline li {
199+ display: grid; grid-template-columns: 92px 1fr; gap: 16px;
200+ padding: 10px 0; border-bottom: 1px dashed var(--line); align-items: start;
201+ }
202+ .timeline li:last-child { border-bottom: none; }
203+ .timeline .t { font-weight: 800; color: var(--teal); font-size: 14px; padding-top: 2px; white-space: nowrap; font-variant-numeric: tabular-nums; }
204+ .timeline .d { color: #cdd3e4; }
205+ .timeline .d strong { color: #fff; }
206+ .timeline .d em { color: #ffb38a; font-style: normal; font-weight: 600; }
207+ .chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
208+ .chip {
209+ font-size: 13px; font-weight: 600; padding: 7px 15px; border-radius: 999px;
210+ background: rgba(45,212,191,.1); color: var(--teal); border: 1px solid rgba(45,212,191,.3);
211+ }
212+ .chip.hotel { background: rgba(255,107,44,.12); color: #ffa06b; border-color: rgba(255,107,44,.35); }
213+ .tip {
214+ margin-top: 18px; background: rgba(250,204,21,.08); border: 1px solid rgba(250,204,21,.3);
215+ border-radius: 14px; padding: 13px 17px; font-size: 14px; color: #fde68a;
216+ }
217+ .maplink {
218+ display: inline-flex; align-items: center; gap: 8px; margin-top: 18px;
219+ font-size: 14px; font-weight: 700; color: var(--teal); text-decoration: none;
220+ padding: 9px 18px; border: 1px solid rgba(45,212,191,.35); border-radius: 999px;
221+ transition: all .2s;
222+ }
223+ .maplink:hover { background: rgba(45,212,191,.12); transform: translateX(3px); }
224+
225+ /* ---------- CONCERT SPOTLIGHT ---------- */
226+ .concert { position: relative; border: none; }
227+ .concert::before {
228+ content: ""; position: absolute; inset: 0; border-radius: var(--radius); padding: 2px;
229+ background: var(--grad); background-size: 300% 100%; animation: shine 5s linear infinite;
230+ -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
231+ -webkit-mask-composite: xor; mask-composite: exclude;
232+ pointer-events: none; z-index: 3;
233+ }
234+ .concert-banner {
235+ background: var(--grad); background-size: 300% 100%; animation: shine 5s linear infinite;
236+ color: #fff; text-align: center; padding: 12px; font-weight: 800; letter-spacing: .16em;
237+ text-transform: uppercase; font-size: 14px;
238+ }
239+ .concert .day-photo .tag { background: linear-gradient(100deg, #ff6b2c, #ff2e88); border-color: transparent; }
240+ .concert-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-top: 20px; }
241+ .concert-fact {
242+ background: var(--card-2); border: 1px solid var(--line); border-radius: 16px;
243+ padding: 16px 14px; text-align: center; transition: transform .25s;
244+ }
245+ .concert-fact:hover { transform: translateY(-3px); }
246+ .concert-fact .k { font-size: 11px; text-transform: uppercase; letter-spacing: .12em; color: var(--ink-soft); }
247+ .concert-fact .v { font-weight: 800; font-size: 16px; margin-top: 4px; background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; }
248+ .eq { display: inline-flex; align-items: flex-end; gap: 3px; height: 16px; margin-left: 10px; }
249+ .eq i { width: 3px; background: #fff; border-radius: 2px; animation: eq 1s ease-in-out infinite; }
250+ .eq i:nth-child(1) { height: 60%; animation-delay: 0s; }
251+ .eq i:nth-child(2) { height: 100%; animation-delay: .18s; }
252+ .eq i:nth-child(3) { height: 45%; animation-delay: .34s; }
253+ .eq i:nth-child(4) { height: 80%; animation-delay: .5s; }
254+ @keyframes eq { 0%, 100% { transform: scaleY(.4); } 50% { transform: scaleY(1); } }
255+
256+ /* ---------- INFO GRID ---------- */
257+ .info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; }
258+ .info-card {
259+ background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
260+ padding: 26px 28px; transition: border-color .3s;
261+ }
262+ .info-card:hover { border-color: rgba(255,255,255,.2); }
263+ .info-card h3 { font-size: 18px; font-weight: 700; margin-bottom: 14px; }
264+ .info-card ul { margin-left: 20px; }
265+ .info-card li { margin-bottom: 8px; font-size: 15px; color: #cdd3e4; }
266+ .info-card li strong { color: #fff; }
267+ table.budget { width: 100%; border-collapse: collapse; font-size: 15px; color: #cdd3e4; }
268+ table.budget td { padding: 9px 4px; border-bottom: 1px solid var(--line); }
269+ table.budget td:last-child { text-align: right; font-weight: 700; white-space: nowrap; color: #fff; }
270+ table.budget tr.total td {
271+ border-top: 2px solid rgba(255,107,44,.6); border-bottom: none;
272+ font-weight: 800; font-size: 16px; padding-top: 14px; color: #fff;
273+ }
274+
275+ /* ---------- REVEAL ANIMATION ---------- */
276+ .reveal { opacity: 0; transform: translateY(28px); transition: opacity .7s ease, transform .7s ease; }
277+ .reveal.in { opacity: 1; transform: none; }
278+
279+ /* ---------- FOOTER ---------- */
280+ footer { margin: 80px 0 50px; color: var(--ink-soft); font-size: 12.5px; text-align: center; }
281+ footer a { color: var(--ink-soft); }
282+ .footer-heart { margin-top: 8px; font-size: 13px; }
283+ .footer-heart span { background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; font-weight: 700; }
284+
285+ @media (max-width: 720px) {
286+ .stats { grid-template-columns: repeat(2, 1fr); }
287+ .info-grid, .concert-grid { grid-template-columns: 1fr; }
288+ .hero-inner { padding-top: 110px; }
289+ .cd-box { min-width: 72px; }
290+ .day-body { padding: 24px 22px 28px; }
291+ .nav-days a { padding: 6px 9px; }
292+ }
293+
294+ @media print {
295+ :root { --bg: #fff; --bg-2: #fff; --card: #fff; --card-2: #f6f7fa; --ink: #1a2233; --ink-soft: #4a556b; --line: #dde2ec; }
296+ body { background: #fff; color: #1a2233; }
297+ .nav, .countdown, .eq { display: none !important; }
298+ .hero { min-height: 340px; }
299+ .hero .sub { color: #333; }
300+ .day, .info-card, .stat, .route-strip { box-shadow: none; border: 1px solid #dde2ec; page-break-inside: avoid; }
301+ .timeline .d, .info-card li, table.budget { color: #1a2233; }
302+ .timeline .d strong, .info-card li strong, table.budget td:last-child { color: #000; }
303+ .reveal { opacity: 1 !important; transform: none !important; }
304+ -webkit-print-color-adjust: exact; print-color-adjust: exact;
305+ }
306+</style>
307+</head>
308+<body>
309+
310+<nav class="nav">
311+ <div class="nav-inner">
312+ <div class="logo">🚗 <span>QC → TO 2026</span></div>
313+ <div class="nav-days">
314+ <a href="#j1">J1</a><a href="#j2">J2</a><a href="#j3">J3</a>
315+ <a href="#j4" class="hot">🎤 J4</a>
316+ <a href="#j5">J5</a><a href="#j6">J6</a><a href="#j7">J7</a><a href="#j8">J8</a>
317+ <a href="#infos">Infos</a>
318+ </div>
319+ </div>
320+</nav>
321+
322+<header class="hero">
323+ <div class="hero-bg"></div>
324+ <div class="hero-inner">
325+ <div class="kicker">Road trip · 17 – 24 août 2026</div>
326+ <h1>Québec → Toronto<br><span class="grad">Ed Sheeran LOOP Tour</span></h1>
327+ <div class="lovers">Le trip de <span class="name">Erika</span> <span class="heart">♥</span> <span class="name">SP</span></div>
328+ <p class="sub">8 jours sur la route — Montréal, Ottawa, les Mille-Îles, Toronto et Niagara. Et au centre de tout : LE show au Rogers Centre.</p>
329+ <div class="badges">
330+ <span class="badge hot">🎤 20 août · Rogers Centre</span>
331+ <span class="badge">🚗 ~1 900 km</span>
332+ <span class="badge">🛏️ 7 nuits</span>
333+ <span class="badge">🏙️ 6 villes</span>
334+ </div>
335+ <div class="countdown" id="countdown">
336+ <div class="cd-label">Compte à rebours avant le show</div>
337+ <div class="cd-box"><div class="cd-num" id="cd-d">–</div><div class="cd-unit">jours</div></div>
338+ <div class="cd-box"><div class="cd-num" id="cd-h">–</div><div class="cd-unit">heures</div></div>
339+ <div class="cd-box"><div class="cd-num" id="cd-m">–</div><div class="cd-unit">min</div></div>
340+ <div class="cd-box"><div class="cd-num" id="cd-s">–</div><div class="cd-unit">sec</div></div>
341+ </div>
342+ </div>
343+</header>
344+
345+<div class="wrap">
346+
347+ <div class="stats reveal">
348+ <div class="stat"><div class="num">8</div><div class="lbl">jours</div></div>
349+ <div class="stat"><div class="num">1 900 km</div><div class="lbl">de route</div></div>
350+ <div class="stat"><div class="num">6</div><div class="lbl">villes-étapes</div></div>
351+ <div class="stat"><div class="num">20 août</div><div class="lbl">🎤 concert</div></div>
352+ </div>
353+
354+ <div class="route-strip reveal">
355+ <span class="city">Québec</span><span class="leg">— 250 km →</span>
356+ <span class="city">Montréal</span><span class="leg">— 200 km →</span>
357+ <span class="city">Ottawa</span><span class="leg">— 195 km →</span>
358+ <span class="city">Kingston</span><span class="leg">— 265 km →</span>
359+ <span class="city">Toronto</span><span class="leg">— 540 km →</span>
360+ <span class="city">Montréal</span><span class="leg">— 250 km →</span>
361+ <span class="city">Québec</span>
362+ </div>
363+
364+ <h2 class="section reveal">📅 Itinéraire jour par jour</h2>
365+ <p class="section-sub reveal">Toutes les durées de route sont sans trafic — ajoute 20-30 % aux heures de pointe (surtout en arrivant à Montréal et Toronto).</p>
366+
367+ <!-- JOUR 1 -->
368+ <div class="day reveal" id="j1">
369+ <div class="day-photo">
370+ <div class="img" style="background-image:url('https://upload.wikimedia.org/wikipedia/commons/thumb/e/e2/Bas%C3%ADlica_de_Notre-Dame%2C_Montreal%2C_Canad%C3%A1%2C_2017-08-12%2C_DD_22-24_HDR.jpg/1920px-Bas%C3%ADlica_de_Notre-Dame%2C_Montreal%2C_Canad%C3%A1%2C_2017-08-12%2C_DD_22-24_HDR.jpg')"></div>
371+ <span class="tag">JOUR 1</span>
372+ <span class="drive">🚗 250 km · ~2 h 45</span>
373+ </div>
374+ <div class="day-body">
375+ <div class="date">Lundi 17 août 2026</div>
376+ <h3>Québec → Montréal</h3>
377+ <ul class="timeline">
378+ <li><span class="t">9 h 30</span><span class="d">Départ de Québec (A-20 ou A-40, au choix)</span></li>
379+ <li><span class="t">11 h 00</span><span class="d">Pause à <strong>Trois-Rivières</strong> — café et marche sur le vieux port</span></li>
380+ <li><span class="t">13 h 00</span><span class="d">Arrivée à Montréal, dîner dans le <strong>Vieux-Montréal</strong></span></li>
381+ <li><span class="t">14 h 30</span><span class="d"><strong>Basilique Notre-Dame</strong>, place Jacques-Cartier, rue Saint-Paul</span></li>
382+ <li><span class="t">18 h 00</span><span class="d">Montée au <strong>belvédère du Mont-Royal</strong> pour le coucher de soleil</span></li>
383+ <li><span class="t">20 h 00</span><span class="d">Souper sur une terrasse du Plateau ou dans le Mile End</span></li>
384+ </ul>
385+ <div class="chips">
386+ <span class="chip hotel">🛏️ Nuit : Montréal (Vieux-Port ou Plateau)</span>
387+ <span class="chip">🍽️ Olive &amp; Gourmando · Foiegwa · Schwartz's</span>
388+ </div>
389+ <a class="maplink" href="https://www.google.com/maps/dir/Qu%C3%A9bec,+QC/Trois-Rivi%C3%A8res,+QC/Montr%C3%A9al,+QC" target="_blank">🗺️ Ouvrir le trajet dans Google Maps →</a>
390+ </div>
391+ </div>
392+
393+ <!-- JOUR 2 -->
394+ <div class="day reveal" id="j2">
395+ <div class="day-photo">
396+ <div class="img" style="background-image:url('https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Centre_Block_-_Parliament_Hill.jpg/1920px-Centre_Block_-_Parliament_Hill.jpg')"></div>
397+ <span class="tag">JOUR 2</span>
398+ <span class="drive">🚗 200 km · ~2 h</span>
399+ </div>
400+ <div class="day-body">
401+ <div class="date">Mardi 18 août 2026</div>
402+ <h3>Montréal → Ottawa</h3>
403+ <ul class="timeline">
404+ <li><span class="t">9 h 00</span><span class="d">Déjeuner : bagels <strong>St-Viateur</strong> ou marché <strong>Jean-Talon</strong></span></li>
405+ <li><span class="t">10 h 30</span><span class="d">Départ vers Ottawa (A-40 → ON-417)</span></li>
406+ <li><span class="t">12 h 30</span><span class="d">Dîner au <strong>marché By</strong> (ByWard Market) — queue de castor obligatoire 🦫</span></li>
407+ <li><span class="t">14 h 00</span><span class="d"><strong>Colline du Parlement</strong> — édifices, flamme du centenaire, vue sur la rivière</span></li>
408+ <li><span class="t">15 h 30</span><span class="d">Au choix : <strong>Galerie nationale du Canada</strong> ou <strong>Musée canadien de l'histoire</strong> (côté Gatineau, superbe vue)</span></li>
409+ <li><span class="t">18 h 30</span><span class="d">Marche le long du <strong>canal Rideau</strong> (UNESCO), souper au centre-ville</span></li>
410+ </ul>
411+ <div class="chips">
412+ <span class="chip hotel">🛏️ Nuit : Ottawa (centre-ville / ByWard)</span>
413+ <span class="chip">🍽️ Play Food &amp; Wine · El Camino</span>
414+ </div>
415+ <a class="maplink" href="https://www.google.com/maps/dir/Montr%C3%A9al,+QC/Ottawa,+ON" target="_blank">🗺️ Ouvrir le trajet dans Google Maps →</a>
416+ </div>
417+ </div>
418+
419+ <!-- JOUR 3 -->
420+ <div class="day reveal" id="j3">
421+ <div class="day-photo">
422+ <div class="img" style="background-image:url('https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/1000_Islands_Tower_view_July_2015_panorama_5.jpg/1920px-1000_Islands_Tower_view_July_2015_panorama_5.jpg')"></div>
423+ <span class="tag">JOUR 3</span>
424+ <span class="drive">🚗 460 km · ~5 h</span>
425+ </div>
426+ <div class="day-body">
427+ <div class="date">Mercredi 19 août 2026</div>
428+ <h3>Ottawa → Mille-Îles → Toronto</h3>
429+ <ul class="timeline">
430+ <li><span class="t">8 h 30</span><span class="d">Départ d'Ottawa vers <strong>Gananoque</strong> (~1 h 45)</span></li>
431+ <li><span class="t">10 h 30</span><span class="d"><strong>Croisière des Mille-Îles</strong> (1 h, City Cruises Gananoque) — châteaux, îlots, chenaux 🏝️ <em>Réserver en ligne!</em></span></li>
432+ <li><span class="t">12 h 00</span><span class="d">Dîner à <strong>Kingston</strong> — centre historique, hôtel de ville, front de lac</span></li>
433+ <li><span class="t">14 h 00</span><span class="d">Route vers Toronto par la 401 (~2 h 45)</span></li>
434+ <li><span class="t">17 h 30</span><span class="d">Check-in à l'hôtel (4 nuits, même hôtel — Entertainment District idéalement)</span></li>
435+ <li><span class="t">19 h 30</span><span class="d">Souper détendu sur <strong>King West</strong> et repérage du Rogers Centre à pied</span></li>
436+ </ul>
437+ <div class="chips">
438+ <span class="chip hotel">🛏️ Nuits 3-4-5-6 : Toronto (Entertainment District)</span>
439+ <span class="chip">💡 À pied du stade : Le Germain · Delta · Marriott City Centre</span>
440+ </div>
441+ <div class="tip">⚠️ Réserve l'hôtel <strong>dès maintenant</strong> : Ed Sheeran joue 3 soirs (20-21-22 août) + saison des Blue Jays = centre-ville plein et cher.</div>
442+ <a class="maplink" href="https://www.google.com/maps/dir/Ottawa,+ON/Gananoque,+ON/Kingston,+ON/Toronto,+ON" target="_blank">🗺️ Ouvrir le trajet dans Google Maps →</a>
443+ </div>
444+ </div>
445+
446+ <!-- JOUR 4 — CONCERT -->
447+ <div class="day concert reveal" id="j4">
448+ <div class="concert-banner">⭐ Le grand soir — Ed Sheeran LOOP Tour <span class="eq"><i></i><i></i><i></i><i></i></span></div>
449+ <div class="day-photo">
450+ <div class="img" style="background-image:url('https://upload.wikimedia.org/wikipedia/commons/thumb/2/21/Toronto_-_ON_-_Rogers_Centre_%28Nacht%29.jpg/1920px-Toronto_-_ON_-_Rogers_Centre_%28Nacht%29.jpg')"></div>
451+ <span class="tag">JOUR 4 · CONCERT 🎤</span>
452+ </div>
453+ <div class="day-body">
454+ <div class="date">Jeudi 20 août 2026</div>
455+ <h3>Toronto + Ed Sheeran au Rogers Centre</h3>
456+ <div class="concert-grid">
457+ <div class="concert-fact"><div class="k">Lieu</div><div class="v">Rogers Centre<br>1 Blue Jays Way</div></div>
458+ <div class="concert-fact"><div class="k">Portes / Show</div><div class="v">16 h 30 / 17 h 30</div></div>
459+ <div class="concert-fact"><div class="k">Premières parties</div><div class="v">Myles Smith<br>Lukas Graham</div></div>
460+ </div>
461+ <ul class="timeline" style="margin-top:22px">
462+ <li><span class="t">9 h 30</span><span class="d">Brunch tranquille, puis <strong>CN Tower</strong> (juste à côté du stade) — réserver un créneau en ligne</span></li>
463+ <li><span class="t">12 h 00</span><span class="d"><strong>Aquarium Ripley's</strong> ou promenade sur le <strong>Harbourfront</strong></span></li>
464+ <li><span class="t">15 h 00</span><span class="d">Souper TÔT près du stade (King West / Front St) — les restos débordent les soirs de show</span></li>
465+ <li><span class="t">16 h 30</span><span class="d"><strong>Ouverture des portes</strong> au Rogers Centre — arriver tôt, sécurité + fouille</span></li>
466+ <li><span class="t">17 h 30</span><span class="d">🎶 Début du spectacle — premières parties puis <strong>~2 h 30 de Ed Sheeran</strong> (hits + album <em>Play</em> + loop pedal)</span></li>
467+ <li><span class="t">22 h 30</span><span class="d">Retour à pied à l'hôtel — aucun stress de stationnement 🙌</span></li>
468+ </ul>
469+ <div class="chips">
470+ <span class="chip hotel">🛏️ Nuit : Toronto</span>
471+ <span class="chip">🎟️ Ticketmaster.ca — app mobile requise (billets électroniques)</span>
472+ </div>
473+ <div class="tip">💡 Laisse l'auto au stationnement de l'hôtel toute la journée. Batterie de téléphone pleine pour le billet électronique + petite veste (le toit peut être ouvert en soirée).</div>
474+ </div>
475+ </div>
476+
477+ <!-- JOUR 5 -->
478+ <div class="day reveal" id="j5">
479+ <div class="day-photo">
480+ <div class="img" style="background-image:url('https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Maid_of_the_Mist_VII_approaching_the_Horseshoe_Falls%2C_West_view_20170418_1.jpg/1920px-Maid_of_the_Mist_VII_approaching_the_Horseshoe_Falls%2C_West_view_20170418_1.jpg')"></div>
481+ <span class="tag">JOUR 5</span>
482+ <span class="drive">🚗 260 km A/R · ~3 h</span>
483+ </div>
484+ <div class="day-body">
485+ <div class="date">Vendredi 21 août 2026</div>
486+ <h3>Excursion — Chutes Niagara &amp; Niagara-on-the-Lake</h3>
487+ <ul class="timeline">
488+ <li><span class="t">8 h 30</span><span class="d">Départ de Toronto par la QEW (~1 h 30 sans trafic)</span></li>
489+ <li><span class="t">10 h 30</span><span class="d"><strong>Croisière <em>Voyage to the Falls</em></strong> (Niagara City Cruises) — au pied des chutes, poncho fourni 🌊 <em>Réserver en ligne!</em></span></li>
490+ <li><span class="t">12 h 00</span><span class="d"><strong>Journey Behind the Falls</strong> + terrasse Table Rock, dîner avec vue</span></li>
491+ <li><span class="t">15 h 00</span><span class="d">Route panoramique <strong>Niagara Parkway</strong> vers <strong>Niagara-on-the-Lake</strong> — village adorable, crème glacée, boutiques</span></li>
492+ <li><span class="t">16 h 30</span><span class="d">Dégustation dans un vignoble (Inniskillin, Peller Estates) — <strong>vin de glace</strong> 🍷 (conducteur désigné!)</span></li>
493+ <li><span class="t">18 h 30</span><span class="d">Retour vers Toronto, souper en chemin ou en ville</span></li>
494+ </ul>
495+ <div class="chips">
496+ <span class="chip hotel">🛏️ Nuit : Toronto</span>
497+ <span class="chip">📸 Meilleure lumière sur les chutes : le matin (soleil derrière toi côté canadien)</span>
498+ </div>
499+ <a class="maplink" href="https://www.google.com/maps/dir/Toronto,+ON/Niagara+Falls,+ON/Niagara-on-the-Lake,+ON/Toronto,+ON" target="_blank">🗺️ Ouvrir le trajet dans Google Maps →</a>
500+ </div>
501+ </div>
502+
503+ <!-- JOUR 6 -->
504+ <div class="day reveal" id="j6">
505+ <div class="day-photo">
506+ <div class="img" style="background-image:url('https://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/Distillery_District%2C_Trinity_Street_looking_north%2C_2026.jpg/1920px-Distillery_District%2C_Trinity_Street_looking_north%2C_2026.jpg')"></div>
507+ <span class="tag">JOUR 6</span>
508+ <span class="drive">🚶 Journée à pied + traversier</span>
509+ </div>
510+ <div class="day-body">
511+ <div class="date">Samedi 22 août 2026</div>
512+ <h3>Toronto à fond</h3>
513+ <ul class="timeline">
514+ <li><span class="t">9 h 00</span><span class="d">Traversier au quai Jack Layton vers les <strong>Toronto Islands</strong> — LA vue iconique sur la skyline 🌆</span></li>
515+ <li><span class="t">10 h 00</span><span class="d">Vélo ou marche sur <strong>Centre Island</strong> et <strong>Ward's Island</strong>, plage si le cœur t'en dit</span></li>
516+ <li><span class="t">13 h 00</span><span class="d">Retour en ville, dîner au <strong>St. Lawrence Market</strong> — sandwich au peameal bacon chez Carousel Bakery</span></li>
517+ <li><span class="t">15 h 00</span><span class="d"><strong>Distillery District</strong> — ruelles pavées, galeries, cafés, microbrasseries</span></li>
518+ <li><span class="t">17 h 30</span><span class="d"><strong>Kensington Market</strong> &amp; Chinatown pour l'ambiance funky (ou Queen West pour le magasinage)</span></li>
519+ <li><span class="t">20 h 00</span><span class="d">Souper + rooftop sur King West, ou match des Blue Jays s'ils sont en ville ⚾</span></li>
520+ </ul>
521+ <div class="chips">
522+ <span class="chip hotel">🛏️ Nuit : Toronto</span>
523+ <span class="chip">🚋 Tramways TTC + marche — pas besoin de l'auto aujourd'hui</span>
524+ </div>
525+ </div>
526+ </div>
527+
528+ <!-- JOUR 7 -->
529+ <div class="day reveal" id="j7">
530+ <div class="day-photo">
531+ <div class="img" style="background-image:url('https://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Sandbanks_Provincial_Park_Ontario_Jul_2020.jpg/1920px-Sandbanks_Provincial_Park_Ontario_Jul_2020.jpg')"></div>
532+ <span class="tag">JOUR 7</span>
533+ <span class="drive">🚗 540 km · ~5 h 30</span>
534+ </div>
535+ <div class="day-body">
536+ <div class="date">Dimanche 23 août 2026</div>
537+ <h3>Toronto → Montréal (retour, étape 1)</h3>
538+ <ul class="timeline">
539+ <li><span class="t">9 h 00</span><span class="d">Brunch d'adieu à Toronto, derniers achats</span></li>
540+ <li><span class="t">11 h 00</span><span class="d">Départ sur la 401 Est</span></li>
541+ <li><span class="t">13 h 00</span><span class="d"><em>Option plage</em> : détour au parc <strong>Sandbanks</strong> (Prince Edward County, +45 min) — dunes et plages magnifiques 🏖️ <em>ou</em> simple pause à <strong>Kingston</strong></span></li>
542+ <li><span class="t">18 h 30</span><span class="d">Arrivée à Montréal, check-in</span></li>
543+ <li><span class="t">20 h 00</span><span class="d">Dernière soirée de vacances — souper dans le Vieux-Montréal 🥂</span></li>
544+ </ul>
545+ <div class="chips">
546+ <span class="chip hotel">🛏️ Nuit : Montréal</span>
547+ <span class="chip">💡 Sandbanks : réserver le stationnement journalier sur ontarioparks.ca</span>
548+ </div>
549+ <a class="maplink" href="https://www.google.com/maps/dir/Toronto,+ON/Kingston,+ON/Montr%C3%A9al,+QC" target="_blank">🗺️ Ouvrir le trajet dans Google Maps →</a>
550+ </div>
551+ </div>
552+
553+ <!-- JOUR 8 -->
554+ <div class="day reveal" id="j8">
555+ <div class="day-photo">
556+ <div class="img" style="background-image:url('https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Ch%C3%A2teau_Frontenac_in_Quebec_city%2C_Canada_colorfull.jpg/1920px-Ch%C3%A2teau_Frontenac_in_Quebec_city%2C_Canada_colorfull.jpg')"></div>
557+ <span class="tag">JOUR 8</span>
558+ <span class="drive">🚗 250 km · ~2 h 45</span>
559+ </div>
560+ <div class="day-body">
561+ <div class="date">Lundi 24 août 2026</div>
562+ <h3>Montréal → Québec — retour à la maison</h3>
563+ <ul class="timeline">
564+ <li><span class="t">10 h 00</span><span class="d">Déjeuner tranquille, départ en fin d'avant-midi</span></li>
565+ <li><span class="t">13 h 00</span><span class="d">Arrivée à Québec, reposé et la tête pleine de souvenirs ✅</span></li>
566+ </ul>
567+ <div class="chips">
568+ <span class="chip">🎶 Playlist du retour : <em>Play</em>, <em>÷</em>, <em>×</em> et <em>+</em> — évidemment</span>
569+ </div>
570+ <a class="maplink" href="https://www.google.com/maps/dir/Montr%C3%A9al,+QC/Qu%C3%A9bec,+QC" target="_blank">🗺️ Ouvrir le trajet dans Google Maps →</a>
571+ </div>
572+ </div>
573+
574+ <!-- ===== INFOS PRATIQUES ===== -->
575+ <h2 class="section reveal" id="infos">🧳 Infos pratiques</h2>
576+
577+ <div class="info-grid">
578+ <div class="info-card reveal">
579+ <h3>✅ À réserver d'avance (par priorité)</h3>
580+ <ul>
581+ <li><strong>Hôtel Toronto (4 nuits, 19-23 août)</strong> — le plus urgent, 3 soirs de Ed Sheeran cette fin de semaine-là</li>
582+ <li><strong>Billets du concert</strong> — Ticketmaster.ca, dans l'app mobile</li>
583+ <li><strong>Croisière Niagara</strong> (niagaracruises.com) — créneau du matin</li>
584+ <li><strong>Croisière Mille-Îles</strong> (cityexperiences.com, Gananoque)</li>
585+ <li><strong>CN Tower</strong> — billet horodaté en ligne (évite 1 h de file)</li>
586+ <li>Hôtels Montréal (2 nuits) et Ottawa (1 nuit)</li>
587+ </ul>
588+ </div>
589+
590+ <div class="info-card reveal">
591+ <h3>💰 Budget estimé (2 personnes)</h3>
592+ <table class="budget">
593+ <tr><td>Hôtels (7 nuits, moy. ~250 $)</td><td>1 750 $</td></tr>
594+ <tr><td>Essence (~1 900 km)</td><td>250 $</td></tr>
595+ <tr><td>Stationnements (Toronto ~40 $/jr)</td><td>200 $</td></tr>
596+ <tr><td>Repas (~120 $/jour)</td><td>950 $</td></tr>
597+ <tr><td>Activités (croisières, CN Tower…)</td><td>350 $</td></tr>
598+ <tr><td>Billets de concert (variable)</td><td>—</td></tr>
599+ <tr class="total"><td>Total (hors billets)</td><td>≈ 3 500 $</td></tr>
600+ </table>
601+ </div>
602+
603+ <div class="info-card reveal">
604+ <h3>🚗 Conduite &amp; stationnement</h3>
605+ <ul>
606+ <li>Éviter d'arriver à Toronto entre 15 h et 19 h (la 401/Gardiner = 🐌)</li>
607+ <li>Le soir du concert : <strong>ne pas bouger l'auto</strong> — tout se fait à pied du centre-ville</li>
608+ <li>Péage optionnel 407 ETR : rapide mais cher (~40-60 $) — la 401 suffit</li>
609+ <li>Green P (app) pour les stationnements municipaux à Toronto</li>
610+ <li>Essence moins chère en périphérie qu'au centre-ville</li>
611+ </ul>
612+ </div>
613+
614+ <div class="info-card reveal">
615+ <h3>🎒 À ne pas oublier</h3>
616+ <ul>
617+ <li>Téléphone chargé + batterie externe (billets électroniques au stade)</li>
618+ <li>Petit sac transparent ou minimal — politique de sacs stricte au Rogers Centre</li>
619+ <li>Veste légère pour le soir (toit du stade parfois ouvert)</li>
620+ <li>Maillot + serviette (Toronto Islands, Sandbanks)</li>
621+ <li>Bouteilles d'eau réutilisables pour la route</li>
622+ <li>Permis de conduire + preuve d'assurance auto</li>
623+ </ul>
624+ </div>
625+ </div>
626+
627+ <footer>
628+ Concert vérifié : Ed Sheeran LOOP Tour, Rogers Centre, jeudi 20 août 2026, 17 h 30 (Ticketmaster.ca / Live Nation)<br>
629+ Photos : <a href="https://commons.wikimedia.org" target="_blank">Wikimedia Commons</a> (licences libres)
630+ <div class="footer-heart">Le road trip d'<span>Erika ♥ SP</span> — été 2026</div>
631+ </footer>
632+
633+</div>
634+
635+<script>
636+ // Countdown to showtime (17:30 EDT, Aug 20 2026)
637+ const SHOW = new Date("2026-08-20T17:30:00-04:00").getTime();
638+ const pad = n => String(n).padStart(2, "0");
639+ function tick() {
640+ let ms = SHOW - Date.now();
641+ const cd = document.getElementById("countdown");
642+ if (ms <= 0) {
643+ cd.querySelector(".cd-label").textContent = "🎶 C'est ce soir (ou c'est déjà passé)!";
644+ ms = 0;
645+ }
646+ const d = Math.floor(ms / 864e5), h = Math.floor(ms % 864e5 / 36e5),
647+ m = Math.floor(ms % 36e5 / 6e4), s = Math.floor(ms % 6e4 / 1e3);
648+ document.getElementById("cd-d").textContent = d;
649+ document.getElementById("cd-h").textContent = pad(h);
650+ document.getElementById("cd-m").textContent = pad(m);
651+ document.getElementById("cd-s").textContent = pad(s);
652+ }
653+ tick(); setInterval(tick, 1000);
654+
655+ // Scroll reveal
656+ const io = new IntersectionObserver(entries => {
657+ for (const e of entries) if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); }
658+ }, { threshold: 0.08 });
659+ document.querySelectorAll(".reveal").forEach(el => io.observe(el));
660+</script>
661+</body>
662+</html>
added server.mjs +52 −0
@@ -0,0 +1,52 @@
1+// Zero-dep static server for the voyage2026 itinerary.
2+// Usage: node server.mjs [port] — serves this directory, / -> index, /healthz -> ok
3+import { createServer } from "node:http";
4+import { readFile } from "node:fs/promises";
5+import { join, extname, normalize } from "node:path";
6+import { fileURLToPath } from "node:url";
7+
8+const ROOT = fileURLToPath(new URL(".", import.meta.url));
9+const PORT = Number(process.argv[2] || process.env.PORT || 8060);
10+const INDEX = "itineraire-toronto-2026.html";
11+
12+const MIME = {
13+ ".html": "text/html; charset=utf-8",
14+ ".css": "text/css; charset=utf-8",
15+ ".js": "text/javascript; charset=utf-8",
16+ ".json": "application/json",
17+ ".png": "image/png",
18+ ".jpg": "image/jpeg",
19+ ".jpeg": "image/jpeg",
20+ ".webp": "image/webp",
21+ ".svg": "image/svg+xml",
22+ ".ico": "image/x-icon",
23+ ".pdf": "application/pdf",
24+};
25+
26+createServer(async (req, res) => {
27+ const url = new URL(req.url, "http://x");
28+ if (url.pathname === "/healthz") {
29+ res.writeHead(200, { "content-type": "text/plain" });
30+ return res.end("ok");
31+ }
32+ let path = decodeURIComponent(url.pathname);
33+ if (path === "/" || path === "/index.html") path = "/" + INDEX;
34+ const file = normalize(join(ROOT, path));
35+ if (!file.startsWith(ROOT)) {
36+ res.writeHead(403);
37+ return res.end("forbidden");
38+ }
39+ try {
40+ const body = await readFile(file);
41+ res.writeHead(200, {
42+ "content-type": MIME[extname(file).toLowerCase()] || "application/octet-stream",
43+ "cache-control": "public, max-age=300",
44+ });
45+ res.end(body);
46+ } catch {
47+ res.writeHead(404, { "content-type": "text/plain; charset=utf-8" });
48+ res.end("404 — page introuvable");
49+ }
50+}).listen(PORT, "0.0.0.0", () => {
51+ console.log(`voyage2026 static server on http://0.0.0.0:${PORT} (root: ${ROOT})`);
52+});
53
Menu

Theme