@font-face{font-family:'Lilita One';font-style:normal;font-weight:400;font-display:swap;src:url('assets/lilita-one.ttf') format('truetype')}
:root{--ink:#292335;--cream:#fff4d6;--lime:#c7f42f;--pink:#f6a1a5;--orange:#ff8858;--line:3px solid var(--ink)}*{box-sizing:border-box}html{scroll-behavior:smooth;scroll-padding-top:30px}body{margin:0;background:var(--cream);color:var(--ink);font:16px/1.65 'DM Sans',Arial,sans-serif}h1,h2,h3,p{margin:0}h1,h2{font-family:'Lilita One',sans-serif;font-weight:400;line-height:1}button,a{-webkit-tap-highlight-color:transparent}button{font:inherit;cursor:pointer;color:inherit}a{color:inherit;text-decoration:none}button:focus-visible,a:focus-visible,summary:focus-visible{outline:3px solid var(--orange);outline-offset:5px}svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}.icon-defs{position:absolute;width:0;height:0}.nav{height:90px;display:flex;align-items:center;justify-content:space-between;gap:20px;padding:0 5%;background:var(--ink);color:var(--cream);border-bottom:2px solid #100e18;position:relative;z-index:20}.brand{display:flex;align-items:center;gap:10px}.brand img{width:49px;height:49px}.brand>span{font:26px/.9 'Lilita One',sans-serif;letter-spacing:1px}.brand small{display:block;font:10px/1 'DM Sans';letter-spacing:3px;margin-top:8px}.navlinks{display:flex;gap:28px;font-size:14px;font-weight:700}.navlinks a:hover{color:var(--lime)}.socials{display:flex;gap:9px}.socials button{display:grid;place-items:center;width:39px;height:39px;border:1.5px solid #fff4d68c;border-radius:50%;background:transparent;color:inherit;transition:.2s}.socials button:hover{background:var(--lime);color:var(--ink);transform:rotate(-8deg)}.menu{display:none}.hero{height:800px;min-height:700px;position:relative;overflow:hidden;background:#323044;color:var(--cream)}.station-back,.station-front{position:absolute;inset:0;background:url('assets/hero-platform.webp') center/cover}.station-front{z-index:2;mask-image:linear-gradient(#000 0%,#000 17%,transparent 20%,transparent 68%,#000 74%);pointer-events:none}.train-track{position:absolute;left:0;right:0;top:19%;height:51%;overflow:hidden;z-index:1}.train{position:absolute;left:0;height:100%;display:flex;width:max-content;transform:translateX(-18%);will-change:transform}.train img{height:100%;width:auto;max-width:none;margin-right:-4px}.hero-shade{position:absolute;inset:0;z-index:3;pointer-events:none;background:linear-gradient(90deg,#252033d9 0%,#252033c2 24%,#2520334a 48%,transparent 75%)}.hero-copy{position:relative;padding:52px 0 0 6%;z-index:7;max-width:640px;pointer-events:none}.hero-copy a{pointer-events:auto}.chain-tag{display:inline-block;font-size:10px;letter-spacing:1.8px;background:var(--lime);color:var(--ink);padding:7px 12px;border:2px solid var(--ink);border-radius:5px;transform:rotate(-2deg);font-weight:700}.hero h1{font-size:clamp(75px,8.8vw,136px);letter-spacing:-4px;line-height:.82;margin:27px 0 18px;text-shadow:4px 6px 0 var(--ink);-webkit-text-stroke:1px var(--ink);display:flex;align-items:end}.hero h1>span{position:relative}.star{color:var(--lime);font-size:39px;position:absolute;right:-30px;top:-20px;transform:rotate(15deg)}.hero h2{font-size:clamp(35px,4vw,58px);line-height:1.06;color:var(--cream);text-shadow:2px 3px var(--ink);transform:rotate(-2deg);margin-top:26px}.hero-copy p{font-size:16px;line-height:1.7;margin:22px 0 25px;color:#fff5dcdd}.button{display:inline-flex;align-items:center;justify-content:center;gap:13px;padding:15px 22px;border:var(--line);border-radius:13px;font-size:14px;font-weight:700;box-shadow:4px 5px 0 var(--ink);transition:transform .2s,box-shadow .2s}.button:hover{transform:translate(-2px,-3px) rotate(-1deg);box-shadow:6px 8px var(--ink)}.lime{background:var(--lime);color:var(--ink)}.dark{background:var(--ink);color:var(--cream)}.light{background:var(--cream);color:var(--ink)}.story-link{display:block;width:max-content;font-size:12px;margin-top:23px;text-decoration:underline;text-underline-offset:5px}.platform-sign{position:absolute;top:26px;right:6%;z-index:4;border:3px solid var(--ink);border-radius:5px;background:var(--cream);color:var(--ink);padding:10px 26px;transform:rotate(2deg);text-align:center;box-shadow:4px 4px #14132288}.platform-sign b{font-size:22px;letter-spacing:9px}.platform-sign span{display:block;font-weight:700;font-size:12px;letter-spacing:1.5px}.platform-sign small{display:block;background:var(--lime);font-size:8px;letter-spacing:1px;padding:3px 6px;margin-top:7px}.hero-scene{position:absolute;inset:0;z-index:5;pointer-events:none}.reunion{position:absolute;width:min(49vw,650px);height:570px;bottom:87px;right:2%;transform-origin:60% 95%;filter:drop-shadow(8px 12px 3px #12112366);pointer-events:auto;cursor:pointer}.reunion img,.reunion canvas{width:100%;height:100%;object-fit:contain;object-position:bottom}.reunion canvas{display:none}.reunion.ready img{display:none}.reunion.ready canvas{display:block}.speech{position:absolute;bottom:590px;right:15%;border:3px solid var(--ink);border-radius:17px 17px 17px 3px;background:var(--cream);color:var(--ink);padding:11px 18px;font-size:13px;font-weight:700;transform:rotate(-4deg);z-index:3;transition:opacity .2s}.solo-dog{position:absolute;width:245px;height:315px;right:20%;bottom:100px;background:transparent;border:0;padding:0;transform-origin:bottom;pointer-events:auto;filter:drop-shadow(7px 12px 2px #15122366)}.solo-dog img,.solo-dog canvas{width:100%;height:100%;object-fit:contain;object-position:bottom}.solo-dog canvas{display:none}.solo-dog.walking img{display:none}.solo-dog.walking canvas{display:block}.scene-ui{position:absolute;right:4%;bottom:32px;z-index:10;display:flex;align-items:center;flex-direction:column;gap:9px}.play-label{font:17px 'Lilita One';transform:rotate(-4deg);align-self:flex-end;margin-right:25px}.play-label b{font-size:24px}.controls{display:flex;gap:7px;padding:9px;background:var(--cream);color:var(--ink);border:3px solid var(--ink);border-radius:13px;box-shadow:4px 5px #19152488}.controls button{font-size:12px;font-weight:700;border:2px solid var(--ink);border-radius:7px;background:transparent;padding:9px 12px;transition:.2s}.controls button:hover,.controls button[aria-pressed=true]{background:var(--lime);transform:translateY(-2px)}.scene-ui>small{font-size:10px;color:#fff4d6a6}.hero-bottom{position:absolute;bottom:27px;left:6%;display:flex;gap:30px;font-size:9px;letter-spacing:1.3px;z-index:8}.hero-bottom a{text-decoration:underline;text-underline-offset:4px}.marquee{overflow:hidden;background:var(--lime);padding:18px 0;border-block:var(--line)}.marquee>div{font:24px 'Lilita One';white-space:nowrap;word-spacing:15px;width:max-content;animation:marquee 35s linear infinite}@keyframes marquee{to{transform:translateX(-50%)}}.lore{height:800px;position:relative;overflow:hidden;background:#333d45;color:var(--cream)}.season-scenes,.season-bg,.lore-shade,.weather{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}.season-bg{opacity:0;transition:opacity 1.2s,transform 8s;object-position:center}.season-bg.active{opacity:1;transform:scale(1.025)}.lore-shade{background:linear-gradient(90deg,#1f293be8,#26303bcc 31%,#26303b35 65%,transparent);z-index:2}.lore-copy{position:relative;z-index:4;padding:115px 0 0 7%;max-width:650px}.section-label{display:block;font-size:11px;letter-spacing:2px;font-weight:700}.lore .section-label{color:var(--lime)}.lore h2{font-size:clamp(43px,5vw,74px);line-height:1.05;margin:25px 0}.lore h2 em{color:var(--lime);font-style:normal}.lore-copy p{font-size:16px;max-width:430px;margin-bottom:20px;line-height:1.8}.lore-note{display:flex;gap:14px;align-items:center;margin-top:25px;font-size:17px;font-weight:600;line-height:1.5}.lore-note>span{font-size:45px;color:var(--pink)}.source{display:block;font-size:10px;opacity:.65;margin-top:23px;text-decoration:underline;text-underline-offset:4px}.season-panel{position:absolute;bottom:38px;left:7%;right:7%;z-index:5;display:flex;justify-content:space-between;align-items:center;gap:20px}.season-panel>div:first-child>span{font-size:9px;letter-spacing:2px;opacity:.7}.season-panel p{font:20px 'Lilita One';margin-top:5px}.season-buttons{display:flex;gap:8px;background:var(--cream);padding:8px;border:var(--line);border-radius:14px}.season-buttons button{background:none;color:var(--ink);border:2px solid transparent;border-radius:7px;font-size:13px;padding:10px 16px;font-weight:700}.season-buttons button[aria-pressed=true]{border-color:var(--ink);background:var(--lime);transform:rotate(-3deg)}.weather{z-index:3;pointer-events:none;overflow:hidden}.weather i{position:absolute;top:-40px;left:calc(var(--i)*3.7%);animation:weatherfall calc(7s + var(--i)*.3s) linear infinite;animation-delay:calc(var(--i)*-.8s);font-style:normal;color:#f7b4c4;font-size:23px}.weather.rain i{width:1px;height:25px;background:#e3efff99;animation-duration:1s;color:transparent}.weather.winter i{font-size:20px;color:white}.weather.autumn i{color:#f2913c}@keyframes weatherfall{to{transform:translate(170px,850px) rotate(130deg)}}.section{padding:95px 7%}.tokenomics{background:var(--cream);position:relative;border-top:var(--line)}.section-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:25px}.hand-note{font:18px 'Lilita One';transform:rotate(-6deg);color:#b44e38}.tokenomics>h2{font-size:clamp(45px,6.5vw,89px);letter-spacing:-1px}.tokenomics>h2>span{color:#a04a2c}.metrics{display:grid;grid-template-columns:repeat(4,1fr);gap:20px;margin-top:45px}.metric{border:var(--line);border-radius:20px;padding:24px;position:relative;box-shadow:5px 7px var(--ink);overflow:hidden;transition:.25s}.metric:hover{transform:translateY(-8px) rotate(-2deg)}.metric.supply{background:#f7c879;transform:rotate(-2deg)}.metric.tax{background:var(--lime);transform:rotate(1.5deg)}.metric.lp{background:var(--pink);transform:rotate(-1deg)}.metric.owner{background:#b8ace1;transform:rotate(2deg)}.metric:hover{transform:translateY(-8px) rotate(0)}.metric-number{font-size:11px;font-weight:700;border:2px solid var(--ink);border-radius:50%;display:grid;place-items:center;width:29px;height:29px}.metric strong{display:block;font:85px/.9 'Lilita One';height:125px;padding-top:25px}.metric strong small{font-size:47px}.metric.lp strong{font-size:42px;line-height:.9}.metric.owner strong{font-size:55px;line-height:.9}.metric.owner strong>span{display:block;font-size:27px}.metric h3{font-size:17px;margin:12px 0 7px}.metric p{font-size:13px;line-height:1.6}.metric>svg{position:absolute;right:20px;top:26px;width:42px;height:42px;transform:rotate(18deg)}.metric-doodle{position:absolute;right:22px;top:17px;font-size:47px;line-height:1}.contract{display:flex;justify-content:space-between;align-items:center;gap:20px;margin-top:50px;border:2px dashed var(--ink);border-radius:13px;padding:20px 24px}.contract small{display:block;font-size:9px;letter-spacing:1.4px;margin-bottom:5px}.contract strong{font-size:17px}.contract>span{background:var(--ink);color:var(--cream);border-radius:20px;padding:7px 15px;font-size:11px;white-space:nowrap}.verification-note{font-size:10px;margin-top:13px;opacity:.6}.buy{display:grid;grid-template-columns:1fr 1fr;gap:12%;background:#f9b9ab;border-block:var(--line)}.buy h2{font-size:clamp(45px,5vw,70px);line-height:.95;margin:25px 0}.buy h2 em{font-style:normal;color:#ad3a23}.buy-title>p{font-size:16px}.boarding-ticket{margin-top:34px;border:var(--line);background:var(--cream);border-radius:12px;width:310px;max-width:100%;padding:21px;transform:rotate(-5deg);box-shadow:5px 6px var(--ink)}.boarding-ticket>span{display:block;font-size:9px;letter-spacing:2px}.boarding-ticket>b{font:30px 'Lilita One';display:block;margin:12px 0}.boarding-ticket i{font-style:normal;color:#bc4727}.boarding-ticket>small{font-size:9px;letter-spacing:1px}.barcode{height:26px;background:repeating-linear-gradient(90deg,var(--ink) 0 2px,transparent 2px 4px,var(--ink) 4px 5px,transparent 5px 9px,var(--ink) 9px 13px,transparent 13px 16px);margin:14px 0}.steps details{border-bottom:2px solid var(--ink);padding:23px 0}.steps details:first-child{border-top:2px solid var(--ink)}.steps summary{display:flex;align-items:center;gap:16px;list-style:none;cursor:pointer}.steps summary::-webkit-details-marker{display:none}.steps summary>span{display:grid;place-items:center;background:var(--cream);border:2px solid var(--ink);border-radius:10px;width:36px;height:36px;flex-shrink:0;font:23px 'Lilita One';transform:rotate(-5deg)}.steps h3{font-size:19px;line-height:1.2}.steps summary>b{margin-left:auto;font-size:26px;font-weight:400}.steps details[open] summary>b{transform:rotate(45deg)}.steps details[open] summary>span{background:var(--lime)}.steps details>div{font-size:14px;padding:17px 0 5px 52px;line-height:1.8}.steps details a{display:block;font-weight:700;text-decoration:underline;margin-top:13px}.steps>.button{margin-top:32px;font-size:12px}.community{position:relative;overflow:hidden;background:var(--lime);padding:90px 7%;display:grid;grid-template-columns:1.25fr 1fr;align-items:center;gap:5%}.community h2{font-size:clamp(46px,5.9vw,84px);line-height:.97;margin:28px 0}.community h2 em{font-style:normal;color:#517021}.community-text>p{font-size:15px}.community-links{display:flex;gap:14px;margin:29px 0 17px}.community-links .button{font-size:12px;padding:13px 17px}.community-text>small{font-size:10px;opacity:.7}.community-character{position:relative;text-align:center;align-self:stretch;display:flex;flex-direction:column;align-items:center;justify-content:center}.circle-word{font:26px 'Lilita One';transform:rotate(9deg);margin-bottom:12px}.community-character>img{width:280px;max-width:100%;height:370px;object-fit:contain;animation:goodboy 3s infinite}.community-character>button{border:2px solid var(--ink);border-radius:14px;background:var(--cream);padding:10px 18px;font-size:12px;font-weight:700;transform:rotate(-5deg)}.boop-heart{position:absolute;top:27%;right:22%;font-size:40px;color:#ba3d45;opacity:0}.community-character.booped .boop-heart{animation:heart 1.4s ease-out}.community-character.booped img{animation:boop .3s 3}.floating-heart{position:absolute;color:var(--pink);font:35px 'Lilita One';animation:heart 1.5s ease-out forwards;bottom:45%;right:24%}@keyframes heart{0%{opacity:0;transform:translateY(0) scale(.6)}20%{opacity:1}100%{opacity:0;transform:translateY(-100px) rotate(15deg) scale(1.4)}}@keyframes boop{50%{transform:rotate(-3deg) translateY(-7px)}}@keyframes goodboy{50%{transform:translateY(-4px) rotate(1deg)}}footer{background:var(--ink);color:var(--cream);padding:45px 7% 24px;display:grid;grid-template-columns:1fr 1fr auto;gap:25px;align-items:center}footer p{font-size:11px;color:#fff4d6a0}footer>a:last-of-type{font-size:12px}footer>small{font-size:9px;grid-column:1/-1;border-top:1px solid #fff4d630;padding-top:22px;color:#fff4d68c}.toast{position:fixed;left:50%;bottom:25px;transform:translate(-50%,30px);opacity:0;background:var(--cream);border:var(--line);border-radius:12px;padding:13px 22px;z-index:99;max-width:90%;box-shadow:4px 5px var(--ink);font-size:14px;pointer-events:none;transition:.2s}.toast.show{opacity:1;transform:translate(-50%,0)}.paused *{animation-play-state:paused!important}.paused .season-bg{transition:none}.paused .reunion{animation:none}.reunion.hello{animation:boop .5s 2}
@media(min-width:1600px){.hero{height:900px}.hero-copy{padding-top:75px}.reunion{height:650px}.speech{bottom:670px}}@media(max-width:1100px){.navlinks{gap:17px;font-size:12px}.brand>span{font-size:23px}.hero h1{font-size:90px}.hero-copy{padding-left:5%;max-width:550px}.hero-copy p{font-size:14px}.reunion{width:51vw;height:490px;right:0;bottom:95px}.speech{right:8%;bottom:550px;font-size:11px}.hero h2{font-size:47px}.scene-ui{right:3%}.controls button{font-size:10px;padding:8px}.hero-bottom{display:none}.platform-sign{right:4%;padding:7px 16px}.lore-copy{padding-left:6%;max-width:520px}.lore-copy p{max-width:390px;font-size:15px}.metrics{gap:15px}.metric{padding:18px}.metric.owner strong>span{font-size:22px}.metric.lp strong{font-size:35px}.community-links{flex-wrap:wrap}.community-character>img{height:310px}.season-buttons button{padding:10px}.buy{gap:8%}}
@media(max-width:700px){.nav{height:76px;padding:0 5%;gap:12px}.brand img{width:40px;height:40px}.brand>span{font-size:22px}.brand small{font-size:8px}.socials{margin-left:auto;gap:6px}.socials button{width:31px;height:31px}.socials svg{width:17px;height:17px}.menu{display:block;color:var(--cream);background:none;border:0;font-size:22px;padding:4px}.navlinks{display:none;position:absolute;left:0;right:0;top:76px;background:var(--ink);padding:25px;box-shadow:0 10px 20px #17122350}.navlinks.open{display:flex;flex-direction:column;font-size:16px}.hero{height:980px;min-height:0}.station-back,.station-front{background-position:62% bottom;background-size:auto 680px;background-repeat:no-repeat}.station-front{mask-image:linear-gradient(transparent 0%,transparent 31%,#000 31%,#000 38%,transparent 40%,transparent 79%,#000 84%)}.train-track{top:40%;height:39%}.hero-shade{background:linear-gradient(180deg,#292335 0%,#292335f0 21%,#29233555 45%,transparent 68%)}.hero-copy{padding:34px 6% 0;max-width:100%}.chain-tag{font-size:8px;letter-spacing:1.1px;padding:6px 9px}.hero h1{font-size:84px;margin:25px 0 20px;letter-spacing:-3px}.hero h2{font-size:39px;margin-top:20px}.hero h2 br{display:none}.hero-copy p{font-size:14px;margin:17px 0 20px}.hero-copy .button{padding:12px 17px;font-size:12px;border-width:2px}.story-link{display:inline-block;margin-left:15px;font-size:10px}.platform-sign{display:none}.reunion{width:95%;right:-5%;height:420px;bottom:120px}.speech{bottom:493px;right:7%;font-size:10px;padding:8px 12px;border-width:2px}.scene-ui{right:4%;left:4%;bottom:29px;gap:8px}.play-label{font-size:14px}.controls{gap:5px;padding:6px;border-width:2px;border-radius:11px;width:100%;justify-content:center}.controls button{font-size:10px;padding:8px 7px;border-width:1.5px}.scene-ui>small{font-size:9px}.solo-dog{bottom:145px;right:21%;width:205px;height:285px}.marquee{padding:14px 0}.marquee>div{font-size:19px}.lore{height:920px}.season-bg{object-position:64% center}.lore-shade{background:linear-gradient(180deg,#1f293bf2 0%,#1f293bd9 27%,#26303b44 63%,#26303b99)}.lore-copy{padding:55px 7% 0;max-width:100%}.lore h2{font-size:48px;margin:23px 0}.lore-copy p{font-size:14px;max-width:345px;margin-bottom:16px;line-height:1.7}.lore-note{font-size:15px;margin-top:19px}.source{font-size:9px;margin-top:15px}.season-panel{bottom:30px;left:5%;right:5%;flex-direction:column;align-items:stretch;gap:14px}.season-panel>div:first-child{text-align:center}.season-panel p{font-size:17px}.season-buttons{justify-content:center;padding:6px;gap:3px;border-width:2px}.season-buttons button{font-size:11px;padding:9px 11px}.section{padding:60px 6%}.section-label{font-size:9px;letter-spacing:1.5px}.hand-note{display:none}.tokenomics>h2{font-size:47px}.tokenomics>h2>span{display:block}.metrics{grid-template-columns:1fr 1fr;gap:20px 14px;margin-top:33px}.metric{padding:15px;border-width:2px;border-radius:15px;box-shadow:3px 5px var(--ink)}.metric strong{font-size:67px;height:106px}.metric strong small{font-size:36px}.metric.lp strong{font-size:33px}.metric.owner strong{font-size:45px}.metric.owner strong>span{font-size:21px}.metric h3{font-size:15px;margin-top:10px}.metric p{font-size:11px}.metric-number{width:24px;height:24px;font-size:10px}.metric>svg{width:30px;height:30px;right:17px;top:21px}.metric-doodle{font-size:37px;right:17px;top:15px}.contract{padding:16px;gap:15px;margin-top:35px}.contract strong{font-size:13px}.contract small{font-size:8px}.contract>span{font-size:9px;padding:6px 10px}.verification-note{font-size:9px}.buy{grid-template-columns:1fr;gap:38px}.buy h2{font-size:53px}.buy-title>p{font-size:14px}.boarding-ticket{width:280px;margin:28px auto 0}.steps h3{font-size:17px}.steps details>div{font-size:13px;padding-left:47px}.steps>.button{font-size:11px;padding:13px 17px}.community{padding:60px 7%;grid-template-columns:1fr;gap:30px}.community h2{font-size:53px;margin:23px 0}.community-text>p{font-size:14px}.community-links .button{font-size:11px;padding:12px;gap:9px}.community-links{gap:11px;margin-top:25px}.community-character>img{width:230px;height:285px}.circle-word{font-size:22px}.community-character{padding-top:8px}.boop-heart{right:20%}footer{grid-template-columns:1fr auto;padding:35px 6% 24px;gap:24px}footer p{grid-column:1/-1;grid-row:2}footer .brand>span{font-size:23px}footer>a:last-of-type{font-size:10px}}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*:before,*:after{animation:none!important;transition:none!important}}[hidden]{display:none!important}

@media(max-width:700px){.hero h1{font-size:clamp(64px,17.5vw,84px)}.hero h2 br{display:block}.hero h2{font-size:37px;line-height:1.04}.season-bg{top:auto;bottom:0;height:590px;object-position:70% center}.lore-shade{background:linear-gradient(180deg,#263344 0%,#263344ec 29%,#26334470 47%,transparent 65%,#26303b70)}}

/* Each subject is anchored to measured platform and rail coordinates. */
.station-front{display:none}.train-track{z-index:3;top:auto;bottom:0;height:235px}.hero-shade{z-index:4}.hero-scene{z-index:5}.hero-copy{z-index:7}.hero-bottom{z-index:8}.reunion{bottom:27%;height:490px}.solo-dog{bottom:27%}.speech{bottom:auto;top:110px}.lore{height:860px}.season-bg.active{transform:none}.season-bg{transition:opacity 1s}.season-panel{bottom:35px}.lore-copy{max-width:610px;padding-top:95px}.lore-copy p{max-width:405px}.lore-shade{background:linear-gradient(90deg,#1f293bf2,#26303bcc 29%,#26303b25 57%,transparent 76%)}#lore-dog{position:absolute;right:16%;bottom:110px;width:255px;height:340px;border:0;background:none;padding:0;z-index:3;cursor:pointer;filter:drop-shadow(7px 6px 3px #17233855);transform-origin:bottom}#lore-dog img,#lore-dog canvas{width:100%;height:100%;object-fit:contain;object-position:bottom}#lore-dog canvas{display:none}#lore-dog.ready canvas{display:block}#lore-dog.ready img{display:none}.lore[data-layered=pending] #lore-dog{display:none}#lore-dog.petted{animation:boop .35s 3}.season-panel{pointer-events:none}.season-panel button{pointer-events:auto}.season-buttons{position:relative;z-index:5}
@media(max-width:700px){.hero{height:980px}.reunion{bottom:207px;height:345px}.speech{top:420px;font-size:10px}.lore{height:1060px}.season-bg{height:630px;object-position:70% bottom;top:auto;bottom:0;transform:none!important}.lore-copy{padding-top:45px}.lore-shade{background:linear-gradient(180deg,#263344 0%,#263344 26%,#263344be 39%,transparent 60%,#26303b45 90%)}#lore-dog{right:12%;bottom:135px;width:185px;height:260px}.lore .season-panel{bottom:25px}.lore-note{margin-top:14px}.season-panel p{font-size:16px}.lore-copy p{max-width:330px}}

/* === Hero framing ========================================================
   The hero is painted from assets/hero-platform.webp (1920x1280 = 3:2) and
   keeps that aspect, so the plate is shown 1:1 with nothing cropped. The
   background geometry is written inline by layoutScene() in app.js from the
   same plate landmarks that place Hachiko and the carriage; the rules below
   are the no-JS fallback plus the depth order. The carriage paints in FRONT
   of Hachiko (the near track really is in front of the platform), so it
   sweeps across and covers him as it passes — calibrated to the reference
   artwork where the carriage is roughly twice the character's height. ===== */
.hero{height:clamp(680px,66.7vw,1040px);min-height:0}
.station-back,.station-front{background-size:cover;background-repeat:no-repeat;background-position:center bottom}
/* depth order: Hachiko < carriage < shade < copy */
.hero-scene{z-index:4}
.train-track{z-index:5}
.hero-shade{z-index:6}
.platform-sign{z-index:6}
.hero-copy{z-index:7}
.hero-bottom{z-index:8}
.scene-ui{z-index:10}
@media(max-width:1100px){.hero{height:clamp(620px,66.7vw,920px)}}
/* The bubble is moved clear of the two things that used to sit on top of it:
   the station sign (top right) on desktop, and the copy block on phones.
   Hachiko is nudged left to match his x position in the reference artwork
   (~0.77 of the width), which also clears the lit green door on the backdrop,
   and the bubble's tail is flipped to point down-right at him. */
.speech{right:24%;border-radius:17px 17px 3px 17px}
.reunion{right:14%}
/* Hero sub-headline: forced onto one line, in the lime that already accents
   the rest of the page. nowrap guarantees the single line; the phone size is
   tuned so the 18 glyphs still fit the copy column. */
.hero h2{color:var(--lime);white-space:nowrap}
@media(max-width:700px){
  .hero{height:980px}
  .hero h2{font-size:clamp(24px,8.4vw,38px);margin-top:16px}
  /* Keep the sprite inside the viewport and clear of the copy block above it
     (the old right:-5% pushed Hachiko off the right edge). */
  .reunion{right:6%}
  .solo-dog{right:16%}
  .speech{right:36%}
}

/* === Lore / story section =================================================
   The story copy is meant to live INSIDE the station artwork, not in a dark
   column beside it. The old scrim was a hard 90deg gradient that stopped at
   ~57% and read as a panel with a visible seam where it met the art. It is
   replaced by a soft, slightly angled scrim (the diagonal edge reads as light,
   not as a panel border) plus top/bottom vignettes, and the copy carries its
   own soft shadow so it stays legible over the illustration without needing
   the whole left side painted flat dark.
   On phones the artwork is full-bleed and the copy simply lays over it — the
   intended look: text over art, no split. NOTE the mobile `.lore` height has
   to sit AFTER the root rule, otherwise the root value wins and the phones
   fall back to the desktop split. ======================================== */
.lore{height:clamp(700px,60vw,880px);background:#26303b}
.lore-shade{background:
  linear-gradient(180deg,rgba(22,30,46,.5) 0%,rgba(22,30,46,0) 30%),
  linear-gradient(0deg,rgba(22,30,46,.55) 0%,rgba(22,30,46,0) 24%),
  linear-gradient(98deg,rgba(22,30,46,.93) 0%,rgba(22,30,46,.9) 16%,rgba(22,30,46,.76) 31%,rgba(22,30,46,.54) 46%,rgba(22,30,46,.3) 61%,rgba(22,30,46,.12) 76%,rgba(22,30,46,0) 92%)}
.lore-copy{padding:clamp(62px,8vh,108px) 0 0 7%;max-width:640px;text-shadow:0 2px 20px rgba(9,13,22,.6)}
.lore h2{text-shadow:0 3px 26px rgba(9,13,22,.7)}
.lore h2 em{text-shadow:none}
.season-panel{bottom:34px}
.season-panel p{text-shadow:0 2px 14px rgba(9,13,22,.75)}
/* The stylesheet has always targeted .story-source while the markup uses
   .source, so this link rendered as unstyled ~9px text on both breakpoints.
   Style the class that is actually in the document. */
.source,.story-source{display:inline-block;margin-top:14px;font-size:12.5px;letter-spacing:.02em;color:#ffeed6d9;text-decoration:underline;text-underline-offset:3px;text-shadow:0 2px 12px rgba(6,10,18,.9)}
@media(max-width:1100px){
  .lore{height:clamp(680px,78vw,860px)}
  .lore-copy{padding-left:6%;max-width:560px}
}
@media(max-width:700px){
  .lore{height:900px}
  /* full-bleed art so the copy lays over the illustration instead of above it.
     The artwork is mirrored here (scale, not transform, so it never fights the
     .active zoom rule) and the cover crop is re-aimed at the dog: in
     spring.webp Hachiko sits at x 0.63-0.83, so the default 62% crop sliced
     him off the right edge. 85% + the mirror lands him fully inside the phone
     frame. */
  .season-bg{top:0;bottom:0;height:100%;scale:-1 1;object-position:82% center}
  /* Hachiko sits at a different x in each season plate, so each one gets its
     own crop offset (measured: spring .63-.83, rain .61-.82, autumn .62-.78,
     winter .52-.72). Mirrored, these offsets centre him in the phone frame. */
  .season-bg[data-bg=rain]{object-position:80% center}
  .season-bg[data-bg=autumn]{object-position:78% center}
  .season-bg[data-bg=winter]{object-position:82% center}
  /* The scrim stops ABOVE Hachiko: the copy lives in the top half and the art
     below it is left untouched, so the dog is never washed out by the overlay. */
  .lore-shade{background:linear-gradient(180deg,rgba(22,30,46,.95) 0%,rgba(22,30,46,.93) 16%,rgba(22,30,46,.85) 28%,rgba(22,30,46,.68) 38%,rgba(22,30,46,.44) 46%,rgba(22,30,46,.2) 52%,rgba(22,30,46,.05) 57%,rgba(22,30,46,0) 61%)}
  /* Phones: tighten the copy so the whole block finishes above y≈0.42, where
     the artwork's lit station interior (and Hachiko) begins. Otherwise the
     note + link land on the bright art and turn illegible. */
  .lore-copy{padding:32px 7% 0;max-width:100%;text-shadow:0 2px 12px rgba(6,10,18,.85),0 0 26px rgba(6,10,18,.55)}
  .lore h2{font-size:clamp(30px,9.4vw,40px);line-height:1.06;margin:13px 0}
  .lore-copy p{max-width:100%;font-size:14px;line-height:1.6;margin-bottom:11px}
  .lore-note{max-width:100%;margin-top:10px;font-size:14.5px;line-height:1.45;text-shadow:0 2px 12px rgba(6,10,18,.9)}
  .lore-note>span{font-size:30px}
  .season-panel{bottom:24px}
}

/* === Seasonal particles ===================================================
   Every particle used to be derived from a single index: left was the fixed
   ladder calc(var(--i)*3.7%), duration and delay stepped in lockstep, and all
   of them shared one keyframe trajectory — which is why the field read as a
   machine-made lattice instead of weather. Each particle now carries its own
   x, horizontal drift, fall distance, spin, speed, phase offset, size and
   opacity, all randomised in setSeason() (app.js). This block is just the
   styling hook that reads them. ========================================== */
.weather i{position:absolute;top:-40px;left:var(--x,0%);font-style:normal;color:#f7b4c4;
  font-size:calc(23px*var(--size,1));opacity:var(--op,1);
  animation:weatherfall var(--dur,10s) linear var(--delay,0s) infinite;will-change:transform}
@keyframes weatherfall{
  from{transform:translate(0,0) rotate(0deg)}
  to{transform:translate(var(--dx,180px),var(--dy,120vh)) rotate(var(--rot,180deg))}}
/* these need the same-or-higher specificity as the original per-season rules,
   otherwise their fixed animation-duration / font-size would win */
.weather.rain i{width:1px;height:25px;background:#e3efff99;color:transparent;animation-duration:var(--dur,.8s)}
.weather.autumn i{color:#f2913c}
.weather.winter i{font-size:calc(20px*var(--size,1));color:#fff}

/* === Section palette ======================================================
   The tokenomics and "how to buy" bands were cream and salmon, which read as a
   different site from the night-station hero (#323044) and story (#26303b)
   sections. Both are pulled into the same navy family so the page flows, and
   the accents that used to be brick red become the lime that already carries
   the hero, the marquee and the community band.
   Every override below exists for contrast: ink borders and ink shadows are
   invisible on navy, and anything sitting on a cream chip (the boarding ticket,
   the step numbers) has to keep ink text now that the section color is cream. */
.tokenomics{background:#232b3c;color:var(--cream);border-top:2px solid rgba(255,244,214,.16)}
.tokenomics>h2>span{color:var(--lime)}
.tokenomics .section-label,.buy .section-label{color:var(--lime)}
.tokenomics .hand-note{color:var(--pink)}
/* The section is cream-on-navy now, but the metric cards are bright chips, so
   they must keep dark ink text (and their doodles/numbers/svg with it). */
.tokenomics .metric{color:var(--ink);box-shadow:6px 8px rgba(0,0,0,.45)}
.tokenomics .contract{border-color:rgba(255,244,214,.42)}
.tokenomics .contract>span{background:var(--lime);color:var(--ink)}
.buy{background:#1c2331;color:var(--cream);border-block:2px solid rgba(255,244,214,.16)}
.buy h2 em{color:var(--lime)}
.buy .boarding-ticket{color:var(--ink);box-shadow:5px 6px var(--lime)}
.buy .steps summary>span{color:var(--ink)}
.buy .steps details{border-bottom-color:rgba(255,244,214,.22)}
.buy .steps details>div{color:#fff5dcdd}
.buy .steps details a{color:var(--cream)}

/* === Auto-rotating seasons + the through-train ============================
   The seasons auto-advance once a second, so the swap has to read as one
   gentle dissolve: a 0.7s ease-in-out crossfade with a short hold at full
   opacity in between. (The inherited 1s/1.2s fade from the base sheet is
   overridden here; while motion is paused `.paused .season-bg` drops the
   transition to none, which is deliberate — a paused page should not fade.)
   The carriage no longer parks at the platform — it rolls straight through.
   x is a percentage of the train's own width (5463px on desktop): +30% clears
   the right edge, -105% clears the left, so a pass is 135% of travel and the
   carriage is on screen for ~4s of it. */
.season-bg{transition:opacity .7s ease-in-out}
.train{transform:translateX(30%)}

/* === Sticker décor (tokenomics + how to buy) ==============================
   Six of the supplied Hachiko stickers, converted to 320px webp — the original
   PNGs were 1.64MB for these six, the webp set is 101KB.
   They are absolute, pointer-events:none decorations behind the copy, so they
   can never push the layout or steal a click.
   Motion is split across two elements on purpose: .sticker owns the ENTRANCE
   (opacity/scale/rotate, toggled by an IntersectionObserver in app.js) and the
   inner <img> owns the endless FLOAT. If both lived on one element the running
   animation would override the transition and the entrance would never play. */
.tokenomics,.buy{position:relative}
.sticker{position:absolute;z-index:0;pointer-events:none;
  opacity:0;transform:translateY(30px) scale(.7) rotate(var(--rot,0deg));
  transition:opacity .55s ease,transform .8s cubic-bezier(.18,1.35,.4,1)}
.sticker.in{opacity:1;transform:translateY(0) scale(1) rotate(var(--rot,0deg))}
.sticker img{display:block;width:100%;height:auto;
  filter:drop-shadow(0 12px 22px rgba(0,0,0,.5));
  animation:stickerFloat var(--float,6.8s) ease-in-out var(--phase,0s) infinite}
@keyframes stickerFloat{
  0%,100%{transform:translateY(0) rotate(0deg)}
  50%{transform:translateY(-9px) rotate(4deg)}}
/* whatever a sticker lands on, the copy always paints above it */
.tokenomics .section-top,.tokenomics>h2,.tokenomics .contract,.tokenomics .verification-note,
.buy>.buy-title,.buy>.steps{position:relative;z-index:1}

/* — one sticker per tokenomics card, sitting in the top-right corner ————————
   That corner used to hold a throwaway glyph (the paw svg on the supply card,
   ✦ / ♨ / ♡ on the others). Those are switched off and the mascot takes their
   place: same corner, same footprint, but an actual piece of art.
   The corner is safe because the only thing in that vertical band is the big
   <strong> number, whose glyph run ends well before the card's right edge at
   every breakpoint (its font-size is fixed, so it never grows with the card).
   Sized as a SHARE OF THE CARD so it tracks the grid rather than the viewport. */
.metric>svg,.metric-doodle{display:none}
/* "BURNED" is the longest word any card prints; at the inherited fixed sizes it
   ran nearly edge-to-edge on tablet/phone and ran under the mascot. Scaling it
   with the viewport keeps ~40px of clear corner at every width (the other
   cards' short numerals are unaffected). */
.metric.lp strong{font-size:clamp(24px,3vw,42px)}
.metric-sticker{right:14px;top:12px;width:clamp(36px,24%,66px);height:auto;--rot:-8deg}
.metric-sticker img{filter:drop-shadow(0 3px 7px rgba(41,35,53,.3))}
.metric.tax .metric-sticker  {--rot:8deg;--float:7.4s}
.metric.lp .metric-sticker   {--rot:-9deg;--float:6.7s}
.metric.owner .metric-sticker{--rot:7deg;--float:8.1s}
/* Four cards in a single row only works while each one still has room for its
   numeral AND the mascot. Between ~700-900px the columns got so tight that the
   fixed-size numerals reached the mascot's corner, so the grid now folds to 2x2
   from 900px instead of waiting for the phone breakpoint. */
@media(max-width:900px){.metrics{grid-template-columns:1fr 1fr;gap:20px 16px}}
/* smallest phones: the corner is genuinely tiny there, so the mascot shrinks
   with it rather than running under the numerals. */
@media(max-width:380px){.metric-sticker{width:clamp(26px,18%,34px)}}

/* === Floating contract address bar =========================================
   Stays pinned to the bottom of the viewport so the CA is one tap away from
   anywhere on the page, same neo-brutalist dressing as the rest of the site
   (--line border, hard 4px/5px ink shadow, lime action). The address itself
   lives in ONE place - CONTRACT_ADDRESS in app.js - and this bar plus the
   tokenomics block both read from it, so there is nothing to keep in sync.
   body gets matching bottom padding so the bar never sits on top of the
   footer's last line, and the toast is lifted above the bar. */
.ca-bar{position:fixed;left:50%;bottom:20px;transform:translateX(-50%);z-index:60;
  display:flex;align-items:center;gap:10px;max-width:calc(100% - 24px);
  padding:7px 7px 7px 16px;border:var(--line);border-radius:999px;
  background:var(--cream);color:var(--ink);box-shadow:4px 5px 0 var(--ink);
  font-weight:700;font-size:13px;line-height:1}
.ca-tag{font-size:9.5px;letter-spacing:.16em;font-weight:800;opacity:.55;white-space:nowrap}
.ca-value{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:12.5px;font-weight:600;max-width:34ch;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ca-copy{flex:0 0 auto;display:inline-flex;align-items:center;
  padding:9px 15px;border:2px solid var(--ink);border-radius:999px;
  background:var(--lime);color:var(--ink);font:inherit;font-size:11.5px;font-weight:800;
  letter-spacing:.04em;cursor:pointer;box-shadow:2px 2px 0 var(--ink);
  transition:transform .14s,box-shadow .14s,background .14s}
.ca-copy:hover{transform:translate(1px,1px);box-shadow:1px 1px 0 var(--ink)}
.ca-copy:active{transform:translate(2px,2px);box-shadow:0 0 0 var(--ink)}
.ca-copy[data-state="done"]{background:var(--pink)}
.ca-copy[data-state="soon"]{background:var(--cream)}
@media(max-width:700px){
  .ca-bar{bottom:14px;gap:8px;padding:6px 6px 6px 13px}
  .ca-tag{display:none}
  .ca-value{max-width:22ch;font-size:11.5px}
  .ca-copy{padding:8px 12px;font-size:11px}
}
body{padding-bottom:84px}
.toast{bottom:96px}
@media(max-width:700px){body{padding-bottom:74px}.toast{bottom:84px}}

/* === Buy section walker ===================================================
   Hachi trots along the very bottom of the "how to buy" section, on the
   boundary line where the community band starts. The section keeps a clear
   strip at its foot for him (nothing to collide with), and overflow:hidden
   clips him as he enters and leaves so he can never widen the page. The sprite
   carries 8.79% transparent space under the paws, so paintWalker() shifts the
   draw down by FEET_OFFSET to stand him exactly on the boundary line. */
.buy{position:relative;overflow:hidden;padding-bottom:210px}
.buy-walker{position:absolute;left:0;bottom:0;width:144px;height:144px;pointer-events:none;
  filter:drop-shadow(0 10px 12px rgba(60,20,0,.3));will-change:transform}
@media(max-width:700px){
  .buy{padding-bottom:158px}
  .buy-walker{width:100px;height:100px}
}
/* the sticker is positioned, so without this it would paint over the glyphs.
   NOTE: z-index only — do NOT set position here. .metric>svg and .metric-doodle
   are absolutely positioned corner decorations; declaring position:relative on
   them (as an earlier pass did) drops them back into the flow, where they land
   as stray glyphs at the foot of every card and add ~50px of dead height. */
.metric-number,.metric strong,.metric h3,.metric p{position:relative;z-index:1}
.metric>svg,.metric-doodle{z-index:1}

/* === Community artwork ====================================================
   The pack group shot replaces the lone sitting sprite. The new art is
   landscape (1.245:1) while the old sprite was portrait, so the frame is now
   driven by width with height:auto — the inherited 280x370 portrait box would
   letterbox it to a small strip in the middle. sitting.png stays in use for
   the hero's solo Hachiko. */
.community-character>img{width:min(100%,470px);height:auto;object-fit:contain}
@media(max-width:1100px){.community-character>img{width:min(100%,420px);height:auto}}
@media(max-width:700px){.community-character>img{width:min(100%,330px);height:auto}}

/* === Film band (index.html #game) ========================================
   section2.mp4 sits where the old game chapter was: full-bleed, edge to edge,
   between the story and tokenomics. The hero "Play Game and Earn!" button
   still scrolls here. */
.game-film{background:#0f1521;line-height:0;border-top:2px solid rgba(255,244,214,.16)}
.game-film-video{display:block;width:100%;height:auto}
/* The hero's second CTA. The site already scrolls smoothly; what makes the game
   get noticed is the nudge every few seconds. Under prefers-reduced-motion the
   global rule at the top of this file kills the animation and the button stays a
   plain link, so nothing shakes for people who asked for calm. */
.play-cta{margin-left:14px;font-size:13px;padding:13px 20px;animation:cta-shake 3.6s ease-in-out infinite}
.play-cta:hover{animation:none}
.play-cta .cta-mark{font-size:15px;line-height:1}
@keyframes cta-shake{
  0%,66%,100%{transform:translate(0,0) rotate(0)}
  68%{transform:translate(-3px,0) rotate(-2deg)}
  71%{transform:translate(3px,0) rotate(2deg)}
  74%{transform:translate(-3px,0) rotate(-2deg)}
  77%{transform:translate(2px,0) rotate(1.5deg)}
  80%{transform:translate(-1px,0) rotate(-1deg)}
  83%{transform:translate(0,0) rotate(0)}
  88%{transform:translateY(-4px)}
  92%{transform:translateY(1px)}
  95%{transform:translateY(0)}
}
@media(max-width:700px){
  .play-cta{margin:14px 0 0;font-size:12px;padding:12px 17px;border-width:2px}
}
