/* ============================================================
   Por & Prem Wedding — Envelope Cover (luxury stationery v0.20.5)
   ============================================================
   v0.20.5 — CRISIS ROUND 3: User: "อนิเมชั่นหายไปหมดเลยการ์ดก็ซ้อน
   หน้าเปิดอยู่ไม่เห็นหน้า". Root causes audited round 3:
     1. Wax crack + flap rotate + card emerge ALL compressed into
        first 1.2s — user saw them simultaneously, perceived as
        "card just appeared on top, no animation"
     2. card-out keyframe jumped to opacity:1 at 18% (~126ms in)
        while flap was barely 17% rotated → card visible BEFORE
        envelope was actually open
     3. Hold beat was 5.3s but front-loaded confusion meant user
        only registered "card sitting there with no opening shown"
   v0.20.5 FIXES — distinct visible phases, each phase fully completes
   before next starts:
     t=0       button dims + spinner
     t=200ms   WAX CRACK starts (800ms cubic-bezier crack-and-fly)
              — user clearly sees L+R seal halves split apart
     t=1000ms  WAX done. FLAP rotates open (1000ms slow elegant pivot)
              — user clearly watches flap arc backward
     t=2000ms  FLAP done. CARD slides up out of envelope (1000ms)
              — user clearly sees card emerge from inside
     t=3000ms  CARD fully visible — HOLD BEGINS (3000ms savour beat)
     t=3000ms  Particles fade to 0.12 so card dominates
     t=3500ms  Petal burst (1500ms decorative trail)
     t=6000ms  Scene gently fades cream→cream (1000ms)
     t=7000ms  Redirect (JS setTimeout, OPEN_DURATION = 7000)
   Total: 7s (up from 7.5s for total, but each phase now has its
   own breathing room — 4s of distinct animation vs old 1.2s).
   v0.20.3 — USER STILL UNHAPPY: "หน้าเปล่าเห็นดอกไม้นานเกิน /
   เห็นการ์ดแว้บเดียว". Root causes audited:
     1. Inside-card text was tiny (P&P 26px, Thai 11px on 320×240
        SVG) — user could not register it as a "card"
     2. Particles never paused during hold — kept moving, dominated
        attention away from card
     3. Hold beat was only 3.8s but card text was so faint it felt
        like flash
   v0.20.3 FIXES (all 5):
     1. MASSIVE inside-card text (P&P 64-70px, Thai 18-20px, Date 16-17px
        + drop-shadow strokes for legibility) — see template-parts/envelope-cover.php
     2. Card-out keyframe sets explicit final state with forwards
        + locked at end position (no drift)
     3. Particles FADE + PAUSE during hold (rose/leaf/sparkle/swirl
        all freeze + drop to opacity 0.12 — card dominates)
     4. Hold beat extended to 5.0s (was 3.8s); total 7.5s (was 6.8s)
     5. Card emerges FAST (t=500ms vs old 1100ms) — user sees card
        almost immediately after click, no "flowers without content"
   New timing table:
     t=0      button dims
     t=100    wax crack starts (400ms)
     t=400    flap rotates (600ms — faster)
     t=500    inside-card preview reveals (500ms)
     t=500    card-out emerges (700ms)
     t=1200   card fully visible — HOLD begins
     t=1200   particles fade to 0.12 + pause
     t=1500   petal burst (1500ms, JS-injected)
     t=1200—6500  HOLD (5300ms savour beat)
     t=6500   scene gently fades (1000ms cream→cream)
     t=7500   redirect (JS setTimeout)
   ============================================================ */

/* ---------- Body modifier — hide site chrome on this surface ---------- */
body.pp-envelope-active .porprem-site-header,
body.pp-envelope-active .porprem-site-footer,
body.pp-envelope-active .porprem-skip-link {
	display: none !important;
}

body.pp-envelope-active {
	/* v0.30.1 — only lock horizontal scroll. Vertical scroll is allowed so
	   that on shorter desktop viewports the "เปิดการ์ด" button is still
	   reachable. Original `overflow: hidden` was clipping the CTA off-screen
	   on laptop heights (≤ 768px) — user report "UI ฝั่งคอม ไม่มีปุ่ม". */
	overflow-x: hidden;
	overflow-y: auto;
	background: #FFFFF8;
}

/* Pin html/body cream throughout opening — prevents any
   white peek during the redirect transition. */
html,
body.pp-envelope-active {
	background-color: #FFFFF8;
}

/* ============================================================
   1. PAGE CONTAINER + SILK FABRIC BACKGROUND
   ============================================================ */
.pp-envelope {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: flex-start;
	min-height: 100vh;          /* fallback */
	min-height: 100dvh;          /* iOS LINE URL bar safe */
	width: 100%;
	margin: 0;
	padding: clamp(20px, 4vh, 60px) 16px clamp(40px, 8vh, 80px);
	background: #FFFFF8;
	overflow: hidden;
	font-family: var(--font-body-th, var(--font-body));
	color: var(--color-ink, #1F2937);
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	isolation: isolate;
}

/* Silk fabric drape — layered gradient simulating folds */
.pp-envelope__silk {
	position: absolute;
	inset: 0;
	z-index: 0;
	background:
		/* Top gold halo */
		radial-gradient(ellipse 60% 35% at 50% 0%, rgba(252, 178, 169, 0.28) 0%, transparent 60%),
		/* Bottom blush halo */
		radial-gradient(ellipse 80% 40% at 50% 100%, rgba(244, 194, 194, 0.22) 0%, transparent 65%),
		/* Left fold shadow */
		radial-gradient(ellipse 25% 80% at 0% 50%, rgba(93, 103, 112, 0.12) 0%, transparent 55%),
		/* Right fold highlight */
		radial-gradient(ellipse 25% 80% at 100% 50%, rgba(253, 233, 229, 0.6) 0%, transparent 55%),
		/* Center silk sheen — diagonal */
		linear-gradient(125deg,
			#FFFFF8 0%,
			#FBF5EF 22%,
			#F4ECE0 45%,
			#FFFFF8 70%,
			#F4ECE0 100%
		);
	pointer-events: none;
	animation: pp-env-silk-fade 1000ms ease-out both;
}

/* Subtle conic fabric folds overlay */
.pp-envelope__silk::before {
	content: "";
	position: absolute;
	inset: -10%;
	background:
		conic-gradient(from 140deg at 50% 50%,
			transparent 0deg,
			rgba(252, 178, 169, 0.04) 30deg,
			transparent 60deg,
			rgba(253, 233, 229, 0.08) 120deg,
			transparent 180deg,
			rgba(252, 178, 169, 0.03) 240deg,
			transparent 320deg
		);
	mix-blend-mode: overlay;
	opacity: 0.85;
}

/* ============================================================
   2. GOLD SPARKLE SWIRLS (large decorative)
   ============================================================ */
.pp-envelope__swirls {
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	overflow: hidden;
}

.pp-envelope__swirl {
	position: absolute;
	width: 110px;
	height: 110px;
	opacity: 0;
	animation: pp-env-swirl-in 1800ms cubic-bezier(0.4, 0, 0.2, 1) 700ms forwards,
	           pp-env-swirl-spin 42s linear infinite;
	will-change: transform, opacity;
}

.pp-envelope__swirl--tr {
	top: clamp(40px, 8vh, 80px);
	right: clamp(-20px, -4vw, 12px);
	width: clamp(120px, 24vw, 170px);
	height: clamp(120px, 24vw, 170px);
	animation-delay: 700ms, 0s;
}

.pp-envelope__swirl--bl {
	bottom: clamp(40px, 7vh, 90px);
	left: clamp(-30px, -5vw, 8px);
	width: clamp(110px, 22vw, 160px);
	height: clamp(110px, 22vw, 160px);
	animation-delay: 900ms, -12s;
	animation-direction: normal, reverse;
}

.pp-envelope__swirl--mid {
	top: 45%;
	left: 6%;
	width: clamp(80px, 16vw, 110px);
	height: clamp(80px, 16vw, 110px);
	opacity: 0;
	animation: pp-env-swirl-in 2000ms ease 1100ms forwards,
	           pp-env-swirl-spin 46s linear 0s infinite;
}

/* ============================================================
   3. FLOATING PARTICLES — rose petals + gold leaves + sparkle dust
   ============================================================ */
.pp-envelope__particles {
	position: absolute;
	inset: 0;
	z-index: 2;
	pointer-events: none;
	overflow: hidden;
}

/* Pink rose petals — soft drift with rotation */
.pp-envelope__rose {
	position: absolute;
	left: var(--x, 50%);
	bottom: -40px;
	width: calc(22px * var(--s, 1));
	height: calc(22px * var(--s, 1));
	background:
		radial-gradient(ellipse 60% 80% at 50% 30%, #FBE5E5 0%, #F4C2C2 45%, #E8A4A4 100%);
	border-radius: 80% 20% 60% 40% / 50% 30% 70% 50%;
	box-shadow:
		inset -1px -2px 4px rgba(160, 64, 64, 0.25),
		inset 1px 2px 4px rgba(255, 245, 245, 0.6);
	opacity: 0;
	transform-origin: 50% 100%;
	animation: pp-env-rose-drift var(--r, 18s) linear var(--d, 0s) infinite;
	will-change: transform, opacity;
}

/* Gold leaf petals — narrower + flip */
.pp-envelope__leaf {
	position: absolute;
	left: var(--x, 50%);
	bottom: -40px;
	width: calc(18px * var(--s, 1));
	height: calc(22px * var(--s, 1));
	background:
		linear-gradient(135deg, #FDE9E5 0%, #FCB2A9 50%, #5D6770 100%);
	border-radius: 100% 0 100% 0;
	box-shadow:
		inset -1px -1px 2px rgba(45, 55, 72, 0.4),
		inset 1px 1px 2px rgba(253, 233, 229, 0.5);
	opacity: 0;
	transform-origin: 50% 50%;
	animation: pp-env-leaf-drift var(--r, 16s) linear var(--d, 0s) infinite;
	will-change: transform, opacity;
}

/* Sparkle dust — twinkling small dots */
.pp-envelope__sparkle {
	position: absolute;
	left: var(--x, 50%);
	top: var(--y, 50%);
	width: calc(3px * var(--s, 1));
	height: calc(3px * var(--s, 1));
	background: #FCB2A9;
	border-radius: 50%;
	box-shadow:
		0 0 6px rgba(252, 178, 169, 0.85),
		0 0 12px rgba(252, 178, 169, 0.5);
	opacity: 0;
	animation: pp-env-twinkle calc(4s + (var(--s, 1) * 2s)) ease-in-out var(--d, 0s) infinite;
	will-change: opacity, transform;
}

/* ============================================================
   4. INNER STACK — mockup proportions (zone-based vertical rhythm)
   ============================================================ */
.pp-envelope__inner {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0;  /* gaps controlled by individual margins for mockup precision */
	width: 100%;
	max-width: 560px;
	z-index: 5;
	margin: 0 auto;
}

/* ============================================================
   5. DECORATIVE FILIGREE LINE (above logo) — wider scrollwork
   ============================================================ */
.pp-envelope__filigree {
	width: clamp(220px, 60vw, 320px);
	margin-bottom: clamp(8px, 1.5vh, 16px);
	opacity: 0;
	animation: pp-env-fade-in 800ms ease 500ms forwards;
}

.pp-envelope__filigree-svg {
	display: block;
	width: 100%;
	height: auto;
	overflow: visible;
}

.pp-envelope__filigree-path {
	stroke-dasharray: 380;
	stroke-dashoffset: 380;
	animation: pp-env-filigree-draw 1500ms cubic-bezier(0.4, 0, 0.2, 1) 600ms forwards;
}

.pp-envelope__filigree-path:nth-of-type(2) { animation-delay: 750ms; }
.pp-envelope__filigree-path:nth-of-type(3) { animation-delay: 900ms; }
.pp-envelope__filigree-path:nth-of-type(4) { animation-delay: 1050ms; }
.pp-envelope__filigree-path:nth-of-type(5) { animation-delay: 1200ms; }
.pp-envelope__filigree-path:nth-of-type(6) { animation-delay: 1350ms; }
.pp-envelope__filigree-path:nth-of-type(7) { animation-delay: 1500ms; }

.pp-envelope__filigree-dot {
	opacity: 0;
	animation: pp-env-fade-in 500ms ease 1900ms forwards;
}

/* ============================================================
   6. BRAND (logo + wordmark) — LOGO DOMINANT (140-160px target)
   ============================================================ */
.pp-envelope__brand {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 10px;
	margin-bottom: clamp(20px, 4vh, 48px);
	opacity: 0;
	animation: pp-env-fade-up 800ms cubic-bezier(0.4, 0, 0.2, 1) 1000ms forwards;
}

.pp-envelope__logo {
	width: clamp(120px, 36vw, 180px);
	height: clamp(120px, 36vw, 180px);
	object-fit: contain;
	filter: drop-shadow(0 6px 18px rgba(252, 178, 169, 0.35));
}

.pp-envelope__logo--fallback {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-family: var(--font-script, 'Pinyon Script', cursive);
	font-size: clamp(72px, 22vw, 108px);
	color: var(--color-gold-text, #5D6770);
	line-height: 1;
}

.pp-envelope__wordmark {
	font-family: var(--font-heading, 'Cormorant Garamond', serif);
	font-size: clamp(12px, 2.8vw, 15px);
	font-weight: 500;
	letter-spacing: 0.34em;
	color: var(--color-gold-text, #5D6770);
	text-transform: uppercase;
	opacity: 0.9;
	margin-top: 4px;
	/* Wordmark "POR & PREM" with 0.34em letter-spacing can wrap awkwardly on
	   narrow viewports (the ampersand sometimes drops alone). nowrap keeps it
	   on one line — it's short enough to fit even on 320px. */
	white-space: nowrap;
}

/* ============================================================
   7. INVITE TEXT (headline + recipient + subline)
   ============================================================ */
.pp-envelope__invite {
	width: 100%;
	max-width: 420px;
	text-align: center;
	margin: 0 0 clamp(20px, 3.5vh, 36px);
	padding: 0 8px;
	opacity: 0;
	animation: pp-env-fade-up 800ms cubic-bezier(0.4, 0, 0.2, 1) 1500ms forwards;
}

.pp-envelope__headline {
	font-family: var(--font-heading-th, 'Noto Serif Thai', serif);
	font-style: italic;
	color: var(--color-gold-text, #5D6770);
	margin: 0;
	line-height: 1.5;
	letter-spacing: 0.01em;
	/* Balance heading lines so the long Thai headline
	   "ข้าพเจ้าขอเรียนเชิญร่วมงานมงคลสมรส" wraps evenly instead of leaving
	   1-2 dangling words on the last line. */
	text-wrap: balance;
}

.pp-envelope__headline--direct {
	font-size: clamp(17px, 4.2vw, 22px);
	font-weight: 400;
	color: #2D3748;
	padding: 4px 0;
	max-width: 90%;
	margin-left: auto;
	margin-right: auto;
}

.pp-envelope__headline--small {
	font-size: clamp(13px, 3.2vw, 15px);
	font-weight: 400;
	opacity: 0.85;
	margin-bottom: 6px;
}

.pp-envelope__recipient {
	font-family: var(--font-heading-th, 'Noto Serif Thai', serif);
	font-style: italic;
	font-weight: 500;
	color: var(--color-gold-deep, #2D3748);
	margin: 0;
	line-height: 1.25;
	letter-spacing: 0.005em;
	opacity: 0;
	animation: pp-env-fade-up 800ms cubic-bezier(0.4, 0, 0.2, 1) 1900ms forwards;
	/* Recipient name displayed prominently — balance any 2-line wrap and prevent
	   awkward break of Thai prefix "คุณ" + name onto separate lines. */
	text-wrap: balance;
	overflow-wrap: break-word;
}

.pp-envelope__recipient--personal,
.pp-envelope__recipient--group {
	font-size: clamp(22px, 6vw, 32px);
	padding: 2px 0;
	text-shadow: 0 1px 2px rgba(253, 233, 229, 0.6);
}

.pp-envelope__subline {
	font-family: var(--font-heading-th, 'Noto Serif Thai', serif);
	font-style: italic;
	font-size: clamp(13px, 3vw, 15px);
	color: var(--color-gold-text, #5D6770);
	margin: 6px 0 0;
	opacity: 0.85;
	font-weight: 400;
	text-wrap: pretty;
}

/* ============================================================
   8. ENVELOPE SVG (cream paper) — THE HERO
   ============================================================ */
.pp-envelope__art {
	position: relative;
	width: clamp(280px, 82vw, 520px);
	aspect-ratio: 7 / 5;
	max-height: 38vh;
	margin: 0 auto clamp(32px, 5vh, 56px);
	opacity: 0;
	transform: translateY(28px) scale(0.92);
	animation: pp-env-envelope-rise 1300ms cubic-bezier(0.34, 1.56, 0.64, 1) 2300ms forwards;
}

.pp-envelope__svg {
	display: block;
	width: 100%;
	height: 100%;
	overflow: visible;
	filter:
		drop-shadow(0 12px 32px rgba(45, 55, 72, 0.18))
		drop-shadow(0 4px 12px rgba(45, 55, 72, 0.12));
	transition: transform 400ms cubic-bezier(0.4, 0, 0.2, 1);
}

.pp-envelope__art:hover .pp-envelope__svg {
	transform: translateY(-4px);
}

/* Flap: opens like real envelope from top edge */
.pp-envelope__flap-wrap {
	transform-origin: 210px 92px;
	transform-box: view-box;
	transition: transform 1000ms cubic-bezier(0.6, 0.05, 0.3, 1.1);
	will-change: transform;
}

.pp-envelope__flap {
	transform-origin: 50% 92px;
}

/* Wax seal — split into left/right halves for crack animation */
.pp-envelope__seal {
	transform-origin: 210px 158px;
	transform-box: view-box;
	opacity: 0;
	transform: scale(0.4) translateY(-30px);
	animation: pp-env-seal-stamp 800ms cubic-bezier(0.34, 1.56, 0.64, 1) 3000ms forwards;
	will-change: transform, opacity;
}

.pp-envelope__seal-wax {
	transform-origin: 210px 158px;
	transform-box: view-box;
	transition: transform 700ms cubic-bezier(0.5, 0, 0.3, 1.2), opacity 700ms ease;
}

/* v0.20.9: .pp-envelope__card-peek removed (no longer in template) — was
   duplicating card-out's content, causing visible card-stacking flash. */

/* Card-out: emerges from envelope on .is-opening. Hidden by default —
   v0.20.4 removed inline opacity="0" SVG attr (conflicted with CSS); now
   CSS owns the opacity entirely so keyframe animations work reliably. */
.pp-envelope__card-out {
	opacity: 0;
	transform-origin: 210px 240px;
	transform-box: view-box;
	transition: transform 900ms cubic-bezier(0.34, 1.56, 0.64, 1), opacity 700ms ease;
}

/* ============================================================
   9. CTA BAR (beveled gold metallic) — prominent + wider
   ============================================================ */
.pp-envelope__cta {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: clamp(10px, 2vh, 16px);
	width: 100%;
	max-width: 520px;
	margin: 0 auto;
	/* v0.30.1 — Removed `opacity:0 + 3700ms fade-in delay`. On desktop the
	   3.7s wait meant the button was invisible for nearly 4 seconds on
	   every page-load — user report "UI ฝั่งคอม ไม่มีปุ่มให้เปิดการ์ด".
	   Short 280ms entrance preserves the polish without making it
	   impossible to find the CTA. */
	opacity: 1;
	animation: pp-env-fade-up 280ms cubic-bezier(0.4, 0, 0.2, 1) 0ms both;
}

.pp-envelope__btn {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	width: clamp(280px, 82vw, 520px);
	min-height: clamp(64px, 9vh, 84px);
	padding: 0;
	border: 0;
	border-radius: 14px;
	background: linear-gradient(135deg,
		#FDE9E5 0%,
		#FCB2A9 18%,
		#FCB2A9 38%,
		#5D6770 55%,
		#FCB2A9 72%,
		#FCB2A9 88%,
		#FDE9E5 100%
	);
	color: #FFFFF8;
	font-family: var(--font-body-th, var(--font-body));
	font-size: clamp(17px, 3.6vw, 20px);
	font-weight: 600;
	letter-spacing: 0.04em;
	cursor: pointer;
	box-shadow:
		inset 0 1px 0 rgba(255, 255, 255, 0.7),
		inset 0 -2px 4px rgba(45, 55, 72, 0.4),
		inset 0 0 0 1px rgba(93, 103, 112, 0.3),
		0 8px 24px rgba(252, 178, 169, 0.35),
		0 2px 6px rgba(45, 55, 72, 0.18);
	overflow: hidden;
	-webkit-tap-highlight-color: transparent;
	transition:
		transform 200ms cubic-bezier(0.4, 0, 0.2, 1),
		box-shadow 200ms ease,
		filter 200ms ease;
}

/* Inner top highlight bevel */
.pp-envelope__btn-bevel {
	position: absolute;
	top: 1px;
	left: 1px;
	right: 1px;
	height: 42%;
	background: linear-gradient(180deg,
		rgba(253, 233, 229, 0.6) 0%,
		rgba(253, 233, 229, 0.2) 60%,
		transparent 100%
	);
	border-radius: 13px 13px 0 0;
	pointer-events: none;
	z-index: 1;
}

/* Shimmer sweep — animated gold sheen */
.pp-envelope__btn-shine {
	position: absolute;
	top: 0;
	left: -50%;
	width: 40%;
	height: 100%;
	background: linear-gradient(120deg,
		rgba(255, 255, 255, 0) 0%,
		rgba(253, 233, 229, 0.55) 40%,
		rgba(253, 233, 229, 0.8) 50%,
		rgba(253, 233, 229, 0.55) 60%,
		rgba(255, 255, 255, 0) 100%
	);
	transform: skewX(-22deg);
	pointer-events: none;
	z-index: 2;
	animation: pp-env-btn-shine 5s ease-in-out 4500ms infinite;
}

.pp-envelope__btn-inner {
	position: relative;
	z-index: 3;
	display: inline-flex;
	align-items: center;
	gap: 12px;
	padding: 18px 28px;
	text-shadow: 0 1px 2px rgba(45, 55, 72, 0.45);
}

.pp-envelope__btn-icon {
	flex: 0 0 auto;
	width: 22px;
	height: 22px;
	margin-right: 4px;
	filter: drop-shadow(0 1px 1px rgba(45, 55, 72, 0.4));
}

.pp-envelope__btn-label {
	font-family: var(--font-body-th, var(--font-body));
	white-space: nowrap;
}

.pp-envelope__btn:hover,
.pp-envelope__btn:focus-visible {
	transform: translateY(-2px);
	box-shadow:
		inset 0 1px 0 rgba(255, 255, 255, 0.8),
		inset 0 -2px 4px rgba(45, 55, 72, 0.4),
		inset 0 0 0 1px rgba(93, 103, 112, 0.3),
		0 14px 30px rgba(252, 178, 169, 0.42),
		0 4px 10px rgba(45, 55, 72, 0.28);
	outline: none;
	filter: brightness(1.04);
}

.pp-envelope__btn:active {
	transform: translateY(1px);
	box-shadow:
		inset 0 2px 4px rgba(45, 55, 72, 0.55),
		inset 0 0 0 1px rgba(45, 55, 72, 0.4),
		0 4px 10px rgba(252, 178, 169, 0.28);
}

.pp-envelope__btn:focus-visible {
	box-shadow:
		inset 0 1px 0 rgba(253, 233, 229, 0.75),
		inset 0 -2px 5px rgba(45, 55, 72, 0.45),
		0 0 0 3px rgba(255, 255, 248, 0.95),
		0 0 0 5px rgba(252, 178, 169, 0.6);
}

.pp-envelope__btn[disabled] {
	cursor: wait;
	opacity: 0.78;
	transform: none;
	filter: none;
}

.pp-envelope__btn[disabled] .pp-envelope__btn-shine {
	animation-play-state: paused;
	opacity: 0;
}

.pp-envelope__hint {
	margin: 0;
	font-size: clamp(13px, 3vw, 15px);
	font-style: italic;
	font-family: var(--font-heading-th, 'Noto Serif Thai', serif);
	color: var(--color-gold-text, #5D6770);
	opacity: 0.82;
	letter-spacing: 0.02em;
	text-align: center;
	opacity: 0;
	animation: pp-env-fade-in 600ms ease 4200ms forwards;
	/* Short hint "แตะเพื่อเปิดการ์ดเชิญ" should never break — fits comfortably
	   on a single line even at 320px. */
	white-space: nowrap;
}

/* ============================================================
   10. LOADING SPINNER
   ============================================================ */
.pp-envelope__spinner {
	display: inline-block;
	width: 18px;
	height: 18px;
	border: 2px solid rgba(255, 255, 248, 0.4);
	border-top-color: #FFFFF8;
	border-radius: 50%;
	animation: pp-env-spin 0.8s linear infinite;
	vertical-align: middle;
	margin-right: 8px;
}

/* ============================================================
   11. ADMIN PREVIEW SKIP LINK
   ============================================================ */
.pp-envelope__skip {
	position: absolute;
	top: 14px;
	right: 14px;
	z-index: 10;
	font-size: 12px;
	font-weight: 500;
	color: var(--color-gold-text, #5D6770);
	opacity: 0.65;
	text-decoration: none;
	padding: 6px 10px;
	border-radius: 8px;
	background: rgba(255, 255, 248, 0.7);
	-webkit-backdrop-filter: blur(6px);
	backdrop-filter: blur(6px);
	border: 1px solid rgba(252, 178, 169, 0.2);
	transition: opacity 200ms ease, background 200ms ease;
	font-family: var(--font-body, system-ui, sans-serif);
}

.pp-envelope__skip:hover,
.pp-envelope__skip:focus-visible {
	opacity: 1;
	background: rgba(255, 255, 248, 0.95);
	outline: none;
}

/* ============================================================
   12. BOTTOM-RIGHT CORNER STAR
   ============================================================ */
.pp-envelope__corner-star {
	position: absolute;
	bottom: clamp(24px, 5vh, 40px);
	right: clamp(18px, 4vw, 32px);
	width: clamp(22px, 5vw, 30px);
	height: clamp(22px, 5vw, 30px);
	z-index: 3;
	opacity: 0;
	animation:
		pp-env-fade-in 1000ms ease 4800ms forwards,
		pp-env-star-pulse 3.4s ease-in-out 5600ms infinite;
	pointer-events: none;
	filter: drop-shadow(0 0 7px rgba(252, 178, 169, 0.5));
}

/* ============================================================
   13. PETAL BURST (populated by JS on click)
   ============================================================ */
.pp-envelope__burst {
	position: absolute;
	top: 50%;
	left: 50%;
	width: 0;
	height: 0;
	z-index: 6;
	pointer-events: none;
}

.pp-envelope__burst-petal {
	position: absolute;
	top: 0;
	left: 0;
	width: 22px;
	height: 22px;
	border-radius: 80% 20% 60% 40% / 50% 30% 70% 50%;
	background:
		radial-gradient(ellipse 60% 80% at 50% 30%, #FBE5E5 0%, #F4C2C2 45%, #E8A4A4 100%);
	box-shadow:
		inset -1px -2px 4px rgba(160, 64, 64, 0.25),
		inset 1px 2px 4px rgba(255, 245, 245, 0.6);
	opacity: 0;
	transform: translate(-50%, -50%) scale(0.4);
	animation: pp-env-burst 1400ms cubic-bezier(0.25, 0.1, 0.25, 1) forwards;
	will-change: transform, opacity;
}

.pp-envelope__burst-petal--gold {
	background: linear-gradient(135deg, #FDE9E5 0%, #FCB2A9 50%, #5D6770 100%);
	border-radius: 100% 0 100% 0;
}

/* ============================================================
   14. OPENING ANIMATION CHOREOGRAPHY (click → 7s → redirect)
   v0.20.5 — DISTINCT VISIBLE PHASES (USER ROUND 3:
   "อนิเมชั่นหายไปหมดเลย")
   ============================================================
   v0.20.9 REDESIGN — clean "one card emerges" flow, no overlapping:

     t=0       button dims + spinner shows
     t=150ms   WAX CRACK starts (700ms — L+R halves fly apart visibly)
     t=750ms   FLAP rotates open (900ms slow elegant pivot,
               overlaps last 100ms of wax for fluid motion)
     t=1500ms  CARD-OUT emerges upward + scales up (900ms)
               No card-peek anymore (was duplicating + stacking)
     t=2100ms  ENVELOPE BODY + back-flap FADE OUT (700ms)
               — card stands alone, clean composition
     t=2400ms  Hint + brand + headline + CTA + filigree fade (700ms)
               so card-out + petals own the screen
     t=2400ms  Petal burst (JS, 1500ms trail celebrates card)
     t=2400ms  Particles fade to subtle bokeh (500ms)
     t=2400-3600ms  HOLD BEAT — card alone with petals (1200ms savour)
     t=3600ms  Scene fade cream→cream (700ms, never white)
     t=4300ms  Redirect to gate (JS OPEN_DURATION = 4300)

   Total: 4300ms (down from 7000ms) — punchy, every phase visible,
   card-out gets a clean hero moment with no envelope visual clutter
   ============================================================ */

/* v0.30.1 — Smooth 1200ms exit. Replaces the 4300ms 7-stage choreography
   that users reported as "เด้งขึ้นมา กระตุก" (jittery card pop). Old version
   stacked seal-crack + flap + spring-easing card-emerge + 4 simultaneous
   fade-outs on different selectors → compositor thrashing on mobile.
   New: single coordinated fade with a small upward lift on the card,
   transform-only on the GPU layer. No spring/overshoot. */

[data-pp-envelope].is-opening .pp-envelope__inner {
	animation: pp-env-inner-exit 900ms cubic-bezier(0.4, 0, 0.2, 1) 0ms both;
	will-change: opacity, transform;
}
[data-pp-envelope].is-opening .pp-envelope__art {
	animation: pp-env-art-exit 900ms cubic-bezier(0.4, 0, 0.2, 1) 0ms both;
	will-change: opacity, transform;
}
/* Card-out replaces the envelope SVG visually during the lift —
   simple ease-out, no spring, no jitter. */
[data-pp-envelope].is-opening .pp-envelope__card-out {
	animation: pp-env-card-out-smooth 700ms cubic-bezier(0.16, 1, 0.3, 1) 100ms both;
	will-change: transform, opacity;
}
/* Particles + corner star + filigree fade with the inner — they're already
   inside .pp-envelope__inner so they inherit the parent fade. The corner-star
   sits OUTSIDE .pp-envelope__inner so it needs its own rule. */
[data-pp-envelope].is-opening .pp-envelope__corner-star,
[data-pp-envelope].is-opening .pp-envelope__rose,
[data-pp-envelope].is-opening .pp-envelope__leaf,
[data-pp-envelope].is-opening .pp-envelope__sparkle,
[data-pp-envelope].is-opening .pp-envelope__swirl {
	animation: pp-env-fade-out-fast 600ms ease-out 0ms forwards !important;
}
/* Scene-wide soft blur during exit so the cream transition feels premium. */
[data-pp-envelope].is-opening {
	animation: pp-env-scene-exit-smooth 1200ms ease-in-out 0ms both;
}

/* ============================================================
   15. KEYFRAMES
   ============================================================ */
/* v0.30.1 — Smooth opening keyframes */
@keyframes pp-env-inner-exit {
	from { opacity: 1; transform: translateY(0) scale(1); }
	to   { opacity: 0; transform: translateY(-12px) scale(0.985); }
}
@keyframes pp-env-art-exit {
	from { opacity: 1; transform: translateY(0) scale(1); }
	to   { opacity: 0; transform: translateY(-24px) scale(1.04); }
}
@keyframes pp-env-card-out-smooth {
	0%   { opacity: 0; transform: translateY(20px) scale(0.92); }
	60%  { opacity: 1; }
	100% { opacity: 0; transform: translateY(-80px) scale(1.08); }
}
@keyframes pp-env-fade-out-fast {
	from { opacity: var(--pp-fade-from, 1); }
	to   { opacity: 0; }
}
@keyframes pp-env-scene-exit-smooth {
	from { filter: blur(0); }
	to   { filter: blur(2px); }
}

@keyframes pp-env-silk-fade {
	from { opacity: 0; }
	to   { opacity: 1; }
}

@keyframes pp-env-swirl-in {
	from { opacity: 0; transform: scale(0.6) rotate(-30deg); }
	to   { opacity: 0.7; transform: scale(1) rotate(0deg); }
}

@keyframes pp-env-swirl-spin {
	from { transform: rotate(0deg); }
	to   { transform: rotate(360deg); }
}

@keyframes pp-env-rose-drift {
	0% {
		transform: translateY(0) translateX(0) rotate(0deg) scale(var(--s, 1));
		opacity: 0;
	}
	8% { opacity: 0.85; }
	25% {
		transform: translateY(-25vh) translateX(20px) rotate(120deg) scale(var(--s, 1));
		opacity: 0.85;
	}
	50% {
		transform: translateY(-55vh) translateX(-15px) rotate(220deg) scale(var(--s, 1));
		opacity: 0.75;
	}
	75% {
		transform: translateY(-85vh) translateX(25px) rotate(310deg) scale(var(--s, 1));
		opacity: 0.6;
	}
	100% {
		transform: translateY(-115vh) translateX(0) rotate(420deg) scale(var(--s, 1));
		opacity: 0;
	}
}

@keyframes pp-env-leaf-drift {
	0% {
		transform: translateY(0) translateX(0) rotate(0deg) scale(var(--s, 1));
		opacity: 0;
	}
	8% { opacity: 0.85; }
	30% {
		transform: translateY(-30vh) translateX(-25px) rotate(180deg) scale(var(--s, 1));
		opacity: 0.9;
	}
	60% {
		transform: translateY(-65vh) translateX(30px) rotate(280deg) scale(var(--s, 1));
		opacity: 0.7;
	}
	100% {
		transform: translateY(-115vh) translateX(-12px) rotate(420deg) scale(var(--s, 1));
		opacity: 0;
	}
}

@keyframes pp-env-twinkle {
	0%, 100% { opacity: 0; transform: scale(0.6); }
	30%      { opacity: 0.85; transform: scale(1); }
	50%      { opacity: 1; transform: scale(1.3); }
	70%      { opacity: 0.85; transform: scale(1); }
}

@keyframes pp-env-fade-in {
	from { opacity: 0; }
	to   { opacity: 1; }
}

@keyframes pp-env-fade-up {
	from { opacity: 0; transform: translateY(14px); }
	to   { opacity: 1; transform: translateY(0); }
}

/* v0.20.4 — explicit `from` is REQUIRED. With `animation-fill-mode: both`
   the 0% frame is applied during the 6500ms delay; without an explicit
   `from` the browser may snapshot inconsistent intermediate state. */
@keyframes pp-env-fade-out {
	from { opacity: 1; transform: translateY(0); }
	to   { opacity: 0; transform: translateY(-8px); }
}

@keyframes pp-env-envelope-rise {
	0% {
		opacity: 0;
		transform: translateY(40px) scale(0.9);
	}
	60% {
		opacity: 1;
		transform: translateY(-8px) scale(1.03);
	}
	100% {
		opacity: 1;
		transform: translateY(0) scale(1);
	}
}

@keyframes pp-env-envelope-lift-fade {
	0%   { opacity: 1; transform: translateY(0) scale(1); filter: blur(0px); }
	60%  { opacity: 0.85; transform: translateY(-30px) scale(1.04); filter: blur(0.5px); }
	100% { opacity: 0.15; transform: translateY(-70px) scale(1.08); filter: blur(2px); }
}

/* Scene exit — gentle scale + soft blur instead of opacity→0.
   Keeps cream filling the viewport so the gate page transition
   never reveals raw white. */
@keyframes pp-env-scene-exit {
	0%   { filter: blur(0px); transform: scale(1); }
	100% { filter: blur(1.5px); transform: scale(1.015); }
}

/* v0.20.9: pp-env-card-peek-reveal keyframe removed — card-peek
   element is gone from the template. */

/* v0.20.9: envelope body + back-flap fade. After card-out emerges
   we collapse the envelope visually so the card stands alone with
   the cream backdrop. Subtle downward drift + slight scale down
   reads as the envelope "settling" away rather than disappearing. */
@keyframes pp-env-body-fade {
	0%   { opacity: 1; transform: translateY(0) scale(1); }
	100% { opacity: 0; transform: translateY(12px) scale(0.97); }
}

@keyframes pp-env-filigree-draw {
	from { stroke-dashoffset: 380; opacity: 0; }
	20%  { opacity: 1; }
	to   { stroke-dashoffset: 0; opacity: 1; }
}

@keyframes pp-env-seal-stamp {
	0% {
		opacity: 0;
		transform: scale(0.4) translateY(-30px);
	}
	60% {
		opacity: 1;
		transform: scale(1.18) translateY(0);
	}
	80% {
		transform: scale(0.95) translateY(0);
	}
	100% {
		opacity: 1;
		transform: scale(1) translateY(0);
	}
}

/* v0.20.5 — explicit transform in 0% so when this keyframe REPLACES
   the seal-stamp entry animation, the seal stays at its rest position
   (scale 1, translateY 0) during the 200ms delay window. Without this,
   the base CSS rule's `transform: scale(0.4) translateY(-30px)` snaps
   back and the seal would appear shrunk + offset before the crack. */
@keyframes pp-env-seal-crack-fade {
	0%   { opacity: 1; transform: scale(1) translateY(0); }
	60%  { opacity: 0.6; transform: scale(1) translateY(0); }
	100% { opacity: 0; transform: scale(1) translateY(0); }
}

/* v0.20.5 — explicit wax half crack keyframes. Each half visibly
   flies outward, rotates, and fades. Stage 0% = visible at rest,
   100% = flown out + invisible. */
@keyframes pp-env-seal-crack-left {
	0% {
		transform: translate(0, 0) rotate(0deg);
		opacity: 1;
	}
	30% {
		transform: translate(-10px, 4px) rotate(-8deg);
		opacity: 1;
	}
	100% {
		transform: translate(-50px, 24px) rotate(-32deg);
		opacity: 0;
	}
}
@keyframes pp-env-seal-crack-right {
	0% {
		transform: translate(0, 0) rotate(0deg);
		opacity: 1;
	}
	30% {
		transform: translate(10px, 4px) rotate(8deg);
		opacity: 1;
	}
	100% {
		transform: translate(50px, 24px) rotate(32deg);
		opacity: 0;
	}
}

@keyframes pp-env-flap-open {
	0% {
		transform: rotateX(0deg);
	}
	100% {
		transform: rotateX(-175deg) translateY(-10px);
	}
}

/* v0.20.9 — card rises BIGGER and HIGHER so it clears the envelope
   silhouette before the body fade kicks in. Final state translateY
   -80px + scale 1.12 makes the card the dominant hero element of
   the hold beat. Spring easing on the rule gives it a satisfying
   settle, not a linear glide. */
@keyframes pp-env-card-out {
	0% {
		opacity: 0;
		transform: translateY(70px) scale(0.88);
	}
	25% {
		opacity: 0.7;
		transform: translateY(30px) scale(0.94);
	}
	55% {
		opacity: 1;
		transform: translateY(-30px) scale(1.06);
	}
	80% {
		opacity: 1;
		transform: translateY(-72px) scale(1.14);
	}
	100% {
		opacity: 1;
		transform: translateY(-78px) scale(1.12);
	}
}

/* v0.20.3 — Particle recede during hold beat.
   Triggered at t=1200ms in opening sequence. Drops particles
   from full opacity to 0.12 (barely visible bokeh) so card
   text dominates the 5.3s hold. We DON'T pause via keyframe
   (non-standard) — instead, after recede completes the
   element keeps the 0.12 opacity via fill-mode: forwards while
   the underlying drift continues at very low visibility (which
   reads as static bokeh from the user's perspective). */
@keyframes pp-env-particle-recede {
	0%   { opacity: 0.85; }
	100% { opacity: 0.12; }
}

@keyframes pp-env-btn-shine {
	0%   { left: -50%; }
	40%  { left: 130%; }
	100% { left: 130%; }
}

@keyframes pp-env-star-pulse {
	0%, 100% { opacity: 0.6; transform: scale(1) rotate(0deg); }
	50%      { opacity: 1; transform: scale(1.18) rotate(45deg); }
}

@keyframes pp-env-burst {
	0% {
		opacity: 0;
		transform: translate(-50%, -50%) scale(0.4) rotate(0deg);
	}
	15% {
		opacity: 1;
	}
	100% {
		opacity: 0;
		transform: translate(calc(-50% + var(--vx, 0px)), calc(-50% + var(--vy, 0px))) scale(0.9) rotate(var(--vr, 180deg));
	}
}

@keyframes pp-env-spin {
	to { transform: rotate(360deg); }
}

/* ============================================================
   16. REDUCED MOTION — collapse to fade-only
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
	.pp-envelope__silk,
	.pp-envelope__swirl,
	.pp-envelope__rose,
	.pp-envelope__leaf,
	.pp-envelope__sparkle,
	.pp-envelope__filigree,
	.pp-envelope__filigree-path,
	.pp-envelope__filigree-dot,
	.pp-envelope__brand,
	.pp-envelope__invite,
	.pp-envelope__recipient,
	.pp-envelope__art,
	.pp-envelope__seal,
	.pp-envelope__cta,
	.pp-envelope__hint,
	.pp-envelope__corner-star,
	.pp-envelope__btn-shine {
		animation: none !important;
		opacity: 1 !important;
		transform: none !important;
		stroke-dashoffset: 0 !important;
	}

	.pp-envelope__rose,
	.pp-envelope__leaf,
	.pp-envelope__sparkle {
		opacity: 0 !important;
	}

	.pp-envelope__swirl {
		opacity: 0.5 !important;
	}

	.pp-envelope__art:hover .pp-envelope__svg {
		transform: none;
	}

	[data-pp-envelope].is-opening .pp-envelope__inner,
	[data-pp-envelope].is-opening .pp-envelope__filigree,
	[data-pp-envelope].is-opening .pp-envelope__brand,
	[data-pp-envelope].is-opening .pp-envelope__invite,
	[data-pp-envelope].is-opening .pp-envelope__art,
	[data-pp-envelope].is-opening .pp-envelope__cta,
	[data-pp-envelope].is-opening .pp-envelope__corner-star {
		animation: pp-env-fade-out 400ms ease forwards !important;
		opacity: 1 !important;
	}

	[data-pp-envelope].is-opening .pp-envelope__flap-wrap,
	[data-pp-envelope].is-opening .pp-envelope__seal,
	[data-pp-envelope].is-opening .pp-envelope__seal-wax--left,
	[data-pp-envelope].is-opening .pp-envelope__seal-wax--right,
	[data-pp-envelope].is-opening .pp-envelope__card-out {
		animation: none !important;
		transition: opacity 300ms ease !important;
		opacity: 0 !important;
		transform: none !important;
	}
}

/* ============================================================
   17. RESPONSIVE
   ============================================================ */

/* Tablet / small desktop */
@media (min-width: 640px) {
	.pp-envelope {
		padding-top: clamp(40px, 7vh, 80px);
	}
	.pp-envelope__inner {
		max-width: 540px;
	}
	.pp-envelope__art {
		max-width: 480px;
	}
	.pp-envelope__btn {
		font-size: 19px;
	}
	.pp-envelope__btn-inner {
		padding: 20px 32px;
	}
}

/* Desktop ≥ 1024px — v0.32.11 — Atelier Spread (final per frontend-design spec)
   Owner: "ทำไมเปิดตอนเปิดการ์ดไม่ปรับ layout ด้วย" + "ออกแบบให้ดี".
   frontend-design final brief: stationery flatlay photography metaphor.
   Envelope LEFT 45fr (landscape 7:5, won't outrun action vertical),
   action stack RIGHT 55fr centered. 4-corner gold flourish via TR/BL
   swirls + reposition --mid to BR. corner-star hidden (BR is occupied
   by mid swirl now). drop-shadow deepened for luxury depth.

   IMPORTANT: animation delays inherited from mobile choreography
   (1000-4200ms) make the right column blank for ~4s on first paint.
   Override delays to 200-1400ms range so desktop reveals fast.

   No PHP edit — `display: contents` on .pp-envelope__inner; assign
   grid-column/grid-row explicitly per child (no grid-template-areas). */
@media (min-width: 1024px) {
	.pp-envelope {
		display: grid;
		grid-template-columns: minmax(0, 45fr) minmax(0, 55fr);
		grid-template-rows: auto auto auto auto auto;
		column-gap: clamp(56px, 6vw, 96px);
		row-gap: clamp(10px, 1.4vh, 18px);
		align-content: center;
		justify-content: center;
		padding: clamp(40px, 6vh, 72px) clamp(48px, 5vw, 96px);
		max-width: 1440px;
		margin-inline: auto;
	}
	.pp-envelope__inner {
		display: contents;
	}

	/* Envelope spans all rows on the LEFT — the hero artifact. */
	.pp-envelope__art {
		grid-column: 1;
		grid-row: 1 / -1;
		align-self: center;
		justify-self: end;
		width: min(540px, 100%);
		max-width: none;
		max-height: none;
		margin: 0;
		filter: drop-shadow(0 32px 64px rgba(45, 55, 72, 0.24));
	}

	/* Action stack on the RIGHT — explicit row positions. */
	.pp-envelope__filigree {
		grid-column: 2;
		grid-row: 1;
		justify-self: center;
		width: clamp(220px, 16vw, 280px);
		margin: 0 0 4px;
	}
	.pp-envelope__brand {
		grid-column: 2;
		grid-row: 2;
		justify-self: center;
		text-align: center;
		margin: 0;
		gap: 6px;
	}
	.pp-envelope__logo {
		width: clamp(140px, 11vw, 180px);
		height: clamp(140px, 11vw, 180px);
	}
	.pp-envelope__logo--fallback {
		font-size: clamp(88px, 10vw, 120px);
	}
	.pp-envelope__wordmark {
		font-size: clamp(13px, 1vw, 16px);
	}
	.pp-envelope__invite {
		grid-column: 2;
		grid-row: 3;
		justify-self: center;
		text-align: center;
		max-width: 460px;
		margin: 0;
		padding: 0;
	}
	.pp-envelope__headline {
		text-align: center;
	}
	.pp-envelope__headline--direct {
		font-size: clamp(22px, 1.8vw, 28px);
		line-height: 1.45;
		max-width: 100%;
		margin-inline: auto;
	}
	.pp-envelope__headline--small {
		font-size: clamp(13px, 1vw, 15px);
	}
	.pp-envelope__btn {
		grid-column: 2;
		grid-row: 4;
		justify-self: center;
		width: 100%;
		max-width: 420px;
		min-height: 72px;
		margin: 8px 0 0;
	}
	.pp-envelope__btn-inner {
		padding: 22px 44px;
	}
	.pp-envelope__btn-label {
		font-size: 20px;
	}
	.pp-envelope__hint {
		grid-column: 2;
		grid-row: 5;
		justify-self: center;
		text-align: center;
		font-size: 15px;
		margin: 0;
	}

	.pp-envelope__skip {
		top: 28px;
		right: 32px;
	}

	/* Compress animation choreography at desktop — mobile's 1.0-4.2s
	   delays leave the right column blank too long on the wider 2-col
	   composition. Pull delays into 0.2-1.4s window. */
	.pp-envelope__filigree { animation-delay: 200ms; }
	.pp-envelope__brand    { animation-delay: 350ms; }
	.pp-envelope__invite   { animation-delay: 500ms; }
	.pp-envelope__art      { animation-delay: 650ms; }
	.pp-envelope__recipient { animation-delay: 700ms; }
	.pp-envelope__btn      { animation-delay: 850ms; }
	.pp-envelope__hint     { animation-delay: 1100ms; }
	.pp-envelope__corner-star { animation-delay: 1400ms; }

	/* 4-corner gold flourish at desktop scale. TR + BL stay; --mid
	   relocates to BR; the page-corner star hides (BR is occupied). */
	.pp-envelope__swirl--tr {
		width: clamp(280px, 22vw, 380px);
		top: -56px;
		right: -56px;
		opacity: 0.55;
	}
	.pp-envelope__swirl--bl {
		width: clamp(280px, 22vw, 380px);
		bottom: -56px;
		left: -56px;
		opacity: 0.55;
	}
	.pp-envelope__swirl--mid {
		display: block;
		top: auto;
		left: auto;
		bottom: clamp(40px, 8vh, 80px);
		right: clamp(40px, 5vw, 80px);
		width: clamp(180px, 16vw, 260px);
		height: clamp(180px, 16vw, 260px);
		opacity: 0.45;
		transform: none;
	}
	.pp-envelope__corner-star {
		display: none; /* BR corner now belongs to --mid swirl */
	}

	/* Slightly enlarge silk fold overlay so the texture reads at this scale. */
	.pp-envelope__silk::before {
		inset: -15%;
	}

	/* Particles dim slightly so they don't compete with brand+CTA. */
	.pp-envelope__rose,
	.pp-envelope__leaf {
		opacity: 0.65;
	}
	.pp-envelope__sparkle {
		opacity: 0.7;
	}
}

/* Wide desktop ≥ 1440px — release more breathing space + scale. */
@media (min-width: 1440px) {
	.pp-envelope {
		padding-inline: clamp(80px, 8vw, 160px);
		column-gap: clamp(80px, 8vw, 140px);
		max-width: 1600px;
	}
	.pp-envelope__art {
		width: min(620px, 100%);
	}
	.pp-envelope__logo {
		width: 190px;
		height: 190px;
	}
	.pp-envelope__headline--direct {
		font-size: 30px;
	}
	.pp-envelope__btn {
		max-width: 460px;
	}
	.pp-envelope__btn-inner {
		padding: 24px 48px;
	}
	.pp-envelope__btn-label {
		font-size: 22px;
	}
	.pp-envelope__swirl--tr,
	.pp-envelope__swirl--bl {
		width: clamp(320px, 24vw, 420px);
	}
	.pp-envelope__swirl--tr {
		top: -80px;
		right: -80px;
	}
	.pp-envelope__swirl--bl {
		bottom: -80px;
		left: -80px;
	}
}

/* Ultra-wide ≥ 1920px — flip to 50/50 grid; envelope can grow more. */
@media (min-width: 1920px) {
	.pp-envelope {
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
		max-width: 1800px;
	}
	.pp-envelope__art {
		width: min(720px, 100%);
	}
	.pp-envelope__invite,
	.pp-envelope__btn {
		max-width: 520px;
	}
	.pp-envelope__headline--direct {
		font-size: 32px;
	}
}

/* Short-height desktop (laptop 1024×600, etc) — tighten everything
   so the 2-col composition fits inside the viewport without scroll. */
@media (min-width: 1024px) and (max-height: 760px) {
	.pp-envelope {
		padding-block: 20px;
		row-gap: clamp(6px, 1.2vh, 14px);
	}
	.pp-envelope__art {
		width: min(440px, 100%);
	}
	.pp-envelope__logo {
		width: clamp(110px, 9vw, 140px);
		height: clamp(110px, 9vw, 140px);
	}
	.pp-envelope__headline--direct {
		font-size: clamp(18px, 1.6vw, 22px);
	}
	.pp-envelope__btn {
		min-height: 64px;
	}
}

/* Print stylesheet — strip decoration, keep the artifact + headline. */
@media print {
	.pp-envelope {
		display: block;
		padding: 24px;
		background: #fff;
	}
	.pp-envelope__silk,
	.pp-envelope__swirls,
	.pp-envelope__particles,
	.pp-envelope__corner-star,
	.pp-envelope__skip,
	.pp-envelope__btn {
		display: none;
	}
	.pp-envelope__art {
		width: 60%;
		margin: 0 auto;
	}
}

/* Very small screens (iPhone SE etc.) */
@media (max-width: 359px) {
	.pp-envelope {
		padding-top: 20px;
	}
	.pp-envelope__logo {
		width: 110px;
		height: 110px;
	}
	.pp-envelope__brand {
		margin-bottom: 18px;
	}
	.pp-envelope__invite {
		margin-bottom: 18px;
	}
	.pp-envelope__art {
		margin-bottom: 26px;
	}
	.pp-envelope__btn {
		min-height: 60px;
		font-size: 16px;
	}
	.pp-envelope__btn-inner {
		padding: 14px 20px;
	}
	.pp-envelope__filigree {
		width: 210px;
	}
}

/* Short viewport (landscape phones) — clamp envelope to fit */
@media (max-height: 720px) {
	.pp-envelope__brand {
		margin-bottom: 16px;
	}
	.pp-envelope__logo {
		width: clamp(100px, 28vw, 130px);
		height: clamp(100px, 28vw, 130px);
	}
	.pp-envelope__art {
		max-height: 32vh;
		margin-bottom: 22px;
	}
	.pp-envelope__invite {
		margin-bottom: 14px;
	}
	.pp-envelope__btn {
		min-height: 58px;
	}
}

/* Extra short (≤ 600px height) — emergency clamp */
@media (max-height: 600px) {
	.pp-envelope__art {
		max-height: 28vh;
	}
	.pp-envelope__logo {
		width: 90px;
		height: 90px;
	}
}
