// shared.jsx — atoms, network-graph motif, shared section content

const VL_COPY = {
  brand: 'VerdiaLink',
  nav: [
    { id: 'concept', label: 'FDEとは' },
    { id: 'services', label: 'Services' },
    { id: 'why', label: 'Why FDE' },
    { id: 'approach', label: 'Approach' },
  ],
  hero: {
    en_kicker: 'FORWARD DEPLOYED ENGINEERING',
    cta_primary: 'お問い合わせ',
  },
  concept: {
    eyebrow: 'CONCEPT',
    title: 'すべての支援は、',
    title2: '「伴走型エンジニアリング(FDE)」として提供します',
    body_a: '私たちは単発の開発やツール導入ではなく、現場に深く入り込み、\n業務理解から設計・実装・改善までを一体で行います。',
    body_b: 'すべてのサービスは個別提供ではなく、FDEとして一気通貫で支援します。',
  },
  services: {
    eyebrow: 'SERVICES',
    title: 'FDEという一つの傘の下にある、\n4つの実装形態',
    items: [
      {
        id: 's1',
        num: '01',
        en: 'RAG Systems',
        title: '源内RAG構築',
        line: '現場業務に最適化された検索・知識基盤を構築',
        position: '業務理解から設計まで伴走',
        detail: '業務文書・ナレッジ・問い合わせログ等を構造化し、現場が実際に使う検索・回答基盤を構築。プロンプト設計、評価設計、運用フローまで一体で内製化を支援します。',
        tags: ['業務理解', 'スキーマ設計', '評価ループ', '運用定着'],
      },
      {
        id: 's2',
        num: '02',
        en: 'Custom SaaS',
        title: 'カスタムSaaS開発',
        line: '業務にフィットするプロダクトをゼロから設計・開発',
        position: '現場に入り込んで継続改善',
        detail: '既存SaaSでは噛み合わない業務に対し、現場フローを起点にプロダクトを設計・実装。リリース後も運用に同席し、機能追加・改善を継続します。',
        tags: ['ドメイン設計', 'UX設計', '実装', '継続改善'],
      },
      {
        id: 's3',
        num: '03',
        en: 'AI Adoption',
        title: 'AI導入支援',
        line: 'ツール導入ではなく業務プロセスから再設計',
        position: '運用定着まで伴走',
        detail: 'AIを「導入する」のではなく、業務プロセスごと再設計。意思決定ポイントの再定義、責任分界、評価指標の整備を伴走しながら行います。',
        tags: ['プロセス再設計', '責任分界', '評価指標', '内製化'],
      },
      {
        id: 's4',
        num: '04',
        en: 'Decision Infra',
        title: '意思決定支援システム構築',
        line: 'データ・判断・実行をつなぐ仕組みを構築',
        position: '継続的な改善サイクルを内製化',
        detail: '散在するデータと意思決定を1つの実行基盤に統合。判断ロジック、自動化、人による介在ポイントを設計し、改善サイクルが回り続ける状態をつくります。',
        tags: ['データ統合', '判断モデル', 'オーケストレーション', '可観測性'],
      },
    ],
  },
  why: {
    eyebrow: 'WHY FDE',
    title: 'なぜ、伴走型なのか',
    body_a: 'AI導入が失敗する理由は、ツールだけが導入され、業務に定着しないことです。',
    body_b: '私たちは外部から提案するのではなく、現場に入り込み、業務そのものを理解しながら\nシステムを設計・実装します。',
    body_c: 'これにより「使われる仕組み」を実現します。',
    pull: 'グローバルでは、業務とシステムを一体で設計するアプローチが\n主流になりつつあります。\nVerdiaLinkはそれを日本企業向けに最適化し\n実行可能な形で提供します。',
  },
  approach: {
    eyebrow: 'APPROACH',
    title: '4つのフェーズで、現場と一体になる',
    steps: [
      { n: '01', t: '業務理解', d: '現場に入り、業務フローと意思決定プロセスを構造化' },
      { n: '02', t: '設計', d: '業務に最適化したアーキテクチャ・データモデルを定義' },
      { n: '03', t: '実装', d: '必要な技術スタックを選定し、プロダクトを構築' },
      { n: '04', t: '運用・改善', d: '使われる仕組みとして継続的に磨き込む' },
    ],
  },
  closing: {
    line_a: '業務に深く入り込む支援を、',
    line_b: '本気で求めている方へ。',
    cta: '相談する',
  },
  footer: {
    items: ['Contact', 'Privacy', '© 2026 VerdiaLink'],
  },
};

// ── Network motif ───────────────────────────────────────────
// Static seedable layout — same render every paint.
function NetworkGraph({ width = 680, height = 360, density = 22, stroke = 'currentColor', dotFill = 'currentColor', opacity = 0.45, animated = false, seed = 7 }) {
  // Deterministic PRNG
  const rng = React.useMemo(() => {
    let s = seed;
    return () => { s = (s * 9301 + 49297) % 233280; return s / 233280; };
  }, [seed]);

  const nodes = React.useMemo(() => {
    const r = (() => { let s = seed; return () => { s = (s * 9301 + 49297) % 233280; return s / 233280; }; })();
    const ns = [];
    for (let i = 0; i < density; i++) {
      ns.push({ x: 30 + r() * (width - 60), y: 30 + r() * (height - 60), s: 1.5 + r() * 2.5 });
    }
    return ns;
  }, [width, height, density, seed]);

  const edges = React.useMemo(() => {
    const es = [];
    for (let i = 0; i < nodes.length; i++) {
      // Connect to 2 nearest
      const dists = nodes.map((n, j) => ({ j, d: Math.hypot(n.x - nodes[i].x, n.y - nodes[i].y) }))
        .filter(d => d.j !== i).sort((a, b) => a.d - b.d);
      for (let k = 0; k < 2; k++) {
        if (dists[k] && dists[k].j > i) es.push([i, dists[k].j]);
      }
    }
    return es;
  }, [nodes]);

  return (
    <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} style={{ display: 'block', overflow: 'visible' }}>
      <g style={{ opacity }}>
        {edges.map(([a, b], i) => (
          <line key={i} x1={nodes[a].x} y1={nodes[a].y} x2={nodes[b].x} y2={nodes[b].y}
                stroke={stroke} strokeWidth={0.6} />
        ))}
        {nodes.map((n, i) => (
          <circle key={i} cx={n.x} cy={n.y} r={n.s} fill={dotFill} />
        ))}
      </g>
      {animated && (
        <g>
          {edges.slice(0, 6).map(([a, b], i) => (
            <circle key={i} r="1.6" fill={stroke}>
              <animateMotion dur={`${4 + i * 0.7}s`} repeatCount="indefinite"
                path={`M${nodes[a].x},${nodes[a].y} L${nodes[b].x},${nodes[b].y}`} />
            </circle>
          ))}
        </g>
      )}
    </svg>
  );
}

// ── Hairline ────────────────────────────────────────────────
function Rule({ vertical = false, color = 'var(--rule)', length = '100%', opacity = 1 }) {
  return (
    <div style={{
      [vertical ? 'width' : 'height']: 1,
      [vertical ? 'height' : 'width']: length,
      background: color,
      opacity,
      flexShrink: 0,
    }} />
  );
}

// ── EnKicker (English uppercase eyebrow) ────────────────────
function EnKicker({ children, color = 'var(--ink-3)', bullet = true, style }) {
  return (
    <div style={{
      fontFamily: 'var(--sans)',
      fontSize: 11,
      fontWeight: 500,
      letterSpacing: '0.18em',
      textTransform: 'uppercase',
      color,
      display: 'flex', alignItems: 'center', gap: 8,
      ...style,
    }}>
      {bullet && <span style={{ width: 4, height: 4, borderRadius: 2, background: 'currentColor', display: 'inline-block' }} />}
      {children}
    </div>
  );
}

// ── Button ──────────────────────────────────────────────────
function VlButton({ children, primary, ghost, onClick, size = 'md', arrow = true, style, type, disabled }) {
  const [hover, setHover] = React.useState(false);
  const sz = size === 'lg' ? { h: 52, pad: '0 24px', font: 14 } : size === 'sm' ? { h: 36, pad: '0 14px', font: 12 } : { h: 44, pad: '0 20px', font: 13 };
  let bg = 'transparent', col = 'var(--ink)', bd = '1px solid var(--ink)';
  if (primary) { bg = hover ? '#15315F' : 'var(--ink)'; col = '#fff'; bd = '1px solid var(--ink)'; }
  else if (ghost) { bg = 'transparent'; col = 'var(--ink)'; bd = 'none'; }
  else { bg = hover ? 'rgba(10,31,68,0.04)' : 'transparent'; col = 'var(--ink)'; bd = '1px solid var(--ink)'; }
  return (
    <button onClick={onClick} type={type} disabled={disabled}
      onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      style={{
        height: sz.h, padding: sz.pad, fontSize: sz.font, fontWeight: 500, fontFamily: 'var(--jp)',
        background: bg, color: col, border: bd, borderRadius: 0,
        cursor: disabled ? 'not-allowed' : 'pointer', opacity: disabled ? 0.55 : 1,
        display: 'inline-flex', alignItems: 'center', gap: 10, letterSpacing: '0.02em',
        transition: 'background .15s, transform .15s', whiteSpace: 'nowrap', ...style,
      }}>
      <span>{children}</span>
      {arrow && (
        <svg width="14" height="10" viewBox="0 0 14 10" fill="none" stroke="currentColor" strokeWidth="1.4" style={{ transition: 'transform .2s', transform: hover ? 'translateX(3px)' : 'none' }}>
          <path d="M1 5h12M9 1l4 4-4 4" strokeLinecap="square" />
        </svg>
      )}
    </button>
  );
}

// ── Logo wordmark ───────────────────────────────────────────
function Logo({ color = 'var(--ink)', size = 16 }) {
  return (
    <div style={{
      fontFamily: 'var(--sans)', fontWeight: 600, fontSize: size, letterSpacing: '-0.01em',
      color, display: 'flex', alignItems: 'center', gap: 8,
    }}>
      <svg width={size} height={size} viewBox="0 0 16 16" fill="none">
        <circle cx="3" cy="3" r="2" fill={color} />
        <circle cx="13" cy="3" r="1.5" stroke={color} strokeWidth="1" />
        <circle cx="13" cy="13" r="2" fill={color} />
        <circle cx="3" cy="13" r="1.5" stroke={color} strokeWidth="1" />
        <line x1="3" y1="3" x2="13" y2="13" stroke={color} strokeWidth="0.8" />
        <line x1="13" y1="3" x2="3" y2="13" stroke={color} strokeWidth="0.8" />
      </svg>
      <span>VerdiaLink</span>
    </div>
  );
}

// ── Reveal-on-scroll inside artboards ──────────────────────
function Reveal({ children, delay = 0, style, as: Tag = 'div' }) {
  const ref = React.useRef(null);
  const [show, setShow] = React.useState(false);
  React.useEffect(() => {
    if (!ref.current) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) { setShow(true); io.disconnect(); } });
    }, { root: ref.current.closest('[data-vl-scroll]') || null, threshold: 0.15 });
    io.observe(ref.current);
    return () => io.disconnect();
  }, []);
  return (
    <Tag ref={ref} style={{
      transform: show ? 'translateY(0)' : 'translateY(12px)',
      opacity: show ? 1 : 0,
      transition: `opacity .8s ${delay}ms, transform .8s ${delay}ms`,
      ...style,
    }}>{children}</Tag>
  );
}

Object.assign(window, { VL_COPY, NetworkGraph, Rule, EnKicker, VlButton, Logo, Reveal });
