// 天水島ヒルズ components
const { useState, useEffect, useRef, useMemo } = React;

const LAND = 'https://amamizushima.com/images/photos/landscape/';
const CONT = 'https://amamizushima.com/assets/content/';
const PHOTOS = {
  // landscape (existing)
  exterior: CONT + 'hero_dusk.jpg',
  spring:   LAND + 'tanada_00.jpg',
  summer:   LAND + 'tanada_02.jpg',
  autumn:   LAND + 'autumn_rice.jpg',
  winter:   CONT + 'winter_contest2025_yanagida.jpg',
  winterPure: CONT + 'winter_landscape_pure.jpg',
  amami:    CONT + 'hamlet_view_winter.jpg',
  winterLandscape: LAND + 'snow_00.jpg',
  // facility
  entrance2f:   CONT + 'entrance_hall_2026.jpg',
  hall:         CONT + 'hall.jpg',
  facEntrance:  CONT + 'building_full_view.jpg',
  kitchen:      CONT + 'kitchen_dining_fridge.jpg',
  room1:        CONT + 'room1_telework.jpg',
  winterLand:   CONT + 'winter_landscape.jpg',
  // host & events
  hostTaue:     CONT + 'host_taue.jpg',
  hostSki:      CONT + 'host_ski.jpg',
  kumano:       CONT + 'kumano_saenokami.jpg',
  saePoster:    CONT + 'saenokami_poster.jpg',
  saeVideo:     CONT + 'saenokami.mp4',
  sansai:       CONT + 'sansai_foraging.jpg',
  ebike:        CONT + 'ebike.jpg',
  // newly added
  winterHero:   CONT + 'exterior_winter_hero.jpg',
  nabeNight:    CONT + 'living_nabe_night.jpg',
  tanadaSpring: CONT + 'tanada_spring.jpg',
  tanadaSummer: CONT + 'tanada_summer.jpg',
  tanadaAutumn: CONT + 'tanada_autumn.jpg',
  tanadaLateAutumn: CONT + 'tanada_late_autumn.jpg',
  jisshoSpring: CONT + 'biyaku_spring.jpg', // 実昇清水（ファイル名は旧名のまま）
  harvestFest:  CONT + 'harvest_festival.jpg',
  winterSunset: CONT + 'winter_sunset.jpg',
  snowCorridor: CONT + 'snow_corridor.jpg',
  merhenRoad:   CONT + 'merhen_road.jpg', // 中坪メルヘンロード（差し替え可）
  // contest winners (十日町市フォトコンテスト入賞作品)
  winterContest2025:        CONT + 'winter_contest2025_yanagida.jpg',
  winterContest2024Ueyama:  CONT + 'winter_contest2024_ueyama.jpg',
  winterSaigamiContest2024: CONT + 'winter_saigami_contest2024_yanagida.jpg',
  tanadaRusuhara:           CONT + 'tanada_rusuhara_summer.jpg',
  // === 2026 expansion: rooms, water, kitchen, outdoor ===
  // Room 1 (telework, 6畳)
  room1Monitor:    CONT + 'room1_monitor.jpg',
  room1Telework:   CONT + 'room1_telework.jpg',
  // Room 2 (8畳・床の間+神棚)
  room2Main:       CONT + 'room2_main.jpg',
  room2_2:         CONT + 'room2_2.jpg',
  room2_3:         CONT + 'room2_3.jpg',
  room2WithLiving: CONT + 'room2_with_living.jpg',
  // Room 3 (8畳・玄関側)
  room3Main:       CONT + 'room3_main.jpg',
  room3_2:         CONT + 'room3_2.jpg',
  room3_3:         CONT + 'room3_3.jpg',
  room3_4:         CONT + 'room3_4.jpg',
  // Living (10畳)
  livingMain:      CONT + 'living_main_2026.jpg',
  living2:         CONT + 'living_2_2026.jpg',
  livingWithRoom2: CONT + 'living_with_room2.jpg',
  livingBtAmp:     CONT + 'living_bluetooth_amp.jpg',
  tv75:            CONT + 'tv_75inch.jpg',
  // Kitchen variants
  kitchenLived:    CONT + 'kitchen_dining_lived.jpg',
  kitchenFridge:   CONT + 'kitchen_dining_fridge.jpg',
  kitchenStove:    CONT + 'kitchen_stove_ih.jpg',
  // Water / closet
  bathroom1:       CONT + 'bathroom_1.jpg',
  bathroom2:       CONT + 'bathroom_2.jpg',
  washroom1:       CONT + 'washroom_1.jpg',
  washroomBath:    CONT + 'washroom_bath.jpg',
  closet:          CONT + 'closet.jpg',
  // Outdoor / common
  gardenTomato:    CONT + 'garden_tomato.jpg',
  gardenTomato2:   CONT + 'garden_tomato_2.jpg',
  stepInPlan:      CONT + 'onsen_gateway_sign.jpg',
  nakatsuboFlower: CONT + 'nakatsubo_flower_summer.jpg',
  winterPond:      CONT + 'winter_pond.jpg',
  snowBuriedSign:  CONT + 'snow_buried_sign_nakatsubo.jpg',
  tanadaSunDrying: CONT + 'tanada_sun_drying_rice.jpg',
  sansaiFresh:     CONT + 'sansai_fresh_picked.jpg',
  snowWallRoad:    CONT + 'snow_wall_road_amami.jpg',
  snowShoveling:   CONT + 'snow_shoveling_work.jpg',
  snowmanPair:     CONT + 'snowman_pair.jpg',
  garage1f:        CONT + 'garage_1f.jpg',
  stairs3f:        CONT + '3f_stairs_no_entry.jpg',
};

// ============== NAV ==============
function Nav({ t, lang, setLang, setPathname, isPrivacy, tweaksOpen, setTweaksOpen, editMode }) {
  const [scrolled, setScrolled] = useState(false);
  const [navOpen, setNavOpen] = useState(false);
  useEffect(() => {
    const onS = () => setScrolled(window.scrollY > 40);
    window.addEventListener('scroll', onS, { passive: true });
    return () => window.removeEventListener('scroll', onS);
  }, []);
  useEffect(() => {
    document.body.style.overflow = navOpen ? 'hidden' : '';
    return () => { document.body.style.overflow = ''; };
  }, [navOpen]);
  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') setNavOpen(false); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);
  return (
    <nav className={`nav ${scrolled ? 'scrolled' : ''}`}>
      <div className="nav-inner">
        <a href="#top" className="brand">
          <img className="brand-logo" src={lang === 'en' ? 'assets/brand/logo_en.png' : 'assets/brand/logo_ja.png'} alt={lang === 'en' ? 'Amamizushima Hills' : '天水島ヒルズ'} />
        </a>
        <div className="nav-links">
          <a href="#house">{t.nav.house}</a>
          <a href="#floorplan">{t.nav.floorplan}</a>
          <a href="#rooms">{t.nav.rooms}</a>
          <a href="#pricing">{t.nav.pricing}</a>
          <a href="#onsen">{t.nav.onsen}</a>
          <a href="#pet">{t.nav.pet}</a>
          <a href="#food">{t.nav.food}</a>
          <a href="#yearly">{t.nav.yearly}</a>
          <a href="#access">{t.nav.access}</a>
        </div>
        <div className="nav-right">
          <div className="lang" role="tablist">
            {['ja','en','zh'].map(l => {
              const base = l === 'ja' ? '/' : `/${l}/`;
              const href = isPrivacy ? (l === 'ja' ? '/privacy/' : `/${l}/privacy/`) : base;
              return (
              <a key={l}
                href={href}
                className={lang === l ? 'on' : ''}
                onClick={(e) => {
                  if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) return;
                  e.preventDefault();
                  window.history.replaceState({ kind: 'lang' }, '', href);
                  setLang(l);
                  if (setPathname) setPathname(href);
                  try {
                    localStorage.setItem('amami_lang', l);
                    document.cookie = `amami_lang=${l}; max-age=15552000; path=/; SameSite=Lax`;
                  } catch(_) {}
                }}>
                {l.toUpperCase()}
              </a>
              );
            })}
          </div>
          <a href="#book" className="btn">{t.nav.book} <span className="arr">→</span></a>
          <button
            type="button"
            className="nav-burger"
            aria-label={navOpen ? 'Close menu' : 'Open menu'}
            aria-expanded={navOpen}
            onClick={() => setNavOpen(v => !v)}
          >
            <span /><span /><span />
          </button>
        </div>
      </div>
      {navOpen && (
        <div className="nav-overlay" onClick={() => setNavOpen(false)}>
          <div className="nav-overlay-inner" onClick={(e) => e.stopPropagation()}>
            <button
              type="button"
              className="nav-overlay-close"
              aria-label="Close"
              onClick={() => setNavOpen(false)}
            >✕</button>
            <ul className="nav-overlay-list">
              {[
                { href: '#house', label: t.nav.house },
                { href: '#floorplan', label: t.nav.floorplan },
                { href: '#rooms', label: t.nav.rooms },
                { href: '#pricing', label: t.nav.pricing },
                { href: '#onsen', label: t.nav.onsen },
                { href: '#pet', label: t.nav.pet },
                { href: '#food', label: t.nav.food },
                { href: '#yearly', label: t.nav.yearly },
                { href: '#access', label: t.nav.access },
                { href: '#book', label: t.nav.book },
              ].map((n, i) => (
                <li key={i}>
                  <a href={n.href} onClick={() => setNavOpen(false)}>
                    <span className="nav-overlay-num mono">{String(i + 1).padStart(2, '0')}</span>
                    <span className="nav-overlay-label">{n.label}</span>
                  </a>
                </li>
              ))}
            </ul>
            <div className="nav-overlay-langs">
              {['ja','en','zh'].map(l => {
                const base = l === 'ja' ? '/' : `/${l}/`;
                const href = isPrivacy ? (l === 'ja' ? '/privacy/' : `/${l}/privacy/`) : base;
                return (
                <a
                  key={l}
                  href={href}
                  className={`nav-overlay-lang ${lang === l ? 'on' : ''}`}
                  onClick={(e) => {
                    if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) return;
                    e.preventDefault();
                    window.history.replaceState({ kind: 'lang' }, '', href);
                    setLang(l);
                    if (setPathname) setPathname(href);
                    setNavOpen(false);
                    try {
                      localStorage.setItem('amami_lang', l);
                      document.cookie = `amami_lang=${l}; max-age=15552000; path=/; SameSite=Lax`;
                    } catch(_) {}
                  }}
                >{l.toUpperCase()}</a>
                );
              })}
            </div>
          </div>
        </div>
      )}
    </nav>
  );
}

// ============== HERO ==============
function Hero({ t, heroMode }) {
  const seasons = ['spring','summer','autumn','winter'];
  const [idx, setIdx] = useState(0);
  useEffect(() => {
    if (heroMode === 'static') return;
    const v = setInterval(() => setIdx(i => (i + 1) % 4), 4500);
    return () => clearInterval(v);
  }, [heroMode]);

  const seasonLabels = { ja: ['春','夏','秋','冬'], en: ['SPRING','SUMMER','AUTUMN','WINTER'], zh: ['春','夏','秋','冬'] };
  const lbls = seasonLabels[t.__lang] || seasonLabels.ja;

  return (
    <header className="hero" id="top">
      <div className="hero-stage">
        {seasons.map((s, i) => (
          <div
            key={s}
            className={`hero-layer ${i === idx ? 'on' : ''}`}
            style={{ backgroundImage: `url(${PHOTOS[s]})`, transform: i === idx ? 'scale(1.08)' : 'scale(1.02)', transitionProperty: 'opacity, transform', transitionDuration: i === idx ? '6s, 9s' : '2.2s, 2.2s' }}
          />
        ))}
        <div className="hero-grid" />
      </div>

      <div className="hero-top">
        <div className="hero-kicker"><span className="dot" /> {t.hero.kicker}</div>
        <div className="hero-open">{t.hero.open}</div>
      </div>

      <div className="hero-main">
        <div>
          <h1 className="hero-title">
            <span className="r1">{t.hero.title1}</span>
            <span className="r2">{t.hero.title2}</span>
          </h1>
          <p className="hero-sub">{t.hero.sub}</p>
          <div className="hero-ctas">
            <a href="#book" className="btn">{t.hero.cta1} <span className="arr">→</span></a>
            <a href="#house" className="btn ghost">{t.hero.cta2}</a>
          </div>
        </div>
        <div className="hero-side">
          <div className="line">
            <div className="lbl">{t.stats.capacity}</div>
            <div className="val">11 <span style={{ fontSize: 13, opacity: .7, letterSpacing: '.1em' }}>{t.stats.people}</span></div>
          </div>
          <div className="line">
            <div className="lbl">{t.stats.onsen}</div>
            <div className="val">2<span style={{ fontSize: 13, opacity: .7, letterSpacing: '.1em' }}> {t.stats.min}</span></div>
          </div>
          <div className="line">
            <div className="lbl">{t.stats.rate}</div>
            <div className="val"><span className="opening-pill">{t.pricing.openingShort}</span><s className="amt-strike amt-strike-sm">¥40k</s>¥28,000</div>
          </div>
        </div>
      </div>

      <div className="season-bar">
        {seasons.map((s, i) => (
          <div key={s} className={`sb ${i === idx ? 'on' : ''}`} onClick={() => setIdx(i)}>
            <span>{lbls[i]}</span>
          </div>
        ))}
      </div>
    </header>
  );
}

// ============== TICKER ==============
function Ticker({ t }) {
  const items = [
    '新潟 · 十日町市 · 松之山', 'AMAMIZUSHIMA HILLS', '定員 11名', '2026.04.25 開業',
    '最寄り温泉「憩いの湯」車2分・松之山温泉街 車4分', 'ONE PARTY PER DAY', '第M150062846号', '豪雪と棚田の山里',
  ];
  const row = items.join('  ·  ');
  return (
    <div className="ticker">
      <div className="ticker-track">
        <span>{row}</span>
        <span>{row}</span>
      </div>
    </div>
  );
}

// ============== HOUSE ==============
function House({ t }) {
  return (
    <section id="house">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.house.tag}</div>
          <div>
            <h2>{t.house.h}</h2>
          </div>
        </div>

        <div className="house-body">
          <div className="prose">
            <p>{t.house.body}</p>
            <p>{t.house.body2}</p>
            <dl className="house-specs" style={{ marginTop: 36 }}>
              {Object.keys(t.house.spec).filter(k => !k.endsWith('V')).map(k => (
                <div className="row" key={k}>
                  <dt>{t.house.spec[k]}</dt>
                  <dd>{t.house.spec[k + 'V']}</dd>
                </div>
              ))}
            </dl>
          </div>
          <div className="house-photo">
            <img src={PHOTOS.exterior} alt="" loading="lazy" />
          </div>
        </div>

        {/* 概念ブロック: 昭和の豪邸を、そのままに */}
        {(t.house.conceptShowa || t.house.conceptFuton) && (
          <div className="house-concept">
            {t.house.conceptShowa && (
              <div className="hc-row">
                <div className="hc-text">
                  <p>{t.house.conceptShowa}</p>
                </div>
                <figure className="hc-fig">
                  <img src="https://amamizushima.com/assets/content/living_75tv_room.jpg" alt="" loading="lazy" />
                  {t.house.conceptShowaCap && <figcaption>{t.house.conceptShowaCap}</figcaption>}
                </figure>
              </div>
            )}
            {t.house.conceptFuton && (
              <div className="hc-row reverse">
                <figure className="hc-fig">
                  <img src="https://amamizushima.com/assets/content/room2_futon.jpg" alt="" loading="lazy" />
                  {t.house.conceptFutonCap && <figcaption>{t.house.conceptFutonCap}</figcaption>}
                </figure>
                <div className="hc-text">
                  <p>{t.house.conceptFuton}</p>
                </div>
              </div>
            )}
          </div>
        )}

        <div className="stat-row">
          <div className="st">
            <div className="lbl">{t.stats.area}</div>
            <div className="val">286<sub>{t.stats.m2}</sub></div>
          </div>
          <div className="st">
            <div className="lbl">{t.stats.capacity}</div>
            <div className="val">11<sub>{t.stats.people}</sub></div>
          </div>
          <div className="st">
            <div className="lbl">{t.stats.onsen}</div>
            <div className="val">2<sub>{t.stats.min}</sub></div>
          </div>
          <div className="st">
            <div className="lbl">{t.stats.ski}</div>
            <div className="val">3<sub>{t.stats.min}</sub></div>
          </div>
          <div className="st">
            <div className="lbl">{t.stats.rate}</div>
            <div className="val" style={{ fontSize: 'clamp(22px, 2.4vw, 32px)' }}><span className="opening-pill">{t.pricing.openingShort}</span><s className="amt-strike amt-strike-sm">¥40k</s>¥28,000</div>
          </div>
        </div>
      </div>
    </section>
  );
}

// ============== FLOORPLAN (actual image, language-switched) ==============
const FLOORPLAN_IMG = {
  ja: 'assets/floorplan_ja.png',
  en: 'assets/floorplan_en.png',
  zh: 'assets/floorplan_zh.png',
};
function Floorplan({ t }) {
  const [zoom, setZoom] = useState(false);
  const lang = t.__lang || 'ja';
  const src = FLOORPLAN_IMG[lang] || FLOORPLAN_IMG.ja;

  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') setZoom(false); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);

  return (
    <section id="floorplan">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.floorplan.tag}</div>
          <div>
            <h2>{t.floorplan.h}</h2>
            <p className="lead">{t.floorplan.body}</p>
          </div>
        </div>

        <div className="fp-wrap">
          <div className="fp-svg-wrap" onClick={() => setZoom(true)} style={{ cursor: 'zoom-in' }}>
            <img className="fp-img" src={src} alt={t.floorplan.h} />
            <div className="zoom-icon" style={{ opacity: 1, position: 'absolute', top: 40, right: 40 }}>⤢</div>
            <div className="fp-label">
              <span>2F · 119.24 {t.stats.m2}</span>
              <span>{t.floorplan.tag}</span>
            </div>
          </div>

          <div>
            <div className="fp-legend">
              {['r1','r2','r3','l'].map(k => (
                <div key={k} className="item">
                  <div className="num">{k === 'l' ? 'L' : k[1]}</div>
                  <div>
                    <div className="name">{t.floorplan.legend[k]}</div>
                    <div className="meta">{t.floorplan.legend[k + 's']}</div>
                  </div>
                  <div className="area">·</div>
                </div>
              ))}
            </div>
            <p style={{ fontSize: 12, color: 'var(--ink-3)', lineHeight: 1.7, marginTop: 18 }}>{t.floorplan.note}</p>
            <a href="https://amamizushima.com/docs/amamizushima_2f_plan.pdf" target="_blank" rel="noopener" className="fp-link">
              {t.floorplan.pdf} ↗
            </a>
          </div>
        </div>
      </div>

      {zoom && (
        <div className="lightbox" onClick={() => setZoom(false)}>
          <button className="lb-close" onClick={(e) => { e.stopPropagation(); setZoom(false); }} aria-label="Close">✕</button>
          <div className="lb-inner" onClick={(e) => e.stopPropagation()}>
            <img src={src} alt={t.floorplan.h} style={{ background: '#fff', padding: 16 }} />
            <div className="lb-cap">
              <div className="lb-meta">
                <div className="n" style={{ fontSize: 28 }}>{t.floorplan.h}</div>
                <div className="m">2F · 119.24 m²</div>
              </div>
              <div className="body">{t.floorplan.sourceNote || t.floorplan.note}</div>
            </div>
          </div>
        </div>
      )}
    </section>
  );
}

// ============== ROOMS ==============
const FACILITY_PHOTOS = [
  // Building exterior + entrance
  { src: PHOTOS.exterior,      cap: { ja: '建物外観 · 木造＋RC三階建て', en: 'Exterior · timber + RC, 3 storeys', zh: '建筑外观 · 木造+RC 三层' } },
  { src: PHOTOS.facEntrance,   cap: { ja: '建物入口 · 専用エントランス', en: 'Facility entrance · private approach', zh: '建筑入口 · 专用通道' } },
  { src: PHOTOS.entrance2f,    cap: { ja: '2階ホール · 玄関から続く廊下', en: '2F hall · from the entrance', zh: '二层走廊 · 从玄关延伸' } },
  { src: PHOTOS.hall,          cap: { ja: 'ホール · 玄関から居間へ', en: 'Hallway · entry to living', zh: '走廊 · 从玄关到起居室' } },
  // Kitchen
  { src: PHOTOS.kitchenLived,  cap: { ja: 'キッチン＆ダイニング · 12畳', en: 'Kitchen & dining · 12-tatami', zh: '厨房与餐厅 · 12叠' } },
  { src: PHOTOS.kitchenFridge, cap: { ja: 'キッチン · 冷蔵庫(右)+冷凍庫(左)', en: 'Kitchen · refrigerator (R) + freezer (L)', zh: '厨房 · 冷藏(右)+冷冻(左)' } },
  { src: PHOTOS.kitchenStove,  cap: { ja: 'キッチン · IHコンロ', en: 'Kitchen · IH cooktop', zh: '厨房 · 电磁炉' } },
  // Water + storage
  { src: PHOTOS.bathroom1,     cap: { ja: '浴室', en: 'Bathroom', zh: '浴室' } },
  { src: PHOTOS.bathroom2,     cap: { ja: '浴室 · 別アングル', en: 'Bathroom · alt angle', zh: '浴室 · 另一角度' } },
  { src: PHOTOS.washroom1,     cap: { ja: '洗面所', en: 'Washroom', zh: '盥洗室' } },
  { src: PHOTOS.washroomBath,  cap: { ja: '洗面所 · 浴室入口', en: 'Washroom · bath entry', zh: '盥洗室 · 浴室入口' } },
  { src: PHOTOS.closet,        cap: { ja: '押入れ', en: 'Closet (oshiire)', zh: '壁柜（押入）' } },
  // Outdoor common
  { src: PHOTOS.garage1f,      cap: { ja: '1階車庫', en: '1F garage', zh: '一层车库' } },
  { src: PHOTOS.stairs3f,      cap: { ja: '3階階段 · 立入禁止エリア', en: '3F stairs · staff-only', zh: '三层楼梯 · 禁止入内' } },
];

const ROOM_PHOTOS = [
  // Room 1 (telework, 6畳)
  [
    { src: PHOTOS.room1Monitor,  cap: { ja: 'デスク+モニター', en: 'Desk + monitor', zh: '书桌+显示器' } },
    { src: PHOTOS.room1Telework, cap: { ja: 'テレワーク利用シーン', en: 'Telework setup', zh: '远程办公场景' } },
  ],
  // Room 2 (8畳・床の間+神棚)
  [
    { src: PHOTOS.room2Main,       cap: { ja: '床の間と神棚のある8畳', en: '8-tatami w/ tokonoma & shrine shelf', zh: '带壁龛与神龛的8叠间' } },
    { src: PHOTOS.room2_2,         cap: { ja: '別アングル', en: 'Alt angle', zh: '另一角度' } },
    { src: PHOTOS.room2_3,         cap: { ja: '畳の質感', en: 'Tatami detail', zh: '榻榻米质感' } },
    { src: PHOTOS.room2WithLiving, cap: { ja: '居間との続き間', en: 'Open to living room', zh: '与起居室相连' } },
  ],
  // Room 3 (8畳・玄関側)
  [
    { src: PHOTOS.room3Main, cap: { ja: '玄関側の8畳', en: 'Entry-side 8-tatami', zh: '玄关侧8叠间' } },
    { src: PHOTOS.room3_2,   cap: { ja: '別アングル', en: 'Alt angle', zh: '另一角度' } },
    { src: PHOTOS.room3_3,   cap: { ja: '床の見え方', en: 'Floor view', zh: '地面视角' } },
    { src: PHOTOS.room3_4,   cap: { ja: '採光', en: 'Natural light', zh: '采光' } },
  ],
  // Living room (10畳)
  [
    { src: PHOTOS.livingMain,      cap: { ja: '10畳の居間', en: '10-tatami living room', zh: '10叠起居室' } },
    { src: PHOTOS.living2,         cap: { ja: '別アングル', en: 'Alt angle', zh: '另一角度' } },
    { src: PHOTOS.livingWithRoom2, cap: { ja: '客室2との続き間', en: 'Open to Room 2', zh: '与客房2相连' } },
    { src: PHOTOS.tv75,            cap: { ja: '75インチTV', en: '75-inch TV', zh: '75寸电视' } },
    { src: PHOTOS.livingBtAmp,     cap: { ja: 'Bluetooth真空管アンプ', en: 'Bluetooth tube amplifier', zh: '蓝牙真空管功放' } },
  ],
];

function Rooms({ t }) {
  const cap = [
    { room: 1, n: 2 }, { room: 2, n: 3 }, { room: 3, n: 3 }, { room: 4, n: 3 }
  ];
  const lang = t.__lang || 'ja';
  const [lb, setLb] = useState(null); // { room: i, idx: j } or { facility: true, idx: j }
  useEffect(() => {
    const onKey = (e) => {
      if (!lb) return;
      const photos = lb.facility ? FACILITY_PHOTOS : (ROOM_PHOTOS[lb.room] || []);
      if (e.key === 'Escape') setLb(null);
      if (e.key === 'ArrowRight') setLb({ ...lb, idx: (lb.idx + 1) % photos.length });
      if (e.key === 'ArrowLeft')  setLb({ ...lb, idx: (lb.idx - 1 + photos.length) % photos.length });
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [lb]);
  useEffect(() => {
    if (!lb) return;
    window.history.pushState({ lb: 'rooms' }, '');
    const onPop = () => setLb(null);
    window.addEventListener('popstate', onPop);
    return () => {
      window.removeEventListener('popstate', onPop);
      if (window.history.state && window.history.state.lb === 'rooms') window.history.back();
    };
  }, [!!lb]);
  return (
    <section id="rooms">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.rooms.tag}</div>
          <div>
            <h2>{t.rooms.h}</h2>
          </div>
        </div>

        <div className="rooms-grid">
          {t.rooms.items.map((r, i) => {
            const photos = ROOM_PHOTOS[i] || [];
            return (
              <div className="room" key={i}>
                {photos.length > 0 && (
                  <div className="room-gallery">
                    <button
                      type="button"
                      className="room-hero"
                      onClick={() => setLb({ room: i, idx: 0 })}
                      aria-label={photos[0].cap[lang]}
                    >
                      <img src={photos[0].src} alt={photos[0].cap[lang]} loading="lazy" />
                      {photos.length > 1 && (
                        <span className="room-count">+{photos.length - 1}</span>
                      )}
                      <span className="room-zoom" aria-hidden="true">⤢</span>
                    </button>
                    {photos.length > 1 && (
                      <div className="room-thumbs">
                        {photos.slice(1).map((p, j) => (
                          <button
                            type="button"
                            className="room-thumb"
                            key={j}
                            onClick={() => setLb({ room: i, idx: j + 1 })}
                            aria-label={p.cap[lang]}
                          >
                            <img src={p.src} alt={p.cap[lang]} loading="lazy" />
                          </button>
                        ))}
                      </div>
                    )}
                  </div>
                )}
                <div className="no">{r.no}</div>
                <div className="sz">{r.size}</div>
                <div className="name">{r.name}</div>
                <div className="area">{r.area}</div>
                <div className="body">{r.body}</div>
                <div className="cap">· {r.cap}</div>
              </div>
            );
          })}
        </div>

        <div className="facility-block">
          <div className="facility-head">
            <h3>{lang === 'en' ? 'Building & Facilities' : (lang === 'zh' ? '建筑与设施' : '建物・設備')}</h3>
            <p>{lang === 'en' ? 'Kitchen, bath, washroom, garden, garage and more — tap to enlarge.'
              : (lang === 'zh' ? '厨房・浴室・洗面・庭院・车库等 — 点击放大。'
              : 'キッチン・浴室・洗面・庭・車庫など建物内の設備をご紹介。タップで拡大。')}</p>
          </div>
          <div className="facility-grid">
            {FACILITY_PHOTOS.map((p, i) => (
              <button key={i} className="facility-tile" onClick={() => setLb({ facility: true, idx: i })} aria-label={p.cap[lang]}>
                <img src={p.src} alt={p.cap[lang]} loading="lazy" />
                <div className="facility-cap">{p.cap[lang]}</div>
              </button>
            ))}
          </div>
        </div>

        {lb !== null && (() => {
          const photos = lb.facility ? FACILITY_PHOTOS : (ROOM_PHOTOS[lb.room] || []);
          if (!photos.length) return null;
          const cur = photos[lb.idx];
          const meta = lb.facility
            ? (lang === 'en' ? 'BUILDING & FACILITIES' : (lang === 'zh' ? '建筑与设施' : '建物・設備'))
            : (t.rooms.items[lb.room]?.name || '');
          return (
            <div className="lightbox"
              onClick={() => setLb(null)}
              onTouchStart={(e) => { window.__lbTouchR = e.touches[0].clientX; }}
              onTouchEnd={(e) => {
                const x0 = window.__lbTouchR; if (x0 == null) return;
                const dx = e.changedTouches[0].clientX - x0;
                window.__lbTouchR = null;
                if (Math.abs(dx) > 40) {
                  if (dx < 0) setLb({ ...lb, idx: (lb.idx + 1) % photos.length });
                  else setLb({ ...lb, idx: (lb.idx - 1 + photos.length) % photos.length });
                }
              }}
            >
              <button className="lb-close" onClick={(e) => { e.stopPropagation(); setLb(null); }} aria-label="Close">✕</button>
              <button className="lb-nav lb-prev" onClick={(e) => { e.stopPropagation(); setLb({ ...lb, idx: (lb.idx - 1 + photos.length) % photos.length }); }} aria-label="Prev">‹</button>
              <button className="lb-nav lb-next" onClick={(e) => { e.stopPropagation(); setLb({ ...lb, idx: (lb.idx + 1) % photos.length }); }} aria-label="Next">›</button>
              <div className="lb-inner" onClick={(e) => e.stopPropagation()}>
                <img src={cur.src} alt="" />
                <div className="lb-cap">
                  <div className="lb-meta">
                    <div className="n" style={{ fontSize: 20, fontWeight: 600 }}>{cur.cap[lang]}</div>
                    <div className="m">{meta}</div>
                  </div>
                  <div className="body"></div>
                  <div className="lb-count">{String(lb.idx + 1).padStart(2,'0')} / {String(photos.length).padStart(2,'0')}</div>
                </div>
              </div>
            </div>
          );
        })()}

        <div className="cap-viz">
          <div className="lbl">{t.stats.capacity}<br/>Total</div>
          <div className="people">
            {Array.from({ length: 11 }).map((_, i) => (
              <div className="p" key={i} />
            ))}
          </div>
          <div className="total">11<small>{t.stats.people} · MAX</small></div>
        </div>
      </div>
    </section>
  );
}

// ============== GALLERY ==============
function Gallery({ t }) {
  const CATS = [
    { id: 'all',      label: { ja: 'すべて', en: 'All', zh: '全部' } },
    { id: 'land',     label: { ja: '土地・集落', en: 'Land & Hamlet', zh: '土地与村落' } },
    { id: 'garden',   label: { ja: '庭・屋外', en: 'Garden & Outdoor', zh: '庭院与户外' } },
    { id: 'seasons',  label: { ja: '四季', en: 'Seasons', zh: '四季' } },
  ];
  const caps = {
    exterior: { ja: '建物外観 · 木造＋RC三階建て', en: 'Exterior · timber + RC, 3 storeys', zh: '建筑外观 · 木造+RC 三层' },
    hamlet:   { ja: '集落を望む · 3階外廊下から冬景色', en: 'View over the hamlet · winter from the 3F corridor', zh: '远眺村落 · 三楼外廊冬景' },
    tanada1:  { ja: '棚田 · 春の水鏡', en: 'Rice terraces · spring meltwater', zh: '梯田 · 春季水镜' },
    tanada2:  { ja: '留守原の棚田 · 夏の青', en: 'Rusuhara terraces · summer green', zh: '留守原的梯田 · 盛夏青翠' },
    autumn:   { ja: '収穫前 · 黄金色の稲穂', en: 'Pre-harvest · golden ears of rice', zh: '收获前 · 金黄稻穗' },
    snow:     { ja: '冬 · 豪雪と一面の白', en: 'Winter · heavy snow, everything white', zh: '冬 · 豪雪尽白' },
    winterHero:{ja: '雪の建物正面 · 2F玄関へ', en: 'Snow · approach to the 2F entrance', zh: '雪中建筑正面 · 二层玄关'},
    winterSunset:{ja: '夕焼けの雪景 · 電柱のシルエット', en: 'Snow at sunset · with power poles', zh: '雪景夕阳 · 电杆剥影'},
    snowCorridor:{ja: '雪景を望む外廊下', en: 'Outdoor corridor over snow', zh: '雪景延线的外廊'},
    winterContest2025: {ja: '冬・4mを超える雪壁（2025 十日町市フォトコンテスト入賞作品／撮影: 植山宏哉、構図とモデル: 簗田友子）', en: 'Winter · over 4m snow wall (2025 Tokamachi Photo Contest award · Photo by Hiroya Ueyama, composition & model by Yuko Yanagida)', zh: '冬·超过4米的雪壁（2025年十日町市摄影比赛获奖作品·摄影: 植山宏哉、构图和模特: 簗田友子）'},
    winterContest2024Ueyama: {ja: '冬・快晴の松之山（2024 十日町市フォトコンテスト入賞作品／撮影: ホスト・植山宏哉）', en: 'Winter · clear-sky Matsunoyama (2024 Tokamachi Photo Contest award · by host Hiroya Ueyama)', zh: '冬·晴空松之山（2024年十日町市摄影比赛获奖作品·主理人植山宏哉拍摄）'},
    winterSaigamiContest: {ja: '塞の神（2024 十日町市フォトコンテスト入賞作品／撮影: ホスト・簗田友子）', en: 'Sai-no-Kami (2024 Tokamachi Photo Contest award · by host Yuko Yanagida)', zh: '塞之神（2024年十日町市摄影比赛获奖作品·主理人簗田友子拍摄）'},
    nabeNight: {ja: '居間で鍋を囲む夜', en: 'Nabe hot-pot evening in the living room', zh: '居间围炉夜晚'},
    tanadaSpring:{ja: '棚田 · 春の早苗', en: 'Terraces · spring seedlings', zh: '梯田 · 春日早苗'},
    tanadaSummer:{ja: '棚田 · 夏の青々', en: 'Terraces · deep summer green', zh: '梯田 · 夏日青翠'},
    tanadaAutumn:{ja: '棚田 · 秋の黄金', en: 'Terraces · autumn gold', zh: '梯田 · 秋日金黄'},
    tanadaLate:{ja: '棚田 · 晩秋', en: 'Terraces · late autumn', zh: '梯田 · 深秋'},
    jissho:    {ja: '実昇清水 · 天水島より車で約15分', en: 'Jissho-shimizu spring · 15 min by car from the house', zh: '实升清水 · 距住所车程约15分钟'},
    harvest:   {ja: '天水島収穫祭 · ヤナギバヒマワリ', en: 'Amamizushima harvest festival', zh: '天水岛收获祭'},
    entrance:  { ja: '建物入口 · 専用エントランス', en: 'Facility entrance · private approach', zh: '建筑入口 · 专用通道' },
    ent2f:     { ja: '2階ホール · 玄関から続く廊下', en: '2F hall · corridor leading from the entrance', zh: '二层走廊 · 从玄关延伸的过道' },
    hall:      { ja: 'ホール · 玄関から居間へ', en: 'Hallway · from entry to living room', zh: '走廊 · 从玄关到起居室' },
    stairs3f:  { ja: '3階階段 · 立入禁止エリア', en: '3F stairs · staff-only area', zh: '三层楼梯 · 禁止入内' },
    garage1f:  { ja: '1階車庫', en: '1F garage', zh: '一层车库' },
    // rooms
    r1Monitor: { ja: '客室1 · デスク+モニター', en: 'Room 1 · desk + monitor', zh: '客房1 · 书桌+显示器' },
    r1Tele:    { ja: '客室1 · テレワーク利用シーン', en: 'Room 1 · telework setup', zh: '客房1 · 远程办公场景' },
    r2Main:    { ja: '客室2 · 8畳（床の間+神棚）', en: 'Room 2 · 8-tatami w/ tokonoma & shrine shelf', zh: '客房2 · 8叠（壁龛+神龛）' },
    r2_2:      { ja: '客室2 · 別アングル', en: 'Room 2 · alt angle', zh: '客房2 · 另一角度' },
    r2_3:      { ja: '客室2 · 畳の質感', en: 'Room 2 · tatami detail', zh: '客房2 · 榻榻米质感' },
    r2WL:      { ja: '客室2 · 居間との続き間', en: 'Room 2 · open to living', zh: '客房2 · 与起居室相连' },
    r3Main:    { ja: '客室3 · 玄関側の8畳', en: 'Room 3 · entry-side 8-tatami', zh: '客房3 · 玄关侧8叠间' },
    r3_2:      { ja: '客室3 · 別アングル', en: 'Room 3 · alt angle', zh: '客房3 · 另一角度' },
    r3_3:      { ja: '客室3 · 床の見え方', en: 'Room 3 · floor view', zh: '客房3 · 地面视角' },
    r3_4:      { ja: '客室3 · 採光', en: 'Room 3 · natural light', zh: '客房3 · 采光' },
    livingMain:{ ja: '居間 · 10畳', en: 'Living room · 10-tatami', zh: '起居室 · 10叠' },
    living2:   { ja: '居間 · 別アングル', en: 'Living · alt angle', zh: '起居室 · 另一角度' },
    livingR2:  { ja: '居間 · 客室2との続き間', en: 'Living · open to Room 2', zh: '起居室 · 与客房2相连' },
    tv75:      { ja: '居間 · 75インチTV', en: 'Living · 75-inch TV', zh: '起居室 · 75寸电视' },
    livingAmp: { ja: '居間 · Bluetooth真空管アンプ', en: 'Living · Bluetooth tube amp', zh: '起居室 · 蓝牙真空管功放' },
    // kitchen
    kitchenLived:  { ja: 'キッチン＆ダイニング · 12畳', en: 'Kitchen & dining · 12-tatami', zh: '厨房与餐厅 · 12叠' },
    kitchenFridge: { ja: 'キッチン · 冷蔵庫(右)+冷凍庫(左)', en: 'Kitchen · refrigerator (R) + freezer (L)', zh: '厨房 · 冷藏(右)+冷冻(左)' },
    kitchenStove:  { ja: 'キッチン · IHコンロ', en: 'Kitchen · IH cooktop', zh: '厨房 · 电磁炉' },
    // water
    bathroom1:    { ja: '浴室', en: 'Bathroom', zh: '浴室' },
    bathroom2:    { ja: '浴室 · 別アングル', en: 'Bathroom · alt angle', zh: '浴室 · 另一角度' },
    washroom1:    { ja: '洗面所', en: 'Washroom', zh: '盥洗室' },
    washroomBath: { ja: '洗面所 · 浴室入口', en: 'Washroom · bath entry', zh: '盥洗室 · 浴室入口' },
    closet:       { ja: '押入れ', en: 'Closet (oshiire)', zh: '壁柜（押入）' },
    // outdoor
    gardenTomato:  { ja: '庭 · トマト畑', en: 'Garden · tomato bed', zh: '庭院 · 番茄园' },
    gardenTomato2: { ja: '庭 · トマト畑（別アングル）', en: 'Garden · tomato bed (alt)', zh: '庭院 · 番茄园（另角度）' },
    stepInPlan:      {ja:'「ステップ イン プラン」（大地の芸術祭・ジョン・クルメリング作）— 松之山温泉郷の入口、登れる地図塔', en:'"Step in Plan" by John Körmeling (Echigo-Tsumari Art Triennale) · climbable map tower at the Matsunoyama onsen entrance', zh:'「Step in Plan」（大地艺术祭·John Körmeling作）— 松之山温泉乡入口的可登地图塔'},
    nakatsuboFlower: {ja:'夏の棚田 · 凌霄花の咲く朝', en:'Summer terraces · trumpet flowers in morning light', zh:'夏日梯田 · 凌霄花盛开的清晨'},
    winterPond:      {ja:'雪解けの晴れた日 · 集落の池', en:'Clear day after the thaw · pond in the hamlet', zh:'雪后晴天 · 村落的池塘'},
    snowBuriedSign:  {ja:'雪に埋もれた標識 · 中坪集落の冬', en:'Road sign buried in snow · winter in Nakatsubo', zh:'埋没雪中的标识 · 中坪村的冬天'},
    tanadaSunDrying: {ja:'秋・はざ掛けの天日干し', en:'Autumn · sun-dried rice on wooden racks (hazakake)', zh:'秋·木架天日干燥稻穗（はざ掛け）'},
    sansaiFresh:     {ja:'春・採れたて山菜（コゴミ）', en:'Spring · freshly-picked mountain vegetables (kogomi fern)', zh:'春·新采山菜（蕨菜）'},
    snowWallRoad:    {ja:'冬・4-5m級の雪壁を抜ける道', en:'Winter · road through 4-5m snow walls', zh:'冬·穿越4-5米雪壁的道路'},
    snowShoveling:   {ja:'冬の暮らし · 雪掘り（埋もれた家を掘り起こす豪雪地ならではの作業）', en:'Winter daily life · yukihori — digging the house out from heavy snow (a Niigata snow-country tradition)', zh:'冬日生活 · 雪掘（从厚厚积雪中挖出被埋家屋的豪雪地特有作业）'},
    snowmanPair:     {ja:'庭に作ったかまくらと雪だるま、ホスト', en:'Snow cave and snowmen in the garden, with the host', zh:'庭院中的雪洞与雪人和主理人'},
    winter:        { ja: '雪景色 · 2階からの冬', en: 'Winter view · from the 2F windows', zh: '雪景 · 二层窗外的冬' },
  };
  const PICS = [
    // ── LAND / HAMLET ──
    { id: 'h2',  cat: 'land',   src: PHOTOS.amami,           cap: caps.hamlet },
    { id: 'l1',  cat: 'land',   src: PHOTOS.jisshoSpring,    cap: caps.jissho },
    { id: 'l2',  cat: 'land',   src: PHOTOS.harvestFest,     cap: caps.harvest },
    { id: 'l3',  cat: 'land',   src: PHOTOS.stepInPlan,      cap: caps.stepInPlan },
    { id: 'l4',  cat: 'land',   src: PHOTOS.nakatsuboFlower, cap: caps.nakatsuboFlower },
    // ── GARDEN / OUTDOOR ──
    { id: 'o1',  cat: 'garden', src: PHOTOS.gardenTomato,  cap: caps.gardenTomato },
    // ── SEASONS ──
    // 春
    { id: 's1',  cat: 'seasons', src: PHOTOS.spring,                cap: caps.tanada1 },
    { id: 's14', cat: 'seasons', src: PHOTOS.sansaiFresh,            cap: caps.sansaiFresh },
    // 夏
    { id: 's2',  cat: 'seasons', src: PHOTOS.summer,                cap: caps.tanada2 },
    // 秋
    { id: 's3',  cat: 'seasons', src: PHOTOS.autumn,                cap: caps.autumn },
    { id: 's7',  cat: 'seasons', src: PHOTOS.tanadaLateAutumn,      cap: caps.tanadaLate },
    { id: 's15', cat: 'seasons', src: PHOTOS.tanadaSunDrying,        cap: caps.tanadaSunDrying },
    // 冬 — 遠景 → 圧倒的雪量 → 暮らし → コンテスト → 茶目っ気
    { id: 's4',  cat: 'seasons', src: PHOTOS.winterLandscape,       cap: caps.snow },
    { id: 's8',  cat: 'seasons', src: PHOTOS.winterHero,            cap: caps.winterHero },
    { id: 's9',  cat: 'seasons', src: PHOTOS.winterSunset,          cap: caps.winterSunset },
    { id: 's10', cat: 'seasons', src: PHOTOS.snowCorridor,          cap: caps.snowCorridor },
    { id: 's17', cat: 'seasons', src: PHOTOS.snowBuriedSign,          cap: caps.snowBuriedSign },
    { id: 's16', cat: 'seasons', src: PHOTOS.snowWallRoad,            cap: caps.snowWallRoad },
    { id: 's18', cat: 'seasons', src: PHOTOS.snowShoveling,           cap: caps.snowShoveling },
    { id: 's19', cat: 'seasons', src: PHOTOS.winterPond,              cap: caps.winterPond },
    { id: 's11', cat: 'seasons', src: PHOTOS.winterContest2025,     cap: caps.winterContest2025 },
    { id: 's12', cat: 'seasons', src: PHOTOS.winterContest2024Ueyama, cap: caps.winterContest2024Ueyama },
    { id: 's13', cat: 'seasons', src: PHOTOS.winterSaigamiContest2024, cap: caps.winterSaigamiContest },
    { id: 's20', cat: 'seasons', src: PHOTOS.snowmanPair,             cap: caps.snowmanPair },
  ];

  const SUB_LABELS = {};

  const [cat, setCat] = useState('all');
  const [open, setOpen] = useState(null);
  const filtered = cat === 'all' ? PICS : PICS.filter(p => p.cat === cat);

  useEffect(() => {
    const onKey = (e) => {
      if (open === null) return;
      if (e.key === 'Escape') setOpen(null);
      if (e.key === 'ArrowRight') setOpen(i => (i + 1) % filtered.length);
      if (e.key === 'ArrowLeft')  setOpen(i => (i - 1 + filtered.length) % filtered.length);
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, filtered.length]);

  // History push: back-button closes lightbox instead of navigating away
  useEffect(() => {
    if (open === null) return;
    window.history.pushState({ lb: 'gallery' }, '');
    const onPop = () => setOpen(null);
    window.addEventListener('popstate', onPop);
    return () => {
      window.removeEventListener('popstate', onPop);
      if (window.history.state && window.history.state.lb === 'gallery') {
        window.history.back();
      }
    };
  }, [open !== null]);

  const lang = t.__lang || 'ja';
  const catLbl = { ja: 'カテゴリ', en: 'Filter', zh: '分类' }[lang];

  // group rooms by sub when 'rooms' filter is active
  const groupedSubs = (cat === 'rooms')
    ? ['r1','r2','r3','lv'].map(sub => ({
        sub,
        items: filtered.filter(p => p.sub === sub),
      }))
    : null;

  // build a flat list mirroring render order so lightbox indices line up
  const flat = groupedSubs
    ? groupedSubs.flatMap(g => g.items)
    : filtered;

  return (
    <section id="gallery">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.gallery.tag}</div>
          <div>
            <h2>{t.gallery.h}</h2>
            <p className="lead">{t.gallery.body}</p>
          </div>
        </div>

        <div className="gal-controls">
          <div className="gal-cat-lbl">{catLbl}</div>
          <div className="gal-cats">
            {CATS.map(c => (
              <button key={c.id}
                className={`gal-chip ${cat === c.id ? 'on' : ''}`}
                onClick={() => { setCat(c.id); }}>
                {c.label[lang]}
                <span className="n">{c.id === 'all' ? PICS.length : PICS.filter(p => p.cat === c.id).length}</span>
              </button>
            ))}
          </div>
          <div className="gal-count">
            <span className="tnum mono">{String(flat.length).padStart(2,'0')}</span>
            <span className="gc-sep" />
            <span>{lang === 'en' ? 'PHOTOS' : (lang === 'zh' ? '张' : '枚')}</span>
          </div>
        </div>

        {groupedSubs ? (
          groupedSubs.map((g, gi) => {
            if (!g.items.length) return null;
            const offset = groupedSubs.slice(0, gi).reduce((n, x) => n + x.items.length, 0);
            return (
              <div className="gal-sub" key={g.sub}>
                <div className="gal-sub-h">
                  <span className="gal-sub-lbl">{SUB_LABELS[g.sub][lang]}</span>
                  <span className="gal-sub-n mono">{String(g.items.length).padStart(2,'0')}</span>
                </div>
                <div className="gal-grid">
                  {g.items.map((p, i) => (
                    <figure key={p.id} className="gal-cell" onClick={() => setOpen(offset + i)}>
                      <div className="gal-imgwrap">
                        <img src={p.src} alt={p.cap[lang]} loading="lazy" />
                      </div>
                      <figcaption>
                        <span className="idx mono">{String(offset + i + 1).padStart(2, '0')}</span>
                        <span className="ct">{p.cap[lang]}</span>
                      </figcaption>
                    </figure>
                  ))}
                </div>
              </div>
            );
          })
        ) : (
          <div className="gal-grid">
            {filtered.map((p, i) => (
              <figure key={p.id} className="gal-cell" onClick={() => setOpen(i)}>
                <div className="gal-imgwrap">
                  <img src={p.src} alt={p.cap[lang]} loading="lazy" />
                </div>
                <figcaption>
                  <span className="idx mono">{String(i + 1).padStart(2, '0')}</span>
                  <span className="ct">{p.cap[lang]}</span>
                </figcaption>
              </figure>
            ))}
          </div>
        )}
      </div>

      {open !== null && (
        <div className="lightbox"
          onClick={() => setOpen(null)}
          onTouchStart={(e) => { window.__lbTouch = e.touches[0].clientX; }}
          onTouchEnd={(e) => {
            const x0 = window.__lbTouch; if (x0 == null) return;
            const dx = e.changedTouches[0].clientX - x0;
            window.__lbTouch = null;
            if (Math.abs(dx) > 40) {
              if (dx < 0) setOpen((open + 1) % flat.length);
              else setOpen((open - 1 + flat.length) % flat.length);
            }
          }}
        >
          <button className="lb-close" onClick={(e) => { e.stopPropagation(); setOpen(null); }} aria-label="Close">✕</button>
          <button className="lb-nav lb-prev" onClick={(e) => { e.stopPropagation(); setOpen((open - 1 + flat.length) % flat.length); }} aria-label="Prev">‹</button>
          <button className="lb-nav lb-next" onClick={(e) => { e.stopPropagation(); setOpen((open + 1) % flat.length); }} aria-label="Next">›</button>
          <div className="lb-inner" onClick={(e) => e.stopPropagation()}>
            <img src={flat[open].src} alt="" />
            <div className="lb-cap">
              <div className="lb-meta">
                <div className="n" style={{ fontSize: 20, fontWeight: 600 }}>{flat[open].cap[lang]}</div>
                <div className="m">AMAMIZUSHIMA · MATSUNOYAMA</div>
              </div>
              <div className="body"></div>
              <div className="lb-count">{String(open + 1).padStart(2,'0')} / {String(flat.length).padStart(2,'0')}</div>
            </div>
          </div>
        </div>
      )}
    </section>
  );
}

// ============== DAY TIMELINE ==============
function DayTimeline({ t }) {
  if (!t.day) return null;
  return (
    <section id="day">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.day.tag}</div>
          <div>
            <h2>{t.day.h}</h2>
          </div>
        </div>
        <div className="day-rail">
          {t.day.items.map((it, i) => (
            <div className="day-item" key={i}>
              <div className="t">{it.t}</div>
              <div className="title">{it.title}</div>
              <div className="body">{it.body}</div>
              <div className="n">{String(i + 1).padStart(2, '0')} / {String(t.day.items.length).padStart(2, '0')}</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

// ============== PRICING ==============
function Pricing({ t }) {
  return (
    <section id="pricing">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.pricing.tag}</div>
          <div>
            <h2>{t.pricing.h}</h2>
            <p className="lead">{t.pricing.body}</p>
          </div>
        </div>

        <div className="price-wrap">
          <div className="price-card">
            {t.pricing.openingTag && (
              <div className="opening-badge">{t.pricing.openingTag}</div>
            )}
            <div className="lbl">{t.pricing.single}</div>
            {t.pricing.strike && (
              <div className="amt-strike">{t.pricing.strike}</div>
            )}
            <div className="amt"><span className="cur">¥</span>28,000</div>
            <div className="per">{t.pricing.after || t.pricing.per}</div>
            <div className="note">
              {t.pricing.openingBody || t.pricing.body}
            </div>
          </div>
          <div className="price-opts">
            <dl>
              {Object.keys(t.pricing.opts).filter(k => !k.endsWith('V') && !k.endsWith('Sub')).map(k => (
                <div className="row" key={k}>
                  <dt>{t.pricing.opts[k]}{t.pricing.opts[k + 'Sub'] && <div className="sub">{t.pricing.opts[k + 'Sub']}</div>}</dt>
                  <dd>{t.pricing.opts[k + 'V']}</dd>
                </div>
              ))}
            </dl>
          </div>
        </div>
      </div>
    </section>
  );
}

// ============== EVENTS ==============
function Events({ t }) {
  return (
    <section id="events">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.events.tag}</div>
          <div>
            <h2>{t.events.h}</h2>
            <p className="lead">{t.events.body}</p>
          </div>
        </div>

        <div className="events-grid">
          <div>
            <ul className="events-uses">
              {t.events.uses.map((u, i) => (<li key={i}>{u}</li>))}
            </ul>
            <a href="#book" className="btn">{t.events.cta} <span className="arr">→</span></a>
            <div className="events-cap">
              <div>
                <div className="lbl">{t.events.priceLbl}</div>
                <div className="big" style={{ fontSize: 'clamp(28px, 3.2vw, 44px)', letterSpacing: 0 }}>{t.events.priceV}</div>
              </div>
              <div>
                <div className="lbl">MAX · DAY-USE</div>
                <div className="big">25<small>{t.stats.people}</small></div>
              </div>
              <div className="dots">
                {Array.from({ length: 25 }).map((_, i) => (
                  <div className="p" key={i} />
                ))}
              </div>
            </div>
          </div>
          <div className="events-video">
            <video
              src="https://amamizushima.com/images/events/banquet.mp4"
              autoPlay muted loop playsInline preload="metadata"
              poster={PHOTOS.amami}
            />
            <div className="vcap">
              <span className="dot" />
              <span>{t.__lang === 'en' ? 'Hot-pot gathering in the living room · Wakashima-kai meet' : (t.__lang === 'zh' ? '起居室围炉聚餐 · 若岛会聚会' : '居間での鍋囲み · 地域の集まり「若島会」より')}</span>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

// ============== SEASONS ==============
function Seasons({ t }) {
  const pics = [PHOTOS.spring, PHOTOS.summer, PHOTOS.autumn, PHOTOS.winterPure];
  const [open, setOpen] = useState(null);
  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') setOpen(null); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);
  return (
    <section id="seasons">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.seasons.tag}</div>
          <div>
            <h2>{t.seasons.h}</h2>
            <p className="lead">{t.seasons.body}</p>
          </div>
        </div>
        <div className="seasons-grid">
          {t.seasons.items.map((s, i) => (
            <div className="season" key={i} onClick={() => setOpen(i)} role="button" tabIndex={0}>
              <img src={pics[i]} alt="" loading="lazy" />
              <div className="zoom-icon">⤢</div>
              <div className="lbl">
                <div className="n">{s.n}</div>
                <div className="m">{s.m}</div>
                <div className="body">{s.body}</div>
              </div>
            </div>
          ))}
        </div>
      </div>

      {open !== null && (
        <div className="lightbox" onClick={() => setOpen(null)}>
          <button className="lb-close" onClick={(e) => { e.stopPropagation(); setOpen(null); }} aria-label="Close">✕</button>
          <button className="lb-nav lb-prev" onClick={(e) => { e.stopPropagation(); setOpen((open + 3) % 4); }} aria-label="Prev">‹</button>
          <button className="lb-nav lb-next" onClick={(e) => { e.stopPropagation(); setOpen((open + 1) % 4); }} aria-label="Next">›</button>
          <div className="lb-inner" onClick={(e) => e.stopPropagation()}>
            <img src={pics[open]} alt="" />
            <div className="lb-cap">
              <div className="lb-meta">
                <div className="n">{t.seasons.items[open].n}</div>
                <div className="m">{t.seasons.items[open].m}</div>
              </div>
              <div className="body">{t.seasons.items[open].body}</div>
              <div className="lb-count">{String(open + 1).padStart(2,'0')} / 04</div>
            </div>
          </div>
        </div>
      )}
    </section>
  );
}

// ============== ONSEN ==============
function Onsen({ t }) {
  const [active, setActive] = useState(0);
  const [lb, setLb] = useState(null);
  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') setLb(null); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);
  useEffect(() => {
    if (!lb) return;
    window.history.pushState({ lb: 'onsen' }, '');
    const onPop = () => setLb(null);
    window.addEventListener('popstate', onPop);
    return () => {
      window.removeEventListener('popstate', onPop);
      if (window.history.state && window.history.state.lb === 'onsen') window.history.back();
    };
  }, [!!lb]);
  const it = t.onsen.items[active];
  return (
    <section id="onsen">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.onsen.tag}</div>
          <div>
            <h2>{t.onsen.h}</h2>
            <p className="lead">{t.onsen.body}</p>
          </div>
        </div>

        <div className="onsen-facts">
          <div className="of-h">{t.onsen.factsH}</div>
          <div className="of-grid">
            {t.onsen.facts.map((f, i) => (
              <div className="of-it" key={i}>
                <div className="k">{f.k}</div>
                <div className="v">{f.v}</div>
              </div>
            ))}
          </div>
        </div>

        <div className="onsen-picks">
          <div className="op-h">
            <div className="tag">{t.onsen.picks}</div>
            <div className="count mono">{String(active + 1).padStart(2,'0')} / {String(t.onsen.items.length).padStart(2,'0')}</div>
          </div>
          <div className="op-tabs">
            {t.onsen.items.map((o, i) => (
              <button key={i} className={`op-tab ${i === active ? 'on' : ''}`} onClick={() => setActive(i)}>
                <span className="n">{o.name}</span>
                <span className="s">{o.sub}</span>
              </button>
            ))}
          </div>
          <div className="op-body">
            <div className="op-left">
              {Array.isArray(it.imgs) && it.imgs.length > 0 ? (
                <div className={`op-figs op-figs-${it.imgs.length}`}>
                  {it.imgs.map((im, j) => (
                    <figure
                      key={j}
                      className={`op-fig ${j === 0 ? 'op-fig-main' : 'op-fig-sub'}`}
                      onClick={() => setLb({ src: im.src, cap: im.cap || it.name })}
                    >
                      <img src={im.src} alt={im.cap || it.name} loading="lazy" />
                      <span className="op-zoom" aria-hidden="true">⤢</span>
                      {im.cap && <figcaption className="op-cap">{im.cap}</figcaption>}
                    </figure>
                  ))}
                </div>
              ) : it.img && (
                <figure className="op-figure">
                  <img src={it.img} alt={it.imgCap || it.name} loading="lazy" />
                  {it.imgCap && <figcaption>{it.imgCap}</figcaption>}
                </figure>
              )}
              <div className="op-tags">
                {it.tags.map((tg, i) => (<span key={i} className="op-tag">{tg}</span>))}
              </div>
              <p className="op-text">{it.body}</p>
            </div>
            <div className="op-right">
              <div className="op-meta">
                <div><span className="lbl">{t.__lang === 'en' ? 'By car' : (t.__lang === 'zh' ? '车程' : '車で')}</span><span className="v">{it.carV}</span></div>
                <div><span className="lbl">{t.__lang === 'en' ? 'On foot' : (t.__lang === 'zh' ? '步行' : '徒歩')}</span><span className="v">{it.walkV}</span></div>
                {it.tel && <div><span className="lbl">TEL</span><span className="v">{it.tel}</span></div>}
                {it.addr && <div><span className="lbl">{t.__lang === 'en' ? 'Address' : '住所'}</span><span className="v">{it.addr}</span></div>}
              </div>
              <div className="op-links">
                {it.site && (
                  <a className="op-link" href={it.site} target="_blank" rel="noopener noreferrer">
                    {it.siteLabel || (t.__lang === 'en' ? 'Official site' : '公式サイト')} <span className="arr">↗</span>
                  </a>
                )}
                {it.map && (
                  <a className="op-link" href={it.map} target="_blank" rel="noopener noreferrer">
                    {it.mapLabel || 'Google Maps'} <span className="arr">↗</span>
                  </a>
                )}
              </div>
              <p className="op-note">{t.onsen.access.note}</p>
            </div>
          </div>
        </div>
        <div className="section-cta">
          <a href="#book" className="section-cta-link">{t.onsen.sectionCta}</a>
        </div>
      </div>
      {lb && (
        <div className="lightbox" onClick={() => setLb(null)}>
          <button className="lb-close" onClick={(e) => { e.stopPropagation(); setLb(null); }} aria-label="Close">✕</button>
          <img src={lb.src} alt="" onClick={(e) => e.stopPropagation()} />
          {lb.cap && <div className="lb-cap" onClick={(e) => e.stopPropagation()}>{lb.cap}</div>}
        </div>
      )}
    </section>
  );
}

// ============== PETS ==============
function Pets({ t }) {
  const p = t.pet;
  return (
    <section id="pet" className="pet-sec">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{p.tag}</div>
          <div>
            <h2>{p.h}</h2>
            <p className="lead">{p.lede}</p>
          </div>
        </div>

        <div className="pet-grid">
          <div className="pet-illus" aria-hidden="true">
            <svg viewBox="0 0 240 200" width="100%" height="100%">
              <defs>
                <linearGradient id="petSky" x1="0" y1="0" x2="0" y2="1">
                  <stop offset="0" stopColor="#e8dfce"/>
                  <stop offset="1" stopColor="#d6c9ad"/>
                </linearGradient>
              </defs>
              <rect x="0" y="0" width="240" height="200" fill="url(#petSky)"/>
              {/* roof */}
              <polygon points="40,90 120,40 200,90 200,150 40,150" fill="#3b2d22"/>
              <polygon points="40,90 120,40 200,90" fill="#2a2018"/>
              {/* entrance */}
              <rect x="100" y="100" width="40" height="50" fill="#1a1410"/>
              <rect x="100" y="100" width="40" height="6" fill="#5a4632"/>
              {/* paw prints leading in */}
              <g fill="#5a4632" opacity="0.55">
                <circle cx="60" cy="175" r="2.5"/><circle cx="64" cy="172" r="2"/><circle cx="68" cy="174" r="2"/><circle cx="62" cy="178" r="3"/>
                <circle cx="80" cy="170" r="2.5"/><circle cx="84" cy="167" r="2"/><circle cx="88" cy="169" r="2"/><circle cx="82" cy="173" r="3"/>
                <circle cx="100" cy="165" r="2.5"/><circle cx="104" cy="162" r="2"/><circle cx="108" cy="164" r="2"/><circle cx="102" cy="168" r="3"/>
              </g>
              {/* dog silhouette at door */}
              <g fill="#2a2018" transform="translate(115,118)">
                <ellipse cx="10" cy="20" rx="12" ry="8"/>
                <circle cx="20" cy="14" r="6"/>
                <polygon points="22,8 26,4 24,12"/>
                <rect x="2" y="22" width="2" height="6"/>
                <rect x="16" y="22" width="2" height="6"/>
                <path d="M-2,16 q-3,-2 -3,4 q3,1 3,-4z"/>
              </g>
            </svg>
          </div>

          <div className="pet-pillars">
            <div className="pet-pillars-h">{p.pillarsH}</div>
            <ol className="pet-pillar-list">
              {p.pillars.map((x, i) => (
                <li key={i}>
                  <div className="pet-pillar-n">{String(i+1).padStart(2,'0')} · {x.n}</div>
                  <div className="pet-pillar-b">{x.body}</div>
                </li>
              ))}
            </ol>
          </div>
        </div>

        <div className="pet-cols">
          <div className="pet-col">
            <div className="pet-col-h">{p.bringH}</div>
            <ul className="pet-bring">
              {p.bring.map((x, i) => (
                <li key={i}>
                  <span className="pet-bring-dot" aria-hidden="true">●</span>
                  <div>
                    <div className="pet-bring-n">{x.n}</div>
                    <div className="pet-bring-b">{x.body}</div>
                  </div>
                </li>
              ))}
            </ul>
          </div>
          <div className="pet-col">
            <div className="pet-col-h">·</div>
            <ul className="pet-bring">
              {p.manners.map((x, i) => (
                <li key={i}>
                  <span className="pet-bring-dot" aria-hidden="true">○</span>
                  <div>
                    <div className="pet-bring-n">{x.n}</div>
                    <div className="pet-bring-b">{x.body}</div>
                  </div>
                </li>
              ))}
            </ul>
          </div>
        </div>

        <div className="pet-foot">
          <p className="pet-disclaimer">{p.disclaimer}</p>
          <a href="#book" className="pet-cta">
            <span>{p.cta}</span>
            <span className="pet-cta-sub">{p.ctaSub}</span>
          </a>
        </div>
      </div>
    </section>
  );
}

// ============== FOOD ==============
function Food({ t }) {
  return (
    <section id="food">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.food.tag}</div>
          <div>
            <h2>{t.food.h}</h2>
            <p className="lead">{t.food.body}</p>
          </div>
        </div>

        <div className="food-grid">
          {t.food.items.map((f, i) => (
            <article className={`food-card${f.wide ? ' wide' : ''}`} key={i}>
              <div className="fc-n mono">{String(i + 1).padStart(2, '0')}</div>
              <div className="fc-type">{f.type}</div>
              <h3 className="fc-name">{f.name}</h3>
              <p className="fc-body">{f.body}</p>
              {f.wide && Array.isArray(f.imgs) && f.imgs.length > 0 && (
                <div className="fc-imgs">
                  {f.imgs.map((im, j) => (
                    <figure key={j} className={`fc-img${im.noCrop ? ' nocrop' : ''}`}>
                      <img src={im.src} alt="" loading="lazy" />
                      {im.cap && <figcaption>{im.cap}</figcaption>}
                    </figure>
                  ))}
                </div>
              )}
              <div className="fc-meta">
                {f.addr && <div className="fc-addr">{f.addr}</div>}
                {f.map && (
                  <a className="fc-link" href={f.map} target="_blank" rel="noopener noreferrer">
                    {f.mapLabel || 'Google Maps'} <span className="arr">↗</span>
                  </a>
                )}
              </div>
            </article>
          ))}
        </div>

        <div className="food-tip">
          <div className="ft-h">{t.food.tip.h}</div>
          <ul className="ft-list">
            {t.food.tip.items.map((s, i) => (<li key={i}><span className="bul">·</span>{s}</li>))}
          </ul>
        </div>
        <div className="section-cta">
          <a href="#book" className="section-cta-link">{t.food.sectionCta}</a>
        </div>
      </div>
    </section>
  );
}

// ============== RULES ==============
function Rules({ t }) {
  return (
    <section id="rules">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.rules.tag}</div>
          <div>
            <h2>{t.rules.h}</h2>
            <p className="lead">{t.rules.body}</p>
          </div>
        </div>
        <div className="rules-grid">
          {t.rules.items.map((r, i) => (
            <div className="rule" key={i}>
              <div className="r-ico">{r.icon}</div>
              <div className="r-n">{r.n}</div>
              <div className="r-b">{r.body}</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

// ============== YEARLY ==============
function Yearly({ t }) {
  return (
    <section id="yearly">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.yearly.tag}</div>
          <div>
            <h2>{t.yearly.h}</h2>
            <p className="lead">{t.yearly.body}</p>
          </div>
        </div>
        <div className="yearly-list">
          {t.yearly.items.map((y, i) => (
            <div className="yr" key={i}>
              <div className="yr-m mono">{y.m}</div>
              <div className="yr-c">
                <div className="yr-n">{y.n}</div>
                <div className="yr-b">{y.body}</div>
                {(y.linkLabel || y.link) && (
                  <a className="yr-link" href={y.link} target="_blank" rel="noopener">
                    {y.linkLabel || y.link} <span className="arr">↗</span>
                  </a>
                )}
                {y.video && (
                  <figure className="yr-media yr-video">
                    <video
                      src={y.video}
                      poster={y.poster}
                      autoPlay muted loop playsInline preload="metadata"
                      controls
                    />
                    {y.vcap && <figcaption className="yr-cap">{y.vcap}</figcaption>}
                  </figure>
                )}
                {!y.video && y.img && (
                  <figure className="yr-media">
                    <img src={y.img} alt="" loading="lazy" />
                    {y.imgCap && <figcaption className="yr-cap">{y.imgCap}</figcaption>}
                  </figure>
                )}
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

// ============== PRACTICAL ==============
function Practical({ t }) {
  const blocks = ['cv', 'bike', 'winter', 'atm', 'delivery', 'pet'];
  return (
    <section id="practical">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.practical.tag}</div>
          <div>
            <h2>{t.practical.h}</h2>
            <p className="lead">{t.practical.body}</p>
          </div>
        </div>
        <div className="prac-grid">
          {blocks.map((k, i) => {
            const blk = t.practical[k];
            const hasImgs = Array.isArray(blk.imgs) && blk.imgs.length > 0;
            return (
              <div className={`prac${blk.img || hasImgs ? ' has-img' : ''}${hasImgs ? ' has-imgs' : ''}`} key={k}>
                <div className="p-n mono">{String(i + 1).padStart(2, '0')}</div>
                <div className="p-h">{blk.h}</div>
                <div className="p-b">{blk.body}</div>
                {blk.img && !hasImgs && (
                  <div className="p-img">
                    <img src={blk.img} alt="" loading="lazy" />
                  </div>
                )}
                {hasImgs && (
                  <div className="p-imgs">
                    {blk.imgs.map((src, j) => (
                      <div className="p-imgs-cell" key={j}>
                        <img src={src} alt="" loading="lazy" />
                      </div>
                    ))}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>
    </section>
  );
}

// ============== AROUND ==============
function NearCarousel({ imgs, name, onZoom }) {
  const [idx, setIdx] = useState(0);
  const n = imgs.length;
  const im = imgs[idx];
  return (
    <div className="near-carousel">
      <button
        type="button"
        className="near-photo"
        onClick={() => onZoom({ src: im.src, cap: im.cap || name })}
        aria-label={`${name} — 拡大`}
      >
        <img src={im.src} alt="" loading="lazy" />
        <span className="near-zoom" aria-hidden="true">⤢</span>
      </button>
      {n > 1 && (
        <>
          <button
            type="button"
            className="nc-arr nc-prev"
            onClick={(e) => { e.stopPropagation(); setIdx(i => (i - 1 + n) % n); }}
            aria-label="前の写真"
          >‹</button>
          <button
            type="button"
            className="nc-arr nc-next"
            onClick={(e) => { e.stopPropagation(); setIdx(i => (i + 1) % n); }}
            aria-label="次の写真"
          >›</button>
          <div className="nc-dots" role="tablist">
            {imgs.map((_, j) => (
              <button
                key={j}
                type="button"
                className={`nc-dot ${j === idx ? 'on' : ''}`}
                onClick={(e) => { e.stopPropagation(); setIdx(j); }}
                aria-label={`写真 ${j + 1}`}
                aria-selected={j === idx}
              />
            ))}
          </div>
          {im.cap && <div className="nc-cap">{im.cap}</div>}
        </>
      )}
    </div>
  );
}

function Around({ t }) {
  const [lb, setLb] = useState(null); // { src, cap }
  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') setLb(null); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);
  return (
    <section id="around">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.around.tag}</div>
          <div>
            <h2>{t.around.h}</h2>
            {t.around.body && <p className="lead">{t.around.body}</p>}
          </div>
        </div>

        <div className="around-map">
          <div className="am-frame">
            <iframe
              title="Around — Google Maps"
              src="https://www.google.com/maps?q=%E6%96%B0%E6%BD%9F%E7%9C%8C%E5%8D%81%E6%97%A5%E7%94%BA%E5%B8%82%E6%9D%BE%E4%B9%8B%E5%B1%B1%E5%A4%A9%E6%B0%B4%E5%B3%B6575-4&z=12&output=embed"
              loading="lazy" referrerPolicy="no-referrer-when-downgrade"
              allowFullScreen
            />
          </div>
          {t.around.mapNote && <div className="am-note">{t.around.mapNote}</div>}
        </div>

        <div className="around-grid">
          {t.around.items.map((n, i) => (
            <article key={i} className="near">
              {Array.isArray(n.imgs) && n.imgs.length > 0 ? (
                <NearCarousel imgs={n.imgs} name={n.n} onZoom={setLb} />
              ) : n.img && (
                <button
                  type="button"
                  className="near-photo"
                  onClick={() => setLb({ src: n.img, cap: n.imgCap || n.n })}
                  aria-label={`${n.n} — 拡大`}
                >
                  <img src={n.img} alt="" loading="lazy" />
                  <span className="near-zoom" aria-hidden="true">⤢</span>
                </button>
              )}
              <div className="near-text">
                <div className="t">{n.t}</div>
                <div className="n">{n.n}</div>
                <div className="body">{n.body}</div>
                <div className="near-links">
                  {n.site && (
                    <a className="near-link" href={n.site} target="_blank" rel="noopener noreferrer">
                      {n.siteLabel || '公式サイト'} <span className="arr">↗</span>
                    </a>
                  )}
                  {n.map && (
                    <a className="near-link" href={n.map} target="_blank" rel="noopener noreferrer">
                      {n.mapLabel || 'Google Maps'} <span className="arr">↗</span>
                    </a>
                  )}
                  {!n.site && !n.map && n.link && (
                    <a className="near-link" href={n.link} target="_blank" rel="noopener noreferrer">
                      {n.linkLabel || 'Google Maps'} <span className="arr">↗</span>
                    </a>
                  )}
                  {n.seasonsLink && (
                    <a className="near-link near-seasons" href={n.seasonsLink}>
                      {n.seasonsLinkLabel} <span className="arr">↓</span>
                    </a>
                  )}
                </div>
              </div>
            </article>
          ))}
        </div>
        <div className="section-cta">
          <a href="#book" className="section-cta-link">{t.around.sectionCta}</a>
        </div>
      </div>

      {lb && (
        <div className="lightbox" onClick={() => setLb(null)}>
          <button className="lb-close" onClick={(e) => { e.stopPropagation(); setLb(null); }} aria-label="Close">✕</button>
          <img src={lb.src} alt="" onClick={(e) => e.stopPropagation()} />
          {lb.cap && <div className="lb-cap" onClick={(e) => e.stopPropagation()}>{lb.cap}</div>}
        </div>
      )}
    </section>
  );
}

// ============== ACCESS ==============
function Access({ t }) {
  return (
    <section id="access">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.access.tag}</div>
          <div>
            <h2 style={{ fontSize: 'clamp(22px, 2.4vw, 34px)', fontWeight: 600 }}>{t.access.h}</h2>
          </div>
        </div>

        <div className="access-wrap">
          <div>
            <h3>ROUTES</h3>
            <dl className="rows">
              <div className="row">
                <dt>{t.access.train}</dt>
                <dd>{t.access.trainV}</dd>
              </div>
              <div className="row">
                <dt>{t.access.car}</dt>
                <dd>{t.access.carV}</dd>
              </div>
              <div className="row">
                <dt>{t.access.tokyo}</dt>
                <dd>{t.access.tokyoV}</dd>
              </div>
            </dl>
            <a href="https://www.google.com/maps/search/?api=1&query=%E6%96%B0%E6%BD%9F%E7%9C%8C%E5%8D%81%E6%97%A5%E7%94%BA%E5%B8%82%E6%9D%BE%E4%B9%8B%E5%B1%B1%E5%A4%A9%E6%B0%B4%E5%B3%B6575-4"
               target="_blank" rel="noopener" className="btn ghost" style={{ marginTop: 24 }}>
              {t.access.map} ↗
            </a>
          </div>
          <div className="map-card">
            <div className="coords">37.1° N · 138.6° E</div>
            <div className="addr">{t.access.h}</div>
            <div className="map-embed">
              <iframe
                title="Google Maps"
                src="https://www.google.com/maps?q=%E6%96%B0%E6%BD%9F%E7%9C%8C%E5%8D%81%E6%97%A5%E7%94%BA%E5%B8%82%E6%9D%BE%E4%B9%8B%E5%B1%B1%E5%A4%A9%E6%B0%B4%E5%B3%B6575-4&z=14&output=embed"
                width="100%" height="100%" style={{ border: 0 }}
                loading="lazy" referrerPolicy="no-referrer-when-downgrade"
                allowFullScreen
              />
            </div>
            <div className="coords" style={{ textAlign: 'right' }}>NIIGATA · MATSUNOYAMA</div>
          </div>
        </div>
      </div>
    </section>
  );
}

const BOOKING_API = 'https://personal-ai.f5.si/api/amamizushima';
const BOOKING_PROPERTY_ID = 1;

const CAL_WEEKDAYS = {
  ja: ['日','月','火','水','木','金','土'],
  en: ['S','M','T','W','T','F','S'],
  zh: ['日','一','二','三','四','五','六'],
};
const CAL_MONTH_LABEL = {
  ja: (y, m) => `${y}年${m}月`,
  en: (y, m) => new Date(y, m - 1, 1).toLocaleDateString('en-US', { year: 'numeric', month: 'long' }),
  zh: (y, m) => `${y}年${m}月`,
};

function isoOf(d) {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, '0');
  const dd = String(d.getDate()).padStart(2, '0');
  return `${y}-${m}-${dd}`;
}

function AvailabilityCalendar({ today, blocked, mode, value, onChange, lang, monthsAhead = 3 }) {
  // mode: 'range' for overnight (value = {start, end}), 'single' for event (value = 'YYYY-MM-DD')
  const start = mode === 'range' ? (value?.start || '') : '';
  const end = mode === 'range' ? (value?.end || '') : '';
  const single = mode === 'single' ? (value || '') : '';
  // today is a local YYYY-MM-DD string. Parse without timezone shift.
  const [ty, tm] = today.split('-').map((s) => parseInt(s, 10));
  const baseYear = ty;
  const baseMonth = tm - 1; // JS months are 0-indexed
  const [monthOffset, setMonthOffset] = useState(0);
  const months = [];
  for (let i = 0; i < monthsAhead; i++) {
    const d = new Date(baseYear, baseMonth + monthOffset + i, 1);
    months.push({ y: d.getFullYear(), m: d.getMonth() });
  }
  const prevDisabled = monthOffset <= 0;
  const weekdayLabels = CAL_WEEKDAYS[lang] || CAL_WEEKDAYS.ja;
  const monthLabel = CAL_MONTH_LABEL[lang] || CAL_MONTH_LABEL.ja;

  const inRange = (iso) => {
    if (mode !== 'range' || !start || !end) return false;
    return iso > start && iso < end;
  };

  function handleClick(iso, blockedDay, isPast) {
    if (blockedDay || isPast) return;
    if (mode === 'single') {
      onChange(iso);
      return;
    }
    if (!start || (start && end)) {
      onChange({ start: iso, end: '' });
      return;
    }
    if (iso <= start) {
      onChange({ start: iso, end: '' });
      return;
    }
    // Range from start to iso must not include blocked
    const cur = new Date(start);
    cur.setDate(cur.getDate() + 1);
    const target = new Date(iso);
    while (cur < target) {
      if (blocked.has(isoOf(cur))) {
        onChange({ start: iso, end: '' });
        return;
      }
      cur.setDate(cur.getDate() + 1);
    }
    onChange({ start, end: iso });
  }

  return (
    <div style={{ color: '#1a1a1a' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
        <button
          type="button"
          onClick={() => setMonthOffset((v) => Math.max(0, v - 1))}
          disabled={prevDisabled}
          aria-label="前の月"
          style={{ padding: '4px 14px', fontSize: 14, background: '#fff', border: '1.5px solid #6b6b6b', color: prevDisabled ? '#bbb' : '#1a1a1a', cursor: prevDisabled ? 'not-allowed' : 'pointer', borderRadius: 3, fontWeight: 600 }}
        >◀</button>
        <div style={{ fontSize: 12, color: '#4a4a4a', letterSpacing: '.05em', fontWeight: 600 }}>
          {monthOffset === 0 ? (lang === 'en' ? 'Today onwards' : lang === 'zh' ? '从今天起' : '今月から') : (lang === 'en' ? `+${monthOffset} mo` : lang === 'zh' ? `+${monthOffset}个月` : `+${monthOffset}ヶ月`)}
        </div>
        <button
          type="button"
          onClick={() => setMonthOffset((v) => v + 1)}
          aria-label="次の月"
          style={{ padding: '4px 14px', fontSize: 14, background: '#fff', border: '1.5px solid #6b6b6b', color: '#1a1a1a', cursor: 'pointer', borderRadius: 3, fontWeight: 600 }}
        >▶</button>
      </div>
    <div className="avail-cal" style={{ display: 'grid', gridTemplateColumns: `repeat(${monthsAhead}, 1fr)`, gap: 16, marginBottom: 14 }}>
      {months.map(({ y, m }) => {
        const firstDay = new Date(y, m, 1);
        const daysInMonth = new Date(y, m + 1, 0).getDate();
        const offset = firstDay.getDay();
        const cells = [];
        for (let i = 0; i < offset; i++) cells.push({ blank: true });
        for (let dnum = 1; dnum <= daysInMonth; dnum++) {
          const iso = isoOf(new Date(y, m, dnum));
          const isPast = iso < today;
          const blockedDay = blocked.has(iso);
          const selected = (mode === 'range' && (iso === start || iso === end)) || (mode === 'single' && iso === single);
          const inSel = inRange(iso);
          cells.push({ dnum, iso, isPast, blockedDay, selected, inSel });
        }
        return (
          <div key={`${y}-${m}`} style={{ background: '#fafaf6', border: '1px solid #d4cdb8', borderRadius: 4, padding: 10 }}>
            <div style={{ fontSize: 13, fontWeight: 700, marginBottom: 8, letterSpacing: '.05em', textAlign: 'center', color: '#1a1a1a' }}>{monthLabel(y, m + 1)}</div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 2, fontSize: 10, marginBottom: 4, textAlign: 'center', color: '#6b6b6b', fontWeight: 600 }}>
              {weekdayLabels.map((w, i) => <div key={i}>{w}</div>)}
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 2 }}>
              {cells.map((c, i) => {
                if (c.blank) return <div key={i} />;
                const base = {
                  height: 30, display: 'flex', alignItems: 'center', justifyContent: 'center',
                  fontSize: 12, borderRadius: 2, position: 'relative', userSelect: 'none',
                };
                let style;
                let title;
                if (c.isPast) {
                  style = { ...base, color: '#bcbcbc', cursor: 'not-allowed', textDecoration: 'line-through', background: '#f1ede2' };
                  title = '過去';
                } else if (c.blockedDay) {
                  style = { ...base, color: '#fff', background: '#dc2626', cursor: 'not-allowed', fontWeight: 700 };
                  title = '予約済み';
                } else if (c.selected) {
                  style = { ...base, color: '#fff', background: 'var(--accent,#8a3b1c)', cursor: 'pointer', fontWeight: 700 };
                } else if (c.inSel) {
                  style = { ...base, color: '#1a1a1a', background: 'rgba(138,59,28,.22)', cursor: 'pointer', fontWeight: 600 };
                } else {
                  style = { ...base, color: '#1a1a1a', background: '#fff', border: '1px solid #e6dfca', cursor: 'pointer', fontWeight: 500 };
                }
                return (
                  <div key={i} role="button" tabIndex={c.isPast || c.blockedDay ? -1 : 0}
                       title={title || c.iso} aria-label={c.iso}
                       onClick={() => handleClick(c.iso, c.blockedDay, c.isPast)}
                       onKeyDown={(e) => { if ((e.key === 'Enter' || e.key === ' ')) handleClick(c.iso, c.blockedDay, c.isPast); }}
                       style={style}>
                    {c.dnum}{c.blockedDay && <span style={{ position: 'absolute', fontSize: 14, lineHeight: 1, fontWeight: 700 }}>×</span>}
                  </div>
                );
              })}
            </div>
          </div>
        );
      })}
    </div>
    </div>
  );
}

function BookingForm({ t, lang }) {
  const f = t.book.form;
  const today = useMemo(() => {
    // Local-time YYYY-MM-DD (toISOString uses UTC and breaks for JST late evening)
    const d = new Date();
    const y = d.getFullYear();
    const m = String(d.getMonth() + 1).padStart(2, '0');
    const dd = String(d.getDate()).padStart(2, '0');
    return `${y}-${m}-${dd}`;
  }, []);

  const [type, setType] = useState('overnight'); // 'overnight' | 'event' | 'inquiry'
  const [checkIn, setCheckIn] = useState('');
  const [checkOut, setCheckOut] = useState('');
  const [eventDate, setEventDate] = useState('');
  const [eventStart, setEventStart] = useState('');
  const [eventEnd, setEventEnd] = useState('');
  const [eventPurpose, setEventPurpose] = useState('');
  const [inquirySubject, setInquirySubject] = useState('');
  const [inquiryMessage, setInquiryMessage] = useState('');
  const [guests, setGuests] = useState(4);
  const [bringOwnLinen, setBringOwnLinen] = useState(false);
  const [withPet, setWithPet] = useState(false);
  const [petCount, setPetCount] = useState(1);
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [phone, setPhone] = useState('');
  const [notes, setNotes] = useState('');
  const [couponCode, setCouponCode] = useState('');
  const [consent, setConsent] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [feedback, setFeedback] = useState(null); // {kind:'ok'|'err', message}
  const [blocked, setBlocked] = useState(new Set());
  const [quote, setQuote] = useState(null);
  const [quoteLoading, setQuoteLoading] = useState(false);

  const guestMax = type === 'event' ? 25 : 11;
  const effectivePetCount = withPet ? petCount : 0;

  // Load blocked dates once on mount
  useEffect(() => {
    const from = today;
    const toD = new Date(today);
    toD.setDate(toD.getDate() + 365);
    const to = toD.toISOString().slice(0, 10);
    const url = `${BOOKING_API}/public/calendar?property_id=${BOOKING_PROPERTY_ID}&from_date=${from}&to_date=${to}`;
    fetch(url, { credentials: 'omit' })
      .then((r) => (r.ok ? r.json() : { blocked_dates: [] }))
      .then((d) => setBlocked(new Set(d.blocked_dates || [])))
      .catch(() => setBlocked(new Set()));
  }, [today]);

  // When type changes, clamp guest count and clear feedback
  useEffect(() => {
    setGuests((g) => Math.min(g, type === 'event' ? 25 : 11));
    setFeedback(null);
  }, [type]);

  // Quote fetch (overnight only) — debounced. Re-fetches when linen / pet toggles change.
  useEffect(() => {
    if (type !== 'overnight' || !checkIn || !checkOut || checkOut <= checkIn) {
      setQuote(null);
      return undefined;
    }
    setQuoteLoading(true);
    const handle = setTimeout(() => {
      const params = new URLSearchParams({
        check_in: checkIn,
        check_out: checkOut,
        num_guests: String(guests),
        bring_own_linen: String(bringOwnLinen),
        pet_count: String(effectivePetCount),
      });
      const url = `${BOOKING_API}/public/quote?${params.toString()}`;
      fetch(url, { credentials: 'omit' })
        .then((r) => (r.ok ? r.json() : null))
        .then((d) => setQuote(d))
        .catch(() => setQuote(null))
        .finally(() => setQuoteLoading(false));
    }, 350);
    return () => {
      clearTimeout(handle);
      setQuoteLoading(false);
    };
  }, [type, checkIn, checkOut, guests, bringOwnLinen, effectivePetCount]);

  const fmt = (n) =>
    lang === 'en' ? `JPY ${Number(n).toLocaleString('en-US')}` : `¥${Number(n).toLocaleString('ja-JP')}`;

  const rangeOverlapsBlocked = (a, b) => {
    if (!a || !b) return false;
    const cur = new Date(a);
    const end = new Date(b);
    while (cur < end) {
      const k = cur.toISOString().slice(0, 10);
      if (blocked.has(k)) return true;
      cur.setDate(cur.getDate() + 1);
    }
    return false;
  };

  async function onSubmit(e) {
    e.preventDefault();
    setFeedback(null);

    // Booking types (overnight / event) require house-rule consent;
    // inquiry doesn't.
    if (type !== 'inquiry' && !consent) {
      setFeedback({ kind: 'err', message: f.consent });
      return;
    }
    if (!phone.trim()) {
      setFeedback({ kind: 'err', message: f.required });
      return;
    }

    setSubmitting(true);
    try {
      let endpoint = `${BOOKING_API}/public/booking`;
      let body;

      if (type === 'inquiry') {
        endpoint = `${BOOKING_API}/public/inquiry`;
        body = {
          name: name.trim(),
          email: email.trim(),
          phone: phone.trim(),
          subject: inquirySubject.trim() || null,
          message: inquiryMessage.trim(),
          lang,
        };
      } else {
        if (type === 'overnight') {
          if (!checkIn || !checkOut) {
            setSubmitting(false);
            return;
          }
          if (checkOut <= checkIn) {
            setFeedback({ kind: 'err', message: f.dateOrder });
            setSubmitting(false);
            return;
          }
          if (rangeOverlapsBlocked(checkIn, checkOut)) {
            setFeedback({ kind: 'err', message: f.unavailable });
            setSubmitting(false);
            return;
          }
        } else {
          if (!eventDate) {
            setSubmitting(false);
            return;
          }
          if (blocked.has(eventDate)) {
            setFeedback({ kind: 'err', message: f.unavailable });
            setSubmitting(false);
            return;
          }
          if (eventStart && eventEnd && eventStart >= eventEnd) {
            setFeedback({ kind: 'err', message: f.dateOrder });
            setSubmitting(false);
            return;
          }
        }
        body = {
          property_id: BOOKING_PROPERTY_ID,
          booking_type: type,
          num_guests: Number(guests),
          bring_own_linen: type === 'overnight' ? bringOwnLinen : false,
          pet_count: type === 'overnight' ? effectivePetCount : 0,
          guest_name: name.trim(),
          guest_email: email.trim(),
          guest_phone: phone.trim(),
          special_requests: (() => {
            const c = couponCode.trim();
            const n = notes.trim();
            if (!c && !n) return null;
            if (!c) return n;
            return `[クーポン: ${c}] ${n}`.trim();
          })(),
          lang,
          consent: true,
        };
        if (type === 'overnight') {
          body.check_in = checkIn;
          body.check_out = checkOut;
        } else {
          body.event_date = eventDate;
          body.event_start_time = eventStart;
          body.event_end_time = eventEnd;
          body.event_purpose = eventPurpose.trim() || null;
        }
      }

      const res = await fetch(endpoint, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'omit',
        body: JSON.stringify(body),
      });
      if (res.status === 409) {
        setFeedback({ kind: 'err', message: f.unavailable });
      } else if (!res.ok) {
        setFeedback({ kind: 'err', message: f.error });
      } else {
        setFeedback({ kind: 'ok', message: type === 'inquiry' ? (f.successInquiry || f.success) : f.success });
        setName(''); setEmail(''); setPhone(''); setNotes(''); setCouponCode('');
        setCheckIn(''); setCheckOut(''); setEventDate('');
        setEventStart(''); setEventEnd(''); setEventPurpose('');
        setInquirySubject(''); setInquiryMessage('');
        setBringOwnLinen(false); setWithPet(false); setPetCount(1);
        setConsent(false); setQuote(null);
      }
    } catch (err) {
      setFeedback({ kind: 'err', message: f.error });
    } finally {
      setSubmitting(false);
    }
  }

  // Higher-contrast styles — earlier version was too faint.
  const inputStyle = {
    width: '100%', padding: '11px 13px', border: '1.5px solid #6b6b6b',
    background: '#fff', color: '#1a1a1a',
    fontSize: 15, borderRadius: 2, boxSizing: 'border-box',
    fontFamily: 'inherit', fontWeight: 500,
  };
  const labelStyle = {
    display: 'block', fontSize: 12, letterSpacing: '.08em',
    fontWeight: 600, color: '#1a1a1a', marginBottom: 6,
  };
  const helpStyle = { fontSize: 12, color: '#4a4a4a', lineHeight: 1.5 };
  const fieldGap = { marginBottom: 16 };
  const checkboxRowStyle = {
    display: 'flex', gap: 12, alignItems: 'flex-start',
    marginBottom: 12, fontSize: 15, lineHeight: 1.55,
    color: '#000', fontWeight: 600, cursor: 'pointer',
  };

  return (
    <form
      onSubmit={onSubmit}
      style={{
        background: '#fff', border: '1px solid #e5e5e5', padding: 24,
        marginBottom: 32,
      }}
    >
      <h3 style={{ margin: 0, fontSize: 20, fontWeight: 700, color: '#1a1a1a' }}>
        {type === 'overnight' ? (f.titleOvernight || f.title)
          : type === 'event' ? (f.titleEvent || f.title)
          : (f.titleInquiry || f.title)}
      </h3>
      <p style={{ margin: '8px 0 16px', fontSize: 14, color: '#4a4a4a', lineHeight: 1.6 }}>
        {type === 'inquiry' ? f.inquiryNote : f.intro}
      </p>

      <div style={{ display: 'flex', border: '1.5px solid #6b6b6b', marginBottom: 18 }}>
        {[
          { v: 'overnight', label: f.typeOvernight },
          { v: 'event', label: f.typeEvent },
          { v: 'inquiry', label: f.typeInquiry },
        ].map((opt, i) => (
          <button
            key={opt.v}
            type="button"
            onClick={() => setType(opt.v)}
            style={{
              flex: 1, padding: '11px 12px', fontSize: 14, fontWeight: 600, fontFamily: 'inherit',
              cursor: 'pointer', border: 'none',
              borderLeft: i === 0 ? 'none' : '1.5px solid #6b6b6b',
              background: type === opt.v ? '#1a1a1a' : '#fff',
              color: type === opt.v ? '#fff' : '#1a1a1a',
              transition: 'background .15s',
            }}
          >
            {opt.label}
          </button>
        ))}
      </div>

      {type === 'overnight' && (
        <>
          <div style={{ ...fieldGap }}>
            <label style={labelStyle}>{f.calendarLabel || '予約状況カレンダー'}</label>
            <AvailabilityCalendar
              today={today}
              blocked={blocked}
              mode="range"
              value={{ start: checkIn, end: checkOut }}
              onChange={(v) => { setCheckIn(v.start || ''); setCheckOut(v.end || ''); }}
              lang={lang}
              monthsAhead={3}
            />
            <div style={{ fontSize: 12, color: '#4a4a4a', marginTop: -4, fontWeight: 500 }}>
              <span style={{ display: 'inline-block', width: 12, height: 12, background: '#dc2626', marginRight: 6, verticalAlign: 'middle', borderRadius: 2 }} />
              {f.legendBlocked || '予約済み（選択不可）'}
              <span style={{ display: 'inline-block', width: 12, height: 12, background: 'var(--accent,#8a3b1c)', marginLeft: 16, marginRight: 6, verticalAlign: 'middle', borderRadius: 2 }} />
              {f.legendSelected || '選択中'}
            </div>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, ...fieldGap }}>
            <div>
              <label style={labelStyle}>{f.checkIn}</label>
              <input type="date" min={today} value={checkIn} onChange={(e) => setCheckIn(e.target.value)} style={inputStyle} required />
            </div>
            <div>
              <label style={labelStyle}>{f.checkOut}</label>
              <input type="date" min={checkIn || today} value={checkOut} onChange={(e) => setCheckOut(e.target.value)} style={inputStyle} required />
            </div>
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, ...fieldGap }}>
            <div>
              <label style={labelStyle}>{f.guests}</label>
              <select value={guests} onChange={(e) => setGuests(Number(e.target.value))} style={inputStyle}>
                {Array.from({ length: guestMax }, (_, i) => i + 1).map((n) => (
                  <option key={n} value={n}>{n} {f.guestUnit}</option>
                ))}
              </select>
            </div>
            <div>
              <label style={labelStyle}>{f.priceLabel}</label>
              <div style={{
                ...inputStyle, background: '#fef3c7', borderColor: '#92400e',
                display: 'flex', alignItems: 'center', minHeight: 46,
                color: '#1a1a1a', fontWeight: 700, fontSize: 18,
              }}>
                {quoteLoading ? (
                  <span style={{ fontSize: 14, color: '#4a4a4a', fontWeight: 500 }}>{f.priceLoading}</span>
                ) : quote && typeof quote.total === 'number' ? (
                  <span>{fmt(quote.total)}</span>
                ) : (
                  <span style={{ fontSize: 14, color: '#4a4a4a', fontWeight: 500 }}>{f.priceUnavailable}</span>
                )}
              </div>
            </div>
          </div>

          {/* Linen / Pet options */}
          <div style={{ marginBottom: 16, padding: '14px 16px', border: '1.5px solid #6b6b6b', background: '#fff' }}>
            <label style={checkboxRowStyle}>
              <input
                type="checkbox"
                checked={bringOwnLinen}
                onChange={(e) => setBringOwnLinen(e.target.checked)}
                style={{ marginTop: 4, width: 22, height: 22, accentColor: '#1a1a1a', flexShrink: 0, cursor: 'pointer' }}
              />
              <span>{f.bringOwnLinen}</span>
            </label>
            <label style={checkboxRowStyle}>
              <input
                type="checkbox"
                checked={withPet}
                onChange={(e) => setWithPet(e.target.checked)}
                style={{ marginTop: 4, width: 22, height: 22, accentColor: '#1a1a1a', flexShrink: 0, cursor: 'pointer' }}
              />
              <span>{f.withPet}</span>
            </label>
            {withPet && (
              <div style={{ marginLeft: 28, marginTop: 4 }}>
                <label style={labelStyle}>{f.petCount}</label>
                <select
                  value={petCount}
                  onChange={(e) => setPetCount(Number(e.target.value))}
                  style={{ ...inputStyle, width: 140 }}
                >
                  <option value={1}>1</option>
                  <option value={2}>2</option>
                </select>
                <div style={{ ...helpStyle, marginTop: 6 }}>{f.petNotice}</div>
              </div>
            )}
          </div>

          {quote && (
            <div style={{
              ...fieldGap, fontSize: 13, color: '#1a1a1a', lineHeight: 1.8,
              padding: '12px 14px', background: '#f7f7f5', border: '1px solid #d4d4d4',
            }}>
              {quote.daily.map((d) => (
                <div key={d.date} style={{ display: 'flex', justifyContent: 'space-between' }}>
                  <span>
                    {d.date}
                    {d.factors && d.factors.length > 0 && (
                      <span style={{ color: '#4a4a4a', marginLeft: 4 }}>（{d.factors.join('・')}）</span>
                    )}
                  </span>
                  <span style={{ fontWeight: 500 }}>{fmt(d.price)}</span>
                </div>
              ))}
              <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 6, paddingTop: 6, borderTop: '1px dashed #999' }}>
                <span>{f.roomSubtotal}</span><span style={{ fontWeight: 500 }}>{fmt(quote.room_subtotal)}</span>
              </div>
              {quote.linen_subtotal > 0 ? (
                <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                  <span>{f.linenSubtotal}（¥{quote.linen_per_guest.toLocaleString()} × {quote.num_guests}）</span>
                  <span style={{ fontWeight: 500 }}>{fmt(quote.linen_subtotal)}</span>
                </div>
              ) : (
                <div style={{ display: 'flex', justifyContent: 'space-between', color: '#4a4a4a' }}>
                  <span>{f.linenSubtotal}（持参）</span>
                  <span>—</span>
                </div>
              )}
              {quote.pet_subtotal > 0 && (
                <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                  <span>{f.petSubtotal}（¥{quote.pet_per_night.toLocaleString()} × {quote.pet_count} × {quote.nights}{f.nightUnit}）</span>
                  <span style={{ fontWeight: 500 }}>{fmt(quote.pet_subtotal)}</span>
                </div>
              )}
              <div style={{
                display: 'flex', justifyContent: 'space-between',
                marginTop: 8, paddingTop: 8, borderTop: '2px solid #1a1a1a',
                fontSize: 16, fontWeight: 700,
              }}>
                <span>{f.priceLabel}</span><span>{fmt(quote.total)}</span>
              </div>
            </div>
          )}
        </>
      )}

      {type === 'event' && (
        <>
          <div style={{ marginBottom: 14, padding: '10px 14px', background: '#fff7ed', border: '1px solid #fed7aa', fontSize: 13, color: '#9a3412', fontWeight: 500 }}>
            {f.eventNote}
          </div>
          <div style={{ ...fieldGap }}>
            <label style={labelStyle}>{f.calendarLabel || '予約状況カレンダー'}</label>
            <AvailabilityCalendar
              today={today}
              blocked={blocked}
              mode="single"
              value={eventDate}
              onChange={(v) => setEventDate(v)}
              lang={lang}
              monthsAhead={3}
            />
            <div style={{ fontSize: 12, color: '#4a4a4a', marginTop: -4, fontWeight: 500 }}>
              <span style={{ display: 'inline-block', width: 12, height: 12, background: '#dc2626', marginRight: 6, verticalAlign: 'middle', borderRadius: 2 }} />
              {f.legendBlocked || '予約済み（選択不可）'}
              <span style={{ display: 'inline-block', width: 12, height: 12, background: 'var(--accent,#8a3b1c)', marginLeft: 16, marginRight: 6, verticalAlign: 'middle', borderRadius: 2 }} />
              {f.legendSelected || '選択中'}
            </div>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12, ...fieldGap }}>
            <div>
              <label style={labelStyle}>{f.eventDate}</label>
              <input type="date" min={today} value={eventDate} onChange={(e) => setEventDate(e.target.value)} style={inputStyle} required />
            </div>
            <div>
              <label style={labelStyle}>{f.eventStart}</label>
              <input type="time" value={eventStart} onChange={(e) => setEventStart(e.target.value)} style={inputStyle} required />
            </div>
            <div>
              <label style={labelStyle}>{f.eventEnd}</label>
              <input type="time" value={eventEnd} onChange={(e) => setEventEnd(e.target.value)} style={inputStyle} required />
            </div>
          </div>
          <div style={fieldGap}>
            <label style={labelStyle}>{f.eventPurpose}</label>
            <input type="text" value={eventPurpose} onChange={(e) => setEventPurpose(e.target.value)} placeholder={f.eventPurposePlaceholder} style={inputStyle} />
          </div>
          <div style={fieldGap}>
            <label style={labelStyle}>{f.guests}</label>
            <select value={guests} onChange={(e) => setGuests(Number(e.target.value))} style={inputStyle}>
              {Array.from({ length: guestMax }, (_, i) => i + 1).map((n) => (
                <option key={n} value={n}>{n} {f.guestUnit}</option>
              ))}
            </select>
          </div>
        </>
      )}

      {type === 'inquiry' && (
        <>
          <div style={fieldGap}>
            <label style={labelStyle}>{f.inquirySubject}</label>
            <input
              type="text"
              value={inquirySubject}
              onChange={(e) => setInquirySubject(e.target.value)}
              placeholder={f.inquirySubjectPlaceholder}
              style={inputStyle}
            />
          </div>
          <div style={fieldGap}>
            <label style={labelStyle}>{f.inquiryMessage}</label>
            <textarea
              value={inquiryMessage}
              onChange={(e) => setInquiryMessage(e.target.value)}
              placeholder={f.inquiryMessagePlaceholder}
              rows={5}
              style={{ ...inputStyle, resize: 'vertical' }}
              required
            />
          </div>
        </>
      )}

      <div style={fieldGap}>
        <label style={labelStyle}>{f.name}</label>
        <input type="text" value={name} onChange={(e) => setName(e.target.value)} placeholder={f.namePlaceholder} style={inputStyle} required />
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, ...fieldGap }}>
        <div>
          <label style={labelStyle}>{f.email}</label>
          <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} style={inputStyle} required />
        </div>
        <div>
          <label style={labelStyle}>{f.phone}</label>
          <input type="tel" value={phone} onChange={(e) => setPhone(e.target.value)} placeholder={f.phonePlaceholder} style={inputStyle} required />
        </div>
      </div>

      {type !== 'inquiry' && (
        <div style={fieldGap}>
          <label style={labelStyle}>{f.notes}</label>
          <textarea value={notes} onChange={(e) => setNotes(e.target.value)} placeholder={f.notesPlaceholder} rows={3} style={{ ...inputStyle, resize: 'vertical' }} />
        </div>
      )}

      {type !== 'inquiry' && (
        <div style={fieldGap}>
          <label style={labelStyle}>{f.coupon}</label>
          <input
            type="text"
            value={couponCode}
            onChange={(e) => setCouponCode(e.target.value)}
            placeholder={f.couponPlaceholder}
            style={inputStyle}
            maxLength={32}
          />
        </div>
      )}

      {type !== 'inquiry' && (
        <label style={checkboxRowStyle}>
          <input type="checkbox" checked={consent} onChange={(e) => setConsent(e.target.checked)} style={{ marginTop: 4, width: 22, height: 22, accentColor: '#1a1a1a', flexShrink: 0, cursor: 'pointer' }} />
          <span style={{ fontWeight: 400 }}>{type === 'event' ? (f.consentEvent || f.consent) : f.consent}</span>
        </label>
      )}

      <button
        type="submit"
        disabled={submitting}
        style={{
          width: '100%', padding: '14px 20px', background: submitting ? '#666' : '#1a1a1a',
          color: '#fff', border: 'none', fontSize: 14, fontWeight: 600, letterSpacing: '.05em',
          textTransform: 'uppercase', cursor: submitting ? 'not-allowed' : 'pointer',
          fontFamily: 'inherit', transition: 'background .15s',
        }}
      >
        {submitting ? f.submitting : (type === 'inquiry' ? (f.submitInquiry || f.submit) : f.submit)}
      </button>

      {feedback && (
        <div
          style={{
            marginTop: 14, padding: '10px 14px', fontSize: 13, lineHeight: 1.5,
            border: '1px solid',
            borderColor: feedback.kind === 'ok' ? '#86efac' : '#fca5a5',
            background: feedback.kind === 'ok' ? '#f0fdf4' : '#fef2f2',
            color: feedback.kind === 'ok' ? '#166534' : '#991b1b',
          }}
          role="status"
        >
          {feedback.message}
        </div>
      )}
    </form>
  );
}

// ============== BOOK ==============
function Book({ t, lang }) {
  const telPlain = (t.book.telV || '').replace(/[^\d+]/g, '');
  const waIntl = telPlain.replace(/^\+?/, '').replace(/^0/, '81');
  const waDisplay = waIntl.startsWith('81') && waIntl.length === 12
    ? `+81 ${waIntl.slice(2,4)}-${waIntl.slice(4,8)}-${waIntl.slice(8)}`
    : `+${waIntl}`;
  return (
    <section id="book">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.book.tag}</div>
          <div>
            <h2>{t.book.h}</h2>
            <p className="lead">{t.book.body}</p>
          </div>
        </div>

        <BookingForm t={t} lang={lang} />

        {/* Email + TEL + WhatsApp */}
        <div className="book-grid three">
          <a className="book-card primary" href="mailto:info@amamizushima.com">
            <div className="lbl">EMAIL</div>
            <div className="big">info@amamizushima.com</div>
            <div className="arr">{t.book.direct} →</div>
          </a>
          {t.book.telV && (
            <a className="book-card primary" href={`tel:${telPlain}`}>
              <div className="lbl">TEL</div>
              <div className="big">{t.book.telV}</div>
              <div className="arr">{t.book.tel} →</div>
              {t.book.telNote && <div className="small" style={{ marginTop: 6, opacity: 0.65 }}>{t.book.telNote}</div>}
            </a>
          )}
          {t.book.telV && (
            <a className="book-card primary" href={`https://wa.me/${waIntl}`} target="_blank" rel="noopener noreferrer">
              <div className="lbl">WHATSAPP</div>
              <div className="big">{waDisplay}</div>
              <div className="arr">{t.book.whatsapp || 'WhatsApp'} →</div>
              {t.book.whatsappNote && <div className="small" style={{ marginTop: 6, opacity: 0.65 }}>{t.book.whatsappNote}</div>}
            </a>
          )}
        </div>

        {/* OTA short note */}
        {t.book.otaShortNote && (
          <div className="ota-warning">{t.book.otaShortNote}</div>
        )}

        {/* Booking.com + Airbnb */}
        <div className="book-grid two">
          <a className="book-card" href={t.book.bkingUrl} target="_blank" rel="noopener noreferrer">
            <div className="lbl">BOOKING.COM</div>
            <div className="big">Booking.com</div>
            <div className="arr">{t.book.bking} ↗</div>
          </a>
          <a className="book-card" href={t.book.abnbUrl} target="_blank" rel="noopener noreferrer">
            <div className="lbl">AIRBNB</div>
            <div className="big">Airbnb</div>
            <div className="arr">{t.book.abnb} ↗</div>
          </a>
        </div>
      </div>
    </section>
  );
}

// ============== INFO ==============
function Info({ t }) {
  return (
    <section id="info">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{t.info.tag}</div>
          <div>
            <h2 style={{ fontSize: 'clamp(18px, 1.8vw, 22px)', fontWeight: 600 }}>{t.info.h}</h2>
          </div>
        </div>
        <div className="info-grid">
          <div className="info-box">
            <h4>{t.info.s1}</h4>
            <dl>
              <div className="row"><dt>商号</dt><dd><a href="https://tomotomo.club/" target="_blank" rel="noopener">TOMOTOMO合同会社 ↗</a></dd></div>
              <div className="row"><dt>代表</dt><dd>代表社員 <a href="https://tomotomo.club/ceoblog/" target="_blank" rel="noopener">簗田友子 ↗</a></dd></div>
              <div className="row"><dt>法人所在地</dt><dd>〒104-0054 東京都中央区勝どき6-3-2-4808</dd></div>
              <div className="row"><dt>物件所在地</dt><dd>〒942-1434 新潟県十日町市松之山天水島575-4</dd></div>
              <div className="row"><dt>届出</dt><dd>第M150062846号／令和8年4月8日（新潟県知事）</dd></div>
            </dl>
          </div>
          <div className="info-box">
            <h4>{t.info.s2}</h4>
            <dl>
              <div className="row"><dt>商号</dt><dd><a href="https://www.instagram.com/coffeehouse_project/" target="_blank" rel="noopener">珈琲ハウス株式会社 ↗</a></dd></div>
              <div className="row"><dt>代表</dt><dd>代表取締役 森野航平</dd></div>
              <div className="row"><dt>所在地</dt><dd>〒130-0002 東京都墨田区業平4-8-3 吉田マンション804</dd></div>
              <div className="row"><dt>登録番号</dt><dd>国土交通大臣(01)第F02745号</dd></div>
              <div className="row"><dt>苦情窓口</dt><dd>090-3231-8088</dd></div>
            </dl>
          </div>
          <div className="info-box">
            <h4>{t.info.s3}</h4>
            <p style={{ fontSize: 13, color: 'var(--ink-2)', margin: '0 0 12px', lineHeight: 1.7 }}>{t.info.s3V}</p>
            <ul>
              {t.info.fire.map((f, i) => <li key={i}>{f}</li>)}
            </ul>
          </div>
        </div>
      </div>
    </section>
  );
}

// ============== FOOTER ==============
function Footer({ t, lang }) {
  return (
    <footer className="foot">
      <div className="foot-inner">
        <div>
          <div className="brand brand-foot">
            <img className="brand-logo brand-logo-foot" src={lang === 'en' ? 'assets/brand/logo_en.png' : 'assets/brand/logo_ja.png'} alt={lang === 'en' ? 'Amamizushima Hills' : '天水島ヒルズ'} />
          </div>
          <div className="foot-addr">{t.foot.addr}</div>
          <div className="foot-license">{t.foot.license}</div>
        </div>
        <div>
          <h5>{t.nav.book}</h5>
          <ul>
            <li><a href="#book">{t.__lang === 'en' ? 'Booking form' : (t.__lang === 'zh' ? '预订表单' : 'ご予約フォーム')}</a></li>
            <li><a href="#book">{t.__lang === 'en' ? 'Availability calendar' : (t.__lang === 'zh' ? '空房日历' : '空室カレンダー')}</a></li>
            <li><a href="mailto:info@amamizushima.com">info@amamizushima.com</a></li>
            <li><a href="tel:+81-90-3231-8088">TEL · 090-3231-8088</a></li>
            <li><a href={t.book.bkingUrl} target="_blank" rel="noopener">Booking.com ↗</a></li>
            <li><a href={t.book.abnbUrl} target="_blank" rel="noopener">Airbnb ↗</a></li>
          </ul>
        </div>
        <div>
          <h5>CONTACT</h5>
          <ul>
            <li><a href="mailto:info@amamizushima.com">info@amamizushima.com</a></li>
            <li><a href="https://tomotomo.club/" target="_blank" rel="noopener">TOMOTOMO合同会社 ↗</a></li>
            <li>代表社員 <a href="https://tomotomo.club/ceoblog/" target="_blank" rel="noopener">簗田友子 ↗</a></li>
          </ul>
        </div>
      </div>
      <div className="foot-bottom">
        <div>© 2026 TOMOTOMO合同会社 · <a href={lang === 'ja' ? '/privacy/' : `/${lang}/privacy/`}>{t.privacy ? t.privacy.linkLabel : 'Privacy'}</a> · <a href="#" onClick={(e) => { e.preventDefault(); window.dispatchEvent(new CustomEvent('amami-reopen-consent')); }}>{t.consent.cookieSettings}</a></div>
        <div>AMAMIZUSHIMA · MATSUNOYAMA · NIIGATA</div>
      </div>
    </footer>
  );
}

// ============== STICKY CTA ==============
function StickyCta({ t }) {
  const [on, setOn] = useState(false);
  useEffect(() => {
    const onS = () => setOn(window.scrollY > window.innerHeight * 0.8);
    window.addEventListener('scroll', onS, { passive: true });
    return () => window.removeEventListener('scroll', onS);
  }, []);
  return (
    <div className={`sticky-cta ${on ? 'on' : ''}`}>
      <span className="dot" />
      <span>1{t.stats.people === 'pax' ? ' party / day' : (t.stats.people === '人' ? '日1組 · 空室確認' : '日1組 · 受付中')} · <span className="opening-pill cta-pill">{t.pricing.openingShort}</span><s className="cta-strike">¥40,000</s>¥28,000/{t.pricing.per.replace(/[/／ ]/g, '')}</span>
      <a href="#book" className="bk">{t.nav.book} →</a>
    </div>
  );
}

// ============== TWEAKS PANEL ==============
function TweaksPanel({ editMode, theme, setTheme, font, setFont, heroMode, setHeroMode, dispatchEdit }) {
  if (!editMode) return null;
  const T = (obj, v, set, k) => {
    set(v);
    dispatchEdit({ [k]: v });
  };
  return (
    <div className={`tw-panel on`}>
      <h6>Tweaks</h6>
      <div className="tw-group">
        <div className="glbl">Season theme</div>
        <div className="tw-chips">
          {['default','spring','summer','autumn','winter'].map(s => (
            <button key={s} className={theme === s ? 'on' : ''} onClick={() => T(null, s, setTheme, 'theme')}>{s}</button>
          ))}
        </div>
      </div>
      <div className="tw-group">
        <div className="glbl">Typeface</div>
        <div className="tw-chips">
          {['sans','serif'].map(f => (
            <button key={f} className={font === f ? 'on' : ''} onClick={() => T(null, f, setFont, 'font')}>{f}</button>
          ))}
        </div>
      </div>
      <div className="tw-group">
        <div className="glbl">Hero</div>
        <div className="tw-chips">
          {['auto','static'].map(h => (
            <button key={h} className={heroMode === h ? 'on' : ''} onClick={() => T(null, h, setHeroMode, 'heroMode')}>{h}</button>
          ))}
        </div>
      </div>
    </div>
  );
}

// ============== PRIVACY POLICY ==============
function PrivacyPolicy({ t, lang }) {
  const pp = t.privacy || {};
  return (
    <section id="privacy" className="privacy">
      <div className="page">
        <div className="sec-head">
          <div className="tag">{pp.tag}</div>
          <div>
            <h2>{pp.h}</h2>
            <p className="lead">{pp.lead}</p>
            <div className="privacy-meta">
              {pp.effectiveLabel}: {pp.effectiveDate}
            </div>
          </div>
        </div>
        <div className="privacy-body">
          {(pp.sections || []).map((s, i) => (
            <section key={i} className="pp-section">
              <h3>{s.h}</h3>
              {s.body.split('\n').map((line, j) => (
                line.trim() ? <p key={j}>{line}</p> : null
              ))}
            </section>
          ))}
        </div>
      </div>
    </section>
  );
}

// ============== APP ==============
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "default",
  "font": "sans",
  "heroMode": "auto",
  "lang": "ja"
}/*EDITMODE-END*/;

function detectLangFromPath() {
  const p = window.location.pathname;
  if (p.startsWith('/en/') || p === '/en') return 'en';
  if (p.startsWith('/zh/') || p === '/zh') return 'zh';
  return 'ja';
}

function App() {
  const saved = (() => {
    try { return JSON.parse(localStorage.getItem('amamizu.tweaks') || 'null'); } catch(e) { return null; }
  })();
  const init = { ...TWEAK_DEFAULTS, ...(saved || {}) };

  const [lang, setLang] = useState(detectLangFromPath());
  const [pathname, setPathname] = useState(window.location.pathname);
  const isPrivacy = pathname.includes('/privacy');
  const [theme, setTheme] = useState(init.theme);
  const [font, setFont] = useState(init.font);
  const [heroMode, setHeroMode] = useState(init.heroMode);
  const [editMode, setEditMode] = useState(false);

  const [consent, setConsent] = useState(() => {
    try { return localStorage.getItem('amami_consent') || ''; } catch { return ''; }
  });
  const [showBanner, setShowBanner] = useState(false);
  const [showSettings, setShowSettings] = useState(false);
  const [analyticsAllowed, setAnalyticsAllowed] = useState(false);
  const [functionalAllowed, setFunctionalAllowed] = useState(true);

  useEffect(() => {
    if (consent) return;
    fetch('/api/eu-info')
      .then(r => r.json())
      .then(d => { if (d && d.is_eu) setShowBanner(true); })
      .catch(() => {});
  }, [consent]);

  const saveConsent = (value) => {
    try {
      localStorage.setItem('amami_consent', value);
      document.cookie = `amami_consent=${value}; max-age=31536000; path=/; SameSite=Lax`;
    } catch(_) {}
    setConsent(value);
    setShowBanner(false);
    setShowSettings(false);
  };
  const acceptAll = () => saveConsent('all');
  const rejectAll = () => saveConsent('essential');
  const saveCustom = () => saveConsent(analyticsAllowed ? 'analytics' : 'essential');

  useEffect(() => {
    const handler = () => { setShowBanner(true); setShowSettings(true); };
    window.addEventListener('amami-reopen-consent', handler);
    return () => window.removeEventListener('amami-reopen-consent', handler);
  }, []);

  const t = useMemo(() => {
    const resolved = lang;
    const o = window.I18N[resolved] || window.I18N.ja;
    return { ...o, __lang: resolved };
  }, [lang]);

  useEffect(() => {
    document.body.classList.remove('theme-default','theme-spring','theme-summer','theme-autumn','theme-winter');
    document.body.classList.add(`theme-${theme}`);
    document.body.classList.toggle('ff-serif', font === 'serif');
  }, [theme, font]);

  useEffect(() => {
    // Handle hash anchor on initial mount (React SPA needs explicit scroll after components render)
    if (window.location.hash) {
      const id = window.location.hash.slice(1);
      const tries = [50, 200, 600, 1500];
      tries.forEach((delay) => {
        setTimeout(() => {
          const el = document.getElementById(id);
          if (el) el.scrollIntoView({ behavior: 'instant', block: 'start' });
        }, delay);
      });
    }
  }, []);

  const dispatchEdit = (edits) => {
    const merged = { ...TWEAK_DEFAULTS, theme, font, heroMode, lang, ...edits };
    localStorage.setItem('amamizu.tweaks', JSON.stringify(merged));
    window.parent.postMessage({ type: '__edit_mode_set_keys', edits }, '*');
  };

  useEffect(() => {
    dispatchEdit({ lang });
  }, [lang]);

  useEffect(() => {
    const onPop = () => {
      setLang(detectLangFromPath());
      setPathname(window.location.pathname);
    };
    window.addEventListener('popstate', onPop);
    return () => window.removeEventListener('popstate', onPop);
  }, []);

  useEffect(() => {
    if (isPrivacy) window.scrollTo(0, 0);
  }, [isPrivacy]);

  useEffect(() => {
    document.documentElement.lang = lang;
  }, [lang]);

  useEffect(() => {
    const onMsg = (e) => {
      if (!e.data) return;
      if (e.data.type === '__activate_edit_mode') setEditMode(true);
      if (e.data.type === '__deactivate_edit_mode') setEditMode(false);
    };
    window.addEventListener('message', onMsg);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', onMsg);
  }, []);

  return (
    <>
      <Nav t={t} lang={lang} setLang={setLang} setPathname={setPathname} isPrivacy={isPrivacy} editMode={editMode} />
      {isPrivacy ? (
        <PrivacyPolicy t={t} lang={lang} />
      ) : (
      <>
      <Hero t={t} heroMode={heroMode} />
      <Ticker t={t} />
      <House t={t} />
      <Floorplan t={t} />
      <Rooms t={t} />
      <Pricing t={t} />
      <Events t={t} />
      <Rules t={t} />
      <Seasons t={t} />
      <Onsen t={t} />
      <Pets t={t} />
      <Food t={t} />
      <Yearly t={t} />
      <Gallery t={t} />
      <Practical t={t} />
      <Around t={t} />
      <Access t={t} />
      <Book t={t} lang={lang} />
      <Info t={t} />
      </>
      )}
      <Footer t={t} lang={lang} />
      {!isPrivacy && <StickyCta t={t} />}
      <TweaksPanel editMode={editMode} theme={theme} setTheme={setTheme} font={font} setFont={setFont} heroMode={heroMode} setHeroMode={setHeroMode} dispatchEdit={dispatchEdit} />
      {showBanner && (
        <div className="cookie-banner" role="dialog" aria-label={t.consent.title}>
          <div className="cookie-inner">
            <h3 className="cookie-title">{t.consent.title}</h3>
            <p className="cookie-body">{t.consent.body}</p>

            {showSettings && (
              <div className="cookie-cats">
                <label className="cookie-cat">
                  <input type="checkbox" checked disabled readOnly />
                  <div>
                    <div className="ccn">{t.consent.catEssential}</div>
                    <div className="ccd">{t.consent.catEssentialDesc}</div>
                  </div>
                </label>
                <label className="cookie-cat">
                  <input type="checkbox" checked={functionalAllowed} onChange={(e) => setFunctionalAllowed(e.target.checked)} />
                  <div>
                    <div className="ccn">{t.consent.catFunctional}</div>
                    <div className="ccd">{t.consent.catFunctionalDesc}</div>
                  </div>
                </label>
                <label className="cookie-cat">
                  <input type="checkbox" checked={analyticsAllowed} onChange={(e) => setAnalyticsAllowed(e.target.checked)} />
                  <div>
                    <div className="ccn">{t.consent.catAnalytics}</div>
                    <div className="ccd">{t.consent.catAnalyticsDesc}</div>
                  </div>
                </label>
              </div>
            )}

            <div className={`cookie-actions ${showSettings ? 'two' : 'three'}`}>
              {showSettings ? (
                <>
                  <button className="cookie-btn" onClick={rejectAll}>{t.consent.btnRejectAll}</button>
                  <button className="cookie-btn cookie-btn-primary" onClick={saveCustom}>{t.consent.btnSave}</button>
                </>
              ) : (
                <>
                  <button className="cookie-btn" onClick={rejectAll}>{t.consent.btnRejectAll}</button>
                  <button className="cookie-btn" onClick={() => setShowSettings(true)}>{t.consent.btnCustomize}</button>
                  <button className="cookie-btn cookie-btn-primary" onClick={acceptAll}>{t.consent.btnAcceptAll}</button>
                </>
              )}
            </div>
          </div>
        </div>
      )}
    </>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
