:root{
  --paper:#f4ecdf; --paper2:#ede2cf; --card:#fffdf8; --ink:#3b2f27; --ink2:#7a6858; --ink3:#a8957f;
  --red:#b9432c; --line:#cdbba3; --tint:#ecd2bc; --night:#251d18;
  --hand:'Ma Shan Zheng',cursive; --body:'LXGW WenKai','Songti SC',serif; --num:'Cormorant Garamond',Georgia,serif;
  --grain:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .42 0 0 0 0 .32 0 0 0 0 .2 0 0 0 .085 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  --sat:env(safe-area-inset-top,0px); --sab:env(safe-area-inset-bottom,0px);
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--body);font-size:18px;line-height:1.6;-webkit-font-smoothing:antialiased}
body{background-image:var(--grain);overflow-x:hidden}
button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}
img{display:block}
.num{font-family:var(--num);font-style:italic;font-weight:500}

/* ---------- views ---------- */
.view{display:none;min-height:100vh}
.view.on{display:block;animation:viewIn .55s cubic-bezier(.2,.7,.2,1)}
@keyframes viewIn{from{opacity:0;transform:scale(.985)}to{opacity:1;transform:none}}
.view.out{display:block;position:fixed;inset:0;overflow:hidden;animation:viewOut .4s ease forwards;pointer-events:none;z-index:5}
@keyframes viewOut{to{opacity:0;transform:scale(1.03)}}

/* ---------- stamp ---------- */
.stamp{position:relative;padding:7px;background:radial-gradient(circle,transparent 0 3.2px,var(--card) 3.7px) -6px -6px/12px 12px;filter:drop-shadow(0 2px 2.5px rgba(70,45,25,.22))}
.stamp img,.stamp .art{width:100%;aspect-ratio:4/5;object-fit:cover;background:#ddd}
.art{position:relative;display:flex;align-items:center;justify-content:center;color:rgba(255,250,240,.93);font-family:var(--hand);overflow:hidden;container-type:inline-size}
.art::before{content:"";position:absolute;inset:6%;border:1px solid rgba(255,250,240,.55)}
.art::after{content:"";position:absolute;inset:0;background:var(--grain),radial-gradient(120% 80% at 30% 20%,rgba(255,255,255,.18),transparent 60%);mix-blend-mode:overlay}
.art b{font-weight:400;font-size:58cqw;line-height:1;transform:translateY(-4%)}
.art small{position:absolute;left:11%;bottom:8%;font-family:var(--body);font-size:max(9px,9cqw);opacity:.85;letter-spacing:.1em}
.art em{position:absolute;right:10%;top:9%;font-family:var(--num);font-size:max(9px,11cqw);opacity:.8}
.postmark{color:var(--red);opacity:.78;mix-blend-mode:multiply;filter:url(#rough)}

/* ---------- gate (envelope) ----------
   动画全部由 v3.js 里的一条时间线驱动（Web Animations），这里只放静止状态 */
#gate{position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;background-color:#1a1410;background-image:var(--grain);overflow:hidden}
#gate[hidden]{display:none}
body.gated #app{visibility:hidden}
/* 夜里只有信封被一束光照着 */
.gate-light{position:absolute;left:50%;top:44%;width:140vmax;height:140vmax;margin:-70vmax 0 0 -70vmax;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,rgba(255,232,196,.30) 0,rgba(255,226,186,.16) 14%,rgba(255,220,180,.05) 26%,transparent 38%)}
/* 拆开信以后：像在暗屋里拧亮一盏台灯——一团柔和的暖光从信封口亮起来，再一圈圈慢慢铺满整个屋子（没有光束、没有光环） */
.gate-room{position:absolute;left:50%;top:44%;width:320vmax;aspect-ratio:1;border-radius:50%;pointer-events:none;opacity:0;transform:translate(-50%,-50%) scale(.04);
  background:radial-gradient(closest-side,rgba(255,220,160,.72) 0,rgba(252,200,138,.56) 9%,rgba(240,180,116,.4) 20%,rgba(214,156,104,.25) 34%,rgba(186,132,88,.14) 52%,rgba(160,112,74,.06) 72%,rgba(140,98,64,0) 100%)}
#gate::after{content:"";position:absolute;inset:0;background:var(--grain);opacity:.55;pointer-events:none}
.gate-glow{position:absolute;left:50%;top:2%;width:150%;aspect-ratio:1.5;border-radius:50%;pointer-events:none;z-index:1;opacity:0;transform:translate(-50%,-50%) scale(.2);
  background:radial-gradient(closest-side,rgba(255,238,200,.95) 0,rgba(255,218,160,.7) 22%,rgba(255,200,138,.36) 48%,rgba(255,190,125,.1) 74%,transparent 100%)}
.gate-inner{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;gap:44px;width:min(560px,88%)}
.envelope{position:relative;width:100%;aspect-ratio:1.55;perspective:1400px;container-type:inline-size;animation:breathe 5s ease-in-out infinite}
@keyframes breathe{50%{transform:translateY(-5px)}}
#gate.go .envelope{animation:none}
.env-back{position:absolute;inset:0;background:#e0caa8;border-radius:6px;overflow:hidden;box-shadow:0 34px 60px -24px rgba(0,0,0,.7)}
.env-inside{position:absolute;left:4%;right:4%;top:-36%;height:110%;border-radius:50%;background:radial-gradient(ellipse at 50% 40%,#fff4d6 0,rgba(255,220,160,.95) 25%,rgba(255,196,128,.55) 50%,transparent 72%);opacity:0}
.env-front{position:absolute;inset:0;border-radius:6px;background:linear-gradient(160deg,#f1e2c8,#e9d5b4);box-shadow:0 18px 40px -18px rgba(80,50,20,.45),inset 0 0 0 1px rgba(120,90,50,.12);clip-path:polygon(0 0,50% 52%,100% 0,100% 100%,0 100%);z-index:3}
.env-front::before{content:"";position:absolute;inset:0;background:var(--grain)}
.env-to{position:absolute;left:8%;bottom:11%;max-width:66%;font-family:var(--hand);font-size:clamp(14px,3.7cqw,21px);color:var(--ink2);line-height:1.5}
.env-to span{font-size:1.32em;color:var(--ink);border-bottom:1.5px dashed var(--line)}
.env-mark{position:absolute;right:8%;bottom:12%;width:22%;transform:rotate(-12deg)}
.env-flapw{position:absolute;left:0;right:0;top:0;height:58%;transform-origin:50% 0;transform-style:preserve-3d;z-index:4}
.env-flap{position:absolute;inset:0;background:linear-gradient(180deg,#ead8ba,#dfc8a4);clip-path:polygon(0 0,100% 0,50% 100%);filter:drop-shadow(0 4px 4px rgba(0,0,0,.1))}
.flap-shade{position:absolute;inset:0;background:linear-gradient(180deg,rgba(120,80,40,0),rgba(120,80,40,.35));opacity:0}
.letter{position:absolute;left:6%;right:6%;top:6%;bottom:6%;z-index:2;transform-origin:50% 50%}
.letter-paper{position:absolute;inset:0;background:var(--card) var(--grain);border-radius:3px;box-shadow:0 2px 10px rgba(80,50,20,.12)}
.letter-txt{position:absolute;left:0;right:0;top:17%;text-align:center;font-family:'Noto Serif SC',var(--body);font-weight:600;font-size:clamp(28px,8.4cqw,48px);line-height:1.3;color:#3b2a1f;letter-spacing:.34em;text-indent:.34em;white-space:nowrap}
.letter-txt span{display:inline-block;opacity:0}
.letter-rule{position:absolute;left:50%;top:46%;width:16%;height:1px;margin-left:-8%;background:linear-gradient(90deg,transparent,rgba(185,67,44,.7) 30%,rgba(185,67,44,.7) 70%,transparent);transform:scaleX(0)}
.letter-sub{position:absolute;left:0;right:0;top:54%;text-align:center;font-family:'Noto Serif SC',var(--body);font-weight:300;font-size:clamp(12px,3.05cqw,16.5px);color:#6e5a49;letter-spacing:.24em;text-indent:.24em;white-space:nowrap;opacity:0}
.letter-photo{position:absolute;right:-5%;top:-11%;width:22%;padding:4% 4% 12%;background:var(--card);box-shadow:0 4px 12px -4px rgba(80,50,20,.4);transform:rotate(7deg);opacity:0}
.letter-photo img{width:100%;aspect-ratio:4/5;object-fit:cover;object-position:50% 28%}
/* 封口：一枚邮票压住封口尖（上半截贴在封口上、下半截贴在信封上）。拆信时邮票被轻轻揭起，再跟着封口完整地翻上去 */
.seal{position:absolute;left:50%;top:100%;width:clamp(62px,17cqw,94px);padding:0;border:0;background:none;cursor:pointer;transform:translate(-50%,-40%) rotate(-3deg);perspective:320px;backface-visibility:hidden;-webkit-backface-visibility:hidden}
.seal-in{display:block;padding:6px;background:radial-gradient(circle,transparent 0 2.7px,#fbf6ec 3.2px) -5px -5px/10px 10px;filter:drop-shadow(0 2px 2.5px rgba(40,25,10,.35));transform-origin:50% 22%}
.seal-in svg{display:block;width:100%;height:auto}
.seal:focus-visible{outline:2px solid #e0a07a;outline-offset:4px}
.code{position:relative;display:flex;flex-direction:column;align-items:center;gap:14px;cursor:text}
.code-label{font-size:18px;color:#cdbba3;letter-spacing:.3em}
.code-boxes{display:flex;gap:14px}
.code-boxes i{width:54px;height:62px;border-radius:12px;background:rgba(255,248,236,.08);box-shadow:inset 0 0 0 1.5px rgba(255,236,210,.28);display:flex;align-items:center;justify-content:center;font-style:normal;font-family:var(--num);font-size:34px;color:#f4e6d2;transition:box-shadow .2s}
.code-boxes i.f{box-shadow:inset 0 0 0 2px #e0a07a}
.code-msg{min-height:24px;font-size:16px;color:#f0b48e}
.code input{position:absolute;inset:0;opacity:0;font-size:16px;width:100%;height:100%;border:0;background:transparent;color:transparent;caret-color:transparent}
/* 到家：首页内容轻轻浮上来 */
body.arrive .hero .greet>*,body.arrive .hero .mapsheet{animation:arrive .9s cubic-bezier(.22,1,.36,1) both}
body.arrive .hero .greet>*:nth-child(2){animation-delay:.12s}
body.arrive .hero .mapsheet{animation-delay:.25s}
body.arrive .topbar{animation:arrive .9s .05s cubic-bezier(.22,1,.36,1) both}
@keyframes arrive{from{opacity:0;transform:translateY(18px)}}

/* ---------- top bar ---------- */
.topbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:space-between;padding:calc(14px + var(--sat)) 28px 10px;pointer-events:none}
.topbar>*{pointer-events:auto}
.brand{text-decoration:none;display:flex;align-items:center;gap:10px;font-family:var(--hand);font-size:24px;color:var(--ink)}
.brand svg{width:44px;height:44px}
.back{display:inline-flex;align-items:center;gap:6px;height:48px;padding:0 20px 0 14px;border-radius:24px;background:rgba(255,253,248,.88);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);box-shadow:0 2px 10px rgba(80,50,20,.12);font-size:19px;color:var(--ink)}
.back svg{width:22px;height:22px}

/* ---------- home: hero ---------- */
.hero{display:grid;grid-template-columns:minmax(330px,0.78fr) 1.5fr;gap:24px;align-items:center;max-width:1440px;margin:0 auto;padding:0 40px 30px;min-height:calc(100vh - 80px)}
.greet{padding-left:28px}
.greet .pre{font-family:var(--hand);font-size:30px;color:var(--ink2);margin:0 0 6px}
.greet h1{font-family:var(--hand);font-weight:400;font-size:clamp(34px,3.1vw,50px);white-space:nowrap;line-height:1.38;margin:0;letter-spacing:.02em}
.greet h1 b{font-family:var(--num);font-style:italic;font-weight:500;color:var(--red);font-size:1.3em;padding:0 .08em}
.latest{display:flex;align-items:center;gap:16px;margin-top:44px;padding:12px 22px 12px 12px;border-radius:16px;background:rgba(255,253,248,.7);box-shadow:0 1px 0 rgba(0,0,0,.03),0 8px 22px -14px rgba(80,50,20,.35);transition:transform .25s,box-shadow .25s;text-align:left}
.latest:hover{transform:translateY(-2px);box-shadow:0 14px 28px -14px rgba(80,50,20,.45)}
.latest .stamp{width:64px;transform:rotate(-3deg)}
.latest small{display:block;color:var(--ink2);font-size:15px}
.latest strong{display:block;font-family:var(--hand);font-weight:400;font-size:27px;line-height:1.3}
.latest .go{margin-left:auto;font-size:26px;color:var(--ink3)}
.shuffle{display:inline-flex;align-items:center;gap:8px;margin-top:18px;margin-left:6px;font-size:17px;color:var(--ink2);border-bottom:1.5px dashed var(--line);padding-bottom:2px}
.shuffle:hover{color:var(--red);border-color:var(--red)}

.mapsheet{position:relative;background:var(--card) var(--grain);padding:22px 22px 18px;transform:rotate(.6deg);box-shadow:0 1px 1px rgba(0,0,0,.04),0 26px 50px -30px rgba(80,50,20,.55)}
.tape{position:absolute;width:120px;height:30px;background:rgba(229,206,160,.72);top:-14px;left:50%;margin-left:-60px;transform:rotate(-2deg);box-shadow:0 1px 2px rgba(0,0,0,.06)}
.tape.r{left:auto;right:-30px;top:40px;transform:rotate(38deg)}
.map{position:relative;aspect-ratio:1000/840}
.map svg.base{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
.prov{fill:#f7f1e6;stroke:#bba78d;stroke-width:.9;stroke-linejoin:round;transition:fill .3s}
.prov.v{fill:var(--tint)}
.prov.hl{fill:#e6bfa3}
.leader{stroke:var(--red);stroke-width:1.4;stroke-dasharray:3 4;opacity:.55;fill:none}
.dot{fill:var(--red)}
.ring{fill:none;stroke:var(--red);stroke-width:1.5;transform-box:fill-box;transform-origin:center;animation:ring 2.6s ease-out infinite}
@keyframes ring{from{transform:scale(.6);opacity:.8}to{transform:scale(2.6);opacity:0}}
.inset{position:absolute;right:1.5%;bottom:1.5%;width:10.5%;aspect-ratio:110/150;border:1px solid #c9b597;background:var(--card)}
.inset svg{width:100%;height:100%}
.inset .l{fill:#f7f1e6;stroke:#bba78d;stroke-width:.5}.inset .j{fill:none;stroke:#8c7a68;stroke-width:1.3}
.mstamp{position:absolute;width:clamp(62px,9.4%,96px);transform:translate(-50%,-50%) rotate(var(--r,0deg));transition:transform .3s cubic-bezier(.3,1.4,.5,1);z-index:2}
.mstamp:hover,.mstamp:focus-visible{transform:translate(-50%,-50%) rotate(0deg) scale(1.1);z-index:3}
.mstamp .stack{position:relative}
.mstamp .stack::before,.mstamp .stack::after{content:"";position:absolute;inset:0;background:radial-gradient(circle,transparent 0 3.2px,var(--card) 3.7px) -6px -6px/12px 12px;filter:drop-shadow(0 1px 2px rgba(70,45,25,.2))}
.mstamp .stack::before{transform:rotate(-8deg) translate(-4px,2px)}
.mstamp .stack::after{transform:rotate(6deg) translate(4px,3px)}
.mstamp .stack .stamp{position:relative;z-index:1}
.mstamp .lab{position:absolute;left:50%;top:100%;transform:translateX(-50%);margin-top:6px;white-space:nowrap;font-family:var(--hand);font-size:clamp(16px,1.5vw,21px);color:var(--ink);text-shadow:0 0 6px var(--card),0 0 4px var(--card)}
.badge{position:absolute;right:-14px;top:-14px;z-index:4;width:34px;height:34px;border-radius:50%;border:2px solid var(--red);color:var(--red);background:rgba(255,253,248,.9);display:flex;align-items:center;justify-content:center;font-family:var(--num);font-style:italic;font-size:20px;font-weight:600;transform:rotate(-10deg)}

/* ---------- home: sections ---------- */
.sec{max-width:1440px;margin:0 auto;padding:70px 0 40px}
.sec-h{display:flex;align-items:baseline;gap:18px;padding:0 68px;margin-bottom:26px}
.sec-h h2{font-family:var(--hand);font-weight:400;font-size:44px;margin:0;line-height:1}
.sec-h span{color:var(--ink2);font-size:16px}
.drift{overflow-x:auto;overflow-y:hidden;scrollbar-width:none;padding:18px 0 30px;cursor:grab}
.drift::-webkit-scrollbar{display:none}
.drift .track{display:flex;gap:34px;width:max-content;padding:0 40px}
.pc{position:relative;flex:none;width:210px;background:var(--card);padding:11px 11px 0;box-shadow:0 1px 1px rgba(0,0,0,.05),0 14px 26px -16px rgba(80,50,20,.55);transform:rotate(var(--r,0deg));transition:transform .3s cubic-bezier(.3,1.4,.5,1),box-shadow .3s;text-align:left}
.pc:hover{transform:rotate(0) translateY(-6px) scale(1.03);box-shadow:0 22px 34px -18px rgba(80,50,20,.6);z-index:2}
.pc img,.pc .art{width:100%;aspect-ratio:4/5;object-fit:cover}
.pc .cap{padding:10px 4px 12px;display:flex;justify-content:space-between;align-items:baseline;gap:8px}
.pc .t{font-family:var(--hand);font-size:24px;line-height:1.2;white-space:nowrap}
.pc .d{font-family:var(--num);font-style:italic;font-size:17px;color:var(--ink2);white-space:nowrap}
.pc .play{position:absolute;left:50%;top:calc(11px + (100% - 11px) * .0 + 42%);width:46px;height:46px;margin:-23px 0 0 -23px;border-radius:50%;background:rgba(255,253,248,.82);display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .25s}
.pc:hover .play{opacity:1}
.play svg{width:18px;height:18px;margin-left:3px;fill:var(--ink)}
.drift.row2 .pc{width:180px}

/* years: clothesline */
.years{padding:0 40px}
.year{display:grid;grid-template-columns:150px 1fr;align-items:start;margin-bottom:34px}
.year .y{font-family:var(--num);font-style:italic;font-weight:500;font-size:64px;line-height:1;color:var(--ink);padding:26px 0 0 28px}
.year .y small{display:block;font-family:var(--body);font-style:normal;font-size:15px;color:var(--ink2);margin-top:8px}
.line{position:relative;padding-top:30px;overflow-x:auto;scrollbar-width:none}
.line::-webkit-scrollbar{display:none}
.rope{position:absolute;left:0;right:0;top:0;height:46px;pointer-events:none}
.rope path{fill:none;stroke:#a88f72;stroke-width:1.6}
.hung{display:flex;gap:30px;padding:0 20px 20px;width:max-content;min-width:100%}
.hang{position:relative;padding-top:6px}
.hang .pc{width:168px;transform-origin:50% -6px;transform:rotate(var(--r,0deg))}
.hang .pc .t{font-size:21px}.hang .pc .d{font-size:15px}
.peg{position:absolute;left:50%;top:-8px;width:12px;height:30px;margin-left:-6px;border-radius:2px;background:linear-gradient(90deg,#c9a479,#dcbb90 45%,#b38d62);z-index:3;box-shadow:0 1px 2px rgba(0,0,0,.2)}
.peg::after{content:"";position:absolute;left:5px;top:3px;bottom:3px;width:1px;background:rgba(90,60,30,.35)}
.hang:hover .pc{animation:sway 1.2s ease-in-out}
@keyframes sway{30%{transform:rotate(calc(var(--r,0deg) + 3deg))}65%{transform:rotate(calc(var(--r,0deg) - 2deg))}}
.foot{text-align:center;padding:40px 0 18px;font-family:var(--hand);font-size:26px;color:var(--ink3)}

/* ---------- place ---------- */
.place{display:grid;grid-template-columns:minmax(330px,430px) minmax(0,1fr);gap:72px;max-width:1240px;margin:0 auto;padding:6px 48px 80px}
.place-l{position:sticky;top:84px;align-self:start}
.place h1{font-family:var(--hand);font-weight:400;font-size:88px;line-height:1;margin:0 0 10px 6px}
.place .sub{color:var(--ink2);font-size:19px;margin:0 0 30px 10px}
.place .sub .num{font-size:1.25em;color:var(--red)}
.place .mapsheet{padding:16px 16px 14px}
.maphint{margin:16px 6px 0;color:var(--ink3);font-size:15px;text-align:center}
.pmap{position:relative}
.pmap svg.base{position:absolute;inset:0;width:100%;height:100%;overflow:hidden}
.dist{fill:#f7f1e6;stroke:#c3ad90;stroke-width:.5}
.dname{font-size:8px;fill:#b3a089;letter-spacing:1px;font-family:var(--body)}
/* 足迹红点：悬停 / 选中时变大，选中的那本在点上方浮出一枚照片邮票 */
.mdot{fill:var(--red);stroke:#fbf6ec;cursor:pointer;opacity:.82;transform-box:fill-box;transform-origin:center;transition:transform .25s cubic-bezier(.3,1.4,.5,1),opacity .2s}
.mdot.hl,.mdot:hover{transform:scale(1.5);opacity:1}
.mdot.far{fill:#fbf6ec;stroke:var(--red)}
.mdot.far.on{fill:#c23f24;stroke:#fbf6ec}
.mdot.on{transform:scale(1.7);opacity:1;fill:#c23f24}
.mpin{position:absolute;width:clamp(64px,22%,92px);transform:translate(-50%,calc(-100% - 12px));z-index:3;animation:pinpop .45s cubic-bezier(.3,1.4,.5,1)}
.mpin.dn{transform:translate(-50%,12px)}
.mpin button{display:block;width:100%;transform:rotate(-3deg)}
.mpin .stamp{padding:5px;background-size:10px 10px;background-position:-5px -5px}
.mpin .n{position:absolute;left:50%;bottom:100%;transform:translateX(-50%);margin-bottom:3px;white-space:nowrap;font-family:var(--hand);font-size:17px;text-shadow:0 0 5px var(--card),0 0 3px var(--card),0 0 2px var(--card)}
.mpin.dn .n{bottom:auto;top:100%;margin:3px 0 0}
@keyframes pinpop{from{opacity:0;margin-top:8px}}
/* 时间线 */
.tl{padding-top:14px;max-width:700px}
.tl-y h2{display:flex;align-items:baseline;gap:14px;margin:26px 0 8px;font-weight:400}
.tl-y h2 span{font-family:var(--num);font-style:italic;font-size:54px;line-height:1;color:var(--red)}
.tl-y h2 small{font-size:16px;color:var(--ink3)}
.tl-y ol{list-style:none;margin:0;padding:0 0 0 30px;border-left:2px dotted rgba(180,140,100,.45);margin-left:12px}
.ti{position:relative;margin:0}
.ti::before{content:"";position:absolute;left:-38px;top:31px;width:12px;height:12px;border-radius:50%;background:var(--paper);box-shadow:inset 0 0 0 2.5px var(--red);transition:background .2s,transform .25s}
.ti.on::before,.ti.hl::before{background:var(--red);transform:scale(1.15)}
.ti-h{display:grid;grid-template-columns:118px 1fr auto;align-items:center;gap:18px;width:100%;padding:12px 14px 12px 6px;border-radius:14px;text-align:left;transition:background .2s}
.ti-h:hover,.ti.hl .ti-h{background:rgba(255,253,248,.7)}
.ti.on .ti-h{background:rgba(255,253,248,.85)}
.ti-d{font-family:var(--num);font-style:italic;color:var(--ink);white-space:nowrap}
.ti-d b{font-weight:500;font-size:34px}
.ti-d i{font-family:var(--body);font-style:normal;font-size:15px;color:var(--ink2);margin:0 3px 0 2px}
.ti-m{min-width:0}
.ti-m strong{display:block;font-family:var(--hand);font-weight:400;font-size:30px;line-height:1.25;color:var(--ink)}
.ti-p{display:flex;align-items:center;gap:3px;color:var(--ink2);font-size:15px;margin-top:2px}
.ti-p:empty{display:none}
.ti-p svg{width:14px;height:14px;fill:var(--red);flex:none}
.ti-th{width:74px;padding:4px;background:var(--card);box-shadow:0 6px 14px -8px rgba(80,50,20,.5);transform:rotate(2deg);transition:opacity .3s,transform .3s}
.ti-th img,.ti-th .art{display:block;width:100%;aspect-ratio:1;object-fit:cover}
.ti.on .ti-th{opacity:0;transform:rotate(2deg) scale(.8)}
/* 展开：大照片 + 一句话 + 看相册按钮 */
.ti-x{display:grid;grid-template-rows:0fr;transition:grid-template-rows .45s cubic-bezier(.22,1,.36,1)}
.ti.on .ti-x{grid-template-rows:1fr}
.ti-xi{overflow:hidden;display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:24px;align-items:center;padding:0 14px 0 6px}
.ti.on .ti-xi{padding:6px 14px 26px 6px}
.ti-ph{position:relative;display:block;background:var(--card);padding:9px;box-shadow:0 16px 30px -20px rgba(80,50,20,.6);transform:rotate(-1.2deg);transition:transform .3s cubic-bezier(.3,1.4,.5,1)}
.ti-ph:hover{transform:rotate(0) translateY(-4px)}
.ti-ph img,.ti-ph .art{display:block;width:100%;aspect-ratio:4/3;object-fit:cover}
.ti-ph .play{position:absolute;left:50%;top:50%;width:58px;height:58px;margin:-29px 0 0 -29px;border-radius:50%;background:rgba(30,22,16,.5);display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}
.ti-ph .play svg{width:22px;height:22px;fill:#fff;margin-left:3px}
.ti-n{margin:0;color:var(--ink);font-size:18px;line-height:1.75}
.ti-ph .dur{position:absolute;right:18px;bottom:18px;padding:3px 11px;border-radius:20px;background:rgba(30,22,16,.55);color:#fff;font-family:var(--num);font-style:italic;font-size:16px;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}

/* ---------- album ---------- */
#albumPanel{position:relative;transition:background-color .9s ease,color .9s ease}
body.dark{background-color:var(--night)}
body.dark #albumPanel{background:var(--night);color:#efe3d2}
body.dark #albumPanel .back{background:rgba(255,255,255,.1);color:#efe3d2;box-shadow:none}
.stage{position:relative;display:grid;grid-template-columns:auto minmax(320px,440px);gap:72px;justify-content:center;align-items:center;min-height:calc(100vh - 80px);padding:0 120px 60px;touch-action:pan-y}
.frame{position:relative;background:var(--card);padding:14px 14px 54px;box-shadow:0 30px 60px -30px rgba(60,35,15,.6);transform:rotate(-1.2deg);transition:transform .8s cubic-bezier(.3,.8,.2,1),box-shadow .8s,background .8s}
body.dark .frame{transform:rotate(0);background:#1a1411;box-shadow:0 30px 80px -20px rgba(0,0,0,.7)}
.screen{position:relative;height:min(74vh,720px);aspect-ratio:var(--ar,9/16);background:#111;overflow:hidden}
.screen img,.screen video,.screen .art{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.screen video{opacity:0;transition:opacity .4s}
.playing .screen video{opacity:1}
.bigplay{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;background:linear-gradient(180deg,transparent 50%,rgba(0,0,0,.25));transition:opacity .35s}
.bigplay .c{width:96px;height:96px;border-radius:50%;background:rgba(255,253,248,.92);display:flex;align-items:center;justify-content:center;box-shadow:0 10px 30px rgba(0,0,0,.25);transition:transform .25s}
.bigplay:hover .c{transform:scale(1.07)}
.bigplay .c svg{width:34px;height:34px;margin-left:6px;fill:var(--ink)}
.bigplay span{color:#fff;font-size:19px;text-shadow:0 1px 6px rgba(0,0,0,.5);letter-spacing:.1em}
.playing .bigplay{opacity:0;pointer-events:none}
.screen.wait .bigplay .c{animation:pulse 1s infinite}
.ctrl{position:absolute;left:10px;right:10px;bottom:8px;display:flex;align-items:center;gap:10px;height:40px;opacity:0;transition:opacity .4s;color:#e2d4c2;font-size:15px}
.playing .ctrl,.paused .ctrl{opacity:1}
.ctrl button{width:40px;height:40px;flex:none;display:flex;align-items:center;justify-content:center;border-radius:50%}
.ctrl button svg{width:18px;height:18px;fill:currentColor}
.ctrl .bar{flex:1;height:40px;display:flex;align-items:center;cursor:pointer;touch-action:none}
.ctrl .track{position:relative;width:100%;height:6px;border-radius:3px;background:rgba(255,255,255,.22)}
.ctrl .fill{position:absolute;left:0;top:0;bottom:0;width:0;border-radius:3px;background:#e9b98f}
.ctrl .fill::after{content:"";position:absolute;right:-8px;top:50%;width:16px;height:16px;margin-top:-8px;border-radius:50%;background:#f6d7bb;box-shadow:0 1px 4px rgba(0,0,0,.4)}
.ctrl .tm{flex:none;font-size:14px;min-width:84px;text-align:right;text-shadow:0 1px 3px rgba(0,0,0,.6)}
.screen::after{content:"";position:absolute;left:0;right:0;bottom:0;height:90px;background:linear-gradient(transparent,rgba(0,0,0,.45));opacity:0;transition:opacity .4s;pointer-events:none}
.playing .screen::after,.paused .screen::after{opacity:1}
.paused .bigplay{opacity:1}
.paused .bigplay .c{transform:scale(.85)}
.frame .cap{position:absolute;left:0;right:0;bottom:12px;text-align:center;font-family:var(--hand);font-size:22px;color:var(--ink2);transition:opacity .4s}
.playing .frame .cap{opacity:0}
.info{position:relative}
.info .pm{position:absolute;right:-10px;top:-80px;width:120px;transform:rotate(-12deg)}
.pmd{fill:currentColor;font-family:var(--num);font-style:italic}
.info .date{font-family:var(--num);font-style:italic;font-size:30px;color:var(--red);line-height:1}
body.dark .info .date{color:#e9a98a}
.info h1{font-family:var(--hand);font-weight:400;font-size:72px;line-height:1.1;margin:12px 0 6px}
.info .where{color:var(--ink2);font-size:18px;display:flex;align-items:center;gap:6px}
body.dark .info .where,body.dark .info .note{color:#bfae99}
.info .where svg{width:16px;height:16px;fill:currentColor}
.info .note{font-size:23px;line-height:1.7;margin:26px 0 30px;color:var(--ink)}
.vers{display:flex;gap:12px;flex-wrap:wrap}
.vers button{height:48px;padding:0 20px;border-radius:24px;box-shadow:inset 0 0 0 1.5px var(--line);font-size:17px}
.vers button .num{font-size:18px;margin-left:6px;opacity:.75}
.vers button.on{background:var(--ink);color:var(--paper);box-shadow:none}
body.dark .vers button{box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.2)}
body.dark .vers button.on{background:#efe3d2;color:var(--night)}
.flip{position:fixed;top:50%;width:64px;height:64px;margin-top:-32px;border-radius:50%;background:rgba(255,253,248,.88);box-shadow:0 6px 20px -8px rgba(80,50,20,.4);display:flex;align-items:center;justify-content:center;z-index:10;transition:background .8s}
.flip svg{width:26px;height:26px;stroke:var(--ink);stroke-width:2.2;fill:none}
.flip.prev{left:28px}.flip.next{right:28px}
.flip .tip{position:absolute;top:100%;margin-top:10px;white-space:nowrap;font-family:var(--hand);font-size:19px;color:var(--ink2)}
body.dark .flip{background:rgba(255,255,255,.1)}
body.dark .flip svg{stroke:#efe3d2}
.nextup{display:none;align-items:center;gap:14px;margin:34px 0 0;padding:12px 20px 12px 12px;border-radius:16px;background:rgba(255,253,248,.7);width:100%;max-width:420px;text-align:left;box-shadow:0 8px 22px -14px rgba(80,50,20,.35);transition:transform .25s}
.nextup:hover{transform:translateY(-2px)}
body.dark .nextup{background:rgba(255,255,255,.07)}
.nextup .stamp{width:54px}
.nextup small{display:block;color:var(--ink2);font-size:15px}
.nextup strong{display:block;font-family:var(--hand);font-weight:400;font-size:25px}
.nextup .go{margin-left:auto;font-size:24px;color:var(--ink3)}
.ended .nextup{box-shadow:0 0 0 2px var(--red),0 8px 22px -14px rgba(80,50,20,.35)}
.slide-l{animation:slideL .5s cubic-bezier(.3,.7,.2,1)}
.slide-r{animation:slideR .5s cubic-bezier(.3,.7,.2,1)}
@keyframes slideL{from{opacity:0;transform:translateX(70px)}to{opacity:1;transform:none}}
@keyframes slideR{from{opacity:0;transform:translateX(-70px)}to{opacity:1;transform:none}}
.flyer{position:fixed;z-index:60;object-fit:cover;pointer-events:none;transition:all .6s cubic-bezier(.3,.7,.2,1);box-shadow:0 20px 40px rgba(0,0,0,.25)}

/* ================= phone ================= */
@media (max-width:760px){
  html,body{font-size:17px}
  .topbar{padding:calc(10px + var(--sat)) 16px 8px}
  .brand{font-size:20px}.brand svg{width:36px;height:36px}
  .back{height:46px;font-size:18px;padding:0 18px 0 12px}
  .hero{display:block;padding:0 16px 10px;min-height:0}
  .greet{padding:8px 6px 0}
  .greet .pre{font-size:24px}
  .greet h1{font-size:33px;line-height:1.45}
  .mapsheet{margin:30px -2px 0;padding:12px 10px 10px;transform:rotate(.4deg)}
  .tape{width:90px;height:24px;margin-left:-45px}
  .tape.r{display:none}
  .mstamp{width:44px}
  .inset{right:auto;left:1.5%}
  .mstamp .lab{font-size:15px;margin-top:1px}
  .badge{width:26px;height:26px;font-size:16px;right:-12px;top:-12px}
  .inset{width:15%}
  .latest{margin-top:26px;width:100%}
  .latest .stamp{width:58px}
  .latest strong{font-size:25px}
  .shuffle{margin-top:14px}
  .sec{padding:46px 0 20px}
  .sec-h{padding:0 22px;margin-bottom:10px}
  .sec-h h2{font-size:36px}
  .drift .track{gap:20px;padding:0 20px}
  .pc{width:168px;padding:8px 8px 0}
  .pc .t{font-size:21px}.pc .d{font-size:15px}
  .drift.row2 .pc{width:150px}
  .years{padding:0}
  .year{display:block;margin-bottom:22px}
  .year .y{font-size:46px;padding:0 0 4px 22px}
  .year .y small{display:inline;margin-left:10px}
  .hang .pc{width:146px}
  .hung{gap:20px}
  .place{display:block;padding:0 16px 60px}
  .place-l{position:static}
  .place h1{font-size:64px;margin:4px 0 2px 4px}
  .place .sub{font-size:17px;margin:0 0 16px 6px}
  .place .mapsheet{margin:22px 6px 0;padding:10px}
  .maphint{font-size:14px;margin-top:10px}
  .mpin{width:60px}.mpin .n{font-size:15px}
  .tl{padding-top:4px}
  .tl-y h2{margin:22px 0 4px}
  .tl-y h2 span{font-size:42px}
  .tl-y ol{padding-left:16px;margin-left:6px}
  .ti::before{left:-23px;top:27px;width:10px;height:10px}
  .ti-h{grid-template-columns:auto 1fr auto;gap:12px;padding:10px 8px 10px 4px}
  .ti-d b{font-size:26px}.ti-d i{font-size:13px;margin:0 2px 0 1px}
  .ti-m strong{font-size:25px}
  .ti-p{font-size:14px}
  .ti-th{width:56px}
  .ti-xi{grid-template-columns:1fr;gap:14px;padding:0 6px 0 4px}
  .ti.on .ti-xi{padding:4px 6px 22px 4px}
  .ti-n{font-size:17px;margin:0 2px}
  .stage{display:block;padding:0 16px 40px;min-height:0}
  .frame{padding:10px 10px 44px;margin:6px auto 0;width:fit-content;max-width:100%}
  .screen{height:min(60vh,560px);max-width:calc(100vw - 52px)}
  .bigplay .c{width:84px;height:84px}
  .frame .cap{font-size:19px;bottom:9px}
  .info{padding:28px 6px 0}
  .info .pm{right:0;top:6px;width:96px}
  .info .date{font-size:26px}
  .info h1{font-size:52px}
  .info .note{font-size:20px;margin:16px 0 22px}
  .flip{display:none}
  .nextup{display:flex;max-width:none}
  .nextup{display:flex;align-items:center;gap:14px;margin:34px 0 0;padding:12px 18px 12px 12px;border-radius:16px;background:rgba(255,253,248,.7);width:100%;text-align:left;box-shadow:0 8px 22px -14px rgba(80,50,20,.35)}
  body.dark .nextup{background:rgba(255,255,255,.07)}
  .nextup .stamp{width:54px}
  .nextup small{display:block;color:var(--ink2);font-size:15px}
  .nextup strong{display:block;font-family:var(--hand);font-weight:400;font-size:25px}
  .nextup .go{margin-left:auto;font-size:24px;color:var(--ink3)}
}
@container (max-width:72px){.art small,.art em{display:none}}
.pc .t{overflow:hidden;text-overflow:ellipsis;min-width:0}

#home .topbar{position:relative}
.hang .pc{width:190px}

/* ---------- v3 additions ---------- */
.sr-only{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
#loading{position:fixed;inset:0;z-index:40;display:flex;align-items:center;justify-content:center;pointer-events:none;transition:opacity .5s}
#loading.done{opacity:0}
#loading .dot{width:12px;height:12px;border-radius:50%;background:var(--red);animation:pulse 1.2s ease-in-out infinite}
@keyframes pulse{50%{transform:scale(1.5);opacity:.5}}
#home .topbar{position:relative}
.hang .pc{width:190px}
/* 家：红色方印 */
.chop{position:relative;display:flex;align-items:center;justify-content:center;aspect-ratio:1;border-radius:9%;background:#b23a25;color:#fbe9df;font-family:var(--hand);line-height:1;box-shadow:0 3px 8px -2px rgba(120,30,10,.45);container-type:inline-size;overflow:hidden}
.chop::before{content:"";position:absolute;inset:8%;border:1.5px solid rgba(251,233,223,.75);border-radius:6%}
.chop::after{content:"";position:absolute;inset:0;background:var(--grain);mix-blend-mode:screen;opacity:.9}
.chop b{font-weight:400;font-size:62cqw;transform:translateY(-3%)}
.mhome{position:absolute;width:clamp(50px,7.4%,76px);transform:translate(-50%,-50%) rotate(var(--r,0deg));transition:transform .3s cubic-bezier(.3,1.4,.5,1);z-index:3}
.mhome:hover,.mhome:focus-visible{transform:translate(-50%,-50%) rotate(0) scale(1.1)}
.mhome[disabled]{cursor:default}
.mhome .lab{position:absolute;left:50%;top:100%;transform:translateX(-50%);margin-top:6px;white-space:nowrap;font-family:var(--hand);font-size:clamp(16px,1.5vw,21px);color:var(--ink);text-shadow:0 0 6px var(--card),0 0 4px var(--card)}
.mhome .badge{right:-16px;top:-16px}
.glow{fill:url(#homeGlow)}
.route{fill:none;stroke:var(--red);stroke-width:1.3;stroke-dasharray:1 6;stroke-linecap:round;opacity:.5}
.place h1{display:flex;align-items:center;gap:20px}
.place h1 .chop{width:.62em;font-size:1em;transform:rotate(-4deg)}
.where .chop{width:22px;display:inline-flex;transform:none;box-shadow:none}
.pmap.nogeo{background:repeating-linear-gradient(0deg,transparent 0 38px,rgba(180,160,130,.12) 38px 39px)}
.err{max-width:520px;margin:30vh auto 0;text-align:center;font-size:20px;color:var(--ink2);padding:0 20px}
.empty-note{padding:0 68px;color:var(--ink2)}
.drift.static{cursor:default}
.drift.static .track{margin:0 auto}
@media (max-width:760px){
  .mhome{width:40px}
  .mhome .lab{font-size:15px;margin-top:2px}
  .mhome .badge{right:-12px;top:-12px}
  .place h1{gap:12px}
  .empty-note{padding:0 22px}
}
.dist.f{fill:#f9efe3}
.paused .screen video{opacity:1}

/* 地图往外扩时：周边国家、主图里的南海诸岛、贴边的远方 */
.map.expanded svg.base{overflow:hidden}
.world path{fill:#f1eadf;stroke:#d3c5ae;stroke-width:.7;stroke-linejoin:round}
.scs-i{fill:#f7f1e6;stroke:#bba78d;stroke-width:.6}
.scs-j{fill:none;stroke:#8c7a68;stroke-width:1.6}
.map.scs .inset{display:none}
.edge{fill:var(--card);stroke:var(--red);stroke-width:2;stroke-dasharray:2 2}

.code-boxes.shake{animation:shake .5s}
@keyframes shake{20%,60%{transform:translateX(-8px)}40%,80%{transform:translateX(8px)}}
.flip.pulse{animation:nudge 1.6s ease-in-out infinite;box-shadow:0 0 0 2px var(--red),0 6px 20px -8px rgba(80,50,20,.4)}
@keyframes nudge{50%{transform:translateX(6px)}}

/* ICP 备案号：首页最底部，小字不显眼 */
.beian{text-align:center;padding:4px 0 calc(70px + var(--sab));font-family:var(--body);font-size:12px;line-height:1.6}
.beian a{color:var(--ink3);text-decoration:none;opacity:.85}
.beian a:hover{text-decoration:underline}
