/* The sealed envelope the card opens on, as in the couple's chosen style ("Hoa vẽ tay", tokens.css): olive
   paper on a plain stage of dawn mist, the couple's names in a cream hand, a seal of wine-red wax stamped
   with a heart whose ring fills while the island loads; inside, a liner painted with a lake and two swans.
   Opening breaks the seal, lifts the flap (it swings behind the card), the card rises and the whole envelope
   gives way to the scene. */
body[data-mode='ticket'] { overflow: hidden; }
body[data-mode='ticket'] .sheet { z-index: 45; }
.envelope-screen {
  position: fixed; inset: 0; z-index: 40; display: grid; place-items: center; overflow: hidden;
  padding: calc(1rem + var(--safe-top)) 1rem calc(1rem + var(--safe-bottom));
  /* Nothing drawn on it: dawn mist turning to warm sand, the grain of paper, a soft light behind the envelope
     and the edges a shade darker, so the eye goes to the seal. */
  background:
    radial-gradient(58% 42% at 50% 47%, rgba(255, 250, 236, 0.6), transparent 72%),
    radial-gradient(150% 110% at 50% 48%, transparent 58%, rgba(var(--shadow-rgb), 0.2) 100%),
    var(--paper-grain),
    linear-gradient(180deg, var(--backdrop-top) 0%, var(--backdrop-mid) 52%, var(--backdrop-bottom) 100%);
  --liner: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 220' preserveAspectRatio='xMidYMid slice'%3E %3Cdefs%3E%3ClinearGradient id='s' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23eef0e4'/%3E%3Cstop offset='.5' stop-color='%23d6dccf'/%3E%3Cstop offset='1' stop-color='%23c1cbc0'/%3E%3C/linearGradient%3E %3Cfilter id='b'%3E%3CfeGaussianBlur stdDeviation='2.2'/%3E%3C/filter%3E%3C/defs%3E %3Cg transform='translate(0 220) scale(1 -1)'%3E %3Crect width='400' height='220' fill='url(%23s)'/%3E %3Cg filter='url(%23b)'%3E%3Cpath d='M0 92Q40 68 82 84Q122 60 168 80Q214 64 258 82Q300 66 342 78Q372 70 400 74V122H0Z' fill='%23a8b2a0' opacity='.75'/%3E %3Cpath d='M250 122Q280 92 318 100Q352 84 400 92V122Z' fill='%2397a390' opacity='.8'/%3E%3C/g%3E %3Crect y='120' width='400' height='100' fill='%23cdd5cf'/%3E %3Cg stroke='%23e9eee8' stroke-width='1.2' opacity='.8'%3E%3Cpath d='M20 168H130M150 182H300M40 200H170M230 208H380M260 160H360'/%3E%3C/g%3E %3Cg filter='url(%23b)'%3E%3Cpath d='M28 220Q30 140 52 86Q60 54 44 20' stroke='%235b4a2e' stroke-width='6' fill='none'/%3E %3Cellipse cx='60' cy='40' rx='58' ry='30' fill='%236f6a3e' opacity='.9'/%3E%3Cellipse cx='94' cy='76' rx='46' ry='22' fill='%23857c48' opacity='.85'/%3E %3Cellipse cx='30' cy='98' rx='40' ry='20' fill='%237a7445' opacity='.8'/%3E%3Cpath d='M0 220V160Q30 152 60 166Q86 154 110 174V220Z' fill='%237d7b4d' opacity='.85'/%3E%3C/g%3E %3Cg fill='%23ffffff' stroke='%23b9beb4' stroke-width='.9'%3E%3Cpath d='M172 146q-18 0-20 -8q10 3 22 -2q-3-17 5-25q6-4 8 4q-8 5-5 22q5 5 2 9z'/%3E%3Cpath d='M228 146q18 0 20 -8q-10 3 -22 -2q3-17 -5-25q-6-4 -8 4q8 5 5 22q-5 5 -2 9z'/%3E%3C/g%3E %3Cg fill='%23f4c3a0'%3E%3Ccircle cx='186' cy='113' r='1.6'/%3E%3Ccircle cx='214' cy='113' r='1.6'/%3E%3C/g%3E %3Cg stroke='%23e8ece6' stroke-width='1.1' opacity='.9'%3E%3Cpath d='M150 152H192M208 152H252'/%3E%3C/g%3E %3C/g%3E%3C/svg%3E");
  --icon-heart: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 20.5C6.4 16.4 3 13.2 3 9.3 3 6.6 5.1 4.5 7.7 4.5c1.8 0 3.3 1 4.3 2.4 1-1.4 2.5-2.4 4.3-2.4 2.6 0 4.7 2.1 4.7 4.8 0 3.9-3.4 7.1-9 11.2z'/%3E%3C/svg%3E");
  transition: opacity 0.7s ease;
}
.envelope-stage { display: grid; justify-items: center; gap: 1.1rem; width: min(100%, 28rem); }
.envelope-kicker { margin: 0; font: 500 var(--fs-note) var(--font-ui); letter-spacing: 0.3em; text-align: center; color: var(--ink); }

.envelope {
  container-type: inline-size;
  position: relative; display: block; width: min(88vw, 26rem); aspect-ratio: 6 / 5; padding: 0; border: 0; background: none;
  cursor: pointer; perspective: 900px; filter: drop-shadow(0 22px 32px rgba(var(--shadow-rgb), 0.26));
  animation: envelope-in 0.9s cubic-bezier(0.2, 0.8, 0.2, 1) both; transition: transform 0.8s cubic-bezier(0.5, 0, 0.75, 0);
}
.envelope:disabled { opacity: 1; cursor: default; }
.envelope:focus-visible { outline: 3px solid var(--rule); outline-offset: 8px; border-radius: 10px; }
.envelope-back, .envelope-card, .envelope-pocket, .envelope-flap, .envelope-address, .envelope-seal { position: absolute; }
@keyframes envelope-in { from { opacity: 0; transform: translateY(18px) scale(0.97); } }

/* The inside of the envelope, seen once the flap is up: the painted lake and its swans. */
.envelope-back { inset: 0; z-index: 0; border-radius: 10px; background: var(--liner) center / cover no-repeat, var(--flap-deep); }
/* The card inside, a heart on it in the wax's colour; it rises out when the envelope opens. */
.envelope-card {
  left: 7%; right: 7%; top: 7%; bottom: 5%; z-index: 1; display: grid; justify-items: center; align-content: start; padding-top: 7%;
  border-radius: 6px; background: var(--paper) var(--paper-grain); box-shadow: 0 0 0 1px rgba(var(--rule-rgb), 0.55) inset;
  transition: transform 0.9s 0.55s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.envelope-card-mark {
  display: block; width: 1.9rem; height: 1.9rem; background: var(--seal);
  -webkit-mask: var(--icon-heart) center / contain no-repeat; mask: var(--icon-heart) center / contain no-repeat;
}
/* The pocket: the envelope's front, notched where the flap closes over it. */
.envelope-pocket {
  inset: 0; z-index: 2; border-radius: 10px; background: var(--envelope) var(--paper-grain);
  clip-path: polygon(0 0, 50% 40%, 100% 0, 100% 100%, 0 100%);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
}
.envelope-flap {
  left: 0; right: 0; top: 0; height: 40%; transform-origin: 50% 0; z-index: 4;
  background: linear-gradient(175deg, var(--flap), var(--flap-deep)); clip-path: polygon(0 0, 100% 0, 50% 100%); border-radius: 10px 10px 0 0;
}
.envelope-address {
  left: 6%; right: 6%; top: 54%; bottom: 5%; z-index: 3; display: grid; align-content: center; justify-items: center; gap: 0.2rem;
  text-align: center;
}
/* Whose wedding: the couple signed on one line under the seal, "&" between them, sized to the envelope. */
.envelope-names {
  display: flex; align-items: baseline; justify-content: center; gap: 0.28em; font-family: var(--font-script); font-weight: 600;
  font-size: 8.4cqi; line-height: 1.15; color: var(--on-envelope); white-space: nowrap;
}
.envelope-join { font-size: 0.8em; opacity: 0.85; }
/* Who it is for, as a printed card is addressed: the spaced capitals, then the guest in the hand on a dotted
   line, as if written in. */
.envelope-invite {
  margin-top: 0.55rem; font: 500 var(--fs-caps) var(--font-ui); letter-spacing: var(--caps-track); text-transform: uppercase;
  color: var(--on-envelope); opacity: 0.85;
}
.envelope-to {
  display: block; width: 74%; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding: 0 0.3em 0.05em; border-bottom: 2px dotted rgba(255, 246, 216, 0.75);
  font-family: var(--font-script); font-weight: 600; font-size: 6.4cqi; line-height: 1.3; color: var(--on-envelope);
}

/* The wax seal at the flap's point (dấu ấn thư sáp), ringed by the loading progress: a pool of wine-red wax
   whose edge spreads unevenly (offset copies of its own shape), a pressed ring, a heart stamped in the middle. */
.envelope-seal {
  --seal-edge: 4px -3px 0 1px var(--seal), -5px 2px 0 1px var(--seal), 3px 4px 0 2px var(--seal), -2px -5px 0 0 var(--seal-light),
    1px 5px 0 0 var(--seal), -4px -2px 0 1px var(--seal);
  --seal-drop: 0 4px 9px rgba(var(--shadow-rgb), 0.45), inset 0 -3px 6px rgba(var(--shadow-rgb), 0.4), inset 0 2px 3px rgba(var(--paper-rgb), 0.25);
  left: 50%; top: 40%; z-index: 5; width: 3.8rem; height: 3.8rem; transform: translate(-50%, -50%) rotate(-8deg);
  /* A layer of its own: the count repainting every frame redraws the seal alone, not the whole envelope. */
  will-change: transform;
  display: grid; place-items: center; border-radius: 48% 52% 45% 55% / 54% 46% 55% 45%;
  background: radial-gradient(circle at 33% 27%, var(--seal-light), var(--seal) 64%); box-shadow: var(--seal-edge), var(--seal-drop);
}
.envelope-seal::after {
  content: ''; position: absolute; inset: 0.4rem; border-radius: 50%;
  box-shadow: inset 0 1px 2px rgba(var(--shadow-rgb), 0.55), inset 0 0 0 1.5px rgba(var(--shadow-rgb), 0.25), 0 1px 0 rgba(var(--paper-rgb), 0.22);
}
.envelope-seal-mark {
  display: block; width: 1.55rem; height: 1.55rem; background: var(--seal-mark); filter: drop-shadow(0 1px 0 rgba(var(--shadow-rgb), 0.6));
  -webkit-mask: var(--icon-heart) center / contain no-repeat; mask: var(--icon-heart) center / contain no-repeat;
}
.seal-ring { position: absolute; inset: -12px; display: block; }
.seal-ring svg { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); overflow: visible; }
.seal-ring circle { fill: none; stroke-width: 2.6; }
.seal-ring-track { stroke: rgba(var(--paper-rgb), 0.3); }
.seal-ring-fill {
  stroke: var(--accent); stroke-linecap: round; stroke-dasharray: 100; stroke-dashoffset: 100;
}
/* While loading, a glint runs round the ring, so the seal looks busy even while the percentage holds; the whole svg
   turns (not a shape inside it), so it runs on the compositor and never stalls while the island is built. */
.seal-ring-spin { will-change: transform; animation: seal-spin 1.3s linear infinite; transition: opacity 0.4s ease; }
.seal-ring-spin circle { stroke: rgba(255, 246, 216, 0.9); stroke-linecap: round; stroke-dasharray: 7 93; }
@keyframes seal-spin { to { transform: rotate(270deg); } }
/* How far the island has loaded, pressed into the wax; the heart is stamped in its place once it is ready. */
.envelope-seal-load {
  position: absolute; inset: 0; display: grid; place-items: center; z-index: 1;
  font: 600 0.95rem/1 var(--font-ui); font-variant-numeric: tabular-nums; color: var(--seal-mark);
  text-shadow: 0 1px 0 rgba(var(--shadow-rgb), 0.6); transition: opacity 0.35s ease, transform 0.35s ease;
}
.envelope-seal-mark { transition: opacity 0.3s 0.15s ease; }
.envelope-screen:not(.is-ready) .envelope-seal-mark { opacity: 0; }
.envelope-screen.is-ready .envelope-seal-load { opacity: 0; transform: scale(0.7); }
.envelope-screen.is-ready .seal-ring-spin { opacity: 0; animation: none; }
.envelope-screen.is-ready .envelope-seal-mark { animation: seal-stamp 0.5s 0.15s cubic-bezier(0.3, 1.6, 0.5, 1) both; }
@keyframes seal-stamp { from { opacity: 0; transform: scale(1.6); } }
.envelope-screen.is-ready .envelope-seal { animation: seal-ready 1.8s ease-in-out infinite; }
@keyframes seal-ready { 50% { box-shadow: var(--seal-edge), var(--seal-drop), 0 0 0 10px rgba(var(--rule-rgb), 0.28); } }

.envelope-cta { margin: 0; font: 500 var(--fs-body) var(--font-ui); letter-spacing: 0.02em; color: var(--ink); opacity: 0.75; transition: opacity 0.3s ease; }
.envelope-cta::after { content: ' ›'; }
.envelope-screen.is-ready .envelope-cta { opacity: 1; animation: cta-ready 1.8s ease-in-out infinite; }
@keyframes cta-ready { 50% { opacity: 0.6; } }
.envelope-status { min-height: 1.3em; margin: -0.4rem 0 0; font-size: var(--fs-note); text-align: center; color: var(--ink-soft); text-wrap: balance; }

/* Opening: the seal breaks, the flap swings up and behind, the card rises out of the pocket. */
.envelope-screen.is-open .envelope-seal { animation: seal-break 0.5s ease-in both; }
.envelope-screen.is-open .envelope-flap { animation: flap-open 0.75s 0.2s cubic-bezier(0.4, 0, 0.2, 1) both; }
.envelope-screen.is-open .envelope-card { transform: translateY(-42%); }
.envelope-screen.is-open .envelope-cta { opacity: 0; animation: none; }
@keyframes seal-break {
  30% { transform: translate(-50%, -50%) rotate(-8deg) scale(1.12); }
  100% { opacity: 0; transform: translate(-50%, 10%) scale(0.6) rotate(-32deg); }
}
@keyframes flap-open {
  0% { transform: rotateX(0); z-index: 4; }
  49% { z-index: 4; }
  50% { z-index: 0; filter: brightness(0.85); }
  100% { transform: rotateX(180deg); z-index: 0; filter: brightness(0.9); }
}
.envelope-screen.is-leaving { opacity: 0; pointer-events: none; }
.envelope-screen.is-leaving .envelope { transform: translateY(6%) scale(1.06); }

@media (min-width: 700px) {
  .envelope { width: 28rem; aspect-ratio: 7 / 5; }
}
@media (prefers-reduced-motion: reduce) {
  .envelope, .envelope-seal, .envelope-cta, .envelope-flap, .seal-ring-spin, .envelope-seal-mark { animation: none !important; }
  .envelope-card, .envelope { transition: none; }
}
