const { useState: useStateH } = window.React;

/* How it works — 3 step */
const HowItWorks = ({ lang }) => {
  const steps = lang === "ja"
    ? [
      { n: "01", t: "チャットを開く", d: "ChatGPT・Claude・Geminiを開いたまま、サイドパネルを起動。", mono: "OPEN" },
      { n: "02", t: "生成を押す", d: "会話全体を読み取り、階層構造に変換します。", mono: "GENERATE" },
      { n: "03", t: "考えを辿る", d: "ノードをクリックして分岐、編集、再生成。時系列の外に出る。", mono: "EXPLORE" },
    ]
    : [
      { n: "01", t: "Open a chat", d: "Keep ChatGPT, Claude, or Gemini open. Launch the side panel.", mono: "OPEN" },
      { n: "02", t: "Press generate", d: "The whole conversation is parsed into a hierarchy in one pass.", mono: "GENERATE" },
      { n: "03", t: "Trace your thinking", d: "Click any node to branch, edit, regenerate. Escape the timeline.", mono: "EXPLORE" },
    ];

  const COUNT = steps.length;
  const [demoStep, setDemoStep] = useStateH(0);
  const sectionRef = window.React.useRef(null);

  return (
    <section id="how" ref={sectionRef} className="section container">
        <div style={{ marginBottom: 40 }}>
          <div className="eyebrow eyebrow-accent">03 STEPS / {lang === "ja" ? "しくみ" : "HOW IT WORKS"}</div>
          <h2 className="title-xl" style={{ marginTop: 20 }}>
            {lang === "ja" ? <>時系列を辿る。</> : <>Break the <em style={{ fontStyle: "italic" }}>timeline</em>.</>}
          </h2>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 32, marginBottom: 32 }}>
          {steps.map((s, i) => (
            <div key={i} style={{
              padding: "24px 0",
              borderTop: "2px solid",
              borderColor: i === demoStep ? "var(--accent)" : "var(--ink-10)",
              opacity: i === demoStep ? 1 : 0.5,
              transition: "opacity 400ms ease, border-color 400ms ease",
            }}>
              <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 10 }}>
                <div style={{
                  width: 28, height: 28, borderRadius: "50%",
                  display: "grid", placeItems: "center",
                  fontFamily: "var(--font-mono)", fontWeight: 600,
                  fontSize: 11, letterSpacing: "0.04em",
                  background: "var(--accent)",
                  color: "#fff",
                  animation: i === demoStep ? "stepPulse 1.8s ease-in-out infinite" : "none",
                }}>{s.n}</div>
                <span className="mono-hi" style={{ color: "var(--accent)" }}>{s.mono}</span>
              </div>
              <div style={{
                fontFamily: "var(--font-sans)", fontWeight: 500,
                fontSize: 18, color: "var(--ink)", letterSpacing: "-0.015em",
              }}>{s.t}</div>
              <div style={{
                marginTop: 6, fontSize: 13.5, lineHeight: 1.55,
                color: "var(--ink-60)",
              }}>{s.d}</div>
            </div>
          ))}
        </div>
        <div style={{ display: "flex", justifyContent: "center", marginTop: 48 }}>
          <ChatPlusExtensionWindow lang={lang} interactive={true} autoPlay={true} fast={true} onStep={setDemoStep}/>
        </div>
        <style>{`
          @keyframes stepPulse {
            0%, 100% { box-shadow: 0 0 0 0 rgba(201,88,60,0.4); }
            50% { box-shadow: 0 0 0 8px rgba(201,88,60,0); }
          }
        `}</style>
    </section>
  );
};

/* Step-aware animated mock screen for HowItWorks */
const HowDemo = ({ lang, step }) => {
  const ja = lang === "ja";
  // Track which steps have been visited so animations play once
  const visited = window.React.useRef(new Set());
  const [phase, setPhase] = useStateH("idle");

  window.React.useEffect(() => {
    if (visited.current.has(step)) return;
    visited.current.add(step);
    setPhase("enter");
    const t = setTimeout(() => setPhase("active"), 600);
    return () => clearTimeout(t);
  }, [step]);

  const tabs = ja
    ? ["販売戦略レビュー", "JBN UI改善", "チェックイン画面"]
    : ["Sales strategy", "JP UI review", "Check-in screen"];

  const msgs = ja
    ? [
        { who: "user", t: "明日クライアント（D2Cのスキンケアブランド、年商18億）と販売戦略のキックオフ。" },
        { who: "ai", t: "CACが1.4倍になってる時点で、広告倍プッシュは赤字を倍にするだけの確率が高いです。" },
      ]
    : [
        { who: "user", t: "Kicking off sales strategy tomorrow with the D2C skincare client (¥1.8B revenue)." },
        { who: "ai", t: "With CAC at 1.4×, doubling ad spend likely just doubles the losses." },
      ];

  // Cursor position per step
  const cursorPos = step === 0
    ? { left: "22%", top: "14%", opacity: phase !== "idle" ? 1 : 0 }
    : step === 1
    ? { left: "82%", top: "38%", opacity: phase !== "idle" ? 1 : 0 }
    : { left: "78%", top: "55%", opacity: phase !== "idle" ? 1 : 0 };

  const showChat = step >= 0 && phase !== "idle";
  const showPanel = step >= 1;
  const showMindmap = step >= 2;

  return (
    <div style={{
      width: "100%", maxWidth: 1400, height: 480,
      borderRadius: 14, overflow: "hidden",
      background: "var(--bg-raised)",
      boxShadow: "0 1px 0 rgba(255,255,255,0.6) inset, 0 0 0 1px var(--ink-10), 0 28px 56px -16px rgba(26,24,21,0.28)",
      fontFamily: "var(--font-sans)",
      display: "flex", flexDirection: "column", position: "relative",
    }}>
      {/* titlebar */}
      <div style={{
        height: 36, display: "flex", alignItems: "center",
        padding: "0 14px", gap: 14, flex: "0 0 auto",
        background: "linear-gradient(180deg, rgba(26,24,21,0.05), rgba(26,24,21,0.01))",
        borderBottom: "1px solid var(--ink-10)",
      }}>
        <div style={{ display: "flex", gap: 6 }}>
          {["#FF5F57","#FEBC2E","#28C840"].map((c,i) => (
            <span key={i} style={{ width: 10, height: 10, borderRadius: "50%", background: c }}/>
          ))}
        </div>
        <div style={{ flex: 1, textAlign: "center", font: '500 12px/1 var(--font-sans)', color: "var(--ink-60)" }}>
          Chrome — chatgpt.com / LLMindMap
        </div>
        <div style={{ width: 42 }}/>
      </div>

      {/* body */}
      <div style={{ flex: 1, display: "flex", minHeight: 0, position: "relative" }}>
        {/* Chat side */}
        <div style={{
          flex: showPanel ? "0 0 50%" : "1 1 100%",
          minWidth: 0, display: "flex", flexDirection: "column",
          borderRight: showPanel ? "1px solid var(--ink-10)" : "none",
          transition: "flex 500ms ease",
        }}>
          {/* Chat header with tabs */}
          <div style={{
            padding: "8px 16px", display: "flex", alignItems: "center", gap: 10,
            borderBottom: "1px solid var(--ink-10)", flex: "0 0 auto",
          }}>
            <span className="mono-hi" style={{ fontSize: 9.5, letterSpacing: "0.18em" }}>CHATGPT</span>
            <span style={{ width: 1, height: 10, background: "var(--ink-10)" }}/>
            {tabs.map((tab, i) => (
              <span key={i} style={{
                fontSize: 11, padding: "3px 8px", borderRadius: 6,
                background: i === 0 && showChat ? "var(--ink-10)" : "transparent",
                color: i === 0 ? "var(--ink)" : "var(--ink-40)",
                fontWeight: i === 0 ? 500 : 400,
                transition: "all 400ms ease",
                cursor: "default",
              }}>{tab}</span>
            ))}
          </div>

          {/* Chat messages */}
          <div style={{
            flex: 1, padding: "16px 18px", overflowY: "auto",
            display: "flex", flexDirection: "column", gap: 16,
            opacity: showChat ? 1 : 0,
            transform: showChat ? "translateY(0)" : "translateY(12px)",
            transition: "opacity 500ms ease 200ms, transform 500ms ease 200ms",
          }}>
            {msgs.map((m, i) => (
              <div key={i} style={{
                display: "flex", gap: 10,
                justifyContent: m.who === "user" ? "flex-end" : "flex-start",
                alignItems: "flex-start",
              }}>
                {m.who === "ai" && (
                  <div style={{
                    width: 24, height: 24, borderRadius: "50%",
                    background: "var(--ink)", color: "var(--bg-raised)",
                    display: "grid", placeItems: "center",
                    fontSize: 10, fontWeight: 700, flexShrink: 0,
                  }}>AI</div>
                )}
                <div style={{
                  maxWidth: "75%", padding: "10px 14px", borderRadius: 12,
                  background: m.who === "user" ? "var(--ink-10)" : "transparent",
                  border: m.who === "ai" ? "1px solid var(--ink-10)" : "none",
                  fontSize: 13, lineHeight: 1.55, color: "var(--ink)",
                }}>{m.t}</div>
                {m.who === "user" && (
                  <div style={{
                    width: 24, height: 24, borderRadius: "50%",
                    background: "var(--accent)", color: "#fff",
                    display: "grid", placeItems: "center",
                    fontSize: 8, fontWeight: 700, flexShrink: 0, letterSpacing: "0.05em",
                  }}>YOU</div>
                )}
              </div>
            ))}
          </div>

          {/* Input bar */}
          <div style={{
            padding: "8px 12px 10px", borderTop: "1px solid var(--ink-10)",
            display: "flex", alignItems: "center", gap: 8, flex: "0 0 auto",
          }}>
            <div style={{
              flex: 1, height: 30, borderRadius: 8, background: "var(--bg)",
              boxShadow: "inset 0 0 0 1px var(--ink-10)",
              display: "flex", alignItems: "center", padding: "0 10px",
              font: '400 12px/1 var(--font-sans)', color: "var(--ink-40)",
            }}>{ja ? "メッセージを送信…" : "Send a message…"}</div>
            <div style={{
              width: 30, height: 30, borderRadius: 8,
              background: "var(--accent)", color: "#fff",
              display: "flex", alignItems: "center", justifyContent: "center",
            }}>
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round">
                <path d="M12 19V5M5 12l7-7 7 7"/>
              </svg>
            </div>
            {/* LLMindMap brand mark — stays at bottom-right of chat pane */}
            <div style={{
              width: 36, height: 36, borderRadius: 10, flexShrink: 0,
              background: "#F5F3EE",
              boxShadow: "2px 2px 5px rgba(0,0,0,0.08), -2px -2px 5px rgba(255,255,255,0.9)",
              display: "grid", placeItems: "center",
            }}>
              <svg width="18" height="18" viewBox="0 0 22 22" fill="none">
                <circle cx="11" cy="11" r="2" fill="#C9583C"/>
                <circle cx="4" cy="4" r="1.7" fill="#C9583C"/>
                <circle cx="18" cy="4" r="1.7" fill="#2E86DE"/>
                <circle cx="4" cy="18" r="1.7" fill="#27AE60"/>
                <circle cx="18" cy="18" r="1.7" fill="#9B59B6"/>
                <path d="M11 11 L4 4 M11 11 L18 4 M11 11 L4 18 M11 11 L18 18"
                  stroke="#3B352D" strokeWidth="1.4" strokeLinecap="round"/>
              </svg>
            </div>
          </div>
        </div>

        {/* Extension panel — slides in at step 1 */}
        <div style={{
          flex: showPanel ? "0 0 50%" : "0 0 0%",
          minWidth: 0, overflow: "hidden",
          transition: "flex 500ms ease",
          display: "flex",
        }}>
          <HowDemoPanel lang={lang} showMindmap={showMindmap}/>
        </div>

        {/* Animated cursor */}
        <div style={{
          position: "absolute",
          ...cursorPos,
          transition: "left 600ms cubic-bezier(0.4, 0, 0.2, 1), top 600ms cubic-bezier(0.4, 0, 0.2, 1), opacity 300ms ease",
          pointerEvents: "none", zIndex: 10,
        }}>
          <svg width="20" height="20" viewBox="0 0 24 24" fill="var(--ink)" stroke="var(--bg-raised)" strokeWidth="1.5">
            <path d="M4 1L4 17L9 12.5L14.5 20L17 18.5L11.5 11L18 10L4 1Z"/>
          </svg>
          {/* click ripple */}
          <div style={{
            position: "absolute", top: 0, left: 0, width: 24, height: 24,
            borderRadius: "50%", border: "2px solid var(--accent)",
            animation: phase === "enter" ? "clickRipple 600ms ease-out forwards" : "none",
            opacity: 0, transform: "scale(0)",
          }}/>
        </div>
      </div>

      <style>{`
        @keyframes clickRipple {
          0% { opacity: 0.8; transform: scale(0); }
          100% { opacity: 0; transform: scale(2.5); }
        }
      `}</style>
    </div>
  );
};

/* Mini extension panel for HowItWorks demo */
const HowDemoPanel = ({ lang, showMindmap }) => {
  const ja = lang === "ja";
  const railIcons = [
    "M6 4L6 14L10 10.5L14 16L16 15L12 9L16 8L6 4",
    "M4.5 10 A4.5 4.5 0 0 1 13 7.5 M13 4.5 L13 7.5 L10 7.5",
    "M3 3 L9 3 L15 9 L9 15 L3 9 Z",
    "M4 8 A4 4 0 1 1 12 8 A4 4 0 1 1 4 8 M11 11 L15 15",
    "M5 3 L13 3 L13 15 L9 12 L5 15 Z",
  ];

  return (
    <div style={{ width: "100%", height: "100%", display: "flex", background: "#F5F0E8" }}>
      {/* Rail */}
      <div style={{
        width: 44, flexShrink: 0, display: "flex", flexDirection: "column",
        alignItems: "center", gap: 6, paddingTop: 10,
        borderRight: "1px solid rgba(59,53,45,0.06)",
      }}>
        {railIcons.map((d, i) => (
          <div key={i} style={{
            width: 34, height: 34, borderRadius: 10,
            display: "grid", placeItems: "center",
            background: "#F5F0E8",
            boxShadow: i === 0
              ? "inset 2px 2px 4px #C8BFAE, inset -2px -2px 4px #FFFDF8"
              : "3px 3px 7px #C8BFAE, -3px -3px 7px #FFFDF8",
          }}>
            <svg width="16" height="16" viewBox="0 0 18 18" fill={i === 0 ? "#C9583C" : "none"}
              stroke={i === 0 ? "none" : "#8C8070"} strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round">
              <path d={d}/>
            </svg>
          </div>
        ))}
      </div>

      {/* Content */}
      <div style={{ flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }}>
        {/* Header */}
        <div style={{
          padding: "10px 14px", display: "flex", alignItems: "center", gap: 8,
          borderBottom: "1px solid rgba(59,53,45,0.06)",
        }}>
          <span style={{ fontWeight: 600, fontSize: 13, color: "#3B352D" }}>LLMindMap</span>
          <span style={{ fontSize: 10, color: "#8C8070" }}>Trace, edit, and surpass any LLM chat</span>
        </div>

        {/* Mindmap area */}
        <div style={{
          flex: 1, display: "grid", placeItems: "center",
          opacity: showMindmap ? 1 : 0,
          transform: showMindmap ? "scale(1)" : "scale(0.9)",
          transition: "opacity 600ms ease 200ms, transform 600ms ease 200ms",
        }}>
          <svg viewBox="0 0 300 200" width="80%" height="80%">
            {/* branches */}
            {[
              { x: 90, y: 60 }, { x: 210, y: 50 }, { x: 220, y: 140 },
              { x: 80, y: 150 }, { x: 180, y: 170 }, { x: 120, y: 40 },
            ].map((p, i) => (
              <line key={i} x1="150" y1="100" x2={p.x} y2={p.y}
                stroke="#8C8070" strokeWidth="1" opacity="0.5"/>
            ))}
            {/* leaves */}
            {[
              { x: 60, y: 40, c: "#E74C3C" }, { x: 90, y: 60, c: "#2E86DE" },
              { x: 120, y: 40, c: "#9B59B6" }, { x: 210, y: 50, c: "#27AE60" },
              { x: 240, y: 35, c: "#F39C12" }, { x: 220, y: 140, c: "#E74C3C" },
              { x: 250, y: 155, c: "#2E86DE" }, { x: 80, y: 150, c: "#9B59B6" },
              { x: 50, y: 165, c: "#27AE60" }, { x: 180, y: 170, c: "#F39C12" },
            ].map((p, i) => (
              <circle key={i} cx={p.x} cy={p.y} r="4" fill={p.c} opacity="0.8"/>
            ))}
            {/* hub */}
            <circle cx="150" cy="100" r="8" fill="#3B352D"/>
            {/* sub branches */}
            {[
              [90, 60, 60, 40], [120, 40, 90, 60], [210, 50, 240, 35],
              [220, 140, 250, 155], [80, 150, 50, 165],
            ].map(([x1, y1, x2, y2], i) => (
              <line key={`s${i}`} x1={x1} y1={y1} x2={x2} y2={y2}
                stroke="#8C8070" strokeWidth="0.8" opacity="0.4"/>
            ))}
          </svg>
        </div>

      </div>
    </div>
  );
};

/* Features grid */
const FeaturesGrid = ({ lang }) => {
  const items = lang === "ja"
    ? [
      { mono: "分類",       t: "カテゴリ自動分類", d: "課題・質問・アイデア・意思決定・情報・余談・未分類。色でパターンが見える。", v: "chips" },
      { mono: "検索",       t: "ノード横断検索",   d: "すべてのマップを横断して、一語で過去の思考に戻る。",                       v: "search" },
      { mono: "スター",     t: "お気に入り",       d: "後で戻りたいノードをマーク。時間軸に縛られない読書リスト。",             v: "star" },
      { mono: "PNG / PDF",  t: "ワンクリック書き出し", d: "思考地図をPNGまたはPDFで保存。共有も振り返りも一瞬で。",              v: "export" },
      { mono: "履歴",       t: "ローカル無限履歴", d: "すべてはブラウザに保存。サーバーに送信しない。",                         v: "history" },
      { mono: "JA / EN",    t: "日英バイリンガル", d: "UIもエクスポートも、日本語と英語を切り替え。",                           v: "bilingual" },
      { mono: "分析",       t: "構造ギャップ検出", d: "チャットでは見えない枝の偏りや孤立した論点を、グラフ構造から発見。",     v: "gaps", pro: true },
      { mono: "LIVE",       t: "ライブ成長",       d: "会話の進行に合わせてマインドマップがリアルタイムで育つ。",               v: "live", pro: true },
      { mono: "思考",       t: "思考プロファイル", d: "あなたの思考パターンを可視化。探索深度、評価率、構造変更を分析。",       v: "profile", pro: true },
      { mono: "統合",       t: "グラフ統合",       d: "複数の会話を1枚の地図に。重複は自動でマージされる。",                   v: "merge", upcoming: true },
    ]
    : [
      { mono: "CLASSIFY",  t: "Color-by-category", d: "Seven roles in plain sight: issue, question, idea, decision, info, aside, unclassified.", v: "chips" },
      { mono: "SEARCH",    t: "Cross-map search",  d: "One query against every map you've ever made. Old thinking, one word away.",            v: "search" },
      { mono: "STAR",      t: "Starred nodes",     d: "A reading list that isn't time-ordered. Mark thoughts to return to.",                    v: "star" },
      { mono: "PNG / PDF", t: "One-click export",  d: "Save your mind map as PNG or PDF. Share or revisit in seconds.",                        v: "export" },
      { mono: "HISTORY",   t: "Local, unbounded",  d: "Everything stays in your browser. Nothing ships to a server.",                          v: "history" },
      { mono: "JA / EN",   t: "Bilingual throughout", d: "Switch the interface and exports between Japanese and English.",                     v: "bilingual" },
      { mono: "ANALYSIS",  t: "Structural gap detection", d: "Find branch imbalance, orphan conclusions, and blind spots invisible in chat.",  v: "gaps", pro: true },
      { mono: "LIVE",      t: "Live grow",          d: "Your mindmap grows in real time as the conversation unfolds.",                          v: "live", pro: true },
      { mono: "PROFILE",   t: "Thinking profile",   d: "Visualize your thinking patterns: exploration depth, evaluation rate, restructuring.", v: "profile", pro: true },
      { mono: "MERGE",    t: "Graph merging",       d: "Multiple conversations fold into a single atlas. Duplicates auto-merge.",              v: "merge", upcoming: true },
    ];

  const COUNT = items.length;
  const [active, setActive] = useStateH(0);
  const sectionRef = window.React.useRef(null);

  window.React.useEffect(() => {
    let raf = 0;
    const compute = () => {
      raf = 0;
      const el = sectionRef.current;
      if (!el) return;
      const rect = el.getBoundingClientRect();
      const scrolled = -rect.top;
      const scrollable = el.offsetHeight - window.innerHeight;
      if (scrollable <= 0) return;
      const progress = Math.max(0, Math.min(1, scrolled / scrollable));
      setActive(Math.min(COUNT - 1, Math.floor(progress * COUNT)));
    };
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(compute); };
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    compute();
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      if (raf) cancelAnimationFrame(raf);
    };
  }, [lang]);

  return (
    <section id="features" ref={sectionRef} style={{ height: `${(COUNT + 1) * 100}vh`, position: "relative", marginTop: 120 }}>
      <div style={{
        position: "sticky",
        top: 0,
        height: "100vh",
        minHeight: "100vh",
        overflow: "hidden",
        contain: "layout paint",
      }}>
      <div className="container" style={{
        height: "100%",
        display: "flex", flexDirection: "column",
        paddingTop: 64, boxSizing: "border-box",
        overflow: "hidden",
      }}>
        <div style={{ marginBottom: 28, maxWidth: 760 }}>
          <div className="eyebrow eyebrow-accent">FEATURES / {lang === "ja" ? "機能" : "CAPABILITIES"}</div>
          <h2 className="title-xl" style={{ marginTop: 12 }}>
            {lang === "ja"
              ? <>より<em style={{ fontStyle: "italic" }}>深い思考</em>のための、十の道具。</>
              : <>Ten tools for <em style={{ fontStyle: "italic" }}>thinking</em>, not just chatting.</>}
          </h2>
        </div>

        <div style={{
          display: "grid",
          gridTemplateColumns: "minmax(0, 1.3fr) minmax(0, 1fr)",
          gap: 48,
          alignItems: "center",
          flex: "1 1 auto",
          minHeight: 0,
          overflow: "hidden",
        }}>
          <div style={{ width: "100%", minWidth: 0 }}>
            <FeatureThumb v={items[active].v} mono={items[active].mono} title={items[active].t} upcoming={items[active].upcoming} pro={items[active].pro}/>
          </div>

          <div style={{
            display: "grid",
            gridTemplateColumns: "1fr 1fr",
            gap: 6,
            overflow: "hidden",
            alignContent: "start",
            minHeight: 0,
          }}>
            {items.map((it, i) => (
              <div key={i}
                onClick={() => setActive(i)}
                style={{
                  display: "flex", flexDirection: "column",
                  padding: "8px 12px",
                  alignItems: "flex-start",
                  minHeight: 0,
                  overflow: "hidden",
                  cursor: "pointer",
                  opacity: i === active ? 1 : 0.5,
                  background: i === active ? "var(--accent-soft)" : "transparent",
                  borderRadius: 12,
                  border: i === active ? "1px solid rgba(201,88,60,0.2)" : "1px solid transparent",
                  transition: "none",
                }}>
                <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 4 }}>
                  <div style={{
                    width: 26, height: 26, borderRadius: "50%",
                    display: "grid", placeItems: "center",
                    fontFamily: "var(--font-mono)", fontWeight: 600,
                    fontSize: 10, letterSpacing: "0.04em",
                    background: i === active ? "var(--accent)" : "transparent",
                    color: i === active ? "#fff" : "var(--ink-60)",
                    boxShadow: i === active ? "none" : "inset 0 0 0 1px var(--ink-20)",
                    transition: "none",
                    flexShrink: 0,
                  }}>{String(i + 1).padStart(2, "0")}</div>
                  <span style={{
                    fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.12em",
                    textTransform: "uppercase", fontWeight: 500,
                    color: it.upcoming ? "var(--ink-40)" : "var(--accent)",
                  }}>{it.mono}</span>
                  {it.pro && <span style={{
                    fontSize: 9, fontFamily: "var(--font-mono)", letterSpacing: "0.1em",
                    textTransform: "uppercase", color: "var(--accent)", fontWeight: 600,
                    border: "1px solid rgba(201,88,60,0.35)", borderRadius: 4, padding: "1px 5px",
                    background: "rgba(201,88,60,0.08)",
                  }}>PRO</span>}
                  {it.upcoming && <span style={{
                    fontSize: 9, fontFamily: "var(--font-mono)", letterSpacing: "0.1em",
                    textTransform: "uppercase", color: "#D4820A", fontWeight: 600,
                    border: "1px solid rgba(212,130,10,0.35)", borderRadius: 4, padding: "1px 5px",
                    background: "rgba(212,130,10,0.08)",
                  }}>COMING SOON</span>}
                </div>
                <div style={{
                  fontFamily: "var(--font-sans)", fontWeight: 600,
                  fontSize: 15, color: it.upcoming ? "var(--ink-40)" : "var(--ink)", letterSpacing: "-0.015em",
                  lineHeight: 1.25,
                }}>{it.t}</div>
                <div style={{
                  marginTop: 3, fontSize: 12.5, lineHeight: 1.45,
                  color: it.upcoming ? "var(--ink-20)" : "var(--ink-60)",
                }}>{it.d}</div>
              </div>
            ))}
          </div>
        </div>
      </div>
      </div>
    </section>
  );
};

const FeatureThumb = ({ v, mono, title, upcoming, pro }) => (
  <div style={{
    background: "#F5F0E8",
    borderRadius: 14, overflow: "hidden",
    boxShadow: "0 22px 46px -18px rgba(30,26,20,0.32), 0 2px 8px rgba(30,26,20,0.08)",
    height: "clamp(430px, 58vh, 570px)",
    display: "flex",
    flexDirection: "column",
  }}>
    <div style={{
      height: 50,
      padding: "0 18px", borderBottom: "1px solid rgba(59,53,45,0.06)",
      display: "flex", alignItems: "center", gap: 10,
      flexShrink: 0,
      boxSizing: "border-box",
    }}>
      <span style={{ width: 8, height: 8, borderRadius: "50%", background: upcoming ? "#B8BCCB" : "var(--accent)" }}/>
      <span style={{
        fontFamily: "var(--font-mono)", fontSize: 11,
        letterSpacing: "0.16em", color: upcoming ? "#8C8070" : "#3B352D", fontWeight: 600,
      }}>{mono}</span>
      {pro && <span style={{
        fontSize: 9, fontFamily: "var(--font-mono)", letterSpacing: "0.1em",
        color: "var(--accent)", border: "1px solid rgba(201,88,60,0.3)", borderRadius: 4, padding: "2px 6px",
        background: "rgba(201,88,60,0.06)",
      }}>PRO</span>}
      {upcoming && <span style={{
        fontSize: 9, fontFamily: "var(--font-mono)", letterSpacing: "0.1em",
        color: "#8C8070", border: "1px solid rgba(59,53,45,0.15)", borderRadius: 4, padding: "2px 6px",
      }}>COMING SOON</span>}
      <span style={{ flex: 1 }}/>
      <span style={{
        minWidth: 0,
        maxWidth: "45%",
        overflow: "hidden",
        textOverflow: "ellipsis",
        whiteSpace: "nowrap",
        fontSize: 12,
        color: "#8C8070",
      }}>{title}</span>
    </div>
    <div style={{
      flex: "1 1 auto",
      minHeight: 0,
      display: "grid",
      placeItems: "center",
      padding: 24,
      position: "relative",
      overflow: "hidden",
    }}>
      <FeatureVignette v={v}/>
    </div>
  </div>
);

const FeatureVignette = ({ v }) => {
  if (v === "chips")     return <VChips/>;
  if (v === "search")    return <VSearch/>;
  if (v === "star")      return <VStar/>;
  if (v === "export")    return <VExport/>;
  if (v === "history")   return <VHistory/>;
  if (v === "bilingual") return <VBilingual/>;
  if (v === "merge")     return <VMerge/>;
  if (v === "gaps")      return <VGaps/>;
  if (v === "live")      return <VLive/>;
  if (v === "profile")   return <VProfile/>;
  return null;
};

const _C = {
  accent: "#C9583C", slate: "#536A8A", iris: "#8F6FA3",
  sage: "#7A9A85", ochre: "#B8864A", ash: "#8A7D86",
  panelInk: "#3B352D", panelMute: "#8C8070", panel: "#F5F0E8", bg: "#F2EFE8",
};

const VChips = () => {
  // Pellets positioned at their corresponding node locations (viewBox 420×440)
  // issue(accent) → チャネル別分解 mid (210,128), info(sage) → 時系列推移 mid (145,272)
  // question(ochre) → 2回目購入率 mid (280,272), decision(slate) → LTV改善 mid (210,320)
  // idea(iris) → 広告経由 leaf (152,72), aside(ash) → 自然流入 leaf (270,72)
  const pellets = [
    { c: _C.accent, l: "issue", n: 12, x: "50%", y: "26%" },
    { c: _C.sage, l: "info", n: 5, x: "28%", y: "58%" },
    { c: _C.ochre, l: "question", n: 8, x: "72%", y: "58%" },
    { c: _C.slate, l: "decision", n: 9, x: "50%", y: "70%" },
    { c: _C.iris, l: "idea", n: 7, x: "30%", y: "12%" },
    { c: _C.ash, l: "aside", n: 3, x: "70%", y: "12%" },
  ];
  return (
    <div style={{ position: "relative", width: "100%", height: "100%" }}>
      {/* Background mindmap */}
      <svg viewBox="0 0 420 440" width="100%" height="100%" preserveAspectRatio="xMidYMid meet"
        style={{ position: "absolute", inset: 0, opacity: 0.3 }}>
        <path d="M210 200 C235 185 235 148 210 128" stroke="#B8BCCB" strokeWidth="1.5" fill="none"/>
        <path d="M210 200 C175 200 148 245 145 272" stroke="#B8BCCB" strokeWidth="1.5" fill="none"/>
        <path d="M210 200 C248 200 275 245 280 272" stroke="#B8BCCB" strokeWidth="1.5" fill="none"/>
        <path d="M210 200 C185 220 185 290 210 320" stroke="#B8BCCB" strokeWidth="1.5" fill="none"/>
        <path d="M210 128 C185 125 165 95 152 72" stroke="#C5C8D4" strokeWidth="1" fill="none"/>
        <path d="M210 128 C240 120 260 95 270 72" stroke="#C5C8D4" strokeWidth="1" fill="none"/>
        <path d="M145 272 C120 278 100 300 95 330" stroke="#C5C8D4" strokeWidth="1" fill="none"/>
        <path d="M280 272 C305 278 325 300 338 325" stroke="#C5C8D4" strokeWidth="1" fill="none"/>
        <path d="M210 320 C188 325 168 350 160 378" stroke="#C5C8D4" strokeWidth="1" fill="none"/>
        <path d="M210 320 C232 325 252 350 260 378" stroke="#C5C8D4" strokeWidth="1" fill="none"/>
        <circle cx="152" cy="72" r="4" fill="#C9583C"/>
        <circle cx="270" cy="72" r="4" fill="#C9583C"/>
        <circle cx="95" cy="330" r="4" fill="#7A9A85"/>
        <circle cx="338" cy="325" r="4" fill="#B8864A"/>
        <circle cx="160" cy="378" r="4" fill="#536A8A"/>
        <circle cx="260" cy="378" r="4" fill="#536A8A"/>
        <circle cx="210" cy="128" r="6" fill="#C9583C"/>
        <circle cx="145" cy="272" r="6" fill="#7A9A85"/>
        <circle cx="280" cy="272" r="6" fill="#B8864A"/>
        <circle cx="210" cy="320" r="6" fill="#536A8A"/>
        <circle cx="210" cy="200" r="10" fill="#3B352D"/>
      </svg>
      {/* Pellets overlaid at node positions */}
      {pellets.map((p, i) => (
        <span key={i} style={{
          position: "absolute", left: p.x, top: p.y,
          transform: "translate(-50%, -50%)",
          display: "inline-flex", alignItems: "center", gap: 6,
          height: 28, padding: "0 12px", borderRadius: 999,
          background: _C.panel,
          fontSize: 11.5, color: _C.panelInk, fontWeight: 500,
          boxShadow: "-2px -2px 5px #FFFDF8, 3px 3px 7px #C8BFAE",
          whiteSpace: "nowrap", zIndex: 1,
        }}>
          <span style={{ width: 8, height: 8, borderRadius: "50%", background: p.c }}/>
          {p.l}
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: _C.panelMute, letterSpacing: "0.04em" }}>{p.n}</span>
        </span>
      ))}
    </div>
  );
};

const VSearch = () => (
  <div style={{ width: "100%", maxWidth: 360, display: "flex", flexDirection: "column", gap: 12 }}>
    <div style={{
      display: "flex", alignItems: "center", gap: 10,
      height: 42, padding: "0 16px", borderRadius: 999,
      background: _C.panel,
      boxShadow: "inset 2px 2px 5px #C8BFAE, inset -2px -2px 5px #FFFDF8",
      fontSize: 13.5, color: _C.panelInk, fontWeight: 500,
    }}>
      <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
        <circle cx="6" cy="6" r="4.5" stroke={_C.panelMute} strokeWidth="1.3"/>
        <path d="M9.5 9.5 L13 13" stroke={_C.panelMute} strokeWidth="1.3" strokeLinecap="round"/>
      </svg>
      cache layer
      <span style={{ flex: 1 }}/>
      <span style={{ fontFamily: "var(--font-mono)", fontSize: 10.5, color: _C.panelMute, letterSpacing: "0.1em" }}>3 MAPS</span>
    </div>
    {[
      { c: _C.iris,   t: "Cache layer",        m: "Eval pipeline · today",   active: true },
      { c: _C.iris,   t: "L2 cache strategy",  m: "Retrieval v3 · 2d ago" },
      { c: _C.accent, t: "Cache invalidation", m: "8k ceiling · 6d ago" },
    ].map((r, i) => (
      <div key={i} style={{
        display: "flex", alignItems: "center", gap: 10,
        padding: "10px 14px", borderRadius: 8,
        background: r.active ? _C.panel : "transparent",
        boxShadow: r.active ? "inset 1px 1px 3px #C8BFAE, inset -1px -1px 3px #FFFDF8" : "none",
      }}>
        <span style={{ width: 7, height: 7, borderRadius: "50%", background: r.c, flexShrink: 0 }}/>
        <span style={{ fontSize: 13, color: _C.panelInk, fontWeight: 500 }}>{r.t}</span>
        <span style={{ flex: 1 }}/>
        <span style={{ fontSize: 11, color: _C.panelMute, fontFamily: "var(--font-mono)" }}>{r.m}</span>
      </div>
    ))}
  </div>
);

const VStar = () => (
  <svg viewBox="0 0 360 220" width="100%" height="100%" style={{ maxHeight: 260 }}
    preserveAspectRatio="xMidYMid meet">
    <g opacity="0.4">
      <circle cx="70" cy="90" r="4" fill={_C.slate}/>
      <circle cx="290" cy="80" r="4" fill={_C.sage}/>
      <circle cx="290" cy="160" r="4" fill={_C.iris}/>
      <circle cx="70" cy="170" r="4" fill={_C.ochre}/>
      <path d="M180 120 L70 90 M180 120 L290 80 M180 120 L290 160 M180 120 L70 170"
        stroke={_C.panelMute} strokeWidth="0.9" fill="none" opacity="0.5"/>
    </g>
    <circle cx="180" cy="120" r="18" fill="none" stroke={_C.accent} strokeWidth="1.6"/>
    <circle cx="180" cy="120" r="9" fill={_C.accent}/>
    <text x="180" y="124" fontSize="12" fontWeight="700" fill={_C.bg} textAnchor="middle">★</text>
    <g transform="translate(195, 50)">
      <rect width="140" height="40" rx="7" fill={_C.panelInk}/>
      <text x="14" y="17" fontSize="10" fontWeight="500" fill="rgba(234,229,218,0.6)"
        style={{ fontFamily: "var(--font-mono)", letterSpacing: "0.14em" }}>STARRED</text>
      <text x="14" y="32" fontSize="12.5" fontWeight="500" fill={_C.bg}>Cache layer</text>
      <path d="M18 40 L14 48 L28 40 Z" fill={_C.panelInk}/>
    </g>
  </svg>
);

const VMerge = () => (
  <svg viewBox="0 0 420 260" width="100%" height="100%" style={{ maxHeight: 300, opacity: 0.55 }}
    preserveAspectRatio="xMidYMid meet">
    {/* Left map — organic radial tree */}
    <g>
      <circle cx="90" cy="100" r="8" fill={_C.panelInk}/>
      {/* branches */}
      <path d="M90 100 C70 80 40 75 30 55" stroke={_C.panelMute} strokeWidth="0.9" fill="none"/>
      <path d="M90 100 C60 95 35 110 20 120" stroke={_C.panelMute} strokeWidth="0.9" fill="none"/>
      <path d="M90 100 C75 115 55 140 40 155" stroke={_C.panelMute} strokeWidth="0.9" fill="none"/>
      <path d="M90 100 C105 80 120 60 135 45" stroke={_C.panelMute} strokeWidth="0.9" fill="none"/>
      <path d="M90 100 C110 105 125 95 140 85" stroke={_C.panelMute} strokeWidth="0.9" fill="none"/>
      <path d="M90 100 C100 120 90 145 80 165" stroke={_C.panelMute} strokeWidth="0.9" fill="none"/>
      {/* mid dots */}
      <circle cx="55" cy="72" r="4" fill={_C.accent}/>
      <circle cx="35" cy="115" r="4" fill={_C.slate}/>
      <circle cx="50" cy="148" r="4" fill={_C.sage}/>
      <circle cx="130" cy="50" r="4" fill={_C.iris}/>
      {/* leaf dots */}
      <circle cx="30" cy="55" r="2.8" fill={_C.panelMute}/>
      <circle cx="20" cy="120" r="2.8" fill={_C.panelMute}/>
      <circle cx="40" cy="155" r="2.8" fill={_C.panelMute}/>
      <circle cx="135" cy="45" r="2.8" fill={_C.panelMute}/>
      <circle cx="140" cy="85" r="2.8" fill={_C.panelMute}/>
      <circle cx="80" cy="165" r="2.8" fill={_C.panelMute}/>
      {/* sub-leaves from mid dots */}
      <path d="M55 72 C42 60 25 48 15 38" stroke={_C.panelMute} strokeWidth="0.7" fill="none"/>
      <circle cx="15" cy="38" r="2" fill={_C.panelMute}/>
      <path d="M55 72 C65 58 72 42 68 30" stroke={_C.panelMute} strokeWidth="0.7" fill="none"/>
      <circle cx="68" cy="30" r="2" fill={_C.panelMute}/>
      <path d="M130 50 C145 38 155 25 165 20" stroke={_C.panelMute} strokeWidth="0.7" fill="none"/>
      <circle cx="165" cy="20" r="2" fill={_C.panelMute}/>
    </g>

    {/* Right map — different shape */}
    <g>
      <circle cx="330" cy="155" r="8" fill={_C.panelInk}/>
      <path d="M330 155 C350 135 370 120 385 105" stroke={_C.panelMute} strokeWidth="0.9" fill="none"/>
      <path d="M330 155 C355 155 375 165 395 170" stroke={_C.panelMute} strokeWidth="0.9" fill="none"/>
      <path d="M330 155 C345 175 355 195 360 215" stroke={_C.panelMute} strokeWidth="0.9" fill="none"/>
      <path d="M330 155 C310 140 290 130 275 115" stroke={_C.panelMute} strokeWidth="0.9" fill="none"/>
      <path d="M330 155 C315 170 300 190 285 205" stroke={_C.panelMute} strokeWidth="0.9" fill="none"/>
      <path d="M330 155 C320 135 305 115 290 100" stroke={_C.panelMute} strokeWidth="0.9" fill="none"/>
      {/* mid dots */}
      <circle cx="375" cy="115" r="4" fill={_C.ochre}/>
      <circle cx="390" cy="168" r="4" fill={_C.accent}/>
      <circle cx="355" cy="210" r="4" fill={_C.slate}/>
      <circle cx="280" cy="118" r="4" fill={_C.sage}/>
      {/* leaf dots */}
      <circle cx="385" cy="105" r="2.8" fill={_C.panelMute}/>
      <circle cx="395" cy="170" r="2.8" fill={_C.panelMute}/>
      <circle cx="360" cy="215" r="2.8" fill={_C.panelMute}/>
      <circle cx="275" cy="115" r="2.8" fill={_C.panelMute}/>
      <circle cx="285" cy="205" r="2.8" fill={_C.panelMute}/>
      <circle cx="290" cy="100" r="2.8" fill={_C.panelMute}/>
      {/* sub-leaves */}
      <path d="M375 115 C385 100 395 88 405 80" stroke={_C.panelMute} strokeWidth="0.7" fill="none"/>
      <circle cx="405" cy="80" r="2" fill={_C.panelMute}/>
      <path d="M280 118 C268 108 255 100 245 92" stroke={_C.panelMute} strokeWidth="0.7" fill="none"/>
      <circle cx="245" cy="92" r="2" fill={_C.panelMute}/>
      <path d="M355 210 C365 225 370 240 372 250" stroke={_C.panelMute} strokeWidth="0.7" fill="none"/>
      <circle cx="372" cy="250" r="2" fill={_C.panelMute}/>
    </g>

    {/* Connecting merge links — dashed bridges between the two maps */}
    <path d="M140 85 C175 90 220 105 275 115" stroke={_C.accent} strokeWidth="1.6" strokeDasharray="4 4" fill="none"/>
    <path d="M130 50 C165 55 230 75 280 118" stroke={_C.accent} strokeWidth="1.2" strokeDasharray="4 4" fill="none" opacity="0.6"/>
    <path d="M80 165 C130 185 220 200 285 205" stroke={_C.accent} strokeWidth="1.2" strokeDasharray="4 4" fill="none" opacity="0.6"/>

    {/* Merge badge */}
    <g transform="translate(197, 90)">
      <rect width="28" height="18" rx="4" fill={_C.panelInk}/>
      <text x="14" y="13" fontSize="10" fontWeight="700" fill="#F5F0E8" textAnchor="middle"
        style={{ fontFamily: "var(--font-mono)", letterSpacing: "0.1em" }}>M</text>
    </g>
  </svg>
);

const VExport = () => (
  <div style={{ display: "flex", gap: 18, alignItems: "center", justifyContent: "center" }}>
    {[
      { ext: "PNG", icon: "M3 5h18v14H3z M8.5 10a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z M21 16l-5-5-10 8", color: _C.accent },
      { ext: "PDF", icon: "M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z M14 3v5h5 M9 14h6 M9 17h4", color: _C.slate },
    ].map((f, i) => (
      <div key={i} style={{
        width: 130, padding: "24px 16px",
        background: "#fff", borderRadius: 14,
        boxShadow: "2px 2px 6px rgba(0,0,0,0.07), -2px -2px 6px rgba(255,255,255,0.7)",
        display: "flex", flexDirection: "column", alignItems: "center", gap: 14,
      }}>
        <div style={{
          width: 48, height: 48, borderRadius: 12,
          background: `${f.color}14`, display: "grid", placeItems: "center",
        }}>
          <svg width="24" height="24" viewBox="0 0 24 24" fill="none"
            stroke={f.color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
            <path d={f.icon}/>
          </svg>
        </div>
        <span style={{
          fontFamily: "var(--font-mono)", fontSize: 13, fontWeight: 700,
          letterSpacing: "0.1em", color: _C.panelInk,
        }}>.{f.ext}</span>
        <div style={{
          width: "100%", height: 28, borderRadius: 8,
          background: `${f.color}18`, display: "grid", placeItems: "center",
        }}>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none"
            stroke={f.color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4 M7 10l5 5 5-5 M12 15V3"/>
          </svg>
        </div>
      </div>
    ))}
  </div>
);

const VHistory = () => (
  <div style={{ width: "100%", minWidth: 320, maxWidth: 380, display: "flex", flexDirection: "column", gap: 6 }}>
    {[
      { t: "LLM evaluation pipeline", m: "today",   active: true },
      { t: "Retrieval v3",            m: "2d ago" },
      { t: "Onboarding rewrite",      m: "5d ago" },
      { t: "Pricing tier study",      m: "1w ago" },
      { t: "8k ceiling",              m: "2w ago" },
    ].map((r, i) => (
      <div key={i} style={{
        display: "flex", alignItems: "center", gap: 10,
        padding: "9px 14px", borderRadius: 8,
        background: r.active ? _C.panel : "transparent",
        boxShadow: r.active ? "inset 1px 1px 3px #C8BFAE, inset -1px -1px 3px #FFFDF8" : "none",
      }}>
        <span style={{ width: 6, height: 6, borderRadius: "50%", background: r.active ? _C.accent : _C.panelMute, flexShrink: 0 }}/>
        <span style={{
          fontSize: 13, color: _C.panelInk, fontWeight: r.active ? 600 : 400,
          whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
        }}>{r.t}</span>
        <span style={{ flex: 1 }}/>
        <span style={{
          fontSize: 11, color: _C.panelMute, fontFamily: "var(--font-mono)",
          letterSpacing: "0.06em", whiteSpace: "nowrap", flexShrink: 0,
        }}>{r.m}</span>
      </div>
    ))}
    <div style={{
      marginTop: 6, paddingTop: 10, borderTop: "1px solid rgba(59,53,45,0.08)",
      fontSize: 11, color: _C.panelMute, fontFamily: "var(--font-mono)",
      letterSpacing: "0.14em", textAlign: "right",
    }}>
      LOCAL · 247 MAPS
    </div>
  </div>
);

const VBilingual = () => (
  <div style={{ display: "flex", flexDirection: "column", gap: 22, alignItems: "center" }}>
    <div style={{
      display: "inline-flex", padding: 4, gap: 2, borderRadius: 999,
      background: _C.panel,
      boxShadow: "inset 2px 2px 4px #C8BFAE, inset -2px -2px 4px #FFFDF8",
      fontFamily: "var(--font-mono)",
    }}>
      <span style={{
        padding: "6px 14px", borderRadius: 999,
        background: _C.panelInk, color: _C.bg,
        fontSize: 11, fontWeight: 600, letterSpacing: "0.14em",
      }}>JA</span>
      <span style={{
        padding: "6px 14px", borderRadius: 999,
        color: _C.panelMute,
        fontSize: 11, fontWeight: 500, letterSpacing: "0.14em",
      }}>EN</span>
    </div>
    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, width: "100%", maxWidth: 340 }}>
      {[
        { lab: "課題",  text: "取得が遅い",         jp: true },
        { lab: "ISSUE", text: "Retrieval latency", jp: false },
      ].map((n, i) => (
        <div key={i} style={{
          background: _C.panel, borderRadius: 8, padding: "12px 14px",
          boxShadow: "3px 3px 7px #C8BFAE, -3px -3px 7px #FFFDF8",
          display: "flex", flexDirection: "column", gap: 8,
        }}>
          <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
            <span style={{ width: 7, height: 7, borderRadius: "50%", background: _C.accent }}/>
            <span style={{
              fontFamily: n.jp ? "var(--font-jp)" : "var(--font-mono)",
              fontSize: n.jp ? 12 : 10,
              letterSpacing: n.jp ? 0 : "0.16em",
              color: _C.panelMute, fontWeight: 500,
              textTransform: n.jp ? "none" : "uppercase",
            }}>{n.lab}</span>
          </div>
          <div style={{
            fontSize: 13.5, color: _C.panelInk, fontWeight: 500,
            fontFamily: n.jp ? "var(--font-jp)" : "var(--font-sans)",
          }}>{n.text}</div>
        </div>
      ))}
    </div>
  </div>
);

const VGaps = () => (
  <div style={{ width: "100%", maxWidth: 340, display: "flex", flexDirection: "column", gap: 8 }}>
    {[
      { icon: "M3 12h4l3-9 4 18 3-9h4", label: "Branch imbalance", desc: "Left: 12 nodes · Right: 3 nodes", color: _C.accent },
      { icon: "M12 12m-3 0a3 3 0 1 0 6 0a3 3 0 1 0-6 0 M12 5v-2 M12 21v-2 M5 12H3 M21 12h-2", label: "Orphan conclusion", desc: "\"Cache layer\" — no parent context", color: _C.ochre },
      { icon: "M9 18l6-6-6-6", label: "Asymmetric depth", desc: "Max 5 vs avg 2.1", color: _C.slate },
    ].map((f, i) => (
      <div key={i} style={{
        display: "flex", gap: 12, alignItems: "flex-start",
        padding: "12px 14px", borderRadius: 10,
        background: _C.panel,
        boxShadow: "3px 3px 7px #C8BFAE, -3px -3px 7px #FFFDF8",
      }}>
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke={f.color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0, marginTop: 2 }}>
          <path d={f.icon}/>
        </svg>
        <div>
          <div style={{ fontSize: 13, fontWeight: 600, color: _C.panelInk }}>{f.label}</div>
          <div style={{ fontSize: 11.5, color: _C.panelMute, marginTop: 2 }}>{f.desc}</div>
        </div>
      </div>
    ))}
  </div>
);

const VLive = () => (
  <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 16 }}>
    <svg width="220" height="160" viewBox="0 0 220 160">
      <g fill="none" stroke={_C.panelMute} strokeWidth="1">
        <line x1="110" y1="80" x2="60" y2="40"/>
        <line x1="110" y1="80" x2="160" y2="50"/>
        <line x1="110" y1="80" x2="80" y2="130"/>
        <line x1="160" y1="50" x2="190" y2="30"/>
      </g>
      <g>
        <circle cx="110" cy="80" r="8" fill={_C.panelInk}/>
        <circle cx="60" cy="40" r="5" fill={_C.accent}/>
        <circle cx="160" cy="50" r="5" fill={_C.slate}/>
        <circle cx="80" cy="130" r="5" fill={_C.sage}/>
        <circle cx="190" cy="30" r="5" fill={_C.iris}/>
      </g>
      <line x1="80" y1="130" x2="40" y2="140" stroke={_C.accent} strokeWidth="1.5" strokeDasharray="4 3">
        <animate attributeName="stroke-dashoffset" from="20" to="0" dur="1.5s" repeatCount="indefinite"/>
      </line>
      <circle cx="40" cy="140" r="4" fill={_C.accent} opacity="0">
        <animate attributeName="opacity" values="0;1;1" dur="1.5s" repeatCount="indefinite"/>
        <animate attributeName="r" values="0;4;4" dur="1.5s" repeatCount="indefinite"/>
      </circle>
    </svg>
    <div style={{
      display: "flex", alignItems: "center", gap: 8,
      fontFamily: "var(--font-mono)", fontSize: 11, letterSpacing: "0.1em", color: _C.panelMute,
    }}>
      <span style={{ width: 6, height: 6, borderRadius: "50%", background: _C.accent, animation: "live-grow-pulse 1.8s ease-in-out infinite" }}/>
      GROWING
    </div>
  </div>
);

const VProfile = () => (
  <div style={{ width: "100%", maxWidth: 300, display: "flex", flexDirection: "column", gap: 10 }}>
    {[
      { label: "探索深度", value: "3.8", sub: "Exploration Depth", pct: 76, color: _C.slate },
      { label: "評価率", value: "42%", sub: "Evaluation Rate", pct: 42, color: _C.sage },
      { label: "構造変更", value: "7", sub: "Restructuring", pct: 58, color: _C.iris },
    ].map((s, i) => (
      <div key={i} style={{
        padding: "12px 14px", borderRadius: 10,
        background: _C.panel,
        boxShadow: "3px 3px 7px #C8BFAE, -3px -3px 7px #FFFDF8",
      }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
          <span style={{ fontSize: 12, color: _C.panelMute, fontWeight: 500 }}>{s.label}</span>
          <span style={{ fontSize: 18, fontWeight: 600, color: _C.panelInk }}>{s.value}</span>
        </div>
        <div style={{ marginTop: 6, height: 3, borderRadius: 2, background: "rgba(59,53,45,0.08)" }}>
          <div style={{ height: "100%", borderRadius: 2, background: s.color, width: s.pct + "%" }}/>
        </div>
        <div style={{ marginTop: 4, fontSize: 10, color: _C.panelMute, fontFamily: "var(--font-mono)", letterSpacing: "0.06em" }}>{s.sub}</div>
      </div>
    ))}
  </div>
);

/* In-product snapshot — exact replica of the LLMindMap side panel,
   set in a soft sand-bezeled frame with a short text block alongside. */
const ThinkingProfile = ({ lang }) => (
  <section style={{ background: "#E8E4DA", padding: "120px 0" }}>
    <div className="container">
      <div style={{ marginBottom: 56, maxWidth: 760 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          <div className="eyebrow eyebrow-accent">LIVE MODE / {lang === "ja" ? "ライブモード" : "REAL-TIME"}</div>
          <span style={{
            display: "inline-block", padding: "3px 10px", borderRadius: 999,
            background: "var(--accent)", color: "#fff",
            fontFamily: "var(--font-mono)", fontSize: 10, fontWeight: 700,
            letterSpacing: "0.08em", lineHeight: "16px",
          }}>PRO</span>
        </div>
        <h2 className="title-xl" style={{ marginTop: 16 }}>
          {lang === "ja"
            ? <>リアルタイムで、<em style={{ fontStyle: "italic" }}>地図が育つ</em>。</>
            : <>Your map, <em style={{ fontStyle: "italic" }}>growing</em> beside the chat.</>}
        </h2>
        <p className="lede" style={{ marginTop: 20, maxWidth: 540 }}>
          {lang === "ja"
            ? "LLMindMapは常にサイドパネルに常駐。会話を書き進めるほど、構造がリアルタイムで姿を現します。ノードをクリックして分岐、統合、再生成。"
            : "LLMindMap lives in the side panel. As you write, structure emerges in real time. Click any node to branch, merge, or regenerate — without losing your place in the conversation."}
        </p>
      </div>
      <div style={{ display: "flex", justifyContent: "center" }}>
        <LiveModeWindow lang={lang}/>
      </div>
    </div>
  </section>
);

/* Live Mode demo — shows a mindmap already generated, then a new prompt
   auto-types, AI responds, and a new branch grows on the map. Loops. */
const LiveModeWindow = ({ lang }) => {
  const ja = lang === "ja";
  const [loopKey, setLoopKey] = React.useState(0);
  const [phase, setPhase] = React.useState("idle"); // idle → typing → sent → responding → growing → done
  const [typedChars, setTypedChars] = React.useState(0);
  const [responseChars, setResponseChars] = React.useState(0);
  const [newBranch, setNewBranch] = React.useState(false);
  const [inView, setInView] = React.useState(false);
  const rootRef = React.useRef(null);

  const newPrompt = ja ? "LTV改善の優先順位を整理して" : "Prioritize the LTV improvement actions";
  const newResponse = ja
    ? "まず解約率の高いセグメントを特定して、初回体験の改善から着手するのが最もインパクトが大きいです。"
    : "Start by identifying the highest churn segment, then focus on first-experience improvement for the biggest impact.";

  const existingMsgs = ja
    ? [
        { who: "user", t: "リピート率が低下してる原因を整理したい" },
        { who: "ai", t: "まず数字を確認しましょう。18ヶ月で42%から31%に落ちているなら、獲得チャネル別に2回目購入率を分解するのが最初の一手です。" },
      ]
    : [
        { who: "user", t: "I want to organize the reasons behind declining repeat rate" },
        { who: "ai", t: "Let's start with the numbers. If repeat rate dropped from 42% to 31% over 18 months, the first move is breaking down second purchase rate by channel." },
      ];

  // IntersectionObserver — start animation only when section is visible
  React.useEffect(() => {
    const el = rootRef.current;
    if (!el) return;
    const obs = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) setInView(true);
    }, { threshold: 0.3 });
    obs.observe(el);
    return () => obs.disconnect();
  }, []);

  // Auto-play sequence — gated on inView
  React.useEffect(() => {
    if (!inView) return;
    const timers = [];
    timers.push(setTimeout(() => setPhase("typing"), 1500));
    return () => timers.forEach(clearTimeout);
  }, [loopKey, inView]);

  // Typing effect for new prompt
  React.useEffect(() => {
    if (phase !== "typing") return;
    if (typedChars < newPrompt.length) {
      const t = setTimeout(() => setTypedChars(c => c + 1), 60);
      return () => clearTimeout(t);
    }
    const t = setTimeout(() => setPhase("sent"), 400);
    return () => clearTimeout(t);
  }, [phase, typedChars]);

  // Send → responding
  React.useEffect(() => {
    if (phase !== "sent") return;
    const t = setTimeout(() => { setPhase("responding"); setResponseChars(0); }, 800);
    return () => clearTimeout(t);
  }, [phase]);

  // AI response typing
  React.useEffect(() => {
    if (phase !== "responding") return;
    if (responseChars < newResponse.length) {
      const t = setTimeout(() => setResponseChars(c => c + 1), 25);
      return () => clearTimeout(t);
    }
    setPhase("growing");
    setNewBranch(true);
  }, [phase, responseChars]);

  // Growing → done → loop
  React.useEffect(() => {
    if (phase !== "growing") return;
    const t = setTimeout(() => {
      setPhase("done");
      setTimeout(() => {
        setPhase("idle");
        setTypedChars(0);
        setResponseChars(0);
        setNewBranch(false);
        setLoopKey(k => k + 1);
      }, 3000);
    }, 2500);
    return () => clearTimeout(t);
  }, [phase]);

  // Build messages list
  const allMsgs = [...existingMsgs];
  if (phase === "sent" || phase === "responding" || phase === "growing" || phase === "done") {
    allMsgs.push({ who: "user", t: newPrompt });
  }
  if (phase === "responding" || phase === "growing" || phase === "done") {
    allMsgs.push({ who: "ai", t: newResponse.slice(0, responseChars) });
  }

  const scrollRef = React.useRef(null);
  React.useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [allMsgs.length, responseChars]);

  const baseTree = INTERACTIVE_CONTENT.trees[0];

  return (
    <div ref={rootRef} style={{
      width: "100%", maxWidth: 1400, height: 580,
      borderRadius: 14, overflow: "hidden",
      background: "var(--bg-raised)",
      boxShadow: "0 1px 0 rgba(255,255,255,0.6) inset, 0 0 0 1px var(--ink-10), 0 28px 56px -16px rgba(26,24,21,0.28), 0 10px 22px -12px rgba(26,24,21,0.20)",
      fontFamily: "var(--font-sans)",
      display: "flex", flexDirection: "column",
    }}>
      {/* titlebar */}
      <div style={{
        height: 36, display: "flex", alignItems: "center",
        padding: "0 14px", gap: 14, flex: "0 0 auto",
        background: "linear-gradient(180deg, rgba(26,24,21,0.05), rgba(26,24,21,0.01))",
        borderBottom: "1px solid var(--ink-10)",
      }}>
        <div style={{ display: "flex", gap: 6 }}>
          {["#FF5F57","#FEBC2E","#28C840"].map((c,i) => (
            <span key={i} style={{ width: 10, height: 10, borderRadius: "50%", background: c }}/>
          ))}
        </div>
        <div style={{ flex: 1, textAlign: "center", font: '500 12px/1 var(--font-sans)', color: "var(--ink-60)" }}>
          Chrome — chatgpt.com / LLMindMap
        </div>
        <div style={{ width: 42 }}/>
      </div>

      {/* body */}
      <div style={{ flex: 1, display: "flex", minHeight: 0 }}>
        {/* Chat pane */}
        <div style={{ flex: "0 0 50%", minWidth: 0, display: "flex", flexDirection: "column", borderRight: "1px solid var(--ink-10)" }}>
          <div style={{
            padding: "8px 16px", display: "flex", alignItems: "center", gap: 10,
            borderBottom: "1px solid var(--ink-10)", flex: "0 0 auto",
          }}>
            <span className="mono-hi" style={{ fontSize: 9.5, letterSpacing: "0.18em" }}>CHATGPT</span>
            <span style={{ width: 1, height: 10, background: "var(--ink-10)" }}/>
            <span style={{ fontSize: 11, color: "var(--ink)", fontWeight: 500 }}>{ja ? "販売戦略レビュー" : "Sales strategy"}</span>
          </div>
          <div ref={scrollRef} style={{
            flex: 1, padding: "16px 18px", overflowY: "auto",
            display: "flex", flexDirection: "column", gap: 14,
          }}>
            {allMsgs.map((m, i) => (
              <div key={i} style={{
                display: "flex", gap: 10,
                justifyContent: m.who === "user" ? "flex-end" : "flex-start",
                alignItems: "flex-start",
              }}>
                {m.who === "ai" && (
                  <div style={{
                    width: 22, height: 22, borderRadius: "50%",
                    background: "var(--ink)", color: "var(--bg-raised)",
                    display: "grid", placeItems: "center",
                    fontSize: 9, fontWeight: 700, flexShrink: 0,
                  }}>AI</div>
                )}
                <div style={{
                  maxWidth: "75%", padding: "10px 14px", borderRadius: 12,
                  background: m.who === "user" ? "var(--ink-10)" : "transparent",
                  border: m.who === "ai" ? "1px solid var(--ink-10)" : "none",
                  fontSize: 12.5, lineHeight: 1.55, color: "var(--ink)",
                }}>
                  {m.t}
                  {i === allMsgs.length - 1 && m.who === "ai" && phase === "responding" && (
                    <span style={{ display: "inline-block", width: 5, height: 14, background: "var(--ink)", marginLeft: 2, verticalAlign: -2, animation: "blink 1.1s steps(2) infinite" }}/>
                  )}
                </div>
                {m.who === "user" && (
                  <div style={{
                    width: 22, height: 22, borderRadius: "50%",
                    background: "var(--accent)", color: "#fff",
                    display: "grid", placeItems: "center",
                    fontSize: 7, fontWeight: 700, flexShrink: 0,
                  }}>YOU</div>
                )}
              </div>
            ))}
          </div>
          <div style={{
            padding: "8px 12px 10px", borderTop: "1px solid var(--ink-10)",
            display: "flex", alignItems: "center", gap: 8, flex: "0 0 auto",
          }}>
            <div style={{
              flex: 1, height: 30, borderRadius: 8, background: "var(--bg)",
              boxShadow: "inset 0 0 0 1px var(--ink-10)",
              display: "flex", alignItems: "center", padding: "0 10px",
              font: '400 12px/1 var(--font-sans)', color: phase === "typing" ? "var(--ink)" : "var(--ink-40)",
            }}>
              {phase === "typing" ? newPrompt.slice(0, typedChars) : (phase === "idle" ? "" : (ja ? "メッセージを送信…" : "Send a message…"))}
              {phase === "typing" && (
                <span style={{ display: "inline-block", width: 5, height: 14, background: "var(--accent)", marginLeft: 1, animation: "blink 1.1s steps(2) infinite" }}/>
              )}
            </div>
            <div style={{
              width: 30, height: 30, borderRadius: 8,
              background: "var(--accent)", color: "#fff",
              display: "flex", alignItems: "center", justifyContent: "center",
              opacity: phase === "typing" ? 1 : 0.5,
            }}>
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round">
                <path d="M12 19V5M5 12l7-7 7 7"/>
              </svg>
            </div>
          </div>
        </div>

        {/* Extension panel with mindmap — uses the real DemoMindmap component */}
        <div style={{ flex: "0 0 50%", minWidth: 0, overflow: "hidden" }}>
          <div style={{ width: "100%", height: "100%", display: "flex", flexDirection: "column", background: "#F5F0E8" }}>
            <div style={{ display: "flex", flex: 1, minHeight: 0 }}>
              {/* Rail */}
              <div style={{
                width: 44, flexShrink: 0, display: "flex", flexDirection: "column",
                alignItems: "center", gap: 6, paddingTop: 10,
                borderRight: "1px solid rgba(59,53,45,0.06)",
              }}>
                {[
                  { kind: "mark", color: "#6BBF8A" },
                  { d: "M4.5 10 A4.5 4.5 0 0 1 13 7.5 M13 4.5 L13 7.5 L10 7.5 M13.5 8 A4.5 4.5 0 0 1 5 10.5 M5 13.5 L5 10.5 L8 10.5", color: "#7BAFD4" },
                  { d: "M3 3 L9 3 L15 9 L9 15 L3 9 Z M6.5 6.5 L6.5 6.5", color: "#D4908A" },
                  { d: "M4 8 A4 4 0 1 1 12 8 A4 4 0 1 1 4 8 M11 11 L15 15", color: "#D4B85C" },
                  { d: "M5 3 L13 3 L13 15 L9 12 L5 15 Z", color: "#D4C24E" },
                ].map((ic, i) => (
                  <div key={i} style={{
                    width: 34, height: 34, borderRadius: 10,
                    display: "grid", placeItems: "center",
                    background: "#F5F0E8",
                    boxShadow: i === 0
                      ? "inset 2px 2px 4px #C8BFAE, inset -2px -2px 4px #FFFDF8"
                      : "3px 3px 7px #C8BFAE, -3px -3px 7px #FFFDF8",
                  }}>
                    {ic.kind === "mark" ? (
                      <svg width="17" height="17" viewBox="0 0 22 22" fill="none">
                        <circle cx="11" cy="11" r="2" fill={ic.color}/>
                        <circle cx="4" cy="4" r="1.7" fill={ic.color}/>
                        <circle cx="18" cy="4" r="1.7" fill={ic.color}/>
                        <circle cx="4" cy="18" r="1.7" fill={ic.color}/>
                        <circle cx="18" cy="18" r="1.7" fill={ic.color}/>
                        <path d="M11 11 L4 4 M11 11 L18 4 M11 11 L4 18 M11 11 L18 18"
                          stroke={ic.color} strokeWidth="1.4" strokeLinecap="round"/>
                      </svg>
                    ) : (
                      <svg width="14" height="14" viewBox="0 0 18 18" fill="none"
                        stroke={ic.color} strokeWidth="1.35" strokeLinecap="round" strokeLinejoin="round">
                        <path d={ic.d}/>
                      </svg>
                    )}
                  </div>
                ))}
              </div>

              {/* Mindmap content */}
              <div style={{ flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }}>
                <div style={{
                  padding: "10px 14px", display: "flex", alignItems: "center", gap: 8,
                  borderBottom: "1px solid rgba(59,53,45,0.06)", flexShrink: 0,
                }}>
                  <svg width="17" height="17" viewBox="0 0 22 22" fill="none" style={{ flexShrink: 0 }}>
                    <circle cx="11" cy="11" r="2" fill="#C9583C"/>
                    <circle cx="4" cy="4" r="1.7" fill="#C9583C"/>
                    <circle cx="18" cy="4" r="1.7" fill="#C9583C"/>
                    <circle cx="4" cy="18" r="1.7" fill="#C9583C"/>
                    <circle cx="18" cy="18" r="1.7" fill="#C9583C"/>
                    <path d="M11 11 L4 4 M11 11 L18 4 M11 11 L4 18 M11 11 L18 18"
                      stroke="#C9583C" strokeWidth="1.4" strokeLinecap="round"/>
                  </svg>
                  <span style={{ fontFamily: "'IBM Plex Sans', var(--font-sans)", fontWeight: 700, fontSize: 13, color: "#3B352D" }}>LL<span style={{ color: "#C9583C" }}>Mind</span>Map</span>
                  <span style={{ flex: 1 }}/>
                  <span style={{
                    display: "inline-flex", alignItems: "center", gap: 5,
                    fontFamily: "'IBM Plex Sans', var(--font-sans)", fontSize: 9,
                    letterSpacing: "0.14em", color: "#34D399", fontWeight: 700,
                  }}>
                    <span style={{
                      width: 6, height: 6, borderRadius: "50%", background: "#34D399",
                      animation: "livePulse 1.5s ease-in-out infinite",
                    }}/>
                    LIVE
                  </span>
                </div>

                {/* DemoMindmap — base tree always static, new branch overlaid with animation */}
                <div style={{ flex: 1, padding: 8, position: "relative" }}>
                  <DemoMindmap key={"base"+loopKey} tree={baseTree} lang={lang} animate={false}/>
                  {/* New branch overlay — same viewBox as DemoMindmap (320×280), center at (160,140) */}
                  <svg viewBox="0 0 320 280" width="100%" height="100%"
                    style={{ position: "absolute", top: 8, left: 8, right: 8, bottom: 8, width: "calc(100% - 16px)", height: "calc(100% - 16px)", pointerEvents: "none" }}
                    preserveAspectRatio="xMidYMid meet">
                    {/* Sonar pulses from hub during growth */}
                    {phase === "growing" && [0, 0.4, 0.8].map((delay, i) => (
                      <circle key={"sonar"+i} cx={160} cy={140} r="5" fill="none"
                        stroke="#C9583C" strokeWidth="1.5"
                        style={{ opacity: 0, animation: `liveMmSonar 2s cubic-bezier(0.2,0.7,0.4,1) ${delay}s 1` }}/>
                    ))}
                    {newBranch && <LiveGrowBranch lang={lang}/>}
                  </svg>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <style>{`
        @keyframes blink { 50% { opacity: 0; } }
        @keyframes livePulse { 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:0.7;transform:scale(0.94)} }
        @keyframes newNodeGlow { 0%{opacity:0;r:4.5} 30%{opacity:0.8;r:10} 100%{opacity:0;r:16} }
        @keyframes liveMmSonar { 0%{r:5;opacity:0.7} 100%{r:60;opacity:0} }
      `}</style>
    </div>
  );
};

/* LiveGrowBranch — renders ONLY the new "LTV改善" branch + leaves as an
   animated overlay, matching DemoMindmap's coordinate system exactly.
   viewBox 0 0 320 280, center (160,140), R1=70, R2=120, startAngle=-π/2.
   The base tree has 3 branches at -90°, 30°, 150°. This new branch sits
   at 90° (bottom center — the widest gap between the two lower branches). */
const LiveGrowBranch = ({ lang }) => {
  const ja = lang === "ja";
  const cx = 160, cy = 140, R1 = 70, R2 = 120;
  // Place the new branch at 90° (π/2 rad) — bottom center gap
  const angle = Math.PI / 2;
  const mx = cx + R1 * Math.cos(angle);
  const my = cy + R1 * Math.sin(angle);

  const branchLabel = ja ? "LTV改善" : "LTV Fix";
  const leaves = [
    { ja: "解約率", en: "Churn Rate" },
    { ja: "初回体験", en: "First Experience" },
  ];
  const branchColor = "#536A8A"; // slate blue — distinct from existing 3 branches

  // Progressive reveal: step 0=nothing, 1=branch link+dot, 2=leaves
  const [step, setStep] = React.useState(0);
  React.useEffect(() => {
    const t1 = setTimeout(() => setStep(1), 100);
    const t2 = setTimeout(() => setStep(2), 650);
    return () => { clearTimeout(t1); clearTimeout(t2); };
  }, []);

  // Curved path helper — same as DemoMindmap
  const curvedPath = (x1, y1, x2, y2, curl) => {
    const pmx = (x1 + x2) / 2, pmy = (y1 + y2) / 2;
    const dx = x2 - x1, dy = y2 - y1;
    const len = Math.sqrt(dx * dx + dy * dy) || 1;
    const px = -dy / len * curl, py = dx / len * curl;
    return "M " + x1 + " " + y1 + " Q " + (pmx + px) + " " + (pmy + py) + " " + x2 + " " + y2;
  };

  return (
    <g>
      {/* Hub → Branch link */}
      <path
        d={step >= 1
          ? curvedPath(cx, cy, mx, my, -15)
          : curvedPath(cx, cy, cx, cy, 0)}
        stroke="var(--ink-20)" strokeWidth="1.2" fill="none" strokeLinecap="round"
        style={{ transition: "d 300ms cubic-bezier(0.33, 1, 0.68, 1)" }}/>

      {/* Branch dot */}
      <circle cx={mx} cy={my}
        r={step >= 1 ? 4.5 : 0}
        fill={branchColor}
        style={{ transition: "r 180ms cubic-bezier(0.34, 1.56, 0.64, 1) 280ms" }}/>

      {/* Branch label */}
      <text x={mx} y={my - 9} textAnchor="middle"
        fontSize="9" fill="var(--ink)" fontWeight="500"
        fontFamily="var(--font-sans)"
        style={{ opacity: step >= 1 ? 1 : 0, transition: "opacity 200ms ease-out 400ms" }}>
        {branchLabel}
      </text>

      {/* New node glow pulse */}
      {step >= 1 && (
        <circle cx={mx} cy={my} r="7" fill="none"
          stroke="#FBBF24" strokeWidth="1.5"
          style={{
            opacity: 0,
            animation: "newNodeGlow 1.5s ease-in-out 0.4s 3",
          }}/>
      )}

      {/* Leaves */}
      {leaves.map((leaf, j) => {
        const leafAngle = angle + (j - (leaves.length - 1) / 2) * 0.45;
        const lx = cx + R2 * Math.cos(leafAngle);
        const ly = cy + R2 * Math.sin(leafAngle);
        const leafLabel = ja ? leaf.ja : leaf.en;
        const leafCurl = (8 + j * 4) * -1;
        const vis = step >= 2;

        return (
          <g key={j}>
            <path
              d={vis
                ? curvedPath(mx, my, lx, ly, leafCurl)
                : curvedPath(mx, my, mx, my, 0)}
              stroke="var(--ink-10)" strokeWidth="0.9" fill="none" strokeLinecap="round"
              style={{ transition: "d 300ms cubic-bezier(0.33, 1, 0.68, 1)" }}/>
            <circle cx={lx} cy={ly}
              r={vis ? 3 : 0}
              fill={branchColor} opacity="0.7"
              style={{ transition: "r 180ms cubic-bezier(0.34, 1.56, 0.64, 1) 280ms" }}/>
            <text x={lx} y={ly - 6} textAnchor="middle"
              fontSize="7.5" fill="var(--ink-60)"
              fontFamily="var(--font-sans)"
              style={{ opacity: vis ? 1 : 0, transition: "opacity 200ms ease-out 400ms" }}>
              {leafLabel}
            </text>
          </g>
        );
      })}
    </g>
  );
};

/* Panel frame — wraps the extension panel with a soft drop shadow only.
   The sand bezel was removed; the panel now sits directly on the page bg. */
const PanelFrame = ({ children }) => (
  <div style={{
    borderRadius: 14, overflow: "hidden",
    background: "#F5F0E8",
    boxShadow: "0 22px 46px -18px rgba(30,26,20,0.32), 0 2px 8px rgba(30,26,20,0.08)",
  }}>
    {children}
  </div>
);

/* Exact replica of the LLMindMap Chrome side panel. Takes a `variant`
   to swap in different mindmap content without altering chrome. */
const ExtensionSnapshot = ({ lang, variant = "checkin", zoom = null, compact = false }) => {
  // rail icon set — matches actual product rail buttons
  const railIcons = [
    { k: "map", kind: "mark" },                                           // generate mindmap
    { k: "refresh", d: "M4.5 10 A4.5 4.5 0 0 1 13 7.5 M13 4.5 L13 7.5 L10 7.5 M13.5 8 A4.5 4.5 0 0 1 5 10.5 M5 13.5 L5 10.5 L8 10.5" },
    { k: "divider" },
    { k: "tag", d: "M14.5 3H9l-6 6 6 6h5.5a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z M7 9h.01" },  // classify
    { k: "search", d: "M4 8 A4 4 0 1 1 12 8 A4 4 0 1 1 4 8 M11 11 L15 15" },
    { k: "star", d: "M9 2l2.2 4.5 5 .7-3.6 3.5.9 5L9 13.3 4.6 15.7l.9-5L1.8 7.2l5-.7L9 2z" },
    { k: "q", d: "M9 14 A5 5 0 1 1 9 4 A5 5 0 1 1 9 14 M7.5 7.5a1.5 1.5 0 0 1 3 0c0 1-1.5 1.3-1.5 2.5 M9 12.5L9 12.51" },  // questions
    { k: "glasses", d: "M5 9a3 3 0 1 0 6 0 3 3 0 1 0-6 0 M7 9h4 M11 9a3 3 0 1 0 6 0 3 3 0 1 0-6 0 M2 9L3.5 7 M16 9L14.5 7" },  // analyze gaps
    { k: "history", d: "M9 14 A5 5 0 1 1 9 4 A5 5 0 1 1 9 14 M9 6v3l2 2" },
    { k: "divider" },
    { k: "download", d: "M15 11v3a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 3 14v-3 M5.5 8L9 11.5 12.5 8 M9 11.5V3" },  // export
  ];

  // mindmap data per variant — different topic, same layout
  const variants = {
    checkin: {
      title: lang === "ja" ? "履歴 (3/3)" : "History (3/3)",
      tabs: lang === "ja"
        ? ["チェックイン画面…", "JBN日本語UI改善", "チェックイン画面…", "チェックイン画面…", "チェックイン画面…"]
        : ["check-in screen…", "JBN JP UI revisions", "check-in screen…", "check-in screen…", "check-in screen…"],
      activeTab: 4,
      banner: lang === "ja" ? "会話データが更新されました" : "Conversation synced",
      stats: [
        { k: "issue", jp: "課題", en: "issue", c: "#C9583C", n: 4 },
        { k: "decision", jp: "決定", en: "decision", c: "#6B8CAE", n: 6 },
        { k: "info", jp: "情報", en: "info", c: "#8FA896", n: 3 },
      ],
      scene: compact ? "checkinDesign" : "product",
    },
    generation: {
      title: lang === "ja" ? "履歴 (1/3)" : "History (1/3)",
      tabs: [
        lang === "ja" ? "評価基盤v2…" : "eval harness v2…",
        lang === "ja" ? "キャッシュ層…" : "cache layer…",
        lang === "ja" ? "8k制限…" : "8k ceiling…",
        lang === "ja" ? "回帰テスト…" : "regression…",
      ],
      activeTab: 2,
      banner: lang === "ja" ? "新しいマップを生成しました" : "New map generated",
      stats: [
        { k: "idea", jp: "アイデア", en: "idea", c: "#8F6FA3", n: 7 },
        { k: "decision", jp: "決定", en: "decision", c: "#6B8CAE", n: 9 },
        { k: "info", jp: "情報", en: "info", c: "#8FA896", n: 5 },
      ],
      scene: "eval",
    },
  };
  const v = variants[variant] || variants.checkin;

  return (
    <div style={{
      background: "#F5F0E8",
      fontFamily: "var(--font-sans)",
      color: "#3B352D",
      display: "grid", gridTemplateColumns: "72px 1fr",
      height: 680,
    }}>
      {/* Rail */}
      <div style={{
        background: "#F5F0E8",
        padding: "16px 12px",
        display: "flex", flexDirection: "column", alignItems: "center", gap: 10,
        borderRight: "1px solid rgba(59,53,45,0.06)",
      }}>
        {railIcons.map((ic, i) => {
          if (ic.k === "divider") return (
            <div key={i} style={{ width: 32, height: 1, background: "rgba(59,53,45,0.1)", margin: "2px 0" }}/>
          );
          const active = i === 0;
          return (
            <div key={i} style={{
              width: 44, height: 44, borderRadius: 12,
              background: "#F5F0E8",
              display: "grid", placeItems: "center",
              boxShadow: active
                ? "inset 3px 3px 7px #C8BFAE, inset -3px -3px 7px #FFFDF8"
                : "4px 4px 9px #C8BFAE, -4px -4px 9px #FFFDF8",
            }}>
              {ic.kind === "mark" ? (
                <svg width="20" height="20" viewBox="0 0 24 24" fill="none">
                  <path d="M12 12L5.5 5.5 M12 12L18.5 5.5 M12 12L5.5 18.5 M12 12L18.5 18.5"
                    stroke="#C9583C" strokeWidth="1.4" strokeLinecap="round"/>
                  <circle cx="12" cy="12" r="2.6" fill="#C9583C"/>
                  <circle cx="5" cy="5" r="2" stroke="#C9583C" strokeWidth="1.2" fill="none"/>
                  <circle cx="19" cy="5" r="2" stroke="#C9583C" strokeWidth="1.2" fill="none"/>
                  <circle cx="5" cy="19" r="2" stroke="#C9583C" strokeWidth="1.2" fill="none"/>
                  <circle cx="19" cy="19" r="2" stroke="#C9583C" strokeWidth="1.2" fill="none"/>
                </svg>
              ) : (
                <svg width="18" height="18" viewBox="0 0 18 18" fill="none"
                  stroke="#8C8070" strokeWidth="1.2"
                  strokeLinecap="round" strokeLinejoin="round">
                  <path d={ic.d}/>
                </svg>
              )}
            </div>
          );
        })}
        <div style={{ flex: 1 }}/>
        {/* Bottom buttons: settings, theme, JA, count, LIVE */}
        <div style={{
          width: 44, height: 44, borderRadius: 12,
          background: "#F5F0E8",
          display: "grid", placeItems: "center",
          boxShadow: "4px 4px 9px #C8BFAE, -4px -4px 9px #FFFDF8",
        }}>
          <svg width="18" height="18" viewBox="0 0 18 18" fill="none" stroke="#8C8070" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round">
            <circle cx="9" cy="9" r="2.2"/><path d="M14.5 11.5a1.2 1.2 0 0 0 .2 1.3l.1.1a1.5 1.5 0 1 1-2.1 2.1l-.1-.1a1.2 1.2 0 0 0-1.3-.2 1.2 1.2 0 0 0-.7 1.1V16a1.5 1.5 0 1 1-3 0v-.1a1.2 1.2 0 0 0-.8-1.1 1.2 1.2 0 0 0-1.3.2l-.1.1a1.5 1.5 0 1 1-2.1-2.1l.1-.1a1.2 1.2 0 0 0 .2-1.3 1.2 1.2 0 0 0-1.1-.7H2.5a1.5 1.5 0 1 1 0-3h.1a1.2 1.2 0 0 0 1.1-.8 1.2 1.2 0 0 0-.2-1.3l-.1-.1a1.5 1.5 0 1 1 2.1-2.1l.1.1a1.2 1.2 0 0 0 1.3.2h.1a1.2 1.2 0 0 0 .7-1.1V2.5a1.5 1.5 0 1 1 3 0v.1a1.2 1.2 0 0 0 .7 1.1 1.2 1.2 0 0 0 1.3-.2l.1-.1a1.5 1.5 0 1 1 2.1 2.1l-.1.1a1.2 1.2 0 0 0-.2 1.3v.1a1.2 1.2 0 0 0 1.1.7h.3a1.5 1.5 0 1 1 0 3h-.1a1.2 1.2 0 0 0-1.1.7z"/>
          </svg>
        </div>
        <div style={{
          width: 44, height: 44, borderRadius: 12,
          background: "#F5F0E8",
          display: "grid", placeItems: "center",
          boxShadow: "4px 4px 9px #C8BFAE, -4px -4px 9px #FFFDF8",
          fontSize: 16, color: "#D4B85C",
        }}>☽</div>
        <div style={{
          width: 44, height: 44, borderRadius: 12,
          background: "#F5F0E8",
          display: "grid", placeItems: "center",
          boxShadow: "4px 4px 9px #C8BFAE, -4px -4px 9px #FFFDF8",
          fontFamily: "var(--font-mono)", fontSize: 11, fontWeight: 600,
          color: "#8C8070", letterSpacing: "0.08em",
        }}>JA</div>
        <div style={{
          width: 44, height: 44, borderRadius: 12,
          background: "#F5F0E8",
          display: "grid", placeItems: "center",
          boxShadow: "4px 4px 9px #C8BFAE, -4px -4px 9px #FFFDF8",
          fontFamily: "var(--font-mono)", fontSize: 11, fontWeight: 600,
          color: "#8C8070",
        }}>20</div>
        <div style={{
          width: 44, height: 44, borderRadius: 12,
          background: "#F5F0E8",
          display: "grid", placeItems: "center",
          boxShadow: "inset 3px 3px 7px #C8BFAE, inset -3px -3px 7px #FFFDF8",
          fontFamily: "'SF Mono', ui-monospace, monospace", fontSize: 11, fontWeight: 700,
          color: "#E05A5A", letterSpacing: "0.02em",
          position: "relative",
        }}>LIVE
          <span style={{
            position: "absolute", top: 8, right: 8, width: 6, height: 6,
            borderRadius: "50%", background: "#DC2626",
            boxShadow: "0 0 4px rgba(220,38,38,0.6)",
          }}/>
        </div>
      </div>

      {/* Main */}
      <div style={{ display: "flex", flexDirection: "column", minWidth: 0 }}>
        {/* Header with big logo */}
        <div style={{
          display: "flex", alignItems: "center", justifyContent: "space-between",
          padding: "16px 22px 14px",
        }}>
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            {/* 6-arm radial brand mark */}
            <svg width="32" height="32" viewBox="0 0 144 144" fill="none">
              <g stroke="#3B352D" strokeWidth="3.2" strokeLinecap="round">
                <path d="M72 72 Q100 78 118 72"/><path d="M72 72 Q44 66 26 72"/>
                <path d="M72 72 Q92 50 95 32"/><path d="M72 72 Q52 94 49 112"/>
                <path d="M72 72 Q52 50 49 32"/><path d="M72 72 Q92 94 95 112"/>
              </g>
              <circle cx="118" cy="72" r="5" fill="#F0A89E"/><circle cx="26" cy="72" r="5" fill="#F0A89E"/>
              <circle cx="95" cy="32" r="5" fill="#B5C9BB"/><circle cx="49" cy="112" r="5" fill="#B5C9BB"/>
              <circle cx="49" cy="32" r="5" fill="#9CB6CE"/><circle cx="95" cy="112" r="5" fill="#9CB6CE"/>
              <circle cx="72" cy="72" r="7" fill="#3B352D"/>
            </svg>
            <div style={{ display: "flex", flexDirection: "column", lineHeight: 1.1 }}>
              <div style={{
                fontFamily: "var(--font-sans)", fontWeight: 700, fontSize: 20,
                letterSpacing: "-0.01em",
              }}>
                <span style={{ color: "#3B352D" }}>LL</span>
                <span style={{ color: "#C9583C" }}>Mind</span>
                <span style={{ color: "#3B352D" }}>Map</span>
              </div>
              <div style={{
                fontFamily: "var(--font-mono)", fontSize: 10.5,
                color: "#8C8070", letterSpacing: "0.01em", marginTop: 3,
              }}>Trace, edit, and surpass any LLM chat</div>
            </div>
          </div>
          <div style={{ display: "flex", alignItems: "center", gap: 16, fontSize: 12, color: "#6A6F85" }}>
            <span>kkh.sigma@gmail.com</span>
            <span style={{ color: "#3B352D" }}>
              {lang === "ja" ? "サインアウト" : "Sign out"}
            </span>
          </div>
        </div>

        {/* Sub-header: history label + small arrow */}
        <div style={{
          display: "flex", alignItems: "center", justifyContent: "space-between",
          padding: "8px 22px 10px",
          borderBottom: "1px solid rgba(59,53,45,0.06)",
        }}>
          <span style={{ fontSize: 13, color: "#6A6F85" }}>{v.title}</span>
          <svg width="10" height="10" viewBox="0 0 10 10" fill="none">
            <path d="M3 1.5 L6.5 5 L3 8.5" stroke="#8C8070" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
        </div>

        {!compact && (
        <>
        {/* Banner pill */}
        <div style={{ padding: "12px 22px 8px" }}>
          <div style={{
            padding: "9px 14px",
            background: "#F5F0E8",
            borderRadius: 10,
            boxShadow: "inset 2px 2px 5px #C8BFAE, inset -2px -2px 5px #FFFDF8",
            display: "flex", alignItems: "center", gap: 8,
            fontSize: 12, color: "#4B8263",
          }}>
            <span style={{
              width: 6, height: 6, borderRadius: "50%",
              background: "#4B8263", boxShadow: "0 0 0 2px rgba(75,130,99,0.2)",
            }}/>
            {v.banner}
          </div>
        </div>

        {/* Category indicator chips — same pattern as global cat-chip, tuned for the panel's cool palette */}
        {v.stats && (
          <div style={{
            display: "flex", flexWrap: "wrap", gap: 8,
            padding: "4px 22px 12px",
          }}>
            {v.stats.map(s => (
              <span key={s.k} style={{
                display: "inline-flex", alignItems: "center", gap: 8,
                height: 26, padding: "0 12px", borderRadius: 999,
                background: "#F5F0E8",
                fontSize: 12, color: "#3B352D", fontWeight: 500,
                boxShadow: "-2px -2px 5px #FFFDF8, 3px 3px 7px #C8BFAE",
                whiteSpace: "nowrap",
              }}>
                <span style={{
                  width: 8, height: 8, borderRadius: "50%",
                  background: s.c, display: "inline-block", flex: "0 0 auto",
                }}/>
                {lang === "ja" ? s.jp : s.en}
                <span style={{
                  fontFamily: "var(--font-mono)", fontSize: 11,
                  color: "#8C8070", marginLeft: 2, letterSpacing: "0.04em",
                }}>{s.n}</span>
              </span>
            ))}
          </div>
        )}
        </>
        )}

        {/* Tabs row */}
        <div style={{
          display: "flex", gap: 10, padding: "12px 22px 14px",
          overflow: "hidden",
        }}>
          {v.tabs.map((t, i) => {
            const isActive = i === v.activeTab;
            return (
              <div key={i} style={{
                flex: 1, minWidth: 0,
                display: "flex", alignItems: "center", justifyContent: "space-between", gap: 6,
                padding: "7px 12px", borderRadius: 8,
                background: isActive ? "#F5F0E8" : "transparent",
                boxShadow: isActive
                  ? "inset 2px 2px 4px #C8BFAE, inset -2px -2px 4px #FFFDF8"
                  : "none",
                fontSize: 12,
                color: isActive ? "#3B352D" : "#8C8070",
                fontWeight: isActive ? 600 : 400,
                whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
              }}>
                <span style={{ overflow: "hidden", textOverflow: "ellipsis" }}>{t}</span>
                {isActive && (
                  <span style={{ color: "#8C8070", fontSize: 13, flexShrink: 0 }}>×</span>
                )}
              </div>
            );
          })}
        </div>

        {/* Map canvas */}
        <div style={{ flex: 1, position: "relative", overflow: "hidden" }}>
          <RadialMindmap scene={v.scene} zoom={zoom}/>
        </div>
      </div>
    </div>
  );
};

/* Hand-authored radial mindmap matching the real product.
   Accepts a `scene` prop selecting one of the pre-composed layouts.
   Each layout has a hub, a small stub, 4 mids at NW/NE/SW/SE, and
   varied leaf counts with curved paths + one highlighted leaf. */
const RadialMindmap = ({ scene = "product", zoom = null }) => {
  const W = 1000, H = 820;
  // hub coords — most scenes center it; checkinDesign offsets it to lower-right
  const SCENE_HUB = {
    checkinDesign: { cx: 760, cy: 600 },
  };
  const { cx, cy } = SCENE_HUB[scene] || { cx: 500, cy: 440 };
  // zoom presets — tighter viewBox onto a node cluster (random-feeling pick: SE leaves)
  const zoomBoxes = {
    leaf: { x: 540, y: 440, w: 460, h: 380 },   // SE cluster: 4-block screen layout
    mid:  { x: 280, y: 280, w: 520, h: 420 },   // upper hub area
  };
  const vb = zoom && zoomBoxes[zoom]
    ? `${zoomBoxes[zoom].x} ${zoomBoxes[zoom].y} ${zoomBoxes[zoom].w} ${zoomBoxes[zoom].h}`
    : `0 0 ${W} ${H}`;
  const INK = "#3B352D";
  const DARK = "#2C3142";
  const GRAY = "#8C8070";
  const FAINT = "#B8BCCB";

  const scenes = {
    // Design-focused conversation — generic & readable
    product: {
      hub: "プロダクト設計の方向性",
      stub: { label: "実装継続を確認", dx: 120, dy: -4 },
      groups: [
        {
          mid: { label: "優先順位の整理", x: cx - 130, y: cy - 120 },
          leaves: [
            { x: cx - 340, y: cy - 250, c1x: cx - 230, c1y: cy - 150, label: "言葉が最優先推奨", anchor: "end" },
            { x: cx - 280, y: cy - 340, c1x: cx - 220, c1y: cy - 220, label: "CTAの見た目（押したくなるか）", anchor: "end" },
            { x: cx - 60,  y: cy - 380, c1x: cx - 130, c1y: cy - 240, label: "回答後メッセージのパターン設計", anchor: "end" },
          ],
        },
        {
          mid: { label: "既存機能の確認", x: cx + 140, y: cy - 120 },
          leaves: [
            { x: cx + 130, y: cy - 360, c1x: cx + 150, c1y: cy - 220, label: "チェックインはlocalStorageのみ", anchor: "start" },
            { x: cx + 310, y: cy - 280, c1x: cx + 230, c1y: cy - 180, label: "API・DBは存在するが未接続", anchor: "start" },
            { x: cx + 370, y: cy - 160, c1x: cx + 260, c1y: cy - 140, label: "DB接続は次フェーズ", anchor: "start" },
          ],
        },
        {
          mid: { label: "UX細部の設計方針", x: cx - 150, y: cy + 100 },
          leaves: [
            { x: cx - 370, y: cy + 70,  c1x: cx - 270, c1y: cy + 90,  label: "強制はNG", anchor: "end" },
            { x: cx - 320, y: cy + 250, c1x: cx - 250, c1y: cy + 180, label: "人っぽいメッセージ返す", anchor: "end" },
            { x: cx - 240, y: cy + 370, c1x: cx - 200, c1y: cy + 250, label: "0.3〜0.5秒遅延で体験感を出す", anchor: "end" },
          ],
        },
        {
          mid: { label: "画面4ブロック構成", x: cx + 120, y: cy + 110 },
          leaves: [
            { x: cx + 340, y: cy + 170, c1x: cx + 230, c1y: cy + 150, label: "①感情：状態の把握", anchor: "start" },
            { x: cx + 360, y: cy + 270, c1x: cx + 240, c1y: cy + 220, label: "②サマリー：数字1〜2個のみ", anchor: "start" },
            { x: cx + 310, y: cy + 360, c1x: cx + 220, c1y: cy + 280, label: "③コンディション選択（4択）", anchor: "start", highlight: true },
            { x: cx + 180, y: cy + 400, c1x: cx + 170, c1y: cy + 300, label: "④CTA：順番の固定", anchor: "start" },
          ],
        },
      ],
    },
    // Live-demo variant — eval pipeline topic, same character
    eval: {
      hub: "LLM評価パイプライン",
      stub: { label: "CI統合を確認", dx: 120, dy: -4 },
      groups: [
        {
          mid: { label: "プロンプト設計", x: cx - 130, y: cy - 120 },
          leaves: [
            { x: cx - 340, y: cy - 230, c1x: cx - 230, c1y: cy - 150, label: "指示の明確化", anchor: "end" },
            { x: cx - 290, y: cy - 330, c1x: cx - 220, c1y: cy - 220, label: "few-shot 例の選定", anchor: "end" },
            { x: cx - 70,  y: cy - 370, c1x: cx - 130, c1y: cy - 240, label: "ガードレール設計", anchor: "end" },
          ],
        },
        {
          mid: { label: "評価指標の定義", x: cx + 140, y: cy - 120 },
          leaves: [
            { x: cx + 140, y: cy - 360, c1x: cx + 150, c1y: cy - 220, label: "精度・再現率", anchor: "start" },
            { x: cx + 320, y: cy - 270, c1x: cx + 240, c1y: cy - 180, label: "コスト・レイテンシ", anchor: "start" },
            { x: cx + 370, y: cy - 150, c1x: cx + 260, c1y: cy - 140, label: "人手レビュースコア", anchor: "start" },
          ],
        },
        {
          mid: { label: "データセット整備", x: cx - 150, y: cy + 100 },
          leaves: [
            { x: cx - 370, y: cy + 70,  c1x: cx - 270, c1y: cy + 90,  label: "合成は最小限", anchor: "end" },
            { x: cx - 320, y: cy + 250, c1x: cx - 250, c1y: cy + 180, label: "難例の集中収集", anchor: "end" },
            { x: cx - 240, y: cy + 370, c1x: cx - 200, c1y: cy + 250, label: "分布のドリフト監視", anchor: "end" },
          ],
        },
        {
          mid: { label: "結果の可視化", x: cx + 120, y: cy + 110 },
          leaves: [
            { x: cx + 340, y: cy + 170, c1x: cx + 230, c1y: cy + 150, label: "①モデル間の比較", anchor: "start" },
            { x: cx + 360, y: cy + 270, c1x: cx + 240, c1y: cy + 220, label: "②失敗例のクラスタ", anchor: "start" },
            { x: cx + 310, y: cy + 360, c1x: cx + 220, c1y: cy + 280, label: "③回帰の早期検出", anchor: "start", highlight: true },
            { x: cx + 180, y: cy + 400, c1x: cx + 170, c1y: cy + 300, label: "④リリース判定", anchor: "start" },
          ],
        },
      ],
    },
    // Reference-style: hub at lower-right, branches reach NW/N/W with
    // a few outliers at NE/E/S. Lots of empty space across the canvas.
    checkinDesign: {
      hub: "チェックイン画面設計",
      hubAnchor: "start",   // label sits to right of hub
      hubDx: 18, hubDy: 6,  // text offset from hub
      stub: { label: "常時表", dx: 130, dy: 0 },
      groups: [
        {
          // upper-NW cluster — three leaves, character of "phase 3/4 + 次は…"
          mid: { label: "段階的実装フェーズ", x: cx - 230, y: cy + 60 },
          leaves: [
            { x: cx - 660, y: cy - 230, label: "Phase4：雪・雨パーティクル", anchor: "start" },
            { x: cx - 760, y: cy - 80,  label: "hase3：グラデ微動アニメ",   anchor: "start" },
            { x: cx - 230, y: cy - 320, label: "次はカード優先順位設計",     anchor: "end"   },
          ],
        },
        {
          // S cluster — bg/weather + 雨も
          mid: { label: "背景：時間帯×天気で変化", x: cx - 200, y: cy + 180 },
          leaves: [
            { x: cx - 660, y: cy + 200, label: "・雨も背景に反映", anchor: "start" },
          ],
        },
        {
          // E cluster — completely separated branches
          mid: { label: "通常時と完全分離", x: cx + 180, y: cy - 60 },
          leaves: [
            { x: cx + 250, y: cy + 170, label: "フルスクリーン表示内容", anchor: "start", highlight: true },
          ],
        },
      ],
    },
    // Sales strategy / repeat-rate conversation — matches LiveDemo chat context
    // ~75% spread — fills the demo container without clipping
    liveDemo: {
      hub: "リピート率低下",
      stub: { label: "初期データ確認", dx: 70, dy: -4 },
      groups: [
        {
          mid: { label: "チャネル別分解", x: cx - 100, y: cy - 95 },
          leaves: [
            { x: cx - 260, y: cy - 195, label: "広告経由", anchor: "end" },
            { x: cx - 215, y: cy - 265, label: "自然流入", anchor: "end" },
            { x: cx - 50,  y: cy - 300, label: "購入率 42%→31%", anchor: "end" },
          ],
        },
        {
          mid: { label: "時系列推移", x: cx + 110, y: cy - 95 },
          leaves: [
            { x: cx + 100, y: cy - 285, label: "18ヶ月の推移", anchor: "start" },
            { x: cx + 245, y: cy - 225, label: "獲得チャネル変化", anchor: "start" },
            { x: cx + 290, y: cy - 130, label: "季節変動の影響", anchor: "start" },
          ],
        },
        {
          mid: { label: "LTV改善", x: cx - 115, y: cy + 80 },
          leaves: [
            { x: cx - 290, y: cy + 55,  label: "解約率の高いセグメント", anchor: "end" },
            { x: cx - 250, y: cy + 195, label: "初回体験の改善", anchor: "end" },
            { x: cx - 190, y: cy + 290, label: "CAC 1.4倍増", anchor: "end" },
          ],
        },
        {
          mid: { label: "ファネル分析", x: cx + 95, y: cy + 90 },
          leaves: [
            { x: cx + 270, y: cy + 135, label: "LP離脱率", anchor: "start" },
            { x: cx + 285, y: cy + 215, label: "CVR低下", anchor: "start" },
            { x: cx + 245, y: cy + 285, label: "クリエイティブ疲弊", anchor: "start", highlight: true },
            { x: cx + 140, y: cy + 315, label: "CACモニタリング", anchor: "start" },
          ],
        },
      ],
    },
  };
  const s = scenes[scene] || scenes.product;

  return (
    <svg width="100%" height="100%" viewBox={vb} preserveAspectRatio="xMidYMid meet"
      style={{ display: "block" }}>
      {/* Hub → each mid : cubic curl matching the leaf character */}
      {s.groups.map((g, i) => {
        const curlSign = [1, -1, -1, 1][i] || 1;
        const vx = g.mid.x - cx, vy = g.mid.y - cy;
        const d  = Math.sqrt(vx*vx + vy*vy) || 1;
        const px = -vy / d, py = vx / d;
        const curl = d * 0.35 * curlSign;
        const c1x = cx + vx * 0.2 + px * curl;
        const c1y = cy + vy * 0.2 + py * curl;
        const c2x = cx + vx * 0.75 + px * curl * 0.4;
        const c2y = cy + vy * 0.75 + py * curl * 0.4;
        return (
          <path key={`hm${i}`}
            d={`M ${cx} ${cy} C ${c1x} ${c1y} ${c2x} ${c2y} ${g.mid.x} ${g.mid.y}`}
            stroke={GRAY} strokeWidth="1" fill="none" strokeLinecap="round"/>
        );
      })}

      {/* Hub → stub (small lateral branch) */}
      <path d={`M ${cx + 10} ${cy - 2} Q ${cx + 60} ${cy - 10} ${cx + s.stub.dx - 8} ${cy + s.stub.dy}`}
        stroke={GRAY} strokeWidth="1" fill="none"/>
      <circle cx={cx + s.stub.dx - 8} cy={cy + s.stub.dy} r="3" fill={GRAY}/>
      <text x={cx + s.stub.dx} y={cy + s.stub.dy + 4}
        fontSize="13" fill={INK} fontFamily="var(--font-sans)">
        {s.stub.label}
      </text>

      {/* Per-group leaves with cubic-Bézier curl. Each leaf's curve is
          computed from its mid→leaf vector: c1 launches tangentially
          from the mid (perpendicular to the direct line, in the group's
          curl direction), c2 approaches the leaf from a softened angle.
          This creates the lazy wind-swept feel of the original. */}
      {s.groups.map((g, i) => {
        // Group curl direction: alternates NW/NE/SW/SE for organic variety.
        // Positive = counterclockwise sweep, negative = clockwise.
        const curlSign = [1, -1, -1, 1][i] || 1;
        return g.leaves.map((l, j) => {
          const mx = g.mid.x, my = g.mid.y;
          const lx = l.x,     ly = l.y;
          const vx = lx - mx, vy = ly - my;
          const dist = Math.sqrt(vx * vx + vy * vy) || 1;
          // unit perpendicular (rotated 90° CCW)
          const px = -vy / dist, py = vx / dist;
          // curl magnitude scales with distance (longer branches curl more)
          const curl = dist * 0.55 * curlSign;
          // c1: launch tangentially from mid — heavily perpendicular, little forward
          const c1x = mx + vx * 0.15 + px * curl;
          const c1y = my + vy * 0.15 + py * curl;
          // c2: arrive at leaf with softened approach — mostly forward, gentle perp
          const c2x = mx + vx * 0.75 + px * curl * 0.35;
          const c2y = my + vy * 0.75 + py * curl * 0.35;
          return (
            <g key={`g${i}l${j}`}>
              <path d={`M ${mx} ${my} C ${c1x} ${c1y} ${c2x} ${c2y} ${lx} ${ly}`}
                stroke={FAINT} strokeWidth="1" fill="none" strokeLinecap="round"/>
              <circle cx={lx} cy={ly} r={l.highlight ? 4.5 : 3.2}
                fill={l.highlight ? DARK : GRAY}/>
              <text x={lx + (l.anchor === "start" ? 10 : -10)}
                y={ly + 4} fontSize="12.5"
                fill={INK} textAnchor={l.anchor}
                fontFamily="var(--font-sans)">
                {l.label}
              </text>
            </g>
          );
        });
      })}

      {/* Mid nodes */}
      {s.groups.map((g, i) => {
        const anchor = g.mid.x > cx ? "start" : "end";
        const tx = g.mid.x + (anchor === "start" ? 9 : -9);
        return (
          <g key={`mid${i}`}>
            <circle cx={g.mid.x} cy={g.mid.y} r="5" fill={DARK}/>
            <text x={tx} y={g.mid.y + 4}
              fontSize="13" fill={INK} textAnchor={anchor}
              fontFamily="var(--font-sans)">
              {g.mid.label}
            </text>
          </g>
        );
      })}

      {/* Central hub */}
      <circle cx={cx} cy={cy} r="10" fill={DARK}/>
      {s.hubAnchor === "start" ? (
        <text x={cx + (s.hubDx || 18)} y={cy + (s.hubDy || 6)}
          fontSize="15" fill={INK} fontWeight="700"
          textAnchor="start" fontFamily="var(--font-sans)">
          {s.hub}
        </text>
      ) : (
        <text x={cx} y={cy + 28}
          fontSize="15" fill={INK} fontWeight="700"
          textAnchor="middle" fontFamily="var(--font-sans)">
          {s.hub}
        </text>
      )}
    </svg>
  );
};

/* ─── Mind Tracing — snapshot of the opt-in + metrics card ──────────────────
   Styled after the control-panel's neumorphic dialect: soft lavender
   background, inset/outset shadows, pill toggle. Mirrors the in-product UI. */
const MindTracing = ({ lang }) => {
  const stats = [
    { jp: "質問力", en: "Inquiry",     v: 68, bg: "#EDE7F6", accent: "#7E57C2" },
    { jp: "決断力", en: "Decisive",    v: 52, bg: "#E3F2FD", accent: "#4A90C4" },
    { jp: "探索力", en: "Exploration", v: 81, bg: "#E8F5E9", accent: "#5BA36B" },
    { jp: "編集力", en: "Editing",     v: 44, bg: "#FFF3E0", accent: "#C48A4A" },
  ];
  const [inView, setInView] = useStateH(false);
  const [toggleOn, setToggleOn] = useStateH(true);
  const sRef = window.React.useRef(null);

  window.React.useEffect(() => {
    const el = sRef.current;
    if (!el) return;
    const obs = new IntersectionObserver(([e]) => setInView(e.isIntersecting), { threshold: 0.3 });
    obs.observe(el);
    return () => obs.disconnect();
  }, []);

  window.React.useEffect(() => {
    if (!inView) return;
    const id = setInterval(() => setToggleOn(v => !v), 3000);
    return () => clearInterval(id);
  }, [inView]);

  return (
    <section ref={sRef} className="section container">
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 72, alignItems: "center" }}>
        {/* Left: copy */}
        <div>
          <div className="eyebrow eyebrow-accent">MIND TRACING / {lang === "ja" ? "思考の軌跡" : "YOUR PATTERNS"}</div>
          <h2 className="title-xl" style={{ marginTop: 16 }}>
            {lang === "ja"
              ? <>地図は、<br/>あなたを<em style={{ fontStyle: "italic" }}>覚えている</em>。</>
              : <>The map <em style={{ fontStyle: "italic" }}>remembers</em><br/>how you think.</>}
          </h2>
          <p className="lede" style={{ marginTop: 24, maxWidth: 460 }}>
            {lang === "ja"
              ? "すべての操作は匿名パターンとして記録され、四つの傾向として返ってくる。問うのが得意か、決めるのが得意か。オプトインで、いつでもオフに。"
              : "Every action is recorded as an anonymous pattern and returned to you as four tendencies. Are you better at asking or deciding? Opt-in, switchable, yours."}
          </p>
          <ul style={{
            marginTop: 28, padding: 0, listStyle: "none",
            display: "flex", flexDirection: "column", gap: 10,
          }}>
            {(lang === "ja"
              ? [
                "データはあなたのもの：閲覧・エクスポート・削除可能",
                "許可なく共有されることはありません",
                "匿名化されたパターンのみ（本文は外部に出ません）",
              ]
              : [
                "Your data stays yours — view, export, or delete anytime",
                "Never shared without your explicit consent",
                "Only anonymized patterns leave your browser (never the text itself)",
              ]).map((t, i) => (
              <li key={i} style={{ display: "flex", gap: 12, alignItems: "flex-start" }}>
                <span style={{ color: "var(--accent)", fontSize: 15, lineHeight: 1.5 }}>✓</span>
                <span className="body" style={{ color: "var(--ink-60)" }}>{t}</span>
              </li>
            ))}
          </ul>
        </div>

        {/* Right: neumorphic snapshot */}
        <div style={{
          background: "#EBE5DC",
          padding: 28, borderRadius: 28,
          boxShadow: "inset 6px 6px 14px #C8BFAE, inset -6px -6px 14px #FFFDF8",
        }}>
          {/* Mind Tracing card */}
          <div style={{
            background: "#F5F0E8", borderRadius: 20, padding: 22,
            boxShadow: "8px 8px 18px #C8BFAE, -8px -8px 18px #FFFDF8",
          }}>
            <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 14 }}>
              <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
                <div style={{
                  width: 40, height: 40, borderRadius: 12,
                  background: "#DDDEEF", display: "grid", placeItems: "center",
                  boxShadow: "inset 2px 2px 5px #C8BFAE, inset -2px -2px 5px #FFFDF8",
                }}>
                  <svg width="20" height="20" viewBox="0 0 20 20" fill="none">
                    <circle cx="10" cy="10" r="2.2" fill="#C9583C"/>
                    <circle cx="3.5" cy="3.5" r="1.6" fill="#C9583C"/>
                    <circle cx="16.5" cy="3.5" r="1.6" fill="#C9583C"/>
                    <circle cx="3.5" cy="16.5" r="1.6" fill="#C9583C"/>
                    <circle cx="16.5" cy="16.5" r="1.6" fill="#C9583C"/>
                    <path d="M10 10 L3.5 3.5 M10 10 L16.5 3.5 M10 10 L3.5 16.5 M10 10 L16.5 16.5" stroke="#C9583C" strokeWidth="1.3"/>
                  </svg>
                </div>
                <span style={{ fontFamily: "var(--font-sans)", fontWeight: 600, fontSize: 15, color: "#3B352D" }}>
                  Mind Tracing
                </span>
              </div>
              <span style={{
                padding: "4px 10px", borderRadius: 999,
                background: "#DDDEEF",
                color: toggleOn ? "#4B8263" : "#8C8070",
                fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.12em", fontWeight: 600,
                boxShadow: "inset 1px 1px 3px #C8BFAE, inset -1px -1px 3px #FFFDF8",
                transition: "color 400ms ease",
              }}>{toggleOn ? "ON" : "OFF"}</span>
            </div>
            <p style={{
              fontSize: 12.5, lineHeight: 1.55, color: "#6A6F85", margin: 0, marginBottom: 14,
            }}>
              {lang === "ja"
                ? "LLMindMapはマインドマップの操作を記録し、あなたの思考パターンを可視化できます。"
                : "LLMindMap logs your interactions and visualizes your thinking patterns over time."}
            </p>
            <ul style={{ margin: 0, padding: 0, listStyle: "none", display: "flex", flexDirection: "column", gap: 7 }}>
              {(lang === "ja"
                ? ["データはあなたのもの：閲覧・エクスポート・削除可能", "許可なく共有されることはありません", "匿名化されたパターンのみ（本文は外部に出ません）"]
                : ["Your data: view, export, or delete it", "Never shared without consent", "Anonymized patterns only (text stays local)"]
              ).map((t, i) => (
                <li key={i} style={{ display: "flex", gap: 8, alignItems: "flex-start" }}>
                  <span style={{ color: "#C9583C", fontSize: 11, marginTop: 2 }}>✓</span>
                  <span style={{ fontSize: 11.5, lineHeight: 1.45, color: "#6A6F85" }}>{t}</span>
                </li>
              ))}
            </ul>
            {/* toggle — animates on/off */}
            <div style={{ marginTop: 16 }}>
              <div style={{
                width: 48, height: 26, borderRadius: 999,
                background: toggleOn
                  ? "linear-gradient(180deg, #56C374 0%, #3FA55C 100%)"
                  : "linear-gradient(180deg, #C0C4D0 0%, #A8ACBA 100%)",
                position: "relative",
                boxShadow: "inset 1px 1px 3px rgba(0,0,0,0.15)",
                transition: "background 400ms ease",
              }}>
                <div style={{
                  position: "absolute", top: 2,
                  left: toggleOn ? 24 : 2,
                  width: 22, height: 22, borderRadius: "50%",
                  background: "#FFFFFF",
                  boxShadow: "0 2px 4px rgba(0,0,0,0.2)",
                  transition: "left 400ms cubic-bezier(0.34,1.56,0.64,1)",
                }}/>
              </div>
            </div>
          </div>

          {/* Thinking pattern label */}
          <div style={{
            display: "flex", alignItems: "center", gap: 10, margin: "22px 4px 14px",
          }}>
            <span style={{ fontFamily: "var(--font-sans)", fontSize: 13, fontWeight: 500, color: "#3B352D" }}>
              {lang === "ja" ? "思考パターン" : "Thinking pattern"}
            </span>
            <span style={{ color: "#A3A7BD", fontSize: 11 }}>·</span>
            <span style={{
              fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.18em",
              color: "#8C8070", fontWeight: 500,
            }}>THINKING PATTERN</span>
          </div>

          {/* 2x2 metric cards */}
          <div style={{
            display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14,
            opacity: toggleOn ? 1 : 0.35,
            filter: toggleOn ? "none" : "grayscale(1)",
            transition: "opacity 500ms ease, filter 500ms ease",
          }}>
            {stats.map((s, i) => (
              <div key={i} style={{
                padding: 16, borderRadius: 16, background: s.bg,
                boxShadow: "6px 6px 14px #C8BFAE, -6px -6px 14px #FFFDF8",
              }}>
                <div style={{ fontFamily: "var(--font-sans)", fontSize: 13, color: s.accent, fontWeight: 500, marginBottom: 6 }}>
                  {lang === "ja" ? s.jp : s.en}
                </div>
                <div style={{ display: "flex", alignItems: "baseline", gap: 2 }}>
                  <span style={{ fontFamily: "var(--font-sans)", fontWeight: 700, fontSize: 30, color: "#3B352D", letterSpacing: "-0.02em" }}>
                    {s.v}
                  </span>
                  <span style={{ fontSize: 14, color: s.accent, fontWeight: 500 }}>%</span>
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
};

/* Category classification explainer */
const CategoryExplainer = ({ lang }) => {
  const [hovCat, setHovCat] = useStateH(null);
  const cats = [
    { k: "issue", jp: "課題", en: "ISSUE", c: "var(--accent)", n: 12, sample: lang === "ja" ? "取得が遅い" : "Retrieval latency" },
    { k: "question", jp: "質問", en: "QUESTION", c: "var(--ochre)", n: 8, sample: lang === "ja" ? "なぜ8k制限？" : "Why 8k ceiling?" },
    { k: "idea", jp: "アイデア", en: "IDEA", c: "#8F6FA3", n: 7, sample: lang === "ja" ? "キャッシュ層" : "Cache layer" },
    { k: "decision", jp: "決定", en: "DECISION", c: "var(--slate)", n: 9, sample: lang === "ja" ? "評価基盤v2" : "Eval harness v2" },
    { k: "info", jp: "情報", en: "INFO", c: "var(--sage)", n: 5, sample: lang === "ja" ? "料金の階層" : "Token pricing" },
    { k: "aside", jp: "余談", en: "ASIDE", c: "#8A7D86", n: 3, sample: lang === "ja" ? "回帰テスト" : "Regression bench" },
    { k: "uncl", jp: "未分類", en: "UNCLASSIFIED", c: "var(--ink-40)", n: 2, sample: "—" },
  ];
  return (
    <section className="section" style={{ background: "var(--bg-deep)" }}>
      <div className="container">
        {/* Centered title */}
        <div style={{ textAlign: "center", marginBottom: 48 }}>
          <div className="eyebrow eyebrow-accent">CLASSIFICATION / {lang === "ja" ? "分類体系" : "SEVEN CATEGORIES"}</div>
          <h2 className="title-xl" style={{ marginTop: 16 }}>
            {lang === "ja" ? <>色が、<em style={{ fontStyle: "italic" }}>構造</em>を語る。</> : <>Color reveals <em style={{ fontStyle: "italic" }}>shape</em>.</>}
          </h2>
          <p className="lede" style={{ marginTop: 16, maxWidth: 520, margin: "16px auto 0" }}>
            {lang === "ja"
              ? "すべてのノードは、7つの分類のいずれかに属す。色が地図の性格を決める。"
              : "Every node belongs to one of seven roles. Color becomes the personality of the map."}
          </p>
        </div>

        {/* Center-stage mindmap */}
        <div style={{
          maxWidth: 620, margin: "0 auto",
          background: "#E8EAF0", borderRadius: 24, padding: "40px 32px 32px",
          boxShadow: "8px 8px 20px rgba(166,170,190,0.45), -8px -8px 20px rgba(255,255,255,0.8), inset 0 0 0 0.5px rgba(255,255,255,0.5)",
        }}>
          <svg viewBox="0 0 420 440" width="100%" preserveAspectRatio="xMidYMid meet">
            {/* Links — hub to mids (product-style arcs) */}
            <path d="M210 200 C235 185 235 148 210 128" stroke="#C5C8D4" strokeWidth="1.5" fill="none"/>
            <path d="M210 200 C175 200 148 245 145 272" stroke="#C5C8D4" strokeWidth="1.5" fill="none"/>
            <path d="M210 200 C248 200 275 245 280 272" stroke="#C5C8D4" strokeWidth="1.5" fill="none"/>
            <path d="M210 200 C185 220 185 290 210 320" stroke="#C5C8D4" strokeWidth="1.5" fill="none"/>
            {/* Links — mids to leaves */}
            <path d="M210 128 C185 125 165 95 152 72" stroke="#D5D8E2" strokeWidth="1" fill="none"/>
            <path d="M210 128 C240 120 260 95 270 72" stroke="#D5D8E2" strokeWidth="1" fill="none"/>
            <path d="M145 272 C120 278 100 300 95 330" stroke="#D5D8E2" strokeWidth="1" fill="none"/>
            <path d="M280 272 C305 278 325 300 338 325" stroke="#D5D8E2" strokeWidth="1" fill="none"/>
            <path d="M210 320 C188 325 168 350 160 378" stroke="#D5D8E2" strokeWidth="1" fill="none"/>
            <path d="M210 320 C232 325 252 350 260 378" stroke="#D5D8E2" strokeWidth="1" fill="none"/>

            {/* Leaf nodes — colored by category */}
            <g className={hovCat === "issue" ? "cat-pulse" : ""} style={{ transition: "opacity 300ms ease", opacity: hovCat && hovCat !== "issue" ? 0.25 : 1 }}>
              <circle cx="152" cy="72" r="5" fill="#C9583C"/>
              <text x="140" y="62" fontSize="12" fill="#3B352D" opacity="0.55" textAnchor="end" fontFamily="var(--font-sans)">{lang === "ja" ? "広告経由" : "Paid channels"}</text>
            </g>
            <g className={hovCat === "issue" ? "cat-pulse" : ""} style={{ transition: "opacity 300ms ease", opacity: hovCat && hovCat !== "issue" ? 0.25 : 1 }}>
              <circle cx="270" cy="72" r="5" fill="#C9583C"/>
              <text x="282" y="62" fontSize="12" fill="#3B352D" opacity="0.55" textAnchor="start" fontFamily="var(--font-sans)">{lang === "ja" ? "自然流入" : "Organic traffic"}</text>
            </g>
            <g className={hovCat === "info" ? "cat-pulse" : ""} style={{ transition: "opacity 300ms ease", opacity: hovCat && hovCat !== "info" ? 0.25 : 1 }}>
              <circle cx="95" cy="330" r="5" fill="#7A9A85" opacity="0.65"/>
              <text x="83" y="325" fontSize="12" fill="#3B352D" opacity="0.55" textAnchor="end" fontFamily="var(--font-sans)">{lang === "ja" ? "18ヶ月" : "18 months"}</text>
            </g>
            <g className={hovCat === "question" ? "cat-pulse" : ""} style={{ transition: "opacity 300ms ease", opacity: hovCat && hovCat !== "question" ? 0.25 : 1 }}>
              <circle cx="338" cy="325" r="5" fill="#B8864A" opacity="0.65"/>
              <text x="350" y="320" fontSize="12" fill="#3B352D" opacity="0.55" textAnchor="start" fontFamily="var(--font-sans)">42%→31%</text>
            </g>
            <g className={hovCat === "decision" ? "cat-pulse" : ""} style={{ transition: "opacity 300ms ease", opacity: hovCat && hovCat !== "decision" ? 0.25 : 1 }}>
              <circle cx="160" cy="378" r="5" fill="#536A8A"/>
              <text x="148" y="374" fontSize="12" fill="#3B352D" opacity="0.55" textAnchor="end" fontFamily="var(--font-sans)">{lang === "ja" ? "初回体験" : "First experience"}</text>
            </g>
            <g className={hovCat === "decision" ? "cat-pulse" : ""} style={{ transition: "opacity 300ms ease", opacity: hovCat && hovCat !== "decision" ? 0.25 : 1 }}>
              <circle cx="260" cy="378" r="5" fill="#536A8A"/>
              <text x="272" y="374" fontSize="12" fill="#3B352D" opacity="0.55" textAnchor="start" fontFamily="var(--font-sans)">{lang === "ja" ? "解約率" : "Churn rate"}</text>
            </g>

            {/* Mid nodes — category colored */}
            <g className={hovCat === "issue" ? "cat-pulse" : ""} style={{ transition: "opacity 300ms ease", opacity: hovCat && hovCat !== "issue" ? 0.25 : 1 }}>
              <circle cx="210" cy="128" r="7.5" fill="#C9583C"/>
              <text x="210" y="113" fontSize="14" fontWeight="700" fill="#3B352D" textAnchor="middle" fontFamily="var(--font-sans)">{lang === "ja" ? "チャネル別分解" : "Channel breakdown"}</text>
            </g>
            <g className={hovCat === "info" ? "cat-pulse" : ""} style={{ transition: "opacity 300ms ease", opacity: hovCat && hovCat !== "info" ? 0.25 : 1 }}>
              <circle cx="145" cy="272" r="7.5" fill="#7A9A85"/>
              <text x="132" y="260" fontSize="14" fontWeight="700" fill="#3B352D" textAnchor="end" fontFamily="var(--font-sans)">{lang === "ja" ? "時系列推移" : "Time series"}</text>
            </g>
            <g className={hovCat === "question" ? "cat-pulse" : ""} style={{ transition: "opacity 300ms ease", opacity: hovCat && hovCat !== "question" ? 0.25 : 1 }}>
              <circle cx="280" cy="272" r="7.5" fill="#B8864A"/>
              <text x="295" y="260" fontSize="14" fontWeight="700" fill="#3B352D" textAnchor="start" fontFamily="var(--font-sans)">{lang === "ja" ? "2回目購入率" : "2nd purchase rate"}</text>
            </g>

            {/* Starred mid node — gold ring */}
            <g className={hovCat === "decision" ? "cat-pulse" : ""} style={{ transition: "opacity 300ms ease", opacity: hovCat && hovCat !== "decision" ? 0.25 : 1 }}>
              <circle cx="210" cy="320" r="15" fill="none" stroke="#FBBF24" strokeWidth="1.5" opacity="0.45"/>
              <circle cx="210" cy="320" r="7.5" fill="#536A8A"/>
              <text x="210" y="305" fontSize="14" fontWeight="700" fill="#3B352D" textAnchor="middle" fontFamily="var(--font-sans)">{lang === "ja" ? "LTV改善" : "Improve LTV"}</text>
            </g>

            {/* Hub */}
            <circle cx="210" cy="200" r="13" fill="#3B352D"/>
            <text x="210" y="182" fontSize="16" fontWeight="700" fill="#3B352D" textAnchor="middle" fontFamily="var(--font-sans)">{lang === "ja" ? "リピート率低下" : "Repeat rate decline"}</text>

            <style>{`
              @keyframes catPulse { 0%,100%{ transform: scale(1); } 50%{ transform: scale(1.12); } }
              .cat-pulse circle { animation: catPulse 1.2s ease-in-out infinite; transform-origin: center; transform-box: fill-box; }
            `}</style>
          </svg>
        </div>

        {/* Floating legend — cat-chips centered below */}
        <div style={{
          display: "flex", flexWrap: "wrap", justifyContent: "center", gap: 10,
          marginTop: 36,
        }}>
          {cats.map((c) => (
            <span key={c.k} className="cat-chip"
              onMouseEnter={() => setHovCat(c.k)}
              onMouseLeave={() => setHovCat(null)}
              style={{ cursor: "pointer", transition: "transform 200ms ease, box-shadow 200ms ease", transform: hovCat === c.k ? "scale(1.08)" : "scale(1)" }}>
              <i style={{ background: c.c }}/>
              {lang === "ja" ? c.jp : c.en.toLowerCase()}
              <b>{c.n}</b>
            </span>
          ))}
        </div>
      </div>
    </section>
  );
};

/* Animated overlay branch for LiveDemo — renders a mid node + leaves
   with path draw-in, node pop, sonar glow, matching RadialMindmap's
   organic cubic-Bézier curves. */
const LiveDemoBranch = ({ branch, hubCx, hubCy }) => {
  const [step, setStep] = useStateH(0);
  window.React.useEffect(() => {
    const t1 = setTimeout(() => setStep(1), 100);
    const t2 = setTimeout(() => setStep(2), 700);
    return () => { clearTimeout(t1); clearTimeout(t2); };
  }, []);

  const GRAY = "#8C8070", INK = "#3B352D", FAINT = "#B8BCCB";
  const mx = branch.mid.x, my = branch.mid.y;

  const vx = mx - hubCx, vy = my - hubCy;
  const d = Math.sqrt(vx * vx + vy * vy) || 1;
  const px = -vy / d, py = vx / d;
  const curl = d * 0.35 * (branch.curlSign || 1);
  const c1x = hubCx + vx * 0.2 + px * curl;
  const c1y = hubCy + vy * 0.2 + py * curl;
  const c2x = hubCx + vx * 0.75 + px * curl * 0.4;
  const c2y = hubCy + vy * 0.75 + py * curl * 0.4;
  const hubPath = `M ${hubCx} ${hubCy} C ${c1x} ${c1y} ${c2x} ${c2y} ${mx} ${my}`;

  const midAnchor = mx > hubCx ? "start" : "end";
  const midTx = mx + (midAnchor === "start" ? 9 : -9);

  return (
    <g>
      <path d={hubPath} stroke={GRAY} strokeWidth="1" fill="none" strokeLinecap="round"
        style={{ strokeDasharray: 600, strokeDashoffset: step >= 1 ? 0 : 600,
          transition: "stroke-dashoffset 500ms cubic-bezier(0.33,1,0.68,1)" }}/>

      <circle cx={mx} cy={my} r={step >= 1 ? 5 : 0} fill={branch.color || "#2C3142"}
        style={{ transition: "r 300ms cubic-bezier(0.34,1.56,0.64,1) 100ms" }}/>

      <text x={midTx} y={my + 4} fontSize="13" fill={INK} textAnchor={midAnchor}
        fontFamily="var(--font-sans)"
        style={{ opacity: step >= 1 ? 1 : 0, transition: "opacity 250ms ease-out 300ms" }}>
        {branch.label}
      </text>

      {step >= 1 && [0, 0.4].map((dl, i) => (
        <circle key={i} cx={mx} cy={my} r="5" fill="none"
          stroke="#FBBF24" strokeWidth="1.5"
          style={{ opacity: 0, animation: `demoNodeGlow 1.5s ease-in-out ${0.1 + dl}s 3` }}/>
      ))}

      {branch.leaves.map((l, j) => {
        const lx = l.x, ly = l.y;
        const lvx = lx - mx, lvy = ly - my;
        const ld = Math.sqrt(lvx * lvx + lvy * lvy) || 1;
        const lpx = -lvy / ld, lpy = lvx / ld;
        const lcurl = ld * 0.55 * (branch.curlSign || 1);
        const lc1x = mx + lvx * 0.15 + lpx * lcurl;
        const lc1y = my + lvy * 0.15 + lpy * lcurl;
        const lc2x = mx + lvx * 0.75 + lpx * lcurl * 0.35;
        const lc2y = my + lvy * 0.75 + lpy * lcurl * 0.35;
        const leafPath = `M ${mx} ${my} C ${lc1x} ${lc1y} ${lc2x} ${lc2y} ${lx} ${ly}`;
        const tx = lx + (l.anchor === "start" ? 10 : -10);
        return (
          <g key={j}>
            <path d={leafPath} stroke={FAINT} strokeWidth="1" fill="none" strokeLinecap="round"
              style={{ strokeDasharray: 400, strokeDashoffset: step >= 2 ? 0 : 400,
                transition: "stroke-dashoffset 400ms cubic-bezier(0.33,1,0.68,1)" }}/>
            <circle cx={lx} cy={ly} r={step >= 2 ? 3.2 : 0} fill={GRAY}
              style={{ transition: "r 250ms cubic-bezier(0.34,1.56,0.64,1) 100ms" }}/>
            <text x={tx} y={ly + 4} fontSize="12.5" fill={INK} textAnchor={l.anchor}
              fontFamily="var(--font-sans)"
              style={{ opacity: step >= 2 ? 1 : 0, transition: "opacity 200ms ease-out 250ms" }}>
              {l.label}
            </text>
          </g>
        );
      })}
    </g>
  );
};

/* Animated mindmap — progressive reveal matching the actual product's D3 animation.
   Link draw-in (300ms easeCubicOut) → dot pop (180ms easeBackOut 1.2, delayed 300ms)
   → label fade (200ms, delayed 500ms). Leaves stagger 220ms apart per group. */
const AnimatedMindmap = ({ treeStep = 0, overlays = [], showSonar = false, lang = "ja" }) => {
  const W = 1000, H = 820, cx = 500, cy = 440;
  const INK = "#3B352D", DARK = "#2C3142", GRAY = "#8C8070", FAINT = "#B8BCCB";
  const EASE_LINK = "cubic-bezier(0.33,1,0.68,1)";
  const EASE_DOT  = "cubic-bezier(0.34,1.56,0.64,1)";
  const ja = lang === "ja";

  const groups = [
    { mid: { label: ja ? "チャネル別分解" : "Channel Breakdown", x: 400, y: 345 },
      leaves: [
        { x: 240, y: 245, label: ja ? "広告経由" : "Paid Ads", anchor: "end" },
        { x: 285, y: 175, label: ja ? "自然流入" : "Organic", anchor: "end" },
        { x: 450, y: 140, label: ja ? "購入率 42%→31%" : "Purchase 42%→31%", anchor: "end" },
      ] },
    { mid: { label: ja ? "時系列推移" : "Timeline Trend", x: 610, y: 345 },
      leaves: [
        { x: 600, y: 155, label: ja ? "18ヶ月の推移" : "18-month trend", anchor: "start" },
        { x: 745, y: 215, label: ja ? "獲得チャネル変化" : "Channel shift", anchor: "start" },
        { x: 790, y: 310, label: ja ? "季節変動の影響" : "Seasonal impact", anchor: "start" },
      ] },
    { mid: { label: ja ? "LTV改善" : "LTV Improvement", x: 385, y: 520 },
      leaves: [
        { x: 210, y: 495, label: ja ? "解約率の高いセグメント" : "High-churn segment", anchor: "end" },
        { x: 250, y: 635, label: ja ? "初回体験の改善" : "First experience fix", anchor: "end" },
        { x: 310, y: 730, label: ja ? "CAC 1.4倍増" : "CAC up 1.4×", anchor: "end" },
      ] },
    { mid: { label: ja ? "ファネル分析" : "Funnel Analysis", x: 595, y: 530 },
      leaves: [
        { x: 770, y: 575, label: ja ? "LP離脱率" : "LP Drop-off", anchor: "start" },
        { x: 785, y: 655, label: ja ? "CVR低下" : "CVR Decline", anchor: "start" },
        { x: 745, y: 725, label: ja ? "クリエイティブ疲弊" : "Creative fatigue", anchor: "start", highlight: true },
        { x: 640, y: 755, label: ja ? "CACモニタリング" : "CAC Monitoring", anchor: "start" },
      ] },
  ];
  const curlSigns = [1, -1, -1, 1];

  const bezier = (ax, ay, bx, by, curl) => {
    const vx = bx - ax, vy = by - ay;
    const d = Math.sqrt(vx * vx + vy * vy) || 1;
    const px = -vy / d, py = vx / d;
    const c1x = ax + vx * 0.2 + px * curl;
    const c1y = ay + vy * 0.2 + py * curl;
    const c2x = ax + vx * 0.75 + px * curl * 0.4;
    const c2y = ay + vy * 0.75 + py * curl * 0.4;
    return `M ${ax} ${ay} C ${c1x} ${c1y} ${c2x} ${c2y} ${bx} ${by}`;
  };
  const leafBez = (mx, my, lx, ly, curl) => {
    const vx = lx - mx, vy = ly - my;
    const d = Math.sqrt(vx * vx + vy * vy) || 1;
    const px = -vy / d, py = vx / d;
    const c = d * 0.55 * curl;
    const c1x = mx + vx * 0.15 + px * c;
    const c1y = my + vy * 0.15 + py * c;
    const c2x = mx + vx * 0.75 + px * c * 0.35;
    const c2y = my + vy * 0.75 + py * c * 0.35;
    return `M ${mx} ${my} C ${c1x} ${c1y} ${c2x} ${c2y} ${lx} ${ly}`;
  };

  const hubOn = treeStep > 0;

  return (
    <svg width="100%" height="100%" viewBox={`0 0 ${W} ${H}`}
      preserveAspectRatio="xMidYMid meet" style={{ display: "block" }}>

      {/* Layer 1 — hub→mid links */}
      {groups.map((g, i) => {
        const show = treeStep > i + 1;
        const vx = g.mid.x - cx, vy = g.mid.y - cy;
        const d = Math.sqrt(vx * vx + vy * vy) || 1;
        const curl = d * 0.35 * curlSigns[i];
        return (
          <path key={`hm${i}`} d={bezier(cx, cy, g.mid.x, g.mid.y, curl)}
            stroke={GRAY} strokeWidth="1" fill="none" strokeLinecap="round"
            style={{ strokeDasharray: 600, strokeDashoffset: show ? 0 : 600,
              transition: `stroke-dashoffset 300ms ${EASE_LINK}` }}/>
        );
      })}

      {/* Layer 2 — mid→leaf links */}
      {groups.map((g, i) => {
        const show = treeStep > i + 1;
        return g.leaves.map((l, j) => {
          const delay = 600 + j * 220;
          return (
            <path key={`ml${i}${j}`} d={leafBez(g.mid.x, g.mid.y, l.x, l.y, curlSigns[i])}
              stroke={FAINT} strokeWidth="1" fill="none" strokeLinecap="round"
              style={{ strokeDasharray: 400, strokeDashoffset: show ? 0 : 400,
                transition: `stroke-dashoffset 300ms ${EASE_LINK} ${delay}ms` }}/>
          );
        });
      })}

      {/* Layer 3 — leaf dots + labels */}
      {groups.map((g, i) => {
        const show = treeStep > i + 1;
        return g.leaves.map((l, j) => {
          const delay = 600 + j * 220;
          return (
            <g key={`ld${i}${j}`}>
              <circle cx={l.x} cy={l.y}
                r={show ? (l.highlight ? 4.5 : 3.2) : 0}
                fill={l.highlight ? DARK : GRAY}
                style={{ transition: `r 180ms ${EASE_DOT} ${delay + 300}ms` }}/>
              <text x={l.x + (l.anchor === "start" ? 10 : -10)} y={l.y + 4}
                fontSize="12.5" fill={INK} textAnchor={l.anchor}
                fontFamily="var(--font-sans)"
                style={{ opacity: show ? 1 : 0,
                  transition: `opacity 200ms ease ${delay + 480}ms` }}>
                {l.label}
              </text>
            </g>
          );
        });
      })}

      {/* Layer 4 — mid dots + labels */}
      {groups.map((g, i) => {
        const show = treeStep > i + 1;
        const anchor = g.mid.x > cx ? "start" : "end";
        return (
          <g key={`md${i}`}>
            <circle cx={g.mid.x} cy={g.mid.y} r={show ? 5 : 0} fill={DARK}
              style={{ transition: `r 180ms ${EASE_DOT} 300ms` }}/>
            <text x={g.mid.x + (anchor === "start" ? 9 : -9)} y={g.mid.y + 4}
              fontSize="13" fill={INK} textAnchor={anchor}
              fontFamily="var(--font-sans)"
              style={{ opacity: show ? 1 : 0, transition: "opacity 200ms ease 500ms" }}>
              {g.mid.label}
            </text>
          </g>
        );
      })}

      {/* Stub */}
      <path d="M 510 438 Q 560 430 562 436" stroke={GRAY} strokeWidth="1" fill="none"
        style={{ strokeDasharray: 80, strokeDashoffset: hubOn ? 0 : 80,
          transition: `stroke-dashoffset 300ms ${EASE_LINK} 150ms` }}/>
      <circle cx={562} cy={436} r={hubOn ? 3 : 0} fill={GRAY}
        style={{ transition: `r 180ms ${EASE_DOT} 450ms` }}/>
      <text x={570} y={440} fontSize="13" fill={INK} fontFamily="var(--font-sans)"
        style={{ opacity: hubOn ? 1 : 0, transition: "opacity 200ms ease 550ms" }}>
        {ja ? "初期データ確認" : "Initial data check"}
      </text>

      {/* Sonar — 3 concentric rings, product timing (0 / 0.6 / 1.2s) */}
      {showSonar && [0, 0.6, 1.2].map((dl, i) => (
        <circle key={`son${i}`} cx={cx} cy={cy} r="5" fill="none"
          stroke="#C9583C" strokeWidth="1.5"
          style={{ opacity: 0,
            animation: `demoLiveSonar 2s cubic-bezier(0.2,0.7,0.4,1) ${dl}s infinite` }}/>
      ))}

      {/* Hub dot (topmost) */}
      <circle cx={cx} cy={cy} r={hubOn ? 10 : 0} fill={DARK}
        style={{ transition: `r 300ms ${EASE_DOT}` }}/>
      <text x={cx} y={cy + 28} fontSize="15" fill={INK} fontWeight="700"
        textAnchor="middle" fontFamily="var(--font-sans)"
        style={{ opacity: hubOn ? 1 : 0, transition: "opacity 250ms ease 200ms" }}>
        {ja ? "リピート率低下" : "Repeat Rate Decline"}
      </text>

      {/* Overlay branches — animate in via LiveDemoBranch */}
      {overlays.map((branch, i) => (
        <LiveDemoBranch key={`ov${i}`} branch={branch} hubCx={cx} hubCy={cy}/>
      ))}
    </svg>
  );
};

/* Live demo — product-accurate extension panel with animated mindmap expansion */
const LiveDemo = ({ lang }) => {
  const ja = lang === "ja";
  const [loopKey, setLoopKey] = useStateH(0);
  const [round, setRound] = useStateH(0); // 0,1,2 — three expansion rounds
  const [phase, setPhase] = useStateH("idle");
  const [typedChars, setTypedChars] = useStateH(0);
  const [responseChars, setResponseChars] = useStateH(0);
  const [grownBranches, setGrownBranches] = useStateH([]);
  const [treeStep, setTreeStep] = useStateH(0); // 0=nothing, 1=hub, 2-5=groups 0-3
  const [inView, setInView] = useStateH(false);
  const rootRef = window.React.useRef(null);
  const scrollRef = window.React.useRef(null);

  // Three rounds of prompt → response → branch growth
  const rounds = ja ? [
    { prompt: "競合との差別化ポイントを整理して", response: "まず価格・機能・UXの3軸で比較表を作り、自社が勝てる象限を特定しましょう。" },
    { prompt: "次の四半期のKPIを設定して", response: "リピート率35%回復、CAC1.2倍以下、NPS+10を主要KPIに据えるのが現実的です。" },
    { prompt: "チーム体制の見直しを提案して", response: "グロースチームを分離し、プロダクト・マーケ・データの3名体制にするのが最小構成です。" },
  ] : [
    { prompt: "Organize our differentiation points vs competitors", response: "Start with a 3-axis comparison — price, features, UX — then identify the quadrant where you win." },
    { prompt: "Set KPIs for next quarter", response: "Target repeat rate recovery to 35%, CAC under 1.2x, and NPS +10 as your primary KPIs." },
    { prompt: "Propose a team restructure", response: "Spin out a dedicated growth team — product, marketing, and data — three people minimum." },
  ];

  const currentRound = rounds[round];

  // Existing messages — continues from LiveModeWindow's conversation
  const baseMsgs = ja
    ? [
        { who: "user", t: "リピート率が低下してる原因を整理したい" },
        { who: "ai", t: "獲得チャネル別に2回目購入率を分解するのが最初の一手です。" },
        { who: "user", t: "LTV改善の優先順位を整理して" },
        { who: "ai", t: "解約率の高いセグメントを特定して、初回体験の改善から着手しましょう。" },
      ]
    : [
        { who: "user", t: "I want to organize the reasons behind declining repeat rate" },
        { who: "ai", t: "Break down second purchase rate by acquisition channel first." },
        { who: "user", t: "Prioritize the LTV improvement actions" },
        { who: "ai", t: "Identify the highest churn segment, then focus on first-experience improvement." },
      ];

  // IntersectionObserver
  window.React.useEffect(() => {
    const el = rootRef.current;
    if (!el) return;
    const obs = new IntersectionObserver(([e]) => { if (e.isIntersecting) setInView(true); }, { threshold: 0.3 });
    obs.observe(el);
    return () => obs.disconnect();
  }, []);

  // Progressive reveal — hub first, then groups, then typing starts
  window.React.useEffect(() => {
    if (!inView) return;
    const ts = [];
    ts.push(setTimeout(() => setTreeStep(1), 100));      // hub
    for (let i = 0; i < 4; i++)
      ts.push(setTimeout(() => setTreeStep(i + 2), 400 + i * 350));
    ts.push(setTimeout(() => setPhase("typing"), 2400)); // start typing
    return () => ts.forEach(clearTimeout);
  }, [loopKey, inView]);

  // Typing
  window.React.useEffect(() => {
    if (phase !== "typing") return;
    if (typedChars < currentRound.prompt.length) {
      const t = setTimeout(() => setTypedChars(c => c + 1), 50);
      return () => clearTimeout(t);
    }
    const t = setTimeout(() => setPhase("sent"), 400);
    return () => clearTimeout(t);
  }, [phase, typedChars]);

  // Sent → responding
  window.React.useEffect(() => {
    if (phase !== "sent") return;
    const t = setTimeout(() => { setPhase("responding"); setResponseChars(0); }, 700);
    return () => clearTimeout(t);
  }, [phase]);

  // AI response
  window.React.useEffect(() => {
    if (phase !== "responding") return;
    if (responseChars < currentRound.response.length) {
      const t = setTimeout(() => setResponseChars(c => c + 1), 20);
      return () => clearTimeout(t);
    }
    setPhase("growing");
    setGrownBranches(prev => [...prev, round]);
  }, [phase, responseChars]);

  // Growing → next round or loop
  window.React.useEffect(() => {
    if (phase !== "growing") return;
    const t = setTimeout(() => {
      if (round < 2) {
        setRound(r => r + 1);
        setTypedChars(0);
        setResponseChars(0);
        setPhase("typing");
      } else {
        setPhase("done");
        setTimeout(() => {
          setRound(0);
          setTypedChars(0);
          setResponseChars(0);
          setGrownBranches([]);
          setTreeStep(0);
          setPhase("idle");
          setLoopKey(k => k + 1);
        }, 3000);
      }
    }, 1800);
    return () => clearTimeout(t);
  }, [phase, round]);

  // Build visible messages
  const allMsgs = [...baseMsgs];
  for (let r = 0; r <= round; r++) {
    if (r < round || phase === "sent" || phase === "responding" || phase === "growing" || phase === "done") {
      allMsgs.push({ who: "user", t: rounds[r].prompt });
    }
    if (r < round || phase === "responding" || phase === "growing" || phase === "done") {
      allMsgs.push({ who: "ai", t: r < round ? rounds[r].response : rounds[r].response.slice(0, responseChars) });
    }
  }

  window.React.useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [allMsgs.length, responseChars]);

  // New branches for RadialMindmap overlay (viewBox 1000×820, hub 500,440)
  const HUB_CX = 500, HUB_CY = 440;
  const newBranches = [
    {
      // Top-right gap — right of NE group (max leaf at 790,310)
      label: ja ? "差別化戦略" : "Differentiation",
      mid: { x: 830, y: 170 },
      leaves: [
        { label: ja ? "価格比較" : "Price Gap", x: 885, y: 95, anchor: "start" },
        { label: ja ? "UX優位性" : "UX Edge", x: 880, y: 245, anchor: "start" },
      ],
      color: "#8F6FA3", curlSign: -1,
    },
    {
      // Left gap — left of NW/SW groups (min leaf at 210,495)
      label: ja ? "Q2 KPI" : "Q2 KPIs",
      mid: { x: 150, y: 400 },
      leaves: [
        { label: ja ? "リピート35%" : "Repeat 35%", x: 85, y: 315, anchor: "end" },
        { label: ja ? "CAC目標" : "CAC Target", x: 75, y: 545, anchor: "end" },
      ],
      color: "#7A9A85", curlSign: 1,
    },
    {
      // Bottom-right gap — right of SE group (max leaf at 785,655)
      label: ja ? "体制変更" : "Restructure",
      mid: { x: 830, y: 560 },
      leaves: [
        { label: ja ? "グロース分離" : "Growth Team", x: 880, y: 490, anchor: "start" },
        { label: ja ? "3名体制" : "3-person", x: 880, y: 630, anchor: "start" },
      ],
      color: "#B8864A", curlSign: -1,
    },
  ];

  const demoRailIcons = [
    { kind: "mark" },
    { d: "M4.5 10 A4.5 4.5 0 0 1 13 7.5 M13 4.5 L13 7.5 L10 7.5 M13.5 8 A4.5 4.5 0 0 1 5 10.5 M5 13.5 L5 10.5 L8 10.5" },
    { d: "M3 3 L9 3 L15 9 L9 15 L3 9 Z M6.5 6.5 L6.5 6.5" },
    { d: "M4 8 A4 4 0 1 1 12 8 A4 4 0 1 1 4 8 M11 11 L15 15" },
    { d: "M5 3 L13 3 L13 15 L9 12 L5 15 Z" },
    { d: "M9 3 L11 7 L15 7.5 L12 10.5 L13 15 L9 12.5 L5 15 L6 10.5 L3 7.5 L7 7 Z" },
    { d: "M6 7 A3 3 0 1 1 10 9.5 L9 11 M9 14 L9 14.01" },
    { d: "M3 4 L15 4 L15 14 L3 14 Z M3 12 L7 8 L10 11 L13 7 L15 9 M11 7 L11 7.01" },
    { d: "M5 3 L11 3 L13 5 L13 15 L5 15 Z M11 3 L11 5 L13 5" },
  ];

  const demoStats = [
    { jp: "課題", en: "issue", c: "#C9583C", n: 4 },
    { jp: "決定", en: "decision", c: "#6B8CAE", n: 6 },
    { jp: "情報", en: "info", c: "#8FA896", n: 3 },
  ];

  const demoTabs = ja
    ? ["リピート率分析…", "LTV改善計画…", "販売戦略レビュー"]
    : ["Repeat rate…", "LTV improve…", "Sales strategy"];

  return (
    <section className="section container">
      <div style={{ textAlign: "center", marginBottom: 48 }}>
        <div className="eyebrow eyebrow-accent">LIVE / {ja ? "実演" : "DEMO"}</div>
        <h2 className="title-xl" style={{ marginTop: 16 }}>
          {ja ? <>思考が、<em style={{ fontStyle: "italic" }}>広がる</em>。</> : <>Watch it <em style={{ fontStyle: "italic" }}>unfold</em>.</>}
        </h2>
      </div>
      <div ref={rootRef} style={{
        width: "100%", maxWidth: 1400, margin: "0 auto", height: 820,
        borderRadius: 14, overflow: "hidden",
        background: "var(--bg-raised)",
        boxShadow: "0 1px 0 rgba(255,255,255,0.6) inset, 0 0 0 1px var(--ink-10), 0 28px 56px -16px rgba(26,24,21,0.28), 0 10px 22px -12px rgba(26,24,21,0.20)",
        fontFamily: "var(--font-sans)",
        display: "flex", flexDirection: "column",
      }}>
        {/* Titlebar */}
        <div style={{
          height: 36, display: "flex", alignItems: "center",
          padding: "0 14px", gap: 14, flex: "0 0 auto",
          background: "linear-gradient(180deg, rgba(26,24,21,0.05), rgba(26,24,21,0.01))",
          borderBottom: "1px solid var(--ink-10)",
        }}>
          <div style={{ display: "flex", gap: 6 }}>
            {["#FF5F57","#FEBC2E","#28C840"].map((c,i) => (
              <span key={i} style={{ width: 10, height: 10, borderRadius: "50%", background: c }}/>
            ))}
          </div>
          <span style={{ flex: 1, textAlign: "center", fontSize: 11, color: "var(--ink-40)", fontWeight: 500 }}>Chrome — chatgpt.com / LLMindMap</span>
          <span style={{ width: 46 }}/>
        </div>

        {/* Content split */}
        <div style={{ flex: 1, display: "flex", overflow: "hidden" }}>
          {/* ChatGPT pane */}
          <div style={{ flex: "0 0 40%", minWidth: 0, display: "flex", flexDirection: "column", borderRight: "1px solid var(--ink-10)" }}>
            <div style={{
              padding: "8px 16px", display: "flex", alignItems: "center", gap: 10,
              borderBottom: "1px solid var(--ink-10)", flex: "0 0 auto",
            }}>
              <span className="mono-hi" style={{ fontSize: 9.5, letterSpacing: "0.18em" }}>CHATGPT</span>
              <span style={{ width: 1, height: 10, background: "var(--ink-10)" }}/>
              <span style={{ fontSize: 11, color: "var(--ink)", fontWeight: 500 }}>{ja ? "販売戦略レビュー" : "Sales strategy"}</span>
            </div>
            <div ref={scrollRef} style={{
              flex: 1, padding: "16px 18px", overflowY: "auto",
              display: "flex", flexDirection: "column", gap: 14,
            }}>
              {allMsgs.map((m, i) => (
                <div key={i} style={{
                  display: "flex", gap: 10,
                  justifyContent: m.who === "user" ? "flex-end" : "flex-start",
                  alignItems: "flex-start",
                }}>
                  {m.who === "ai" && (
                    <div style={{
                      width: 22, height: 22, borderRadius: "50%",
                      background: "var(--ink)", color: "var(--bg-raised)",
                      display: "grid", placeItems: "center",
                      fontSize: 9, fontWeight: 700, flexShrink: 0,
                    }}>AI</div>
                  )}
                  <div style={{
                    maxWidth: "75%", padding: "10px 14px", borderRadius: 12,
                    background: m.who === "user" ? "var(--ink-10)" : "transparent",
                    border: m.who === "ai" ? "1px solid var(--ink-10)" : "none",
                    fontSize: 12.5, lineHeight: 1.55, color: "var(--ink)",
                  }}>
                    {m.t}
                    {i === allMsgs.length - 1 && m.who === "ai" && phase === "responding" && (
                      <span style={{ display: "inline-block", width: 5, height: 14, background: "var(--ink)", marginLeft: 2, verticalAlign: -2, animation: "blink 1.1s steps(2) infinite" }}/>
                    )}
                  </div>
                  {m.who === "user" && (
                    <div style={{
                      width: 22, height: 22, borderRadius: "50%",
                      background: "var(--accent)", color: "#fff",
                      display: "grid", placeItems: "center",
                      fontSize: 7, fontWeight: 700, flexShrink: 0,
                    }}>YOU</div>
                  )}
                </div>
              ))}
              {phase === "typing" && (
                <div style={{ display: "flex", gap: 10, justifyContent: "flex-end", alignItems: "flex-start" }}>
                  <div style={{
                    maxWidth: "75%", padding: "10px 14px", borderRadius: 12,
                    background: "var(--ink-10)",
                    fontSize: 12.5, lineHeight: 1.55, color: "var(--ink)",
                  }}>
                    {currentRound.prompt.slice(0, typedChars)}
                    <span style={{ display: "inline-block", width: 5, height: 14, background: "var(--accent)", marginLeft: 1, animation: "blink 1.1s steps(2) infinite" }}/>
                  </div>
                  <div style={{
                    width: 22, height: 22, borderRadius: "50%",
                    background: "var(--accent)", color: "#fff",
                    display: "grid", placeItems: "center",
                    fontSize: 7, fontWeight: 700, flexShrink: 0,
                  }}>YOU</div>
                </div>
              )}
            </div>
            <div style={{
              padding: "8px 12px 10px", borderTop: "1px solid var(--ink-10)",
              display: "flex", alignItems: "center", gap: 8, flex: "0 0 auto",
            }}>
              <div style={{
                flex: 1, height: 30, borderRadius: 8, background: "var(--bg)",
                boxShadow: "inset 0 0 0 1px var(--ink-10)",
                display: "flex", alignItems: "center", padding: "0 10px",
                font: '400 12px/1 var(--font-sans)', color: "var(--ink-40)",
              }}>
                {ja ? "メッセージを送信…" : "Send a message…"}
              </div>
              <div style={{
                width: 30, height: 30, borderRadius: 8,
                background: "var(--accent)", color: "#fff",
                display: "flex", alignItems: "center", justifyContent: "center", opacity: 0.5,
              }}>
                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round">
                  <path d="M12 19V5M5 12l7-7 7 7"/>
                </svg>
              </div>
            </div>
          </div>

          {/* LLMindMap extension panel — product-accurate chrome */}
          <div style={{ flex: 1, minWidth: 0, background: "#F5F0E8", display: "grid", gridTemplateColumns: "52px 1fr" }}>
            {/* Rail */}
            <div style={{
              background: "#F5F0E8", padding: "10px 6px",
              display: "flex", flexDirection: "column", alignItems: "center", gap: 6,
              borderRight: "1px solid rgba(59,53,45,0.06)",
            }}>
              {demoRailIcons.map((ic, i) => {
                const railColors = ["#6BBF8A","#7BAFD4","#D4908A","#D4B85C","#D4C24E","#D4956A","#5CBBAA","#5CBBAA","#A8A29E","#D4B85C"];
                const iconColor = railColors[i] || "#8C8070";
                return (
                <div key={i} style={{
                  width: 36, height: 36, borderRadius: 10,
                  background: "#F5F0E8",
                  display: "grid", placeItems: "center",
                  boxShadow: i === 0
                    ? "inset 2px 2px 4px #C8BFAE, inset -2px -2px 4px #FFFDF8"
                    : "3px 3px 6px #C8BFAE, -3px -3px 6px #FFFDF8",
                }}>
                  {ic.kind === "mark" ? (
                    <svg width="16" height="16" viewBox="0 0 22 22" fill="none">
                      <circle cx="11" cy="11" r="2" fill="#6BBF8A"/>
                      <circle cx="4" cy="4" r="1.7" fill="#6BBF8A"/>
                      <circle cx="18" cy="4" r="1.7" fill="#6BBF8A"/>
                      <circle cx="4" cy="18" r="1.7" fill="#6BBF8A"/>
                      <circle cx="18" cy="18" r="1.7" fill="#6BBF8A"/>
                      <path d="M11 11 L4 4 M11 11 L18 4 M11 11 L4 18 M11 11 L18 18"
                        stroke="#6BBF8A" strokeWidth="1.4" strokeLinecap="round"/>
                    </svg>
                  ) : (
                    <svg width="14" height="14" viewBox="0 0 18 18" fill="none"
                      stroke={iconColor} strokeWidth="1.35" strokeLinecap="round" strokeLinejoin="round">
                      <path d={ic.d}/>
                    </svg>
                  )}
                </div>
                );
              })}
              <div style={{ flex: 1 }}/>
              <div style={{
                width: 34, height: 34, borderRadius: 10,
                background: "#F5F0E8",
                display: "grid", placeItems: "center",
                boxShadow: "3px 3px 6px #C8BFAE, -3px -3px 6px #FFFDF8",
                fontFamily: "var(--font-mono)", fontSize: 10, fontWeight: 600,
                color: "#8C8070", letterSpacing: "0.08em",
              }}>JA</div>
            </div>

            {/* Main column */}
            <div style={{ display: "flex", flexDirection: "column", minWidth: 0, overflow: "hidden" }}>
              {/* Header with logo + LIVE badge */}
              <div style={{
                display: "flex", alignItems: "center", justifyContent: "space-between",
                padding: "10px 14px 8px",
              }}>
                <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                  <svg width="22" height="22" viewBox="0 0 22 22" fill="none">
                    <circle cx="11" cy="11" r="2" fill="#C9583C"/>
                    <circle cx="4" cy="4" r="1.7" fill="#C9583C"/>
                    <circle cx="18" cy="4" r="1.7" fill="#C9583C"/>
                    <circle cx="4" cy="18" r="1.7" fill="#C9583C"/>
                    <circle cx="18" cy="18" r="1.7" fill="#C9583C"/>
                    <path d="M11 11 L4 4 M11 11 L18 4 M11 11 L4 18 M11 11 L18 18"
                      stroke="#C9583C" strokeWidth="1.4" strokeLinecap="round"/>
                  </svg>
                  <div style={{ lineHeight: 1.1 }}>
                    <div style={{ fontFamily: "'IBM Plex Sans', var(--font-sans)", fontWeight: 700, fontSize: 14 }}>
                      <span style={{ color: "#3B352D" }}>LL</span>
                      <span style={{ color: "#C9583C" }}>Mind</span>
                      <span style={{ color: "#3B352D" }}>Map</span>
                    </div>
                    <div style={{
                      fontFamily: "var(--font-mono)", fontSize: 8.5,
                      color: "#8C8070", letterSpacing: "0.01em", marginTop: 2,
                    }}>Trace, edit, and surpass any LLM chat</div>
                  </div>
                </div>
                <span style={{
                  display: "inline-flex", alignItems: "center", gap: 5,
                  fontFamily: "'IBM Plex Sans', var(--font-sans)", fontSize: 9,
                  letterSpacing: "0.14em", color: "#34D399", fontWeight: 700,
                }}>
                  <span style={{ width: 6, height: 6, borderRadius: "50%", background: "#34D399", animation: "livePulse 1.5s ease-in-out infinite" }}/>
                  LIVE
                </span>
              </div>

              {/* History label */}
              <div style={{
                display: "flex", alignItems: "center", justifyContent: "space-between",
                padding: "4px 14px 6px",
                borderBottom: "1px solid rgba(59,53,45,0.08)",
              }}>
                <span style={{ fontSize: 11, color: "#8C8070" }}>{ja ? "履歴 (3/3)" : "History (3/3)"}</span>
                <svg width="8" height="8" viewBox="0 0 10 10" fill="none">
                  <path d="M3 1.5 L6.5 5 L3 8.5" stroke="#8C8070" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round"/>
                </svg>
              </div>

              {/* Banner */}
              <div style={{ padding: "8px 14px 4px" }}>
                <div style={{
                  padding: "7px 10px", borderRadius: 8,
                  background: "#F5F0E8",
                  boxShadow: "inset 2px 2px 4px #C8BFAE, inset -2px -2px 4px #FFFDF8",
                  display: "flex", alignItems: "center", gap: 6,
                  fontSize: 10.5, color: "#4B8263",
                }}>
                  <span style={{
                    width: 5, height: 5, borderRadius: "50%",
                    background: "#4B8263", boxShadow: "0 0 0 2px rgba(75,130,99,0.2)",
                  }}/>
                  {ja ? "会話データが更新されました" : "Conversation synced"}
                </div>
              </div>

              {/* Category chips */}
              <div style={{ display: "flex", flexWrap: "wrap", gap: 6, padding: "6px 14px 8px" }}>
                {demoStats.map(s => (
                  <span key={s.en} style={{
                    display: "inline-flex", alignItems: "center", gap: 5,
                    height: 22, padding: "0 10px", borderRadius: 999,
                    background: "#F5F0E8", fontSize: 10.5, color: "#3B352D", fontWeight: 500,
                    boxShadow: "-2px -2px 4px #FFFDF8, 2px 2px 5px #C8BFAE",
                  }}>
                    <span style={{ width: 6, height: 6, borderRadius: "50%", background: s.c }}/>
                    {ja ? s.jp : s.en}
                    <span style={{ fontFamily: "var(--font-mono)", fontSize: 9.5, color: "#8C8070", marginLeft: 1 }}>{s.n}</span>
                  </span>
                ))}
              </div>

              {/* Tabs */}
              <div style={{ display: "flex", gap: 6, padding: "6px 14px 8px", overflow: "hidden" }}>
                {demoTabs.map((t, i) => {
                  const isActive = i === demoTabs.length - 1;
                  return (
                    <div key={i} style={{
                      flex: 1, minWidth: 0,
                      display: "flex", alignItems: "center", justifyContent: "space-between", gap: 4,
                      padding: "5px 8px", borderRadius: 6,
                      background: isActive ? "#F5F0E8" : "transparent",
                      boxShadow: isActive ? "inset 2px 2px 3px #C8BFAE, inset -2px -2px 3px #FFFDF8" : "none",
                      fontSize: 10, color: isActive ? "#3B352D" : "#8C8070",
                      fontWeight: isActive ? 600 : 400,
                      whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
                    }}>
                      <span style={{ overflow: "hidden", textOverflow: "ellipsis" }}>{t}</span>
                      {isActive && <span style={{ color: "#8C8070", fontSize: 11, flexShrink: 0 }}>×</span>}
                    </div>
                  );
                })}
              </div>

              {/* Mindmap area — progressive reveal matching product animation */}
              <div key={loopKey} style={{ flex: 1, position: "relative", overflow: "hidden" }}>
                <AnimatedMindmap
                  treeStep={treeStep}
                  overlays={grownBranches.map(ri => newBranches[ri])}
                  showSonar={phase === "growing"}
                  lang={lang}
                />
              </div>
            </div>
          </div>
        </div>
      </div>

      {/* Round indicators */}
      <div style={{ display: "flex", justifyContent: "center", gap: 8, marginTop: 20 }}>
        {rounds.map((_, i) => (
          <span key={i} style={{
            width: i <= round && phase !== "idle" ? 20 : 8, height: 4, borderRadius: 2,
            background: i <= round && phase !== "idle" ? "var(--accent)" : "var(--ink-20)",
            transition: "width 280ms ease, background 280ms ease",
          }}/>
        ))}
      </div>

      <style>{`
        @keyframes blink { 50% { opacity: 0; } }
        @keyframes livePulse { 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:0.7;transform:scale(0.94)} }
        @keyframes demoLiveSonar { 0%{r:5;opacity:0} 15%{opacity:0.55} 100%{r:100;opacity:0} }
        @keyframes demoNodeGlow { 0%{opacity:0;r:5} 30%{opacity:0.8;r:14} 100%{opacity:0;r:22} }
      `}</style>
    </section>
  );
};

/* CTA band */
const Pricing = ({ lang }) => {
  const ja = lang === "ja";
  const free = [
    ja ? "マインドマップ生成 20回/月" : "20 mindmaps / month",
    ja ? "7種自動カテゴリ分類" : "7-way auto-categorize",
    ja ? "スターノード" : "Starred nodes",
    ja ? "PNG・PDF書き出し" : "PNG & PDF export",
    ja ? "ローカル履歴（3件）" : "Local history (3 maps)",
    ja ? "横断検索" : "Cross-map search",
    ja ? "日本語 / 英語 UI" : "JA / EN interface",
  ];
  const pro = [
    ja ? "マインドマップ生成 無制限" : "Unlimited mindmaps",
    ja ? "構造的ギャップ検出" : "Structural gap detection",
    ja ? "Markdown・SVG書き出し" : "Markdown & SVG export",
    ja ? "履歴 無制限" : "Unlimited history",
    ja ? "ライブ成長" : "Live grow",
    ja ? "思考プロファイル" : "Thinking profile",
  ];
  const check = (
    <svg width="14" height="14" viewBox="0 0 16 16" fill="none" style={{ flexShrink: 0, marginTop: 2 }}>
      <path d="M3 8.5L6.5 12L13 4" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  );
  const cardBase = {
    borderRadius: 20, padding: "36px 32px",
    display: "flex", flexDirection: "column",
  };
  return (
    <section id="pricing" className="section" style={{ background: "var(--bg-deep)" }}>
      <div className="container">
        <div style={{ textAlign: "center", marginBottom: 56 }}>
          <div className="eyebrow eyebrow-accent">PRICING / {ja ? "料金" : "PLANS"}</div>
          <h2 className="title-xl" style={{ marginTop: 16 }}>
            {ja ? <>無料で整理。<br/>Proで、<em style={{ fontStyle: "italic" }}>思考</em>する。</> : <>Free organizes.<br/>Pro <em style={{ fontStyle: "italic" }}>thinks</em> with you.</>}
          </h2>
        </div>

        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 28, maxWidth: 920, margin: "0 auto", alignItems: "stretch" }}>
          {/* Free */}
          <div style={{
            ...cardBase, padding: "44px 38px",
            background: "var(--bg-raised)",
            boxShadow: "0 1px 0 rgba(255,255,255,0.6) inset, 0 0 0 1px var(--ink-10)",
          }}>
            <div className="mono-hi" style={{ marginBottom: 12, fontSize: 13 }}>FREE</div>
            <div style={{ fontFamily: "var(--font-serif)", fontSize: 64, fontWeight: 400, letterSpacing: "-0.03em", lineHeight: 1 }}>
              {ja ? "¥0" : "$0"}
            </div>
            <div style={{ marginTop: 8, fontSize: 15, color: "var(--ink-40)" }}>{ja ? "ずっと無料" : "Free forever"}</div>
            <div style={{ margin: "28px 0", height: 1, background: "var(--rule)" }}/>
            <div style={{ display: "flex", flexDirection: "column", gap: 14, flex: 1 }}>
              {free.map((f, i) => (
                <div key={i} style={{ display: "flex", gap: 10, fontSize: 15, color: "var(--ink-60)", lineHeight: 1.45 }}>
                  <span style={{ color: "var(--ink-40)" }}>{check}</span>
                  {f}
                </div>
              ))}
            </div>
            <a className="btn btn-ghost" href="https://chromewebstore.google.com/detail/llmindmap/jlaffgbaoefnmgfkagopepnljgpcfepl" target="_blank" rel="noopener" style={{ marginTop: 32, width: "100%", justifyContent: "center", height: 50, fontSize: 14.5 }}>
              {ja ? "無料で始める" : "Get started free"}
            </a>
          </div>

          {/* Pro */}
          <div style={{
            ...cardBase, padding: "44px 38px",
            background: "var(--ink)",
            color: "var(--bg)",
            boxShadow: "0 32px 64px -16px rgba(26,24,21,0.45)",
          }}>
            <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 12 }}>
              <span className="mono-hi" style={{ color: "rgba(255,255,255,0.5)", fontSize: 13 }}>PRO</span>
            </div>
            <div style={{ display: "flex", alignItems: "baseline", gap: 6 }}>
              <span style={{ fontFamily: "var(--font-serif)", fontSize: 64, fontWeight: 400, letterSpacing: "-0.03em", lineHeight: 1 }}>
                {ja ? "¥1,500" : "$15"}
              </span>
              <span style={{ fontSize: 18, color: "rgba(255,255,255,0.45)", fontWeight: 400 }}>{ja ? "/月" : "/​mo"}</span>
            </div>
            <div style={{ marginTop: 8, fontSize: 15, color: "rgba(255,255,255,0.4)" }}>
              {ja ? "年払い ¥15,000/年（2ヶ月分お得）" : "$150/year — save 2 months"}
            </div>
            <div style={{ margin: "28px 0", height: 1, background: "rgba(255,255,255,0.12)" }}/>
            <div style={{ display: "flex", flexDirection: "column", gap: 14, flex: 1 }}>
              {pro.map((p, i) => (
                <div key={i} style={{ display: "flex", gap: 10, fontSize: 15, color: "rgba(255,255,255,0.7)", lineHeight: 1.45 }}>
                  <span style={{ color: "var(--accent)" }}>{check}</span>
                  {p}
                </div>
              ))}
            </div>
            <a className="btn btn-accent" href="https://chromewebstore.google.com/detail/llmindmap/jlaffgbaoefnmgfkagopepnljgpcfepl" target="_blank" rel="noopener" style={{ marginTop: 32, width: "100%", justifyContent: "center", height: 50, fontSize: 14.5 }}>
              {ja ? "Proを始める" : "Start Pro"}
            </a>
          </div>
        </div>
      </div>
    </section>
  );
};

const BigCTA = ({ lang }) => (
  <section className="section container">
    <div style={{
      padding: "80px 48px", background: "var(--ink)", color: "var(--bg)",
      borderRadius: 28, display: "grid", gridTemplateColumns: "2fr 1fr", gap: 48, alignItems: "center",
    }}>
      <div>
        <div className="eyebrow" style={{ color: "rgba(255,255,255,0.5)" }}>INSTALL</div>
        <h2 className="title-xl" style={{ marginTop: 12, color: "var(--bg)" }}>
          {lang === "ja" ? <>60秒で、あなたの<br/>思考地図が始まる。</> : <>Sixty seconds<br/>to your first map.</>}
        </h2>
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 14, alignItems: "flex-start" }}>
        <a className="btn btn-accent" href="https://chromewebstore.google.com/detail/llmindmap/jlaffgbaoefnmgfkagopepnljgpcfepl" target="_blank" rel="noopener" style={{ width: "100%", justifyContent: "center" }}>
          {lang === "ja" ? "思考を、地図にする。" : "Map your thinking"}
        </a>
        <a className="btn btn-ghost" href="#pricing" style={{ width: "100%", justifyContent: "center", color: "var(--bg)", boxShadow: "inset 0 0 0 1px rgba(255,255,255,0.3)" }}>
          {lang === "ja" ? "料金を見る" : "See pricing"}
        </a>
      </div>
    </div>
  </section>
);

/* Coming Soon — roadmap tease for unreleased features */
const ComingSoon = ({ lang }) => {
  const items = lang === "ja"
    ? [
      {
        mono: "統合", t: "グラフ統合",
        d: "複数の会話を1枚の地図に。重複は自動でマージされる。",
        icon: "M18 21V8a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v13 M6 15l6-6 6 6",
      },
    ]
    : [
      {
        mono: "MERGE", t: "Graph merging",
        d: "Multiple conversations fold into a single atlas. Duplicates auto-merge.",
        icon: "M18 21V8a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v13 M6 15l6-6 6 6",
      },
    ];

  return (
    <section style={{ padding: "80px 0" }}>
      <div className="container">
        <div style={{ marginBottom: 40, maxWidth: 560 }}>
          <div className="eyebrow eyebrow-accent">COMING SOON / {lang === "ja" ? "開発中" : "ROADMAP"}</div>
          <h2 className="title" style={{ marginTop: 12 }}>
            {lang === "ja" ? "次に届くもの。" : "What\u2019s next."}
          </h2>
        </div>
        <div style={{ display: "flex", flexWrap: "wrap", gap: 24 }}>
          {items.map((item, i) => (
            <div key={i} style={{
              flex: "0 0 340px", padding: "28px 24px",
              background: "var(--bg-raised)",
              border: "1px dashed var(--ink-20)",
              borderRadius: 16, display: "flex", flexDirection: "column", gap: 12,
            }}>
              <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                <div style={{
                  width: 36, height: 36, borderRadius: 10,
                  background: "var(--ink-05)", display: "flex", alignItems: "center", justifyContent: "center",
                }}>
                  <svg width="18" height="18" viewBox="0 0 24 24" fill="none"
                    stroke="var(--ink-40)" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
                    <path d={item.icon}/>
                  </svg>
                </div>
                <span style={{
                  fontFamily: "var(--font-mono)", fontSize: 10, fontWeight: 700,
                  letterSpacing: "0.14em", color: "var(--ink-40)",
                }}>{item.mono}</span>
              </div>
              <div>
                <div style={{
                  fontSize: 16, fontWeight: 600, color: "var(--ink)",
                  fontFamily: "var(--font-sans)", marginBottom: 4,
                }}>{item.t}</div>
                <p style={{
                  fontSize: 13.5, lineHeight: 1.6, color: "var(--ink-60)",
                  fontFamily: "var(--font-sans)", margin: 0,
                }}>{item.d}</p>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
};

Object.assign(window, { HowItWorks, FeaturesGrid, ThinkingProfile, MindTracing, CategoryExplainer, LiveDemo, Pricing, BigCTA, ComingSoon, ExtensionSnapshot, PanelFrame });
