// sc-components.jsx — shared Nav, Footer, AnimateIn, UI primitives const LINE_URL = "https://lin.ee/1YA6KpG"; const LOGO_URL = "images/logo.png"; const PAGE_URLS = { home: "index.html", begin: "begin.html", course: "service.html", voice: "voice.html", bio: "about.html", contact: "contact.html", }; function pageUrl(id) { return PAGE_URLS[id] || "index.html"; } /* ── AnimateIn ─────────────────────────────────────────────── */ function AnimateIn({ children, delay = 0, className = "", style = {} }) { const ref = React.useRef(null); const [visible, setVisible] = React.useState(false); React.useEffect(() => { const el = ref.current; if (!el) return; const obs = new IntersectionObserver( ([e]) => { if (e.isIntersecting) { setVisible(true); obs.disconnect(); } }, { threshold: 0.08 } ); obs.observe(el); return () => obs.disconnect(); }, []); return (
{children}
); } /* ── SectionHeader ─────────────────────────────────────────── */ function SectionHeader({ label, title, sub, center = false, light = false }) { const align = center ? "center" : "left"; return (
{label && (

{label}

)}

{title}

{sub && (

{sub}

)}
); } /* ── LineButton — CTA → contact.html ──────────────────────── */ function LineButton({ children = "1週間の無料トライアルはこちら", large = false, ghost = false }) { const base = { display: "inline-flex", alignItems: "center", gap: "10px", fontFamily: "var(--font-sans)", fontWeight: 500, letterSpacing: "0.06em", borderRadius: "2px", cursor: "pointer", textDecoration: "none", transition: "all 0.25s ease", }; const filled = { background: "var(--accent)", color: "#fff", padding: large ? "18px 44px" : "14px 32px", fontSize: large ? "15px" : "14px", border: "1.5px solid var(--accent)", }; const ghostStyle = { background: "transparent", color: "var(--accent)", padding: large ? "18px 44px" : "14px 32px", fontSize: large ? "15px" : "14px", border: "1.5px solid var(--accent)", }; return ( { e.currentTarget.style.opacity = "0.82"; e.currentTarget.style.transform = "translateY(-1px)"; }} onMouseLeave={e => { e.currentTarget.style.opacity = "1"; e.currentTarget.style.transform = "none"; }}> {children} ); } /* ── GoldLine ──────────────────────────────────────────────── */ function GoldLine({ width = "48px", margin = "0" }) { return
; } /* ── Nav ───────────────────────────────────────────────────── */ function Nav({ currentPage }) { const [scrolled, setScrolled] = React.useState(false); const [mobileOpen, setMobileOpen] = React.useState(false); React.useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 40); window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); const links = [ { id: "home", label: "ホーム" }, { id: "begin", label: "初めての方へ" }, { id: "course", label: "サービス内容" }, { id: "voice", label: "利用者の声" }, { id: "bio", label: "運営者" }, ]; const navBg = scrolled || mobileOpen ? "rgba(255,255,255,0.97)" : "transparent"; const navBorder = scrolled || mobileOpen ? "1px solid var(--border)" : "1px solid transparent"; const linkColor = (!scrolled && !mobileOpen && currentPage === "home") ? "#fff" : "var(--text)"; return ( ); } /* ── Footer ────────────────────────────────────────────────── */ function Footer() { const links = [ { id: "begin", label: "初めての方へ" }, { id: "course", label: "サービス内容" }, { id: "voice", label: "利用者の声" }, { id: "bio", label: "運営者" }, ]; return ( ); } /* ── CtaSection ────────────────────────────────────────────── */ function CtaSection({ title = "まず、1週間。無料で試してください。", sub = "現状のタスクを整理し、行動の道筋をつける初回セッションから始めます。" }) { return (

{title}

{sub}

); } Object.assign(window, { AnimateIn, SectionHeader, LineButton, GoldLine, Nav, Footer, CtaSection, LINE_URL, pageUrl, PAGE_URLS });