/* ============ Fonts (self-host, OFL — tải từ Google Fonts) ============ */
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/lora-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/lora-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/lora-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Ms Madi';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/msmadi-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: 'Ms Madi';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/msmadi-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Ms Madi';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/msmadi-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Pinyon Script';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/pinyonscript-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: 'Pinyon Script';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/pinyonscript-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Pinyon Script';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/pinyonscript-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ============================================================
   THIỆP CƯỚI — Long Phụng (đỏ #680E0E + vàng #E9CE9E)
   Cấu trúc & tỉ lệ dựng theo thiệp cưới cổ điển trang trọng.
   Tokens trước, component chỉ tiêu token.
   ============================================================ */

:root {
  /* ---- Màu ---- */
  --bg:        #680E0E;   /* đỏ thân thiệp */
  --bg-deep:   #100101;   /* đáy gradient cover */
  --cover-grad: linear-gradient(to bottom right, #2A0404, #1A0202, #100101);
  --brown:     #553F18;
  --seal-text: #360202;
  --gold-a80:  rgba(233, 206, 158, .8);
  --guest-box: rgba(233, 206, 158, .15);
  --bronze:    #D9BC86;   /* vàng dịu cho hoạ tiết nhỏ (nốt kim cương timeline…) */
  --surface:   #7A1B1B;   /* panel sáng hơn */
  --ink:       #E9CE9E;   /* chữ vàng chính — 8.3:1 trên bg */
  --ink-soft:  #D9BC86;   /* chữ vàng phụ   — 6.8:1 */
  --gold:      #E9CE9E;
  --on-gold:   #553F18;   /* chữ trên nút vàng */
  --line:      color-mix(in srgb, #E9CE9E 30%, transparent);
  --line-soft: color-mix(in srgb, #E9CE9E 16%, transparent);
  --shadow:    0 14px 36px -14px rgba(0, 0, 0, .6);

  /* ---- Chữ (stack đúng reference) ---- */
  --f-script:  "Pinyon Script", "Great Vibes", cursive;
  --f-amp:     "Ms Madi", cursive;
  --f-serif:   Baskerville, "Times New Roman", serif;
  --f-lora:    "Lora", "Times New Roman", serif;
  --f-sans:    -apple-system, "Segoe UI", Roboto, sans-serif;

  --fs-xs:     .75rem;    /* 12px — ghi chú, thứ bậc, giờ lưu bút */
  --fs-sm:     .8125rem;  /* 13px — địa chỉ, body phụ (đo từ mẫu) */
  --fs-base:   .875rem;   /* 14px — body (đo từ mẫu: 14px/1.625) */
  --fs-md:     1.25rem;   /* 20px — tiêu đề section, giờ */
  --fs-lg:     1.875rem;  /* 30px — số ngày cỡ lớn */
  --fs-script: clamp(2.5rem, 11vw, 4rem);     /* tên cô dâu chú rể: 40px mobile → 64px desktop */

  /* ---- Layout Contract (đo từ mẫu tham chiếu) ---- */
  --container:      480px;                  /* mobile: w-full, trần 480 */
  --container-md:   900px;                  /* ≥768px: 900 canh giữa, có viền mảnh */
  --content:        600px;                  /* bề rộng ruột nội dung bên trong panel */
  --gutter:         24px;
  --space-within:   12px;                   /* trong một nhóm */
  --space-between:  28px;                   /* giữa các nhóm  */
  --space-section:  64px;                   /* giữa các section */

  --r-card: 10px;
  --r-pill: 999px;
  --ease:   cubic-bezier(.22, .8, .3, 1);
}

/* ============ Nền tảng ============ */
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
/* Trong lúc trang tự cuộn PHẢI tắt smooth: asStep() gọi window.scrollTo mỗi frame, mà
   scroll-behavior:smooth biến mỗi lần gọi thành một animation cuộn mới của trình duyệt
   thay vì nhảy tới đúng vị trí — 60 lần/giây khởi động lại nhau nên cuộn bị kéo lê, giật. */
html.autoscrolling { scroll-behavior: auto; }
body {
  margin: 0;
  background: #fff;                 /* desktop: main 900px căn giữa trên nền trắng (thiết kế gốc) */
  color: var(--ink);
  font-family: var(--f-serif);
  font-size: var(--fs-base);
  font-weight: 300;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
/* Đang mở popup (album, lightbox, RSVP, hộp quà): khoá cuộn nền. Chỉ overflow:hidden thì
   iOS Safari vẫn cho nền trượt sau dialog — dùng position:fixed như gate-locked, JS đặt
   body.style.top = -scrollY để trang không nhảy về đầu, đóng thì trả lại đúng chỗ. */
html.dialog-open, html.dialog-open body { overflow: hidden; overscroll-behavior: none; }
html.dialog-open body { position: fixed; left: 0; right: 0; width: 100%; }
html.gate-locked, html.gate-locked body {
  overflow: hidden; overscroll-behavior: none;
  position: fixed; inset: 0; width: 100%; height: 100%;   /* iOS Safari: chỉ overflow:hidden là nền vẫn cuộn, lòi ảnh dưới đáy */
}

img { max-width: 100%; height: auto; display: block; }
h1, h2, h3 { margin: 0; font-weight: 400; line-height: 1.2; }
p { margin: 0; }
a { color: inherit; }
button { font: inherit; color: inherit; cursor: pointer; }
:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: 4px; }

.skip-link {
  position: absolute; left: var(--space-within); top: var(--space-within); z-index: 100;
  padding: var(--space-within) var(--space-between);
  background: var(--gold); color: var(--on-gold);
  border-radius: var(--r-pill); transform: translateY(-200%);
}
.skip-link:focus { transform: none; }

/* ============ Thân thiệp: một dải đỏ có watermark chìm ============ */
main {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  background: var(--bg);
  position: relative;
  overflow: hidden;
}
@media (min-width: 768px) {
  main {
    max-width: var(--container-md);
    border: 1px solid #E9CE9E22;
    border-radius: var(--r-card);
  }
}
/* 3 lớp texture parallax — transform set bằng JS theo scrollY */
.plx {
  position: absolute; z-index: 0;
  width: clamp(800px, 150vw, 1600px);
  height: clamp(1200px, 300vw, 2400px);
  background: url(../img/bg-main.webp) center / contain no-repeat;
  opacity: .4;
  will-change: transform;
  pointer-events: none;
}
.plx1 { left: 50%; top: 500px; background-position: center top; }
.plx2 { left: 65%; bottom: 1500px; background-position: center bottom; }
.plx3 { left: 35%; bottom: -450px; background-position: center bottom; }
@media (min-width: 768px) { /* PHẢI đứng sau base rule để không bị ghi đè */
  .plx1 { top: 700px; }
  .plx2 { bottom: -200px; }
  .plx3 { display: none; }
}

.sec {
  position: relative; z-index: 1;
  padding: var(--space-section) var(--gutter);
  text-align: center;
}
.sec > *, .footer > * { max-width: var(--content); margin-inline: auto; }
.sec-panel { background: color-mix(in srgb, #000 12%, var(--bg)); }

/* tiêu đề section: serif caps giãn chữ + gạch nhũ */
/* mẫu có 2 bậc tiêu đề: thường 16→20px, hai mục điểm nhấn 20→26px */
.sec-h {
  font-family: var(--f-serif);
  font-size: 20px; font-weight: 400; line-height: 1.5;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ink);
  margin-block-end: 16px;
}
@media (min-width: 768px) { #wishes .sec-h, #gift .sec-h { font-size: 26px; } }
.note, .center { text-align: center; }
/* trạng thái rỗng của sổ lưu bút: đóng khung nhẹ cho đỡ trống trải */
#wishes-empty, #wishes-note {
  max-width: 440px;
  margin: var(--space-between) auto 0;
  padding: 18px var(--gutter);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-card);
}
.note { font-size: 14px; line-height: 1.6; color: var(--ink-soft); }

/* chữ script vàng: tên cô dâu chú rể */
.script {
  font-family: var(--f-script);
  font-weight: 400;
  color: var(--gold);
  line-height: 1.25;
}
.script .amp { font-family: var(--f-serif); font-size: .38em; display: block; line-height: 1.5; margin-block: -.1em; } /* optical: & sát hai tên */

/* ============ Nút ============ */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px;
  padding: var(--space-within) var(--space-between);
  border: 1px solid var(--gold); border-radius: var(--r-pill);
  background: var(--gold); color: var(--on-gold);
  font-family: var(--f-serif); font-size: 14px; font-weight: 600; line-height: 20px;
  letter-spacing: .06em; text-transform: uppercase; text-decoration: none;
  transition: background .2s var(--ease), transform .2s var(--ease);
}
.btn:hover { background: color-mix(in srgb, var(--gold), #fff 14%); }
.btn:active { transform: translateY(1px); }
.btn[disabled] { opacity: .55; cursor: default; }
.btn-block { width: 100%; }
.party-rsvp, #rsvp-submit { font-size: 16px; line-height: 24px; }   /* mẫu: nút xác nhận 16px/600 */
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn-ghost:hover { background: color-mix(in srgb, var(--gold) 12%, transparent); }
.cta-row { display: grid; justify-content: center; margin-block-start: var(--space-between); }
.link-line {
  display: inline-block;
  font-size: 14px; font-weight: 300; line-height: 20px;
  color: var(--ink-soft);
  border-block-end: 1px solid var(--line);
  padding-block-end: 4px;  /* mẫu: underline-offset-4 */
  text-decoration: none;
  margin-block-start: var(--space-between);
}
.link-line:hover { color: var(--ink); border-color: var(--gold); }

/* ============ Phong bì ============ */
.gate {
  position: fixed; inset: 0; z-index: 60;
  height: 100vh; height: 100dvh;          /* dvh: co giãn theo thanh công cụ Safari, không hụt đáy */
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  overflow-y: auto; overscroll-behavior: none;   /* màn thấp thì cuộn cả lớp phủ, không lan ra nền */
  -webkit-overflow-scrolling: touch;
  padding: var(--gutter);
  background: var(--cover-grad);
  transition: opacity .5s var(--ease), visibility .5s;
}
html.no-js .gate { display: none; }
.gate.open { opacity: 0; visibility: hidden; }
/* Lúc tấm phóng to, nền lớp phủ phải về đúng màu trang để gỡ lớp phủ là liền cảnh. KHÔNG
   transition thuộc tính background từ gradient sang màu đặc: background-image không animate
   được nên bị bỏ ngay, còn background-color chạy từ trong suốt lên đỏ trong .45s — khoảng đó
   lớp phủ trong suốt, thấy mục đếm ngược xuyên qua (đo trên iPhone). Dùng lớp ::after đỏ
   đặc và animate opacity — thuộc tính animate được. Stage nằm trên nó nhờ z-index. */
.gate::after { content: ""; position: absolute; inset: 0; z-index: 0; background: var(--bg); opacity: 0; pointer-events: none; transition: opacity .45s ease-out; }
.gate.flying::after { opacity: 1; }
.gate-stage { position: relative; z-index: 1; }
/* viền bìa tắt ở 200ms cuối cú phóng, không thì lúc gỡ lớp phủ thấy một vạch nhũ mất phựt */
.gate.flying .gate-card { border-color: transparent; transition: border-color .2s ease-out .5s; }
/* .gate-stage giữ khổ tờ thiệp; phong bì tính theo % của khổ này nên tự co giãn mọi máy */
.gate-stage {
  position: relative;
  width: 310px; max-width: 100%;
  margin: auto;
  --env-h:    max(62%, 290px);                      /* chiều cao phong bì: theo tờ thiệp nhưng có sàn — bìa chỉ còn tên đôi thì thấp, để 62% thuần là phong bì co còn 179px, triện đè lên nhãn */
  --slip-s:   .57;                                  /* thiệp thu nhỏ bằng này khi còn trong phong bì */
  --env-top:  calc((100% - var(--env-h)) / 2);      /* phong bì căn giữa khổ thiệp */
  --env-flap: .42;                                  /* nắp cao 42% phong bì */
  --seal-y:   calc(var(--env-top) + var(--env-h) * var(--env-flap));   /* triện sáp ở mũi nắp */
  --fold-s:   .62;                                  /* tấm 3 nấc thu còn bằng này cho vừa chiều cao khung */
}
@media (max-height: 730px) { .gate-stage { --fold-s: .52; } }
@media (min-width: 640px)  { .gate-stage { width: 340px; } }
/* Từ 768px bìa thiệp thành hình chữ nhật NGANG (rộng hơn cao), nên phong bì phải cao
   hơn theo % — giữ 62% thì phong bì dẹt 2,7:1, không còn ra dáng phong bì. */
@media (min-width: 768px)  { .gate-stage { width: 520px; --env-h: max(82%, 300px); --slip-s: .74; --fold-s: .50; } }
@media (min-width: 768px) and (max-height: 780px) { .gate-stage { --fold-s: .44; } }
@media (min-width: 1024px) { .gate-stage { width: 600px; } }

.gate-card {
  position: relative;
  width: 100%;
  /* Bìa là hero thu theo tỉ lệ cỡ chữ 36/50 = 0,72: hero min-height 472, padding 64,
     long phụng top 48 / gap 32 / ảnh 354 → bìa 340 / 46 / 35 / 23 / 255. Cùng bố cục grid
     căn giữa như .hero để cú phóng cuối đưa cả chữ lẫn hoạ tiết về đúng chỗ. */
  display: grid; place-items: center;
  min-height: 340px;
  padding: 46px 24px;
  text-align: center;
  background: var(--bg);
  border: 1px solid color-mix(in srgb, var(--gold) 55%, transparent);
  border-radius: var(--r-card);
  box-shadow: var(--shadow);
  overflow: hidden;        /* hoạ tiết rồng phượng phải nằm gọn trong thiệp — Safari iOS từng lòi ảnh dưới đáy */
}
@media (min-width: 768px) { .gate-card { min-height: 446px; padding: 44px 24px; } }   /* 48/70 = 0,686 của hero 650/64 */
.gate-card .longphung { top: 35px; gap: 23px; }
.gate-card .longphung img { height: 255px; }
@media (min-width: 768px) {
  .gate-card .longphung { top: 44px; gap: 22px; }
  .gate-card .longphung img { height: 392px; }
}
.gate-seal {
  position: absolute; left: 50%; top: 50px;
  width: 72px; height: 72px;
  border-radius: var(--r-pill);
  display: grid; place-items: center;
  line-height: 1;
  --seal-shadow: rgba(233, 206, 158, .28);   /* quầng sáng nhẹ sau hoạ tiết */
  z-index: 2;
}
.gate-seal img { display: block; width: 100%; height: 100%; object-fit: contain; }
@keyframes seal-pulse {
  0%, 100% { transform: translate(-50%, -50%) scale(1);    box-shadow: 0 4px 20px var(--seal-shadow); }
  50%      { transform: translate(-50%, -50%) scale(1.06); box-shadow: 0 6px 35px var(--seal-shadow); }
}
/* triện vỡ khi bấm mở thiệp (keyframe theo reference) — áp cho triện SÁP niêm phong bì */
.gate.opening .env-seal { animation: seal-break .5s cubic-bezier(.4, 0, .2, 1) forwards; }
@keyframes seal-break {
  0%   { transform: translate(-50%, -50%) scale(1)    rotate(0deg);  opacity: 1;  filter: brightness(1); }
  30%  { transform: translate(-50%, -50%) scale(1.15) rotate(5deg);  opacity: .9; filter: brightness(1.3); }
  60%  { transform: translate(-50%, -50%) scale(1.05) rotate(-3deg); opacity: .5; filter: brightness(1.5); }
  100% { transform: translate(-50%, -50%) scale(0)    rotate(15deg); opacity: 0;  filter: brightness(2); }
}
/* vòng sáng lan từ triện */
.seal-ring {
  position: absolute; left: 50%; top: var(--seal-y); z-index: 9;
  width: 56px; height: 56px;
  border: 2px solid var(--gold); border-radius: var(--r-pill);
  opacity: 0; pointer-events: none;
  transform: translate(-50%, -50%) scale(.8);
}
.gate.opening .seal-ring { animation: seal-ring .6s ease-out forwards; }
@keyframes seal-ring {
  0%   { opacity: .8; transform: translate(-50%, -50%) scale(.8); }
  100% { opacity: 0;  transform: translate(-50%, -50%) scale(2.5); }
}


/* Mở xong ba nấc: nấc 1 (bìa, chỉ có tên đôi) PHÓNG TO cho tới khi trùng khít trang đầu —
   chữ "Xuân Thế & Giáp Hân" trên bìa nằm đúng vị trí và cỡ của chữ ở hero, rồi gỡ lớp phủ.
   Không fade, không lao qua camera. Scale và độ dịch KHÔNG hardcode được (phụ thuộc khổ máy,
   cỡ chữ, vị trí hero) nên main.js đo hai khung chữ lúc chạy và animate .gate-stage bằng
   Web Animations API (zoomStageIntoHero). CSS chỉ lo phần phụ: nấc 2-3 và viền bìa mờ đi,
   hoạ tiết bìa nhường chỗ cho long phụng của hero. */
.gate-stage { will-change: transform; }
/* CẢ TẤM phóng lên — hoạ tiết rồng phượng, viền bìa, nấc 2-3 đều đi cùng (tắt sớm là
   nhìn như chỉ có chữ chạy). Nấc 2-3 chỉ mờ trong 200ms cuối của cú phóng 700ms, vì chỗ
   chúng đứng sau khi gỡ lớp phủ là mục đếm ngược của trang — không mờ thì chữ đổi phựt. */
.gate.opening.flying .pan-2,
.gate.opening.flying .pan-3 { animation: pan-fade .2s ease-out .5s forwards; }
@keyframes pan-fade { to { opacity: 0; } }

/* ============ Phong bì bọc ngoài tờ thiệp ============
   Hình học: phong bì thấp hơn và rộng hơn tờ thiệp, căn giữa khổ thiệp; tờ thiệp
   nằm trong ở scale .57 rồi vừa trượt lên vừa lớn dần về khổ thật.
   LƯU Ý: .gate-stage KHÔNG dùng preserve-3d — nếu dùng thì translateZ/độ sâu của tờ
   thiệp sẽ đưa nó ra trước mặt phong bì và mất cảm giác "nằm trong". Nắp cần phối
   cảnh để lật nên được cấp perspective cục bộ. */
.env-inside, .env-front, .env-flapwrap {
  position: absolute; left: -3%; right: -3%;      /* phong bì rộng hơn tờ thiệp */
  top: var(--env-top);
}
.env-inside, .env-front { height: var(--env-h); border-radius: 3px 3px var(--r-card) var(--r-card); }

/* lòng phong bì: tối, nằm sau tờ thiệp — mở nắp ra là thấy chiều sâu */
.env-inside {
  z-index: 2;
  background: linear-gradient(180deg, #1E0303, #3A0606 40%, #4A0808);
  border: 1px solid color-mix(in srgb, var(--gold) 22%, transparent);
  box-shadow: inset 0 14px 22px rgba(0, 0, 0, .6);
}
/* tờ thiệp nằm trong phong bì */
.env-slip { position: relative; z-index: 4; transform: translateY(2%) scale(var(--slip-s)); }
/* bóng lòng phong bì đổ lên tờ thiệp, mờ dần khi thiệp ra hẳn */
.env-slipshadow {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
  height: 48%; pointer-events: none;
  border-radius: 0 0 var(--r-card) var(--r-card);
  background: linear-gradient(0deg, rgba(0, 0, 0, .68), rgba(0, 0, 0, .28) 55%, transparent);
}
/* mặt trước phong bì */
.env-front {
  z-index: 6; overflow: hidden;
  background: linear-gradient(165deg, #7C1C1C, #611010 55%, #4E0A0A);
  border: 1px solid color-mix(in srgb, var(--gold) 52%, transparent);
  box-shadow: 0 -10px 24px rgba(0, 0, 0, .35), var(--shadow);
}
.env-front::after {                       /* viền nhũ kép như bìa thiệp */
  content: ""; position: absolute; inset: 6px;
  border: 1px solid color-mix(in srgb, var(--gold) 20%, transparent);
  border-radius: 6px; pointer-events: none;
}
.env-decor {
  position: absolute; left: 50%; top: 46%; translate: -50% -50%; z-index: 0;
  width: 62%; aspect-ratio: 1171 / 1444;
  background: url(/assets/img/bg-main.webp) center / contain no-repeat;
  opacity: .16;
}
.env-art { position: absolute; z-index: 0; height: auto; opacity: .1; pointer-events: none; }
.env-art.l { width: 48%; left: -17%; top: -6%; }
.env-art.r { width: 48%; right: -17%; bottom: -9%; }
/* Mặt trước phong bì KHÔNG lặp chữ của bìa thiệp: bìa đã có tên đôi, ngày, "Thân Mời"
   và tên khách — để lại chữ nào trong số đó cũng bị thấy hai lần lúc thiệp trượt lên. */
.env-txt {
  /* căn giữa khoảng trống dưới mũi nắp, không dán sát đáy phong bì */
  position: absolute; left: 0; right: 0; z-index: 1;
  top: calc(var(--env-flap) * 100% + (100% - var(--env-flap) * 100%) / 2);
  translate: 0 -50%;
  padding: 0 18px; text-align: center;
}
.env-label {
  margin: 0;
  font-family: var(--f-lora); font-size: 11px; letter-spacing: .3em; text-transform: uppercase;
  color: var(--gold-a80);
}
/* tên khách in trên phong bì như phong bì thật ghi người nhận — chỉ hiện khi vào bằng
   link có mã mời (?g=…). Phải mờ đi ngay khi bắt đầu mở, không thì lúc tờ thiệp trượt
   lên sẽ thấy tên khách hai lần (một trên phong bì, một trên bìa thiệp). */
.gate.opening .env-txt { animation: env-txt-out .4s ease-out .3s forwards; }
@keyframes env-txt-out { to { opacity: 0; } }
.env-label::after {
  content: ""; display: block; width: 44px; height: 1px; margin: 8px auto 0;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
}
@media (min-width: 768px) { .env-label { font-size: 13px; } }

/* ánh nhũ lọt ra từ miệng phong bì lúc rút thiệp — giữa lớp thiệp (4) và mặt trước (6) */
.env-glow {
  position: absolute; left: 8%; right: 8%; top: var(--env-top); z-index: 5;
  height: 76px; opacity: 0; pointer-events: none; filter: blur(7px);
  background: radial-gradient(64% 100% at 50% 0%, rgba(233, 206, 158, .5), transparent 72%);
}

/* nắp phong bì: bản lề cạnh trên. drop-shadow tôn trọng clip-path nên nắp nổi khối */
.env-flapwrap { height: calc(var(--env-h) * var(--env-flap)); z-index: 8; perspective: 700px; }
.env-flap {
  position: absolute; inset: 0;
  transform-origin: top center;
  filter: drop-shadow(0 3px 4px rgba(0, 0, 0, .5));
}
.env-flap-out, .env-flap-in, .env-flap-shade {
  position: absolute; inset: 0;
  clip-path: polygon(0 0, 100% 0, 50% 100%);
}
.env-flap-out {                        /* mặt ngoài nắp: cùng tông giấy mặt sau, đậm hơn mặt trước */
  background: linear-gradient(180deg, #8A2222, #661111 70%, #571010);
  border-top: 1px solid color-mix(in srgb, var(--gold) 52%, transparent);
}
.env-flap-out i {                      /* dải tối theo hai cạnh chéo cho ra nếp gấp */
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, .05), rgba(0, 0, 0, .3));
}
.env-flap-in {                         /* mặt trong nắp, thấy khi lật ngửa */
  background: linear-gradient(0deg, #2A0505, #451414);
  border-top: 1px solid color-mix(in srgb, var(--gold) 26%, transparent);
  opacity: 0;
}
.env-flap-shade { z-index: 2; opacity: 0; background: linear-gradient(180deg, rgba(0, 0, 0, 0), rgba(0, 0, 0, .55)); }


/* ============ Tờ thiệp gấp 3 nấc (mở lần lượt sau khi rút khỏi phong bì) ============
   Nếp gấp NẰM NGANG, thiệp mở dài xuống theo chiều dọc — như gấp một tờ thư ba nấc.
   Gấp kiểu cuốn: nấc 2 quay -180 độ quanh mép dưới nấc 1 nên úp đúng lên nấc 1; nấc 3 là
   CON của nấc 2 nên cũng quay -180 độ trong hệ đã lộn của nấc 2, lại úp về đúng khổ một
   nấc. Nhờ vậy lúc gấp cả ba chồng nhau, mở ra thì dàn dọc thành 3 nấc.

   Nấc 2 và 3 KHÔNG dựa vào backface-visibility: thuộc tính đó không kế thừa xuống hoạ
   tiết bên trong, và nấc 3 là con của nấc 2 nên khi còn gấp nó luôn vẽ đè lên cha. Cách
   chắc chắn là để chúng trong suốt cho tới đúng lúc đi qua mốc 90 độ rồi mới bật lên. */
.fold3 {
  position: relative;
  transform-origin: center top;
  transform-style: preserve-3d;
  perspective: 1200px;
}
.fold3 > .gate-card { z-index: 3; }
.pan {
  position: absolute; left: 0; top: 100%;
  width: 100%; height: 100%;
  transform-origin: center top;
  transform-style: preserve-3d;
  transform: rotateX(-180deg);
  opacity: 0;                     /* còn gấp thì ẩn hẳn, không che nấc trước */
  border-radius: var(--r-card);
  background: linear-gradient(158deg, #7A1B1B, #550B0B 62%, #420707);
  border: 1px solid color-mix(in srgb, var(--gold) 34%, transparent);
}
.pan-2 { z-index: 2; }
.pan-3 { z-index: 1; }
.pan::before {                    /* khung nhũ mảnh của mặt trong tờ thiệp */
  content: ""; position: absolute; inset: 12px;
  border: 1px solid color-mix(in srgb, var(--gold) 20%, transparent);
  border-radius: 6px; pointer-events: none;
}
/* overflow phải nằm ở LỚP TRONG, không phải ở .pan: nấc 3 là con của nấc 2 và nằm
   ngoài biên cha nên overflow trên .pan sẽ cắt mất nó. */
.pan-inner {
  position: absolute; inset: 0; z-index: 1;
  overflow: hidden;
  border-radius: var(--r-card);
  pointer-events: none;
}
.pan-inner .sec {                 /* nội dung thật co vào bề rộng một nấc, cắt bớt phần dưới */
  width: 100%; max-width: none;
  padding-block: 18px 0;
  margin: 0;
}
.pan-inner .sec-h { margin-block-start: 0; }
.pan-inner::after {               /* cắt ngang giữa chữ trông như lỗi, nên mờ dần xuống đáy nấc */
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 34%;
  background: linear-gradient(180deg, transparent, var(--bg));
  pointer-events: none;
}
.pan-decor {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%;
  width: 68%; aspect-ratio: 1171 / 1444;
  background: url(/assets/img/bg-main.webp) center / contain no-repeat;
  opacity: .22;
}
.pan::after {                     /* hoạ tiết phượng — dùng background nên không tràn ra ngoài nấc */
  content: ""; position: absolute; inset: 0; z-index: 0;
  background: url(/assets/img/phuong.webp) right -14% bottom -6% / 74% auto no-repeat;
  opacity: .13; pointer-events: none;
}
/* nấc 3 dùng rồng, không thì hai nấc sau trùng hoạ tiết y hệt nhau khi mở phẳng */
.pan-3::after { background-image: url(/assets/img/rong.webp); background-position: left -16% top -4%; }

/* --- mở lần lượt: nấc 2 rồi nấc 3 --- */
.gate.opening .pan-2 { animation: pan-open .55s cubic-bezier(.34, .06, .26, 1) 2s forwards; }
.gate.opening .pan-3 { animation: pan-open .55s cubic-bezier(.34, .06, .26, 1) 2.28s forwards; }
@keyframes pan-open {
  0%   { transform: rotateX(-180deg); opacity: 0; }
  32%  { opacity: 0; }
  33%  { opacity: 1; }              /* đo từ transform thực tế: nấc qua 90 độ ở 33% */
  100% { transform: rotateX(0deg);    opacity: 1; }
}
/* tấm rộng dần W thành 3W nên phải thu nhỏ cho vừa khung — đây là cái giá của kiểu đàn xếp */
.gate.opening .fold3 { animation: fold3-fit 1s cubic-bezier(.3, .1, .3, 1) 2s forwards; }
/* Tấm cao dần H thành 3H nên phải thu nhỏ cho vừa chiều cao khung.
   translateY bù = (1 - 3 x scale) / 2 tính theo chiều cao một nấc — đó là lượng dịch để
   tấm ba nấc nằm giữa khung khi transform-origin đặt ở mép trên.
   Mức thu nhỏ --fold-s khai theo khổ máy: mở dọc thì cái siết là CHIỀU CAO màn, không
   phải bề rộng, nên breakpoint đi theo max-height. */
@keyframes fold3-fit {
  0%   { transform: translateY(0) scale(1); }
  28%  { transform: translateY(calc((1 - 3 * var(--fold-s)) * 50%)) scale(calc(var(--fold-s) + (1 - var(--fold-s)) * .45)); }
  65%  { transform: translateY(calc((1 - 3 * var(--fold-s)) * 50%)) scale(calc(var(--fold-s) * 1.06)); }
  100% { transform: translateY(calc((1 - 3 * var(--fold-s)) * 50%)) scale(var(--fold-s)); }
}

/* Triện SÁP niêm ở mũi nắp — CHÍNH LÀ nút mở thiệp (không còn nút chữ riêng),
   nên vùng bấm phải đủ lớn (≥44px) và animation phải đủ mời gọi để khách biết bấm vào đây. */
.env-seal {
  position: absolute; left: 50%; top: var(--seal-y); z-index: 9;
  width: 54px; height: 54px;
  padding: 0; border: 0; background: none;
  border-radius: var(--r-pill);       /* thiếu cái này thì quầng sáng seal-pulse đổ theo hộp VUÔNG */
  transform: translate(-50%, -50%);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  --seal-shadow: rgba(233, 206, 158, .28);
  animation: seal-pulse 2s ease-in-out infinite;
}
.env-seal img { display: block; width: 100%; height: 100%; object-fit: contain; pointer-events: none; }
@media (min-width: 768px) { .env-seal { width: 68px; height: 68px; } }
/* hai vòng nhũ lan ra liên tục quanh triện — tín hiệu "bấm vào đây" */
.env-seal::before, .env-seal::after {
  content: ""; position: absolute; inset: -2px;
  border: 1.5px solid var(--gold); border-radius: var(--r-pill);
  opacity: 0; pointer-events: none;
  animation: seal-invite 2.6s cubic-bezier(.2, .7, .3, 1) infinite;
}
.env-seal::after { animation-delay: 1.3s; }
@keyframes seal-invite {
  0%   { opacity: .75; transform: scale(1); }
  70%  { opacity: 0;   transform: scale(2.1); }
  100% { opacity: 0;   transform: scale(2.1); }
}
.env-seal:hover  { --seal-shadow: rgba(233, 206, 158, .55); }
.env-seal:active { filter: brightness(1.15); }
.env-seal:focus-visible { outline: 2px solid var(--gold); outline-offset: 6px; }
/* bấm rồi thì thôi mời gọi, nhường chỗ cho cú triện vỡ */
.gate.opening .env-seal::before,
.gate.opening .env-seal::after { animation: none; opacity: 0; }

/* ---- Nhịp mở (mốc đổi mặt nắp đo từ transform thực tế: qua 90° ở 36% timeline;
        backface-visibility không kế thừa xuống con nên phải đổi mặt bằng opacity) ---- */
.gate.opening .env-flap { animation: env-flap-open .8s cubic-bezier(.4, .02, .3, 1) .26s forwards; }
@keyframes env-flap-open { 0% { transform: rotateX(0); } 85% { transform: rotateX(-152deg); } 100% { transform: rotateX(-158deg); } }
@keyframes env-face-hide { 0%, 36% { opacity: 1; } 37%, 100% { opacity: 0; } }
@keyframes env-face-show { 0%, 36% { opacity: 0; } 37%, 100% { opacity: 1; } }
.gate.opening .env-flap-out   { animation: env-face-hide .8s linear .26s forwards; }
.gate.opening .env-flap-in    { animation: env-face-show .8s linear .26s forwards; }
.gate.opening .env-flap-shade { animation: env-flap-shade .8s ease-in .26s forwards; }
@keyframes env-flap-shade { 0% { opacity: 0; } 60% { opacity: .85; } 100% { opacity: 1; } }
/* nắp mở quá 90° phải ra SAU tờ thiệp, không thì thiệp trượt lên bị nắp cắt */
.gate.opening .env-flapwrap { animation: env-flap-z 1.65s linear forwards; }
@keyframes env-flap-z {
  0%, 27%  { z-index: 8; opacity: 1; transform: translateY(0)   scale(1);   }
  28%, 54% { z-index: 1; opacity: 1; transform: translateY(0)   scale(1);   }
  100%     { z-index: 1; opacity: 0; transform: translateY(26%) scale(.97); }
}
.gate.opening .env-glow { animation: env-glow 1.1s ease-out .5s forwards; }
@keyframes env-glow { 0% { opacity: 0; } 28% { opacity: .8; } 100% { opacity: 0; } }
/* tờ thiệp: trượt lên khỏi phong bì rồi lớn dần về khổ thật */
.gate.opening .env-slip { animation: env-slip-out 1.15s cubic-bezier(.24, .78, .24, 1) .7s forwards; }
@keyframes env-slip-out {
  0%   { transform: translateY(2%)   scale(var(--slip-s)); }
  40%  { transform: translateY(-21%) scale(calc(var(--slip-s) + (1 - var(--slip-s)) * .3)); }
  70%  { transform: translateY(-14%) scale(calc(var(--slip-s) + (1 - var(--slip-s)) * .68)); }
  100% { transform: translateY(0)    scale(1.04); }
}
/* phong bì cao hơn thì thiệp chỉ cần trượt lên ít là đã ra khỏi miệng */
@media (min-width: 768px) {
  @keyframes env-slip-out {
    0%   { transform: translateY(2%)   scale(var(--slip-s)); }
    40%  { transform: translateY(-18%) scale(calc(var(--slip-s) + (1 - var(--slip-s)) * .3)); }
    70%  { transform: translateY(-12%) scale(calc(var(--slip-s) + (1 - var(--slip-s)) * .68)); }
    100% { transform: translateY(0)    scale(1.04); }
  }
}
.gate.opening .env-slipshadow { animation: env-shadow-out .7s ease-out .7s forwards; }
@keyframes env-shadow-out { to { opacity: 0; } }
/* phong bì rơi khỏi khung */
.gate.opening .env-inside,
.gate.opening .env-front { animation: env-away .65s ease-out 1s forwards; }   /* xong ở 1,65s — fold bắt đầu 2,0s, cách 350ms cho mắt thấy phong bì đã đi hẳn */
@keyframes env-away { to { transform: translateY(26%) scale(.97); opacity: 0; } }

.gate-seal.small { position: static; transform: none; width: 56px; height: 56px; margin: 0 auto var(--space-within); animation: none; }
/* Tên đôi trên bìa phải CÙNG kiểu chữ với hero (trang đầu trong thiệp): cùng weight,
   cùng line-height, dấu & cùng là Ms Madi và cùng tỉ lệ 37/50 so với tên — vì cuối cú mở
   tấm thiệp phóng to xuyên vào hero, khác font là thấy chữ "đổi mặt" ngay lúc nối. Chỉ
   khác cỡ: cỡ bìa x hệ số phóng cuối (fold-s x 2.8) ra đúng ~50px của hero. */
.gate-names { font-size: 36px; font-weight: 300; line-height: 1.5; position: relative; z-index: 1; }
.gate-names .amp { font-family: var(--f-amp); font-size: 27px; font-weight: 300; }
@media (min-width: 640px) { .gate-names { font-size: 40px; } .gate-names .amp { font-size: 30px; } }
@media (min-width: 768px) { .gate-names { font-size: 48px; } .gate-names .amp { font-size: 36px; } }
.rule {
  width: 96px; height: 1px; border: 0;
  margin: 28px auto; /* optical: gạch nhũ trong thiệp cần sát hơn nhịp chung */
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
  position: relative; overflow: visible;
}
.rule::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 5px; height: 5px; translate: -50% -50%; rotate: 45deg;
  background: var(--gold);
}
/* Tên khách trên mặt phong bì (bìa thiệp bên trong chỉ còn tên đôi). Chữ viết tay
   uốn lượn (Ms Madi — cùng font dấu &), trơn, KHÔNG hộp nền — chủ nhà bỏ hộp vì nhìn lởm. */
.env-guest {
  display: block;
  font-family: var(--f-amp); font-size: 27px; line-height: 1.2;
  color: var(--gold);
  margin-block-start: 8px;
  position: relative; z-index: 1;
}
@media (min-width: 768px) { .env-guest { font-size: 32px; } }


/* tia sáng nhấp nháy quanh thiệp / hộp quà */
.spark {
  position: absolute; color: var(--gold); font-size: var(--fs-base);
  animation: twinkle 2s ease-in-out infinite; pointer-events: none;
}
.spark.s1 { top: -10px; left: 8%; }
.spark.s2 { top: 16%; right: -12px; animation-delay: .6s; }
.spark.s3 { bottom: -10px; left: 18%; animation-delay: 1.2s; }
.spark.s4 { bottom: 22%; left: -12px; animation-delay: 1.7s; }
@keyframes float3 { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
@keyframes twinkle { 0%, 100% { opacity: .25; transform: scale(.7); } 50% { opacity: 1; transform: scale(1.15); } }

/* ============ Hero ============ */
/* hoạ tiết long phụng chìm sau tên (tự vẽ — tools/make_longphung.py) */
.longphung {
  position: absolute; top: 48px; left: 0; right: 0;
  display: flex; justify-content: center; gap: 32px;
  opacity: .15;
  pointer-events: none;
  z-index: 0;
}
.longphung img { height: 354px; width: auto; }
@media (min-width: 768px) {
  .longphung { top: 64px; }
  .longphung img { height: 572px; }
}
.hero-names { position: relative; z-index: 1; }

.hero {
  position: relative; z-index: 1;
  min-height: 472px;
  display: grid; place-items: center;
  padding: var(--space-section) var(--gutter);
  text-align: center;
}
.hero-names { font-size: 50px; font-weight: 300; line-height: 1.5; }
.hero-names .amp { font-family: var(--f-amp); font-size: 37px; font-weight: 300; }
@media (min-width: 768px) {
  .hero-names { font-size: 70px; }
  .hero-names .amp { font-size: 50px; }
}
@media (min-width: 768px) { .hero { min-height: 650px; } }

/* ============ Album: lưới 2 cột ô vuông ============ */
/* chips chọn danh mục ảnh */
.cate-tabs {                      /* T2 · Ngoặc nhũ: tab đang chọn được hai dấu ⟨ ⟩ ôm lấy */
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
  gap: 2px;
  margin-block-end: var(--space-between);
}
.cate-tab {
  position: relative;
  border: 0; background: transparent;
  font-family: var(--f-serif);
  font-size: 14px; font-weight: 400; letter-spacing: .12em; text-transform: uppercase;
  color: color-mix(in srgb, var(--ink) 55%, transparent);
  padding: 12px 18px;
  min-height: 48px;
  transition: color .3s var(--ease);
}
.cate-tab:hover { color: color-mix(in srgb, var(--ink) 80%, transparent); }
.cate-tab[aria-selected="true"] { color: var(--gold); }
.cate-tab[aria-selected="true"]::before,
.cate-tab[aria-selected="true"]::after {
  position: absolute; top: 50%; translate: 0 -52%;
  font-size: 16px; line-height: 1; color: var(--gold);
}
.cate-tab[aria-selected="true"]::before { content: "\27E8"; left: 2px; }
.cate-tab[aria-selected="true"]::after  { content: "\27E9"; right: 2px; }
.cate-tab + .cate-tab { margin-inline-start: 14px; }
.cate-tab + .cate-tab::marker { content: none; }
.cate-tabs .cate-sep {            /* viên kim cương ngăn giữa hai tab */
  width: 4px; height: 4px; rotate: 45deg; background: var(--line);
  flex: none;
}
@media (min-width: 768px) { .cate-tab { font-size: 15px; padding-inline: 22px; } }
@media (max-width: 430px) {       /* hẹp thì thu nhỏ cho vừa 3 tab, không phải cuộn */
  .cate-tab { font-size: 12px; letter-spacing: .08em; padding-inline: 13px; }
  .cate-tab + .cate-tab { margin-inline-start: 9px; }
}

.album { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-within); }
.ph {
  position: relative; display: block; width: 100%; padding: 0; text-decoration: none;
  border: 1px solid var(--line-soft); border-radius: var(--r-card);
  background: color-mix(in srgb, #000 10%, var(--bg));
  overflow: hidden;
}
.ph img { width: 100%; aspect-ratio: 1; object-fit: cover; transition: transform .3s var(--ease); }
.ph:hover img { transform: scale(1.04); }
.ph .more { /* ô cuối: +N ảnh nữa */
  position: absolute; inset: 0;
  display: grid; place-items: center;
  background: color-mix(in srgb, #000 55%, transparent);
  color: var(--gold); font-size: var(--fs-md);
}

/* ============ Thông tin lễ cưới ============ */
/* hai nhà đứng cạnh nhau như mẫu: trai trái · gái phải */
.fams {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: var(--space-between) var(--gutter);
  margin-block-start: var(--space-between);
  align-items: start;
}
.fam-label {
  font-size: 14px; line-height: 1.5; font-weight: 600;
  letter-spacing: .04em;
  color: var(--ink);
  margin-block-end: var(--space-within);
}
.fam-names { font-size: 13px; font-weight: 300; line-height: 1.5; letter-spacing: .05em; }
.fam-addr { font-size: 12px; font-weight: 300; line-height: 1.6; color: var(--ink-soft); margin-block-start: var(--space-within); }
@media (min-width: 768px) {   /* số đo lấy từ mẫu */
  .fam-label { font-size: 20px; }
  .fam-names { font-size: 23px; line-height: 1.5; }
  .fam-addr { font-size: 18px; line-height: 1.5; }
}

.announce {
  margin-block-start: var(--space-section);
  font-size: var(--fs-sm); letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-soft); line-height: 2;
}
.couple { margin-block-start: var(--space-between); }
.couple-name { font-size: 40px; font-weight: 400; line-height: 1.25; }
@media (min-width: 768px) { .couple-name { font-size: 64px; line-height: 1.5625; } }
.couple-rank {
  font-size: var(--fs-xs); letter-spacing: .2em; text-transform: uppercase;
  color: var(--ink-soft);
}
.amp-line {
  font-family: var(--f-amp);
  font-size: 35px; font-weight: 300;     /* & Ms Madi như mẫu: 35 → 48px */
  line-height: 1.5;
  color: var(--gold);
  margin-block: var(--space-within);
}
@media (min-width: 768px) { .amp-line { font-size: 48px; } }   /* phải đứng sau khai báo gốc */

.ceremony { margin-block-start: var(--space-section); }
.cer-label { font-size: 16px; font-weight: 300; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-soft); }
.cer-label.vao-luc { font-weight: 400; letter-spacing: normal; margin-block-start: var(--space-between); }
@media (min-width: 768px) { .cer-label.vao-luc { font-size: 18px; } }
.cer-venue { font-size: 17px; font-weight: 400; letter-spacing: .05em; margin-block-start: var(--space-within); }
.cer-addr { font-size: 14px; font-weight: 300; letter-spacing: .025em; line-height: 1.43; color: var(--ink-soft); margin-block-start: 4px; } /* optical: địa chỉ dính tên nơi */
@media (min-width: 768px) { .cer-venue { font-size: 19px; } .cer-addr { font-size: 16px; letter-spacing: .025em; } }
.cer-time { font-size: 20px; font-weight: 300; margin-block-start: var(--space-within); font-variant-numeric: lining-nums tabular-nums; }
@media (min-width: 768px) { .cer-time { font-size: 30px; } }

/* khối ngày: thứ | ngày | tháng — vạch là phần tử riêng 2px nên luôn đối xứng (đo từ mẫu) */
.date-row {
  display: flex; justify-content: center; align-items: center;
  gap: 24px;
  margin-block-start: var(--space-within);
}
.date-sep { width: 2px; height: 24px; background: var(--gold); flex: none; }
.dc-sm  { font-size: 12px; font-weight: 300; text-transform: uppercase; }
.dc-big { font-size: 30px; font-weight: 300; line-height: 1.5; font-variant-numeric: lining-nums tabular-nums; }
.date-year {
  font-size: 18px; font-weight: 300;      /* năm đứng riêng dưới hàng ngày, như mẫu */
  font-variant-numeric: lining-nums tabular-nums;
  margin-block-start: var(--space-within);
}
@media (min-width: 768px) {
  .date-sep { height: 32px; }
  .dc-sm { font-size: 16px; }
  .dc-big { font-size: 40px; }
  .date-year { font-size: 24px; }
}
.cer-lunar { font-size: 12px; font-weight: 300; letter-spacing: .1em; text-transform: uppercase; line-height: 1.6; color: var(--ink-soft); margin-block-start: var(--space-within); }
@media (min-width: 768px) { .cer-lunar { font-size: 14px; letter-spacing: .12em; } }

/* ============ Thông tin tiệc cưới ============ */
.party-item {
  margin-block-start: var(--space-between);   /* không dính tiêu đề mục */
  margin-block-end: var(--space-between);
  padding: var(--space-between) var(--gutter);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-card);
}
.party-item:last-child { margin-block-end: 0; }
.party-side {
  position: relative;
  font-size: 20px; font-weight: 400;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink);
  padding-block-end: 18px;
  margin-block-end: var(--space-between);
}
.party-side::after {          /* vạch nhũ ngắn ở giữa thay cho đường kẻ chạy hết bề ngang */
  content: ""; position: absolute; left: 50%; bottom: 0;
  width: 56px; height: 1px; background: var(--gold);
  translate: -50% 0;
}
@media (min-width: 768px) { .party-side { font-size: 22px; } }
.party-links { margin-block-start: var(--space-within); }
.link-dot { color: var(--ink-soft); margin-inline: 8px; }
.party-lead { font-size: 16px; font-weight: 300; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-soft); }
.party-host { font-size: 17px; font-weight: 400; letter-spacing: .05em; margin-block-start: var(--space-within); }
@media (min-width: 768px) { .party-host { font-size: 19px; } }

/* đếm ngược: dùng lại ngôn ngữ ô ngày — số lớn, vạch nhũ ngăn giữa */
.cd-row {
  display: flex; justify-content: center; align-items: center;
  gap: 18px;
  margin-block-end: var(--space-between);
}
.cd-cell { display: grid; justify-items: center; gap: 4px; min-width: 52px; }
.cd-num {
  font-size: 30px; font-weight: 300; line-height: 1.5;
  font-variant-numeric: lining-nums tabular-nums;
  color: var(--ink);
}
/* cửa sổ trượt: hai số chồng lên nhau, cắt gọn phần tràn ra ngoài */
.cd-num { display: inline-grid; overflow: hidden; }
.cd-num > .cd-digit { grid-area: 1 / 1; }
/* mềm: đi quãng ngắn (58%), ease-out cubic, mờ dần sớm nên không thấy hai số cùng lúc */
.cd-digit.out { animation: cdSlideOut .58s cubic-bezier(.33, 1, .68, 1) forwards; }
.cd-digit.in { animation: cdSlideIn .58s cubic-bezier(.33, 1, .68, 1); }
@keyframes cdSlideOut {
  0%   { translate: 0 0;     opacity: 1; }
  100% { translate: 0 -58%;  opacity: 0; }
}
@keyframes cdSlideIn {
  0%   { translate: 0 58%;   opacity: 0; }
  55%  { opacity: 1; }
  100% { translate: 0 0;     opacity: 1; }
}
/* bốn ô hiện dần so le khi cuộn tới */
.cd-cell, .cd-row .date-sep {
  opacity: 0; translate: 0 10px;
  transition: opacity .45s var(--ease), translate .45s var(--ease);
  transition-delay: calc(var(--i, 0) * 90ms);
}
.cd-row.in .cd-cell, .cd-row.in .date-sep { opacity: 1; translate: 0; }
@media (prefers-reduced-motion: reduce) {
  .cd-cell, .cd-row .date-sep { opacity: 1; translate: 0; transition: none; }
  .cd-digit.out, .cd-digit.in { animation: none; }
}
.cd-lb {
  font-size: 11px; font-weight: 300; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-soft);
}
.cd-row .date-sep { height: 30px; }
@media (min-width: 768px) {
  .cd-row { gap: 26px; }
  .cd-cell { min-width: 68px; }
  .cd-num { font-size: 40px; }
  .cd-lb { font-size: 12px; }
  .cd-row .date-sep { height: 40px; }
}
@media (max-width: 360px) { .cd-row { gap: 12px; } .cd-num { font-size: 26px; } }

/* lịch tháng — card viền vàng, hàng thứ gạch đậm, ngày cưới có tim (như mẫu) */
.cal {
  max-width: 560px; margin: var(--space-between) auto 0;
  padding: 20px 16px 24px;
  border: 1px solid var(--line-soft); border-radius: var(--r-card);
}
.cal-title {
  font-size: 13px; font-weight: 600; letter-spacing: .025em; text-align: center;
  padding-block-end: 14px; margin-block-end: 4px;
  border-block-end: 1px solid var(--line-soft);
}
.cal-head {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  border-block-end: 2px solid var(--gold);
}
.cal-wd { padding: 12px 0 10px; font-size: 10px; font-weight: 500; color: var(--ink-soft); text-align: center; }
.cal-grid {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); row-gap: 6px;
  padding-block-start: 12px;
  font-size: 12px; font-weight: 300; font-variant-numeric: lining-nums tabular-nums;
}
.cal-d { position: relative; display: grid; place-items: center; min-height: 44px; }
.cal-d.mark svg { position: absolute; width: 34px; height: 34px; fill: var(--gold); }
.cal-d.mark b { position: relative; font-weight: 700; font-size: 11px; color: var(--on-gold); translate: 0 2px; }
@media (min-width: 768px) {
  .cal { padding: 24px 24px 28px; }
  .cal-title { font-size: 14px; }
  .cal-wd { font-size: 11px; }
  .cal-grid { font-size: 13px; }
}


/* nút xác nhận riêng của từng tiệc */
.party-rsvp { margin-block-start: var(--space-between); }

/* ============ Album dạng popup ============ */
.album-modal .album-sheet {
  width: min(960px, 100vw); max-width: 100vw;
  height: 100dvh; max-height: 100dvh;
  padding: 0; border: 0; border-radius: 0;
  display: flex; flex-direction: column;
  overflow: hidden;                 /* lưới cuộn bên trong, đầu trang đứng yên */
  animation: albumSheetIn .4s var(--ease) both;
}
/* Backdrop album phải ĐẶC: bản 85% đen để trang phía sau nhìn xuyên qua ở khoảng hở quanh
   khung (desktop hở 165px mỗi bên) — chủ nhà thấy "chưa che hẳn page". */
.modal.album-modal::backdrop { background: var(--bg-deep); animation: albumFade .2s var(--ease) both; }   /* .modal.album-modal: phải thắng ".modal::backdrop" khai ở dưới */
.lightbox::backdrop { background: rgba(16, 1, 1, .96); }
@keyframes albumSheetIn { from { opacity: 0; transform: translateY(26px) scale(.99); } }
@keyframes albumFade { from { opacity: 0; } }
@media (min-width: 768px) {
  .album-modal .album-sheet {
    height: 92dvh; border: 1px solid var(--line); border-radius: var(--r-card);
  }
}
.album-sheet-head {
  flex: none; position: relative; z-index: 2;
  padding: 26px var(--gutter) 14px;
  border-block-end: 1px solid var(--line-soft);
  background: var(--bg);
}
.album-sheet-head .sec-h { margin-block-end: 6px; }
.album-sheet-head .cate-tabs { margin-block-end: 0; margin-block-start: 10px; }
.album-count { margin-block-start: 0; }
.album-modal .album-full {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  align-content: start;
  padding: var(--space-between) var(--gutter) var(--space-section);
}
@media (min-width: 768px) { .album-modal .album-full { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .album-modal .album-full { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* ---- Lưới album trong popup: ô đều nhau, khung mảnh, ảnh hiện dần ---- */
.album-full {
  gap: 12px;
  align-content: start;
  grid-auto-rows: max-content;   /* bắt buộc: thiếu dòng này hàng bị kéo giãn đều và ảnh đè lên nhau */
}
.album-full .ph {
  /* <button> không truyền chiều cao của ảnh ra ngoài → hàng lưới bị co rồi kéo giãn đều,
     ảnh tràn đè lên hàng dưới. Cố định tỉ lệ ngay trên ô và cho ảnh phủ tuyệt đối. */
  position: relative;
  aspect-ratio: 3 / 4;
  border: 1px solid var(--line-soft);
  border-radius: var(--r-card);
  padding: 0;
}
.album-full .ph img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;   /* giữa khung — không cắt mất mặt */
  border-radius: inherit;
  opacity: 0; transition: opacity .45s var(--ease);
}
.album-full .ph img.loaded { opacity: 1; }
.album-full .ph:hover img, .album-full .ph:focus-visible img { opacity: .88; }
/* hiện dần: mờ + nhích lên, so le theo --i */
.album-full .ph {
  opacity: 0; translate: 0 14px;
  transition: opacity .42s var(--ease), translate .42s var(--ease);
  transition-delay: calc(var(--i, 0) * 55ms);
}
.album-full .ph.in { opacity: 1; translate: 0; }
@media (prefers-reduced-motion: reduce) {
  .album-full .ph { opacity: 1; translate: 0; transition: none; }
  .album-full .ph img { opacity: 1; transition: none; }
}

/* ============ Chuyện tình yêu — S2 · Nguyệt môn ============
   Ảnh cắt tròn viền chỉ nhũ đôi, so le hai bên,
   phía sau là số thứ tự viết bằng chữ thư pháp cỡ lớn mờ. */
.story { list-style: none; margin: 0 auto; padding: 0; max-width: 640px; }
.story-item {
  position: relative;
  display: grid; grid-template-columns: 124px 1fr;
  align-items: center; gap: 18px;
  padding-block: var(--space-between);
}
.story-item:nth-child(even) { grid-template-columns: 1fr 124px; }
.story-num {                      /* số thứ tự thư pháp chìm sau ảnh */
  position: absolute; z-index: 0; top: 6px; left: 50%; translate: -50% 0;
  font-family: var(--f-script); font-size: 84px; line-height: 1;
  color: color-mix(in srgb, var(--gold) 14%, transparent);
  pointer-events: none; user-select: none;
}
.story-fig {
  position: relative; z-index: 1; grid-column: 1; grid-row: 1;
  margin: 0; justify-self: start;
}
.story-item:nth-child(even) .story-fig { grid-column: 2; justify-self: end; }
.story-fig img {
  display: block; width: 124px; aspect-ratio: 1;
  object-fit: cover; object-position: center 22%;
  border-radius: 50%;
  box-shadow: 0 0 0 1px var(--line), 0 0 0 6px transparent, 0 0 0 7px var(--line-soft);
}
.story-body {
  position: relative; z-index: 1; grid-column: 2; grid-row: 1;
  text-align: left;
}
.story-item:nth-child(even) .story-body { grid-column: 1; text-align: right; }
.story-item.no-photo .story-body { grid-column: 1 / -1; text-align: center; }
.story-date {
  font-size: 11px; font-weight: 300; letter-spacing: .22em; text-transform: uppercase;
  color: var(--ink-soft);
}
.story-title { font-size: 18px; font-weight: 500; line-height: 1.35; margin-block: 5px 0; }
.story-text { font-size: 14px; font-weight: 300; line-height: 1.625; color: var(--ink-soft); margin-block-start: 8px; }

@media (min-width: 768px) {
  .story-item { grid-template-columns: 168px 1fr; gap: 28px; }
  .story-item:nth-child(even) { grid-template-columns: 1fr 168px; }
  .story-fig img { width: 168px; }
  .story-num { font-size: 120px; top: -6px; }
  .story-title { font-size: 20px; }
}

/* ============ Hộp quà ============ */
.gift-reveal { display: grid; justify-content: center; }
/* hai phong bao lì xì vàng tựa vào nhau (tự dựng CSS, hoạ tiết rồng/phượng chìm) */
/* hộp quà: hai phong bao — hình học & animation đo từ mẫu (ienv*) */
.ienv {
  position: relative;
  width: 250px; height: 357px;
  padding: 0; border: 0; background: transparent;
  cursor: pointer;
}
.ienv-stage {
  position: relative; width: 100%; height: 100%;
  display: flex; align-items: flex-end; justify-content: center;
  padding-block-end: 48px;
}
.ienv-pair { position: relative; width: 190px; height: 275px; }
.ienv-shadow {
  position: absolute; left: 50%; bottom: -6px;
  width: 125.4px; height: 11px; margin-inline-start: -62.7px;
  border-radius: 50%; background: rgba(0, 0, 0, .45);
  filter: blur(4px); pointer-events: none;
  animation: ienvShadowPulse 3s ease-in-out infinite;
}
.ienv-back, .ienv-card {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain; object-position: center bottom;
  pointer-events: none;
}
.ienv-back {
  transform-origin: 50% 100%;
  transform: translateX(20%) translateY(-10%) scale(-.8, .8) rotate(-15deg);  /* lật gương, lùi ra sau */
  z-index: 1;
  filter: drop-shadow(0 8px 14px rgba(0, 0, 0, .18));
  animation: ienvFloat 5.2s ease-in-out .5s infinite;
}
.ienv-card {
  transform-origin: 50% 92%;
  rotate: -10deg; z-index: 2;
  filter: drop-shadow(0 10px 18px rgba(0, 0, 0, .22));
  transition: transform .35s;
  animation: ienvFloatMain 3s ease-in-out infinite;
}
@keyframes ienvFloat { 0%, 100% { translate: 0; } 50% { translate: 0 -7px; } }
@keyframes ienvFloatMain { 0%, 100% { translate: -15%; } 50% { translate: -15% -7px; } }
@keyframes ienvShadowPulse { 0%, 100% { transform: scaleX(1); opacity: .28; } 50% { transform: scaleX(.9); opacity: .16; } }
@keyframes ienvSparkleAnim { 0%, 100% { opacity: 0; transform: scale(.4); } 50% { opacity: 1; transform: scale(1.15); } }
@keyframes ienvHintPulse { 0%, 100% { opacity: .45; } 50% { opacity: 1; } }
@keyframes ienvGrow { from { transform: scale(1); } to { transform: scale(1.12); } }
@keyframes ienvWave {
  0% { transform: scale(1.12) rotate(0deg); }
  20% { transform: scale(1.12) rotate(-6deg); }
  40% { transform: scale(1.12) rotate(4.5deg); }
  60% { transform: scale(1.12) rotate(-3deg); }
  80% { transform: scale(1.12) rotate(1.5deg); }
  100% { transform: scale(1.12) rotate(0deg); }
}
@keyframes ienvBackWave { 0%, 100% { rotate: 0deg; } 20% { rotate: -1deg; } 40% { rotate: 2deg; } 60% { rotate: -2.5deg; } 80% { rotate: 1.5deg; } }
.ienv:hover .ienv-card, .ienv:focus-visible .ienv-card {
  animation: ienvFloatMain 3s ease-in-out infinite, ienvGrow .35s ease forwards, ienvWave 1.1s ease-in-out .35s infinite;
}
.ienv:hover .ienv-back, .ienv:focus-visible .ienv-back {
  animation: ienvFloat 5.2s ease-in-out .5s infinite, ienvBackWave 2.2s ease-in-out infinite;
}
.ienv-sparkle {
  position: absolute; z-index: 3; pointer-events: none;
  color: var(--bronze);
  animation: ienvSparkleAnim 2s ease-in-out infinite;
}
.ienv-sparkle.s1 { top: 6%;  left: 12%;  font-size: 20.9px; }
.ienv-sparkle.s2 { top: 14%; right: 8%;  font-size: 15.2px; animation-delay: .6s; }
.ienv-sparkle.s3 { top: 34%; left: 3%;   font-size: 13.3px; animation-delay: 1.2s; }
.ienv-sparkle.s4 { top: 24%; right: 3%;  font-size: 13.3px; animation-delay: 1.7s; }
.ienv-hint {
  position: absolute; bottom: 0; left: 50%; translate: -50% 0;
  margin: 0; white-space: nowrap;
  font-size: 12px; font-weight: 500; color: var(--ink);
  animation: ienvHintPulse 2s ease-in-out infinite;
}
.gift-grid { display: grid; gap: var(--space-between); }
.gift-card { display: grid; justify-items: center; gap: var(--space-within); }
.gift-card h3 { font-size: var(--fs-base); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-soft); }
.gift-card img {
  width: min(220px, 62vw); aspect-ratio: 1; object-fit: contain;
  background: #fff; /* QR phải nền trắng để quét được */
  border-radius: var(--r-card); padding: var(--space-within);
}
.gift-acc { font-size: var(--fs-base); letter-spacing: .06em; font-variant-numeric: lining-nums tabular-nums; }

/* ============ Footer ============ */
.footer {
  position: relative; z-index: 1;
  padding: var(--space-section) var(--gutter);
  text-align: center;
  border-block-start: 1px solid var(--line-soft);
}
.footer p { font-size: 14px; line-height: 1.6; color: var(--ink-soft); }
.footer .footer-names {      /* trước bị .footer p đè xuống 13px */
  font-size: clamp(26px, 8vw, 34px); line-height: 1.4; color: var(--gold);
  margin-block-start: var(--space-between);
}
@media (min-width: 768px) { .footer .footer-names { font-size: 46px; } }

/* ============ Nút nhạc nổi ============ */
.disc {
  position: fixed; z-index: 50;
  right: var(--gutter); bottom: max(var(--gutter), env(safe-area-inset-bottom));
  width: 52px; height: 52px;
  display: grid; place-items: center;
  border: 0; border-radius: var(--r-pill);
  background: var(--gold);
  box-shadow: var(--shadow);
  opacity: 0; translate: 0 12px;
  transition: opacity .3s var(--ease), translate .3s var(--ease);
}
html.gate-opened .disc { opacity: 1; translate: 0 0; }
.disc .eq { display: flex; align-items: flex-end; gap: 3px; height: 18px; }
.disc .eq i { width: 3px; height: 5px; background: var(--on-gold); border-radius: 1px; }
.disc .eq i:nth-child(2) { height: 12px; animation-delay: .12s; }
.disc .eq i:nth-child(3) { height: 8px; animation-delay: .22s; }
.disc[aria-pressed="true"] .eq i { animation: dance .4s ease-in-out infinite alternate; }
@keyframes dance { to { height: 18px; } }

/* ============ Modal ============ */
.modal { border: 0; padding: 0; background: transparent; max-width: 100vw; max-height: 100dvh; }
.modal::backdrop { background: rgba(0, 0, 0, .85); }
.modal-box {
  position: relative;
  width: min(430px, 92vw);
  max-height: 88dvh; overflow-y: auto;
  padding: var(--space-section) var(--gutter) var(--space-between);
  background: var(--bg); color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  text-align: center;
  animation: modalUp .35s var(--ease);
}
@keyframes modalUp { from { opacity: 0; transform: translateY(16px); } }
/* hộp quà: dải tiêu đề nền nhũ như mẫu */
.modal-box.modal-gold { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.modal-gold .modal-head {
  position: relative;
  padding: 22px var(--gutter) 18px;
  background: var(--gold); color: var(--on-gold);
}
.modal-gold .modal-head .sec-h { margin: 0; color: var(--on-gold); }
.modal-gold .modal-x { color: var(--on-gold); border-color: transparent; }
.modal-gold .modal-head { flex: 0 0 auto; }
/* thân hộp quà cuộn riêng — dải tiêu đề nhũ đứng yên */
.modal-gold .gift-grid {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
  padding: var(--space-between) var(--gutter) var(--space-section);
}
.modal-x {
  position: absolute; top: var(--space-within); right: var(--space-within);
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border: 1px solid var(--line); border-radius: var(--r-pill);
  background: transparent; color: var(--ink);
}

/* ============ Form ============ */
.rsvp-greeting { font-size: var(--fs-sm); color: var(--ink-soft); margin-block-end: var(--space-between); }
.rsvp-greeting strong { color: var(--ink); font-weight: 600; }
.field { display: grid; gap: var(--space-within); margin-block-end: var(--space-between); text-align: left; border: 0; padding: 0; margin-inline: 0; }
.field > label, .field legend { font-size: var(--fs-sm); letter-spacing: .04em; color: var(--ink); padding: 0; }
.field .hint { color: var(--ink-soft); }
input[type="text"], textarea, select {
  font-family: var(--f-sans); font-size: var(--fs-base); color: var(--ink);
  background: color-mix(in srgb, #000 18%, var(--bg));
  border: 1px solid var(--line-soft); border-radius: var(--r-card);
  padding: var(--space-within); min-height: 48px; width: 100%;
}
input::placeholder, textarea::placeholder { color: color-mix(in srgb, var(--ink-soft) 65%, transparent); }
textarea { min-height: 96px; resize: vertical; }
input:focus, textarea:focus, select:focus { outline: 2px solid var(--gold); outline-offset: 1px; border-color: transparent; }
.choice-row { display: grid; gap: var(--space-within); }
.choice {                       /* hàng viên thuốc, dấu tick tròn bên trái */
  position: relative;
  display: flex; align-items: center; gap: 14px;
  min-height: 58px; padding: 12px 18px;
  font-size: 15px; cursor: pointer;
  background: color-mix(in srgb, #000 14%, var(--bg));
  border: 1px solid var(--line-soft); border-radius: var(--r-pill);
  transition: border-color .25s var(--ease), background .25s var(--ease);
}
.choice input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.choice-tick {
  flex: none; width: 28px; height: 28px; border-radius: 50%;
  border: 1px solid var(--line);
  display: grid; place-items: center;
  transition: background .25s var(--ease), border-color .25s var(--ease);
}
.choice-tick::before {
  content: ""; width: 11px; height: 6px;
  border-left: 1.5px solid var(--ink-soft); border-bottom: 1.5px solid var(--ink-soft);
  rotate: -45deg; translate: 0 -1px;
}
.choice.no .choice-tick::before {   /* dấu × cho lựa chọn không đến */
  width: 10px; height: 10px; rotate: 0deg; translate: 0;
  border: 0;
  background:
    linear-gradient(var(--ink-soft), var(--ink-soft)) center / 100% 1.5px no-repeat,
    linear-gradient(var(--ink-soft), var(--ink-soft)) center / 1.5px 100% no-repeat;
  transform: rotate(45deg);
}
.choice:has(input:checked) { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 10%, var(--bg)); }
.choice:has(input:checked) .choice-tick { background: var(--gold); border-color: var(--gold); }
.choice:has(input:checked) .choice-tick::before { border-color: var(--on-gold); }
.choice.no:has(input:checked) .choice-tick::before {
  background:
    linear-gradient(var(--on-gold), var(--on-gold)) center / 100% 1.5px no-repeat,
    linear-gradient(var(--on-gold), var(--on-gold)) center / 1.5px 100% no-repeat;
}
.choice:has(input:focus-visible) { outline: 2px solid var(--gold); outline-offset: 2px; }

/* ---- khung viết lời chúc ngay trong mục Sổ lưu bút ---- */
.wish-form {
  display: grid; gap: var(--space-within);
  max-width: 560px; margin: 0 auto var(--space-between);
  padding: var(--space-between) var(--gutter);
  border: 1px solid var(--line-soft); border-radius: var(--r-card);
  text-align: left;
}
.wish-form input, .wish-form textarea {
  border-radius: var(--r-card);
  background: color-mix(in srgb, #000 12%, var(--bg));
}
.wish-form textarea { min-height: 116px; }
.wish-actions { display: flex; align-items: center; justify-content: space-between; gap: var(--space-within); }
.wish-magic {
  flex: none; width: 44px; height: 44px;
  display: grid; place-items: center;
  font-size: 16px; color: var(--bronze);
  background: color-mix(in srgb, #000 12%, var(--bg));
  border: 1px solid var(--line-soft); border-radius: var(--r-card);
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.wish-magic:hover { color: var(--gold); border-color: var(--line); }
.wish-actions .btn { flex: 1; max-width: 260px; }
/* ---- Một dòng cho nơi đãi tiệc ---- */
.party-venue {
  font-size: 17px; font-weight: 400; line-height: 1.4;
  letter-spacing: .05em; color: var(--ink);
  margin-block-start: var(--space-between);
}
@media (min-width: 768px) { .party-venue { font-size: 19px; } }

/* ---- Danh sách lời chúc ---- */
.wishes-list {
  display: grid; gap: var(--space-within);
  max-width: 560px; margin: 0 auto;
  text-align: left;
}
.wish {
  position: relative;
  padding: 16px 18px 16px 20px;
  border: 1px solid var(--line-soft); border-radius: var(--r-card);
  background: color-mix(in srgb, #000 8%, var(--bg));
}
/* vạch nhũ mảnh bên trái — dấu hiệu "đây là lời của khách" */
.wish::before {
  content: ''; position: absolute; inset: 14px auto 14px 0;
  width: 2px; border-radius: 2px;
  background: linear-gradient(180deg, var(--gold), transparent);
  opacity: .55;
}
.wish-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; flex-wrap: wrap;
  margin-block-end: 6px;
}
.wish-name {
  font-size: var(--fs-base); font-weight: 600; letter-spacing: .03em;
  color: var(--gold);
}
.wish-time {
  font-size: var(--fs-xs); font-weight: 300; letter-spacing: .04em;
  color: var(--ink-soft); font-variant-numeric: lining-nums tabular-nums;
  white-space: nowrap; margin-inline-start: auto;   /* tên dài xuống dòng thì giờ vẫn nằm bên phải */
}
.wish-msg {
  margin: 0; font-size: var(--fs-base); font-weight: 300; line-height: 1.625;
  color: var(--ink); overflow-wrap: anywhere;
}
/* ---- Chuyển trang lời chúc ---- */
.wish-pager {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  max-width: 560px; margin: var(--space-within) auto 0;
}
.wish-page-btn {
  width: 38px; height: 38px; flex: none;
  display: grid; place-items: center;
  font-size: 18px; line-height: 1; color: var(--gold);
  background: transparent;
  border: 1px solid var(--line-soft); border-radius: var(--r-pill);
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.wish-page-btn:hover:not(:disabled) { color: var(--ink); border-color: var(--line); }
.wish-page-btn:disabled { opacity: .35; }
.wish-page-num {
  font-size: var(--fs-sm); letter-spacing: .1em; color: var(--ink-soft);
  font-variant-numeric: lining-nums tabular-nums; min-width: 54px; text-align: center;
}
/* mỗi trang hiện ra so le một nhịp cho đỡ khô */
.wishes-list .wish { animation: wishIn .38s var(--ease) both; animation-delay: calc(var(--i, 0) * 60ms); }
@media (prefers-reduced-motion: reduce) { .wishes-list .wish { animation: none; } }

/* lời chúc vừa gửi trượt vào cho khách thấy nó đã lên bảng */
.wish.fresh { animation: wishIn .45s var(--ease); }
@keyframes wishIn { from { opacity: 0; translate: 0 -10px; } }

/* khung xám nhấp nháy trong lúc chờ tải */
.wish.skeleton { min-height: 86px; overflow: hidden; }
.wish.skeleton::before { opacity: .2; }
.wish.skeleton::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--gold) 12%, transparent), transparent);
  animation: wishShimmer 1.6s linear infinite;
}
@keyframes wishShimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.form-status.ok { color: var(--ink); }
.field-error { font-size: var(--fs-sm); color: #FFD9C0; display: none; }
.field.invalid .field-error { display: block; }
.field.invalid input, .field.invalid textarea { border-color: #FFD9C0; }
.form-status { display: none; font-size: var(--fs-sm); border-radius: var(--r-card); padding: var(--space-within); }
.form-status.error { display: block; background: color-mix(in srgb, #000 25%, var(--bg)); color: #FFD9C0; }
.rsvp-success { display: grid; justify-items: center; gap: var(--space-within); }
/* ---- Tung hoa khi xác nhận xong ---- */
.rsvp-success { position: relative; }
.rsvp-success > h3, .rsvp-success > p { position: relative; z-index: 1; }
.rsvp-confetti {
  position: absolute; inset: -28px -24px -24px;
  overflow: hidden; pointer-events: none; z-index: 0;
}
.petal {
  position: absolute; top: -26px;
  width: 10px; height: 14px;
  border-radius: 60% 0 60% 0;          /* cánh hoa */
  opacity: 0;
  animation-name: petalFall;
  animation-timing-function: cubic-bezier(.36, .1, .55, 1);
  animation-fill-mode: forwards;
}
.petal.round { width: 8px; height: 8px; border-radius: 50%; }
.petal.strip { width: 4px; height: 13px; border-radius: 1px; }
@keyframes petalFall {
  0%   { transform: translate3d(0, 0, 0) rotate(0deg); opacity: 0; }
  8%   { opacity: 1; }
  80%  { opacity: 1; }
  100% { transform: translate3d(var(--dx, 0), var(--fall, 420px), 0) rotate(var(--spin, 540deg)); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) { .petal { display: none; } }

.rsvp-success h3 { font-size: var(--fs-md); letter-spacing: .06em; }
.rsvp-success p { font-size: var(--fs-sm); color: var(--ink-soft); }
.rsvp-success .btn { margin-block-start: var(--space-within); }

/* honeypot — ẩn với người thật, bot vẫn thấy trong DOM */
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ============ Lightbox ============ */
.lightbox { border: 0; padding: 0; background: transparent; max-width: 100vw; max-height: 100dvh; }
.lightbox::backdrop { background: rgba(10, 6, 6, .92); }
.lb-frame { display: grid; place-items: center; }
.lb-frame img { max-width: 92vw; max-height: 82dvh; object-fit: contain; border-radius: var(--r-card); }
.lb-bar {
  position: fixed; inset-inline: 0; bottom: max(var(--gutter), env(safe-area-inset-bottom));
  display: flex; justify-content: center; align-items: center; gap: var(--space-within);
}
.lb-btn {
  display: grid; place-items: center;
  width: 48px; height: 48px;
  border: 1px solid var(--line); border-radius: var(--r-pill);
  background: rgba(29, 20, 20, .8); color: var(--gold);
  font-size: var(--fs-md); line-height: 1;
}
.lb-close { position: fixed; top: var(--space-within); right: var(--space-within); }
.lb-count { font-size: var(--fs-sm); color: var(--ink); min-width: 64px; text-align: center; font-variant-numeric: lining-nums tabular-nums; }

[hidden] { display: none !important; }

/* ============ Giảm chuyển động ============ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .gate-card, .ienv-back, .ienv-card, .ienv-shadow, .ienv-sparkle, .ienv-hint, .spark, .disc .eq i, .wish.skeleton::after, .modal-box,
  .gate-seal, .seal-ring,
  .env-seal::before, .env-seal::after,
  .env-seal, .env-flap, .env-flap-out, .env-flap-in, .env-flap-shade, .env-flapwrap,
  .env-glow, .env-slip, .env-slipshadow, .env-inside, .env-front, .env-txt,
  .fold3, .pan { animation: none !important; }
  .env-slip { transform: none; }                 /* không animation thì thiệp phải nằm đúng khổ thật */
  .fold3 { transform: none !important; animation: none !important; }
  .pan { display: none; }
  .env-inside, .env-front, .env-flapwrap, .env-glow, .env-slipshadow, .env-seal, .seal-ring { display: none; }
  .gate.opening .gate-stage { animation: none !important; opacity: 0; transition: opacity .2s; }
  .ph img, .btn { transition: none; }
}

/* ============ Nới cỡ chữ trên điện thoại ============
   Bản gốc đo từ mẫu ở 13/14px — trên máy thật hơi nhỏ, nên nhích lên ~1-2px
   cho phần chữ đọc (không đụng tới tên script, số đếm ngược và bản desktop). */
@media (max-width: 767px) {
  /* Điện thoại: main phủ hết bề rộng nên nền trắng của body không bao giờ lộ ra — trừ dải
     status bar / vùng kéo quá đỉnh của Safari iOS lấy màu body → trắng bệch (đo trên iPhone).
     Đổi sang màu thiệp, không ảnh hưởng gì khác. */
  body { background: var(--bg); }
  :root {
    --fs-xs:   .8125rem;   /* 12 → 13 */
    --fs-sm:   .875rem;    /* 13 → 14 */
    --fs-base: .9375rem;   /* 14 → 15 */
  }
  body { font-size: var(--fs-base); }
  .note { font-size: 15px; }
  .fam-names { font-size: 15px; }
  .fam-addr { font-size: 13px; }
  .cer-label { font-size: 17px; }
  .cer-venue { font-size: 18px; }
  .cer-addr { font-size: 15px; line-height: 1.5; }
  .cer-lunar { font-size: 13px; }
  .dc-sm { font-size: 13px; }
  .date-year { font-size: 19px; }
  .party-lead { font-size: 17px; }
  .party-host { font-size: 18px; }
  .cd-lb { font-size: 12px; }
  .cal-title { font-size: 14px; }
  .cal-wd { font-size: 11px; }
  .cal-d { font-size: 13px; }
  .cal-d.mark b { font-size: 12px; }
  .story-eyebrow { font-size: 12px; }
  .story-title { font-size: 19px; }
  .story-text { font-size: 15px; }
  .ienv-hint { font-size: 13px; }
  .footer p { font-size: 15px; }
  .cate-tab { font-size: 15px; }
}
@media (max-width: 400px) {
  .cate-tab { font-size: 13px; letter-spacing: .08em; padding-inline: 13px; }
}
