"use client"; // Genesis (docs/DESIGN.md) — กริดจุดอันตรกิริยา: ลวดลายตกแต่งชิ้นเดียวที่ design // system อนุญาต ("the interactive dot grid is the only decorative element") ใช้เป็น // พื้นหลังหน้า login — จุดเทาถี่ 24px + ไฮไลต์น้ำเงินจางตามตำแหน่ง pointer // ⚠️ ต้องเป็น pointer-events-none เสมอ: ตัว layer เป็น absolute inset-0 ครอบพื้นที่ // ทั้งหน้า ส่วนการ์ด login เป็น static element — ตัว positioned จะชนะ hit-test ทับ // การ์ดจนคลิก/focus ช่องกรอกไม่ได้ (bug report 2026-09-23) จึงฟัง pointermove ที่ // window แทนของตัวเอง — ไฮไลต์ยังตามเมาส์ได้แม้อยู่เหนือการ์ด + อัปเดตผ่าน CSS // variable บน style ตรง ๆ ไม่ setState กัน re-render ทุก mousemove // mask ไล่จางขอบให้กลืนกับพื้น canvas แทนการตัดเส้นชัด import { useEffect, useRef } from "react"; export default function DotGrid() { const ref = useRef(null); useEffect(() => { const onPointerMove = (e: PointerEvent) => { const el = ref.current; if (!el) return; const rect = el.getBoundingClientRect(); el.style.setProperty("--dot-mx", `${e.clientX - rect.left}px`); el.style.setProperty("--dot-my", `${e.clientY - rect.top}px`); }; window.addEventListener("pointermove", onPointerMove, { passive: true }); return () => window.removeEventListener("pointermove", onPointerMove); }, []); return (
); }