# Fluid Gallery：给其他 Agent 的复现提示词

独立实现WebGL照片流与点击翻转全屏。Three.js/GSAP版本使用 ../../fluid-gallery-wall/ 下现有vendor文件；素材 assets/img-{num}.jpeg（相对该原案例目录），数据本目录images.json。可复用本目录index.html静态CSS/结构，不读旧JS。保留浅灰暖色横向背景渐变、圆角照片卡、全屏后左下元信息，glow/hud/hint/strip当前CSS隐藏。

## 布局与状态
renderer alpha/antialias，高性能，DPR<=1.75；正交相机(0,W,H,0,.1,1000)，z10。共用1×1的48×48细分Plane，每卡独立ShaderMaterial，transparent、depthTest/depthWrite false、DoubleSide。纹理先用accent一像素DataTexture占位，加载后sRGB、LinearFilter、无mipmap。每卡revealT从0到1，1.1秒back.out(1.5)、delay .09*i。其他初始morphT/hoverT=0。

base=min(W<760?.8W:H>W?.58W:min(460,max(280,.27W)),.74H/1.25)。下表每行[r,cx,cy,s,rot,opacity]：横屏[-2,.10,.06,.40,−12,0],[-1,.22,.25,.52,−9,1],[0,.47,.53,1,0,1],[1,.73,.69,.52,9,1],[2,.86,.88,.40,12,0]；竖屏[-2,.24,1.18,1,−32,0],[-1,.36,.92,1,−20,.18],[0,.50,.50,1,0,1],[1,.50,.42,.88,9,1],[2,.50,.37,.78,−8,.9],[3,.50,.335,.70,5,0]。

focus/smooth初始0，每帧smooth+=(focus−smooth)*.1；相对r=正模(i−smooth,N)，>N/2时减N。端点外夹到最外条目，内部用t²(3−2t)插值全部参数；cx/cy乘W/H，宽base*s、高1.25base*s。wheel累计deltaY*.0034；touch累计(旧Y−新Y)*.009，打开期间禁用。

时钟首帧dt=.016，后续min(.05,秒差)，累计clock。pointer归一化偏移(x/W−.5,y/H−.5)，仅未打开且inside有效，否则0，平滑.05。每卡hoverT+=(上一帧hover命中?1:0−hoverT)*.09（准确表达为(target−hoverT)*.09）。rev=revealT,entr=1−rev,m=morphT,grow=mix(.6,1,rev)，尺寸mix(slot.wh*grow,全屏wh,m)，relScale=slot.w/max(1,base)，par=(1−m)*rev；cx=mix(slot.cx,W/2,m)−30*px*relScale*par，cy=mix(slot.cy+entr*.08H,H/2,m)−30*py*relScale*par，rot=mix(slot.rot,0,m)+2.2*px*relScale*par。mesh位置(cx,H−cy,0)、scale(w,h,1)、rotation.z=−rotπ/180。打开项order100，其余横屏i、竖屏round(−10*r)。

uniforms：time=clock,hover=hoverT,morph=0（保留字段，不激活额外大幅变形），tilt=.42sin(mπ)+1.25entr，entr，size(w,h)，radius=(1−m³)*min(w,h)*.12；far=r<−.05?smoothstep(clamp((abs(r)−.25)/1)):0，blur=.02far*(1−m)+.06entr；opacity=打开项?1:slot.opacity*rev。默认hoverPt(.5,.5)、focus(.5,item.focusY??.5)、exposure=item.exposure??1、texAspect=imageW/H、tiltDir偶数1/奇数−1。

## 着色方程
顶点vUv=uv，p=position；ew=smoothstep(.1,1,max(abs(uv−.5)*2))，field=sin(uv.x*6.2831*.55+t*.7)*cos(uv.y*6.2831*.55−t*.55)*.55+sin((uv.x+uv.y)*6.2831*.4−t*.45)*.45；p.xy+=normalize(uv−.5+1e−4)*field*morph*.26*(.35+ew)。hd=distance(uv,hoverPt)，local=smoothstep(.4,0,hd)*hover；p.xy+=(uv−hoverPt)*sin(hd*40−t*5)*local*.06。tilt>.0001时先绕X角tilt*.28，再绕Y角tilt*tiltDir；p.xy乘1/(1−p.z*(.55+entr*.3))，z置0，最后投影矩阵。

片元cover：aspect=size.x/size.y，fill=smoothstep(.78,.55,aspect)，zoom=mix(1,clamp(texAspect/aspect*.55,1.2,1.95),fill)。宽幅时sy=(texAspect/aspect)/zoom,sx=1/zoom；否则sx=(aspect/texAspect)/zoom,sy=1/zoom。uv每轴=(vUv−.5)*scale+clamp(focus,.5scale,1−.5scale)。localHover=smoothstep(.4,0,distance(vUv,hoverPt))*hover；flow=(sin(vUv.y*22+t*2.2)+sin(vUv.y*9−t*1.3), cos(vUv.x*20−t*1.9)+cos(vUv.x*8+t))；uv+=flow*(localHover*.02+morph*.006)。blur<.0006仅采样中心，否则中心加8方向角i*.7853982、距离blur和blur*.5共17次采样除17。颜色=pow(max(color,0),1/exposure)。圆角SDF q=abs((vUv−.5)*size)−size*.5+radius，d=min(max(q.x,q.y),0)+length(max(q,0))−radius；aa=fwidth(d)+1，alpha=1−smoothstep(−aa,aa,d)，rim=smoothstep(−20,−1,d)−smoothstep(−1,10,d)，color+=rim*localHover*.6，输出alpha*opacity。

## 操作
命中忽略opacity<.4的卡，对点减中心、按−rot逆旋转，在w/h半宽内且renderOrder最高者胜出。每帧布局后再命中用于下一帧hover；hoverPt另按+rot旋转dx/dy，(.5+lx/w,.5−ly/h)夹0..1。pointerleave仅inside=false，不主动清hover，保持原反馈。

点击卡：busy或已有open时不重复打开；open=i,busy=true,hover=−1,order100,opacity1,tiltDir=−1；morphT→1，1.15秒power2.inOut；完成busy=false并填metadata(category/title/caption/location·year)，子元素从autoAlpha0/y26/blur12到1/0/blur0，.9秒power4.out/stagger.09/overwrite。点击全屏或Escape关闭（busy时忽略），元信息autoAlpha0/y14/blur8/.3秒power2.in，tiltDir=1，morphT→0/1秒power2.inOut，完成恢复order与open=−1/busy=false。清理GPU资源与动画/事件。

验收1440×1000、390×844，16ms固定帧：600ms入场、2800ms稳定、hover640ms、展开576ms/2176ms、关闭480ms/1880ms、wheel300后640ms、touch500→380后1000ms。运行 ../scripts/check-fluid-gallery.mjs；该测试比较全部几何、uniforms及元信息，另对18张采样截图做像素比较，当前全部一致。

## 本地图片与中英文（2026-09-21 更新）

本轮已接入本地公开图片和中英双语。复现时同时遵循 [共享规范](../../shared/README.md)：沿用当前本地图片路径，使用共享词典与语言偏好（`zh` / `en`），覆盖动态内容、辅助标签和 Canvas 文字；不要恢复旧的远程图片链接。中文拆字标题应先翻译再拆分，并保持原有动画机制。图片来源与替换映射在共享规范中列出。
