/* ============================================================
   wedding-stitch｜一針一線（一塊繡布）
   概念：喜帖＝一塊亞麻布，所有線條都是一色繡線一針一針縫出來的。
   - 開場「拆線」：兩片布被一道梯形縫從中間縫起來，賓客拉住底下的線頭往上拆，
     針腳一針一針被拆開、兩片布分開；縫在正中間的縮寫繡字飛進 Hero 落定（一鏡到底）
   - Hero：方形木繡框裡的婚紗照（照片四周一圈針腳）、縮寫繡字、輪廓繡的名字、布標婚期
   - Gallery 原生版式「布標補丁」（patch）＝鋸齒縫邊的布片拼接，圖說是縫在下緣的小布標
   - 終章「十字繡」：按住不放，一格一格繡出賓客的名字；蓄滿打結、線尾剪斷
   動態語彙：針腳一針一針縫出（steps() 分段，不是平滑掃過）、線頭輕晃、布料只用光影不用 3D。
   色彩與間距 token 覆寫自 /shared/base.css。

   ── 這一套的五條體系規則，改這份檔案前先讀 ──
   ① 材質是布與線，不是紙：沒有膠帶、沒有拍立得、沒有蠟封、沒有圓形繡框（圓是牽手日常的池畔）。
      框一律是「方形木繡框」或「縫上去的一圈針腳」。
   ② 靜就是貴：把針腳全拿掉，版面仍是一張乾淨、留白、單一強調色、襯線標題的喜帖。
      針腳只出現在「邊」與「分隔」上，內容區塊本身不加花。
   ③ 強調色分兩階：--accent＝繡線（裝飾、面積小），--accent-tx＝當文字與實色按鈕底
      （對紙與對 --sand 都 ≥4.5）。新增配色要兩個一起給（同韓系 UX-P0-1）。
   ④ 「縫出來」一律 steps()：針腳是一針一針出現的，平滑的 dashoffset 掃描讀起來像畫筆不像針線。
      而且 clip／遮罩掛在 ::before 或子元素上，絕不掛在 .reveal 本身（零面積元素 IO 永遠判定不在畫面裡）。
   ⑤ 會一直動的東西（鈕扣的線頭、終章的針）預設 paused，只有捲進畫面才 running（.is-live）。
   ============================================================ */

:root {
  --paper:        #f1ece1;              /* 亞麻 */
  --paper-raise:  #fbf8f2;              /* 布標、卡片、輸入框（漂白過的棉布） */
  --ink:          #2f2a24;              /* 深棕墨（正文／標題），對紙 12 */
  --ink-soft:     #5a5147;              /* 次要文字（對紙 6.6／對 --sand 5.9；R3：WebKit 細字偏灰，加深一階） */
  --accent:       #b2453a;              /* 茜紅線（唯一強調色：針腳、繡字），對紙 4.7 */
  --accent-tx:    #93352b;              /* 茜紅「當文字用」與實色按鈕底（對紙 6.4／對 --sand 5.7） */
  --accent-ink:   #fbf8f2;              /* 強調色底上的文字色 */
  --hairline:     rgba(47, 42, 36, .14);
  --ink-rgb:      47, 42, 36;           /* 墨的 rgba 家族單一來源 */
  --sand:         #e6dfd0;              /* RSVP：換一塊顏色深一點的布 */
  --scratch-a:    #e4dccb;              /* 刮刮樂塗層＝一塊亞麻補布 */
  --scratch-b:    #d6ccb7;
  --warn:         #8a3a24;              /* 錯誤字（對 --paper-raise 7.4／對 --sand 5.8） */
  /* 木繡框：物件本色（同拍立得白框的例外——這是木頭，不是設計選色），四組配色共用 */
  --wood:         #c8a67c;
  --wood-d:       #9d7b55;
  --wood-l:       #e0c8a3;
  --wood-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' stitchTiles='stitch' baseFrequency='.012 .22' numOctaves='3' seed='7'/%3E%3CfeColorMatrix values='0 0 0 0 .32  0 0 0 0 .2  0 0 0 0 .09  0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23g)' opacity='.55'/%3E%3C/svg%3E");
  --font-sans-tc: "Noto Sans TC", "PingFang TC", sans-serif;
  --font-serif-latin: "Cormorant Garamond", "Georgia", serif;

  --radius: .5rem;                      /* 布與木頭：小圓角 */
  --section-y: clamp(3.2rem, 9.5vw, 6rem);
  --shadow-soft: 0 22px 50px -30px rgba(var(--ink-rgb), .34);
  /* 針腳：一針 9px、間隔 5px（跟著字級走的另外算） */
  /* 手縫的針腳（R2 評審：機器虛線讀成 dashed border）：一組 66px 的循環裡五針長短不一（8／7／9／7／8）、
     間距不一、圓頭——當遮罩用，顏色由元素自己的 background 決定（四組配色與自由取色自動跟）。
     --st-frame＝四邊一圈（上下用橫的、左右用直的），掛在 ::before／::after 上。 */
  --st-h: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='66' height='4'%3E%3Cpath d='M3 2h8M16 2h7M28 2h9M42 2h7M54 2h8' stroke='%23000' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
  --st-v: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='66'%3E%3Cpath d='M2 3v8M2 16v7M2 28v9M2 42v7M2 54v8' stroke='%23000' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
  --st-frame: var(--st-h) top left / 66px 4px repeat-x, var(--st-h) bottom left / 66px 4px repeat-x, var(--st-v) top left / 4px 66px repeat-y, var(--st-v) top right / 4px 66px repeat-y;
  --st-frame-s: var(--st-h) top left / 44px 3px repeat-x, var(--st-h) bottom left / 44px 3px repeat-x, var(--st-v) top left / 3px 44px repeat-y, var(--st-v) top right / 3px 44px repeat-y;
  /* 亞麻織紋：經緯兩組 1px 細線＋幾條粗細不勻的竹節紗（極淡，關掉質感檔位＝素面） */
  --linen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='w'%3E%3CfeTurbulence type='fractalNoise' stitchTiles='stitch' baseFrequency='.9 .045' numOctaves='2' seed='3' result='a'/%3E%3CfeTurbulence type='fractalNoise' stitchTiles='stitch' baseFrequency='.045 .9' numOctaves='2' seed='9' result='b'/%3E%3CfeComposite in='a' in2='b' operator='arithmetic' k2='.5' k3='.5'/%3E%3CfeColorMatrix values='0 0 0 0 .18  0 0 0 0 .16  0 0 0 0 .13  0 0 0 -1.6 1.02'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23w)' opacity='.14'/%3E%3C/svg%3E") 0 0 / 300px 300px;
}

/* ---------- 配色變體：靛藍線（config.theme = "indigo"）----------
   只覆寫色彩 token、版式一律不動（DESIGN.md §7）。預設茜紅是暖調，這組走冷。 */
html[data-wk-theme="indigo"] {
  --accent:     #3f5f8f;
  --accent-tx:  #2f4c78;
  --accent-ink: #f8f9fb;
  --sand:       #e2e1da;
  --scratch-a:  #cfd3d8;
  --scratch-b:  #bcc2cb;
}
/* ---------- 配色變體：橄欖線（config.theme = "olive"）----------
   冷調（偏綠），比靛藍柔；與赭金互為冷暖。 */
html[data-wk-theme="olive"] {
  --accent:     #6b7a3a;
  --accent-tx:  #515d27;
  --accent-ink: #fafbf5;
  --sand:       #e3e1d0;
  --scratch-a:  #d6d6be;
  --scratch-b:  #c4c6a8;
}
/* ---------- 配色變體：赭金線（config.theme = "ochre"）----------
   暖調，像舊繡線的金。--accent 只給針腳（對紙 3.1，面積小的裝飾），文字一律走 --accent-tx。 */
html[data-wk-theme="ochre"] {
  --accent:     #b07d2a;
  --accent-tx:  #80591a;
  --accent-ink: #fdfaf2;
  --sand:       #ebe3cf;
  --scratch-a:  #e2d3b2;
  --scratch-b:  #d4c095;
}

/* 主按鈕底色壓 --accent-tx（規則③）；次按鈕＝描邊 */
.btn:not(.btn-ghost) { background: var(--accent-tx); border-radius: var(--radius); }
.on-dark .btn:not(.btn-ghost) { background: var(--accent-ink); color: var(--accent-tx); }
/* 次要按鈕＝一塊縫上去的漂白棉：只有一圈紅色手縫針腳，不再疊灰色實線框（R7-B：雙框像樣式殘留） */
.btn-ghost { border-radius: var(--radius); background: var(--paper-raise); box-shadow: 0 6px 14px -12px rgba(var(--ink-rgb), .6); }
.btn-ghost:hover { box-shadow: 0 8px 18px -12px rgba(var(--ink-rgb), .7); }
.btn-ghost { position: relative; }
.btn-ghost { box-shadow: none; color: var(--accent-tx); background: var(--linen), #e9e1d1; }
.btn { border-radius: 0;
  --z: 3.5px;
  -webkit-mask: conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y, conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y, linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
  mask: conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y, conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y, linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
}
.btn:focus-visible { outline: 2px solid var(--accent-tx); outline-offset: 4px; }
/* 次要按鈕：亞麻布片裡縫一圈茜紅針腳，一眼看得出是按鈕（R13：淡米底淡紅字不像按鈕） */
.btn-ghost::before { content: ""; position: absolute; inset: 6px; background: var(--accent); -webkit-mask: var(--st-frame-s); mask: var(--st-frame-s); pointer-events: none; }
.btn-ghost { font-weight: 500; }
/* 實色按鈕裡面縫一圈針腳（按鈕＝一塊縫上去的布） */
.btn:not(.btn-ghost) { position: relative; }
.btn:not(.btn-ghost)::after { display: none; }
.btn:not(.btn-ghost)::before {
  content: "";
  position: absolute;
  inset: 4px;
  background: rgba(255, 255, 255, .5);
  -webkit-mask: var(--st-frame-s);
  mask: var(--st-frame-s);
  pointer-events: none;
}

/* 底色放 html、body 透明（規矩同其他各套：body 有底色會蓋掉負 z 的裝飾層） */
html { background: var(--linen), var(--paper); }
html[data-wk-texture="off"] { background: var(--paper); }
body {
  font-family: var(--wk-f-body, var(--font-sans-tc));
  font-weight: 400;
  font-size: var(--text-body);
  line-height: 1.85;
  letter-spacing: .02em;
  background: transparent;
  color: var(--ink);
  overflow-x: hidden;
}

/* ---------- 動態語彙：浮上來（位移小、收得軟） ---------- */
.reveal {
  transform: translateY(14px);
  transition: opacity 1s var(--ease-out), transform 1s var(--ease-out);
}
/* 縫出來：一針一針（steps），從左到右 */
@keyframes st-sew { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes st-sew-down { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }

/* ════════════════════════════════════════════════════════════
   開場「拆線」
   ════════════════════════════════════════════════════════════ */
.intro { display: none; }
html.has-intro .intro {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: block;
  cursor: pointer;
  touch-action: none;                 /* 手勢自己接管 */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  --cut: 0;
  --seam-top: 47%;                    /* 縫線（梯形縫的橫針）從這裡… */
  --seam-bot: 70%;                    /* …縫到這裡（由下往上拆） */
  --gap: calc((var(--seam-bot) - var(--seam-top)) / 18);
}
html.has-intro .intro-play { --st-d: .4s; }
.intro-stage { position: absolute; inset: 0; overflow: hidden; }

/* 兩片布：各佔一半、在正中間縫合。布邊折進去一點（.cloth-fold 的光影＝折邊的厚度）。
   拖曳時從下面鬆開：以縫線頂端為軸各自轉一點點，露出底下的喜帖（V 形縫隙）。 */
.cloth {
  position: absolute;
  top: -2%;
  bottom: -2%;
  width: 50.5%;
  background: var(--linen), var(--paper);
  will-change: transform;
  transition: transform .5s cubic-bezier(.2, 1.4, .4, 1);   /* 反悔：彈回去 */
}
html[data-wk-texture="off"] .cloth { background: var(--paper); }
.cloth-l { left: 0; transform-origin: 100% calc(var(--seam-bot) + 2% - var(--cut) * var(--gap)); transform: translateX(calc(var(--cut) * -.8px)) rotate(calc(var(--cut) * .6deg)); }
.cloth-r { right: 0; transform-origin: 0 calc(var(--seam-bot) + 2% - var(--cut) * var(--gap)); transform: translateX(calc(var(--cut) * .8px)) rotate(calc(var(--cut) * -.6deg)); }
/* 布邊掀起的影子：拆越多，接縫那一側的影子越深（布離開襯裡＝有厚度） */
.cloth-l { box-shadow: calc(var(--cut) * .7px) 0 calc(var(--cut) * 1.4px) rgba(var(--ink-rgb), calc(var(--cut) * .026)); }
.cloth-r { box-shadow: calc(var(--cut) * -.7px) 0 calc(var(--cut) * 1.4px) rgba(var(--ink-rgb), calc(var(--cut) * .026)); }
/* 襯裡：縫隙裡看到的是一層暗一點的布（R1 評審：縫裡露出 Hero 的碎字像髒東西）；布分開時才淡掉 */
.intro-lining {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg, transparent 42%, rgba(var(--ink-rgb), .16) 50%, transparent 58%),
    var(--linen), #ddd4c2;
}
.intro-part .intro-lining { opacity: 0; transition: opacity .55s .25s; }
.is-dragging .cloth { transition: none; }
.cloth-fold { position: absolute; top: 0; bottom: 0; width: 18px; pointer-events: none; }
.cloth::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  width: 4px;
  background: repeating-linear-gradient(180deg, rgba(var(--ink-rgb), .1) 0 1px, transparent 1px 5px, rgba(var(--ink-rgb), .06) 5px 6px, transparent 6px 9px, rgba(var(--ink-rgb), .09) 9px 10px, transparent 10px 17px);
  opacity: .8;
  pointer-events: none;
}
.cloth-l::after { right: -3px; }
.cloth-r::after { left: -3px; }
.cloth-l .cloth-fold {
  right: 0;
  background: linear-gradient(90deg, transparent, rgba(var(--ink-rgb), .07) 70%, rgba(255, 255, 255, .5) 92%, rgba(var(--ink-rgb), .16));
}
.cloth-r .cloth-fold {
  left: 0;
  background: linear-gradient(270deg, transparent, rgba(var(--ink-rgb), .07) 70%, rgba(255, 255, 255, .5) 92%, rgba(var(--ink-rgb), .16));
}

/* 縫線：18 根橫跨接縫的橫針（梯形縫）。第 i 根在 --cut 之下＝已拆掉，只剩兩個針孔。 */
.seam {
  position: absolute;
  left: 50%;
  top: var(--seam-top);
  bottom: calc(100% - var(--seam-bot));
  width: 26px;
  margin-left: -13px;
  pointer-events: none;
}
.rung {
  --on: clamp(0, calc((var(--i) - var(--cut) + 1) * 99), 1);
  position: absolute;
  left: 3px;
  right: 3px;
  bottom: calc(var(--i) * 100% / 18 + 100% / 36);
  height: 2.4px;
  border-radius: 50%;                 /* 兩頭收細＝一股線被拉緊 */
  background: var(--accent);
  opacity: var(--on);
  /* 拆掉的那一針：被線往上抽起、翻一下再消失（不是原地不見） */
  transform: translateY(calc((1 - var(--on)) * -14px)) rotate(calc((1 - var(--on)) * -38deg)) scaleX(calc(.55 + var(--on) * .45));
  transition: opacity .32s ease-in, transform .32s var(--ease-out);
}
/* 針孔：拆掉之後留下的兩個小點（布上有洞才看得出「這裡縫過」） */
.rung::before, .rung::after {
  content: "";
  position: absolute;
  top: 0;
  width: 2px; height: 2px;
  border-radius: 50%;
  background: rgba(var(--ink-rgb), .5);
  opacity: calc(.45 + (1 - var(--on)) * .55);   /* 針孔一直在（縫著時淡、拆掉後清楚） */
}
.rung::before { left: -1px; }
.rung::after { right: -1px; }
/* 手縫的不完美：三組長短 × 四組斜度 × 兩組上下錯位輪替（純 nth-child，針數不變） */
.rung:nth-child(3n)   { left: -1px; right: 5px; }
.rung:nth-child(3n+1) { left: 5px; right: 0; }
.rung:nth-child(5n)   { left: 2px; right: -2px; }
.rung:nth-child(4n)   { rotate: -11deg; }
.rung:nth-child(4n+1) { rotate: 7deg; }
.rung:nth-child(4n+2) { rotate: -4deg; }
.rung:nth-child(4n+3) { rotate: 12deg; }
.rung:nth-child(2n)   { margin-bottom: 1px; }
/* 線頭：從還沒拆的最下面那一針垂下來；拉的時候被手指往上帶一點 */
.intro-tail {
  position: absolute;
  left: 50%;
  top: calc(100% - var(--cut) * 100% / 18 - 1px);
  width: 34px;
  height: clamp(4.5rem, 11vh, 6.5rem);
  margin-left: -17px;
  max-width: none;
  overflow: visible;
  transform-origin: 50% 0;
  transform: translateY(calc(var(--wk-open, 0) * -10px)) scaleY(calc(1 + var(--wk-open, 0) * .35));
  transition: top .12s;
}
.intro-tail path { fill: none; stroke: var(--accent); stroke-width: 2.2; stroke-linecap: round; }
.intro-tail circle { fill: var(--accent); stroke: var(--paper-raise); stroke-width: 1.5; }
/* 線頭輕晃：晃的是 SVG 裡的線本身（R1：WebKit 對整顆 svg 掛獨立 rotate 動畫會把描邊畫成白色空心） */
.intro-tail path, .intro-tail circle { transform-box: view-box; transform-origin: 20px 0; }
html.has-intro .intro-wait:not(.is-touched) .intro-tail :is(path, circle) { animation: st-tail 2.8s ease-in-out infinite; }
@keyframes st-tail {
  0%, 100% { transform: rotate(-5deg); }
  50%      { transform: rotate(6deg); }
}

/* 縮寫繡字（開場與 Hero 共用 .mono-t）：緞面繡——字心是斜紋兩色繡線（pattern），外緣一圈細輪廓線。
   R1 評審：虛線描邊在 WebKit 畫不出來（text 的 stroke-dasharray＋clip 動畫），改成跟名字同一種緞面繡。 */
.mono-t {
  font-family: var(--wk-f-latin, var(--font-serif-latin));
  font-style: italic;
  font-weight: 600;
  font-size: 88px;
  letter-spacing: 2px;
  fill: var(--accent);
  stroke: var(--accent-tx);
  stroke-width: .9;
  stroke-linejoin: round;
}
.intro-mono .mono-t { fill: url(#st-satin-i); }
.hero-mono .mono-t { fill: url(#st-satin-h); }
.satin-a { fill: var(--accent); }
.satin-b { fill: var(--accent-tx); }
.mono-t.is-cjk { font-family: var(--wk-f-heading, var(--font-serif-tc)); font-style: normal; font-size: 64px; letter-spacing: 6px; }
.intro-mono {
  position: absolute;
  z-index: 3;                         /* 永遠在兩片布上面（R10-A：放手那一格 & 被布邊切到） */
  left: 50%;
  bottom: calc(100% - var(--seam-top) - .3rem);
  width: min(56vw, 17rem);
  margin-left: calc(min(56vw, 17rem) / -2);
  pointer-events: none;
  transform-origin: 50% 50%;
}
.intro-mono svg { display: block; width: 100%; height: auto; overflow: visible; }
/* 開場的縮寫自己縫出來：一進場就一針一針繡上（steps） */
html.has-intro .intro:not(.intro-commit) .intro-mono { animation: st-sew 1.1s steps(22) .15s both; }
.intro-date {
  position: absolute;
  left: 0; right: 0;
  bottom: calc(100% - var(--seam-top) + min(28vw, 8.5rem) + 3.6rem);
  text-align: center;
  font-family: var(--wk-f-latin, var(--font-serif-latin));
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: .3em;
  text-indent: .3em;
  color: var(--ink-soft);
  pointer-events: none;
}
.intro-names {
  position: absolute;
  left: 1.5rem; right: 1.5rem;
  bottom: calc(100% - var(--seam-top) + min(28vw, 8.5rem) + .9rem);
  display: flex;
  justify-content: center;
  align-items: center;
  gap: .7rem;
  white-space: nowrap;
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-size: calc(1.05rem * var(--names-fit, 1));
  font-weight: 600;
  letter-spacing: .16em;
  color: var(--ink);
  pointer-events: none;
}
.intro-names .intro-g { text-align: right; }
.intro-x { width: .7em; height: .7em; flex: none; position: relative; }
.intro-x::before, .intro-x::after {
  content: "";
  position: absolute;
  left: -15%; top: 50%;
  width: 130%; height: 1.5px;
  background: var(--accent);
  border-radius: 1px;
}
.intro-x::before { rotate: 45deg; }
.intro-x::after { rotate: -45deg; }
/* 冠名：右片布的角落縫著一枚布標「to ◯◯」（專屬短碼進場才有） */
.intro-to {
  position: absolute;
  right: 1.2rem;
  top: max(6%, 2.4rem);
  max-width: 60%;
  display: flex;
  align-items: baseline;
  gap: .45em;
  padding: .5rem 1.05rem .55rem;
  background: var(--paper-raise);
  color: var(--ink);
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-weight: 600;
  font-size: 1.05rem;
  letter-spacing: .1em;
  white-space: nowrap;
  rotate: 2.5deg;
  box-shadow: 0 6px 14px -9px rgba(var(--ink-rgb), .5);
  pointer-events: none;
}
.intro-to[hidden] { display: none; }
.intro-to::before {
  content: "";
  position: absolute;
  inset: 4px;
  background: var(--accent);
  -webkit-mask: var(--st-frame-s);
  mask: var(--st-frame-s);
  pointer-events: none;
}
.intro-to .to-pre {
  font-family: var(--wk-f-latin, var(--font-serif-latin));
  font-style: italic;
  font-weight: 500;
  font-size: 1.05rem;
  letter-spacing: .04em;
  color: var(--accent-tx);
}
.intro-to .to-name { overflow: hidden; text-overflow: ellipsis; }

.intro-guide {
  display: none;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: calc(var(--seam-bot) + 12vh);
  white-space: nowrap;
  font-size: 1rem;
  letter-spacing: .06em;
  color: var(--accent-tx);
  padding: .6rem 1.15rem;
  min-height: 44px;
  border-radius: 2px;
  background: var(--paper-raise);
  box-shadow: 0 6px 14px -10px rgba(var(--ink-rgb), .5);
}
/* 開場提示＝一枚鋸齒剪邊的小布標（R12：直角白框加硬陰影，第一眼最像 UI） */
.intro-guide { box-shadow: none; border-radius: 0; background: var(--linen), #e9e1d1; color: var(--accent-tx);
  --z: 3.5px;
  -webkit-mask: conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y, conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y, linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
  mask: conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y, conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y, linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
}
html.has-intro .intro-wait .intro-guide { display: block; animation: st-guide 2.6s ease-in-out infinite; }
@keyframes st-guide { 0%, 100% { transform: translateX(-50%) translateY(0); } 50% { transform: translateX(-50%) translateY(-3px); } }
html.has-intro .intro-wait.is-touched .intro-guide { animation: none; opacity: max(0, calc(.9 - var(--wk-open, 0) * 3)); }
.intro-skip {
  position: absolute;
  bottom: max(1.6rem, env(safe-area-inset-bottom, 0px) + 1.2rem);
  left: 50%;
  transform: translateX(-50%);
  font-size: .9rem;
  color: var(--ink-soft);
  text-decoration: underline;
  text-decoration-color: rgba(var(--ink-rgb), .3);
  text-underline-offset: .3em;
  padding: .7rem 1.6rem;
  min-height: 44px;
  min-width: 88px;
}

/* ---------- commit 之後：拆完、分開、縮寫飛走 ---------- */
.intro-commit .intro-guide, .intro-commit .intro-skip { opacity: 0; transition: opacity .2s; pointer-events: none; }
.intro-commit .intro-tail { opacity: 0; transition: opacity .3s .1s; }
/* 放手後剩下的針拆得乾脆：不留半透明殘影漂在 V 縫裡（R10-A） */
.intro-commit .rung { transition: opacity .1s ease-in, transform .14s ease-in; }
.intro-commit .intro-date, .intro-commit .intro-names { opacity: 0; transition: opacity .3s; }
.intro-part .cloth { transition: transform .7s cubic-bezier(.5, 0, .3, 1), filter .7s; }   /* R13：.95s 太慢，720ms 時布條還把 Hero 擠成窄欄 */
.intro-part .cloth-l { transform: translateX(-104%) rotate(-5deg); }
.intro-part .cloth-r { transform: translateX(104%) rotate(5deg); }
/* 縮寫被放開：先浮起來一點（有影子＝離開布面），land() 之後飛到 Hero */
.intro-commit .intro-mono {
  animation: none;
  clip-path: none;
  transition: transform .45s var(--ease-out);
  transform: translateY(-8px) scale(1.06);
  filter: drop-shadow(0 8px 10px rgba(var(--ink-rgb), .18));
}
/* 飛行走弧線（R1 評審：直線飛過去會壓在新人臉上）：先往上浮、變透一點，再落到 Hero 那一枚上。
   keyframes 讀 land() 寫的 --fx／--fy／--fs，最後一格跟 Hero 那一枚分毫不差。 */
.intro-land .intro-mono { animation: st-fly .92s cubic-bezier(.45, 0, .25, 1) both; }
@keyframes st-fly {
  0%   { transform: translateY(-8px) scale(1.06); filter: drop-shadow(0 0 2px rgba(251, 248, 242, .95)) drop-shadow(0 8px 10px rgba(var(--ink-rgb), .18)); }
  32%  { transform: translate(calc(var(--fx, 0px) * .78), calc(var(--fy, 0px) * .78 - var(--st-arc, 40px))) scale(max(calc(var(--fs, 1) * 1.25), .7)); filter: drop-shadow(0 0 2px rgba(251, 248, 242, .95)) drop-shadow(0 16px 16px rgba(var(--ink-rgb), .22)); }
  100% { transform: translate(var(--fx, 0px), calc(var(--fy, 0px) - 8px)) rotate(var(--fr, 0deg)) scale(var(--fs, 1)); filter: drop-shadow(0 0 0 rgba(251, 248, 242, 0)) drop-shadow(0 0 0 rgba(var(--ink-rgb), 0)); }
}
/* 沒量到落點（跳過／Hero 不在畫面）：縮寫跟著淡掉 */
html.has-intro:not(.wk-stitch-landed) .intro-land .intro-mono { animation: none; opacity: 0; transition: opacity .4s; }
/* auto 模式：一律延後一拍（先讓人看到縫線） */
.intro-play .cloth, .intro-play .intro-mono { transition-delay: var(--st-d, 0s); }
html.fx.has-intro .hero-content > :not(.hero-frame):not(.hero-mono) { opacity: 0 !important; transition: none !important; }
html.fx .hero-content > :not(.hero-frame):not(.hero-mono).is-in { transition: opacity .7s var(--ease-out), transform .7s var(--ease-out); }
html.fx.has-intro.wk-stitch-landed .hero-content > :not(.hero-frame):not(.hero-mono).is-in { opacity: 1 !important; transition: opacity .5s var(--ease-out) .5s !important; }
/* 飛行中畫面上只准有一枚縮寫：Hero 那一枚在開場結束前隱身（版面在、land() 照量） */
html.has-intro .hero-mono svg { visibility: hidden; }
/* 布章本身（漂白棉＋一圈針腳）也先藏著，縮寫快飛到時才淡入接住它（R8 自檢：飛行中看到一個空的布章） */
html.has-intro .hero-mono { opacity: 0; }
html.has-intro.wk-stitch-landed .hero-mono { opacity: 1; transition: opacity .45s var(--ease-out) .5s; }

/* ════════════════════════════════════════════════════════════
   通用：標頭系統（全站置中）
   ════════════════════════════════════════════════════════════ */
.section { text-align: center; }
main > .section > .container-wide { text-align: center; }
.custom .label-en { margin-bottom: clamp(.2rem, 1vw, .4rem); }
.label-en {
  font-family: var(--wk-f-latin, var(--font-serif-latin));
  font-size: calc(1.02rem * var(--wk-fs-latin, 1));
  font-style: italic;
  font-weight: 500;
  letter-spacing: .2em;
  text-indent: .2em;
  text-transform: lowercase;
  color: var(--accent-tx);
}
.section-title {
  margin-top: .5rem;
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-size: calc(clamp(1.5rem, 5.6vw, 2rem) * var(--wk-fs-heading, 1));
  font-weight: 600;
  line-height: 1.45;
  letter-spacing: .12em;
  text-indent: .12em;
  color: var(--ink);
}
/* 一行針腳（區塊分隔）：捲進畫面時一針一針縫出來 */
.stitch-rule {
  display: block;
  position: relative;
  width: 6.6rem;
  height: 10px;
  margin: 1.1rem auto clamp(1.6rem, 5vw, 2.4rem);
}
.stitch-rule::before {
  content: "";
  position: absolute;
  inset: 3px 0;
  background: var(--accent);
  -webkit-mask: var(--st-h) left center / 66px 4px repeat-x;
  mask: var(--st-h) left center / 66px 4px repeat-x;
}
/* 兩端各一個打結的點 */
.stitch-rule::after {
  content: "";
  position: absolute;
  top: 3px;
  left: -7px;
  right: -7px;
  height: 4px;
  background:
    radial-gradient(circle, var(--accent) 1.6px, transparent 2px) left center / 4px 4px no-repeat,
    radial-gradient(circle, var(--accent) 1.6px, transparent 2px) right center / 4px 4px no-repeat;
}
html.fx .stitch-rule::before { clip-path: inset(0 100% 0 0); }
html.fx .stitch-rule.is-in::before { animation: st-sew .8s steps(8) .25s both; }
html.fx .stitch-rule::after { opacity: 0; transition: opacity .3s 1.05s; }
html.fx .stitch-rule.is-in::after { opacity: 1; }

/* ════════════════════════════════════════════════════════════
   ① Hero
   ════════════════════════════════════════════════════════════ */
.hero {
  padding: clamp(3rem, 10vw, 4.6rem) var(--gutter) clamp(1.4rem, 5vw, 2.4rem);
  text-align: center;
}
.hero-content { max-width: 34rem; margin-inline: auto; display: flex; flex-direction: column; align-items: center; }
.hero-label {
  font-family: var(--wk-f-latin, var(--font-serif-latin));
  font-size: calc(1.02rem * var(--wk-fs-latin, 1));
  font-style: italic;
  font-weight: 600;
  letter-spacing: .32em;
  text-indent: .32em;
  text-transform: lowercase;
  color: var(--ink-soft);
}
.hero-greeting {
  margin-top: .7rem;
  max-width: 22em;
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-size: calc(1.02rem * var(--wk-fs-heading, 1));
  letter-spacing: .1em;
  color: var(--ink);
  white-space: pre-line;
  text-wrap: balance;
}
.hero-greeting:empty, .hero-greeting[hidden] { display: none; }

/* 方形木繡框：外框（木頭）＋內框一圈線（雙層框）＋右上角的黃銅螺絲；
   框裡是一塊亞麻（.hero-mat），照片縫在布上，四周一圈針腳。 */
.hero-frame {
  position: relative;
  width: min(80vw, 21.5rem);
  margin-top: clamp(1.6rem, 6vw, 2.2rem);
  padding: 10px;
  border-radius: 14px;
  background:
    var(--wood-grain) 0 0 / 240px 240px,
    linear-gradient(135deg, #d9c19f, var(--wood) 50%, #b39268);
  box-shadow: 0 22px 40px -30px rgba(var(--ink-rgb), .42), inset 0 0 0 1px rgba(0, 0, 0, .1), inset 0 1px 0 rgba(255, 255, 255, .3);
}
.hoop { position: absolute; inset: 0; border-radius: inherit; pointer-events: none; z-index: 2; }
/* 內框：比外框細一圈的那條縫（繡框是兩個框夾住布） */
.hoop::before {
  content: "";
  position: absolute;
  inset: 5px;
  border-radius: 10px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .16), 0 0 0 1px rgba(255, 255, 255, .22);
}
.hoop-screw {
  position: absolute;
  top: -7px;
  right: 16%;
  width: 14px;
  height: 10px;
  border-radius: 3px 3px 2px 2px;
  background: linear-gradient(180deg, #e6d3a3, #b8955a 60%, #8c6c3b);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .22);
}
.hoop-screw::after {
  content: "";
  position: absolute;
  left: 50%; top: 2px;
  width: 1px; height: 6px;
  background: rgba(0, 0, 0, .35);
}
.hero-mat {
  position: relative;
  display: block;
  padding: clamp(14px, 4vw, 18px);
  border-radius: 6px;
  background: radial-gradient(70% 60% at 50% 45%, rgba(255, 255, 255, .45), transparent 70%), var(--linen), var(--paper);
  box-shadow: inset 0 2px 7px rgba(var(--ink-rgb), .2);
}
.hero-photo {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: center 30%;
  border-radius: 2px;
  background: rgba(var(--ink-rgb), .06);
}
/* 照片四周一圈針腳（縫在布上） */
.hero-mat::after {
  content: "";
  position: absolute;
  inset: 6px;
  background: var(--accent);
  -webkit-mask: var(--st-frame);
  mask: var(--st-frame);
  pointer-events: none;
}
html.fx .hero-mat::after { animation: st-sew 1.4s steps(28) .5s both; }

.hero-mono { margin-top: clamp(1rem, 3.6vw, 1.4rem); width: clamp(7rem, 34vw, 9rem); line-height: 0; }
.hero-content > .hero-label { order: 1; }
.hero-content > .hero-greeting { order: 2; }
.hero-content > .hero-mono { order: 3; margin-bottom: -.4rem; }
/* 縮寫落定成徽章：一小塊漂白棉、一圈手縫針腳（R6-B：只是一組字，不像徽章；方的，不用圓框） */
.hero-mono { position: relative; padding: .5rem 1.1rem .6rem; background: var(--paper-raise); box-shadow: 0 8px 16px -12px rgba(var(--ink-rgb), .55); rotate: -1.5deg; }
.hero-mono::before { content: ""; position: absolute; inset: 4px; background: var(--accent); -webkit-mask: var(--st-frame-s); mask: var(--st-frame-s); pointer-events: none; }
.hero-content > .hero-frame { order: 4; }
.hero-content > :not(.hero-label):not(.hero-greeting):not(.hero-mono):not(.hero-frame) { order: 5; }
.hero-mono svg { display: block; width: 100%; height: auto; overflow: visible; }

.hero-names {
  width: 100%;
  margin-top: clamp(1.2rem, 4.5vw, 1.6rem);
  display: flex;
  justify-content: center;
  align-items: center;
  gap: .5em;
  white-space: nowrap;
  max-width: 100%;
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-size: calc(clamp(1.9rem, 8.4vw, 2.9rem) * var(--wk-fs-heading, 1) * var(--names-fit, 1));
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: .12em;
  color: var(--ink);
}
.hero-names > span[id] { position: relative; isolation: isolate; display: inline-block; }
/* 繡出來的字（緞面繡）：字心是一道一道斜向的線（兩個深淺相近的墨色交錯），像用繡線把字填滿；
   進場時一針一針從左縫到右（steps）。⚠ 用 -webkit-text-fill-color 透明＋background-clip:text，
   不動 color——輔具、對比量測、F07 讀到的照樣是 --ink（對紙 12）。不支援 text 裁切的瀏覽器＝純墨色字。
   （2026-10-31 草稿試過 SVG／偽元素疊輪廓描邊：390 寬讀起來像陰影字、不像繡，改成緞面繡。） */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .hero-names > span[id] {
    background: repeating-linear-gradient(116deg, var(--ink) 0 1.3px, #463e35 1.3px 2.1px);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
  }
}
html.fx .hero-names > span[id] { clip-path: inset(-10% 100% -10% 0); }
html.fx .hero-names.is-in > span[id] { animation: st-sew-name 1.1s steps(14) .5s both; }
html.fx .hero-names.is-in > #name-bride { animation-delay: 1.05s; }
@keyframes st-sew-name { from { clip-path: inset(-10% 100% -10% 0); } to { clip-path: inset(-10% 0 -10% 0); } }
.hero-names .amp { width: .62em; height: .62em; flex: none; display: inline-flex; }
.hero-names .amp svg { width: 100%; height: 100%; overflow: visible; }
.hero-names .amp path { fill: none; stroke: var(--accent); stroke-width: 2.4; stroke-linecap: round; }
.hero-names-en {
  margin-top: .2rem;
  font-family: var(--wk-f-latin, var(--font-serif-latin));
  font-size: calc(1.1rem * var(--wk-fs-latin, 1));
  font-style: italic;
  letter-spacing: .12em;
  color: var(--ink-soft);
}
.hero-names-en:empty { display: none; }

/* 婚期＝布標：兩端各縫一針固定在布上；長按翻到背面（彩蛋） */
.hero-date {
  margin-top: clamp(1.2rem, 4.5vw, 1.6rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .6rem;
}
.hero-tag {
  position: relative;
  display: inline-grid;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}
.tag-face {
  grid-area: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  padding: .55rem 1.5rem .6rem;
  background: var(--paper-raise);
  box-shadow: 0 7px 16px -11px rgba(var(--ink-rgb), .6);
  /* 翻面不靠 backface-visibility（R1：WebKit 在沒有 preserve-3d 時不認兄弟面的背面隱藏，
     一落地就顯示鏡像的背面）。改成兩段：轉到 90° 側面時換面（visibility 跟著延遲切換）。 */
  transition: transform .3s cubic-bezier(.5, 0, .7, .4) .3s, visibility 0s .3s;
}
.tag-front {
  font-family: var(--wk-f-latin, var(--font-serif-latin));
  font-size: calc(1.12rem * var(--wk-fs-latin, 1));
  font-weight: 600;
  letter-spacing: .1em;
  color: var(--ink);
  font-variant-numeric: lining-nums;
}
.tag-front #hero-date { font-family: var(--wk-f-heading, var(--font-serif-tc)); font-size: .92em; letter-spacing: .06em; }
.tag-front #hero-day { font-family: var(--wk-f-heading, var(--font-serif-tc)); font-size: .82em; color: var(--ink-soft); }
.tag-face::before {
  content: "";
  position: absolute;
  inset: 4px;
  background: var(--accent);
  -webkit-mask: var(--st-frame-s);
  mask: var(--st-frame-s);
  pointer-events: none;
}
/* 兩端固定的那一針（R4 起不畫：四周已有一圈手縫針腳，再加兩端的豎線讀成殘件） */
.tag-face::after {
  display: none;
  content: "";
  position: absolute;
  top: 50%;
  left: 9px; right: 9px;
  height: 10px;
  margin-top: -5px;
  background:
    linear-gradient(var(--accent), var(--accent)) left center / 1.6px 10px no-repeat,
    linear-gradient(var(--accent), var(--accent)) right center / 1.6px 10px no-repeat;
  pointer-events: none;
}
.dot-sep { width: 3px; height: 3px; border-radius: 50%; background: var(--accent); flex: none; }
.tag-back {
  transform: perspective(600px) rotateY(90deg);
  visibility: hidden;
  transition: transform .3s cubic-bezier(.5, 0, .7, .4), visibility 0s .3s;
  background: var(--paper-raise);              /* 背面是同一塊布的反面（R7-B：整塊飽和紅太重） */
  color: var(--accent-tx);
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-weight: 600;
  font-size: .95rem;
  letter-spacing: .1em;
  line-height: 1.5;
  white-space: pre-line;
  text-align: center;
}
.tag-back::before { background: var(--accent); }
.tag-back::after { background:
    linear-gradient(var(--accent-ink), var(--accent-ink)) left center / 1.6px 10px no-repeat,
    linear-gradient(var(--accent-ink), var(--accent-ink)) right center / 1.6px 10px no-repeat; }
.hero-tag.is-flipped .tag-front { transform: perspective(600px) rotateY(-90deg); visibility: hidden; transition: transform .3s cubic-bezier(.5, 0, .7, .4), visibility 0s .3s; }
.hero-tag.is-flipped .tag-back { transform: none; visibility: visible; transition: transform .3s cubic-bezier(.3, .6, .5, 1) .3s, visibility 0s .3s; }
html[data-wk-eggs] .hero-tag { cursor: pointer; }
.hero-tag.is-holding .tag-front { transform: scale(.97); transition: transform .55s; }
.hero-tag:focus-visible { outline: 2px solid var(--accent-tx); outline-offset: 4px; }
.hero-note { font-size: var(--text-small); color: var(--ink-soft); white-space: pre-line; }
.hero-note:empty { display: none; }

/* 倒數：四格，中間用一行直向的針腳隔開 */
.countdown {
  display: flex;
  justify-content: center;
  margin-top: clamp(1.8rem, 6vw, 2.4rem);
}
.cd-cell {
  position: relative;
  display: grid;
  justify-items: center;
  min-width: 4.2rem;
  padding: 0 .6rem;
}
.cd-cell + .cd-cell::before {
  content: "";
  position: absolute;
  left: 0; top: 18%; bottom: 18%;
  width: 1.5px;
  background: repeating-linear-gradient(180deg, var(--accent) 0 5px, transparent 5px 9px);
  opacity: .7;
}
.cd-cell strong {
  font-family: var(--wk-f-latin, var(--font-serif-latin));
  font-size: calc(2rem * var(--wk-fs-latin, 1));
  font-weight: 600;
  line-height: 1.1;
  color: var(--accent-tx);
  font-variant-numeric: lining-nums tabular-nums;
}
.countdown .cd-tick { animation: st-tick .45s var(--ease-out); }
@keyframes st-tick { from { transform: translateY(-5px); } to { transform: none; } }
.cd-cell span { font-size: var(--text-tiny); color: var(--ink-soft); letter-spacing: .2em; text-indent: .2em; }

/* 彩蛋：縫在布上的鈕扣（拉一下線頭跳一下） */
.st-button {
  display: block;
  width: 72px; height: 72px;
  margin: .3rem auto 0;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.st-button[hidden] { display: none; }
.st-button svg { width: 100%; height: 100%; overflow: visible; }
.btn-body { fill: var(--accent); }
.btn-rim { fill: none; stroke: rgba(255, 255, 255, .35); stroke-width: 1.2; }
.btn-holes circle { fill: var(--paper-raise); }   /* 四個孔是亮的（看得到穿過去的布），線是深紅細線——不像白色 × 的關閉鈕 */
.btn-x { fill: none; stroke: var(--accent-tx); stroke-width: 1.4; stroke-linecap: round; }
.btn-thread { fill: none; stroke: var(--accent); stroke-width: 1.6; stroke-linecap: round; transform-origin: 32px 46px; animation: st-sway 3.2s ease-in-out infinite paused; }
.st-button.is-live .btn-thread { animation-play-state: running; }
.st-button.is-live:not(.is-hop) svg { animation: st-wiggle 1.2s ease-in-out .4s 1; }
@keyframes st-wiggle { 0%, 100% { transform: none; } 20% { transform: rotate(-12deg); } 45% { transform: rotate(9deg); } 70% { transform: rotate(-4deg); } }
@keyframes st-sway { 0%, 100% { rotate: -6deg; } 50% { rotate: 8deg; } }
.st-button.is-hop svg { animation: st-hop .6s cubic-bezier(.3, 1.6, .5, 1); }
@keyframes st-hop {
  0%   { transform: translateY(0) rotate(0); }
  35%  { transform: translateY(-14px) rotate(-14deg); }
  70%  { transform: translateY(2px) rotate(4deg); }
  100% { transform: none; }
}
.st-button:focus-visible { outline: 2px solid var(--accent-tx); outline-offset: 3px; border-radius: 50%; }
.st-button-say { min-height: 1.6em; margin-top: .2rem; font-size: var(--text-small); color: var(--accent-tx); letter-spacing: .06em; }
.st-button-say.is-hint { color: var(--ink); font-size: .86rem; }
.st-button-say.is-pop { animation: st-pop 3.2s var(--ease-out) both; }
@keyframes st-pop {
  0%   { opacity: 0; transform: translateY(6px); }
  12%  { opacity: 1; transform: none; }
  85%  { opacity: 1; }
  100% { opacity: 0; }
}

/* ════════════════════════════════════════════════════════════
   ② Story：一條往下縫的時間線，每一則是一個法式結（French knot）
   ════════════════════════════════════════════════════════════ */
.timeline { max-width: 30rem; margin-inline: auto; text-align: left; }
.timeline-item {
  position: relative;
  padding: 0 0 clamp(2.2rem, 7vw, 2.8rem) 2.1rem;
}
.timeline-item:last-child { padding-bottom: 0; }
/* 這一則的那一段縫線（到下一則為止）。逐則縫下來＝一條連續的線 */
.timeline-item::before {
  content: "";
  position: absolute;
  left: .42rem;
  top: .75rem;
  bottom: -.75rem;
  width: 2px;
  background: var(--accent);
  -webkit-mask: var(--st-v) center top / 4px 66px repeat-y;
  mask: var(--st-v) center top / 4px 66px repeat-y;
  width: 4px;
  border-radius: 2px;
}
.timeline-item:last-child::before { display: none; }
html.fx .timeline-item::before { clip-path: inset(0 0 100% 0); }
html.fx .timeline-item.is-in::before { animation: st-sew-down 1s steps(9) .35s both; }
.timeline-item::after {
  content: "";
  position: absolute;
  left: .12rem;
  top: .45rem;
  width: .62rem; height: .62rem;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, rgba(255, 255, 255, .35), transparent 45%), var(--accent);
  box-shadow: 0 1px 2px rgba(var(--ink-rgb), .3);
}
.tl-date {
  display: block;
  font-family: var(--wk-f-latin, var(--font-serif-latin));
  font-size: calc(1.05rem * var(--wk-fs-latin, 1));
  font-style: italic;
  font-weight: 600;
  letter-spacing: .1em;
  color: var(--accent-tx);
}
.tl-title {
  margin-top: .1rem;
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-size: calc(clamp(1.12rem, 4vw, 1.3rem) * var(--wk-fs-heading, 1));
  font-weight: 600;
  letter-spacing: .08em;
}
.tl-text { margin-top: .45rem; color: var(--ink); white-space: pre-line; }
.tl-photo {
  position: relative;
  margin: .9rem 0 .2rem;
  padding: 8px;
  background: var(--paper-raise);
  box-shadow: 0 10px 20px -16px rgba(var(--ink-rgb), .6);
  width: min(100%, 17rem);
  rotate: -1deg;
}
.tl-photo img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.tl-photo::after {
  content: "";
  position: absolute;
  inset: 3px;
  background: var(--accent);
  -webkit-mask: var(--st-frame-s);
  mask: var(--st-frame-s);
  pointer-events: none;
}

/* ════════════════════════════════════════════════════════════
   ③ Gallery：原生版式「布標補丁」（patch）
   每片＝一塊鋸齒剪邊的布（::before，鋸齒用 mask），照片縫在上面、四周一圈針腳（::after），
   圖說＝縫在下緣的小布標。比例四種、傾角六種輪替（render.js 寫 data-patch＝0…5）。
   ⚠ 只屬於這一套：全部包在 #gallery:not([data-wk-gallery]) 底下，切到 shared 版式時一條都選不到。
   ════════════════════════════════════════════════════════════ */
#gallery:not([data-wk-gallery]) .photo-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.6rem, 6vw, 2.4rem) clamp(1rem, 4.5vw, 1.8rem);
  align-items: start;
  max-width: 46rem;
  margin-inline: auto;
  padding-inline: .3rem;
}
@media (min-width: 760px) {
  #gallery:not([data-wk-gallery]) .photo-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); max-width: 60rem; }
}
#gallery:not([data-wk-gallery]) .photo-item {
  --z: 3.5px;                          /* 鋸齒的齒距一半（布的花邊剪齒是細的；大齒會讀成郵票） */
  --pr: -1.2deg;
  --par: 4 / 5;
  position: relative;
  margin: 0;
  padding: 11px;
  rotate: var(--pr);
  cursor: zoom-in;
}
#gallery:not([data-wk-gallery]) .photo-item:nth-child(2n) { margin-top: clamp(1.4rem, 6vw, 2.2rem); }
#gallery:not([data-wk-gallery]) .photo-item[data-patch="1"] { --pr: 1.3deg; --par: 1 / 1; }
#gallery:not([data-wk-gallery]) .photo-item[data-patch="2"] { --pr: .8deg; --par: 3 / 4; }
#gallery:not([data-wk-gallery]) .photo-item[data-patch="3"] { --pr: -1.4deg; --par: 5 / 4; }
#gallery:not([data-wk-gallery]) .photo-item[data-patch="4"] { --pr: .5deg; --par: 4 / 5; }
#gallery:not([data-wk-gallery]) .photo-item[data-patch="5"] { --pr: -.9deg; --par: 1 / 1; }
/* 布：四邊鋸齒（花邊剪刀剪的），底色是漂白棉＋同一組織紋 */
#gallery:not([data-wk-gallery]) .photo-item::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--linen), var(--paper-raise);
  -webkit-mask:
    conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y,
    conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y,
    linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
  mask:
    conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y,
    conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y,
    linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
}
#gallery:not([data-wk-gallery]) .photo-item img {
  filter: sepia(.14) saturate(.88) contrast(.97);
  display: block;
  width: 100%;
  aspect-ratio: var(--par);
  object-fit: cover;
  border-radius: 1px;
}
/* 照片四周的針腳 */
#gallery:not([data-wk-gallery]) .photo-item::after {
  content: "";
  position: absolute;
  inset: 4px;
  background: var(--accent);
  -webkit-mask: var(--st-frame-s);
  mask: var(--st-frame-s);
  pointer-events: none;
}
html.fx #gallery:not([data-wk-gallery]) .photo-item::after { clip-path: inset(0 100% 0 0); }
html.fx #gallery:not([data-wk-gallery]) .photo-item.is-in::after { animation: st-sew 1s steps(14) .35s both; }
/* 圖說＝縫在下緣的小布標（壓在布邊上，兩端各一針） */
#gallery:not([data-wk-gallery]) .patch-tag {
  position: absolute;
  left: 0; right: 0;
  bottom: -.85rem;
  width: fit-content;
  max-width: 88%;
  margin-inline: auto;
  z-index: 1;                          /* 壓在照片那一圈針腳上面（R1：虛線橫切圖說） */
  rotate: calc(var(--pr) * -1.4);
  padding: .32rem 1.05rem .36rem;
  background: var(--paper-raise);
  color: var(--ink);
  font-size: .86rem;
  line-height: 1.45;
  letter-spacing: .04em;
  text-align: center;
  text-wrap: balance;
  box-shadow: 0 4px 9px -6px rgba(var(--ink-rgb), .6), inset 0 0 0 1px rgba(var(--ink-rgb), .08);
}
#gallery:not([data-wk-gallery]) .patch-tag:empty { display: none; }
/* 布標自己一圈內縮的針腳（字永遠在針腳裡面） */
#gallery:not([data-wk-gallery]) .patch-tag::before {
  content: "";
  position: absolute;
  inset: 3px;
  background: var(--accent);
  -webkit-mask: var(--st-frame-s);
  mask: var(--st-frame-s);
  pointer-events: none;
}
/* 有圖說的那片，下方多留一點位置給布標 */
#gallery:not([data-wk-gallery]) .photo-item:has(.patch-tag:not(:empty)) { margin-bottom: .7rem; }


/* 燈箱（WK.initLightbox；每套自己的皮） */
.wk-lightbox {
  position: fixed; inset: 0; z-index: 100;
  display: none;
  align-items: center; justify-content: center;
  background: rgba(30, 26, 22, .94);
  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: 88dvh; margin-inline: auto; border-radius: 3px; outline: 1.5px dashed rgba(251, 248, 242, .5); outline-offset: 6px; }
.wk-lightbox button {
  position: absolute;
  color: #f8f5ee;
  font-size: 2rem;
  line-height: 1;
  padding: .75rem 1rem;
  min-width: 44px; min-height: 44px;
  display: grid; place-items: center;
  opacity: .8;
  transition: opacity .3s var(--ease-out);
}
.wk-lightbox button:hover { opacity: 1; }
.wk-lightbox button:active { opacity: 1; scale: .92; }
.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%); }

/* ════════════════════════════════════════════════════════════
   ③b 婚禮影片：框＝布標邊（漂白棉一圈＋一圈針腳）
   ════════════════════════════════════════════════════════════ */
.video-frame {
  position: relative;
  margin-top: clamp(.5rem, 2vw, 1rem);
  aspect-ratio: 16 / 9;
  background: #000;
  border-radius: 3px;
  overflow: hidden;
  box-shadow: 0 0 0 11px var(--paper-raise), 0 0 0 12px rgba(var(--ink-rgb), .1), 0 22px 40px -26px rgba(var(--ink-rgb), .55);
}
.video-frame[data-ratio="portrait"] { aspect-ratio: 9 / 16; width: min(100%, 20rem); margin-inline: auto; }
.video-frame.is-noposter { background: var(--accent-tx); }
.video-frame.is-noposter .video-poster { display: none; }
.video-frame[data-provider="instagram"] { aspect-ratio: 10 / 19; width: min(100%, 20rem); margin-inline: auto; }
.video-facade { position: absolute; inset: 0; width: 100%; height: 100%; padding: 0; border: 0; background: none; display: block; cursor: pointer; }
.video-poster { width: 100%; height: 100%; object-fit: cover; display: block; }
.video-facade::after { content: ""; position: absolute; inset: 0; background: rgba(0, 0, 0, .24); }
.video-play-ico {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: 3.8rem; height: 3.8rem;
  z-index: 1;
  color: #f8f5ee;
  border-radius: 50%;
  border: 1.5px dashed rgba(248, 245, 238, .9);
  background: rgba(0, 0, 0, .12);
}
.video-play-ico::before {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-38%, -50%);
  border-style: solid;
  border-width: .5rem 0 .5rem .86rem;
  border-color: transparent transparent transparent currentColor;
}
.video-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }
@media (hover: hover) { .video-facade:hover::after { background: rgba(0, 0, 0, .12); } }
.video-facade:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: -6px; }

/* ════════════════════════════════════════════════════════════
   ④ Event Details
   ════════════════════════════════════════════════════════════ */
.details-date {
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-size: calc(clamp(1.25rem, 5vw, 1.6rem) * var(--wk-fs-heading, 1));
  font-weight: 600;
  letter-spacing: .06em;
  line-height: 1.5;
}
.details-note { color: var(--ink-soft); font-size: var(--text-small); margin-top: .5rem; white-space: pre-line; }
.details-note:empty { display: none; }
/* 月曆＝一塊縫上去的布標（⚠ 絕不對 .wk-cal 宣告 display——顯隱靠 [hidden]） */
.wk-cal {
  position: relative;
  width: 100%;
  max-width: 19rem;
  margin: clamp(2rem, 6vw, 2.8rem) auto 0;
  padding: clamp(1.3rem, 4vw, 1.7rem) clamp(1rem, 3.5vw, 1.4rem);
  background: var(--paper-raise);
  border-radius: 4px;
  box-shadow: 0 14px 30px -24px rgba(var(--ink-rgb), .7);
  text-align: center;
}
/* 月曆：只在上緣縫一道（不是整圈）——一張縫在布上的小卡 */
/* 月曆卡：一塊鋸齒剪邊的漂白棉（不再縫一整圈） */
.wk-cal { box-shadow: none; filter: drop-shadow(0 10px 12px rgba(var(--ink-rgb), .12));
  --z: 5px;
  -webkit-mask:
    conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y,
    conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y,
    linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
  mask:
    conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y,
    conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y,
    linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
}
.wk-cal-title { margin-top: .35rem; }
/* 「還有 N 天」底下一道手縫短線（R6-C：上一版把整塊塗成茜紅底，字讀不到） */
.wk-cal-count::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: var(--accent); -webkit-mask: var(--st-h) left center / 44px 3px repeat-x; mask: var(--st-h) left center / 44px 3px repeat-x; }
.wk-cal-title {
  font-family: var(--wk-f-latin, var(--font-serif-latin));
  font-size: calc(clamp(1.4rem, 5.6vw, 1.7rem) * var(--wk-fs-latin, 1));
  font-weight: 600;
  line-height: 1;
  letter-spacing: .16em;
  text-indent: .16em;
  color: var(--accent-tx);
  font-variant-numeric: lining-nums tabular-nums;
}
.wk-cal-grid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: .15rem;
  margin-top: clamp(.9rem, 3.5vw, 1.2rem);
  font-variant-numeric: lining-nums tabular-nums;
}
.wk-cal-wd, .wk-cal-d, .wk-cal-pad { position: relative; }
.wk-cal-wd { padding-bottom: .5rem; color: var(--ink-soft); font-size: .72rem; letter-spacing: .04em; }
.wk-cal-d, .wk-cal-pad { aspect-ratio: 1; }
.wk-cal-d { display: grid; place-items: center; font-size: clamp(.84rem, 3.3vw, .95rem); }
/* 婚期那一格：一小塊茜紅布，裡面一圈針腳（不用愛心——這一套的記號是針線） */
.wk-cal-heart { display: none; }
.wk-cal-d.is-day { color: var(--accent-ink); font-weight: 600; }
.wk-cal-d.is-day::before {
  content: "";
  position: absolute;
  inset: 6%;
  background: var(--accent-tx);
  border-radius: 3px;
  outline: 1px dashed rgba(255, 255, 255, .6);
  outline-offset: -4px;
  rotate: -3deg;
}
.wk-cal-n { position: relative; z-index: 1; }
.wk-cal-count {
  display: inline-block;
  margin-top: clamp(.9rem, 3.5vw, 1.2rem);
  position: relative;
  padding: 0 0 .45rem;
  color: var(--ink-soft);
  font-size: var(--text-small);
}
.event-list { margin: clamp(2.2rem, 7vw, 3rem) auto 0; max-width: 24rem; display: grid; text-align: left; }
.event-row {
  position: relative;
  display: grid;
  grid-template-columns: 4.4rem 1fr;
  column-gap: 1.1rem;
  align-items: baseline;
  padding-block: clamp(.95rem, 3.4vw, 1.25rem);
}
/* 列與列之間一行淡淡的針腳（不是髮絲線） */
.event-row + .event-row::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 1.4px;
  background: repeating-linear-gradient(90deg, rgba(var(--ink-rgb), .3) 0 6px, transparent 6px 11px);
}
.event-row dt {
  font-family: var(--wk-f-latin, var(--font-serif-latin));
  font-size: calc(1.2rem * var(--wk-fs-latin, 1));
  font-weight: 600;
  color: var(--accent-tx);
  font-variant-numeric: lining-nums tabular-nums;
  letter-spacing: .06em;
}
.event-row dd strong {
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-size: calc(clamp(1.08rem, 3vw, 1.2rem) * var(--wk-fs-heading, 1));
  font-weight: 600;
  letter-spacing: .04em;
  display: block;
}
.event-row dd span { color: var(--ink-soft); font-size: .94rem; }
.calendar-actions .btn { min-width: 13.5rem; }
.calendar-actions { display: flex; flex-wrap: wrap; gap: .75rem; justify-content: center; margin-top: clamp(2.2rem, 7vw, 3rem); }
.parents { margin-top: clamp(2.2rem, 7vw, 3rem); color: var(--ink); font-size: .94rem; line-height: 2; }
.parents:empty { display: none; }
.parents { word-break: keep-all; text-wrap: balance; }   /* 「女方主婚人」不在詞中間斷（R6-C） */

/* ④b Dress Code：一捲一捲的繡線（線軸：上下兩片木頭、中間纏著線） */
.dc-note { max-width: 26em; margin-inline: auto; color: var(--ink-soft); white-space: pre-line; }
.dc-note:empty { display: none; }
.dc-swatches { display: flex; flex-wrap: wrap; justify-content: center; gap: clamp(1rem, 5vw, 1.6rem); margin-top: clamp(1.8rem, 6vw, 2.4rem); }
.dc-swatch {
  position: relative;
  width: 2.5rem;
  height: 3.2rem;
  margin-block: .4rem;
  border-radius: 3px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
}
/* 線的紋路：一圈一圈纏上去 */
.dc-swatch::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: repeating-linear-gradient(170deg, rgba(255, 255, 255, .2) 0 1px, transparent 1px 3px, rgba(0, 0, 0, .06) 3px 4px);
}
.dc-swatch::after {
  content: "";
  position: absolute;
  left: -.35rem; right: -.35rem;
  top: -.45rem; bottom: -.45rem;
  background:
    linear-gradient(var(--wood-l), var(--wood)) top / 100% .45rem no-repeat,
    linear-gradient(var(--wood), var(--wood-d)) bottom / 100% .45rem no-repeat;
  border-radius: 3px;
  pointer-events: none;
}

/* ⑤b 自訂區塊 */
.custom-text { max-width: 28em; margin-inline: auto; white-space: pre-line; }
/* 標準樣式的小提醒＝一塊鋸齒剪邊的漂白棉（R13-B：整區沒有材質） */
.custom-block:not(.custom-block-card):not(.custom-block-quote) .custom-text { padding: 1.1rem 1.3rem; background: var(--linen), var(--paper-raise);
  --z: 3.5px;
  -webkit-mask: conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y, conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y, linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
  mask: conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y, conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y, linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
}
.custom-text:empty { display: none; }
.custom-block + .custom-block { margin-top: clamp(2.6rem, 8vw, 3.6rem); }
.custom-block-card {
  position: relative;
  padding: clamp(1.7rem, 6vw, 2.3rem) clamp(1.3rem, 5vw, 2rem);
  background: var(--paper-raise);
  border-radius: 4px;
  box-shadow: 0 14px 30px -24px rgba(var(--ink-rgb), .7);
}
.custom-block-card::before { content: ""; position: absolute; left: 1.2rem; right: 1.2rem; top: 7px; height: 4px; background: var(--accent); -webkit-mask: var(--st-h) left center / 66px 4px repeat-x; mask: var(--st-h) left center / 66px 4px repeat-x; pointer-events: none; }
.custom-block-quote .custom-text {
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-size: calc(clamp(1.1rem, 4vw, 1.25rem) * var(--wk-fs-heading, 1));
  line-height: 2;
  letter-spacing: .04em;
}
/* 引言：開頭一個十字繡的 × */
.custom-block-quote::before {
  content: "";
  display: block;
  width: 14px; height: 14px;
  margin: 0 auto 1.2rem;
  background:
    linear-gradient(45deg, transparent calc(50% - 1px), var(--accent) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)),
    linear-gradient(-45deg, transparent calc(50% - 1px), var(--accent) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px));
}
.custom-anchored { padding-bottom: var(--section-y); text-align: center; }
.custom-img { display: block; width: min(100%, 22rem); margin: 0 auto clamp(1.2rem, 4vw, 1.6rem); border-radius: 3px; }
.custom-block-side::after { content: ""; display: block; clear: both; }
@media (min-width: 560px) {
  .custom-block-side .custom-img { float: left; width: 42%; margin: .3rem 1.6rem .8rem 0; }
  .custom-block-side .custom-text { text-align: left; }
}

/* ⑤c 悄悄話：一塊縫上去的補布（塗層＝補布，刮開＝把補布拆掉） */
.secret .scratch-card {
  background: var(--paper-raise);
  border-radius: 4px;
  box-shadow: 0 14px 30px -24px rgba(var(--ink-rgb), .7);
}
.secret .scratch-card {
  --z: 6px;
  -webkit-mask:
    conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y,
    conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y,
    linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
  mask:
    conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y,
    conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y,
    linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
}
.secret .scratch-card::after {
  content: "";
  position: absolute;
  inset: 12px;
  background: var(--accent);
  -webkit-mask: var(--st-frame);
  mask: var(--st-frame);
  pointer-events: none;
  z-index: 3;
}
.secret .scratch-text {
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-size: calc(1.08rem * var(--wk-fs-heading, 1));
  color: var(--ink);
  white-space: pre-line;      /* 長悄悄話的換行靠這條（功能，不是裝飾，別刪） */
}
.secret .scratch-card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--linen), var(--linen);
  background-size: 300px 300px, 220px 220px;
  background-position: 0 0, 37px 61px;
  mix-blend-mode: multiply;
  opacity: 1;
  pointer-events: none;
}
.secret .scratch-card.is-revealed::before { opacity: .35; }
.secret .scratch-hint { z-index: 3; color: var(--ink);   /* 不要蓋 position：base.css 用 absolute＋50% 把提示放在補布正中（R13：寫成 relative 掉到底部） */ font-weight: 500; text-shadow: 0 1px 0 rgba(255, 255, 255, .7); font-size: 1.02rem; font-weight: 500; letter-spacing: .12em; text-indent: .12em; }
.secret .scratch-hint::after {
  content: "";
  display: block;
  width: 5.5rem;
  height: 4px;
  margin: .7rem auto 0;
  background: var(--accent-tx);
  -webkit-mask: var(--st-h) left center / 66px 4px repeat-x;
  mask: var(--st-h) left center / 66px 4px repeat-x;
  animation: st-swipe 2.4s ease-in-out infinite;
}
@keyframes st-swipe { 0%, 100% { transform: translateX(-14px); opacity: .5; } 50% { transform: translateX(14px); opacity: 1; } }
.secret .scratch-open { color: var(--ink); font-size: .95rem; border-radius: var(--radius); min-height: 44px; }

/* ════════════════════════════════════════════════════════════
   ⑤ Venue：地圖降彩＋一層織紋，像印在布上
   ════════════════════════════════════════════════════════════ */
.venue-hall {
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-size: calc(1.12rem * var(--wk-fs-heading, 1));
  font-weight: 600;
  letter-spacing: .06em;
  color: var(--ink);
}
.venue-hall:empty { display: none; }
.venue-address { color: var(--ink-soft); margin-top: .25rem; }
.venue-tag {
  width: fit-content;
  margin: 0 auto .8rem;
  padding: .2rem 1rem;
  font-size: var(--text-small);
  color: var(--accent-tx);
  background: var(--paper-raise);
  box-shadow: inset 0 0 0 1px rgba(var(--ink-rgb), .1);
}
.venue--dual .venue-card2 { margin-top: clamp(3rem, 9vw, 4rem); padding-top: clamp(3rem, 9vw, 4rem); position: relative; }
.venue--dual .venue-card2::before {
  content: "";
  position: absolute;
  top: 0; left: 50%;
  width: 6.6rem;
  height: 2px;
  margin-left: -3.3rem;
  background: var(--accent);
  -webkit-mask: var(--st-h) left center / 66px 4px repeat-x;
  mask: var(--st-h) left center / 66px 4px repeat-x;
  height: 4px;
}
.venue2-name {
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-size: calc(clamp(1.3rem, 4.8vw, 1.7rem) * var(--wk-fs-heading, 1));
  font-weight: 600;
  letter-spacing: .08em;
  line-height: 1.5;
}
.map-frame {
  position: relative;
  margin-top: clamp(1.9rem, 5vw, 2.6rem);
  aspect-ratio: 4 / 3;
  border-radius: 3px;
  overflow: hidden;
  --z: 5px;
  background: var(--sand);
  -webkit-mask:
    conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y,
    conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y,
    linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
  mask:
    conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y,
    conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y,
    linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
}
@media (min-width: 700px) { .map-frame { aspect-ratio: 16 / 8; } }
.map-frame::before { content: "地圖載入中⋯"; position: absolute; inset: 0; display: grid; place-items: center; color: var(--ink-soft); font-size: .92rem; letter-spacing: .1em; }
html.wk-lang-en .map-frame::before { content: "Loading map…"; }
.map-frame iframe { position: relative; width: 100%; height: 100%; border: 0; display: block; filter: grayscale(1) sepia(.32) contrast(.9) brightness(1.04); }
.map-frame::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--linen), rgba(241, 236, 225, .26);
  pointer-events: none;
}
.venue-bottom { margin: clamp(1.9rem, 5.5vw, 2.6rem) auto 0; max-width: 28rem; display: grid; gap: 1.6rem; justify-items: center; }
/* 交通資訊＝一塊鋸齒剪邊的漂白棉（R12-B：整屏只有細灰字，沒有布） */
.transport { display: grid; gap: 0; width: 100%; text-align: left; padding: .4rem 1.2rem; background: var(--linen), var(--paper-raise);
  --z: 3.5px;
  -webkit-mask: conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y, conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y, linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
  mask: conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y, conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y, linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
}
.transport:empty { display: none; }
.transport li {
  position: relative;
  display: grid; grid-template-columns: 3.6rem 1fr; gap: 1rem; align-items: baseline;
  padding-block: .95rem;
}
.transport li + li::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 1.4px;
  background: repeating-linear-gradient(90deg, rgba(var(--ink-rgb), .3) 0 6px, transparent 6px 11px);
}
.transport strong { font-weight: 500; color: var(--accent-tx); font-size: var(--text-small); }
.transport span { color: var(--ink-soft); white-space: pre-line; font-size: .98rem; }

/* ════════════════════════════════════════════════════════════
   ⑥ RSVP：換一塊顏色深一點的布（上緣一道鋸齒剪邊）
   ⚠ background-color 單獨寫：computed 的 backgroundColor 是 --sand，表單文字的對比基準就是它。
   ════════════════════════════════════════════════════════════ */
.rsvp { position: relative; background-color: var(--sand); background-image: var(--linen); }
html[data-wk-texture="off"] .rsvp { background-image: none; }
.rsvp::before {
  content: "";
  position: absolute;
  left: 0; right: 0;
  top: -6px;
  height: 6px;
  background: var(--sand);
  -webkit-mask: conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / 12px 6px repeat-x;
  mask: conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / 12px 6px repeat-x;
}
.rsvp-intro { max-width: 28em; margin-inline: auto; white-space: pre-line; }
.rsvp-deadline { font-size: var(--text-small); color: var(--ink-soft); margin-top: .5rem; }
.rsvp-form {
  position: relative;
  margin-top: clamp(2.2rem, 7vw, 3rem);
  padding: clamp(1.8rem, 6vw, 2.6rem) clamp(1.3rem, 5vw, 2.1rem);
  display: grid;
  gap: 1.5rem;
  text-align: left;
  background: var(--linen), var(--paper-raise);
  border-radius: 0;
  box-shadow: none;
  --z: 5px;
  -webkit-mask:
    conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y,
    conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y,
    linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
  mask:
    conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y,
    conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y,
    linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
}
/* 表單外框不再縫一圈（R9-C：外框、選項、按鈕、欄位全是針腳，疊太多層）——只留欄位底線與選項卡 */
.rsvp .field label, .rsvp .field legend { font-size: .95rem; letter-spacing: .02em; color: var(--ink); font-weight: 500; }
/* ⚠ iOS：input 字級必 ≥16px——這裡不宣告 font-size＝繼承 body，天生安全 */
.rsvp .field :is(input, textarea)::placeholder { color: #756b5f; opacity: 1; }   /* 對 --paper 4.6（R4-A：預設灰約 3:1） */
.rsvp .field input, .rsvp .field textarea, .rsvp .field select {
  background: var(--paper);
  border: 0;
  border-bottom: 2px dashed var(--accent);
  border-radius: 2px 2px 0 0;
  box-shadow: none;
  background: var(--paper-raise);
}
.rsvp .field textarea { resize: none; }
.rsvp .field :is(input, textarea, select) { background: var(--paper-raise); }
.field input:focus-visible, .field textarea:focus-visible, .field select:focus-visible {
  border-color: var(--accent-tx);
  box-shadow: 0 0 0 3px rgba(var(--ink-rgb), .1);
}
.rsvp .field select {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1.5 L6 6.5 L11 1.5' fill='none' stroke='%23665d52' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  padding-right: 2.6rem;
}
/* 錯誤字：對自己的底（表單＝--paper-raise）≥4.5 */
.rsvp .error-text, .rsvp-error { color: var(--warn); }
.rsvp .field.has-error input, .rsvp .field.has-error textarea { border-color: var(--warn); }
.attend-field { border: 0; }
.companion-list { display: grid; gap: .5rem; }
[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; }
.rsvp .cq-checks input[type="checkbox"] { width: 1.15rem; height: 1.15rem; flex: none; accent-color: var(--accent-tx); }
.attend-options { display: grid; grid-template-columns: 1fr 1fr; gap: .75rem; margin-top: .6rem; }
.attend-options.is-stack { grid-template-columns: 1fr; }
.attend-options.is-stack .attend-pill span { text-align: center; line-height: 1.5; letter-spacing: .06em; text-wrap: balance; }
/* 選項卡＝一枚布標：選中＝茜紅布、裡面一圈白針腳 */
.attend-pill { position: relative; }
.attend-pill input { position: absolute; opacity: 0; pointer-events: none; }
.attend-pill span {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  min-height: 50px;
  padding: .7rem 1rem;
  background: var(--paper);
  box-shadow: none;
  border-radius: var(--radius);
  letter-spacing: .06em;
  transition: background .35s var(--ease-out), color .35s var(--ease-out), box-shadow .35s var(--ease-out), scale .2s var(--ease-out);
  user-select: none;
}
.attend-pill span::after { display: none; }
.attend-pill span::before {
  content: "";
  position: absolute;
  inset: 5px;
  background: var(--accent);
  -webkit-mask: var(--st-frame-s);
  mask: var(--st-frame-s);
  opacity: .95;
  transition: background .35s var(--ease-out);
  pointer-events: none;
}
.attend-pill:active span { scale: .97; }
.attend-pill span { background: var(--linen), #e9e1d1; box-shadow: none; color: var(--ink);
  --z: 3.5px;
  -webkit-mask:
    conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y,
    conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y,
    linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
  mask:
    conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y,
    conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y,
    linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
}
.attend-pill input:checked + span::before {
  content: "";
  display: inline-block !important;
  width: .7em; height: .7em;
  margin-right: .45em;
  flex: none;
  background:
    linear-gradient(45deg, transparent calc(50% - 1px), currentColor calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)),
    linear-gradient(-45deg, transparent calc(50% - 1px), currentColor calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px));
}
.attend-pill { border-radius: var(--radius); }
.attend-pill:has(input:focus-visible) { outline: 2px solid var(--accent-tx); outline-offset: 3px; }
.attend-pill input:checked + span { background: var(--accent-tx); color: var(--accent-ink); box-shadow: none; }
.attend-pill input:checked + span::after { background: rgba(255, 255, 255, .7); }
.attend-pill input:focus-visible + span { box-shadow: 0 0 0 3px rgba(var(--ink-rgb), .18); }
.rsvp-details { display: grid; gap: 1.5rem; }
.field-row { display: grid; gap: 1.5rem; }
@media (min-width: 520px) { .field-row { grid-template-columns: repeat(3, 1fr); } }
.stepper {
  display: grid;
  grid-template-columns: 3rem 1fr 3rem;
  align-items: stretch;
  min-height: 48px;
  background: var(--paper);
  box-shadow: none;
  border-radius: var(--radius);
  overflow: hidden;
  position: relative;
}
.stepper { background: var(--paper-raise); box-shadow: inset 0 0 0 1.5px rgba(var(--ink-rgb), .45) !important; }
.rsvp .field .stepper input { border: 0; background: transparent; text-align: center; padding-inline: .25rem; }
.stepper input::-webkit-outer-spin-button, .stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.stepper input[type="number"] { -moz-appearance: textfield; }
.rsvp .field .stepper input:focus-visible { box-shadow: none; border-color: transparent; }
.stepper:focus-within { box-shadow: 0 0 0 3px rgba(var(--ink-rgb), .12); }
.stepper button { border: 0; background: transparent; cursor: pointer; color: var(--ink); font-size: 1.2rem; line-height: 1; transition: background .3s var(--ease-out), opacity .3s var(--ease-out); }
.stepper button:active { background: rgba(var(--ink-rgb), .08); }
.stepper button[disabled] { opacity: .3; cursor: default; }
.cap-note { font-size: var(--text-small); color: var(--ink-soft); }
.rsvp-error { font-size: var(--text-small); }
.rsvp-submit { width: 100%; min-height: 54px; letter-spacing: .12em; font-weight: 500; border-radius: 0;   /* 600 會被合成加粗、字發糊（R12） */
  --z: 4px;
  -webkit-mask:
    conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y,
    conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y,
    linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
  mask:
    conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x,
    conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y,
    conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y,
    linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
}
.rsvp-submit::before {
  content: "" !important;
  display: block !important;
  position: absolute;
  inset: 7px;
  background: rgba(255, 255, 255, .55);
  -webkit-mask: var(--st-frame-s);
  mask: var(--st-frame-s);
  pointer-events: none;
}
.rsvp-submit:focus-visible { outline: 2px solid var(--accent-tx); outline-offset: 4px; }
.rsvp-success, .rsvp-closed {
  position: relative;
  margin-top: clamp(2.2rem, 7vw, 3rem);
  text-align: center;
  display: grid;
  gap: .75rem;
  justify-items: center;
  padding: clamp(2.2rem, 6vw, 3rem) var(--gutter);
  background: var(--paper-raise);
  border-radius: 4px;
  box-shadow: var(--shadow-soft);
}
.rsvp-success::before, .rsvp-closed::before {
  content: "";
  position: absolute;
  inset: 8px;
  background: var(--accent);
  -webkit-mask: var(--st-frame);
  mask: var(--st-frame);
  pointer-events: none;
}
.success-mark {
  width: 2.8rem; height: 2.8rem;
  display: grid; place-items: center;
  background: var(--accent-tx);
  color: var(--accent-ink);
  font-size: 1.3rem;
  border-radius: 6px;
  rotate: -4deg;
}
.rsvp-success h3, .rsvp-closed h3 {
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-size: calc(clamp(1.2rem, 3.2vw, 1.4rem) * var(--wk-fs-heading, 1));
  font-weight: 600;
  letter-spacing: .06em;
}
/* 紀念章＝一枚縫上去的小布標（×＋see you there），落章動畫在 base.css（wk-stamp-drop） */
.rsvp-stamp {
  --stamp-rot: -8deg;
  position: absolute;
  top: 1rem; right: 1rem;
  width: 4.6rem;
  padding: .55rem .3rem .5rem;
  display: grid;
  justify-items: center;
  gap: .3rem;
  background: var(--paper);
  color: var(--accent-tx);
  box-shadow: 0 5px 10px -7px rgba(var(--ink-rgb), .6);
}
.rsvp-stamp::before {
  content: "";
  position: absolute;
  inset: 3px;
  background: var(--accent);
  -webkit-mask: var(--st-frame-s);
  mask: var(--st-frame-s);
  pointer-events: none;
}
.rsvp-stamp i {
  width: 12px; height: 12px;
  background:
    linear-gradient(45deg, transparent calc(50% - 1px), currentColor calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)),
    linear-gradient(-45deg, transparent calc(50% - 1px), currentColor calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px));
}
.rsvp-stamp em {
  font-family: var(--wk-f-latin, var(--font-serif-latin));
  font-style: italic;
  font-weight: 600;
  font-size: .72rem;
  line-height: 1.15;
  letter-spacing: .06em;
  text-align: center;
}
.success-note { font-size: var(--text-small); color: var(--ink-soft); }

/* ════════════════════════════════════════════════════════════
   ⑦ Footer：收線
   ════════════════════════════════════════════════════════════ */
.footer {
  padding: var(--section-y) var(--gutter) max(3.2rem, env(safe-area-inset-bottom, 0px) + 2.4rem);
  text-align: center;
}
.footer .stitch-rule { margin-top: 0; margin-bottom: 1.8rem; }
.footer-yours {
  font-family: var(--wk-f-latin, var(--font-serif-latin));
  font-size: calc(1.05rem * var(--wk-fs-latin, 1));
  font-style: italic;
  font-weight: 500;
  letter-spacing: .24em;
  text-indent: .24em;
  text-transform: lowercase;
  color: var(--accent-tx);
}
.footer-message { max-width: 24em; margin: 1.2rem auto 0; white-space: pre-line; }
.footer-names {
  margin-top: 1rem;
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-size: calc(1.1rem * var(--wk-fs-heading, 1));
  font-weight: 600;
  letter-spacing: .1em;
}
.footer-brand {
  display: inline-block;
  margin-top: 2.4rem;
  padding: .6rem 1rem;
  min-height: 44px;
  line-height: calc(44px - 1.2rem);
  font-size: var(--text-tiny);
  color: var(--ink-soft);
  text-decoration: none;
  letter-spacing: .06em;
}
.footer-brand:hover { color: var(--ink); }
.footer-contacts { margin-top: 2rem; display: flex; flex-direction: column; align-items: center; gap: 1.5rem; }
.footer-contacts[hidden] { display: none; }
.contact-row { display: inline-flex; align-items: center; gap: .5rem; }
.contact-who { font-size: .92rem; color: var(--ink); letter-spacing: .04em; margin-right: .3rem; }
.contact-ico {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;
  margin-block: -6px 6px;
  color: var(--ink-soft);
  transition: color .3s var(--ease-out), transform .3s var(--ease-out);
}
.contact-ico svg { width: 20px; height: 20px; display: block; }
.contact-ico:hover { color: var(--accent-tx); transform: translateY(-1px); }
.contact-ico[data-kind]::after {
  position: absolute;
  left: 50%; top: calc(50% + 14px);
  translate: -50% 0;
  font-size: .72rem;
  line-height: 1;
  letter-spacing: .06em;
  white-space: nowrap;
  color: var(--ink-soft);
}
.contact-ico[data-kind="phone"]::after { content: "電話"; }
.contact-ico[data-kind="line"]::after  { content: "LINE"; }
.contact-ico[data-kind="ig"]::after    { content: "IG"; }

/* ⑦c 終章祝福「十字繡」：小木繡框裡一塊十字繡布（Aida），按住一格一格繡 */
.blessing { margin-top: clamp(2.8rem, 8vw, 3.6rem); }
.blessing-lead { max-width: 19em; margin-inline: auto; font-size: .98rem; line-height: 1.7; color: var(--ink-soft); }
.blessing-seal {
  display: block;
  width: min(100%, 19rem);
  margin: 1.1rem auto 0;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  touch-action: none;                 /* 按住蓄力期間不捲頁（小面積按鈕才准用 none） */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  border-radius: 12px;
}
.blessing-seal:focus-visible { outline: 2px solid var(--accent-tx); outline-offset: 5px; }
.xs-hoop {
  position: relative;
  display: block;
  padding: 9px;
  border-radius: 12px;
  background:
    var(--wood-grain) 0 0 / 240px 240px,
    linear-gradient(135deg, var(--wood-l), var(--wood) 40%, var(--wood-d));
  box-shadow: 0 18px 34px -24px rgba(var(--ink-rgb), .6), inset 0 0 0 1px rgba(0, 0, 0, .12);
  transition: transform .3s var(--ease-out);
}
.blessing-seal.is-pressing .xs-hoop { transform: scale(.985); }
/* 繡布（Aida）：規律的格子孔，十字繡格點畫在上面的 svg 裡；針在同一層，跟著剛繡好的那一格走 */
.xs-cloth {
  position: relative;
  display: block;
  border-radius: 5px;
  background:
    radial-gradient(circle, rgba(var(--ink-rgb), .16) .7px, transparent 1.1px) 0 0 / 7px 7px,
    var(--paper-raise);
  box-shadow: inset 0 2px 6px rgba(var(--ink-rgb), .18);
}
.xs-grid {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: var(--xs-ratio, 2);
  max-width: none;
  overflow: visible;
}
.xs-needle {
  position: absolute;
  left: var(--nx, 10%);
  top: var(--ny, 20%);
  width: 44px;
  height: 66px;
  max-width: none;
  margin: -62px 0 0 -5px;            /* 針尖（svg 的 4,56）對準格子中心 */
  overflow: visible;
  pointer-events: none;
  transition: left .03s linear, top .03s linear, opacity .4s;   /* 一秒繡兩三百格：過渡太長針會落後好幾格 */
}
.nd-shadow { fill: none; stroke: rgba(var(--ink-rgb), .2); stroke-width: 2.4; stroke-linecap: round; }
.nd-body { fill: none; stroke: #8f8a80; stroke-width: 2.4; stroke-linecap: round; }
.nd-eye { fill: var(--paper-raise); }
.nd-thread { fill: none; stroke: var(--accent); stroke-width: 1.5; stroke-linecap: round; }
/* 繡的時候針一上一下（穿過布） */
.xs-cloth.is-stitching .xs-needle { animation: st-needle .18s ease-in-out infinite alternate; }
@keyframes st-needle { from { translate: 0 0; } to { translate: -2px 5px; } }
.blessing.is-sealed .xs-needle { opacity: 0; transform: translate(14px, -24px); transition: opacity .5s .2s, transform .6s var(--ease-out); }
.xs-plan circle { fill: var(--accent); opacity: .72; }
.xs {
  fill: none;
  stroke: var(--accent);
  stroke-width: .17;
  stroke-linecap: round;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: 50% 50%;
}
.xs.is-on { opacity: 1; }
.xs.is-new { animation: st-xs .28s cubic-bezier(.3, 1.6, .5, 1); }
@keyframes st-xs { from { transform: scale(1.7); opacity: .3; } to { transform: none; opacity: 1; } }
/* 打結＋剪線：蓄滿那一刻，最後一針旁邊打一個結（留著）、多出來的線尾被剪斷落下 */
.xs-snip {
  position: absolute;
  left: var(--nx, 90%);
  top: var(--ny, 80%);
  width: 60px;
  height: 36px;
  margin: -18px 0 0 24px;
  max-width: none;
  overflow: visible;
  opacity: 0;
  pointer-events: none;
}
.xs-snip .sn-tail { fill: none; stroke: var(--accent); stroke-width: 1.6; stroke-linecap: round; }
.xs-snip .sn-knot { fill: var(--accent); stroke: var(--accent-tx); stroke-width: .8; }
.xs-snip .sn-ring { fill: none; stroke: var(--accent); stroke-width: 1.2; opacity: 0; }
.xs-snip .sn-coil { fill: none; stroke: var(--accent-tx); stroke-width: .8; stroke-linecap: round; }
.blessing.is-sealed .xs-snip .sn-ring { animation: st-ring .9s var(--ease-out) .15s both; transform-box: fill-box; transform-origin: center; }
@keyframes st-ring { 0% { opacity: 1; transform: scale(.6); } 100% { opacity: 0; transform: scale(5); } }
.xs-snip .sn-ring { stroke-width: 2.4; }
.blessing.is-sealed .xs-snip { opacity: 1; transition: opacity .2s .1s; }
.blessing.is-sealed .xs-snip :is(.sn-knot, .sn-coil) { animation: st-knot .7s cubic-bezier(.3, 1.6, .5, 1) .05s both; transform-box: fill-box; transform-origin: center; }
.blessing.is-sealed .xs-snip .sn-tail { animation: st-cut 1.1s var(--ease-out) .8s both; transform-box: view-box; }
@keyframes st-knot { 0% { transform: scale(0); } 45% { transform: scale(3.6); } 100% { transform: scale(2.6); } }
.blessing.is-sealed .xs-snip :is(.sn-knot, .sn-coil) { transform: scale(2.6); transform-box: view-box; transform-origin: 5px 12px; }
.blessing.is-sealed .xs-cloth { animation: st-taut .6s cubic-bezier(.3, 1.6, .5, 1) .1s; }
@keyframes st-taut { 0%, 100% { transform: none; } 35% { transform: scale(.985, .97); } }
@keyframes st-cut {
  0%   { transform: none; opacity: 1; }
  25%  { transform: translate(2px, -1px); opacity: 1; }
  100% { transform: translate(10px, 30px) rotate(40deg); opacity: 0; }
}
/* 簽名布標：繡完才縫上去「◯◯ 繡 · 11.14」——這一格是賓客想截圖的那一張 */
.xs-sign {
  position: absolute;
  left: 8%;                            /* 線結在名字的右下，布標放左下，兩個焦點不打架（R6-C） */
  bottom: -2.6rem;                     /* 整枚在木框外（R7-B：壓到框下緣 8px） */
  z-index: 2;
  padding: .28rem .8rem .3rem;
  background: var(--paper-raise);
  color: var(--accent-tx);
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-style: normal;
  font-weight: 600;
  font-size: .9rem;
  letter-spacing: .08em;
  white-space: nowrap;
  rotate: -3deg;
  box-shadow: 0 5px 10px -7px rgba(var(--ink-rgb), .6);
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
}
.xs-sign:empty { display: none; }
.xs-sign::before {
  content: "";
  position: absolute;
  inset: 3px;
  background: var(--accent);
  -webkit-mask: var(--st-frame-s);
  mask: var(--st-frame-s);
}
.blessing.is-sealed .xs-sign { opacity: 1; transform: none; transition: opacity .5s var(--ease-out) 1.5s, transform .6s cubic-bezier(.3, 1.5, .5, 1) 1.5s; }
.blessing-hint { margin-top: 1.1rem; font-size: .95rem; letter-spacing: .08em; color: var(--accent-tx); }
.blessing-seal.wants-hold + .blessing-hint { animation: st-nudge .5s ease-in-out 2; }
@keyframes st-nudge { 0%, 100% { transform: none; } 30% { transform: translateX(-5px); } 70% { transform: translateX(5px); } }
.blessing.is-sealed .blessing-hint { display: none; }
.blessing-done {
  margin-top: 3.8rem;
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: .08em;
  color: var(--accent-tx);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity .7s var(--ease-out) .4s, transform .7s var(--ease-out) .4s;
}
.blessing-done:empty { display: none; }
.blessing.is-sealed .blessing-done { opacity: 1; transform: none; }

/* 彩蛋：針線盒（點開掉出一枚頂針） */
.ps-egg {
  --z: 3.5px;
  -webkit-mask: conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y, conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y, linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
  mask: conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y, conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y, linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
  display: flex;
  width: fit-content;
  margin-inline: auto;
  align-items: center;
  gap: .55rem;
  margin-top: 2rem;
  padding: .65rem 1.1rem;
  min-height: 44px;
  position: relative;
  border: 0;
  border-radius: var(--radius);
  background: var(--linen), #e9e1d1;
  box-shadow: none;
  color: var(--ink);
  font-size: .94rem;
  letter-spacing: .04em;
  cursor: pointer;
}
.ps-egg[hidden] { display: none; }
.ps-egg::before {
  content: "";
  width: 18px; height: 13px;
  border-radius: 2px 2px 4px 4px;
  background: linear-gradient(var(--wood-l), var(--wood) 45%, var(--wood-d) 46%, var(--wood-d) 54%, var(--wood) 55%);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .15);
}
.ps-egg:hover { color: var(--ink); }

.ps-egg-text {
  display: grid;
  justify-items: center;
  gap: .6rem;
  max-width: 22em;
  margin: 2rem auto 0;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .6s var(--ease-out), transform .6s var(--ease-out);
}
.ps-egg-text[hidden] { display: none; }
.ps-egg-text.is-open { opacity: 1; transform: none; }
.ps-thimble { width: 3.4rem; height: auto; overflow: visible; filter: drop-shadow(0 4px 4px rgba(var(--ink-rgb), .2)); }
.ps-egg-text.is-open .ps-thimble { animation: st-drop .9s cubic-bezier(.3, 1.5, .5, 1) both; }
@keyframes st-drop {
  0%   { transform: translateY(-38px) rotate(-30deg); opacity: 0; }
  40%  { opacity: 1; }
  70%  { transform: translateY(2px) rotate(6deg); }
  100% { transform: none; }
}
.th-body { fill: var(--wood-l); stroke: var(--wood-d); stroke-width: 1.4; }
.th-rim { fill: var(--wood-d); }
.th-dots circle { fill: var(--wood-d); }
.ps-egg-say { font-family: var(--wk-f-heading, var(--font-serif-tc)); font-size: 1rem; letter-spacing: .06em; color: var(--ink); white-space: pre-line; text-wrap: balance; line-break: strict; }
:is(.footer-message, .blessing-lead, .blessing-done, .dc-note, .rsvp-intro, .tl-text, .custom-text, .hero-greeting, .st-button-say) { text-wrap: pretty; line-break: strict; }

/* 粒子的皮（WKFX.tapBurst／burstAt 的物件池）：小小的 × 與線段 */
.wk-cross-p {
  width: 10px; height: 10px;
  background:
    linear-gradient(45deg, transparent calc(50% - 1px), var(--accent) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px)),
    linear-gradient(-45deg, transparent calc(50% - 1px), var(--accent) calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px));
}
.wk-thread-p { width: 9px; height: 2px; border-radius: 2px; background: var(--accent); }

/* ============ shared 婚紗照版式的覆寫（/shared/gallery-layouts.css） ============
   ⚠ 特異度 (1,1,0) 高於 gallery-layouts.css :root 的預設 (0,1,0)。 */
#gallery[data-wk-gallery] { --gl-frame-shadow: var(--shadow-soft); }

/* ---------- reduced-motion：不降級 ----------
   2026-10-01 起賓客頁不因 RM 降級（DESIGN §7）：index.html 的旗標 script 在 <html> 掛
   wk-keep-motion，base.css 的 RM 通殺整段讓位。這一款從頭就沒有 RM 分支——開場、針腳、
   十字繡、彩蛋都跟一般模式同一套。?preview=1 不掛旗標＝編輯器預覽照樣素顏。 */

/* ============ 桌機（≥960px）：Hero 走左圖右文 ============ */
@media (min-width: 960px) {
  .hero-content {
    max-width: 62rem;
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    grid-template-areas:
      "frame ."
      "frame label"
      "frame greet"
      "frame mono"
      "frame names"
      "frame en"
      "frame date"
      "frame cd"
      "frame btn"
      "frame say"
      "frame .";
    grid-template-rows: 1fr auto auto auto auto auto auto auto auto auto 1fr;
    column-gap: clamp(3rem, 6vw, 5rem);
    align-items: center;
    justify-items: center;
    text-align: center;
  }
  .hero-frame { grid-area: frame; width: 100%; max-width: 25rem; margin-top: 0; align-self: center; }
  .hero-label { grid-area: label; align-self: end; }
  .hero-greeting { grid-area: greet; }
  .hero-mono { grid-area: mono; }
  .hero-names { grid-area: names; font-size: calc(clamp(2.4rem, 3.8vw, 3.2rem) * var(--wk-fs-heading, 1) * var(--names-fit, 1)); }
  .hero-names-en { grid-area: en; }
  .hero-date { grid-area: date; }
  .countdown { grid-area: cd; }
  .st-button { grid-area: btn; }
  .st-button-say { grid-area: say; }
  html.has-intro .intro { --st-arc: 18px; }
  .parents { max-width: 26em; margin-inline: auto; text-wrap: balance; font-family: var(--wk-f-heading, var(--font-serif-tc)); }
  html.has-intro .intro { --seam-top: 42%; --seam-bot: 74%; }
  /* 桌機縫線放大一號（R6-C：只有 35px 寬，像拉鍊） */
  .seam { width: 44px; margin-left: -22px; }
  .rung { height: 3px; }
  .intro-tail { width: 46px; margin-left: -23px; height: clamp(6rem, 13vh, 8.5rem); }
  .intro-mono { width: 23rem; margin-left: -11.5rem; }
  /* 桌機：布一分開就看得到右欄（R14-C：720ms 那格縮寫已到、布章與文字還沒出來，右欄半空） */
  html.fx.has-intro.wk-stitch-landed .hero-content > :not(.hero-frame):not(.hero-mono).is-in { transition: opacity .45s var(--ease-out) .12s !important; }
  html.has-intro.wk-stitch-landed .hero-mono { transition: opacity .35s var(--ease-out) .2s; }
  .hero { min-height: 100svh; display: grid; align-content: center; padding-block: 4rem; }
  :root { --section-y: clamp(3.6rem, 7vh, 5.6rem); }
  .hero-mono { width: 10.5rem; }
  .details > .container { max-width: 56rem; display: grid; grid-template-columns: 19rem minmax(0, 1fr); column-gap: 4.5rem; align-items: center; }
  .details > .container > :not(.wk-cal):not(.event-list) { grid-column: 1 / -1; }
  .details > .container > .wk-cal { grid-column: 1; margin-top: 2rem; }
  .details > .container > .wk-cal[hidden] + .event-list { grid-column: 1 / -1; }
  .details > .container > .event-list { grid-column: 2; margin-top: 2rem; max-width: none; position: relative; padding-left: 2.4rem; }
  /* 時程欄左邊一道直向手縫針腳，跟月曆卡隔開 */
  .details > .container > .event-list::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--accent); opacity: .7; -webkit-mask: var(--st-v) center top / 4px 66px repeat-y; mask: var(--st-v) center top / 4px 66px repeat-y; }
  .wk-cal { max-width: 19rem; }
  /* 地圖收成一張跟交通資訊同寬的布片，不再滿版搶戲 */
  #venue:not(.venue--dual) > .container-wide { max-width: 60rem; }
  .map-frame { aspect-ratio: auto; height: 26rem; max-width: 60rem; margin-inline: auto; }
  .venue-bottom { max-width: 40rem; }
  /* 線軸放大 */
  .dc-swatch { width: 3.4rem; height: 4.4rem; }
  .dc-swatches { gap: 2.4rem; }
  /* 相簿與下一區之間不留大洞 */
  #gallery:not([data-wk-gallery]) .photo-grid { max-width: 64rem; }
  .parents { font-size: var(--text-body); }
  .timeline { max-width: 48rem; }
  .tl-text { font-size: 1.1rem; }
  .tl-title { font-size: calc(1.4rem * var(--wk-fs-heading, 1)); }
  .timeline-item > .tl-date { position: relative; justify-self: end; height: fit-content; padding: .2rem .7rem; background: var(--paper-raise); box-shadow: 0 5px 10px -8px rgba(var(--ink-rgb), .6); rotate: -2deg; }
  .timeline-item > .tl-date::before { content: ""; position: absolute; inset: 3px; background: var(--accent); -webkit-mask: var(--st-frame-s); mask: var(--st-frame-s); }
  .timeline-item { display: grid; grid-template-columns: 7rem minmax(0, 1fr); column-gap: 1.6rem; padding-left: 0; }
  .timeline-item > * { grid-column: 2; }
  .timeline-item > .tl-date { grid-column: 1; grid-row: 1 / span 2; text-align: right; padding-top: .15rem; }
  .timeline-item::before { left: calc(7rem + .8rem - 1px); }
  .timeline-item::after { left: calc(7rem + .8rem - .31rem); }
  .rsvp > .container { max-width: 44rem; }
  .blessing-seal { width: min(100%, 36rem); }
  .xs-sign { font-size: 1.05rem; }
  .tl-text, .custom-text, .rsvp-intro, .footer-message { font-size: 1.06rem; }
  body::before, body::after {
    content: "";
    position: fixed;
    top: 0; bottom: 0;
    width: 4px;
    z-index: 1;                         /* 在區塊底色上面（R13：RSVP 那塊深色布把左邊那道蓋掉） */
    background: var(--accent);
    opacity: .55;
    -webkit-mask: var(--st-v) center top / 4px 66px repeat-y;
    mask: var(--st-v) center top / 4px 66px repeat-y;
    pointer-events: none;
  }
  body::before { left: max(2.4rem, calc(50vw - 36rem)); }
  body::after { right: max(2.4rem, calc(50vw - 36rem)); }
  .intro-names { font-size: calc(1.35rem * var(--names-fit, 1)); bottom: calc(100% - var(--seam-top) + 11.5rem + 1rem); }
  .intro-date { font-size: 1.2rem; bottom: calc(100% - var(--seam-top) + 11.5rem + 4.4rem); }
}

/* ============================================================
   字型庫 bridge（P2-26）——由 shared/fonts.js（WKFONTS）驅動
   ⚠ gate 屬性名與變數名都由引擎決定（tools/fonts-check.mjs 會逐條核對），別改拼法。
   ============================================================ */
html[data-wkf-ls-heading] :is(.hero-names, .section-title, .tl-title, .event-row dd strong, .venue2-name, .venue-hall, .footer-names, .details-date, .intro-names, .hero-greeting, .rsvp-success h3, .rsvp-closed h3) { letter-spacing: var(--wk-fls-heading); }
html[data-wkf-lh-heading] :is(.hero-names, .section-title, .tl-title, .event-row dd strong, .venue2-name, .venue-hall, .footer-names, .details-date, .intro-names, .hero-greeting, .rsvp-success h3, .rsvp-closed h3) { line-height: var(--wk-flh-heading); }
html[data-wkf-w-heading] :is(.hero-names, .section-title, .tl-title, .event-row dd strong, .venue2-name, .venue-hall, .footer-names, .details-date, .intro-names, .hero-greeting, .rsvp-success h3, .rsvp-closed h3) { font-weight: var(--wk-fw-heading); }

html[data-wkf-ls-body] :is(body, .tl-text, .hero-note, .venue-tag, .blessing-lead) { letter-spacing: var(--wk-fls-body); }
html[data-wkf-lh-body] :is(body, .tl-text, .hero-note, .venue-tag, .blessing-lead) { line-height: var(--wk-flh-body); }
html[data-wkf-w-body] :is(body, .tl-text, .hero-note, .venue-tag, .blessing-lead) { font-weight: var(--wk-fw-body); }

html[data-wkf-ls-latin] :is(.label-en, .hero-label, .hero-names-en, .cd-cell strong, .tl-date, .wk-cal-title, .event-row dt, .footer-yours, .tag-front) { letter-spacing: var(--wk-fls-latin); }
html[data-wkf-lh-latin] :is(.label-en, .hero-label, .hero-names-en, .cd-cell strong, .tl-date, .wk-cal-title, .event-row dt, .footer-yours, .tag-front) { line-height: var(--wk-flh-latin); }
html[data-wkf-w-latin] :is(.label-en, .hero-label, .hero-names-en, .cd-cell strong, .tl-date, .wk-cal-title, .event-row dt, .footer-yours, .tag-front) { font-weight: var(--wk-fw-latin); }
html[data-wkf-i-latin] :is(.label-en, .hero-label, .hero-names-en, .cd-cell strong, .tl-date, .wk-cal-title, .event-row dt, .footer-yours, .tag-front) { font-style: italic; }

/* ============================================================
   英文版（P2-10）：只在 html.wk-lang-en（shared/i18n.js 掛的）生效，中文版一個像素都不動。
   ① 拉丁字型排第一（Noto TC 的 ’ “ ” 是全形）② 中文的寬字距在英文歸到 0–.04em
   ③ 與名字重複的英文副標收掉 ④ 英文比中文長：按鈕與選項卡允許折行、text-wrap: balance
   ============================================================ */
@font-face {
  font-family: "WK Latin Quotes";
  src: local("Georgia"), local("Times New Roman"), local("Noto Serif"), local("Droid Serif");
  unicode-range: U+2018-201F;
}
html.wk-lang-en {
  --font-serif-tc: "WK Latin Quotes", "Xitie Serif", "Noto Serif TC", "Songti TC", "PMingLiU", serif;
  --font-sans-tc: "Cormorant Garamond", "Noto Sans TC", "PingFang TC", Georgia, serif;
}
html.wk-lang-en body { font-size: calc(var(--text-body) * 1.1); font-weight: 500; letter-spacing: 0; hyphens: manual; }
html.wk-lang-en .hero-names-en { display: none; }
html.wk-lang-en .section-title { letter-spacing: .02em; text-indent: 0; text-wrap: balance; }
html.wk-lang-en .hero-names { letter-spacing: .03em; }
html.wk-lang-en .intro-names { letter-spacing: .04em; }
html.wk-lang-en :is(.tl-title, .details-date, .event-row dd strong, .venue2-name, .venue-hall, .footer-names, .rsvp-success h3, .rsvp-closed h3, .custom-block-quote .custom-text, .hero-greeting, .blessing-done, .ps-egg-say) { letter-spacing: .02em; }
html.wk-lang-en :is(.hero-note, .venue-tag, .contact-who, .footer-brand, .st-button-say, .blessing-hint) { letter-spacing: .03em; }
html.wk-lang-en :is(.event-row dt, .wk-cal-title) { letter-spacing: .08em; }
html.wk-lang-en :is(.rsvp .field label, .rsvp .field legend, .attend-pill span, .btn) { letter-spacing: .02em; }
html.wk-lang-en .secret .scratch-hint { letter-spacing: .04em; text-indent: 0; }
html.wk-lang-en :is(.details-date, .details-note, .tl-text, .dc-note, .rsvp-intro, .rsvp-deadline, .footer-message, .blessing-lead, .venue-address, .hero-greeting) { text-wrap: balance; }
html.wk-lang-en .intro-guide { white-space: normal; width: max-content; max-width: min(19em, calc(100vw - 2.5rem)); text-align: center; line-height: 1.4; text-wrap: balance; }
html.wk-lang-en .tag-back { font-family: var(--wk-f-latin, var(--font-serif-latin)); font-style: italic; font-size: 1.02rem; letter-spacing: .02em; }
html.wk-lang-en .contact-ico[data-kind="phone"]::after { content: "Phone"; }
@media (max-width: 720px) {
  html.wk-has-lang .hero { padding-top: calc(clamp(3rem, 10vw, 4.6rem) + 16px); }
}

/* 按鈕與選項卡不再縫整圈（R11 收斂：針腳只留分隔、繡框、布章、布標、相簿、表單底線、終章） */
.btn:not(.btn-ghost)::before { display: none; }


/* ════════════════════════════════════════════════════════════
   R16 改版：「刺繡樣本布海報」（2026-11-01 Jacob：中規中矩、要「哇」）
   ① 尺度反差：名字放到海報級、左右錯開；② 拿掉優惠券式虛線框，針腳改成手縫的 Z 字（相簿、繡框）；
   ③ 婚期＝一條織標緞帶（兩端剪燕尾）；④ 每一區標題下是一條縫進來的波浪線（中間繞一個線圈）。
   ════════════════════════════════════════════════════════════ */
:root {
  /* 手縫 Z 字針（一針斜上、一針斜下，中間留一點空——手縫，不是車縫的連續鋸齒） */
  --st-zh: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='7'%3E%3Cpath d='M1.5 5.6L5.6 1.4M8.4 1.4l4.1 4.2' stroke='%23000' stroke-width='1.7' stroke-linecap='round'/%3E%3C/svg%3E");
  --st-zv: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='14'%3E%3Cpath d='M5.6 1.5L1.4 5.6M1.4 8.4l4.2 4.1' stroke='%23000' stroke-width='1.7' stroke-linecap='round'/%3E%3C/svg%3E");
  --st-zframe: var(--st-zh) top left / 14px 7px repeat-x, var(--st-zh) bottom left / 14px 7px repeat-x, var(--st-zv) top left / 7px 14px repeat-y, var(--st-zv) top right / 7px 14px repeat-y;
}

/* ── 標題系統：放大一階，眉標貼近 ── */
.section-title {
  font-size: calc(clamp(1.95rem, 7.6vw, 2.9rem) * var(--wk-fs-heading, 1));
  line-height: 1.3;
  letter-spacing: .1em;
  text-indent: .1em;
}
/* 標題下的線：一條波浪的繡線，中間繞一個線圈，兩端打結；捲進畫面時從左往右縫進來 */
.stitch-rule { width: min(19rem, 76vw); height: auto; margin-top: .9rem; }
.stitch-rule::before, .stitch-rule::after { display: none; }
.stitch-rule svg { display: block; width: 100%; height: auto; overflow: visible; }
.stitch-rule .tr, .stitch-rule .tr-sh { fill: none; stroke-width: 2.4; stroke-linecap: round; stroke-dasharray: 9 5.5; }
.stitch-rule .tr { stroke: var(--accent); }
.stitch-rule .tr-sh { stroke: rgba(var(--ink-rgb), .2); transform: translate(.6px, 1.4px); }
.stitch-rule .tr-k { fill: var(--accent-tx); }
html.fx .stitch-rule svg { clip-path: inset(-20% 100% -20% 0); }
html.fx .stitch-rule.is-in svg { animation: st-sew-wide 1.2s steps(16) .2s both; }
@keyframes st-sew-wide { from { clip-path: inset(-20% 100% -20% 0); } to { clip-path: inset(-20% -2% -20% -2%); } }
.footer .stitch-rule { margin-bottom: 1.8rem; }

/* ── Hero ── */
.hero-content { max-width: 26rem; }
.hero-content > .hero-greeting { margin-bottom: clamp(1.4rem, 5vw, 2rem); }
/* 繡框放大到幾乎滿版：這張照片就是整張帖的主角 */
.hero-frame { width: min(90vw, 25rem); margin-top: 0; }
/* 照片四周：手縫 Z 字針（不是虛線框） */
.hero-mat::after { inset: 5px; -webkit-mask: var(--st-zh) top left / 16px 8px repeat-x, var(--st-zh) bottom left / 16px 8px repeat-x, var(--st-zv) top left / 8px 16px repeat-y, var(--st-zv) top right / 8px 16px repeat-y; mask: var(--st-zh) top left / 16px 8px repeat-x, var(--st-zh) bottom left / 16px 8px repeat-x, var(--st-zv) top left / 8px 16px repeat-y, var(--st-zv) top right / 8px 16px repeat-y; }
/* 縮寫布章：縫在繡框左上角、斜著壓上去（拼貼，不再是置中的一個小方塊） */
.hero-mono { --mono-rot: -6deg; rotate: var(--mono-rot); }
.hero-content > .hero-mono {
  order: 3;
  align-self: flex-start;
  position: relative;
  z-index: 3;
  width: clamp(7.4rem, 36vw, 9.4rem);
  margin: 0 0 -1.05rem -2%;           /* 只壓在木框與布邊上，絕不蓋到照片（裝飾不蓋照片） */
}
/* 名字：海報級大字、新郎靠左、新娘靠右，中間一個繡線打的 ✕ */
.hero-names {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
  margin-top: clamp(1.4rem, 5vw, 2rem);
  font-size: calc(clamp(2.9rem, 15.5vw, 4.5rem) * var(--wk-fs-heading, 1) * var(--names-fit, 1));
  line-height: 1.12;
  letter-spacing: .08em;
}
.hero-names > #name-groom { justify-self: start; }
.hero-names > #name-bride { justify-self: end; }
.hero-names .amp { justify-self: center; width: .46em; height: .46em; margin: -.05em 0; }
.hero-names .amp path { stroke-width: 3; }
.hero-names-en { margin-top: .6rem; }
/* 婚期＝一條織標緞帶：茜紅底、兩端剪燕尾、細細的織紋、白線兩針縫住 */
.hero-tag { filter: drop-shadow(0 8px 10px rgba(var(--ink-rgb), .22)); }
.tag-face {
  padding: .7rem 2.3rem .74rem;
  box-shadow: none;
  clip-path: polygon(0 0, 100% 0, calc(100% - 14px) 50%, 100% 100%, 0 100%, 14px 50%);
}
.tag-front {
  background: repeating-linear-gradient(0deg, rgba(0, 0, 0, .07) 0 1px, transparent 1px 3px), var(--accent-tx);
  color: var(--accent-ink);
}
.tag-front #hero-day { color: var(--accent-ink); opacity: .86; }
.tag-front .dot-sep { background: var(--accent-ink); }
.tag-face::before { inset: 6px 18px; }
.tag-front::before { background: rgba(251, 248, 242, .55); }
.tag-back { background: repeating-linear-gradient(0deg, rgba(var(--ink-rgb), .04) 0 1px, transparent 1px 3px), var(--paper-raise); }

/* ── 相簿：照片四周改成手縫 Z 字針；布標小一點的 Z 字 ── */
#gallery:not([data-wk-gallery]) .photo-item::after { inset: 3px; -webkit-mask: var(--st-zframe); mask: var(--st-zframe); }

/* ── 開場：縮寫放大成主角 ── */
.intro-mono { width: min(74vw, 21rem); margin-left: calc(min(74vw, 21rem) / -2); }

@media (min-width: 960px) {
  .hero-content { max-width: 68rem; grid-template-columns: minmax(0, 11fr) minmax(0, 12fr); }
  .hero-frame { max-width: 29rem; }
  .hero-content > .hero-mono { width: 11rem; margin: 0 0 .4rem; align-self: center; --mono-rot: -4deg; }
  .hero-names { max-width: 32rem; font-size: calc(clamp(3.4rem, 5.4vw, 5rem) * var(--wk-fs-heading, 1) * var(--names-fit, 1)); }
  .intro-mono { width: 28rem; margin-left: -14rem; }
}

/* ── R16b 開場：一條繡好的手帕。四周一圈手縫邊（只縫外側三邊，接縫那一邊留給拆線）、四角十字繡花枝；
      一進場先縫邊、再繡花，接著縮寫自己繡上。兩片布分開時跟著布走。 ── */
.cloth-hem {
  position: absolute;
  top: calc(1.92% + clamp(14px, 4vw, 26px));
  bottom: calc(1.92% + clamp(14px, 4vw, 26px));
  pointer-events: none;
  background: var(--accent);
  opacity: .85;
}
.cloth-l .cloth-hem {
  left: clamp(14px, 4vw, 26px); right: -2px;
  -webkit-mask: var(--st-h) top left / 66px 4px repeat-x, var(--st-h) bottom left / 66px 4px repeat-x, var(--st-v) top left / 4px 66px repeat-y;
  mask: var(--st-h) top left / 66px 4px repeat-x, var(--st-h) bottom left / 66px 4px repeat-x, var(--st-v) top left / 4px 66px repeat-y;
}
.cloth-r .cloth-hem {
  right: clamp(14px, 4vw, 26px); left: -2px;
  -webkit-mask: var(--st-h) top right / 66px 4px repeat-x, var(--st-h) bottom right / 66px 4px repeat-x, var(--st-v) top right / 4px 66px repeat-y;
  mask: var(--st-h) top right / 66px 4px repeat-x, var(--st-h) bottom right / 66px 4px repeat-x, var(--st-v) top right / 4px 66px repeat-y;
}
.sprig {
  position: absolute;
  width: clamp(76px, 21vw, 118px);
  height: auto;
  overflow: visible;
  pointer-events: none;
  --o: calc(1.92% + clamp(24px, 7vw, 44px));
}
.sprig .sp-f, .sprig .sp-s { fill: none; stroke-width: 1.5; stroke-linecap: round; }
.sprig .sp-f { stroke: var(--accent); }
.sprig .sp-s { stroke: var(--accent-tx); opacity: .8; }
.sprig-tl { top: var(--o); left: clamp(24px, 7vw, 44px); }
.sprig-bl { bottom: var(--o); left: clamp(24px, 7vw, 44px); transform: scaleY(-1); }
.sprig-tr { top: var(--o); right: clamp(24px, 7vw, 44px); transform: scaleX(-1); }
.sprig-br { bottom: var(--o); right: clamp(24px, 7vw, 44px); transform: scale(-1, -1); }
html.has-intro .intro:not(.intro-commit) .cloth-hem { animation: st-sew 1s steps(20) both; }
html.has-intro .intro:not(.intro-commit) .cloth-r .cloth-hem { animation-name: st-sew-r; }
@keyframes st-sew-r { from { clip-path: inset(0 0 0 100%); } to { clip-path: inset(0 0 0 0); } }
html.has-intro .intro:not(.intro-commit) .sprig { animation: st-sew .7s steps(11) .45s both; }
html.has-intro .intro:not(.intro-commit) :is(.sprig-tr, .sprig-br) { animation-name: st-sew-r; }

/* 布章：手縫 Z 字邊（不是虛線框）；婚期緞帶：只有上下兩道布邊針腳（織標的布邊） */
.hero-mono::before { -webkit-mask: var(--st-zframe); mask: var(--st-zframe); inset: 5px; }
.tag-face::before { -webkit-mask: var(--st-h) top left / 44px 3px repeat-x, var(--st-h) bottom left / 44px 3px repeat-x; mask: var(--st-h) top left / 44px 3px repeat-x, var(--st-h) bottom left / 44px 3px repeat-x; inset: 6px 16px; }

@media (min-width: 960px) {
  .hero-names { font-size: calc(clamp(3.2rem, 4.8vw, 4.4rem) * var(--wk-fs-heading, 1) * var(--names-fit, 1)); }
  .hero-content > .hero-mono { width: 9.6rem; }
  .hero-frame { max-width: 27rem; }
  .hero-names-en { margin-top: .3rem; }
}


/* ════ R17（R16 嚴評共識） ════ */
/* ① P0：相簿圖說整塊落在照片下方（裝飾絕不蓋照片） */
#gallery:not([data-wk-gallery]) .patch-tag { bottom: auto; top: calc(100% - 2px); }
#gallery:not([data-wk-gallery]) .photo-item:has(.patch-tag:not(:empty)) { margin-bottom: clamp(2.6rem, 9vw, 3.2rem); }

/* ② Hero 名字真的是「繡」的：粗一階、緞面繡線看得見（斜向線＋一層光），字浮在布上（線有厚度） */
.hero-names { font-weight: 600; }   /* Noto Serif TC 只載到 600：再粗就是合成粗體（WebKit 不合成） */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .hero-names > span[id] {
    background:
      linear-gradient(180deg, rgba(255, 255, 255, .2), transparent 42%, rgba(0, 0, 0, .2)),
      repeating-linear-gradient(116deg, var(--ink) 0 1.5px, #6a5d50 1.5px 2.3px, var(--ink) 2.3px 3.3px);
    -webkit-background-clip: text;
    background-clip: text;
    filter: drop-shadow(0 -1px 0 rgba(255, 255, 255, .55)) drop-shadow(0 2px 1.6px rgba(var(--ink-rgb), .32));
  }
}

/* ③ 一條線貫穿整頁：每一區的標題左右交替（render.js 依實際顯示的順序寫 data-side），
      繡線從頁面邊緣一路直針縫進來，到標題底下繞一個線圈、打結——往下捲就是同一條線在布上來回走 */
.section[data-side] :is(.container, .container-wide) > .label-en, .section[data-side] .section-title { text-align: left; text-indent: 0; }
.section[data-side="r"] :is(.container, .container-wide) > .label-en, .section[data-side="r"] .section-title { text-align: right; }
.section[data-side] .stitch-rule {
  display: flex;
  align-items: center;
  width: calc(50vw + min(9rem, 30vw));
  max-width: none;
  margin-left: calc(50% - 50vw);
  margin-right: 0;
}
.section[data-side="r"] .stitch-rule { flex-direction: row-reverse; margin-left: auto; margin-right: calc(50% - 50vw); }
.section[data-side] .stitch-rule::before {
  display: block;
  content: "";
  position: static;
  flex: 1 1 auto;
  height: 4px;
  margin-top: 2px;
  background: var(--accent);
  -webkit-mask: var(--st-h) left center / 66px 4px repeat-x;
  mask: var(--st-h) left center / 66px 4px repeat-x;
}
.section[data-side="r"] .stitch-rule::before { -webkit-mask-position: right center; mask-position: right center; }
.section[data-side] .stitch-rule svg { flex: none; width: min(15rem, 56vw); }
.section[data-side="r"] .stitch-rule svg { transform: scaleX(-1); }
html.fx .section[data-side] .stitch-rule::before { clip-path: inset(0 100% 0 0); }
html.fx .section[data-side="r"] .stitch-rule::before { clip-path: inset(0 0 0 100%); }
html.fx .section[data-side] .stitch-rule.is-in::before { animation: st-sew .6s steps(10) .1s both; }
html.fx .section[data-side="r"] .stitch-rule.is-in::before { animation-name: st-sew-r; }
html.fx .section[data-side] .stitch-rule.is-in svg { animation-delay: .6s; }

/* ④ 線軸放大成一排真的線（R16：四個小物件孤零零） */
.dc-swatch { width: clamp(3.2rem, 15vw, 4.2rem); height: clamp(4.4rem, 20vw, 5.8rem); }
.dc-swatches { gap: clamp(1.4rem, 6vw, 2.4rem); }

/* ⑤ 終章：繡框放到最大、底稿點看得清楚（R16：情緒高點要是整頁最大的東西） */
.xs-plan circle { opacity: .9; }

@media (min-width: 960px) {
  .dc-swatch { width: 4.8rem; height: 6.6rem; }
}

/* ⑥ RSVP：邊打名字、欄位下方一枚布標邊把名字繡出來（中段的互動哇點） */
.rsvp-nametag {
  display: none;
  width: fit-content;
  max-width: 100%;
  margin: .9rem 0 0 auto;
  padding: .45rem 1.1rem .5rem;
  rotate: -2deg;
  background: var(--linen), var(--paper-raise);
  filter: drop-shadow(0 5px 6px rgba(var(--ink-rgb), .18));
  position: relative;
  --z: 3.5px;
  -webkit-mask: conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y, conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y, linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
  mask: conic-gradient(from 135deg at top, #0000, #000 1deg 89deg, #0000 90deg) top / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / calc(2 * var(--z)) var(--z) repeat-x, conic-gradient(from 45deg at left, #0000, #000 1deg 89deg, #0000 90deg) left / var(--z) calc(2 * var(--z)) repeat-y, conic-gradient(from -135deg at right, #0000, #000 1deg 89deg, #0000 90deg) right / var(--z) calc(2 * var(--z)) repeat-y, linear-gradient(#000 0 0) center / calc(100% - 2 * var(--z) + 1px) calc(100% - 2 * var(--z) + 1px) no-repeat;
}
.rsvp-nametag.is-on { display: flex; align-items: baseline; gap: .6rem; }
.rsvp-nametag::before { content: ""; position: absolute; inset: 4px; background: var(--accent); -webkit-mask: var(--st-zframe); mask: var(--st-zframe); pointer-events: none; }
.rsvp-nametag .nt-pre { font-family: var(--wk-f-latin, var(--font-serif-latin)); font-style: italic; font-size: .9rem; color: var(--ink-soft); letter-spacing: .08em; }
.rsvp-nametag .nt-name {
  font-family: var(--wk-f-heading, var(--font-serif-tc));
  font-size: 1.45rem;
  font-weight: 600;
  letter-spacing: .1em;
  color: var(--accent-tx);
  overflow-wrap: anywhere;
}
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .rsvp-nametag .nt-name { background: repeating-linear-gradient(116deg, var(--accent-tx) 0 1.3px, var(--accent) 1.3px 2.2px); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
}
.rsvp-nametag.is-sew .nt-name { animation: st-sew .5s steps(8) both; }
.blessing-seal { width: min(100%, 21rem); }
@media (min-width: 960px) { .blessing-seal { width: min(100%, 36rem); } }

/* ════ R18（R17 嚴評：手機 7.97／桌機 7.9） ════ */
/* ① 名字改成茜紅緞面繡（跟開場那枚 G&B 同一條線；R17 三組都說灰斜紋像髒、斷了線）。
      color 仍是 --ink＝不支援 text 裁切時的退路；實際看到的是 --accent-tx 系（對紙 6.4） */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .hero-names > span[id] {
    background:
      linear-gradient(180deg, rgba(255, 255, 255, .16), transparent 45%, rgba(0, 0, 0, .16)),
      repeating-linear-gradient(116deg, var(--accent-tx) 0 1.6px, var(--accent) 1.6px 2.5px, var(--accent-tx) 2.5px 3.4px);
    -webkit-background-clip: text;
    background-clip: text;
  }
}
.hero-names .amp path { stroke: var(--ink-soft); }
/* ② 區塊之間的空白收一階（R17：中段 110–270px 的洞把「一條線一路縫下來」打斷） */
:root { --section-y: clamp(2.6rem, 8vw, 5rem); }
/* ③ 倒數數字用襯線中文字型的齊線數字（Cormorant 的數字高低不齊） */
.cd-cell strong { font-family: var(--wk-f-heading, var(--font-serif-tc)); font-weight: 600; letter-spacing: .02em; }
/* ④ 地圖濾鏡淡一點，路名讀得到（R17：洗到約 2:1） */
.map-frame iframe { filter: grayscale(.7) sepia(.18) contrast(1.02); }
/* ⑤ 頂針放大（R17：太小太扁） */
.ps-thimble { width: 5.2rem; }
@media (min-width: 960px) {
  /* 縮寫落定有份量（R17-C：600px 縮成 230px 的小布標） */
  .hero-content > .hero-mono { width: 12.5rem; }
}

/* ⑥ 中段改成「縫在布上的東西」（R17 三組：時間軸、行程是標準版型加針腳）：
      時間軸與行程的每一個點＝一顆縫上去的四孔鈕扣（遮罩挖孔、看得到底下的布；顏色跟配色走），
      行程左邊一條直針把鈕扣串起來——跟故事那條線是同一個語彙 */
:root {
  --sbtn-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill-rule='evenodd' d='M10 .6a9.4 9.4 0 1 1 0 18.8A9.4 9.4 0 0 1 10 .6zM7.6 6a1.6 1.6 0 1 0 0 3.2A1.6 1.6 0 0 0 7.6 6zm4.8 0a1.6 1.6 0 1 0 0 3.2 1.6 1.6 0 0 0 0-3.2zM7.6 10.8a1.6 1.6 0 1 0 0 3.2 1.6 1.6 0 0 0 0-3.2zm4.8 0a1.6 1.6 0 1 0 0 3.2 1.6 1.6 0 0 0 0-3.2z'/%3E%3C/svg%3E");
  --sbtn-bg: radial-gradient(circle, transparent 0 60%, rgba(0, 0, 0, .2) 63% 69%, transparent 72%), radial-gradient(circle at 32% 28%, rgba(255, 255, 255, .45), transparent 48%), var(--accent);
}
.timeline-item::after {
  left: -.05rem;
  top: .3rem;
  width: 1.05rem; height: 1.05rem;
  border-radius: 0;
  background: var(--sbtn-bg);
  box-shadow: none;
  -webkit-mask: var(--sbtn-mask) center / contain no-repeat;
  mask: var(--sbtn-mask) center / contain no-repeat;
  rotate: calc(var(--tl-r, 0) * 1deg);
}
.timeline-item:nth-child(2n)::after { --tl-r: 24; }
.timeline-item:nth-child(3n)::after { --tl-r: -18; }
.event-list { position: relative; padding-left: 2.1rem; }
.event-list::before { content: ""; position: absolute; left: .42rem; top: 1.6rem; bottom: 1.6rem; width: 4px; background: var(--accent); opacity: .8; -webkit-mask: var(--st-v) center top / 4px 66px repeat-y; mask: var(--st-v) center top / 4px 66px repeat-y; }
.event-row::after {
  content: "";
  position: absolute;
  left: -2.15rem;
  top: calc(clamp(.95rem, 3.4vw, 1.25rem) + .22rem);
  width: 1.05rem; height: 1.05rem;
  background: var(--sbtn-bg);
  -webkit-mask: var(--sbtn-mask) center / contain no-repeat;
  mask: var(--sbtn-mask) center / contain no-repeat;
}
.event-row:nth-child(2n)::after { rotate: 20deg; }
@media (min-width: 960px) {
  .timeline-item::after { left: calc(7rem + .8rem - .52rem); }
  .details > .container > .event-list { padding-left: 2.6rem; }
  .details > .container > .event-list::before { left: .42rem; top: 1.6rem; bottom: 1.6rem; }
  .hero-content > .hero-mono { width: 11rem; }
}

/* ════ R19（R18 嚴評：手機 8.1／iPhone 7.7／桌機 7.3） ════ */
/* 小破綻 */
.hero-names .amp path { stroke: var(--accent); }
.rsvp-nametag .nt-pre { font-family: var(--wk-f-heading, var(--font-serif-tc)); font-style: normal; letter-spacing: .12em; }
html.wk-lang-en .rsvp-nametag .nt-pre { font-family: var(--wk-f-latin, var(--font-serif-latin)); font-style: italic; }
.rsvp .field :is(input, textarea, select):focus-visible { outline: 2px solid var(--accent-tx); outline-offset: 2px; box-shadow: none; }
/* 標題下的線圈不要每一條都一樣：依顯示順序輪三種（render.js 寫 data-v） */
.section[data-v="1"] .stitch-rule svg { transform: scaleY(-1); }
.section[data-v="1"][data-side="r"] .stitch-rule svg { transform: scale(-1, -1); }
.section[data-v="2"] .stitch-rule svg { transform: scale(1.12, .8); }
.section[data-v="2"][data-side="r"] .stitch-rule svg { transform: scale(-1.12, .8); }

/* 桌機：版面用滿、尺度放大、收掉垂直的洞（R18-C：只用了 35–45% 寬、多處 250px 空洞） */
@media (min-width: 960px) {
  :root { --section-y: clamp(3rem, 6vh, 4.2rem); }
  main .section > .container { max-width: 58rem; }
  .section-title { font-size: calc(clamp(2.6rem, 3.6vw, 3.4rem) * var(--wk-fs-heading, 1)); }
  .label-en { font-size: calc(1.2rem * var(--wk-fs-latin, 1)); }
  .timeline { max-width: 54rem; }
  .tl-text { font-size: 1.15rem; line-height: 1.95; }
  .custom-text { max-width: 40rem; font-size: 1.12rem; }
  .custom-block:not(.custom-block-card):not(.custom-block-quote) .custom-text { padding: 1.8rem 2.4rem; }
  .secret .scratch-wrap, .secret .scratch-card { max-width: 40rem; margin-inline: auto; }
  .secret .scratch-card { min-height: 15rem; }
  .rsvp-form { max-width: 44rem; margin-inline: auto; }
  .rsvp-intro { font-size: 1.1rem; }
  .details > .container { max-width: 62rem; grid-template-columns: 22rem minmax(0, 1fr); align-items: start; }
  .wk-cal { max-width: 22rem; }
  .event-row dd strong { font-size: calc(1.4rem * var(--wk-fs-heading, 1)); }
  .event-row dt { font-size: calc(1.45rem * var(--wk-fs-latin, 1)); }
  .dc-swatch { width: 6rem; height: 8.4rem; }
  .dc-swatches { gap: 3.4rem; }
  .dc-note { font-size: 1.12rem; }
  #venue:not(.venue--dual) > .container-wide { max-width: 64rem; }
  .map-frame { height: 30rem; max-width: 64rem; }
  .transport { max-width: 44rem; margin-inline: auto; font-size: 1.05rem; }
  .blessing-seal { width: min(100%, 44rem); }
  .ps-thimble { width: 6.4rem; }
}

/* R19b 桌機：行程、加入日曆、主婚人都收進月曆右邊那一欄（R19-C：月曆旁行程下方約 400px 空洞） */
@media (min-width: 960px) {
  .details > .container:has(> .wk-cal:not([hidden])) { grid-template-rows: repeat(7, auto) 1fr; }
  .details > .container:has(> .wk-cal:not([hidden])) > .wk-cal { grid-column: 1; grid-row: 6 / span 3; }
  .details > .container:has(> .wk-cal:not([hidden])) > .event-list { grid-row: 6; }
  .details > .container:has(> .wk-cal:not([hidden])) > .calendar-actions { grid-column: 2; grid-row: 7; justify-content: flex-start; margin-top: 2.2rem; padding-left: 2.6rem; }
  .details > .container:has(> .wk-cal:not([hidden])) > .parents { grid-column: 2; grid-row: 8; text-align: left; margin-top: 1.8rem; padding-left: 2.6rem; align-self: start; }
}

/* 修（Jacob 11/1 實測 /marry/afterhours）：圖文並排的小提醒，照片被文字那塊布蓋住——
   布片有遮罩＝自成堆疊層，畫在浮動的照片上面。文字那塊改成自己的區塊格式（flow-root），
   乖乖排在照片右邊、不再墊到照片底下。 */
.custom-block-side .custom-text { display: flow-root; }
.custom-block-side .custom-img { position: relative; z-index: 1; }

/* 祝福留言牆：頁尾本身已有 --gutter 內距，共用樣式的 min(100% - 2.5rem) 會再扣一次、390 手機只剩 270px */
.footer .wk-bless { width: min(100%, 34rem); }
