{
  "name": "LOCATE - AI Travel Guide",
  "short_name": "LOCATE",
  "description": "AIがあなただけの旅程を提案する旅行ガイドアプリ",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#0d0d0d",
  "theme_color": "#0d0d0d",
  "orientation": "portrait",
  "icons": [
    {
      "src": "/icon-192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any maskable"
    },
    {
      "src": "/icon-512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "any maskable"
    }
  ]
}
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="theme-color" content="#0f0e0c">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="LOCATE">
<meta name="description" content="LOCATE — AI Travel Guide | Your personal AI travel guide for anywhere in the world">
<link rel="manifest" href="manifest.json">
<link rel="icon" href="icon-192.png" type="image/png">
<link rel="apple-touch-icon" href="icon-192.png">
<title>LOCATE — AI Travel Guide</title>
<link href="https://fonts.googleapis.com/css2?family=Lobster&family=Noto+Sans+JP:wght@300;400;500;700&family=Noto+Sans+KR:wght@300;400;500&family=Noto+Sans+SC:wght@300;400;500&family=Playfair+Display:ital,wght@0,400;0,700;1,400&display=swap" rel="stylesheet">
<style>
:root {
  --base-font: 15px;
  --bg: #0f0e0c;
  --surface: #1a1916;
  --surface2: #232220;
  --border: #2e2c28;
  --gold: #c9a84c;
  --gold-dim: rgba(201,168,76,0.15);
  --text: #f0ebe0;
  --text-dim: #8a8070;
  --text-mid: #c0b8a8;
  --accent: #e8734a;
  --green: #6ab187;
  --radius: 16px;
  --radius-sm: 10px;
}

* { margin:0; padding:0; box-sizing:border-box; -webkit-tap-highlight-color:transparent; }

html, body {
  width:100%; height:100%;
  background: var(--bg);
  color: var(--text);
  font-family: 'Noto Sans JP', sans-serif;
  font-size: 15px;
  overscroll-behavior: none;
}

/* ── APP SHELL ── */
#app {
  width: 100%;
  max-width: 430px;
  min-height: 100vh;
  margin: 0 auto;
  position: relative;
  overflow-x: hidden;
  background: var(--bg);
}

.screen {
  display: none;
  flex-direction: column;
  min-height: 100vh;
  animation: slideUp .35s cubic-bezier(.22,.8,.36,1);
}
.screen.active { display: flex; }

@keyframes slideUp {
  from { opacity:0; transform:translateY(20px); }
  to   { opacity:1; transform:translateY(0); }
}

/* ── TYPOGRAPHY ── */
.display { font-family:'Playfair Display',serif; }

/* ── COMPONENTS ── */
.btn {
  display:flex; align-items:center; justify-content:center; gap:8px;
  padding:16px 24px; border-radius:var(--radius);
  font-family:inherit; font-size:14px; font-weight:500;
  cursor:pointer; border:none; transition:all .2s; letter-spacing:.03em;
}
.btn-gold {
  background: linear-gradient(135deg, #c9a84c, #e8c96a);
  color: #0f0e0c; font-weight:700;
}
.btn-gold:hover { transform:translateY(-1px); box-shadow:0 8px 24px rgba(201,168,76,.3); }
.btn-gold:disabled { opacity:.4; cursor:default; transform:none; box-shadow:none; }
.btn-outline {
  background:transparent; border:1px solid var(--border);
  color:var(--text-mid);
}
.btn-outline:hover { border-color:var(--gold); color:var(--gold); }
.btn-ghost { background:transparent; color:var(--text-dim); padding:8px; }
.btn-ghost:hover { color:var(--text); }

.input-field {
  width:100%; padding:14px 16px;
  background:var(--surface); border:1px solid var(--border);
  border-radius:var(--radius-sm); color:var(--text);
  font-family:inherit; font-size:15px; outline:none;
  transition:border-color .2s;
}
.input-field:focus { border-color:var(--gold); }
.input-field::placeholder { color:var(--text-dim); }

.tag {
  display:inline-flex; align-items:center; gap:4px;
  padding:4px 10px; border-radius:20px;
  font-size:11px; font-weight:500; letter-spacing:.06em;
}
.tag-gold { background:var(--gold-dim); color:var(--gold); }
.tag-green { background:rgba(106,177,135,.12); color:var(--green); }
.tag-blue { background:rgba(100,160,255,.12); color:#64a0ff; }
.tag-purple { background:rgba(180,130,255,.12); color:#b482ff; }
.tag-orange { background:rgba(255,160,80,.12); color:#ffa050; }
.tag-teal { background:rgba(80,200,180,.12); color:#50c8b4; }

.divider {
  height:1px; background:var(--border); margin:0;
}

.chip {
  padding:8px 14px; border-radius:20px;
  background:var(--surface2); border:1px solid var(--border);
  font-size:12px; color:var(--text-mid); cursor:pointer;
  white-space:nowrap; transition:all .15s;
}
.chip:hover, .chip.active {
  background:var(--gold-dim); border-color:var(--gold); color:var(--gold);
}

/* ── LANG SWITCHER ── */
.lang-bar {
  display:flex; gap:2px; padding:4px;
  background:var(--surface); border-radius:10px;
}
.lang-btn {
  flex:1; padding:6px 0; border-radius:7px;
  font-size:12px; font-weight:500; cursor:pointer;
  border:none; background:transparent; color:var(--text-dim);
  transition:all .15s;
}
.lang-btn.active {
  background:var(--gold);
  color:#0f0e0c;
}

/* ════════════════════════════════
   SCREEN: SPLASH
════════════════════════════════ */
#screen-splash {
  background: var(--bg);
  justify-content:center; align-items:center;
  gap:24px; padding:40px;
}
.splash-logo {
  font-family:'Playfair Display',serif;
  font-size:72px; font-weight:700;
  background: linear-gradient(135deg, #c9a84c 0%, #e8c96a 50%, #c9a84c 100%);
  -webkit-background-clip:text; -webkit-text-fill-color:transparent;
  letter-spacing:.1em;
}
.splash-tagline {
  text-align:center; font-size:13px;
  color:var(--text-dim); line-height:1.8; letter-spacing:.05em;
}
.splash-langs {
  display:flex; gap:8px; flex-wrap:wrap; justify-content:center;
}
.splash-lang {
  padding:6px 14px; border-radius:20px;
  background:var(--surface); border:1px solid var(--border);
  font-size:12px; color:var(--text-mid);
}
.splash-start {
  width:100%; padding:18px;
  background: linear-gradient(135deg, #c9a84c, #e8c96a);
  border:none; border-radius:var(--radius);
  font-family:inherit; font-size:15px; font-weight:700;
  color:#0f0e0c; cursor:pointer; letter-spacing:.05em;
  transition:all .2s;
}
.splash-start:hover { transform:translateY(-2px); box-shadow:0 12px 32px rgba(201,168,76,.3); }
.splash-divider {
  display:flex; align-items:center; gap:12px;
  color:var(--text-dim); font-size:11px; width:100%;
}
.splash-divider::before, .splash-divider::after {
  content:''; flex:1; height:1px; background:var(--border);
}

/* ════════════════════════════════
   SCREEN: HOME
════════════════════════════════ */
#screen-home { background:var(--bg); }

.home-header {
  padding:52px 20px 20px;
  display:flex; justify-content:space-between; align-items:center;
}
.home-logo {
  font-family:'Playfair Display',serif;
  font-size:28px; letter-spacing:.1em;
  background:linear-gradient(135deg, #c9a84c, #e8c96a);
  -webkit-background-clip:text; -webkit-text-fill-color:transparent;
}
.home-actions { display:flex; gap:8px; align-items:center; }

.home-hero {
  padding:0 20px 24px;
  border-bottom:1px solid var(--border);
}
.home-greeting {
  font-size:22px; font-weight:300; line-height:1.4;
  color:var(--text); margin-bottom:4px;
}
.home-greeting strong { color:var(--gold); font-weight:700; }
.home-sub { font-size:12px; color:var(--text-dim); }

.home-search-wrap {
  padding:20px; display:flex; flex-direction:column; gap:12px;
}
.search-row { display:flex; gap:10px; }
.search-input-wrap { flex:1; position:relative; }
.search-clear {
  position:absolute; right:12px; top:50%; transform:translateY(-50%);
  color:var(--text-dim); cursor:pointer; font-size:16px;
  background:none; border:none;
}
.gps-btn {
  padding:14px; background:var(--surface); border:1px solid var(--border);
  border-radius:var(--radius-sm); color:var(--gold); cursor:pointer;
  font-size:18px; transition:all .2s; flex-shrink:0;
}
.gps-btn:hover { background:var(--gold-dim); }

.section-title {
  font-size:11px; letter-spacing:.15em; text-transform:uppercase;
  color:var(--text-dim); font-weight:500;
}

.dest-scroll {
  display:flex; gap:8px; overflow-x:auto; padding:0 20px;
  scrollbar-width:none;
}
.dest-scroll::-webkit-scrollbar { display:none; }

.dest-card {
  flex-shrink:0; width:110px; height:130px;
  border-radius:var(--radius); overflow:hidden; position:relative;
  cursor:pointer; transition:transform .2s;
  border:1px solid var(--border);
}
.dest-card:hover { transform:scale(1.03); }
.dest-card-bg {
  width:100%; height:100%; display:flex;
  align-items:center; justify-content:center;
  font-size:40px;
}
.dest-card-overlay {
  position:absolute; bottom:0; left:0; right:0;
  padding:8px 10px;
  background:linear-gradient(transparent, rgba(0,0,0,.8));
}
.dest-card-name { font-size:13px; font-weight:500; }
.dest-card-en { font-size:10px; color:rgba(255,255,255,.5); }

.dest-bgs {
  tokyo: 'linear-gradient(135deg,#1a1f3a,#2d3561)';
}

.home-next-wrap { padding:20px; margin-top:auto; }

/* ════════════════════════════════
   SCREEN: QUESTIONS
════════════════════════════════ */
#screen-questions { background:var(--bg); }

.q-header {
  padding:52px 20px 20px;
  border-bottom:1px solid var(--border);
  position:sticky;
  top:0;
  z-index:10;
  background:var(--bg);
}
.q-nav { display:grid; grid-template-columns:1fr auto 1fr; align-items:center; margin-bottom:16px; }
.q-nav > *:last-child { display:flex; justify-content:flex-end; }
.q-back { background:none; border:none; color:var(--text-dim); cursor:pointer; font-size:14px; padding:0; display:flex; align-items:center; gap:4px; letter-spacing:.03em; }
.q-back:hover { color:var(--text); }
.q-progress-text { font-size:11px; color:var(--text-dim); letter-spacing:.1em; }
.q-progress-bar { height:2px; background:var(--border); border-radius:1px; }
.q-progress-fill { height:100%; background:var(--gold); border-radius:1px; transition:width .4s ease; }
.q-city {
  font-family:'Playfair Display',serif;
  font-size:30px; font-weight:400; color:var(--text);
  margin-top:12px; letter-spacing:.03em;
}
.q-city-sub { font-size:12px; color:var(--text-dim); margin-top:2px; }

.q-body { flex:1; padding:24px 20px; display:flex; flex-direction:column; gap:28px; }

.q-block {}
.q-label {
  display:flex; align-items:center; gap:8px;
  font-size:14px; font-weight:500; color:var(--text);
  margin-bottom:12px;
}
.q-emoji { font-size:20px; }

.q-grid { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
.q-opt {
  padding:14px 10px; background:var(--surface); border:1.5px solid var(--border);
  border-radius:var(--radius-sm); cursor:pointer; text-align:center;
  transition:all .15s; font-family:inherit;
}
.q-opt-icon { font-size:22px; margin-bottom:6px; display:block; }
.q-opt-label { font-size:12px; color:var(--text-dim); line-height:1.4; }
.q-opt:hover { border-color:var(--gold); }
.q-opt.selected { background:var(--gold-dim); border-color:var(--gold); }
.q-opt.selected .q-opt-label { color:var(--gold); }

.q-footer {
  padding:16px 20px 32px;
  border-top:1px solid var(--border);
}

/* ════════════════════════════════
   SCREEN: LOADING
════════════════════════════════ */
#screen-loading {
  background:var(--bg);
  justify-content:center; align-items:center;
  gap:32px; padding:40px;
}
.load-orb {
  width:100px; height:100px; border-radius:50%;
  background:radial-gradient(circle at 35% 35%, #e8c96a, #c9a84c 50%, #8a6020);
  box-shadow:0 0 60px rgba(201,168,76,.4);
  animation:pulse 2s ease-in-out infinite;
}
@keyframes pulse {
  0%,100% { transform:scale(1); box-shadow:0 0 60px rgba(201,168,76,.4); }
  50% { transform:scale(1.08); box-shadow:0 0 90px rgba(201,168,76,.6); }
}
.load-city {
  font-family:'Playfair Display',serif;
  font-size:40px; text-align:center; color:var(--text);
}
.load-label {
  font-size:13px; color:var(--text-dim);
  letter-spacing:.08em; text-align:center;
}
.load-steps { display:flex; flex-direction:column; gap:12px; width:100%; max-width:280px; }
.load-step {
  display:flex; align-items:center; gap:12px;
  font-size:13px; color:var(--border);
  transition:color .5s, transform .3s;
}
.load-step.done { color:var(--text-dim); }
.load-step.active { color:var(--gold); transform:translateX(4px); }
.load-step-dot {
  width:8px; height:8px; border-radius:50%;
  background:currentColor; flex-shrink:0;
}

/* ════════════════════════════════
   SCREEN: RESULT
════════════════════════════════ */
#screen-result { background:var(--bg); }

.result-header {
  padding:52px 20px 20px;
  border-bottom:1px solid var(--border);
  position:relative;
}
.result-top { display:flex; justify-content:space-between; align-items:flex-start; }
.result-city {
  font-family:'Playfair Display',serif;
  font-size:36px; font-weight:700; color:var(--text);
  letter-spacing:.03em;
}
.result-badges { display:flex; flex-wrap:wrap; gap:6px; margin-top:10px; }

.result-body { flex:1; overflow-y:auto; padding:0 0 220px; }

.result-section {
  padding:20px; border-bottom:1px solid var(--border);
}
.result-section-title {
  display:flex; align-items:center; gap:8px;
  font-size:13px; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--gold);
  margin-bottom:14px;
}

.result-content {
  font-size:14px; line-height:1.9; color:var(--text-mid);
  white-space:pre-wrap; word-break:break-word;
}
.result-content strong { color:var(--text); font-weight:600; }

/* Timeline */
.timeline { display:flex; flex-direction:column; gap:0; }
.tl-day-label {
  font-size:11px; font-weight:700; letter-spacing:.1em; text-transform:uppercase;
  color:var(--gold); background:var(--gold-dim);
  padding:4px 10px; border-radius:20px; display:inline-block;
  margin:8px 0 12px 58px;
}
.tl-note {
  font-size:11px; color:var(--text-dim); line-height:1.6;
  padding:10px 14px; background:var(--surface);
  border-left:2px solid var(--border); border-radius:0 6px 6px 0;
  margin-bottom:12px;
}
.tl-item { display:flex; gap:14px; }
.tl-left { display:flex; flex-direction:column; align-items:center; width:44px; flex-shrink:0; }
.tl-time { font-size:10px; color:var(--gold); font-weight:700; letter-spacing:.04em; text-align:center; line-height:1.2; }
.tl-line { flex:1; width:1px; background:var(--border); margin:4px 0; min-height:20px; }
.tl-badge {
  width:24px; height:24px; border-radius:50%;
  background:var(--gold-dim); border:1px solid var(--gold);
  color:var(--gold); font-size:10px; font-weight:700;
  display:flex; align-items:center; justify-content:center;
  flex-shrink:0; margin-top:4px;
}
.tl-right { padding-bottom:20px; flex:1; padding-top:4px; }
.tl-title { font-size:14px; font-weight:600; color:var(--text); margin-bottom:4px; }
.tl-desc { font-size:13px; color:var(--text-dim); line-height:1.65; }

/* Restaurant card */
.rest-card {
  display:flex; gap:14px; padding:14px;
  background:var(--surface); border-radius:10px;
  border:1px solid var(--border); margin-bottom:10px;
  transition:border-color .2s;
}
.rest-card:last-child { margin-bottom:0; }
.rest-icon-wrap {
  width:48px; height:48px; border-radius:12px;
  background:var(--gold-dim); display:flex; align-items:center;
  justify-content:center; font-size:24px; flex-shrink:0;
}
.rest-info { flex:1; }
.rest-name { font-size:14px; font-weight:600; color:var(--text); margin-bottom:4px; }
.rest-desc { font-size:12px; color:var(--text-dim); line-height:1.55; margin-bottom:6px; }
.rest-price {
  display:inline-block; font-size:11px; font-weight:600;
  color:var(--gold); background:var(--gold-dim);
  padding:2px 8px; border-radius:20px;
}

/* Hotel card */
.hotel-card {
  padding:14px 14px 14px 16px; background:var(--surface);
  border-radius:10px; border:1px solid var(--border);
  border-left:3px solid var(--gold);
  margin-bottom:10px;
}
.hotel-card:last-child { margin-bottom:0; }
.hotel-header { display:flex; justify-content:space-between; align-items:flex-start; gap:8px; margin-bottom:6px; }
.hotel-name { font-size:14px; font-weight:600; color:var(--text); }
.hotel-price {
  font-size:11px; font-weight:600; color:var(--gold);
  background:var(--gold-dim); padding:2px 8px; border-radius:20px;
  white-space:nowrap; flex-shrink:0;
}
.hotel-desc { font-size:12px; color:var(--text-dim); line-height:1.55; }

/* Font size control */
.font-ctrl { display:flex; align-items:center; }
.font-ctrl-btn {
  background:none; border:none;
  color:var(--text-dim); cursor:pointer;
  padding:4px; line-height:1;
  display:flex; align-items:center; justify-content:center;
  transition:color .15s;
}
.font-ctrl-btn:hover { color:var(--text); }
.font-ctrl-btn svg { display:block; }

/* Tips */
.tip-item {
  display:flex; gap:12px; padding:12px 0;
  border-bottom:1px solid var(--border);
}
.tip-item:last-child { border-bottom:none; }
.tip-num {
  width:24px; height:24px; border-radius:50%;
  background:var(--gold-dim); color:var(--gold);
  font-size:11px; font-weight:700;
  display:flex; align-items:center; justify-content:center;
  flex-shrink:0; margin-top:1px;
}
.tip-text { font-size:13px; color:var(--text-dim); line-height:1.65; }

/* Destination intro */
.dest-intro { background:var(--surface); border-radius:10px; border:1px solid var(--border); border-left:3px solid var(--gold); padding:14px 16px; margin-bottom:4px; }
.dest-intro-label { font-size:10px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--gold); margin-bottom:8px; }
.dest-intro-summary { font-size:13px; color:var(--text); line-height:1.65; margin-bottom:10px; }
.dest-intro-highlights { display:flex; flex-direction:column; gap:6px; }
.dest-intro-highlight { display:flex; align-items:flex-start; gap:8px; font-size:12px; color:var(--text-dim); line-height:1.5; }
.dest-intro-dot { width:6px; height:6px; border-radius:50%; background:var(--gold); flex-shrink:0; margin-top:5px; }

/* Result footer */
.result-footer {
  position:fixed; bottom:0; left:50%; transform:translateX(-50%);
  width:100%; max-width:430px;
  padding:12px 20px 28px;
  background:linear-gradient(transparent, var(--bg) 30%);
  display:flex; gap:8px;
}

/* ════════════════════════════════
   SCREEN: PREMIUM
════════════════════════════════ */
#screen-premium { background:var(--bg); }
.premium-header {
  padding:52px 20px 0;
  display:flex; justify-content:space-between; align-items:center;
}
.premium-hero {
  padding:32px 20px;
  text-align:center;
}
.premium-crown { font-size:48px; margin-bottom:12px; }
.premium-title {
  font-family:'Playfair Display',serif;
  font-size:28px; color:var(--text); margin-bottom:8px;
}
.premium-sub { font-size:13px; color:var(--text-dim); line-height:1.7; }

.premium-features {
  padding:0 20px; display:flex; flex-direction:column; gap:10px;
}
.pf-item {
  display:flex; gap:14px; padding:14px;
  background:var(--surface); border-radius:var(--radius-sm);
  border:1px solid var(--border);
}
.pf-icon { font-size:24px; flex-shrink:0; }
.pf-text {}
.pf-name { font-size:14px; font-weight:600; color:var(--text); margin-bottom:2px; }
.pf-desc { font-size:12px; color:var(--text-dim); line-height:1.5; }

.premium-plans {
  padding:24px 20px; display:flex; flex-direction:column; gap:10px;
}
.plan-card {
  padding:16px; border-radius:var(--radius);
  border:1.5px solid var(--border);
  cursor:pointer; transition:all .2s; position:relative;
}
.plan-card.recommended {
  border-color:var(--gold);
  background:var(--gold-dim);
}
.plan-badge {
  position:absolute; top:-10px; left:50%; transform:translateX(-50%);
  padding:3px 12px; border-radius:10px;
  background:var(--gold); color:#0f0e0c;
  font-size:10px; font-weight:700; letter-spacing:.06em;
  white-space:nowrap;
}
.plan-name { font-size:13px; color:var(--text-dim); margin-bottom:4px; }
.plan-price { font-size:24px; font-weight:700; color:var(--text); }
.plan-price span { font-size:13px; font-weight:400; color:var(--text-dim); }
.plan-desc { font-size:12px; color:var(--text-dim); margin-top:4px; }

.premium-footer { padding:0 20px 40px; }

/* ════════════════════════════════
   TOAST
════════════════════════════════ */
#toast {
  position:fixed; top:80px; left:50%; transform:translateX(-50%) translateY(-10px);
  background:var(--surface2); border:1px solid var(--border);
  border-radius:10px; padding:10px 16px;
  font-size:13px; color:var(--text-mid);
  opacity:0; transition:all .3s; pointer-events:none;
  white-space:normal; max-width:80vw; text-align:center;
  z-index:1000;
}
#toast.show { opacity:1; transform:translateX(-50%) translateY(0); }

/* ════════════════════════════════
   FREE USAGE COUNTER
════════════════════════════════ */
.usage-bar-wrap { padding:0 20px 24px; }
.usage-bar-top { display:flex; justify-content:space-between; font-size:11px; color:var(--text-dim); margin-bottom:6px; }
.usage-bar { height:4px; background:var(--surface2); border-radius:2px; }
.usage-fill { height:100%; border-radius:2px; background:linear-gradient(90deg,var(--green),var(--gold)); transition:width .5s; }
</style>
</head>
<body>
<div id="app">

<!-- ══ SPLASH ══ -->
<div id="screen-splash" class="screen active">
  <img src="locate-logo-white.png" alt="Locate" style="width:80%;max-width:300px;height:auto">
  <p class="splash-tagline" id="splash-text" style="white-space:pre-line;text-align:center">AIがあなただけの旅程を提案
飲食店・宿泊先・観光スポットを一括ガイド</p>
  <p style="font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--text-dim);text-align:center;margin-top:16px">
    <span id="splash-lang-label">言語を選択</span> / Select Language
  </p>
  <div class="lang-bar" style="width:100%">
    <button class="lang-btn active" data-lang="ja" onclick="setLang('ja')">日本語</button>
    <button class="lang-btn" data-lang="en" onclick="setLang('en')">English</button>
    <button class="lang-btn" data-lang="zh" onclick="setLang('zh')">中文</button>
    <button class="lang-btn" data-lang="ko" onclick="setLang('ko')">한국어</button>
  </div>
  <button class="splash-start" onclick="showScreen('screen-home')" id="splash-start-btn">はじめる →</button>
  <div class="splash-divider"><span id="splash-free-label">無料で3回まで利用可能</span></div>
  <p style="font-size:11px;color:var(--text-dim);text-align:center;line-height:1.7;cursor:pointer;text-decoration:underline;text-underline-offset:3px;" id="splash-note" onclick="showScreen('screen-premium')">
    プレミアムプラン（有料）で<br>無制限利用・詳細プランが解放されます
  </p>
  <p style="font-size:10px;color:var(--text-dim);opacity:.6;text-align:center;line-height:1.7;padding:0 8px;min-height:40px;white-space:pre-line" id="splash-disclaimer">本アプリはAIを活用していますが、提案内容に誤りを含む場合があります。ご利用の際は必ず内容をご確認ください。</p>
</div>

<!-- ══ HOME ══ -->
<div id="screen-home" class="screen">
  <div class="q-header">
    <div class="q-nav">
      <button class="q-back" onclick="showScreen('screen-splash')">← <span id="back-label-home">戻る</span></button>
      <button class="btn btn-ghost" onclick="showScreen('screen-premium')" style="font-size:18px;padding:4px 8px;justify-self:center">👑</button>
      <div class="font-ctrl" style="justify-self:end"><button class="font-ctrl-btn" onclick="changeFontSize()" title="文字サイズ変更">
        <svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
          <circle cx="9" cy="9" r="6.5" stroke="currentColor" stroke-width="1.8"/>
          <line x1="14" y1="14" x2="20" y2="20" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
          <line class="zoom-h" x1="6.5" y1="9" x2="11.5" y2="9" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
          <line class="zoom-v" x1="9" y1="6.5" x2="9" y2="11.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
        </svg>
      </button>
      </div>
    </div>
    <div class="q-progress-bar"><div style="height:100%;width:0%"></div></div>
    <div class="q-city display" id="home-greeting">目的地を選択</div>
    <div class="q-city-sub" id="home-sub">都市名を入力するか、人気の目的地から選んでください</div>
  </div>

  <div class="home-search-wrap">
    <div class="section-title" id="label-destination" style="margin-bottom:8px">目的地</div>
    <div class="search-row">
      <div class="search-input-wrap">
        <input type="text" class="input-field" id="city-input"
          placeholder="例：京都、Tokyo、首尔..."
          autocomplete="off" autocorrect="off" spellcheck="false">
        <button class="search-clear" onclick="clearCity()" id="clear-btn" style="display:none">✕</button>
      </div>
      <button class="gps-btn" onclick="useGPS()" title="GPS">📍</button>
    </div>
    <div class="section-title" id="label-popular">人気の目的地</div>
    <div class="dest-scroll" id="dest-chips"></div>
  </div>

  <div id="pwa-banner" style="display:none;margin:0 20px 16px;padding:12px 14px;background:var(--surface);border:1px solid var(--border);border-radius:12px;position:relative">
    <button onclick="dismissPwaBanner()" style="position:absolute;top:0;right:0;bottom:0;background:none;border:none;color:var(--text-dim);font-size:20px;cursor:pointer;padding:0 14px;line-height:1;display:flex;align-items:center">×</button>
    <div style="font-size:13px;font-weight:600;color:var(--text);margin-bottom:4px;padding-right:32px" id="pwa-title">📲 ホーム画面に追加できます</div>
    <div style="font-size:12px;color:var(--text-dim);line-height:1.6;padding-right:32px" id="pwa-desc">Safariで開き、共有ボタン（□↑）→「ホーム画面に追加」</div>
  </div>

  <div class="usage-bar-wrap">
    <div class="usage-bar-top">
      <span id="usage-label">無料残り回数</span>
      <span id="usage-count">3 / 3</span>
    </div>
    <div class="usage-bar">
      <div class="usage-fill" id="usage-fill" style="width:100%"></div>
    </div>
  </div>

  <div style="padding:24px 20px 40px">
    <button class="btn btn-gold" style="width:100%" id="home-next-btn" onclick="confirmCity()" disabled>
      <span id="home-next-label">目的地を入力してください</span>
    </button>
  </div>
</div>

<!-- ══ DISAMBIGUATION POPUP ══ -->
<div id="disambiguation-overlay" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.7);z-index:200;align-items:center;justify-content:center;padding:24px">
  <div style="background:var(--surface);border-radius:16px;border:1px solid var(--border);padding:24px;width:100%;max-width:380px">
    <div style="font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--gold);margin-bottom:8px">同名の地名があります</div>
    <div style="font-size:14px;color:var(--text);margin-bottom:16px">「<span id="disambig-city"></span>」はどちらですか？</div>
    <div id="disambig-options" style="display:flex;flex-direction:column;gap:8px"></div>
    <button class="btn" style="width:100%;margin-top:12px;background:var(--bg);border:1px solid var(--border)" onclick="document.getElementById('disambiguation-overlay').style.display='none'">キャンセル</button>
  </div>
</div>

<!-- ══ CITY CONFIRM POPUP ══ -->
<div id="city-confirm-overlay" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.7);z-index:200;align-items:center;justify-content:center;padding:24px">
  <div style="background:var(--surface);border-radius:16px;border:1px solid var(--border);padding:24px;width:100%;max-width:380px">
    <div style="font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--gold);margin-bottom:12px" id="city-confirm-label">目的地の確認</div>
    <div style="font-size:16px;font-weight:700;color:var(--text);margin-bottom:6px;line-height:1.5" id="city-confirm-name"></div>
    <div style="font-size:13px;color:var(--text-dim);line-height:1.65;margin-bottom:12px;min-height:40px" id="city-confirm-desc"></div>
    <div style="font-size:13px;color:var(--text);font-weight:500;margin-bottom:20px;min-height:20px" id="city-confirm-question"></div>
    <div style="display:flex;gap:10px">
      <button class="btn" style="flex:1;background:var(--bg);border:1px solid var(--border);display:none" onclick="cancelCityConfirm()" id="city-confirm-no">違う</button>
      <button class="btn btn-gold" style="flex:1;display:none" onclick="acceptCityConfirm()" id="city-confirm-yes">はい、進む →</button>
    </div>
  </div>
</div>

<!-- ══ TIMING POPUP ══ -->
<div id="timing-overlay" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.7);z-index:200;align-items:center;justify-content:center;padding:24px">
  <div style="background:var(--surface);border-radius:16px;border:1px solid var(--border);padding:24px;width:100%;max-width:380px">
    <div style="font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--gold);margin-bottom:12px" id="timing-label">この旅はいつ？</div>
    <div style="font-size:15px;font-weight:600;color:var(--text);margin-bottom:6px;line-height:1.5" id="timing-title">旅のタイミングを教えてください</div>
    <div style="font-size:13px;color:var(--text-dim);line-height:1.65;margin-bottom:20px" id="timing-desc">提案するスケジュールの時間軸が変わります。</div>
    <div style="display:flex;gap:10px">
      <button class="btn" style="flex:1;background:var(--bg);border:1px solid var(--border);display:flex;flex-direction:column;align-items:center;gap:6px;padding:14px 8px" onclick="selectTiming('plan')" id="timing-plan-btn">
        <span style="font-size:22px">🗓</span>
        <span style="font-size:13px;font-weight:600;color:var(--text)" id="timing-plan-label">計画中</span>
        <span style="font-size:11px;color:var(--text-dim)" id="timing-plan-sub">日時未定</span>
      </button>
      <button class="btn btn-gold" style="flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;padding:14px 8px" onclick="selectTiming('now')" id="timing-now-btn">
        <span style="font-size:22px">📍</span>
        <span style="font-size:13px;font-weight:600" id="timing-now-label">今すぐ出発</span>
        <span style="font-size:11px;opacity:.8" id="timing-now-sub">現在時刻から提案</span>
      </button>
    </div>
  </div>
</div>
<div id="screen-questions" class="screen">
  <div class="q-header">
    <div class="q-nav">
      <button class="q-back" onclick="showScreen('screen-home')">← <span id="back-label-q">戻る</span></button>
      <button class="btn btn-ghost" onclick="showScreen('screen-premium')" style="font-size:18px;padding:4px 8px;justify-self:center">👑</button>
      <div class="font-ctrl" style="justify-self:end"><button class="font-ctrl-btn" onclick="changeFontSize()" title="文字サイズ変更">
        <svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
          <circle cx="9" cy="9" r="6.5" stroke="currentColor" stroke-width="1.8"/>
          <line x1="14" y1="14" x2="20" y2="20" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
          <line class="zoom-h" x1="6.5" y1="9" x2="11.5" y2="9" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
          <line class="zoom-v" x1="9" y1="6.5" x2="9" y2="11.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
        </svg>
      </button>
      </div>
    </div>
    <div class="q-progress-bar">
      <div class="q-progress-fill" id="q-progress-fill" style="width:0%"></div>
    </div>
    <div style="text-align:right;margin-top:4px"><span class="q-progress-text" id="q-progress-text">0 / 5</span></div>
    <div class="q-city display" id="q-city-name">京都</div>
    <div style="margin-top:6px;display:flex;flex-wrap:wrap;gap:6px;align-items:center" id="q-badges-row"><span class="tag tag-teal" id="q-timing-badge">🗓 計画中</span><span id="q-prev-answers" style="display:contents"></span></div>
    <div class="q-city-sub" id="q-city-sub">旅のスタイルを教えてください</div>
  </div>

  <div class="q-body" id="q-body">
    <!-- Dynamically rendered -->
  </div>

  <div class="q-footer">
    <div id="q-error" style="display:none;margin-bottom:12px;padding:10px 14px;background:rgba(220,80,80,.1);border:1px solid rgba(220,80,80,.2);border-radius:8px;font-size:12px;color:#e07070;line-height:1.6"></div>
    <button class="btn btn-gold" style="width:100%" id="generate-btn" onclick="generatePlan()" disabled>
      <span id="generate-label">✨ 旅程を生成する</span>
    </button>
  </div>
</div>

<!-- ══ LOADING ══ -->
<div id="screen-loading" class="screen">
  <div class="load-orb"></div>
  <div class="load-city display" id="load-city">京都</div>
  <div class="load-label" id="load-label">AIが最適な旅程を設計しています…</div>
  <div class="load-steps" id="load-steps"></div>
</div>

<!-- ══ RESULT ══ -->
<div id="screen-result" class="screen">
  <div class="result-header">
    <div class="q-nav" style="margin-bottom:12px">
      <img src="locate-logo-white.png" alt="Locate" style="height:28px;width:auto">
      <button class="btn btn-ghost" onclick="showScreen('screen-premium')" style="font-size:18px;padding:4px 8px;justify-self:center">👑</button>
      <div class="font-ctrl" style="justify-self:end"><button class="font-ctrl-btn" onclick="changeFontSize()" title="文字サイズ変更">
        <svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
          <circle cx="9" cy="9" r="6.5" stroke="currentColor" stroke-width="1.8"/>
          <line x1="14" y1="14" x2="20" y2="20" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
          <line class="zoom-h" x1="6.5" y1="9" x2="11.5" y2="9" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
          <line class="zoom-v" x1="9" y1="6.5" x2="9" y2="11.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
        </svg>
      </button>
      </div>
    </div>
    <div class="result-top">
      <div>
        <div class="result-city display" id="result-city">京都</div>
        <div class="result-badges" id="result-badges"></div>
      </div>
    </div>
  </div>

  <div class="result-body" id="result-body"></div>

  <div class="result-footer">
    <div style="display:flex;flex-direction:column;gap:8px;width:100%">

      <div style="display:flex;gap:8px">
        <button class="btn btn-outline" style="flex:1" onclick="showBackWarning()" id="result-retry-btn">条件を変更</button>
        <button class="btn btn-gold" style="flex:2" onclick="showComingSoon()" id="result-new-btn">💾 保存して条件変更</button>
      </div>
    </div>
  </div>
</div>


<!-- ══ 戻る警告ポップアップ ══ -->
<div id="back-warning-overlay" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.7);z-index:200;align-items:center;justify-content:center;padding:24px">
  <div style="background:var(--surface2);border:1px solid var(--border);border-radius:20px;padding:28px 24px;max-width:360px;width:100%">
    <div style="font-size:28px;text-align:center;margin-bottom:16px">⚠️</div>
    <div id="warn-title" style="font-size:16px;font-weight:700;color:var(--text);text-align:center;margin-bottom:12px">条件を変更しますか？</div>
    <p id="warn-body" style="font-size:13px;color:var(--text-dim);line-height:1.8;text-align:center;margin-bottom:24px">
      画面を戻ると回数が新たにカウントされます。この提案は保存されませんので、必要であればスクリーンショットを取っておいてください。
    </p>
    <div style="display:flex;gap:10px">
      <button id="warn-close" onclick="hideBackWarning()" style="flex:1;padding:14px;background:transparent;border:1px solid var(--border);border-radius:12px;color:var(--text-mid);font-family:inherit;font-size:14px;cursor:pointer">閉じる</button>
      <button id="warn-confirm" onclick="confirmGoBack()" style="flex:1;padding:14px;background:var(--accent);border:none;border-radius:12px;color:white;font-family:inherit;font-size:14px;font-weight:700;cursor:pointer">条件変更</button>
    </div>
  </div>
</div>

<!-- ══ 変更なし確認ポップアップ ══ -->
<div id="no-change-overlay" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.7);z-index:200;align-items:center;justify-content:center;padding:24px">
  <div style="background:var(--surface2);border:1px solid var(--border);border-radius:20px;padding:28px 24px;max-width:360px;width:100%">
    <div style="font-size:28px;text-align:center;margin-bottom:16px">🔄</div>
    <div id="no-change-title" style="font-size:16px;font-weight:700;color:var(--text);text-align:center;margin-bottom:12px">条件は変更されていません</div>
    <p id="no-change-body" style="font-size:13px;color:var(--text-dim);line-height:1.8;text-align:center;margin-bottom:24px">
      前回と同じ条件で生成します。このまま続けますか？
    </p>
    <div style="display:flex;gap:10px">
      <button id="no-change-cancel" onclick="hideNoChangePopup()" style="flex:1;padding:14px;background:transparent;border:1px solid var(--border);border-radius:12px;color:var(--text-mid);font-family:inherit;font-size:14px;cursor:pointer">戻る</button>
      <button id="no-change-confirm" onclick="forceGenerate()" style="flex:1;padding:14px;background:var(--gold);border:none;border-radius:12px;color:#0f0e0c;font-family:inherit;font-size:14px;font-weight:700;cursor:pointer">生成する</button>
    </div>
  </div>
</div>

<!-- ══ PREMIUM ══ -->
<div id="screen-premium" class="screen">
  <div class="premium-header">
    <button class="q-back" onclick="goBack()">← <span id="back-label-premium">戻る</span></button>
    <div class="tag tag-gold" style="justify-self:center">PREMIUM</div>
    <div class="font-ctrl" style="justify-self:end"><button class="font-ctrl-btn" onclick="changeFontSize()" title="文字サイズ変更">
        <svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
          <circle cx="9" cy="9" r="6.5" stroke="currentColor" stroke-width="1.8"/>
          <line x1="14" y1="14" x2="20" y2="20" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
          <line class="zoom-h" x1="6.5" y1="9" x2="11.5" y2="9" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
          <line class="zoom-v" x1="9" y1="6.5" x2="9" y2="11.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
        </svg>
      </button>
    </div>
  </div>

  <div class="premium-hero">
    <div class="premium-crown">👑</div>
    <div class="premium-title display" id="premium-title">LOCATEプレミアム</div>
    <p class="premium-sub" id="premium-sub">旅をもっと深く、もっと自由に</p>
  </div>

  <div class="premium-features">
    <div class="pf-item">
      <div class="pf-icon">♾️</div>
      <div class="pf-text">
        <div class="pf-name" id="pf1-name">無制限プラン生成</div>
        <div class="pf-desc" id="pf1-desc">何度でも旅程を作り直せます</div>
      </div>
    </div>
    <div class="pf-item">
      <div class="pf-icon">🗓️</div>
      <div class="pf-text">
        <div class="pf-name" id="pf2-name">複数日程プラン（最大7日間）</div>
        <div class="pf-desc" id="pf2-desc">長期旅行も詳細にプランニング</div>
      </div>
    </div>
    <div class="pf-item">
      <div class="pf-icon">💾</div>
      <div class="pf-text">
        <div class="pf-name" id="pf3-name">旅程の保存・共有</div>
        <div class="pf-desc" id="pf3-desc">お気に入りのプランをシェア</div>
      </div>
    </div>
    <div class="pf-item">
      <div class="pf-icon">🗺️</div>
      <div class="pf-text">
        <div class="pf-name" id="pf4-name">マップ連携</div>
        <div class="pf-desc" id="pf4-desc">Google Mapsで即ナビ開始</div>
      </div>
    </div>
    <div class="pf-item">
      <div class="pf-icon">🌐</div>
      <div class="pf-text">
        <div class="pf-name" id="pf5-name">オフライン対応</div>
        <div class="pf-desc" id="pf5-desc">電波のない場所でも旅程を確認</div>
      </div>
    </div>
  </div>

  <div class="premium-plans">
    <div class="plan-card">
      <div class="plan-name" id="plan1-name">月額プラン</div>
      <div class="plan-price">¥480 <span id="plan1-per">/ 月</span></div>
      <div class="plan-desc" id="plan1-desc">いつでもキャンセル可能</div>
    </div>
    <div class="plan-card recommended">
      <div class="plan-badge">おすすめ</div>
      <div class="plan-name" id="plan2-name">年額プラン</div>
      <div class="plan-price">¥3,800 <span id="plan2-per">/ 年</span></div>
      <div class="plan-desc" id="plan2-desc">月額より34%お得 · 月あたり¥317</div>
    </div>
  </div>

  <div class="premium-footer">
    <button class="btn btn-gold" style="width:100%" onclick="showComingSoon()">
      <span id="premium-cta">プレミアムを始める</span>
    </button>
    <p style="text-align:center;font-size:11px;color:var(--text-dim);margin-top:12px" id="premium-note">
      いつでもキャンセル可能 · 安全なStripe決済
    </p>
  </div>
</div>

<!-- ══ TOAST ══ -->
<div id="toast"></div>

</div><!-- #app -->

<script>
// ════════════════════════════════
// STATE
// ════════════════════════════════
let lang = 'ja';
let currentCity = '';
let answers = {};
let freeUsage = localStorage.getItem('locateFreeUsage') !== null ? parseInt(localStorage.getItem('locateFreeUsage'), 10) : 3;
let prevScreen = 'screen-home';
let previousAnswers = {}; // RESULTから戻ったときの前回の選択を保持
let previousCity = ''; // 前回の選択をした都市名

// ════════════════════════════════
// I18N
// ════════════════════════════════
const T = {
  ja: {
    splashText: 'AIがあなただけの旅程を提案\n飲食店・宿泊先・観光スポットを一括ガイド',
    splashStart: 'はじめる →',
    splashNote: 'プレミアムプラン（有料）で<br>無制限利用・詳細プランが解放されます',
    greeting: '目的地を入力',
    greetingCity: '{city}',
    homeSub: 'AIが旅程・グルメ・宿泊先を提案します',
    labelDest: '目的地',
    labelPop: '人気の目的地',
    usageLabel: '無料残り回数',
    nextBtn: '目的地を入力してください',
    nextBtnReady: '{city}を探索する →',
    qSub: '旅のスタイルを教えてください',
    generateBtn: '✨ 旅程を生成する',
    loadLabel: 'AIが最適な旅程を設計しています…',
    loadSteps: ['目的地情報を分析中', 'おすすめスポットを選定中', '旅程を組み立て中', '飲食店・宿泊先を調査中', '最終仕上げ中'],
    retryBtn: '条件を変更',
    newBtn: '新しい旅を計画',
    questions: [
      { key:'style', emoji:'🎯', label:'旅のスタイルは？', opts:[
        {icon:'🏛️',label:'観光スポット巡り',val:'観光スポット・歴史文化巡り'},
        {icon:'🍜',label:'グルメ重視',val:'グルメ・食べ歩き重視'},
        {icon:'🌿',label:'自然・アウトドア',val:'自然・アウトドア体験'},
        {icon:'🛍️',label:'ショッピング',val:'ショッピング・カフェ巡り'},
      ]},
      { key:'budget', emoji:'💰', label:'予算感は？', opts:[
        {icon:'💴',label:'節約（〜¥5,000/日）',val:'節約重視（1日5,000円以内）'},
        {icon:'💳',label:'普通（〜¥15,000/日）',val:'普通（1日5,000〜15,000円）'},
        {icon:'✨',label:'少し贅沢',val:'少し贅沢（1日15,000〜30,000円）'},
        {icon:'👑',label:'高級志向',val:'贅沢・高級志向（予算制限なし）'},
      ]},
      { key:'food', emoji:'🍽️', label:'食事の好みは？', opts:[
        {icon:'🥢',label:'郷土料理・和食',val:'その土地の郷土料理・和食'},
        {icon:'☕',label:'カフェ・洋食',val:'おしゃれなカフェ・洋食'},
        {icon:'🍡',label:'B級グルメ',val:'コスパ重視・B級グルメ'},
        {icon:'😊',label:'なんでもOK',val:'特にこだわりなし'},
      ]},
      { key:'member', emoji:'👥', label:'旅のメンバーは？', opts:[
        {icon:'🧍',label:'ひとり旅',val:'ひとり旅'},
        {icon:'💑',label:'カップル',val:'カップル・夫婦旅行'},
        {icon:'👫',label:'友人グループ',val:'友人グループ旅行'},
        {icon:'👨‍👩‍👧',label:'家族旅行',val:'子連れ家族旅行'},
      ]},
      { key:'days', emoji:'⏱️', label:'時間・日数は？', opts:[
        {icon:'⏱️',label:'2時間',val:'2時間（散歩・デート・プチ旅）'},
        {icon:'🌤️',label:'半日',val:'半日（3〜4時間）'},
        {icon:'🌄',label:'日帰り',val:'日帰り（1日）'},
        {icon:'🌙',label:'1泊2日',val:'1泊2日'},
        {icon:'🌙🌙',label:'2泊3日',val:'2泊3日'},
        {icon:'✈️',label:'3泊以上',val:'3泊以上'},
      ]},
    ],
    destinations: [
      {name:'京都',en:'Kyoto',icon:'🏯',bg:'#1e1a2e'},
      {name:'東京',en:'Tokyo',icon:'🗼',bg:'#1a1e2e'},
      {name:'大阪',en:'Osaka',icon:'🎭',bg:'#2e1a1a'},
      {name:'沖縄',en:'Okinawa',icon:'🌺',bg:'#1a2e2a'},
      {name:'北海道',en:'Hokkaido',icon:'🦀',bg:'#1a2230'},
      {name:'奈良',en:'Nara',icon:'🦌',bg:'#1e2a1a'},
    ],
    promptTemplate: (city, a, now) => `あなたは経験豊富な旅行コンシェルジュです。
【目的地】${city}
${now ? `【現在時刻】${now.time}（今すぐ出発。この時刻からスケジュールを組んでください。${now.sameDay ? '日帰り・短時間プランのため、当日中に収まるようにしてください。翌日に持ち越さないこと。' : '1泊以上のプランのため、この時刻を出発点として通常通り組んでください。'}）` : '【旅のタイミング】将来の計画（朝8時〜9時頃の標準的な出発時間で組んでください）'}
【旅のスタイル】${a.style}
【予算】${a.budget}
【食事の好み】${a.food}
【旅のメンバー】${a.member}
【旅の日数】${a.days}

以下のJSON形式で旅程を返してください。他のテキストは一切含めず、JSONのみ返してください：

{
  "destination_intro": {
    "summary": "目的地の概要（1文のみ）",
    "highlights": ["旅行者が知っておくべき特徴1", "特徴2"]
  },
  "concept": "この旅のコンセプト（2〜3文）",
  "timeline": [
    {"time": "08:00", "title": "場所・活動名", "desc": "詳細説明（具体的な場所名・アドバイス含む）"}
  ],
  "restaurants": [
    {"icon": "🍜", "name": "店名", "desc": "特徴・おすすめメニュー", "price": "価格帯"}
  ],
  "hotels": [
    {"name": "宿泊施設名", "desc": "特徴・立地", "price": "価格帯（1泊）"}
  ],
  "tips": ["アドバイス1", "アドバイス2", "アドバイス3"]
}

以下の件数で返してください：
- 「2時間」「半日」の場合：timeline 3〜4件、restaurants 1〜2件、hotels 0件（短時間のため不要）
- 「日帰り（1日）」の場合：timeline 6〜8件、restaurants 2〜3件、hotels 0件
- 「1泊2日」以上の場合：timeline 各日4〜6件、restaurants 3〜4件、hotels 2〜3件
tipsは3件。【店名・施設名のルール】有名観光地・世界遺産・有名神社仏閣など広く知られた施設は積極的に実名で記載してください。飲食店・宿泊施設は実在が確認できるものは実名で、不確かな場合は「地元の蕎麦店」「駅前の食堂」など一般的な表現にしてください。架空の固有名詞は絶対に使わないこと。短時間の場合は徒歩圏内・近距離でまわれるプランにしてください。スケジュールの最初の項目は最寄り駅や出発地点から始め、交通手段を明記してください。多日程の場合は各日の最初も同様に起点を示してください。`,
    resultLabels: { concept:'✦ 旅のコンセプト', timeline:'🗓 スケジュール', restaurants:'🍜 おすすめ飲食店', hotels:'🏨 おすすめ宿泊先', tips:'💡 旅のポイント' },
  },

  en: {
    splashText: 'Your AI travel guide, anywhere in the world\nRestaurants · Hotels · Sightseeing, all in one',
    splashStart: 'Get Started →',
    splashNote: 'Upgrade to Premium (paid) for<br>unlimited plans & detailed itineraries',
    greeting: 'Enter Destination',
    greetingCity: '{city}',
    homeSub: 'AI suggests itineraries, dining & accommodation',
    labelDest: 'Destination',
    labelPop: 'Popular Destinations',
    usageLabel: 'Free uses left',
    nextBtn: 'Enter a destination',
    nextBtnReady: 'Explore {city} →',
    qSub: 'Tell us your travel style',
    generateBtn: '✨ Generate Itinerary',
    loadLabel: 'AI is designing your perfect trip…',
    loadSteps: ['Analyzing destination','Selecting top spots','Building itinerary','Finding restaurants & hotels','Final touches'],
    retryBtn: 'Change preferences',
    newBtn: 'Plan another trip',
    questions: [
      { key:'style', emoji:'🎯', label:'Travel style?', opts:[
        {icon:'🏛️',label:'Sightseeing',val:'sightseeing and cultural experiences'},
        {icon:'🍜',label:'Food-focused',val:'food tours and gourmet dining'},
        {icon:'🌿',label:'Nature & outdoor',val:'nature and outdoor activities'},
        {icon:'🛍️',label:'Shopping',val:'shopping and cafe hopping'},
      ]},
      { key:'budget', emoji:'💰', label:'Budget range?', opts:[
        {icon:'💴',label:'Budget (¥5k/day)',val:'budget-friendly (under ¥5,000/day)'},
        {icon:'💳',label:'Moderate (¥15k)',val:'moderate (¥5,000–¥15,000/day)'},
        {icon:'✨',label:'Comfortable',val:'comfortable (¥15,000–¥30,000/day)'},
        {icon:'👑',label:'Luxury',val:'luxury (no budget limit)'},
      ]},
      { key:'food', emoji:'🍽️', label:'Food preference?', opts:[
        {icon:'🥢',label:'Local cuisine',val:'local and traditional Japanese cuisine'},
        {icon:'☕',label:'Cafes & western',val:'trendy cafes and western food'},
        {icon:'🍡',label:'Street food',val:'budget street food and local favorites'},
        {icon:'😊',label:'No preference',val:'no preference, anything goes'},
      ]},
      { key:'member', emoji:'👥', label:'Traveling with?', opts:[
        {icon:'🧍',label:'Solo',val:'solo traveler'},
        {icon:'💑',label:'Couple',val:'couple or spouse'},
        {icon:'👫',label:'Friend group',val:'group of friends'},
        {icon:'👨‍👩‍👧',label:'Family',val:'family with children'},
      ]},
      { key:'days', emoji:'⏱️', label:'Time / Duration?', opts:[
        {icon:'⏱️',label:'2 hours',val:'2 hours (stroll / date / quick trip)'},
        {icon:'🌤️',label:'Half day',val:'half day (3–4 hours)'},
        {icon:'🌄',label:'Day trip',val:'day trip (1 day)'},
        {icon:'🌙',label:'1 night',val:'1 night 2 days'},
        {icon:'🌙🌙',label:'2 nights',val:'2 nights 3 days'},
        {icon:'✈️',label:'3+ nights',val:'3 or more nights'},
      ]},
    ],
    destinations: [
      {name:'Kyoto',en:'京都',icon:'🏯',bg:'#1e1a2e'},
      {name:'Tokyo',en:'東京',icon:'🗼',bg:'#1a1e2e'},
      {name:'Osaka',en:'大阪',icon:'🎭',bg:'#2e1a1a'},
      {name:'Okinawa',en:'沖縄',icon:'🌺',bg:'#1a2e2a'},
      {name:'Hokkaido',en:'北海道',icon:'🦀',bg:'#1a2230'},
      {name:'Nara',en:'奈良',icon:'🦌',bg:'#1e2a1a'},
    ],
    promptTemplate: (city, a, now) => `You are an expert travel concierge for any destination worldwide.
City: ${city}
${now ? `Current time: ${now.time} (leaving now — start the schedule from this time. ${now.sameDay ? 'This is a day trip or short outing, so keep all activities within today — do not extend to the next day.' : 'This is an overnight trip, so start from this time and continue normally.'})` : 'Timing: Planning ahead (use standard 8–9am departure time)'}
Style: ${a.style}
Budget: ${a.budget}
Food: ${a.food}
Group: ${a.member}
Duration: ${a.days}

Return ONLY a JSON object, no other text:
{
  "destination_intro": {
    "summary": "Brief overview (1 sentence only)",
    "highlights": ["Key fact 1", "Key fact 2"]
  },
  "concept": "Trip concept (2-3 sentences)",
  "timeline": [{"time":"09:00","title":"Place/Activity","desc":"Details with specific venue names"}],
  "restaurants": [{"icon":"🍜","name":"Restaurant name","desc":"Description and recommendations","price":"Price range"}],
  "hotels": [{"name":"Hotel name","desc":"Description and location","price":"Price per night"}],
  "tips": ["Tip 1","Tip 2","Tip 3"]
}
Output counts:
- '2 hours' or 'half day': timeline 3-4 items, restaurants 1-2, hotels 0
- 'day trip': timeline 6-8 items, restaurants 2-3, hotels 0
- '1 night' or more: timeline 4-6 per day, restaurants 3-4, hotels 2-3
Tips: 3. VENUE NAMING RULES: Well-known attractions, landmarks, temples, and shrines should always be named specifically (e.g. "Kinkaku-ji", "Senso-ji"). For restaurants and hotels, use real names when confident they exist; if unsure, use descriptive phrases like "local ramen shop near the station". Never fabricate venue names. For short durations, keep all spots within walking distance. Start the first timeline item from the nearest station or departure point, including transport details. Do the same for each day in multi-day trips.`,
    resultLabels: { concept:'✦ Trip Concept', timeline:'🗓 Schedule', restaurants:'🍜 Recommended Restaurants', hotels:'🏨 Recommended Hotels', tips:'💡 Travel Tips' },
  },

  zh: {
    splashText: 'AI为您规划专属旅程\n餐厅 · 住宿 · 景点一站式导览',
    splashStart: '开始使用 →',
    splashNote: '升级至高级版（付费），<br>享受无限次规划和详细行程',
    greeting: '输入目的地',
    greetingCity: '{city}',
    homeSub: 'AI推荐行程、餐厅和住宿',
    labelDest: '目的地',
    labelPop: '热门目的地',
    usageLabel: '免费剩余次数',
    nextBtn: '请输入目的地',
    nextBtnReady: '探索{city} →',
    qSub: '告诉我们您的旅行风格',
    generateBtn: '✨ 生成行程',
    loadLabel: 'AI正在为您设计完美行程…',
    loadSteps: ['分析目的地','筛选热门景点','制定行程','搜索餐厅和住宿','最终优化'],
    retryBtn: '修改条件',
    newBtn: '规划新旅程',
    questions: [
      { key:'style', emoji:'🎯', label:'旅行风格？', opts:[
        {icon:'🏛️',label:'观光游览',val:'观光和文化体验'},
        {icon:'🍜',label:'美食探索',val:'美食之旅和餐厅探索'},
        {icon:'🌿',label:'自然户外',val:'自然和户外活动'},
        {icon:'🛍️',label:'购物休闲',val:'购物和咖啡馆巡游'},
      ]},
      { key:'budget', emoji:'💰', label:'预算范围？', opts:[
        {icon:'💴',label:'经济（¥5千/天）',val:'经济实惠（每天5000日元以内）'},
        {icon:'💳',label:'适中（¥1.5万）',val:'适中（每天5000-15000日元）'},
        {icon:'✨',label:'舒适',val:'舒适（每天15000-30000日元）'},
        {icon:'👑',label:'豪华',val:'豪华（不限预算）'},
      ]},
      { key:'food', emoji:'🍽️', label:'饮食偏好？', opts:[
        {icon:'🥢',label:'当地料理',val:'当地和传统日本料理'},
        {icon:'☕',label:'咖啡馆和西餐',val:'时尚咖啡馆和西餐'},
        {icon:'🍡',label:'街头小吃',val:'平价街头美食'},
        {icon:'😊',label:'无特别偏好',val:'无特别偏好'},
      ]},
      { key:'member', emoji:'👥', label:'出行人员？', opts:[
        {icon:'🧍',label:'独行',val:'独自旅行'},
        {icon:'💑',label:'情侣',val:'情侣或夫妻旅行'},
        {icon:'👫',label:'朋友团',val:'朋友群体旅行'},
        {icon:'👨‍👩‍👧',label:'家庭出游',val:'带孩子的家庭旅行'},
      ]},
      { key:'days', emoji:'⏱️', label:'时间 / 天数？', opts:[
        {icon:'⏱️',label:'2小时',val:'2小时（散步・约会・短途）'},
        {icon:'🌤️',label:'半天',val:'半天（3～4小时）'},
        {icon:'🌄',label:'当天往返',val:'当天往返'},
        {icon:'🌙',label:'1晚2天',val:'1晚2天'},
        {icon:'🌙🌙',label:'2晚3天',val:'2晚3天'},
        {icon:'✈️',label:'3晚以上',val:'3晚以上'},
      ]},
    ],
    destinations: [
      {name:'京都',en:'Kyoto',icon:'🏯',bg:'#1e1a2e'},
      {name:'东京',en:'Tokyo',icon:'🗼',bg:'#1a1e2e'},
      {name:'大阪',en:'Osaka',icon:'🎭',bg:'#2e1a1a'},
      {name:'冲绳',en:'Okinawa',icon:'🌺',bg:'#1a2e2a'},
      {name:'北海道',en:'Hokkaido',icon:'🦀',bg:'#1a2230'},
      {name:'奈良',en:'Nara',icon:'🦌',bg:'#1e2a1a'},
    ],
    promptTemplate: (city, a, now) => `你是一位全球旅游专家。
目的地：${city}
${now ? `当前时间：${now.time}（现在出发，请从此时间开始安排行程。${now.sameDay ? '这是当天行程，所有活动须在当天内完成，不得延续到第二天。' : '这是多日行程，从此时间出发正常安排即可。'}）` : '出行时间：计划中（请使用早上8-9点的标准出发时间）'}
风格：${a.style}
预算：${a.budget}
餐饮：${a.food}
同行：${a.member}
天数：${a.days}

仅返回以下JSON格式，不要包含其他文字：
{
  "destination_intro": {
    "summary": "目的地简介（仅1句话）",
    "highlights": ["特点1", "特点2"]
  },
  "concept": "旅行概念（2-3句话）",
  "timeline": [{"time":"09:00","title":"地点/活动名称","desc":"详细说明（包含具体地点名称）"}],
  "restaurants": [{"icon":"🍜","name":"餐厅名称","desc":"描述和推荐菜品","price":"价格范围"}],
  "hotels": [{"name":"酒店名称","desc":"描述和位置","price":"每晚价格"}],
  "tips": ["建议1","建议2","建议3"]
}`,
    resultLabels: { concept:'✦ 旅行概念', timeline:'🗓 行程安排', restaurants:'🍜 推荐餐厅', hotels:'🏨 推荐住宿', tips:'💡 旅行贴士' },
  },

  ko: {
    splashText: 'AI가 당신만의 여행을 계획\n맛집 · 숙소 · 관광지 원스톱 가이드',
    splashStart: '시작하기 →',
    splashNote: '프리미엄（유료）으로<br>무제한 사용 및 상세 일정을 이용하세요',
    greeting: '목적지 입력',
    greetingCity: '{city}',
    homeSub: 'AI가 일정, 맛집, 숙소를 추천합니다',
    labelDest: '목적지',
    labelPop: '인기 목적지',
    usageLabel: '무료 남은 횟수',
    nextBtn: '목적지를 입력해 주세요',
    nextBtnReady: '{city} 탐색하기 →',
    qSub: '여행 스타일을 알려주세요',
    generateBtn: '✨ 일정 생성하기',
    loadLabel: 'AI가 최적의 여행 일정을 만들고 있습니다…',
    loadSteps: ['목적지 정보 분석 중','추천 스팟 선정 중','일정 구성 중','맛집 및 숙소 조사 중','최종 마무리 중'],
    retryBtn: '조건 변경',
    newBtn: '새 여행 계획',
    questions: [
      { key:'style', emoji:'🎯', label:'여행 스타일은？', opts:[
        {icon:'🏛️',label:'관광 명소',val:'관광지 및 문화 체험'},
        {icon:'🍜',label:'맛집 탐방',val:'미식 투어 및 맛집 탐방'},
        {icon:'🌿',label:'자연 아웃도어',val:'자연 및 아웃도어 체험'},
        {icon:'🛍️',label:'쇼핑',val:'쇼핑 및 카페 탐방'},
      ]},
      { key:'budget', emoji:'💰', label:'예산은？', opts:[
        {icon:'💴',label:'절약（¥5천/일）',val:'절약 여행 (하루 5,000엔 이내)'},
        {icon:'💳',label:'보통（¥1.5만）',val:'보통 (하루 5,000~15,000엔)'},
        {icon:'✨',label:'여유롭게',val:'여유로운 여행 (하루 15,000~30,000엔)'},
        {icon:'👑',label:'럭셔리',val:'럭셔리 여행 (예산 무제한)'},
      ]},
      { key:'food', emoji:'🍽️', label:'음식 선호도는？', opts:[
        {icon:'🥢',label:'향토 요리',val:'현지 전통 일본 요리'},
        {icon:'☕',label:'카페 & 양식',val:'트렌디한 카페 및 양식'},
        {icon:'🍡',label:'B급 맛집',val:'가성비 길거리 음식'},
        {icon:'😊',label:'상관없음',val:'특별한 선호 없음'},
      ]},
      { key:'member', emoji:'👥', label:'함께하는 사람은？', opts:[
        {icon:'🧍',label:'혼자 여행',val:'혼자 여행'},
        {icon:'💑',label:'커플',val:'커플 또는 부부 여행'},
        {icon:'👫',label:'친구 그룹',val:'친구들과 여행'},
        {icon:'👨‍👩‍👧',label:'가족 여행',val:'아이와 함께하는 가족 여행'},
      ]},
      { key:'days', emoji:'⏱️', label:'시간 / 기간은？', opts:[
        {icon:'⏱️',label:'2시간',val:'2시간（산책・데이트・짧은 여행）'},
        {icon:'🌤️',label:'반나절',val:'반나절（3～4시간）'},
        {icon:'🌄',label:'당일치기',val:'당일치기'},
        {icon:'🌙',label:'1박 2일',val:'1박 2일'},
        {icon:'🌙🌙',label:'2박 3일',val:'2박 3일'},
        {icon:'✈️',label:'3박 이상',val:'3박 이상'},
      ]},
    ],
    destinations: [
      {name:'교토',en:'Kyoto',icon:'🏯',bg:'#1e1a2e'},
      {name:'도쿄',en:'Tokyo',icon:'🗼',bg:'#1a1e2e'},
      {name:'오사카',en:'Osaka',icon:'🎭',bg:'#2e1a1a'},
      {name:'오키나와',en:'Okinawa',icon:'🌺',bg:'#1a2e2a'},
      {name:'홋카이도',en:'Hokkaido',icon:'🦀',bg:'#1a2230'},
      {name:'나라',en:'Nara',icon:'🦌',bg:'#1e2a1a'},
    ],
    promptTemplate: (city, a, now) => `당신은 전 세계 여행 전문 컨시어지입니다.
목적지: ${city}
${now ? `현재 시각: ${now.time}（지금 출발 — 이 시간부터 일정 구성. ${now.sameDay ? '당일 일정이므로 모든 활동을 당일 내로 마무리할 것. 다음 날로 넘기지 말 것.' : '숙박 일정이므로 이 시간부터 정상적으로 구성할 것.'}）` : '여행 시기: 계획 중（오전 8-9시 표준 출발 시간으로 구성）'}
여행 스타일: ${a.style}
예산: ${a.budget}
음식: ${a.food}
동행: ${a.member}
기간: ${a.days}

다른 텍스트 없이 JSON만 반환해 주세요:
{
  "destination_intro": {
    "summary": "목적지 소개 (1문장)",
    "highlights": ["특징1", "특징2"]
  },
  "concept": "여행 콘셉트 (2-3문장)",
  "timeline": [{"time":"09:00","title":"장소/활동명","desc":"구체적인 장소명 포함 상세 설명"}],
  "restaurants": [{"icon":"🍜","name":"식당명","desc":"설명 및 추천 메뉴","price":"가격대"}],
  "hotels": [{"name":"숙소명","desc":"설명 및 위치","price":"1박 가격"}],
  "tips": ["팁1","팁2","팁3"]
}`,
    resultLabels: { concept:'✦ 여행 콘셉트', timeline:'🗓 일정', restaurants:'🍜 추천 맛집', hotels:'🏨 추천 숙소', tips:'💡 여행 팁' },
  },
};

// ════════════════════════════════
// LANG
// ════════════════════════════════
function setLang(l) {
  lang = l;
  document.querySelectorAll('.lang-btn').forEach(b => {
    b.classList.toggle('active', b.dataset.lang === l);
  });
  const t = T[lang];

  const st = document.getElementById('splash-text');
  if(st) st.innerHTML = t.splashText.replace(/\n/g,'<br>');
  const ss = document.getElementById('splash-start-btn');
  if(ss) ss.textContent = t.splashStart;
  const sn = document.getElementById('splash-note');
  if(sn) sn.innerHTML = t.splashNote;
  const warnTexts = {
    ja: { title:'条件を変更しますか？', body:'画面を戻ると回数が新たにカウントされます。この提案は保存されませんので、必要であればスクリーンショットを取っておいてください。', close:'閉じる', confirm:'条件変更' },
    en: { title:'Change preferences?', body:'Going back will use another free count. This plan will not be saved — please take a screenshot if needed.', close:'Close', confirm:'Change' },
    zh: { title:'要修改条件吗？', body:'返回将重新计算使用次数。此方案不会被保存，如需保留请截图。', close:'关闭', confirm:'修改条件' },
    ko: { title:'조건을 변경하시겠어요?', body:'돌아가면 횟수가 새로 카운트됩니다. 이 제안은 저장되지 않으니 필요하면 스크린샷을 찍어두세요.', close:'닫기', confirm:'조건 변경' },
  };
  const w = warnTexts[l] || warnTexts.ja;
  const wTitle = document.getElementById('warn-title');
  const wBody = document.getElementById('warn-body');
  const wClose = document.getElementById('warn-close');
  const wConfirm = document.getElementById('warn-confirm');
  if(wTitle) wTitle.textContent = w.title;
  if(wBody) wBody.textContent = w.body;
  if(wClose) wClose.textContent = w.close;
  if(wConfirm) wConfirm.textContent = w.confirm;
  const retryBtn = document.getElementById('result-retry-btn');
  if(retryBtn) retryBtn.textContent = t.retryBtn;
  const saveLabels = { ja:'💾 保存して条件変更', en:'💾 Save & Change', zh:'💾 保存并修改', ko:'💾 저장 후 변경' };
  const newBtn = document.getElementById('result-new-btn');
  if(newBtn) { newBtn.textContent = saveLabels[l] || saveLabels.ja; newBtn.onclick = showComingSoon; }
  const premiumTexts = {
    ja: { title:'LOCATEプレミアム', sub:'旅をもっと深く、もっと自由に', pf1:'無制限プラン生成', pf1d:'何度でも旅程を作り直せます', pf2:'複数日程プラン（最大7日間）', pf2d:'長期旅行も詳細にプランニング', pf3:'旅程の保存・共有', pf3d:'お気に入りのプランをシェア', pf4:'マップ連携', pf4d:'Google Mapsで即ナビ開始', pf5:'オフライン対応', pf5d:'電波のない場所でも旅程を確認', p1name:'月額プラン', p1per:'/ 月', p1desc:'いつでもキャンセル可能', p2name:'年額プラン', p2per:'/ 年', p2desc:'月額より34%お得 · 月あたり¥317', cta:'プレミアムを始める', note:'いつでもキャンセル可能 · 安全なStripe決済' },
    en: { title:'LOCATE Premium', sub:'Deeper travel, more freedom', pf1:'Unlimited plan generation', pf1d:'Regenerate itineraries as many times as you like', pf2:'Multi-day plans (up to 7 days)', pf2d:'Detailed planning for longer trips', pf3:'Save & share itineraries', pf3d:'Share your favorite plans', pf4:'Map integration', pf4d:'Launch navigation instantly in Google Maps', pf5:'Offline access', pf5d:'View your itinerary without internet', p1name:'Monthly plan', p1per:'/ mo', p1desc:'Cancel anytime', p2name:'Annual plan', p2per:'/ yr', p2desc:'34% cheaper than monthly · ¥317/mo', cta:'Start Premium', note:'Cancel anytime · Secure Stripe payment' },
    zh: { title:'LOCATE高级版', sub:'更深入的旅行，更多自由', pf1:'无限次行程生成', pf1d:'随时重新规划行程', pf2:'多日行程（最多7天）', pf2d:'长途旅行也能详细规划', pf3:'保存和分享行程', pf3d:'分享您喜欢的行程', pf4:'地图集成', pf4d:'即时在Google Maps导航', pf5:'离线访问', pf5d:'无网络也能查看行程', p1name:'月付方案', p1per:'/ 月', p1desc:'随时取消', p2name:'年付方案', p2per:'/ 年', p2desc:'比月付便宜34% · 每月¥317', cta:'开始高级版', note:'随时取消 · 安全的Stripe支付' },
    ko: { title:'LOCATE 프리미엄', sub:'더 깊은 여행, 더 많은 자유', pf1:'무제한 일정 생성', pf1d:'원하는 만큼 일정을 다시 만들 수 있어요', pf2:'다일정 플랜 (최대 7일)', pf2d:'장기 여행도 상세하게 플래닝', pf3:'일정 저장 및 공유', pf3d:'마음에 드는 플랜을 공유하세요', pf4:'지도 연동', pf4d:'Google Maps로 즉시 내비게이션 시작', pf5:'오프라인 지원', pf5d:'인터넷 없이도 일정 확인 가능', p1name:'월간 플랜', p1per:'/ 월', p1desc:'언제든지 취소 가능', p2name:'연간 플랜', p2per:'/ 년', p2desc:'월간보다 34% 저렴 · 월 ¥317', cta:'프리미엄 시작하기', note:'언제든지 취소 가능 · 안전한 Stripe 결제' },
  };
  const p = premiumTexts[l] || premiumTexts.ja;
  const setT = (id, txt) => { const el = document.getElementById(id); if(el) el.textContent = txt; };
  setT('premium-title', p.title); setT('premium-sub', p.sub);
  setT('pf1-name', p.pf1); setT('pf1-desc', p.pf1d);
  setT('pf2-name', p.pf2); setT('pf2-desc', p.pf2d);
  setT('pf3-name', p.pf3); setT('pf3-desc', p.pf3d);
  setT('pf4-name', p.pf4); setT('pf4-desc', p.pf4d);
  setT('pf5-name', p.pf5); setT('pf5-desc', p.pf5d);
  setT('plan1-name', p.p1name); setT('plan1-per', p.p1per); setT('plan1-desc', p.p1desc);
  setT('plan2-name', p.p2name); setT('plan2-per', p.p2per); setT('plan2-desc', p.p2desc);
  setT('premium-cta', p.cta); setT('premium-note', p.note);
  const backLabel = {ja:'戻る', en:'Back', zh:'返回', ko:'뒤로'}[l] || '戻る';
  const blHome = document.getElementById('back-label-home');
  const blQ = document.getElementById('back-label-q');
  if(blHome) blHome.textContent = backLabel;
  if(blQ) blQ.textContent = backLabel;
  const blP = document.getElementById('back-label-premium');
  if(blP) blP.textContent = backLabel;
  const langLabel = {ja:'言語を選択', en:'Select Language', zh:'选择语言', ko:'언어 선택'}[l] || '言語を選択';
  const sll = document.getElementById('splash-lang-label');
  if(sll) sll.textContent = langLabel;
  const freeLabel = {ja:'無料で3回まで利用可能', en:'3 free uses available', zh:'免费使用3次', ko:'무료로 3번 이용 가능'}[l] || '無料で3回まで利用可能';
  const sfl = document.getElementById('splash-free-label');
  if(sfl) sfl.textContent = freeLabel;
  clearError();
  updateDisclaimerLang(l);
  updateHomeUI();
  renderDestChips();
}

function updateHomeUI() {
  const t = T[lang];
  const greeting = document.getElementById('home-greeting');
  if(greeting) { greeting.textContent = t.greeting; }
  const sub = document.getElementById('home-sub');
  if(sub) sub.textContent = t.homeSub;
  const ld = document.getElementById('label-destination');
  if(ld) ld.textContent = t.labelDest;
  const lp = document.getElementById('label-popular');
  if(lp) lp.textContent = t.labelPop;
  const ul = document.getElementById('usage-label');
  if(ul) ul.textContent = t.usageLabel;
  updateUsageDisplay();
  const nb = document.getElementById('home-next-label');
  if(nb) {
    nb.textContent = currentCity
      ? t.nextBtnReady.replace('{city}', currentCity)
      : t.nextBtn;
  }
  document.getElementById('home-next-btn').disabled = !currentCity;
}

// ════════════════════════════════
// SCREENS
// ════════════════════════════════
const screenHistory = [];

function showScreen(id) {
  const current = document.querySelector('.screen.active')?.id;
  if(current && current !== id) screenHistory.push(current);
  document.querySelectorAll('.screen').forEach(s => s.classList.remove('active'));
  document.getElementById(id).classList.add('active');
  window.scrollTo(0,0);
}

function goBack() {
  if(screenHistory.length > 0) {
    const prev = screenHistory.pop();
    document.querySelectorAll('.screen').forEach(s => s.classList.remove('active'));
    document.getElementById(prev).classList.add('active');
    window.scrollTo(0,0);
  } else {
    showScreen('screen-splash');
  }
}

// ════════════════════════════════
// DESTINATIONS
// ════════════════════════════════
function renderDestChips() {
  const wrap = document.getElementById('dest-chips');
  if(!wrap) return;
  const dests = T[lang].destinations;
  wrap.innerHTML = dests.map(d => `
    <div class="dest-card" onclick="selectCity('${d.name}')" style="background:${d.bg}">
      <div class="dest-card-bg">${d.icon}</div>
      <div class="dest-card-overlay">
        <div class="dest-card-name">${d.name}</div>
        <div class="dest-card-en">${d.en}</div>
      </div>
    </div>
  `).join('');
}

// ════════════════════════════════
// CITY INPUT
// ════════════════════════════════
document.addEventListener('DOMContentLoaded', () => {
  applyFontSize();
  setLang('ja');
  renderDestChips();
  updateUsageDisplay();

  document.getElementById('city-input').addEventListener('input', function() {
    currentCity = this.value.trim();
    document.getElementById('clear-btn').style.display = currentCity ? 'block' : 'none';
    updateHomeUI();
  });

  document.getElementById('city-input').addEventListener('keydown', e => {
    if(e.key === 'Enter' && currentCity) confirmCity();
  });
});

function clearCity() {
  currentCity = '';
  document.getElementById('city-input').value = '';
  document.getElementById('clear-btn').style.display = 'none';
  updateHomeUI();
}

function selectCity(city) {
  currentCity = city;
  document.getElementById('city-input').value = city;
  document.getElementById('clear-btn').style.display = 'block';
  updateHomeUI();
}

function useGPS() {
  if(!navigator.geolocation) { showToast({ja:'GPSが利用できません',en:'GPS not available',zh:'GPS不可用',ko:'GPS를 사용할 수 없습니다'}[lang]||'GPS not available'); return; }
  const btn = document.querySelector('.gps-btn');
  btn.textContent = '⏳';
  navigator.geolocation.getCurrentPosition(async pos => {
    try {
      const r = await fetch(`https://nominatim.openstreetmap.org/reverse?lat=${pos.coords.latitude}&lon=${pos.coords.longitude}&format=json&accept-language=${lang}`);
      const d = await r.json();
      const city = d.address.city || d.address.town || d.address.village || d.address.county || 'Current Location';
      selectCity(city);
    } catch(e) {
      selectCity('Current Location');
    }
    btn.textContent = '📍';
  }, () => {
    showToast({ja:'位置情報を取得できませんでした',en:'Could not get location',zh:'无法获取位置',ko:'위치를 가져올 수 없습니다'}[lang]||'Could not get location');
    btn.textContent = '📍';
  });
}

// ════════════════════════════════
// USAGE
// ════════════════════════════════
function updateUsageDisplay() {
  document.getElementById('usage-count').textContent = `${freeUsage} / 3`;
  document.getElementById('usage-fill').style.width = `${(freeUsage/3)*100}%`;
}

// ════════════════════════════════
// QUESTIONS
// ════════════════════════════════
let confirmedCity = '';
let confirmedLocation = '';

async function confirmCity() {
  if(!currentCity) return;

  const broadAreaPattern = /^(日本|全国|関東|関西|九州|四国|東北|北海道|中部|近畿|中国地方|アジア|ヨーロッパ|アメリカ|世界|japan|asia|europe|america|world|africa|oceania|中国|韓国|korea|china|france|germany|italy|spain|australia|canada|brazil|india|全域|全土)$/i;
  if(broadAreaPattern.test(currentCity.trim())) {
    const msg = {
      ja: '範囲が広すぎます。例：東京、京都、大阪、札幌など具体的な都市名を入力してください',
      en: 'Too broad. Please enter a specific city. Ex: Tokyo, Kyoto, London',
      zh: '范围太广。请输入具体城市名。例：东京、京都、大阪',
      ko: '범위가 너무 넓습니다. 예: 도쿄, 교토, 오사카',
    };
    showToast(msg[lang] || msg.ja);
    document.getElementById('city-input').select();
    return;
  }

  const ambiguous = checkAmbiguous(currentCity.trim());
  if(ambiguous && lang === 'ja') {
    showDisambiguationPopup(ambiguous);
    return;
  }

  const t = T[lang];
  const overlay = document.getElementById('city-confirm-overlay');
  const nameEl = document.getElementById('city-confirm-name');
  const descEl = document.getElementById('city-confirm-desc');
  const labelEl = document.getElementById('city-confirm-label');
  const yesBtn = document.getElementById('city-confirm-yes');
  const noBtn = document.getElementById('city-confirm-no');

  const confirmLabels = {
    ja: {label:'目的地の確認', loading:'地名を確認中...', confirm:'こちらで間違いないですか？', yes:'はい、進む →', no:'再度入力'},
    en: {label:'Confirm destination', loading:'Checking destination...', confirm:'Is this correct?', yes:'Yes, continue →', no:'Re-enter'},
    zh: {label:'确认目的地', loading:'正在确认地名...', confirm:'请确认是否正确？', yes:'是，继续 →', no:'重新输入'},
    ko: {label:'목적지 확인', loading:'지명 확인 중...', confirm:'맞으신가요？', yes:'네, 계속 →', no:'다시 입력'},
  };
  const cl = confirmLabels[lang] || confirmLabels.ja;

  labelEl.textContent = cl.label;
  yesBtn.textContent = cl.yes;
  yesBtn.disabled = true;
  noBtn.textContent = cl.no;
  nameEl.textContent = cl.loading;
  descEl.textContent = '';
  document.getElementById('city-confirm-question').textContent = '';
  yesBtn.style.display = 'none';
  noBtn.style.display = 'none';
  overlay.style.display = 'flex';

  try {
    const promptMap = {
      ja: `「${currentCity}」という場所について、必ず日本語でJSONオブジェクトのみを返してください。他のテキスト不可。形式：{"name":"日本語の正式名称（例：瀬戸市）","location":"所在地（例：愛知県）","desc":"旅行者向けの1〜2文の日本語説明。"} マークダウン不可。英語での回答不可。`,
      en: `You must return ONLY a JSON object with no other text. For the place "${currentCity}", respond with exactly this format: {"name":"Manchester","location":"Greater Manchester, United Kingdom","desc":"One or two sentences about this destination for travelers."} Do not include any explanation or markdown.`,
      zh: `必须用中文回答。请只返回一个JSON对象，不要其他任何文字。关于地点"${currentCity}"，格式如下：{"name":"正式名称（例：曼彻斯特）","location":"所在地（例：英格兰，英国）","desc":"给旅行者的1-2句中文介绍。"} 不要Markdown。禁止使用英文。`,
      ko: `반드시 한국어로만 답하세요. "${currentCity}" 장소에 대해 JSON 객체만 반환하세요. 다른 텍스트 불가. 형식: {"name":"정식 명칭（예: 맨체스터）","location":"소재지（예: 잉글랜드, 영국）","desc":"여행자를 위한 1-2문장 한국어 설명."} 마크다운 불가. 영어 사용 불가.`,
    };
    const res = await fetch('/api/generate', {
      method:'POST',
      headers:{'Content-Type':'application/json'},
      body: JSON.stringify({prompt: promptMap[lang] || promptMap.ja})
    });
    const data = await res.json();
    console.log('confirm API raw response:', JSON.stringify(data).slice(0, 300));
    let raw = (data.content || []).map(c => c.text||'').join('');
    raw = raw.replace(/^```[\w]*\s*/,'').replace(/\s*```\s*$/,'').trim();
    const j = raw.indexOf('{'), k = raw.lastIndexOf('}');
    if(j !== -1 && k !== -1) raw = raw.slice(j, k+1);
    const info = JSON.parse(raw);
    const displayName = currentCity;
    const displayLocation = (info.location || '').trim();
    const displayDesc = (info.desc || '').trim();
    nameEl.textContent = displayName + (displayLocation ? '　' + displayLocation : '');
    descEl.textContent = displayDesc;
    document.getElementById('city-confirm-question').textContent = cl.confirm;
    confirmedCity = currentCity;
    confirmedLocation = displayLocation;
  } catch(e) {
    confirmedCity = currentCity;
    nameEl.textContent = currentCity;
    descEl.textContent = '';
    document.getElementById('city-confirm-question').textContent = cl.confirm;
  }

  yesBtn.style.display = '';
  noBtn.style.display = '';
  yesBtn.disabled = false;
}

let tripTiming = 'plan';

function acceptCityConfirm() {
  document.getElementById('city-confirm-overlay').style.display = 'none';
  if(confirmedCity) currentCity = confirmedCity;
  showTimingPopup();
}

function showTimingPopup() {
  const labels = {
    ja: { label:'この旅はいつ？', title:'旅のタイミングを教えてください', desc:'提案するスケジュールの時間軸が変わります。', planLabel:'計画中', planSub:'日時未定・標準的な時間軸', nowLabel:'今すぐ出発', nowSub:'現在時刻から提案' },
    en: { label:'When is this trip?', title:'Tell us your travel timing', desc:'This changes how we schedule your itinerary.', planLabel:'Planning ahead', planSub:'Flexible dates', nowLabel:'Leaving now', nowSub:'Based on current time' },
    zh: { label:'这次旅行是什么时候？', title:'请告诉我们您的出行时间', desc:'这将影响我们为您规划的行程时间轴。', planLabel:'计划中', planSub:'日期未定', nowLabel:'现在出发', nowSub:'根据当前时间推荐' },
    ko: { label:'이 여행은 언제인가요？', title:'여행 시기를 알려주세요', desc:'일정 시간축이 달라집니다.', planLabel:'계획 중', planSub:'날짜 미정', nowLabel:'지금 출발', nowSub:'현재 시간 기준 추천' },
  };
  const l = labels[lang] || labels.ja;
  document.getElementById('timing-label').textContent = l.label;
  document.getElementById('timing-title').textContent = l.title;
  document.getElementById('timing-desc').textContent = l.desc;
  document.getElementById('timing-plan-label').textContent = l.planLabel;
  document.getElementById('timing-plan-sub').textContent = l.planSub;
  document.getElementById('timing-now-label').textContent = l.nowLabel;
  document.getElementById('timing-now-sub').textContent = l.nowSub;
  document.getElementById('timing-overlay').style.display = 'flex';
}

function selectTiming(mode) {
  tripTiming = mode;
  document.getElementById('timing-overlay').style.display = 'none';
  goToQuestions();
}

function cancelCityConfirm() {
  document.getElementById('city-confirm-overlay').style.display = 'none';
  confirmedCity = '';
  const input = document.getElementById('city-input');
  input.focus();
  input.select();
}

function goToQuestions() {
  if(!currentCity) return;

  // RESULTから戻ってきた場合は前回の選択を引き継ぐ、新規の場合はリセット
  // 同じ都市で戻ってきた場合のみ前回の選択を引き継ぐ
  const isReturning = Object.keys(previousAnswers).length > 0 && previousCity === currentCity;
  answers = isReturning ? Object.assign({}, previousAnswers) : {};

  clearError();
  const t = T[lang];
  document.getElementById('q-city-name').textContent = currentCity;
  document.getElementById('q-city-sub').textContent = t.qSub;
  const qTimingBadge = document.getElementById('q-timing-badge');
  if(qTimingBadge) {
    qTimingBadge.textContent = tripTiming === 'now'
      ? ({ja:'📍 今すぐ', en:'📍 Now', zh:'📍 现在', ko:'📍 지금'}[lang] || '📍 今すぐ')
      : ({ja:'🗓 計画中', en:'🗓 Planning', zh:'🗓 计划中', ko:'🗓 계획 중'}[lang] || '🗓 計画中');
  }
  document.getElementById('generate-label').textContent = t.generateBtn;
  document.getElementById('q-error').style.display = 'none';

  const body = document.getElementById('q-body');
  body.innerHTML = t.questions.map(q => `
    <div class="q-block">
      <div class="q-label">
        <span class="q-emoji">${q.emoji}</span>${q.label}
      </div>
      <div class="q-grid">
        ${q.opts.map(o => `
          <button class="q-opt" data-q="${q.key}" data-v="${o.val}" onclick="selectOpt(this)">
            <span class="q-opt-icon">${o.icon}</span>
            <span class="q-opt-label">${o.label}</span>
          </button>
        `).join('')}
      </div>
    </div>
  `).join('');

  // 前回の選択を画面に反映（ボタンをselected状態にする）
  if(isReturning) {
    Object.keys(answers).forEach(key => {
      const btn = document.querySelector(`.q-opt[data-q="${key}"][data-v="${CSS.escape ? answers[key] : answers[key]}"]`);
      // data-v属性で正確にマッチ
      document.querySelectorAll(`.q-opt[data-q="${key}"]`).forEach(b => {
        if(b.dataset.v === answers[key]) b.classList.add('selected');
      });
    });
  }

  // プログレスバーと生成ボタンの状態を更新
  const keys = t.questions.map(q=>q.key);
  const done = keys.filter(k=>answers[k]).length;
  document.getElementById('q-progress-fill').style.width = `${(done/keys.length)*100}%`;
  document.getElementById('q-progress-text').textContent = `${done} / ${keys.length}`;
  document.getElementById('generate-btn').disabled = done < keys.length;

  updateQBadges(); // 条件バッジを更新

  showScreen('screen-questions');
}

function updateQBadges() {
  const keys = T[lang].questions.map(q=>q.key);
  const tagColors = ['tag-gold','tag-green','tag-blue','tag-purple','tag-orange'];
  const prevBadgeArea = document.getElementById('q-prev-answers');
  if(!prevBadgeArea) return;
  prevBadgeArea.innerHTML = keys.map((k,i) => answers[k]
    ? `<span class="tag ${tagColors[i]}">${answers[k].split(/[・,（(]/)[0].trim()}</span>`
    : ''
  ).join('');
}

function selectOpt(btn) {
  const q = btn.dataset.q;
  document.querySelectorAll(`[data-q="${q}"]`).forEach(b => b.classList.remove('selected'));
  btn.classList.add('selected');
  answers[q] = btn.dataset.v;

  const keys = T[lang].questions.map(q=>q.key);
  const done = keys.filter(k=>answers[k]).length;
  document.getElementById('q-progress-fill').style.width = `${(done/keys.length)*100}%`;
  document.getElementById('q-progress-text').textContent = `${done} / ${keys.length}`;
  document.getElementById('generate-btn').disabled = done < keys.length;
  updateQBadges();
}

// ════════════════════════════════
// GENERATE
// ════════════════════════════════
function showNoChangePopup() {
  const texts = {
    ja: { title:'条件は変更されていません', body:'前回と同じ条件で生成します。このまま続けますか？', cancel:'戻る', confirm:'生成する' },
    en: { title:'No changes made', body:'You\'re about to generate with the same conditions as last time. Continue?', cancel:'Back', confirm:'Generate' },
    zh: { title:'条件未更改', body:'将使用与上次相同的条件生成。要继续吗？', cancel:'返回', confirm:'生成' },
    ko: { title:'조건이 변경되지 않았습니다', body:'이전과 같은 조건으로 생성합니다. 계속하시겠어요？', cancel:'돌아가기', confirm:'생성하기' },
  };
  const t = texts[lang] || texts.ja;
  document.getElementById('no-change-title').textContent = t.title;
  document.getElementById('no-change-body').textContent = t.body;
  document.getElementById('no-change-cancel').textContent = t.cancel;
  document.getElementById('no-change-confirm').textContent = t.confirm;
  document.getElementById('no-change-overlay').style.display = 'flex';
}

function hideNoChangePopup() {
  document.getElementById('no-change-overlay').style.display = 'none';
}

function forceGenerate() {
  hideNoChangePopup();
  previousAnswers = {}; // リセットして再度同じ条件でも通過させる
  doGenerate();
}

async function generatePlan() {
  // RESULTから戻って何も変えていない場合はポップアップを出す
  const keys = T[lang].questions.map(q=>q.key);
  const allAnswered = keys.every(k => answers[k]);
  if(allAnswered && Object.keys(previousAnswers).length > 0) {
    const unchanged = keys.every(k => answers[k] === previousAnswers[k]);
    if(unchanged) {
      showNoChangePopup();
      return;
    }
  }
  // 条件が変わっていたらpreviousAnswersをリセット
  previousAnswers = {};
  await doGenerate();
}

async function doGenerate() {
  if(freeUsage <= 0) {
    showScreen('screen-premium');
    return;
  }

  showScreen('screen-loading');
  document.getElementById('load-city').textContent = currentCity;

  const t = T[lang];
  document.getElementById('load-label').textContent = t.loadLabel;
  const stepsEl = document.getElementById('load-steps');
  stepsEl.innerHTML = t.loadSteps.map((s,i) => `
    <div class="load-step" id="ls${i}">
      <div class="load-step-dot"></div>${s}
    </div>
  `).join('');

  for(let i=0;i<t.loadSteps.length;i++) {
    await delay(500);
    if(i>0) document.getElementById(`ls${i-1}`).className='load-step done';
    document.getElementById(`ls${i}`).className='load-step active';
  }

  const now = new Date();
  const currentTime = `${now.getHours()}:${String(now.getMinutes()).padStart(2,'0')}`;
  const cityWithLocation = confirmedLocation ? currentCity + '（' + confirmedLocation + '）' : currentCity;
  const isDayTrip = answers.days && /2時間|半日|日帰り|2 hours|half day|day trip|当天|당일/.test(answers.days);
  const timeContext = tripTiming === 'now' ? { time: currentTime, sameDay: isDayTrip } : null;
  const prompt = t.promptTemplate(cityWithLocation, answers, timeContext);

  try {
    const res = await fetch('/api/generate', {
      method:'POST',
      headers:{'Content-Type':'application/json'},
      body: JSON.stringify({ prompt })
    });

    if(!res.ok) {
      const httpErrMsg = {ja:`通信エラーが発生しました (HTTP ${res.status})。もう一度お試しください。`, en:`Connection error (HTTP ${res.status}). Please try again.`, zh:`连接错误 (HTTP ${res.status})，请重试。`, ko:`연결 오류 (HTTP ${res.status}). 다시 시도해 주세요.`};
      throw new Error(httpErrMsg[lang] || httpErrMsg.en);
    }

    let responseText = await res.text();
    if(responseText.includes('<!DOCTYPE')) {
      const htmlErrMsg = {ja:'サーバーへの接続に失敗しました。しばらくしてからもう一度お試しください。', en:'Failed to connect to server. Please try again later.', zh:'连接服务器失败，请稍后重试。', ko:'서버 연결에 실패했습니다. 잠시 후 다시 시도해 주세요.'};
      throw new Error(htmlErrMsg[lang] || htmlErrMsg.en);
    }

    const data = JSON.parse(responseText);
    let raw = data.content.map(c=>c.text||'').join('');
    raw = raw.replace(/^```[\w]*\s*/,'').replace(/\s*```\s*$/,'').trim();
    const jsonStart = raw.indexOf('{');
    const jsonEnd = raw.lastIndexOf('}');
    if(jsonStart !== -1 && jsonEnd !== -1) {
      raw = raw.slice(jsonStart, jsonEnd + 1);
    }
    let plan;
    try { plan = JSON.parse(raw); }
    catch(e) {
      const parseErrMsg = {ja:'AIの応答をパースできませんでした。もう一度お試しください。', en:'Failed to parse AI response. Please try again.', zh:'无法解析AI响应，请重试。', ko:'AI 응답을 파싱할 수 없습니다. 다시 시도해 주세요.'};
      throw new Error(parseErrMsg[lang] || parseErrMsg.en);
    }

    t.loadSteps.forEach((_,i) => {
      const el = document.getElementById(`ls${i}`);
      if(el) el.className='load-step done';
    });

    freeUsage = Math.max(0, freeUsage-1);
    localStorage.setItem('locateFreeUsage', freeUsage);
    updateUsageDisplay();
    renderResult(plan);

  } catch(e) {
    showScreen('screen-questions');
    const errEl = document.getElementById('q-error');
    const errPrefix = {ja:'エラー: ', en:'Error: ', zh:'错误：', ko:'오류: '};
    errEl.textContent = (errPrefix[lang] || errPrefix.ja) + e.message;
    errEl.style.display = 'block';
  }
}

function delay(ms) { return new Promise(r=>setTimeout(r,ms)); }

// ════════════════════════════════
// RENDER RESULT
// ════════════════════════════════
let lastPlan = null;

function renderResult(plan) {
  lastPlan = plan;
  const t = T[lang];
  document.getElementById('result-city').textContent = currentCity;

  const badges = document.getElementById('result-badges');
  const timingLabel = tripTiming === 'now'
    ? {ja:'📍 今すぐ', en:'📍 Now', zh:'📍 现在', ko:'📍 지금'}[lang] || '📍 今すぐ'
    : {ja:'🗓 計画中', en:'🗓 Planning', zh:'🗓 计划中', ko:'🗓 계획 중'}[lang] || '🗓 計画中';
  badges.innerHTML = [
    `<span class="tag tag-teal">${timingLabel}</span>`,
    answers.style   ? `<span class="tag tag-gold">${answers.style.split(/[・,（]/)[0].trim()}</span>` : '',
    answers.budget  ? `<span class="tag tag-green">${answers.budget.split(/[（]/)[0].trim()}</span>` : '',
    answers.food    ? `<span class="tag tag-blue">${answers.food.split(/[・,（]/)[0].trim()}</span>` : '',
    answers.member  ? `<span class="tag tag-purple">${answers.member.split(/[・,（]/)[0].trim()}</span>` : '',
    answers.days    ? `<span class="tag tag-orange">${answers.days.split(/[（]/)[0].trim()}</span>` : '',
  ].join('');

  const body = document.getElementById('result-body');
  let html = '';

  if(plan.destination_intro) {
    const di = plan.destination_intro;
    const introLabel = {ja:'📍 この目的地について', en:'📍 About this destination', zh:'📍 关于目的地', ko:'📍 목적지 소개'}[lang] || '📍 この目的地について';
    const highlightsHtml = (di.highlights||[]).map(function(h) {
      return '<div class="dest-intro-highlight"><div class="dest-intro-dot"></div><span>' + h + '</span></div>';
    }).join('');
    html += '<div class="result-section">'
      + '<div class="dest-intro">'
      + '<div class="dest-intro-label">' + introLabel + '</div>'
      + '<div class="dest-intro-summary">' + (di.summary||'') + '</div>'
      + '<div class="dest-intro-highlights">' + highlightsHtml + '</div>'
      + '</div>'
      + '</div>';
  }

  if(plan.concept) {
    html += `<div class="result-section">
      <div class="result-section-title">${t.resultLabels.concept}</div>
      <div class="result-content">${plan.concept}</div>
    </div>`;
  }

  if(plan.timeline?.length) {
    const noteStart = {ja:'⚠️ 表示時刻は現地での行動時間の目安です。出発・移動時間を加えてご計画ください。', en:'⚠️ Times shown are approximate activity times. Please account for travel time to each location.', zh:'⚠️ 显示时间为现场活动的参考时间，请加上出行和交通时间。', ko:'⚠️ 표시 시간은 현지 활동 기준입니다. 이동 시간을 추가로 고려해 주세요.'};
    const noteEnd = {ja:'🏠 最後の場所からの帰路・移動時間もお忘れなく。', en:"🏠 Don't forget to account for your return journey after the last stop.", zh:'🏠 别忘了最后一个地点的返程时间。', ko:'🏠 마지막 장소에서의 귀로 시간도 잊지 마세요.'};
    let seenDays = new Set();
    let timelineHtml = '';
    plan.timeline.forEach(function(item, i) {
      const timeStr = item.time || '';
      const dayMatch = timeStr.match(/Day\s*(\d+)/i);
      if(dayMatch) {
        const dayKey = dayMatch[0];
        if(!seenDays.has(dayKey)) {
          seenDays.add(dayKey);
          timelineHtml += '<div class="tl-day-label">Day ' + dayMatch[1] + '</div>';
        }
      }
      const cleanTime = timeStr.replace(/Day\s*\d+\s*/i, '');
      const line = i < plan.timeline.length - 1 ? '<div class="tl-line"></div>' : '';
      const mapQuery = encodeURIComponent((item.title||'') + ' ' + currentCity);
      const mapUrl = 'https://www.google.com/maps/search/?api=1&query=' + mapQuery;
      const mapLinkLabel = ({'ja':'地図で見る', 'en':'View on Maps', 'zh':'查看地图', 'ko':'지도 보기'})[lang] || '地図で見る';
      const mapLink = '<a href="' + mapUrl + '" target="_blank" rel="noopener" style="font-size:11px;color:var(--gold);text-decoration:none;display:inline-flex;align-items:center;gap:3px;margin-top:6px;opacity:.85">🗺 ' + mapLinkLabel + '</a>';
      timelineHtml += '<div class="tl-item">'
        + '<div class="tl-left">'
        + '<div class="tl-time">' + cleanTime + '</div>'
        + '<div class="tl-badge">' + (i+1) + '</div>'
        + line
        + '</div>'
        + '<div class="tl-right">'
        + '<div class="tl-title">' + (item.title||'') + '</div>'
        + '<div class="tl-desc">' + (item.desc||'') + '</div>'
        + mapLink
        + '</div>'
        + '</div>';
    });
    html += '<div class="result-section">'
      + '<div class="result-section-title">' + t.resultLabels.timeline + '</div>'
      + '<div class="tl-note">' + (noteStart[lang]||noteStart.ja) + '</div>'
      + '<div class="timeline">' + timelineHtml + '</div>'
      + '<div class="tl-note" style="margin-top:12px;margin-bottom:0">' + (noteEnd[lang]||noteEnd.ja) + '</div>'
      + '</div>';
  }

  if(plan.restaurants?.length) {
    html += `<div class="result-section">
      <div class="result-section-title">${t.resultLabels.restaurants}</div>
      ${plan.restaurants.map(r => `
        <div class="rest-card">
          <div class="rest-icon-wrap">${r.icon||'🍽️'}</div>
          <div class="rest-info">
            <div class="rest-name">${r.name||''}</div>
            <div class="rest-desc">${r.desc||''}</div>
            ${r.price ? `<div class="rest-price">${r.price}</div>` : ''}
            <a href="https://www.google.com/maps/search/?api=1&query=${encodeURIComponent((r.name||'') + ' ' + currentCity)}" target="_blank" rel="noopener" style="font-size:11px;color:var(--gold);text-decoration:none;display:inline-flex;align-items:center;gap:3px;margin-top:6px;opacity:.85">🗺 ${({'ja':'地図で見る', 'en':'View on Maps', 'zh':'查看地图', 'ko':'지도 보기'})[lang] || '地図で見る'}</a>
          </div>
        </div>
      `).join('')}
    </div>`;
  }

  if(plan.hotels?.length) {
    html += `<div class="result-section">
      <div class="result-section-title">${t.resultLabels.hotels}</div>
      ${plan.hotels.map(h => `
        <div class="hotel-card">
          <div class="hotel-header">
            <div class="hotel-name">🏨 ${h.name||''}</div>
            ${h.price ? `<div class="hotel-price">${h.price}</div>` : ''}
          </div>
          <div class="hotel-desc">${h.desc||''}</div>
          <a href="https://www.google.com/maps/search/?api=1&query=${encodeURIComponent((h.name||'') + ' ' + currentCity)}" target="_blank" rel="noopener" style="font-size:11px;color:var(--gold);text-decoration:none;display:inline-flex;align-items:center;gap:3px;margin-top:8px;opacity:.85">🗺 ${({'ja':'地図で見る', 'en':'View on Maps', 'zh':'查看地图', 'ko':'지도 보기'})[lang] || '地図で見る'}</a>
        </div>
      `).join('')}
    </div>`;
  }

  if(plan.tips?.length) {
    html += `<div class="result-section">
      <div class="result-section-title">${t.resultLabels.tips}</div>
      <div>
        ${plan.tips.map((tip,i) => `
          <div class="tip-item">
            <div class="tip-num">${i+1}</div>
            <div class="tip-text">${tip}</div>
          </div>
        `).join('')}
      </div>
    </div>`;
  }

  const disclaimerMsg = disclaimerTexts[lang] || disclaimerTexts.ja;
  html += `<div style="padding:20px;text-align:center">
    <p style="font-size:10px;color:var(--text-dim);opacity:.6;line-height:1.7;white-space:pre-line" id="result-disclaimer-text">${disclaimerMsg}</p>
  </div>`;

  body.innerHTML = html;

  document.getElementById('result-retry-btn').textContent = t.retryBtn;
  const saveBtnText = lang==='ja'?'💾 保存して条件変更':lang==='en'?'💾 Save & Change':lang==='zh'?'💾 保存并修改':'💾 저장 후 변경';
  const saveBtn = document.getElementById('result-new-btn');
  saveBtn.textContent = saveBtnText;
  saveBtn.onclick = showComingSoon;

  showScreen('screen-result');
}

// ════════════════════════════════
// FONT SIZE
// ════════════════════════════════
const FONT_SIZES = [1, 1.1, 1.2];
let fontSizeIdx = parseInt(localStorage.getItem('locateFontIdx') || '0');

function applyFontSize() {
  document.getElementById('app').style.zoom = FONT_SIZES[fontSizeIdx];
  // ★修正②: id→classに変えたので querySelectorAll('.zoom-v') で取得
  const vLines = document.querySelectorAll('.zoom-v');
  vLines.forEach(el => {
    el.style.display = fontSizeIdx >= FONT_SIZES.length - 1 ? 'none' : 'block';
  });
}

function changeFontSize() {
  fontSizeIdx = (fontSizeIdx + 1) % FONT_SIZES.length;
  localStorage.setItem('locateFontIdx', fontSizeIdx);
  applyFontSize();
}

function showDisambiguationPopup(candidates) {
  document.getElementById('disambig-city').textContent = currentCity;
  const optEl = document.getElementById('disambig-options');
  optEl.innerHTML = candidates.map(c => `
    <button class="btn" style="width:100%;background:var(--bg);border:1px solid var(--border);flex-direction:column;align-items:flex-start;gap:2px;padding:12px 16px"
      onclick="selectDisambiguation('${c.name}', '${c.location}')">
      <span style="font-size:14px;font-weight:600;color:var(--text)">${c.name}　<span style="font-size:12px;color:var(--gold)">${c.location}</span></span>
      <span style="font-size:12px;color:var(--text-dim)">${c.hint}</span>
    </button>
  `).join('');
  document.getElementById('disambiguation-overlay').style.display = 'flex';
}

function selectDisambiguation(name, location) {
  document.getElementById('disambiguation-overlay').style.display = 'none';
  confirmedCity = currentCity;
  confirmedLocation = location;
  document.getElementById('city-input').value = currentCity;
  showTimingPopup();
}

// ════════════════════════════════
// DISCLAIMER
// ════════════════════════════════
const disclaimerTexts = {
  ja: '⚠️ AIによる提案のため、情報に誤りを含む場合があります。\nご利用の際は必ず内容をご確認ください。',
  en: '⚠️ AI-generated content may contain inaccuracies.\nPlease verify all information before use.',
  zh: '⚠️ 本内容由AI生成，可能包含错误。\n使用前请务必核实相关信息。',
  ko: '⚠️ AI가 생성한 내용으로 오류가 포함될 수 있습니다.\n이용 전 반드시 내용을 확인해 주세요.',
};
const splashDisclaimerTexts = {
  ja: 'AIの回答は誤りを含む場合があります。\n内容は必ずご確認ください。',
  en: 'AI responses may contain errors. Please verify all information.',
  zh: 'AI回答可能包含错误，请务必核实内容。',
  ko: 'AI 답변에는 오류가 포함될 수 있습니다. 내용을 반드시 확인하세요。',
};

function updateDisclaimerLang(l) {
  const sd = document.getElementById('splash-disclaimer');
  if(sd) sd.textContent = splashDisclaimerTexts[l] || splashDisclaimerTexts.ja;
  const rd = document.getElementById('result-disclaimer-text');
  if(rd) rd.textContent = disclaimerTexts[l] || disclaimerTexts.ja;
}

function showResultDisclaimer() {
  const banner = document.getElementById('result-disclaimer');
  if(!banner) return;
  const rd = document.getElementById('result-disclaimer-text');
  if(rd) rd.textContent = disclaimerTexts[lang] || disclaimerTexts.ja;
  banner.style.display = 'block';
}

// ════════════════════════════════
// PWA INSTALL BANNER
// ════════════════════════════════
function initPwaBanner() {
  if(localStorage.getItem('pwaBannerDismissed')) return;
  const isStandalone = window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone;
  if(isStandalone) return;
  const isIos = /iphone|ipad|ipod/i.test(navigator.userAgent);
  const isAndroid = /android/i.test(navigator.userAgent);
  if(!isIos && !isAndroid) return;
  const titles = {
    ja: '📲 ホーム画面に追加できます',
    en: '📲 Add to Home Screen',
    zh: '📲 可添加到主屏幕',
    ko: '📲 홈 화면에 추가할 수 있습니다',
  };
  const descs = {
    ja: isIos ? 'Safariで開き、共有ボタン（□↑）→「ホーム画面に追加」' : 'ブラウザのメニュー →「ホーム画面に追加」またはインストール',
    en: isIos ? 'In Safari, tap Share (□↑) → "Add to Home Screen"' : 'Tap browser menu → "Add to Home Screen" or Install',
    zh: isIos ? '在Safari中，点击分享（□↑）→「添加到主屏幕」' : '点击浏览器菜单 → 「添加到主屏幕」',
    ko: isIos ? 'Safari에서 공유(□↑) → 「홈 화면에 추가」' : '브라우저 메뉴 → 「홈 화면에 추가」',
  };
  document.getElementById('pwa-title').textContent = titles[lang] || titles.ja;
  document.getElementById('pwa-desc').textContent = descs[lang] || descs.ja;
  document.getElementById('pwa-banner').style.display = 'block';
}

function dismissPwaBanner() {
  document.getElementById('pwa-banner').style.display = 'none';
  localStorage.setItem('pwaBannerDismissed', '1');
}

// ════════════════════════════════
// DISAMBIGUATION（同名地名）
// ════════════════════════════════
const AMBIGUOUS_PLACES = {
  '松山': [{name:'松山市', location:'愛媛県', hint:'道後温泉・松山城'}, {name:'松山市', location:'岩手県', hint:'岩手県中部の都市'}],
  '長岡': [{name:'長岡市', location:'新潟県', hint:'花火大会で有名'}, {name:'長岡京市', location:'京都府', hint:'京都南部の都市'}],
  '高松': [{name:'高松市', location:'香川県', hint:'讃岐うどんの聖地'}, {name:'高松市', location:'群馬県', hint:'群馬県内の地名'}],
  '富山': [{name:'富山市', location:'富山県', hint:'黒部・立山'}, {name:'富山', location:'神奈川県', hint:'神奈川の地名'}],
  '府中': [{name:'府中市', location:'東京都', hint:'大国魂神社・競馬場'}, {name:'府中市', location:'広島県', hint:'広島県東部の都市'}],
  '伊達': [{name:'伊達市', location:'北海道', hint:'北海道南部の都市'}, {name:'伊達市', location:'福島県', hint:'福島県中通りの都市'}],
  '三条': [{name:'三条市', location:'新潟県', hint:'金物の町'}, {name:'三条', location:'京都市', hint:'京都市内の地名'}],
  '大和': [{name:'大和市', location:'神奈川県', hint:'神奈川県央の都市'}, {name:'大和高田市', location:'奈良県', hint:'奈良県北部の都市'}],
};

function checkAmbiguous(city) {
  return AMBIGUOUS_PLACES[city] || null;
}


// ════════════════════════════════
// TOAST
// ════════════════════════════════
function showComingSoon() {
  const msg = {ja:'近日公開予定です！',en:'Coming soon!',zh:'即将推出！',ko:'곧 출시 예정입니다！'}[lang] || 'Coming soon!';
  showToast(msg);
}

function showToast(msg) {
  const t = document.getElementById('toast');
  t.textContent = msg;
  t.classList.add('show');
  setTimeout(() => t.classList.remove('show'), 3000);
}

// ════════════════════════════════
// RESULT: BACK WARNING
// ════════════════════════════════
function showBackWarning() {
  const warnTexts = {
    ja: { title:'条件を変更しますか？', body:'画面を戻ると回数が新たにカウントされます。この提案は保存されませんので、必要であればスクリーンショットを取っておいてください。', close:'閉じる', confirm:'条件変更' },
    en: { title:'Change preferences?', body:'Going back will use another free count. This plan will not be saved — please take a screenshot if needed.', close:'Close', confirm:'Change' },
    zh: { title:'要修改条件吗？', body:'返回将重新计算使用次数。此方案不会被保存，如需保留请截图。', close:'关闭', confirm:'修改条件' },
    ko: { title:'조건을 변경하시겠어요?', body:'돌아가면 횟수가 새로 카운트됩니다. 이 제안은 저장되지 않으니 필요하면 스크린샷을 찍어두세요.', close:'닫기', confirm:'조건 변경' },
  };
  const w = warnTexts[lang] || warnTexts.ja;
  document.getElementById('warn-title').textContent = w.title;
  document.getElementById('warn-body').textContent = w.body;
  document.getElementById('warn-close').textContent = w.close;
  document.getElementById('warn-confirm').textContent = w.confirm;
  document.getElementById('back-warning-overlay').style.display = 'flex';
}

function hideBackWarning() {
  const overlay = document.getElementById('back-warning-overlay');
  overlay.style.display = 'none';
}

function clearError() {
  const errEl = document.getElementById('q-error');
  if(errEl) { errEl.style.display = 'none'; errEl.textContent = ''; }
}

function confirmGoBack() {
  hideBackWarning();
  previousAnswers = Object.assign({}, answers); // 前回の選択を保存
  previousCity = currentCity; // 前回の都市を保存
  goToQuestions();
}

// ════════════════════════════════
// INIT
// ════════════════════════════════
// setLang is called inside DOMContentLoaded above
</script>
</body>
</html>
