// ============================================================
// EFFECTS — Background visual atmospherics
// MatrixRain · EdoWaves (Hokusai animated) · Layer3DStack · GamingGrid
// ============================================================

// ---------------- MATRIX RAIN (AiKo) ----------------
function MatrixRain({ opacity = 0.55 }) {
  const canvasRef = useRef(null);
  const animRef = useRef(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    const chars = 'アイコAIKOabcdefghijklmnop0123456789@#$RPGSQLDCLPROCFETCHINTOFROMWHEREJOIN'.split('');
    const fontSize = 14;
    let columns = 0, drops = [];

    const resize = () => {
      const rect = canvas.parentElement.getBoundingClientRect();
      canvas.width = Math.ceil(rect.width) + 2;
      canvas.height = Math.ceil(rect.height) + 2;
      columns = Math.ceil(canvas.width / fontSize);
      drops = Array.from({ length: columns }, () => Math.random() * -100);
    };
    resize();
    window.addEventListener('resize', resize);

    const draw = () => {
      ctx.fillStyle = 'rgba(15,15,35,0.07)';
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      drops.forEach((y, i) => {
        const char = chars[Math.floor(Math.random() * chars.length)];
        const x = i * fontSize;
        if (Math.random() > 0.5) {
          ctx.fillStyle = `rgba(255,215,0,${0.15 + Math.random() * 0.2})`;
        } else {
          ctx.fillStyle = `rgba(45,200,120,${0.15 + Math.random() * 0.25})`;
        }
        ctx.font = `${fontSize}px monospace`;
        ctx.fillText(char, x, y * fontSize);
        if (Math.random() > 0.96) {
          ctx.fillStyle = 'rgba(255,235,150,0.85)';
          ctx.fillText(char, x, y * fontSize);
        }
        if (y * fontSize > canvas.height && Math.random() > 0.975) drops[i] = 0;
        drops[i] += 0.2 + Math.random() * 0.25;
      });
      animRef.current = requestAnimationFrame(draw);
    };
    animRef.current = requestAnimationFrame(draw);
    return () => {
      window.removeEventListener('resize', resize);
      cancelAnimationFrame(animRef.current);
    };
  }, []);

  return <canvas ref={canvasRef} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', opacity, pointerEvents: 'none' }} />;
}

// ---------------- FLOW CURRENT — animated water current ----------------
// Particle flow field simulating river/stream current: thousands of tiny
// particles follow noise-based velocity vectors, leaving glowing trails.
// Reads as "data flowing through a pipe" — perfect for file flow orchestration.
function FlowCurrent({ accent = '#f4d03f', deep = '#1e3a8a' }) {
  const canvasRef = useRef(null);
  const animRef = useRef(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let W = 0, H = 0, t = 0;
    const dpr = Math.min(window.devicePixelRatio || 1, 2);
    let particles = [];

    const PARTICLE_COUNT = 220;

    const resize = () => {
      const rect = canvas.parentElement.getBoundingClientRect();
      W = Math.ceil(rect.width); H = Math.ceil(rect.height);
      canvas.width = W * dpr; canvas.height = H * dpr;
      canvas.style.width = W + 'px'; canvas.style.height = H + 'px';
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      // Initialize particles
      particles = Array.from({ length: PARTICLE_COUNT }, () => ({
        x: Math.random() * W,
        y: Math.random() * H,
        vx: 0, vy: 0,
        life: Math.random() * 200,
        maxLife: 150 + Math.random() * 200,
        speed: 0.5 + Math.random() * 1.2,
        color: Math.random() > 0.85 ? 'gold' : (Math.random() > 0.5 ? 'cyan' : 'blue'),
      }));
    };
    resize();
    window.addEventListener('resize', resize);

    // Pseudo-noise: layered sines for smooth curl-noise-like field
    const flowAngle = (x, y, time) => {
      const nx = x * 0.0035;
      const ny = y * 0.005;
      // Primary horizontal current
      const primary = Math.sin(ny * 1.8 + time * 0.4) * 0.5;
      // Secondary curl
      const curl = Math.sin(nx + ny * 1.2 + time * 0.3) * 0.6
                 + Math.cos(nx * 1.5 - ny * 0.8 + time * 0.5) * 0.4;
      // Tilt towards rightward flow (current direction)
      return curl + primary * 0.3 + 0.05; // bias right
    };

    const draw = () => {
      t += 0.012;
      // Trail fade — semi-transparent overlay
      ctx.fillStyle = 'rgba(8,12,30,0.12)';
      ctx.fillRect(0, 0, W, H);

      particles.forEach(p => {
        // Field-driven velocity
        const ang = flowAngle(p.x, p.y, t);
        p.vx = p.vx * 0.92 + Math.cos(ang) * p.speed * 0.4;
        p.vy = p.vy * 0.92 + Math.sin(ang) * p.speed * 0.25;
        p.x += p.vx;
        p.y += p.vy;
        p.life++;

        // Re-spawn if off-screen or too old
        if (p.x > W + 20 || p.x < -20 || p.y < -20 || p.y > H + 20 || p.life > p.maxLife) {
          p.x = -10 + Math.random() * 20;
          p.y = Math.random() * H;
          p.vx = 0; p.vy = 0;
          p.life = 0;
          p.maxLife = 150 + Math.random() * 200;
          p.speed = 0.5 + Math.random() * 1.2;
        }

        // Render — glowing dot with brightness pulsing
        const lifeRatio = p.life / p.maxLife;
        const alpha = Math.sin(lifeRatio * Math.PI) * 0.8;
        const r = p.color === 'gold' ? 1.6 : 1.0;

        let fill;
        if (p.color === 'gold') fill = `rgba(244,208,63,${alpha})`;
        else if (p.color === 'cyan') fill = `rgba(140,210,250,${alpha * 0.85})`;
        else fill = `rgba(80,140,220,${alpha * 0.7})`;

        ctx.beginPath();
        ctx.arc(p.x, p.y, r, 0, Math.PI * 2);
        ctx.fillStyle = fill;
        ctx.fill();

        // Soft glow for gold particles
        if (p.color === 'gold') {
          ctx.beginPath();
          ctx.arc(p.x, p.y, 4, 0, Math.PI * 2);
          ctx.fillStyle = `rgba(244,208,63,${alpha * 0.15})`;
          ctx.fill();
        }
      });

      // Faint horizontal current lines for added depth
      ctx.strokeStyle = `rgba(140,180,220,0.08)`;
      ctx.lineWidth = 0.6;
      for (let i = 0; i < 8; i++) {
        const baseY = (H / 8) * i + (H / 16);
        ctx.beginPath();
        for (let x = 0; x <= W; x += 6) {
          const off = Math.sin(x * 0.008 + t * 0.6 + i * 0.5) * 6
                    + Math.sin(x * 0.02 + t * 1.1) * 2;
          if (x === 0) ctx.moveTo(x, baseY + off);
          else ctx.lineTo(x, baseY + off);
        }
        ctx.stroke();
      }

      animRef.current = requestAnimationFrame(draw);
    };

    // Initial deep blue fill
    const grad = ctx.createLinearGradient(0, 0, 0, H);
    grad.addColorStop(0, '#0c1530');
    grad.addColorStop(0.5, '#0f2150');
    grad.addColorStop(1, '#08102a');
    ctx.fillStyle = grad;
    ctx.fillRect(0, 0, W, H);

    animRef.current = requestAnimationFrame(draw);

    return () => {
      window.removeEventListener('resize', resize);
      cancelAnimationFrame(animRef.current);
    };
  }, []);

  return (
    <div style={{ position: 'absolute', inset: 0, overflow: 'hidden', pointerEvents: 'none' }} aria-hidden="true">
      {/* Base deep gradient under the canvas (in case canvas alpha) */}
      <div style={{
        position: 'absolute', inset: 0,
        background: `
          radial-gradient(ellipse 70% 50% at 30% 50%, rgba(30,58,138,0.4), transparent 60%),
          radial-gradient(ellipse 60% 40% at 80% 70%, rgba(244,208,63,0.06), transparent 60%),
          linear-gradient(180deg, #0c1530 0%, #0f2150 50%, #08102a 100%)
        `,
      }} />
      <canvas ref={canvasRef} style={{ display: 'block', width: '100%', height: '100%', position: 'relative' }} />
      {/* Top fade for navbar */}
      <div style={{
        position: 'absolute', top: 0, left: 0, right: 0, height: 100,
        background: 'linear-gradient(180deg, rgba(15,15,35,0.85), transparent)',
      }} />
    </div>
  );
}

// ---------------- EDO WAVES — Procedural Hokusai canvas (legacy) ----------------
function EdoWaves({ accent = '#f4d03f' }) {
  const canvasRef = useRef(null);
  const animRef = useRef(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let W = 0, H = 0, t = 0;
    const dpr = Math.min(window.devicePixelRatio || 1, 2);

    const resize = () => {
      const rect = canvas.parentElement.getBoundingClientRect();
      W = Math.ceil(rect.width); H = Math.ceil(rect.height);
      canvas.width = W * dpr; canvas.height = H * dpr;
      canvas.style.width = W + 'px'; canvas.style.height = H + 'px';
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    };
    resize();
    window.addEventListener('resize', resize);

    const drawClaw = (cx, cy, size, angle, depth) => {
      if (depth <= 0 || size < 4) return;
      const x2 = cx + Math.cos(angle) * size;
      const y2 = cy + Math.sin(angle) * size;
      ctx.beginPath();
      ctx.moveTo(cx, cy);
      ctx.quadraticCurveTo(
        cx + Math.cos(angle - 0.3) * size * 0.6,
        cy + Math.sin(angle - 0.3) * size * 0.6,
        x2, y2
      );
      ctx.lineWidth = depth * 0.6;
      ctx.strokeStyle = `rgba(245,250,255,${0.55 + depth * 0.05})`;
      ctx.stroke();
      ctx.beginPath();
      ctx.arc(x2, y2, depth * 0.7, 0, Math.PI * 2);
      ctx.fillStyle = `rgba(255,255,255,${0.35 + depth * 0.08})`;
      ctx.fill();
      drawClaw(x2, y2, size * 0.62, angle - 0.45, depth - 1);
      if (depth > 2) drawClaw(x2, y2, size * 0.55, angle - 0.15, depth - 2);
    };

    const wavePath = (yBase, amp, freq, phase, color) => {
      ctx.beginPath();
      ctx.moveTo(-20, H);
      ctx.lineTo(-20, yBase);
      for (let x = -20; x <= W + 20; x += 8) {
        const y = yBase + Math.sin((x * freq) + phase) * amp
                  + Math.sin((x * freq * 2.3) + phase * 1.4) * amp * 0.35;
        ctx.lineTo(x, y);
      }
      ctx.lineTo(W + 20, H);
      ctx.closePath();
      ctx.fillStyle = color;
      ctx.fill();
    };

    const crestWave = (phase) => {
      ctx.save();
      const baseY = H * 0.62;
      const drift = Math.sin(phase * 0.7) * 18;
      ctx.beginPath();
      ctx.moveTo(-30, H);
      ctx.lineTo(-30, baseY + 60);
      ctx.quadraticCurveTo(W * 0.08, baseY + 40, W * 0.18, baseY - 20 + drift);
      ctx.bezierCurveTo(
        W * 0.24, baseY - 180 + drift, W * 0.30, baseY - 240 + drift, W * 0.36, baseY - 200 + drift
      );
      ctx.bezierCurveTo(
        W * 0.42, baseY - 160 + drift, W * 0.40, baseY - 60 + drift, W * 0.48, baseY - 40 + drift
      );
      ctx.bezierCurveTo(
        W * 0.58, baseY - 20, W * 0.70, baseY + 20, W * 0.85, baseY + 30
      );
      ctx.lineTo(W + 30, baseY + 60);
      ctx.lineTo(W + 30, H);
      ctx.closePath();
      const grad = ctx.createLinearGradient(0, baseY - 240, 0, H);
      grad.addColorStop(0, '#1a3a7a');
      grad.addColorStop(0.3, '#0f2150');
      grad.addColorStop(0.7, '#0a1638');
      grad.addColorStop(1, '#050a1f');
      ctx.fillStyle = grad;
      ctx.fill();

      ctx.beginPath();
      ctx.moveTo(W * 0.18, baseY - 20 + drift);
      ctx.bezierCurveTo(
        W * 0.24, baseY - 180 + drift, W * 0.30, baseY - 240 + drift, W * 0.36, baseY - 200 + drift
      );
      ctx.bezierCurveTo(
        W * 0.30, baseY - 130 + drift, W * 0.26, baseY - 80 + drift, W * 0.24, baseY - 30 + drift
      );
      ctx.closePath();
      ctx.fillStyle = 'rgba(8,16,40,0.6)';
      ctx.fill();
      ctx.restore();

      ctx.save();
      ctx.lineCap = 'round';
      const points = [
        [W * 0.20, baseY - 60 + drift], [W * 0.24, baseY - 130 + drift],
        [W * 0.30, baseY - 210 + drift], [W * 0.36, baseY - 200 + drift],
        [W * 0.40, baseY - 150 + drift],
      ];
      ctx.beginPath();
      ctx.moveTo(points[0][0], points[0][1]);
      ctx.quadraticCurveTo(W * 0.22, baseY - 220 + drift, points[2][0], points[2][1]);
      ctx.quadraticCurveTo(W * 0.34, baseY - 250 + drift, points[3][0], points[3][1]);
      ctx.quadraticCurveTo(W * 0.40, baseY - 210 + drift, points[4][0], points[4][1]);
      ctx.lineTo(W * 0.36, baseY - 180 + drift);
      ctx.quadraticCurveTo(W * 0.30, baseY - 200 + drift, W * 0.24, baseY - 150 + drift);
      ctx.closePath();
      ctx.fillStyle = 'rgba(245,250,255,0.92)';
      ctx.fill();

      const clawBase = [
        [W * 0.22, baseY - 200 + drift, -1.7, 60],
        [W * 0.27, baseY - 230 + drift, -1.55, 70],
        [W * 0.32, baseY - 245 + drift, -1.35, 75],
        [W * 0.36, baseY - 235 + drift, -1.15, 65],
        [W * 0.40, baseY - 215 + drift, -0.9, 55],
      ];
      clawBase.forEach(([x, y, ang, sz], i) => {
        drawClaw(x, y, sz + Math.sin(phase + i) * 5, ang + Math.sin(phase * 0.8 + i) * 0.08, 4);
      });

      ctx.fillStyle = 'rgba(255,255,255,0.7)';
      for (let i = 0; i < 28; i++) {
        const dx = W * 0.25 + Math.sin(phase * 0.5 + i * 1.2) * 120;
        const dy = baseY - 220 + Math.cos(phase * 0.7 + i * 0.9) * 60;
        const r = 1 + ((i * 7) % 3) * 0.7;
        ctx.beginPath();
        ctx.arc(dx, dy, r, 0, Math.PI * 2);
        ctx.fill();
      }
      ctx.restore();
    };

    const drawFuji = () => {
      const cx = W * 0.62, cy = H * 0.66;
      const size = Math.min(W, H) * 0.13;
      ctx.save();
      const fg = ctx.createLinearGradient(cx - size, cy - size, cx + size, cy + size);
      fg.addColorStop(0, '#3a4a6a');
      fg.addColorStop(0.5, '#2a3050');
      fg.addColorStop(1, '#1a2040');
      ctx.fillStyle = fg;
      ctx.beginPath();
      ctx.moveTo(cx, cy - size);
      ctx.lineTo(cx + size * 1.4, cy + size * 0.5);
      ctx.lineTo(cx - size * 1.4, cy + size * 0.5);
      ctx.closePath();
      ctx.fill();
      ctx.beginPath();
      ctx.moveTo(cx, cy - size);
      ctx.lineTo(cx + size * 0.3, cy - size * 0.55);
      ctx.lineTo(cx + size * 0.18, cy - size * 0.5);
      ctx.lineTo(cx + size * 0.1, cy - size * 0.6);
      ctx.lineTo(cx, cy - size * 0.5);
      ctx.lineTo(cx - size * 0.12, cy - size * 0.6);
      ctx.lineTo(cx - size * 0.22, cy - size * 0.55);
      ctx.lineTo(cx - size * 0.3, cy - size * 0.55);
      ctx.closePath();
      ctx.fillStyle = 'rgba(245,250,255,0.85)';
      ctx.fill();
      ctx.restore();
    };

    const drawSky = () => {
      const sky = ctx.createLinearGradient(0, 0, 0, H);
      sky.addColorStop(0, '#1a1f3a');
      sky.addColorStop(0.5, '#2a2f4f');
      sky.addColorStop(1, '#3a3a55');
      ctx.fillStyle = sky;
      ctx.fillRect(0, 0, W, H);
      const vig = ctx.createRadialGradient(W * 0.5, H * 0.4, 0, W * 0.5, H * 0.4, Math.max(W, H) * 0.7);
      vig.addColorStop(0, 'rgba(255,235,180,0.05)');
      vig.addColorStop(1, 'rgba(0,0,0,0.4)');
      ctx.fillStyle = vig;
      ctx.fillRect(0, 0, W, H);
    };

    const drawBoats = (phase) => {
      const boats = [
        { x: W * 0.12, y: H * 0.78, scale: 0.7 },
        { x: W * 0.78, y: H * 0.74, scale: 0.55 },
      ];
      boats.forEach((b, i) => {
        ctx.save();
        const bob = Math.sin(phase * 1.4 + i * 2) * 4;
        ctx.translate(b.x, b.y + bob);
        ctx.scale(b.scale, b.scale);
        ctx.fillStyle = '#d4a85c';
        ctx.beginPath();
        ctx.moveTo(-50, 0);
        ctx.quadraticCurveTo(0, 18, 50, 0);
        ctx.lineTo(40, -8);
        ctx.lineTo(-40, -8);
        ctx.closePath();
        ctx.fill();
        ctx.fillStyle = 'rgba(60,30,10,0.5)';
        ctx.fillRect(-40, -8, 80, 4);
        ctx.restore();
      });
    };

    const draw = () => {
      t += 0.012;
      drawSky();
      drawFuji();
      wavePath(H * 0.68, 8, 0.012, t * 0.8, 'rgba(28,42,80,0.55)');
      wavePath(H * 0.74, 12, 0.018, t * 1.1 + 1, 'rgba(20,32,68,0.7)');
      drawBoats(t);
      wavePath(H * 0.78, 18, 0.014, t * 1.3 + 2, 'rgba(15,28,60,0.85)');
      crestWave(t);
      wavePath(H * 0.92, 14, 0.020, t * 1.6 + 3, 'rgba(8,16,40,0.95)');
      animRef.current = requestAnimationFrame(draw);
    };
    animRef.current = requestAnimationFrame(draw);

    return () => {
      window.removeEventListener('resize', resize);
      cancelAnimationFrame(animRef.current);
    };
  }, []);

  return (
    <div style={{ position: 'absolute', inset: 0, overflow: 'hidden', pointerEvents: 'none' }} aria-hidden="true">
      <canvas ref={canvasRef} style={{ display: 'block', width: '100%', height: '100%' }} />
      <div style={{
        position: 'absolute', top: 0, left: 0, right: 0, height: 100,
        background: 'linear-gradient(180deg, rgba(15,15,35,0.85), transparent)',
      }} />
      <div style={{
        position: 'absolute', top: 110, right: 30,
        padding: '14px 8px',
        border: `1.5px solid ${accent}`,
        background: 'rgba(245,235,200,0.08)',
        backdropFilter: 'blur(2px)',
        fontFamily: "'Cinzel', serif",
        color: accent,
        writingMode: 'vertical-rl',
        textOrientation: 'mixed',
        fontSize: '0.7rem',
        letterSpacing: 4,
        opacity: 0.7,
      }}>LESTAGE · 流</div>
    </div>
  );
}

// ---------------- 3D LAYER STACK (Tecnologia) ----------------
function Layer3DStack({ layers, active = null, onSelect = null, compact = false }) {
  const [hoveredLocal, setHoveredLocal] = useState(null);
  const focused = active != null ? active : hoveredLocal;
  const cardH = compact ? 110 : 130;
  const stepY = compact ? 64 : 78;
  return (
    <div style={{
      perspective: '1800px',
      perspectiveOrigin: '50% 30%',
      padding: compact ? '20px 0 40px' : '40px 0 60px',
      display: 'flex', justifyContent: 'center',
      width: '100%',
    }}>
      <div style={{
        position: 'relative',
        width: '100%', maxWidth: compact ? 540 : 720,
        height: layers.length * stepY + cardH,
        transformStyle: 'preserve-3d',
        transform: 'rotateX(58deg) rotateZ(-32deg)',
        transition: 'transform 0.6s cubic-bezier(.3,.7,.3,1)',
      }} className="l3d-stage">
        {layers.map((l, i) => {
          const isFocused = focused === i;
          const lifted = isFocused ? 110 : 0;
          // dim non-focused layers when something is focused
          const dim = focused !== null && !isFocused ? 0.55 : 1;
          const baseY = i * stepY; // top card = last layer (L1 Data)
          return (
            <div key={i}
              onMouseEnter={() => { setHoveredLocal(i); onSelect && onSelect(i); }}
              onMouseLeave={() => setHoveredLocal(null)}
              onClick={() => onSelect && onSelect(i)}
              style={{
                position: 'absolute', top: baseY, left: 0, right: 0,
                height: cardH,
                borderRadius: 14,
                background: `linear-gradient(135deg, ${l.color}${isFocused ? '28' : '18'}, rgba(15,15,35,0.85))`,
                border: `1px solid ${l.color}${isFocused ? '99' : '55'}`,
                boxShadow: `0 0 0 1px ${l.color}22 inset, 0 30px 60px -20px rgba(0,0,0,0.7), 0 0 ${isFocused ? 80 : 50}px ${l.color}${isFocused ? '40' : '25'}`,
                transform: `translateZ(${lifted}px)`,
                transition: 'transform 0.45s cubic-bezier(.3,.7,.3,1), box-shadow 0.3s, opacity 0.3s, border-color 0.3s, background 0.3s',
                cursor: onSelect ? 'pointer' : 'default',
                opacity: dim,
                display: 'flex', alignItems: 'center', gap: 24,
                padding: '0 32px',
                backdropFilter: 'blur(8px)',
                WebkitBackdropFilter: 'blur(8px)',
              }}>
              <div style={{
                width: 56, height: 56, flexShrink: 0,
                borderRadius: 12,
                background: `linear-gradient(135deg, ${l.color}40, ${l.color}10)`,
                border: `1px solid ${l.color}70`,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                boxShadow: `0 0 24px ${l.color}50`,
              }}>
                <Icon name={l.icon} size={26} color={l.color} />
              </div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{
                  fontFamily: "'DM Sans', sans-serif",
                  fontSize: '1.1rem', color: colors.textPrimary,
                  fontWeight: 600, marginBottom: 4,
                  whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                }}>{l.name}</div>
                <div style={{
                  fontFamily: "'Courier Prime', monospace",
                  fontSize: '0.7rem', color: l.color,
                  letterSpacing: 2, fontWeight: 700,
                  whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                }}>{l.n} · {l.brand}</div>
              </div>
              <div style={{
                position: 'absolute', inset: 0,
                background: `radial-gradient(ellipse 70% 50% at 50% 50%, ${l.color}10, transparent 70%)`,
                pointerEvents: 'none',
              }} />
            </div>
          );
        })}
      </div>
      <style>{`
        @media (max-width: 820px) {
          .l3d-stage { transform: rotateX(45deg) rotateZ(-20deg) !important; }
        }
      `}</style>
    </div>
  );
}

// ---------------- GAMING GRID (AiKo page) ----------------
function GamingGrid({ accent = '#ffd700' }) {
  return (
    <div style={{ position: 'absolute', inset: 0, overflow: 'hidden', pointerEvents: 'none' }} aria-hidden="true">
      <div style={{
        position: 'absolute', inset: 0,
        background: `radial-gradient(ellipse 60% 70% at 50% 30%, rgba(255,215,0,0.1), transparent 70%), radial-gradient(ellipse 80% 50% at 50% 100%, rgba(45,200,120,0.08), transparent 70%)`,
      }} />
      <div style={{
        position: 'absolute', bottom: 0, left: '50%',
        width: '180%', height: '60%',
        transform: 'translateX(-50%) perspective(700px) rotateX(60deg)',
        transformOrigin: '50% 100%',
        backgroundImage: `
          linear-gradient(${accent}55 1px, transparent 1px),
          linear-gradient(90deg, ${accent}55 1px, transparent 1px)
        `,
        backgroundSize: '50px 50px',
        animation: 'gaming-scroll 6s linear infinite',
        maskImage: 'linear-gradient(180deg, transparent, black 30%, black 80%, transparent)',
        WebkitMaskImage: 'linear-gradient(180deg, transparent, black 30%, black 80%, transparent)',
      }} />
      <div style={{
        position: 'absolute', inset: 0,
        background: 'repeating-linear-gradient(0deg, transparent, transparent 3px, rgba(255,215,0,0.025) 3px, rgba(255,215,0,0.025) 4px)',
        mixBlendMode: 'screen',
      }} />
      <div style={{
        position: 'absolute', left: 0, right: 0, top: '50%',
        height: 2,
        background: `linear-gradient(90deg, transparent, ${accent}, transparent)`,
        boxShadow: `0 0 20px ${accent}`,
        animation: 'gaming-scan 5s linear infinite',
      }} />
      <style>{`
        @keyframes gaming-scroll {
          0% { background-position: 0 0; }
          100% { background-position: 0 50px; }
        }
        @keyframes gaming-scan {
          0% { transform: translateY(-300px); opacity: 0; }
          15% { opacity: 0.9; }
          85% { opacity: 0.9; }
          100% { transform: translateY(300px); opacity: 0; }
        }
      `}</style>
    </div>
  );
}

// ---------------- EDO CARTOUCHE — vertical kanji label ----------------
function Cartouche({ accent = '#f4d03f', text = '', top = 110, right = 30, opacity = 0.95 }) {
  return (
    <div style={{
      position: 'absolute', top, right,
      padding: '16px 10px',
      border: `2px solid ${accent}`,
      background: 'rgba(15,15,30,0.72)',
      backdropFilter: 'blur(4px)',
      WebkitBackdropFilter: 'blur(4px)',
      boxShadow: `0 0 18px ${accent}55, inset 0 0 12px rgba(0,0,0,0.4)`,
      fontFamily: "'Cinzel', serif",
      color: accent,
      writingMode: 'vertical-rl',
      textOrientation: 'mixed',
      fontSize: '0.72rem',
      letterSpacing: 4,
      fontWeight: 600,
      textShadow: `0 0 6px ${accent}66`,
      opacity,
      zIndex: 2,
      pointerEvents: 'none',
    }}>{text}</div>
  );
}

// ---------------- HIKARI RAYS — light shafts for Lumiere ----------------
// Volumetric light rays (god rays) emanating from the top, with floating
// dust motes catching the light. "Hikari" 光 = light.
function HikariRays({ accent = '#c9a84c', warm = '#e8d090' }) {
  const canvasRef = useRef(null);
  const animRef = useRef(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let W = 0, H = 0, t = 0;
    const dpr = Math.min(window.devicePixelRatio || 1, 2);

    let motes = [];
    const MOTE_COUNT = 80;

    const resize = () => {
      const rect = canvas.parentElement.getBoundingClientRect();
      W = Math.ceil(rect.width); H = Math.ceil(rect.height);
      canvas.width = W * dpr; canvas.height = H * dpr;
      canvas.style.width = W + 'px'; canvas.style.height = H + 'px';
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      motes = Array.from({ length: MOTE_COUNT }, () => ({
        x: Math.random() * W,
        y: Math.random() * H,
        r: 0.6 + Math.random() * 1.8,
        vx: (Math.random() - 0.5) * 0.3,
        vy: 0.05 + Math.random() * 0.25,
        alpha: 0.25 + Math.random() * 0.5,
        twinklePhase: Math.random() * Math.PI * 2,
        big: Math.random() > 0.85,
      }));
    };
    resize();
    window.addEventListener('resize', resize);

    // Source points for rays — slightly above viewport top
    const raySources = [
      { x: 0.18, intensity: 0.7, width: 80 },
      { x: 0.32, intensity: 1.0, width: 110 },
      { x: 0.48, intensity: 0.85, width: 95 },
      { x: 0.62, intensity: 1.0, width: 120 },
      { x: 0.78, intensity: 0.65, width: 75 },
      { x: 0.90, intensity: 0.55, width: 65 },
    ];

    const draw = () => {
      t += 0.006;
      // Base atmosphere — deep amber/ink
      const bg = ctx.createLinearGradient(0, 0, 0, H);
      bg.addColorStop(0, '#1a1408');
      bg.addColorStop(0.5, '#0f0a04');
      bg.addColorStop(1, '#080502');
      ctx.fillStyle = bg;
      ctx.fillRect(0, 0, W, H);

      // Radial halo top-center
      const halo = ctx.createRadialGradient(W * 0.5, -100, 0, W * 0.5, -100, Math.max(W, H) * 0.9);
      halo.addColorStop(0, `rgba(232,208,144,0.18)`);
      halo.addColorStop(0.4, `rgba(201,168,76,0.06)`);
      halo.addColorStop(1, 'rgba(0,0,0,0)');
      ctx.fillStyle = halo;
      ctx.fillRect(0, 0, W, H);

      // Light rays — additive blending for glow buildup
      ctx.globalCompositeOperation = 'lighter';
      raySources.forEach((src, i) => {
        const sx = src.x * W;
        // Origin slightly above viewport
        const oy = -120;
        // Sway — each ray drifts independently
        const sway = Math.sin(t * 0.3 + i * 1.3) * 30;
        const intensity = src.intensity * (0.7 + Math.sin(t * 0.5 + i) * 0.2);

        // Ray = wide trapezoid that fades to bottom
        ctx.save();
        ctx.translate(sx + sway, oy);
        // Slight rotation
        const ang = Math.sin(t * 0.2 + i * 0.7) * 0.04 + (i - raySources.length / 2) * 0.02;
        ctx.rotate(ang);

        // Multi-layer ray for soft edge
        for (let layer = 3; layer >= 0; layer--) {
          const w = src.width * (1 + layer * 0.6);
          const h = H + 200;
          const grad = ctx.createLinearGradient(0, 0, 0, h);
          const a = intensity * 0.18 * (1 - layer * 0.18);
          grad.addColorStop(0, `rgba(232,208,144,${a})`);
          grad.addColorStop(0.4, `rgba(201,168,76,${a * 0.6})`);
          grad.addColorStop(1, 'rgba(201,168,76,0)');
          ctx.fillStyle = grad;
          ctx.beginPath();
          // Trapezoid widening downward
          const topW = w * 0.4;
          const botW = w * 1.6;
          ctx.moveTo(-topW / 2, 0);
          ctx.lineTo(topW / 2, 0);
          ctx.lineTo(botW / 2, h);
          ctx.lineTo(-botW / 2, h);
          ctx.closePath();
          ctx.fill();
        }
        ctx.restore();
      });
      ctx.globalCompositeOperation = 'source-over';

      // Dust motes
      motes.forEach((m, i) => {
        m.x += m.vx;
        m.y += m.vy;
        m.twinklePhase += 0.04;
        if (m.y > H + 10) { m.y = -10; m.x = Math.random() * W; }
        if (m.x > W + 10) m.x = -10;
        if (m.x < -10) m.x = W + 10;

        // Inside a ray? boost alpha — quick approximation
        let glow = 0;
        raySources.forEach((src, j) => {
          const sx = src.x * W + Math.sin(t * 0.3 + j * 1.3) * 30;
          const dx = m.x - sx;
          const widthAtY = src.width * (0.4 + (m.y / H) * 1.2);
          if (Math.abs(dx) < widthAtY) {
            glow += (1 - Math.abs(dx) / widthAtY) * src.intensity;
          }
        });
        const twinkle = (Math.sin(m.twinklePhase) + 1) * 0.5;
        const a = m.alpha * (0.4 + glow * 0.7) * (0.6 + twinkle * 0.4);

        ctx.beginPath();
        ctx.arc(m.x, m.y, m.r, 0, Math.PI * 2);
        ctx.fillStyle = m.big
          ? `rgba(255,235,180,${a})`
          : `rgba(232,208,144,${a * 0.85})`;
        ctx.fill();

        if (m.big && glow > 0.3) {
          ctx.beginPath();
          ctx.arc(m.x, m.y, m.r * 3, 0, Math.PI * 2);
          ctx.fillStyle = `rgba(255,235,180,${a * 0.15})`;
          ctx.fill();
        }
      });

      animRef.current = requestAnimationFrame(draw);
    };

    animRef.current = requestAnimationFrame(draw);

    return () => {
      window.removeEventListener('resize', resize);
      cancelAnimationFrame(animRef.current);
    };
  }, []);

  return (
    <div style={{ position: 'absolute', inset: 0, overflow: 'hidden', pointerEvents: 'none' }} aria-hidden="true">
      <canvas ref={canvasRef} style={{ display: 'block', width: '100%', height: '100%' }} />
      {/* Top fade for navbar */}
      <div style={{
        position: 'absolute', top: 0, left: 0, right: 0, height: 80,
        background: 'linear-gradient(180deg, rgba(8,5,2,0.7), transparent)',
      }} />
    </div>
  );
}

// ---------------- STEEL HEX GRID — solid hex tiles for Kodari ----------------
// Tessellated hexagons rendered like brushed steel plates, with an
// emerald glow that travels along the borders. Reads as "solid platform".
function SteelHexGrid({ accent = '#2d6a4f', glow = '#52b788' }) {
  const canvasRef = useRef(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let W = 0, H = 0;
    const dpr = Math.min(window.devicePixelRatio || 1, 2);

    const HEX_R = 38;
    const HEX_W = HEX_R * Math.sqrt(3);
    const HEX_H = HEX_R * 2;
    const ROW_STEP = HEX_H * 0.75;

    const hexPath = (cx, cy, r) => {
      ctx.beginPath();
      for (let i = 0; i < 6; i++) {
        const ang = (Math.PI / 3) * i + Math.PI / 6;
        const px = cx + r * Math.cos(ang);
        const py = cy + r * Math.sin(ang);
        if (i === 0) ctx.moveTo(px, py);
        else ctx.lineTo(px, py);
      }
      ctx.closePath();
    };

    // One-shot render. Bakes a "wave snapshot" of the emerald glow so the
    // page keeps the lively look without paying ~60fps of canvas cost.
    const render = () => {
      const rect = canvas.parentElement.getBoundingClientRect();
      W = Math.ceil(rect.width); H = Math.ceil(rect.height);
      canvas.width = W * dpr; canvas.height = H * dpr;
      canvas.style.width = W + 'px'; canvas.style.height = H + 'px';
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);

      // Steel gunmetal base
      const bg = ctx.createLinearGradient(0, 0, 0, H);
      bg.addColorStop(0, '#0e1614');
      bg.addColorStop(0.5, '#0a1110');
      bg.addColorStop(1, '#060a0a');
      ctx.fillStyle = bg;
      ctx.fillRect(0, 0, W, H);

      const vig = ctx.createRadialGradient(W * 0.5, H * 0.5, 0, W * 0.5, H * 0.5, Math.max(W, H) * 0.7);
      vig.addColorStop(0, 'rgba(45,106,79,0.06)');
      vig.addColorStop(1, 'rgba(0,0,0,0.35)');
      ctx.fillStyle = vig;
      ctx.fillRect(0, 0, W, H);

      const cols = Math.ceil(W / HEX_W) + 2;
      const rows = Math.ceil(H / ROW_STEP) + 2;
      const hexes = [];
      for (let r = -1; r < rows; r++) {
        for (let c = -1; c < cols; c++) {
          const offsetX = (r % 2 === 0) ? 0 : HEX_W / 2;
          const cx = c * HEX_W + offsetX;
          const cy = r * ROW_STEP;
          const seed = ((r * 73 + c * 31) % 100 + 100) % 100;
          hexes.push({ cx, cy, depth: 0.7 + (seed / 100) * 0.3, row: r, col: c });
        }
      }

      // PASS 1 — brushed steel fill + scratches (static)
      hexes.forEach((h) => {
        const grad = ctx.createRadialGradient(
          h.cx - HEX_R * 0.3, h.cy - HEX_R * 0.4, 0,
          h.cx, h.cy, HEX_R
        );
        const baseLight = 22 + h.depth * 8;
        const baseDark = 8;
        grad.addColorStop(0, `rgb(${baseLight + 8},${baseLight + 14},${baseLight + 12})`);
        grad.addColorStop(0.5, `rgb(${baseLight - 2},${baseLight + 4},${baseLight + 2})`);
        grad.addColorStop(1, `rgb(${baseDark},${baseDark + 4},${baseDark + 2})`);
        ctx.fillStyle = grad;
        hexPath(h.cx, h.cy, HEX_R - 1.5);
        ctx.fill();

        ctx.strokeStyle = 'rgba(180,200,190,0.04)';
        ctx.lineWidth = 0.5;
        for (let i = -3; i <= 3; i++) {
          const ly = h.cy + i * 8;
          ctx.beginPath();
          ctx.moveTo(h.cx - HEX_R * 0.6, ly);
          ctx.lineTo(h.cx + HEX_R * 0.6, ly);
          ctx.stroke();
        }
      });

      // PASS 2 — emerald borders with a baked diagonal wave snapshot.
      // Picking a phase that gives a visually-pleasing spread of bright/dim cells.
      const tBake = 1.7;
      hexes.forEach((h) => {
        const wavePos = (h.col + h.row) * 0.4;
        const pulse = Math.sin(tBake * 1.2 - wavePos) * 0.5 + 0.5;
        const glowAlpha = pulse * 0.35;

        if (glowAlpha > 0.2) {
          ctx.shadowBlur = 12 + glowAlpha * 16;
          ctx.shadowColor = `rgba(82,183,136,${glowAlpha})`;
        } else {
          ctx.shadowBlur = 0;
        }
        ctx.strokeStyle = `rgba(82,183,136,${0.25 + glowAlpha * 0.7})`;
        ctx.lineWidth = 1 + glowAlpha * 1.2;
        hexPath(h.cx, h.cy, HEX_R - 1.5);
        ctx.stroke();
        ctx.shadowBlur = 0;

        ctx.strokeStyle = 'rgba(45,106,79,0.18)';
        ctx.lineWidth = 0.6;
        hexPath(h.cx, h.cy, HEX_R - 5);
        ctx.stroke();

        ctx.beginPath();
        ctx.arc(h.cx, h.cy, 1.5, 0, Math.PI * 2);
        ctx.fillStyle = 'rgba(120,140,130,0.25)';
        ctx.fill();
      });
    };

    render();
    // Re-render on resize, throttled
    let resizeT = null;
    const onResize = () => {
      clearTimeout(resizeT);
      resizeT = setTimeout(render, 150);
    };
    window.addEventListener('resize', onResize);

    return () => {
      window.removeEventListener('resize', onResize);
      clearTimeout(resizeT);
    };
  }, []);

  return (
    <div style={{ position: 'absolute', inset: 0, overflow: 'hidden', pointerEvents: 'none' }} aria-hidden="true">
      <canvas ref={canvasRef} style={{
        display: 'block', width: '100%', height: '100%',
      }} />
      <div style={{
        position: 'absolute', top: 0, left: 0, right: 0, height: 100,
        background: 'linear-gradient(180deg, rgba(6,10,10,0.85), transparent)',
      }} />
    </div>
  );
}

Object.assign(window, { MatrixRain, EdoWaves, FlowCurrent, Layer3DStack, GamingGrid, Cartouche, HikariRays, SteelHexGrid });
