/* ============ 设计变量 ============ */
:root{
  --cream:#FBF4EE; --paper:#FFFAF6; --ink:#422F38; --soft:#80636D;
  --rose:#C96B82; --rose-deep:#A64C66; --gold:#D5A25E; --blush:#F4DCE1;
  --gold-lt:#EED49A; --gold-dk:#B78942; --champ:#EBD6A6;
  --dusk:#573346; --dusk-deep:#3E2434;
  --line:rgba(166,76,102,.16); --line-gold:rgba(213,162,94,.4);
  --spring:#86B178; --summer:#E09C56; --autumn:#CC764A; --winter:#899FB6;
  --serif:'LXGW WenKai Screen','LXGW WenKai','Kaiti SC','STKaiti','KaiTi','Songti SC','STSong','SimSun',serif;
  --sans:'LXGW WenKai Screen','LXGW WenKai','PingFang SC','Microsoft YaHei','Hiragino Sans GB',sans-serif;
  /* 花束（水彩玫瑰）在序幕里的高度上限：手机竖屏按视口高度走，桌面上放大一档 */
  --bq-h:min(58vh,560px);
}
@media (min-width:768px){:root{--bq-h:min(66vh,760px);}}
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent;}
html{scroll-behavior:smooth;}
/* 双击缩放防护：手机浏览器会把「同一位置快速点两下」当成放大 / 缩小，
   在锁屏、序幕这种整屏交互里非常出戏。touch-action:manipulation 只关掉双击缩放，
   滚动与双指捏合照常保留 —— 所以不采用 user-scalable=no 那种连无障碍缩放一起砍掉的做法。
   写在 #lock / #loader 上是给只认「被触摸元素自身」的老引擎兜底。 */
html,body,#lock,#loader{touch-action:manipulation;}
body{font-family:var(--sans);color:var(--ink);background:var(--cream);
  line-height:1.8;font-weight:400;overflow-x:hidden;
  /* 移动端长按不再弹出「复制/分享」菜单（长按蜡烛吹灭时最容易误触发） */
  -webkit-user-select:none;user-select:none;-webkit-touch-callout:none;}
body::before{content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  background:
   radial-gradient(circle at 12% 8%,rgba(237,208,143,.20),transparent 30%),
   radial-gradient(circle at 88% 20%,rgba(213,162,94,.15),transparent 32%),
   radial-gradient(circle at 18% 68%,rgba(201,107,130,.10),transparent 35%),
   radial-gradient(circle at 84% 90%,rgba(237,208,143,.16),transparent 30%);}
img{display:block;max-width:100%;}
button{font-family:inherit;}
a{color:inherit;text-decoration:none;}
.wrap{width:100%;max-width:760px;margin:0 auto;padding:0 22px;position:relative;}

/* 章节通用 */
section{padding:84px 0;position:relative;}
.sec-head{text-align:center;margin-bottom:46px;}
.sec-kicker{font-family:var(--serif);color:var(--gold-dk);font-size:15px;letter-spacing:.28em;
  font-weight:600;margin-bottom:14px;}
.sec-title{font-family:var(--serif);font-weight:700;font-size:30px;letter-spacing:.04em;
  color:var(--ink);text-wrap:balance;}
.sec-sub{color:var(--soft);font-size:14.5px;margin-top:14px;font-weight:300;}
.sec-head::after{content:"";display:block;width:190px;height:18px;margin:22px auto 0;
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 24'%3E%3Cpath d='M6 12h86M148 12h86' stroke='%23D5A25E' stroke-width='1.2' stroke-linecap='round' opacity='.85'/%3E%3Cpath d='M120 4l9 8-9 8-9-8z' fill='none' stroke='%23D5A25E' stroke-width='1.3'/%3E%3Ccircle cx='120' cy='12' r='2.3' fill='%23D5A25E'/%3E%3Cpath d='M98 12c5-6 12-6 16 0M126 12c4 6 11 6 16 0' stroke='%23D5A25E' fill='none' stroke-width='1' opacity='.7'/%3E%3C/svg%3E") center/contain no-repeat;}

/* 滚动揭示 */
.reveal{opacity:0;transform:translateY(28px);transition:opacity .9s cubic-bezier(.22,1,.36,1),
  transform .9s cubic-bezier(.22,1,.36,1);}
.reveal.in{opacity:1;transform:none;}

/* ============ HERO ============ */
.hero{height:100vh;height:100svh;min-height:560px;padding:0;position:relative;
  display:flex;align-items:center;justify-content:center;overflow:hidden;}
.hero-bg{position:absolute;inset:0;background:url('../assets/hero.jpg') center 30%/cover no-repeat;}
/* 开场视频（可选）：填了 CONFIG.heroVideo 才会淡入显示，未填时保持用 hero.jpg */
.hero-video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transition:opacity 1.4s ease;pointer-events:none;}
.hero-video.on{opacity:1;}
.hero-mask{position:absolute;inset:0;
  background:linear-gradient(to bottom,rgba(60,30,40,.28) 0%,rgba(120,60,80,.18) 42%,
  rgba(70,35,50,.55) 100%);}
#petals{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;}
.hero-inner{position:relative;z-index:2;text-align:center;color:#fff;padding:0 26px;width:100%;}
.hero-pre{font-family:var(--serif);font-size:15px;letter-spacing:.34em;font-weight:500;color:#F6E6BD;
  opacity:0;animation:fadeUp .9s .15s forwards;text-shadow:0 2px 14px rgba(60,20,35,.5);}
.hero-name{font-size:14px;letter-spacing:.2em;margin-top:18px;opacity:0;font-weight:300;color:#FBF1D8;
  animation:fadeUp .9s .35s forwards;text-shadow:0 2px 12px rgba(60,20,35,.5);}
.hero-title{font-family:var(--serif);font-weight:900;font-size:64px;letter-spacing:.1em;
  margin:16px 0 8px;line-height:1.1;opacity:0;
  background:linear-gradient(105deg,#FFF7E2 0%,#F2D78E 22%,#FFFDF4 42%,#E3BE72 62%,#F8E6B4 82%,#FFF7E2 100%);
  background-size:220% auto;-webkit-background-clip:text;background-clip:text;color:transparent;
  filter:drop-shadow(0 5px 20px rgba(120,70,20,.5));
  animation:fadeUp 1s .5s forwards,shine 5.5s 1.6s linear infinite;}
.hero-date{font-family:var(--serif);font-size:15px;letter-spacing:.5em;margin-left:.5em;color:#F4E0B0;
  opacity:0;animation:fadeUp .9s .7s forwards;font-weight:600;
  text-shadow:0 2px 12px rgba(60,20,35,.5);}
/* 倒计时 */
.countdown{display:flex;justify-content:center;gap:12px;margin:38px auto 0;max-width:380px;
  opacity:0;animation:fadeUp 1s .9s forwards;}
.cd-cell{flex:1;background:linear-gradient(160deg,rgba(92,46,64,.44),rgba(48,24,38,.38));
  border:1px solid rgba(238,212,154,.55);border-radius:16px;padding:15px 4px 13px;backdrop-filter:blur(6px);
  box-shadow:inset 0 1px 0 rgba(255,240,200,.35),0 10px 26px rgba(40,15,30,.28);}
/* 实色兜底：任何浏览器都能看见 */
.cd-num{font-family:var(--serif);font-size:30px;font-weight:700;line-height:1;
  font-feature-settings:'tnum';color:#FDEBC4;text-shadow:0 2px 12px rgba(255,214,140,.32);}
/* 渐变文字只在支持 background-clip:text 的浏览器启用。
   注意：翻牌会把数字包进 .odo 子元素，子元素会继承 color:transparent 却继承不到背景，
   所以必须把同一组声明也应用到 .odo/.odo-cur/.odo-new，否则数字整个消失。 */
@supports ((-webkit-background-clip:text) or (background-clip:text)){
  .cd-num,.cd-num .odo,.cd-num .odo-cur,.cd-num .odo-new{
    background:linear-gradient(#FFF8E0,#E4C17F);
    -webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:none;}
}
.cd-label{font-size:12px;letter-spacing:.2em;margin-top:8px;color:#F0DDA8;font-weight:400;}
.cd-today{font-family:var(--serif);font-size:24px;font-weight:700;letter-spacing:.2em;margin-top:34px;
  opacity:0;animation:fadeUp 1s .9s forwards;}
.hero-scroll{position:absolute;bottom:30px;left:50%;transform:translateX(-50%);z-index:2;
  color:#fff;font-size:12.5px;letter-spacing:.24em;font-weight:300;opacity:0;animation:fade 1s 1.4s forwards;
  display:flex;flex-direction:column;align-items:center;gap:9px;}
.hero-scroll svg{animation:bob 1.8s ease-in-out infinite;}
@keyframes fadeUp{from{opacity:0;transform:translateY(26px);}to{opacity:1;transform:none;}}
@keyframes fade{to{opacity:1;}}
@keyframes bob{0%,100%{transform:translateY(0);}50%{transform:translateY(7px);}}
@keyframes shine{to{background-position:-220% center;}}

/* ============ 告白信 ============ */
.words{background:var(--cream);}
.letter{background:linear-gradient(180deg,#FFFDF9,var(--paper));border-radius:20px;padding:44px 32px 36px;
  box-shadow:0 22px 60px rgba(120,60,80,.14),inset 0 1px 0 #fff;border:1px solid var(--line-gold);
  position:relative;overflow:hidden;}
.letter::before{content:"";position:absolute;top:22px;left:22px;right:22px;bottom:22px;
  border:1px solid rgba(213,162,94,.45);border-radius:12px;pointer-events:none;}
.letter::after{content:"";position:absolute;top:13px;right:13px;width:48px;height:48px;opacity:.75;
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath d='M4 4h15M4 4v15' stroke='%23D5A25E' stroke-width='1.2' fill='none'/%3E%3Cpath d='M15 4c0 8-6 11-11 11' stroke='%23D5A25E' fill='none' stroke-width='1' opacity='.8'/%3E%3Ccircle cx='4' cy='4' r='1.8' fill='%23D5A25E'/%3E%3C/svg%3E") center/contain no-repeat;pointer-events:none;}
.letter h3{font-family:var(--serif);font-size:21px;font-weight:700;margin-bottom:22px;color:var(--rose-deep);}
.letter p{font-size:15.5px;font-weight:300;margin-bottom:18px;color:#57404A;text-align:justify;}
.letter .sign{text-align:right;font-family:var(--serif);color:var(--rose-deep);font-weight:600;
  margin-top:24px;font-size:15px;}

/* ============ 照片墙 ============ */
.photos{background:linear-gradient(180deg,#F7E9E4 0%,var(--cream) 100%);}
.photo-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;}
.photo-grid figure{position:relative;border-radius:17px;padding:3px;cursor:pointer;
  background:linear-gradient(150deg,#F4E3B4,#C99B52 55%,#EBD49A);
  box-shadow:0 12px 30px rgba(120,60,80,.18);}
.photo-grid img{width:100%;aspect-ratio:1/1;object-fit:cover;border-radius:14px;
  transition:transform .6s cubic-bezier(.22,1,.36,1);}
.photo-grid figure:active img{transform:scale(1.06);}
.photo-grid figcaption{position:absolute;left:3px;right:3px;bottom:3px;border-radius:0 0 14px 14px;
  padding:24px 12px 10px;color:#FBF3DC;font-size:12px;letter-spacing:.14em;font-weight:400;
  background:linear-gradient(to top,rgba(60,25,20,.72),transparent);}
/* lightbox */
.lightbox{position:fixed;inset:0;z-index:60;background:rgba(35,18,28,.92);
  display:none;align-items:center;justify-content:center;padding:26px;}
.lightbox.open{display:flex;}
.lightbox img,.lightbox video{max-width:100%;max-height:82vh;border-radius:14px;border:2px solid rgba(238,212,154,.6);
  box-shadow:0 20px 60px rgba(0,0,0,.5);}
.lightbox video{background:#000;}
.lb-close{position:absolute;top:22px;right:22px;width:42px;height:42px;border-radius:50%;
  background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.25);display:flex;
  align-items:center;justify-content:center;cursor:pointer;}
.lb-cap{position:absolute;bottom:34px;left:0;right:0;text-align:center;color:#fff;font-size:13px;
  letter-spacing:.16em;font-weight:300;}

/* ============ 四季时间线 ============ */
.timeline{background:var(--cream);position:relative;overflow:hidden;transition:background-color 1.6s ease;}
.timeline.sp{background-color:#F4F7EE;}
.timeline.su{background-color:#FDF5E3;}
.timeline.au{background-color:#FCEEE2;}
.timeline.wi{background-color:#EDF1F6;}
#seasons{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:0;}
.timeline .wrap{z-index:1;}
/* 竖版四季长卡：一条竖轴串起四张 3:4 大图，季节字压在图上，顺序 春→夏→秋→冬 */
/* --ax：竖轴中心线距 .tl 左边缘的距离；轴和圆点都按它算，保证严格同心 */
.tl{--ax:9px;position:relative;max-width:400px;margin:0 auto;padding:8px 0 8px 40px;}
/* 竖轴：从第一颗圆点贯穿到最后一张卡 */
.tl::before{content:"";position:absolute;left:calc(var(--ax) - 1px);top:16px;bottom:16px;width:2px;border-radius:2px;
  background:linear-gradient(180deg,rgba(213,162,94,.9) 0%,rgba(213,162,94,.35) 55%,rgba(213,162,94,.08) 100%);}
.tl-item{position:relative;}
.tl-item+.tl-item{margin-top:34px;}
/* 圆点在 .tl-item 里，而 .tl-item 的左边缘 = .tl 左边缘 + 40px 内边距 → 减掉 40 再减半个圆点(7.5) */
.tl-dot{position:absolute;left:calc(var(--ax) - 47.5px);top:12px;width:15px;height:15px;border-radius:50%;border:3px solid;
  z-index:2;background:radial-gradient(circle at 35% 30%,#FFF8E0,#E2BE72);
  box-shadow:0 0 0 2px rgba(255,255,255,.6),0 0 14px rgba(228,193,127,.85);}
.tl-card{background:linear-gradient(180deg,#FFFDF9,var(--paper));border-radius:18px;overflow:hidden;
  border:1px solid var(--line-gold);box-shadow:0 18px 44px rgba(120,60,80,.14);}
.tl-fig{position:relative;aspect-ratio:3/4;overflow:hidden;background:#151013;}
.tl-fig img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 1.2s cubic-bezier(.22,1,.36,1);}
.tl-item.in .tl-fig img{transform:scale(1.05);}
/* 图上一层轻渐变，保证季节大字在亮图上也不糊 */
.tl-fig::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(24,12,18,.44) 0%,rgba(24,12,18,0) 40%,rgba(24,12,18,.26) 100%);}
/* 季节大字压在照片上：多层阴影 + 一圈同色描边，保证在明亮/杂乱的照片上也立得住 */
.tl-season{position:absolute;left:18px;top:12px;z-index:2;font-family:var(--serif);font-weight:700;
  font-size:clamp(44px,13vw,58px);line-height:1;
  -webkit-text-stroke:1.5px rgba(28,14,20,.42);
  text-shadow:0 2px 4px rgba(24,12,18,.85),0 6px 22px rgba(24,12,18,.7),0 0 42px rgba(24,12,18,.5);}
.tl-body{padding:20px 22px 22px;}
.tl-body h4{font-family:var(--serif);font-size:18px;font-weight:700;margin-bottom:9px;letter-spacing:.02em;}
.tl-body p{font-size:14.5px;font-weight:300;color:#654B54;line-height:1.95;}
.s-spring{color:var(--spring);}.s-summer{color:var(--summer);}
.s-autumn{color:var(--autumn);}.s-winter{color:var(--winter);}
.d-spring{border-color:var(--spring);}.d-summer{border-color:var(--summer);}
.d-autumn{border-color:var(--autumn);}.d-winter{border-color:var(--winter);}

/* ============ 结尾许愿 ============ */
.wish{background:linear-gradient(180deg,var(--dusk) 0%,var(--dusk-deep) 100%);color:#FBEFF2;
  text-align:center;overflow:hidden;}
.wish .sec-kicker{color:var(--gold);}
.wish .sec-title{background:linear-gradient(105deg,#FFF7E2,#F2D78E 28%,#FFFDF4 50%,#E3BE72 72%,#FFF7E2);
  background-size:220% auto;-webkit-background-clip:text;background-clip:text;color:transparent;
  animation:shine 5s linear infinite;filter:drop-shadow(0 3px 14px rgba(180,130,40,.5));}
.cake-wrap{position:relative;width:252px;height:252px;margin:10px auto 32px;
  display:flex;align-items:center;justify-content:center;}
.cake{width:218px;height:218px;border-radius:50%;object-fit:cover;
  box-shadow:0 18px 50px rgba(0,0,0,.45);border:3px solid rgba(245,210,160,.55);}
.cake-wrap::before{content:"";position:absolute;inset:2px;border-radius:50%;
  border:1.5px dashed rgba(238,212,154,.6);animation:spin 24s linear infinite;}
.cake-wrap::after{content:"";position:absolute;inset:-14px;border-radius:50%;
  background:repeating-conic-gradient(rgba(240,216,150,.32) 0deg 1.4deg,transparent 1.4deg 14deg);
  -webkit-mask:radial-gradient(circle,transparent 60%,#000 61%);mask:radial-gradient(circle,transparent 60%,#000 61%);
  animation:spin 36s linear infinite reverse;}
.wish-btn{position:relative;overflow:hidden;display:inline-block;
  background:linear-gradient(135deg,#E7C884,#C88F49);color:#fff;
  font-family:var(--serif);font-weight:600;font-size:16px;letter-spacing:.18em;padding:15px 44px;
  border-radius:40px;border:none;cursor:pointer;box-shadow:0 14px 34px rgba(213,162,94,.4);}
.wish-btn::before{content:"";position:absolute;top:0;left:-60%;width:42%;height:100%;
  background:linear-gradient(105deg,transparent,rgba(255,255,255,.75),transparent);
  transform:skewX(-20deg);animation:sweep 3.4s ease-in-out infinite;}
.wish-btn:active{transform:scale(.97);}
@keyframes spin{to{transform:rotate(360deg);}}
@keyframes sweep{0%,55%{left:-60%;}100%{left:140%;}}
.wish-bless{max-width:520px;margin:34px auto 0;opacity:0;max-height:0;overflow:hidden;
  transition:opacity 1s ease,max-height 1s ease;}
.wish-bless.show{opacity:1;max-height:260px;}
.wish-bless p{font-family:var(--serif);font-size:18px;font-weight:600;line-height:2;margin-bottom:10px;color:var(--gold-lt);}
.wish-bless .small{font-size:14px;font-weight:300;opacity:.85;font-family:var(--sans);}
.wish-foot{margin-top:40px;font-size:14px;letter-spacing:.16em;font-weight:300;opacity:.8;}
.again{display:inline-flex;align-items:center;margin-top:22px;font-size:13px;letter-spacing:.18em;color:var(--gold);
  border:1px solid rgba(213,162,94,.5);border-radius:30px;padding:11px 28px;min-height:44px;cursor:pointer;background:transparent;}
#confetti{position:fixed;inset:0;pointer-events:none;z-index:70;}
/* 文字烟花浮层：固定在视口，保证拼字严格居中（层级低于照片大图 60） */
#fwText{position:fixed;inset:0;width:100%;height:100%;pointer-events:none;z-index:58;}
.footer{background:var(--dusk-deep);color:rgba(255,255,255,.55);text-align:center;padding:26px 0 34px;
  font-size:12px;letter-spacing:.14em;font-weight:300;}
.footer svg{vertical-align:-3px;margin:0 5px;}

/* ============ 桌面增强 ============ */
@media(min-width:680px){
  .hero-title{font-size:84px;}
  .sec-title{font-size:35px;}
  .photo-grid{grid-template-columns:repeat(3,1fr);gap:16px;}
  .photo-grid img{aspect-ratio:1/1;}
  .tl{max-width:440px;}
  .tl-season{font-size:60px;}
  .tl-body{padding:22px 26px 24px;}
  .letter{padding:52px 56px 46px;}
}
/* ===== 复杂特效版 新增 ===== */
/* Loading 序幕 */
#loader{position:fixed;inset:0;z-index:100;display:flex;flex-direction:column;align-items:center;
  justify-content:center;background:radial-gradient(circle at 50% 35%,#6E3F54,#3C2333 75%);
  transition:opacity .8s ease,visibility .8s;}
#loader.hide{opacity:0;visibility:hidden;}
/* 礼物盒背景视频 + 遮罩（giftVideo 生效时显示，失败自动退回渐变底色） */
#giftVideo{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;
  opacity:0;transition:opacity 1.4s ease;pointer-events:none;}
#giftVideo.on{opacity:1;}
.gift-mask{position:absolute;inset:0;z-index:1;pointer-events:none;
  background:radial-gradient(ellipse at 50% 42%,rgba(30,16,26,.30) 0%,rgba(16,10,20,.68) 55%,rgba(10,6,14,.88) 100%);}
#loader.has-video{background:#160C16;}
.loader-ring{position:relative;width:118px;height:118px;}
.loader-ring::before{content:"";position:absolute;inset:0;border-radius:50%;border:2px solid transparent;
  border-top-color:var(--gold-lt);border-right-color:var(--gold);animation:spin 1.6s linear infinite;}
.loader-ring::after{content:"";position:absolute;inset:14px;border-radius:50%;border:1.5px dashed rgba(238,212,154,.6);
  animation:spin 9s linear infinite reverse;}
.loader-heart{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;}
.loader-text{margin-top:30px;font-family:var(--serif);color:#F3E3BC;letter-spacing:.4em;font-size:15px;
  font-weight:500;opacity:0;animation:fadeUp 1s .4s forwards;}
.loader-sub{margin-top:12px;color:rgba(243,227,188,.7);font-size:11px;letter-spacing:.3em;opacity:0;
  animation:fadeUp 1s .7s forwards;}
.loader-skip{position:absolute;bottom:30px;right:26px;color:rgba(243,227,188,.8);font-size:12px;
  letter-spacing:.2em;border:1px solid rgba(238,212,154,.5);border-radius:30px;padding:9px 20px;
  background:transparent;cursor:pointer;min-height:40px;}
/* 顶部滚动进度条 */
#progress{position:fixed;top:0;left:0;height:3px;width:0;z-index:90;
  background:linear-gradient(90deg,#E7C884,#FBEFC4,#C99B52);box-shadow:0 0 10px rgba(228,193,127,.8);}
/* 右侧章节导航 */
#navdots{position:fixed;right:10px;top:50%;transform:translateY(-50%);z-index:80;display:flex;
  flex-direction:column;gap:15px;}
.nav-dot{width:9px;height:9px;border-radius:50%;border:1px solid var(--gold-dk);background:transparent;
  cursor:pointer;padding:0;position:relative;transition:all .3s;}
.nav-dot::before{content:"";position:absolute;inset:-11px;}
.nav-dot.active{background:var(--gold);box-shadow:0 0 9px rgba(228,193,127,.9);transform:scale(1.3);}
.nav-dot span{position:absolute;right:18px;top:50%;transform:translateY(-50%);white-space:nowrap;
  font-size:11px;color:#fff;background:rgba(70,40,55,.88);padding:3px 9px;border-radius:8px;
  opacity:0;pointer-events:none;transition:opacity .25s;}
.nav-dot:hover span{opacity:1;}
/* 音乐按钮 */
#music{position:fixed;top:13px;left:12px;z-index:80;width:44px;height:44px;border-radius:50%;
  background:rgba(255,250,246,.16);border:1px solid rgba(238,212,154,.5);display:flex;align-items:center;
  justify-content:center;cursor:pointer;}
#music.playing svg{animation:spin 4s linear infinite;}
/* 音乐还没起来时，按钮轻微呼吸提示可点 */
#music.hint{animation:musicHint 1.8s ease-in-out infinite;}
@keyframes musicHint{0%,100%{transform:scale(1);box-shadow:0 0 0 0 rgba(231,200,132,.5);}
  50%{transform:scale(1.08);box-shadow:0 0 0 12px rgba(231,200,132,0);}}
.music-tip{position:fixed;top:60px;left:13px;z-index:80;color:#E9D8AE;font-size:11px;
  background:rgba(50,28,40,.85);padding:5px 10px;border-radius:8px;display:none;}
/* 点击爱心 */
.tap-heart{position:fixed;pointer-events:none;z-index:95;width:18px;height:18px;}
@keyframes tapFloat{to{transform:translateY(-70px) scale(1.3);opacity:0;}}
/* 相恋时光 */
.love{background:linear-gradient(180deg,var(--cream),#F6E7E2);text-align:center;}
.love-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:9px;max-width:480px;margin:0 auto;}
.love-cell{background:linear-gradient(170deg,#FFFDF9,#FBEFEA);border:1px solid var(--line-gold);
  border-radius:15px;padding:17px 4px;box-shadow:0 10px 24px rgba(120,60,80,.1);}
.love-num{font-family:var(--serif);font-size:23px;font-weight:700;color:var(--rose-deep);
  font-feature-settings:'tnum';line-height:1;}
.love-label{font-size:11px;letter-spacing:.15em;color:var(--soft);margin-top:8px;}
.love-note{margin-top:26px;font-family:var(--serif);color:var(--rose-deep);font-size:15px;letter-spacing:.06em;}
/* 下一个特殊节点（纪念日）提示，由 CONFIG.milestones 驱动 */
.love-next{margin-top:14px;font-size:13px;letter-spacing:.14em;color:var(--gold-dk);opacity:.92;}
.love-next:empty{display:none;}
/* 照片3D翻转 */
.flip{perspective:1100px;}
.flip-inner{position:relative;width:100%;transform-style:preserve-3d;
  transition:transform .8s cubic-bezier(.22,1,.36,1);}
.flip.flipped .flip-inner{transform:rotateY(180deg);}
.flip-face{backface-visibility:hidden;-webkit-backface-visibility:hidden;}
.flip-front{position:relative;border-radius:14px;overflow:hidden;z-index:2;}
.flip-front img{width:100%;aspect-ratio:1/1;object-fit:cover;border-radius:14px;}
.flip-back{position:absolute;inset:0;transform:rotateY(180deg);border-radius:14px;overflow:hidden;
  background:linear-gradient(160deg,#B85E78,#7E3F56);display:flex;flex-direction:column;align-items:center;
  justify-content:center;padding:18px;text-align:center;visibility:hidden;}
.flip.flipped .flip-front{visibility:hidden;}
.flip.flipped .flip-back{visibility:visible;}
.flip-back p{font-family:var(--serif);color:#FBEED1;font-size:15px;line-height:1.9;font-weight:500;}
.flip-hint{position:absolute;top:7px;right:7px;background:rgba(60,25,40,.55);color:#F3E3BC;font-size:10px;
  letter-spacing:.12em;padding:3px 8px;border-radius:20px;}
.flip-zoom{position:absolute;top:7px;left:7px;width:30px;height:30px;border-radius:50%;background:rgba(60,25,40,.55);
  display:flex;align-items:center;justify-content:center;cursor:pointer;border:none;}
.flip-zoom::before{content:"";position:absolute;inset:-8px;}
/* 结尾烟花 */
.wish-hint{margin-top:18px;font-size:12.5px;color:rgba(243,227,188,.72);letter-spacing:.1em;font-weight:300;}
.firework-btn{display:inline-block;margin:8px 6px 0;font-size:12.5px;color:var(--gold-lt);
  border:1px solid rgba(238,212,154,.5);border-radius:30px;padding:9px 20px;background:transparent;
  cursor:pointer;min-height:44px;}

/* ================= iPhone 解锁界面 ================= */
.lock{position:fixed;inset:0;z-index:200;display:flex;flex-direction:column;align-items:center;
  color:#fff;font-family:var(--sans);user-select:none;-webkit-touch-callout:none;overflow:hidden;
  transition:opacity .6s ease,transform .6s cubic-bezier(.3,.8,.4,1);}
.lock-bg{position:absolute;inset:0;background:url('../assets/lock.jpg') center/cover no-repeat;transform:scale(1.02);}
.lock-bg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(0,0,0,.10) 0%,rgba(0,0,0,0) 26%,rgba(0,0,0,0) 58%,rgba(0,0,0,.46) 100%);}
/* 顶部状态栏：小锁居中，右侧信号 / Wi-Fi / 电量（还原 iPhone） */
.lock-status{position:relative;z-index:2;width:100%;display:flex;justify-content:flex-end;align-items:center;
  padding:12px 24px 0;gap:6px;}
.ls-lock{position:absolute;left:50%;top:12px;transform:translateX(-50%);opacity:.95;}
.ls-right{display:flex;align-items:center;gap:6px;text-shadow:0 1px 8px rgba(0,0,0,.35);}
.ls-pct{font-size:13.5px;font-weight:500;color:#34C759;min-width:20px;text-align:right;}
.ls-batt{position:relative;width:26px;height:13px;border:1px solid rgba(255,255,255,.65);border-radius:4px;display:inline-block;}
.ls-batt::after{content:"";position:absolute;right:-3.5px;top:3.5px;width:2px;height:4.5px;border-radius:1px;background:rgba(255,255,255,.65);}
.ls-batt i{position:absolute;left:1.5px;top:1.5px;bottom:1.5px;width:50%;min-width:3px;border-radius:1.5px;background:#34C759;display:block;transition:width .3s,background .3s;}
/* 时钟区：日期 + 超细大时钟，参考截图还原 */
.lock-clock{position:relative;z-index:1;margin-top:8vh;text-align:center;
  transition:transform .5s cubic-bezier(.3,.8,.4,1),opacity .4s ease;}
.lock-batt{font-size:15px;font-weight:500;color:rgba(255,255,255,.95);text-shadow:0 1px 12px rgba(0,0,0,.4);}
.lock-date{margin-top:6px;font-size:16.5px;font-weight:500;letter-spacing:.02em;color:rgba(255,255,255,.95);
  text-shadow:0 1px 14px rgba(0,0,0,.4);}
.lock-time{font-size:90px;line-height:1.02;font-weight:200;letter-spacing:-.015em;margin-top:0;
  font-variant-numeric:tabular-nums;text-shadow:0 2px 26px rgba(0,0,0,.38);}
/* 「向上轻扫以打开」提示；呼出键盘后淡出 */
.lock-swipe{position:relative;z-index:1;margin:auto auto 108px;display:flex;flex-direction:column;align-items:center;gap:9px;
  font-size:13.5px;font-weight:500;color:rgba(255,255,255,.88);text-shadow:0 1px 10px rgba(0,0,0,.45);
  transition:opacity .3s ease;}
.lock.entering .lock-swipe{opacity:0;}
.lock.entering .lock-clock{transform:translateY(-11vh) scale(.5);opacity:0;pointer-events:none;}
/* 密码键盘：呼出前藏在底部，iPhone 输密码的姿势 */
.lock-inner{position:absolute;z-index:3;left:0;right:0;bottom:0;width:100%;max-width:344px;margin:0 auto;
  padding:0 22px 24px;text-align:center;
  opacity:0;transform:translateY(34px);pointer-events:none;
  transition:opacity .38s ease .08s,transform .5s cubic-bezier(.3,.8,.4,1) .08s;}
.lock.entering .lock-inner{opacity:1;transform:none;pointer-events:auto;}
.lock-head{margin-top:0;}
.lock-title{font-family:var(--serif);font-size:16.5px;letter-spacing:.14em;color:#F6E9D2;}
.lock-sub{margin-top:8px;font-size:11.5px;letter-spacing:.1em;color:rgba(255,255,255,.56);min-height:16px;}
.lock-dots{display:flex;justify-content:center;gap:16px;margin:22px auto 0;height:13px;}
.lock-dots i{width:12px;height:12px;border-radius:50%;border:1.4px solid rgba(255,255,255,.78);
  background:transparent;transition:background .18s,border-color .18s,transform .18s;}
.lock-dots i.on{background:#fff;border-color:#fff;transform:scale(1.06);}
.lock-dots i.ok{background:#8FE0A6;border-color:#8FE0A6;transform:scale(1.1);}
.lock-dots i.bad{background:#FF8A9B;border-color:#FF8A9B;}
.lock-err{margin-top:14px;font-size:12.5px;letter-spacing:.1em;color:#FF9FAE;opacity:0;height:18px;
  transition:opacity .25s;}
.lock-err.show{opacity:1;}
.lock-pad{display:grid;grid-template-columns:repeat(3,1fr);gap:14px 20px;max-width:296px;margin:22px auto 0;}
.lk-key{width:74px;height:74px;border-radius:50%;border:none;background:rgba(255,255,255,.15);
  color:#fff;font-size:27px;font-weight:300;cursor:pointer;backdrop-filter:blur(8px);
  transition:background .12s,transform .12s;font-family:var(--sans);
  display:flex;align-items:center;justify-content:center;justify-self:center;padding:0;}
.lk-key:active,.lk-key.hit{background:rgba(255,255,255,.52);transform:scale(.94);}
.lk-key.fn{background:transparent;backdrop-filter:none;font-size:14.5px;letter-spacing:.04em;}
.lk-key.fn:active{background:rgba(255,255,255,.16);}
.lk-key.ghost{visibility:hidden;}
.lock-foot{margin-top:16px;font-size:11px;letter-spacing:.14em;color:rgba(255,255,255,.44);}
/* 左下手电筒 / 右下相机：毛玻璃圆钮，还原 iPhone 锁屏两角 */
.lq-btn{position:absolute;bottom:58px;z-index:2;width:52px;height:52px;border-radius:50%;border:none;cursor:pointer;
  background:rgba(120,120,128,.42);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  display:flex;align-items:center;justify-content:center;color:#fff;padding:0;
  transition:transform .15s,background .15s,opacity .3s ease;}
.lq-btn:active{transform:scale(.9);background:rgba(255,255,255,.3);}
.lq-torch{left:44px;}
.lq-cam{right:44px;}
.lock.entering .lq-btn{opacity:0;pointer-events:none;}
/* 底部 Home 指示条 */
.lock-home{position:absolute;bottom:9px;left:50%;transform:translateX(-50%);z-index:2;width:134px;height:5px;
  border-radius:3px;background:rgba(255,255,255,.92);pointer-events:none;}
.lock.shake .lock-dots{animation:lockShake .44s ease;}
@keyframes lockShake{0%,100%{transform:translateX(0);}18%{transform:translateX(-12px);}
  38%{transform:translateX(10px);}58%{transform:translateX(-7px);}78%{transform:translateX(4px);}}
.lock.unlocked{opacity:0;transform:scale(1.09);pointer-events:none;}
body.locked{overflow:hidden;}
@media (max-height:660px){
  .lock-time{font-size:60px;}
  .lock-clock{margin-top:5vh;}
  .lk-key{width:62px;height:62px;font-size:23px;}
  .lock-dots{margin-top:14px;}
  .lock-pad{margin-top:14px;gap:10px 18px;}
  .lq-btn{bottom:46px;width:46px;height:46px;}
  .lock-swipe{margin-bottom:88px;}
}
@media (max-width:360px){
  .lk-key{width:64px;height:64px;font-size:24px;}
  .lock-pad{gap:12px 14px;}
}
@media (prefers-reduced-motion:reduce){
  .lock.unlocked{transform:none;}
  .lock.shake .lock-dots{animation:none;}
}

/* ================= v2 华丽升级 ================= */
/* ---- 拆礼物开场 ---- */
/* 拆礼物的礼花画布：canvas 是替换元素，inset:0 不会自动拉伸，必须显式给宽高 */
#burst{position:absolute;inset:0;width:100%;height:100%;z-index:2;pointer-events:none;}
/* 拆盒瞬间的一记柔光，从礼盒位置向外扩散 */
.loader.flash::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:radial-gradient(circle at 50% 54%,rgba(255,244,214,.52),rgba(255,214,150,.14) 36%,transparent 64%);
  animation:bqFlash 1s ease-out forwards;}
@keyframes bqFlash{0%{opacity:0;}16%{opacity:1;}100%{opacity:0;}}
/* 花束：水彩玫瑰（assets/bouquet），礼花之后从画面底部缓缓升起 */
.bouquet{position:absolute;left:0;right:0;bottom:0;z-index:1;pointer-events:none;
  height:var(--bq-h);
  display:flex;align-items:flex-end;justify-content:center;   /* 居中交给 flex，见下方注释 */
  opacity:0;transform:translateY(52px) scale(.96);
  transition:opacity 1.2s ease .5s,transform 1.7s cubic-bezier(.16,.84,.28,1) .5s;
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 22%,#000 100%);
  mask-image:linear-gradient(180deg,transparent 0,#000 22%,#000 100%);}
.bouquet.show{opacity:1;transform:none;}
/* 这里曾经是 left:50% + translateX(-50%) + height:100% + width:auto，
   在窄窗口下会把花束横向压扁：绝对定位元素宽度为 auto 时走的是 shrink-to-fit，
   只会拿「从 50% 到容器右边缘」这点空间来算，窗口一窄（实测约 <790px 宽）就把图片宽度掐到一半以下；
   而 height:100% 是写死的，于是宽高比当场塌掉（1200×1359 的花束被压到 0.61，瘦成一条）。
   现在宽度交给 flex 居中去排，图片只用 max-width / max-height + auto 尺寸，
   走 CSS 替换元素的固有比例算法 —— 无论窗口多窄多宽，比例都不会变。 */
.bq-pos{position:relative;bottom:-1%;max-width:100%;min-width:0;}
/* min-width:0 别删：flex 项默认 min-width:auto，对图片来说等于固有宽度 1200px，
   它会拒绝收缩，窄屏上花束就会溢出屏幕。 */
.bouquet picture{display:block;}
.bouquet img{width:auto;height:auto;display:block;
  max-width:100%;max-height:var(--bq-h);
  transform-origin:50% 100%;
  animation:bqSway 6.5s ease-in-out infinite;
  filter:drop-shadow(0 -2px 30px rgba(255,178,196,.16));}
@keyframes bqSway{0%,100%{transform:rotate(-1.1deg);}50%{transform:rotate(1.1deg);}}
@media (prefers-reduced-motion:reduce){.bouquet img{animation:none;}}
/* 外层负责「缓慢浮到中间」，内层保留呼吸浮动，两者互不打架 */
.gift-wrap{position:relative;z-index:3;opacity:0;transform:translateY(52px) scale(.93);
  transition:opacity 1.7s ease,transform 1.7s cubic-bezier(.16,.84,.28,1);
  pointer-events:none;}   /* 还没浮出时不接受点击，免得视频还在放就被手滑点开 */
.gift-wrap.reveal{opacity:1;transform:translateY(0) scale(1);pointer-events:auto;}
.gift{position:relative;width:206px;height:206px;cursor:pointer;
  animation:giftFloat 5.4s ease-in-out infinite;}
.gift svg{width:100%;height:100%;overflow:visible;filter:drop-shadow(0 18px 34px rgba(0,0,0,.45));}
/* 平时缓慢呼吸浮动；每轮快结束时「怂一下」——像等不及要被拆开，暗示这里可以点 */
@keyframes giftFloat{
  0%,36%{transform:translateY(0) rotate(-1.2deg);}
  18%{transform:translateY(-10px) rotate(1.2deg);}
  44%{transform:translate(0,0) rotate(0deg);}
  47%{transform:translate(-5px,0) rotate(-2.8deg);}
  50%{transform:translate(5px,1px) rotate(2.8deg);}
  53%{transform:translate(-4.5px,0) rotate(-2.4deg);}
  56%{transform:translate(4px,0) rotate(2deg);}
  59%{transform:translate(-2.5px,0) rotate(-1.2deg);}
  62%{transform:translate(1px,0) rotate(.6deg);}
  65%{transform:translate(0,0) rotate(0deg);}
  82%,100%{transform:translateY(0) rotate(-1.2deg);}
}
/* 点下去先急抖一下再掀盖：把「要打开了」的期待感做出来 */
.gift.pre-open{animation:giftShake .6s cubic-bezier(.36,.07,.19,.97) both;pointer-events:none;}
@keyframes giftShake{
  0%{transform:translate(0,0) rotate(0) scale(1);}
  12%{transform:translate(-6px,0) rotate(-3deg) scale(1.02);}
  24%{transform:translate(6px,0) rotate(3deg) scale(1.02);}
  36%{transform:translate(-7px,0) rotate(-3.6deg) scale(1.03);}
  48%{transform:translate(7px,0) rotate(3.6deg) scale(1.03);}
  60%{transform:translate(-4px,0) rotate(-2deg) scale(1.01);}
  72%{transform:translate(4px,0) rotate(2deg) scale(1);}
  84%{transform:translate(-2px,0) rotate(-1deg) scale(1);}
  100%{transform:translate(0,0) rotate(0) scale(1);}
}
@media (prefers-reduced-motion:reduce){
  .gift{animation:none;}
  .gift.pre-open{animation:none;}
}
/* 金属光泽扫过盒面 */
.gift-sheen{transform-box:fill-box;transform-origin:50% 50%;
  animation:sheenSweep 4.4s 1.2s ease-in-out infinite;}
@keyframes sheenSweep{0%{transform:translateX(-120px) skewX(-14deg);}
  58%,100%{transform:translateX(260px) skewX(-14deg);}}
/* 四周金色小星：错开时间闪烁 */
.gift-sparks .sp{transform-box:fill-box;transform-origin:50% 50%;
  animation:sparkTw 2.6s ease-in-out infinite;opacity:.2;}
.gift-sparks .sp2{animation-delay:.45s;}
.gift-sparks .sp3{animation-delay:.9s;}
.gift-sparks .sp4{animation-delay:1.35s;}
.gift-sparks .sp5{animation-delay:1.8s;}
.gift-sparks .sp6{animation-delay:.22s;}
.gift-sparks .sp7{animation-delay:.66s;}
.gift-sparks .sp8{animation-delay:1.1s;}
.gift-sparks .sp9{animation-delay:1.55s;}
@keyframes sparkTw{0%,100%{opacity:.12;transform:scale(.55) rotate(0);}
  50%{opacity:.95;transform:scale(1.15) rotate(45deg);}}
/* 宝石上的星芒 */
.gem-spark{transform-box:fill-box;transform-origin:50% 50%;
  animation:gemTw 2.2s ease-in-out infinite;}
@keyframes gemTw{0%,100%{opacity:.35;transform:scale(.7);}50%{opacity:1;transform:scale(1.2);}}
.gift.open .gift-sheen-group,.gift.open .gift-sparks{opacity:0;transition:opacity .4s;}
.gift-lid,.gift-bow{transform-box:fill-box;transform-origin:50% 50%;
  transition:transform 1s cubic-bezier(.22,1,.36,1),opacity .9s ease;}
.gift-body{transform-box:fill-box;transform-origin:50% 100%;
  transition:transform .8s .2s ease,opacity .8s .3s ease;}
.gift.open{animation:none;pointer-events:none;}
.gift.open .gift-lid{transform:translateY(-170px) rotate(-24deg);opacity:0;}
/* 蝴蝶结整体放大了 1.26 倍，飞出位移同步加大，不然会像没飞开 */
.gift.open .gift-bow-l{transform:translate(-138px,-64px) rotate(-86deg);opacity:0;}
.gift.open .gift-bow-r{transform:translate(138px,-64px) rotate(86deg);opacity:0;}
.gift.open .gift-bow-knot{opacity:0;transition:opacity .4s;}
.gift.open .gift-body{transform:scale(.86) translateY(14px);opacity:0;}
.gift-glow{position:absolute;left:50%;top:52%;width:150px;height:150px;margin:-75px 0 0 -75px;
  border-radius:50%;background:radial-gradient(circle,rgba(255,246,214,.95),rgba(255,228,170,.5) 45%,transparent 70%);
  opacity:0;pointer-events:none;z-index:1;}
.gift.open .gift-glow{animation:glowPop 1.1s ease-out forwards;}
@keyframes glowPop{0%{opacity:0;transform:scale(.2);}35%{opacity:1;transform:scale(1.5);}100%{opacity:0;transform:scale(3.4);}}
/* 提示文字跟礼盒一起浮出（视频第一遍播完才加 .reveal），不能在视频还在放时就冒出来 */
.gift-tip{margin-top:26px;font-family:var(--serif);color:#F3E3BC;letter-spacing:.3em;font-size:14px;
  font-weight:500;opacity:0;text-align:center;transition:opacity .5s;z-index:3;position:relative;
  text-shadow:0 2px 14px rgba(24,10,20,.75),0 1px 3px rgba(24,10,20,.6);}
/* 浮出后持续呼吸闪烁，和礼盒的「怂一下」一起引导点击 */
.gift-tip.reveal{animation:fadeUp 1s .45s forwards,tipBreath 2.6s 1.6s ease-in-out infinite;}
@keyframes tipBreath{0%,100%{opacity:1;}50%{opacity:.58;}}
.gift-sub{margin-top:10px;color:rgba(243,227,188,.72);font-size:11px;letter-spacing:.22em;
  opacity:0;text-align:center;z-index:3;position:relative;
  text-shadow:0 2px 12px rgba(24,10,20,.8),0 1px 3px rgba(24,10,20,.6);}
.gift-sub.reveal{animation:fadeUp 1s .8s forwards;}

/* ---- 吹蜡烛蛋糕 ---- */
.cake-stage{position:relative;width:252px;height:252px;display:flex;align-items:flex-end;justify-content:center;}
.cake-svg{width:212px;height:212px;position:relative;z-index:2;filter:drop-shadow(0 12px 26px rgba(0,0,0,.4));}
.cake-glow{position:absolute;left:50%;top:14%;width:130px;height:130px;margin:-65px 0 0 -65px;border-radius:50%;
  background:radial-gradient(circle,rgba(255,198,112,.34),transparent 68%);z-index:3;pointer-events:none;
  animation:glowPulse 2.6s ease-in-out infinite;}
@keyframes glowPulse{0%,100%{opacity:.75;transform:scale(1);}50%{opacity:1;transform:scale(1.12);}}
.cake-stage.dark .cake-glow{opacity:0;transition:opacity .9s;}
.candle{position:absolute;left:50%;top:30px;transform:translateX(-50%);width:16px;z-index:5;cursor:pointer;}
.candle-body{width:16px;height:54px;border-radius:7px 7px 3px 3px;
  background:repeating-linear-gradient(135deg,#FFF6E2 0 6px,#F2D3A6 6px 12px);
  box-shadow:inset -3px 0 6px rgba(180,120,70,.28),0 2px 6px rgba(0,0,0,.25);}
.flame{position:absolute;left:50%;top:-30px;width:20px;height:32px;transform-origin:50% 100%;
  border-radius:50% 50% 46% 46%/62% 62% 38% 38%;
  background:radial-gradient(circle at 50% 72%,#FFFBE0 0%,#FFD34E 34%,#FF9330 62%,rgba(255,90,40,.12) 82%,transparent 88%);
  box-shadow:0 0 26px 10px rgba(255,175,80,.42);
  animation:flicker .3s ease-in-out infinite alternate;}
.flame::after{content:"";position:absolute;left:50%;top:36%;transform:translateX(-50%);width:7px;height:14px;
  border-radius:50%;background:radial-gradient(circle,#fff,#FFE9A8 70%,transparent);opacity:.92;}
@keyframes flicker{
  0%{transform:translateX(-50%) scale(1) rotate(-2deg);opacity:.94;}
  100%{transform:translateX(-50%) scale(1.12,.9) rotate(2deg);opacity:1;}}
.candle.out .flame{animation:none;opacity:0;transform:translateX(-50%) scale(.15);transition:all .5s ease;}
.smoke{position:absolute;left:50%;bottom:100%;width:20px;height:70px;transform:translateX(-50%);
  pointer-events:none;opacity:0;z-index:6;}
.candle.out .smoke{opacity:1;}
.smoke i{position:absolute;bottom:0;left:50%;width:7px;height:7px;border-radius:50%;
  background:rgba(226,220,214,.55);filter:blur(2.5px);opacity:0;}
.candle.out .smoke i{animation:smokeUp 2.4s ease-out forwards;}
.candle.out .smoke i:nth-child(2){animation-delay:.25s;margin-left:-8px;}
.candle.out .smoke i:nth-child(3){animation-delay:.5s;margin-left:8px;}
@keyframes smokeUp{0%{opacity:0;transform:translate(0,0) scale(.5);}
  25%{opacity:.75;}100%{opacity:0;transform:translate(-6px,-58px) scale(2.6);}}
.blow-bar{position:absolute;left:50%;bottom:-14px;transform:translateX(-50%);width:132px;height:5px;
  border-radius:5px;background:rgba(255,255,255,.2);overflow:hidden;opacity:0;transition:opacity .3s;}
.blow-bar.on{opacity:1;}
.blow-bar span{display:block;height:100%;width:0;border-radius:5px;
  background:linear-gradient(90deg,#FFD98E,#FF8FB0);transition:width .12s linear;}
.blow-tip{margin-top:14px;font-size:12px;letter-spacing:.14em;color:rgba(243,227,188,.72);font-weight:300;}
.blow-err{margin-top:8px;font-size:11.5px;color:#F0B8A8;letter-spacing:.08em;display:none;}

/* ---- 我们的时光 · 竖版拍立得 ---- */
/* 4:5 竖构图：宽度撑满容器但封顶 340px。
   注意用 width:100% + max-width，不能写 width:min(340px,78vw)——
   后者在窄屏上会算出比容器更宽的值，直接把卡片顶出 .wrap。 */
.polaroid{position:relative;width:100%;max-width:340px;margin:6px auto 0;perspective:1400px;}
/* 背后垫两张微微歪斜的空白相纸，做出「一叠照片」的厚度感 */
.polaroid::before,.polaroid::after{content:"";position:absolute;inset:0;border-radius:5px;
  background:#FFFDF8;box-shadow:0 12px 26px rgba(60,28,40,.2);}
.polaroid::before{transform:rotate(-2.4deg) translate(-7px,5px);opacity:.5;}
.polaroid::after{transform:rotate(2deg) translate(8px,-3px);opacity:.34;}
.pol-inner{position:relative;z-index:1;transform-style:preserve-3d;
  transition:transform .85s cubic-bezier(.22,1,.36,1);}
.polaroid.flipped .pol-inner{transform:rotateY(180deg);}
.pol-face{backface-visibility:hidden;-webkit-backface-visibility:hidden;}
.pol-front{position:relative;padding:13px 13px 0;border-radius:5px;
  background:linear-gradient(168deg,#FFFDF8,#F4EBDD);
  box-shadow:0 18px 40px rgba(60,28,40,.3),inset 0 0 0 1px rgba(255,255,255,.6);}
.proj-photo{position:relative;border-radius:2px;overflow:hidden;background:#151013;}
.proj-photo img,.proj-photo video{width:100%;aspect-ratio:4/5;object-fit:cover;display:block;
  transition:transform .8s cubic-bezier(.22,1,.36,1),filter .8s;}
.proj-photo.swap img{transform:scale(1.06);filter:brightness(1.3) blur(2px);}
/* 相纸下沿留白写图注 —— 真正的拍立得就是这样 */
.pol-cap{margin:0;padding:15px 8px 17px;text-align:center;font-family:var(--serif);
  font-size:15.5px;font-weight:500;letter-spacing:.14em;color:#8A6A74;}
.pol-back{position:absolute;inset:0;border-radius:5px;transform:rotateY(180deg);visibility:hidden;
  background:linear-gradient(160deg,#B85E78,#7E3F56);display:flex;align-items:center;justify-content:center;
  padding:30px 26px;text-align:center;box-shadow:0 18px 40px rgba(60,28,40,.3);}
.polaroid.flipped .pol-back{visibility:visible;}
.polaroid.flipped .pol-front{visibility:hidden;}
.pol-back p{font-family:var(--serif);color:#FBEED1;font-size:17px;line-height:1.95;font-weight:500;}
/* 顶部那条半透明胶带 */
.pol-tape{position:absolute;top:-9px;left:50%;width:78px;height:22px;margin-left:-39px;
  transform:rotate(-2.5deg);border-radius:2px;pointer-events:none;
  background:linear-gradient(180deg,rgba(255,246,214,.62),rgba(255,240,196,.42));
  box-shadow:0 2px 6px rgba(60,28,40,.12);}
.proj-zoom{position:absolute;top:23px;right:23px;width:32px;height:32px;border-radius:50%;
  background:rgba(255,253,248,.84);border:1px solid rgba(138,106,116,.28);display:flex;align-items:center;
  justify-content:center;cursor:pointer;z-index:4;}
.proj-nav{position:absolute;top:45%;width:38px;height:38px;border-radius:50%;
  background:rgba(38,20,30,.55);border:1px solid rgba(238,212,154,.45);color:#F3E3BC;cursor:pointer;
  display:flex;align-items:center;justify-content:center;font-size:18px;line-height:1;z-index:5;}
.proj-nav.prev{left:-4px;} .proj-nav.next{right:-4px;}
.film-strip{position:relative;margin:20px auto 0;max-width:400px;padding:10px 0;
  background:linear-gradient(180deg,#2E2229,#1D151B);border-radius:6px;overflow:hidden;
  box-shadow:inset 0 0 0 1px rgba(238,212,154,.16),0 10px 24px rgba(60,30,40,.2);}
.film-strip::before,.film-strip::after{content:"";position:absolute;left:0;right:0;height:9px;
  background:repeating-linear-gradient(90deg,rgba(255,255,255,.24) 0 9px,transparent 9px 20px);}
.film-strip::before{top:0;} .film-strip::after{bottom:0;}
.film-frames{display:flex;gap:6px;overflow-x:auto;scroll-behavior:smooth;padding:2px 9px;
  scrollbar-width:none;-webkit-overflow-scrolling:touch;}
.film-frames::-webkit-scrollbar{display:none;}
.film-frame{flex:0 0 auto;width:72px;height:72px;border-radius:4px;overflow:hidden;padding:0;border:none;
  cursor:pointer;opacity:.45;filter:grayscale(.5);background:none;transition:all .35s;}
.film-frame img{width:100%;height:100%;object-fit:cover;display:block;}
.film-frame.active{opacity:1;filter:none;transform:translateY(-3px);
  box-shadow:0 0 0 2px var(--gold-lt),0 8px 18px rgba(0,0,0,.45);}
.proj-meta{display:flex;align-items:center;justify-content:center;gap:14px;margin-top:14px;}
.proj-count{font-size:12px;letter-spacing:.2em;color:var(--soft);font-feature-settings:'tnum';}
.proj-auto{font-size:12px;letter-spacing:.16em;color:var(--gold-dk);border:1px solid rgba(213,162,94,.45);
  border-radius:30px;padding:8px 18px;background:transparent;cursor:pointer;min-height:38px;}
.proj-auto.on{background:rgba(213,162,94,.14);}
.proj-tip{margin-top:12px;text-align:center;font-size:12px;color:var(--soft);letter-spacing:.1em;font-weight:300;}

/* ---- 数字翻牌 ---- */
.odo{position:relative;display:inline-block;overflow:hidden;vertical-align:bottom;min-width:1.05em;}
.odo-cur{display:block;}
.odo-new{position:absolute;left:0;top:0;transform:translateY(105%);opacity:0;
  transition:transform .42s cubic-bezier(.22,1,.36,1),opacity .42s;}
.odo-new.in{transform:translateY(0);opacity:1;}
.odo-cur.out{transform:translateY(-105%);opacity:0;
  transition:transform .42s cubic-bezier(.22,1,.36,1),opacity .42s;}
/* ---- 打字机 ---- */
.typer{display:inline-block;width:2px;height:1.02em;background:var(--rose-deep);vertical-align:-2px;
  margin-left:2px;animation:blink .8s steps(2,end) infinite;}
@keyframes blink{0%,50%{opacity:1;}51%,100%{opacity:0;}}
/* ---- 章节金粉扫过 ---- */
.sec-sweep{position:absolute;left:0;right:0;top:0;height:150px;overflow:hidden;pointer-events:none;z-index:0;opacity:0;}
section.sweep .sec-sweep{opacity:1;}
.sec-sweep::before{content:"";position:absolute;top:0;left:-45%;width:45%;height:100%;transform:skewX(-18deg);
  background:linear-gradient(100deg,transparent,rgba(238,212,154,.5),rgba(255,248,230,.85),rgba(238,212,154,.5),transparent);}
section.sweep .sec-sweep::before{animation:sweepOnce 1.5s cubic-bezier(.3,.1,.2,1);}
@keyframes sweepOnce{0%{left:-45%;}100%{left:105%;}}
.q-low .sec-sweep{display:none;}
/* ---- Hero 名字粒子 ---- */
#namefx{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:3;transition:opacity .8s ease;}
.hero-title.nofx{animation:shine 5.5s linear infinite;opacity:0;transition:opacity .9s ease;}
.hero-title.nofx.on{opacity:1;}
/* ---- 音乐频谱 ---- */
#viz{position:fixed;top:62px;left:14px;z-index:80;width:44px;height:24px;display:none;}
#viz.on{display:block;}

/* ---- 心动留言 + 情话生成器 ---- */
.voice-sec{background:linear-gradient(180deg,var(--cream),#F5E6E8);}
.voice-card{display:flex;align-items:center;gap:16px;max-width:520px;margin:0 auto;
  background:linear-gradient(180deg,#FFFDF9,var(--paper));border:1px solid var(--line-gold);
  border-radius:18px;padding:18px 20px;box-shadow:0 16px 40px rgba(120,60,80,.12);}
.voice-play{flex:0 0 auto;width:58px;height:58px;border-radius:50%;border:none;cursor:pointer;
  background:linear-gradient(135deg,#E7C884,#C88F49);display:flex;align-items:center;justify-content:center;
  box-shadow:0 10px 24px rgba(213,162,94,.38);}
.voice-play:active{transform:scale(.95);}
.voice-play.playing{animation:pulseRing 1.8s ease-out infinite;}
@keyframes pulseRing{0%{box-shadow:0 0 0 0 rgba(213,162,94,.55);}100%{box-shadow:0 0 0 18px rgba(213,162,94,0);}}

/* ===== 板块分章：每章独立包裹，章与章之间用过渡带隔开 ===== */
.chapter{position:relative;}
.chapter.pre{opacity:0;transform:translateY(30px);}
.chapter.in{opacity:1;transform:none;
  transition:opacity .85s ease,transform 1s cubic-bezier(.22,.72,.28,1);}
.ch-seam{position:relative;height:104px;display:flex;align-items:center;justify-content:center;
  overflow:hidden;
  background:linear-gradient(180deg,rgba(255,255,255,0),rgba(201,155,82,.09) 50%,rgba(255,255,255,0));}
.ch-seam::before{content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:1px;height:56px;background:linear-gradient(180deg,transparent,rgba(213,162,94,.7),transparent);}
.ch-seam i{position:relative;z-index:2;width:7px;height:7px;background:rgba(213,162,94,.92);
  transform:rotate(45deg);box-shadow:0 0 12px rgba(231,200,132,.65);}
.seam-sweep{position:absolute;inset:0;transform:translateX(-110%);
  background:linear-gradient(90deg,transparent,rgba(231,200,132,.30),transparent);}
.ch-seam.in .seam-sweep{animation:seamSweep 1.6s ease .08s forwards;}
@keyframes seamSweep{to{transform:translateX(110%);}}
@media (prefers-reduced-motion:reduce){
  .chapter.pre{opacity:1;transform:none;}
  .seam-sweep{display:none;}
}

/* ===== 「想说给你听」之后：提示把手机竖回来（只有横屏才出现） ===== */
.rotate-back-tip{position:fixed;inset:0;z-index:76;display:none;align-items:center;justify-content:center;
  background:rgba(22,12,18,.95);padding:24px;text-align:center;}
.rotate-back-tip.show{display:flex;animation:rtIn .45s ease;}
@keyframes rtIn{from{opacity:0;}to{opacity:1;}}
.rt-inner{max-width:320px;display:flex;flex-direction:column;align-items:center;gap:14px;}
.rt-title{margin:0;font-family:var(--serif);font-size:19px;font-weight:600;color:#F3E3BC;letter-spacing:.06em;}
.rt-sub{margin:0;font-size:12px;color:rgba(243,227,188,.62);letter-spacing:.04em;line-height:1.7;}
.rt-skip{flex:0 0 auto;font-size:11px;color:rgba(243,227,188,.8);letter-spacing:.1em;
  border:1px solid rgba(238,212,154,.4);border-radius:20px;padding:7px 14px;background:transparent;
  cursor:pointer;min-height:32px;}
.rb-icon{animation:rbTilt 2.4s ease-in-out infinite;}
/* 手机现在是横的(-90deg)，动画里短暂回到竖直(0)，提示「把它转回竖屏」 */
@keyframes rbTilt{0%,60%,100%{transform:rotate(-90deg);}30%{transform:rotate(0) scale(1.04);}}
/* 竖屏下不显示：只有横屏 + 走到后面章节才弹出 */
@media (orientation:portrait){.rotate-back-tip.show{display:none !important;}}

/* ===== 矮横屏（手机横过来）下「我们的时光」紧凑排版：卡片按视口高度收缩，仍是竖版 4:5 ===== */
@media (orientation:landscape) and (max-height:600px){
  .photos{padding:26px 0 30px;}
  .photos .sec-head{margin-bottom:16px;}
  .photos .sec-title{font-size:22px;}
  .photos .sec-sub{font-size:12px;margin-top:6px;}
  /* 矮横屏：高度是瓶颈，改成「按高度定尺寸 + 4:5.5 的比例」，仍然是竖着的一张照片，只是整体缩小 */
  .polaroid{width:auto;max-width:none;height:min(420px,92vh);aspect-ratio:4/5.5;margin:0 auto;}
  .pol-inner{height:100%;}
  .pol-front{height:100%;display:flex;flex-direction:column;padding:10px 10px 0;}
  .proj-photo{flex:1;min-height:0;}
  .proj-photo img,.proj-photo video{aspect-ratio:auto;height:100%;}
  .pol-cap{padding:9px 8px 10px;font-size:13.5px;}
  .film-strip{margin-top:12px;max-width:340px;}
  .film-frame{width:56px;height:56px;}
  .proj-meta{margin-top:10px;}
  .proj-tip{display:none;}
}
/* ===== 矮横屏下四季长卡按高度收缩，避免一屏塞不下 ===== */
@media (orientation:landscape) and (max-height:600px){
  .tl{max-width:300px;}
  .tl-item+.tl-item{margin-top:22px;}
  .tl-season{font-size:44px;}
  .tl-body{padding:16px 18px 18px;}
  .tl-body p{font-size:13.5px;line-height:1.8;}
}
.voice-info{flex:1;min-width:0;}
.voice-title{font-family:var(--serif);font-size:15.5px;font-weight:600;color:var(--rose-deep);margin-bottom:9px;}
.voice-wave{display:flex;align-items:center;gap:3px;height:24px;}
.voice-wave i{flex:1;height:5px;border-radius:3px;background:rgba(201,107,130,.32);}
.voice-card.playing .voice-wave i{animation:wave 1.1s ease-in-out infinite;}
.voice-card.playing .voice-wave i:nth-child(3n){animation-delay:.18s;}
.voice-card.playing .voice-wave i:nth-child(3n+1){animation-delay:.36s;}
@keyframes wave{0%,100%{height:5px;background:rgba(201,107,130,.32);}50%{height:20px;background:var(--rose);}}
.voice-time{font-size:11.5px;color:var(--soft);letter-spacing:.1em;margin-top:7px;font-feature-settings:'tnum';}
.quote-box{position:relative;max-width:520px;margin:32px auto 0;text-align:center;padding:32px 26px 26px;
  background:linear-gradient(180deg,#FFFDF9,var(--paper));border:1px solid var(--line-gold);border-radius:18px;
  box-shadow:0 16px 40px rgba(120,60,80,.12);}
.quote-box::before{content:"\201C";position:absolute;top:2px;left:20px;font-family:var(--serif);
  font-size:54px;line-height:1;color:rgba(213,162,94,.32);}
.quote-text{font-family:var(--serif);font-size:17px;line-height:2;color:#5A4149;font-weight:500;
  min-height:4em;transition:opacity .35s ease;}
.quote-text.fade{opacity:0;}
.quote-btn{margin-top:16px;font-family:var(--serif);font-size:13px;letter-spacing:.18em;color:var(--gold-dk);
  border:1px solid rgba(213,162,94,.45);border-radius:30px;padding:11px 26px;background:transparent;
  cursor:pointer;min-height:42px;}
.quote-btn:active{transform:scale(.96);}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important;}
  html{scroll-behavior:auto;}
  .reveal{opacity:1;transform:none;}
}