:root {
  --red: #e2323f;
  --red-d: #c42a36;
  --gold: #ffc83d;
  --ink: #4b3a34;
  --bg: #fbe9ec;
  --bg-grad: radial-gradient(120% 80% at 50% 38%, #fff7f8 0%, #fbe9ec 70%, #f8dfe4 100%);
  --paper: #fcf6ea;
  --mottle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.012' numOctaves='3' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .5 0 0 0 0 .36 0 0 0 0 .22 0 0 0 .16 -.04'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23m)'/%3E%3C/svg%3E");
  --frame: rgba(214, 58, 58, .5);
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .45 0 0 0 0 .3 0 0 0 0 .2 0 0 0 .07 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  --soft: cubic-bezier(.22, 1, .36, 1);
  --spring: cubic-bezier(.3, 1.2, .45, 1);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body { height: 100%; }

body {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: var(--bg);
  font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Noto Sans SC', sans-serif;
  color: var(--ink);
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
  user-select: none;
}

button {
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  outline: none;
}

/* ---------- Stage ---------- */
.stage {
  --w: min(100vw, 50vh, 540px);
  position: relative;
  width: var(--w);
  height: calc(var(--w) * 2);
  container-type: size;
  overflow: hidden;
  background: var(--bg-grad);
}
@supports (height: 100dvh) {
  .stage { --w: min(100vw, 50dvh, 540px); }
}
@media (max-aspect-ratio: 1/2) {
  .stage { width: 100vw; height: 100vh; height: 100dvh; }
}
@media (min-width: 640px) and (min-aspect-ratio: 3/4) {
  .stage {
    border-radius: 24px;
    box-shadow: 0 10px 50px rgba(0, 0, 0, .07), 0 0 0 1px rgba(0, 0, 0, .04);
  }
}

.sparkles {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
}
.sparkle {
  position: absolute;
  opacity: 0;
  animation: twinkle var(--d, 3s) ease-in-out var(--delay, 0s) infinite;
}
.sparkle.star {
  clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
}
.sparkle.dot { border-radius: 50%; }
.sparkle.twinkle4 {
  clip-path: polygon(50% 0, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0 50%, 38% 38%);
}
@keyframes twinkle {
  0%, 100% { opacity: 0; transform: scale(.4) rotate(0deg); }
  50% { opacity: .85; transform: scale(1) rotate(40deg); }
}

/* ---------- Intro: 收到来信 ---------- */
.intro {
  position: absolute;
  inset: 0;
  z-index: 20;
  background: var(--bg-grad);
  transition: opacity 1.2s ease, visibility 1.2s;
}
.intro.gone {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
.intro > * { position: absolute; left: 50%; }

.intro-title, .intro-from, .intro-hint {
  white-space: nowrap;
  text-align: center;
  opacity: 0;
  transform: translate(-50%, 1cqh);
}
.intro-title {
  top: 32%;
  font-size: 5.4cqw;
  font-weight: 500;
  letter-spacing: .6cqw;
  text-indent: .6cqw;
  color: #2f2a28;
}
.intro-from {
  top: 35.6%;
  font-size: 3.2cqw;
  letter-spacing: .3cqw;
  color: #9a9290;
}
.intro-hint {
  top: 64.5%;
  font-size: 3.1cqw;
  letter-spacing: .3cqw;
  color: #b3aaa7;
}
.intro.run .intro-title { animation: fadeUp 1.2s var(--soft) .3s forwards; }
.intro.run .intro-from  { animation: fadeUp 1.2s var(--soft) .3s forwards; }
.intro.run .intro-hint  { animation: fadeUp 1s var(--soft) 1.4s forwards; }
@keyframes fadeUp { to { opacity: 1; transform: translate(-50%, 0); } }

.mail {
  top: 38.5%;
  width: 64cqw;
  opacity: 0;
  transform: translateX(-50%);
  cursor: pointer;
}
.mail img {
  display: block;
  width: 100%;
  pointer-events: none;
  -webkit-user-drag: none;
}
.intro.run .mail { animation: mailIn 1.2s var(--soft) .3s both; }
.intro.run .mail img { animation: mailFloat 4s ease-in-out 1.6s infinite; }
@keyframes mailIn {
  from { opacity: 0; transform: translate(-50%, 3cqh); }
  to { opacity: 1; transform: translate(-50%, 0); }
}
@keyframes mailFloat {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-1.2cqw); }
}

.intro.opening .mail { animation: mailOpen 1s ease-in-out forwards; }
.intro.opening .mail img { animation: none; }
@keyframes mailOpen {
  0%   { opacity: 1; transform: translate(-50%, 0); }
  20%  { transform: translate(-50%, 0) rotate(-3deg); }
  40%  { opacity: 1; transform: translate(-50%, 0) rotate(2deg); }
  100% { opacity: 0; transform: translate(-50%, -3cqh) scale(1.12); }
}
.intro.opening .intro-title,
.intro.opening .intro-from,
.intro.opening .intro-hint {
  animation: none;
  opacity: 0;
  transform: translate(-50%, -1cqh);
  transition: opacity .7s ease, transform .7s ease;
}

/* ---------- Scene pieces ---------- */
.piece {
  position: absolute;
  z-index: 3;
  transition: transform 2s var(--soft), opacity 1.8s ease, filter 1.6s ease;
}
.piece img {
  display: block;
  width: 100%;
  height: auto;
  pointer-events: none;
  -webkit-user-drag: none;
}
.enter { opacity: 0; }
.float {
  animation: bob var(--bd, 6s) ease-in-out var(--bdl, 0s) infinite;
  will-change: transform;
}
@keyframes bob {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
  50% { transform: translate3d(0, var(--by, -1.2%), 0) rotate(var(--br, .6deg)); }
}

.p-title  { left: -1%; top: 1.5%; width: 102%; z-index: 4; --bd: 5.5s; --by: -2%; --br: -.4deg; }
.p-deco   { left: -1%; top: 10.5%; width: 102%; z-index: 2; --bd: 7s; --by: -1.5%; --br: .3deg; --bdl: -1s; }
.p-left   { left: -2.5%; top: 37.5%; width: 49%; --bd: 6.5s; --by: -1.4%; --br: -.8deg; --bdl: -2s; }
.p-right  { right: -1.5%; top: 38.5%; width: 49%; --bd: 6s; --by: -1.6%; --br: .8deg; --bdl: -3s; }
.p-center { left: 14.5%; top: 42.5%; width: 71%; z-index: 4; --bd: 5s; --by: -2.5%; --br: 0deg; }
.p-bottom { left: 0; bottom: .3%; width: 100%; z-index: 4; --bd: 6s; --by: -3%; --br: .4deg; --bdl: -1.5s; }

.play .p-bottom .enter { animation: inUp 1.6s var(--soft) .25s both; }
.play .p-left   .enter { animation: inLeft 1.8s var(--soft) .9s both; }
.play .p-right  .enter { animation: inRight 1.8s var(--soft) 1.3s both; }
.play .p-deco   .enter { animation: inDrop 1.7s var(--soft) 2s both; }
.play .p-title  .enter { animation: popIn 1.5s var(--soft) 2.8s both; }
.play .p-center .enter { animation: write 2.1s cubic-bezier(.45, .1, .35, 1) 3.9s both; }

@keyframes inUp {
  from { opacity: 0; transform: translateY(60%); }
  45% { opacity: 1; }
  to { opacity: 1; transform: none; }
}
@keyframes inLeft {
  from { opacity: 0; transform: translateX(-100%) rotate(-10deg); }
  45% { opacity: 1; }
  to { opacity: 1; transform: none; }
}
@keyframes inRight {
  from { opacity: 0; transform: translateX(100%) rotate(10deg); }
  45% { opacity: 1; }
  to { opacity: 1; transform: none; }
}
@keyframes inDrop {
  from { opacity: 0; transform: translateY(-70%) scale(.92); }
  45% { opacity: 1; }
  to { opacity: 1; transform: none; }
}
@keyframes popIn {
  0% { opacity: 0; transform: scale(.4) rotate(-5deg); }
  55% { opacity: 1; transform: scale(1.05) rotate(1deg); }
  100% { opacity: 1; transform: none; }
}
@keyframes write {
  from { opacity: 1; clip-path: inset(0 100% 0 0); }
  to { opacity: 1; clip-path: inset(0 0 0 0); }
}

/* Letter time: the center clears away and the frame steps aside */
.opened .p-center {
  opacity: 0;
  transform: translateY(-6%) scale(1.08);
  filter: blur(8px);
}
.opened .p-left  { transform: translateX(-48%) scale(.9) rotate(-4deg); }
.opened .p-right { transform: translateX(48%) scale(.9) rotate(4deg); }
.opened .p-deco  { transform: translateY(-8%) scale(.95); }

/* ---------- Fireworks canvas ---------- */
.fx {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 25;
  pointer-events: none;
}

/* ---------- Letter ---------- */
.letter {
  position: absolute;
  left: 12.5cqw;
  right: 12.5cqw;
  top: 35.5cqh;
  bottom: 16.5cqh;
  z-index: 10;
  border-radius: .4cqw;
  background: var(--grain), var(--mottle), var(--paper);
  box-shadow:
    0 0 0 1px rgba(120, 80, 50, .05),
    0 .2cqw .3cqw rgba(90, 40, 40, .07),
    0 .8cqw 1.4cqw rgba(90, 40, 40, .06),
    0 2cqw 3.5cqw rgba(110, 45, 55, .08),
    0 4.5cqw 8cqw rgba(120, 50, 60, .1);
  opacity: 0;
  transform: translateY(2cqh);
  pointer-events: none;
  transition: opacity 1.8s ease, transform 1.8s var(--soft);
}
.letter.show {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* 垫在下面、微微斜出的第二张信纸 */
.letter-back {
  position: absolute;
  left: 12.5cqw;
  right: 12.5cqw;
  top: 35.5cqh;
  bottom: 16.5cqh;
  z-index: 9;
  border-radius: .4cqw;
  background:
    linear-gradient(155deg, rgba(255, 255, 255, .25), transparent 40%, rgba(110, 75, 45, .08)),
    var(--grain), var(--mottle), #f5ead8;
  box-shadow:
    0 0 0 1px rgba(120, 80, 50, .06),
    0 .4cqw .8cqw rgba(90, 40, 40, .07),
    0 2.5cqw 5cqw rgba(120, 50, 60, .1);
  opacity: 0;
  transform: translateY(2cqh);
  pointer-events: none;
  transition: opacity 1.8s ease, transform 1.6s var(--soft) .6s;
}
.letter.show ~ .letter-back {
  opacity: 1;
  transform: translate(1.5cqw, .5cqh) rotate(3.2deg);
}

.letter::before {
  content: '';
  position: absolute;
  inset: 2cqw;
  border: 1px solid var(--frame);
  border-radius: .6cqw;
  outline: 1px solid rgba(214, 58, 58, .22);
  outline-offset: -.9cqw;
  pointer-events: none;
}

.letter::after {
  --c: rgba(214, 58, 58, .6);
  --l: 2.8cqw;
  content: '';
  position: absolute;
  inset: 3.7cqw;
  pointer-events: none;
  background:
    linear-gradient(var(--c), var(--c)) left top / var(--l) 1px,
    linear-gradient(var(--c), var(--c)) left top / 1px var(--l),
    linear-gradient(var(--c), var(--c)) right top / var(--l) 1px,
    linear-gradient(var(--c), var(--c)) right top / 1px var(--l),
    linear-gradient(var(--c), var(--c)) left bottom / var(--l) 1px,
    linear-gradient(var(--c), var(--c)) left bottom / 1px var(--l),
    linear-gradient(var(--c), var(--c)) right bottom / var(--l) 1px,
    linear-gradient(var(--c), var(--c)) right bottom / 1px var(--l);
  background-repeat: no-repeat;
}

/* 光照与边缘压暗 */
.letter-fold {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  pointer-events: none;
  background:
    linear-gradient(155deg, rgba(255, 255, 255, .35) 0%, transparent 35%, transparent 70%, rgba(110, 75, 45, .07) 100%),
    radial-gradient(130% 110% at 50% 45%, transparent 62%, rgba(110, 75, 45, .08) 100%);
}

.letter-scroll {
  position: relative;
  z-index: 1;
  height: 100%;
  overflow: hidden;
  padding: 6cqw 6cqw 5.5cqw;
  font-size: 3.3cqw;
  line-height: 1.8;
  letter-spacing: .01em;
  color: #3a2e29;
  text-shadow: 0 0 .5px rgba(58, 46, 41, .45);
  -webkit-user-select: text;
  user-select: text;
}

.letter-scroll .ch { opacity: 0; }
.letter-scroll .ch.on { animation: chIn .35s ease-out forwards; }
@keyframes chIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
.caret {
  display: inline-block;
  width: 1px;
  height: 1.05em;
  margin-right: -1px;
  vertical-align: -.16em;
  background: var(--red);
  animation: blink 1s steps(2) infinite;
}
@keyframes blink { 50% { opacity: 0; } }

.letter-scroll .greet {
  margin-bottom: .3em;
  font-size: 1.1em;
  font-weight: 600;
  letter-spacing: .06em;
}
.letter-scroll .para {
  margin-bottom: .3em;
  text-indent: 2em;
  text-align: justify;
}
.letter-scroll .sign { text-align: right; }
.letter-scroll .date {
  margin-top: .8em;
  text-align: right;
  font-size: .88em;
  color: rgba(75, 58, 52, .5);
}

.make-tab {
  position: absolute;
  right: 0;
  top: 58.5%;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 7cqw;
  height: 21cqw;
  border-radius: 1.6cqw 0 0 1.6cqw;
  background: #7cb5ec;
  box-shadow: 0 .4cqw 1.2cqw rgba(60, 110, 170, .18);
  color: #fff;
  font-size: 3.3cqw;
  font-weight: 500;
  line-height: 1;
  letter-spacing: .5cqw;
  writing-mode: vertical-rl;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.make-tab:active { background: #6aa6e0; }

@media (prefers-reduced-motion: reduce) {
  .float, .sparkle, .mail img { animation: none !important; }
}
