/* ============================================================
   custom-voyage「航空信」｜style.css（2026-10-02 v1）
   視覺系統：一整套郵政文件——做舊牛皮紙＋紙紋顆粒、齒孔郵票、巨大襯線城市名、紅日、圓形郵戳、
   紅藍航空信條紋、登機證、護照、行李吊牌、回函明信片。
   - 色：vermilion #c8402a（大字／章）＋ navy #1f3a5f（字／框）＋ cream #efe3c8（紙）＋ 墨 #2b2622，少量金。
     朱紅當「文字」一律用加深的 --verm-tx（對奶油紙 ≥ 5:1）；原色只給大字、圖形、章。
   - 字：Fraunces（巨型拉丁海報字，opsz 144／wght 800）、裝置明體（中文內文與直排；沒有內建明體的裝置才掛 Google 的 Noto Serif TC）、
     清松手寫體（收件人、明信片背面、新人短信）、Courier Prime（所有郵政欄位與小標）、Noto Serif JP（只當裝飾小字）。
   - 幾何符號（✕、飛機、郵戳框、齒孔）一律 CSS／SVG 畫，不靠字型。
   規則：
   - 動畫的前置隱藏態一律寫在 html.wc（CSS 進場）或 html.fx（GSAP 層）底下，預設 CSS 永遠是完成態——
     preview／爬蟲／降級永遠看得到內容。
   - 賓客頁不因減少動態降級（旗標 wk-keep-motion）：本檔沒有 RM 分支。
   - 齒孔 mask 不掛 .reveal 本體；3D 翻面的旋轉元素本體不掛 opacity／filter／clip-path／overflow。
   ============================================================ */

@font-face {
  font-family: "Fraunces";
  src: url("/shared/vendor/fraunces-latin-vf-1.0.woff2") format("woff2-variations"),
       url("/shared/vendor/fraunces-latin-vf-1.0.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --cream: #efe3c8;
  --cream-hi: #f7f0de;
  --cream-lo: #e4d2ab;
  --kraft: #d6b98a;
  --kraft-lo: #c9a771;
  --ink: #2b2622;
  --ink-soft: #564c43;          /* 奶油紙上 ≥ 6:1（長輩看小字不吃力） */
  --verm: #c8402a;
  --verm-tx: #a3311e;           /* 朱紅當文字用：對 --cream ≥ 5.3:1 */
  --verm-hi: #ef7a5c;           /* 深藍底上的朱紅（大字用，≥ 4.5:1） */
  --navy: #1f3a5f;
  --navy-deep: #152b49;
  --navy-ink: #0f2038;
  --gold: #b48a3c;
  --rubber: #7d2516;

  /* 標準 token（base.css 與共用元件會讀） */
  --paper: var(--cream);
  --paper-raise: var(--cream-hi);
  --accent: var(--navy);
  --accent-ink: var(--cream-hi);
  --hairline: rgba(43, 38, 34, .2);
  --scratch-a: #cdb27c;
  --scratch-b: #e9d9b4;
  --warn: #a3311e;

  --font-display: "Fraunces", "Times New Roman", serif;
  /* 數字與拉丁字由最前面的 Fraunces 接（拉丁字只到它就停），中文才往後找 */
  /* 裝置內建明體在前（iOS／mac 宋體-繁、桌機有裝的 Noto Serif CJK／思源宋體／Noto Serif TC），都沒有才輪到 Google Fonts 的 Noto Serif TC
     ——那條 css2 只在偵測不到內建明體時才由 index.html <head> 的 script 掛上（不用 @font-face local()：太慢，理由寫在那裡）。
     Android 走最後的 generic serif（＝系統的 Noto Serif CJK）。刻意不列新細明體（PMingLiU／MingLiU）。 */
  --tc-face: "Songti TC", "Noto Serif CJK TC", "Source Han Serif TC", "Noto Serif TC";
  --font-tc: "Fraunces", var(--tc-face), serif;
  --font-hw: "JasonHandwriting9", "Kaiti TC", "DFKai-SB", var(--tc-face), cursive;
  --font-mono: "Courier Prime", "Courier New", var(--tc-face), monospace;
  --font-jp: "Noto Serif JP", "Hiragino Mincho ProN", "Yu Mincho", serif;
  --font-serif-tc: var(--font-tc);

  --airmail: repeating-linear-gradient(-45deg, var(--verm) 0 10px, var(--cream-hi) 10px 16px, var(--navy) 16px 26px, var(--cream-hi) 26px 32px);
  /* 墨印質感：feTurbulence 雜訊當 mask（內嵌 data URI，零外部請求）——章、郵戳、簽證章共用 */
  --ink-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' seed='7'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5 3.6'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3C/svg%3E");

  --wide-max: 74rem;
  --radius: 4px;
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-snap: cubic-bezier(.2, 1.4, .4, 1);
  --ease-in: cubic-bezier(.55, 0, .9, .4);
}

/* 橫向溢出用 clip 不用 hidden（hidden 會讓 body 變捲動容器，ScrollTrigger 量錯）；
   scroll-behavior 一律 auto（蓋掉 base.css 的 smooth：ScrollTrigger.refresh 先捲到 0 再捲回，smooth 會讓量到的 start 漂移） */
html { background: var(--cream); overflow-x: clip; scroll-behavior: auto; }
body {
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-tc);
  font-size: var(--text-body);
  line-height: 1.85;
  overflow-x: clip;
}
.hw { font-family: var(--font-hw); font-weight: 400; }
.jp { font-family: var(--font-jp); font-weight: 500; }
.section { position: relative; overflow-x: clip; }

/* 紙紋顆粒：全頁固定一層（獨立 fixed div；不用負 z 的偽元素——body 有底色會蓋掉） */
.grain {
  position: fixed; inset: 0;
  z-index: 60;
  pointer-events: none;
  opacity: .12;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .25 0 0 0 0 .18 0 0 0 0 .1 0 0 0 .75 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 240px 240px;
}

/* 頂端航空信條紋進度條 */
.vy-progress { position: fixed; left: 0; right: 0; top: 0; height: 5px; z-index: 55; pointer-events: none; }
.vy-progress i { display: block; height: 100%; width: 100%; transform-origin: 0 50%; transform: scaleX(var(--p, 0)); background: var(--airmail); background-size: 45px 100%; }
html.has-intro .vy-progress { opacity: 0; }

/* ============ 齒孔（郵票邊）：兩層 mask，上下一層（.perf）、左右一層（.perf-y） ============ */
.perf {
  --r: 6px; --s: 20px;
  -webkit-mask:
    radial-gradient(circle var(--r) at 50% 0, #0000 calc(100% - .5px), #000 100%) top / var(--s) 51% round no-repeat,
    radial-gradient(circle var(--r) at 50% 100%, #0000 calc(100% - .5px), #000 100%) bottom / var(--s) 51% round no-repeat;
  mask:
    radial-gradient(circle var(--r) at 50% 0, #0000 calc(100% - .5px), #000 100%) top / var(--s) 51% round no-repeat,
    radial-gradient(circle var(--r) at 50% 100%, #0000 calc(100% - .5px), #000 100%) bottom / var(--s) 51% round no-repeat;
}
.perf-y {
  height: 100%;
  -webkit-mask:
    radial-gradient(circle var(--r) at 0 50%, #0000 calc(100% - .5px), #000 100%) left / 51% var(--s) no-repeat round,
    radial-gradient(circle var(--r) at 100% 50%, #0000 calc(100% - .5px), #000 100%) right / 51% var(--s) no-repeat round;
  mask:
    radial-gradient(circle var(--r) at 0 50%, #0000 calc(100% - .5px), #000 100%) left / 51% var(--s) no-repeat round,
    radial-gradient(circle var(--r) at 100% 50%, #0000 calc(100% - .5px), #000 100%) right / 51% var(--s) no-repeat round;
}

/* ============ 區塊抬頭：郵政表單編號＋巨字＋貼上去的中文標籤 ============ */
.sh { position: relative; margin-bottom: clamp(1.6rem, 5vw, 2.8rem); }
.sh-no {
  display: flex; align-items: center; gap: .7em;
  font-family: var(--font-mono); font-weight: 700;
  font-size: .82rem; letter-spacing: .2em; text-transform: uppercase;
  color: var(--verm-tx);
}
.sh-no::before { content: ""; flex: none; width: 2.6rem; height: 9px; background: var(--airmail); background-size: 32px 100%; }
.sh-word {
  font-family: var(--font-display);
  font-weight: 800;
  font-variation-settings: "opsz" 144, "wght" 800;
  font-size: calc(clamp(4rem, 21vw, 13.5rem) * var(--names-fit, 1));
  line-height: .8;
  letter-spacing: -.035em;
  color: var(--navy);
  white-space: nowrap;
  margin-top: .3rem;
  user-select: none;
}
/* 節奏：每隔幾區把巨字換成朱紅空心字，九區不會一路同一個重量 */
#dresscode .sh-word, #custom .sh-word, #rsvp .sh-word { color: transparent; -webkit-text-stroke: 2px var(--verm); }
@media (min-width: 900px) { #dresscode .sh-word, #custom .sh-word, #rsvp .sh-word { -webkit-text-stroke-width: 3px; } }
.section-title {
  position: relative; z-index: 2;
  display: inline-block;
  font-family: var(--font-tc); font-weight: 400;
  font-size: clamp(1.45rem, 5.4vw, 2.1rem);
  line-height: 1.25;
  letter-spacing: .12em;
  color: var(--ink);
  background: var(--cream-hi);
  border: 1.5px solid var(--ink);
  box-shadow: 4px 4px 0 var(--verm);
  padding: .3em .75em .36em;
  margin: -.55em 0 0 clamp(.6rem, 7vw, 5rem);
  transform: rotate(-1.6deg);
}
.section-title:empty { display: none; }

/* ============================================================
   開場：航空信封
   ============================================================ */
.intro {
  position: fixed; inset: 0; z-index: 80;
  display: grid; place-items: center;
  overflow: hidden;
  touch-action: none;
  cursor: pointer;
  -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none;
}
.intro-desk {
  position: absolute; inset: 0;
  background:
    radial-gradient(70% 55% at 50% 42%, rgba(255, 236, 196, .22), transparent 70%),
    radial-gradient(120% 90% at 50% 50%, #23426b 0%, #142a47 62%, #0b1a2f 100%);
}
.intro-desk::after {
  content: ""; position: absolute; inset: 0; opacity: .5; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.7' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
.env-wrap { position: relative; z-index: 2; margin-top: -5vh; }
.env {
  --wk-open: 0;
  --st: 15.5%;                  /* 撕條上緣 */
  --sh: 7%;                     /* 撕條高 */
  position: relative;
  width: min(82vw, 370px);
  aspect-ratio: 5 / 7;
  perspective: 1100px;
  color: var(--ink);
  font-family: var(--font-mono);
  filter: drop-shadow(0 28px 34px rgba(5, 12, 24, .55)) drop-shadow(0 2px 3px rgba(5, 12, 24, .4));
}
@media (min-width: 760px) and (min-aspect-ratio: 1/1) {
  .env { width: min(62vw, 640px); aspect-ratio: 16 / 10; --st: 17%; --sh: 9%; }
}
/* 信封內側：撕開後上緣翻起才看得到 */
.env-inside {
  position: absolute; left: 3%; right: 3%; top: 2%; height: calc(var(--st) + var(--sh) + 6%);
  background: linear-gradient(180deg, #b8935c, #a8834c);
  border-radius: 2px;
  overflow: hidden;
}
.env-letter {
  position: absolute; left: 6%; right: 6%; top: 14%; height: 150%;
  background: #f9f4e6;
  background-image: repeating-linear-gradient(180deg, transparent 0 17px, rgba(31, 58, 95, .2) 17px 18px);
  background-position: 0 30px;
  padding: 10px 14px;
  box-shadow: 0 -2px 6px rgba(0, 0, 0, .15);
}
.el-dear { font-family: var(--font-hw); font-size: 1.05rem; color: var(--navy); line-height: 1.2; }
.el-dear b { font-weight: 400; }
.env-letter span { display: none; }
/* 本體（撕條以下） */
.env-body {
  position: absolute; left: 0; right: 0; bottom: 0;
  top: calc(var(--st) + var(--sh));
  background: var(--airmail);
  background-size: 45px 45px;
  padding: 9px;
  border-radius: 0 0 3px 3px;
}
.env-body::before {
  content: ""; position: absolute; inset: 9px;
  background:
    radial-gradient(90% 70% at 30% 20%, rgba(255, 255, 255, .5), transparent 60%),
    linear-gradient(180deg, #f8f1df, #efe4ca);
}
.env-body > * { position: absolute; z-index: 1; }
.env-stamp { right: 7%; top: 7%; width: 27%; aspect-ratio: 4 / 5; transform: rotate(3deg); }
.es-perf { --r: 3px; --s: 9px; height: 100%; -webkit-mask: radial-gradient(circle var(--r) at 50% 0, #0000 calc(100% - .5px), #000 100%) top / var(--s) 51% round no-repeat, radial-gradient(circle var(--r) at 50% 100%, #0000 calc(100% - .5px), #000 100%) bottom / var(--s) 51% round no-repeat; mask: radial-gradient(circle var(--r) at 50% 0, #0000 calc(100% - .5px), #000 100%) top / var(--s) 51% round no-repeat, radial-gradient(circle var(--r) at 50% 100%, #0000 calc(100% - .5px), #000 100%) bottom / var(--s) 51% round no-repeat; }
.es-perf-y { height: 100%; -webkit-mask: radial-gradient(circle var(--r) at 0 50%, #0000 calc(100% - .5px), #000 100%) left / 51% var(--s) no-repeat round, radial-gradient(circle var(--r) at 100% 50%, #0000 calc(100% - .5px), #000 100%) right / 51% var(--s) no-repeat round; mask: radial-gradient(circle var(--r) at 0 50%, #0000 calc(100% - .5px), #000 100%) left / 51% var(--s) no-repeat round, radial-gradient(circle var(--r) at 100% 50%, #0000 calc(100% - .5px), #000 100%) right / 51% var(--s) no-repeat round; }
.es-face {
  position: relative; height: 100%;
  background: #fbf6ea;
  padding: 6px;
  overflow: hidden;
}
.es-face::before { content: ""; position: absolute; inset: 6px; background: linear-gradient(180deg, #f3e2bf, #efd7a8); }
.es-sun { position: absolute; left: 50%; top: 30%; width: 46%; aspect-ratio: 1; border-radius: 50%; background: var(--verm); transform: translate(-50%, -50%); }
.es-wave {
  position: absolute; left: 6px; right: 6px; bottom: 6px; height: 42%;
  background:
    radial-gradient(circle at 50% 100%, transparent 38%, var(--navy) 40% 52%, transparent 54% 64%, var(--navy) 66% 74%, transparent 76%) 0 0 / 22px 18px repeat-x,
    linear-gradient(var(--navy), var(--navy)) 0 100% / 100% 45% no-repeat;
}
.es-val { position: absolute; left: 9px; top: 7px; font-family: var(--font-display); font-weight: 800; font-size: clamp(.82rem, 3.4vw, 1.05rem); color: var(--navy); line-height: 1; }
.es-ctry { position: absolute; left: 0; right: 0; bottom: 9px; text-align: center; font-style: normal; font-size: .8rem; font-weight: 700; letter-spacing: .04em; color: #fbf6ea; }
.env-jp { right: 10%; top: 38%; writing-mode: vertical-rl; font-size: .86rem; letter-spacing: .3em; color: var(--verm-tx); }
.env-airmail {
  left: 7%; top: 27%;
  display: grid; gap: 1px;
  padding: .35rem .6rem;
  border: 2px solid var(--navy);
  color: var(--navy);
  font-size: .8rem; line-height: 1.15; letter-spacing: .08em;
  background: rgba(255, 255, 255, .4);
}
.env-airmail b { font-size: .92rem; letter-spacing: .1em; }
.env-airmail i { font-style: normal; font-family: var(--font-tc); font-size: .82rem; letter-spacing: .4em; }
.env-priority {
  left: 9%; top: 46%;
  transform: rotate(-8deg);
  border: 2.5px solid var(--verm); color: var(--verm-tx);
  padding: .15rem .5rem; font-weight: 700; font-size: .8rem; letter-spacing: .12em; line-height: 1.25;
  -webkit-mask: var(--ink-mask); mask: var(--ink-mask);
  opacity: .85;
}
.env-to { left: 9%; right: 9%; bottom: 9%; display: grid; gap: .1rem; }
/* 直式信封空間不夠：優先郵件章只在橫式出現 */
.env-priority { display: none; }
.et-label { font-size: .82rem; font-weight: 700; letter-spacing: .24em; color: var(--ink); }
.et-name {
  line-height: 1.15;
  color: var(--navy-ink);
  border-bottom: 1.5px solid rgba(31, 58, 95, .45);
  padding: 0 .1em .05em;
}
.et-addr { font-size: .82rem; letter-spacing: .14em; line-height: 1.5; color: var(--ink); margin-top: .3rem; border-bottom: 1px solid rgba(31, 58, 95, .3); padding-bottom: .2rem; }
@media (min-width: 760px) and (min-aspect-ratio: 1/1) {
  .env-to { left: 40%; right: 7%; bottom: 10%; }
  .env-priority { display: block; top: auto; bottom: 14%; left: 8%; }
  .env-stamp { width: 15%; top: 9%; }
  .env-jp { right: 8%; top: 52%; }
}
/* 郵戳：commit 後才蓋（預設不可見；墨漬 mask 預先掛好＝暖機，蓋下那幀不用等解碼） */
.env-postmark {
  right: 21%; top: 2%;
  width: 40%; aspect-ratio: 1;
  color: var(--navy);
  opacity: 0;
  transform: rotate(-12deg);
  -webkit-mask: var(--ink-mask); mask: var(--ink-mask);
  -webkit-mask-size: 160px; mask-size: 160px;
}
@media (min-width: 760px) and (min-aspect-ratio: 1/1) { .env-postmark { width: 26%; right: 14%; top: 0; } .env-airmail { top: 40%; } }
.pm-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.pm-ring-text { font-family: var(--font-mono); font-weight: 700; font-size: 17px; letter-spacing: 2px; fill: currentColor; }
.pm-center { position: absolute; inset: 22%; display: grid; place-content: center; text-align: center; line-height: 1.05; }
/* 撕開處的紙纖維（從左到右跟著撕的長度長出來） */
.env-fibers {
  left: 0; right: 0; top: -3px; height: 6px;
  background: radial-gradient(circle at 3px 0, #fffaf0 2px, transparent 2.5px) 0 0 / 7px 6px repeat-x;
  clip-path: inset(0 calc((1 - var(--wk-open)) * 100%) 0 0);
}
/* 上緣（撕條以上）：撕開後往後翻 */
.env-top {
  position: absolute; left: 0; right: 0; top: 0; height: var(--st);
  transform-origin: 50% 100%;
  transform-style: preserve-3d;
  transform: rotateX(calc(var(--wk-open) * 22deg));
  z-index: 3;
}
.et-face { position: absolute; inset: 0; -webkit-backface-visibility: hidden; backface-visibility: hidden; transform: translateZ(.1px); border-radius: 3px 3px 0 0; }
.et-front { background: var(--airmail); background-size: 45px 45px; padding: 9px 9px 0; }
.et-front::before { content: ""; position: absolute; inset: 9px 9px 0; background: linear-gradient(180deg, #faf4e4, #f6eedb); }
.et-back { transform: rotateX(180deg) translateZ(.1px); background: linear-gradient(0deg, #b8935c, #9f7a44); }
.env-from { position: absolute; left: 7%; top: 22%; display: grid; line-height: 1.25; z-index: 1; }
.env-from small { font-size: .8rem; font-weight: 700; letter-spacing: .24em; color: var(--verm-tx); }
.env-from b { font-family: var(--font-hw); font-weight: 400; font-size: 1.15rem; color: var(--navy-ink); }
.env-from span { font-size: .8rem; letter-spacing: .06em; color: var(--ink);
  /* 寄件地址是日文（目黒区）：日文明體排在繁中之前，免得為了兩個日文字形去抓 Noto Serif TC 的切片 */
  font-family: "Courier Prime", "Courier New", "Noto Serif JP", "Hiragino Mincho ProN", "Yu Mincho", var(--tc-face), monospace; }
.env-flight { position: absolute; right: 7%; bottom: 14%; z-index: 1; font-weight: 700; font-size: .82rem; letter-spacing: .2em; color: var(--navy); }
/* 撕條 */
.env-strip { position: absolute; left: 0; right: 0; top: var(--st); height: var(--sh); z-index: 4; }
.strip-band {
  position: absolute; inset: 0;
  background:
    radial-gradient(circle at 4px 0, #8f2a19 1.6px, transparent 2px) 0 0 / 9px 100% repeat-x,
    radial-gradient(circle at 4px 100%, #8f2a19 1.6px, transparent 2px) 0 0 / 9px 100% repeat-x,
    linear-gradient(180deg, #d24a33, #b8371f);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25);
  clip-path: inset(0 0 0 calc(var(--wk-open) * 100%));
  overflow: hidden;
  display: flex; align-items: center;
}
.strip-band span { white-space: nowrap; padding-left: 3.2rem; font-weight: 700; font-size: .8rem; letter-spacing: .18em; color: #fff4e6; }
.strip-tab {
  position: absolute; left: -10px; top: -25%; bottom: -25%; width: 2.6rem;
  display: grid; place-items: center;
  background: #a8321d; color: #fff4e6;
  border-radius: 4px 10px 10px 4px;
  font-weight: 700; font-size: .8rem; letter-spacing: .06em;
  box-shadow: 0 3px 6px rgba(0, 0, 0, .3);
  transform: translateX(calc(var(--wk-open) * 100% * 0));
  opacity: calc(1 - var(--wk-open) * 7);
}
/* 捲起的那一截：跟著撕的進度往右走、翻起來 */
.strip-curl {
  position: absolute; z-index: 5;
  top: calc(var(--st) - 1%); height: calc(var(--sh) + 2%);
  left: calc(var(--wk-open) * 100% - min(var(--wk-open) * 100%, 92px));
  width: min(calc(var(--wk-open) * 100%), 92px);
  background:
    radial-gradient(circle at 4px 0, rgba(143, 42, 25, .6) 1.4px, transparent 1.8px) 0 0 / 9px 100% repeat-x,
    radial-gradient(circle at 4px 100%, rgba(143, 42, 25, .6) 1.4px, transparent 1.8px) 0 0 / 9px 100% repeat-x,
    linear-gradient(90deg, #a33019 0, #e28a72 9px, #f2ad98 40%, #e8957e 100%);
  border-radius: 9px 2px 2px 9px / 50% 2px 2px 50%;
  transform-origin: 100% 60%;
  transform: rotate(calc(-6deg - var(--wk-open) * 22deg)) translateY(calc(var(--wk-open) * -10px));
  box-shadow: 0 10px 14px -4px rgba(0, 0, 0, .35);
  opacity: min(1, calc(var(--wk-open) * 12));
  pointer-events: none;
}
/* 提示 */
.intro-guide {
  position: absolute; left: 50%; bottom: max(7vh, calc(env(safe-area-inset-bottom, 0px) + 2.4rem));
  transform: translateX(-50%);
  display: grid; justify-items: center; gap: .15rem;
  color: #f7f0de;
  font-family: var(--font-tc); font-size: 1.15rem; letter-spacing: .12em;
  white-space: nowrap;
  padding: .5rem 1rem;
  opacity: 0;
  pointer-events: none;
  z-index: 3;
}
.intro-guide small { font-family: var(--font-mono); font-size: .84rem; letter-spacing: .16em; color: #d9cfb8; }
.ig-arrow { display: block; width: 4.6rem; height: 12px; position: relative; margin-bottom: .3rem; }
.ig-arrow::before { content: ""; position: absolute; left: 0; right: 10px; top: 5px; height: 2px; background: #f7f0de; }
.ig-arrow::after { content: ""; position: absolute; right: 1px; top: 1px; width: 9px; height: 9px; border-top: 2px solid #f7f0de; border-right: 2px solid #f7f0de; transform: rotate(45deg); }
.intro-wait .ig-arrow { animation: vy-nudge 1.5s ease-in-out infinite; }
@keyframes vy-nudge { 0%, 100% { transform: translateX(-6px); } 50% { transform: translateX(8px); } }
.intro-wait .intro-guide { animation: vy-fadein .8s .5s ease forwards; }
@keyframes vy-fadein { to { opacity: 1; } }
.intro-wait .strip-tab { animation: vy-tab 2.2s 1.2s ease-in-out infinite; }
@keyframes vy-tab { 0%, 70%, 100% { translate: 0 0; } 80% { translate: 5px 0; } 90% { translate: -1px 0; } }
.intro-skip {
  position: absolute; z-index: 3;
  right: max(.8rem, env(safe-area-inset-right, 0px)); top: max(.8rem, env(safe-area-inset-top, 0px));
  color: #e3d9c3; font-family: var(--font-mono); font-size: .82rem; letter-spacing: .24em;
  padding: .8rem 1.1rem; min-height: 44px;
  border: 1px solid rgba(239, 227, 200, .35); border-radius: 3px;
}
/* 手指鬆開沒過閾值：撕條彈回（拖曳時跟手不加 transition） */
.strip-band, .env-top, .strip-curl, .env-fibers { transition: clip-path .45s var(--ease-snap), transform .45s var(--ease-snap), left .45s var(--ease-snap), width .45s var(--ease-snap), opacity .3s; }
.intro.is-dragging .strip-band, .intro.is-dragging .env-top, .intro.is-dragging .strip-curl, .intro.is-dragging .env-fibers { transition: none; }

/* commit：撕到底 → 上緣翻起、信紙探頭 → 郵戳蓋下＋註銷波浪線 → 信封飛走、桌面淡出（收場只認 vy-desk-out） */
.intro-commit .strip-band { animation: vy-tear .2s var(--ease-in) forwards; transition: none; }
@keyframes vy-tear { from { clip-path: inset(0 0 0 calc(var(--wk-from, 0) * 100%)); } to { clip-path: inset(0 0 0 100%); } }
.intro-commit .strip-curl { animation: vy-curl .5s ease-in forwards; transition: none; }
@keyframes vy-curl {
  0% { left: calc(var(--wk-from, 0) * 100% - 92px); width: 92px; opacity: 1; transform: rotate(calc(-6deg - var(--wk-from, 0) * 22deg)) translateY(-10px); }
  40% { left: calc(100% - 92px); width: 92px; opacity: 1; transform: rotate(-30deg) translateY(-18px); }
  100% { left: calc(100% + 20px); width: 92px; opacity: 0; transform: rotate(-70deg) translate(40px, -40px); }
}
.intro-commit .strip-tab { opacity: 0; transition: none; }
.intro-commit .env-fibers { clip-path: inset(0 0 0 0); transition: clip-path .2s; }
.intro-commit .env-top { animation: vy-lid .55s .12s cubic-bezier(.3, .7, .25, 1) both; transition: none; }
@keyframes vy-lid { from { transform: rotateX(calc(var(--wk-from, 0) * 22deg)); } to { transform: rotateX(118deg); } }
.intro-commit .env-letter { animation: vy-letter .55s .26s var(--ease-out) both; }
@keyframes vy-letter { from { transform: translateY(0); } to { transform: translateY(-30%); } }
.intro-commit .env-postmark { animation: vy-stamp .36s .38s cubic-bezier(.3, 1.4, .5, 1) both; }
@keyframes vy-stamp {
  0% { opacity: 0; transform: rotate(-20deg) scale(1.6); }
  55% { opacity: 1; transform: rotate(-12deg) scale(.94); }
  100% { opacity: .92; transform: rotate(-12deg) scale(1); }
}
@keyframes vy-draw { to { stroke-dashoffset: 0; } }
.intro-commit .env { animation: vy-thud .28s .4s ease-out; }
@keyframes vy-thud { 0%, 100% { translate: 0 0; } 40% { translate: 0 4px; } }
.intro-commit .env-wrap { animation: vy-env-out .44s .76s var(--ease-in) forwards; }
@keyframes vy-env-out { to { transform: translateY(-115vh) rotate(-7deg) scale(.88); } }
.intro-commit .intro-desk { animation: vy-desk-out .3s .8s ease forwards; }
@keyframes vy-desk-out { to { opacity: 0; } }
.intro-commit .intro-guide, .intro-commit .intro-skip { animation: vy-fadeout .25s ease forwards; }
@keyframes vy-fadeout { to { opacity: 0; } }
.intro-play .strip-tab { animation: vy-tab .9s ease-in-out; }

/* ============================================================
   ① 海報：巨型郵票
   ============================================================ */
.hero {
  position: relative;
  min-height: 100svh;
  padding: max(16px, env(safe-area-inset-top, 0px)) 12px 40px;
  background:
    radial-gradient(80% 60% at 50% 30%, #eadbb9, #dcc79c 100%);
  display: grid;
  align-content: start;
}
.hs-shadow { position: relative; }
.hs-shadow::before {
  content: ""; position: absolute; inset: 14px 14px 6px;
  box-shadow: 0 26px 50px -12px rgba(43, 38, 34, .45), 0 4px 10px rgba(43, 38, 34, .18);
}
.hs-perf { --r: 7px; --s: 22px; position: relative; }
.hs {
  position: relative;
  min-height: calc(100svh - 56px);
  padding: 26px 22px 24px;
  background:
    radial-gradient(90% 60% at 20% 10%, rgba(255, 255, 255, .55), transparent 60%),
    radial-gradient(70% 50% at 90% 95%, rgba(200, 160, 100, .18), transparent 70%),
    var(--cream-hi);
  display: grid;
  grid-template-rows: auto auto 1fr auto auto;
  overflow: hidden;
  isolation: isolate;
}
/* 郵票內框線 */
.hs::before { content: ""; position: absolute; inset: 14px; border: 1.5px solid var(--navy); pointer-events: none; z-index: 6; }
.hs-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; position: relative; z-index: 5; }
.hs-label { display: grid; gap: .1rem; font-family: var(--font-mono); font-weight: 700; font-size: .82rem; letter-spacing: .2em; line-height: 1.3; color: var(--verm-tx); padding-top: .1rem; }
.hs-label span:last-child { font-family: var(--font-tc); font-weight: 400; letter-spacing: .3em; color: var(--ink); }
.hs-value {
  display: grid; justify-items: end; line-height: 1;
  background: var(--verm-tx); color: var(--cream-hi);
  padding: .45rem .6rem .5rem;
  margin: -12px -8px 0 0;
}
.hs-value small { font-family: var(--font-mono); font-size: .8rem; font-weight: 700; letter-spacing: .2em; }
.hs-value b { font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 48, "wght" 800; font-size: clamp(1.15rem, 5.4vw, 1.9rem); letter-spacing: -.01em; margin-top: .2rem; }
.hs-word {
  position: relative; z-index: 5;
  font-family: var(--font-display);
  font-weight: 800; font-variation-settings: "opsz" 144, "wght" 800;
  font-size: calc(min(30vw, 15rem) * var(--names-fit, 1));
  line-height: .76;
  letter-spacing: -.04em;
  color: var(--navy);
  white-space: nowrap;
  overflow: hidden;
  padding-top: .06em;
}
.hs-word span { display: inline-block; }
.hs-word-a { margin-top: .5rem; color: var(--verm); }
.hs-word-b { display: flex; align-items: center; gap: .1em; }
/* ✕：兩條 CSS 斜線，不靠字型 */
.hs-x { position: relative; width: .42em; height: .42em; flex: none; margin-right: .06em; }
.hs-x::before, .hs-x::after { content: ""; position: absolute; left: 50%; top: 50%; width: 118%; height: .085em; background: var(--verm); transform: translate(-50%, -50%) rotate(45deg); border-radius: 2px; }
.hs-x::after { transform: translate(-50%, -50%) rotate(-45deg); }

.hs-art { position: relative; min-height: clamp(300px, 41svh, 500px); margin: .5rem -6px .3rem; }
.hs-art > * { position: absolute; }
.hs-sun { left: 8%; top: 4%; width: 52%; aspect-ratio: 1; border-radius: 50%; background: var(--verm); z-index: 1; translate: calc(var(--px, 0px) * .3) calc(var(--py, 0px) * .3); }
.ly { pointer-events: none; height: auto; -webkit-user-select: none; user-select: none; }
.ly-taipei { left: -8%; bottom: -2%; width: 44%; z-index: 2; translate: calc(var(--px, 0px) * .55) calc(var(--py, 0px) * .55); }
.ly-tokyo { right: -10%; bottom: 2%; width: 40%; z-index: 2; translate: calc(var(--px, 0px) * .7) calc(var(--py, 0px) * .7); }
.hs-photo {
  right: 6%; top: 7%;
  width: 56%; aspect-ratio: 3 / 4;
  z-index: 3;
  background: #fffdf6;
  padding: 7px 7px 26px;
  box-shadow: 0 14px 26px -10px rgba(43, 38, 34, .5), 0 0 0 1px rgba(43, 38, 34, .12);
  transform: rotate(2deg);
}
.hs-photo::after { content: "TPE · HND"; position: absolute; left: 9px; bottom: 6px; font-family: var(--font-mono); font-size: .8rem; font-weight: 700; letter-spacing: .14em; color: var(--ink-soft); }
.hero-photo { width: 100%; height: 100%; object-fit: cover; object-position: 50% 30%; background: var(--cream-lo); display: block; }
.ly-sakura { left: 26%; top: -9%; width: 60%; z-index: 4; translate: calc(var(--px, 0px) * 1) calc(var(--py, 0px) * 1); }
.hero-names {
  left: 2%; top: 12%;
  z-index: 5;
  writing-mode: vertical-rl;
  font-family: var(--font-tc); font-weight: 400;
  font-size: clamp(1.45rem, 6.6vw, 2.4rem);
  line-height: 1.1; letter-spacing: .18em;
  color: var(--ink);
  background: var(--cream-hi);
  border: 1.5px solid var(--ink);
  padding: .55em .32em;
  box-shadow: 3px 3px 0 rgba(43, 38, 34, .85);
  display: flex; align-items: center; gap: .3em;
  white-space: nowrap;
}
.hero-names .amp { font-size: .55em; color: var(--verm-tx); letter-spacing: 0; }
.hs-jp { right: 1%; bottom: 8%; z-index: 5; writing-mode: vertical-rl; font-size: .86rem; letter-spacing: .32em; color: var(--verm-tx); background: rgba(247, 240, 222, .85); padding: .4em .15em; }
.ly-wave { left: -6%; width: 112%; bottom: -4%; z-index: 1; opacity: .95; translate: calc(var(--px, 0px) * .4) 0; }

.hs-foot { position: relative; z-index: 5; display: grid; gap: .35rem; margin-top: .6rem; }
.hero-greeting {
  text-wrap: balance;
  font-family: var(--font-tc);
  font-size: clamp(1.15rem, 4.8vw, 1.5rem);
  line-height: 1.5; letter-spacing: .06em;
  color: var(--ink);
  background: var(--cream-hi);
  justify-self: start;
  padding: 0 .2em;
}
.hero-names-en { font-family: var(--font-mono); font-weight: 700; font-size: .82rem; letter-spacing: .16em; text-transform: uppercase; color: var(--navy); }
.hero-names-en:empty { display: none; }
.hs-meta { display: grid; gap: .3rem; border-top: 1.5px solid var(--navy); padding-top: .6rem; }
.hero-date { display: flex; flex-wrap: wrap; align-items: baseline; gap: .1em .7em; font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 36, "wght" 700; font-size: clamp(1.2rem, 5vw, 1.6rem); color: var(--navy); letter-spacing: .01em; }
.hero-day { font-family: var(--font-tc); font-weight: 400; font-size: .72em; color: var(--ink); letter-spacing: .1em; }
.hero-note { font-family: var(--font-tc); font-weight: 400; font-size: .7em; color: var(--ink-soft); }
.hero-note:empty, .hero-day:empty { display: none; }
.hs-coord { font-family: var(--font-mono); font-size: .84rem; letter-spacing: .14em; color: var(--ink); }
.countdown {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .1em .6em;
  font-family: var(--font-mono); font-size: .95rem; letter-spacing: .06em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.cd-l { font-family: var(--font-tc); font-size: .95rem; letter-spacing: .14em; color: var(--verm-tx); }
.cd-d { font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 48, "wght" 800; font-size: 1.6rem; color: var(--verm-tx); line-height: 1; }
.cd-d i { font-style: normal; }
.cd-d strong { font-weight: 800; }
.cd-hms strong { font-weight: 700; display: inline-block; min-width: 2ch; text-align: center; }
.cd-hms i { font-style: normal; color: var(--ink-soft); }
.countdown.is-past .cd-l::after { content: "・已寄達"; }
.hero-scroll {
  justify-self: center;
  margin-top: 1.2rem;
  display: grid; justify-items: center; gap: .4rem;
  font-family: var(--font-tc); font-size: .9rem; letter-spacing: .2em; color: var(--ink);
}
.hero-scroll i { width: 1.5px; height: 2.4rem; background: var(--ink); transform-origin: top; animation: vy-scrollline 1.8s ease-in-out infinite; }
@keyframes vy-scrollline { 0% { transform: scaleY(0); } 50% { transform: scaleY(1); } 100% { transform: scaleY(0); transform-origin: bottom; } }

@media (min-width: 900px) {
  .hero { padding: 26px 26px 40px; }
  .hs {
    min-height: calc(100svh - 68px);
    padding: 34px 40px 32px;
    grid-template-columns: 1.18fr 1fr;
    grid-template-rows: auto auto auto 1fr auto;
    column-gap: 2.5rem;
  }
  .hs-top { grid-column: 1 / -1; }
  .hs-word { grid-column: 1; font-size: calc(min(17vw, 16rem) * var(--names-fit, 1)); }
  .hs-word-a { grid-row: 2; margin-top: 1.4rem; }
  .hs-word-b { grid-row: 3; }
  .hs-art { grid-column: 2; grid-row: 2 / 6; margin: .4rem 0 0; min-height: 0; }
  .hs-foot { grid-column: 1; grid-row: 5; align-self: end; }
  .ly-wave { bottom: 0; left: -10%; width: 120%; }
  .hs-photo { width: 58%; right: 16%; top: 6%; }
  .hero-names { left: auto; right: 0; top: 10%; font-size: clamp(1.8rem, 2.6vw, 2.6rem); }
  .hs-sun { left: 2%; top: 3%; width: 54%; }
  .ly-sakura { left: 10%; top: -5%; width: 62%; }
  .ly-taipei { left: -6%; bottom: 0; width: 38%; }
  .ly-tokyo { right: 12%; bottom: 0; width: 30%; }
  .hs-jp { right: 0; bottom: 4%; }
}

/* 海報進場（開場收掉才開演；沒開場＝直接完成態） */
html.wc .hs-shadow { opacity: 0; transform: translateY(26px) scale(1.03); }
html.wc .hero.is-on .hs-shadow { animation: vy-rise .9s var(--ease-out) forwards; }
html.wc .hs-word span { transform: translateY(105%); }
html.wc .hero.is-on .hs-word span { animation: vy-up .9s .25s var(--ease-out) forwards; }
html.wc .hero.is-on .hs-word-b span { animation-delay: .4s; }
html.wc .hs-x { transform: scale(0) rotate(-90deg); }
html.wc .hero.is-on .hs-x { animation: vy-pop .6s .65s var(--ease-snap) forwards; }
html.wc .hs-sun { transform: scale(.2); opacity: 0; }
html.wc .hero.is-on .hs-sun { animation: vy-sun 1s .35s var(--ease-snap) forwards; }
html.wc .hs-photo { opacity: 0; transform: rotate(9deg) translateY(30px); }
html.wc .hero.is-on .hs-photo { animation: vy-photo .9s .5s var(--ease-out) forwards; }
html.wc .ly { opacity: 0; }
html.wc .hero.is-on .ly { animation: vy-ly 1.1s .7s var(--ease-out) forwards; }
html.wc .hero.is-on .ly-sakura { animation-delay: .95s; }
html.wc .hero.is-on .ly-wave { animation-delay: .55s; }
html.wc .hero-names, html.wc .hs-jp, html.wc .hs-foot > *, html.wc .hs-top { opacity: 0; transform: translateY(10px); }
html.wc .hero.is-on .hero-names { animation: vy-rise-s .7s .85s var(--ease-out) forwards; }
html.wc .hero.is-on .hs-jp { animation: vy-rise-s .7s 1.15s var(--ease-out) forwards; }
html.wc .hero.is-on .hs-top { animation: vy-rise-s .6s .2s var(--ease-out) forwards; }
html.wc .hero.is-on .hs-foot > * { animation: vy-rise-s .7s 1s var(--ease-out) forwards; }
html.wc .hero.is-on .hs-foot > :nth-child(2) { animation-delay: 1.1s; }
html.wc .hero.is-on .hs-foot > :nth-child(3) { animation-delay: 1.2s; }
@keyframes vy-rise { to { opacity: 1; transform: none; } }
@keyframes vy-rise-s { to { opacity: 1; transform: none; } }
@keyframes vy-up { to { transform: translateY(0); } }
@keyframes vy-pop { to { transform: none; } }
@keyframes vy-sun { to { transform: none; opacity: 1; } }
@keyframes vy-photo { to { opacity: 1; transform: rotate(2deg); } }
@keyframes vy-ly { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
html.wc .hero.is-on .ly-wave { animation-name: vy-ly-w; }
@keyframes vy-ly-w { from { opacity: 0; transform: translateY(16px); } to { opacity: .9; transform: none; } }

/* ============================================================
   ② 航線
   ============================================================ */
.story { padding-block: clamp(4.5rem, 13vw, 8rem) clamp(4rem, 10vw, 7rem); }
.route { position: relative; padding: 4.2rem 0 4.8rem; }
.route-svg { position: absolute; left: 0; top: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; z-index: 0; }
.route-ghost { fill: none; stroke: var(--navy); stroke-opacity: .28; stroke-width: 2; stroke-dasharray: 1.5 9; stroke-linecap: round; }
/* 飛過的段落＝一條朱紅航跡（dashoffset 畫出；不用 mask，scrub 時每幀重算 mask 太貴） */
.route-line { fill: none; stroke: var(--verm); stroke-width: 2.6; stroke-linecap: round; stroke-dasharray: 1 1; stroke-dashoffset: var(--route-off, 0); }
.route-end { position: absolute; z-index: 2; display: grid; line-height: 1; }
.route-end b { font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 72, "wght" 800; font-size: 2.1rem; color: var(--navy); letter-spacing: -.01em; }
.route-end span { font-family: var(--font-tc); font-size: .95rem; letter-spacing: .3em; color: var(--ink); margin-top: .2rem; }
.route-from { left: 4%; top: 0; }
.route-to { right: 4%; bottom: 0; text-align: right; }
.route-end::before { content: ""; position: absolute; width: 12px; height: 12px; border-radius: 50%; background: var(--verm); box-shadow: 0 0 0 4px var(--cream), 0 0 0 5.5px var(--verm); }
.route-from::before { left: calc(100% + 12px); top: .75rem; }
.route-to::before { right: calc(100% + 12px); top: .75rem; }
.route-list { position: relative; z-index: 1; display: grid; gap: clamp(4.2rem, 15vw, 6rem); padding-top: 1.2rem; }
.stop { position: relative; width: min(84%, 30rem); }
.stop:nth-child(odd) { justify-self: start; --rot: -2.2deg; }
.stop:nth-child(even) { justify-self: end; --rot: 2deg; }
/* 明信片：button，3D 翻面。旋轉的 .pc-inner 本體不掛 opacity／filter／clip-path／overflow */
.pc {
  position: relative; display: block; width: 100%;
  aspect-ratio: 3 / 2;
  perspective: 1200px;
  transform: rotate(var(--rot, 0deg));
  transition: transform .7s var(--ease-out);
  -webkit-tap-highlight-color: transparent;
}
.pc-inner { position: absolute; inset: 0; -webkit-transform-style: preserve-3d; transform-style: preserve-3d; transition: transform .8s cubic-bezier(.3, .7, .25, 1); }
.pc.is-flipped .pc-inner { transform: rotateY(180deg); }
.pc-face {
  position: absolute; inset: 0;
  -webkit-backface-visibility: hidden; backface-visibility: hidden;
  transform: translateZ(.1px);
  background: #fbf6ea;
  box-shadow: 0 16px 30px -14px rgba(43, 38, 34, .55), 0 0 0 1px rgba(43, 38, 34, .14);
  overflow: hidden;
  text-align: left;
}
.pc-front { padding: 8px; }
.pc-front img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pc-front::after { content: ""; position: absolute; inset: 8px; background: linear-gradient(180deg, transparent 50%, rgba(15, 32, 56, .55)); pointer-events: none; }
.pc-place {
  position: absolute; left: 18px; bottom: 10px; z-index: 2;
  font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 144, "wght" 800;
  font-size: clamp(2.2rem, 11vw, 3.6rem); line-height: .9; letter-spacing: -.03em;
  color: #fff7e8;
  text-shadow: 3px 3px 0 var(--verm);
}
.pc-greet { position: absolute; left: 20px; top: 16px; z-index: 2; font-family: var(--font-mono); font-weight: 700; font-size: .8rem; letter-spacing: .2em; color: #fff7e8; background: rgba(15, 32, 56, .62); padding: .15rem .45rem; }
.pc-flipme {
  position: absolute; right: 16px; bottom: 16px; z-index: 2;
  display: grid; place-items: center;
  width: 2.9rem; height: 2.9rem; border-radius: 50%;
  background: var(--cream-hi); color: var(--navy);
  font-family: var(--font-tc); font-size: .8rem; font-weight: 400; letter-spacing: .05em; line-height: 1.1;
  box-shadow: 0 3px 8px rgba(0, 0, 0, .3);
}
.pc-back { transform: rotateY(180deg) translateZ(.1px); display: grid; grid-template-columns: 1.15fr 1fr; padding: 14px 14px 12px; gap: 12px; background: #fbf6ea; }
.pc-back::before { content: ""; position: absolute; left: 53.5%; top: 14%; bottom: 10%; width: 1px; background: rgba(43, 38, 34, .3); }
.pcb-hw { font-family: var(--font-hw); font-size: clamp(1rem, 4.2vw, 1.25rem); line-height: 1.5; color: var(--navy-ink); align-self: center; }
.pcb-right { position: relative; display: grid; align-content: end; gap: .5rem; padding-left: 8px; }
.pcb-stamp { position: absolute; right: 0; top: 0; width: 34%; aspect-ratio: 4 / 5; background: var(--verm); outline: 2px dashed var(--cream-hi); outline-offset: -5px; }
.pcb-stamp::after { content: ""; position: absolute; left: 50%; top: 42%; width: 46%; aspect-ratio: 1; border-radius: 50%; background: var(--cream-hi); transform: translate(-50%, -50%); }
.pcb-pm { position: absolute; right: 14%; top: 4%; width: 54%; aspect-ratio: 1; border: 2px solid var(--navy); border-radius: 50%; display: grid; place-content: center; text-align: center; transform: rotate(-14deg); color: var(--navy); -webkit-mask: var(--ink-mask); mask: var(--ink-mask); }
.pcb-pm b { font-family: var(--font-mono); font-weight: 700; font-size: .8rem; letter-spacing: .04em; line-height: 1.15; }
.pcb-pm i { font-style: normal; font-family: var(--font-mono); font-size: .8rem; }
.pcb-to { font-family: var(--font-mono); font-size: .8rem; line-height: 1.6; color: var(--ink); border-bottom: 1px solid rgba(43, 38, 34, .35); }
.pcb-to b { font-family: var(--font-hw); font-weight: 400; font-size: 1rem; }
.stop-txt { position: relative; z-index: 2; margin-top: .9rem; padding: .3rem .4rem .5rem .3rem; background: var(--cream); box-shadow: 0 0 0 6px var(--cream); }
.stop-date { font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 72, "wght" 800; font-size: 1.7rem; color: var(--verm-tx); line-height: 1; letter-spacing: -.01em; }
.stop-title { font-family: var(--font-tc); font-weight: 400; font-size: 1.35rem; letter-spacing: .08em; line-height: 1.4; margin-top: .35rem; color: var(--ink); }
.stop-text { font-size: 1rem; line-height: 1.9; color: var(--ink); margin-top: .3rem; white-space: pre-line; max-width: 26em; }
/* 到站時蓋在明信片角落的小郵戳 */
.pc-wrap { position: relative; }
.stop-pm { position: absolute; right: -14px; top: -20px; z-index: 3; width: 4.6rem; aspect-ratio: 1; border-radius: 50%; border: 2.5px solid var(--verm); color: var(--verm-tx); background: rgba(247, 240, 222, .7); display: grid; place-content: center; text-align: center; font-family: var(--font-mono); font-weight: 700; font-size: .8rem; line-height: 1.1; transform: rotate(-16deg); -webkit-mask: var(--ink-mask); mask: var(--ink-mask); pointer-events: none; }
.stop:nth-child(even) .stop-pm { transform: rotate(12deg); }
/* fx：飛機還沒到的站＝明信片淡著、郵戳還沒蓋 */
/* 淡化用蓋在上面的紙色遮片，不對 .pc 下 opacity：WebKit 會把祖先的 opacity 當成壓平 3D，背面整片翻到正面（2026-10-02 WebKit 實測） */
.pc-wrap::after { content: ""; position: absolute; inset: -4px; background: var(--cream); opacity: 0; pointer-events: none; transition: opacity .6s ease; z-index: 2; }
html.fx .stop:not(.is-arrived) .pc-wrap::after { opacity: .6; }
html.fx .stop:not(.is-arrived) .pc { transform: rotate(calc(var(--rot, 0deg) * 2.2)) translateY(22px) scale(.96); }
html.fx .stop:not(.is-arrived) .stop-pm { opacity: 0; transform: rotate(-16deg) scale(1.7); }
html.fx .stop.is-arrived .stop-pm { animation: vy-pm-in .45s .2s cubic-bezier(.3, 1.4, .5, 1) both; }
@keyframes vy-pm-in { from { opacity: 0; transform: rotate(-30deg) scale(1.7); } }
.plane {
  position: absolute; left: 0; top: 0; z-index: 4;
  width: clamp(104px, 30vw, 160px); aspect-ratio: 2 / 1;
  transform: translate3d(var(--x, -200px), var(--y, -200px), 0) translate(-50%, -50%) rotate(var(--a, 0deg)) scale(var(--fx, 1), var(--fy, 1));
  will-change: transform;
  pointer-events: none;
  filter: drop-shadow(0 0 2.5px #fbf6ea);
}
.plane img { width: 100%; height: 100%; object-fit: contain; display: block; }
.plane.is-noimg { background: var(--navy); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 60'%3E%3Cpath d='M118 30c0-3-6-5-14-5H78L52 4h-9l13 21H30l-9-10h-7l5 15-5 15h7l9-10h26L43 56h9l26-21h26c8 0 14-2 14-5z'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 60'%3E%3Cpath d='M118 30c0-3-6-5-14-5H78L52 4h-9l13 21H30l-9-10h-7l5 15-5 15h7l9-10h26L43 56h9l26-21h26c8 0 14-2 14-5z'/%3E%3C/svg%3E") center / contain no-repeat; }
.plane.is-noimg img { display: none; }
@media (min-width: 960px) {
  .route { padding: 6.5rem 0 5.5rem; }
  .route-list { grid-template-columns: repeat(4, 1fr); gap: 2.4rem; align-items: start; }
  .stop { width: 100%; }
  .stop:nth-child(even) { margin-top: 7rem; }
  .route-from { left: 0; top: 0; }
  .route-to { right: 0; bottom: 0; }
  .pc-place { font-size: clamp(1.8rem, 2.6vw, 2.6rem); }
  .pcb-hw { font-size: clamp(.95rem, 1.2vw, 1.1rem); }
}

/* ============================================================
   ③ 集郵冊
   ============================================================ */
.gallery {
  padding-block: clamp(4.5rem, 12vw, 7.5rem);
  background:
    repeating-linear-gradient(0deg, rgba(255, 255, 255, .025) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(90deg, rgba(0, 0, 0, .06) 0 1px, transparent 1px 4px),
    radial-gradient(120% 80% at 50% 0%, #22406a, #142a47 70%);
  color: var(--cream-hi);
}
.gallery::before, .gallery::after { content: ""; position: absolute; left: 0; right: 0; height: 12px; background: var(--airmail); background-size: 45px 100%; }
.gallery::before { top: 0; }
.gallery::after { bottom: 0; }
.sh-inv .sh-word { color: var(--cream); opacity: .95; }
.sh-inv .sh-no { color: #f19a7f; }
.gal-hint { display: flex; align-items: center; gap: .6rem; font-size: 1rem; letter-spacing: .06em; color: #e9dfc8; margin: -.4rem 0 1.8rem; }
.gh-loupe { flex: none; position: relative; width: 22px; height: 22px; border: 2.5px solid #f19a7f; border-radius: 50%; }
.gh-loupe::after { content: ""; position: absolute; right: -8px; bottom: -6px; width: 9px; height: 3px; background: #f19a7f; transform: rotate(45deg); border-radius: 2px; }
.gh-fine { display: none; }
@media (hover: hover) and (pointer: fine) { .gh-fine { display: inline; } .gh-touch { display: none; } }
.album {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-auto-flow: dense;
  gap: 2rem 1.1rem;
  align-items: center;
}
.st { position: relative; margin: 0; transform: rotate(var(--rot, 0deg)); }
.st:nth-child(7n+2), .st:nth-child(7n+5), .st:nth-child(7n) { grid-column: span 2; }
.st:nth-child(3n+1) { --rot: -1.4deg; }
.st:nth-child(3n+2) { --rot: 1deg; }
.st:nth-child(3n) { --rot: -.4deg; }
.st-shadow { position: relative; }
.st-shadow::before { content: ""; position: absolute; inset: 6px; box-shadow: 0 14px 22px -8px rgba(0, 0, 0, .55); }
.st .perf { --r: 4px; --s: 13px; }
.st-face {
  position: relative;
  background: #fbf6ea;
  padding: 11px 11px 0;
  color: var(--ink);
}
.st-pic { position: relative; aspect-ratio: 1; overflow: hidden; background: var(--cream-lo); }
.st:nth-child(7n+2) .st-pic, .st:nth-child(7n+5) .st-pic, .st:nth-child(7n) .st-pic { aspect-ratio: 4 / 3; }
.st-pic img { width: 100%; height: 100%; object-fit: cover; display: block; cursor: zoom-in; -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; -webkit-user-drag: none; }
.st-val { position: absolute; left: 0; top: 0; z-index: 1; background: rgba(15, 32, 56, .62); padding: .2rem .5rem .25rem; font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 48, "wght" 800; font-size: 1.2rem; color: #fffaf0; text-shadow: 0 1px 3px rgba(0, 0, 0, .55), 0 0 1px rgba(0, 0, 0, .8); pointer-events: none; }
.st-cap { display: grid; gap: .05rem; padding: .45rem 0 .55rem; font-family: var(--font-mono); font-size: .8rem; font-weight: 700; letter-spacing: .08em; line-height: 1.3; color: var(--ink); }
.st-cap span:last-child { font-family: var(--font-tc); font-weight: 400; font-size: .92rem; letter-spacing: .06em; }
/* 集郵冊的透明護膜條（玻璃紙）：蓋在郵票下半部 */
.st::after {
  content: ""; position: absolute; left: -7%; right: -7%; bottom: -5%; height: 40%;
  background: linear-gradient(180deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, .05) 30%, rgba(255, 255, 255, .07));
  border-top: 1px solid rgba(255, 255, 255, .32);
  pointer-events: none;
  z-index: 2;
}
@media (min-width: 900px) {
  .album { grid-template-columns: repeat(12, 1fr); gap: 3rem 2rem; }
  .st { grid-column: span 3; }
  .st:nth-child(7n+1) { grid-column: span 4; margin-top: 3rem; }
  .st:nth-child(7n+2) { grid-column: span 5; }
  .st:nth-child(7n+3) { grid-column: span 3; margin-top: 5rem; }
  .st:nth-child(7n+4) { grid-column: span 3; margin-top: -2rem; }
  .st:nth-child(7n+5) { grid-column: span 5; margin-top: 2rem; }
  .st:nth-child(7n+6) { grid-column: span 4; }
  .st:nth-child(7n) { grid-column: 3 / span 7; }
  .st:nth-child(7n+1) .st-pic, .st:nth-child(7n+6) .st-pic { aspect-ratio: 4 / 5; }
}
/* 放大鏡 */
.loupe {
  position: fixed; left: 0; top: 0; z-index: 90;
  width: 168px; height: 168px; border-radius: 50%;
  border: 5px solid #fbf6ea;
  box-shadow: 0 0 0 2px var(--navy), 0 18px 34px rgba(0, 0, 0, .5), inset 0 0 20px rgba(0, 0, 0, .25);
  background-color: #222; background-repeat: no-repeat;
  transform: translate3d(var(--lx, -400px), var(--ly, -400px), 0) translate(-50%, -50%) scale(.55);
  opacity: 0;
  transition: opacity .18s ease, transform .18s var(--ease-out);
  pointer-events: none;
}
.loupe.is-on { opacity: 1; transform: translate3d(var(--lx, -400px), var(--ly, -400px), 0) translate(-50%, -50%) scale(1); }
.loupe.is-moving { transition: opacity .18s ease; }
.loupe i { position: absolute; right: -34px; bottom: -22px; width: 48px; height: 14px; border-radius: 7px; background: linear-gradient(180deg, #2a4a74, var(--navy-ink)); transform: rotate(40deg); box-shadow: 0 3px 6px rgba(0, 0, 0, .4); }

/* ============ ③b 影片 ============ */
.video-frame { position: relative; background: #000; aspect-ratio: 16 / 9; overflow: hidden; border: 12px solid var(--navy); box-shadow: 0 0 0 4px var(--cream-hi), 0 18px 30px -12px rgba(0, 0, 0, .5); }
.video-frame[data-ratio="portrait"] { aspect-ratio: 9 / 16; max-width: 24rem; margin-inline: auto; }
.video-facade { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.video-poster { width: 100%; height: 100%; object-fit: cover; opacity: .88; }
.is-noposter .video-poster { display: none; }
.video-play-ico { position: absolute; left: 50%; top: 50%; width: 76px; height: 76px; border-radius: 50%; background: var(--verm); transform: translate(-50%, -50%); box-shadow: 0 0 0 6px rgba(247, 240, 222, .8); }
.video-play-ico::after { content: ""; position: absolute; left: 31px; top: 24px; border-left: 22px solid var(--cream-hi); border-top: 14px solid transparent; border-bottom: 14px solid transparent; }
.video-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* ============================================================
   ④ 登機證
   ============================================================ */
.details { padding-block: clamp(4.5rem, 12vw, 7.5rem); }
.bp {
  position: relative;
  display: grid;
  background: #fbf6ea;
  border-radius: 18px;
  box-shadow: 0 30px 50px -26px rgba(43, 38, 34, .6), 0 0 0 1px rgba(43, 38, 34, .12);
  font-family: var(--font-mono);
}
.bp-main { padding: 0 0 1.6rem; min-width: 0; }
.bp-head { display: flex; justify-content: space-between; align-items: center; gap: 1rem; background: var(--navy); color: var(--cream-hi); padding: 1rem 1.3rem; border-radius: 18px 18px 0 0; }
.bp-air { display: grid; grid-template-columns: auto 1fr; column-gap: .7rem; align-items: center; line-height: 1.15; }
.bp-air b { font-family: var(--font-tc); font-weight: 400; font-size: 1.15rem; letter-spacing: .14em; }
.bp-air small { grid-column: 2; font-size: .8rem; font-weight: 700; letter-spacing: .2em; color: #d9cfb8; }
.bp-logo { grid-row: span 2; width: 2.4rem; height: 2.4rem; border-radius: 50%; background: var(--verm); position: relative; box-shadow: 0 0 0 2px var(--cream-hi); }
.bp-logo::after { content: ""; position: absolute; inset: 22% 18%; background: var(--cream-hi); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 60'%3E%3Cpath d='M118 30c0-3-6-5-14-5H78L52 4h-9l13 21H30l-9-10h-7l5 15-5 15h7l9-10h26L43 56h9l26-21h26c8 0 14-2 14-5z'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 60'%3E%3Cpath d='M118 30c0-3-6-5-14-5H78L52 4h-9l13 21H30l-9-10h-7l5 15-5 15h7l9-10h26L43 56h9l26-21h26c8 0 14-2 14-5z'/%3E%3C/svg%3E") center / contain no-repeat; }
.bp-kind { text-align: right; font-weight: 700; font-size: .82rem; letter-spacing: .2em; line-height: 1.3; }
.bp-kind span { font-family: var(--font-tc); font-weight: 400; font-size: .95rem; letter-spacing: .3em; }
.bp-route { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: .8rem; padding: 1.4rem 1.3rem .6rem; }
.bpr-end { display: grid; line-height: 1; }
.bpr-end small { font-size: .8rem; font-weight: 700; letter-spacing: .2em; color: var(--ink-soft); }
.bpr-end b { font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 144, "wght" 800; font-size: clamp(2.6rem, 13vw, 4.4rem); letter-spacing: -.03em; color: var(--navy); margin: .2rem 0 .25rem; }
.bpr-end span { font-family: var(--font-tc); font-size: .95rem; letter-spacing: .1em; color: var(--ink); }
.bpr-to { text-align: right; }
.bpr-to b { color: var(--verm); }
.bpr-line { position: relative; height: 2px; background: repeating-linear-gradient(90deg, var(--navy) 0 6px, transparent 6px 11px); }
.bpr-plane { position: absolute; left: 50%; top: 50%; width: 2.4rem; height: 1.2rem; transform: translate(-50%, -50%); background: var(--verm); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 60'%3E%3Cpath d='M118 30c0-3-6-5-14-5H78L52 4h-9l13 21H30l-9-10h-7l5 15-5 15h7l9-10h26L43 56h9l26-21h26c8 0 14-2 14-5z'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 60'%3E%3Cpath d='M118 30c0-3-6-5-14-5H78L52 4h-9l13 21H30l-9-10h-7l5 15-5 15h7l9-10h26L43 56h9l26-21h26c8 0 14-2 14-5z'/%3E%3C/svg%3E") center / contain no-repeat; }
.bp-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); margin: .8rem 1.3rem 0; border-top: 1.5px solid var(--ink); }
.bp-grid > div { padding: .65rem .2rem .6rem; border-bottom: 1px dashed rgba(43, 38, 34, .3); min-width: 0; }
.bp-grid dt { font-size: .8rem; font-weight: 700; letter-spacing: .08em; color: var(--ink-soft); white-space: nowrap; }
.bp-grid dd { font-size: 1.05rem; font-weight: 700; letter-spacing: .04em; color: var(--ink); overflow-wrap: anywhere; line-height: 1.35; }
.bp-grid dd.tc { font-family: var(--font-tc); font-weight: 400; letter-spacing: .08em; }
.bp-grid dd.hw { font-family: var(--font-hw); font-weight: 400; font-size: 1.4rem; color: var(--navy-ink); line-height: 1.1; }
.bp-grid > div.is-hl dd { color: var(--verm-tx); }
.bp-day { display: flex; flex-wrap: wrap; gap: .2rem .9rem; margin: 1rem 1.3rem 0; font-family: var(--font-tc); font-size: 1.05rem; letter-spacing: .08em; }
.details-note { color: var(--ink-soft); }
.details-note:empty { display: none; }
.bp-itin { margin: 1.2rem 1.3rem 0; }
.bp-sub { font-size: .8rem; font-weight: 700; letter-spacing: .2em; color: var(--verm-tx); margin-bottom: .2rem; }
.event-list { display: grid; }
.event-row { display: grid; grid-template-columns: 4.6rem 1fr; gap: .9rem; align-items: baseline; padding: .75rem 0; border-bottom: 1px dashed rgba(43, 38, 34, .3); }
.event-row dt { font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 48, "wght" 700; font-size: 1.45rem; color: var(--navy); letter-spacing: -.01em; }
.event-row dd strong { display: block; font-family: var(--font-tc); font-weight: 400; font-size: 1.15rem; letter-spacing: .1em; color: var(--ink); }
.event-row dd span { display: block; font-family: var(--font-tc); font-size: 1rem; color: var(--ink-soft); margin-top: .1rem; line-height: 1.7; }
.parents { margin: 1.3rem 1.3rem 0; font-family: var(--font-tc); font-size: 1rem; letter-spacing: .08em; line-height: 2; color: var(--ink); }
.parents:empty { display: none; }
/* 郵戳日曆：婚期那格蓋紅章（絕不對 .wk-cal 宣告 display） */
.wk-cal { margin: 1.4rem 1.3rem 0; padding: 1rem; border: 1.5px solid var(--navy); background: rgba(255, 255, 255, .35); }
.wk-cal-title { font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 72, "wght" 800; font-size: 1.9rem; color: var(--navy); margin-bottom: .5rem; letter-spacing: .02em; }
.wk-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; font-size: .9rem; position: relative; }
.wk-cal-wd { text-align: center; font-family: var(--font-tc); font-size: .85rem; color: var(--ink-soft); padding-bottom: .3rem; }
.wk-cal-d, .wk-cal-pad { aspect-ratio: 1; display: grid; place-items: center; font-weight: 700; color: var(--ink); }
.wk-cal-d { border-top: 1px dotted rgba(43, 38, 34, .25); }
.wk-cal-d.is-day { position: relative; color: var(--verm-tx); }
.wk-cal-d.is-day::before { content: ""; position: absolute; inset: -12%; border-radius: 50%; border: 2.5px solid var(--verm); box-shadow: inset 0 0 0 3px rgba(200, 64, 42, .12), 0 0 0 2px rgba(200, 64, 42, .15); transform: rotate(-12deg); -webkit-mask: var(--ink-mask); mask: var(--ink-mask); }
.wk-cal-d.is-day::after { content: "囍"; position: absolute; right: -24%; top: -36%; font-family: var(--font-tc); font-size: .8rem; color: #fff; background: var(--verm); border-radius: 50%; width: 1.3rem; height: 1.3rem; display: grid; place-items: center; line-height: 1; }
.wk-cal-heart { display: none; }
.wk-cal-n { position: relative; z-index: 1; }
.wk-cal-count { display: inline-block; margin-top: .7rem; font-family: var(--font-tc); font-size: 1rem; letter-spacing: .08em; color: var(--verm-tx); }
/* 票根 */
.bp-stub { position: relative; padding: 1.3rem 1.3rem 1.5rem; touch-action: pan-y; }
.stub-perf { position: absolute; left: 22px; right: 22px; top: 0; height: 0; border-top: 2.5px dashed rgba(43, 38, 34, .5); }
.bp-stub::before, .bp-stub::after { content: ""; position: absolute; top: -18px; width: 36px; height: 36px; border-radius: 50%; background: var(--cream); box-shadow: inset 0 2px 6px rgba(43, 38, 34, .25); z-index: 2; }
.bp-stub::before { left: -18px; }
.bp-stub::after { right: -18px; }
.stub-card {
  --tear: 0;
  position: relative;
  transform-origin: 0 0;
  transform: rotate(calc(var(--tear) * 9deg)) translate(calc(var(--tear) * 34px), calc(var(--tear) * 10px));
  transition: transform .5s var(--ease-snap);
  touch-action: pan-y;
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
  cursor: grab;
}
.stub-card.is-dragging { transition: none; cursor: grabbing; }
.stub-card.is-torn { animation: vy-stub-fall .9s var(--ease-in) forwards; pointer-events: none; }
@keyframes vy-stub-fall { 0% { transform: rotate(calc(var(--tear) * 9deg)) translate(calc(var(--tear) * 34px), calc(var(--tear) * 10px)); opacity: 1; } 100% { transform: rotate(28deg) translate(120px, 340px); opacity: 0; } }
.stub-card.is-back { animation: vy-stub-back .6s var(--ease-out) both; }
@keyframes vy-stub-back { from { opacity: 0; transform: translateY(-14px); } to { opacity: 1; transform: none; } }
.stub-hint { display: flex; align-items: center; gap: .55rem; font-family: var(--font-tc); font-size: 1rem; letter-spacing: .06em; color: var(--verm-tx); margin-bottom: .8rem; }
.sh-arrow { flex: none; position: relative; width: 2.2rem; height: 10px; }
.sh-arrow::before { content: ""; position: absolute; left: 0; right: 6px; top: 4px; height: 2px; background: currentColor; }
.sh-arrow::after { content: ""; position: absolute; right: 1px; top: 0; width: 7px; height: 7px; border-top: 2px solid currentColor; border-right: 2px solid currentColor; transform: rotate(45deg); }
.stub-hint .sh-arrow { animation: vy-nudge 1.6s ease-in-out infinite; }
.stub-fields { display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: .6rem; }
.stub-fields p { display: grid; line-height: 1.25; min-width: 0; }
.stub-fields small { font-size: .8rem; font-weight: 700; letter-spacing: .14em; color: var(--ink-soft); }
.stub-fields b { font-size: 1rem; overflow-wrap: anywhere; }
.stub-fields b#stub-name { font-family: var(--font-hw); font-weight: 400; font-size: 1.25rem; color: var(--navy-ink); }
.stub-barcode { display: block; height: 46px; margin: .9rem 0 1rem; background: var(--bars, repeating-linear-gradient(90deg, var(--ink) 0 2px, transparent 2px 4px, var(--ink) 4px 7px, transparent 7px 9px)); }
.calendar-actions { display: flex; flex-wrap: wrap; gap: .6rem; }
.calendar-actions .btn { position: relative; z-index: 1; }
.stub-done { font-family: var(--font-tc); font-size: 1rem; color: var(--navy); min-height: 1.5em; margin-top: .4rem; }
@media (min-width: 900px) {
  .bp { grid-template-columns: 1fr 22rem; }
  .bp-head { border-radius: 18px 0 0 0; }
  .bp-stub { padding: 1.6rem 1.6rem 1.6rem 2rem; background: linear-gradient(180deg, var(--navy) 0 4.15rem, transparent 4.15rem); border-radius: 0 18px 18px 0; }
  .stub-perf { left: 0; right: auto; top: 22px; bottom: 22px; height: auto; border-top: 0; border-left: 2.5px dashed rgba(43, 38, 34, .5); }
  .bp-stub::before, .bp-stub::after { top: auto; left: -18px; right: auto; }
  .bp-stub::before { top: -18px; }
  .bp-stub::after { bottom: -18px; }
  .stub-hint { margin-top: 3.4rem; }
  .stub-fields { grid-template-columns: 1fr 1fr; }
  .stub-fields p:first-child { grid-column: 1 / -1; }
  .bp-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .bp-main { display: grid; grid-template-columns: 1fr 1fr; align-content: start; column-gap: 0; }
  .bp-head, .bp-route, .bp-grid, .bp-day { grid-column: 1 / -1; }
  .bp-itin { grid-column: 1; }
  .wk-cal { grid-column: 2; grid-row: span 2; align-self: start; margin-top: 1.4rem; }
  .parents { grid-column: 1; }
}

/* ============================================================
   ④b 護照簽證頁
   ============================================================ */
.dresscode { padding-block: clamp(4rem, 11vw, 7rem); }
.pp { position: relative; perspective: 1800px; max-width: 30rem; margin-inline: auto; }
.pp-page, .pp-face {
  background:
    repeating-radial-gradient(circle at 20% 30%, rgba(31, 58, 95, .045) 0 1px, transparent 1px 7px),
    repeating-radial-gradient(circle at 85% 75%, rgba(200, 64, 42, .04) 0 1px, transparent 1px 9px),
    linear-gradient(160deg, #f6eedb, #ece0c4);
  border-radius: 6px;
  box-shadow: 0 24px 40px -22px rgba(43, 38, 34, .55), inset 0 0 0 1px rgba(43, 38, 34, .12);
}
.pp-page { position: relative; min-height: 31rem; padding: 1.4rem 1.4rem 11rem; }
.pp-head { display: flex; gap: .8rem; align-items: baseline; font-family: var(--font-mono); font-weight: 700; font-size: .82rem; letter-spacing: .24em; color: var(--navy); border-bottom: 1.5px solid var(--navy); padding-bottom: .45rem; margin-bottom: 1.1rem; }
.pp-head span:nth-child(2) { font-family: var(--font-tc); font-weight: 400; letter-spacing: .3em; font-size: .9rem; }
.pp-no { margin-left: auto; }
.dc-note { font-size: 1.05rem; line-height: 1.95; color: var(--ink); white-space: pre-line; max-width: 24em; }
.dc-swatches { display: flex; flex-wrap: wrap; gap: 1.3rem 1rem; margin-top: 1.5rem; }
.dc-swatch {
  position: relative;
  width: 4.6rem; aspect-ratio: 3 / 4;
  border-radius: 5px;
  box-shadow: inset 0 0 0 4px rgba(255, 255, 255, .6), inset 0 0 0 5px rgba(43, 38, 34, .15), 0 3px 6px rgba(43, 38, 34, .25);
  transform: rotate(var(--r, 0deg));
  margin-bottom: 1.5rem;
}
.dc-swatch::before { content: ""; position: absolute; inset: 0; border-radius: 5px; background: linear-gradient(125deg, transparent 30%, rgba(255, 255, 255, .45) 45%, transparent 55%, rgba(255, 255, 255, .2) 70%, transparent 80%); }
.dc-swatch::after { content: attr(data-hex); position: absolute; left: 0; right: 0; top: calc(100% + .35rem); text-align: center; font-family: var(--font-mono); font-size: .8rem; font-weight: 700; letter-spacing: .04em; color: var(--ink); text-transform: uppercase; }
.dc-swatch:nth-child(2n) { --r: 3deg; }
.dc-swatch:nth-child(3n) { --r: -4deg; }
.visa-stamp { position: absolute; display: grid; place-content: center; text-align: center; pointer-events: none; -webkit-mask: var(--ink-mask); mask: var(--ink-mask); }
.vs-rect { right: 1rem; bottom: 4.4rem; width: 12.5rem; padding: .5rem .7rem; border: 3px double var(--verm); color: var(--verm-tx); transform: rotate(-7deg); background: rgba(247, 240, 222, .35); }
.vs-rect b { font-family: var(--font-mono); font-weight: 700; font-size: .95rem; letter-spacing: .1em; }
.vs-rect span { font-family: var(--font-mono); font-size: .8rem; letter-spacing: .08em; }
.vs-rect i { font-style: normal; font-family: var(--font-display); font-weight: 800; font-size: 1.4rem; letter-spacing: .02em; }
.vs-rect em { position: absolute; right: .45rem; top: .3rem; font-style: normal; font-family: var(--font-mono); font-weight: 700; font-size: .8rem; border: 1.5px solid currentColor; padding: 0 .2rem; }
.vs-round { left: 1.2rem; bottom: 1.6rem; width: 7.4rem; aspect-ratio: 1; border-radius: 50%; border: 3px solid var(--navy); color: var(--navy); transform: rotate(14deg); line-height: 1.15; }
.vs-round b { font-family: var(--font-mono); font-weight: 700; font-size: .82rem; letter-spacing: .1em; }
.vs-round span { font-family: var(--font-display); font-weight: 800; font-size: 1.2rem; }
.vs-round i { font-style: normal; font-family: var(--font-tc); font-size: .9rem; letter-spacing: .3em; }
.pp-mrz { position: absolute; left: 1.4rem; right: 1.4rem; bottom: .6rem; font-family: var(--font-mono); font-size: .8rem; letter-spacing: .12em; color: var(--ink-soft); white-space: nowrap; overflow: hidden; display: none; }
/* 翻頁的葉片：封面（正）／資料頁（背）；本體不掛 opacity／filter／clip-path／overflow */
.pp-leaf { position: absolute; left: 0; top: 0; width: 100%; height: 100%; transform-origin: 0 50%; transform-style: preserve-3d; transform: rotateY(-180deg); transition: transform 1.4s cubic-bezier(.55, .05, .25, 1); z-index: 3; pointer-events: none; }
.pp-face { position: absolute; inset: 0; -webkit-backface-visibility: hidden; backface-visibility: hidden; transform: translateZ(.1px); }
.pp-cover {
  background:
    radial-gradient(80% 60% at 40% 30%, rgba(255, 255, 255, .08), transparent 60%),
    repeating-linear-gradient(45deg, rgba(0, 0, 0, .06) 0 2px, transparent 2px 5px),
    #1d365a;
  display: grid; place-content: center; justify-items: center; gap: .8rem; text-align: center;
  color: #d8b56a;
  box-shadow: 0 24px 40px -22px rgba(0, 0, 0, .6), inset 0 0 0 1px rgba(0, 0, 0, .3);
}
.pp-cover b { font-family: var(--font-display); font-weight: 700; font-variation-settings: "opsz" 72, "wght" 700; font-size: 2rem; letter-spacing: .3em; padding-left: .3em; }
.pp-cover span:last-child { font-family: var(--font-tc); font-size: 1rem; letter-spacing: .4em; }
.ppc-emblem { width: 5.4rem; aspect-ratio: 1; border-radius: 50%; border: 2px solid #d8b56a; position: relative; }
.ppc-emblem::before { content: ""; position: absolute; inset: 20%; border-radius: 50%; background: #d8b56a; -webkit-mask: radial-gradient(circle at 50% 50%, transparent 30%, #000 31% 40%, transparent 41%), repeating-conic-gradient(#000 0 8deg, transparent 8deg 20deg); mask: radial-gradient(circle at 50% 50%, transparent 30%, #000 31% 40%, transparent 41%), repeating-conic-gradient(#000 0 8deg, transparent 8deg 20deg); }
.pp-data { transform: rotateY(180deg) translateZ(.1px); padding: 1.4rem; }
.ppd-grid { display: grid; grid-template-columns: 6rem 1fr; gap: .9rem 1rem; align-items: start; }
.ppd-photo { grid-row: span 3; aspect-ratio: 3 / 4; border: 1.5px solid var(--navy); background: radial-gradient(circle at 50% 38%, rgba(31, 58, 95, .35) 0 22%, transparent 23%), radial-gradient(ellipse at 50% 100%, rgba(31, 58, 95, .35) 0 45%, transparent 46%), rgba(255, 255, 255, .4); }
.ppd-grid p { display: grid; line-height: 1.3; }
.ppd-grid small { font-family: var(--font-mono); font-weight: 700; font-size: .8rem; letter-spacing: .16em; color: var(--ink-soft); }
.ppd-grid b { font-family: var(--font-mono); font-size: 1.05rem; color: var(--ink); }
.ppd-grid b.hw { font-family: var(--font-hw); font-weight: 400; font-size: 1.6rem; color: var(--navy-ink); }
.pp-history { position: relative; height: 14rem; margin-top: 1.6rem; }
.pph-stamp { position: absolute; display: grid; place-content: center; text-align: center; line-height: 1.15; font-family: var(--font-mono); font-weight: 700; color: var(--navy); opacity: .5; -webkit-mask: var(--ink-mask); mask: var(--ink-mask); }
.pph-stamp b { font-size: .95rem; letter-spacing: .1em; }
.pph-stamp i { font-style: normal; font-size: .8rem; }
.pph-stamp em { font-style: normal; font-size: .8rem; letter-spacing: .06em; }
.pph-0 { left: 4%; top: 6%; width: 7rem; height: 4.6rem; border: 2.5px solid currentColor; border-radius: 10px; transform: rotate(-9deg); }
.pph-1 { left: 44%; top: 0; width: 6.2rem; aspect-ratio: 1; border: 2.5px solid currentColor; border-radius: 50%; color: var(--verm-tx); transform: rotate(12deg); }
.pph-2 { left: 16%; top: 52%; width: 6.8rem; height: 4.4rem; border: 2.5px double currentColor; transform: rotate(5deg); color: #3d6b4e; }
.pph-3 { left: 60%; top: 50%; width: 6.4rem; aspect-ratio: 1; border: 2.5px dashed currentColor; border-radius: 50%; color: var(--verm-tx); transform: rotate(-14deg); }
html.wc .pp:not(.is-open) .pp-leaf { transform: rotateY(0deg); }
html.wc .pp:not(.is-stamped) .visa-stamp { opacity: 0; }
html.wc .pp.is-stamped .vs-rect { animation: vy-visa .5s cubic-bezier(.3, 1.4, .5, 1) both; }
html.wc .pp.is-stamped .vs-round { animation: vy-visa2 .5s .35s cubic-bezier(.3, 1.4, .5, 1) both; }
@keyframes vy-visa { 0% { opacity: 0; transform: rotate(-16deg) scale(1.8); } 60% { opacity: 1; transform: rotate(-7deg) scale(.95); } 100% { opacity: .95; transform: rotate(-7deg) scale(1); } }
@keyframes vy-visa2 { 0% { opacity: 0; transform: rotate(30deg) scale(1.8); } 60% { opacity: 1; transform: rotate(14deg) scale(.95); } 100% { opacity: .92; transform: rotate(14deg) scale(1); } }
html.wc .pp:not(.is-open) .dc-swatch { opacity: 0; transform: translateY(10px) rotate(var(--r, 0deg)); }
html.wc .pp.is-open .dc-swatch { transition: opacity .5s ease, transform .6s var(--ease-snap); transition-delay: calc(.9s + var(--i, 0) * .1s); }
@media (min-width: 860px) {
  .pp { max-width: 62rem; display: grid; grid-template-columns: 1fr 1fr; }
  .pp-page { grid-column: 2; border-radius: 0 6px 6px 0; }
  .pp-leaf { left: 50%; width: 50%; }
  .pp-cover { border-radius: 0 6px 6px 0; }
  .pp-data { border-radius: 6px 0 0 6px; }
  .pp-mrz { display: block; }
  .pp::before { content: ""; position: absolute; left: 50%; top: 0; bottom: 0; width: 18px; transform: translateX(-50%); background: linear-gradient(90deg, transparent, rgba(43, 38, 34, .18) 45%, rgba(43, 38, 34, .3) 50%, rgba(43, 38, 34, .18) 55%, transparent); z-index: 4; pointer-events: none; }
}

/* ============================================================
   ⑤ 目的地
   ============================================================ */
.venue { padding-block: clamp(4.5rem, 12vw, 7.5rem); }
.venue-tag { font-family: var(--font-mono); font-weight: 700; font-size: .82rem; letter-spacing: .24em; color: var(--verm-tx); margin-top: .6rem; }
.vn { display: grid; gap: 2.2rem; }
.vn-stamp { position: relative; }
.vn-stamp::before { content: ""; position: absolute; inset: 10px; box-shadow: 0 24px 40px -14px rgba(43, 38, 34, .5); }
.vn-perf { --r: 7px; --s: 22px; }
.vn-face { position: relative; background: #fbf6ea; padding: 18px 18px 0; }
.map-frame { aspect-ratio: 4 / 3; overflow: hidden; background: var(--cream-lo); outline: 1.5px solid var(--navy); }
.map-frame iframe { width: 100%; height: 100%; border: 0; display: block; filter: sepia(.25) saturate(.85) contrast(.98); }
.vn-cap { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; padding: .55rem 0 .7rem; }
.vn-cap b { font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 72, "wght" 800; font-size: 1.6rem; color: var(--verm); letter-spacing: -.01em; }
.vn-cap span { font-family: var(--font-mono); font-size: .82rem; font-weight: 700; letter-spacing: .1em; color: var(--ink); }
.venue-hall { font-family: var(--font-tc); font-size: 1.5rem; letter-spacing: .14em; color: var(--ink); }
.venue-hall:empty { display: none; }
.venue-address { font-family: var(--font-tc); font-size: 1.05rem; letter-spacing: .06em; color: var(--ink); margin-top: .2rem; }
.transport { display: grid; gap: 0; margin-top: 1.4rem; border-top: 1.5px solid var(--navy); }
.transport li { display: grid; grid-template-columns: 4.2rem 1fr; gap: .9rem; align-items: baseline; padding: .8rem 0; border-bottom: 1px dashed rgba(43, 38, 34, .3); }
.transport strong { font-family: var(--font-mono); font-weight: 700; font-size: .9rem; letter-spacing: .12em; color: var(--navy); }
.transport span { font-size: 1rem; line-height: 1.75; color: var(--ink); white-space: pre-line; }
/* 行李吊牌（導航鈕）：形狀畫在 ::before（clip-path 不掛 .reveal 本體） */
.tag {
  position: relative; isolation: isolate;
  display: inline-grid; grid-template-columns: auto 1fr auto; align-items: center; gap: .9rem;
  margin-top: 1.8rem;
  padding: .9rem 1.2rem .9rem 1.4rem;
  min-height: 64px; min-width: 15rem;
  color: var(--ink);
  text-decoration: none;
  transform-origin: 0 50%;
  transition: transform .5s var(--ease-snap);
}
.tag::before { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(180deg, #e1c48f, #d1ae72); clip-path: polygon(1.6rem 0, 100% 0, 100% 100%, 1.6rem 100%, 0 calc(100% - 1.2rem), 0 1.2rem); filter: drop-shadow(0 6px 8px rgba(43, 38, 34, .3)); }
.tag::after { content: ""; position: absolute; left: .9rem; top: 50%; width: 3.2rem; height: 2.2rem; border: 2px solid #3b4f6b; border-right: 0; border-radius: 50% 0 0 50%; transform: translate(-100%, -55%) rotate(-12deg); z-index: -2; }
.tag-hole { width: 18px; height: 18px; border-radius: 50%; background: var(--cream); box-shadow: 0 0 0 4px #b48a3c, inset 0 1px 3px rgba(0, 0, 0, .35); }
.tag-txt { display: grid; line-height: 1.25; }
.tag-txt small { font-family: var(--font-mono); font-weight: 700; font-size: .8rem; letter-spacing: .14em; color: #4a3c25; }
.tag-txt b { font-family: var(--font-tc); font-weight: 400; font-size: 1.25rem; letter-spacing: .16em; }
.tag-code { font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 72, "wght" 800; font-size: 1.7rem; color: var(--verm-tx); letter-spacing: -.01em; }
.tag:hover, .tag:focus-visible { transform: rotate(-3deg); }
.tag:active { transform: rotate(-5deg) scale(.98); }
.tag.reveal { transform: translateY(20px); }
.tag.reveal.is-in { transform: none; }
.venue-card2 { margin-top: clamp(3rem, 8vw, 4.5rem); padding-top: clamp(2rem, 5vw, 3rem); border-top: 2px dashed rgba(43, 38, 34, .3); }
.venue2-name { font-family: var(--font-tc); font-weight: 400; font-size: clamp(1.7rem, 5.5vw, 2.4rem); letter-spacing: .1em; margin-bottom: 1.2rem; }
.venue-card2 .transport:empty { display: none; }
@media (min-width: 900px) {
  .vn { grid-template-columns: 1.35fr 1fr; gap: 3.5rem; align-items: center; }
}

/* ============================================================
   ⑤b 行李：旅行貼紙／吊牌
   ============================================================ */
.custom { padding-block: clamp(4rem, 11vw, 6.5rem); }
#custom-blocks { display: grid; gap: 1.8rem; }
.custom-block {
  position: relative;
  padding: 1.5rem 1.4rem 1.5rem 3.6rem;
  background: linear-gradient(180deg, #e3c792, #d5b47a);
  color: var(--ink);
  border-radius: 6px 14px 14px 6px;
  box-shadow: 0 16px 26px -16px rgba(43, 38, 34, .55);
}
.cb-eyelet { position: absolute; left: 1.2rem; top: 1.7rem; width: 18px; height: 18px; border-radius: 50%; background: var(--cream); box-shadow: 0 0 0 4px #b48a3c, inset 0 1px 3px rgba(0, 0, 0, .35); }
.custom-block-title { font-family: var(--font-tc); font-weight: 400; font-size: 1.45rem; letter-spacing: .12em; margin-bottom: .35rem; }
.custom-text { white-space: pre-line; font-size: 1.02rem; line-height: 1.9; }
.custom-block:nth-child(even) { background: var(--navy); color: var(--cream-hi); border-radius: 50px 8px 8px 50px; padding-left: 4rem; }
.custom-block:nth-child(even) .cb-eyelet { box-shadow: 0 0 0 4px #d8b56a, inset 0 1px 3px rgba(0, 0, 0, .35); left: 1.5rem; }
.custom-block.reveal { transform: translateY(24px) rotate(-1deg); }
.custom-block.reveal.is-in { transform: rotate(-1deg); }
.custom-block:nth-child(even).reveal { transform: translateY(24px) rotate(1.2deg); }
.custom-block:nth-child(even).reveal.is-in { transform: rotate(1.2deg); }

/* ============================================================
   ⑥ 海關抽檢（刮刮卡）
   ============================================================ */
.secret { padding-block: clamp(4rem, 11vw, 6.5rem); }
.scratch-card {
  position: relative;
  background:
    repeating-linear-gradient(180deg, transparent 0 2.05rem, rgba(31, 58, 95, .14) 2.05rem calc(2.05rem + 1px)),
    #fbf6ea;
  color: var(--ink);
  border: 3px double var(--navy);
  border-radius: 4px;
  padding: 3.2rem 1.4rem 1.6rem;
  box-shadow: 0 20px 34px -20px rgba(43, 38, 34, .55);
  text-align: left;
}
.scratch-card::before { content: "CUSTOMS DECLARATION · 海關申報書"; position: absolute; left: 1.2rem; right: 1.2rem; top: .9rem; font-family: var(--font-mono); font-weight: 700; font-size: .8rem; letter-spacing: .14em; color: var(--navy); border-bottom: 1.5px solid var(--navy); padding-bottom: .4rem; }
.scratch-text { font-family: var(--font-tc); font-size: 1.15rem; line-height: 2.05; letter-spacing: .04em; white-space: pre-line; }
.scratch-hint { font-family: var(--font-tc); font-size: 1.1rem; letter-spacing: .1em; color: #fff8ec; text-shadow: 0 1px 3px rgba(0, 0, 0, .55); }
.scratch-open { font-family: var(--font-tc); font-size: 1rem; color: var(--ink); text-decoration: underline; text-underline-offset: .3em; min-height: 44px; padding: .5rem 1rem; }

/* ============================================================
   ⑦ 回函明信片
   ============================================================ */
.rsvp { padding-block: clamp(4.5rem, 12vw, 7.5rem); background: linear-gradient(180deg, var(--cream), #e7d6b2); }
.pcard {
  position: relative;
  max-width: 62rem; margin-inline: auto;
  background:
    radial-gradient(90% 60% at 20% 0%, rgba(255, 255, 255, .6), transparent 60%),
    #fbf6ea;
  border-radius: 6px;
  padding: 1.4rem 1.3rem 1.8rem;
  box-shadow: 0 34px 50px -26px rgba(43, 38, 34, .6), 0 0 0 1px rgba(43, 38, 34, .12);
}
.pcard-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; }
.pc-postcard { display: grid; font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 72, "wght" 800; font-size: clamp(1.7rem, 7vw, 2.4rem); letter-spacing: .06em; color: var(--navy); line-height: 1; }
.pc-postcard span { font-family: var(--font-tc); font-weight: 400; font-variation-settings: normal; font-size: .95rem; letter-spacing: .2em; color: var(--ink); margin-top: .4rem; }
.pc-stampbox { position: relative; flex: none; width: 5.2rem; aspect-ratio: 4 / 5; border: 1.5px dashed rgba(43, 38, 34, .5); display: grid; place-items: center; }
.pcs-empty { font-family: var(--font-mono); font-size: .8rem; font-weight: 700; letter-spacing: .12em; color: var(--ink-soft); text-align: center; line-height: 1.3; }
.pcs-stamp { position: absolute; inset: -4px; display: grid; place-content: center; justify-items: center; background: var(--verm); color: var(--cream-hi); outline: 2px dashed var(--cream-hi); outline-offset: -6px; opacity: 0; transform: rotate(-8deg) scale(1.4); transition: opacity .3s ease, transform .45s var(--ease-snap); }
.pcs-sun { width: 1.9rem; aspect-ratio: 1; border-radius: 50%; background: var(--cream-hi); }
.pcs-stamp b { font-family: var(--font-display); font-weight: 800; font-size: .95rem; margin-top: .2rem; }
.pcs-stamp em { font-style: normal; font-family: var(--font-tc); font-size: .8rem; letter-spacing: .2em; }
.pcard.has-choice .pcs-stamp { opacity: 1; transform: rotate(4deg); }
.pcard.is-no .pcs-stamp { background: var(--navy); }
.pcard-addr { display: grid; gap: .1rem; margin: 1.4rem 0 1rem; }
.pcard-addr p { display: grid; grid-template-columns: auto 1fr; align-items: baseline; gap: .6rem; padding: .5rem 0; border-bottom: 1.5px solid rgba(43, 38, 34, .3); }
.pcard-addr small { white-space: nowrap; font-family: var(--font-mono); font-weight: 700; font-size: .8rem; letter-spacing: .06em; color: var(--ink-soft); }
.pcard-addr b { font-family: var(--font-tc); font-weight: 400; font-size: 1.2rem; letter-spacing: .1em; color: var(--ink); overflow-wrap: anywhere; }
.pcard-addr b.hw { font-family: var(--font-hw); font-size: 1.8rem; color: var(--navy-ink); letter-spacing: .02em; line-height: 1.2; }
.rsvp-intro { font-size: 1.05rem; line-height: 1.95; color: var(--ink); white-space: pre-line; }
.rsvp-deadline { font-family: var(--font-mono); font-size: .9rem; font-weight: 700; letter-spacing: .1em; color: var(--verm-tx); margin-top: .5rem; }
.rsvp-deadline:empty { display: none; }
.rsvp-form { margin-top: 1.8rem; display: grid; gap: 1.6rem; }
.rsvp .field label, .rsvp .field legend { font-family: var(--font-mono); font-weight: 700; font-size: .84rem; letter-spacing: .1em; color: var(--ink); }
.rsvp .field input[type="text"], .rsvp .field input[type="tel"], .rsvp .field input[type="number"], .rsvp .field textarea, .rsvp .field select {
  font-family: var(--font-tc);
  font-size: max(16px, 1.08rem);
  color: var(--navy-ink);
  background: transparent;
  border: 0; border-bottom: 1.5px solid rgba(43, 38, 34, .55);
  border-radius: 0;
  padding: .55rem .2rem;
}
.rsvp .field textarea { background: repeating-linear-gradient(180deg, transparent 0 2.15rem, rgba(43, 38, 34, .25) 2.15rem calc(2.15rem + 1px)); line-height: 2.15rem; padding-top: 0; border-bottom: 0; }
.rsvp .field input:focus-visible, .rsvp .field textarea:focus-visible, .rsvp .field select:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; border-color: var(--navy); box-shadow: none; }
.rsvp .field ::placeholder { color: #7a6e62; opacity: 1; }
.rsvp .field .error-text { color: var(--verm-tx); font-size: .9rem; }
.rsvp .field.has-error input { border-color: var(--verm-tx); }
.attend-field { border: 0; padding: 0; margin: 0; min-width: 0; }
.attend-options { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: .8rem; }
.attend-pill { position: relative; display: grid; place-items: center; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.attend-pill input { position: absolute; opacity: 0; pointer-events: none; }
/* 選章：沒選＝虛線空章；選了＝墨印章（朱紅＝赴約、深藍＝祝福） */
.attend-pill > span {
  position: relative;
  width: min(100%, 9.4rem); aspect-ratio: 1;
  border-radius: 50%;
  display: grid; place-content: center; justify-items: center; text-align: center; gap: .15rem;
  border: 2px dashed rgba(43, 38, 34, .45);
  color: var(--ink);
  transition: color .3s, border-color .3s, transform .45s var(--ease-snap), background-color .3s;
  -webkit-user-select: none; user-select: none;
}
.attend-pill > span::before { content: ""; position: absolute; inset: 7px; border-radius: 50%; border: 1.5px solid transparent; transition: border-color .3s; }
.attend-pill b { font-family: var(--font-tc); font-weight: 400; font-size: 1.2rem; letter-spacing: .14em; }
.attend-pill i { font-style: normal; font-family: var(--font-mono); font-weight: 700; font-size: .8rem; letter-spacing: .1em; }
.attend-pill:active > span { transform: scale(.95); }
.ap-yes input:checked + span { color: var(--verm-tx); border: 3px solid var(--verm); transform: rotate(-8deg); background: rgba(200, 64, 42, .06); }
.ap-no input:checked + span { color: var(--navy); border: 3px solid var(--navy); transform: rotate(7deg); background: rgba(31, 58, 95, .06); }
.attend-pill input:checked + span::before { border-color: currentColor; }
.ap-yes input:checked + span, .ap-no input:checked + span { animation: vy-choose .45s cubic-bezier(.3, 1.4, .5, 1); }
@keyframes vy-choose { 0% { scale: 1.25; } 60% { scale: .94; } 100% { scale: 1; } }
.attend-pill input:focus-visible + span { outline: 2px solid var(--navy); outline-offset: 4px; }
/* 紙本喜帖那組 radio 是一般膠囊 */
.ao-plain .attend-pill > span { aspect-ratio: auto; width: 100%; border-radius: 4px; padding: .75rem .6rem; min-height: 48px; }
.ao-plain .attend-pill > span::before { display: none; }
.ao-plain .attend-pill b { font-size: 1rem; letter-spacing: .06em; }
.ao-plain .attend-pill input:checked + span { color: var(--cream-hi); background: var(--navy); border: 2px solid var(--navy); transform: none; animation: none; }
.rsvp-details { display: grid; gap: 1.5rem; }
.field-row { display: grid; gap: 1.25rem; }
@media (min-width: 560px) { .field-row { grid-template-columns: repeat(3, 1fr); } }
.stepper { display: grid; grid-template-columns: 44px 1fr 44px; align-items: center; gap: .3rem; }
.stepper button { width: 44px; height: 44px; border-radius: 50%; border: 1.5px solid var(--navy); color: var(--navy); font-size: 1.3rem; line-height: 1; background: transparent; }
.stepper button:active { background: rgba(31, 58, 95, .1); }
.rsvp .stepper input { text-align: center; -moz-appearance: textfield; appearance: textfield; font-family: var(--font-display); font-weight: 700; font-size: 1.3rem; }
.stepper input::-webkit-outer-spin-button, .stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.cap-note { font-family: var(--font-tc); font-size: .9rem; color: var(--ink-soft); }
.companion-list { display: grid; gap: .5rem; }
.companion-list input { font-family: var(--font-tc); font-size: max(16px, 1.05rem); border: 0; border-bottom: 1.5px solid rgba(43, 38, 34, .5); background: transparent; padding: .5rem .2rem; color: var(--navy-ink); }
[data-rsvp-custom] { display: grid; gap: 1.5rem; }
.cq-checks { display: grid; gap: .5rem; }
.rsvp .cq-checks label { display: flex; align-items: center; gap: .5rem; font-size: 1rem; cursor: pointer; font-family: var(--font-tc); letter-spacing: 0; }
.rsvp .cq-checks input[type="checkbox"] { width: 1.15rem; height: 1.15rem; flex: none; accent-color: var(--navy); }
.rsvp-error { color: var(--verm-tx); font-size: 1rem; }
/* 橡皮章送出鈕：長按蓄力（--wk-press）章往下壓、印面周圍的進度環填滿 */
.stamp-row { display: flex; align-items: center; gap: 1.2rem; flex-wrap: wrap; margin-top: .4rem; }
.rubber {
  --wk-press: 0;
  position: relative; flex: none;
  width: 8.6rem; height: 9.4rem;
  touch-action: none;
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  cursor: pointer;
}
.rb-knob, .rb-neck, .rb-face { position: absolute; left: 50%; transform: translate(-50%, calc(var(--wk-press) * 16px)); transition: transform .25s var(--ease-snap); }
.rubber.is-pressing .rb-knob, .rubber.is-pressing .rb-neck, .rubber.is-pressing .rb-face { transition: none; }
.rb-knob { top: 0; width: 3.4rem; height: 3.4rem; border-radius: 50%; background: radial-gradient(circle at 35% 30%, #c79a62, #8a5a2b 60%, #5e3a18); box-shadow: inset 0 -4px 6px rgba(0, 0, 0, .3), 0 4px 8px rgba(0, 0, 0, .25); z-index: 2; }
.rb-neck { top: 2.9rem; width: 1.9rem; height: 2.6rem; background: linear-gradient(90deg, #6e4520, #a8773f 45%, #6e4520); border-radius: 3px; z-index: 1; }
.rb-face {
  top: 5.2rem; width: 8rem; height: 3.4rem;
  display: grid; place-content: center; justify-items: center;
  background: linear-gradient(180deg, #3b2a1a 0 28%, var(--rubber) 28% 100%);
  border-radius: 6px;
  box-shadow: 0 8px 14px -6px rgba(0, 0, 0, .45);
  color: #fbe9dc;
  padding-top: .7rem;
  z-index: 3;
}
.rb-text { font-family: var(--font-tc); font-weight: 400; font-size: 1.15rem; letter-spacing: .3em; line-height: 1; padding-left: .3em; }
.rb-sub { font-style: normal; font-family: var(--font-mono); font-weight: 700; font-size: .8rem; letter-spacing: .2em; margin-top: .15rem; }
.rb-ring { position: absolute; left: 50%; bottom: -.5rem; width: 9rem; height: 1.4rem; transform: translateX(-50%); border-radius: 50%; background: conic-gradient(var(--verm) calc(var(--wk-press) * 360deg), rgba(43, 38, 34, .18) 0); -webkit-mask: radial-gradient(closest-side, transparent 70%, #000 72%); mask: radial-gradient(closest-side, transparent 70%, #000 72%); }
.rubber.wants-hold .rb-face { animation: vy-wiggle .5s ease; }
@keyframes vy-wiggle { 0%, 100% { rotate: 0deg; } 25% { rotate: -4deg; } 75% { rotate: 4deg; } }
.rubber:focus-visible { outline: 2px solid var(--navy); outline-offset: 6px; border-radius: 8px; }
.rubber[disabled] { opacity: .6; }
.stamp-help { display: grid; gap: .3rem; min-width: 12rem; flex: 1; }
.stamp-hint { font-family: var(--font-tc); font-size: 1.05rem; letter-spacing: .06em; color: var(--ink); line-height: 1.6; }
.rubber.wants-hold ~ .stamp-help .stamp-hint { color: var(--verm-tx); }
.stamp-skip { justify-self: start; font-family: var(--font-tc); font-size: .95rem; color: var(--ink); text-decoration: underline; text-underline-offset: .3em; min-height: 44px; padding: .4rem 0; }
/* 成功：明信片蓋郵戳、飛回去 → 留下掛號回執 */
.rsvp-success { position: relative; }
/* offset-path 的座標原點是包含塊左上角：卡片絕對定位在 .sent-wrap 左上、offset-anchor 0 0，路徑起點才剛好是卡片原位 */
.sent-wrap { display: none; }
.rsvp-success.is-fresh .sent-wrap { display: block; position: relative; width: min(100%, 22rem); aspect-ratio: 3 / 2; margin: 0 auto 1.4rem; }
.sent-card {
  position: absolute; left: 0; top: 0; width: 100%; height: 100%;
  background: #fbf6ea;
  box-shadow: 0 18px 30px -14px rgba(43, 38, 34, .6), 0 0 0 1px rgba(43, 38, 34, .15);
  offset-path: path("M 0 0 C 30 -60, 140 -140, 420 -330");
  offset-anchor: 0 0;
  offset-rotate: 0deg;
  offset-distance: 0%;
}
.rsvp-success.is-fresh .sent-card { animation: vy-fly .85s 1.05s var(--ease-in) forwards; }
@keyframes vy-fly { 0% { offset-distance: 0%; transform: rotate(-3deg) scale(1); opacity: 1; } 100% { offset-distance: 100%; transform: rotate(18deg) scale(.35); opacity: 0; } }
.rsvp-success.is-fresh .sent-wrap { animation: vy-collapse .4s 1.85s ease forwards; }
@keyframes vy-collapse { to { aspect-ratio: 30 / 1; margin-bottom: 0; } }
.sc-face { position: absolute; left: 1.2rem; bottom: 1.1rem; display: grid; }
.sc-face b { font-family: var(--font-hw); font-weight: 400; font-size: 2rem; color: var(--navy-ink); line-height: 1.1; }
.sc-face i { font-style: normal; font-family: var(--font-tc); font-size: 1rem; color: var(--ink); letter-spacing: .1em; }
.sc-pm { position: absolute; right: 1rem; top: .8rem; width: 6.6rem; aspect-ratio: 1; color: var(--verm); display: grid; place-content: center; text-align: center; -webkit-mask: var(--ink-mask); mask: var(--ink-mask); }
.sc-pm svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.sc-pm b { font-family: var(--font-mono); font-weight: 700; font-size: 1.05rem; letter-spacing: .14em; }
.sc-pm i { font-style: normal; font-family: var(--font-mono); font-size: .8rem; font-weight: 700; }
.rsvp-success.is-fresh .sc-pm { animation: vy-stamp .4s .3s cubic-bezier(.3, 1.4, .5, 1) both; }
.rsvp-success.is-fresh .receipt { animation: vy-rise-s .6s 1.6s var(--ease-out) both; opacity: 0; transform: translateY(14px); }
.receipt { position: relative; padding: 1.2rem 0 0; border-top: 2px dashed rgba(43, 38, 34, .35); }
.rc-kind { display: flex; align-items: center; justify-content: space-between; gap: 1rem; white-space: nowrap; font-family: var(--font-mono); font-weight: 700; font-size: .82rem; letter-spacing: .08em; color: var(--ink-soft); }
.receipt .rsvp-stamp { position: static; display: grid; place-content: center; text-align: center; width: 6.8rem; flex: none; aspect-ratio: 1; border-radius: 50%; border: 2.5px solid var(--navy); color: var(--navy); line-height: 1.15; -webkit-mask: var(--ink-mask); mask: var(--ink-mask); transform: rotate(-10deg); }
.receipt .rsvp-stamp b { font-size: .8rem; letter-spacing: .06em; }
.receipt .rsvp-stamp i { font-style: normal; font-family: var(--font-tc); font-size: .85rem; font-weight: 400; letter-spacing: .1em; }
.receipt h3 { font-family: var(--font-tc); font-weight: 400; font-size: 1.7rem; letter-spacing: .12em; margin-top: .4rem; }
.receipt p { font-size: 1.02rem; line-height: 1.9; color: var(--ink); margin-top: .4rem; }
.success-summary { font-family: var(--font-mono); font-size: .9rem; white-space: pre-line; color: var(--ink); }
.success-note { color: var(--ink-soft); }
.receipt .btn-ghost { margin-top: 1rem; }
.rsvp-closed h3 { font-family: var(--font-tc); font-weight: 400; font-size: 1.7rem; letter-spacing: .1em; }
@media (min-width: 900px) {
  .pcard { display: grid; grid-template-columns: 1.25fr 1fr; grid-template-areas: "head head" "intro addr" "form addr" "succ succ"; column-gap: 3rem; padding: 2.2rem 2.4rem 2.4rem; }
  .pcard-head { grid-area: head; }
  .pcard-addr { grid-area: addr; align-self: start; border-left: 1.5px solid rgba(43, 38, 34, .3); padding-left: 2rem; margin: 1.4rem 0 0; }
  .pcard-addr p { grid-template-columns: 1fr; gap: .2rem; padding: .9rem 0; }
  .rsvp-intro, .rsvp-deadline { grid-area: intro; }
  .rsvp-deadline { align-self: end; }
  .rsvp-form { grid-area: form; grid-template-columns: 1.25fr 1fr; column-gap: 3rem; align-items: start; }
  .rsvp-form > * { grid-column: 1; }
  .rsvp-form > .stamp-row { grid-column: 2; grid-row: 1 / span 8; align-self: end; flex-direction: column; align-items: flex-start; padding-left: 2rem; border-left: 1.5px solid rgba(43, 38, 34, .3); }
  .pcard { grid-template-areas: "head head" "intro addr" "form form" "succ succ"; }
  .rsvp-success, .rsvp-closed { grid-area: form; }
}

/* ============================================================
   ⑧ 片尾
   ============================================================ */
.footer { position: relative; background: radial-gradient(120% 70% at 50% 0%, #22406a, #142a47 60%, #0f2038); color: var(--cream-hi); padding: 0 0 max(2.4rem, env(safe-area-inset-bottom, 0px)); overflow-x: clip; }
.footer::before { content: ""; display: block; height: 12px; background: var(--airmail); background-size: 45px 100%; }
.dl { position: relative; padding: clamp(4rem, 12vw, 7rem) var(--gutter) 2rem; display: grid; justify-items: center; text-align: center; }
.dl-wave { position: absolute; left: 0; width: 100%; top: calc(clamp(4rem, 12vw, 7rem) + min(39vw, 190px) - 40px); height: 80px; overflow: visible; }
.dl-wave path { fill: none; stroke: rgba(239, 227, 200, .4); stroke-width: 2; stroke-dasharray: 1; stroke-dashoffset: 0; vector-effect: non-scaling-stroke; }
.dl-mark { position: relative; z-index: 1; width: min(78vw, 380px); aspect-ratio: 1; color: var(--cream); -webkit-mask: var(--ink-mask); mask: var(--ink-mask); -webkit-mask-size: 220px; mask-size: 220px; transform: rotate(-9deg); background: radial-gradient(circle, #183152 0 70%, transparent 70.5%); border-radius: 50%; }
.dl-mark svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.dl-ring-text { font-family: var(--font-mono); font-weight: 700; font-size: 22px; letter-spacing: 3px; fill: currentColor; }
.dl-center { position: absolute; inset: 22%; display: grid; place-content: center; justify-items: center; line-height: 1.1; }
.dl-center small { font-family: var(--font-mono); font-weight: 700; font-size: .82rem; letter-spacing: .3em; }
.dl-center b { font-family: var(--font-hw); font-weight: 400; font-size: clamp(2.2rem, 11vw, 3.6rem); color: var(--verm-hi); margin: .25rem 0; max-width: 5.5em; white-space: nowrap; overflow: hidden; text-overflow: clip; }
.dl-center i { font-style: normal; font-family: var(--font-display); font-weight: 800; font-size: 1.15rem; letter-spacing: .06em; }
.dl-line { text-wrap: balance; position: relative; z-index: 1; margin-top: 1.6rem; font-family: var(--font-tc); font-size: clamp(1.25rem, 5vw, 1.6rem); letter-spacing: .14em; color: var(--cream-hi); }
.dl-line:empty { display: none; }
html.wc .dl:not(.is-stamped) .dl-mark { opacity: 0; transform: rotate(-20deg) scale(1.5); }
html.wc .dl.is-stamped .dl-mark { animation: vy-dl .55s cubic-bezier(.3, 1.4, .5, 1) both; }
@keyframes vy-dl { 0% { opacity: 0; transform: rotate(-22deg) scale(1.55); } 60% { opacity: 1; transform: rotate(-9deg) scale(.95); } 100% { opacity: 1; transform: rotate(-9deg) scale(1); } }
html.wc .dl:not(.is-stamped) .dl-wave path { stroke-dashoffset: 1; }
html.wc .dl.is-stamped .dl-wave path { animation: vy-draw .8s .35s ease-out forwards; stroke-dashoffset: 1; }
html.wc .dl.is-stamped .dl-wave path:nth-child(2) { animation-delay: .45s; }
html.wc .dl.is-stamped .dl-wave path:nth-child(3) { animation-delay: .55s; }
html.wc .dl.is-stamped .dl-wave path:nth-child(4) { animation-delay: .65s; }
/* 新人短信：航空郵簡 */
.letter {
  position: relative;
  width: min(calc(100% - 2 * var(--gutter)), 40rem);
  margin: 1.5rem auto 0;
  padding: 2.4rem 1.6rem 1.8rem;
  color: var(--ink);
  background:
    repeating-linear-gradient(180deg, transparent 0 2.4rem, rgba(31, 58, 95, .18) 2.4rem calc(2.4rem + 1px)) 0 4.8rem / 100% 100% no-repeat,
    #f6efdd;
  box-shadow: 0 30px 50px -24px rgba(0, 0, 0, .7);
  border: 10px solid transparent;
  border-image: var(--airmail) 14;
  background-clip: padding-box;
}
.letter.reveal { transform: rotate(-1deg) translateY(24px); }
.letter.reveal.is-in { transform: rotate(-1deg); }
.lt-head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; white-space: nowrap; font-family: var(--font-mono); font-weight: 700; font-size: .82rem; letter-spacing: .12em; color: var(--navy); border-bottom: 1.5px solid var(--navy); padding-bottom: .4rem; }
.lt-head .jp { letter-spacing: .2em; color: var(--verm-tx); font-family: var(--font-jp); font-weight: 500; }
.lt-msg { text-wrap: pretty; font-size: clamp(1.4rem, 5.6vw, 1.8rem); line-height: 2.4rem; color: var(--navy-ink); margin-top: 1.4rem; white-space: pre-line; }
.lt-msg:empty { display: none; }
.lt-names { text-align: right; font-family: var(--font-tc); font-size: 1.1rem; letter-spacing: .14em; margin-top: 1.2rem; }
.share-stamp { display: flex; align-items: center; gap: .9rem; margin-top: 1.6rem; text-align: left; min-height: 64px; -webkit-tap-highlight-color: transparent; }
.ss-perf { --r: 3px; --s: 9px; display: block; width: 3.8rem; height: 4.6rem; flex: none; transform: rotate(-5deg); transition: transform .4s var(--ease-snap); -webkit-mask: radial-gradient(circle var(--r) at 50% 0, #0000 calc(100% - .5px), #000 100%) top / var(--s) 51% round no-repeat, radial-gradient(circle var(--r) at 50% 100%, #0000 calc(100% - .5px), #000 100%) bottom / var(--s) 51% round no-repeat; mask: radial-gradient(circle var(--r) at 50% 0, #0000 calc(100% - .5px), #000 100%) top / var(--s) 51% round no-repeat, radial-gradient(circle var(--r) at 50% 100%, #0000 calc(100% - .5px), #000 100%) bottom / var(--s) 51% round no-repeat; }
.ss-perf-y { display: block; height: 100%; -webkit-mask: radial-gradient(circle var(--r) at 0 50%, #0000 calc(100% - .5px), #000 100%) left / 51% var(--s) no-repeat round, radial-gradient(circle var(--r) at 100% 50%, #0000 calc(100% - .5px), #000 100%) right / 51% var(--s) no-repeat round; mask: radial-gradient(circle var(--r) at 0 50%, #0000 calc(100% - .5px), #000 100%) left / 51% var(--s) no-repeat round, radial-gradient(circle var(--r) at 100% 50%, #0000 calc(100% - .5px), #000 100%) right / 51% var(--s) no-repeat round; }
.ss-face { display: grid; place-content: center; justify-items: center; height: 100%; background: var(--verm-tx); color: var(--cream-hi); box-shadow: inset 0 0 0 4px var(--cream-hi), inset 0 0 0 5.5px var(--verm); }
.ss-face b { font-family: var(--font-tc); font-weight: 400; font-size: 1rem; letter-spacing: .14em; }
.ss-face i { font-style: normal; font-family: var(--font-mono); font-weight: 700; font-size: .8rem; letter-spacing: .1em; }
.ss-label { font-family: var(--font-tc); font-size: 1.05rem; letter-spacing: .08em; color: var(--ink); text-decoration: underline; text-underline-offset: .3em; }
.share-stamp:hover .ss-perf, .share-stamp:focus-visible .ss-perf { transform: rotate(4deg) scale(1.05); }
.share-done { font-family: var(--font-tc); font-size: 1rem; color: var(--verm-tx); min-height: 1.4em; margin-top: .4rem; }
/* 終章：郵筒 */
.blessing { text-align: center; padding: clamp(3.5rem, 10vw, 5rem) var(--gutter) 1rem; display: grid; justify-items: center; gap: .8rem; }
.bl-kicker { font-family: var(--font-mono); font-weight: 700; font-size: .82rem; letter-spacing: .3em; color: #e3d9c3; }
.blessing-lead { font-family: var(--font-tc); font-size: clamp(1.3rem, 5vw, 1.6rem); letter-spacing: .12em; color: var(--cream-hi); }
.pbox-wrap { position: relative; width: 11rem; height: 15.5rem; margin-top: .8rem; }
.pbox { position: absolute; inset: 0; }
.pbox > span { position: absolute; }
.pb-body { left: 1.4rem; right: 1.4rem; top: 3rem; bottom: 1.4rem; background: linear-gradient(90deg, #a52c18, #d24a30 40%, #b8371f 70%, #8f2614); border-radius: 0 0 6px 6px; display: grid; justify-items: center; align-content: start; padding-top: 3.2rem; }
.pb-body i { font-style: normal; display: block; background: #f6efdd; color: var(--verm-tx); font-family: var(--font-mono); font-weight: 700; font-size: .82rem; letter-spacing: .2em; padding: .15rem .5rem; border-radius: 2px; }
.pb-body em { font-style: normal; font-family: var(--font-tc); font-size: 1.6rem; color: #f6efdd; margin-top: .4rem; }
.pb-cap { left: .9rem; right: .9rem; top: .6rem; height: 3.2rem; background: linear-gradient(90deg, #a52c18, #dd5638 40%, #b8371f 70%, #8f2614); border-radius: 50% 50% 8px 8px / 85% 85% 8px 8px; z-index: 2; }
.pb-slot { left: 3rem; right: 3rem; top: 4.4rem; height: .7rem; background: #2a0d07; border-radius: 4px; z-index: 3; box-shadow: 0 1px 0 rgba(255, 255, 255, .3); }
.pb-foot { left: 1rem; right: 1rem; bottom: 0; height: 1.5rem; background: #3a1a12; border-radius: 3px; }
.pb-flag { right: -.4rem; top: 4.6rem; width: 2.4rem; height: .55rem; background: #f6efdd; transform-origin: 0 50%; transform: rotate(0deg); transition: transform .6s var(--ease-snap); z-index: 1; border-radius: 2px; box-shadow: 0 2px 4px rgba(0, 0, 0, .3); }
.pb-flag::after { content: ""; position: absolute; right: 0; top: -.6rem; width: .9rem; height: 1.8rem; background: #e8b04a; border-radius: 3px; }
.pb-letter {
  left: 3.4rem; right: 3.4rem; top: calc(4.75rem - 4.6rem); height: 4.6rem;
  background: #f6efdd;
  border: 2px solid transparent; border-image: var(--airmail) 8;
  display: grid; place-items: center;
  z-index: 2;
  transform: translateY(calc(var(--drop, 0) * 4.6rem));
  clip-path: inset(0 0 calc(var(--drop, 0) * 100%) 0);
  transition: transform .25s ease, clip-path .25s ease;
}
.pb-letter b { font-family: var(--font-hw); font-weight: 400; font-size: 1.1rem; color: var(--navy-ink); white-space: nowrap; max-width: 100%; overflow: hidden; }
.blessing.is-dropping .pb-letter { transition: none; }
.blessing.is-stamped .pb-letter { --drop: 1; transition: transform .35s var(--ease-in), clip-path .35s var(--ease-in); }
.blessing.is-stamped .pb-flag { transform: rotate(-80deg); transition-delay: .3s; }
.blessing.is-stamped .pbox { animation: vy-box .5s .35s ease; }
@keyframes vy-box { 0%, 100% { transform: none; } 30% { transform: translateY(3px) scaleY(.98); } 60% { transform: translateY(-2px); } }
.pbox-btn {
  --wk-press: 0;
  position: relative; width: 84px; height: 84px; margin-top: .6rem;
  border-radius: 50%;
  touch-action: none;
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
  display: grid; place-items: center;
}
.pbb-ring { position: absolute; inset: 0; border-radius: 50%; background: conic-gradient(var(--verm-hi) calc(var(--wk-press) * 360deg), rgba(239, 227, 200, .2) 0); -webkit-mask: radial-gradient(circle, transparent 60%, #000 62%); mask: radial-gradient(circle, transparent 60%, #000 62%); }
.pbb-core { width: 60px; height: 60px; border-radius: 50%; display: grid; place-items: center; background: var(--cream-hi); color: var(--verm-tx); font-family: var(--font-tc); font-size: 1.05rem; letter-spacing: .1em; padding-left: .1em; transition: transform .15s; box-shadow: 0 4px 10px rgba(0, 0, 0, .35); }
.pbox-btn.is-pressing .pbb-core { transform: scale(.92); }
.pbox-btn.is-committed .pbb-core { background: var(--verm); color: var(--cream-hi); }
.pbox-btn:focus-visible { outline: 2px solid var(--cream); outline-offset: 4px; }
.blessing-hint { font-family: var(--font-tc); font-size: 1.05rem; letter-spacing: .1em; color: #e9dfc8; transition: color .3s; }
.pbox-btn.wants-hold + .blessing-hint { color: var(--verm-hi); }
.blessing-skip { font-family: var(--font-tc); font-size: .95rem; letter-spacing: .06em; color: #e3d9c3; text-decoration: underline; text-underline-offset: .35em; padding: .6rem 1rem; min-height: 44px; }
.blessing.is-stamped .blessing-hint, .blessing.is-stamped .pbox-btn, .blessing.is-stamped .blessing-skip { display: none; }
.blessing-done { font-family: var(--font-hw); font-size: clamp(1.4rem, 5.6vw, 1.8rem); color: var(--cream-hi); line-height: 1.5; }
.blessing:not(.is-stamped) .blessing-done { display: none; }
.blessing.is-stamped .blessing-done { animation: vy-rise-s .6s .7s var(--ease-out) both; opacity: 0; transform: translateY(8px); }

.footer-contacts { display: grid; gap: .8rem; justify-items: center; padding: 2rem var(--gutter) 0; }
.contact-row { display: flex; align-items: center; gap: .6rem; }
.contact-who { font-family: var(--font-tc); letter-spacing: .12em; font-size: 1.05rem; color: var(--cream-hi); }
.contact-ico { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; border: 1px solid rgba(239, 227, 200, .4); color: var(--cream-hi); }
.contact-ico svg { width: 18px; height: 18px; fill: currentColor; }
.footer-brand { display: block; text-align: center; padding: 1.8rem var(--gutter) 0; font-family: var(--font-mono); font-size: .82rem; letter-spacing: .16em; color: #d9cfb8; text-decoration: none; }

/* ============ 燈箱（引擎 shared/utils.js） ============ */
.wk-lightbox {
  position: fixed; inset: 0; z-index: 100; display: none;
  align-items: center; justify-content: center;
  background: rgba(15, 32, 56, .95);
  padding: max(4vh, env(safe-area-inset-top, 0px)) max(4vw, env(safe-area-inset-right, 0px)) max(4vh, env(safe-area-inset-bottom, 0px)) max(4vw, env(safe-area-inset-left, 0px));
  overscroll-behavior: contain;
}
.wk-lightbox.is-open { display: flex; }
.wk-lightbox img { max-width: 100%; max-height: 86dvh; margin-inline: auto; border: 10px solid #fbf6ea; box-shadow: 0 20px 40px rgba(0, 0, 0, .5); }
.wk-lightbox button { position: absolute; color: var(--cream-hi); font-size: 2rem; line-height: 1; padding: .75rem 1rem; min-width: 44px; min-height: 44px; opacity: .9; }
.wk-lb-close { top: max(.5rem, env(safe-area-inset-top, 0px)); right: max(.75rem, env(safe-area-inset-right, 0px)); font-size: 2.4rem; }
.wk-lb-prev { left: max(.25rem, env(safe-area-inset-left, 0px)); top: 50%; transform: translateY(-50%); }
.wk-lb-next { right: max(.25rem, env(safe-area-inset-right, 0px)); top: 50%; transform: translateY(-50%); }

/* ============ 共用按鈕皮 ============ */
.btn { border-radius: 3px; font-family: var(--font-tc); font-size: 1rem; letter-spacing: .08em; padding: .8rem 1.2rem; min-height: 46px; background: var(--navy); color: var(--cream-hi); }
.btn-ghost { background: transparent; color: var(--navy); box-shadow: inset 0 0 0 1.5px var(--navy); }

/* ============ 背景音樂鈕＝一枚小郵票（覆寫 bgm.js 注入的圓鈕皮；位置與行為不動） ============ */
html body #wk-bgm-toggle {
  border-radius: 0; border: 0;
  width: 46px; height: 54px;
  background: var(--verm); color: var(--cream-hi);
  box-shadow: inset 0 0 0 3px var(--cream-hi), inset 0 0 0 4px var(--verm);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  -webkit-mask: radial-gradient(circle 3px at 50% 0, #0000 calc(100% - .5px), #000 100%) top / 9px 51% round no-repeat, radial-gradient(circle 3px at 50% 100%, #0000 calc(100% - .5px), #000 100%) bottom / 9px 51% round no-repeat;
  mask: radial-gradient(circle 3px at 50% 0, #0000 calc(100% - .5px), #000 100%) top / 9px 51% round no-repeat, radial-gradient(circle 3px at 50% 100%, #0000 calc(100% - .5px), #000 100%) bottom / 9px 51% round no-repeat;
  filter: drop-shadow(0 4px 8px rgba(43, 38, 34, .35));
}
html body #wk-bgm-toggle.is-off { background: var(--navy); }

/* ============ 字型庫 bridge（P2-26）：custom-* 是鎖定帖，不接字型庫角色；留空 ============ */


/* ================================================================
   第 2 輪（評審第 1 輪回饋，2026-10-02）——集中寫在這裡，蓋過上面
   ================================================================ */

/* ---- 字級規格：內文 ≥17px、資訊列 ≥15px、功能字 ≥12.8px ---- */
.hero-names-en { font-size: .95rem; }
.hs-coord { font-size: .95rem; }
.countdown { font-size: 1.05rem; }
.stop-text, .dc-note, .custom-text, .transport span, .rsvp-intro, .receipt p, .event-row dd span { font-size: 1.0625rem; }
.pcb-hw { font-size: clamp(1.0625rem, 4.4vw, 1.25rem); }
@media (min-width: 960px) { .pcb-hw { font-size: clamp(1.0625rem, 1.25vw, 1.15rem); } }
@media (min-width: 900px) {
  .hero-names-en, .hs-coord { font-size: 1rem; }
  .countdown { font-size: 1.1rem; }
  .cd-l { font-size: 1.05rem; }
}

/* ---- 音樂鈕：36px 圓形小郵票；底部內容讓出位置 ---- */
html body #wk-bgm-toggle {
  width: 40px; height: 40px; border-radius: 50%;
  -webkit-mask: none; mask: none;
  background: var(--verm-tx);
  box-shadow: 0 0 0 2px var(--cream-hi), 0 0 0 3.5px var(--verm-tx), 0 4px 10px rgba(43, 38, 34, .35);
  filter: none;
  right: calc(12px + env(safe-area-inset-right, 0px)); bottom: calc(12px + env(safe-area-inset-bottom, 0px));
}
html body #wk-bgm-toggle.is-off { background: var(--navy); box-shadow: 0 0 0 2px var(--cream-hi), 0 0 0 3.5px var(--navy), 0 4px 10px rgba(43, 38, 34, .35); }
html body #wk-bgm-toggle .wk-bgm-ico { width: 16px; height: 16px; }
.hs { padding-bottom: 64px; }
.footer { padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px)); }
.rsvp { padding-bottom: clamp(5rem, 13vw, 7.5rem); }

/* ---- 頂端進度條：細一點、只在捲動時出現 ---- */
.vy-progress { height: 3px; opacity: 0; transition: opacity .4s ease; }
.vy-progress.is-on { opacity: 1; }

/* ---- 首屏：撕條 1.2s 後自己抖一下、之後每 2 秒一次，手指一碰就停 ---- */
.intro-wait .env-strip { animation: vy-strip-nudge 2s 1.2s ease-in-out infinite; }
.intro.is-dragging .env-strip, .intro-commit .env-strip { animation: none; }
@keyframes vy-strip-nudge { 0%, 68%, 100% { transform: none; } 76% { transform: translateY(-2px) rotate(-.8deg); } 84% { transform: translateY(1px) rotate(.5deg); } 92% { transform: none; } }

/* ---- 手機海報：浪圖兩側漸隱、直排日文收進來、× 變成兩行之間的印記 ---- */
.ly-wave { -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 14%, #000 86%, transparent 100%); mask-image: linear-gradient(90deg, transparent 0, #000 14%, #000 86%, transparent 100%); }
@media (max-width: 899px) {
  .hs-jp { display: none; }
  /* × 併進 TOKYO 行首：小一號、置中在大寫字高 */
  .hs-x { width: .26em; height: .26em; margin-right: .08em; align-self: center; }
  .hs-x::before, .hs-x::after { height: .07em; }
  .hero-names-en { letter-spacing: .06em; }
  .sha-corner { display: none; }
  .sh-album { grid-template-columns: 1fr; }
}

/* ---- 海報進場：底部資訊早一點到終態（無 GSAP 也一樣是純 CSS） ---- */
html.wc .hero.is-on .hs-foot > * { animation-delay: .55s; }
html.wc .hero.is-on .hs-foot > :nth-child(2) { animation-delay: .62s; }
html.wc .hero.is-on .hs-foot > :nth-child(3) { animation-delay: .7s; }

/* ---- 區塊間距收緊：鬆緊有節奏 ---- */
.gallery { padding-block: clamp(3.5rem, 10vw, 6rem) clamp(3rem, 8vw, 5rem); }
.details { padding-block: clamp(3.5rem, 10vw, 6rem) clamp(2.5rem, 7vw, 4.5rem); }
.dresscode, .custom { padding-block: clamp(3rem, 9vw, 5rem); }
.secret { padding-block: clamp(3rem, 9vw, 5rem) clamp(2.5rem, 7vw, 4rem); }
.venue { padding-block: clamp(3.5rem, 10vw, 6rem); }

/* ---- 航線：飛機從卡片「後面」飛過（不壓字、不壓臉），翻面時角落小郵戳讓開 ---- */
.plane { z-index: 1; }
.stop { z-index: 2; }
.pc.is-flipped + .stop-pm { opacity: 0 !important; transition: opacity .3s; }
.pc-greet { background: rgba(15, 32, 56, .82); }
/* 背面：郵票與郵戳分開、日期讀得出來（一張卡一枚郵戳） */
.pcb-stamp { width: 30%; }
.pcb-pm { right: 36%; top: 0; width: 46%; transform: rotate(-10deg); -webkit-mask: none; mask: none; background: rgba(251, 246, 234, .9); border-width: 2px; }
.pcb-pm b, .pcb-pm i { font-size: .82rem; }

/* ---- 集郵冊：價格改實色小標 ---- */
.st-val { background: var(--cream-hi); color: var(--navy); text-shadow: none; font-size: 1.05rem; padding: .2rem .5rem; box-shadow: 0 1px 0 rgba(15, 32, 56, .25); }

/* ================= 抬頭的四種非公式版 ================= */
/* 集郵冊頁眉：燙金雙框銘牌＋左右頁碼角 */
.sh-album { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 1rem; margin-bottom: 1.6rem; }
.sha-corner { font-family: var(--font-display); font-weight: 800; font-size: 1.1rem; color: #e2c47c; border: 1.5px solid rgba(226, 196, 124, .6); width: 2.6rem; height: 2.6rem; display: grid; place-items: center; border-radius: 50%; }
.sha-plate { position: relative; text-align: center; padding: 1.1rem 1rem 1rem; border: 2px solid #c9a65a; outline: 1px solid rgba(226, 196, 124, .55); outline-offset: 5px; background: linear-gradient(180deg, rgba(255, 255, 255, .04), rgba(0, 0, 0, .12)); }
.sha-kicker, .sha-sub { font-family: var(--font-mono); font-weight: 700; font-size: .82rem; letter-spacing: .24em; color: #e2c47c; }
.sh-album .section-title { display: block; margin: .35rem auto; transform: none; background: none; border: 0; box-shadow: none; padding: 0; font-size: clamp(2rem, 8vw, 3.2rem); letter-spacing: .3em; padding-left: .3em; color: transparent; background-image: linear-gradient(180deg, #f6e3a8 0%, #d6b25e 45%, #f2dc9a 60%, #b8913a 100%); -webkit-background-clip: text; background-clip: text; text-shadow: 0 1px 0 rgba(0, 0, 0, .15); }
.sh-album .section-title { color: #e9cf86; }
@supports (-webkit-background-clip: text) { .sh-album .section-title { color: transparent; } }
.gal-hint { justify-content: center; }

/* 登機門翻牌看板 */
.sh-flap { position: relative; background: #121c2b; color: #f4d27a; padding: 1rem 1rem 1.2rem; border-radius: 10px; box-shadow: inset 0 0 0 2px #1d2b40, 0 18px 30px -18px rgba(0, 0, 0, .6); margin-bottom: 1.8rem; }
.sh-flap.reveal { opacity: 1; transform: none; }
.flap-top { display: flex; justify-content: space-between; gap: 1rem; font-family: var(--font-mono); font-weight: 700; font-size: .84rem; letter-spacing: .14em; color: #d9d2c0; border-bottom: 1px solid #2a3a52; padding-bottom: .5rem; margin-bottom: .8rem; }
.flap-row { display: flex; gap: 4px; perspective: 600px; }
.flap { position: relative; flex: 1 1 0; max-width: 3.4rem; aspect-ratio: 3 / 4; display: grid; place-items: center; background: linear-gradient(180deg, #24324a 0 49.5%, #0d1522 49.5% 50.5%, #1c2a40 50.5%); border-radius: 4px; font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 72, "wght" 800; font-size: clamp(1.5rem, 7vw, 2.6rem); color: #f7e6b0; line-height: 1; box-shadow: 0 2px 0 #070c14; transform-origin: 50% 50%; }
.flap.is-sp { background: #18233a; }
.flap-small { margin-top: .5rem; gap: 3px; }
.flap-small .flap { max-width: 1.9rem; font-family: var(--font-mono); font-size: clamp(.9rem, 3.6vw, 1.15rem); color: #9fe0b8; }
html.wc .sh-flap:not(.is-in) .flap { transform: rotateX(-88deg); }
html.wc .sh-flap.is-in .flap { animation: vy-flap .5s calc(var(--i) * 70ms) cubic-bezier(.3, 1.3, .5, 1) both; }
@keyframes vy-flap { 0% { transform: rotateX(-88deg); } 60% { transform: rotateX(10deg); } 100% { transform: rotateX(0); } }
.sh-flap .section-title { display: block; margin: 1rem 0 0; transform: none; background: none; border: 0; box-shadow: none; padding: 0; color: #f4d27a; font-size: clamp(1.5rem, 5.6vw, 2rem); letter-spacing: .2em; }
@media (min-width: 900px) { .flap { flex: 0 0 3.8rem; max-width: none; } .flap-small .flap { flex: 0 0 2rem; max-width: none; } .sh-flap { display: grid; grid-template-columns: auto 1fr; column-gap: 2rem; align-items: end; } .flap-top { grid-column: 1 / -1; } .flap-big { grid-column: 1; } .flap-small { grid-column: 1; } .sh-flap .section-title { grid-column: 2; grid-row: 2 / 4; align-self: center; justify-self: end; margin: 0; } }

/* 護照封面燙金 */
.sh-cover { display: flex; align-items: center; gap: 1.2rem; background: radial-gradient(80% 60% at 30% 20%, rgba(255, 255, 255, .08), transparent 60%), repeating-linear-gradient(45deg, rgba(0, 0, 0, .07) 0 2px, transparent 2px 5px), #1d365a; color: #e2c47c; padding: 1.3rem 1.4rem; border-radius: 8px 14px 14px 8px; box-shadow: inset 6px 0 0 #152b49, 0 20px 30px -20px rgba(0, 0, 0, .6); margin-bottom: 1.8rem; max-width: 30rem; }
.sh-cover.reveal { transform: translateY(16px); }
.sh-cover.reveal.is-in { transform: none; }
.shc-emblem { flex: none; width: 4rem; aspect-ratio: 1; border-radius: 50%; border: 2px solid #e2c47c; position: relative; }
.shc-emblem::before { content: ""; position: absolute; inset: 18%; border-radius: 50%; background: #e2c47c; -webkit-mask: radial-gradient(circle, transparent 30%, #000 31% 40%, transparent 41%), repeating-conic-gradient(#000 0 8deg, transparent 8deg 20deg); mask: radial-gradient(circle, transparent 30%, #000 31% 40%, transparent 41%), repeating-conic-gradient(#000 0 8deg, transparent 8deg 20deg); }
.shc-kicker, .shc-sub { font-family: var(--font-mono); font-weight: 700; font-size: .82rem; letter-spacing: .22em; color: #e2c47c; }
.shc-sub { font-family: var(--font-tc); font-weight: 400; letter-spacing: .3em; }
.sh-cover .section-title { display: block; margin: .3rem 0; transform: none; background: none; border: 0; box-shadow: none; padding: 0; font-size: clamp(1.7rem, 6vw, 2.4rem); letter-spacing: .24em; color: #ecd28e; text-shadow: 0 -1px 0 rgba(0, 0, 0, .35), 0 1px 0 rgba(255, 240, 200, .25); }
@media (min-width: 860px) { .sh-cover { max-width: 62rem; margin-inline: auto; } }

/* 海關章蓋在標題上 */
.sh-customs { position: relative; margin-bottom: 2rem; padding: 1rem 0 .6rem; border-top: 3px double var(--navy); border-bottom: 1.5px solid var(--navy); }
.sh-customs.reveal { transform: none; }
.shx-no { font-family: var(--font-mono); font-weight: 700; font-size: .84rem; letter-spacing: .2em; color: var(--navy); }
.sh-customs .section-title { display: block; margin: .3rem 0 0; transform: none; background: none; border: 0; box-shadow: none; padding: 0; font-size: clamp(2.4rem, 11vw, 4.2rem); letter-spacing: .12em; color: var(--ink); }
.shx-stamp { position: absolute; right: 2%; top: 50%; display: grid; place-content: center; text-align: center; padding: .4rem .9rem; border: 3.5px solid var(--verm); color: var(--verm-tx); transform: translateY(-40%) rotate(-11deg); -webkit-mask: var(--ink-mask); mask: var(--ink-mask); background: rgba(247, 240, 222, .55); line-height: 1.15; }
.shx-stamp b { font-family: var(--font-mono); font-weight: 700; font-size: clamp(1.1rem, 4.6vw, 1.6rem); letter-spacing: .1em; }
.shx-stamp i { font-style: normal; font-family: var(--font-tc); font-size: .95rem; letter-spacing: .14em; }
html.wc .sh-customs:not(.is-in) .shx-stamp { opacity: 0; transform: translateY(-40%) rotate(-24deg) scale(1.7); }
html.wc .sh-customs.is-in .shx-stamp { animation: vy-shx .5s .35s cubic-bezier(.3, 1.4, .5, 1) both; }
@keyframes vy-shx { 0% { opacity: 0; transform: translateY(-40%) rotate(-24deg) scale(1.7); } 60% { opacity: 1; transform: translateY(-40%) rotate(-11deg) scale(.95); } 100% { opacity: 1; transform: translateY(-40%) rotate(-11deg) scale(1); } }

/* ---- 票根：撕下後整塊移走；完成訊息與兩顆鈕正向直排 ---- */
.stub-after { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; margin-top: 1rem; }
.stub-after .calendar-actions { display: flex; flex-direction: column; align-items: stretch; gap: 12px; width: min(100%, 20rem); }
.stub-after .calendar-actions .btn { text-align: center; }
.stub-or, .stub-hint { font-family: var(--font-tc); font-size: 1.05rem; letter-spacing: .06em; color: var(--verm-tx); }
.stub-done { font-family: var(--font-tc); font-size: 1.05rem; line-height: 1.7; color: var(--navy); margin: 0; min-height: 0; }
.bp-stub.is-torn .stub-card { animation: vy-stub-off .6s var(--ease-in) forwards; pointer-events: none; }
@keyframes vy-stub-off { 0% { transform: rotate(calc(var(--tear) * 9deg)) translate(calc(var(--tear) * 34px), calc(var(--tear) * 10px)); opacity: 1; } 100% { transform: rotate(22deg) translate(160px, 60px); opacity: 0; } }
.bp-stub.is-gone .stub-card { display: none; }
.bp-stub.is-gone .stub-after { margin-top: .4rem; }

/* ---- 刮刮卡：申報書文字對齊橫線、靠左 ---- */
.scratch-card { background-origin: content-box; background-clip: padding-box; }
.scratch-text { text-align: left; line-height: 2.05rem; }

/* ---- 回函成功：兩欄回執、留言用手寫回顯、郵票是真圖 ---- */
.pcs-stamp { padding: 6px; background: #fbf6ea; outline: 0; box-shadow: 0 2px 6px rgba(43, 38, 34, .3); }
.pcs-stamp img { width: 100%; height: 72%; object-fit: cover; display: block; }
.pcs-stamp b { color: var(--verm-tx); font-size: .85rem; margin-top: .15rem; }
.pcard.is-no .pcs-stamp { background: #fbf6ea; }
.receipt .rsvp-stamp { position: static; }
.rc-kind { margin-bottom: .4rem; }
.rc-grid { display: grid; grid-template-columns: 1fr; gap: 1.2rem; align-items: start; }
.rc-grid .rsvp-stamp { justify-self: center; width: 9rem; border-width: 3px; transform: rotate(-10deg); }
.rc-grid .rsvp-stamp b { font-size: 1rem; }
.rc-grid .rsvp-stamp i { font-size: 1.1rem; }
.rc-grid .rsvp-stamp em { font-style: normal; font-family: var(--font-mono); font-weight: 700; font-size: .85rem; margin-top: .2rem; }
.sent-msg { margin: 1rem 0 .4rem; padding: .4rem 1rem .6rem; border-left: 3px solid var(--verm); background: repeating-linear-gradient(180deg, transparent 0 2.2rem, rgba(31, 58, 95, .18) 2.2rem calc(2.2rem + 1px)); }
.sent-msg p { font-size: clamp(1.25rem, 5vw, 1.5rem); line-height: 2.2rem; color: var(--navy-ink); margin: 0; }
.sent-msg cite { display: block; text-align: right; font-style: normal; font-family: var(--font-tc); font-size: 1rem; color: var(--ink-soft); }
@media (min-width: 640px) { .rc-grid { grid-template-columns: 1fr 11rem; } .rc-grid .rsvp-stamp { width: 10rem; margin-top: 1rem; } }

/* ---- 護照：色名＋色碼、手機一排四枚、章另起一列不壓字 ---- */
.dc-swatches { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1rem .7rem; max-width: 26rem; }
.dc-swatch { width: auto; aspect-ratio: auto; box-shadow: none; transform: none; margin: 0; display: grid; justify-items: center; gap: .3rem; text-align: center; }
.dc-swatch::before, .dc-swatch::after { display: none; }
.dc-chip { position: relative; display: block; width: 100%; max-width: 4.4rem; aspect-ratio: 3 / 4; border-radius: 5px; box-shadow: inset 0 0 0 4px rgba(255, 255, 255, .6), inset 0 0 0 5px rgba(43, 38, 34, .15), 0 3px 6px rgba(43, 38, 34, .25); transform: rotate(var(--r, 0deg)); }
.dc-chip::before { content: ""; position: absolute; inset: 0; border-radius: 5px; background: linear-gradient(125deg, transparent 30%, rgba(255, 255, 255, .45) 45%, transparent 55%); }
.dc-name { font-family: var(--font-tc); font-weight: 400; font-size: 1.0625rem; letter-spacing: .06em; color: var(--ink); line-height: 1.3; }
.dc-hex { font-family: var(--font-mono); font-size: .8rem; color: var(--ink-soft); }
html.wc .pp:not(.is-open) .dc-swatch { opacity: 0; transform: translateY(10px); }
.pp-page { padding-bottom: 3rem; }
.visa-stamp { position: relative; left: auto; right: auto; top: auto; bottom: auto; display: inline-grid; vertical-align: middle; margin: 1.6rem .8rem 0 0; }
.vs-rect { width: auto; max-width: 13rem; }
.vs-rect em { position: static; display: inline-block; justify-self: center; margin-top: .25rem; }
.pp-mrz { position: static; margin-top: 1.2rem; }
/* 出入境舊章：裝飾、不承載資訊，但至少 3:1 */
.pph-stamp { opacity: 1; color: var(--navy); }
.pph-1, .pph-3 { color: var(--verm-tx); }
.pph-2 { color: #2f5a40; }

/* ---- 地圖：點了才載 ---- */
.map-frame { position: relative; }
.map-load { position: absolute; inset: 0; display: grid; place-content: center; justify-items: center; gap: .4rem; width: 100%; background: repeating-linear-gradient(0deg, rgba(31, 58, 95, .07) 0 1px, transparent 1px 28px), repeating-linear-gradient(90deg, rgba(31, 58, 95, .07) 0 1px, transparent 1px 28px), radial-gradient(60% 50% at 60% 55%, rgba(159, 184, 208, .5), transparent 70%), #ece2c9; color: var(--navy); cursor: pointer; }
.map-load b { font-family: var(--font-tc); font-weight: 400; font-size: 1.15rem; letter-spacing: .12em; background: var(--cream-hi); padding: .5rem 1rem; border: 1.5px solid var(--navy); }
.map-load small { font-family: var(--font-tc); font-size: .95rem; color: var(--ink); max-width: 18rem; text-align: center; }
.ml-pin { width: 26px; height: 26px; border-radius: 50% 50% 50% 0; background: var(--verm); transform: rotate(-45deg); box-shadow: inset 0 0 0 7px var(--verm), inset 0 0 0 13px var(--cream-hi); }
.map-frame iframe[hidden] { display: none; }

/* ---- 片尾：一次收尾（郵簡 → 郵筒單擊 → DELIVERED 郵戳） ---- */
.pbox-btn { width: auto; height: auto; min-height: 52px; padding: .8rem 1.8rem; border-radius: 999px; background: var(--cream-hi); color: var(--verm-tx); box-shadow: 0 6px 14px rgba(0, 0, 0, .35); touch-action: manipulation; }
.pbb-core { width: auto; height: auto; background: none; box-shadow: none; font-size: 1.15rem; letter-spacing: .16em; color: inherit; padding: 0; }
.pbox-btn:active { transform: scale(.97); }
.blessing { padding-bottom: 0; }
.dl { padding-top: clamp(2rem, 6vw, 3rem); }
.dl-wave { top: calc(clamp(2rem, 6vw, 3rem) + min(39vw, 190px) - 40px); }

/* 選了章、郵票貼上去：PLACE STAMP 底字收掉；投遞後的信收進郵筒（不再可見） */
.pcard.has-choice .pcs-empty { visibility: hidden; }
.blessing.is-stamped .pb-letter { visibility: hidden; transition: transform .35s var(--ease-in), clip-path .35s var(--ease-in), visibility 0s .4s; }


/* 撕票根：票根飛走的 .6s 內，完成訊息與按鈕先不出現，等票根移走（.is-gone）才淡入，不會被壓住 */
.bp-stub.is-torn:not(.is-gone) .stub-after { opacity: 0; }
.bp-stub.is-gone .stub-after { animation: vy-fadein .35s ease both; }

/* 明信片翻面：不只靠 backface-visibility（WebKit 在祖先 transform 過渡中會壓平 3D、背面鏡像露出來）——
   背對的那一面直接 visibility:hidden，翻到 90°（這條緩動約在 .18s）切換 */
.pc:not(.is-flipped) .pc-back, .pc.is-flipped .pc-front { visibility: hidden; transition: visibility 0s .18s; }
.pc.is-flipped .pc-back, .pc:not(.is-flipped) .pc-front { visibility: visible; transition: visibility 0s .18s; }


/* ================================================================
   第 3 輪（評審第 2 輪回饋，2026-10-02）
   ================================================================ */
/* 中英混排：中文一律明體、不加粗（拉丁打字機字的粗體不拿來硬撐中文） */
.tc { font-family: var(--font-tc); font-weight: 400; letter-spacing: .1em; }
/* 夾在拉丁字之間的中文段落（span）左右留一個空：:first-child 不能用——前面的拉丁字是文字節點，不算 child */
span.tc { margin-inline: .6em; }
.rsvp .field label, .rsvp .field legend { font-family: var(--font-tc); font-weight: 400; font-size: 1rem; letter-spacing: .1em; }
.bp-grid dt .tc, .pcard-addr small .tc, .ppd-grid small .tc { font-size: .9rem; color: var(--ink); }

/* ---- P0：桌機票根撕下後，完成訊息讓開上方那條深藍帶 ---- */
@media (min-width: 900px) {
  .bp-stub.is-gone .stub-after { margin-top: 0; padding-top: 5.4rem; }
}

/* ---- 底部郵件追蹤列（進度＋狀態＋音樂鈕的位置） ---- */
.vy-dock {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 70;
  height: calc(52px + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
  background: var(--cream-hi);
  box-shadow: 0 -6px 16px -10px rgba(43, 38, 34, .45);
  transition: transform .5s var(--ease-out);
}
.vy-dock[hidden] { display: none; }
html.has-intro .vy-dock { transform: translateY(110%); }
.vy-dock .vy-progress { position: absolute; left: 0; right: 0; top: 0; height: 6px; opacity: 1; background: rgba(43, 38, 34, .12); }
.vd-line { display: flex; align-items: center; gap: .7rem; height: 52px; padding: 6px 64px 0 var(--gutter); font-family: var(--font-mono); font-weight: 700; font-size: .84rem; letter-spacing: .1em; color: var(--navy); white-space: nowrap; overflow: hidden; }
.vd-line span { font-family: var(--font-tc); font-weight: 400; font-size: .95rem; letter-spacing: .08em; color: var(--ink); overflow: hidden; text-overflow: ellipsis; }
.vd-line i { font-style: normal; margin-left: auto; color: var(--verm-tx); }
html.vy-docked body { padding-bottom: calc(52px + env(safe-area-inset-bottom, 0px)); }
html.vy-docked .footer { padding-bottom: max(2.4rem, env(safe-area-inset-bottom, 0px)); }
html.vy-docked .hs { padding-bottom: 24px; min-height: calc(100svh - 56px - 52px); }
@media (min-width: 900px) { html.vy-docked .hs { padding-bottom: 32px; min-height: calc(100svh - 68px - 52px); } }
/* 音樂鈕：44×44，停在追蹤列右端（不蓋任何內容） */
html body #wk-bgm-toggle {
  width: 44px; height: 44px;
  right: calc(10px + env(safe-area-inset-right, 0px)); bottom: calc(1px + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 0 0 2px var(--cream-hi), 0 0 0 3.5px var(--verm-tx);
}
html body #wk-bgm-toggle.is-off { box-shadow: 0 0 0 2px var(--cream-hi), 0 0 0 3.5px var(--navy); }

/* ---- 航線：飛機在卡片與內文之下（疊放順序），手機走卡片旁的空道 ---- */
.route-list { z-index: 2; }
.plane { z-index: 1; filter: none; }
@media (max-width: 899px) {
  .plane { width: 74px; }
  .route-list { gap: clamp(5.4rem, 20vw, 6.6rem); }
  .stop { width: min(80%, 28rem); }
}
/* 到站小郵戳：蓋在文字塊的紙面上（不壓照片），乾淨的章不加雜點 */
.stop-pm, .stop:nth-child(even) .stop-pm { right: .2rem; left: auto; top: -.2rem; bottom: auto; width: 4.2rem; -webkit-mask: none; mask: none; background: transparent; transform: rotate(-10deg); }
.pc.is-flipped + .stop-pm { opacity: 1 !important; }
html.fx .stop:not(.is-arrived) .stop-pm { transform: rotate(-10deg) scale(1.7); }
.stop-txt { padding-right: 4.8rem; }
/* 明信片背面郵戳：三行小字收在圓框內 */
.pcb-pm { width: 44%; line-height: 1.1; padding: 0 2px; }
.pcb-pm b, .pcb-pm i { display: block; font-size: .8rem; letter-spacing: 0; }
@media (max-width: 899px) { .pcb-pm { width: 50%; right: 32%; } .pcb-stamp { width: 28%; } }

/* ---- 信封郵票小字：深底白字 ---- */
.es-ctry { bottom: 6px; left: 6px; right: 6px; background: var(--navy-ink); padding: 2px 0; letter-spacing: .12em; }

/* ---- 集郵冊頁眉：兩行各自成句 ---- */
.sha-sub { display: flex; flex-wrap: wrap; justify-content: center; gap: 0 1.2em; }
.sha-sub > span { white-space: nowrap; }
.sha-kicker { white-space: nowrap; }
@media (max-width: 899px) { .sha-kicker, .sha-sub { letter-spacing: .16em; } .sh-album .section-title { letter-spacing: .24em; } }

/* ---- 地點抬頭：機場入境指標牌 ---- */
.sh-sign { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 1rem; background: #17263c; color: #f6efdd; padding: 1rem 1.1rem; border-radius: 6px; box-shadow: inset 0 0 0 2px #24385a, 0 18px 28px -18px rgba(0, 0, 0, .55); margin-bottom: 2rem; }
.sh-sign.reveal { transform: translateY(14px); }
.sh-sign.reveal.is-in { transform: none; }
.shs-ico { width: 3.4rem; aspect-ratio: 1; background: #f2c14e; border-radius: 6px; display: grid; place-items: center; }
.shs-ico i { width: 70%; height: 38%; background: #17263c; transform: rotate(18deg) scaleX(-1); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 60'%3E%3Cpath d='M118 30c0-3-6-5-14-5H78L52 4h-9l13 21H30l-9-10h-7l5 15-5 15h7l9-10h26L43 56h9l26-21h26c8 0 14-2 14-5z'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 60'%3E%3Cpath d='M118 30c0-3-6-5-14-5H78L52 4h-9l13 21H30l-9-10h-7l5 15-5 15h7l9-10h26L43 56h9l26-21h26c8 0 14-2 14-5z'/%3E%3C/svg%3E") center / contain no-repeat; }
.shs-kicker { font-family: var(--font-mono); font-weight: 700; font-size: .9rem; letter-spacing: .2em; color: #f2c14e; }
.shs-kicker .tc { color: #f6efdd; }
.sh-sign .section-title { display: block; margin: .15rem 0 0; transform: none; background: none; border: 0; box-shadow: none; padding: 0; color: #f6efdd; font-size: clamp(1.6rem, 6.4vw, 2.6rem); letter-spacing: .14em; }
.sh-sign .venue-tag { color: #f2c14e; margin-top: .2rem; }
.shs-arrow { width: 2.4rem; height: 2.4rem; border-top: .5rem solid #f2c14e; border-right: .5rem solid #f2c14e; transform: rotate(135deg) translate(-.4rem, .4rem); margin-right: .6rem; }
@media (max-width: 480px) { .shs-arrow { width: 1.5rem; height: 1.5rem; border-width: .36rem; margin-right: .3rem; } .shs-ico { width: 2.8rem; } }

/* ---- 行李抬頭：託運行李條 ---- */
.sh-bagtag { display: grid; grid-template-columns: 2.2rem 1fr auto 2.2rem; align-items: stretch; gap: 0; background: #fbf6ea; border: 1.5px solid var(--ink); margin-bottom: 2rem; min-height: 5.2rem; box-shadow: 4px 4px 0 var(--verm); }
.sh-bagtag.reveal { transform: translateY(14px) rotate(-.6deg); }
.sh-bagtag.reveal.is-in { transform: rotate(-.6deg); }
.sbt-bars { background: repeating-linear-gradient(180deg, var(--ink) 0 3px, transparent 3px 5px, var(--ink) 5px 6px, transparent 6px 10px, var(--ink) 10px 14px, transparent 14px 16px); margin: 6px; }
.sbt-mid { display: grid; align-content: center; gap: .1rem; padding: .6rem .8rem; border-left: 1.5px dashed rgba(43, 38, 34, .4); }
.sbt-mid small { font-family: var(--font-mono); font-weight: 700; font-size: .84rem; letter-spacing: .2em; color: var(--verm-tx); }
.sbt-mid b { font-size: clamp(1.5rem, 6vw, 2.1rem); letter-spacing: .2em; color: var(--ink); margin: 0; }
.sbt-code { display: grid; align-content: center; justify-items: end; padding: .4rem .9rem; border-left: 1.5px dashed rgba(43, 38, 34, .4); border-right: 1.5px dashed rgba(43, 38, 34, .4); line-height: 1; }
.sbt-code b { font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 144, "wght" 800; font-size: clamp(2.2rem, 10vw, 3.4rem); letter-spacing: -.02em; color: var(--navy); }
.sbt-code small { font-family: var(--font-mono); font-weight: 700; font-size: .84rem; letter-spacing: .14em; color: var(--ink); margin-top: .2rem; }

/* ---- 桌機：行李、海關改兩欄，不再一條窄欄 ---- */
@media (min-width: 900px) {
  #custom-blocks { grid-template-columns: 1fr 1fr; gap: 2.2rem; align-items: start; }
  .custom-block:nth-child(even) { margin-top: 2.2rem; }
  .sec-grid { display: grid; grid-template-columns: 1fr 1.25fr; column-gap: 4rem; align-items: center; }
  .sec-grid .sh-customs { margin-bottom: 0; }
  .sec-grid .sh-customs .section-title { font-size: clamp(3rem, 5.4vw, 5rem); }
}

/* ---- 刮卡提示：深墨字＋實底膠囊（原白字壓牛皮紙只有 1.64:1） ---- */
.scratch-hint { color: var(--ink); text-shadow: none; background: var(--cream-hi); padding: .35rem 1rem; border-radius: 999px; border: 1.5px solid var(--ink); width: max-content; max-width: 90%; left: 50%; transform: translate(-50%, -50%); top: 42%; right: auto; bottom: auto; position: absolute; margin: 0; }

/* ---- 郵筒：版畫質感（網點＋陰影線＋墨線輪廓） ---- */
.pb-body, .pb-cap { box-shadow: inset 0 0 0 2.5px #2a0d07; }
.pb-body::before, .pb-cap::before { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background:
    radial-gradient(circle at 1.5px 1.5px, rgba(42, 13, 7, .5) 1px, transparent 1.4px) 0 0 / 5px 5px,
    linear-gradient(90deg, transparent 0 52%, rgba(42, 13, 7, .5) 100%);
  -webkit-mask: linear-gradient(90deg, transparent 0 48%, #000 78%); mask: linear-gradient(90deg, transparent 0 48%, #000 78%); }
.pb-body::after { content: ""; position: absolute; left: 8%; top: 6%; bottom: 6%; width: 12%; border-radius: 4px; background: repeating-linear-gradient(180deg, rgba(255, 244, 230, .5) 0 2px, transparent 2px 6px); pointer-events: none; }
.pb-body { position: absolute; }
.pb-foot { box-shadow: inset 0 0 0 2.5px #1c0905; background: repeating-linear-gradient(90deg, #3a1a12 0 5px, #2a110b 5px 8px); }
.pb-flag { box-shadow: inset 0 0 0 2px #2a0d07, 0 2px 4px rgba(0, 0, 0, .3); }
.pbox-wrap::after { content: ""; position: absolute; left: 6%; right: 6%; bottom: -8px; height: 14px; border-radius: 50%; background: repeating-linear-gradient(90deg, rgba(0, 0, 0, .45) 0 3px, transparent 3px 6px); -webkit-mask: radial-gradient(closest-side, #000 40%, transparent 100%); mask: radial-gradient(closest-side, #000 40%, transparent 100%); }

/* 首屏以下先不排版：開頁第一輪只排首屏與航線；其餘各區由 render.js 一區一個 task 渲染、排版、量實高，
   字型到齊後再趁閒置一區一區正式解開（content-visibility: visible）——所以賓客往下捲的時候，這些區塊早就排好、畫好了。
   **只在 Chromium 系開（旗標 script 掛 html.vy-cv）**：WebKit 的 content-visibility 會讓點擊命中測試落到別的區塊
   （2026-10-02 實測：票根的位置 elementFromPoint 回傳下一區的護照頁，撕票根完全沒反應）。 */
html.vy-cv #gallery, html.vy-cv #details, html.vy-cv #dresscode, html.vy-cv #venue, html.vy-cv #custom, html.vy-cv #secret, html.vy-cv #rsvp, html.vy-cv .footer { content-visibility: auto; contain-intrinsic-size: 1000px; }
/* 佔位高度：render.js 每一區渲染完就量實高寫回 inline（字型換上來、視窗寬度變了會重量），所以整頁第一次往下捲文件高度不會跳、追蹤列不會倒退。
   這裡的數字只是「JS 還沒輪到那一區」之前的估計值（示範內容在 390／1440 寬的內容高度——contain-intrinsic-size 管的是 content box，不含這一區自己的上下 padding）。
   **刻意不寫 auto**：auto 會優先用瀏覽器記住的「上一次渲染的高度」，而開頁那一瞬間這幾區被排過一次空殼（內容還沒渲染），
   記住的是空殼的高度——集郵冊佔位只有 298px、實高 1815px，一捲到就跳 1500px（2026-10-02 實測）。
   等那一區真的捲進視窗渲染過，render.js 才改寫成 auto（之後回函展開、撕票根改了高度，離開視窗時用的是記住的實高）。 */
html.vy-cv #gallery { contain-intrinsic-size: 1711px; }
html.vy-cv #details { contain-intrinsic-size: 2028px; }
html.vy-cv #dresscode { contain-intrinsic-size: 1402px; }
html.vy-cv #venue { contain-intrinsic-size: 923px; }
html.vy-cv #custom { contain-intrinsic-size: 540px; }
html.vy-cv #secret { contain-intrinsic-size: 506px; }
html.vy-cv #rsvp { contain-intrinsic-size: 1381px; }
html.vy-cv .footer { contain-intrinsic-size: 1987px; }
@media (min-width: 900px) {
  html.vy-cv #gallery { contain-intrinsic-size: 1842px; }
  html.vy-cv #details { contain-intrinsic-size: 1137px; }
  html.vy-cv #dresscode { contain-intrinsic-size: 791px; }
  html.vy-cv #venue { contain-intrinsic-size: 657px; }
  html.vy-cv #custom { contain-intrinsic-size: 338px; }
  html.vy-cv #secret { contain-intrinsic-size: 385px; }
  html.vy-cv #rsvp { contain-intrinsic-size: 1472px; }
  html.vy-cv .footer { contain-intrinsic-size: 2037px; }
}

/* 郵票進場（IO 掛 .is-in；前置隱藏態只在 html.wc 底下） */
html.wc .st:not(.is-in) .st-shadow { opacity: 0; transform: translateY(42px) rotate(4deg); }
html.wc .st .st-shadow { transition: opacity .6s ease, transform .9s cubic-bezier(.2, 1.3, .4, 1); transition-delay: calc(var(--i, 0) * 90ms); }

/* 手機海報收一點高度：倒數那一行不要掉到追蹤列底下 */
@media (max-width: 899px) { .hs-art { min-height: clamp(270px, 35svh, 460px); } .hs { padding-top: 22px; } }

/* 桌機：海關章蓋在標題下緣外側，不遮字 */
@media (min-width: 900px) { .sec-grid .shx-stamp { right: auto; left: 55%; top: 100%; } }


/* ================================================================
   第 4 輪（評審第 3 輪回饋，2026-10-02）
   ================================================================ */

/* ---- 捲軸溝槽固定：開場鎖捲動（overflow:hidden）與收場後的版面寬度一致——
        桌機原本收場那一刻捲軸冒出來、整頁變窄 15px，全部重排，而且開場期間量到的各區實高全部失準 ---- */
html { scrollbar-gutter: stable; }
html.has-intro { background: linear-gradient(180deg, #0f2038, #152c4a 50%, #0f2038) #142a47; }   /* 開場時溝槽那一條露出來的是 html 底色：照桌面在右緣的顏色配 */

/* ---- 名字排版：字級＝容器寬 ÷ 一行的字寬數（--n 由 index.html 的 __vyFit 算；不量版面） ----
   用法：節點掛 .vy-fit，父層開 container-type: inline-size，再給 --fit-base（上限字級）。
   不支援 container query 單位的舊瀏覽器走 --fit-k（上限字級下一行放得下幾個字寬）等比縮。 */
/* 選擇器寫兩次＝特異度壓過各處原本的「.xxx b { font-size }」 */
.vy-fit.vy-fit { white-space: nowrap; font-size: var(--fit-base, 1em); }
@supports (width: 1cqw) { .vy-fit.vy-fit { font-size: min(var(--fit-base, 1em), calc((100cqw - var(--fit-pad, 0px)) / var(--n, 3))); } }
@supports not (width: 1cqw) { .vy-fit.vy-fit { font-size: calc(var(--fit-base, 1em) * min(1, var(--fit-k, 4) / var(--n, 3))); } }
.vy-fit.vy-fit[data-lines="2"] { white-space: normal; text-wrap: balance; overflow-wrap: anywhere; line-height: 1.14; }
/* 會自己折行的名字欄位（回函寄件人、票根、護照、登機證）：折行時兩行等長，不留孤字 */
#rsvp-guest, #stub-name, #pp-holder, .bp-grid dd.hw, .blessing-lead, .hero-greeting { text-wrap: balance; }
/* 帶名字的短句（「○○，這封信，已經送到你手上了」）：只在標點斷行，不把「這封／信」拆開；名字太長才硬斷 */
.dl-line, .blessing-lead, .hero-greeting { word-break: keep-all; overflow-wrap: anywhere; }

/* ---- 信封 ---- */
.env { --st: 17%; }
.env-airmail { top: 32.5%; padding: .3rem .55rem; letter-spacing: .06em; }   /* 讓開上面的標語框與圓戳 */
.env-airmail b { font-size: .86rem; letter-spacing: .08em; }
@media (min-width: 760px) and (min-aspect-ratio: 1/1) { .env-airmail { top: 42%; } }
/* 寄件人：FROM 標籤跟名字排同一列（省一列高度），地址底緣離撕條 ≥ 6px（原本貼死、320 寬還會壓進撕條） */
.env-from { top: 21%; line-height: 1.2; grid-template-columns: auto 1fr; column-gap: .55em; align-items: baseline; }
.env-from b { font-size: 1.05rem; }
.env-from span { grid-column: 1 / -1; }
.env-to { container-type: inline-size; }
.et-name { --fit-base: clamp(2.3rem, 12vw, 3.6rem); --fit-pad: 8px; --fit-k: 5.4; }
.env-letter { container-type: inline-size; }
.el-dear { --fit-base: 1.05rem; --fit-pad: 28px; --fit-k: 13; }
@media (min-width: 760px) and (min-aspect-ratio: 1/1) {
  .env-to { right: 15%; }                            /* 橫式：收件欄讓出右邊一欄給直排的「春の台北へ」（原本被底線橫穿） */
}
/* 很矮或很窄的手機：規則在檔尾「第 5 輪」（信封高度下限／矮螢幕縮信封、拿掉 BY AIR MAIL 框） */
@media (min-width: 760px) and (min-aspect-ratio: 1/1) {
  .env { width: min(62vw, 640px, calc((100svh - 150px) * 1.6)); }
}
/* 圓戳：只放日期；標語框：致 ○○ */
.pm-center { inset: 24%; line-height: 1; gap: 2px; justify-items: center; }
.pm-center small { font-family: var(--font-mono); font-weight: 700; font-size: .8rem; letter-spacing: .08em; }
.pm-center small:last-child { font-family: var(--font-tc); font-weight: 400; letter-spacing: .24em; padding-left: .24em; }
.pm-center b { font-family: var(--font-display); font-weight: 800; font-variation-settings: "opsz" 48, "wght" 800; font-size: clamp(1.05rem, 5.4vw, 1.45rem); letter-spacing: -.01em; white-space: nowrap; }
.env-slogan {
  left: 7%; top: 8%; width: 33%;
  display: grid; align-content: center; justify-items: center; gap: 1px;
  padding: .5rem 6px .45rem;
  border-top: 2.5px solid currentColor; border-bottom: 2.5px solid currentColor;
  color: var(--navy);
  container-type: inline-size;
  opacity: 0;
  transform: rotate(-3deg);
  -webkit-mask: var(--ink-mask); mask: var(--ink-mask);
  -webkit-mask-size: 160px; mask-size: 160px;
}
.env-slogan::before { content: ""; position: absolute; left: 0; right: 0; top: 3px; bottom: 3px; border-top: 1px solid currentColor; border-bottom: 1px solid currentColor; pointer-events: none; }
.sl-tag { justify-self: start; font-family: var(--font-mono); font-weight: 700; font-size: .8rem; letter-spacing: .12em; line-height: 1.1; white-space: nowrap; }
#intro-pm-name { --fit-base: 1.45rem; --fit-pad: 2px; --fit-k: 4; font-weight: 400; color: var(--navy-ink); line-height: 1.15; text-align: center; }
#intro-pm-name[data-lines="2"] { --fit-base: 1.05rem; }
@media (min-width: 760px) and (min-aspect-ratio: 1/1) {
  .env-slogan { left: auto; right: 39%; top: 9%; width: 28%; }
}
/* 先蓋「致 ○○」的標語框（.36s），圓戳接著蓋（.5s）：名字是這一幕的主角，先到、停最久 */
.intro-commit .env-slogan { animation: vy-slogan .34s .36s cubic-bezier(.3, 1.4, .5, 1) both; }
.intro-commit .env-postmark { animation-delay: .5s; }
.intro-commit .env { animation-delay: .38s; }
@keyframes vy-slogan {
  0% { opacity: 0; transform: rotate(-9deg) scale(1.5); }
  55% { opacity: 1; transform: rotate(-3deg) scale(.95); }
  100% { opacity: .94; transform: rotate(-3deg) scale(1); }
}
/* 郵戳蓋下後多停 0.7 秒才退場（「致 ○○」原本只讀得到約 0.65 秒）：信封飛走 .76s → 1.5s、桌面淡出 .8s → 1.54s。
   看門狗（index.html 的行內 script）排在 2.4s，比桌面淡出結束的 1.84s 晚半秒以上。 */
.intro-commit .env-wrap { animation: vy-env-out .44s 1.5s var(--ease-in) forwards; }
.intro-commit .intro-desk { animation: vy-desk-out .3s 1.54s ease forwards; }

/* ---- 航線 ---- */
/* 明信片的高度跟內容：正反兩面疊在同一格 grid，3:2 是下限（由一個佔位偽元素撐），背面手寫字多就整張長高——
   原本固定 3:2、背面絕對定位，窄卡片上最後一行會被裁掉 */
.pc { aspect-ratio: auto; }
.pc-inner { position: relative; inset: auto; display: grid; grid-template-columns: minmax(0, 1fr); }
/* 佔位偽元素寬度釘 100%、不拉伸：讓它被拉高的話，aspect-ratio 會反過來把寬度撐成 1.5 倍的高，整張卡片比欄位還寬 */
.pc-inner::before { content: ""; grid-area: 1 / 1; width: 100%; aspect-ratio: 3 / 2; align-self: start; pointer-events: none; }
.pc-face { position: relative; inset: auto; grid-area: 1 / 1; min-width: 0; }
.pc-front img { position: absolute; left: 8px; top: 8px; width: calc(100% - 16px); height: calc(100% - 16px); }
.pc-flipme { right: 12px; top: 12px; bottom: auto; width: 2.75rem; height: 2.75rem; font-size: .95rem; }
.pc-greet { left: 18px; top: 18px; letter-spacing: .14em; }
.pc-back { container-type: inline-size; grid-template-columns: 1.2fr 1fr; align-items: stretch; gap: 10px; padding: 14px 12px 12px; }
.pcb-hw { font-size: clamp(1.0625rem, 6.2cqw, 1.5rem); line-height: 1.5; overflow-wrap: anywhere; align-self: center; }
@media (min-width: 960px) { .pcb-hw { font-size: clamp(1.0625rem, 6.2cqw, 1.5rem); } }
.pcb-right { display: flex; flex-direction: column; justify-content: flex-end; gap: .45rem; min-width: 0; padding-left: 8px; }
.pcb-top { display: flex; justify-content: flex-end; align-items: flex-start; margin-bottom: auto; padding-bottom: .6rem; }
.pcb-stamp { position: relative; right: auto; top: auto; flex: none; width: min(3rem, 11cqw); aspect-ratio: 4 / 5; outline-width: 1.5px; outline-offset: -4px; }
@media (max-width: 899px) { .pcb-stamp { width: min(3rem, 11cqw); } }
/* 背面郵戳：正圓（原本被三行字撐成橢圓）、三行字收在圓內；壓住郵票左緣一點＝註銷 */
.pcb-pm, .pcb-pm:not(#_) { position: relative; right: auto; top: auto; flex: none; width: 3.9rem; height: 3.9rem; aspect-ratio: auto; box-sizing: border-box; padding: 0; margin-right: -5px; z-index: 1; line-height: 1.08; background: rgba(251, 246, 234, .86); }
.pcb-pm b, .pcb-pm i { white-space: nowrap; }
.pcb-to { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; word-spacing: -.25em; }
.pcb-to .tc { margin-inline: 0; letter-spacing: 0; }   /* 前面的拉丁字後面已經有一個空白，不再另外留邊（320 寬的卡片差 5px 就放不下） */
/* 到站小郵戳：蓋在卡片右下角，一半壓卡緣、一半落在日期那一列右邊的空白——不壓照片主體、不壓字；內文吃滿卡寬 */
.stop-pm, .stop:nth-child(even) .stop-pm { position: absolute; right: -6px; left: auto; top: auto; bottom: -2.15rem; width: 4rem; z-index: 3; background: rgba(247, 240, 222, .94); transform: rotate(-10deg); }
.pc.is-flipped + .stop-pm { opacity: 0 !important; transition: opacity .3s; }
.route-list { grid-template-columns: minmax(0, 1fr); }   /* 欄寬釘在容器寬：auto 欄會被最長那段內文的 max-content 撐爆 */
.stop-txt { padding-right: .4rem; }
.stop-date { padding-right: 4.2rem; }
.stop-title { text-wrap: balance; }
.stop-text { max-width: none; }
@media (min-width: 960px) {
  /* 桌機：兩欄交錯，中間留一條走道給飛機（原本四張一排：卡片 212–253px、內文一行 6–9 個字、航線從卡片上方拱過被遮） */
  .route { padding: 7rem 0 8.5rem; }
  .route-list { grid-template-columns: repeat(2, minmax(0, min(30rem, 43%))); justify-content: space-between; gap: 3.5rem 0; align-items: start; }
  .stop { width: 100%; }
  .stop:nth-child(even) { margin-top: 11rem; }
  .pc-place { font-size: clamp(2.6rem, 4.4vw, 4rem); left: 22px; bottom: 14px; }
  .plane { width: var(--plane-w, 120px); }
  .stop-pm, .stop:nth-child(even) .stop-pm { width: 4.6rem; bottom: -2.4rem; font-size: .88rem; }
  .stop-date { font-size: 2rem; padding-right: 5rem; }
  .stop-title { font-size: 1.55rem; }
  .pc-back { padding: 20px 20px 18px; gap: 18px; }
  .pcb-pm, .pcb-pm:not(#_) { width: 4.4rem; height: 4.4rem; }
  .pcb-pm b, .pcb-pm i { font-size: .9rem; }
  .pcb-to { font-size: .9rem; }
  .pcb-to b { font-size: 1.2rem; }
}

/* ---- 護照簽證章：一行寫完（原本「春／裝」拆成兩行） ---- */
.vs-rect { max-width: 16rem; }
.vs-rect b, .vs-rect span { white-space: nowrap; }
.vs-rect .tc { margin-inline: .4em 0; }

/* ---- 回函 ---- */
.field-row { align-items: end; }                       /* 欄名折行時，三顆步進器照樣對齊在同一條基線 */
.rsvp .stepper input { min-height: 44px; }
.sc-face { right: 8.2rem; container-type: inline-size; }
.sc-face b { --fit-base: 2rem; --fit-k: 5; line-height: 1.12; }
.sc-face b[data-lines="2"] { --fit-base: 1.5rem; }
@media (min-width: 900px) {
  /* 桌機：右半是明信片的地址面（橫線），橡皮章跟著捲動停在視窗裡——填到哪一欄，章都在手邊；右半不再一片空白 */
  .rsvp-form::before { content: ""; grid-column: 2; grid-row: 1 / span 12; align-self: stretch; border-left: 1.5px solid rgba(43, 38, 34, .3); background: repeating-linear-gradient(180deg, transparent 0 3.6rem, rgba(43, 38, 34, .16) 3.6rem calc(3.6rem + 1px)) 2rem 1.2rem / calc(100% - 2rem) 100% no-repeat; }
  .rsvp-form > .stamp-row { grid-row: 1 / span 12; align-self: start; position: sticky; top: 20vh; border-left: 0; margin: 1.6rem 0 1.6rem 2rem; padding: 1rem 1rem 1rem 0; background: #fbf6ea; }
}

/* ---- 「直接拆封」是長輩的退路：做成一顆正式的次要按鈕（原本是全頁最淡的字，像素對比 3.54） ---- */
.scratch-open { display: inline-flex; align-items: center; justify-content: center; margin-top: 1.1rem; font-size: 1.0625rem; font-weight: 700; letter-spacing: .14em; color: var(--navy-ink); text-decoration: none; background: var(--cream-hi); box-shadow: inset 0 0 0 1.5px var(--navy); border-radius: 3px; min-height: 48px; padding: .6rem 1.5rem; }
.scratch-open[hidden] { display: none; }
/* 13px 級的中文一律升到 15px（明體橫筆在 1× 螢幕只剩 1px）；月曆星期列另外加粗 */
/* 星期列改粗黑體：明體的橫筆再怎麼加粗都只有 1px，「一二三」在 1× 螢幕糊成灰線（像素對比 2 上下） */
.wk-cal-wd { font-family: system-ui, "PingFang TC", "Microsoft JhengHei", "Noto Sans TC", "Noto Sans CJK TC", sans-serif; font-size: .95rem; font-weight: 700; color: var(--ink); }
.hs-label span:last-child, .env-airmail i, .shc-sub, .pp-head span:nth-child(2), .bp-grid dt .tc, .pcard-addr small .tc, .ppd-grid small .tc, .cap-note, .rsvp .field .error-text, .et-addr, .bp-kind span, .pcs-stamp em { font-size: .95rem; }

/* ---- 片尾：郵筒上的信、DELIVERED ---- */
.pb-slot { left: 2rem; right: 2rem; }
.pb-letter { left: 2.2rem; right: 2.2rem; top: -.25rem; height: 5rem; padding: 0 4px; container-type: inline-size; transform: translateY(calc(var(--drop, 0) * 5rem)); }
.pb-letter b { --fit-base: 1.3rem; --fit-pad: 4px; --fit-k: 4.3; max-width: none; overflow: visible; text-align: center; line-height: 1.15; }
.pb-letter b[data-lines="2"] { --fit-base: 1.15rem; }
/* 最後一屏整屏留給 DELIVERED：郵筒要先整個捲離視窗上緣，郵戳才自己蓋（沒投遞的人的收尾） */
.dl { min-height: calc(100svh - 44px); align-content: center; padding-top: 2rem; padding-bottom: 2.5rem; }
.dl-wave { position: relative; left: auto; top: auto; grid-area: 1 / 1; align-self: center; justify-self: center; width: calc(100% + 2 * var(--gutter)); max-width: none; }
.dl-mark { grid-area: 1 / 1; }
.dl-center { inset: 20.5%; container-type: inline-size; }
.dl-center b { --fit-base: clamp(2.2rem, 11vw, 3.6rem); --fit-pad: 14px; --fit-k: 3.8; max-width: none; overflow: visible; text-align: center; line-height: 1.1; }
.dl-center b[data-lines="2"] { --fit-base: clamp(1.7rem, 8.4vw, 2.7rem); }

/* ---- 追蹤列降噪：44px、往下捲收成一條條紋進度、底色跟著區塊走、音樂鈕線框（播放中才實心） ---- */
.vy-dock { height: calc(44px + env(safe-area-inset-bottom, 0px)); background: #f7f0de; color: var(--navy); transition: transform .45s var(--ease-out), background-color .4s ease, color .4s ease; }
.vy-dock[data-tone="dark"] { background: #12233d; color: #f7f0de; box-shadow: 0 -1px 0 rgba(239, 227, 200, .2); }
.vy-dock .vy-progress { height: 4px; }
.vy-dock[data-tone="dark"] .vy-progress { background: rgba(239, 227, 200, .2); }
.vd-line { height: 44px; padding: 4px 60px 0 var(--gutter); color: inherit; }
.vd-line span { color: var(--ink); }
.vy-dock[data-tone="dark"] .vd-line span { color: #f7f0de; }
html.vy-dock-min .vy-dock { transform: translateY(calc(100% - 4px)); }
html.has-intro .vy-dock { transform: translateY(110%); }
html.vy-docked body { padding-bottom: calc(44px + env(safe-area-inset-bottom, 0px)); }
html.vy-docked .hs { min-height: calc(100svh - 56px - 44px); }
@media (min-width: 900px) { html.vy-docked .hs { min-height: calc(100svh - 68px - 44px); } }
html body #wk-bgm-toggle {
  width: 44px; height: 44px;
  right: calc(8px + env(safe-area-inset-right, 0px)); bottom: env(safe-area-inset-bottom, 0px);
  border-radius: 50%; box-shadow: none;
  background: radial-gradient(circle, var(--verm-tx) 0 16.5px, transparent 17px);
  color: var(--cream-hi);
  transition: translate .45s var(--ease-out), opacity .3s, visibility .3s;
}
html body #wk-bgm-toggle.is-off { background: radial-gradient(circle, transparent 0 15px, currentColor 15px 16.5px, transparent 17px); color: var(--navy); box-shadow: none; }
html[data-dock-tone="dark"] body #wk-bgm-toggle.is-off { color: #f7f0de; }
html.vy-dock-min body #wk-bgm-toggle { translate: 0 56px; }


/* ================================================================
   第 5 輪（評審第 4 輪回饋，2026-10-02）
   前幾輪都用 390 寬測，360–384 與 320 的相撞沒抓到；常設檢查補了「窄寬相撞矩陣」（qa/narrow.mjs）。
   ================================================================ */

/* ---- 信封：360–384 寬「TO.」被 BY AIR MAIL 框壓住 ----
   框是從上面算位置、收件欄是從下面算，信封一矮兩個就撞。直式信封給一個高度下限（不再跟著寬度一路變矮）；
   視窗本身就矮的手機（≤700px 高）放不下這個高度：拿掉 BY AIR MAIL 框與直排日文、信封依視窗高度縮。 */
@media (max-width: 759px) and (min-height: 701px) {
  .env { min-height: 460px; }
}
@media (max-width: 759px) and (max-height: 700px), (max-width: 350px) {
  .env { width: min(82vw, 370px, calc((100svh - 250px) * .714)); }
  .env-airmail, .env-jp { display: none; }
}
@media (max-width: 350px) {
  .env-flight { display: none; }                       /* 320 寬：寄件地址跟航班號擠在同一列 */
}
.env-jp { top: 41%; }                                   /* 直排日文離郵票底緣遠一點（原本頂端貼著郵票） */
@media (min-width: 760px) and (min-aspect-ratio: 1/1) { .env-jp { top: 52%; } }
/* 收件人名字的寬度上限扣掉右邊那一欄直排日文（5 個字的名字末字原本貼上去） */
.et-name { --fit-pad: calc(10cqw + 6px); }
@media (min-width: 760px) and (min-aspect-ratio: 1/1) { .et-name { --fit-pad: 8px; } }

/* ---- 登機證欄名：英文、中文各自不折，兩個放不下同一行就拆兩行（≤360 寬「PASSENGER · 旅客」原本壓到隔壁欄） ---- */
.bp-grid dt { white-space: normal; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 .5em; }
.bp-grid dt .dt-en { white-space: nowrap; }
.bp-grid dt .tc { margin: 0; white-space: nowrap; }
.flap-top > span { white-space: nowrap; }
@media (max-width: 360px) { .flap-top { letter-spacing: .06em; gap: .6rem; } .flap-top .tc { margin-inline: .35em; } }

/* ---- 片尾註銷波浪線：畫完之後拿掉 dasharray（pathLength＋non-scaling-stroke 在寬螢幕會讓線斷一截） ---- */
.dl-wave path { stroke-dasharray: none; }
html.wc .dl:not(.is-stamped) .dl-wave path { stroke-dasharray: 1; stroke-dashoffset: 1; }
html.wc .dl.is-stamped .dl-wave path { stroke-dasharray: 1; stroke-dashoffset: 1; animation: vy-draw .8s .35s ease-out forwards, vy-undash .01s 1.5s forwards; }
html.wc .dl.is-stamped .dl-wave path:nth-child(2) { animation-delay: .45s, 1.6s; }
html.wc .dl.is-stamped .dl-wave path:nth-child(3) { animation-delay: .55s, 1.7s; }
html.wc .dl.is-stamped .dl-wave path:nth-child(4) { animation-delay: .65s, 1.8s; }
@keyframes vy-undash { to { stroke-dasharray: none; stroke-dashoffset: 0; } }
/* 送達句等郵戳蓋下才出現（原本比郵戳早 0.9 秒） */
html.wc .dl:not(.is-stamped) .dl-line { opacity: 0; transform: translateY(8px); }
html.wc .dl.is-stamped .dl-line { transition: opacity .6s .6s ease, transform .6s .6s var(--ease-out); }
/* 名字＋逗號綁成一塊：名字太長要硬斷時，逗號跟著最後幾個字走，不會掉到下一行行首 */
.vy-who { display: inline-block; max-width: 100%; word-break: normal; overflow-wrap: anywhere; }

/* ---- 手機護照：持照人資料頁改成排在簽證頁上面的一頁（原本翻到左邊、整頁在視窗外，賓客名與出入境章只有桌機看得到）。
        封面蓋在資料頁上，進場時往左掀開。 ---- */
@media (max-width: 859px) {
  .pp { display: grid; gap: 1.1rem; }
  .pp-leaf, html.wc .pp:not(.is-open) .pp-leaf { position: relative; left: auto; top: auto; width: auto; height: auto; order: -1; transform: none; transition: none; }
  .pp-data { position: relative; inset: auto; transform: none; -webkit-backface-visibility: visible; backface-visibility: visible; }
  .pp-cover {
    -webkit-backface-visibility: visible; backface-visibility: visible;
    z-index: 2; transform-origin: 0 50%;
    opacity: 0; visibility: hidden; transform: perspective(1400px) rotateY(-100deg);
    transition: transform 1.1s cubic-bezier(.55, .05, .25, 1), opacity .45s .6s, visibility 0s 1.1s;
  }
  html.wc .pp:not(.is-open) .pp-cover { opacity: 1; visibility: visible; transform: none; transition: none; }
}

/* ---- 回函 ---- */
.rsvp .field label .lab-sub { margin-left: .5em; font-size: .8rem; letter-spacing: .04em; color: var(--ink-soft); white-space: nowrap; }
#f-name-hint { margin-top: .35rem; }

/* ---- 雜項 ---- */
.stop-text { text-wrap: pretty; }                      /* 段落最後一行不留孤字 */
.stop-text .nb { white-space: nowrap; }                /* 舊瀏覽器沒有 pretty：render.js 把最後 5 個字綁成一塊 */
.st-pic:focus-visible { outline: 3px solid var(--navy); outline-offset: 3px; }
.bp-sub .tc { font-size: .95rem; color: var(--ink); }  /* 「當天流程」12.8px 朱紅明體像素對比只有 3.92 */
