
:root{--lavender:#eee7f5;--ink:#554061;--muted:#8b7698;--paper:#fffdf7;--serif:Georgia,'Times New Roman',serif}
*{box-sizing:border-box}body{margin:0;color:var(--ink);background:var(--lavender);font-family:Arial,Helvetica,sans-serif;-webkit-font-smoothing:antialiased}button{font:inherit;color:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}button:focus-visible{outline:2px solid var(--ink);outline-offset:7px}button:disabled{opacity:.6;cursor:wait}[hidden]{display:none!important}h1,h2,p,figure{margin:0}h1,h2{font-family:var(--serif);font-weight:400;letter-spacing:-1.5px;line-height:1.1}h1:focus,h2:focus{outline:none}h1{font-size:clamp(42px,6vw,64px)}h1 span{font-size:.7em}h2{font-size:clamp(36px,5vw,55px)}img{display:block;width:100%;height:100%;object-fit:cover}.scene{min-height:100svh;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:38px 24px;text-align:center;animation:arrive .65s ease both}.quiet{border:0;background:transparent;font-size:12px;padding:12px 20px;letter-spacing:.2px;min-height:44px}.quiet:hover{color:#8a64a5}.date{font-size:9px;letter-spacing:3px;color:var(--muted);margin-bottom:25px}.intro h1{margin-bottom:55px}.envelope{position:relative;width:min(300px,78vw);aspect-ratio:1.52;border:1px solid #d0bfdc;background:#faf7ef;box-shadow:0 12px 35px #60437613;transform:rotate(-5deg);padding:0;transition:transform .35s}.envelope:hover{transform:rotate(0deg) translateY(-5px)}.envelope:before,.envelope:after{content:'';position:absolute;bottom:0;width:51%;height:100%;background:#f5f0e9}.envelope:before{left:0;clip-path:polygon(0 0,100% 60%,100% 100%,0 100%)}.envelope:after{right:0;clip-path:polygon(100% 0,0 60%,0 100%,100% 100%)}.flap{position:absolute;inset:0;background:#e7daee;clip-path:polygon(0 0,100% 0,50% 61%)}.heart{position:absolute;z-index:2;left:50%;top:48%;transform:translate(-50%,-50%);display:grid;place-items:center;width:46px;height:46px;background:#9776ad;color:#fff8ff;font:29px var(--serif);border-radius:50%;border:3px double #c2a9d1;box-shadow:0 3px 6px #715b8015}.whisper{font:italic 17px var(--serif);margin-top:43px}.intro>.quiet{margin-top:18px;color:var(--muted)}.album h2{font-size:clamp(30px,4vw,42px);margin-bottom:35px}.photo-stack{position:relative;width:min(310px,72vw);height:clamp(280px,47svh,410px);margin:0 10px}.back-photo{position:absolute;inset:0;background:#fcfaf5;border:1px solid #dfd3e6;box-shadow:0 5px 15px #6043760b}.back-one{transform:rotate(-7deg)}.back-two{transform:rotate(6deg)}.photo{position:relative;width:100%;height:100%;background:var(--paper);border:0;padding:10px 10px 40px;transform:rotate(-2deg);box-shadow:0 7px 20px #60437615;transition:transform .25s}.photo:hover{transform:rotate(0deg)}.photo img{object-position:50% 53%;background:#ded1e7}.photo-heart{position:absolute;bottom:7px;left:0;right:0;font:24px var(--serif);color:#987bab}.album-controls{display:flex;align-items:center;gap:25px;margin-top:24px}.arrow{border:0;background:none;font-size:20px;width:44px;height:44px}.album-controls>span{font-size:10px;letter-spacing:3px;color:var(--muted);min-width:40px}.continue{margin-top:10px}.wish h2{margin-bottom:12px}.cake-stage{position:relative;width:min(380px,85vw);margin:5px auto 0}.cake{display:block;width:100%;height:auto;overflow:visible}.cake-controls{display:flex;flex-direction:column;align-items:center;gap:7px}.pill{border:1px solid #9f86b0;border-radius:30px;background:transparent;padding:15px 24px;font-size:12px;transition:background .2s;min-height:44px}.pill:hover{background:#dfd0e9}.cake-controls .quiet{font-size:11px;color:var(--muted)}#mic-status{font-size:11px;line-height:1.8;min-height:36px;max-width:280px;margin-top:16px;color:var(--muted)}.birthday-chinese{font-family:var(--serif);font-size:16px;letter-spacing:7px;color:var(--muted);margin-bottom:20px}.ending h2{font-size:clamp(40px,5vw,57px);margin-bottom:30px}.ending h2 em{color:#8b6c9d}.last-photo{width:min(245px,64vw);height:clamp(230px,36svh,330px);background:var(--paper);padding:9px 9px 30px;transform:rotate(4deg);box-shadow:0 7px 25px #60437615}.last-photo img{object-position:50% 66%}.last-photo figcaption{padding-top:3px;font:23px var(--serif)}#final-note{font:italic 19px/1.5 var(--serif);margin-top:36px}.signature{font:italic 16px var(--serif);margin-top:13px;color:var(--muted)}.replay{font-size:21px;margin-top:10px;color:var(--muted)}.flames{transform-origin:50% 100%;animation:flicker 1.3s ease-in-out infinite alternate;transition:opacity .5s}.blown .flames{opacity:0;animation:none}#confetti{position:absolute;inset:0;pointer-events:none}#confetti i{position:absolute;top:5%;left:var(--x);width:5px;height:10px;background:var(--color);opacity:0;animation:confetti 2.6s var(--delay) ease-out both}@keyframes flicker{from{transform:scaleX(.95)}to{transform:scaleX(1.04) translateY(-2px)}}@keyframes confetti{0%{transform:translateY(0) rotate(0);opacity:0}10%{opacity:1}100%{transform:translateY(300px) rotate(var(--turn));opacity:0}}@keyframes arrive{from{opacity:0;transform:translateY(9px)}to{opacity:1;transform:translateY(0)}}@media(max-height:700px){.scene{padding:25px 20px}.intro h1{margin-bottom:35px}.album h2{margin-bottom:25px}.photo-stack{height:43svh}.album-controls{margin-top:15px}.ending h2{margin-bottom:20px}.birthday-chinese{margin-bottom:15px}#final-note{margin-top:26px}.wish .cake-stage{width:min(300px,75vw)}}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation:none!important;transition:none!important}}

/* Each memory stays on the table. The next one lands on top. */
.photo-stack{position:relative;display:block;border:0;background:transparent;padding:0;isolation:isolate;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent;width:min(310px,72vw);height:clamp(280px,49svh,420px);margin:0 12px}
.photo-stack:disabled{opacity:1;cursor:wait}
#polaroid-pile{position:absolute;inset:0;display:block;pointer-events:none}
.polaroid-card{position:absolute;inset:0;display:flex;flex-direction:column;gap:0;padding:11px 11px 0;background:#fffdf7;box-shadow:0 5px 15px #60437620;border:1px solid #ebe3ef;transform:translateX(var(--offset)) rotate(var(--rotation));animation:polaroid-drop .85s cubic-bezier(.2,.72,.25,1) both;transform-origin:50% 65%;will-change:transform}
.polaroid-card img{flex:1;min-height:0;width:100%;height:0;object-fit:cover;background:#f3eee8;user-select:none}
.polaroid-card figcaption{display:grid;place-items:center;min-height:49px;padding:8px 0 11px;font:italic clamp(15px,2vw,19px)/1.2 var(--serif);color:#71547f;white-space:normal}
.photo-cue{font-size:11px;letter-spacing:.4px;line-height:1.7;color:var(--muted);margin-top:42px;min-height:35px;max-width:270px}
.album{overflow:hidden}.album h2{margin-bottom:45px}
@keyframes polaroid-drop{0%{transform:translate(calc(var(--offset) + 25px),-110svh) rotate(calc(var(--rotation) - 15deg));opacity:0;box-shadow:0 40px 50px #6043760a}12%{opacity:1}73%{transform:translate(var(--offset),9px) rotate(calc(var(--rotation) + 1deg));box-shadow:0 3px 8px #60437624}87%{transform:translate(var(--offset),-4px) rotate(calc(var(--rotation) - .5deg))}100%{transform:translate(var(--offset),0) rotate(var(--rotation));opacity:1}}
@media(max-height:700px){.album h2{margin-bottom:30px}.photo-stack{height:43svh}.photo-cue{margin-top:31px}}
@media(prefers-reduced-motion:reduce){.polaroid-card{animation:none!important;will-change:auto}}

/* The same cards move from the pile to a lasting little tabletop. */
.ending{justify-content:center;padding:32px 24px 22px;overflow:hidden;background:radial-gradient(ellipse at 50% 43%,#f6f0f9 0%,#eee7f5 68%)}
.memory-table{position:relative;flex:none;width:min(740px,87vw);height:clamp(265px,48svh,440px);margin:0 auto 30px}
.polaroid-card.on-table{inset:auto;width:25%;height:auto;aspect-ratio:.78;padding:7px 7px 0;left:var(--table-x);top:var(--table-y);transform:rotate(var(--table-rotation));animation:spread-on-table 1.1s cubic-bezier(.22,.7,.25,1) var(--table-delay) both;box-shadow:2px 7px 14px #60437623}
.polaroid-card.on-table img{height:0;object-fit:cover}
.polaroid-card.on-table figcaption{min-height:27px;padding:4px 0 7px;font-size:clamp(8px,1.3vw,13px)}
.ending h2{max-width:490px;margin:12px auto 0;font:italic clamp(24px,3.2vw,35px)/1.3 var(--serif);letter-spacing:-.6px}
#love-note{font:italic 21px/1.4 var(--serif);margin-top:19px}
.ending .signature{font:italic 22px var(--serif);margin-top:10px}
.birthday-greeting{font:italic 18px var(--serif);margin:0 0 26px;color:var(--muted)}
.ending .replay{margin-top:14px}
@keyframes spread-on-table{from{left:37.5%;top:21%;transform:rotate(var(--rotation));opacity:1}to{left:var(--table-x);top:var(--table-y);transform:rotate(var(--table-rotation));opacity:1}}
@media(max-width:600px){.memory-table{height:clamp(265px,39svh,350px);margin-bottom:15px}.polaroid-card.on-table{padding:4px 4px 0}.polaroid-card.on-table figcaption{min-height:23px;font-size:8px;padding:4px 0 5px}.ending h2{max-width:290px;margin-top:12px}.birthday-greeting{margin-bottom:24px}}
@media(max-height:700px){.memory-table{height:37svh;min-height:235px;margin-bottom:8px}.ending{padding-top:26px}.ending h2{font-size:23px}#love-note{margin-top:12px}.birthday-greeting{margin-bottom:17px}}

/* A larger recap, with a third row on phones so every photo has room. */
.memory-table{width:min(820px,87vw);height:clamp(380px,62svh,580px)}
.polaroid-card.on-table{width:29%}
.polaroid-card.on-table figcaption{font-size:clamp(9px,1.4vw,14px)}
@media(max-width:600px){
  .memory-table{height:clamp(365px,107vw,450px);min-height:365px;margin-bottom:18px}
  .polaroid-card.on-table{width:32%;--table-x:var(--table-mobile-x)!important;--table-y:var(--table-mobile-y)!important}
  .polaroid-card.on-table figcaption{font-size:9px;min-height:27px}
  .ending{overflow-x:clip;overflow-y:visible}
}

/* The first Polaroid is the opening. Each memory brings its own little compliment. */
.album h2{display:grid;place-items:center;max-width:590px;min-height:110px;margin-bottom:28px;font-size:clamp(29px,3.5vw,42px);text-wrap:balance}
@media(max-width:600px){.album h2{min-height:124px;max-width:330px;margin-bottom:25px;font-size:28px;line-height:1.15;letter-spacing:-.8px}}
@media(max-height:700px){.album h2{min-height:104px;font-size:25px;margin-bottom:22px}}

@media(min-width:601px){.memory-table{height:calc(min(820px,87vw) * .78)}}


@font-face{font-family:'Polaroid Marker';src:url('/fonts/PermanentMarker-Regular.ttf') format('truetype');font-style:normal;font-weight:400;font-display:swap}
/* Broad, slightly uneven felt-tip ink on the physical Polaroid border. */
.polaroid-card figcaption{display:flex;flex-direction:column;justify-content:center;align-items:stretch;gap:5px;min-height:79px;padding:10px 8px 12px;font-family:'Polaroid Marker','Kaiti SC','STKaiti',cursive;font-style:normal;font-weight:400;font-size:clamp(16px,1.8vw,20px);line-height:1.18;color:#685a63}
.polaroid-card .caption-text{display:block;text-align:left;transform:rotate(-1.2deg);letter-spacing:.1px;text-shadow:none;font-size:.95em;opacity:1}
.polaroid-card:nth-child(3n+2) .caption-text{transform:rotate(.8deg)}
.polaroid-card:nth-child(3n) .caption-text{transform:rotate(-.5deg)}
.polaroid-card figcaption time{display:block;align-self:flex-end;transform:rotate(-2deg);font-size:12px;color:#685a63;letter-spacing:.3px;line-height:1.2}
.polaroid-card.on-table{aspect-ratio:.74}
.polaroid-card.on-table figcaption{min-height:49px;padding:6px 3px 8px;font-size:clamp(9px,1.2vw,13px);gap:3px}
.polaroid-card.on-table figcaption time{font-size:9px}
@media(max-width:600px){.polaroid-card.on-table figcaption{font-size:9px;min-height:43px;padding:5px 1px 6px;gap:2px}.polaroid-card.on-table figcaption time{font-size:7px;letter-spacing:0}}

/* A little lavender bakery cake: soft light, piping, striped candles and living flames. */
.wish{position:relative;overflow:hidden;background:radial-gradient(ellipse at 50% 48%,#f9f2f6 0%,#eee7f5 64%)}
.wish h2{font-size:clamp(38px,5vw,55px);max-width:440px;min-height:65px;display:grid;place-items:center;margin-bottom:0;text-wrap:balance;position:relative;z-index:1}
.wish .cake-stage{--breath-energy:0;width:min(440px,94vw);margin:0 auto -2px}
.cake-stage:before{content:'';position:absolute;width:70%;height:60%;left:15%;top:0;background:radial-gradient(ellipse,#ffe5b34a,transparent 68%);pointer-events:none;transition:opacity 1.2s}
.cake-stage.all-out:before{opacity:0}
.cake{position:relative}
.candle-flame{transform-origin:0 0;transform:rotate(calc(var(--breath-energy) * -30deg)) scaleX(calc(1 + var(--breath-energy) * .35)) scaleY(calc(1 - var(--breath-energy) * .22));transition:transform 90ms linear,opacity 180ms;opacity:1}
.flame-shape{transform-origin:0 0;animation:candle-dance 1.2s ease-in-out infinite alternate;animation-delay:var(--flicker-delay)}
.flame-glow{opacity:.75;animation:candle-halo 2s ease-in-out infinite alternate;animation-delay:var(--flicker-delay)}
.candle.is-out .candle-flame{opacity:0;transform:rotate(-38deg) scaleY(.15)}
.candle-smoke{opacity:0;pointer-events:none}
.candle.is-out .candle-smoke{animation:smoke-appear 2.3s ease-out both}
.candle.is-out .smoke-one{animation:smoke-rise 2.3s ease-out both}
.candle.is-out .smoke-two{animation:smoke-rise 2s .15s ease-out both;stroke-width:1;opacity:.6}
.wish .cake-controls{gap:7px;position:relative;z-index:1;min-height:100px}
.wish .pill{background:#80658f;color:#fffaf5;border-color:#80658f;padding:16px 25px;box-shadow:0 4px 12px #7d628b13;min-width:192px}
.wish .pill:hover{background:#70567f;border-color:#70567f}
.wish .pill[aria-pressed=true]{background:transparent;color:#80658f;box-shadow:none}
.wish .cake-controls .quiet{font-size:11px;color:#8c7898}
.breath-meter{--breath-progress:0;width:105px;height:3px;margin:8px auto 0;background:#ded1e5;border-radius:10px;overflow:hidden}
.breath-meter span{display:block;width:100%;height:100%;background:#c8a467;transform:scaleX(var(--breath-progress));transform-origin:left;transition:transform 70ms linear}
.wish #mic-status{min-height:40px;margin-top:13px;font-size:11px;max-width:290px;color:#87718e}
@keyframes candle-dance{0%{transform:rotate(-3deg) scale(.96,1.03)}55%{transform:rotate(2deg) scale(1.02,.97)}100%{transform:rotate(4deg) scale(.97,1.05)}}
@keyframes candle-halo{from{opacity:.5}to{opacity:.95}}
@keyframes smoke-appear{0%{opacity:0}10%{opacity:.65}65%{opacity:.3}100%{opacity:0}}
@keyframes smoke-rise{from{transform:translate(0,0) scaleX(.7)}to{transform:translate(12px,-28px) scaleX(1.3)}}
@media(max-width:600px){.wish{padding:40px 20px}.wish h2{font-size:40px;min-height:94px;max-width:320px}.wish .cake-stage{width:min(410px,96vw);margin-top:-8px}.wish .cake-controls{min-height:100px}.wish #mic-status{font-size:11px}}
@media(max-height:700px){.wish{padding-block:20px}.wish h2{font-size:34px;min-height:66px}.wish .cake-stage{width:min(350px,82vw)}}
@media(prefers-reduced-motion:reduce){.candle-smoke{display:none}.candle.is-out .candle-flame{transition:none}}

@font-face{font-family:'Cake Icing';src:url('/fonts/Pacifico-Regular.ttf') format('truetype');font-style:normal;font-weight:400;font-display:swap}
/* Flame envelopes deform around the wick; smoke is carried by air, then buoyancy. */
.cake-stage.has-flame-physics .candle-flame,.cake-stage.has-flame-physics .candle.is-out .candle-flame{transform:none;transition:opacity 150ms}
.cake-stage.has-flame-physics .flame-shape,.cake-stage.has-flame-physics .flame-glow{animation:none}
.cake-stage.has-smoke-physics .candle-smoke{display:none}
.cake-stage:before{opacity:var(--candle-light,1);transition:opacity .2s linear;background:radial-gradient(ellipse,#ffdf9a39,transparent 70%)}
.cake-stage.all-out:before{opacity:var(--candle-light,0)}
.cake-smoke-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:3}
#confetti{z-index:4}
.cake .icing-message{font-family:'Cake Icing',cursive}
@media(prefers-reduced-motion:reduce){.cake-smoke-layer{display:none}}

.breath-space{height:11px;width:100%;flex:none}
