# Aperture：可直接交给其他 Agent 的复现提示词

独立实现编辑风摄影墙，持续缓慢向上循环，滚轮/拖动时整墙沿竖直方向弯曲，停下恢复平面；点击照片打开详情。使用本目录works.json的全部数据与image，保持照片顺序、aspect、标题/说明/相机参数。禁止旧JS与iframe，拆分确定性布局、运动模型、渲染、详情状态。

## 静态视觉

背景#fafafa，文字#0a0a0a，Geist正文、Geist Mono辅助、详情Bebas Neue标题。全屏overflowhidden，stage touch-actionnone，grab/grabbing。wall全屏perspective1400px,preserve3d；照片圆角3px、无阴影、cover、filter saturate(.96) contrast(1.03)。仅右上28px提示Scroll · Click to open，10px等宽/.24em/opacity.5。顶部底部bar、品牌与总数保留节点但隐藏。

桌面W≥760，只显示前13张，以下每项[x/W,baseY/W,width/W,aspect]，height=width/aspect：
`[[-.02,.04,.3,.78],[.065,.47,.19,.8],[.05,.84,.22,.82],[.085,1.16,.15,.9],[.415,.1,.17,.78],[.44,.42,.12,.8],[.4,.6,.2,.85],[.425,.95,.15,.95],[.415,1.19,.17,.8],[.74,.02,.2,.78],[.74,.32,.2,.85],[.72,.72,.3,.8],[.76,1.12,.16,.8]]`
循环带高1.49W。注意x可为负，编辑构图有意露出屏幕边缘。

手机W<760显示全部，两列瀑布流。random(i,k)=fract(43758.5453sin((i+1)12.9898+7.233k))；两列当前高初始.08W；column=(W−.1W−.055W)/2。每张选较短列（相等选左），width=column×(.82+.18random(i,1))，height=width/作品aspect，x=.05W+col×(column+.055W)+(column−width)random(i,2)，baseY=当前列高；列高再加height+.08W×(.7+1.1random(i,3))。循环带高取最高列。resize重新布局。

## 运动与镜头弯曲

scroll/flick/boost/bow初始0。每帧非拖动时scroll−=(.35−flick)，flick*=min(.96,.9+.012boost)，|flick|<.01清0；boost*=.95，<.01清0。maxBow=.8×(手机?.6:1)，target=clamp(sign(flick)min(maxBow,.02|flick|),−maxBow,maxBow)；bow+=(target−bow)×.04；|bow|<.0006且target0则bow0。详情打开时暂停全部运动。

wall scale=1+.12bow，保留4位，注意使用有符号bow。隐藏bar高度=round(clamp(.068H,38,76)×(1+.3clamp(|flick|/150)))。

每照片repeat=round((H/2−(baseY+scroll))/带高)，y=baseY+repeat×带高+scroll。若y+height<−280或y>H+280则opacity0并跳过姿态更新。否则cy=y+height/2，t=(cy−H/2)/(H/2)，amount=|bow|，dir=bow≥0?1:−1，bend=t×amount×.36，curved=H/2+(cy−H/2)cos(|bend|)，z=−85dir×amount×t²，rx=−dir×bend×26。

transform=translate3d(x,curved−height/2,z) rotateX(rx)，x/y/rx2位、z1位；z-index=round(2000+z)，opacity1。循环移动是每张卡独立回卷，不是重建列表。

## 输入与详情

滚轮阻止默认，详情未打开时flick−=deltaY×.55、boost1。按下清flick，保存lastY、累计移动0，捕获指针；每次拖动scroll+=dy、flick=dy、累计|dy|。松开/cancel累计<6则elementFromPoint命中的照片打开详情。详情阻止滚轮/拖动。

详情全屏z200、#fafafa背景。桌面照片区left49%,right7%,top/bottom9.5%，无圆角/阴影，图片contain/max-height81vh；文案left4.5%,top10%,bottom6%,width37%。类别10px等宽、.24em、opacity.5；大写Bebas Neue标题clamp(48px,7.4vw,108px)/.84、margin24px0；介绍12px/max40ch/1.6/opacity.62。左栏底部两列相机信息、顶部细线、gap12，依次显示body、lens、焦距·光圈·快门·ISO。右上26/24处40px圆关闭钮。手机≤767照片左右20,top60,bottom48%，maxheight44vh；文案left24,top55%,bottom24,width calc(100%−48px)，overflowauto,padding-bottom85；标题46px/margin15，介绍11px，相机8px。

打开填入所选作品：scrim opacity0→1 .3s；shot opacity0/scale.94→1/1 .6s power3.out；meta直接子元素opacity0/y16→1/0，delay.1,duration.5,stagger.08,power3.out。关闭按钮/背景/Escape使整个zoom opacity0持续.28s，完成后displaynone、清除内联opacity、恢复墙运动。避免重复时间线和关闭重入。

初次作品加载后GSAP.fromTo所有卡opacity0/y60→1/y0，duration1s,stagger.03,power3.out，关闭lagSmoothing。保留数学动画归rAF的属性所有权，不能造成两套循环争夺位置。

## 验收

1440×1000、390×844；初始2800ms、滚轮240后180ms的弯曲、再1800ms的恢复、向上拖动、点击照片与Escape。比较每卡尺寸/transform/opacity、墙scale、图片内容与相机信息。已通过两种视口上述状态精确对照。生命周期清理事件、rAF、GSAP。脚本 `rewrite/scripts/check-aperture.mjs`，证据 `artifacts/rewrite-validation/aperture/`。

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

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