// Hero — Visual redesign: White canvas, rework-work-section scroll-brightening text,
// original 5-layer holographic diamond (larger mouse parallax) + halftone dot glow
(function () {
  const { useEffect, useState, useRef } = React;

  const GREEN = [74, 222, 128]; // --accent #4ADE80

  // 13 viscoelastic soap-bubble diamond nodes:
  // Node 0 = Layer 1 (~64vmin, ~1/4 viewport area); Nodes 1..12 = 12 concentric gossamer echo rings
  const LAYER_COUNT = 13;
  const DIAMOND_LAYERS = Array.from({ length: LAYER_COUNT }, (_, i) => {
    const t = i / (LAYER_COUNT - 1);
    const opacity =
      i === 0
        ? 0.96
        : +(0.15 * Math.pow(1 - t * 0.88, 1.75)).toFixed(3);
    const blur =
      i <= 5
        ? 0
        : +(Math.pow((i - 5) / (LAYER_COUNT - 6), 1.85) * 3.8).toFixed(2);
    const hueShift = Math.round(Math.sin(i * 0.22) * 16 + i * 1.2);
    return {
      idx: i,
      num: i + 1,
      sizeVmin: +(64.0 + i * 1.20).toFixed(2),
      minPx: Math.round(336 + i * 7.2),
      maxPx: Math.round(840 + i * 14.5),
      opacity,
      blur,
      hueShift,
    };
  });
  const DIAMOND_LAYERS_BACK_TO_FRONT = [...DIAMOND_LAYERS].reverse();

  // Cached ~58,000-particle Lagrangian GPU bank + fallback PNG URLs
  let cachedParticleBank = null;
  let cachedCoreBubbleUrl = null;
  let cachedOuterBubbleUrl = null;

  function Hero() {
    const heroRef = useRef(null);
    const pinRef = useRef(null);
    const titleRef = useRef(null);
    const descRef = useRef(null);
    const ctaRef = useRef(null);
    const titleSpansRef = useRef(null);
    const descSpansRef = useRef(null);
    const canvasRef = useRef(null);
    const layerRefs = useRef([]);
    const uploadBankRef = useRef(null);
    const productLineRef = useRef(null);
    const productCanvasRef = useRef(null);
    const productCharCpRef = useRef(new Float32Array(7));

    const [revealed, setRevealed] = useState(false);
    const [menuOpen, setMenuOpen] = useState(false);
    const [particleCoreReady, setParticleCoreReady] = useState(false);
    const [productParticlesReady, setProductParticlesReady] = useState(false);
    const [coreBubbleSrc, setCoreBubbleSrc] = useState(cachedCoreBubbleUrl || './assets/star-holo.png');
    const [outerBubbleSrc, setOuterBubbleSrc] = useState(cachedOuterBubbleUrl || './assets/star-holo.png');

    const isMinimalMotion = () =>
      typeof window !== 'undefined' &&
      (window.matchMedia('(prefers-reduced-motion: reduce)').matches ||
        document.documentElement.getAttribute('data-motion') === 'minimal');

    const reduceMotion = isMinimalMotion();

    // Build ~58,000-particle jewel-saturated GPU bank + fallback PNGs from star-holo.png
    useEffect(() => {
      if (cachedParticleBank && cachedCoreBubbleUrl && cachedOuterBubbleUrl) {
        setCoreBubbleSrc(cachedCoreBubbleUrl);
        setOuterBubbleSrc(cachedOuterBubbleUrl);
        if (uploadBankRef.current) uploadBankRef.current(cachedParticleBank);
        return;
      }
      let cancelled = false;
      const srcImg = new Image();
      srcImg.decoding = 'async';
      srcImg.onload = () => {
        if (cancelled) return;
        try {
          const texDim = 512;
          const off = document.createElement('canvas');
          off.width = texDim;
          off.height = texDim;
          const octx = off.getContext('2d');
          octx.drawImage(srcImg, 0, 0, texDim, texDim);
          const baseData = octx.getImageData(0, 0, texDim, texDim);
          const src = baseData.data;

          const coreImg = octx.createImageData(texDim, texDim);
          const outerImg = octx.createImageData(texDim, texDim);
          const cd = coreImg.data;
          const od = outerImg.data;

          const blurField512 = (input, radius) => {
            const tmp = new Float32Array(texDim * texDim);
            const out = new Float32Array(texDim * texDim);
            const inv = 1 / (2 * radius + 1);
            for (let y = 0; y < texDim; y++) {
              const row = y * texDim;
              let sum = 0;
              for (let dx = -radius; dx <= radius; dx++) {
                const cx = dx < 0 ? 0 : dx >= texDim ? texDim - 1 : dx;
                sum += input[row + cx];
              }
              for (let x = 0; x < texDim; x++) {
                tmp[row + x] = sum * inv;
                const rem = x - radius < 0 ? 0 : x - radius;
                const add = x + radius + 1 >= texDim ? texDim - 1 : x + radius + 1;
                sum += input[row + add] - input[row + rem];
              }
            }
            for (let x = 0; x < texDim; x++) {
              let sum = 0;
              for (let dy = -radius; dy <= radius; dy++) {
                const cy = dy < 0 ? 0 : dy >= texDim ? texDim - 1 : dy;
                sum += tmp[cy * texDim + x];
              }
              for (let y = 0; y < texDim; y++) {
                out[y * texDim + x] = sum * inv;
                const rem = y - radius < 0 ? 0 : y - radius;
                const add = y + radius + 1 >= texDim ? texDim - 1 : y + radius + 1;
                sum += tmp[add * texDim + x] - tmp[rem * texDim + x];
              }
            }
            return out;
          };

          const nTex = texDim * texDim;
          const alpha0 = new Float32Array(nTex);
          for (let i = 0; i < nTex; i++) {
            alpha0[i] = src[i * 4 + 3] / 255;
          }
          const blurNear = blurField512(blurField512(alpha0, 12), 12);
          const blurWide = blurField512(blurField512(alpha0, 34), 34);

          // High-voltage Cyberpunk / Post-Future palette engineered for maximum punch on #ffffff
          // (Zero pale yellows or muddy greys — pure hyper-magenta, electric cyan, neon cobalt, hyper-violet, acid emerald, laser tangerine)
          const cyberStops = [
            [0.00, 0.86, 0.44], // Acid Signal-Emerald (#00DC70)
            [0.00, 0.76, 1.00], // Electric Cyber-Cyan (#00C2FF)
            [0.10, 0.20, 1.00], // Neon Ultramarine-Cobalt (#1A33FF)
            [0.48, 0.00, 1.00], // Post-Future Hyper-Violet (#7A00FF)
            [1.00, 0.00, 0.42], // Cyber Hyper-Magenta (#FF006B)
            [1.00, 0.36, 0.00], // Laser Tangerine-Amber (#FF5C00)
          ];
          const sampleCyber = (t) => {
            const x = ((t % 1) + 1) % 1;
            const sc = x * cyberStops.length;
            const i0 = Math.floor(sc) % cyberStops.length;
            const i1 = (i0 + 1) % cyberStops.length;
            const f = sc - Math.floor(sc);
            const a = cyberStops[i0];
            const b = cyberStops[i1];
            return [
              a[0] + (b[0] - a[0]) * f,
              a[1] + (b[1] - a[1]) * f,
              a[2] + (b[2] - a[2]) * f,
            ];
          };

          const inkArr = new Float32Array(nTex);
          for (let i = 0; i < nTex; i++) {
            const p = i * 4;
            const oa = src[p + 3] / 255;
            if (oa < 0.01) continue;
            const minC = Math.min(src[p], src[p + 1], src[p + 2]) / 255;
            // True visual contrast against #ffffff: excludes both outer transparency AND inner white cutout!
            inkArr[i] = oa * (1 - minC);
          }
          const blurInk = blurField512(inkArr, 4);
          const centerTransparent = src[(256 * texDim + 256) * 4 + 3] < 32;

          const colR = new Float32Array(nTex);
          const colG = new Float32Array(nTex);
          const colB = new Float32Array(nTex);
          const edgeBandArr = new Float32Array(nTex);

          for (let p = 0; p < src.length; p += 4) {
            const origA = src[p + 3] / 255;
            if (origA < 0.01) continue;

            const idx = p >> 2;
            const px = idx & 511;
            const py = idx >> 9;
            const nx = px / texDim - 0.5;
            const ny = py / texDim - 0.5;

            const r = src[p] / 255;
            const g = src[p + 1] / 255;
            const b = src[p + 2] / 255;
            const maxC = Math.max(r, g, b);
            const minC = Math.min(r, g, b);
            const chroma = maxC - minC;
            const darkness = 1 - maxC;
            const ink = inkArr[idx];

            const rimProximity = Math.min(1, Math.max(0, (0.94 - blurNear[idx]) / 0.42));
            const inkGradient = Math.min(1, Math.abs(ink - blurInk[idx]) * 4.2);
            edgeBandArr[idx] = Math.max(rimProximity * (ink > 0.04 ? 1 : 0), inkGradient);

            const phase = nx * 1.25 - ny * 1.05 + rimProximity * 0.45;
            const [pR, pG, pB] = sampleCyber(phase);

            let hR = pR;
            let hG = pG;
            let hB = pB;

            if (chroma > 0.022) {
              let sR = (r - minC) / chroma;
              let sG = (g - minC) / chroma;
              let sB = (b - minC) / chroma;
              // Shift pale high-luminance yellows into punchy Cyber Tangerine or Acid Emerald so they pop on #ffffff
              if (sR > 0.70 && sG > 0.65 && sB < 0.28) {
                if (sG > sR * 0.96) {
                  sR = 0.0;
                  sG = 0.88;
                  sB = 0.46;
                } else {
                  sR = 1.0;
                  sG *= 0.42;
                  sB = 0.0;
                }
              } else if (sG > 0.78 && sB > 0.78 && sR < 0.22) {
                // Deepen electric cyan slightly for razor-sharp contrast on white
                sG = 0.76;
                sB = 1.0;
              }
              const srcW = Math.min(1, chroma * 3.8 + darkness * 1.6);
              const mR = pR + (sR - pR) * srcW;
              const mG = pG + (sG - pG) * srcW;
              const mB = pB + (sB - pB) * srcW;
              const mMax = Math.max(mR, mG, mB);
              const mMin = Math.min(mR, mG, mB);
              const mSpan = Math.max(0.001, mMax - mMin);
              hR = (mR - mMin) / mSpan;
              hG = (mG - mMin) / mSpan;
              hB = (mB - mMin) / mSpan;
            } else if (darkness > 0.08) {
              // Dark chromatic core ring -> Deep Neon Ultramarine / Hyper-Violet
              hR = 0.20 + 0.28 * Math.min(1, darkness);
              hG = 0.12 * (1 - Math.min(1, darkness));
              hB = 1.00;
            }

            // 99%-100% pure cyber saturation, vivid non-muddy brightness
            const targetS = 0.995;
            const targetV = Math.max(0.68, Math.min(0.98, 0.96 - darkness * 0.26));

            const cr = targetV * (1 - targetS + targetS * hR);
            const cg = targetV * (1 - targetS + targetS * hG);
            const cb = targetV * (1 - targetS + targetS * hB);

            colR[idx] = cr;
            colG[idx] = cg;
            colB[idx] = cb;

            const coreAlpha = Math.min(1, Math.pow(ink, 0.72) * 1.25);
            cd[p] = Math.min(255, Math.round(cr * 255));
            cd[p + 1] = Math.min(255, Math.round(cg * 255));
            cd[p + 2] = Math.min(255, Math.round(cb * 255));
            cd[p + 3] = Math.min(255, Math.round(coreAlpha * 255));

            // Fallback outer echo PNG: desaturated light cool-silver so only Layer 1 focal diamond stays vivid
            const outerAlpha = Math.min(1, ink * 0.28);
            od[p] = Math.round((0.68 * 0.92 + cr * 0.08) * 255);
            od[p + 1] = Math.round((0.72 * 0.92 + cg * 0.08) * 255);
            od[p + 2] = Math.round((0.78 * 0.92 + cb * 0.08) * 255);
            od[p + 3] = Math.min(255, Math.round(outerAlpha * 255));
          }

          // Deterministic PRNG + 8x8 Bayer Digital Dither Matrix for crisp post-future cybernetic texture
          let rngState = 0x85ebca6b;
          const rand = () => {
            rngState = (rngState + 0x6d2b79f5) | 0;
            let t = Math.imul(rngState ^ (rngState >>> 15), 1 | rngState);
            t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
            return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
          };

          const bayer8 = (x, y) => {
            const xc = x & 7;
            const yc = y & 7;
            const xm = xc ^ yc;
            let v = 0;
            v |= ((xm & 4) >> 1) | (yc & 4);
            v = (v << 2) | ((xm & 2) | ((yc & 2) << 1));
            v = (v << 2) | (((xm & 1) << 1) | ((yc & 1) << 2));
            return ((v >> 2) + 0.5) / 64;
          };

          // Encode digital glyph type (0: Square Pixel ■, 1: Scan-Bar ▬/▮, 2: Crosshair +, 3: Hollow Voxel □) + seed
          const packGlyphSeed = (glyphId, s) => glyphId + (0.02 + s * 0.96);

          // Painter's order buckets:
          // [0] Full-viewport scattered cyber-field + 3 thin wireframe echo contours
          // [1] Layer 1 structured HUD matrix & dithered plasma halos
          // [2] Layer 1 solid hyper-saturated chromatic lobes
          // [3] Layer 1 razor-sharp outer & inner concrete diamond contours + fiducial reticles
          const buckets = [[], [], [], []];

          // A) Full-Viewport Scattered Cyberpunk / Post-Future Particles (ringIdx = 255, spanning 100vw x 100vh)
          const inTextSafeZone = (ux, uy) =>
            (ux > 0.03 && ux < 0.43 && uy > 0.27 && uy < 0.73) ||
            (ux > 0.60 && ux < 0.96 && uy > 0.45 && uy < 0.77);

          // A1) 280 Quantized Cyber-Telemetry Constellations across the entire screen
          const CLUST_X = 20;
          const CLUST_Y = 14;
          for (let cy = 0; cy < CLUST_Y; cy++) {
            for (let cx = 0; cx < CLUST_X; cx++) {
              const ax = (cx + 0.14 + rand() * 0.72) / CLUST_X;
              const ay = (cy + 0.14 + rand() * 0.72) / CLUST_Y;
              const inText = inTextSafeZone(ax, ay);
              if (inText && rand() < 0.52) continue;

              // Quantize anchor onto a clean virtual HUD grid
              const qx = Math.round(ax * 320) / 320;
              const qy = Math.round(ay * 200) / 200;
              const [cR, cG, cB] = cyberStops[Math.floor(rand() * cyberStops.length)];
              const pattern = Math.floor(rand() * 3);
              const sizeScale = inText ? 0.68 : 1.0;
              const countInCluster = 4 + Math.floor(rand() * 5);
              const baseComp = 0.55 + rand() * 1.25;

              for (let m = 0; m < countInCluster; m++) {
                let ox = 0;
                let oy = 0;
                let glyph = 0;
                let diam = 1.9;

                if (pattern === 0) {
                  // Horizontal barcode / data-packet stream (▬ + ■)
                  ox = (m - (countInCluster - 1) * 0.5) * 0.0052;
                  oy = ((m & 1) - 0.5) * 0.0022;
                  glyph = m % 2 === 0 ? 1 : 0;
                  diam = (glyph === 1 ? 2.6 + rand() * 1.3 : 1.8 + rand() * 0.9) * sizeScale;
                } else if (pattern === 1) {
                  // Post-future precision '+' reticle node + corner voxel ticks
                  if (m === 0) {
                    ox = 0;
                    oy = 0;
                    glyph = 2;
                    diam = (3.8 + rand() * 1.6) * sizeScale;
                  } else {
                    const ang = ((m - 1) * Math.PI) * 0.5;
                    ox = Math.round(Math.cos(ang)) * 0.0065;
                    oy = Math.round(Math.sin(ang)) * 0.0095;
                    glyph = m === 1 ? 3 : 0;
                    diam = (1.7 + rand() * 0.9) * sizeScale;
                  }
                } else {
                  // Stepped cyber-diagonal matrix packet (□ + ■)
                  ox = (m - 2) * 0.0042;
                  oy = Math.floor(m * 0.5) * 0.0062;
                  glyph = m === 0 ? 3 : 0;
                  diam = (glyph === 3 ? 3.1 + rand() * 1.0 : 1.8 + rand() * 1.0) * sizeScale;
                }

                const px = Math.min(0.992, Math.max(0.008, qx + ox));
                const py = Math.min(0.990, Math.max(0.010, qy + oy));
                buckets[0].push(
                  px,
                  py,
                  255,
                  baseComp + (rand() - 0.5) * 0.18,
                  cR,
                  cG,
                  cB,
                  diam,
                  inText ? 0.72 : 0.88 + 0.10 * rand(),
                  packGlyphSeed(glyph, rand())
                );
              }
            }
          }

          // A2) ~2,400 Stratified Full-Screen Digital Pixels, Scan-Ticks & Fiducial Crosshairs
          const FIELD_X = 52;
          const FIELD_Y = 46;
          for (let fy = 0; fy < FIELD_Y; fy++) {
            for (let fx = 0; fx < FIELD_X; fx++) {
              const ux = (fx + 0.08 + rand() * 0.84) / FIELD_X;
              const uy = (fy + 0.08 + rand() * 0.84) / FIELD_Y;
              const inText = inTextSafeZone(ux, uy);
              if (inText && rand() < 0.46) continue;

              const qx = Math.round(ux * 480) / 480;
              const qy = Math.round(uy * 300) / 300;
              const [cR, cG, cB] = sampleCyber(qx * 1.4 - qy * 1.1 + rand() * 0.35);

              const rg = rand();
              let glyph = 0;
              let diam = 1.65 + rand() * 1.35;
              if (rg > 0.90) {
                glyph = 2; // '+' crosshair
                diam = 3.2 + rand() * 1.9;
              } else if (rg > 0.83) {
                glyph = 3; // '□' hollow voxel
                diam = 2.6 + rand() * 1.3;
              } else if (rg > 0.64) {
                glyph = 1; // '▬' scan-bar
                diam = 2.2 + rand() * 1.4;
              }
              if (inText) diam *= 0.66;

              buckets[0].push(
                qx,
                qy,
                255,
                0.48 + rand() * 1.45,
                cR,
                cG,
                cB,
                diam,
                inText ? 0.68 + 0.16 * rand() : 0.82 + 0.16 * rand(),
                packGlyphSeed(glyph, rand())
              );
            }
          }

          // B) 3 Crisp, Thin Stepped Cyber-Wireframe Echo Contours (nodes 3, 7, 11 — zero edge blur on Layer 1)
          const echoNodeIndices = [11, 7, 3];
          const ECHO_GRID = 230;
          for (let e = 0; e < echoNodeIndices.length; e++) {
            const nodeIdx = echoNodeIndices[e];
            const ringScale = 1.0 + nodeIdx * 0.0115;
            const ringAlpha = 0.36 + e * 0.16;
            const hueOff = nodeIdx * 0.04;

            for (let iy = 0; iy < ECHO_GRID; iy++) {
              const v = (iy + 0.5) / ECHO_GRID;
              const ty = Math.min(511, Math.floor(v * texDim));
              for (let ix = 0; ix < ECHO_GRID; ix++) {
                const u = (ix + 0.5) / ECHO_GRID;
                const tx = Math.min(511, Math.floor(u * texDim));
                const tidx = ty * texDim + tx;

                // Strictly trace only the sharpest outer contour peak so Layer 1 stays razor-distinct
                const oa = alpha0[tidx];
                if (oa < 0.18 || oa > 0.86) continue;
                if (inkArr[tidx] < 0.14) continue;
                if (((ix + iy + e) & 1) !== 0) continue;

                const [eR, eG, eB] = sampleCyber((u - 0.5) * 1.3 - (v - 0.5) * 1.1 + hueOff);
                const glyph = (ix + iy) % 9 === 0 ? 1 : 0;

                buckets[0].push(
                  (u - 0.5) * ringScale,
                  (v - 0.5) * ringScale,
                  nodeIdx,
                  0.85 + rand() * 0.90,
                  colR[tidx] * 0.65 + eR * 0.35,
                  colG[tidx] * 0.65 + eG * 0.35,
                  colB[tidx] * 0.65 + eB * 0.35,
                  glyph === 1 ? 1.55 : 1.25,
                  ringAlpha,
                  packGlyphSeed(glyph, rand())
                );
              }
            }
          }

          // C) Layer 1 Concrete Cyber-Diamond (~52,000 pixel-locked digital voxels, scan-bars & reticles)
          const CORE_GRID = 456;
          for (let iy = 0; iy < CORE_GRID; iy++) {
            const v = (iy + 0.5) / CORE_GRID;
            const ny = v - 0.5;
            const ty = Math.min(511, Math.floor(v * texDim));

            for (let ix = 0; ix < CORE_GRID; ix++) {
              const u = (ix + 0.5) / CORE_GRID;
              const nx = u - 0.5;
              const tx = Math.min(511, Math.floor(u * texDim));
              const tidx = ty * texDim + tx;

              const oa = alpha0[tidx];
              if (oa < 0.06) continue;

              const dInner = Math.abs(nx) / 0.312 + Math.abs(ny) / 0.308;
              // Keep the inner geometric diamond cutout 100% clean pure #ffffff!
              if (!centerTransparent && dInner < 0.992) continue;

              const ink = inkArr[tidx];
              const edgeBand = edgeBandArr[tidx];
              const isInnerWire = oa > 0.65 && Math.abs(dInner - 1.0) < 0.0068;
              const isOuterWire = oa >= 0.18 && oa <= 0.78 && ink > 0.08;

              let cr = colR[tidx];
              let cg = colG[tidx];
              let cb = colB[tidx];
              let diam = 1.38;
              let alpha = 0.96;
              let glyph = 0;
              let bucketIdx = 2;

              if (isOuterWire || isInnerWire || edgeBand > 0.56) {
                // Razor-sharp architectural outer 4-point contour & inner geometric diamond contour
                if (ink < 0.06) {
                  const [wR, wG, wB] = sampleCyber(nx * 1.4 - ny * 1.2 + 0.18);
                  cr = wR;
                  cg = wG;
                  cb = wB;
                }
                const rg = bayer8(ix, iy);
                glyph = rg > 0.94 ? 3 : rg > 0.80 ? 1 : 0;
                diam = glyph === 0 ? 1.52 : 1.95;
                alpha = 0.98;
                bucketIdx = 3;
              } else if (ink >= 0.28) {
                // Solid, hyper-saturated chromatic aberration bands & magenta/cyan/cobalt cores
                const rg = bayer8(ix, iy);
                glyph = rg > 0.88 ? 1 : 0;
                diam = glyph === 1 ? 1.75 : 1.38 + 0.28 * Math.min(1, ink);
                alpha = 0.96;
                bucketIdx = 2;
              } else if (ink >= 0.022) {
                // Ordered 8x8 Bayer digital dithering across soft plasma gradients (crispy digital halftone!)
                const normInk = Math.pow((ink - 0.022) / 0.258, 0.72);
                if (bayer8(ix, iy) > normInk) continue;
                glyph = ((ix + iy) & 7) === 0 ? 1 : 0;
                diam = glyph === 1 ? 1.65 : 1.28;
                alpha = 0.90 + 0.08 * normInk;
                bucketIdx = 1;
              } else {
                // Clean, disciplined post-future HUD dot-matrix inside white star arms (keeps shape 100% concrete!)
                if (oa < 0.82 || dInner < 1.02) continue;
                if (ix % 6 !== 0 || iy % 6 !== 0) continue;
                const [mR, mG, mB] = sampleCyber(nx * 1.2 - ny * 1.0 + 0.22);
                cr = mR;
                cg = mG;
                cb = mB;
                glyph = (ix + iy) % 24 === 0 ? 2 : 0;
                diam = glyph === 2 ? 2.85 : 1.22;
                alpha = glyph === 2 ? 0.86 : 0.74;
                bucketIdx = 1;
              }

              buckets[bucketIdx].push(
                nx,
                ny,
                0,
                0.82 + rand() * 0.42,
                cr,
                cg,
                cb,
                diam,
                alpha,
                packGlyphSeed(glyph, rand())
              );
            }
          }

          // D) Architectural Post-Future Cardinal Fiducial Reticles (+) on Layer 1 vertices
          const fiducials = [
            [0.0, -0.492, 0.00, 0.78, 1.00, 5.2], // Top outer tip
            [0.492, 0.0, 0.00, 0.86, 0.46, 5.2],  // Right outer tip
            [0.0, 0.492, 0.12, 0.24, 1.00, 5.2],  // Bottom outer tip
            [-0.492, 0.0, 1.00, 0.00, 0.42, 5.2], // Left outer tip
            [0.0, -0.308, 0.48, 0.00, 1.00, 4.2], // Top inner diamond vertex
            [0.312, 0.0, 0.00, 0.78, 1.00, 4.2],  // Right inner diamond vertex
            [0.0, 0.308, 0.00, 0.86, 0.46, 4.2],  // Bottom inner diamond vertex
            [-0.312, 0.0, 1.00, 0.00, 0.42, 4.2], // Left inner diamond vertex
          ];
          for (let f = 0; f < fiducials.length; f++) {
            const fd = fiducials[f];
            buckets[3].push(
              fd[0],
              fd[1],
              0,
              0.90,
              fd[2],
              fd[3],
              fd[4],
              fd[5],
              0.98,
              packGlyphSeed(2, (f + 0.5) / fiducials.length)
            );
          }

          const STRIDE = 10;
          const totalParticles =
            (buckets[0].length +
              buckets[1].length +
              buckets[2].length +
              buckets[3].length) /
            STRIDE;

          const homeX = new Float32Array(totalParticles);
          const homeY = new Float32Array(totalParticles);
          const ringIdx = new Uint8Array(totalParticles);
          const compliance = new Float32Array(totalParticles);
          // 7 floats per particle (28 bytes): r, g, b, diam, alpha, glyphSeed, intrinsicFocus
          const staticMeta = new Float32Array(totalParticles * 7);

          let outIdx = 0;
          for (let b = 0; b < 4; b++) {
            const arr = buckets[b];
            for (let k = 0; k < arr.length; k += STRIDE) {
              const r = arr[k + 2];
              homeX[outIdx] = arr[k];
              homeY[outIdx] = arr[k + 1];
              ringIdx[outIdx] = r;
              compliance[outIdx] = arr[k + 3];

              // Visual focal hierarchy:
              // r === 0 (central Layer 1 diamond) = 1.0 (always vivid saturated)
              // r === 3, 7, 11 (echo wireframes) & r === 255 (scattered field) = muted light cool-grey until hovered!
              const intrinsicFocus =
                r === 0 ? 1.0 : r === 3 ? 0.14 : r === 7 ? 0.05 : 0.0;

              const m = outIdx * 7;
              staticMeta[m] = arr[k + 4];
              staticMeta[m + 1] = arr[k + 5];
              staticMeta[m + 2] = arr[k + 6];
              staticMeta[m + 3] = arr[k + 7];
              staticMeta[m + 4] = arr[k + 8];
              staticMeta[m + 5] = arr[k + 9];
              staticMeta[m + 6] = intrinsicFocus;
              outIdx++;
            }
          }

          cachedParticleBank = {
            count: totalParticles,
            homeX,
            homeY,
            ringIdx,
            compliance,
            staticMeta,
          };

          octx.putImageData(coreImg, 0, 0);
          cachedCoreBubbleUrl = off.toDataURL('image/png');

          octx.putImageData(outerImg, 0, 0);
          cachedOuterBubbleUrl = off.toDataURL('image/png');

          if (!cancelled) {
            setCoreBubbleSrc(cachedCoreBubbleUrl);
            setOuterBubbleSrc(cachedOuterBubbleUrl);
            if (uploadBankRef.current) uploadBankRef.current(cachedParticleBank);
          }
        } catch (_) {
          // Graceful fallback if getImageData is restricted
        }
      };
      srcImg.src = './assets/star-holo.png';
      return () => {
        cancelled = true;
      };
    }, []);

    // Entrance reveal
    useEffect(() => {
      const t = setTimeout(() => setRevealed(true), 120);
      return () => clearTimeout(t);
    }, []);

    useEffect(() => {
      document.body.classList.toggle('hero-revealed', revealed);
    }, [revealed]);

    // 3.7 Fixed header — watch the hero top-left brand
    useEffect(() => {
      const big = document.querySelector('.hero__brand');
      if (!big || !('IntersectionObserver' in window)) {
        document.body.classList.add('big-yui-hidden');
        return;
      }
      const io = new IntersectionObserver(
        ([entry]) => {
          document.body.classList.toggle('big-yui-hidden', !entry.isIntersecting);
        },
        { threshold: 0.05 }
      );
      io.observe(big);
      return () => {
        io.disconnect();
        document.body.classList.remove('big-yui-hidden');
      };
    }, []);

    // 3.5 Scroll-linked per-char brightening + green wave crest (from rework-work-section)
    const applySplit = (containerEl, spansRef, startY, endY, baseRGB) => {
      if (!containerEl) return;
      if (!spansRef.current || !spansRef.current.length) {
        let prodIdx = 0;
        spansRef.current = [...containerEl.querySelectorAll('.stxc')].map((el) => {
          const keepColor = !!el.closest('.hero__title-line--accent');
          const productCharIdx = keepColor ? prodIdx++ : -1;
          return { el, keepColor, productCharIdx };
        });
      }
      const spans = spansRef.current;
      const n = spans.length;
      if (!n) return;
      const p = Math.max(0, Math.min(1,
        (window.scrollY - startY) / Math.max(1, endY - startY)));
      const w = 0.3;
      const span = 1 - w;
      for (let i = 0; i < n; i++) {
        const start = (i / Math.max(1, n - 1)) * span;
        const cp = Math.max(0, Math.min(1, (p - start) / w));
        const s = spans[i];
        if (s.productCharIdx >= 0 && s.productCharIdx < 7) {
          productCharCpRef.current[s.productCharIdx] = cp;
        }
        s.el.style.opacity = (0.2 + 0.8 * cp).toFixed(3);
        if (s.keepColor) {
          const a = Math.max(0, 1 - Math.max(0, (cp - 0.45) / 0.55));
          s.el.style.setProperty('-webkit-text-fill-color', `rgba(30,30,34,${a.toFixed(3)})`);
        } else {
          const g = Math.max(0, Math.min(1, Math.min(cp / 0.5, (1 - cp) / 0.25)));
          if (g > 0.001) {
            const r = Math.round(baseRGB[0] + (GREEN[0] - baseRGB[0]) * g);
            const gg = Math.round(baseRGB[1] + (GREEN[1] - baseRGB[1]) * g);
            const b = Math.round(baseRGB[2] + (GREEN[2] - baseRGB[2]) * g);
            s.el.style.color = `rgb(${r},${gg},${b})`;
          } else {
            s.el.style.color = '';
          }
        }
      }
    };

    // Scroll parallax + split-text reveal driver
    useEffect(() => {
      let raf = 0;
      const update = () => {
        raf = 0;
        const el = heroRef.current;
        if (!el) return;
        const h = el.offsetHeight || 1;
        const pinH = pinRef.current ? pinRef.current.offsetHeight : h;
        const D = Math.max(pinH - h, 0);
        const vh = window.innerHeight || 1;
        const Deff = D > 40 ? D : vh * 0.5;
        const p = Math.min(1, Math.max(0, (window.scrollY - D) / h));
        el.style.setProperty('--hs', p.toFixed(4));

        // Dark header/brand toggle over #projects
        const dark = document.getElementById('projects');
        const overDark = !!dark && (() => {
          const r = dark.getBoundingClientRect();
          return r.top < 64 && r.bottom > 64;
        })();
        document.body.classList.toggle('brand-on-dark', overDark);

        // Scroll-linked split-text brightening
        if (!isMinimalMotion()) {
          applySplit(titleRef.current, titleSpansRef, 0, Deff * 0.62, [30, 30, 34]);
          applySplit(descRef.current, descSpansRef, Deff * 0.18, Deff * 0.88, [14, 14, 16]);
        } else {
          productCharCpRef.current.fill(1);
        }

        // Frosted-glass blur & strong attenuation ("霧化玻璃特淡化") when Yui intersects hero title / hero desc
        const heroBrandEl = el.querySelector('.hero__brand');
        const heroBrandOff =
          document.body.classList.contains('big-yui-hidden') ||
          (heroBrandEl ? heroBrandEl.getBoundingClientRect().bottom <= 4 : true);
        const yuiEl = heroBrandOff
          ? (window.innerWidth <= 1024
              ? el.querySelector('.mnav__brand')
              : document.querySelector('.site-brand'))
          : heroBrandEl;
        const titleEl = titleRef.current;
        const descEl = descRef.current;
        const ctaEl = ctaRef.current;

        if (yuiEl && (titleEl || descEl || ctaEl)) {
          const yr = yuiEl.getBoundingClientRect();
          const glassCoreY = yr.bottom + 10;
          const glassFeatherY = yr.bottom + 62;
          const yuiCx = (yr.left + yr.right) * 0.5;
          const yuiCy = (yr.top + yr.bottom) * 0.5;
          const isMobileHeader = window.innerWidth <= 1024;
          let anyOverlap = false;

          if (titleEl) {
            const tr = titleEl.getBoundingClientRect();
            const hHit = isMobileHeader || (tr.left < yr.right + 96 && tr.right > yr.left - 16);
            if (hHit && tr.top < glassFeatherY && tr.bottom > yr.top - 16) {
              anyOverlap = true;
              const s1 = glassCoreY - tr.top;
              const s2 = glassFeatherY - tr.top;
              const mask = `linear-gradient(to bottom, rgba(0,0,0,0.05) 0px, rgba(0,0,0,0.05) ${s1.toFixed(1)}px, rgba(0,0,0,1) ${s2.toFixed(1)}px, rgba(0,0,0,1) 100%)`;
              titleEl.style.webkitMaskImage = mask;
              titleEl.style.maskImage = mask;
              const lines = titleEl.querySelectorAll('.hero__title-line');
              for (let i = 0; i < lines.length; i++) {
                const lr = lines[i].getBoundingClientRect();
                const center = lr.top + lr.height * 0.42;
                const t = Math.max(0, Math.min(1, (glassFeatherY - center) / Math.max(1, glassFeatherY - yr.top)));
                lines[i].style.setProperty('--yui-blur', t > 0.01 ? `${(t * 8.0).toFixed(2)}px` : '0px');
              }
            } else if (titleEl.style.maskImage || titleEl.style.webkitMaskImage) {
              titleEl.style.webkitMaskImage = '';
              titleEl.style.maskImage = '';
              const lines = titleEl.querySelectorAll('.hero__title-line');
              for (let i = 0; i < lines.length; i++) {
                lines[i].style.setProperty('--yui-blur', '0px');
              }
            }
          }

          const applyBlockFrostedFade = (blockEl, maxBlur) => {
            if (!blockEl) return;
            const br = blockEl.getBoundingClientRect();
            const hHit = isMobileHeader || (br.left < yr.right + 96 && br.right > yr.left - 16);
            if (hHit && br.top < glassFeatherY && br.bottom > yr.top - 16) {
              anyOverlap = true;
              const cx = yuiCx - br.left;
              const cy = yuiCy - br.top;
              const s1 = glassCoreY - br.top;
              const s2 = glassFeatherY - br.top;
              const mask =
                `radial-gradient(ellipse 175px 64px at ${cx.toFixed(1)}px ${cy.toFixed(1)}px, rgba(0,0,0,0.04) 0%, rgba(0,0,0,0.12) 52%, rgba(0,0,0,1) 100%), ` +
                `linear-gradient(to bottom, rgba(0,0,0,0.06) 0px, rgba(0,0,0,0.06) ${s1.toFixed(1)}px, rgba(0,0,0,1) ${s2.toFixed(1)}px, rgba(0,0,0,1) 100%)`;
              blockEl.style.webkitMaskImage = mask;
              blockEl.style.webkitMaskComposite = 'source-in';
              blockEl.style.maskImage = mask;
              blockEl.style.maskComposite = 'intersect';
              const t = Math.max(0, Math.min(1, (glassFeatherY - br.top) / 68));
              blockEl.style.setProperty('--yui-blur', t > 0.01 ? `${(t * maxBlur).toFixed(2)}px` : '0px');
            } else if (blockEl.style.maskImage || blockEl.style.webkitMaskImage) {
              blockEl.style.webkitMaskImage = '';
              blockEl.style.webkitMaskComposite = '';
              blockEl.style.maskImage = '';
              blockEl.style.maskComposite = '';
              blockEl.style.setProperty('--yui-blur', '0px');
            }
          };

          applyBlockFrostedFade(descEl, 6.5);
          applyBlockFrostedFade(ctaEl, 7.5);

          document.body.classList.toggle('yui-hero-overlap', anyOverlap);
        }
      };
      const onScroll = () => { if (!raf) raf = requestAnimationFrame(update); };
      window.addEventListener('scroll', onScroll, { passive: true });
      window.addEventListener('resize', onScroll, { passive: true });
      update();
      return () => {
        window.removeEventListener('scroll', onScroll);
        window.removeEventListener('resize', onScroll);
        cancelAnimationFrame(raf);
        document.body.classList.remove('yui-hero-overlap');
      };
    }, []);

    // High-Density ~58,000-Particle Lagrangian GPU gl.POINTS Engine + Extreme Mouse Displacement Physics
    useEffect(() => {
      const el = heroRef.current;
      const canvas = canvasRef.current;
      if (!el || !canvas) return;

      let gl = null;
      try {
        gl =
          canvas.getContext('webgl', {
            alpha: true,
            premultipliedAlpha: true,
            antialias: false,
            depth: false,
            stencil: false,
          }) ||
          canvas.getContext('experimental-webgl', {
            alpha: true,
            premultipliedAlpha: true,
            antialias: false,
          });
      } catch (_) {
        gl = null;
      }

      let prog = null;
      let posBuf = null;
      let metaBuf = null;
      let aPosLoc = -1;
      let aColLoc = -1;
      let aMetaLoc = -1;

      let uViewCss = null;
      let uDpr = null;
      let uTime = null;
      let uCursorPx = null;
      let uCursorActive = null;
      let uAmoebaR = null;
      let uAmoebaW1 = null;
      let uAmoebaA = null;
      let uAmoebaB = null;

      let activeBank = null;
      let posX = null;
      let posY = null;
      let velX = null;
      let velY = null;
      let gpuPos = null;
      let positionsSeeded = false;

      if (gl) {
        const vsSrc = `
          attribute vec2 a_pos;
          attribute vec3 a_col;
          attribute vec4 a_meta;

          uniform vec2 u_viewCss;
          uniform float u_dpr;
          uniform float u_time;
          uniform vec2 u_cursorPx;
          uniform float u_cursorActive;
          uniform float u_amoebaR;
          uniform vec2 u_amoebaW1;
          uniform vec4 u_amoebaA;
          uniform vec4 u_amoebaB;

          varying vec3 v_col;
          varying float v_alpha;
          varying float v_pointSizePx;
          varying float v_radiusPx;
          varying float v_glyph;
          varying float v_orient;

          void main() {
            float glyphId = floor(a_meta.z);
            float seed = clamp((fract(a_meta.z) - 0.02) / 0.96, 0.0, 1.0);
            float intrinsicFocus = a_meta.w;

            vec2 pCss = a_pos;

            // Compact, peristaltic 5-harmonic liquid-amoeba cursor spotlight & force membrane
            vec2 dCur = pCss - u_cursorPx;
            float d2 = dot(dCur, dCur);
            float invD = inversesqrt(d2 + 49.0);
            vec2 uDir = dCur * invD;
            vec2 cs2 = vec2(uDir.x * uDir.x - uDir.y * uDir.y, 2.0 * uDir.x * uDir.y);
            vec2 cs3 = vec2(cs2.x * uDir.x - cs2.y * uDir.y, cs2.y * uDir.x + cs2.x * uDir.y);
            vec2 cs4 = vec2(cs2.x * cs2.x - cs2.y * cs2.y, 2.0 * cs2.x * cs2.y);
            vec2 cs5 = vec2(cs4.x * uDir.x - cs4.y * uDir.y, cs4.y * uDir.x + cs4.x * uDir.y);
            float rMod = clamp(
              1.0 + dot(u_amoebaW1, uDir)
                  + dot(u_amoebaA.xy, cs2) + dot(u_amoebaA.zw, cs3)
                  + dot(u_amoebaB.xy, cs4) + dot(u_amoebaB.zw, cs5),
              0.48,
              1.54
            );
            float localR = max(1.0, u_amoebaR * rMod);
            float qNorm = sqrt(d2) / localR;
            float curGlow = (1.0 - smoothstep(0.16, 1.06, qNorm)) * u_cursorActive;

            // Only the focal Layer 1 diamond OR particles inside the undulating amoeba hover zone stay vivid;
            // all non-focal scattered particles rest in a clean, desaturated light cool-silver!
            float vivid = clamp(max(intrinsicFocus, curGlow), 0.0, 1.0);
            float vividS = vivid * vivid * (3.0 - 2.0 * vivid);

            // Post-future vertical holographic telemetry scanline pulse + quantized digital blink
            float scanPhase = pCss.y * 0.015 - u_time * 7.2;
            float scanWave = pow(0.5 + 0.5 * sin(scanPhase), 12.0);
            float cyberStep = step(0.18, fract(seed * 17.3 + floor(u_time * 9.0) * 0.13));
            float pulse = (glyphId > 0.5 ? (0.90 + 0.10 * cyberStep) : 0.97) + 0.14 * scanWave;

            float scaleFocus = mix(0.92, 1.0, vividS);
            float cssDiam = a_meta.x * scaleFocus * (1.0 + 0.24 * curGlow + 0.07 * scanWave * vividS);
            float radiusPx = max(0.72, 0.5 * cssDiam * u_dpr);
            float pointSizePx = (glyphId > 0.5)
              ? ceil(radiusPx * 3.6 + 3.0)
              : ceil(radiusPx * 2.0 + 2.0);

            vec2 clip = (pCss / u_viewCss) * 2.0 - 1.0;
            gl_Position = vec4(clip.x, -clip.y, 0.0, 1.0);
            gl_PointSize = pointSizePx;

            vec3 coolSilver = vec3(0.66, 0.70, 0.76);
            vec3 mutedCol = mix(coolSilver, a_col, 0.08);
            vec3 vividCol = clamp(a_col * (1.0 + 0.10 * curGlow + 0.08 * scanWave), 0.0, 1.0);

            float mutedAlpha = a_meta.y * (0.36 + 0.04 * scanWave);
            float vividAlpha = clamp(a_meta.y * pulse + 0.12 * curGlow, 0.0, 0.995);

            v_col = mix(mutedCol, vividCol, vividS);
            v_alpha = mix(mutedAlpha, vividAlpha, vividS);
            v_pointSizePx = pointSizePx;
            v_radiusPx = radiusPx;
            v_glyph = glyphId;
            v_orient = step(0.28, seed);
          }
        `;

        const fsSrc = `
          #ifdef GL_FRAGMENT_PRECISION_HIGH
          precision highp float;
          #else
          precision mediump float;
          #endif

          varying vec3 v_col;
          varying float v_alpha;
          varying float v_pointSizePx;
          varying float v_radiusPx;
          varying float v_glyph;
          varying float v_orient;

          void main() {
            vec2 p = (gl_PointCoord - 0.5) * v_pointSizePx;
            float r = v_radiusPx;
            float aa = 0.46;
            float mask = 0.0;

            if (v_glyph < 0.5) {
              // Glyph 0: Razor-sharp square digital pixel / micro-voxel (■)
              float d = max(abs(p.x), abs(p.y)) - r;
              mask = 1.0 - smoothstep(-aa, aa, d);
            } else if (v_glyph < 1.5) {
              // Glyph 1: Cybernetic telemetry scan-bar (▬ / ▮)
              vec2 ext = (v_orient > 0.5)
                ? vec2(r * 1.62, max(0.72, r * 0.44))
                : vec2(max(0.72, r * 0.44), r * 1.62);
              vec2 q = abs(p) - ext;
              mask = 1.0 - smoothstep(-aa, aa, max(q.x, q.y));
            } else if (v_glyph < 2.5) {
              // Glyph 2: Post-future precision crosshair fiducial (+)
              float armLen = max(1.8, r * 1.66);
              float armHalf = max(0.62, r * 0.24);
              float dH = max(abs(p.x) - armLen, abs(p.y) - armHalf);
              float dV = max(abs(p.x) - armHalf, abs(p.y) - armLen);
              mask = 1.0 - smoothstep(-aa, aa, min(dH, dV));
            } else {
              // Glyph 3: Hollow digital voxel frame (□)
              float outerR = max(1.6, r * 1.36);
              float stroke = max(0.76, r * 0.36);
              float dOut = max(abs(p.x), abs(p.y));
              float mOut = 1.0 - smoothstep(outerR - aa, outerR + aa, dOut);
              float mIn = 1.0 - smoothstep(outerR - stroke - aa, outerR - stroke + aa, dOut);
              mask = clamp(mOut - mIn, 0.0, 1.0);
            }

            if (mask <= 0.004) discard;

            float a = mask * v_alpha;
            gl_FragColor = vec4(v_col * a, a);
          }
        `;

        const compile = (type, src) => {
          const sh = gl.createShader(type);
          gl.shaderSource(sh, src);
          gl.compileShader(sh);
          if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {
            gl.deleteShader(sh);
            return null;
          }
          return sh;
        };

        const vs = compile(gl.VERTEX_SHADER, vsSrc);
        const fs = compile(gl.FRAGMENT_SHADER, fsSrc);
        if (vs && fs) {
          prog = gl.createProgram();
          gl.attachShader(prog, vs);
          gl.attachShader(prog, fs);
          gl.linkProgram(prog);
          gl.deleteShader(vs);
          gl.deleteShader(fs);
          if (gl.getProgramParameter(prog, gl.LINK_STATUS)) {
            gl.useProgram(prog);

            posBuf = gl.createBuffer();
            metaBuf = gl.createBuffer();

            aPosLoc = gl.getAttribLocation(prog, 'a_pos');
            aColLoc = gl.getAttribLocation(prog, 'a_col');
            aMetaLoc = gl.getAttribLocation(prog, 'a_meta');

            gl.enableVertexAttribArray(aPosLoc);
            gl.enableVertexAttribArray(aColLoc);
            gl.enableVertexAttribArray(aMetaLoc);

            uViewCss = gl.getUniformLocation(prog, 'u_viewCss');
            uDpr = gl.getUniformLocation(prog, 'u_dpr');
            uTime = gl.getUniformLocation(prog, 'u_time');
            uCursorPx = gl.getUniformLocation(prog, 'u_cursorPx');
            uCursorActive = gl.getUniformLocation(prog, 'u_cursorActive');
            uAmoebaR = gl.getUniformLocation(prog, 'u_amoebaR');
            uAmoebaW1 = gl.getUniformLocation(prog, 'u_amoebaW1');
            uAmoebaA = gl.getUniformLocation(prog, 'u_amoebaA');
            uAmoebaB = gl.getUniformLocation(prog, 'u_amoebaB');

            gl.clearColor(0, 0, 0, 0);
            gl.enable(gl.BLEND);
            gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);

            const uploadBank = (bank) => {
              if (!gl || !prog || !bank) return;
              activeBank = bank;
              const n = bank.count;
              posX = new Float32Array(n);
              posY = new Float32Array(n);
              velX = new Float32Array(n);
              velY = new Float32Array(n);
              gpuPos = new Float32Array(n * 2);
              positionsSeeded = false;

              gl.bindBuffer(gl.ARRAY_BUFFER, metaBuf);
              gl.bufferData(gl.ARRAY_BUFFER, bank.staticMeta, gl.STATIC_DRAW);
              gl.vertexAttribPointer(aColLoc, 3, gl.FLOAT, false, 28, 0);
              gl.vertexAttribPointer(aMetaLoc, 4, gl.FLOAT, false, 28, 12);

              gl.bindBuffer(gl.ARRAY_BUFFER, posBuf);
              gl.bufferData(gl.ARRAY_BUFFER, gpuPos.byteLength, gl.DYNAMIC_DRAW);
              gl.vertexAttribPointer(aPosLoc, 2, gl.FLOAT, false, 0, 0);

              setParticleCoreReady(true);
            };

            uploadBankRef.current = uploadBank;
            if (cachedParticleBank) {
              uploadBank(cachedParticleBank);
            }
          } else {
            gl.deleteProgram(prog);
            prog = null;
            gl = null;
          }
        } else {
          if (vs) gl.deleteShader(vs);
          if (fs) gl.deleteShader(fs);
          gl = null;
        }
      }

      const ctx2d = !gl ? canvas.getContext('2d') : null;

      let width = 0;
      let height = 0;
      let dpr = 1;
      let heroVisible = true;
      let animId = 0;

      const rawPointer = { x: 0.5, y: 0.5 };
      let pointerActive = 0;
      let pointerInside = 0;
      let pointerPresence = 0;
      let cursorInitialized = false;
      const cursorPx = { x: 0, y: 0 };
      const cursorVel = { x: 0, y: 0 };

      // 13-node viscoelastic spring-damper chain for slow, syrupy surface-tension diamond motion
      const diamondNodes = Array.from({ length: LAYER_COUNT }, () => ({
        x: 0.5,
        y: 0.5,
        vx: 0,
        vy: 0,
      }));
      const ringCx = new Float32Array(LAYER_COUNT);
      const ringCy = new Float32Array(LAYER_COUNT);
      const ringM00 = new Float32Array(LAYER_COUNT);
      const ringM01 = new Float32Array(LAYER_COUNT);
      const ringM10 = new Float32Array(LAYER_COUNT);
      const ringM11 = new Float32Array(LAYER_COUNT);

      const resize = () => {
        const r = el.getBoundingClientRect();
        const nextW = Math.max(1, r.width);
        const nextH = Math.max(1, r.height);
        if (positionsSeeded && posX && posY && width > 0 && height > 0) {
          const sx = nextW / width;
          const sy = nextH / height;
          for (let i = 0; i < posX.length; i++) {
            posX[i] *= sx;
            posY[i] *= sy;
          }
        }
        width = nextW;
        height = nextH;
        dpr = Math.min(window.devicePixelRatio || 1, 2);
        canvas.width = Math.round(width * dpr);
        canvas.height = Math.round(height * dpr);
        if (!cursorInitialized) {
          cursorPx.x = width * 0.5;
          cursorPx.y = height * 0.5;
        }
        if (gl) {
          gl.viewport(0, 0, canvas.width, canvas.height);
        } else if (ctx2d) {
          ctx2d.setTransform(dpr, 0, 0, dpr, 0, 0);
        }
      };
      resize();

      const onPointerMove = (e) => {
        const rect = el.getBoundingClientRect();
        const rw = Math.max(1, rect.width || width || window.innerWidth || 1);
        const rh = Math.max(1, rect.height || height || window.innerHeight || 1);
        rawPointer.x = Math.max(0, Math.min(1, (e.clientX - rect.left) / rw));
        rawPointer.y = Math.max(0, Math.min(1, (e.clientY - rect.top) / rh));
        pointerActive = 1;
        pointerInside = 1;
      };

      const onPointerLeave = () => {
        pointerActive = 0;
        pointerInside = 0;
      };

      let visIo = null;
      if ('IntersectionObserver' in window) {
        visIo = new IntersectionObserver(
          ([entry]) => {
            const next = entry.isIntersecting;
            if (next && !heroVisible) {
              heroVisible = true;
              if (!animId) animId = requestAnimationFrame(tick);
            } else {
              heroVisible = next;
            }
          },
          { threshold: 0.01 }
        );
        visIo.observe(el);
      }

      let time = 0;
      let amoebaPhase = 0;
      let frameCount = 0;

      const tick = () => {
        animId = 0;
        if (!heroVisible) return;

        const minimal = isMinimalMotion();
        if (!minimal) time += 0.0015;
        frameCount++;

        const wSafe = Math.max(1, width);
        const hSafe = Math.max(1, height);

        // Smooth liquid cursor tracking + controlled velocity for subtle ameboid peristalsis
        const targetCx = rawPointer.x * wSafe;
        const targetCy = rawPointer.y * hSafe;
        if (!cursorInitialized && pointerInside > 0) {
          cursorPx.x = targetCx;
          cursorPx.y = targetCy;
          cursorInitialized = true;
        }
        const prevCx = cursorPx.x;
        const prevCy = cursorPx.y;
        cursorPx.x += (targetCx - cursorPx.x) * 0.22;
        cursorPx.y += (targetCy - cursorPx.y) * 0.22;

        const stepVx = cursorPx.x - prevCx;
        const stepVy = cursorPx.y - prevCy;
        cursorVel.x = cursorVel.x * 0.84 + stepVx * 0.88;
        cursorVel.y = cursorVel.y * 0.84 + stepVy * 0.88;
        const velMag = Math.hypot(cursorVel.x, cursorVel.y);
        if (velMag > 36) {
          const sc = 36 / velMag;
          cursorVel.x *= sc;
          cursorVel.y *= sc;
        }
        const cursorSpeedNorm = Math.min(1, velMag / 18);
        if (!minimal) {
          amoebaPhase += 0.028 + cursorSpeedNorm * 0.024;
        }
        pointerPresence += ((minimal ? 0 : pointerInside) - pointerPresence) * 0.09;

        pointerActive *= 0.997;
        const idleOrbitX = 0.5 + 0.044 * Math.sin(time * 0.58) + 0.018 * Math.cos(time * 1.06);
        const idleOrbitY = 0.5 + 0.036 * Math.cos(time * 0.46) + 0.016 * Math.sin(time * 0.86);
        const effTargetX = minimal
          ? 0.5
          : idleOrbitX + (rawPointer.x - idleOrbitX) * pointerActive;
        const effTargetY = minimal
          ? 0.5
          : idleOrbitY + (rawPointer.y - idleOrbitY) * pointerActive;

        // Overdamped slow-motion viscoelastic spring-damper chain
        const n0 = diamondNodes[0];
        n0.vx = (n0.vx + (effTargetX - n0.x) * 0.0024) * 0.87;
        n0.vy = (n0.vy + (effTargetY - n0.y) * 0.0024) * 0.87;
        n0.x += n0.vx;
        n0.y += n0.vy;

        for (let i = 1; i < LAYER_COUNT; i++) {
          const prev = diamondNodes[i - 1];
          const ni = diamondNodes[i];
          const k = 0.016 - i * 0.00045;
          ni.vx = (ni.vx + (prev.x - ni.x) * k) * 0.78;
          ni.vy = (ni.vy + (prev.y - ni.y) * k) * 0.78;
          ni.x += ni.vx;
          ni.y += ni.vy;
        }

        const elems = layerRefs.current;
        const r0Sq = Math.pow(Math.min(wSafe, hSafe) * 0.19, 2);
        const vmin = Math.min(window.innerWidth || wSafe, window.innerHeight || hSafe);
        const coreSizePx = Math.max(336, Math.min(840, vmin * 0.64));

        for (let i = 0; i < LAYER_COUNT; i++) {
          const ni = diamondNodes[i];

          const dx =
            (ni.x - 0.5) * (66 - i * 1.4) +
            (ni.x - n0.x) * 96 +
            (minimal ? 0 : Math.cos(time * 1.10 - i * 0.24) * (0.5 + i * 0.08));
          const dy =
            (ni.y - 0.5) * (48 - i * 1.0) +
            (ni.y - n0.y) * 74 +
            (minimal ? 0 : Math.sin(time * 0.94 - i * 0.24) * (0.4 + i * 0.06));

          const pullNormX = (effTargetX - ni.x) * 0.36 + (n0.x - ni.x) * 1.45 + ni.vx * 14.0;
          const pullNormY = (effTargetY - ni.y) * 0.36 + (n0.y - ni.y) * 1.45 + ni.vy * 14.0;
          const ambX = minimal ? 0 : Math.cos(time * 0.80 - i * 0.18) * 15;
          const ambY = minimal ? 0 : Math.sin(time * 0.80 - i * 0.18) * 15;

          const tx = pullNormX * wSafe + ambX;
          const ty = pullNormY * hSafe + ambY;
          const rSq = tx * tx + ty * ty;

          const maxStretch = 0.088 + i * 0.0022;
          const stretch = minimal ? 0 : maxStretch * (rSq / (rSq + r0Sq));
          const pullRad = Math.atan2(ty, tx);
          const pullDeg = pullRad * (180 / Math.PI);

          const shearRot =
            (ni.x - n0.x) * -18 +
            (ni.x - 0.5) * (0.62 + i * 0.14);
          const idleRot = Math.sin(time * 0.62 - i * 0.20) * (0.40 + i * 0.10);
          const rot = minimal ? 0 : idleRot + shearRot;

          const breath = minimal
            ? 1
            : 1 + (0.006 + i * 0.0005) * Math.sin(time * 1.12 - i * 0.22);
          const sx = breath * (1 + stretch);
          const sy = breath * (1 - stretch * 0.52);

          const alphaRad = (-pullDeg + rot) * (Math.PI / 180);
          const cb = Math.cos(pullRad);
          const sb = Math.sin(pullRad);
          const ca = Math.cos(alphaRad);
          const sa = Math.sin(alphaRad);

          const fwd00 = cb * (sx * ca) - sb * (sy * sa);
          const fwd01 = -cb * (sx * sa) - sb * (sy * ca);
          const fwd10 = sb * (sx * ca) + cb * (sy * sa);
          const fwd11 = -sb * (sx * sa) + cb * (sy * ca);

          ringCx[i] = wSafe * 0.5 + dx;
          ringCy[i] = hSafe * 0.5 + dy;
          ringM00[i] = fwd00 * coreSizePx;
          ringM01[i] = fwd01 * coreSizePx;
          ringM10[i] = fwd10 * coreSizePx;
          ringM11[i] = fwd11 * coreSizePx;

          const layerEl = elems[i];
          if (layerEl) {
            layerEl.style.transform =
              `translate3d(${dx.toFixed(2)}px, ${dy.toFixed(2)}px, 0) ` +
              `rotate(${pullDeg.toFixed(2)}deg) ` +
              `scale(${sx.toFixed(4)}, ${sy.toFixed(4)}) ` +
              `rotate(${(-pullDeg + rot).toFixed(2)}deg)`;
          }
        }

        if (gl && prog && activeBank && posX && gpuPos) {
          const n = activeBank.count;
          const hX = activeBank.homeX;
          const hY = activeBank.homeY;
          const rIdx = activeBank.ringIdx;
          const compArr = activeBank.compliance;

          const curX = cursorPx.x;
          const curY = cursorPx.y;
          const cvx = cursorVel.x;
          const cvy = cursorVel.y;
          const cAct = pointerPresence;

          // Compact, peristaltic 5-harmonic liquid-amoeba boundary (~85px..110px mean radius)
          const baseR = Math.max(72, Math.min(118, coreSizePx * 0.168));
          const maxR = baseR * 1.56;
          const maxR2 = maxR * maxR;

          const velStretch = Math.min(0.26, velMag / 82);
          const vUx = velMag > 0.08 ? cvx / velMag : 0;
          const vUy = velMag > 0.08 ? cvy / velMag : 0;

          // Asymmetric crawling pseudopod harmonics (incommensurate frequencies = non-repeating liquid amoeba)
          const w1x = 0.13 * Math.cos(amoebaPhase * 0.83) - vUx * velStretch;
          const w1y = 0.13 * Math.sin(amoebaPhase * 0.71) - vUy * velStretch;
          const w2c = 0.20 * Math.sin(amoebaPhase * 1.09 + 0.4) + (vUx * vUx - vUy * vUy) * velStretch * 0.65;
          const w2s = 0.20 * Math.cos(amoebaPhase * 0.93 - 0.7) + (2 * vUx * vUy) * velStretch * 0.65;
          const w3c = 0.24 * Math.cos(amoebaPhase * 1.37) + 0.09 * Math.sin(amoebaPhase * -0.79 + 1.8);
          const w3s = 0.24 * Math.sin(amoebaPhase * 1.21) + 0.09 * Math.cos(amoebaPhase * 0.97 + 0.6);
          const w4c = 0.15 * Math.sin(amoebaPhase * -1.73 + 2.1);
          const w4s = 0.15 * Math.cos(amoebaPhase * 1.57 - 1.2);
          const w5c = 0.09 * Math.cos(amoebaPhase * 2.29 + 0.9);
          const w5s = 0.09 * Math.sin(amoebaPhase * -2.07 + 2.7);

          // Calm, poised 3D parallax so the bright digital layout stays crisp and composed
          const parBaseX = (curX - wSafe * 0.5) * 0.022 * cAct;
          const parBaseY = (curY - hSafe * 0.5) * 0.022 * cAct;
          const parCoreX = parBaseX * 0.28;
          const parCoreY = parBaseY * 0.28;

          const rc0x = ringCx[0] + parCoreX;
          const rc0y = ringCy[0] + parCoreY;
          const m00_0 = ringM00[0];
          const m01_0 = ringM01[0];
          const m10_0 = ringM10[0];
          const m11_0 = ringM11[0];

          if (!positionsSeeded) {
            for (let i = 0; i < n; i++) {
              const r = rIdx[i];
              const hx = hX[i];
              const hy = hY[i];
              let px0;
              let py0;
              if (r === 255) {
                px0 = hx * wSafe;
                py0 = hy * hSafe;
              } else {
                px0 = ringCx[r] + hx * ringM00[r] + hy * ringM01[r];
                py0 = ringCy[r] + hx * ringM10[r] + hy * ringM11[r];
              }
              posX[i] = px0;
              posY[i] = py0;
              gpuPos[i * 2] = px0;
              gpuPos[i * 2 + 1] = py0;
            }
            positionsSeeded = true;
          } else {
            // Subtle, tactile liquid-protoplasm force (~18px..44px undulating displacement)
            const repelAmp = 1.48 + cursorSpeedNorm * 1.55;
            const peristalticWave = Math.sin(amoebaPhase * 1.9);
            const driftT1 = time * 2.4;
            const driftT2 = time * 1.7;

            for (let i = 0; i < n; i++) {
              const r = rIdx[i];
              const hx = hX[i];
              const hy = hY[i];
              const comp = compArr[i];

              let targetX;
              let targetY;
              if (r === 0) {
                targetX = rc0x + hx * m00_0 + hy * m01_0;
                targetY = rc0y + hx * m10_0 + hy * m11_0;
              } else if (r === 255) {
                const driftX = minimal ? 0 : Math.sin(driftT1 + hy * 16.0) * 6.0;
                const driftY = minimal ? 0 : Math.cos(driftT2 + hx * 14.0) * 4.5;
                targetX = hx * wSafe + driftX + parBaseX * comp;
                targetY = hy * hSafe + driftY + parBaseY * comp;
              } else {
                targetX = ringCx[r] + hx * ringM00[r] + hy * ringM01[r] + parCoreX * (1 + r * 0.08);
                targetY = ringCy[r] + hx * ringM10[r] + hy * ringM11[r] + parCoreY * (1 + r * 0.08);
              }

              let px = posX[i];
              let py = posY[i];
              let vx = velX[i];
              let vy = velY[i];

              const kSpring = r === 0 ? 0.048 : 0.035 * (1.20 - 0.16 * comp);
              let ax = (targetX - px) * kSpring;
              let ay = (targetY - py) * kSpring;

              if (cAct > 0.004) {
                const dx = px - curX;
                const dy = py - curY;
                const d2 = dx * dx + dy * dy;
                if (d2 < maxR2) {
                  const invD = 1 / Math.sqrt(d2 + 49);
                  const ux = dx * invD;
                  const uy = dy * invD;

                  // Chebyshev angular harmonics for zero-trig undulating amoeba silhouette
                  const c2 = ux * ux - uy * uy;
                  const s2 = 2 * ux * uy;
                  const c3 = c2 * ux - s2 * uy;
                  const s3 = s2 * ux + c2 * uy;
                  const c4 = c2 * c2 - s2 * s2;
                  const s4 = 2 * c2 * s2;
                  const c5 = c4 * ux - s4 * uy;
                  const s5 = s4 * ux + c4 * uy;

                  let rMod =
                    1.0 +
                    w1x * ux + w1y * uy +
                    w2c * c2 + w2s * s2 +
                    w3c * c3 + w3s * s3 +
                    w4c * c4 + w4s * s4 +
                    w5c * c5 + w5s * s5;
                  if (rMod < 0.48) rMod = 0.48;
                  else if (rMod > 1.54) rMod = 1.54;

                  const localR = baseR * rMod;
                  const localR2 = localR * localR;

                  if (d2 < localR2) {
                    const dist = Math.sqrt(d2);
                    const q = dist / localR;
                    const oneMinusQ = 1 - q;
                    // Smooth liquid meniscus profile + membrane wall slope normal
                    const falloff = oneMinusQ * oneMinusQ * (1 + 2 * q) * cAct;
                    const meniscus = q * oneMinusQ * 4.0 * cAct;

                    // Angular derivative d(rMod)/d(theta) bends force perpendicular to each pseudopod lobe!
                    const dMod =
                      (-w1x * uy + w1y * ux) +
                      2 * (-w2c * s2 + w2s * c2) +
                      3 * (-w3c * s3 + w3s * c3) +
                      4 * (-w4c * s4 + w4s * c4);
                    const tangSlope = (-dMod / rMod) * 0.42;

                    const normX = ux - uy * tangSlope;
                    const normY = uy + ux * tangSlope;

                    // 1) Gentle liquid-protoplasm parting sculpted to the wriggling amoeba lobes
                    const push = repelAmp * falloff * comp;
                    ax += normX * push;
                    ay += normY * push;

                    // 2) Continuous cytoplasmic peristaltic crawl inside the amoeba even when cursor is still
                    const crawl = (0.34 * dMod + 0.18 * peristalticWave) * meniscus * comp;
                    ax += -uy * crawl;
                    ay += ux * crawl;

                    // 3) Soft viscous drag wake along cursor glide
                    const wake = 0.22 * falloff * comp;
                    ax += cvx * wake;
                    ay += cvy * wake;
                  }
                }
              }

              vx = (vx + ax) * 0.84;
              vy = (vy + ay) * 0.84;

              const v2 = vx * vx + vy * vy;
              if (v2 > 256) {
                const vs = 16 / Math.sqrt(v2);
                vx *= vs;
                vy *= vs;
              }

              px += vx;
              py += vy;

              posX[i] = px;
              posY[i] = py;
              velX[i] = vx;
              velY[i] = vy;
              gpuPos[i * 2] = px;
              gpuPos[i * 2 + 1] = py;
            }
          }

          gl.clear(gl.COLOR_BUFFER_BIT);
          gl.bindBuffer(gl.ARRAY_BUFFER, posBuf);
          gl.bufferSubData(gl.ARRAY_BUFFER, 0, gpuPos);

          gl.uniform2f(uViewCss, wSafe, hSafe);
          gl.uniform1f(uDpr, dpr);
          gl.uniform1f(uTime, time);
          gl.uniform2f(uCursorPx, curX, curY);
          gl.uniform1f(uCursorActive, cAct);
          gl.uniform1f(uAmoebaR, baseR);
          gl.uniform2f(uAmoebaW1, w1x, w1y);
          gl.uniform4f(uAmoebaA, w2c, w2s, w3c, w3s);
          gl.uniform4f(uAmoebaB, w4c, w4s, w5c, w5s);

          gl.drawArrays(gl.POINTS, 0, n);
        } else if (ctx2d) {
          ctx2d.clearRect(0, 0, width, height);
        }

        if (!minimal || frameCount < 2) {
          animId = requestAnimationFrame(tick);
        }
      };

      window.addEventListener('pointermove', onPointerMove, { passive: true });
      document.addEventListener('mouseleave', onPointerLeave, { passive: true });
      window.addEventListener('resize', resize, { passive: true });
      animId = requestAnimationFrame(tick);

      return () => {
        uploadBankRef.current = null;
        window.removeEventListener('pointermove', onPointerMove);
        document.removeEventListener('mouseleave', onPointerLeave);
        window.removeEventListener('resize', resize);
        if (visIo) visIo.disconnect();
        cancelAnimationFrame(animId);
        if (gl) {
          if (posBuf) gl.deleteBuffer(posBuf);
          if (metaBuf) gl.deleteBuffer(metaBuf);
          if (prog) gl.deleteProgram(prog);
        }
      };
    }, []);

    // Colorful "Product" Digital Micro-Glyph Particle Engine (Subtle / Restrained Mouse Influence)
    useEffect(() => {
      const heroEl = heroRef.current;
      const lineEl = productLineRef.current;
      const canvas = productCanvasRef.current;
      if (!heroEl || !lineEl || !canvas) return;

      const PAD = 26;
      const CHARS = ['P', 'r', 'o', 'd', 'u', 'c', 't'];

      let gl = null;
      try {
        gl =
          canvas.getContext('webgl', {
            alpha: true,
            premultipliedAlpha: true,
            antialias: false,
            depth: false,
            stencil: false,
          }) ||
          canvas.getContext('experimental-webgl', {
            alpha: true,
            premultipliedAlpha: true,
            antialias: false,
          });
      } catch (_) {
        gl = null;
      }

      let prog = null;
      let posBuf = null;
      let metaBuf = null;
      let aPosLoc = -1;
      let aUvCharLoc = -1;
      let aMetaLoc = -1;

      let uViewCss = null;
      let uDpr = null;
      let uTime = null;
      let uCursorPx = null;
      let uCursorActive = null;
      let uHoverR = null;
      let uCharCpALoc = null;
      let uCharCpBLoc = null;

      if (gl) {
        const vsSrc = `
          #ifdef GL_FRAGMENT_PRECISION_HIGH
          precision highp float;
          #else
          precision mediump float;
          #endif

          attribute vec2 a_pos;
          attribute vec3 a_uvChar;
          attribute vec4 a_meta;

          uniform vec2 u_viewCss;
          uniform float u_dpr;
          uniform float u_time;
          uniform vec2 u_cursorPx;
          uniform float u_cursorActive;
          uniform float u_hoverR;
          uniform vec4 u_charCpA;
          uniform vec3 u_charCpB;

          varying vec3 v_col;
          varying float v_alpha;
          varying float v_pointSizePx;
          varying float v_radiusPx;
          varying float v_glyph;
          varying float v_orient;

          vec3 sampleProductHolo(float t) {
            float x = fract(t) * 6.0;
            float idx = floor(x);
            float f = x - idx;
            vec3 c0 = vec3(0.00, 0.84, 0.44); // Acid Signal-Emerald (#00D670)
            vec3 c1 = vec3(0.00, 0.78, 0.98); // Electric Cyber-Cyan (#00C7FA)
            vec3 c2 = vec3(0.15, 0.36, 1.00); // Neon Ultramarine-Cobalt (#265CFF)
            vec3 c3 = vec3(0.56, 0.17, 1.00); // Post-Future Hyper-Violet (#8F2BFF)
            vec3 c4 = vec3(0.96, 0.10, 0.56); // Cyber Hyper-Magenta (#F51A8F)
            vec3 c5 = vec3(0.18, 0.62, 0.98); // Luminous Sky-Azure bridge (#2E9EFA — avoids RGB muddy grey!)
            if (idx < 0.5) return mix(c0, c1, f);
            if (idx < 1.5) return mix(c1, c2, f);
            if (idx < 2.5) return mix(c2, c3, f);
            if (idx < 3.5) return mix(c3, c4, f);
            if (idx < 4.5) return mix(c4, c3, f);
            if (f < 0.5) return mix(c3, c5, f * 2.0);
            return mix(c5, c0, (f - 0.5) * 2.0);
          }

          float lookupCharCp(float ci) {
            if (ci < 0.5) return u_charCpA.x;
            if (ci < 1.5) return u_charCpA.y;
            if (ci < 2.5) return u_charCpA.z;
            if (ci < 3.5) return u_charCpA.w;
            if (ci < 4.5) return u_charCpB.x;
            if (ci < 5.5) return u_charCpB.y;
            return u_charCpB.z;
          }

          void main() {
            float uNorm = a_uvChar.x;
            float vNorm = a_uvChar.y;
            float charIdx = a_uvChar.z;

            float glyphId = floor(a_meta.z);
            float seed = clamp((fract(a_meta.z) - 0.02) / 0.96, 0.0, 1.0);
            float isSpark = a_meta.w;

            vec2 pCss = a_pos;
            vec2 dCur = pCss - u_cursorPx;
            float d = length(dCur);
            float qNorm = d / max(1.0, u_hoverR);
            float curGlow = (1.0 - smoothstep(0.10, 1.0, qNorm)) * u_cursorActive;

            float cp = clamp(lookupCharCp(charIdx), 0.0, 1.0);

            // Flowing holographic cyber spectrum across italic "Product"
            float holoPhase = uNorm * 0.88 - vNorm * 0.18 - u_time * 0.14 + (seed - 0.5) * 0.06;
            vec3 holoCol = sampleProductHolo(holoPhase);

            // Digital telemetry scanline pulse + quantized voxel shimmer
            float scanPhase = pCss.y * 0.055 - u_time * 6.8;
            float scanWave = pow(0.5 + 0.5 * sin(scanPhase), 10.0);
            float cyberStep = step(0.16, fract(seed * 19.7 + floor(u_time * 8.5) * 0.13));
            float pulse = (glyphId > 0.5 ? (0.91 + 0.09 * cyberStep) : 0.97) + 0.11 * scanWave;

            // Gentle micro-scale response on cursor hover (much subtler than diamond)
            float cssDiam = a_meta.x * (1.0 + 0.11 * curGlow + 0.04 * scanWave);
            float radiusPx = max(0.68, 0.5 * cssDiam * u_dpr);
            float pointSizePx = (glyphId > 0.5)
              ? ceil(radiusPx * 3.6 + 3.0)
              : ceil(radiusPx * 2.0 + 2.0);

            vec2 clip = (pCss / u_viewCss) * 2.0 - 1.0;
            gl_Position = vec4(clip.x, -clip.y, 0.0, 1.0);
            gl_PointSize = pointSizePx;

            // Matches Hero title scroll-reveal choreography:
            // muted digital voxels at scroll=0 -> vivid holographic cyber particles on scroll (or gentle cursor glimmer)
            vec3 mutedInk = vec3(0.118, 0.118, 0.133);
            float colorMix = clamp(max(smoothstep(0.30, 0.88, cp), curGlow * 0.82), 0.0, 1.0);
            vec3 baseCol = mix(mutedInk, holoCol * (0.96 + 0.08 * scanWave + 0.08 * curGlow), colorMix);
            vec3 col = clamp(baseCol, 0.0, 1.0);

            float strokeReveal = mix(0.30, 1.0, smoothstep(0.0, 0.92, cp));
            float sparkReveal = mix(0.16, 0.88, smoothstep(0.15, 0.96, cp));
            float alphaReveal = max(isSpark > 0.5 ? sparkReveal : strokeReveal, curGlow * (isSpark > 0.5 ? 0.58 : 0.78));

            v_col = col;
            v_alpha = clamp(a_meta.y * alphaReveal * pulse, 0.0, 0.995);
            v_pointSizePx = pointSizePx;
            v_radiusPx = radiusPx;
            v_glyph = glyphId;
            v_orient = step(0.30, seed);
          }
        `;

        const fsSrc = `
          #ifdef GL_FRAGMENT_PRECISION_HIGH
          precision highp float;
          #else
          precision mediump float;
          #endif

          varying vec3 v_col;
          varying float v_alpha;
          varying float v_pointSizePx;
          varying float v_radiusPx;
          varying float v_glyph;
          varying float v_orient;

          void main() {
            vec2 p = (gl_PointCoord - 0.5) * v_pointSizePx;
            float r = v_radiusPx;
            float aa = 0.44;
            float mask = 0.0;

            if (v_glyph < 0.5) {
              float d = max(abs(p.x), abs(p.y)) - r;
              mask = 1.0 - smoothstep(-aa, aa, d);
            } else if (v_glyph < 1.5) {
              vec2 ext = (v_orient > 0.5)
                ? vec2(r * 1.62, max(0.70, r * 0.44))
                : vec2(max(0.70, r * 0.44), r * 1.62);
              vec2 q = abs(p) - ext;
              mask = 1.0 - smoothstep(-aa, aa, max(q.x, q.y));
            } else if (v_glyph < 2.5) {
              float armLen = max(1.75, r * 1.64);
              float armHalf = max(0.60, r * 0.24);
              float dH = max(abs(p.x) - armLen, abs(p.y) - armHalf);
              float dV = max(abs(p.x) - armHalf, abs(p.y) - armLen);
              mask = 1.0 - smoothstep(-aa, aa, min(dH, dV));
            } else {
              float outerR = max(1.55, r * 1.36);
              float stroke = max(0.72, r * 0.36);
              float dOut = max(abs(p.x), abs(p.y));
              float mOut = 1.0 - smoothstep(outerR - aa, outerR + aa, dOut);
              float mIn = 1.0 - smoothstep(outerR - stroke - aa, outerR - stroke + aa, dOut);
              mask = clamp(mOut - mIn, 0.0, 1.0);
            }

            if (mask <= 0.004) discard;
            float a = mask * v_alpha;
            gl_FragColor = vec4(v_col * a, a);
          }
        `;

        const compile = (type, src) => {
          const sh = gl.createShader(type);
          gl.shaderSource(sh, src);
          gl.compileShader(sh);
          if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {
            gl.deleteShader(sh);
            return null;
          }
          return sh;
        };

        const vs = compile(gl.VERTEX_SHADER, vsSrc);
        const fs = compile(gl.FRAGMENT_SHADER, fsSrc);
        if (vs && fs) {
          prog = gl.createProgram();
          gl.attachShader(prog, vs);
          gl.attachShader(prog, fs);
          gl.linkProgram(prog);
          gl.deleteShader(vs);
          gl.deleteShader(fs);
          if (gl.getProgramParameter(prog, gl.LINK_STATUS)) {
            gl.useProgram(prog);
            posBuf = gl.createBuffer();
            metaBuf = gl.createBuffer();

            aPosLoc = gl.getAttribLocation(prog, 'a_pos');
            aUvCharLoc = gl.getAttribLocation(prog, 'a_uvChar');
            aMetaLoc = gl.getAttribLocation(prog, 'a_meta');
            gl.enableVertexAttribArray(aPosLoc);
            gl.enableVertexAttribArray(aUvCharLoc);
            gl.enableVertexAttribArray(aMetaLoc);

            uViewCss = gl.getUniformLocation(prog, 'u_viewCss');
            uDpr = gl.getUniformLocation(prog, 'u_dpr');
            uTime = gl.getUniformLocation(prog, 'u_time');
            uCursorPx = gl.getUniformLocation(prog, 'u_cursorPx');
            uCursorActive = gl.getUniformLocation(prog, 'u_cursorActive');
            uHoverR = gl.getUniformLocation(prog, 'u_hoverR');
            uCharCpALoc = gl.getUniformLocation(prog, 'u_charCpA');
            uCharCpBLoc = gl.getUniformLocation(prog, 'u_charCpB');

            gl.clearColor(0, 0, 0, 0);
            gl.enable(gl.BLEND);
            gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
          } else {
            gl.deleteProgram(prog);
            prog = null;
            gl = null;
          }
        } else {
          if (vs) gl.deleteShader(vs);
          if (fs) gl.deleteShader(fs);
          gl = null;
        }
      }

      const ctx2d = !gl ? canvas.getContext('2d') : null;

      const bayer8 = (x, y) => {
        const xc = x & 7;
        const yc = y & 7;
        const xm = xc ^ yc;
        let v = 0;
        v |= ((xm & 4) >> 1) | (yc & 4);
        v = (v << 2) | ((xm & 2) | ((yc & 2) << 1));
        v = (v << 2) | (((xm & 1) << 1) | ((yc & 1) << 2));
        return ((v >> 2) + 0.5) / 64;
      };
      const packGlyphSeed = (glyphId, s) => glyphId + (0.02 + s * 0.96);

      const blur2D = (input, w, h, radius) => {
        const tmp = new Float32Array(w * h);
        const out = new Float32Array(w * h);
        const inv = 1 / (2 * radius + 1);
        for (let y = 0; y < h; y++) {
          const row = y * w;
          let sum = 0;
          for (let dx = -radius; dx <= radius; dx++) {
            const cx = dx < 0 ? 0 : dx >= w ? w - 1 : dx;
            sum += input[row + cx];
          }
          for (let x = 0; x < w; x++) {
            tmp[row + x] = sum * inv;
            const rem = x - radius < 0 ? 0 : x - radius;
            const add = x + radius + 1 >= w ? w - 1 : x + radius + 1;
            sum += input[row + add] - input[row + rem];
          }
        }
        for (let x = 0; x < w; x++) {
          let sum = 0;
          for (let dy = -radius; dy <= radius; dy++) {
            const cy = dy < 0 ? 0 : dy >= h ? h - 1 : dy;
            sum += tmp[cy * w + x];
          }
          for (let y = 0; y < h; y++) {
            out[y * w + x] = sum * inv;
            const rem = y - radius < 0 ? 0 : y - radius;
            const add = y + radius + 1 >= h ? h - 1 : y + radius + 1;
            sum += tmp[add * w + x] - tmp[rem * w + x];
          }
        }
        return out;
      };

      let bank = null;
      let posX = null;
      let posY = null;
      let velX = null;
      let velY = null;
      let gpuPos = null;
      let cssW = 1;
      let cssH = 1;
      let dpr = 1;
      let curFontSize = 64;
      let lastSig = '';
      let heroVisible = true;
      let animId = 0;

      const buildProductBank = (force = false) => {
        const spans = lineEl.querySelectorAll('.hero__product-sizer .stxc');
        if (!spans || spans.length < 7) return;
        const lr = lineEl.getBoundingClientRect();
        if (lr.width < 4 || lr.height < 4) return;

        const sRects = [...spans].map((sp) => sp.getBoundingClientRect());
        const cs = getComputedStyle(lineEl);
        const fontSize = Math.max(24, parseFloat(cs.fontSize) || 64);
        const fontStyle = cs.fontStyle || 'italic';
        const fontWeight = cs.fontWeight || '500';
        const fontFamily = cs.fontFamily || "Georgia, 'Times New Roman', serif";

        const nextDpr = Math.min(window.devicePixelRatio || 1, 2);
        const contentRight = Math.max(lr.width, sRects[6].right - lr.left + 12);
        const nextW = Math.ceil(contentRight + PAD * 2);
        const nextH = Math.ceil(lr.height + PAD * 2);
        const sig = `${nextW}x${nextH}@${fontSize.toFixed(2)}@${nextDpr.toFixed(2)}`;
        if (!force && sig === lastSig && bank) return;
        lastSig = sig;

        cssW = nextW;
        cssH = nextH;
        dpr = nextDpr;
        curFontSize = fontSize;

        canvas.style.width = `${cssW}px`;
        canvas.style.height = `${cssH}px`;
        canvas.width = Math.round(cssW * dpr);
        canvas.height = Math.round(cssH * dpr);
        if (gl) {
          gl.viewport(0, 0, canvas.width, canvas.height);
        } else if (ctx2d) {
          ctx2d.setTransform(dpr, 0, 0, dpr, 0, 0);
        }

        const SS = 2;
        const tw = Math.max(8, cssW * SS);
        const th = Math.max(8, cssH * SS);
        const off = document.createElement('canvas');
        off.width = tw;
        off.height = th;
        const octx = off.getContext('2d');
        if (!octx) return;

        octx.scale(SS, SS);
        octx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;
        octx.textBaseline = 'alphabetic';
        octx.fillStyle = '#000';

        const tm = octx.measureText('Product');
        const fAsc = tm.fontBoundingBoxAscent || fontSize * 0.78;
        const fDesc = tm.fontBoundingBoxDescent || fontSize * 0.22;

        const charCxs = new Float32Array(7);
        let baselineY = PAD + lr.height * 0.78;
        for (let k = 0; k < 7; k++) {
          const sr = sRects[k];
          const cx = PAD + (sr.left - lr.left);
          const cy = PAD + (sr.top - lr.top) + (sr.height - (fAsc + fDesc)) * 0.5 + fAsc;
          if (k === 0) baselineY = cy;
          charCxs[k] = cx + sr.width * 0.42;
          octx.fillText(CHARS[k], cx, cy);
        }

        const wordLeft = PAD + (sRects[0].left - lr.left);
        const wordSpan = Math.max(12, PAD + (sRects[6].right - lr.left) - wordLeft);

        let imgData;
        try {
          imgData = octx.getImageData(0, 0, tw, th).data;
        } catch (_) {
          return;
        }

        const nPix = tw * th;
        const alphaSS = new Float32Array(nPix);
        for (let i = 0; i < nPix; i++) {
          alphaSS[i] = imgData[i * 4 + 3] / 255;
        }
        const haloRad = Math.max(4, Math.round(fontSize * 0.08 * SS));
        const haloSS = blur2D(alphaSS, tw, th, haloRad);

        let rng = 0x51f15eed;
        const rand = () => {
          rng = (rng + 0x6d2b79f5) | 0;
          let t = Math.imul(rng ^ (rng >>> 15), 1 | rng);
          t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
          return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
        };

        // Quantized cyber-voxel grid scaled so individual square digital pixels stay visibly distinct on #ffffff
        const stepCss = Math.max(1.55, Math.min(2.75, fontSize * 0.0228));
        const cols = Math.floor(cssW / stepCss);
        const rows = Math.floor(cssH / stepCss);
        const cellAvg = new Float32Array(cols * rows);
        const cellMax = new Float32Array(cols * rows);
        const cellBestX = new Float32Array(cols * rows);
        const cellBestY = new Float32Array(cols * rows);

        for (let gy = 0; gy < rows; gy++) {
          const sy0 = Math.max(0, Math.floor(gy * stepCss * SS));
          const sy1 = Math.min(th - 1, Math.ceil((gy + 1) * stepCss * SS));
          for (let gx = 0; gx < cols; gx++) {
            const sx0 = Math.max(0, Math.floor(gx * stepCss * SS));
            const sx1 = Math.min(tw - 1, Math.ceil((gx + 1) * stepCss * SS));
            let sumA = 0;
            let maxA = 0;
            let wX = 0;
            let wY = 0;
            let cnt = 0;
            for (let sy = sy0; sy <= sy1; sy++) {
              const rowOff = sy * tw;
              for (let sx = sx0; sx <= sx1; sx++) {
                const a = alphaSS[rowOff + sx];
                sumA += a;
                cnt++;
                if (a > maxA) maxA = a;
                if (a > 0.05) {
                  wX += ((sx + 0.5) / SS) * a;
                  wY += ((sy + 0.5) / SS) * a;
                }
              }
            }
            const ci = gy * cols + gx;
            cellAvg[ci] = cnt > 0 ? sumA / cnt : 0;
            cellMax[ci] = maxA;
            if (sumA > 0.08) {
              cellBestX[ci] = wX / sumA;
              cellBestY[ci] = wY / sumA;
            } else {
              cellBestX[ci] = (gx + 0.5) * stepCss;
              cellBestY[ci] = (gy + 0.5) * stepCss;
            }
          }
        }

        // Stride 10 temp array: hx, hy, uNorm, vNorm, charIdx, comp, diam, alpha, glyphSeed, isSpark
        const items = [];
        const pickCharIdx = (px, py) => {
          const unslantedX = px + (py - baselineY) * 0.21;
          let bestK = 0;
          let bestDist = Infinity;
          for (let k = 0; k < 7; k++) {
            const d = Math.abs(unslantedX - charCxs[k]);
            if (d < bestDist) {
              bestDist = d;
              bestK = k;
            }
          }
          return bestK;
        };

        for (let gy = 0; gy < rows; gy++) {
          for (let gx = 0; gx < cols; gx++) {
            const ci = gy * cols + gx;
            const maxA = cellMax[ci];
            const avgA = cellAvg[ci];
            const gridCx = (gx + 0.5) * stepCss;
            const gridCy = (gy + 0.5) * stepCss;

            if (maxA >= 0.24) {
              const nL = gx > 0 ? cellAvg[ci - 1] : 0;
              const nR = gx + 1 < cols ? cellAvg[ci + 1] : 0;
              const nU = gy > 0 ? cellAvg[ci - cols] : 0;
              const nD = gy + 1 < rows ? cellAvg[ci + cols] : 0;
              const minNeighbor = Math.min(nL, nR, nU, nD);
              const deepInterior = avgA > 0.84 && minNeighbor > 0.72;

              if (deepInterior) {
                // Structured LED / Bayer cyber-matrix breathing inside thick stems so digital particle grid is unmistakable
                const bVal = bayer8(gx, gy);
                if (bVal > 0.87) continue;

                const rg = bayer8(gx + 3, gy + 5);
                let glyph = 0;
                let diam = stepCss * 0.60;
                if (rg > 0.92) {
                  glyph = 3; // □ hollow digital voxel
                  diam = stepCss * 0.72;
                } else if (rg > 0.73) {
                  glyph = 1; // ▬ cyber scan-bar
                  diam = stepCss * 0.67;
                }

                const uNorm = Math.max(0, Math.min(1, (gridCx - wordLeft) / wordSpan));
                const vNorm = Math.max(0, Math.min(1, (gridCy - PAD) / Math.max(1, lr.height)));
                items.push(
                  gridCx,
                  gridCy,
                  uNorm,
                  vNorm,
                  pickCharIdx(gridCx, gridCy),
                  0.85 + rand() * 0.28,
                  diam,
                  0.97,
                  packGlyphSeed(glyph, rand()),
                  0.0
                );
              } else {
                // Contour & thin italic serif/hairline voxels: snap 52% toward subpixel ink centroid so serifs stay razor-sharp
                if (avgA < 0.14 && maxA < 0.50) continue;
                const hx = gridCx * 0.48 + cellBestX[ci] * 0.52;
                const hy = gridCy * 0.48 + cellBestY[ci] * 0.52;
                const rg = bayer8(gx, gy);
                const glyph = rg > 0.94 ? 3 : rg > 0.82 ? 1 : 0;
                const diam =
                  (glyph === 0 ? stepCss * 0.64 : stepCss * 0.69) *
                  (0.86 + 0.14 * Math.min(1, avgA + 0.35));

                const uNorm = Math.max(0, Math.min(1, (hx - wordLeft) / wordSpan));
                const vNorm = Math.max(0, Math.min(1, (hy - PAD) / Math.max(1, lr.height)));
                items.push(
                  hx,
                  hy,
                  uNorm,
                  vNorm,
                  pickCharIdx(hx, hy),
                  0.66 + rand() * 0.22,
                  diam,
                  0.98,
                  packGlyphSeed(glyph, rand()),
                  0.0
                );
              }
            } else {
              // Subtle detached cyber-telemetry sparks (+, □, ▬, ■) hugging the outer aura of "Product"
              const hsx = Math.min(tw - 1, Math.floor(gridCx * SS));
              const hsy = Math.min(th - 1, Math.floor(gridCy * SS));
              const haloVal = haloSS[hsy * tw + hsx];
              if (haloVal > 0.045 && haloVal < 0.40) {
                const bSpark = bayer8(gx * 3 + 1, gy * 5 + 2);
                if (bSpark <= 0.956) continue;
                const rs = rand();
                let glyph = 0;
                let diam = stepCss * 0.58;
                if (rs > 0.78) {
                  glyph = 2; // + precision fiducial reticle
                  diam = stepCss * 1.16;
                } else if (rs > 0.58) {
                  glyph = 3; // □ hollow voxel
                  diam = stepCss * 0.78;
                } else if (rs > 0.36) {
                  glyph = 1; // ▬ scan-tick
                  diam = stepCss * 0.74;
                }
                const uNorm = Math.max(0, Math.min(1, (gridCx - wordLeft) / wordSpan));
                const vNorm = Math.max(0, Math.min(1, (gridCy - PAD) / Math.max(1, lr.height)));
                items.push(
                  gridCx,
                  gridCy,
                  uNorm,
                  vNorm,
                  pickCharIdx(gridCx, gridCy),
                  1.35 + rand() * 0.35,
                  diam,
                  0.82,
                  packGlyphSeed(glyph, rand()),
                  1.0
                );
              }
            }
          }
        }

        const count = items.length / 10;
        if (!count) return;

        const homeX = new Float32Array(count);
        const homeY = new Float32Array(count);
        const compliance = new Float32Array(count);
        const isSparkArr = new Uint8Array(count);
        const staticMeta = new Float32Array(count * 7);

        posX = new Float32Array(count);
        posY = new Float32Array(count);
        velX = new Float32Array(count);
        velY = new Float32Array(count);
        gpuPos = new Float32Array(count * 2);

        for (let i = 0; i < count; i++) {
          const k = i * 10;
          const hx = items[k];
          const hy = items[k + 1];
          homeX[i] = hx;
          homeY[i] = hy;
          posX[i] = hx;
          posY[i] = hy;
          gpuPos[i * 2] = hx;
          gpuPos[i * 2 + 1] = hy;
          compliance[i] = items[k + 5];
          isSparkArr[i] = items[k + 9] > 0.5 ? 1 : 0;

          const m = i * 7;
          staticMeta[m] = items[k + 2];     // uNorm
          staticMeta[m + 1] = items[k + 3]; // vNorm
          staticMeta[m + 2] = items[k + 4]; // charIdx
          staticMeta[m + 3] = items[k + 6]; // diam
          staticMeta[m + 4] = items[k + 7]; // baseAlpha
          staticMeta[m + 5] = items[k + 8]; // glyphSeed
          staticMeta[m + 6] = items[k + 9]; // isSpark
        }

        bank = { count, homeX, homeY, compliance, isSparkArr, staticMeta };

        if (gl && prog) {
          gl.useProgram(prog);
          gl.bindBuffer(gl.ARRAY_BUFFER, metaBuf);
          gl.bufferData(gl.ARRAY_BUFFER, staticMeta, gl.STATIC_DRAW);
          gl.vertexAttribPointer(aUvCharLoc, 3, gl.FLOAT, false, 28, 0);
          gl.vertexAttribPointer(aMetaLoc, 4, gl.FLOAT, false, 28, 12);

          gl.bindBuffer(gl.ARRAY_BUFFER, posBuf);
          gl.bufferData(gl.ARRAY_BUFFER, gpuPos.byteLength, gl.DYNAMIC_DRAW);
          gl.vertexAttribPointer(aPosLoc, 2, gl.FLOAT, false, 0, 0);
        }

        setProductParticlesReady(true);
      };

      buildProductBank(true);
      let cancelled = false;
      if (document.fonts && document.fonts.ready) {
        document.fonts.ready.then(() => {
          if (!cancelled) buildProductBank(true);
        });
      }

      let resizeRaf = 0;
      const scheduleRebuild = () => {
        if (!resizeRaf) {
          resizeRaf = requestAnimationFrame(() => {
            resizeRaf = 0;
            if (!cancelled) buildProductBank(false);
          });
        }
      };

      let ro = null;
      if ('ResizeObserver' in window) {
        ro = new ResizeObserver(scheduleRebuild);
        ro.observe(lineEl);
      }
      window.addEventListener('resize', scheduleRebuild, { passive: true });

      const rawClient = { x: -9999, y: -9999 };
      let pointerInside = 0;
      let pointerPresence = 0;
      let cursorInit = false;
      const cursorPx = { x: -9999, y: -9999 };
      const cursorVel = { x: 0, y: 0 };

      const onPointerMove = (e) => {
        rawClient.x = e.clientX;
        rawClient.y = e.clientY;
        pointerInside = 1;
      };
      const onPointerLeave = () => {
        pointerInside = 0;
      };

      let visIo = null;
      if ('IntersectionObserver' in window) {
        visIo = new IntersectionObserver(
          ([entry]) => {
            const next = entry.isIntersecting;
            if (next && !heroVisible) {
              heroVisible = true;
              if (!animId) animId = requestAnimationFrame(tick);
            } else {
              heroVisible = next;
            }
          },
          { threshold: 0.01 }
        );
        visIo.observe(heroEl);
      }

      let time = 0;
      let phase = 0;
      let frameCount = 0;

      const sampleHoloJS = (t) => {
        const x = (((t % 1) + 1) % 1) * 6;
        const i0 = Math.floor(x) % 6;
        const f = x - Math.floor(x);
        const stops = [
          [0, 214, 112],
          [0, 199, 250],
          [38, 92, 255],
          [143, 43, 255],
          [245, 26, 143],
          [34, 184, 246],
        ];
        const a = stops[i0];
        const b = stops[(i0 + 1) % 6];
        return `rgb(${Math.round(a[0] + (b[0] - a[0]) * f)},${Math.round(a[1] + (b[1] - a[1]) * f)},${Math.round(a[2] + (b[2] - a[2]) * f)})`;
      };

      const tick = () => {
        animId = 0;
        if (!heroVisible || cancelled) return;

        const minimal = isMinimalMotion();
        if (!minimal) time += 0.014;
        frameCount++;

        if (bank && posX && gpuPos) {
          const rect = canvas.getBoundingClientRect();
          const targetCx = rawClient.x - rect.left;
          const targetCy = rawClient.y - rect.top;

          if (!cursorInit && pointerInside > 0) {
            cursorPx.x = targetCx;
            cursorPx.y = targetCy;
            cursorInit = true;
          }
          const prevCx = cursorPx.x;
          const prevCy = cursorPx.y;
          cursorPx.x += (targetCx - cursorPx.x) * 0.20;
          cursorPx.y += (targetCy - cursorPx.y) * 0.20;

          const stepVx = cursorPx.x - prevCx;
          const stepVy = cursorPx.y - prevCy;
          cursorVel.x = cursorVel.x * 0.80 + stepVx * 0.80;
          cursorVel.y = cursorVel.y * 0.80 + stepVy * 0.80;
          const velMag = Math.hypot(cursorVel.x, cursorVel.y);
          if (velMag > 24) {
            const sc = 24 / velMag;
            cursorVel.x *= sc;
            cursorVel.y *= sc;
          }
          const speedNorm = Math.min(1, velMag / 16);
          if (!minimal) phase += 0.032 + speedNorm * 0.018;

          const nearCanvas =
            pointerInside > 0 &&
            targetCx > -80 &&
            targetCx < cssW + 80 &&
            targetCy > -80 &&
            targetCy < cssH + 80
              ? 1
              : 0;
          pointerPresence += ((minimal ? 0 : nearCanvas) - pointerPresence) * 0.11;

          const n = bank.count;
          const hX = bank.homeX;
          const hY = bank.homeY;
          const compArr = bank.compliance;
          const sparkArr = bank.isSparkArr;

          const curX = cursorPx.x;
          const curY = cursorPx.y;
          const cvx = cursorVel.x;
          const cvy = cursorVel.y;
          const cAct = pointerPresence;

          // Restrained, delicate local hover radius & subtle ~4px..8px micro-displacement (~1/6th of central diamond)
          const hoverR = Math.max(44, Math.min(78, curFontSize * 0.62));
          const maxR = hoverR * 1.28;
          const maxR2 = maxR * maxR;
          const fontScale = Math.max(0.45, Math.min(1.10, curFontSize / 120));
          const repelAmp = (0.58 + speedNorm * 0.44) * fontScale;
          const maxStrokeDisp = Math.max(3.8, curFontSize * 0.072);

          const w2c = 0.14 * Math.sin(phase * 1.1);
          const w2s = 0.14 * Math.cos(phase * 0.9);
          const w3c = 0.12 * Math.cos(phase * 1.4);
          const w3s = 0.12 * Math.sin(phase * 1.2);

          for (let i = 0; i < n; i++) {
            const hx = hX[i];
            const hy = hY[i];
            const comp = compArr[i];
            const isSpark = sparkArr[i] === 1;

            // Tiny subtle ambient breathing on outer telemetry sparks only
            const sparkDriftX = !minimal && isSpark ? Math.sin(time * 1.6 + hy * 0.18) * 0.9 : 0;
            const sparkDriftY = !minimal && isSpark ? Math.cos(time * 1.3 + hx * 0.16) * 0.9 : 0;
            const tx = hx + sparkDriftX;
            const ty = hy + sparkDriftY;

            let px = posX[i];
            let py = posY[i];
            let vx = velX[i];
            let vy = velY[i];

            const kSpring = isSpark ? 0.068 : 0.090;
            let ax = (tx - px) * kSpring;
            let ay = (ty - py) * kSpring;

            if (cAct > 0.004) {
              const dx = px - curX;
              const dy = py - curY;
              const d2 = dx * dx + dy * dy;
              if (d2 < maxR2) {
                const invD = 1 / Math.sqrt(d2 + 36);
                const ux = dx * invD;
                const uy = dy * invD;
                const c2 = ux * ux - uy * uy;
                const s2 = 2 * ux * uy;
                const c3 = c2 * ux - s2 * uy;
                const s3 = s2 * ux + c2 * uy;
                const rMod = Math.max(0.72, Math.min(1.26, 1.0 + w2c * c2 + w2s * s2 + w3c * c3 + w3s * s3));
                const localR = hoverR * rMod;
                if (d2 < localR * localR) {
                  const q = Math.sqrt(d2) / localR;
                  const omq = 1 - q;
                  const falloff = omq * omq * (1 + 2 * q) * cAct;
                  const push = repelAmp * falloff * comp;
                  ax += ux * push + (-uy * 0.045 + cvx * 0.038) * falloff * comp;
                  ay += uy * push + (ux * 0.045 + cvy * 0.038) * falloff * comp;
                }
              }
            }

            vx = (vx + ax) * 0.79;
            vy = (vy + ay) * 0.79;
            const v2 = vx * vx + vy * vy;
            if (v2 > 9) {
              const vs = 3 / Math.sqrt(v2);
              vx *= vs;
              vy *= vs;
            }

            px += vx;
            py += vy;

            // Gentle radial tether so "Product" always stays crisp and legible
            const offX = px - tx;
            const offY = py - ty;
            const maxD = isSpark ? maxStrokeDisp * 1.55 : maxStrokeDisp;
            const offD2 = offX * offX + offY * offY;
            if (offD2 > maxD * maxD) {
              const sc = maxD / Math.sqrt(offD2);
              px = tx + offX * sc;
              py = ty + offY * sc;
              vx *= 0.5;
              vy *= 0.5;
            }

            posX[i] = px;
            posY[i] = py;
            velX[i] = vx;
            velY[i] = vy;
            gpuPos[i * 2] = px;
            gpuPos[i * 2 + 1] = py;
          }

          if (gl && prog) {
            gl.useProgram(prog);
            gl.clear(gl.COLOR_BUFFER_BIT);
            gl.bindBuffer(gl.ARRAY_BUFFER, posBuf);
            gl.bufferSubData(gl.ARRAY_BUFFER, 0, gpuPos);

            gl.uniform2f(uViewCss, Math.max(1, cssW), Math.max(1, cssH));
            gl.uniform1f(uDpr, dpr);
            gl.uniform1f(uTime, time);
            gl.uniform2f(uCursorPx, curX, curY);
            gl.uniform1f(uCursorActive, cAct);
            gl.uniform1f(uHoverR, hoverR);
            const cpArr = productCharCpRef.current;
            gl.uniform4f(uCharCpALoc, cpArr[0], cpArr[1], cpArr[2], cpArr[3]);
            gl.uniform3f(uCharCpBLoc, cpArr[4], cpArr[5], cpArr[6]);

            gl.drawArrays(gl.POINTS, 0, n);
          } else if (ctx2d) {
            ctx2d.clearRect(0, 0, cssW, cssH);
            const meta = bank.staticMeta;
            const cpArr = productCharCpRef.current;
            for (let i = 0; i < n; i++) {
              const m = i * 7;
              const uNorm = meta[m];
              const vNorm = meta[m + 1];
              const ci = Math.min(6, Math.max(0, Math.round(meta[m + 2])));
              const cp = cpArr[ci] || 0;
              const d = meta[m + 3];
              ctx2d.fillStyle =
                cp > 0.38
                  ? sampleHoloJS(uNorm * 0.88 - vNorm * 0.18 - time * 0.14)
                  : 'rgb(30,30,34)';
              ctx2d.globalAlpha = meta[m + 4] * (0.30 + 0.68 * cp);
              ctx2d.fillRect(posX[i] - d * 0.5, posY[i] - d * 0.5, d, d);
            }
            ctx2d.globalAlpha = 1;
          }
        }

        if (!minimal || frameCount < 3) {
          animId = requestAnimationFrame(tick);
        }
      };

      window.addEventListener('pointermove', onPointerMove, { passive: true });
      document.addEventListener('mouseleave', onPointerLeave, { passive: true });
      animId = requestAnimationFrame(tick);

      return () => {
        cancelled = true;
        window.removeEventListener('pointermove', onPointerMove);
        document.removeEventListener('mouseleave', onPointerLeave);
        window.removeEventListener('resize', scheduleRebuild);
        if (ro) ro.disconnect();
        if (visIo) visIo.disconnect();
        cancelAnimationFrame(resizeRaf);
        cancelAnimationFrame(animId);
        if (gl) {
          if (posBuf) gl.deleteBuffer(posBuf);
          if (metaBuf) gl.deleteBuffer(metaBuf);
          if (prog) gl.deleteProgram(prog);
        }
      };
    }, []);

    // Split helper — renders a string as per-char spans (spaces stay as text)
    const initialCharStyle = reduceMotion ? undefined : { opacity: 0.2 };
    const splitChars = (text, keyPrefix, padding = false) => {
      const style = padding
        ? Object.assign({ paddingRight: '0.08em', marginRight: '-0.08em' }, initialCharStyle)
        : initialCharStyle;
      return [...text].map((c, i) =>
        c === ' '
          ? ' '
          : <span className="stxc" style={style} key={keyPrefix + i}>{c}</span>
      );
    };

    return (
      <div className="hero-pin" ref={pinRef}>
        <section
          className={`hero hero--diamond ${revealed ? 'is-revealed' : ''}`}
          id="top"
          ref={heroRef}
        >
          {/* Mobile nav */}
          <div className="mnav" aria-hidden={menuOpen}>
            <a href="#top" className="mnav__brand">Yui</a>
            <button
              type="button"
              className="mnav__toggle"
              onClick={() => setMenuOpen(true)}
              aria-label="Open menu"
            >
              MENU&nbsp;[≡]
            </button>
          </div>
          {menuOpen && (
            <div className="mnav-overlay" role="dialog" aria-modal="true">
              <div className="mnav-overlay__top">
                <span className="mnav-overlay__logo">Yui</span>
                <button
                  type="button"
                  className="mnav-overlay__close"
                  onClick={() => setMenuOpen(false)}
                >
                  CLOSE&nbsp;[×]
                </button>
              </div>
              <nav className="mnav-overlay__links">
                <a href="#top" onClick={() => setMenuOpen(false)}>About Me</a>
                <a href="#projects" onClick={() => setMenuOpen(false)}>Works</a>
                <a href="#solutions" onClick={() => setMenuOpen(false)}>How I Work</a>
                <a href="#contact" onClick={() => setMenuOpen(false)}>Contact Me</a>
              </nav>
            </div>
          )}

          {/* ============ ~58,000-Particle GPU Sculpture (Pure #ffffff Canvas, DOM Fallback Only) ============ */}
          <div className="hero__diamond-stage" aria-hidden="true">
            <div className="hero__diamond-entrance">
              <canvas className="hero__diamond-particles" ref={canvasRef} />

              {!particleCoreReady &&
                DIAMOND_LAYERS_BACK_TO_FRONT.map((layer) => {
                  const imgFilter =
                    layer.idx === 0
                      ? undefined
                      : layer.blur > 0
                        ? `blur(${layer.blur}px) saturate(0.86) hue-rotate(${layer.hueShift}deg)`
                        : `saturate(0.86) hue-rotate(${layer.hueShift}deg)`;
                  return (
                    <div
                      key={layer.num}
                      ref={(node) => { layerRefs.current[layer.idx] = node; }}
                      className={
                        `hero__diamond-layer hero__diamond-layer--${layer.num}` +
                        (layer.idx >= 8 ? ' hero__diamond-layer--mobile-trim' : '')
                      }
                      style={{
                        width: `clamp(${layer.minPx}px, ${layer.sizeVmin}vmin, ${layer.maxPx}px)`,
                        height: `clamp(${layer.minPx}px, ${layer.sizeVmin}vmin, ${layer.maxPx}px)`,
                        opacity: layer.opacity,
                      }}
                    >
                      <img
                        src={layer.idx === 0 ? coreBubbleSrc : outerBubbleSrc}
                        alt=""
                        className={`hero__diamond-img${layer.idx === 0 ? ' hero__diamond-core' : ''}`}
                        style={imgFilter ? { filter: imgFilter } : undefined}
                      />
                    </div>
                  );
                })}
            </div>
          </div>

          {/* ============ Text composition ============ */}
          <div className="hero__content">
            {/* Top-left: brand */}
            <div className="hero__brand hero__brand--text">
              <span className="hero__brand-text">Yui</span>
            </div>

            {/* Centre-left: Title lines with scroll-linked char brightening */}
            <div className="hero__title-block">
              <h1 className="hero__title" ref={titleRef}>
                <div className="hero__title-line hero__title-line--1">
                  {splitChars('Designing', 't0-')}
                </div>
                <div
                  className={`hero__title-line hero__title-line--2 hero__title-line--accent is-split${productParticlesReady ? ' has-product-particles' : ''}`}
                  ref={productLineRef}
                >
                  <canvas
                    className="hero__product-particles"
                    ref={productCanvasRef}
                    aria-hidden="true"
                  />
                  <span className="hero__product-sizer">
                    {splitChars('Product', 't1-', true)}
                  </span>
                </div>
                <div className="hero__title-line hero__title-line--3">
                  {splitChars('that actually', 't2-')}
                </div>
                <div className="hero__title-line hero__title-line--4">
                  {splitChars('ships.', 't3-')}
                </div>
              </h1>
            </div>

            {/* Right column: description + CTA with scroll-linked char brightening */}
            <div className="hero__desc-col">
              <p className="hero__desc" ref={descRef}>
                <span className="hero__desc-bold">{splitChars('UIUX Designer', 'd0-')}</span>
                {splitChars('，擅長', 'd1-')}
                <span className="hero__desc-bold">{splitChars('介面設計', 'd2-')}</span>
                {splitChars('與', 'd3-')}
                <span className="hero__desc-bold">{splitChars('體驗優化', 'd4-')}</span>
                <br />
                {splitChars('參與產品策略、用戶體驗、設計系統建置、設計執行與跨職能協作。', 'd5-')}
              </p>
              <div className="hero__cta-row" ref={ctaRef}>
                <a href="./assets/CV_2026.pdf" className="hero__cta-link" target="_blank" rel="noopener noreferrer">
                  <span className="hero__cta-text">Download CV</span> <span className="hero__cta-arrow">↓</span>
                </a>
                <a href="#projects" className="hero__cta-link">
                  <span className="hero__cta-text">View Works</span> <span className="hero__cta-arrow">→</span>
                </a>
              </div>
            </div>
          </div>

        </section>
      </div>
    );
  }

  // Standalone diagonal marquee — pinned (sticky) while projects scroll under it
  function HeroMarquee() {
    return (
      <div className="hero__marquee" aria-hidden="true">
        <div className="hero__marquee-band">
          <div className="hero__marquee-track">
            {[
              "Hi, I'm Yui Yu", "Product Designer",
              "Hi, I'm Yui Yu", "Product Designer",
              "Hi, I'm Yui Yu", "Product Designer",
              "Hi, I'm Yui Yu", "Product Designer",
            ].map((text, i) => (
              <span className="hero__marquee-item" key={i}>{text}</span>
            ))}
          </div>
        </div>
        {/* Black triangle below the band — clean sticky transition into Works */}
        <div className="hero__marquee-tri" />
      </div>
    );
  }

  // Fixed nav pill
  function HeroNavPill() {
    return (
      <div className="hero__nav-pill">
        <div className="hero__nav-pill__inner">
          <div className="hero__nav-pill__items">
            <a href="#top" className="hero__nav-pill__item">About Me</a>
            <a href="#projects" className="hero__nav-pill__item">Works</a>
            <a href="#solutions" className="hero__nav-pill__item">How I Work</a>
          </div>
          <a href="#contact" className="hero__nav-pill__cta">
            Contact Me <span>→</span>
          </a>
        </div>
      </div>
    );
  }

  // Fixed top-left brand
  function SiteBrand() {
    return (
      <a href="#top" className="site-brand" aria-label="Yui — back to top">
        <span className="site-brand__text">Yui</span>
        <img src="./assets/star-holo.png" alt="" className="site-brand__star" />
      </a>
    );
  }

  window.Hero = Hero;
  window.HeroMarquee = HeroMarquee;
  window.HeroNavPill = HeroNavPill;
  window.SiteBrand = SiteBrand;
})();
