/* global React */

// ============================================================
// Overseas CDN, Hero
// Tagline: 全球節點 · 300Gb+ 國際頻寬 · 全球平均延時 < 100ms
// Visual: compact wireframe GLOBE key-visual beside the H1/H2,
//         with HK origin hub + pulsing worldwide edge nodes.
// ============================================================
const OV_HERO_CSS = `
.OV-hero{position:relative;background:linear-gradient(180deg,#FAFAFE 0%,#F6F4FB 100%);font-family:'Inter','Noto Sans HK','Noto Sans TC',sans-serif;color:#0F2A47;overflow:hidden;padding:112px 0 96px}
.OV-hero::before{content:'';position:absolute;inset:0;background-image:linear-gradient(rgba(139,92,246,0.10) 1.5px,transparent 1.5px),linear-gradient(90deg,rgba(139,92,246,0.10) 1.5px,transparent 1.5px);background-size:64px 64px;mask-image:radial-gradient(ellipse 70% 60% at 50% 35%,#000 25%,transparent 80%);-webkit-mask-image:radial-gradient(ellipse 70% 60% at 50% 35%,#000 25%,transparent 80%);pointer-events:none}
.OV-hero::after{content:'';position:absolute;top:-80px;right:-8%;width:52%;height:80%;background:radial-gradient(ellipse 50% 40% at 60% 30%,rgba(139,92,246,0.12) 0%,transparent 70%);pointer-events:none}

.OV-hero-inner{position:relative;z-index:2;display:grid;grid-template-columns:1.08fr 0.92fr;gap:56px;align-items:center}

/* Left column */
.OV-hero-left{position:relative;z-index:2}
.OV-h1{margin:0;font-weight:700;font-size:clamp(46px,5.2vw,80px);line-height:1.04;letter-spacing:-2.2px;color:#0F2A47;text-wrap:balance}
.OV-h1 .accent{background:linear-gradient(135deg,#A855F7 0%,#7C3AED 100%);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent}
.OV-h1 .l2{display:block;margin-top:4px}
.OV-sub{margin:26px 0 0;max-width:540px;font-size:19px;line-height:1.7;color:#475569;text-wrap:pretty}
.OV-sub strong{color:#0F2A47;font-weight:600}

.OV-ctas{margin-top:38px;display:flex;flex-wrap:wrap;gap:12px;align-items:center}
.OV-btn-primary{display:inline-flex;align-items:center;gap:10px;padding:16px 30px;font-size:15px;font-weight:600;color:#fff;background:linear-gradient(135deg,#A855F7 0%,#7C3AED 100%);border:1.5px solid transparent;border-radius:999px;box-shadow:0 10px 24px rgba(139,92,246,0.30);letter-spacing:.3px;cursor:pointer;transition:all .15s;text-decoration:none}
.OV-btn-primary:hover{background:linear-gradient(135deg,#9333EA 0%,#6D28D9 100%);transform:translateY(-1px);box-shadow:0 14px 32px rgba(139,92,246,0.45)}
.OV-btn-outline{display:inline-flex;align-items:center;gap:10px;padding:16px 30px;font-size:15px;font-weight:600;color:#0F2A47;background:rgba(255,255,255,0.5);border:1.5px solid rgba(15,42,71,0.30);border-radius:999px;letter-spacing:.3px;cursor:pointer;text-decoration:none;transition:all .15s}
.OV-btn-outline:hover{background:#fff;border-color:#0F2A47}

/* Right column, globe key visual */
.OV-kv{position:relative;z-index:2;display:flex;justify-content:center}
.OV-globe{width:100%;max-width:430px;height:auto;display:block;overflow:visible}

@media (max-width: 1080px){
  .OV-hero{padding:88px 0 72px}
  .OV-hero-inner{grid-template-columns:1fr;gap:40px}
  .OV-kv{justify-content:flex-start}
  .OV-globe{max-width:360px}
}
@media (max-width: 700px){
  .OV-hero{padding:64px 0 56px}
  .OV-h1{font-size:clamp(40px,9vw,54px);letter-spacing:-1.2px}
  .OV-sub{font-size:16.5px}
  .OV-globe{max-width:300px}
  .OV-btn-primary,.OV-btn-outline{padding:14px 22px;font-size:14px}
}
`;

// ----- Compact wireframe globe -----
// Slowly spinning lat/long wireframe with HK origin hub + worldwide edge nodes.
function OVGlobe() {
  const [rot, setRot] = React.useState(0);
  React.useEffect(() => {
    let raf, last = performance.now();
    const tick = (t) => {
      if (t - last > 55) { setRot((r) => (r + 0.85) % 360); last = t; }
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);

  const C = 215, R = 140, tilt = (20 * Math.PI) / 180;
  const project = (latD, lonD) => {
    const lat = (latD * Math.PI) / 180;
    const lon = ((lonD + rot) * Math.PI) / 180;
    const x = R * Math.cos(lat) * Math.sin(lon);
    const y0 = R * Math.sin(lat);
    const z0 = R * Math.cos(lat) * Math.cos(lon);
    const y = y0 * Math.cos(tilt) - z0 * Math.sin(tilt);
    const z = y0 * Math.sin(tilt) + z0 * Math.cos(tilt);
    return { X: C + x, Y: C - y, z };
  };

  // split a sampled line into front (z>=0) / back segments for depth opacity
  const toSegs = (pts) => {
    const segs = []; let cur = [pts[0]]; let f = pts[0].z >= 0;
    for (let i = 1; i < pts.length; i++) {
      const nf = pts[i].z >= 0;
      if (nf !== f) { cur.push(pts[i]); segs.push({ front: f, pts: cur }); cur = [pts[i]]; f = nf; }
      else cur.push(pts[i]);
    }
    segs.push({ front: f, pts: cur });
    return segs;
  };
  const d = (pts) => pts.map((p, i) => (i ? 'L' : 'M') + p.X.toFixed(1) + ' ' + p.Y.toFixed(1)).join(' ');

  const meridians = [];
  for (let lon = 0; lon < 180; lon += 30) {
    const pts = [];
    for (let lat = -90; lat <= 90; lat += 4) pts.push(project(lat, lon));
    meridians.push(pts);
  }
  const parallels = [];
  for (let lat = -60; lat <= 60; lat += 30) {
    const pts = [];
    for (let lon = -180; lon <= 180; lon += 4) pts.push(project(lat, lon));
    parallels.push(pts);
  }

  const lines = [...meridians, ...parallels];

  // worldwide edge nodes + HK origin
  const cities = [
    { lat: 35, lon: 139 }, { lat: 1, lon: 104 }, { lat: 50, lon: 8 },
    { lat: 25, lon: 55 }, { lat: 19, lon: 73 }, { lat: 34, lon: -118 },
    { lat: -23, lon: -46 }, { lat: -33, lon: 151 }, { lat: 40, lon: -74 },
  ];
  const HK = project(22, 114);

  const orbRx = R + 26, orbRy = (R + 26) * 0.34;
  const orbPath = `M ${C - orbRx} ${C} a ${orbRx} ${orbRy} 0 1 0 ${2 * orbRx} 0 a ${orbRx} ${orbRy} 0 1 0 ${-2 * orbRx} 0`;

  return (
    <svg className="OV-globe" viewBox="0 0 430 430" role="img"
      aria-label="UD 海外 CDN 全球節點地球示意圖">
      <defs>
        <radialGradient id="ov-fill" cx="38%" cy="32%" r="75%">
          <stop offset="0%" stopColor="#ffffff" />
          <stop offset="62%" stopColor="#F4F0FE" />
          <stop offset="100%" stopColor="#EAE2FB" />
        </radialGradient>
        <radialGradient id="ov-hub" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor="#A855F7" />
          <stop offset="100%" stopColor="#7c3aed" />
        </radialGradient>
      </defs>

      {/* glow */}
      <circle cx={C} cy={C} r={R + 18} fill="#A855F7" opacity="0.07" />

      {/* sphere body */}
      <circle cx={C} cy={C} r={R} fill="url(#ov-fill)" stroke="#A855F7" strokeWidth="1.6" strokeOpacity="0.5" />

      {/* wireframe lat/long */}
      {lines.map((pts, i) =>
        toSegs(pts).map((s, j) => (
          <path key={`l-${i}-${j}`} d={d(s.pts)} fill="none"
            stroke="#A855F7" strokeWidth={s.front ? 1.3 : 1}
            strokeOpacity={s.front ? 0.5 : 0.16} strokeLinecap="round" />
        ))
      )}

      {/* orbit ring + travelling delivery packets */}
      <path d={orbPath} fill="none" stroke="#A855F7" strokeWidth="1.2"
        strokeOpacity="0.30" strokeDasharray="3 6" />
      <circle r="3.4" fill="#A855F7">
        <animateMotion dur="6s" repeatCount="indefinite" path={orbPath} />
      </circle>
      <circle r="3.4" fill="#A855F7">
        <animateMotion dur="6s" begin="-3s" repeatCount="indefinite" path={orbPath} />
      </circle>

      {/* edge nodes (front-facing only) */}
      {cities.map((c, i) => {
        const p = project(c.lat, c.lon);
        if (p.z < 0) return null;
        return (
          <g key={`c-${i}`}>
            <circle cx={p.X} cy={p.Y} r="9" fill="#A855F7" opacity="0.14">
              <animate attributeName="r" values="6;12;6" dur="2.6s"
                repeatCount="indefinite" begin={`${i * 0.3}s`} />
            </circle>
            <circle cx={p.X} cy={p.Y} r="3.6" fill="#fff" stroke="#A855F7" strokeWidth="2" />
          </g>
        );
      })}

      {/* HK origin hub */}
      {HK.z >= -30 && (
        <g>
          <circle cx={HK.X} cy={HK.Y} r="16" fill="#A855F7" opacity="0.16">
            <animate attributeName="r" values="11;19;11" dur="3s" repeatCount="indefinite" />
          </circle>
          <circle cx={HK.X} cy={HK.Y} r="6.5" fill="url(#ov-hub)" stroke="#fff" strokeWidth="2.2" />
        </g>
      )}
    </svg>
  );
}

function OverseasHero() {
  return (
    <>
      <style>{OV_HERO_CSS}</style>
      <section className="OV-hero" data-screen-label="01 Hero">
        <div className="container OV-hero-inner">
          <div className="OV-hero-left">
            <h1 className="OV-h1">
              <span className="accent">海外 CDN</span>
            </h1>
            <p className="OV-lede" style={{ margin: '14px 0 0', fontWeight: 700, fontSize: 'clamp(20px, 2.1vw, 28px)', lineHeight: 1.3, color: '#0F2A47', letterSpacing: '-0.5px' }}>全球節點，環球網站加速</p>
            <p className="OV-sub">
              讓全球用戶以本地速度瀏覽你的網站。透過遍佈亞洲、歐洲及美洲的邊緣節點與
              <strong> 300Gb+ 國際頻寬</strong>，把跨境延遲變成更快的載入、更低的跳出率，
              以及更高的轉換。
            </p>
            <div className="OV-ctas">
              <a className="OV-btn-primary" href="https://passport.8338.hk/zh-hant/signup" data-cta="start-trial">免費試用</a>
              <a className="OV-btn-outline" href="#pricing" data-cta="view-pricing">查看定價</a>
            </div>
          </div>

          <div className="OV-kv">
            <OVGlobe />
          </div>
        </div>
      </section>
    </>
  );
}

window.OverseasHero = OverseasHero;
