// Scroll-driven vertical convergence:
//   sources (asymmetric) → exoteam mark → vertical pipeline (rank → draft → link) → briefs.

const ConvergeAnimation = () => {
  const wrapRef = React.useRef(null);
  const [progress, setProgress] = React.useState(0);
  const [isMobile, setIsMobile] = React.useState(
    typeof window !== 'undefined' && window.innerWidth < 760
  );

  React.useEffect(() => {
    const onScroll = () => {
      if (!wrapRef.current) return;
      const rect = wrapRef.current.getBoundingClientRect();
      const vh = window.innerHeight;
      const total = rect.height - vh;
      const scrolled = -rect.top;
      const p = Math.max(0, Math.min(1, scrolled / total));
      setProgress(p);
    };
    const onResize = () => {
      setIsMobile(window.innerWidth < 760);
      onScroll();
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onResize);
    return () => {
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onResize);
    };
  }, []);

  const clamp = (v, lo = 0, hi = 1) => Math.max(lo, Math.min(hi, v));
  const phase = (p, start, end) => clamp((p - start) / (end - start));

  const headerOp   = phase(progress, 0.00, 0.08);
  const sourcesOp  = phase(progress, 0.04, 0.18);
  const linesInP   = phase(progress, 0.14, 0.36);
  const dotsInP    = phase(progress, 0.20, 0.42);
  const markOp     = phase(progress, 0.30, 0.46);
  const pipeLineP  = phase(progress, 0.42, 0.74);     // 0..1, drives the vertical line draw + stage reveals
  const linesOutP  = phase(progress, 0.72, 0.86);
  const briefP     = phase(progress, 0.78, 0.96);

  // ─── Layout (separate desktop vs mobile so the SVG can use a portrait
  //     viewBox on phones and fill the viewport width instead of being
  //     letterboxed). All other animation logic is shared. ───
  const W = isMobile ? 480 : 1100;
  const stageH = isMobile ? 740 : 740;

  const SRC_ICON = isMobile ? 32 : 38;
  const sources = isMobile ? [
    { id: 'gmail',  x: 100, y: 40,  icon: <GmailLogo size={SRC_ICON} /> },
    { id: 'drive',  x: 380, y: 50,  icon: <DriveLogo size={SRC_ICON} /> },
    { id: 'slack',  x: 60,  y: 140, icon: <SlackLogo size={SRC_ICON} /> },
    { id: 'sheets', x: 420, y: 150, icon: <SheetsLogo size={SRC_ICON} /> },
    { id: 'cal',    x: 170, y: 240, icon: <CalendarLogo size={SRC_ICON} /> },
    { id: 'docs',   x: 310, y: 250, icon: <DocsLogo size={SRC_ICON} /> },
  ] : [
    { id: 'gmail',  x: 320, y: 40,  icon: <GmailLogo size={SRC_ICON} /> },
    { id: 'slack',  x: 400, y: 170, icon: <SlackLogo size={SRC_ICON} /> },
    { id: 'cal',    x: 500, y: 20,  icon: <CalendarLogo size={SRC_ICON} /> },
    { id: 'docs',   x: 600, y: 180, icon: <DocsLogo size={SRC_ICON} /> },
    { id: 'sheets', x: 700, y: 30,  icon: <SheetsLogo size={SRC_ICON} /> },
    { id: 'drive',  x: 780, y: 160, icon: <DriveLogo size={SRC_ICON} /> },
  ];

  // Mark / wordmark — sized differently on mobile
  const markX = W / 2;
  const markY = isMobile ? 320 : 240;
  const markW = isMobile ? 160 : 220;
  const markH = isMobile ? 44 : 56;
  const markImgX = isMobile ? -68 : -90;
  const markImgY = isMobile ? -15 : -19;
  const markImgSize = isMobile ? 30 : 38;
  const markTextX = isMobile ? -30 : -44;
  const markTextY = isMobile ? 8 : 10;
  const markTextSize = isMobile ? 22 : 30;

  // Vertical pipeline stages (rank → draft → link)
  const pipeX = markX;
  const pipeTop = markY + markH / 2 + 10;
  const pipeBottom = isMobile ? 510 : 490;
  const stages = isMobile ? [
    { id: 'rank',  y: 380, label: 'Rank',  sub: 'by urgency' },
    { id: 'draft', y: 430, label: 'Draft', sub: 'in your voice' },
    { id: 'link',  y: 480, label: 'Link',  sub: 'cited docs' },
  ] : [
    { id: 'rank',  y: 305, label: 'Rank',  sub: 'by urgency & context' },
    { id: 'draft', y: 380, label: 'Draft', sub: 'in your voice' },
    { id: 'link',  y: 455, label: 'Link',  sub: 'cited docs & threads' },
  ];

  // Brief tiles
  const briefY = isMobile ? 540 : 525;
  const briefW = isMobile ? 140 : 180;
  const briefH = isMobile ? 80  : 95;
  const briefs = isMobile ? [
    { id: 'b1', x: 15,  y: 0,  tag: 'Reply',  tagColor: '#5b8def', title: 'Sarah Chen\nQ3 update',  meta: '2 docs · drafted' },
    { id: 'b2', x: 170, y: 0,  tag: 'Sign',   tagColor: '#e07ab0', title: 'SAFE\nMaven Ventures',   meta: '$250k · clean' },
    { id: 'b3', x: 325, y: 0,  tag: 'Decide', tagColor: '#e8995b', title: 'TechCrunch\n4pm window', meta: 'decide today' },
    { id: 'b4', x: 90,  y: 90, tag: 'Read',   tagColor: '#5db98a', title: 'Morning brief',          meta: 'Across 6 inboxes' },
    { id: 'b5', x: 250, y: 90, tag: 'Defer',  tagColor: '#9a9aa1', title: '24 low-priority',        meta: 'Auto-snoozed' },
  ] : [
    { id: 'b1', x: 250, y: 0,   tag: 'Reply',  tagColor: '#5b8def', title: 'Sarah Chen —\nQ3 update',  meta: '2 cited docs · drafted' },
    { id: 'b2', x: 460, y: 0,   tag: 'Sign',   tagColor: '#e07ab0', title: 'SAFE —\nMaven Ventures',   meta: '$250k · clean terms' },
    { id: 'b3', x: 670, y: 0,   tag: 'Decide', tagColor: '#e8995b', title: 'TechCrunch —\n4pm window', meta: 'PR offer · decide today' },
    { id: 'b4', x: 355, y: 110, tag: 'Read',   tagColor: '#5db98a', title: 'Morning brief',            meta: 'Across 6 inboxes' },
    { id: 'b5', x: 565, y: 110, tag: 'Defer',  tagColor: '#9a9aa1', title: '24 low-priority',          meta: 'Auto-snoozed' },
  ];

  // Brief tile typography (smaller on mobile)
  const briefTitleSize = isMobile ? 11 : 13;
  const briefMetaSize  = isMobile ? 9.5 : 11.5;
  const briefTagH      = isMobile ? 15 : 18;
  const briefTagSize   = isMobile ? 8.5 : 10;
  const briefPad       = isMobile ? 10 : 14;

  const curveDown = (x1, y1, x2, y2) => {
    const dy = (y2 - y1) / 2;
    return `M ${x1} ${y1} C ${x1} ${y1 + dy}, ${x2} ${y2 - dy}, ${x2} ${y2}`;
  };

  // Pipeline line — drawn progressively from pipeTop to pipeBottom
  const pipeLen = pipeBottom - pipeTop;
  const pipeRevealY = pipeTop + pipeLineP * pipeLen;

  const markSvg = (window.__resources && window.__resources.markSvg) || 'mark.svg';

  return (
    <section className="dirA-converge-v" ref={wrapRef}>
      <style>{`
.dirA-converge-v {
  position: relative;
  background: linear-gradient(180deg, #ffffff 0%, #fafafa 100%);
  height: 320vh;
}
.dirA-converge-v-sticky {
  position: sticky; top: 0;
  min-height: 100vh;
  display: flex; flex-direction: column;
  padding: 60px 56px 80px;
  box-sizing: border-box;
}
.dirA-converge-v-head { text-align: center; margin-bottom: 24px; }
.dirA-converge-v-head h2 {
  font-size: 48px; letter-spacing: -0.03em; font-weight: 600; line-height: 1.06;
  margin: 0 auto 12px; max-width: 820px; color: #1d1d1f;
}
.dirA-converge-v-head .lede {
  font-size: 17px; color: #6e6e73; max-width: 600px; margin: 0 auto; line-height: 1.55;
}
.dirA-converge-v-stage {
  flex: 1; width: 100%; max-width: 1180px; margin: 0 auto; position: relative;
}
.dirA-converge-v-stage svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }

.dirA-converge-tile-text { font-size: 12px; font-weight: 500; color: #1d1d1f; }
.dirA-converge-brief-tag {
  display: inline-block;
  font-size: 10px; font-weight: 600; padding: 3px 8px; border-radius: 999px;
  color: #fff; letter-spacing: 0.02em;
}
.dirA-converge-stage-label { font-size: 15px; font-weight: 600; color: #1d1d1f; letter-spacing: -0.01em; }
.dirA-converge-stage-sub   { font-size: 12px; color: #86868b; margin-top: 2px; }

@media (max-width: 900px) {
  .dirA-converge-v { height: 260vh; }
  .dirA-converge-v-head h2 { font-size: 34px; }
  .dirA-converge-v-sticky { padding: 30px 20px; }
}

@media (max-width: 760px) {
  .dirA-converge-v { height: 220vh; }
  .dirA-converge-v-head { margin-bottom: 16px; }
  .dirA-converge-v-head h2 { font-size: 28px; line-height: 1.1; }
  .dirA-converge-v-head .lede { font-size: 15px; padding: 0 8px; }
  .dirA-converge-v-sticky { padding: 24px 16px 32px; }
}
      `}</style>

      <div className="dirA-converge-v-sticky">
        <div className="dirA-converge-v-head" style={{ opacity: headerOp, transform: `translateY(${(1 - headerOp) * 14}px)` }}>
          <div className="dirA-eyebrow" style={{ marginBottom: 16, justifyContent: 'center', display: 'inline-flex' }}>How it comes together</div>
          <h2>Your whole workspace,<br/>sorted before you sit down.</h2>
          <p className="lede">Every inbox, doc, calendar, and chat — read, ranked, and rolled up so you never miss what matters and can focus on what does.</p>
        </div>

        <div className="dirA-converge-v-stage">
          <svg viewBox={`0 0 ${W} ${stageH}`} preserveAspectRatio="xMidYMid meet">
            <defs>
              <linearGradient id="conv-line-in-v" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%" stopColor="rgba(91,141,239,0)"/>
                <stop offset="60%" stopColor="rgba(91,141,239,0.4)"/>
                <stop offset="100%" stopColor="rgba(91,141,239,0.7)"/>
              </linearGradient>
              <linearGradient id="conv-line-out-v" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%" stopColor="rgba(124,105,224,0.7)"/>
                <stop offset="40%" stopColor="rgba(124,105,224,0.4)"/>
                <stop offset="100%" stopColor="rgba(124,105,224,0)"/>
              </linearGradient>
              <linearGradient id="conv-pipe" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%" stopColor="#5b8def"/>
                <stop offset="100%" stopColor="#7c69e0"/>
              </linearGradient>
              <filter id="conv-soft-v" x="-50%" y="-50%" width="200%" height="200%">
                <feGaussianBlur stdDeviation="1.4"/>
              </filter>
            </defs>

            {/* ── Incoming curves: sources → mark top ── */}
            {sources.map((s) => {
              const d = curveDown(s.x, s.y + SRC_ICON / 2 + 4, markX, markY - markH / 2 - 4);
              return (
                <path
                  key={'in-' + s.id}
                  d={d}
                  stroke="url(#conv-line-in-v)"
                  strokeWidth="1.4"
                  fill="none"
                  pathLength="1"
                  strokeDasharray="1"
                  strokeDashoffset={1 - linesInP}
                  opacity="0.9"
                />
              );
            })}

            {/* Dots along incoming */}
            {sources.map((s) => {
              if (dotsInP <= 0) return null;
              const d = curveDown(s.x, s.y + SRC_ICON / 2 + 4, markX, markY - markH / 2 - 4);
              return (
                <circle key={'d-in-' + s.id} r="3.5" fill="#5b8def" filter="url(#conv-soft-v)" opacity={dotsInP < 0.05 ? 0 : 1}>
                  <animateMotion key={`am-${s.id}-${Math.round(dotsInP * 100)}`} dur="0.01s" path={d} keyPoints={`0;${dotsInP}`} keyTimes="0;1" fill="freeze"/>
                </circle>
              );
            })}

            {/* ── Exoteam mark + wordmark (native SVG so iOS scales correctly) ── */}
            <g
              transform={`translate(${markX}, ${markY})`}
              opacity={markOp}
              style={{ transition: 'opacity 0.3s ease' }}
            >
              <image href={markSvg} x={markImgX} y={markImgY} width={markImgSize} height={markImgSize} />
              <text
                x={markTextX} y={markTextY}
                fontFamily="Inter, -apple-system, sans-serif"
                fontSize={markTextSize}
                fontWeight="500"
                letterSpacing="-0.025em"
                fill="#1d1d1f"
              >exoteam</text>
            </g>

            {/* ── Vertical pipeline line — dotted between stages ── */}
            {[
              { y1: pipeTop, y2: stages[0].y - 8 },
              { y1: stages[0].y + 8, y2: stages[1].y - 8 },
              { y1: stages[1].y + 8, y2: stages[2].y - 8 },
              { y1: stages[2].y + 8, y2: pipeBottom },
            ].map((seg, i) => {
              const visible = clamp((pipeRevealY - seg.y1) / Math.max(1, seg.y2 - seg.y1));
              if (visible <= 0) return null;
              const y2 = seg.y1 + (seg.y2 - seg.y1) * visible;
              return (
                <line
                  key={'pipe-' + i}
                  x1={pipeX} y1={seg.y1}
                  x2={pipeX} y2={y2}
                  stroke="#5b8def"
                  strokeWidth="2"
                  strokeLinecap="round"
                  strokeDasharray="1.5 6"
                  opacity={markOp * 0.7}
                />
              );
            })}

            {/* Pipeline stage markers + labels (native SVG) */}
            {stages.map((st, i) => {
              const reach = clamp((pipeRevealY - st.y + 30) / 40);
              return (
                <g key={st.id} opacity={reach}>
                  <circle cx={pipeX} cy={st.y} r={isMobile ? 5 : 6} fill="#fff" stroke="#5b8def" strokeWidth="2"/>
                  <circle cx={pipeX} cy={st.y} r={isMobile ? 2 : 2.5} fill="#5b8def"/>
                  <text
                    x={pipeX + (isMobile ? 16 : 22)} y={st.y - (isMobile ? 2 : 3)}
                    fontFamily="Inter, -apple-system, sans-serif"
                    fontSize={isMobile ? 13 : 15} fontWeight="600" letterSpacing="-0.01em"
                    fill="#1d1d1f"
                  >{st.label}</text>
                  <text
                    x={pipeX + (isMobile ? 16 : 22)} y={st.y + (isMobile ? 12 : 14)}
                    fontFamily="Inter, -apple-system, sans-serif"
                    fontSize={isMobile ? 10.5 : 12}
                    fill="#86868b"
                  >{st.sub}</text>
                </g>
              );
            })}

            {/* ── Outgoing curves: pipe bottom → briefs ── */}
            {briefs.map((b) => {
              const d = curveDown(pipeX, pipeBottom, b.x + briefW / 2, briefY + b.y);
              return (
                <path
                  key={'out-' + b.id}
                  d={d}
                  stroke="url(#conv-line-out-v)"
                  strokeWidth="1.4"
                  fill="none"
                  pathLength="1"
                  strokeDasharray="1"
                  strokeDashoffset={1 - linesOutP}
                  opacity="0.9"
                />
              );
            })}

            {/* ── Source logos as nested SVG (no foreignObject — iOS scales correctly) ── */}
            {sources.map((s, i) => {
              const tileOp = clamp(sourcesOp * 1.4 - i * 0.05);
              return (
                <g
                  key={'src-' + s.id}
                  transform={`translate(${s.x - SRC_ICON / 2}, ${s.y - SRC_ICON / 2})`}
                  opacity={tileOp}
                  style={{ transition: 'opacity 0.3s ease' }}
                >
                  {s.icon}
                </g>
              );
            })}

            {/* ── Brief tiles as native SVG ── */}
            {briefs.map((b, i) => {
              const tileOp = clamp(briefP * 1.4 - i * 0.06);
              const tagW = b.tag.length * (isMobile ? 5.6 : 6.5) + (isMobile ? 12 : 14);
              const titleLines = b.title.split('\n');
              const tagY = isMobile ? 9 : 11;
              const titleY = titleLines.length > 1
                ? (isMobile ? 40 : 45)
                : (isMobile ? 46 : 52);
              return (
                <g
                  key={'b-' + b.id}
                  transform={`translate(${b.x}, ${briefY + b.y})`}
                  opacity={tileOp}
                  style={{ transition: 'opacity 0.3s ease' }}
                >
                  {/* Card body */}
                  <rect x="0" y="0" width={briefW} height={briefH} rx={isMobile ? 10 : 12} fill="#ffffff" stroke="rgba(0,0,0,0.08)" strokeWidth="1"/>
                  {/* Tag pill */}
                  <rect x={briefPad} y={tagY} width={tagW} height={briefTagH} rx={briefTagH / 2} fill={b.tagColor}/>
                  <text
                    x={briefPad + tagW / 2} y={tagY + briefTagH / 2 + briefTagSize / 3}
                    textAnchor="middle"
                    fontFamily="Inter, -apple-system, sans-serif"
                    fontSize={briefTagSize} fontWeight="600" letterSpacing="0.02em"
                    fill="#ffffff"
                  >{b.tag}</text>
                  {/* Title (single or two-line via tspan) */}
                  <text
                    x={briefPad}
                    y={titleY}
                    fontFamily="Inter, -apple-system, sans-serif"
                    fontSize={briefTitleSize} fontWeight="500" letterSpacing="-0.005em"
                    fill="#1d1d1f"
                  >
                    {titleLines.map((line, li) => (
                      <tspan key={li} x={briefPad} dy={li === 0 ? 0 : '1.25em'}>{line}</tspan>
                    ))}
                  </text>
                  {/* Meta line */}
                  <text
                    x={briefPad}
                    y={briefH - (isMobile ? 9 : 12)}
                    fontFamily="Inter, -apple-system, sans-serif"
                    fontSize={briefMetaSize}
                    fill="#86868b"
                  >{b.meta}</text>
                </g>
              );
            })}
          </svg>
        </div>
      </div>
    </section>
  );
};

window.ConvergeAnimation = ConvergeAnimation;
