@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700;900&family=ZCOOL+KuaiLe&family=Princess+Sofia&family=Noto+Serif+SC:wght@700;900&display=swap');
:root{--ink:#6b4f45;--ink-soft:#8d7266;--paper:#fff8ec;--paper-2:#fbefdc;--pink:#f8cdd8;--pink-2:#f2b0c2;--pink-deep:#e48ea7;--butter:#f8dc98;--sage:#acd393;--sky:#b7daf0;--display:'ZCOOL KuaiLe','Noto Sans SC',sans-serif}
html:not(.react-ready),html:not(.react-ready) body{margin:0;width:100%;height:100%;overflow:hidden}
#offline-preview{position:relative;width:100vw;height:100svh;min-height:560px;overflow:hidden;background:var(--sky);color:var(--ink);font-family:'Noto Sans SC',sans-serif}
.react-ready #offline-preview{display:none}
#offline-preview *{box-sizing:border-box}
#offline-preview button,#offline-preview input{font:inherit;cursor:pointer}
#offline-preview button:focus-visible,#offline-preview input:focus-visible{outline:3px solid var(--pink-deep);outline-offset:3px}
#street-canvas{display:block;width:100%;height:100%}
/* paper grain over everything, like the crayon texture in the illustrations */
.paper-grain{position:absolute;inset:0;z-index:1;pointer-events:none;opacity:.2;mix-blend-mode:multiply;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .42 0 0 0 0 .31 0 0 0 0 .27 0 0 0 .55 -.18'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}
.preview-wash{position:absolute;inset:0;pointer-events:none;background:linear-gradient(90deg,#fff8eccc 0%,#fff8ec8a 24%,transparent 44%),linear-gradient(0deg,#fff8ec80,transparent 20%)}
.preview-header,.preview-intro,.preview-project,.preview-guide,.preview-hint,.preview-walker{position:absolute;z-index:2}
.preview-header{top:14px;left:2.5%;right:2.5%;height:62px;display:flex;align-items:center;justify-content:space-between;padding:0 26px;background:#fff8ecee;border:2px solid var(--ink);border-radius:999px;box-shadow:0 4px 0 #6b4f4522}
.preview-header button{background:none;border:0;color:var(--ink);font-weight:700;white-space:nowrap}
.preview-brand{font-family:var(--display);font-size:21px!important;font-weight:400!important;letter-spacing:.02em}
.preview-brand::first-letter{color:var(--pink-deep)}
.preview-header nav{display:flex;gap:10px}
.preview-header nav button{font-size:13px;padding:7px 16px;border-radius:999px;transition:background .2s}
.preview-header nav button:hover{background:var(--pink)}
.preview-header small{font-size:10px;font-weight:700;letter-spacing:.14em;color:var(--ink-soft)}
.preview-intro{top:118px;left:6.5%;width:480px;max-width:40vw;pointer-events:none}
.preview-intro>p:first-child{display:inline-block;font-size:10px;letter-spacing:.14em;color:var(--ink);font-weight:700;background:var(--butter);border:1.5px solid var(--ink);border-radius:999px;padding:5px 12px;transform:rotate(-2deg)}
.preview-intro h1{font-family:var(--display);font-weight:400;font-size:clamp(40px,4.5vw,72px);white-space:nowrap;line-height:1.12;letter-spacing:.01em;margin:16px 0 14px;color:var(--ink);text-shadow:3px 3px 0 #fff8ec}
.preview-intro h1 em{font-style:normal;color:var(--pink-deep)}
.preview-intro h1 span{color:var(--pink-deep)}
#preview-intro-text{font-size:13px;line-height:1.8;color:var(--ink-soft);max-width:380px;background:#fff8ecc7;border-radius:14px;padding:4px 0}
#preview-intro-text span{display:block}
#preview-intro-text span+span{margin-top:.55em}
#preview-start{pointer-events:auto;border:2px solid var(--ink);background:var(--pink);color:var(--ink);border-radius:999px;box-shadow:3px 4px 0 var(--ink);font-size:13px!important;font-weight:700!important;padding:12px 22px;margin-top:14px;transition:transform .15s,box-shadow .15s}
#preview-start:hover{transform:translate(-1px,-1px);box-shadow:4px 5px 0 var(--ink)}
#preview-start:active{transform:translate(2px,3px);box-shadow:1px 1px 0 var(--ink)}
.preview-walker{height:min(38vh,380px);aspect-ratio:240/330;left:50%;bottom:8%;transform:translateX(-50%);pointer-events:none}
/* the mouse walks while the street moves, and turns to face the direction of travel */
.mouse-walker{display:block;width:100%;height:100%;overflow:visible;transition:transform .35s ease}
[data-facing=right] .mouse-walker{transform:scaleX(-1)}
.mouse-walker g{transform-box:view-box}
.mw-leg-front{transform-origin:102px 204px}
.mw-leg-back{transform-origin:138px 204px}
.mw-arm{transform-origin:104px 124px;animation:mw-arm 2.4s ease-in-out infinite alternate}
.mw-tail{transform-origin:150px 214px;animation:mw-tail 2.6s ease-in-out infinite alternate}
.mw-head{transform-origin:114px 110px;animation:mw-nod 3s ease-in-out infinite alternate}
[data-walking] .mw-leg-front{animation:mw-step .5s ease-in-out infinite alternate}
[data-walking] .mw-leg-back{animation:mw-step .5s ease-in-out infinite alternate-reverse}
[data-walking] .mw-body{animation:mw-bob .25s ease-in-out infinite alternate}
[data-walking] .mw-arm{animation-duration:.5s}
[data-walking] .mw-tail{animation-duration:.5s}
[data-walking] .mw-head{animation-duration:.5s}
@keyframes mw-step{from{transform:rotate(12deg)}to{transform:rotate(-12deg)}}
@keyframes mw-bob{from{transform:translateY(0)}to{transform:translateY(-4px)}}
@keyframes mw-arm{from{transform:rotate(-3deg)}to{transform:rotate(4deg)}}
@keyframes mw-tail{from{transform:rotate(-5deg)}to{transform:rotate(7deg)}}
@keyframes mw-nod{from{transform:rotate(-1.5deg)}to{transform:rotate(2deg)}}
.preview-project{right:3.5%;bottom:92px;width:270px;padding:22px 22px 18px;background:var(--paper);border:2px solid var(--ink);border-radius:20px;box-shadow:4px 5px 0 #6b4f4533;transform:rotate(1.2deg)}
.preview-project::before{content:'';position:absolute;top:-12px;left:50%;width:74px;height:22px;transform:translateX(-50%) rotate(-3deg);background:#f8cdd8cc;border:1.5px dashed #e48ea7}
.preview-project small{font-size:10px;letter-spacing:.12em;color:var(--pink-deep);font-weight:700}
.preview-project h2{font-family:var(--display);font-weight:400;font-size:24px;line-height:1.3;margin:8px 0 6px}
.preview-project p{font-size:11.5px;line-height:1.65;color:var(--ink-soft);margin:0}
.preview-project button{margin-top:12px;background:var(--butter);border:1.5px solid var(--ink);border-radius:999px;padding:6px 14px;font-size:12px;font-weight:700;color:var(--ink)}
.preview-project button:hover{background:var(--pink)}
.preview-guide{left:29%;right:31%;bottom:30px;display:flex;align-items:center;gap:14px;background:#fff8ecdd;border:2px solid var(--ink);border-radius:999px;padding:9px 18px}
.preview-guide span{font-size:11px;white-space:nowrap;font-weight:700;color:var(--ink)}
.preview-guide input{--fill:0%;flex:1;appearance:none;-webkit-appearance:none;height:10px;border:1.5px solid var(--ink);border-radius:8px;background:linear-gradient(90deg,var(--pink-2) var(--fill),#fff var(--fill))}
.preview-guide input::-webkit-slider-thumb{-webkit-appearance:none;width:24px;height:24px;border-radius:50%;background:var(--butter);border:2px solid var(--ink);box-shadow:2px 2px 0 var(--ink)}
.preview-guide input::-moz-range-thumb{width:20px;height:20px;border-radius:50%;background:var(--butter);border:2px solid var(--ink)}
.preview-hint{right:3.5%;top:96px;background:var(--paper);border:2px solid var(--ink);border-radius:18px;padding:10px 16px;color:var(--ink);font-size:12px;font-weight:700;transform:rotate(-1.5deg)}
.preview-hint small{display:block;font-size:10px;color:var(--ink-soft);font-weight:500;margin-top:2px}
.preview-overlay{position:absolute;z-index:9;inset:0;background:#6b4f4566;display:flex;justify-content:flex-end}
.preview-overlay[hidden]{display:none}
.preview-panel{position:relative;background:var(--paper);width:min(620px,100%);height:100%;overflow:auto;padding:80px 52px 50px;border-left:3px solid var(--ink);box-shadow:-8px 0 0 #f8cdd8}
.preview-close{position:absolute;right:25px;top:20px;width:44px;height:44px;border:2px solid var(--ink);border-radius:50%;background:var(--pink);font-size:26px!important;line-height:1;color:var(--ink);box-shadow:2px 3px 0 var(--ink)}
.preview-panel .kicker{display:inline-block;font-size:10px;letter-spacing:.14em;font-weight:700;color:var(--ink);background:var(--butter);border:1.5px solid var(--ink);border-radius:999px;padding:5px 12px}
.preview-panel h2{font-family:var(--display);font-weight:400;font-size:clamp(32px,3.6vw,48px);line-height:1.25;margin:18px 0;color:var(--ink)}
.preview-panel p{font-size:14px;line-height:1.9;color:var(--ink-soft)}
.preview-panel img{display:block;width:100%;max-height:350px;object-fit:cover;object-position:top;margin:28px 0;border:2px solid var(--ink);border-radius:14px}
.preview-panel .map-item{width:100%;border:0;border-top:2px dashed #d9c4b4;background:none;display:flex;gap:16px;align-items:center;text-align:left;padding:18px 6px;color:var(--ink);border-radius:12px}
.preview-panel .map-item:hover{background:var(--paper-2)}
.preview-panel .map-item b{font-weight:700;font-size:15px;color:var(--pink-deep)}
.preview-panel .map-item span{flex:1;font-weight:700}
.preview-panel .map-item small{display:block;color:var(--ink-soft);font-size:11px;margin-top:5px;font-weight:500}
.preview-panel .tag{display:inline-block;padding:7px 14px;border:1.5px solid var(--ink);background:var(--pink);border-radius:999px;margin:8px 6px 0 0;font-size:12px;font-weight:700}
.preview-panel a{display:inline-block;margin-top:20px;color:var(--ink);background:var(--pink);border:2px solid var(--ink);border-radius:999px;padding:11px 20px;text-decoration:none;font-weight:700;box-shadow:3px 4px 0 var(--ink)}
.preview-panel .folder-count{font-size:12px;font-weight:700;color:var(--pink-deep);margin-top:-5px}
.folder-tree{margin-top:26px;border-top:2px dashed #d9c4b4}
.folder-tree details{border-bottom:2px dashed #e6d6c8}
.folder-tree summary{list-style:none;padding:16px 2px;display:flex;align-items:center;gap:10px;font-size:13px;font-weight:700;color:var(--ink);cursor:pointer}
.folder-tree summary::-webkit-details-marker{display:none}
.folder-tree summary:before{content:"▸";color:var(--pink-deep);transition:transform .2s}
.folder-tree details[open]>summary:before{transform:rotate(90deg)}
.folder-tree .folder-inner{padding:0 0 12px 19px}
.folder-tree .file-item{display:flex;align-items:center;gap:11px;width:100%;background:none;border:1.5px solid transparent;border-radius:12px;text-align:left;color:var(--ink-soft);padding:9px 8px;font-size:12px;line-height:1.45}
.folder-tree .file-item:hover,.folder-tree .file-item.active{background:#fdeef2;border-color:var(--pink-2);color:var(--ink)}
.folder-tree .file-item .file-icon{font-size:16px;flex:none;color:var(--pink-deep)}
.file-preview{margin-top:24px;padding:18px;background:var(--paper-2);border:2px solid var(--ink);border-radius:18px}
.file-preview h3{font-size:15px;line-height:1.5;margin:0 0 14px;overflow-wrap:anywhere}
.file-preview img{max-height:450px;object-fit:contain;width:100%;margin:0;background:#fff}
.file-preview video{width:100%;max-height:380px;background:#3d2f2a;border-radius:10px}
.file-preview iframe{width:100%;height:440px;border:2px solid var(--ink);border-radius:10px;background:#fff}
.file-preview a{display:inline-block;margin-top:15px}
@media(max-width:850px){.preview-header small{display:none}.preview-intro{left:5%;max-width:42vw}.preview-intro h1{font-size:52px}.preview-walker{height:33vh}.preview-guide{left:22%;right:30%}}
@media(max-width:650px){.preview-header{top:10px;left:10px;right:10px;height:54px;padding:0 14px}.preview-brand{font-size:13px!important;padding:0!important}.preview-header nav{gap:2px}.preview-header nav button{font-size:11px;padding:6px 8px}.preview-wash{background:linear-gradient(180deg,#fff8ecee 0%,#fff8ecbb 38%,transparent 62%),linear-gradient(0deg,#fff8ecb3,transparent 31%)}.preview-intro{top:80px;left:20px;right:20px;width:auto;max-width:none}.preview-intro>p:first-child{font-size:8px}.preview-intro h1{font-size:40px;margin:8px 0}.preview-intro p{font-size:11px!important;max-width:300px}.preview-intro #preview-start{margin-top:5px;padding:9px 15px}.preview-walker{height:30vh;bottom:11%}.preview-project{width:190px;right:14px;bottom:88px;padding:14px}.preview-project h2{font-size:17px;margin:6px 0}.preview-project p{font-size:10px}.preview-hint{top:auto;bottom:270px;right:14px;padding:8px 11px;font-size:10px}.preview-hint small{display:none}.preview-guide{left:14px;right:14px;bottom:24px;padding:8px 12px}.preview-guide span{font-size:10px}.preview-panel{padding:78px 24px 40px}}
/* the hint and slider change once 「开始探索」 is pressed */
.preview-hint .hint-walk{display:none}
[data-exploring] .preview-hint .hint-front{display:none}
[data-exploring] .preview-hint .hint-walk{display:block}
.preview-guide input:disabled{cursor:default;opacity:.55}
#street-canvas:focus{outline:none}
/* once the walk starts, the intro steps aside so the left-hand houses are visible */
.preview-intro,.preview-wash{transition:opacity .5s ease,transform .5s ease}
[data-exploring] .preview-intro{opacity:0;transform:translateX(-24px);pointer-events:none}
[data-exploring] .preview-intro #preview-start{pointer-events:none}
[data-exploring] .preview-wash{opacity:.25}
@media(prefers-reduced-motion:reduce){.mouse-walker,.mouse-walker g{animation:none!important;transition:none}}
.preview-panel p.email{font-family:"Noto Sans SC",sans-serif;font-weight:700;font-size:18px;letter-spacing:.02em;user-select:all;color:var(--ink);margin:18px 0 0}

/* ---------- 关于我: two columns, pixel polaroid, stickers, timeline ---------- */
.pixelated-image-card{position:relative;overflow:hidden;isolation:isolate;-webkit-tap-highlight-color:transparent}
.pixelated-image-card:focus-visible{outline:3px solid var(--pink-deep);outline-offset:3px}
.pixelated-image-card__default,.pixelated-image-card__active{position:absolute;inset:0}
.pixelated-image-card__pixels{position:absolute;inset:0;z-index:1;display:block;width:100%;height:100%;pointer-events:none}
.preview-panel--wide{width:min(900px,100%)}
.about-grid{display:grid;grid-template-columns:280px 1fr;gap:40px;align-items:start;margin-top:22px}
.polaroid{position:sticky;top:0;margin:8px 0 0;background:#fffdf8;border:2px solid var(--ink);border-radius:6px;padding:12px 12px 16px;box-shadow:5px 7px 0 #6b4f4526;transform:rotate(-2deg);transition:transform .45s cubic-bezier(.34,1.4,.64,1),box-shadow .45s ease}
.polaroid:hover,.polaroid:focus-within{transform:rotate(0) translateY(-4px);box-shadow:7px 11px 0 #6b4f451f}
.polaroid .tape{position:absolute;z-index:2;top:-13px;left:50%;width:96px;height:26px;transform:translateX(-50%) rotate(-4deg);background:#f8cdd8d9;border:1.5px dashed var(--pink-deep);transition:transform .45s cubic-bezier(.34,1.4,.64,1)}
.polaroid:hover .tape{transform:translate(-50%,-3px) rotate(-8deg)}
.polaroid-photo{aspect-ratio:4/5;border-radius:3px;background:var(--paper-2);cursor:pointer}
.polaroid-photo img{width:100%;height:100%;object-fit:cover;display:block;user-select:none;-webkit-user-drag:none}
.polaroid figcaption{font-family:var(--display);font-size:17px;text-align:center;margin-top:12px;color:var(--ink)}
.about-body h2{margin-top:4px!important;margin-bottom:6px!important}
.preview-panel .aka{margin:0 0 14px;font-size:13px;font-weight:700;letter-spacing:.06em;color:var(--ink-soft)}
.stickers{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:22px}
.sticker{display:inline-block;padding:5px 13px;border:1.5px solid var(--ink);border-radius:999px;font-size:12px;font-weight:700;box-shadow:2px 2px 0 var(--ink)}
.sticker--pink{background:var(--pink);transform:rotate(-2deg)}
.sticker--butter{background:var(--butter);transform:rotate(1.5deg)}
.timeline{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-bottom:10px}
.timeline h3,.about-body .skills-title{font-family:var(--display);font-weight:400;font-size:18px;margin:0 0 8px;color:var(--ink)}
.timeline ol{list-style:none;margin:0;padding:0 0 0 14px;border-left:2px dashed #e2cbbd}
.timeline li{position:relative;margin:0 0 12px;font-size:12.5px;line-height:1.5;color:var(--ink)}
.timeline li::before{content:'';position:absolute;left:-21px;top:4px;width:10px;height:10px;border-radius:50%;background:var(--pink);border:1.5px solid var(--ink)}
.timeline time{display:block;font-size:11px;font-weight:700;color:var(--pink-deep);letter-spacing:.04em}
.about-body .skills-title{margin-top:18px}
@media(max-width:760px){.about-grid{grid-template-columns:1fr;gap:26px}.polaroid{position:relative;width:min(280px,100%);margin:12px auto 0}.timeline{grid-template-columns:1fr}}
@media(prefers-reduced-motion:reduce){.polaroid,.polaroid .tape{transition:none}}

/* ---------- custom cursor (mouse only; see custom-cursor.js) ---------- */
html.has-custom-cursor, html.has-custom-cursor * { cursor: none !important; }
.cursor-dot, .cursor-ring { position: fixed; left: 0; top: 0; z-index: 2147483647; pointer-events: none; opacity: 0; transition: opacity .2s ease; }
html.cursor-visible .cursor-dot, html.cursor-visible .cursor-ring { opacity: 1; }
.cursor-dot { width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px; border-radius: 50%; background: var(--ink); }
.cursor-ring { width: 0; height: 0; }
.cursor-ring::before { content: ''; position: absolute; left: -17px; top: -17px; width: 34px; height: 34px; border-radius: 50%; border: 1.5px solid var(--pink-deep); background: #f8cdd800; transition: transform .25s cubic-bezier(.34,1.5,.64,1), background .25s ease, border-color .25s ease; }
.cursor-ring.is-hot::before { transform: scale(1.55); background: #f8cdd859; }
.cursor-ring.has-label::before { transform: scale(1.9); background: #f8cdd8cc; border-color: var(--ink); }
.cursor-ring.is-down::before { transform: scale(.8); }
.cursor-ring.has-label.is-down::before { transform: scale(1.6); }
.cursor-label { position: absolute; left: 0; top: 0; transform: translate(-50%, -50%); font-size: 11px; font-weight: 700; color: var(--ink); white-space: nowrap; opacity: 0; transition: opacity .2s ease; }
.cursor-ring.has-label .cursor-label { opacity: 1; }

/* ---------- homepage title: hand-lettered, pink fill + ink outline in an oval frame ---------- */
.preview-intro h1.title-lettering{position:relative;display:inline-flex;flex-direction:column;align-items:flex-start;white-space:nowrap;margin:22px 0 22px;padding:26px 46px 30px 30px;background:#fff8ecdd;border:2px solid var(--ink);border-radius:30px;box-shadow:inset 0 0 0 6px #fff8ec,inset 0 0 0 7.5px #e9b8c4,5px 6px 0 #6b4f4530;font-family:'Princess Sofia','ZCOOL KuaiLe',cursive;font-size:clamp(46px,5vw,80px);line-height:1;text-shadow:none;letter-spacing:.01em}
.title-lettering .tl-line{position:relative;z-index:1;color:#f4b6c5;-webkit-text-fill-color:#f4b6c5;-webkit-text-stroke:3px #5e463f;paint-order:stroke fill}
.title-lettering .tl-line--1{font-size:1.18em;margin-left:.15em}
.title-lettering .tl-line--2{font-size:.86em;margin:.02em 0 0 .7em}
.tl-frame{display:none}
/* sticker outline that hugs the letters: a thick cream copy behind the text, ringed in ink */
.title-lettering .tl-line::before,.title-lettering .tl-line::after{content:attr(data-text);position:absolute;inset:0;-webkit-text-fill-color:#fff8ec;paint-order:stroke fill;stroke-linejoin:round}
/* two vector strokes (ink under cream) give a smooth outline that hugs every curl */
.title-lettering .tl-line::before{z-index:-2;-webkit-text-stroke:calc(.2em + 6px) #5e463f;-webkit-text-fill-color:#5e463f}
.title-lettering .tl-line::after{z-index:-1;-webkit-text-stroke:.2em #fff8ec}
.tl-star,.tl-spark,.tl-heart{position:absolute;z-index:2;overflow:visible}
.tl-star--left{width:.62em;left:-.18em;top:56%;transform:rotate(-14deg)}
.tl-star--right{width:.56em;right:-.12em;top:12%;transform:rotate(12deg);animation:tl-twinkle 2.6s ease-in-out infinite alternate}
.tl-star--tiny{width:.2em;left:44%;top:-.08em}
.tl-heart{width:.32em;left:50%;bottom:-.06em;transform:translateX(-50%)}
.tl-spark{width:.16em}
.tl-spark--a{left:.25em;top:30%}.tl-spark--b{right:.9em;top:-.05em}.tl-spark--c{right:.25em;bottom:22%}.tl-spark--d{left:30%;bottom:.05em;width:.12em}
@keyframes tl-twinkle{to{transform:rotate(22deg) scale(1.08)}}
@media(max-width:850px){.preview-intro h1.title-lettering{font-size:44px;padding:26px 40px 32px 34px}}
@media(max-width:650px){.preview-intro h1.title-lettering{font-size:34px;margin:10px 0 14px;padding:22px 32px 26px 26px}}
@media(prefers-reduced-motion:reduce){.tl-star--right{animation:none}}

.title-lettering .tl-type{display:block;position:relative;z-index:1;width:min(30vw,440px);height:auto;overflow:visible}
@media(max-width:850px){.title-lettering .tl-type{width:340px}}
@media(max-width:650px){.title-lettering .tl-type{width:min(250px,64vw)}}

/* a full-screen room is open: hide the covered street layers so the browser skips compositing them */
[data-room] #street-canvas,[data-room] .paper-grain,[data-room] .preview-wash,[data-room] .preview-walker{visibility:hidden}
