// daysection.jsx — Day timeline for okomori & shuyu, seasonal spots, closing function DaySection({ plan, entries, index }) { const isOko = plan.id === 'okomori'; const isMobile = useIsMobile(); return (
{/* watermark kanji */}
{plan.kanji}
{entries.map((e, i) => ( ))}
そ し て 、 ま た 朝 へ
); } function TimelineRow({ entry, index, side, isLast, bg = '#F7F3E8' }) { const ref = React.useRef(null); const [inView, setInView] = React.useState(false); const isMobile = useIsMobile(); React.useEffect(() => { if (!ref.current) return; const io = new IntersectionObserver( ([e]) => e.isIntersecting && setInView(true), { threshold: 0.15 } ); io.observe(ref.current); return () => io.disconnect(); }, []); const isLeft = side === 'left'; if (isMobile) { return (
{/* Left: spine */}
{entry.time}
{/* Right: content */}
{entry.highlight && (
★ signature
)}
); } return (
{/* Left side — photo when isLeft, text when !isLeft */}
{isLeft ?
: }
{/* Center — time marker */}
{/* vertical line */}
{entry.time}
{entry.highlight && (
★ signature
)}
{/* Right */}
{isLeft ? :
}
); } function TextBlock({ entry, align }) { return (
{entry.tuk && (
Tuk-Tuk · {entry.tuk} min
)}

{entry.title}

{entry.body}

); } // Seasonal spots row (ties into Shuyu plan narrative) function SeasonalSpots() { const isMobile = useIsMobile(); return (
{SEASONAL_SPOTS.map(s => (
{s.label}
{s.sub}
Tuk · approx {s.km} km
))}
); } function FaqSection() { const [open, setOpen] = React.useState(0); const isMobile = useIsMobile(); return (
{FAQ.map((f, i) => { const isOpen = open === i; return (
{f.a}
); })}
); } function Reserve() { const r = window.RESERVE_DATA || {}; const isMobile = useIsMobile(); return (
{PLANS.map((p) => (
{p.kana}
¥ {p.reservePrice}
{r.priceUnitLabel || '二泊一名あたり'}
{(window.PRICE || {}).subNote}
ご 予 約 は こ ち ら
))}
); } function Footer() { const site = window.SITE_INFO || {}; const isMobile = useIsMobile(); return ( ); } Object.assign(window, { DaySection, SeasonalSpots, FaqSection, Reserve, Footer });