@font-face{font-family:"Dancing Script";src:url("assets/DancingScript.ttf") format("truetype");font-style:normal;font-weight:400 700;font-display:swap}
@font-face{font-family:"Be Vietnam Pro";src:url("assets/BeVietnamPro-Regular.ttf") format("truetype");font-style:normal;font-weight:400;font-display:swap}
@font-face{font-family:"Be Vietnam Pro";src:url("assets/BeVietnamPro-SemiBold.ttf") format("truetype");font-style:normal;font-weight:600;font-display:swap}

:root{
  color-scheme:light;
  --paper:#fff8fb;
  --pink-100:#ffe4ef;
  --pink-200:#ffcadf;
  --pink-300:#ffa8cc;
  --pink-400:#ff7fb4;
  --pink-500:#f45d9c;
  --pink-600:#d9407f;
  --berry:#c2367a;
  --plum:#6b2650;
  --plum-soft:#8a4870;
  --script:"Dancing Script",cursive;
  --ease:cubic-bezier(.22,.8,.22,1);
  --bounce:cubic-bezier(.34,1.56,.64,1);
}
*{box-sizing:border-box}
[hidden]{display:none!important}
html,body{width:100%;height:100%;margin:0}
body{min-height:100vh;min-height:100dvh;overflow:hidden;background:#ffe2ef;color:var(--plum);font-family:"Be Vietnam Pro",system-ui,sans-serif;-webkit-font-smoothing:antialiased;-webkit-tap-highlight-color:transparent;touch-action:pan-y pinch-zoom;overscroll-behavior:none}
button{font:inherit;color:inherit;cursor:pointer}
:focus-visible{outline:2.5px solid var(--pink-500);outline-offset:3px}
::selection{background:var(--pink-300);color:#fff}
p{margin:0}

/* Sky: a bubblegum gradient with soft glows, clouds and twinkles. */
.sky{position:fixed;inset:0;overflow:hidden;pointer-events:none;background:linear-gradient(180deg,#ffc8df 0,#ffd9e9 34%,#ffeaf3 64%,#ffe0ee 100%)}
.glow{position:absolute;border-radius:50%;animation:glow-drift 18s ease-in-out infinite alternate}
.glow--a{left:-18vmax;top:-20vmax;width:62vmax;height:62vmax;background:radial-gradient(circle,#ffb3d4 0,#ffb3d400 68%)}
.glow--b{right:-22vmax;top:4vmax;width:58vmax;height:58vmax;background:radial-gradient(circle,#e6d6ff 0,#e6d6ff00 66%);animation-duration:22s;animation-delay:-6s}
.glow--c{left:10vw;bottom:-28vmax;width:70vmax;height:60vmax;background:radial-gradient(circle,#fff3f8 0,#fff3f800 66%);animation-duration:26s}
@keyframes glow-drift{to{transform:translate3d(3vmax,2vmax,0) scale(1.06)}}
/* Each stop tints the sky a little: matcha green, pizza peach, the evening ride home lilac. */
.tint{position:absolute;inset:0;opacity:0;transition:opacity 1.6s var(--ease)}
.tint--mint{background:radial-gradient(ellipse 70% 55% at 75% 40%,#d7f3c2aa 0,#d7f3c200 70%)}
.tint--peach{background:radial-gradient(ellipse 70% 55% at 35% 70%,#ffdcae99 0,#ffdcae00 70%)}
.tint--lilac{background:linear-gradient(180deg,#cdb5ff66 0,#e7d8ff33 45%,#e7d8ff00 80%)}
body[data-chapter="2"] .tint--mint{opacity:1}
body[data-chapter="3"] .tint--peach{opacity:1}
body[data-chapter="4"] .tint--lilac{opacity:1}

.sparkles{position:absolute;inset:0}
.sparkle{position:absolute;left:var(--x);top:var(--y);width:var(--s);height:var(--s);background:#fff;clip-path:polygon(50% 0,60% 40%,100% 50%,60% 60%,50% 100%,40% 60%,0 50%,40% 40%);opacity:.2;animation:twinkle var(--d) ease-in-out var(--delay) infinite alternate}
@keyframes twinkle{to{opacity:.95;transform:scale(1.25) rotate(20deg)}}

.cloud{position:absolute;width:var(--w);height:calc(var(--w)*.34);border-radius:999px;background:#fff;opacity:.8;animation:cloud-drift var(--t) linear infinite}
.cloud:before,.cloud:after{content:"";position:absolute;border-radius:50%;background:inherit}
.cloud:before{left:16%;bottom:30%;width:44%;height:130%}
.cloud:after{left:46%;bottom:22%;width:34%;height:100%}
.cloud--a{--w:130px;--t:70s;top:9%;left:-20%}
.cloud--b{--w:90px;--t:90s;top:30%;left:-30%;opacity:.6;animation-delay:-40s}
.cloud--c{--w:160px;--t:110s;top:62%;left:-30%;opacity:.55;animation-delay:-75s}
@keyframes cloud-drift{to{transform:translateX(150vw)}}

.cloud-sea{position:absolute;left:-10%;right:-10%;bottom:-2px;height:22vh}
.cloud-sea i{position:absolute;inset:0;background:radial-gradient(circle at 50% 100%,#fff 0 47%,#fff0 48%) 0 100%/150px 120px repeat-x;opacity:.9;animation:sea-sway 14s ease-in-out infinite alternate}
.cloud-sea i:first-child{bottom:28px;opacity:.55;background-color:transparent;background-image:radial-gradient(circle at 50% 100%,#ffeaf4 0 47%,#ffeaf400 48%);background-size:190px 150px;animation-duration:19s}
@keyframes sea-sway{to{transform:translateX(-40px)}}

/* The map of the day. */
.scene{position:fixed;z-index:2;left:0;right:0;top:0;height:56dvh;display:grid;place-items:center;padding:max(10px,env(safe-area-inset-top)) 10px 4dvh}
.map{display:block;width:100%;height:100%;max-width:520px;overflow:visible}
.map-sparkles use{fill:#fff;opacity:.3;transform-box:fill-box;transform-origin:center;animation:twinkle 2.6s ease-in-out var(--d) infinite alternate}

.route-road{fill:none;stroke:#fff;stroke-opacity:.62;stroke-width:15;stroke-linecap:round}
.route-dots{fill:none;stroke:var(--pink-300);stroke-width:5;stroke-linecap:round;stroke-dasharray:0 12}
.route-done{fill:none;stroke:var(--pink-400);stroke-width:5;stroke-linecap:round}

.stop{cursor:pointer}
.stop-float{animation:isle-float 5.4s ease-in-out infinite}
.stop--sundate .stop-float{animation-delay:-1.8s;animation-duration:6s}
.stop--bella .stop-float{animation-delay:-3.4s;animation-duration:5.8s}
@keyframes isle-float{50%{transform:translateY(-4px)}}
.stop-shadow{fill:#e2629f;opacity:.14}
.stop-glow{opacity:0;transform-box:fill-box;transform-origin:center;transition:opacity .8s var(--ease)}
.stop.is-here .stop-glow{opacity:1;animation:glow-pulse 2.6s ease-in-out infinite}
@keyframes glow-pulse{50%{transform:scale(1.08)}}
.landmark{transform-box:fill-box;transform-origin:50% 100%}
.stop.just-arrived .landmark{animation:land-hop .7s var(--bounce)}
@keyframes land-hop{40%{scale:1.08 .92}70%{scale:.96 1.06}}
.stop-label{font-family:var(--script);font-weight:700;font-size:19px;text-anchor:middle;fill:var(--plum-soft);stroke:#fff;stroke-width:5px;stroke-linejoin:round;paint-order:stroke;transition:fill .5s ease}
.stop.is-here .stop-label{fill:var(--pink-500)}

.balloon-bob{animation:balloon-bob 3.2s ease-in-out infinite}
@keyframes balloon-bob{50%{transform:translateY(-5px)}}

/* Soap bubbles drift up behind the card; tap one for a little note. */
.bubbles{position:fixed;z-index:3;inset:0;overflow:hidden;pointer-events:none}
.bubble{position:absolute;left:var(--x);bottom:calc(var(--s) * -1 - 10px);width:var(--s);height:var(--s);pointer-events:auto;cursor:pointer;animation:bubble-rise var(--d) linear var(--delay) infinite}
.bubble:before{content:"";position:absolute;inset:-10px}
.bubble i{display:block;width:100%;height:100%;border-radius:50%;background:radial-gradient(circle at 32% 28%,#fffffff2 0 7%,#fff0 20%),radial-gradient(circle at 68% 74%,#ffffff8c 0 5%,#fff0 14%),radial-gradient(circle,#fff0 0 56%,#ffd6ec55 66%,#dcc8ff80 78%,#ffb0d6a6 88%,#ffffffd9 100%);box-shadow:inset 0 0 6px #ffffff99,0 2px 10px #f45d9c1f;animation:bubble-sway calc(var(--d) / 3) ease-in-out infinite alternate}
@keyframes bubble-rise{to{transform:translateY(calc(-100dvh - var(--s) - 40px))}}
@keyframes bubble-sway{from{transform:translateX(calc(var(--sway) * -1)) scale(1,.97)}to{transform:translateX(var(--sway)) scale(.97,1)}}
.pop{position:fixed;z-index:4;width:var(--s);height:var(--s);margin:calc(var(--s) / -2) 0 0 calc(var(--s) / -2);pointer-events:none}
.pop:before{content:"";position:absolute;inset:0;border-radius:50%;border:2px solid #fff;animation:pop-ring .45s ease-out forwards}
.pop i{position:absolute;left:50%;top:50%;width:6px;height:6px;margin:-3px;border-radius:50%;background:#fff;box-shadow:0 0 6px #ff9cc8;animation:pop-drop .55s ease-out forwards}
@keyframes pop-ring{from{transform:scale(.85);opacity:1}to{transform:scale(1.6);opacity:0}}
@keyframes pop-drop{to{transform:rotate(var(--a)) translateY(calc(var(--s) * -.9)) scale(.3);opacity:0}}

.pop-message{position:fixed;z-index:6;left:var(--x,50%);top:var(--y,40%);width:max-content;max-width:min(260px,80vw);padding:10px 16px;border-radius:20px;background:#fff;color:var(--berry);font-family:var(--script);font-weight:700;font-size:1.3rem;line-height:1.2;text-align:center;box-shadow:0 10px 30px #f45d9c33,0 0 0 1.5px var(--pink-200);transform:translate(-50%,-100%) scale(.7);opacity:0;pointer-events:none;transition:opacity .25s ease,transform .35s var(--bounce)}
.pop-message:after{content:"";position:absolute;left:50%;bottom:-7px;width:14px;height:14px;margin-left:-7px;background:#fff;border-radius:0 0 4px 0;box-shadow:1.5px 1.5px 0 var(--pink-200);transform:rotate(45deg)}
.pop-message.is-visible{opacity:1;transform:translate(-50%,-100%) translateY(-10px) scale(1)}

/* The card: a frosted letter with a stitched edge. */
.card{position:fixed;z-index:5;left:0;right:0;bottom:0;display:flex;flex-direction:column;min-height:45dvh;max-height:62dvh;padding:26px max(22px,env(safe-area-inset-left) + 18px) max(16px,env(safe-area-inset-bottom) + 10px) max(22px,env(safe-area-inset-right) + 18px);background:#fff8fbd9;-webkit-backdrop-filter:blur(14px) saturate(1.15);backdrop-filter:blur(14px) saturate(1.15);border-radius:32px 32px 0 0;box-shadow:0 -12px 40px #f45d9c26,inset 0 1px 0 #fff;text-align:center}
.card:after{content:"";position:absolute;inset:9px 9px 0;border:1.5px dashed var(--pink-200);border-bottom:0;border-radius:24px 24px 0 0;pointer-events:none}
.card-body{position:relative;z-index:1;flex:1;min-height:0;overflow-y:auto;scrollbar-width:none;display:flex;flex-direction:column;align-items:center;gap:9px;padding:4px 2px}
.card-body::-webkit-scrollbar{display:none}
/* Centred while it fits, top-aligned and scrollable once it does not. */
.card-body>:first-child{margin-top:auto}
.card-body:after{content:"";margin-top:auto}
.card-body>*{transition:opacity .35s ease,transform .45s var(--ease)}
.card-body.is-leaving>*{opacity:0;transform:translateY(8px);transition-duration:.18s}

.card-eyebrow{font-weight:600;font-size:.72rem;letter-spacing:.18em;text-transform:uppercase;color:var(--pink-500)}
.card-title{margin:0;max-width:16ch;font-family:var(--script);font-weight:700;font-size:clamp(2.15rem,9.4vw,2.9rem);line-height:1.12;color:var(--berry);text-wrap:balance;text-shadow:0 2px 0 #fff,0 8px 22px #ff7fb440}
.card-title .word{display:inline-block;animation:word-in .75s var(--ease) both;animation-delay:calc(var(--i) * 75ms + 60ms)}
@keyframes word-in{from{opacity:0;transform:translateY(.42em) rotate(-4deg);filter:blur(4px)}}
.card-note{max-width:31ch;font-size:.95rem;line-height:1.6;color:var(--plum-soft);text-wrap:pretty}

.place{display:grid;justify-items:start;gap:2px;width:100%;max-width:330px;margin-top:4px;padding:12px 15px 13px;border-radius:18px;background:#fff;box-shadow:0 0 0 1px var(--pink-100),0 8px 20px #f45d9c17;text-align:left}
.place-name{font-weight:600;font-size:.92rem;color:var(--plum)}
.place-address{font-size:.8rem;line-height:1.45;color:var(--plum-soft)}
.pill-link{display:inline-flex;align-items:center;min-height:34px;margin-top:8px;padding:6px 14px;border-radius:999px;background:var(--pink-100);color:var(--berry);font-weight:600;font-size:.8rem;text-decoration:none;transition:background .2s ease,transform .2s var(--ease)}
.pill-link:hover{background:var(--pink-200)}
.pill-link:active{transform:scale(.96)}

.summary{display:flex;flex-direction:column;align-items:center;width:100%;max-width:340px}
.route-list{position:relative;width:100%;margin:2px 0 0;padding:0;list-style:none;text-align:left}
.route-list:before{content:"";position:absolute;left:15px;top:18px;bottom:18px;border-left:2.5px dotted var(--pink-300)}
.route-item{position:relative;display:grid;grid-template-columns:32px 1fr;align-items:center;gap:10px;width:100%;padding:5px 6px 5px 0;border:0;border-radius:14px;background:none;text-align:left;transition:background .2s ease}
.route-item:hover{background:#ffe4ef80}
.route-num{display:grid;place-items:center;width:32px;height:32px;border-radius:50%;background:var(--pink-400);color:#fff;font-family:var(--script);font-weight:700;font-size:1.15rem;box-shadow:0 3px 0 var(--pink-600),inset 0 2px 0 #ffffff55}
.route-text{display:grid;line-height:1.3}
.route-text b{font-weight:600;font-size:.88rem;color:var(--plum)}
.route-text small{font-size:.76rem;color:var(--plum-soft)}

.card-actions{position:relative;z-index:1;display:flex;justify-content:center;gap:10px;margin-top:14px}
.btn{position:relative;min-height:48px;padding:12px 22px;border:0;border-radius:999px;font-weight:600;font-size:.95rem;transition:transform .15s var(--ease),box-shadow .15s var(--ease)}
.btn--candy{min-width:156px;color:#fff;background:linear-gradient(180deg,#ffa0ca 0,#ff74af 55%,#f45d9c 100%);box-shadow:0 5px 0 var(--pink-600),0 14px 24px #f45d9c4d;text-shadow:0 1px 0 #d9407f80}
.btn--candy:before{content:"";position:absolute;left:16%;right:16%;top:5px;height:36%;border-radius:999px;background:linear-gradient(180deg,#ffffffb3,#fff0);pointer-events:none}
.btn--candy:active{transform:translateY(4px);box-shadow:0 1px 0 var(--pink-600),0 6px 14px #f45d9c40}
.btn--ghost{background:#fff;color:var(--berry);box-shadow:inset 0 0 0 1.5px var(--pink-200),0 4px 0 var(--pink-100)}
.btn--ghost:active{transform:translateY(3px);box-shadow:inset 0 0 0 1.5px var(--pink-200),0 1px 0 var(--pink-100)}
.btn--candy.is-wiggle{animation:wiggle 2.4s ease-in-out 1.2s infinite}
@keyframes wiggle{0%,72%,100%{transform:none}76%{transform:rotate(-3deg) scale(1.03)}82%{transform:rotate(3deg) scale(1.03)}88%{transform:rotate(-2deg)}}

.dots{position:relative;z-index:1;display:flex;justify-content:center;gap:7px;margin-top:14px}
.dot{position:relative;width:8px;height:8px;padding:0;border:0;border-radius:999px;background:var(--pink-200);transition:width .35s var(--ease),background .35s ease}
.dot:after{content:"";position:absolute;inset:-9px -4px}
.dot.is-active{width:24px;background:var(--pink-400)}
.card-hint{position:relative;z-index:1;margin-top:10px;font-size:.74rem;color:var(--pink-400);transition:opacity .4s ease}

.confetti-bit{position:fixed;z-index:7;width:var(--s);height:var(--s);margin:calc(var(--s) / -2) 0 0 calc(var(--s) / -2);pointer-events:none}
.confetti-bit--heart{background:var(--c);-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-16 -29 32 30'%3E%3Cpath d='M0 0C-4-4-15-11-15-19C-15-25-10-28-6-28C-3-28-1-26 0-24C1-26 3-28 6-28C10-28 15-25 15-19C15-11 4-4 0 0Z'/%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-16 -29 32 30'%3E%3Cpath d='M0 0C-4-4-15-11-15-19C-15-25-10-28-6-28C-3-28-1-26 0-24C1-26 3-28 6-28C10-28 15-25 15-19C15-11 4-4 0 0Z'/%3E%3C/svg%3E") center/contain no-repeat}
.confetti-bit--dot{border-radius:50%;background:radial-gradient(circle at 32% 30%,#fff 0 12%,#fff0 30%),radial-gradient(circle,#fff0 55%,#ffc2df 80%,#fff 100%)}

.no-script{position:fixed;z-index:9;left:50%;bottom:20px;transform:translateX(-50%);padding:10px 16px;border-radius:14px;background:#fff;color:var(--berry)}

/* Wide screens and phones held sideways: map on the left, letter on the right. */
@media (min-width:900px),(orientation:landscape) and (max-height:560px){
  .scene{right:auto;bottom:0;height:auto;width:calc(100% - min(430px,38vw) - clamp(28px,5vw,80px));padding:5vh 2vw 5vh 4vw}
  .map{max-width:none;max-height:92vh}
  .card{left:auto;right:clamp(28px,5vw,80px);top:50%;bottom:auto;transform:translateY(-50%);width:min(430px,38vw);min-height:min(480px,84dvh);max-height:88dvh;padding:38px 30px 24px;border-radius:32px;box-shadow:0 24px 60px #f45d9c2e,inset 0 1px 0 #fff}
  .card:after{inset:10px;border-bottom:1.5px dashed var(--pink-200);border-radius:24px}
}
@media (orientation:landscape) and (max-height:560px){
  .card{min-height:0;padding:22px 24px 14px}
  .card-title{font-size:2rem}
  .card-actions{margin-top:10px}
  .dots{margin-top:10px}
  .card-hint{display:none}
}
@media (max-width:899px) and (max-height:700px) and (orientation:portrait){
  .scene{height:52dvh}
  .card{min-height:48dvh;max-height:62dvh;padding-top:22px}
  .card-title{font-size:2.05rem}
  .card-note{font-size:.9rem}
}

body.is-paused *,body.is-paused *:before,body.is-paused *:after{animation-play-state:paused!important}
@media (prefers-reduced-motion:reduce){
  .glow,.cloud,.cloud-sea i,.sparkle,.map-sparkles use,.stop-float,.balloon-bob,.stop.is-here .stop-glow,.btn--candy.is-wiggle{animation:none}
  .bubble,.bubble i{animation-duration:0s;animation-iteration-count:1}
  .card-title .word{animation:none}
}
