/* ============================================================
   第四页 Joe's Portfolio · 宝藏铁盒（开盖交互）
   设计画布 1920x1080（源素材 2560x1440，×0.75）
   布局由总体图模板匹配得出（layout4.json / reconstruct4.py）
   ============================================================ */

body.page4 .backdrop {
  background: url("../assets/img/p4_bg.jpg") center / cover no-repeat;
}

body.page4 .scene { width: 1920px; height: 1080px; }
/* 手账统一：以第一页手账渲染位置/大小为标准（内容整体仿射变换，内部相对布局不变） */
body.page4 .content { transform: translate(-97.72px, -15.39px) scale(1.0376847); transform-origin: 0 0; }

/* ---------------- 共享层 ---------------- */
.notebook4 { position: absolute; left: 379px; top: 158px; width: 1313px; z-index: 1; }

/* 胶卷三框视频位（在 ccd 图层之下，透过镂空框显示） */
.frame-video {
  position: absolute;
  z-index: 2;
  overflow: hidden;
  background: transparent;
}
.frame-video video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity .3s ease;
}
.frame-video.has-video video { opacity: 1; }
.frame-play {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0 0 0 2px;
  border: 2px solid #fffdf6;
  border-radius: 50%;
  background: rgba(156, 74, 58, .88);
  color: #fffdf6;
  cursor: pointer;
  box-shadow: 0 3px 10px rgba(0,0,0,.25);
  transition: opacity .25s ease, transform .2s ease;
}
.frame-play:hover { transform: translate(-50%, -50%) scale(1.1); }
.frame-video.playing .frame-play { opacity: 0; pointer-events: none; }
.frame-video:not(.has-video) .frame-play { display: none; }

/* 放大角标：**常显**，不藏起来。
   （第一版做成"hover 才浮出"，结果根本没人发现能放大 —— 入口看不见等于没有入口。）
   图标用实心四角块而不是细描边箭头 —— 整个场景会被等比缩放（1600×900 时只有 0.7 倍），
   描边细线缩完就糊成一团，实心色块缩小后仍然立得住。 */
.frame-zoom {
  position: absolute;
  right: 5px;
  top: 5px;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid rgba(255, 253, 246, .5);
  border-radius: 9px;
  background: rgba(46, 38, 28, .58);
  color: #fffdf6;
  cursor: pointer;
  opacity: .92;
  transition: opacity .2s ease, background .2s ease, scale .2s ease;
}
.frame-video.has-video:hover .frame-zoom,
.frame-zoom:focus-visible { opacity: 1; }
.frame-video.has-video:hover .frame-zoom { scale: 1.06; }
.frame-zoom:hover { background: rgba(156, 74, 58, .95); scale: 1.12; }
/* 视频被搬进浮层后框是空的，角标要藏起来，否则会变成"空框上浮着一枚放大标" */
.frame-video.zoomed .frame-zoom { opacity: 0; pointer-events: none; }
/* 触屏不会 hover，角标再放大一点，手指好点 */
@media (hover: none) {
  .frame-video.has-video .frame-zoom { width: 34px; height: 34px; }
}

.ccd4  { position: absolute; left: 512px; top: 245px; width: 424px; z-index: 3; pointer-events: none; }

/* ---------------- 状态切换（闭盖 ⇄ 开盖） ---------------- */
.state { transition: opacity .55s ease; }
.state .p4 { position: absolute; }
.state-open { opacity: 0; pointer-events: none; }
.scene.open .state-closed { opacity: 0; pointer-events: none; }
.scene.open .state-open { opacity: 1; pointer-events: auto; }

/* ---- 闭盖状态：新闭盖参考图右页整区（坐标 = 切图原点 ×0.75） ---- */
.closedbox { left: 1050px; top: 210px; width: 510px; height: 750px; z-index: 4; }
/* 口红与新参考图左页一致（与开盖态同位） */
.lipstick  { left: 134px;  top: 527px; width: 119px; z-index: 9; }

/* ============================================================
   铁盒轮廓光环组（脉冲 / 盒内暖光 / 相纸高光）
   几何参数由 p4_closed.jpg 像素级测量得出：
   图片内 铁盒边框 x 40~425.5、y 222~462.3、圆角 ≈57px。
   闭盖图为 1:1 映射，故 content 坐标 = 图片坐标 + 原点 (1050, 210)。
   ⚠️ 换掉 p4_closed.jpg 或改 .closedbox 尺寸后，这组数值要重新测。
   ============================================================ */
.state-closed, .state-open {
  --tin-x: 1090px;   /* 1050 + 40      */
  --tin-y: 432px;    /* 210 + 222      */
  --tin-w: 386px;    /* 425.5 - 40     */
  --tin-h: 241px;    /* 462.3 - 222    */
  --tin-r: 57px;
}

/* 盒内暖光呼吸：让闭盖的铁盒看起来"里面是活的" */
.tin-glow {
  position: absolute;
  left: var(--tin-x); top: var(--tin-y);
  width: var(--tin-w); height: var(--tin-h);
  border-radius: var(--tin-r);
  z-index: 5;
  pointer-events: none;
  background: radial-gradient(78% 72% at 50% 42%, rgba(255,250,232,.5), rgba(255,246,222,0) 72%);
  animation: tinBreath 4.6s ease-in-out infinite;
}
@keyframes tinBreath {
  0%, 100% { opacity: .14; }
  50%      { opacity: .36; }
}

/* 相纸高光斜扫：一道柔光每隔几秒从盒面上掠过 */
.tin-sheen {
  position: absolute;
  left: var(--tin-x); top: var(--tin-y);
  width: var(--tin-w); height: var(--tin-h);
  border-radius: var(--tin-r);
  z-index: 6;
  overflow: hidden;
  pointer-events: none;
}
.tin-sheen::after {
  content: '';
  position: absolute;
  top: -45%; bottom: -45%;
  left: -70%; width: 42%;
  background: linear-gradient(100deg,
    rgba(255,255,255,0) 0%,
    rgba(255,255,255,.3) 42%,
    rgba(255,255,255,.68) 50%,
    rgba(255,255,255,.3) 58%,
    rgba(255,255,255,0) 100%);
  transform: skewX(-14deg);
  opacity: 0;
  animation: tinSheen 6.4s ease-in-out 1.6s infinite;
}
@keyframes tinSheen {
  0%        { left: -70%; opacity: 0; }
  6%        { opacity: 1; }
  46%       { left: 128%; opacity: 1; }
  47%, 100% { left: 128%; opacity: 0; }
}

/* 铁盒轮廓脉冲：一圈暖金描边 + 两层错相位从轮廓向外扩出去的光环
   （纸面本身就是浅米色，纯白发光在上面几乎看不见，所以描边取暖金，
     靠明度差把"一圈"立起来，同时也贴合"宝藏"的调子） */
.tin-pulse {
  position: absolute;
  left: var(--tin-x); top: var(--tin-y);
  width: var(--tin-w); height: var(--tin-h);
  border-radius: var(--tin-r);
  z-index: 7;
  pointer-events: none;
  animation: tinEdge 2.8s ease-in-out infinite;
}
@keyframes tinEdge {
  0%, 100% {
    box-shadow: 0 0 0 1.5px rgba(240,203,134,.62), 0 0 14px 3px rgba(240,203,134,.22);
  }
  50% {
    box-shadow: 0 0 0 2.5px rgba(234,190,110,.95), 0 0 24px 9px rgba(240,203,134,.46);
  }
}
/* 两层扩散环：贴着轮廓边缘整圈往外推，边推边淡 */
.tin-pulse::before,
.tin-pulse::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  animation: tinRing 2.8s cubic-bezier(.24,.6,.36,1) infinite;
}
.tin-pulse::after { animation-delay: 1.4s; }
@keyframes tinRing {
  0%   { box-shadow: 0 0 0 2px rgba(238,196,120,.8); opacity: 1; }
  72%  { box-shadow: 0 0 0 26px rgba(238,196,120,0); opacity: .6; }
  100% { box-shadow: 0 0 0 34px rgba(238,196,120,0); opacity: 0; }
}

/* 闭盖点击热区（对齐铁盒轮廓，四周各外扩 24px 方便点击） */
.tin-hit {
  position: absolute;
  left: 1066px;
  top: 408px;
  width: 434px;
  height: 289px;
  z-index: 11;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
}

/* ---- 开盖状态元素 ---- */
.tinopen    { left: 1112px; top: 340px; width: 377px; z-index: 3; }
.heart      { left: 1131px; top: 363px; width: 152px; z-index: 4; }
.smallshell { left: 1229px; top: 510px; width: 50px;  z-index: 5; }
.mirror     { left: 1164px; top: 627px; width: 107px; z-index: 6; }
.clip       { left: 1120px; top: 689px; width: 256px; z-index: 7; }
.tape       { left: 1303px; top: 593px; width: 173px; z-index: 8; }
.girl2      { left: 1279px; top: 372px; width: 228px; z-index: 9; }
.bow2       { left: 1382px; top: 296px; width: 143px; z-index: 10; }
.shell2     { left: 1078px; top: 220px; width: 99px;  z-index: 11; }
.lipstick2  { left: 134px;  top: 527px; width: 119px; z-index: 10; }

/* 开盖点击热区（点击合盖） */
.tin-hit-open {
  position: absolute;
  left: 1092px;
  top: 320px;
  width: 417px;
  height: 516px;
  z-index: 12;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
}

/* ---------------- 轻量动效（手账质感：幅度小、节奏慢） ---------------- */
@keyframes floatC {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-8px) rotate(1.2deg); }
}
@keyframes floatD {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(6px) rotate(-1.6deg); }
}
/* 贴纸光泽呼吸：亮度/饱和度轻微起伏，像有光在贴纸上走 */
@keyframes glisten {
  0%, 100% { filter: brightness(1) saturate(1); }
  50%      { filter: brightness(1.12) saturate(1.14); }
}
/* 爱心贴纸的心跳 */
@keyframes heartbeat {
  0%, 100% { scale: 1; }
  11%      { scale: 1.1; }
  22%      { scale: 1; }
  33%      { scale: 1.065; }
  45%      { scale: 1; }
}
.lipstick, .lipstick2 { animation: floatC 6.5s ease-in-out infinite; }
.bow   { animation: floatD 7s ease-in-out .5s infinite; }
.bow2  { animation: floatD 7s ease-in-out .8s infinite; }
.shell, .shell2 { animation: floatC 8s ease-in-out 1s infinite; }

/* ---------------- 开盖：小物从盒里依次浮出 ---------------- */
/* 用独立的 scale / translate 属性，避开各自气浮动画占用的 transform */
.state-open .p4 {
  scale: .9;
  translate: 0 14px;
  transition: scale .62s cubic-bezier(.34,1.42,.52,1), translate .62s cubic-bezier(.34,1.42,.52,1);
}
.scene.open .state-open .p4 { scale: 1; translate: 0 0; }
/* 口红在闭盖态就已就位，不参与浮出，免得"跳一下" */
.state-open .lipstick2 { scale: 1; translate: 0 0; }

/* 错峰：铁盒先开，小物随后一件件冒出来（像从盒子里一样样拿出来） */
.scene.open .state-open .tinopen    { transition-delay:   0ms; }
.scene.open .state-open .girl2      { transition-delay: 110ms; }
.scene.open .state-open .bow2       { transition-delay: 240ms; }
.scene.open .state-open .shell2     { transition-delay: 300ms; }
.scene.open .state-open .clip       { transition-delay: 460ms; }
.scene.open .state-open .smallshell { transition-delay: 520ms; }
/* 这三个还带悬停反馈，delay 得按属性逐项给，别把悬停也一起拖慢 */
.scene.open .state-open .heart  { transition-delay: 180ms, 180ms, 0s, 0s; }
.scene.open .state-open .mirror { transition-delay: 350ms, 350ms, 0s, 0s; }
.scene.open .state-open .tape   { transition-delay: 400ms, 400ms, 0s, 0s; }

/* 落定之后的持续微动（起伏都很轻，页面才不吵） */
.state-open .girl2      { animation: floatC 11s ease-in-out .7s infinite; }
.state-open .tape       { animation: floatC 10s ease-in-out 1.3s infinite; }
.state-open .clip       { animation: floatD 9.5s ease-in-out 1.1s infinite; }
.state-open .heart      { animation: heartbeat 2.6s ease-in-out 1.1s infinite; }
.state-open .mirror     { animation: floatD 9s ease-in-out .9s infinite, glisten 6.4s ease-in-out 2s infinite; }
.state-open .shell2     { animation: floatC 8s ease-in-out 1s infinite, glisten 5.4s ease-in-out 2.4s infinite; }
.state-open .smallshell { animation: floatC 8.6s ease-in-out 1.5s infinite, glisten 5.8s ease-in-out 1.8s infinite; }

/* 悬停微反馈：rotate / filter 与气浮动画占用的 transform 互不干扰 */
.state-open .heart, .state-open .mirror, .state-open .tape {
  pointer-events: auto;
  transition: scale .62s cubic-bezier(.34,1.42,.52,1), translate .62s cubic-bezier(.34,1.42,.52,1),
              rotate .3s ease, filter .3s ease;
}
.state-open .heart:hover  { filter: drop-shadow(0 0 9px rgba(255,150,170,.85)); }
.state-open .mirror:hover { rotate: 3deg; }
.state-open .tape:hover   { rotate: -2.5deg; }

/* ---------------- 开盖瞬间：暖光从盒口升起 ---------------- */.tin-burst {
  position: absolute;
  left: var(--tin-x); top: var(--tin-y);
  width: var(--tin-w); height: var(--tin-h);
  border-radius: var(--tin-r);
  z-index: 20;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(58% 58% at 50% 56%, rgba(255,247,222,.95), rgba(255,240,205,0) 74%);
}
.scene.open .tin-burst { animation: tinBurst 1.15s ease-out .1s both; }
@keyframes tinBurst {
  0%   { opacity: 0;  transform: scale(.52); }
  22%  { opacity: .9; }
  100% { opacity: 0;  transform: scale(1.3); }
}

/* 看不见的那一层不必继续跑动画，省电也省性能 */
.scene.open .state-closed, .scene.open .state-closed *,
.scene.open .state-closed *::before, .scene.open .state-closed *::after,
.scene:not(.open) .state-open, .scene:not(.open) .state-open *,
.scene:not(.open) .state-open *::before, .scene:not(.open) .state-open *::after {
  animation-play-state: paused;
}

/* ============================================================
   闭盖态 · 鼠标触碰动效
   ⚠️ 全部用 hover 派生状态 + 可自由过渡的属性
      （scale / translate / rotate / filter / opacity），
      不碰 transform / width / height —— 那些要么和脉冲动画自身的 transform 打架，
      要么逼着浏览器每帧重算圆角矩形的阴影位图，卡顿很明显。
   ============================================================ */

/* ---- 1. 铁盒本体：靠近时整盒轻微抬起 + 纸面受光变亮 ---- */
.closedbox {
  transition: scale .55s cubic-bezier(.34,1.3,.5,1),
              translate .55s cubic-bezier(.34,1.3,.5,1),
              filter .5s ease;
}
.state-closed:has(.tin-hit:hover) .closedbox {
  scale: 1.016;
  translate: 0 -4px;
  filter: brightness(1.045) saturate(1.05);
}

/* ---- 2. 光环：靠近时脉冲提速一倍，更急地催促点击 ---- */
.state-closed .tin-pulse { animation-duration: 2.8s; }
.state-closed:has(.tin-hit:hover) .tin-pulse { animation-duration: 1.5s; }
.state-closed:has(.tin-hit:hover) .tin-pulse::before,
.state-closed:has(.tin-hit:hover) .tin-pulse::after { animation-duration: 1.5s; }
.state-closed:has(.tin-hit:hover) .tin-pulse::after  { animation-delay: .75s; }

/* ---- 3. 盒内暖光：越靠近越亮，像里面应了一声 ---- */
.state-closed .tin-glow { transition: opacity .4s ease; }
.state-closed:has(.tin-hit:hover) .tin-glow {
  animation-play-state: paused;
  opacity: .6;
}

/* ---- 4. 口红（左页）：靠近时轻轻浮起、偏个头 ---- */
.lipstick {
  transition: translate .5s cubic-bezier(.34,1.32,.5,1),
              rotate .5s cubic-bezier(.34,1.32,.5,1),
              filter .45s ease;
}
.state-closed:has(.tin-hit:hover) .lipstick {
  animation-play-state: paused;
  translate: 0 -9px;
  rotate: -4deg;
  filter: drop-shadow(0 10px 13px rgba(120,70,60,.3));
}

/* ---- 5. 键盘可达性：Tab 聚焦到铁盒时给同级反馈 ---- */
.state-closed:has(.tin-hit:focus-visible) .closedbox {
  scale: 1.016; translate: 0 -4px; filter: brightness(1.045);
}
.tin-hit:focus-visible {
  outline: 2px solid rgba(156,74,58,.75);
  outline-offset: 6px;
  border-radius: var(--tin-r);
}

/* 入场淡入（整页只做很短的一层，长淡入会把下面各素材的错峰层次糊掉） */
.scene { animation: sceneIn .34s ease both; }
@keyframes sceneIn { from { opacity: 0; } }

/* ---------------- 素材入场编排 ----------------
   机制与通用注意事项见 style.css 的「素材落位」一节。
   本页的素材不多，但有两个必须特殊处理的地方：

   1) 三个胶卷视频位 + ccd 贴图必须完全同步 ——
      视频是从 ccd 的镂空框里透出来的，两者若各自位移/缩放，
      画面就会从框里滑出去。所以只位移、不缩放（--ss: 1），并共用同一延迟。

   2) .state 是 0×0 的纯定位容器（子元素全是 position:absolute），
      对它用 scale / rotate 会绕 content 原点 (0,0) 缩放而整体漂移，
      所以这里只给 translate。
      更要紧的是：它的 opacity 已经被"开盖/合盖"的淡入淡出占用了，
      入场过渡里的 opacity 延迟必须留在 0s ——
      否则每次合盖都要先干等一次入场延迟，才开始淡出。 */
.frame-video, .ccd4 { --ss: 1; --sr: 0deg; }

.notebook4           { --d: 0s;   --sy: 18px;  --ss: .984; --sr: 0deg; }
.frame-video,
.ccd4                { --d: .30s; --sx: -18px; --sy: 0px; }

.content > .state {
  --d: .44s;
  --sy: 20px;
  --ss: 1;
  --sr: 0deg;
  transition:
    opacity   .55s ease 0s,                                  /* 留给开合切换，延迟必须 0 */
    translate var(--settle-dur) var(--settle-ease) var(--d, 0s);
}
@starting-style {
  /* 闭盖态：只从下方滑上来，opacity 起始值必须中和成 1 ——
     通用规则给的是 opacity:0，若照用，这里会和"开合切换"抢同一个过渡，
     合盖的淡出时序会被打乱。 */
  .content > .state-closed { opacity: 1; scale: 1; translate: 0 20px; rotate: 0deg; }
  /* 开盖态：起始值全部对齐静止值，入场期间不动它（它是隐藏的，没必要参与） */
  .content > .state-open   { opacity: 0; scale: 1; translate: 0 0;    rotate: 0deg; }
}

/* ---------------- 返回标签（与前页同款，不随场景缩放） ---------------- */
.back-chip {
  position: fixed;
  left: 22px;
  top: 20px;
  z-index: 50;
  display: inline-block;
  padding: 8px 16px;
  background: #fffdf6;
  border: 1px solid #e0d3bd;
  border-radius: 999px;
  box-shadow: 0 4px 14px rgba(0,0,0,.14);
  color: #9c4a3a;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  transition: transform .2s ease, box-shadow .2s ease;
}
.back-chip:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(0,0,0,.18); }

/* 悬停右下区域浮现"下一页"角标（与第二、三页同款的缩小版胶囊） */
.goto-page5 {
  position: absolute;
  left: 965px;    /* 手账本中缝右侧起 */
  top: 171px;
  width: 955px;   /* 延伸至画布右缘 */
  height: 909px;  /* 延伸至画布底缘 */
  z-index: 6;
  pointer-events: none; /* 不挡铁盒开盖交互 */
}
.goto-page5 .page-pill {
  position: absolute;
  right: 18px;
  bottom: 15px;
  padding: 5px 11px;
  background: rgba(255, 253, 246, .95);
  border: 1px solid #e0d3bd;
  border-radius: 999px;
  box-shadow: 0 3px 9px rgba(0,0,0,.14);
  color: #9c4a3a;
  font-size: 10.5px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity .22s ease, transform .22s ease;
  pointer-events: auto;
}
.goto-page5.hover .page-pill { opacity: 1; transform: translateY(0); }
.goto-page5 .page-pill:hover { background: #fffdf6; }
/* 触碰反馈：鼠标压到角标上时轻微放大，和铁盒的"可点"暗示保持一致 */
.goto-page5 .page-pill { transition: opacity .22s ease, transform .22s ease, scale .24s ease, box-shadow .24s ease; }
.goto-page5 .page-pill:hover { scale: 1.06; box-shadow: 0 6px 16px rgba(0,0,0,.2); }

/* 尊重系统"减少动态效果"设置 */
@media (prefers-reduced-motion: reduce) {
  .lipstick, .lipstick2, .bow, .bow2, .shell, .shell2,
  .scene, .state-open .p4, .state-open .girl2, .state-open .tape,
  .state-open .clip, .state-open .heart, .state-open .mirror,
  .state-open .shell2, .state-open .smallshell,
  .tin-glow, .tin-pulse, .tin-pulse::before, .tin-pulse::after,
  .tin-sheen::after, .tin-burst { animation: none; }
  .state-open .p4 { transition: none; scale: 1; translate: 0 0; }
  /* 停掉动效后，给铁盒留一圈静态柔光，别让它彻底失去"可点"的暗示 */
  .tin-glow { opacity: .22; }
  .tin-pulse { box-shadow: 0 0 18px 5px rgba(255,240,200,.35); }
  .tin-sheen::after, .tin-burst { opacity: 0; }
  /* 触碰反馈不必"动"，但状态变化要保留，否则用户不知道鼠标已经落在铁盒上 */
  .closedbox, .lipstick, .tin-glow, .goto-page5 .page-pill { transition: none; }
  .scene.open .state-open .p4 { transition-delay: 0s; }
  /* 「素材落位」入场走 transition，上面的 animation:none 关不掉它。
     .state 那条特异性比 `.content > *` 高，必须单独列出来才压得住。 */
  .content > *,
  .content > .state { transition: none; }
  .content > .state-closed { translate: 0 0; }
}
