body{margin:0;background:#FFF4F6;color:#3A0A17;font-family:'Quicksand',system-ui,sans-serif;-webkit-font-smoothing:antialiased}
a{color:#B3123A}a:hover{color:#7A0B27}
*{box-sizing:border-box}
.serif{font-family:'Fraunces',Georgia,serif}
.hand{font-family:'Caveat',cursive}

/* floating hearts */
.float-heart{position:absolute;bottom:-60px;animation-name:floatUp;animation-timing-function:linear;animation-iteration-count:infinite;opacity:0}
@keyframes floatUp{0%{transform:translateY(0) rotate(0deg) scale(.8);opacity:0}10%{opacity:.9}50%{transform:translateY(-55vh) translateX(30px) rotate(20deg) scale(1)}90%{opacity:.7}100%{transform:translateY(-115vh) translateX(-20px) rotate(-15deg) scale(1.1);opacity:0}}

/* intro messages */
.msg{opacity:0;transform:translateY(24px) scale(.96);animation:msgIn .9s cubic-bezier(.2,.8,.2,1) forwards}
@keyframes msgIn{to{opacity:1;transform:none}}
.d1{animation-delay:.4s}.d2{animation-delay:1.9s}.d3{animation-delay:3.4s}.d4{animation-delay:4.6s}
.beat{animation:beat 1.4s ease-in-out infinite;transform-origin:center}
@keyframes beat{0%,100%{transform:scale(1)}15%{transform:scale(1.18)}30%{transform:scale(.96)}45%{transform:scale(1.1)}}
.typing span{display:inline-block;width:8px;height:8px;border-radius:50%;background:#E8436F;margin:0 3px;animation:dot 1.2s infinite}
.typing span:nth-child(2){animation-delay:.2s}.typing span:nth-child(3){animation-delay:.4s}
@keyframes dot{0%,80%,100%{transform:translateY(0);opacity:.4}40%{transform:translateY(-6px);opacity:1}}

/* buttons */
.btn{font-family:'Quicksand',sans-serif;font-weight:700;font-size:18px;border:0;cursor:pointer;border-radius:999px;padding:16px 36px;background:#B3123A;color:#fff;box-shadow:0 10px 30px rgba(179,18,58,.35);transition:transform .2s,box-shadow .2s,background .2s;text-decoration:none;display:inline-flex;align-items:center;gap:10px}
.btn:hover{transform:translateY(-2px) scale(1.03);background:#9A0F31;color:#fff;box-shadow:0 14px 36px rgba(179,18,58,.45)}
.btn:focus-visible{outline:3px solid #FF8FB1;outline-offset:3px}
.btn-ghost{background:#fff;color:#B3123A;box-shadow:0 6px 18px rgba(179,18,58,.18)}
.btn-ghost:hover{background:#FFE3EA;color:#7A0B27}

/* lock */
.lock-card{animation:msgIn .8s cubic-bezier(.2,.8,.2,1) both}
.shake{animation:shake .5s}
@keyframes shake{10%,90%{transform:translateX(-2px)}20%,80%{transform:translateX(5px)}30%,50%,70%{transform:translateX(-10px)}40%,60%{transform:translateX(10px)}}
.key{width:76px;height:76px;border-radius:50%;border:2px solid #FFC2D2;background:#fff;color:#7A0B27;font-family:'Fraunces',serif;font-size:28px;cursor:pointer;transition:transform .12s,background .2s,border-color .2s}
.key:hover{background:#FFE3EA;border-color:#E8436F}
.key:active{transform:scale(.9);background:#FFC2D2}
.key:focus-visible{outline:3px solid #B3123A;outline-offset:2px}
.code-input{width:220px;text-align:center;font-family:'Fraunces',serif;font-size:40px;letter-spacing:18px;padding:12px 0 12px 18px;border:0;border-bottom:3px solid #FFC2D2;background:transparent;color:#B3123A;outline:none}
.code-input:focus{border-bottom-color:#B3123A}

/* unlock */
.unlock-flash{position:fixed;inset:0;background:#B3123A;z-index:50;pointer-events:none;animation:flash 1.2s ease forwards}
@keyframes flash{0%{opacity:1;clip-path:circle(150% at 50% 50%)}100%{opacity:1;clip-path:circle(0% at 50% 50%)}}
.hero-title{animation:heroIn 1.4s cubic-bezier(.2,.8,.2,1) .5s both}
@keyframes heroIn{from{opacity:0;transform:translateY(40px) scale(.9);filter:blur(8px)}to{opacity:1;transform:none;filter:none}}
.hero-sub{animation:msgIn 1s ease 1.3s both;opacity:0}
.hero-photo{position:absolute;border:8px solid #fff;border-bottom-width:30px;box-shadow:0 18px 40px rgba(58,10,23,.35);animation:dropIn 1s cubic-bezier(.2,.9,.3,1.2) both;background:#fff}
.hero-photo img{display:block;width:100%;height:100%;object-fit:cover}
@keyframes dropIn{from{opacity:0;transform:translateY(-80px) rotate(-20deg) scale(.6)}}
.scroll-cue{animation:bob 1.8s ease-in-out infinite}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(10px)}}

/* polaroids */
.masonry{columns:4 220px;column-gap:22px}
.polaroid{break-inside:avoid;margin:0 0 22px;background:#fff;padding:10px 10px 14px;box-shadow:0 8px 24px rgba(122,11,39,.14);transition:transform .35s cubic-bezier(.2,.8,.2,1),box-shadow .35s;cursor:zoom-in;display:block;width:100%;border:0;text-align:left;font:inherit}
.polaroid:hover{transform:rotate(0deg) scale(1.05) !important;box-shadow:0 20px 44px rgba(122,11,39,.28);z-index:2;position:relative}
.polaroid:focus-visible{outline:3px solid #B3123A;outline-offset:3px}
.polaroid img{display:block;width:100%;height:auto}
.tape{display:block;width:70px;height:22px;background:rgba(255,143,177,.55);margin:-20px auto 8px;transform:rotate(-3deg)}

@supports (animation-timeline: view()){
.reveal{animation:revealUp linear both;animation-timeline:view();animation-range:entry 0% cover 28%}
.reveal-side{animation:revealSide linear both;animation-timeline:view();animation-range:entry 0% cover 30%}
}
@keyframes revealUp{from{opacity:0;transform:perspective(800px) translateY(80px) rotateX(28deg) scale(.9)}to{opacity:1;transform:none}}
@keyframes revealSide{from{opacity:0;transform:translateX(-60px)}to{opacity:1;transform:none}}

.year-num{font-family:'Fraunces',serif;font-weight:700;font-size:clamp(72px,12vw,160px);line-height:.85;color:transparent;-webkit-text-stroke:2px #E8436F}

/* lightbox */
.lb{position:fixed;inset:0;background:rgba(58,10,23,.88);z-index:60;display:flex;align-items:center;justify-content:center;padding:24px;animation:fadeIn .3s ease}
.lb img{max-width:min(92vw,900px);max-height:84vh;border:10px solid #fff;border-bottom-width:40px;box-shadow:0 30px 80px rgba(0,0,0,.5);animation:zoomIn .4s cubic-bezier(.2,.9,.3,1.2)}
@keyframes fadeIn{from{opacity:0}}
@keyframes zoomIn{from{transform:scale(.7) rotate(-4deg);opacity:0}}

/* wish burst */
.burst{position:absolute;width:28px;height:28px;margin:-14px 0 0 -14px;animation:burst 1.8s cubic-bezier(.1,.8,.3,1) forwards}
@keyframes burst{0%{left:0;top:0;transform:scale(.2);opacity:1}70%{opacity:1}100%{transform:scale(1.2) rotate(35deg);opacity:0}}
.wish-text{animation:msgIn .8s ease .3s both;opacity:0}
.candle-flame{animation:flicker .15s ease-in-out infinite alternate;transform-origin:50% 100%}
@keyframes flicker{from{transform:scaleY(1) rotate(-2deg)}to{transform:scaleY(1.12) rotate(2deg)}}

/* ---- extra animations ---- */
.progress{position:fixed;left:0;top:0;height:5px;width:100%;background:#FF8FB1;transform-origin:0 50%;transform:scaleX(0);z-index:70;pointer-events:none}
@supports (animation-timeline: scroll()){.progress{animation:grow linear both;animation-timeline:scroll(root)}}
@keyframes grow{to{transform:scaleX(1)}}
.wave{display:inline-block;animation:wave 2.6s ease-in-out infinite}
@keyframes wave{0%,100%{transform:translateY(0) rotate(0)}25%{transform:translateY(-14px) rotate(-4deg)}50%{transform:translateY(0) rotate(0)}}
.balloon{position:absolute;bottom:-180px;animation:rise linear infinite;z-index:1}
@keyframes rise{0%{transform:translateY(0) rotate(-4deg)}50%{transform:translateY(-60vh) rotate(5deg)}100%{transform:translateY(-130vh) rotate(-3deg)}}
.hero-photo{overflow:hidden}
.hero-photo img{animation:kenburns 10s ease-in-out infinite alternate}
@keyframes kenburns{from{transform:scale(1)}to{transform:scale(1.14) translate(-3%,-2%)}}
.rain{position:fixed;top:-40px;z-index:55;pointer-events:none;animation:rainFall linear forwards;opacity:0}
@keyframes rainFall{0%{opacity:1;transform:translateY(0) rotate(0)}85%{opacity:1}100%{opacity:0;transform:translateY(110vh) rotate(540deg)}}
.twinkle{position:absolute;animation:twinkle 2.4s ease-in-out infinite}
@keyframes twinkle{0%,100%{opacity:0;transform:scale(.3) rotate(0)}50%{opacity:1;transform:scale(1) rotate(45deg)}}
.marquee{overflow:hidden;white-space:nowrap;background:#E8436F;color:#fff;padding:14px 0}
.marquee-track{display:inline-block;animation:marq 26s linear infinite}
.marquee-track.rev{animation-direction:reverse}
@keyframes marq{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.bobber{animation:bobSlow 5s ease-in-out infinite}
@keyframes bobSlow{0%,100%{transform:translateY(0)}50%{transform:translateY(-12px)}}
.pop{position:fixed;width:22px;height:22px;margin:-11px 0 0 -11px;pointer-events:none;z-index:80;opacity:0;animation-duration:1s;animation-timing-function:cubic-bezier(.1,.8,.3,1);animation-fill-mode:forwards}
@keyframes popA{0%{margin-left:-11px;margin-top:-11px;opacity:1;transform:scale(.3)}100%{opacity:0;transform:scale(1.1) rotate(30deg)}}
@keyframes popB{0%{margin-left:-11px;margin-top:-11px;opacity:1;transform:scale(.3)}100%{opacity:0;transform:scale(1.1) rotate(-30deg)}}
.env{position:relative;width:min(520px,100%);aspect-ratio:3/2;margin:0 auto;background:#FFC2D2;border-radius:12px;box-shadow:0 30px 70px rgba(58,10,23,.4);animation:envFloat 3s ease-in-out infinite}
@keyframes envFloat{0%,100%{transform:translateY(0) rotate(-1deg)}50%{transform:translateY(-10px) rotate(1deg)}}
.env-flap{position:absolute;left:0;right:0;top:0;height:60%;background:#FF8FB1;clip-path:polygon(0 0,100% 0,50% 100%);border-radius:12px 12px 0 0}
.env-seal{position:absolute;left:50%;top:60%;transform:translate(-50%,-50%)}
.letter-in{animation:letterIn 1.1s cubic-bezier(.2,.9,.3,1.1) both}
@keyframes letterIn{from{opacity:0;transform:translateY(120px) scale(.85) rotate(-4deg)}to{opacity:1;transform:rotate(-.6deg)}}
.bday-num{font-family:'Fraunces',serif;font-weight:700;font-size:96px;line-height:1;color:#B3123A;animation:beat 2s ease-in-out infinite}
@supports (animation-timeline: view()){.year-num{animation:yearFill linear both;animation-timeline:view();animation-range:entry 10% cover 45%}}
@keyframes yearFill{from{color:transparent;letter-spacing:.2em}to{color:#FFC2D2;letter-spacing:0}}

/* ---- one constant sticky calendar for the whole story ---- */
.story-layout{display:flex;align-items:flex-start;gap:36px 48px}
.cal-rail{flex:0 0 240px;position:sticky;top:28px;z-index:4;padding-top:14px;align-self:flex-start}
.chapter-stack{flex:999 1 560px;min-width:0}
.chapter{margin-bottom:130px}
.chapter:last-child{margin-bottom:40px}
.cal-wrap{position:relative;width:220px;height:250px;margin:0 auto;perspective:1000px}
.cal,.cal-edge{position:absolute;inset:0;border-radius:18px}
.cal{background:#fff;box-shadow:0 16px 36px rgba(122,11,39,.2);overflow:hidden;display:flex;flex-direction:column;transform-origin:50% 0;backface-visibility:hidden}
.cal-edge{background:#FFE3EA;box-shadow:0 6px 16px rgba(122,11,39,.12)}
.cal-edge.e1{transform:translateY(7px) scale(.97);background:#FFC2D2}
.cal-edge.e2{transform:translateY(14px) scale(.94);background:#FF8FB1}
.cal-edge.e3{transform:translateY(21px) scale(.91);background:#E8436F}
.cal-head{position:relative;height:64px;background:#B3123A;color:#FFE3EA;display:flex;align-items:flex-end;justify-content:center;padding-bottom:10px;font-family:'Quicksand',sans-serif;font-weight:700;font-size:13px;letter-spacing:.32em;text-transform:uppercase}
.cal-head::after{content:'';position:absolute;left:10px;right:10px;bottom:-5px;border-bottom:3px dotted #FFC2D2}
.cal-body{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px}
.cal-year{font-family:'Fraunces',serif;font-weight:700;font-size:78px;line-height:1;color:#B3123A;letter-spacing:-.02em}
.cal-sub{font-family:'Caveat',cursive;font-size:26px;color:#E8436F}
.cal-ring{position:absolute;top:-14px;width:16px;height:34px;border:4px solid #7A0B27;border-radius:10px;background:#FFF4F6;z-index:5}
.cal-prev{display:none;pointer-events:none}
.cal-wrap.tearing .cal-prev{display:flex;animation:calTear .85s cubic-bezier(.2,.7,.2,1) both}
.cal-wrap.tearing .cal-now{animation:calSettle .85s cubic-bezier(.2,.7,.2,1) both}
.cal-wrap.tearing .cal-edge.e1{animation:calBump .85s ease both}
@keyframes calTear{0%{transform:rotateX(0) rotate(0);opacity:1}35%{transform:rotateX(-30deg) rotate(-2deg);opacity:1}75%{transform:rotateX(-120deg) translateY(-30px) rotate(-6deg);opacity:1}100%{transform:rotateX(-175deg) translate(-40px,-120px) rotate(-14deg);opacity:0}}
@keyframes calSettle{0%{transform:translateY(0) scale(.97);filter:brightness(.92)}100%{transform:none;filter:none}}
@keyframes calBump{0%,100%{transform:translateY(7px) scale(.97)}50%{transform:translateY(11px) scale(.96)}}
.polaroid::after{content:'';position:absolute;inset:0;background:linear-gradient(115deg,transparent 40%,rgba(255,255,255,.55) 50%,transparent 60%);background-size:250% 100%;background-position:120% 0;opacity:0;transition:opacity .2s;pointer-events:none}
.polaroid{position:relative}
.polaroid:hover::after{opacity:1;animation:shine .9s ease}
@keyframes shine{from{background-position:120% 0}to{background-position:-60% 0}}
@media (max-width:760px){.story-layout{flex-direction:column;gap:8px}.cal-rail{position:sticky;top:12px;flex:0 0 auto;width:100%;padding-top:8px;background:linear-gradient(#FFF4F6 70%,rgba(255,244,246,0));padding-bottom:12px}.cal-wrap{width:190px;height:216px}.cal-year{font-size:66px}}

@media (prefers-reduced-motion: reduce){*{animation-duration:.01ms !important;animation-iteration-count:1 !important}}
@media (max-width:640px){.key{width:64px;height:64px;font-size:24px}.hero-photo{display:none}.masonry{columns:2 140px;column-gap:14px}.polaroid{margin-bottom:14px;padding:6px 6px 10px}}
[hidden]{display:none !important}
