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

独立实现18张摄影作品绕立轴旋转的 Rotunda。保持下面的照片、暗场色彩、尺寸、运动公式、详情布局和交互时间。不得加载旧JS或用iframe；按作品数据、几何/运动模型、详情状态、输入、渲染拆模块。连续动画只用一个rAF；GSAP只改变入场标量和有限UI时间线。

## 数据与画面

读取本目录 works.json 的18件作品，保持顺序和全部字段：title/tagline/photoId/tags/description/coords/camera/date/awards。图像URL模板 `https://images.unsplash.com/photo-{photoId}?w={w}&h={h}&fit=crop&crop=entropy&q={q}&auto=format`；卡片720×1008,q78；详情1440×2016,q85；相邻缩略图240×160,q70。需要联网加载这些照片，不替换为其他图片。

全屏100dvh，overflowhidden,touch-actionnone，grab/grabbing光标。背景从上至下 linear-gradient(#020413 0%,#03061a 53%,#07102e 67%,#12246a 82%,#2745b2 93%,#3c66dc 100%)。正文Geist，标签Geist Mono，标题Bodoni Moda italic400，卡片标题Playfair Display italic。

ring-scene全屏perspective1700px；ring left50%,top50%,preserve-3d，无自身perspective，transform translateY(−lift) rotateX(−14deg)。卡片圆角18px、无阴影、margin为负半宽高、图片cover。宽度断点与[cardW,cardH,radius,lift,titleY]：<380=[80,112,290,38,−72]；<640=[100,140,360,48,−95]；<1024=[124,174,430,60,−125]；<1440=[144,202,470,68,−165]；其他=[160,224,560,84,−190]。

中心标题translate(calc(−50% + .5vw),calc(−50% + titleY))；上行A selection of，11px/.42em/opacity.55/margin-bottom20；下行My Photographs，italic400 clamp(2.4rem,7.5vw,4.8rem)/1、字距−.02em、黑色柔影。<640上行9px/margin12。右下32px/36px显示⊙ drag · click to open，11px斜体Playfair/opacity.55，手机右12/底16。左下32px/60px有1px进度线，宽clamp(64px,18vw,92px)，其下11px/.32em SCROLL；手机左12/底39。原frontCopy与品牌作者节点存在但视觉隐藏。

## 环形状态与物理

rotation=0、velocity=0、spinDir=−1、clock=0、hovered=−1。releasedAt/lastTs初始performance.now。dt=min(50,now−lastTs)；非详情时clock+=dt。不拖动且不在详情时：rotation+=velocity，然后velocity*=.93；idle=now−releasedAt，超过400ms后rotation+=.07×spinDir×smoothstep(clamp((idle−400)/600))，smoothstep(t)=t²(3−2t)。rotation>720时减720，<−720时加720。保持60Hz逐帧阻尼节奏，不能擅自改成不同惯性。

入场标量intro从0，经5.5s power2.out到1.5，完成后明确设1.6。每卡grow=1−(1−clamp((intro−.105×min(i,18−i))/.45))³。原始角raw=20i+rotation；归一角到[−180,180]，away=绝对值。基础透明度：away<78时1；78…90时1−(away−78)/12×.6；90…180时.4−(away−90)/90×.28，最终opacity=clamp(基础值×grow)。

hover每帧+=((i==hovered?1:0)−hover)×.1。settled=grow>.95?1:0；phase=i/18×2π+.7π；t=.001clock；bob=2.5sin(.7t+phase)，bobScale=.005sin(.55t+1.3phase)。lift=14hover×settled+bob；scale=(.08+.92grow+bobScale)×(1+.06hover×settled)；实际半径=(radius+2.5min(48,|velocity|×2.5))×grow。

卡片transform严格为rotateY(raw) translateZ(实际半径) translateY(−lift) scale(scale)。角/Y保留2位，半径1位，scale/opacity3位。z-index=round((1−away/180)100)+round(200hover)；底部渐变cap opacity=hover，cap里显示title与tagline。进度线scaleX=正模(−rotation/360,1)保留4位。

选away最小卡为front；非详情且front变化时更新隐藏frontCopy，用opacity.45/y8→1/0，.42s power2.out。保持初始按序从中心向两侧展开的感觉，不要一次性显示整圈。

## 输入

垂直滚轮阻止默认：rotation+=deltaY×.06，velocity=deltaY×.06×.35，releasedAt=now。按下stage保存startX,lastX,lastTime，dragVelocity0,movedfalse，清空velocity，捕获指针。每次拖动rotation+=dx×.35；dt>0时dragVelocity=dx×.35/dt×16；离起点>6px标记moved。松开/取消：velocity=dragVelocity，releasedAt=now；|dragVelocity|>.05则spinDir=sign(dragVelocity)。未移动时命中卡打开详情。非拖动/非详情时，通过elementFromPoint寻找hover卡；离开stage清除hover。详情期间冻结clock与轮盘惯性，禁止新的拖动滚轮。

## 详情三列布局

打开后stage加viewing：中心标题opacity0，ring-scene CSS scale1.45、transition .7s；覆盖层z200。桌面三列均top36.7%、height49vh、圆角40：左奖项面板left13.8%,width22%,背景#f5f1e3、文字#625e52、padding30；中央照片left50%、translateX−50%、width25.7vw；右文案left64.2%,width22%,padding36px 28px，渐变玻璃底、blur24、#fff2细边。奖项显示HONORS、❧ Award Winning ❧和数据中的4组年份/名称/星级；右侧分类与日期8px，标题Playfair400大写clamp(24px,2.7vw,42px)/.96、margin-top35；描述12px/1.6；坐标/相机/日期8px，上细边。tags数据保留但视觉隐藏。右上关闭圆钮28px，right15%,top39%。

手机≤767：覆盖层#060b18a6与blur10；照片top8%,width70%,height44%,圆角24；隐藏奖项；文案left6%,top55%,width88%,height34%,padding20,圆角24；标题28px;margin-top12；描述11px；关闭right8%,top57%。

底部5%（手机4%）居中显示前后各1件相邻作品按钮，间距35px，只显示两位编号与作品名9px等宽，缩略图节点隐藏。打开时填入所有字段，照片alt=作品名：覆盖层opacity0→1 .35s power2.out；图片scale1.14→1持续1.4s power3.out；copy子元素opacity0/y22→1/0，delay.12,duration.6,stagger.07,power3.out；相邻按钮opacity0/x24→.55/0，delay.3,duration.5,stagger.06,power3.out。关闭按钮或Escape覆盖层淡出.3s power2.in，然后移除viewing/is-open并恢复轮盘。

点击相邻作品：先关闭、令rotation=−目标索引×20、front=−1，340ms后打开新作品。清理/取消重复的延时操作与时间线，不能在关闭后意外重新弹出。

## 验收

在1440×1000和390×844，等待18张照片与字体加载；比较入场1800ms、再过4600ms的自动旋转、滚轮240、横向拖动、点击作品详情。卡片半径、角度、浮动、淡出和图片顺序应匹配；详情文字与照片一致，相邻按钮切换作品，Escape回到轮盘。无横向溢出或控制台错误；检查照片请求失败时的可诊断性。离开时清理动画/事件/定时器，后台暂停rAF。验证脚本 `rewrite/scripts/check-rotunda.mjs`；证据 `artifacts/rewrite-validation/rotunda/`。

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

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