Initial commit — site configs
- vault.hidrago.click: Vaultwarden (password manager) - git.hidrago.click: Gitea (git service) - All static sites (suma, weather, combien-jour, tokyo-trip, etc.) - Nginx configs for all subdomains - Systemd user service for Vaultwarden
This commit is contained in:
@@ -0,0 +1,261 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Tokyo Trip — Itinéraire</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 2rem 1rem;
|
||||
}
|
||||
.lang-switch {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.lang-btn {
|
||||
padding: 0.4rem 1rem;
|
||||
border: 2px solid rgba(255,255,255,0.4);
|
||||
background: rgba(255,255,255,0.15);
|
||||
color: #fff;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.lang-btn:hover { background: rgba(255,255,255,0.3); }
|
||||
.lang-btn.active {
|
||||
background: #fff;
|
||||
color: #764ba2;
|
||||
border-color: #fff;
|
||||
}
|
||||
h1 {
|
||||
color: #fff;
|
||||
font-size: 2rem;
|
||||
margin-bottom: 0.3rem;
|
||||
text-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
||||
}
|
||||
.subtitle {
|
||||
color: rgba(255,255,255,0.8);
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.trip-date {
|
||||
color: rgba(255,255,255,0.6);
|
||||
font-size: 0.85rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.reminder {
|
||||
background: rgba(255,255,255,0.95);
|
||||
color: #e8893b;
|
||||
font-weight: 700;
|
||||
font-size: 1rem;
|
||||
padding: 0.8rem 1.2rem;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 2rem;
|
||||
max-width: 580px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.1);
|
||||
border: 2px solid #e8893b;
|
||||
}
|
||||
.timeline {
|
||||
max-width: 580px;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.step-card {
|
||||
background: rgba(255,255,255,0.95);
|
||||
border-radius: 16px;
|
||||
padding: 1.2rem 1.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.1);
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
.step-card:hover { transform: translateX(4px); }
|
||||
.step-time {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 800;
|
||||
color: #764ba2;
|
||||
min-width: 60px;
|
||||
text-align: center;
|
||||
}
|
||||
.step-icon {
|
||||
font-size: 2rem;
|
||||
min-width: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
.step-body {
|
||||
flex: 1;
|
||||
}
|
||||
.step-city {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
}
|
||||
.step-station {
|
||||
font-size: 0.85rem;
|
||||
color: #888;
|
||||
}
|
||||
.step-action {
|
||||
font-size: 0.95rem;
|
||||
color: #555;
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
.step-note {
|
||||
font-size: 0.8rem;
|
||||
color: #e8893b;
|
||||
margin-top: 0.3rem;
|
||||
font-style: italic;
|
||||
}
|
||||
.connector {
|
||||
text-align: center;
|
||||
color: rgba(255,255,255,0.5);
|
||||
font-size: 1.5rem;
|
||||
margin: 0.1rem 0;
|
||||
line-height: 1;
|
||||
}
|
||||
footer {
|
||||
margin-top: 2rem;
|
||||
color: rgba(255,255,255,0.6);
|
||||
font-size: 0.8rem;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="lang-switch">
|
||||
<button class="lang-btn active" data-lang="fr">FR</button>
|
||||
<button class="lang-btn" data-lang="en">EN</button>
|
||||
<button class="lang-btn" data-lang="ja">日本語</button>
|
||||
</div>
|
||||
<h1 id="heading">🚄 Tokyo Trip</h1>
|
||||
<p class="subtitle" id="subtitle">Itinéraire de voyage</p>
|
||||
<p class="trip-date" id="trip-date"></p>
|
||||
<div class="reminder" id="reminder"></div>
|
||||
<div class="timeline">
|
||||
|
||||
<div class="step-card">
|
||||
<div class="step-time">07:30</div>
|
||||
<div class="step-icon">🚉</div>
|
||||
<div class="step-body">
|
||||
<div class="step-city">Kuwana</div>
|
||||
<div class="step-station" data-step-station="0"></div>
|
||||
<div class="step-action" data-step-action="0"></div>
|
||||
<div class="step-note" data-step-note="0"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step-card">
|
||||
<div class="step-time">08:35</div>
|
||||
<div class="step-icon">🛬</div>
|
||||
<div class="step-body">
|
||||
<div class="step-city">Nagoya</div>
|
||||
<div class="step-station" data-step-station="1"></div>
|
||||
<div class="step-action" data-step-action="1"></div>
|
||||
<div class="step-note" data-step-note="1"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step-card">
|
||||
<div class="step-time">08:57</div>
|
||||
<div class="step-icon">🚄</div>
|
||||
<div class="step-body">
|
||||
<div class="step-city">Nagoya</div>
|
||||
<div class="step-station" data-step-station="2"></div>
|
||||
<div class="step-action" data-step-action="2"></div>
|
||||
<div class="step-note" data-step-note="2"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step-card">
|
||||
<div class="step-time">—</div>
|
||||
<div class="step-icon">🏁</div>
|
||||
<div class="step-body">
|
||||
<div class="step-city">Tokyo</div>
|
||||
<div class="step-station" data-step-station="3"></div>
|
||||
<div class="step-action" data-step-action="3"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<span data-i18n="updated">Mis à jour le</span> 25/07/2026 à 08:39 UTC
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
const I18N = {"fr": {"title": "Tokyo Trip — Itinéraire", "heading": "🚄 Tokyo Trip", "subtitle": "Itinéraire de voyage", "step": "Étape", "time": "Heure", "station": "Gare", "action": "Action", "note": "Note", "no_date": "Date à définir", "updated": "Mis à jour le"}, "en": {"title": "Tokyo Trip — Itinerary", "heading": "🚄 Tokyo Trip", "subtitle": "Travel itinerary", "step": "Step", "time": "Time", "station": "Station", "action": "Action", "note": "Note", "no_date": "Date TBD", "updated": "Updated on"}, "ja": {"title": "東京旅行 — 旅程", "heading": "🚄 東京旅行", "subtitle": "旅程表", "step": "ステップ", "time": "時刻", "station": "駅", "action": "行動", "note": "メモ", "no_date": "日付未定", "updated": "更新日時"}};
|
||||
const TRIP = {"title": {"fr": "Tokyo Trip", "en": "Tokyo Trip", "ja": "東京旅行"}, "date_label": {"fr": "Date du voyage", "en": "Trip date", "ja": "旅行日"}, "date": "", "steps": [{"time": "07:30", "city": "Kuwana", "station": {"fr": "Gare de Kuwana", "en": "Kuwana Station", "ja": "桑名駅"}, "action": {"fr": "Départ", "en": "Departure", "ja": "出発"}, "icon": "🚉", "note": {"fr": "Train depuis Kuwana", "en": "Train from Kuwana", "ja": "桑名から電車で出発"}}, {"time": "08:35", "city": "Nagoya", "station": {"fr": "Gare de Nagoya", "en": "Nagoya Station", "ja": "名古屋駅"}, "action": {"fr": "Arrivée à Nagoya", "en": "Arrival at Nagoya", "ja": "名古屋到着"}, "icon": "🛬", "note": {"fr": "22 minutes avant le Shinkansen", "en": "22 minutes before Shinkansen", "ja": "新幹線まで22分"}}, {"time": "08:57", "city": "Nagoya", "station": {"fr": "Gare de Nagoya", "en": "Nagoya Station", "ja": "名古屋駅"}, "action": {"fr": "Shinkansen pour Tokyo", "en": "Shinkansen to Tokyo", "ja": "新幹線で東京へ"}, "icon": "🚄", "note": {"fr": "Départ en Shinkansen", "en": "Shinkansen departure", "ja": "新幹線出発"}}, {"time": "—", "city": "Tokyo", "station": {"fr": "Gare de Tokyo", "en": "Tokyo Station", "ja": "東京駅"}, "action": {"fr": "Arrivée à Tokyo", "en": "Arrival at Tokyo", "ja": "東京到着"}, "icon": "🏁", "note": {"fr": "", "en": "", "ja": ""}}]};
|
||||
const REMINDER = {"fr": "📅 Rappel : le 30 juillet, départ pour Saitama ! Chichi-bouh ! 🎉", "en": "📅 Reminder: July 30th, departure for Saitama! Chichi-bouh! 🎉", "ja": "📅 リマインダー:7月30日、埼玉へ出発!ちちぶー!🎉"};
|
||||
let currentLang = 'fr';
|
||||
|
||||
function applyLang(lang) {
|
||||
currentLang = lang;
|
||||
const t = I18N[lang];
|
||||
document.title = t.title;
|
||||
document.getElementById('heading').textContent = t.heading;
|
||||
document.getElementById('subtitle').textContent = t.subtitle;
|
||||
|
||||
// Reminder banner
|
||||
const remEl = document.getElementById('reminder');
|
||||
if (remEl && REMINDER[lang]) remEl.textContent = REMINDER[lang];
|
||||
|
||||
// Trip date
|
||||
const dateEl = document.getElementById('trip-date');
|
||||
if (TRIP.date) {
|
||||
dateEl.textContent = t.date_label + ' : ' + TRIP.date;
|
||||
} else {
|
||||
dateEl.textContent = t.no_date;
|
||||
}
|
||||
|
||||
// Step stations, actions, notes
|
||||
TRIP.steps.forEach((step, i) => {
|
||||
const stEl = document.querySelector('[data-step-station="' + i + '"]');
|
||||
if (stEl) stEl.textContent = step.station[lang];
|
||||
const actEl = document.querySelector('[data-step-action="' + i + '"]');
|
||||
if (actEl) actEl.textContent = step.action[lang];
|
||||
const noteEl = document.querySelector('[data-step-note="' + i + '"]');
|
||||
if (noteEl && step.note[lang]) noteEl.textContent = step.note[lang];
|
||||
});
|
||||
|
||||
// Generic i18n labels
|
||||
document.querySelectorAll('[data-i18n]').forEach(el => {
|
||||
const key = el.getAttribute('data-i18n');
|
||||
if (t[key]) el.textContent = t[key];
|
||||
});
|
||||
|
||||
// Active button
|
||||
document.querySelectorAll('.lang-btn').forEach(btn => {
|
||||
btn.classList.toggle('active', btn.getAttribute('data-lang') === lang);
|
||||
});
|
||||
document.documentElement.lang = lang;
|
||||
}
|
||||
|
||||
document.querySelectorAll('.lang-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
applyLang(btn.getAttribute('data-lang'));
|
||||
localStorage.setItem('trip-lang', btn.getAttribute('data-lang'));
|
||||
});
|
||||
});
|
||||
|
||||
const saved = localStorage.getItem('trip-lang');
|
||||
if (saved && I18N[saved]) {
|
||||
applyLang(saved);
|
||||
} else {
|
||||
const browserLang = navigator.language.slice(0, 2);
|
||||
if (I18N[browserLang]) applyLang(browserLang);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user