Files
admin 0593ff7e62
nginx serve /uploads direct (audio speed) / patch-nginx (push) Failing after 1m34s
数字我 Digital Me:全量入库(大文件走 Git LFS)
2026-10-10 16:24:43 +08:00

116 lines
26 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>无字卷|若生于乱世,你会是谁?</title>
<style>
:root{--ink:#27261f;--red:#8b3c30;--paper:#e7d8b8;--gold:#d5ad6d}
*{box-sizing:border-box}html,body{margin:0;width:100%;height:100%;overflow:hidden;background:#0a0e0e;color:var(--ink);font-family:"Noto Serif SC","Songti SC","STSong",serif}button{font:inherit}.app{position:relative;width:100%;height:100%;overflow:hidden;background:radial-gradient(circle at 50% 48%,#f1e4c9 0,#d6c19a 65%,#aa8d63 100%);isolation:isolate}.app:before{content:"";position:absolute;z-index:0;inset:-3%;background:url('assets/homepage-origin.png') center/cover no-repeat;opacity:.08;filter:grayscale(.55) blur(1px);transform:scale(1.04);transition:opacity .8s}.grain{position:absolute;z-index:90;inset:0;pointer-events:none;opacity:.13;mix-blend-mode:multiply;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence baseFrequency='.76' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.2'/%3E%3C/svg%3E")}
.topbar{position:absolute;z-index:100;top:0;left:0;right:0;height:72px;padding:0 36px;display:flex;align-items:center;justify-content:space-between;color:#4d473b;transition:color .7s,opacity .5s}.brand{font-weight:700;letter-spacing:.34em}.brand small{font:10px Arial,sans-serif;letter-spacing:.18em;opacity:.55;margin-left:12px}.sound{width:39px;height:39px;border:1px solid rgba(61,54,43,.3);border-radius:50%;background:rgba(243,233,211,.18);color:inherit;cursor:pointer}
.intro{position:absolute;z-index:10;inset:78px 5vw 34px;display:flex;flex-direction:column;align-items:center;text-align:center;transition:opacity .55s,transform .75s,filter .55s}.kicker{font:11px Arial,sans-serif;letter-spacing:.32em;color:var(--red);margin-top:1.5vh}.intro h1{font-size:clamp(44px,5.8vw,82px);font-weight:500;line-height:1.15;letter-spacing:.08em;margin:2vh 0 1.1vh}.intro h1 span{display:block}.intro p{margin:0;max-width:680px;font-size:15px;line-height:1.9;color:#645d50;letter-spacing:.035em}.scroll-zone{width:min(920px,87vw);margin:auto 0;position:relative;display:flex;flex-direction:column;align-items:center}.scroll-button{border:0;background:transparent;width:100%;padding:0;cursor:pointer;position:relative;filter:drop-shadow(0 22px 20px rgba(71,52,29,.2));transition:transform .5s,filter .5s}.scroll-button img{display:block;width:100%;height:auto}.scroll-button:after{content:"启卷";position:absolute;left:50%;top:58%;transform:translate(-50%,-50%);width:48px;height:48px;display:grid;place-items:center;color:#ead8bd;font-size:11px;letter-spacing:.1em;writing-mode:vertical-rl;opacity:.92}.scroll-button:hover{transform:translateY(-6px) scale(1.012);filter:drop-shadow(0 30px 25px rgba(71,52,29,.28))}.scroll-button:hover:before{content:"";position:absolute;left:50%;top:55%;width:54px;height:54px;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 12px rgba(143,62,49,.08),0 0 35px rgba(143,62,49,.2);animation:ring 1.5s infinite}.prompt{margin-top:-3.2%;font-size:12px;letter-spacing:.23em;color:#675e4d}.subprompt{font:10px Arial,sans-serif;letter-spacing:.08em;color:#8b806b;margin-top:8px}@keyframes ring{50%{box-shadow:0 0 0 19px rgba(143,62,49,0),0 0 45px rgba(143,62,49,.3)}}
.app.is-opening{background:#080c0c}.app.is-opening:before{opacity:0}.app.is-opening .intro{opacity:0;transform:scale(.96);filter:blur(5px);pointer-events:none}.app.is-opening .topbar{color:#d9c8aa}.portal{position:absolute;z-index:30;inset:0;opacity:0;pointer-events:none;clip-path:inset(0 47% 0 47% round 44%);transform:scale(.76,.86);filter:blur(3px) brightness(.62);transform-origin:50% 53%;background:url('assets/homepage-open-scroll-cinematic.png') center/contain no-repeat;transition:clip-path 2.55s cubic-bezier(.5,.02,.14,1),opacity .25s,transform 3.15s cubic-bezier(.16,.75,.16,1),filter 2s}.app.portal-open .portal{opacity:1;clip-path:inset(0 0 0 0 round 0);transform:scale(1.035);filter:none;pointer-events:auto}
.unfurl-roll{position:absolute;z-index:48;left:50%;top:52%;width:64px;height:min(58vh,590px);opacity:0;border-radius:35px;background:linear-gradient(90deg,#58391f 0,#b7894c 7%,#e2c388 22%,#f2dca7 46%,#c79a5b 72%,#6d4727 94%,#2a1a11);border:1px solid rgba(57,33,18,.8);box-shadow:0 18px 35px rgba(0,0,0,.45),0 0 26px rgba(226,155,67,.2);transform-origin:center}.unfurl-roll:before{content:"";position:absolute;inset:3px 7px;background:repeating-linear-gradient(90deg,rgba(73,43,23,.1) 0 1px,transparent 1px 5px);border-radius:30px;mix-blend-mode:multiply}.unfurl-roll i{position:absolute;left:50%;bottom:-11px;width:72px;height:29px;transform:translateX(-50%);border-radius:50%;background:repeating-radial-gradient(ellipse at center,#382115 0 4px,#c39659 5px 9px,#6b4328 10px 13px);border:2px solid #3d281a;box-shadow:0 5px 12px rgba(0,0,0,.45)}.app.is-opening .roll-left{animation:rollLeft 2.75s .18s cubic-bezier(.5,.02,.13,1) forwards}.app.is-opening .roll-right{animation:rollRight 2.75s .18s cubic-bezier(.5,.02,.13,1) forwards}@keyframes rollLeft{0%{opacity:0;transform:translate(-108%,-50%) rotate(-1deg) scale(.92)}8%{opacity:1}74%{opacity:1}100%{opacity:0;transform:translate(calc(-34vw - 50%),-50%) rotate(-8deg) scale(1.02)}}@keyframes rollRight{0%{opacity:0;transform:translate(8%,-50%) rotate(1deg) scale(.92)}8%{opacity:1}74%{opacity:1}100%{opacity:0;transform:translate(calc(34vw - 50%),-50%) rotate(8deg) scale(1.02)}}
.route-glow{position:absolute;z-index:3;left:29%;top:37%;width:53%;height:28%;overflow:visible;opacity:0;transform:rotate(-4deg);filter:drop-shadow(0 0 5px #ffc968) drop-shadow(0 0 13px rgba(240,147,36,.7));pointer-events:none}.route-glow path{fill:none;stroke:#ffd47d;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:1120;stroke-dashoffset:1120}.route-glow circle{fill:#fff2b0;opacity:0}.app.portal-open .route-glow{animation:routeFade 3.25s .75s ease forwards}.app.portal-open .route-glow path{animation:traceRoute 2.25s .9s cubic-bezier(.38,.05,.18,1) forwards}.app.portal-open .route-glow circle{animation:nodeGlow .45s var(--delay) ease forwards}@keyframes traceRoute{to{stroke-dashoffset:0}}@keyframes nodeGlow{to{opacity:1}}@keyframes routeFade{0%{opacity:0}12%{opacity:.9}72%{opacity:.88}100%{opacity:0}}
.origin-copy{position:absolute;z-index:5;left:19.5%;top:18%;width:min(475px,37vw);padding:18px 24px 20px;color:#211a13;text-shadow:0 1px 0 rgba(255,244,211,.78),0 0 12px rgba(245,225,181,.28);transform:translateY(13px);opacity:0;transition:opacity .8s .15s,transform .9s .15s}.origin-copy:before{content:"";position:absolute;z-index:-1;inset:-12px -34px -16px -24px;background:linear-gradient(90deg,rgba(231,211,171,.8) 0%,rgba(232,213,174,.58) 66%,rgba(232,213,174,0) 100%);filter:blur(7px);border-left:2px solid rgba(110,55,36,.35)}.app.story-visible .origin-copy{opacity:1;transform:none}.chapter{font:700 11px Arial,sans-serif;letter-spacing:.28em;color:#7e392c}.origin-copy h2{font-size:clamp(29px,3.2vw,50px);line-height:1.3;font-weight:700;letter-spacing:.045em;margin:12px 0 17px;max-width:9em;color:#241b13}.story-lines{font-size:clamp(14px,1.05vw,16px);font-weight:600;line-height:1.85;color:#3b2d20}.story-lines span{display:block;opacity:0;transform:translateY(7px);transition:.5s}.app.story-visible .story-lines span{opacity:1;transform:none}.story-lines span:nth-child(1){transition-delay:.6s}.story-lines span:nth-child(2){transition-delay:.9s}.story-lines span:nth-child(3){transition-delay:1.2s}.story-lines span:nth-child(4){transition-delay:1.55s;color:#7b261f;margin-top:5px;font-size:1.08em}.continue{position:relative;margin-top:20px;border:1px solid rgba(70,38,26,.72);background:rgba(228,199,145,.78);box-shadow:0 3px 12px rgba(60,34,20,.12);color:#3f2019;padding:12px 21px;font-weight:600;letter-spacing:.13em;opacity:0;transform:translateY(8px);transition:opacity .55s 1.8s,transform .55s 1.8s,background .25s,color .25s;cursor:pointer;overflow:hidden}.app.story-visible .continue{opacity:1;transform:none}.continue:before{content:"";position:absolute;inset:0;background:linear-gradient(100deg,transparent,rgba(255,245,207,.75),transparent);transform:translateX(-120%)}.continue:hover{background:#7d392e;color:#f5e8cf}.continue:hover:before{transition:transform .7s;transform:translateX(120%)}.chapter-mark{position:absolute;z-index:5;right:11%;bottom:10%;color:#d4b27b;font-size:11px;letter-spacing:.22em;opacity:0;transition:opacity .6s 1.3s}.app.story-visible .chapter-mark{opacity:.8}
.next-module{position:absolute;z-index:4;inset:-6%;display:grid;place-items:center;background:linear-gradient(rgba(12,13,11,.43),rgba(7,8,7,.58)),url('assets/story-01-fire.png') center/cover no-repeat;opacity:0;transform:scale(.74);filter:blur(9px);transition:opacity 1.1s,transform 2.25s cubic-bezier(.16,.72,.18,1),filter 1.4s}.next-module:after{content:"";position:absolute;inset:0;background:radial-gradient(circle at center,transparent 30%,rgba(0,0,0,.58) 100%)}.next-copy{position:relative;z-index:2;text-align:center;color:#f0dfc3;text-shadow:0 3px 25px #000;opacity:0;transform:translateY(20px);transition:opacity .75s,transform .8s}.next-copy .chapter{color:#d9a767}.next-copy h2{font-weight:500;font-size:clamp(44px,7vw,94px);letter-spacing:.22em;margin:12px 0}.next-copy p{font-size:15px;letter-spacing:.13em;color:#d7c7ad}.app.revealing-next .next-module{opacity:1;transform:scale(1.06);filter:none}.app.leaving-origin .portal{opacity:0;transform:scale(1.28);filter:blur(11px) brightness(.58);transition:opacity 1.15s,transform 1.8s cubic-bezier(.2,.72,.2,1),filter 1.15s}.app.leaving-origin .origin-copy,.app.leaving-origin .chapter-mark{opacity:0!important;transition:opacity .3s!important}.app.next-entered .next-copy{opacity:1;transform:none}.app.next-entered .topbar{opacity:.72}
@media(max-width:760px){.topbar{padding:0 18px}.brand small{display:none}.intro{inset:72px 18px 22px}.intro h1{font-size:42px;margin-top:2vh}.intro p{font-size:13px}.scroll-zone{width:98vw}.prompt{margin-top:-1%;font-size:11px}.portal{background-size:cover;background-position:56% center}.origin-copy{left:8%;top:17%;width:78vw;padding:15px 17px}.origin-copy:before{inset:-8px -22px -10px -13px}.origin-copy h2{font-size:30px}.story-lines{font-size:14px;line-height:1.7}.continue{margin-top:14px;padding:10px 14px}.chapter-mark{display:none}.next-copy p{font-size:12px;padding:0 24px}}@media(prefers-reduced-motion:reduce){*{animation-duration:.01ms!important;transition-duration:.01ms!important;transition-delay:0s!important}}
@media(max-width:760px){.unfurl-roll{width:48px;height:48vh}.unfurl-roll i{width:55px;height:24px}.app.is-opening .roll-left{animation-name:rollLeftMobile}.app.is-opening .roll-right{animation-name:rollRightMobile}@keyframes rollLeftMobile{0%{opacity:0;transform:translate(-105%,-50%) scale(.9)}8%{opacity:1}74%{opacity:1}100%{opacity:0;transform:translate(calc(-40vw - 50%),-50%) rotate(-5deg)}}@keyframes rollRightMobile{0%{opacity:0;transform:translate(5%,-50%) scale(.9)}8%{opacity:1}74%{opacity:1}100%{opacity:0;transform:translate(calc(40vw - 50%),-50%) rotate(5deg)}}.route-glow{left:12%;top:39%;width:78%;height:22%}}
.unfurl-roll{pointer-events:none}
.portal{clip-path:inset(0 47% 0 47% round 8px)}.app.portal-open .portal{clip-path:inset(0 0 0 0 round 0)}
.unfurl-roll{width:285px;height:min(67vh,650px);border:0;border-radius:0;background:url('assets/unfurl-paper-roll-real.png') center/contain no-repeat;box-shadow:none;filter:drop-shadow(0 18px 18px rgba(0,0,0,.44))}.unfurl-roll:before,.unfurl-roll i{display:none}.app.is-opening .roll-left{animation:rollRealLeft 2.75s .18s cubic-bezier(.5,.02,.13,1) forwards}.app.is-opening .roll-right{animation:rollRealRight 2.75s .18s cubic-bezier(.5,.02,.13,1) forwards;filter:brightness(.9) drop-shadow(0 18px 18px rgba(0,0,0,.44))}@keyframes rollRealLeft{0%{opacity:0;transform:translate(-71%,-50%) rotate(-1deg) scale(.94)}8%{opacity:1}74%{opacity:.96}100%{opacity:0;transform:translate(calc(-34vw - 50%),-50%) rotate(-8deg) scale(.9)}}@keyframes rollRealRight{0%{opacity:0;transform:translate(-29%,-50%) rotate(1deg) scale(-.94,.94)}8%{opacity:1}74%{opacity:.94}100%{opacity:0;transform:translate(calc(34vw - 50%),-50%) rotate(8deg) scale(-.9,.9)}}
@media(max-width:760px){.unfurl-roll{width:190px;height:53vh}.app.is-opening .roll-left{animation-name:rollRealLeftMobile}.app.is-opening .roll-right{animation-name:rollRealRightMobile}@keyframes rollRealLeftMobile{0%{opacity:0;transform:translate(-72%,-50%) scale(.9)}8%{opacity:1}74%{opacity:.95}100%{opacity:0;transform:translate(calc(-40vw - 50%),-50%) rotate(-5deg) scale(.86)}}@keyframes rollRealRightMobile{0%{opacity:0;transform:translate(-28%,-50%) scale(-.9,.9)}8%{opacity:1}74%{opacity:.92}100%{opacity:0;transform:translate(calc(40vw - 50%),-50%) rotate(5deg) scale(-.86,.86)}}}
/* Horizontal paired rolls: unfold from the centre toward top and bottom. */
.portal{clip-path:inset(47% 0 47% 0 round 8px)}.app.portal-open .portal{clip-path:inset(0 0 0 0 round 0)}
.app.is-opening .roll-left{animation:rollRealTop 2.75s .18s cubic-bezier(.5,.02,.13,1) forwards}.app.is-opening .roll-right{animation:rollRealBottom 2.75s .18s cubic-bezier(.5,.02,.13,1) forwards}
@keyframes rollRealTop{0%{opacity:0;transform:translate(-50%,-50%) translateY(-52px) rotate(90deg) scale(.94)}8%{opacity:1}74%{opacity:.96}100%{opacity:0;transform:translate(-50%,-50%) translateY(-31vh) rotate(84deg) scale(.9)}}
@keyframes rollRealBottom{0%{opacity:0;transform:translate(-50%,-50%) translateY(52px) rotate(-90deg) scale(.94)}8%{opacity:1}74%{opacity:.94}100%{opacity:0;transform:translate(-50%,-50%) translateY(31vh) rotate(-84deg) scale(.9)}}
@media(max-width:760px){.app.is-opening .roll-left{animation-name:rollRealTopMobile}.app.is-opening .roll-right{animation-name:rollRealBottomMobile}@keyframes rollRealTopMobile{0%{opacity:0;transform:translate(-50%,-50%) translateY(-38px) rotate(90deg) scale(.9)}8%{opacity:1}74%{opacity:.95}100%{opacity:0;transform:translate(-50%,-50%) translateY(-34vh) rotate(86deg) scale(.86)}}@keyframes rollRealBottomMobile{0%{opacity:0;transform:translate(-50%,-50%) translateY(38px) rotate(-90deg) scale(.9)}8%{opacity:1}74%{opacity:.92}100%{opacity:0;transform:translate(-50%,-50%) translateY(34vh) rotate(-86deg) scale(.86)}}}
/* Simplified transition: no auxiliary scroll-roll animation. */
.portal{clip-path:none!important;opacity:0;background-color:#080c0c!important;transform:scale(.9);filter:blur(8px) brightness(.62);transition:opacity 1s ease,transform 1.65s cubic-bezier(.18,.76,.18,1),filter 1.25s ease}.app.portal-open .portal{clip-path:none!important;opacity:1;transform:scale(1.02);filter:none}.app.leaving-origin .portal{opacity:0!important;transform:scale(.95)!important;filter:blur(10px) brightness(.45)!important;pointer-events:none!important;transition:opacity .62s ease,transform .72s ease,filter .62s ease!important}
/* [版本 A 动效优化] 单一合成层完成旋转,不再逐帧计算大图模糊、亮度和双层浮动。 */
.app.scroll-unfurling .scroll-button{pointer-events:none;animation:sealedScrollUnfurl 1100ms linear both;transition:opacity 620ms ease;transform-origin:50% 50%;filter:none;will-change:transform,opacity;backface-visibility:hidden;contain:paint}
.app.scroll-unfurling .scroll-button img{animation:none;transform:translateZ(0);backface-visibility:hidden}
.app.scroll-unfurling .scroll-zone:before{content:"";position:absolute;z-index:-1;left:50%;top:48%;width:42%;height:48%;border-radius:50%;background:radial-gradient(ellipse,rgba(255,239,195,.72),rgba(213,161,82,.24) 46%,transparent 73%);transform:translate3d(-50%,-50%,0) scale(.35);opacity:0;animation:unfurlHalo 1100ms cubic-bezier(.42,0,.2,1) both;will-change:transform,opacity;pointer-events:none}
.app.scroll-unfurling .prompt,.app.scroll-unfurling .subprompt{animation:sealCopyOut .45s ease forwards}
@keyframes sealedScrollUnfurl{0%{transform:translate3d(0,0,0) rotate(0deg) scale(.88);opacity:1;animation-timing-function:cubic-bezier(.42,0,.16,1)}84%{transform:translate3d(0,-4px,0) rotate(93deg) scale(.615);opacity:1;animation-timing-function:cubic-bezier(.2,.65,.35,1)}100%{transform:translate3d(0,0,0) rotate(90deg) scale(.62);opacity:1}}
@keyframes unfurlHalo{0%{opacity:0;transform:translate(-50%,-50%) scale(.35)}18%{opacity:.34}72%{opacity:.72}100%{opacity:0;transform:translate(-50%,-50%) scale(2.5,.9)}}
@keyframes sealCopyOut{to{opacity:0;transform:translateY(-10px)}}
/* [修改 2] 竖直单卷完成后淡出,由两侧实体卷轴和中间画布无缝接替。 */
.app.scroll-fade-out .scroll-button{animation:none;transform:translateY(0) rotate(90deg) scale(.62);opacity:0;filter:drop-shadow(0 34px 30px rgba(71,52,29,.1)) brightness(1.18) blur(4px)}
/* [修改 3] 中间画布从竖直窄缝向左右展开;改用正视水墨素材,纸面上下边缘保持绝对水平。 */
.app{--canvas-unfurl-duration:2400ms;--canvas-unfurl-ease:cubic-bezier(.5,.02,.14,1);--roll-left-travel:-49.4vw;--roll-right-travel:49.4vw}
/* [结构修复] 画布只占卷轴纸身高度:顶部 12.5% 至底部 19.5%,木轴区域完全没有画面。 */
.portal{inset:12.5% 0 19.5%;overflow:hidden;clip-path:inset(0 49.4% 0 49.4% round 10px)!important;opacity:0;background-color:transparent!important;background-image:url('assets/homepage-origin-canvas-v2.png')!important;background-position:center;background-size:100% 128%;background-repeat:no-repeat;border:0;box-shadow:0 16px 34px rgba(34,23,14,.24);transform:none;filter:blur(5px) brightness(.72);transition:clip-path var(--canvas-unfurl-duration) var(--canvas-unfurl-ease),opacity .32s ease,filter 1600ms ease!important}
.app.portal-open .portal{clip-path:inset(0 0 0 0 round 0)!important;opacity:1;transform:none;filter:none;pointer-events:auto}
.portal:before{content:"";position:absolute;z-index:2;top:7%;bottom:7%;left:50%;width:30px;opacity:0;transform:translateX(-50%) scaleY(.22);background:linear-gradient(90deg,transparent,rgba(255,220,137,.42),rgba(255,235,179,.58),rgba(255,220,137,.42),transparent);filter:blur(7px);pointer-events:none}.app.portal-open .portal:before{animation:canvasSeamGlow 2400ms cubic-bezier(.42,0,.18,1) both}
@keyframes canvasSeamGlow{0%{opacity:0;transform:translateX(-50%) scaleY(.22)}10%{opacity:.52}38%{opacity:.28;transform:translateX(-50%) scaleY(.86)}56%,100%{opacity:0;transform:translateX(-50%) scaleY(1)}}
/* [修改 4] 复用真实卷轴素材:两根卷轴从中央重合位置向左右移动,画布始终夹在中间。 */
.canvas-roll{position:absolute;z-index:52;left:50%;top:50%;width:46vh;height:88vh;opacity:0;background:url('assets/unfurl-paper-roll-real.png') center/contain no-repeat;filter:drop-shadow(0 22px 24px rgba(0,0,0,.48)) drop-shadow(0 0 15px rgba(221,153,67,.2));transition:opacity .28s ease;pointer-events:none;will-change:transform,opacity}
.app.portal-open .canvas-roll{opacity:1}.app.portal-open .canvas-roll-left{animation:canvasRollLeft var(--canvas-unfurl-duration) var(--canvas-unfurl-ease) both}.app.portal-open .canvas-roll-right{animation:canvasRollRight var(--canvas-unfurl-duration) var(--canvas-unfurl-ease) both}.app.leaving-origin .canvas-roll{opacity:0;transition-duration:.62s}
/* [修复穿帮] 卷轴中心与 portal 裁切边界同步移动:画布在展开阶段始终被两根卷轴夹住。 */
@keyframes canvasRollLeft{0%{transform:translate(-50%,-50%) scale(.96)}100%{transform:translate(calc(var(--roll-left-travel) - 50%),-50%) scale(1)}}
@keyframes canvasRollRight{0%{transform:translate(-50%,-50%) scale(-.96,.96)}100%{transform:translate(calc(var(--roll-right-travel) - 50%),-50%) scale(-1,1)}}
/* [版本 B] 缘起在首页红框区域展开:保留顶部标题,卷轴与纸幅缩放到同一舞台。 */
.app.layout-inframe{--roll-left-travel:-47vw;--roll-right-travel:47vw}.app.layout-inframe.is-opening{background:radial-gradient(circle at 50% 48%,#f1e4c9 0,#d6c19a 65%,#aa8d63 100%)}.app.layout-inframe.is-opening:before{opacity:.08}.app.layout-inframe.is-opening .intro{opacity:1;transform:none;filter:none;pointer-events:none}.app.layout-inframe.is-opening .scroll-zone{opacity:0;transition:opacity .45s ease}.app.layout-inframe.is-opening .topbar{color:#4d473b}.app.layout-inframe .portal{inset:45% 3% 0;background-size:100% 128%}.app.layout-inframe .canvas-roll{top:74%;width:34.5vh;height:66vh}.app.layout-inframe .origin-copy{left:14%;top:7%;width:min(475px,42vw);padding-top:10px}.app.layout-inframe.leaving-origin .intro{opacity:0;transform:scale(.97);filter:blur(4px)}
@media(max-width:760px){.canvas-roll{width:46vh;height:89vh}.app.portal-open .canvas-roll-left{animation-name:canvasRollLeftMobile}.app.portal-open .canvas-roll-right{animation-name:canvasRollRightMobile}.app.layout-inframe .portal{inset:43% 2% 0;background-position:58% center}.app.layout-inframe .canvas-roll{top:73%;width:35vh;height:68vh}.app.layout-inframe .origin-copy{left:8%;top:7%;width:82vw}@keyframes canvasRollLeftMobile{0%{transform:translate(-50%,-50%) scale(.94)}100%{transform:translate(calc(var(--roll-left-travel) - 50%),-50%) scale(1)}}@keyframes canvasRollRightMobile{0%{transform:translate(-50%,-50%) scale(-.94,.94)}100%{transform:translate(calc(var(--roll-right-travel) - 50%),-50%) scale(-1,1)}}}
/* [修改 5] 减少动效模式:JS 直接打开缘起;CSS 同时确保复杂动画不会执行。 */
@media(prefers-reduced-motion:reduce){.app.scroll-unfurling .scroll-button,.app.scroll-unfurling .scroll-button img,.app.scroll-unfurling .scroll-zone:before{animation:none!important}.app.scroll-fade-out .scroll-button{transition:none!important}}
/* 低高度桌面屏:正文和继续按钮始终完整落在画卷纸幅内。 */
@media(max-height:800px) and (min-width:761px){.origin-copy{top:8%;padding-top:10px}.origin-copy h2{font-size:clamp(27px,3vw,42px);margin:8px 0 11px}.story-lines{font-size:14px;line-height:1.58}.continue{margin-top:10px;padding:9px 17px}.chapter-mark{bottom:6%}}
/* 手机端:两侧卷轴缩进屏幕边缘,正文收进中央安全区,避免被木轴遮挡。 */
@media(max-width:760px){.app{--roll-left-travel:-50vw;--roll-right-travel:50vw}.canvas-roll,.app.layout-inframe .canvas-roll{top:50%;width:18vh;height:72vh}.origin-copy,.app.layout-inframe .origin-copy{left:19%;top:6%;width:62vw;padding:7px 5px}.origin-copy:before{inset:-5px -8px -7px -6px}.origin-copy h2{max-width:none;font-size:clamp(22px,6.5vw,27px);line-height:1.25;margin:7px 0 10px}.story-lines{font-size:11.5px;line-height:1.5}.continue{margin-top:10px;padding:8px 10px;font-size:11px;letter-spacing:.06em;white-space:nowrap}}
</style>
</head>
<body>
<main class="app" id="app">
<section class="next-module" aria-label="铸身模块"><div class="next-copy"><div class="chapter">第二章 · 铸身</div><h2>铸身</h2><p>不必描述自己。走进故事,让每一次选择替你回答。</p></div></section>
<div class="grain"></div>
<header class="topbar"><div class="brand">无字卷 <small>THREE KINGDOMS · 208</small></div><button class="sound" aria-label="切换声音">♪</button></header>
<section class="intro" id="intro">
<div class="kicker">一卷只属于你的无字史书</div><h1><span>若生于乱世</span><span>你会是谁?</span></h1><p>无字卷不问你想成为谁,只把你放进那个时代,看你会走向哪里。<br>不是观看历史,而是让自己的选择,成为历史里的一笔。</p>
<div class="scroll-zone"><button class="scroll-button" id="openScroll" aria-label="展开无字卷"><img src="assets/homepage-closed-scroll-alpha.png" alt="封印中的无字卷"></button><div class="prompt">轻触封印,寻找历史里的你</div><div class="subprompt">建议开启声音 · 戴上耳机</div></div>
</section>
<!-- [修改 6] 左右实体卷轴必须位于 portal 外层,避免被中间画布的 clip-path 裁切。 -->
<div class="canvas-roll canvas-roll-left" aria-hidden="true"></div><div class="canvas-roll canvas-roll-right" aria-hidden="true"></div>
<section class="portal" id="portal" aria-live="polite">
<article class="origin-copy"><div class="chapter">缘起 · 建安十三年</div><h2>史书里,少了一个没有名字的人。</h2><div class="story-lines"><span>赤壁之前,史官在旧卷中发现了一段陌生的记载。</span><span>那人的一个选择,改变了许多人的命运。</span><span>可他的姓名、出身与面容,都被墨色抹去。</span><span>而那段人生,与你惊人地相似。</span></div><button class="continue" id="continueBtn">以我之名,继续写下去</button></article><div class="chapter-mark">第一章 · 缘起</div>
</section>
</main>
<script>
const app=document.getElementById('app'),openButton=document.getElementById('openScroll'),continueButton=document.getElementById('continueBtn');let opened=false,transitioning=false;
/* [双版本] layout=fullscreen 为全画面缘起;layout=inframe 为红框区域内缘起。 */
const layout=new URLSearchParams(location.search).get('layout');app.classList.add(layout==='inframe'?'layout-inframe':'layout-fullscreen');
/* [修改 7] 严格时间轴:封印卷轴平滑转为竖直 1100ms → 左右卷轴携画布展开 2400ms → 缘起。 */
openButton.addEventListener('click',()=>{
if(opened)return;
opened=true;
openButton.disabled=true;
const reduceMotion=window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if(reduceMotion){
app.classList.add('is-opening','portal-open','story-visible');
return;
}
app.classList.add('scroll-unfurling');
setTimeout(()=>app.classList.add('scroll-fade-out','is-opening','portal-open'),1100);
setTimeout(()=>app.classList.add('story-visible'),3650);
});
continueButton.addEventListener('click',()=>{
if(transitioning)return;
transitioning=true;
continueButton.disabled=true;
app.classList.add('leaving-origin');
setTimeout(()=>{
try {
if(typeof window.parent.__wuzijuanContinue==='function') window.parent.__wuzijuanContinue();
else window.parent.postMessage({type:'wuzijuan:continue'},location.origin);
} catch {
window.parent.postMessage({type:'wuzijuan:continue'},location.origin);
}
},720);
});
document.querySelector('.sound').addEventListener('click',e=>{e.currentTarget.textContent=e.currentTarget.textContent==='♪'?'×':'♪'});
</script>
</body>
</html>