// hero.jsx — Hero section, intro prologue, plan chooser
function Hero() {
const hero = window.HERO || {};
const [y, setY] = React.useState(0);
const isMobile = useIsMobile();
React.useEffect(() => {
const h = () => setY(window.scrollY);
window.addEventListener('scroll', h, { passive: true });
return () => window.removeEventListener('scroll', h);
}, []);
const descLines = (hero.description || '').split('\n');
return (
{/* tagline — vertical on desktop, horizontal centered on mobile */}
{isMobile ? (
{hero.titleLine1 || '急がない、贅沢。'}
{hero.titleLine2 || '連泊の、過ごし方。'}
{hero.enLabel || 'Renpaku. A Two-Night Stay.'}
) : (
{hero.titleLine1 || '急がない、贅沢。'}
{hero.titleLine2 || '連泊の、過ごし方。'}
{hero.enLabel || 'Renpaku. A Two-Night Stay.'}
)}
{/* left: copy */}
{hero.enEyebrow || '— Tatsuta Renpaku Plan —'}
{descLines.map((line, i) => (
{line}
{i < descLines.length - 1 &&
}
))}
);
}
function Prologue() {
const pro = window.PROLOGUE || {};
const isMobile = useIsMobile();
const body = pro.body || '';
const highlight = pro.highlight || '特別オプション';
// ハイライト語をstrong化(改行も処理)
const renderBody = () => {
if (!body) return null;
const parts = body.split(highlight);
if (parts.length === 1) {
return body.split('\n').map((line, i, arr) => (
{line}
{i < arr.length - 1 &&
}
));
}
const out = [];
parts.forEach((part, idx) => {
const lines = part.split('\n');
lines.forEach((line, lidx) => {
out.push({line});
if (lidx < lines.length - 1) out.push(
);
});
if (idx < parts.length - 1) {
out.push({highlight});
}
});
return out;
};
return (
— 01. Prologue —
{pro.titleLine1 || '連泊という、'}
{pro.titleLine2 || 'ゆるやかな時間。'}
{renderBody()}
);
}
// Plan chooser — two cards, same price
function PlanChoose() {
const isMobile = useIsMobile();
return (
{PLANS.map((p) => (
{p.en}
{p.kana}
{p.tagline}
{p.body}
{p.note && (
{p.note}
)}
{(p.keywords || []).map(k => (
{k}
))}
ご 予 約 は こ ち ら
))}
);
}
// プロモーションバナー(サマーセール等の期間限定キャンペーン)
// 表示・非表示はACFで切替可能。レスポンシブ幅にも対応
function PromoBanner() {
const banner = window.PROMO_BANNER || {};
if (!banner.enabled || !banner.image) {
return null;
}
const widthPercent = banner.widthPercent || 50;
const widthPercentMobile = banner.widthPercentMobile || 95;
const breakpoint = banner.breakpoint || 768;
const bgColor = banner.bgColor || '#F7F3E8';
const padding = banner.padding || '60px 40px';
const paddingMobile = banner.paddingMobile || '32px 16px';
const url = banner.url || '#';
const alt = banner.alt || '';
const newTab = banner.openInNewTab !== false;
const wrapClass = 'tatsuta-renpaku-lp-v8-promo-wrap';
const linkClass = 'tatsuta-renpaku-lp-v8-promo-link';
const responsiveCss = `
.${wrapClass} { padding: ${padding}; }
.${linkClass} { display: inline-block; width: ${widthPercent}%; }
@media (max-width: ${breakpoint}px) {
.${wrapClass} { padding: ${paddingMobile}; }
.${linkClass} { width: ${widthPercentMobile}%; }
}
`;
return (
);
}
Object.assign(window, { Hero, Prologue, PlanChoose, PromoBanner });