// Dataflow diagram, inputs → Światowid → outputs with animated particles

function DataflowDiagram() {
  const [isMobile, setIsMobile] = React.useState(
    typeof window !== 'undefined' && window.matchMedia('(max-width: 720px)').matches
  );

  React.useEffect(() => {
    if (typeof window === 'undefined') return;
    const mq = window.matchMedia('(max-width: 720px)');
    const onChange = (e) => setIsMobile(e.matches);
    mq.addEventListener('change', onChange);
    return () => mq.removeEventListener('change', onChange);
  }, []);

  // Icon renderers, minimal line-art glyphs that match each node's concept.
  // All draw at an origin of (0,0) inside a 20x20 box; positioned via transform.
  const Icons = {
    market: (
      <g stroke="var(--amber)" strokeWidth="1.4" fill="none" strokeLinecap="square">
        <line x1="3" y1="3" x2="3" y2="17" />
        <rect x="1" y="7" width="4" height="6" fill="var(--amber)" stroke="none" />
        <line x1="10" y1="5" x2="10" y2="15" />
        <rect x="8" y="9" width="4" height="4" fill="var(--bg)" />
        <line x1="17" y1="1" x2="17" y2="19" />
        <rect x="15" y="5" width="4" height="8" fill="var(--amber)" stroke="none" />
      </g>
    ),
    osint: (
      <g stroke="var(--amber)" strokeWidth="1.4" fill="none" strokeLinecap="square" strokeLinejoin="miter">
        <path d="M 1 3 L 15 3 L 15 13 L 8 13 L 5 17 L 5 13 L 1 13 Z" />
        <line x1="4" y1="7" x2="12" y2="7" />
        <line x1="4" y1="10" x2="9" y2="10" />
      </g>
    ),
    sat: (
      <g stroke="var(--amber)" strokeWidth="1.4" fill="none" strokeLinecap="square">
        <rect x="7" y="7" width="6" height="6" />
        <line x1="7" y1="7" x2="2" y2="2" />
        <line x1="13" y1="7" x2="18" y2="2" />
        <line x1="7" y1="13" x2="2" y2="18" />
        <line x1="13" y1="13" x2="18" y2="18" />
        <circle cx="10" cy="10" r="1.2" fill="var(--amber)" stroke="none" />
      </g>
    ),
    sigint: (
      <g stroke="var(--amber)" strokeWidth="1.4" fill="none" strokeLinecap="square">
        <polyline points="1,10 4,10 5,5 7,15 9,3 11,17 13,7 15,13 17,10 19,10" />
      </g>
    ),
    genesis: (
      <g stroke="var(--amber)" strokeWidth="1.4" fill="none" strokeLinecap="square">
        <circle cx="10" cy="10" r="3" fill="var(--amber)" stroke="none" />
        <line x1="10" y1="1" x2="10" y2="4" />
        <line x1="10" y1="16" x2="10" y2="19" />
        <line x1="1" y1="10" x2="4" y2="10" />
        <line x1="16" y1="10" x2="19" y2="10" />
        <line x1="3.5" y1="3.5" x2="5.5" y2="5.5" />
        <line x1="14.5" y1="14.5" x2="16.5" y2="16.5" />
        <line x1="3.5" y1="16.5" x2="5.5" y2="14.5" />
        <line x1="14.5" y1="5.5" x2="16.5" y2="3.5" />
      </g>
    ),
    conflict: (
      <g stroke="var(--amber)" strokeWidth="1.4" fill="none" strokeLinecap="square">
        <circle cx="10" cy="10" r="7" />
        <circle cx="10" cy="10" r="3" />
        <line x1="10" y1="1" x2="10" y2="5" />
        <line x1="10" y1="15" x2="10" y2="19" />
        <line x1="1" y1="10" x2="5" y2="10" />
        <line x1="15" y1="10" x2="19" y2="10" />
      </g>
    ),
    logistics: (
      <g stroke="var(--amber)" strokeWidth="1.4" fill="none" strokeLinecap="square" strokeLinejoin="miter">
        <polyline points="2,5 10,1 18,5 18,15 10,19 2,15 2,5" />
        <line x1="2" y1="5" x2="10" y2="9" />
        <line x1="18" y1="5" x2="10" y2="9" />
        <line x1="10" y1="9" x2="10" y2="19" />
      </g>
    ),
    scenario: (
      <g stroke="var(--amber)" strokeWidth="1.4" fill="none" strokeLinecap="square">
        <circle cx="3" cy="10" r="1.5" fill="var(--amber)" stroke="none" />
        <circle cx="17" cy="3" r="1.5" fill="var(--amber)" stroke="none" />
        <circle cx="17" cy="10" r="1.5" fill="var(--amber)" stroke="none" />
        <circle cx="17" cy="17" r="1.5" fill="var(--amber)" stroke="none" />
        <line x1="4.5" y1="10" x2="15.5" y2="3" />
        <line x1="4.5" y1="10" x2="15.5" y2="10" />
        <line x1="4.5" y1="10" x2="15.5" y2="17" />
      </g>
    ),
  };

  const NodeShape = ({ x, y, w = 140, h = 92, children, highlight, className = '' }) => {
    const clip = 10;
    const d = `M ${x + clip} ${y}
               L ${x + w - clip} ${y}
               L ${x + w} ${y + clip}
               L ${x + w} ${y + h - clip}
               L ${x + w - clip} ${y + h}
               L ${x + clip} ${y + h}
               L ${x} ${y + h - clip}
               L ${x} ${y + clip} Z`;
    const cx = x + w / 2;
    const cy = y + h / 2;
    return (
      <g className={`df-node ${className}`} style={{ transformBox: 'fill-box', transformOrigin: `${cx}px ${cy}px` }}>
        <path className="df-node-shape" d={d} fill="var(--bg-2)" stroke={highlight ? 'var(--amber)' : 'var(--line-2)'} strokeWidth="1" />
        {children}
      </g>
    );
  };

  if (isMobile) {
    return <MobileDataflow Icons={Icons} NodeShape={NodeShape} />;
  }
  return <DesktopDataflow Icons={Icons} NodeShape={NodeShape} />;
}

function DesktopDataflow({ Icons, NodeShape }) {
  const W = 1400, H = 640;
  const CENTER = { x: 700, y: 320 };

  const inputs = [
    { y: 46,  label: 'PREDICTION\nMARKETS', icon: 'market' },
    { y: 161, label: 'OSINT /\nTELEGRAM',   icon: 'osint' },
    { y: 391, label: 'SAT / AIS /\nADS-B',  icon: 'sat' },
    { y: 506, label: 'SIGINT\nDIGEST',      icon: 'sigint' },
  ];

  const outputs = [
    { y: 46,  label: 'MARKET\nGENESIS',      icon: 'genesis' },
    { y: 161, label: 'CONFLICT\nFORECAST',   icon: 'conflict' },
    { y: 391, label: 'LOGISTICS\nANOMALY',   icon: 'logistics' },
    { y: 506, label: 'SCENARIO\nSIMULATION', icon: 'scenario' },
  ];

  const INPUT_X = 140;
  const INPUT_W = 180;
  const OUTPUT_X = W - 140 - 180;
  const OUTPUT_W = 180;
  const NODE_H = 88;

  const CX = CENTER.x - 120;
  const CY = CENTER.y - 120;
  const CW = 240;
  const CH = 240;

  const LEFT_JUNCTION_X = 540;
  const RIGHT_JUNCTION_X = 860;
  const R = 10;

  const mkPathLeftToCenter = (srcY) => {
    const x1 = INPUT_X + INPUT_W;
    const y1 = srcY + NODE_H / 2;
    const jx = LEFT_JUNCTION_X;
    const y2 = CENTER.y;
    const x2 = CX;
    if (Math.abs(y1 - y2) < 1) {
      return `M ${x1} ${y1} L ${x2} ${y1}`;
    }
    const down = y2 > y1;
    const ySign = down ? 1 : -1;
    return `M ${x1} ${y1} L ${jx - R} ${y1} Q ${jx} ${y1} ${jx} ${y1 + ySign * R} L ${jx} ${y2 - ySign * R} Q ${jx} ${y2} ${jx + R} ${y2} L ${x2} ${y2}`;
  };

  const mkPathCenterToRight = (dstY) => {
    const x1 = CX + CW;
    const y1 = CENTER.y;
    const jx = RIGHT_JUNCTION_X;
    const y2 = dstY + NODE_H / 2;
    const x2 = OUTPUT_X;
    if (Math.abs(y1 - y2) < 1) {
      return `M ${x1} ${y1} L ${x2} ${y1}`;
    }
    const down = y2 > y1;
    const ySign = down ? 1 : -1;
    return `M ${x1} ${y1} L ${jx - R} ${y1} Q ${jx} ${y1} ${jx} ${y1 + ySign * R} L ${jx} ${y2 - ySign * R} Q ${jx} ${y2} ${jx + R} ${y2} L ${x2} ${y2}`;
  };

  // Per-path lengths so every line draws at the SAME tempo (px/sec).
  // Shorter paths finish drawing earlier and just hold longer.
  const leftLens = inputs.map((inp) => {
    const srcY = inp.y + NODE_H / 2;
    const hLen = (LEFT_JUNCTION_X - (INPUT_X + INPUT_W)) + (CX - LEFT_JUNCTION_X);
    const vLen = Math.abs(CENTER.y - srcY);
    return Math.ceil(hLen + vLen + 8);
  });
  const rightLens = outputs.map((out) => {
    const dstY = out.y + NODE_H / 2;
    const hLen = (RIGHT_JUNCTION_X - (CX + CW)) + (OUTPUT_X - RIGHT_JUNCTION_X);
    const vLen = Math.abs(dstY - CENTER.y);
    return Math.ceil(hLen + vLen + 8);
  });
  const MAX_LEFT = Math.max.apply(null, leftLens);
  const MAX_RIGHT = Math.max.apply(null, rightLens);

  // Coordinated 8s timeline:
  //   0.0 → left phase begins (longest path takes the full 3s; shorter ones finish earlier)
  //   3.0 → right phase begins (same px/sec speed, left holds)
  //   6.0 → all 8 lines glow together
  //   7.5 → fade out (left-to-right via negative offset)
  //   7.8 → rest
  //   8.0 → loop
  const TOTAL = 7;
  const LEFT_PHASE = 2.5;
  const RIGHT_PHASE = 2.5;

  return (
    <div style={{ border: '1px solid var(--line)', background: 'var(--bg)', padding: '28px 24px 28px', position: 'relative', overflow: 'hidden' }}>
      <svg viewBox={`0 0 ${W} ${H}`} style={{ width: '100%', display: 'block' }}>
        <defs>
          <pattern id="bggrid" width="40" height="40" patternUnits="userSpaceOnUse">
            <path d="M 40 0 L 0 0 0 40" fill="none" stroke="var(--line)" strokeWidth="0.5" />
          </pattern>
          <filter id="glow">
            <feGaussianBlur stdDeviation="2.5" result="b" />
            <feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
          </filter>
        </defs>

        <rect width={W} height={H} fill="transparent" />

        {inputs.map((inp, i) => (
          <g key={`pi-${i}`} pointerEvents="none">
            <path id={`pathL-${i}`} d={mkPathLeftToCenter(inp.y)} fill="none" stroke="var(--line-2)" strokeWidth="1" />
          </g>
        ))}
        {outputs.map((out, i) => (
          <g key={`po-${i}`} pointerEvents="none">
            <path id={`pathR-${i}`} d={mkPathCenterToRight(out.y)} fill="none" stroke="var(--line-2)" strokeWidth="1" />
          </g>
        ))}

        {inputs.map((_, i) => {
          const len = leftLens[i];
          const drawEnd = (LEFT_PHASE * len / MAX_LEFT) / TOTAL;
          const ktL = '0;' + drawEnd.toFixed(4) + ';0.9286;0.9714;1';
          const valsL = len + ';0;0;' + len + ';' + len;
          const dashL = len + ' ' + len;
          return (
            <path
              key={'segL-' + i}
              d={mkPathLeftToCenter(inputs[i].y)}
              fill="none"
              stroke="var(--amber)"
              strokeWidth="2"
              strokeLinecap="butt"
              strokeDasharray={dashL}
              strokeDashoffset={len}
              pointerEvents="none"
            >
              <animate
                attributeName="stroke-dashoffset"
                values={valsL}
                keyTimes={ktL}
                calcMode="spline"
                keySplines="0.4 0 0.6 1; 0 0 1 1; 0.4 0 1 1; 0 0 1 1"
                dur={TOTAL + 's'}
                begin="0s"
                repeatCount="indefinite"
              />
            </path>
          );
        })}

        {outputs.map((_, i) => {
          const len = rightLens[i];
          const drawStart = LEFT_PHASE / TOTAL;
          const drawEnd = (LEFT_PHASE + RIGHT_PHASE * len / MAX_RIGHT) / TOTAL;
          const ktR = '0;' + drawStart.toFixed(4) + ';' + drawEnd.toFixed(4) + ';0.9286;0.9714;1';
          const valsR = len + ';' + len + ';0;0;' + len + ';' + len;
          const dashR = len + ' ' + len;
          return (
            <path
              key={'segR-' + i}
              d={mkPathCenterToRight(outputs[i].y)}
              fill="none"
              stroke="var(--amber)"
              strokeWidth="2"
              strokeLinecap="butt"
              strokeDasharray={dashR}
              strokeDashoffset={len}
              pointerEvents="none"
            >
              <animate
                attributeName="stroke-dashoffset"
                values={valsR}
                keyTimes={ktR}
                calcMode="spline"
                keySplines="0 0 1 1; 0.4 0 0.6 1; 0 0 1 1; 0.4 0 1 1; 0 0 1 1"
                dur={TOTAL + 's'}
                begin="0s"
                repeatCount="indefinite"
              />
            </path>
          );
        })}

        {inputs.map((inp, i) => (
          <NodeShape key={`in-${i}`} x={INPUT_X} y={inp.y} w={INPUT_W} h={NODE_H} className="df-input">
            <g transform={`translate(${INPUT_X + 18} ${inp.y + NODE_H / 2 - 10})`}>
              {Icons[inp.icon]}
            </g>
            {inp.label.split('\n').map((ln, k) => {
              const lines = inp.label.split('\n');
              const totalH = lines.length * 16;
              const cy = inp.y + NODE_H / 2;
              return (
                <text key={k} x={INPUT_X + 48} y={cy - totalH / 2 + 12 + k * 16} fontFamily="var(--mono)" fontSize="13" fill="var(--fg)" letterSpacing="1">{ln}</text>
              );
            })}
            <circle cx={INPUT_X + INPUT_W} cy={inp.y + NODE_H / 2} r="3" fill="var(--amber)" opacity="0.3" pointerEvents="none">
              <animate
                attributeName="opacity"
                values="0.3;1;1;0.3;0.3"
                keyTimes="0;0.3571;0.9286;0.9714;1"
                calcMode="spline"
                keySplines="0.4 0 0.6 1; 0 0 1 1; 0.4 0 1 1; 0 0 1 1"
                dur={`${TOTAL}s`}
                repeatCount="indefinite"
              />
            </circle>
          </NodeShape>
        ))}

        {outputs.map((out, i) => (
          <NodeShape key={`out-${i}`} x={OUTPUT_X} y={out.y} w={OUTPUT_W} h={NODE_H} className="df-output">
            <g transform={`translate(${OUTPUT_X + 18} ${out.y + NODE_H / 2 - 10})`}>
              {Icons[out.icon]}
            </g>
            {out.label.split('\n').map((ln, k) => {
              const lines = out.label.split('\n');
              const totalH = lines.length * 16;
              const cy = out.y + NODE_H / 2;
              return (
                <text key={k} x={OUTPUT_X + 48} y={cy - totalH / 2 + 12 + k * 16} fontFamily="var(--mono)" fontSize="13" fill="var(--fg)" letterSpacing="1">{ln}</text>
              );
            })}
            <circle cx={OUTPUT_X} cy={out.y + NODE_H / 2} r="3" fill="var(--amber)" opacity="0.3" pointerEvents="none">
              <animate
                attributeName="opacity"
                values="0.3;0.3;1;1;0.3;0.3"
                keyTimes="0;0.3571;0.7143;0.9286;0.9714;1"
                calcMode="spline"
                keySplines="0 0 1 1; 0.4 0 0.6 1; 0 0 1 1; 0.4 0 1 1; 0 0 1 1"
                dur={`${TOTAL}s`}
                repeatCount="indefinite"
              />
            </circle>
          </NodeShape>
        ))}

        <NodeShape x={CX} y={CY} w={CW} h={CH} highlight className="df-core">
          {[[CX, CY],[CX+CW,CY],[CX,CY+CH],[CX+CW,CY+CH]].map(([x,y], i) => {
            const dx = i % 2 === 0 ? 1 : -1;
            const dy = i < 2 ? 1 : -1;
            return (
              <g key={i}>
                <line x1={x} y1={y} x2={x + dx * 14} y2={y} stroke="var(--amber)" strokeWidth="2" />
                <line x1={x} y1={y} x2={x} y2={y + dy * 14} stroke="var(--amber)" strokeWidth="2" />
              </g>
            );
          })}
        </NodeShape>

        {/* Inline logo as native SVG <g>+<path>. Mirrors the mobile fix
            (avoids iOS Safari foreignObject mis-positioning). */}
        {(() => {
          const inner = 40;
          const innerW = CW - inner * 2;
          const innerH = CH - inner * 2;
          const logoVb = { w: 534, h: 564 };
          const scale = Math.min(innerW / logoVb.w, innerH / logoVb.h);
          const drawW = logoVb.w * scale;
          const drawH = logoVb.h * scale;
          const tx = CX + inner + (innerW - drawW) / 2;
          const ty = CY + inner + (innerH - drawH) / 2;
          return (
            <g transform={`translate(${tx} ${ty}) scale(${scale})`} fill="var(--amber)" pointerEvents="none">
              <path d="M266.301 82.1228C379.837 76.4168 476.475 163.883 482.078 277.421C487.682 390.958 400.125 487.514 286.579 493.014C173.178 498.507 76.7697 411.09 71.1737 297.698C65.5777 184.306 152.91 87.8214 266.301 82.1228ZM212.66 467.374C212.227 454.066 212.736 440.555 212.489 427.226C212.451 425.148 212.403 422.841 212.501 420.782C202.662 420.174 191.758 421.121 182.362 420.466C178.009 416.929 174.096 412.118 170.023 408.329C165.951 404.541 165.083 402.788 165.369 397.247C165.215 377.87 165.671 358.391 165.247 339.024C161.691 338.979 142.346 339.658 140.937 337.949C139.043 335.652 140.934 328.819 141.468 326.05L151.964 273.879C154.238 262.275 156.59 247.937 159.418 236.61C155.936 236.893 146.842 236.863 143.191 236.723C143.067 229.637 143.03 222.55 143.08 215.463C143.081 211.82 142.932 205.311 143.365 201.914C148.075 196.707 156.303 190.144 161.863 185.537L190.451 162.03C197.312 156.477 204.097 150.832 210.805 145.095C213.697 142.587 217.458 138.744 220.213 136.62C225.981 136 237.692 136.38 244.052 136.394L287.31 136.377L314.754 136.361C317.496 136.355 330 135.903 331.825 137.103L332.253 137.382C334.575 138.914 339.505 143.481 341.894 145.524C347.703 150.459 353.536 155.365 359.395 160.241L387.932 183.815C394.939 189.575 402.925 195.988 409.481 202.227C409.645 203.729 409.723 205.172 409.694 206.683C409.502 216.641 409.924 226.688 409.532 236.63C405.573 236.701 396.496 236.957 392.839 236.608C396.888 256.864 400.832 277.14 404.671 297.436L409.467 321.771C410.293 326.013 411.129 330.288 411.807 334.555C412.552 339.241 407.132 338.75 404.21 338.686C398.419 338.559 392.648 338.731 386.927 338.556C387.265 357.17 386.715 375.873 386.953 394.495C387.017 399.546 387.803 403.17 383.729 406.849C379.167 410.967 374.581 416.836 369.751 420.517C359.872 420.598 349.992 420.614 340.113 420.564L340.083 450.4C340.074 455.674 340.248 462.072 340.072 467.253C348.334 464.163 356.409 460.596 364.257 456.57C403.203 436.409 434.175 403.657 452.13 363.648C472.181 317.485 473.124 265.258 454.753 218.401C436.495 171.333 400.211 133.494 353.948 113.278C330.429 102.963 305.021 97.6548 279.339 97.6905C275.154 97.661 269.93 97.5757 265.813 97.9014C214.259 100.64 165.991 124.06 131.937 162.861C100.2 198.845 82.6936 250.306 85.7189 298.159C88.4402 348.714 111.309 396.069 149.211 429.636C164.146 442.81 180.991 453.645 199.173 461.772C203.796 463.879 208.112 465.421 212.66 467.374ZM179.809 372.222C182.546 372.118 185.414 372.024 188.134 372.054C194.039 372.118 202.95 370.405 202.788 379.164C202.72 382.807 200.769 385.115 196.986 385.545C191.284 385.827 185.372 385.551 179.649 385.591C179.943 389.613 179.525 393.818 179.723 397.857C182.447 400.622 186.744 405.406 189.482 407.803C197.086 407.842 205.481 407.908 213.079 407.731C225.397 396.634 237.288 384.744 249.402 373.404C250.584 372.298 251.883 370.996 252.938 369.766C253.421 358.093 253.014 344.04 253.018 332.161L253.024 272.4C253.013 260.636 252.864 248.568 253.041 236.838C234.718 236.34 214.513 236.74 196.092 236.751L181.006 236.763C179.416 236.764 174.924 236.851 173.518 236.641C169.045 258.229 164.706 279.845 160.502 301.486C159.01 309.144 156.793 318.543 155.621 326.089C161.264 326.299 170.617 325.654 175.639 326.284C178.036 313.397 180.59 300.54 183.299 287.715C184.018 284.275 186.777 269.01 188.19 267.035C192.372 265.258 233.026 265.927 240.14 266.334C240.221 270.094 240.3 274.728 240.099 278.468C235.273 278.943 230.21 278.777 225.352 278.81C216.743 278.868 208.062 278.661 199.458 278.894C196.417 294.445 192.726 310.29 189.784 325.793C196.326 325.713 205.268 323.97 204.478 334.103C204.279 336.657 200.855 338.5 198.614 338.7C192.387 339.161 186.099 338.472 179.833 339.064C179.767 342.592 179.821 346.258 179.728 349.736L207.527 349.717C211.879 349.711 216.566 349.53 220.885 349.98C221.936 350.089 223.194 351.253 223.901 352.008C224.870 354.213 225.426 356.634 224.547 358.988C224.001 360.437 222.902 361.610 221.491 362.248C219.248 363.286 185.246 362.819 179.754 362.941L179.809 372.222ZM299.359 370.103C312.121 382.536 325.999 395.107 338.437 407.790C346.309 407.841 354.791 407.913 362.653 407.765C364.959 405.438 370.797 399.900 372.625 397.631L372.625 385.608C366.587 385.495 360.053 385.778 354.045 385.275C347.576 384.733 347.427 373.275 354.137 372.420C360.136 371.787 366.560 372.284 372.653 372.113C372.590 369.131 372.493 365.893 372.584 362.918C363.547 362.811 354.509 362.776 345.471 362.814C341.763 362.820 331.337 363.752 328.634 361.018C325.710 358.060 326.907 349.612 332.264 349.865C337.231 349.647 341.888 349.711 346.740 349.720L372.827 349.797C372.505 346.491 372.584 342.386 372.571 338.998C367.174 338.669 355.961 339.131 351.723 338.412C350.223 337.910 348.994 337.245 348.474 335.815C345.881 328.689 349.848 325.166 356.824 325.705C358.231 325.813 360.892 325.751 362.289 325.748C358.590 310.491 356.177 293.930 352.367 278.830C347.087 279.107 339.832 278.810 334.521 278.867C331.216 278.903 313.763 279.282 311.946 278.188C311.377 275.938 311.679 268.897 311.724 266.294C318.078 265.994 358.885 265.398 363.071 266.817C365.021 268.595 367.047 279.932 367.742 283.216L372.179 304.654L375.063 319.002C375.377 320.622 376.193 324.511 376.284 326.069L396.330 326.085L383.457 261.075C382.157 254.270 379.560 243.198 378.776 236.737L326.651 236.757L309.102 236.783C306.250 236.789 302.077 236.917 299.308 236.684C299.951 280.913 298.910 325.767 299.359 370.103ZM285.314 478.028C294.446 477.592 302.554 476.875 311.562 475.054C316.385 474.080 321.081 472.822 325.871 471.721C325.263 453.366 325.929 433.042 325.769 414.431C315.972 404.853 305.249 395.876 295.384 386.341C293.210 384.240 286.410 378.612 284.831 376.709C284.255 358.725 284.636 338.796 284.670 320.691L284.620 236.472C279.518 236.519 272.459 236.701 267.474 236.457L267.493 325.171L267.523 358.893C267.517 364.688 267.666 371.536 267.383 377.216C263.684 380.288 260.107 383.746 256.521 386.977L226.553 414.508L226.503 451.647C226.505 457.453 226.249 466.060 226.670 471.707C234.958 473.639 242.704 475.715 251.200 476.781C262.367 478.183 274.059 478.290 285.314 478.028ZM258.476 150.500C248.123 150.504 236.438 150.256 226.215 150.670C221.160 154.272 215.291 160.010 210.297 164.088C192.795 178.381 175.656 193.559 157.540 207.095C157.452 212.690 157.463 218.286 157.574 223.880L295.091 223.850L361.862 223.869L384.021 223.874C387.540 223.874 391.970 223.738 395.403 223.890C395.397 218.749 395.284 213.178 395.437 208.071C382.446 197.761 369.578 187.296 356.837 176.678L339.480 162.108C335.036 158.305 330.615 154.237 326.073 150.582L258.476 150.500Z" />
            </g>
          );
        })()}
      </svg>
    </div>
  );
}

function MobileDataflow({ Icons, NodeShape }) {
  // Single-row layout: 4 inputs → bus → core → bus → 4 outputs
  const W = 720, H = 780;

  const NODE_W = 170, NODE_H = 104;
  // 4 nodes across: 170*4 + 6*3 + 11*2 = 720
  const COLS_X = [11, 187, 363, 539];
  const colCenter = (c) => COLS_X[c] + NODE_W / 2;

  const inputs = [
    { col: 0, label: 'PREDICTION\nMARKETS', icon: 'market' },
    { col: 1, label: 'OSINT /\nTELEGRAM',   icon: 'osint' },
    { col: 2, label: 'SAT / AIS /\nADS-B',  icon: 'sat' },
    { col: 3, label: 'SIGINT\nDIGEST',      icon: 'sigint' },
  ];
  const outputs = [
    { col: 0, label: 'MARKET\nGENESIS',      icon: 'genesis' },
    { col: 1, label: 'CONFLICT\nFORECAST',   icon: 'conflict' },
    { col: 2, label: 'LOGISTICS\nANOMALY',   icon: 'logistics' },
    { col: 3, label: 'SCENARIO\nSIMULATION', icon: 'scenario' },
  ];

  const IN_Y = 24;
  const IN_BOTTOM = IN_Y + NODE_H; // 128
  const IN_BUS_Y = 180;

  const CX = 240, CY = 230, CW = 240, CH = 240;
  const CORE_CX = CX + CW / 2; // 360
  const CORE_TOP_Y = CY; // 230
  const CORE_BOT_Y = CY + CH; // 470

  const OUT_BUS_Y = 530;
  const OUT_Y = 580;
  const OUT_TOP = OUT_Y;

  const R = 8;

  const mkPathIn = (col) => {
    const xi = colCenter(col);
    const y1 = IN_BOTTOM;
    const busY = IN_BUS_Y;
    const cx = CORE_CX;
    const y2 = CORE_TOP_Y;
    if (Math.abs(xi - cx) < 1) return `M ${xi} ${y1} L ${cx} ${y2}`;
    const right = cx > xi;
    const s = right ? 1 : -1;
    return `M ${xi} ${y1} L ${xi} ${busY - R} Q ${xi} ${busY} ${xi + s * R} ${busY} L ${cx - s * R} ${busY} Q ${cx} ${busY} ${cx} ${busY + R} L ${cx} ${y2}`;
  };

  const mkPathOut = (col) => {
    const x2 = colCenter(col);
    const y2 = OUT_TOP;
    const busY = OUT_BUS_Y;
    const cx = CORE_CX;
    const y1 = CORE_BOT_Y;
    if (Math.abs(cx - x2) < 1) return `M ${cx} ${y1} L ${x2} ${y2}`;
    const right = x2 > cx;
    const s = right ? 1 : -1;
    return `M ${cx} ${y1} L ${cx} ${busY - R} Q ${cx} ${busY} ${cx + s * R} ${busY} L ${x2 - s * R} ${busY} Q ${x2} ${busY} ${x2} ${busY + R} L ${x2} ${y2}`;
  };

  // Per-path lengths so each line draws at the same px/sec tempo.
  const inLens = inputs.map((inp) => {
    const xi = colCenter(inp.col);
    const v1 = IN_BUS_Y - IN_BOTTOM;
    const h = Math.abs(CORE_CX - xi);
    const v2 = CORE_TOP_Y - IN_BUS_Y;
    return Math.ceil(v1 + h + v2 + 8);
  });
  const outLens = outputs.map((out) => {
    const xi = colCenter(out.col);
    const v1 = OUT_BUS_Y - CORE_BOT_Y;
    const h = Math.abs(CORE_CX - xi);
    const v2 = OUT_TOP - OUT_BUS_Y;
    return Math.ceil(v1 + h + v2 + 8);
  });
  const MAX_IN = Math.max.apply(null, inLens);
  const MAX_OUT = Math.max.apply(null, outLens);
  const TOTAL = 7;
  const LEFT_PHASE = 2.5;
  const RIGHT_PHASE = 2.5;

  // Icon on left, 2-line label to the right, vertically centered
  const renderNode = (node, x, y) => {
    const iconScale = 1.6; // 32×32 rendered
    const iconX = x + 12;
    const iconY = y + NODE_H / 2 - 16;
    const labelX = x + 52;
    const cy = y + NODE_H / 2;
    const lines = node.label.split('\n');
    const lineH = 22;
    return (
      <g>
        <g transform={`translate(${iconX} ${iconY}) scale(${iconScale})`}>
          {Icons[node.icon]}
        </g>
        {lines.map((ln, k) => {
          const totalH = lines.length * lineH;
          const yy = cy - totalH / 2 + 16 + k * lineH;
          return (
            <text key={k} x={labelX} y={yy} fontFamily="var(--mono)" fontSize="17" fill="var(--fg)" letterSpacing="0.8">{ln}</text>
          );
        })}
      </g>
    );
  };

  return (
    <div style={{ border: '1px solid var(--line)', background: 'var(--bg)', padding: '20px 14px', position: 'relative', overflow: 'hidden' }}>
      <svg viewBox={`0 0 ${W} ${H}`} style={{ width: '100%', display: 'block' }}>
        <defs>
          <filter id="glow">
            <feGaussianBlur stdDeviation="2.5" result="b" />
            <feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
          </filter>
        </defs>

        {/* Static guide paths */}
        {inputs.map((_, i) => (
          <path key={`pi-${i}`} d={mkPathIn(i)} fill="none" stroke="var(--line-2)" strokeWidth="1" pointerEvents="none" />
        ))}
        {outputs.map((_, i) => (
          <path key={`po-${i}`} d={mkPathOut(i)} fill="none" stroke="var(--line-2)" strokeWidth="1" pointerEvents="none" />
        ))}

        {/* Animated input lines: each at same px/sec, shorter ones finish earlier */}
        {inputs.map((_, i) => {
          const len = inLens[i];
          const drawEnd = (LEFT_PHASE * len / MAX_IN) / TOTAL;
          const ktL = '0;' + drawEnd.toFixed(4) + ';0.9286;0.9714;1';
          const valsL = len + ';0;0;' + len + ';' + len;
          const dashL = len + ' ' + len;
          return (
            <path
              key={'segL-' + i}
              d={mkPathIn(i)}
              fill="none"
              stroke="var(--amber)"
              strokeWidth="2.5"
              strokeLinecap="butt"
              strokeDasharray={dashL}
              strokeDashoffset={len}
              pointerEvents="none"
            >
              <animate
                attributeName="stroke-dashoffset"
                values={valsL}
                keyTimes={ktL}
                calcMode="spline"
                keySplines="0.4 0 0.6 1; 0 0 1 1; 0.4 0 1 1; 0 0 1 1"
                dur={TOTAL + 's'}
                begin="0s"
                repeatCount="indefinite"
              />
            </path>
          );
        })}

        {/* Animated output lines: start when left phase ends, fade left-to-right */}
        {outputs.map((_, i) => {
          const len = outLens[i];
          const drawStart = LEFT_PHASE / TOTAL;
          const drawEnd = (LEFT_PHASE + RIGHT_PHASE * len / MAX_OUT) / TOTAL;
          const ktR = '0;' + drawStart.toFixed(4) + ';' + drawEnd.toFixed(4) + ';0.9286;0.9714;1';
          const valsR = len + ';' + len + ';0;0;' + len + ';' + len;
          const dashR = len + ' ' + len;
          return (
            <path
              key={'segR-' + i}
              d={mkPathOut(i)}
              fill="none"
              stroke="var(--amber)"
              strokeWidth="2.5"
              strokeLinecap="butt"
              strokeDasharray={dashR}
              strokeDashoffset={len}
              pointerEvents="none"
            >
              <animate
                attributeName="stroke-dashoffset"
                values={valsR}
                keyTimes={ktR}
                calcMode="spline"
                keySplines="0 0 1 1; 0.4 0 0.6 1; 0 0 1 1; 0.4 0 1 1; 0 0 1 1"
                dur={TOTAL + 's'}
                begin="0s"
                repeatCount="indefinite"
              />
            </path>
          );
        })}

        {/* Input nodes */}
        {inputs.map((inp, i) => {
          const x = COLS_X[i];
          const y = IN_Y;
          const cx = colCenter(i);
          return (
            <NodeShape key={`in-${i}`} x={x} y={y} w={NODE_W} h={NODE_H} className="df-input">
              {renderNode(inp, x, y)}
              <circle cx={cx} cy={y + NODE_H} r="3.5" fill="var(--amber)" opacity="0.3" pointerEvents="none">
                <animate
                  attributeName="opacity"
                  values="0.3;1;1;0.3;0.3"
                  keyTimes="0;0.3571;0.9286;0.9714;1"
                  calcMode="spline"
                  keySplines="0.4 0 0.6 1; 0 0 1 1; 0.4 0 1 1; 0 0 1 1"
                  dur={`${TOTAL}s`}
                  repeatCount="indefinite"
                />
              </circle>
            </NodeShape>
          );
        })}

        {/* Output nodes */}
        {outputs.map((out, i) => {
          const x = COLS_X[i];
          const y = OUT_Y;
          const cx = colCenter(i);
          return (
            <NodeShape key={`out-${i}`} x={x} y={y} w={NODE_W} h={NODE_H} className="df-output">
              {renderNode(out, x, y)}
              <circle cx={cx} cy={y} r="3.5" fill="var(--amber)" opacity="0.3" pointerEvents="none">
                <animate
                  attributeName="opacity"
                  values="0.3;0.3;1;1;0.3;0.3"
                  keyTimes="0;0.3571;0.7143;0.9286;0.9714;1"
                  calcMode="spline"
                  keySplines="0 0 1 1; 0.4 0 0.6 1; 0 0 1 1; 0.4 0 1 1; 0 0 1 1"
                  dur={`${TOTAL}s`}
                  repeatCount="indefinite"
                />
              </circle>
            </NodeShape>
          );
        })}

        {/* Central Światowid core, just a big logo inside the bracketed square */}
        <NodeShape x={CX} y={CY} w={CW} h={CH} highlight className="df-core">
          {[[CX, CY],[CX+CW,CY],[CX,CY+CH],[CX+CW,CY+CH]].map(([x,y], i) => {
            const dx = i % 2 === 0 ? 1 : -1;
            const dy = i < 2 ? 1 : -1;
            return (
              <g key={i}>
                <line x1={x} y1={y} x2={x + dx * 18} y2={y} stroke="var(--amber)" strokeWidth="2.5" />
                <line x1={x} y1={y} x2={x} y2={y + dy * 18} stroke="var(--amber)" strokeWidth="2.5" />
              </g>
            );
          })}
        </NodeShape>

        {/* Inline logo as native SVG <g>+<path>. Avoids foreignObject which
            mis-positions on iOS Safari (logo escapes the core box). */}
        {(() => {
          const inner = 32; // padding inside the core box
          const innerW = CW - inner * 2;
          const innerH = CH - inner * 2;
          const logoVb = { w: 534, h: 564 };
          const scale = Math.min(innerW / logoVb.w, innerH / logoVb.h);
          const drawW = logoVb.w * scale;
          const drawH = logoVb.h * scale;
          const tx = CX + inner + (innerW - drawW) / 2;
          const ty = CY + inner + (innerH - drawH) / 2;
          return (
            <g transform={`translate(${tx} ${ty}) scale(${scale})`} fill="var(--amber)" pointerEvents="none">
              <path d="M266.301 82.1228C379.837 76.4168 476.475 163.883 482.078 277.421C487.682 390.958 400.125 487.514 286.579 493.014C173.178 498.507 76.7697 411.09 71.1737 297.698C65.5777 184.306 152.91 87.8214 266.301 82.1228ZM212.66 467.374C212.227 454.066 212.736 440.555 212.489 427.226C212.451 425.148 212.403 422.841 212.501 420.782C202.662 420.174 191.758 421.121 182.362 420.466C178.009 416.929 174.096 412.118 170.023 408.329C165.951 404.541 165.083 402.788 165.369 397.247C165.215 377.87 165.671 358.391 165.247 339.024C161.691 338.979 142.346 339.658 140.937 337.949C139.043 335.652 140.934 328.819 141.468 326.05L151.964 273.879C154.238 262.275 156.59 247.937 159.418 236.61C155.936 236.893 146.842 236.863 143.191 236.723C143.067 229.637 143.03 222.55 143.08 215.463C143.081 211.82 142.932 205.311 143.365 201.914C148.075 196.707 156.303 190.144 161.863 185.537L190.451 162.03C197.312 156.477 204.097 150.832 210.805 145.095C213.697 142.587 217.458 138.744 220.213 136.62C225.981 136 237.692 136.38 244.052 136.394L287.31 136.377L314.754 136.361C317.496 136.355 330 135.903 331.825 137.103L332.253 137.382C334.575 138.914 339.505 143.481 341.894 145.524C347.703 150.459 353.536 155.365 359.395 160.241L387.932 183.815C394.939 189.575 402.925 195.988 409.481 202.227C409.645 203.729 409.723 205.172 409.694 206.683C409.502 216.641 409.924 226.688 409.532 236.63C405.573 236.701 396.496 236.957 392.839 236.608C396.888 256.864 400.832 277.14 404.671 297.436L409.467 321.771C410.293 326.013 411.129 330.288 411.807 334.555C412.552 339.241 407.132 338.75 404.21 338.686C398.419 338.559 392.648 338.731 386.927 338.556C387.265 357.17 386.715 375.873 386.953 394.495C387.017 399.546 387.803 403.17 383.729 406.849C379.167 410.967 374.581 416.836 369.751 420.517C359.872 420.598 349.992 420.614 340.113 420.564L340.083 450.4C340.074 455.674 340.248 462.072 340.072 467.253C348.334 464.163 356.409 460.596 364.257 456.57C403.203 436.409 434.175 403.657 452.13 363.648C472.181 317.485 473.124 265.258 454.753 218.401C436.495 171.333 400.211 133.494 353.948 113.278C330.429 102.963 305.021 97.6548 279.339 97.6905C275.154 97.661 269.93 97.5757 265.813 97.9014C214.259 100.64 165.991 124.06 131.937 162.861C100.2 198.845 82.6936 250.306 85.7189 298.159C88.4402 348.714 111.309 396.069 149.211 429.636C164.146 442.81 180.991 453.645 199.173 461.772C203.796 463.879 208.112 465.421 212.66 467.374ZM179.809 372.222C182.546 372.118 185.414 372.024 188.134 372.054C194.039 372.118 202.95 370.405 202.788 379.164C202.72 382.807 200.769 385.115 196.986 385.545C191.284 385.827 185.372 385.551 179.649 385.591C179.943 389.613 179.525 393.818 179.723 397.857C182.447 400.622 186.744 405.406 189.482 407.803C197.086 407.842 205.481 407.908 213.079 407.731C225.397 396.634 237.288 384.744 249.402 373.404C250.584 372.298 251.883 370.996 252.938 369.766C253.421 358.093 253.014 344.04 253.018 332.161L253.024 272.4C253.013 260.636 252.864 248.568 253.041 236.838C234.718 236.34 214.513 236.74 196.092 236.751L181.006 236.763C179.416 236.764 174.924 236.851 173.518 236.641C169.045 258.229 164.706 279.845 160.502 301.486C159.01 309.144 156.793 318.543 155.621 326.089C161.264 326.299 170.617 325.654 175.639 326.284C178.036 313.397 180.59 300.54 183.299 287.715C184.018 284.275 186.777 269.01 188.19 267.035C192.372 265.258 233.026 265.927 240.14 266.334C240.221 270.094 240.3 274.728 240.099 278.468C235.273 278.943 230.21 278.777 225.352 278.81C216.743 278.868 208.062 278.661 199.458 278.894C196.417 294.445 192.726 310.29 189.784 325.793C196.326 325.713 205.268 323.97 204.478 334.103C204.279 336.657 200.855 338.5 198.614 338.7C192.387 339.161 186.099 338.472 179.833 339.064C179.767 342.592 179.821 346.258 179.728 349.736L207.527 349.717C211.879 349.711 216.566 349.53 220.885 349.98C221.936 350.089 223.194 351.253 223.901 352.008C224.870 354.213 225.426 356.634 224.547 358.988C224.001 360.437 222.902 361.610 221.491 362.248C219.248 363.286 185.246 362.819 179.754 362.941L179.809 372.222ZM299.359 370.103C312.121 382.536 325.999 395.107 338.437 407.790C346.309 407.841 354.791 407.913 362.653 407.765C364.959 405.438 370.797 399.900 372.625 397.631L372.625 385.608C366.587 385.495 360.053 385.778 354.045 385.275C347.576 384.733 347.427 373.275 354.137 372.420C360.136 371.787 366.560 372.284 372.653 372.113C372.590 369.131 372.493 365.893 372.584 362.918C363.547 362.811 354.509 362.776 345.471 362.814C341.763 362.820 331.337 363.752 328.634 361.018C325.710 358.060 326.907 349.612 332.264 349.865C337.231 349.647 341.888 349.711 346.740 349.720L372.827 349.797C372.505 346.491 372.584 342.386 372.571 338.998C367.174 338.669 355.961 339.131 351.723 338.412C350.223 337.910 348.994 337.245 348.474 335.815C345.881 328.689 349.848 325.166 356.824 325.705C358.231 325.813 360.892 325.751 362.289 325.748C358.590 310.491 356.177 293.930 352.367 278.830C347.087 279.107 339.832 278.810 334.521 278.867C331.216 278.903 313.763 279.282 311.946 278.188C311.377 275.938 311.679 268.897 311.724 266.294C318.078 265.994 358.885 265.398 363.071 266.817C365.021 268.595 367.047 279.932 367.742 283.216L372.179 304.654L375.063 319.002C375.377 320.622 376.193 324.511 376.284 326.069L396.330 326.085L383.457 261.075C382.157 254.270 379.560 243.198 378.776 236.737L326.651 236.757L309.102 236.783C306.250 236.789 302.077 236.917 299.308 236.684C299.951 280.913 298.910 325.767 299.359 370.103ZM285.314 478.028C294.446 477.592 302.554 476.875 311.562 475.054C316.385 474.080 321.081 472.822 325.871 471.721C325.263 453.366 325.929 433.042 325.769 414.431C315.972 404.853 305.249 395.876 295.384 386.341C293.210 384.240 286.410 378.612 284.831 376.709C284.255 358.725 284.636 338.796 284.670 320.691L284.620 236.472C279.518 236.519 272.459 236.701 267.474 236.457L267.493 325.171L267.523 358.893C267.517 364.688 267.666 371.536 267.383 377.216C263.684 380.288 260.107 383.746 256.521 386.977L226.553 414.508L226.503 451.647C226.505 457.453 226.249 466.060 226.670 471.707C234.958 473.639 242.704 475.715 251.200 476.781C262.367 478.183 274.059 478.290 285.314 478.028ZM258.476 150.500C248.123 150.504 236.438 150.256 226.215 150.670C221.160 154.272 215.291 160.010 210.297 164.088C192.795 178.381 175.656 193.559 157.540 207.095C157.452 212.690 157.463 218.286 157.574 223.880L295.091 223.850L361.862 223.869L384.021 223.874C387.540 223.874 391.970 223.738 395.403 223.890C395.397 218.749 395.284 213.178 395.437 208.071C382.446 197.761 369.578 187.296 356.837 176.678L339.480 162.108C335.036 158.305 330.615 154.237 326.073 150.582L258.476 150.500Z" />
            </g>
          );
        })()}
      </svg>
    </div>
  );
}

Object.assign(window, { DataflowDiagram });
