// 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 */}
{/* Right: content */}
{entry.highlight && (
★ signature
)}
);
}
return (
{/* Left side — photo when isLeft, text when !isLeft */}
{/* Center — time marker */}
{/* vertical line */}
{entry.time}
{entry.highlight && (
★ signature
)}
{/* Right */}
);
}
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 (
);
})}
);
}
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 });