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

独立实现一个摄影作品集：全屏照片像相机光圈一样收合、换图、重新张开。使用本目录slides.json中的14张照片与文字，保持顺序、src、mono黑白标记。不调用旧页面JS、不嵌入iframe。实现清晰的enter→idle→close→open→idle状态机和独立几何渲染，不需要动画框架。

## 视觉

全屏100vh，overflowhidden，底色#08080a，径向80%70% at50%45%从#141419到#08080a75%。照片铺满object-fitcover；mono图使用grayscale(1) contrast(1.06)；照片上方linear-gradient(#0003,#0005)压暗。clip-path圆形裁切，另加SVG evenodd环作挡片，填#08080a。

中央文字上下居中、白色#f3f1ec、阴影0 1px 3px #0009与0 2px 44px #000b。eyebrow为Geist500 11px/1.5、大写、字距.34em；两行标题Playfair Display400 clamp(2.9rem,8.2vw,7.2rem)/.94、字距−.01em、上间距14.4px；城市年份11px Geist Mono、字距.18em、不强制大写、上间距17.6px、opacity.7。<640标题改clamp(2.5rem,12vw,4.8rem)。

中心有三条轨道圆，SVG viewBox−800 −800 1600 1600，半径795/541/296，stroke#ffffff57,width1.3；小圆半径9、fill#ffffffb3，坐标(−795,0),(795,0),(0,−296),(0,296)。轨道层z3，跟随光圈缩放。

左上30/26px显示portfolio®与两行STREETS & CITIES / SELECTED WORK；主字13px，sup8px，副字8px/.24em。右下30/28px两位计数，12px等宽。左下30/28px提示│ Scroll Down，12pxGeist、opacity.75。左右导航圆在垂直中央、距边44px、52×52，半透明玻璃底/细白边/内高光。手机<640距边12px、40×40；品牌left/top20px，底部左右20、底22。

## 光圈几何

open初始0，范围[0,1]。fullRadius=hypot(W,H)/2+24；r=fullRadius×clamp(open)，中心cx=W/2,cy=H/2。照片clip-path为circle(r px at cx px cy px)，r保留1位。easeOut(t)=1−(1−t)^3.2。照片scale=mix(1.12,1,easeOut(clamp(open)))，3位。文字copyIn=clamp((open−.5)/.45)，opacity=copyIn²(3−2copyIn)，scale=.985+.015copyIn，均3位，transform=translateY(−50%) scale(...)。

orbit scale=min(.4W,.64H)/795×(.5+.5open)，transform=translate(−50%,−50%) scale(...)，opacity=open。SVG挡片外圆半径fullRadius+40，内圆半径max(.5,r)，每圆用两段半圆路径拼合：从(cx−radius,cy)出发，A radius radius 0 1 0 到(cx+radius,cy)，再同样弧回起点并Z闭合，各数保留1位。两圆拼成同一个path，fill-ruleevenodd。open<.999时显示挡片并更新path，否则opacity0。resize立即重新计算。

## 时间与切图

初始enter持续1900ms，从0到1使用easeOut。每帧根据performance时间计算进度并渲染；完成后精确open1并进入idle。只有idle接受step(direction)。step进入close：从当前open到0，620ms，easeIn=t³。关闭达到终点的那一帧，将index正模(index+direction,14)，更新src/alt/mono与全部文字；立即进入open，从0到1持续2600ms、easeOut，完成后idle。切图必须在闭合处，不能提前交叉淡入。初始化预载全部14张，避免切换时闪白。

## 输入

next/右/下键step(+1)，prev/左/上键step(−1)。动画中忽略step，防止叠加。滚轮阻止默认；仅idle累积deltaY，每次有效输入重置160ms定时器，定时器清空sum并重新armed。armed且|sum|≥90时触发sum方向的step，armed=false且sum清0。

按下stage（排除nav）开始水平拖动、记录startX、dragFiredfalse；总|dx|超过阈值才触发一次：W<640阈值=.18W，其他230px；向左step(+1)，向右step(−1)；标记fired，不在同次拖动重复触发。pointerup/cancel清理drag与grabbing样式。

## 验收

1440×1000与390×844：初入900ms和2500ms，点击next后320ms关闭中、再1200ms张开中、再2100ms完成；应切到Zebra Lines且黑白。左键回到Night Shift；滚轮100再切下一张；水平划过阈值切到Blue Hour。验证照片、文字、计数、圆形clip、SVG环、图像呼吸和轨道同步，途中快速重复点击不跳帧或错序。无控制台异常或横向溢出。清理事件、定时器与rAF；后台暂停绘制。验证脚本 `rewrite/scripts/check-iris.mjs`；证据 `artifacts/rewrite-validation/iris/`。

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

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