/* ═══════════════════════════════════════════════════════════════════
   Brand: PoligusMark, PoligusLogo, IconSet, CinematicBackdrop, Particles
   ═══════════════════════════════════════════════════════════════════ */

/* ── PREMIUM ICON SET (stroke-based SVGs replacing all emojis) ────── */
const Icon = ({ name, size = 22, stroke = 1.5, color = "currentColor" }) => {
  const p = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: stroke, strokeLinecap: "round", strokeLinejoin: "round" };
  const paths = {
    bolt:        <><path d="M13 2L4 14h7l-1 8 9-12h-7l1-8z" /></>,
    chart:       <><path d="M3 3v18h18" /><path d="M7 14l4-4 4 4 5-5" /></>,
    target:      <><circle cx="12" cy="12" r="9" /><circle cx="12" cy="12" r="5" /><circle cx="12" cy="12" r="1.5" fill={color} /></>,
    rocket:      <><path d="M4.5 16.5c-1.5 1.5-2 5-2 5s3.5-.5 5-2c.85-.85.85-2.15 0-3-.85-.85-2.15-.85-3 0z" /><path d="M14 18l3-3 4-4c.66-.66 1-1.66 1-3 0-3-3-6-6-6-1.33 0-2.33.33-3 1l-4 4-3 3" /><path d="M9 11l4 4" /><circle cx="15.5" cy="8.5" r="1" fill={color} /></>,
    search:      <><circle cx="11" cy="11" r="7" /><path d="m21 21-4.3-4.3" /></>,
    layers:      <><path d="m12 2 10 5-10 5L2 7l10-5z" /><path d="m2 12 10 5 10-5" /><path d="m2 17 10 5 10-5" /></>,
    gear:        <><circle cx="12" cy="12" r="3" /><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" /></>,
    handshake:   <><path d="M11 17l-5-5a2.83 2.83 0 0 1 4-4l1 1 1-1a2.83 2.83 0 0 1 4 4l-2 2" /><path d="M16 14l3 3" /><path d="M14 16l2.5 2.5" /><path d="M12 18l2 2" /></>,
    shield:      <><path d="M12 2 4 5v6c0 5 4 9 8 11 4-2 8-6 8-11V5z" /><path d="m9 12 2 2 4-4" /></>,
    chat:        <><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8z" /></>,
    site:        <><rect x="3" y="3" width="18" height="18" rx="2" /><path d="M3 9h18" /><circle cx="6.5" cy="6" r="0.5" fill={color} /><circle cx="9" cy="6" r="0.5" fill={color} /></>,
    dashboard:   <><rect x="3" y="3" width="7" height="9" rx="1" /><rect x="14" y="3" width="7" height="5" rx="1" /><rect x="14" y="12" width="7" height="9" rx="1" /><rect x="3" y="16" width="7" height="5" rx="1" /></>,
    megaphone:   <><path d="m3 11 18-5v12L3 13v-2z" /><path d="M11.6 16.8a3 3 0 1 1-5.8-1.6" /></>,
    repeat:      <><path d="m17 1 4 4-4 4" /><path d="M3 11V9a4 4 0 0 1 4-4h14" /><path d="m7 23-4-4 4-4" /><path d="M21 13v2a4 4 0 0 1-4 4H3" /></>,
    cpu:         <><rect x="4" y="4" width="16" height="16" rx="2" /><rect x="9" y="9" width="6" height="6" /><path d="M9 1v3M15 1v3M9 20v3M15 20v3M20 9h3M20 14h3M1 9h3M1 14h3" /></>,
    sparkle:     <><path d="M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M5.6 18.4l2.1-2.1M16.3 7.7l2.1-2.1" /><circle cx="12" cy="12" r="2" fill={color} /></>,
    arrowRight:  <><path d="M5 12h14M13 5l7 7-7 7" /></>,
    check:       <><path d="M5 12l5 5 9-12" /></>,
    plus:        <><path d="M12 5v14M5 12h14" /></>,
    calendar:    <><rect x="3" y="4" width="18" height="18" rx="2" /><path d="M16 2v4M8 2v4M3 10h18" /></>,
    mic:         <><rect x="9" y="2" width="6" height="12" rx="3" /><path d="M5 10a7 7 0 0 0 14 0M12 19v3" /></>,
    whatsapp:    <path stroke="none" fill={color} d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.148-.198.297-.768.967-.942 1.165-.174.198-.348.223-.645.074-.297-.149-1.255-.462-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.174-.297-.019-.458.13-.606.133-.133.297-.347.446-.52.148-.174.198-.297.297-.495.099-.198.05-.371-.025-.52-.074-.148-.67-1.614-.918-2.21-.248-.595-.5-.495-.67-.495h-.57c-.198 0-.52.074-.793.371-.273.297-1.04 1.016-1.04 2.478 0 1.462 1.065 2.875 1.213 3.074.148.198 2.095 3.199 5.076 4.485 2.981 1.286 2.981.857 3.518.804.537-.053 1.758-.719 2.006-1.413.248-.694.248-1.288.174-1.412-.074-.124-.272-.198-.569-.347zM12.05 21.785h-.004a9.87 9.87 0 0 1-5.031-1.378l-.36-.214-3.741.982 1-3.648-.235-.374a9.86 9.86 0 0 1-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 0 1 2.893 6.994c-.003 5.45-4.437 9.884-9.888 9.884zm8.413-18.297A11.815 11.815 0 0 0 12.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 0 0 5.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 0 0-3.48-8.413z" />,
  };
  return <svg {...p}>{paths[name] || paths.sparkle}</svg>;
};

const WhatsAppIcon = ({ size = 20 }) => <Icon name="whatsapp" size={size} />;

/* ── CINEMATIC CIRCUIT BACKDROP — full SVG, animated data pulses ──── */
const CircuitBackdrop = ({ size = 520, opacity = 1 }) => {
  const id = React.useId();
  const V = 800;
  return (
    <svg width={size} height={size} viewBox={`0 0 ${V} ${V}`}
      style={{ position: "absolute", inset: 0, margin: "auto", pointerEvents: "none", opacity }}
      aria-hidden="true">
      <defs>
        <radialGradient id={`${id}-chip`} cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor="#7DD3FF" stopOpacity="0.55" />
          <stop offset="50%" stopColor="#2B7BFF" stopOpacity="0.22" />
          <stop offset="100%" stopColor="#2B7BFF" stopOpacity="0" />
        </radialGradient>
        <linearGradient id={`${id}-pulse`} x1="0" y1="0" x2="1" y2="0">
          <stop offset="0%" stopColor="#7DD3FF" stopOpacity="0" />
          <stop offset="50%" stopColor="#A8E4FF" stopOpacity="1" />
          <stop offset="100%" stopColor="#7DD3FF" stopOpacity="0" />
        </linearGradient>
        <filter id={`${id}-blur`} x="-20%" y="-20%" width="140%" height="140%"><feGaussianBlur stdDeviation="2.5" /></filter>
        <radialGradient id={`${id}-mask`} cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor="white" stopOpacity="1" />
          <stop offset="60%" stopColor="white" stopOpacity="1" />
          <stop offset="92%" stopColor="white" stopOpacity="0.25" />
          <stop offset="100%" stopColor="white" stopOpacity="0" />
        </radialGradient>
        <mask id={`${id}-disk`}><rect x="0" y="0" width={V} height={V} fill={`url(#${id}-mask)`} /></mask>
      </defs>

      <g mask={`url(#${id}-disk)`}>
        {/* grid */}
        <g opacity="0.18">
          {Array.from({ length: 21 }).map((_, i) => <line key={`v${i}`} x1={i * 40} y1="0" x2={i * 40} y2={V} stroke="#7DD3FF" strokeWidth="0.4" />)}
          {Array.from({ length: 21 }).map((_, i) => <line key={`h${i}`} x1="0" y1={i * 40} x2={V} y2={i * 40} stroke="#7DD3FF" strokeWidth="0.4" />)}
        </g>

        {/* hex dots */}
        <g opacity="0.6">
          {Array.from({ length: 14 }).map((_, r) =>
            Array.from({ length: 14 }).map((_, c) => {
              const cx = 30 + c * 58 + (r % 2 ? 29 : 0);
              const cy = 50 + r * 56;
              if (Math.hypot(cx - V/2, cy - V/2) < 180) return null;
              const accent = ((r * 31 + c * 17) % 9 === 0);
              return <circle key={`d${r}-${c}`} cx={cx} cy={cy} r={accent ? 2 : 1} fill={accent ? "#A8E4FF" : "#7DD3FF"} opacity={accent ? 0.85 : 0.4} />;
            })
          )}
        </g>

        {/* octagonal bus */}
        <g fill="none" strokeLinecap="round" strokeLinejoin="round">
          <path d="M 60 200 L 60 600 L 200 740 L 600 740 L 740 600 L 740 200 L 600 60 L 200 60 Z" stroke="#7DD3FF" strokeOpacity="0.35" strokeWidth="1.2" />
          <path d="M 110 240 L 110 560 L 240 690 L 560 690 L 690 560 L 690 240 L 560 110 L 240 110 Z" stroke="#A8E4FF" strokeOpacity="0.28" strokeWidth="1" strokeDasharray="6 6">
            <animate attributeName="stroke-dashoffset" from="0" to="-120" dur="9s" repeatCount="indefinite" />
          </path>

          {/* radial branches */}
          {[
            "M 400 60 L 400 140 L 460 200",
            "M 600 60 L 600 130 L 540 190 L 540 250",
            "M 740 200 L 660 200 L 600 260",
            "M 740 400 L 660 400 L 620 360",
            "M 740 600 L 660 600 L 600 540",
            "M 600 740 L 600 670 L 540 610 L 540 560",
            "M 400 740 L 400 660 L 460 600",
            "M 200 740 L 200 670 L 260 610 L 260 560",
            "M 60 600 L 140 600 L 200 540",
            "M 60 400 L 140 400 L 180 360",
            "M 60 200 L 140 200 L 200 260",
            "M 200 60 L 200 130 L 260 190 L 260 250",
          ].map((d, i) => (
            <path key={`r${i}`} d={d}
              stroke={i % 3 === 0 ? "#A8E4FF" : i % 3 === 1 ? "#7DD3FF" : "#8C5BFF"}
              strokeOpacity={i % 3 === 2 ? 0.5 : 0.75}
              strokeWidth={i % 3 === 0 ? 1.6 : 1.1} />
          ))}

          {/* travelling data pulses */}
          {[
            { d: "M 60 200 L 60 600 L 200 740 L 600 740 L 740 600 L 740 200 L 600 60 L 200 60 Z", dur: "5s", delay: "0s" },
            { d: "M 110 240 L 110 560 L 240 690 L 560 690 L 690 560 L 690 240 L 560 110 L 240 110 Z", dur: "7s", delay: "1.5s" },
          ].map((p, i) => (
            <circle key={`pulse${i}`} r="3.5" fill="#A8E4FF" filter={`url(#${id}-blur)`}>
              <animateMotion dur={p.dur} repeatCount="indefinite" begin={p.delay}><mpath href={`#${id}-path${i}`} /></animateMotion>
            </circle>
          ))}
          <path id={`${id}-path0`} d="M 60 200 L 60 600 L 200 740 L 600 740 L 740 600 L 740 200 L 600 60 L 200 60 Z" fill="none" />
          <path id={`${id}-path1`} d="M 110 240 L 110 560 L 240 690 L 560 690 L 690 560 L 690 240 L 560 110 L 240 110 Z" fill="none" />

          <path d="M 60 480 L 240 480 L 320 400" stroke="#A8E4FF" strokeOpacity="0.6" strokeWidth="1" strokeDasharray="3 7">
            <animate attributeName="stroke-dashoffset" from="0" to="-200" dur="6s" repeatCount="indefinite" />
          </path>
          <path d="M 740 320 L 560 320 L 480 240" stroke="#7DD3FF" strokeOpacity="0.55" strokeWidth="1" strokeDasharray="3 7">
            <animate attributeName="stroke-dashoffset" from="0" to="-200" dur="7s" repeatCount="indefinite" />
          </path>
        </g>

        {/* chip pads */}
        <g>
          {[[60,100],[60,300],[60,500],[60,700],[740,100],[740,300],[740,500],[740,700],[100,60],[300,60],[500,60],[700,60],[100,740],[300,740],[500,740],[700,740]].map(([x,y], i) => (
            <g key={`p${i}`}>
              <rect x={x-7} y={y-3} width="14" height="6" rx="1.2" fill="rgba(43,123,255,0.18)" stroke="#7DD3FF" strokeOpacity="0.7" strokeWidth="0.8" />
              <circle cx={x} cy={y} r="1.8" fill="#A8E4FF">
                <animate attributeName="opacity" values="0.35;1;0.35" dur={`${2 + (i % 4) * 0.4}s`} repeatCount="indefinite" begin={`${(i % 6) * 0.3}s`} />
              </circle>
            </g>
          ))}
        </g>

        {/* solder junctions */}
        <g>
          {[[200,200,"#A8E4FF"],[600,200,"#7DD3FF"],[200,600,"#8C5BFF"],[600,600,"#A8E4FF"],[400,110,"#7DD3FF"],[110,400,"#A8E4FF"],[690,400,"#8C5BFF"],[400,690,"#7DD3FF"]].map(([x,y,c], i) => (
            <g key={`j${i}`}>
              <circle cx={x} cy={y} r="7" fill="none" stroke={c} strokeOpacity="0.7" strokeWidth="0.9" />
              <circle cx={x} cy={y} r="2.8" fill={c}>
                <animate attributeName="r" values="2;3.8;2" dur={`${3 + i*0.3}s`} repeatCount="indefinite" />
              </circle>
            </g>
          ))}
        </g>

        {/* central halo */}
        <circle cx={V/2} cy={V/2} r="260" fill={`url(#${id}-chip)`} />
      </g>
    </svg>
  );
};

/* ── PCB SHEET BACKDROP — full-width, scrolls behind hero ────────── */
const PcbSheet = ({ opacity = 0.7 }) => {
  const id = React.useId();
  return (
    <svg viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice"
      style={{ position: "absolute", inset: 0, width: "100%", height: "100%", pointerEvents: "none", opacity }}
      aria-hidden="true">
      <defs>
        <linearGradient id={`${id}-trace`} x1="0" y1="0" x2="1" y2="0">
          <stop offset="0%" stopColor="#7DD3FF" stopOpacity="0" />
          <stop offset="50%" stopColor="#A8E4FF" stopOpacity="0.95" />
          <stop offset="100%" stopColor="#7DD3FF" stopOpacity="0" />
        </linearGradient>
        <filter id={`${id}-blur`}><feGaussianBlur stdDeviation="3" /></filter>
        <linearGradient id={`${id}-fade`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="white" stopOpacity="0" />
          <stop offset="30%" stopColor="white" stopOpacity="1" />
          <stop offset="70%" stopColor="white" stopOpacity="1" />
          <stop offset="100%" stopColor="white" stopOpacity="0" />
        </linearGradient>
        <mask id={`${id}-fadeMask`}><rect width="1600" height="900" fill={`url(#${id}-fade)`} /></mask>
      </defs>

      <g mask={`url(#${id}-fadeMask)`} fill="none" strokeLinecap="round" strokeLinejoin="round">
        {/* horizontal traces */}
        {[120, 220, 340, 460, 600, 720, 820].map((y, i) => (
          <g key={`row${i}`}>
            <path d={`M 0 ${y} L 240 ${y} L 320 ${y - 40} L 720 ${y - 40} L 800 ${y} L 1080 ${y} L 1160 ${y + 50} L 1480 ${y + 50} L 1600 ${y}`} stroke="#7DD3FF" strokeOpacity="0.15" strokeWidth="1" />
            <path id={`${id}-row${i}`} d={`M 0 ${y} L 240 ${y} L 320 ${y - 40} L 720 ${y - 40} L 800 ${y} L 1080 ${y} L 1160 ${y + 50} L 1480 ${y + 50} L 1600 ${y}`} fill="none" />
            <circle r="4" fill="#A8E4FF" filter={`url(#${id}-blur)`}>
              <animateMotion dur={`${10 + i * 1.5}s`} repeatCount="indefinite" begin={`${i * 1.2}s`}>
                <mpath href={`#${id}-row${i}`} />
              </animateMotion>
            </circle>
          </g>
        ))}
        {/* vertical traces */}
        {[180, 380, 580, 780, 980, 1180, 1380].map((x, i) => (
          <g key={`col${i}`}>
            <path d={`M ${x} 0 L ${x} 200 L ${x + 40} 240 L ${x + 40} 460 L ${x - 30} 500 L ${x - 30} 720 L ${x} 760 L ${x} 900`} stroke="#7DD3FF" strokeOpacity="0.10" strokeWidth="1" />
          </g>
        ))}
        {/* solder joints */}
        {[[240,120],[720,80],[800,460],[1080,460],[1160,510],[320,180],[380,380],[980,720]].map(([x,y], i) => (
          <g key={`sj${i}`}>
            <circle cx={x} cy={y} r="6" fill="none" stroke="#7DD3FF" strokeOpacity="0.4" />
            <circle cx={x} cy={y} r="2.5" fill="#A8E4FF">
              <animate attributeName="opacity" values="0.3;1;0.3" dur={`${3 + i * 0.4}s`} repeatCount="indefinite" />
            </circle>
          </g>
        ))}
        {/* chip rect */}
        <rect x="600" y="380" width="160" height="120" rx="6" fill="rgba(43,123,255,0.05)" stroke="#7DD3FF" strokeOpacity="0.3" />
        <text x="680" y="450" textAnchor="middle" fill="#7DD3FF" fillOpacity="0.45" fontFamily="JetBrains Mono, monospace" fontSize="13" letterSpacing="2">POLIGUS-AI</text>
      </g>
    </svg>
  );
};

/* ── REAL-TIME 3D POLIGUS SPHERE (Three.js / WebGL) ──────────────────
   Núcleo geodésico facetado (facetas em gradiente da marca), arestas
   incandescentes, atmosfera fresnel, nós que pulsam, partículas de
   dados em órbita. Reage ao ponteiro e ao scroll. Faz fallback para
   a imagem da marca quando WebGL não está disponível. */
function makeGlowTexture(THREE, soft) {
  var s = 128, c = document.createElement("canvas"); c.width = c.height = s;
  var ctx = c.getContext("2d");
  var g = ctx.createRadialGradient(s/2, s/2, 0, s/2, s/2, s/2);
  if (soft) {
    g.addColorStop(0,    "rgba(220,240,255,0.55)");
    g.addColorStop(0.16, "rgba(150,210,255,0.26)");
    g.addColorStop(0.42, "rgba(125,211,255,0.07)");
    g.addColorStop(1,    "rgba(125,211,255,0)");
  } else {
    g.addColorStop(0,    "rgba(255,255,255,1)");
    g.addColorStop(0.25, "rgba(190,235,255,0.7)");
    g.addColorStop(0.55, "rgba(125,211,255,0.25)");
    g.addColorStop(1,    "rgba(125,211,255,0)");
  }
  ctx.fillStyle = g; ctx.fillRect(0, 0, s, s);
  var tex = new THREE.CanvasTexture(c);
  tex.minFilter = THREE.LinearFilter;
  return tex;
}

function createPoligusSphere(container, opts) {
  opts = opts || {};
  var THREE = window.THREE;
  if (!THREE || !container) return null;

  var detail  = opts.detail != null ? opts.detail : 1;
  var reduced = !!opts.reduced;

  var renderer;
  try {
    renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, powerPreference: "high-performance" });
  } catch (e) { return null; }
  if (!renderer || !renderer.getContext()) return null;
  renderer.setClearColor(0x000000, 0);
  renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
  var cv = renderer.domElement;
  cv.style.width = "100%"; cv.style.height = "100%"; cv.style.display = "block"; cv.style.cursor = "grab";
  container.appendChild(cv);

  var scene  = new THREE.Scene();
  var camera = new THREE.PerspectiveCamera(42, 1, 0.1, 100);
  camera.position.set(0, 0, 4.7);

  var root = new THREE.Group();   // tilt by input + scroll
  var spin = new THREE.Group();   // continuous auto-spin
  root.add(spin); scene.add(root);

  var R = 1.5;
  var BLUE = new THREE.Color(0x2B7BFF), CYAN = new THREE.Color(0xA8E4FF),
      DEEP = new THREE.Color(0x0E2A6B), VIOLET = new THREE.Color(0x8C5BFF);

  /* faceted gem — gem-like facets in the brand gradient */
  var baseGeo = new THREE.IcosahedronGeometry(R, detail);
  var gemGeo = baseGeo.index ? baseGeo.toNonIndexed() : baseGeo.clone();
  var posAttr = gemGeo.getAttribute("position");
  var nFaces  = posAttr.count / 3;
  var colArr  = new Float32Array(posAttr.count * 3);
  var a = new THREE.Vector3(), b = new THREE.Vector3(), cc = new THREE.Vector3(), cen = new THREE.Vector3(), col = new THREE.Color();
  for (var f = 0; f < nFaces; f++) {
    var i0 = f * 3;
    a.fromBufferAttribute(posAttr, i0); b.fromBufferAttribute(posAttr, i0 + 1); cc.fromBufferAttribute(posAttr, i0 + 2);
    cen.copy(a).add(b).add(cc).multiplyScalar(1 / 3);
    var t  = (cen.y / R) * 0.5 + 0.5;
    var az = (Math.atan2(cen.z, cen.x) / Math.PI) * 0.5 + 0.5;
    if (t < 0.5) col.copy(DEEP).lerp(BLUE, t * 2);
    else         col.copy(BLUE).lerp(CYAN, (t - 0.5) * 2);
    col.lerp(VIOLET, az * 0.26);
    var r = (Math.sin(f * 127.1 + 311.7) * 43758.5453); r = r - Math.floor(r);
    col.multiplyScalar(0.8 + r * 0.45);
    for (var k = 0; k < 3; k++) { colArr[(i0 + k) * 3] = col.r; colArr[(i0 + k) * 3 + 1] = col.g; colArr[(i0 + k) * 3 + 2] = col.b; }
  }
  gemGeo.setAttribute("color", new THREE.BufferAttribute(colArr, 3));
  gemGeo.computeVertexNormals();
  var gemMat = new THREE.MeshStandardMaterial({
    vertexColors: true, flatShading: true, metalness: 0.85, roughness: 0.32,
    emissive: new THREE.Color(0x0a1a44), emissiveIntensity: 0.5
  });
  var gem = new THREE.Mesh(gemGeo, gemMat); spin.add(gem);

  /* glowing wireframe */
  var edges = new THREE.EdgesGeometry(baseGeo, 1);
  var edgeMat = new THREE.LineBasicMaterial({ color: 0x9fe6ff, transparent: true, opacity: 0.32, blending: THREE.AdditiveBlending });
  var wire = new THREE.LineSegments(edges, edgeMat); wire.scale.setScalar(1.006); spin.add(wire);

  /* glow texture (shared with orbiting particles) */
  var nodeTex = makeGlowTexture(THREE);

  /* fresnel atmosphere */
  var atmMat = new THREE.ShaderMaterial({
    transparent: true, blending: THREE.AdditiveBlending, side: THREE.BackSide, depthWrite: false,
    uniforms: { uColor: { value: new THREE.Color(0x4aa8ff) }, uPower: { value: 3.6 }, uIntensity: { value: 0.72 } },
    vertexShader: "varying vec3 vN; varying vec3 vP; void main(){ vN=normalize(normalMatrix*normal); vec4 mv=modelViewMatrix*vec4(position,1.0); vP=mv.xyz; gl_Position=projectionMatrix*mv; }",
    fragmentShader: "varying vec3 vN; varying vec3 vP; uniform vec3 uColor; uniform float uPower; uniform float uIntensity; void main(){ vec3 v=normalize(-vP); float fr=pow(1.0-max(dot(vN,v),0.0),uPower); gl_FragColor=vec4(uColor*fr*uIntensity, fr); }"
  });
  var atm = new THREE.Mesh(new THREE.SphereGeometry(R * 1.06, 48, 48), atmMat); root.add(atm);

  /* soft bloom halo */
  var haloMat = new THREE.SpriteMaterial({ map: makeGlowTexture(THREE, 0.5), color: 0x3A8BFF, transparent: true, blending: THREE.AdditiveBlending, depthWrite: false, opacity: 0.16 });
  var halo = new THREE.Sprite(haloMat); halo.scale.setScalar(R * 2.0); scene.add(halo);

  /* orbiting data particles */
  var pCount = reduced ? 60 : 150;
  var pGeo = new THREE.BufferGeometry(); var pPos = new Float32Array(pCount * 3);
  for (var i = 0; i < pCount; i++) {
    var rr = R * (1.12 + Math.random() * 0.55);
    var th = Math.random() * Math.PI * 2, ph = Math.acos(2 * Math.random() - 1);
    pPos[i*3] = rr * Math.sin(ph) * Math.cos(th);
    pPos[i*3+1] = rr * Math.cos(ph) * 0.62;
    pPos[i*3+2] = rr * Math.sin(ph) * Math.sin(th);
  }
  pGeo.setAttribute("position", new THREE.BufferAttribute(pPos, 3));
  var pMat = new THREE.PointsMaterial({ size: 0.05, map: nodeTex, transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, color: 0x7DD3FF, opacity: 0.8 });
  var parts = new THREE.Points(pGeo, pMat); root.add(parts);

  /* lights */
  scene.add(new THREE.AmbientLight(0x2a4a86, 1.05));
  var key  = new THREE.DirectionalLight(0xBFEAFF, 2.4); key.position.set(2.5, 3, 2.5); scene.add(key);
  var rim  = new THREE.DirectionalLight(0x2B7BFF, 1.8); rim.position.set(-3, -1.5, -2); scene.add(rim);
  var fill = new THREE.PointLight(0x8C5BFF, 1.3, 14); fill.position.set(-1.5, 1.5, 3); scene.add(fill);

  /* interaction */
  var tx = 0, ty = 0, cx = 0, cy = 0, hover = 0, hoverT = 0;
  /* drag state (mouse + touch) with momentum */
  var dragging = false, lastX = 0, lastY = 0;
  var velY = 0, velX = 0;        // angular velocity carried after release
  var manualTiltX = 0;           // accumulated vertical tilt from drag
  function clampTilt(v) { return v < -0.7 ? -0.7 : (v > 0.7 ? 0.7 : v); }

  function onMove(e) {
    var r = container.getBoundingClientRect();
    var mx = (e.clientX - r.left) / r.width, my = (e.clientY - r.top) / r.height;
    tx = (my - 0.5) * 0.9; ty = (mx - 0.5) * 1.4;
  }
  function onEnter() { hoverT = 1; }
  function onLeave() { hoverT = 0; tx *= 0.3; ty *= 0.3; }

  function dragStart(x, y) { dragging = true; lastX = x; lastY = y; velY = 0; velX = 0; hoverT = 1; }
  function dragMove(x, y) {
    if (!dragging) return;
    var dx = x - lastX, dy = y - lastY;
    lastX = x; lastY = y;
    velY = dx * 0.009;
    velX = dy * 0.006;
    spin.rotation.y += velY;               // 1:1 response while dragging
    manualTiltX = clampTilt(manualTiltX + velX);
  }
  function dragEnd() { dragging = false; hoverT = 0; }

  function onTouchStart(e) { if (e.touches && e.touches[0]) dragStart(e.touches[0].clientX, e.touches[0].clientY); }
  function onTouchMove(e)  {
    if (e.touches && e.touches[0]) {
      if (dragging && e.cancelable) e.preventDefault();   // gira a esfera sem rolar a página
      dragMove(e.touches[0].clientX, e.touches[0].clientY);
    }
  }

  window.addEventListener("mousemove", onMove, { passive: true });
  container.addEventListener("mouseenter", onEnter);
  container.addEventListener("mouseleave", onLeave);
  container.addEventListener("touchstart", onTouchStart, { passive: true });
  container.addEventListener("touchmove", onTouchMove, { passive: false });
  container.addEventListener("touchend", dragEnd, { passive: true });
  container.addEventListener("touchcancel", dragEnd, { passive: true });

  function resize() {
    var w = container.clientWidth || 1, h = container.clientHeight || 1;
    renderer.setSize(w, h, false);
    camera.aspect = w / h; camera.updateProjectionMatrix();
  }
  var ro = (typeof ResizeObserver !== "undefined") ? new ResizeObserver(resize) : null;
  if (ro) ro.observe(container); else window.addEventListener("resize", resize);
  resize();

  var raf = 0, t0 = performance.now();
  var isTouch = (typeof window !== "undefined") && (("ontouchstart" in window) || ((navigator.maxTouchPoints || 0) > 0));
  var baseSpeed = reduced ? 0.02 : (isTouch ? 0.30 : 0.14);
  function frame(now) {
    raf = requestAnimationFrame(frame);
    if (container.clientWidth === 0 || container.clientHeight === 0) return;
    var dt = Math.min((now - t0) / 1000, 0.05); t0 = now;
    var ts = now * 0.001;
    hover += (hoverT - hover) * Math.min(dt * 6, 1);
    cx += (tx - cx) * Math.min(dt * 4, 1);
    cy += (ty - cy) * Math.min(dt * 4, 1);
    var scroll = (window.scrollY || 0) * 0.0006;
    /* momentum after releasing the drag */
    if (!dragging) {
      if (velY * velY + velX * velX > 1e-8) {
        spin.rotation.y += velY; velY *= 0.94;
        manualTiltX = clampTilt(manualTiltX + velX); velX *= 0.94;
      }
      manualTiltX *= 0.985;   // slowly recenter the vertical tilt
    }
    spin.rotation.y += dt * (baseSpeed + hover * 0.28);
    spin.rotation.x = Math.sin(ts * 0.2) * 0.05;
    root.rotation.x = cx + scroll * 0.4 + manualTiltX;
    root.rotation.y = cy * 0.6;
    edgeMat.opacity = 0.26 + Math.sin(ts * 1.3) * 0.06 + hover * 0.18;
    haloMat.opacity = 0.13 + Math.sin(ts * 1.1) * 0.04 + hover * 0.08;
    gemMat.emissiveIntensity = 0.45 + Math.sin(ts * 1.5) * 0.08 + hover * 0.18;
    parts.rotation.y -= dt * 0.05; parts.rotation.x = Math.sin(ts * 0.15) * 0.1;
    renderer.render(scene, camera);
  }
  raf = requestAnimationFrame(frame);

  return {
    destroy: function () {
      cancelAnimationFrame(raf);
      window.removeEventListener("mousemove", onMove);
      container.removeEventListener("mouseenter", onEnter);
      container.removeEventListener("mouseleave", onLeave);
      container.removeEventListener("touchstart", onTouchStart);
      container.removeEventListener("touchmove", onTouchMove);
      container.removeEventListener("touchend", dragEnd);
      container.removeEventListener("touchcancel", dragEnd);
      if (ro) ro.disconnect(); else window.removeEventListener("resize", resize);
      [gemGeo, baseGeo, edges, pGeo, atm.geometry, nodeTex, haloMat.map].forEach(function (o) { try { o && o.dispose && o.dispose(); } catch (_) {} });
      [gemMat, edgeMat, atmMat, pMat, haloMat].forEach(function (m) { try { m && m.dispose && m.dispose(); } catch (_) {} });
      try { renderer.dispose(); } catch (_) {}
      if (cv && cv.parentNode) cv.parentNode.removeChild(cv);
    }
  };
}

/* ── POLIGUS LOGO (3D-feeling sphere with rotating energy rings) ────── */
const PoligusMark = ({ size = 56, animated = false, glow = true }) => (
  <div style={{
    width: size, height: size, position: "relative", flexShrink: 0,
    animation: animated ? "float 6s ease-in-out infinite" : "none",
  }}>
    <div style={{ position: "absolute", inset: 0, animation: glow ? "glow-pulse 3.5s ease-in-out infinite" : "none" }}>
      <img src={(typeof window !== "undefined" && window.__resources && window.__resources.poligusSphere) || "assets/poligus-sphere.jpeg"} alt="Poligus"
        style={{ width: "100%", height: "100%", borderRadius: "50%", display: "block", mixBlendMode: "screen" }} />
    </div>
  </div>
);

/* ── POLIGUS SPHERE 3D (React wrapper around the WebGL engine) ── */
const PoligusSphere3D = ({ size = 320, detail = 1, className = "", style = {} }) => {
  const ref = React.useRef(null);
  const [failed, setFailed] = React.useState(false);
  React.useEffect(() => {
    if (!ref.current) return;
    if (typeof window === "undefined" || !window.THREE || !window.createPoligusSphere) { setFailed(true); return; }
    const reduced = !!(window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches);
    let inst = null, cancelled = false, raf1 = 0, raf2 = 0, to = 0;
    const start = () => {
      if (cancelled || !ref.current) return;
      try { inst = window.createPoligusSphere(ref.current, { detail, reduced }); } catch (e) { inst = null; }
      if (!inst) setFailed(true);
    };
    // defer heavy WebGL build so the hero text paints + reveals fire first
    to = setTimeout(() => { raf1 = requestAnimationFrame(() => { raf2 = requestAnimationFrame(start); }); }, 90);
    return () => {
      cancelled = true; clearTimeout(to); cancelAnimationFrame(raf1); cancelAnimationFrame(raf2);
      if (inst) { try { inst.destroy(); } catch (e) {} }
    };
  }, [detail]);

  if (failed) {
    return (
      <div style={{ width: size, height: size, position: "relative", display: "flex", alignItems: "center", justifyContent: "center", ...style }}>
        <PoligusMark size={Math.round(size * 0.62)} animated />
      </div>
    );
  }
  return <div ref={ref} className={"poligus-sphere-3d " + className}
    style={{ width: size, height: size, position: "relative", filter: "drop-shadow(0 18px 60px rgba(43,123,255,0.35))", ...style }} />;
};

/* ── POLIGUS WORDMARK (premium tracking, gradient blend) ────────────── */
const PoligusLogo = ({ height = 44 }) => {
  const sphereSize = height;
  const titleSize = Math.round(height * 0.62);
  const subSize = Math.round(height * 0.205);
  return (
    <div style={{ display: "inline-flex", alignItems: "center", gap: Math.round(height * 0.34), lineHeight: 1, userSelect: "none" }}>
      <PoligusMark size={sphereSize} glow />
      <div style={{ display: "flex", flexDirection: "column", justifyContent: "center" }}>
        <div style={{
          fontFamily: "var(--font-display)", fontWeight: 600, fontSize: titleSize,
          letterSpacing: "-0.02em", lineHeight: 0.95,
          background: "linear-gradient(180deg, #FFFFFF 0%, #A8E4FF 100%)",
          WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent", backgroundClip: "text",
        }}>Poligus</div>
        <div style={{
          fontFamily: "var(--font-mono)", fontWeight: 500, fontSize: subSize,
          letterSpacing: 3, textTransform: "uppercase",
          color: "rgba(125,224,255,0.7)",
          marginTop: Math.max(3, height * 0.10), whiteSpace: "nowrap",
        }}>IA · PARA · WHATSAPP</div>
      </div>
    </div>
  );
};

/* ── Particles (small drifting dots) ─────────────────────────────── */
const Particles = ({ density = 22 }) => {
  const particles = React.useMemo(() => Array.from({ length: density }, (_, i) => ({
    id: i, x: Math.random() * 100, size: Math.random() * 2.5 + 0.8,
    delay: Math.random() * 8, duration: Math.random() * 6 + 7,
    opacity: Math.random() * 0.45 + 0.18,
    color: Math.random() > 0.7 ? "#A8E4FF" : "#7DD3FF",
  })), [density]);
  return (
    <div style={{ position: "absolute", inset: 0, overflow: "hidden", pointerEvents: "none" }}>
      {particles.map(p => (
        <div key={p.id} style={{
          position: "absolute", left: `${p.x}%`, bottom: "-20px",
          width: p.size, height: p.size, borderRadius: "50%",
          background: p.color, opacity: p.opacity,
          boxShadow: `0 0 6px ${p.color}`,
          animation: `particle-drift ${p.duration}s ${p.delay}s ease-in infinite`,
        }} />
      ))}
    </div>
  );
};

/* ── Ambient orbs (drifting blurred color clouds) ────────────────── */
const AmbientOrbs = ({ palette = "cool" }) => {
  const orbs = palette === "warm"
    ? [{ color: "rgba(140,91,255,0.18)", x: "8%", y: "20%", size: 520 }, { color: "rgba(43,123,255,0.14)", x: "78%", y: "62%", size: 420 }]
    : [{ color: "rgba(125,211,255,0.16)", x: "10%", y: "16%", size: 560 }, { color: "rgba(43,123,255,0.14)", x: "82%", y: "70%", size: 460 }, { color: "rgba(140,91,255,0.10)", x: "55%", y: "45%", size: 380 }];
  return (
    <>
      {orbs.map((o, i) => (
        <div key={i} className="hero-orb" style={{ background: o.color, left: o.x, top: o.y, width: o.size, height: o.size, animationDelay: `${i * 4}s` }} />
      ))}
    </>
  );
};

/* ── Aurora / gradient mesh (fundo premium, substitui partículas) ── */
const Aurora = () => (
  <div className="aurora" aria-hidden="true">
    <div className="aurora__blob b1" />
    <div className="aurora__blob b2" />
    <div className="aurora__blob b3" />
  </div>
);

Object.assign(window, { Icon, PoligusMark, PoligusSphere3D, createPoligusSphere, makeGlowTexture, PoligusLogo, Particles, WhatsAppIcon, CircuitBackdrop, PcbSheet, AmbientOrbs, Aurora });
