// pages-shop.jsx — Home, Product detail, Purchase complete
const { Icon, Logo, MediaPH, PRODUCTS, CATEGORIES } = window.LCS;

// ─────────────────────────────────────────────────────────────
// Carousel — 16:9 main image with side arrows, plus a thumbnail
// strip below flanked by left/right buttons.
// ─────────────────────────────────────────────────────────────
const Carousel = ({ slides, autoplay = false, interval = 6500, thumbVisible = 3, go, ruleLink }) => {
  const [idx, setIdx] = React.useState(0);
  const [paused, setPaused] = React.useState(false);
  const [fullscreen, setFullscreen] = React.useState(false);
  const n = slides.length;

  React.useEffect(() => {
    if (!autoplay || paused || fullscreen || n <= 1) return;
    const t = setInterval(() => setIdx((i) => (i + 1) % n), interval);
    return () => clearInterval(t);
  }, [autoplay, paused, fullscreen, n, interval]);

  React.useEffect(() => {
    if (!fullscreen) return;
    const prevOverflow = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    const onKeyDown = (e) => {
      if (e.key === "Escape") setFullscreen(false);
      if (e.key === "ArrowLeft") goTo(idx - 1);
      if (e.key === "ArrowRight") goTo(idx + 1);
    };
    window.addEventListener("keydown", onKeyDown);
    return () => {
      document.body.style.overflow = prevOverflow;
      window.removeEventListener("keydown", onKeyDown);
    };
  }, [fullscreen, idx, n]);

  const goTo = (i) => setIdx(((i % n) + n) % n);
  const s = slides[idx];
  const followSlide = (e, href) => {
    if (!go || !href?.startsWith("/")) return;
    const [route, id] = href.replace(/^\//, "").split("/");
    e.preventDefault();
    go(route || "home", id);
  };

  // 表示ウィンドウ: 現在スライドが中央付近に来るよう winStart を算出
  const visCount = Math.min(thumbVisible, n);
  const half = Math.floor(visCount / 2);
  const winStart = Math.max(0, Math.min(idx - half, n - visCount));
  const visibleThumbs = slides.slice(winStart, winStart + visCount);

  return (
    <div className="carousel"
      onMouseEnter={() => setPaused(true)}
      onMouseLeave={() => setPaused(false)}>
      <div className="carousel__main">
        {s.href
          ? <a href={s.href} onClick={(e) => followSlide(e, s.href)}><img src={s.src} alt={s.alt} /></a>
          : <img src={s.src} alt={s.alt} />}
      </div>
      {n > 1 &&
        <div className="carousel__strip">
          <button className="carousel__strip-nav" onClick={() => goTo(idx - 1)} aria-label="前のサムネイル">
            <Icon name="chev-l" size={16} />
          </button>
          <div className="carousel__thumbs" style={{ gridTemplateColumns: `repeat(${visCount}, minmax(0, 1fr))` }}>
            {visibleThumbs.map((t, i) => {
              const actualIdx = winStart + i;
              return (
                <button key={actualIdx}
                  className={"carousel__thumb" + (actualIdx === idx ? " active" : "")}
                  onClick={() => setIdx(actualIdx)}
                  aria-label={`slide ${actualIdx + 1}`}>
                  <img src={t.src} alt={t.alt} />
                </button>
              );
            })}
          </div>
          <button className="carousel__strip-nav" onClick={() => goTo(idx + 1)} aria-label="次のサムネイル">
            <Icon name="chev-r" size={16} />
          </button>
        </div>
      }
      {ruleLink && (
        <button className="carousel__rule-link" onClick={ruleLink.onClick} type="button">
          {ruleLink.label}
        </button>
      )}
      <button className="carousel__fullscreen" onClick={() => setFullscreen(true)} type="button" aria-label="画像を全画面表示">
        <Icon name="expand" size={18} />
      </button>
      {fullscreen && (
        <div className="image-viewer" role="dialog" aria-modal="true" aria-label="画像を全画面表示">
          <button className="image-viewer__close" onClick={() => setFullscreen(false)} type="button" aria-label="閉じる">
            <Icon name="x" size={22} />
          </button>
          {n > 1 && (
            <button className="image-viewer__nav image-viewer__nav--prev" onClick={() => goTo(idx - 1)} type="button" aria-label="前の画像">
              <Icon name="chev-l" size={28} />
            </button>
          )}
          <div className="image-viewer__stage">
            <img src={s.src} alt={s.alt} />
          </div>
          {n > 1 && (
            <button className="image-viewer__nav image-viewer__nav--next" onClick={() => goTo(idx + 1)} type="button" aria-label="次の画像">
              <Icon name="chev-r" size={28} />
            </button>
          )}
          <div className="image-viewer__count">{idx + 1} / {n}</div>
        </div>
      )}
    </div>
  );
};

// ─────────────────────────────────────────────────────────────
// Shared: product card (16:9 media)
// ─────────────────────────────────────────────────────────────
const ProductCard = ({ p, go }) =>
<a className="product-card" onClick={() => go("product", p.id)} style={{ cursor: "pointer" }}>
    <div className="product-card__media">
      <img src={p.images[0].src} alt={p.images[0].alt} />
      {p.badge?.label && (
        <span className="badge" style={{ position: "absolute", top: 12, left: 12, background: p.badge.bg, color: p.badge.color, borderColor: "transparent" }}>{p.badge.label}</span>
      )}
    </div>
    <div className="product-card__body">
      <div style={{ fontSize: 11, fontWeight: 700, color: "var(--c-ink-3)", letterSpacing: "0.16em" }}>{p.en.toUpperCase()}</div>
      <div className="product-card__title">{p.name}</div>
      <div className="product-card__meta">
        <div className="product-card__price">¥{p.price.toLocaleString()}<small> 税込</small></div>
        {p.tags[0] && (
          <span className="badge" style={{ background: p.tags[0].bg, color: p.tags[0].color, borderColor: "transparent" }}>{p.tags[0].label}</span>
        )}
      </div>
    </div>
  </a>;


// ─────────────────────────────────────────────────────────────
// HERO — image-only 16:9 carousel (no overlay text or UI)
// ─────────────────────────────────────────────────────────────
const HERO_SLIDES = [
  { src: "/uploads/lcs-card-maker-8.webp", alt: "LCS カード メーカー 8", href: "/product/lcs-card-maker-8" },
  { src: "/games/crossone/top.webp", alt: "クロスワン", href: "/product/crossone" },
  { src: "/games/calc/top.webp", alt: "カルク Ver2.0", href: "/product/calc" },
  { src: "/games/battlemonsters/deck1.webp", alt: "バトルモンスターズ草原デッキ", href: "/product/bm-grass" },
  { src: "/games/battlemonsters/deck2.webp", alt: "バトルモンスターズ砂漠デッキ", href: "/product/bm-desert" },
  { src: "/games/battlemonsters/deck3.webp", alt: "バトルモンスターズ山デッキ", href: "/product/bm-mountain" },
  { src: "/games/battlemonsters/deck4.webp", alt: "バトルモンスターズ海デッキ", href: "/product/bm-ocean" },
];

const Hero = ({ go }) =>
  <section className="hero-carousel">
    <Carousel slides={HERO_SLIDES} autoplay go={go} />
  </section>;

// ─────────────────────────────────────────────────────────────
// Markdown description accordion
// ─────────────────────────────────────────────────────────────
const MD_LEVEL_CLASS = { 1: "h1", 2: "h2", 3: "h3", 4: "h4", 5: "h5", 6: "h6" };

const escapeHtml = (value = "") =>
  value
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;");

const renderInlineMarkdown = (value = "") =>
  escapeHtml(value)
    .replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>")
    .replace(/\*([^*]+)\*/g, "<em>$1</em>");

const parseMarkdownBlocks = (lines) => {
  const blocks = [];
  let paragraph = [];
  let list = null;

  const flushParagraph = () => {
    if (!paragraph.length) return;
    blocks.push({ type: "p", text: paragraph.join("\n") });
    paragraph = [];
  };
  const flushList = () => {
    if (!list) return;
    blocks.push(list);
    list = null;
  };

  lines.forEach((raw) => {
    const line = raw.trimEnd();
    const unordered = line.match(/^\s*[-*]\s+(.+)$/);
    const ordered = line.match(/^\s*\d+\.\s+(.+)$/);

    if (!line.trim()) {
      flushParagraph();
      flushList();
      return;
    }

    if (unordered || ordered) {
      flushParagraph();
      const type = unordered ? "ul" : "ol";
      if (!list || list.type !== type) {
        flushList();
        list = { type, items: [] };
      }
      list.items.push((unordered || ordered)[1]);
      return;
    }

    flushList();
    paragraph.push(line.trim());
  });

  flushParagraph();
  flushList();
  return blocks;
};

const parseMarkdownAccordion = (markdown = "") => {
  const root = { level: 0, children: [], blocks: [] };
  const stack = [root];
  let pending = [];

  const flushPending = () => {
    if (!pending.length) return;
    stack[stack.length - 1].blocks.push(...parseMarkdownBlocks(pending));
    pending = [];
  };

  markdown.replace(/\r\n?/g, "\n").split("\n").forEach((line) => {
    const heading = line.match(/^(#{1,6})\s+(.+)$/);
    if (!heading) {
      pending.push(line);
      return;
    }

    flushPending();
    const level = heading[1].length;
    const node = { level, title: heading[2].trim(), blocks: [], children: [] };
    while (stack.length > 1 && stack[stack.length - 1].level >= level) stack.pop();
    stack[stack.length - 1].children.push(node);
    stack.push(node);
  });

  flushPending();
  return root;
};

const MarkdownBlock = ({ block }) => {
  if (block.type === "ul" || block.type === "ol") {
    const Tag = block.type;
    return (
      <Tag>
        {block.items.map((item, i) => (
          <li key={i} dangerouslySetInnerHTML={{ __html: renderInlineMarkdown(item) }} />
        ))}
      </Tag>
    );
  }

  return <p dangerouslySetInnerHTML={{ __html: renderInlineMarkdown(block.text).replace(/\n/g, "<br />") }} />;
};

const MarkdownAccordionNode = ({ node, path }) => {
  const isOpen = path.every((index) => index === 0);
  const iconSize = Math.max(8, 15 - node.level);

  return (
    <details className={`md-acc md-acc--${MD_LEVEL_CLASS[node.level]}`} open={isOpen} data-md-title={node.title}>
      <summary className="md-acc__sum">
        <span className="md-acc__title">{node.title}</span>
        {node.level < 6 && (
          <span className="md-acc__chev" aria-hidden="true">
            <Icon name="chev" size={iconSize} />
          </span>
        )}
      </summary>
      <div className="md-acc__body">
        {node.blocks.map((block, i) => <MarkdownBlock key={`b-${i}`} block={block} />)}
        {node.children.map((child, i) => (
          <MarkdownAccordionNode key={`${child.level}-${child.title}-${i}`} node={child} path={[...path, i]} />
        ))}
      </div>
    </details>
  );
};

const getProductKind = (product) => product.type === "service" ? "service" : "game";

const getDescriptionSections = (product) => {
  if (getProductKind(product) !== "service") {
    return {
      about: "このゲームについて",
      flow: "遊び方の流れ",
      contents: "内容物",
      flowItems: product.howToPlay || [],
      contentItems: product.contents || [],
    };
  }

  return {
    about: "サービス内容",
    flow: "ご注文後の流れ",
    contents: "制作・納品内容",
    flowItems: product.serviceFlow || product.howToPlay || [],
    contentItems: product.deliverables || product.contents || [],
  };
};

const buildProductMarkdownFallback = (p) => {
  const sections = getDescriptionSections(p);
  return [
  `# ${sections.about}`,
  "",
  p.short,
  "",
  p.desc,
  "",
  `# ${sections.flow}`,
  "",
  ...sections.flowItems.flatMap((step) => ["- " + step.replace(/\n+/g, " ").trim()]),
  "",
  `# ${sections.contents}`,
  "",
  ...sections.contentItems.map((item) => "- " + item),
  ].join("\n");
};

const getProductPriceRows = (product) => {
  if (Array.isArray(product.priceRows)) return product.priceRows;
  if (getProductKind(product) === "service") {
    return [
      { label: "入稿方法", value: "購入後メールで専用URLを送付" },
      { label: "制作目安", value: "入稿完了後 7〜14 営業日" },
    ];
  }
  return [
    { label: "送料", value: "商品価格に含む" },
    { label: "発送目安", value: "ご注文から 7〜14 営業日" },
  ];
};

const getProductSpecRows = (product) => {
  if (Array.isArray(product.specRows)) return product.specRows;
  if (getProductKind(product) === "service") {
    return [
      { label: "制作枚数", value: product.spec.cards },
      { label: "入稿画像", value: product.spec.upload },
      { label: "カードサイズ", value: product.spec.size },
      { label: "納品形式", value: product.spec.delivery },
      { label: "制作目安", value: product.spec.schedule },
      { label: "修正対応", value: product.spec.revision },
    ].filter((row) => row.value);
  }
  return [
    { label: "プレイ人数", value: product.spec.players },
    { label: "プレイ時間", value: product.spec.time },
    { label: "対象年齢", value: product.spec.age },
    { label: "カード枚数", value: product.spec.count },
    { label: "カードサイズ", value: product.spec.size },
    { label: "発売", value: product.releaseDate },
  ];
};

const ProductDescriptionAccordion = ({ product }) => {
  const [state, setState] = React.useState({ status: "loading", markdown: "" });
  const markdownPath = product.descriptionMarkdown || `/products/${product.id}.md`;

  React.useEffect(() => {
    let active = true;
    setState({ status: "loading", markdown: "" });

    fetch(markdownPath)
      .then((res) => {
        if (!res.ok) throw new Error(`Markdown not found: ${markdownPath}`);
        if (res.headers.get("content-type")?.includes("text/html")) {
          throw new Error(`Markdown fallback returned HTML: ${markdownPath}`);
        }
        return res.text();
      })
      .then((markdown) => {
        if (active) setState({ status: "ready", markdown });
      })
      .catch(() => {
        if (active) setState({ status: "ready", markdown: buildProductMarkdownFallback(product) });
      });

    return () => { active = false; };
  }, [markdownPath, product.id]);

  if (state.status === "loading") {
    return (
      <div className="mt-32 desc-md desc-md--loading" aria-live="polite">
        説明を読み込んでいます...
      </div>
    );
  }

  const tree = parseMarkdownAccordion(state.markdown);
  return (
    <div className="mt-32 desc-md">
      {tree.blocks.map((block, i) => <MarkdownBlock key={`root-${i}`} block={block} />)}
      {tree.children.map((node, i) => (
        <MarkdownAccordionNode key={`${node.level}-${node.title}-${i}`} node={node} path={[i]} />
      ))}
    </div>
  );
};

// ─────────────────────────────────────────────────────────────
// HOME — FAQ teaser items (matched to FAQ page answers)
// ─────────────────────────────────────────────────────────────
const HOME_FAQ_ITEMS = [
  {
    q: "注文してから手元に届くまで、どれくらいかかりますか？",
    a: "通常、ご注文から 7〜14 営業日以内を目安に発送いたします。受注生産のため、ご注文状況や生産状況により発送時期が前後する場合があります。",
  },
  {
    q: "キャンセルや返品はできますか？",
    a: "受注生産のため、ご注文完了（決済完了）後のキャンセルおよびお客様都合による返品はお受けしておりません。商品に破損や不良があった場合は、商品到着後 7 日以内にお問い合わせください。",
  },
  {
    q: "海外への発送はしていますか？",
    a: "現在は日本国内への配送のみ対応しています。予めご了承ください。",
  },
  {
    q: "支払い方法を教えてください。",
    a: "クレジットカード（Stripe 決済）がご利用いただけます。分割払いの可否はご利用のクレジットカード会社の設定によって異なります。",
  },
];

const FaqTeaserList = () => {
  const [open, setOpen] = React.useState({});
  return (
    <ul>
      {HOME_FAQ_ITEMS.map((it, i) => {
        const num = String(i + 1).padStart(2, "0");
        const isOpen = !!open[i];
        return (
          <li key={i} className={"faq-teaser__item" + (isOpen ? " open" : "")}>
            <button className="faq-teaser__q" onClick={() => setOpen({ ...open, [i]: !isOpen })} aria-expanded={isOpen}>
              <b>{num}</b>
              <span>{it.q}</span>
              <span className="faq-teaser__chev"><Icon name="chev" size={16} /></span>
            </button>
            {isOpen && <div className="faq-teaser__a">{it.a}</div>}
          </li>
        );
      })}
    </ul>
  );
};

const HomePage = ({ go }) =>
<main className="page" data-screen-label="01 Top">
    <div className="shell">
      {/* HERO CAROUSEL — image only */}
      <Hero go={go} />

      {/* FEATURED */}
      <section className="section">
        <div className="section__head">
          <div>
            <span className="section__title-en">PRODUCTS</span>
            <h2 className="section__title">商品一覧</h2>
          </div>
          <a className="section__more" onClick={() => go("shop")}>すべて見る <Icon name="chev-r" size={14} /></a>
        </div>
        <div className="product-grid">
          {PRODUCTS.map((p) => <ProductCard key={p.id} p={p} go={go} />)}
        </div>
      </section>

      {/* SHOP BLURB */}
      <section className="section">
        <div className="blurb">
          <div>
            <span className="section__title-en">ABOUT THE SHOP</span>
            <h2 className="blurb__title">社会貢献に繋がる、<br />ハンドメイド生産のカード。</h2>
            <p className="blurb__body">
              ローシスカードショップの製品づくりには、働きたくても機会に恵まれない方々の「輝ける場所」を創るという想いがあります。
            </p>
            <p className="blurb__body">
              現在は、ご縁のある身近な高齢者や障がいを持つ方々と共に、一つひとつ手作業で生産しています。
            </p>
            <p className="blurb__body">
              この活動の輪が広がることで、より多くの方が社会と繋がり、自分らしく楽しく働ける場を広げていきたいと考えています。
            </p>
          </div>
          <div className="blurb__panel">
            <div className="blurb__stat"><span className="blurb__stat-k">◆ これまでの作品数</span><span className="blurb__stat-v">6<small>タイトル</small></span></div>
            <div className="blurb__stat"><span className="blurb__stat-k">◆ 発送までの目安</span><span className="blurb__stat-v">7〜14<small>営業日</small></span></div>
            <div className="blurb__stat"><span className="blurb__stat-k">◆ 送料</span><span className="blurb__stat-v">商品価格に含む</span></div>
            <div className="blurb__stat"><span className="blurb__stat-k">◆ 決済</span><span className="blurb__stat-v">Stripe<small> 各種カード対応</small></span></div>
          </div>
          <div className="blurb__cta">
            <button className="btn" onClick={() => go("about")}>ショップについて <Icon name="arrow-r" size={14} /></button>
          </div>
        </div>
      </section>

      {/* FAQ TEASER */}
      <section className="section">
        <div className="faq-teaser">
          <div>
            <span className="section__title-en" style={{ color: "var(--c-main)" }}>FAQ</span>
            <h2 className="faq-teaser__title">よくある<em>質問</em></h2>
            <p style={{ color: "rgba(255,251,234,.7)", fontSize: 14, lineHeight: 1.7, maxWidth: 320 }}>
              ご注文の前に、よく聞かれる質問をまとめました。一覧は FAQ ページからもご覧いただけます。
            </p>
            <button className="btn btn--primary mt-16" onClick={() => go("faq")}>すべての FAQ を見る <Icon name="arrow-r" size={14} /></button>
          </div>
          <FaqTeaserList />
        </div>
      </section>
    </div>
  </main>;


// ─────────────────────────────────────────────────────────────
// PRODUCT DETAIL
// ─────────────────────────────────────────────────────────────
const ProductPage = ({ pid, go }) => {
  const p = PRODUCTS.find((x) => x.id === pid) || PRODUCTS[0];
  const gallery = p.images;
  const productKind = getProductKind(p);
  const priceRows = getProductPriceRows(p);
  const specRows = getProductSpecRows(p);
  const isService = productKind === "service";
  const [noticeOpen, setNoticeOpen] = React.useState(false);
  const descriptionRef = React.useRef(null);

  React.useEffect(() => {
    if (!noticeOpen) return;
    const onKeyDown = (e) => {
      if (e.key === "Escape") setNoticeOpen(false);
    };
    window.addEventListener("keydown", onKeyDown);
    return () => window.removeEventListener("keydown", onKeyDown);
  }, [noticeOpen]);

  const scrollToRules = () => {
    if (!descriptionRef.current) return;
    const headerOffset = document.querySelector(".header")?.offsetHeight || 0;
    const targetY = descriptionRef.current.getBoundingClientRect().top + window.scrollY - headerOffset - 18;
    window.scrollTo({ top: Math.max(0, targetY), behavior: "smooth" });
  };

  return (
    <main className="page" data-screen-label="02 Product">
      <div className="shell">
        <div className="crumb">
          <a onClick={() => go("home")}>ホーム</a>
          <span className="crumb__sep">/</span>
          <a onClick={() => go("shop")}>商品一覧</a>
          <span className="crumb__sep">/</span>
          <span className="crumb__cur">{p.name}</span>
        </div>

        <section className={"pdp" + (gallery.length === 1 ? " pdp--single-image" : "")}>
          {/* GALLERY */}
          <div className="pdp__gallery">
            <Carousel
              slides={gallery}
              thumbVisible={4}
              ruleLink={{ label: isService ? "サービス説明を見る" : "ルール説明を見る", onClick: scrollToRules }}
            />
          </div>

          <div className="pdp__side">
            {/* INFO */}
            <aside className="pdp__info">
              <div className="pdp__brand">LOWSYS CARD SHOP · {p.en.toUpperCase()}</div>
              <h1 className="pdp__title">{p.name}</h1>
              <div className="pdp__badges">
                {p.badge?.label && (
                  <span className="badge" style={{ background: p.badge.bg, color: p.badge.color, borderColor: "transparent" }}>{p.badge.label}</span>
                )}
                {p.tags.map((t, i) => (
                  <span key={i} className="badge" style={{ background: t.bg, color: t.color, borderColor: "transparent" }}>{t.label}</span>
                ))}
              </div>

              <div className="price-block">
                <div className="price-block__main">
                  <div className="price-block__amount">¥{p.price.toLocaleString()}<small>JPY</small></div>
                  <div className="price-block__tax">税込 / Tax incl.</div>
                </div>
                {priceRows.map((row) => (
                  <div className="price-block__row" key={row.label}><span>{row.label}</span><b>{row.value}</b></div>
                ))}
              </div>

              <button className="pdp-notice" onClick={() => setNoticeOpen(true)} type="button">
                <span className="note__icon">!</span>
                <span>
                  <b>{isService ? "オーダー制作サービスです" : "受注生産のお品です"}</b>
                  <small>ご注文前の注意事項を確認する</small>
                </span>
                <Icon name="chev-r" size={16} />
              </button>

              {noticeOpen && (
                <div className="modal-backdrop" onClick={() => setNoticeOpen(false)}>
                  <div className="modal" role="dialog" aria-modal="true" aria-labelledby="production-notice-title" onClick={(e) => e.stopPropagation()}>
                    <button className="modal__close" onClick={() => setNoticeOpen(false)} type="button" aria-label="閉じる">
                      <Icon name="x" size={18} />
                    </button>
                    <div className="modal__icon">!</div>
                    <h2 id="production-notice-title">{isService ? "オーダー制作サービスです" : "受注生産のお品です"}</h2>
                    {isService ? (
                      <>
                        <ul>
                          <li>ご注文完了後、購入時のメールアドレス宛にカード画像の入稿URLをお送りします。</li>
                          <li>画像送信後の制作開始となるため、送信前に内容をよくご確認ください。</li>
                          <li>ご注文完了後のキャンセルおよびお客様都合による返金はお受けしておりません。</li>
                        </ul>
                        <h3 className="modal__subhead">画像送信前のご注意</h3>
                        <ul>
                          <li>画像送信後は、同じURLから再アップロードすることはできません。</li>
                          <li>送信完了後の画像差し替え・修正依頼は、原則としてお受けできません。</li>
                          <li>低価格での制作サービスのため、送信後の個別修正対応は制作工程・作業コストの都合上、対応が難しくなります。</li>
                          <li>画像の内容、表裏の組み合わせ、向き、枚数に誤りがないか、必ず確認してから送信してください。</li>
                        </ul>
                      </>
                    ) : (
                      <ul>
                        <li>ご注文完了（決済完了）後のキャンセルおよびお客様都合による返品はお受けしておりません。</li>
                        <li>商品に破損や不良があった場合は、商品到着後 7 日以内にお問い合わせください。</li>
                      </ul>
                    )}
                    <button className="btn btn--primary btn--block" onClick={() => setNoticeOpen(false)} type="button">確認しました</button>
                  </div>
                </div>
              )}

              <button className="btn btn--accent btn--xl btn--block" onClick={() => { window.location.href = p.stripeUrl; }}>
                <Icon name="lock" size={18} /> Stripe で購入する　¥{p.price.toLocaleString()}
              </button>
              <div className="muted center" style={{ fontSize: 12, marginTop: 10 }}>
                決済は Stripe の安全なチェックアウト画面に遷移します
              </div>
            </aside>

            {/* SPECS */}
            <aside className="pdp__specs">
              <div className="section__head" style={{ marginTop: 36, marginBottom: 12, paddingBottom: 8 }}>
                <h3 className="section__title" style={{ fontSize: 18 }}>商品仕様</h3>
              </div>
              <table className="spec-table">
                <tbody>
                  {specRows.map((row) => (
                    <tr key={row.label}><th>{row.label}</th><td>{row.value}</td></tr>
                  ))}
                </tbody>
              </table>
            </aside>
          </div>

          {/* DESCRIPTION */}
          <div className="pdp__description" ref={descriptionRef}>
            <ProductDescriptionAccordion product={p} />
          </div>

        </section>

        {/* RELATED */}
        <section className="section">
          <div className="section__head">
            <h2 className="section__title">こちらもおすすめ</h2>
          </div>
          <div className="product-grid">
            {PRODUCTS.filter((x) => x.id !== p.id).slice(0, 4).map((x) => <ProductCard key={x.id} p={x} go={go} />)}
          </div>
        </section>
      </div>
    </main>);

};

// ─────────────────────────────────────────────────────────────
// PURCHASE COMPLETE
// ─────────────────────────────────────────────────────────────
const CompletePage = ({ go }) =>
<main className="page" data-screen-label="03 Complete">
    <div className="shell">
      <div className="complete">
        <div className="complete__seal">
          <Icon name="check" size={56} />
        </div>
        <h1 className="complete__title">ご注文ありがとうございました。</h1>
        <p className="complete__sub">
          決済が完了しました。ご登録のメールアドレスに、Stripe から領収メールをお送りしています。<br />
          ご注文内容のご確認は、そちらのメールよりお願いいたします。
        </p>

        <div className="steps">
          <div className="step">
            <div className="step__num">1</div>
            <h3 className="step__title">レシートメールを確認</h3>
            <p className="step__body">Stripe より自動送信のメールが届きます。届かない場合は迷惑メールフォルダもご確認ください。</p>
          </div>
          <div className="step">
            <div className="step__num">2</div>
            <h3 className="step__title">発送までの期間</h3>
            <p className="step__body">受注生産のため、ご注文から発送まで 7〜14 営業日ほどお時間をいただきます。</p>
          </div>
          <div className="step">
            <div className="step__num">3</div>
            <h3 className="step__title">発送通知</h3>
            <p className="step__body">商品を発送する際、別途追跡番号付きのメールをお送りします。</p>
          </div>
        </div>

        <div className="note" style={{ textAlign: "left", maxWidth: 560, margin: "0 auto 28px" }}>
          <div className="note__icon">?</div>
          <div>
            <b>ご質問・配送先の変更がある場合</b>
            お問い合わせフォームより、注文番号を添えてご連絡ください。発送前であれば対応可能です。
          </div>
        </div>

        <div className="flex gap-12" style={{ justifyContent: "center" }}>
          <button className="btn btn--primary btn--lg" onClick={() => go("home")}>ホームに戻る</button>
          <a className="btn btn--lg" href="https://lcs.lowsys.co.jp/contact" target="_blank" rel="noopener">お問い合わせ <Icon name="mail" size={14} /></a>
        </div>
      </div>
    </div>
  </main>;


window.LCS = Object.assign(window.LCS, { HomePage, ProductPage, CompletePage, ProductCard, Carousel });
