{"version":3,"file":"Dots_sim_hex.DnZ95Sy7.mjs","names":["useRef","rect","useState","_Fragment"],"sources":["https:/framerusercontent.com/modules/8ZUcqshwPWn5AvIHJVll/1IZ9B9lPxqApkuBE5rpR/Dots_sim_hex.js"],"sourcesContent":["import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from\"react/jsx-runtime\";import{useEffect,useRef,useState}from\"react\";// =============================================================================\n// CONFIGURATION\n// =============================================================================\nconst CONFIG={PALETTE:[\"#4169e1\",\"#b7feb9\",\"#a8feff\",\"#feb1fe\",\"#1BFF37\",\"#12FFFF\",\"#FF31FF\"],BACKGROUND_COLOR:\"#F6F4F1\",TRAIL_FADE_OPACITY:.06,LIFE_OPACITY:.2,DOT_RADIUS_BASE:2,SATURATION_RANGE:[.2,.8],BRIGHTNESS_RANGE:[.7,.99],HEX_SIZE_RANGE:[5,12.5],SCREEN_AREA_RANGE:[3e5,1e7],DEATH_THRESHOLD:.05,MUTATION_RATE_HUE:[.95,1.05],MUTATION_RATE_METABOLISM:[.95,1.01],MUTATION_RATE_AGGRESSION:[.95,1.01],UPDATE_RATE_RANGE:[1,10],MOUSE_GROWTH_BASE:4,MOUSE_GROWTH_DIVISOR:4,STATIONARY_CLICK_INTERVAL:15,RESISTANCE_GROWTH:1.01,AGGRESSION_GROWTH:1.01,FOOD_RECOVERY_CHANCE:.99,FOOD_RECOVERY_AMOUNT:.005,PRIORITY_UPDATE_INTERVAL:10,LOW_PRIORITY_UPDATE_INTERVAL:2,NOISE_SCALE:10,INITIAL_GROWTH_MULTIPLIER:8,FUNGUS_SPAWN_CHANCE:.2,FUNGUS_SPREAD_CHANCE:.5,FUNGUS_LIFESPAN:120,FUNGUS_COLOR:\"#F5F3F0\",// Canvas resolution: multiplier against device pixels.\n// 0.5 on a 2x retina = 1x CSS pixels (visually identical to non-retina).\n// 1.0 = full retina sharpness. Lower = less GPU compositing work.\nCANVAS_SCALE:.5};// =============================================================================\n// WORKER SOURCE\n// The entire simulation + render loop runs in a Web Worker, completely off\n// the main thread. The main thread only forwards mouse coordinates.\n// =============================================================================\nconst WORKER_SOURCE=/* js */`\n\"use strict\";\n\nlet canvas, ctx, CONFIG;\nlet cells = [], cw = 0, ch = 0, hexSize = 0, cssW = 0, cssH = 0;\nlet frameCount = 0;\nlet mouseX = 0, mouseY = 0, oldCol = 0, oldRow = 0;\nconst lifePool = [];\n\n// --- Math helpers ---\nconst rng = (a, b) => {\n    if (a === undefined) return Math.random();\n    if (b === undefined) return Math.random() * a;\n    return Math.random() * (b - a) + a;\n};\nconst mapv = (v, s1, e1, s2, e2) => s2 + (e2 - s2) * ((v - s1) / (e1 - s1));\nconst clamp = (v, lo, hi) => v < lo ? lo : v > hi ? hi : v;\nconst { floor, ceil, abs, sqrt, round, PI } = Math;\nconst TAU = PI * 2;\nconst HEX_SQRT3 = Math.sqrt(3);\n\n// --- Noise ---\nconst perm = Array.from({length:256}, () => floor(Math.random()*256));\nconst p = [...perm,...perm];\nconst fade = t => t*t*t*(t*(t*6-15)+10);\nconst lerp = (t,a,b) => a+t*(b-a);\nconst grad = (hash,x,y) => {\n    const h=hash&3, u=h<2?x:y, v=h<2?y:x;\n    return ((h&1)===0?u:-u)+((h&2)===0?v:-v);\n};\nconst noiseFn = (x,y) => {\n    const X=floor(x)&255, Y=floor(y)&255;\n    x-=floor(x); y-=floor(y);\n    const u=fade(x), v=fade(y);\n    const A=p[X]+Y, B=p[X+1]+Y;\n    return (lerp(v,\n        lerp(u,grad(p[A],x,y),grad(p[B],x-1,y)),\n        lerp(u,grad(p[A+1],x,y-1),grad(p[B+1],x-1,y-1))\n    )+1)/2;\n};\n\n// --- Color ---\nconst hsbToRgb = (h,s,b) => {\n    h=h%1; const i=floor(h*6), f=h*6-i;\n    const pp=b*(1-s), q=b*(1-f*s), t=b*(1-(1-f)*s);\n    let r=0,g=0,bl=0;\n    switch(i%6){\n        case 0:r=b;g=t;bl=pp;break;case 1:r=q;g=b;bl=pp;break;\n        case 2:r=pp;g=b;bl=t;break;case 3:r=pp;g=q;bl=b;break;\n        case 4:r=t;g=pp;bl=b;break;case 5:r=b;g=pp;bl=q;break;\n    }\n    return [r*255,g*255,bl*255];\n};\nconst hexToRgb = hex => {\n    const m=/^#?([a-f\\\\d]{2})([a-f\\\\d]{2})([a-f\\\\d]{2})$/i.exec(hex);\n    return m ? [parseInt(m[1],16),parseInt(m[2],16),parseInt(m[3],16)] : [0,0,0];\n};\nlet paletteRgb;\nconst matchPaletteIndex = (r,g,b) => {\n    let best=0, bd=1e9;\n    for(let i=0;i<paletteRgb.length;i++){\n        const pr=paletteRgb[i][0],pg=paletteRgb[i][1],pb=paletteRgb[i][2];\n        const d=(r-pr)*(r-pr)+(g-pg)*(g-pg)+(b-pb)*(b-pb);\n        if(d<bd){bd=d;best=i;}\n    }\n    return best;\n};\n\n// --- Hex geometry ---\nconst hexCX = (col,hs) => col*hs*HEX_SQRT3 + hs*HEX_SQRT3/2;\nconst hexCY = (col,row,hs) => row*hs*2*0.75 + (col&1)*(hs*2*0.75/2) + hs;\nconst pxToHex = (px,py,hs) => {\n    const hw=hs*HEX_SQRT3, vs=hs*2*0.75;\n    const col=floor(px/hw);\n    const row=floor((py-(col&1)*(vs/2)-hs+vs/2)/vs);\n    let bc=col,br=row,md=1e9;\n    const cands=[col,row,col,row-1,col,row+1,col-1,row,col+1,row,\n        col-1,(col&1)?row+1:row-1, col+1,(col&1)?row+1:row-1];\n    for(let k=0;k<14;k+=2){\n        const cc=cands[k],cr=cands[k+1];\n        const cx=hexCX(cc,hs),cy=hexCY(cc,cr,hs);\n        const d=(px-cx)**2+(py-cy)**2;\n        if(d<md){md=d;bc=cc;br=cr;}\n    }\n    return [bc,br];\n};\nconst EVEN_OFF = [[1,-1],[1,0],[0,1],[-1,0],[-1,-1],[0,-1]];\nconst ODD_OFF  = [[1,0],[1,1],[0,1],[-1,1],[-1,0],[0,-1]];\nconst toroidalDistSq = (c1,r1,c2,r2) => {\n    let dc=abs(c2-c1),dr=abs(r2-r1);\n    if(dc>cw/2)dc=cw-dc; if(dr>ch/2)dr=ch-dr;\n    return dc*dc+dr*dr;\n};\n\n// --- Life ---\nfunction Life(cell) {\n    this.cell=cell; this.hue=rng(); this.metabolism=rng();\n    this.size=rng(); this.agression=rng(); this.resistance=0;\n    this.updateCounter=0;\n    this.updateRate=floor(mapv(1-this.metabolism,0,1,CONFIG.UPDATE_RATE_RANGE[0],CONFIG.UPDATE_RATE_RANGE[1]));\n    this.paletteIdx=computePaletteIdx(this);\n}\nfunction computePaletteIdx(life) {\n    const [r,g,b]=hsbToRgb(\n        ((life.hue*3)%3)/3,\n        mapv(1-life.agression,0,1,CONFIG.SATURATION_RANGE[0],CONFIG.SATURATION_RANGE[1]),\n        mapv(life.metabolism,0,1,CONFIG.BRIGHTNESS_RANGE[0],CONFIG.BRIGHTNESS_RANGE[1]));\n    return matchPaletteIndex(r,g,b);\n}\nfunction lifeStats(life,h,m,a) {\n    life.hue=h; life.metabolism=m; life.size=life.cell.food/2; life.agression=a;\n    life.updateRate=floor(mapv(1-m,0,1,CONFIG.UPDATE_RATE_RANGE[0],CONFIG.UPDATE_RATE_RANGE[1]));\n    life.paletteIdx=computePaletteIdx(life);\n}\nfunction lifeUpdate(life) {\n    life.updateCounter++;\n    if(life.updateCounter<life.updateRate) return;\n    life.updateCounter=0;\n    life.cell.food-=life.metabolism*life.size;\n    life.size*=life.cell.food/life.size;\n    life.size=clamp(life.size,0,1);\n    if(life.size<CONFIG.DEATH_THRESHOLD){killLife(life.cell);return;}\n    if(rng()*rng()<life.metabolism) haveChild(life);\n    let sum=0; const c=life.cell;\n    if(c.ne&&c.ne.life) sum+=1-c.ne.life.agression;\n    if(c.e&&c.e.life) sum+=1-c.e.life.agression;\n    if(c.se&&c.se.life) sum+=1-c.se.life.agression;\n    if(c.sw&&c.sw.life) sum+=1-c.sw.life.agression;\n    if(c.w&&c.w.life) sum+=1-c.w.life.agression;\n    if(c.nw&&c.nw.life) sum+=1-c.nw.life.agression;\n    life.resistance=sum/6/life.agression;\n}\nfunction haveChild(life) {\n    const i=round(rng(6));\n    let h=life.hue*rng(CONFIG.MUTATION_RATE_HUE[0],CONFIG.MUTATION_RATE_HUE[1]);\n    if(h<0)h+=1;if(h>1)h-=1;\n    let a=life.agression*rng(CONFIG.MUTATION_RATE_AGGRESSION[0],CONFIG.MUTATION_RATE_AGGRESSION[1]);\n    if(a<0)a+=1;if(a>1)a-=1;\n    let m=life.metabolism*rng(CONFIG.MUTATION_RATE_METABOLISM[0],CONFIG.MUTATION_RATE_METABOLISM[1]);\n    if(m<0)m+=1;if(m>1)m-=1;\n    const c=life.cell;\n    const target=i===0?c.ne:i===1?c.e:i===2?c.se:i===3?c.sw:i===4?c.w:c.nw;\n    if(target){\n        let l;\n        if(lifePool.length>0){l=lifePool.pop();l.cell=target;}\n        else{l=new Life(target);}\n        lifeStats(l,h,m,a);\n        addExistingLife(target,l);\n    }\n}\n\n// --- Cell ---\nfunction Cell(hs,col,row) {\n    this.hexSize=hs; this.growthMod=1; this.col=col; this.row=row;\n    this.cx=hexCX(col,hs); this.cy=hexCY(col,row,hs);\n    this.food=rng(); this.life=null; this.fungusLife=0; this.humus=false;\n    this.ne=null;this.e=null;this.se=null;this.sw=null;this.w=null;this.nw=null;\n    this.growth=noiseFn(col/CONFIG.NOISE_SCALE,row/CONFIG.NOISE_SCALE)*CONFIG.INITIAL_GROWTH_MULTIPLIER;\n    this.updatePriority=1;\n}\nfunction addLife(cell) {\n    if(!cell.life){\n        if(lifePool.length>0){\n            cell.life=lifePool.pop();cell.life.cell=cell;\n            cell.life.hue=rng();cell.life.metabolism=rng();cell.life.size=rng();\n            cell.life.agression=rng();cell.life.resistance=0;cell.life.updateCounter=0;\n            cell.life.updateRate=floor(mapv(1-cell.life.metabolism,0,1,CONFIG.UPDATE_RATE_RANGE[0],CONFIG.UPDATE_RATE_RANGE[1]));\n            cell.life.paletteIdx=computePaletteIdx(cell.life);\n        } else { cell.life=new Life(cell); }\n    }\n}\nfunction addExistingLife(cell,l) {\n    if(!cell.life){cell.life=l;l.cell=cell;}\n    else if(cell.life.resistance>l.agression){cell.life.resistance*=CONFIG.RESISTANCE_GROWTH;lifePool.push(l);}\n    else if(cell.life.resistance<l.agression){\n        cell.food*=cell.life.size;l.agression*=CONFIG.AGGRESSION_GROWTH;\n        lifePool.push(cell.life);cell.life=l;l.cell=cell;\n    } else {lifePool.push(l);}\n}\nfunction killLife(cell) {\n    if(cell.life){\n        cell.food+=cell.life.size/2; lifePool.push(cell.life);\n        cell.life=null; cell.humus=true;\n        if(rng()<CONFIG.FUNGUS_SPAWN_CHANCE) cell.fungusLife=CONFIG.FUNGUS_LIFESPAN;\n    }\n}\nfunction cellNext(cell) {\n    cell.growth=cell.growthMod;\n    if(cell.life){lifeUpdate(cell.life);}\n    else{cell.food=cell.growth*cell.food*(1-cell.food);}\n    cell.food=clamp(cell.food,0.01,1);\n    if(cell.food===0&&cell.growth>1&&rng()>CONFIG.FOOD_RECOVERY_CHANCE)\n        cell.food+=CONFIG.FOOD_RECOVERY_AMOUNT;\n    if(cell.fungusLife>0){\n        cell.humus=false;\n        let nlc=0;\n        if(cell.ne&&cell.ne.life)nlc++;if(cell.e&&cell.e.life)nlc++;if(cell.se&&cell.se.life)nlc++;\n        if(cell.sw&&cell.sw.life)nlc++;if(cell.w&&cell.w.life)nlc++;if(cell.nw&&cell.nw.life)nlc++;\n        if(nlc>0){cell.fungusLife=0;}\n        else{\n            cell.fungusLife--;\n            if(cell.fungusLife>0){\n                const nbs=[cell.ne,cell.e,cell.se,cell.sw,cell.w,cell.nw];\n                let hc=0;\n                for(let n=0;n<6;n++){const nb=nbs[n];if(nb&&!nb.life&&nb.fungusLife===0&&nb.humus)hc++;}\n                if(hc>0&&rng()<CONFIG.FUNGUS_SPREAD_CHANCE){\n                    if(rng()<1/hc){\n                        for(let n=0;n<6;n++){\n                            const nb=nbs[n];\n                            if(nb&&!nb.life&&nb.fungusLife===0&&nb.humus)nb.fungusLife=CONFIG.FUNGUS_LIFESPAN;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\nfunction calcPriority(cell) {\n    let a=0;\n    if(cell.ne&&cell.ne.life)a++;if(cell.e&&cell.e.life)a++;if(cell.se&&cell.se.life)a++;\n    if(cell.sw&&cell.sw.life)a++;if(cell.w&&cell.w.life)a++;if(cell.nw&&cell.nw.life)a++;\n    cell.updatePriority=a>0?2:1;\n}\n\n// --- Grid init ---\nlet fadeFill, fungusFill;\n\nfunction initGrid(w, h, scale) {\n    cssW=w; cssH=h;\n    canvas.width=w*scale; canvas.height=h*scale;\n    ctx.setTransform(scale,0,0,scale,0,0);\n\n    hexSize=mapv(w*h,\n        CONFIG.SCREEN_AREA_RANGE[0],CONFIG.SCREEN_AREA_RANGE[1],\n        CONFIG.HEX_SIZE_RANGE[0],CONFIG.HEX_SIZE_RANGE[1]);\n    const hexWidth=hexSize*HEX_SQRT3, vertSpacing=hexSize*2*0.75;\n    cw=ceil(w/hexWidth)+1; ch=ceil(h/vertSpacing)+1;\n    if(cw===0||ch===0) return;\n\n    lifePool.length=0;\n    cells=[];\n    for(let c=0;c<cw;c++){\n        cells[c]=[];\n        for(let r=0;r<ch;r++) cells[c][r]=new Cell(hexSize,c,r);\n    }\n    for(let c=0;c<cw;c++){\n        const off=(c&1)?ODD_OFF:EVEN_OFF;\n        for(let r=0;r<ch;r++){\n            const cell=cells[c][r];\n            const wc=v=>((v%cw)+cw)%cw, wr=v=>((v%ch)+ch)%ch;\n            cell.ne=cells[wc(c+off[0][0])][wr(r+off[0][1])];\n            cell.e =cells[wc(c+off[1][0])][wr(r+off[1][1])];\n            cell.se=cells[wc(c+off[2][0])][wr(r+off[2][1])];\n            cell.sw=cells[wc(c+off[3][0])][wr(r+off[3][1])];\n            cell.w =cells[wc(c+off[4][0])][wr(r+off[4][1])];\n            cell.nw=cells[wc(c+off[5][0])][wr(r+off[5][1])];\n        }\n    }\n    ctx.fillStyle=CONFIG.BACKGROUND_COLOR;\n    ctx.fillRect(0,0,w,h);\n}\n\n// --- Draw loop (runs entirely in worker via rAF on OffscreenCanvas) ---\nfunction draw() {\n    if(!cells.length){requestAnimationFrame(draw);return;}\n\n    frameCount++;\n    const fc=frameCount;\n    const [mCol,mRow]=pxToHex(mouseX,mouseY,hexSize);\n    const updateLow=fc%CONFIG.LOW_PRIORITY_UPDATE_INTERVAL===0;\n    const updatePri=fc%CONFIG.PRIORITY_UPDATE_INTERVAL===0;\n\n    const colorBufs=[];\n    for(let i=0;i<CONFIG.PALETTE.length;i++) colorBufs.push([]);\n    const fungusBuf=[];\n    const fungusR=(hexSize+CONFIG.DOT_RADIUS_BASE)/2;\n\n    for(let i=0;i<cw;i++){\n        for(let j=0;j<ch;j++){\n            const cell=cells[i][j];\n            if(updatePri) calcPriority(cell);\n            if(cell.updatePriority>1||updateLow){\n                cellNext(cell);\n                const dSq=toroidalDistSq(i,j,mCol,mRow);\n                cell.growthMod=CONFIG.MOUSE_GROWTH_BASE-sqrt(dSq)/CONFIG.MOUSE_GROWTH_DIVISOR;\n            }\n            if(cell.life){\n                const r=(hexSize*cell.life.size+CONFIG.DOT_RADIUS_BASE)/2;\n                colorBufs[cell.life.paletteIdx].push(cell.cx,cell.cy,r);\n            }\n            if(cell.fungusLife>0) fungusBuf.push(cell.cx,cell.cy,fungusR);\n        }\n    }\n\n    ctx.fillStyle=fadeFill;\n    ctx.fillRect(0,0,cssW,cssH);\n\n    ctx.globalAlpha=CONFIG.LIFE_OPACITY;\n    for(let c=0;c<CONFIG.PALETTE.length;c++){\n        const buf=colorBufs[c];\n        if(!buf.length) continue;\n        ctx.fillStyle=CONFIG.PALETTE[c];\n        ctx.beginPath();\n        for(let k=0;k<buf.length;k+=3){\n            ctx.moveTo(buf[k]+buf[k+2],buf[k+1]);\n            ctx.arc(buf[k],buf[k+1],buf[k+2],0,TAU);\n        }\n        ctx.fill();\n    }\n    ctx.globalAlpha=1.0;\n\n    if(fungusBuf.length){\n        ctx.fillStyle=fungusFill;\n        ctx.beginPath();\n        for(let k=0;k<fungusBuf.length;k+=3){\n            ctx.moveTo(fungusBuf[k]+fungusBuf[k+2],fungusBuf[k+1]);\n            ctx.arc(fungusBuf[k],fungusBuf[k+1],fungusBuf[k+2],0,TAU);\n        }\n        ctx.fill();\n    }\n\n    {\n        const cc=clamp(mCol,0,cw-1), cr=clamp(mRow,0,ch-1);\n        if(cc!==oldCol||cr!==oldRow){\n            cells[cc][cr].life?killLife(cells[cc][cr]):addLife(cells[cc][cr]);\n        } else if(fc%CONFIG.STATIONARY_CLICK_INTERVAL===0){\n            cells[cc][cr].life?killLife(cells[cc][cr]):addLife(cells[cc][cr]);\n        }\n        oldCol=cc; oldRow=cr;\n    }\n\n    requestAnimationFrame(draw);\n}\n\n// --- Worker message handler ---\nself.onmessage = function(e) {\n    const msg = e.data;\n    if (msg.type === 'init') {\n        canvas = msg.canvas;\n        ctx = canvas.getContext('2d');\n        CONFIG = msg.config;\n        paletteRgb = CONFIG.PALETTE.map(hexToRgb);\n        const bgRgb = hexToRgb(CONFIG.BACKGROUND_COLOR);\n        fadeFill = \"rgba(\"+bgRgb[0]+\",\"+bgRgb[1]+\",\"+bgRgb[2]+\",\"+CONFIG.TRAIL_FADE_OPACITY+\")\";\n        fungusFill = CONFIG.FUNGUS_COLOR || CONFIG.BACKGROUND_COLOR;\n        initGrid(msg.cssWidth, msg.cssHeight, msg.scale);\n        requestAnimationFrame(draw);\n    } else if (msg.type === 'mouse') {\n        mouseX = msg.x;\n        mouseY = msg.y;\n    } else if (msg.type === 'resize') {\n        initGrid(msg.cssWidth, msg.cssHeight, msg.scale);\n    }\n};\n`;// =============================================================================\n// REACT COMPONENT — thin main-thread shell\n// =============================================================================\nfunction HexDotsCanvas({target}){const workerRef=useRef(null);useEffect(()=>{// --- Create DOM elements ---\nconst container=document.createElement(\"div\");container.style.cssText=\"position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:0;\";const canvas=document.createElement(\"canvas\");canvas.style.cssText=\"display:block;width:100%;height:100%;\";container.appendChild(canvas);const cs=window.getComputedStyle(target);if(cs.position===\"static\")target.style.position=\"relative\";if(target.firstChild)target.insertBefore(container,target.firstChild);else target.appendChild(container);// --- Compute scale ---\nconst DPR=window.devicePixelRatio||1;const scale=DPR*CONFIG.CANVAS_SCALE;// --- Check OffscreenCanvas support ---\nconst supportsOffscreen=typeof canvas.transferControlToOffscreen===\"function\"&&typeof Worker!==\"undefined\";if(!supportsOffscreen){// Graceful degradation: static background, no simulation.\n// OffscreenCanvas is supported in Chrome 69+, Firefox 105+,\n// Safari 16.4+, Edge 79+. This fallback essentially never triggers\n// in Framer's target browsers.\nconst ctx=canvas.getContext(\"2d\");if(ctx){const rect=container.getBoundingClientRect();canvas.width=rect.width*scale;canvas.height=rect.height*scale;ctx.setTransform(scale,0,0,scale,0,0);ctx.fillStyle=CONFIG.BACKGROUND_COLOR;ctx.fillRect(0,0,rect.width,rect.height);}return()=>{container.remove();};}// --- Worker path (primary) ---\nconst offscreen=canvas.transferControlToOffscreen();const blob=new Blob([WORKER_SOURCE],{type:\"application/javascript\"});const url=URL.createObjectURL(blob);const worker=new Worker(url);URL.revokeObjectURL(url);workerRef.current=worker;// Send canvas + config to worker\nconst rect=container.getBoundingClientRect();worker.postMessage({type:\"init\",canvas:offscreen,config:CONFIG,cssWidth:rect.width,cssHeight:rect.height,scale},[offscreen]// Transfer ownership — canvas is now worker-owned\n);// --- Mouse forwarding (throttled to 1 message per rAF) ---\nlet pendingMouse=false;let lastMX=0;let lastMY=0;const flushMouse=()=>{if(pendingMouse){worker.postMessage({type:\"mouse\",x:lastMX,y:lastMY});pendingMouse=false;}};const onMouse=e=>{const r=container.getBoundingClientRect();lastMX=e.clientX-r.left;lastMY=e.clientY-r.top;if(!pendingMouse){pendingMouse=true;requestAnimationFrame(flushMouse);}};const onTouch=e=>{if(!e.touches.length)return;const r=container.getBoundingClientRect();lastMX=e.touches[0].clientX-r.left;lastMY=e.touches[0].clientY-r.top;if(!pendingMouse){pendingMouse=true;requestAnimationFrame(flushMouse);}};// --- Resize forwarding ---\nconst onResize=()=>{const r=container.getBoundingClientRect();const newScale=(window.devicePixelRatio||1)*CONFIG.CANVAS_SCALE;worker.postMessage({type:\"resize\",cssWidth:r.width,cssHeight:r.height,scale:newScale});};document.addEventListener(\"mousemove\",onMouse);document.addEventListener(\"touchstart\",onTouch,{passive:true});document.addEventListener(\"touchmove\",onTouch,{passive:true});window.addEventListener(\"resize\",onResize);// --- Cleanup ---\nreturn()=>{worker.terminate();workerRef.current=null;document.removeEventListener(\"mousemove\",onMouse);document.removeEventListener(\"touchstart\",onTouch);document.removeEventListener(\"touchmove\",onTouch);window.removeEventListener(\"resize\",onResize);container.remove();};},[target]);return null;}// =============================================================================\n// EXPORTS — drop-in replacement for original withDots / withHexDots\n// =============================================================================\nexport function withHexDots(Component){return props=>{const ref=useRef(null);const[element,setElement]=useState(null);useEffect(()=>{if(ref.current)setElement(ref.current);},[]);return /*#__PURE__*/_jsxs(_Fragment,{children:[/*#__PURE__*/_jsx(Component,{...props,ref:ref}),element&&/*#__PURE__*/_jsx(HexDotsCanvas,{target:element})]});};}export const withDots=withHexDots;export default withHexDots;\nexport const __FramerMetadata__ = {\"exports\":{\"withHexDots\":{\"type\":\"reactHoc\",\"name\":\"withHexDots\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"withDots\":{\"type\":\"variable\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"default\":{\"type\":\"reactHoc\",\"name\":\"withHexDots\",\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./Dots_sim_hex.map"],"mappings":"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"}