/* =============================================================
   THIỆP CƯỚI ĐIỆN TỬ — style.css
   Đổi màu / bo góc / font ở khối :root bên dưới là đủ.
   ============================================================= */

:root{
  /* Fonts */
  /* Chỉ ba họ font, đều nằm trong assets/fonts/ — không gọi ra Google Fonts.
     Cormorant Garamond và Dancing Script đã bị bỏ; --font-title gộp về
     SVN-BonVoyage, --font-script gộp về SVN-Janelotus. Giữ lại đủ 5 tên biến
     (thay vì rút còn 3) để sau này muốn tách font tiêu đề khỏi font bìa thì
     sửa đúng một dòng, khỏi lần theo hơn 20 chỗ dùng. */
  --font-body:   'Be Vietnam Pro', system-ui, sans-serif;
  --font-title:  'SVN-BonVoyage', Georgia, serif;
  --font-script: 'SVN-Janelotus', cursive;
  --font-accent: 'SVN-Janelotus', cursive;
  --font-cover:  'SVN-BonVoyage', Georgia, serif;

  /* Colors */
  --color-base: #ffffff;
  --color-base-content: #404040;
  --color-primary: #000000;
  --color-primary-content: #ffffff;
  --color-line: rgba(0,0,0,.12);

  /* Radius */
  --radius-box: 18px;
  --radius-button: 8px;

  /* Layout */
  --container-xs: 560px;
  /* Bản mẫu để nội dung mục RSVP rộng đúng 480px; .container-sm còn cộng
     padding-inline 1rem mỗi bên nên đặt 512px để phần chữ ra đúng 480px.
     Biến này chỉ .container-sm đọc, và .container-sm chỉ dùng ở #wish. */
  --container-sm: 512px;
  --container: 1200px;
  --pad: 1.5rem;

  --ease: cubic-bezier(.22,.61,.36,1);
}


/* ---------- FONT CHỮ THÂN BÀI: Be Vietnam Pro, tự host ----------
   Trước đây tải từ Google Fonts dù 18 file .ttf đã nằm sẵn trong assets/fonts/
   mà không được khai báo, nên chẳng file nào được dùng. Giờ nhúng thẳng.

   Chỉ khai 6 dáng thật sự có chỗ dùng, đúng theo các mức font-weight đang có
   trong file này (300 / 400 / 500 / 600 / 700) cộng một dáng nghiêng ở 300:
     300  body mặc định
     400  thẻ <b> kế thừa từ 300 sẽ nhảy lên 400, không phải 700
     500  nút bấm, tên đầy đủ, tiêu đề modal
     600  tên người gửi lời chúc, số tài khoản
     700  giờ trong lịch trình, tên sự kiện, đếm ngược
     300i địa chỉ ở màn bìa, lời chúc, thông báo form, câu quote
   Thiếu dáng nào thì trình duyệt tự bóp méo dáng gần nhất, chữ bị nhoè. */
@font-face{
  font-family:'Be Vietnam Pro';
  src:url('../fonts/BeVietnamPro-Light.ttf') format('truetype');
  font-weight:300;font-style:normal;font-display:swap;
}
@font-face{
  font-family:'Be Vietnam Pro';
  src:url('../fonts/BeVietnamPro-LightItalic.ttf') format('truetype');
  font-weight:300;font-style:italic;font-display:swap;
}
@font-face{
  font-family:'Be Vietnam Pro';
  src:url('../fonts/BeVietnamPro-Regular.ttf') format('truetype');
  font-weight:400;font-style:normal;font-display:swap;
}
@font-face{
  font-family:'Be Vietnam Pro';
  src:url('../fonts/BeVietnamPro-Medium.ttf') format('truetype');
  font-weight:500;font-style:normal;font-display:swap;
}
@font-face{
  font-family:'Be Vietnam Pro';
  src:url('../fonts/BeVietnamPro-SemiBold.ttf') format('truetype');
  font-weight:600;font-style:normal;font-display:swap;
}
@font-face{
  font-family:'Be Vietnam Pro';
  src:url('../fonts/BeVietnamPro-Bold.ttf') format('truetype');
  font-weight:700;font-style:normal;font-display:swap;
}

/* Font tự host cho chữ "The" ở màn hình mở thiệp và mọi chữ nhấn viết tay.
   Chỉ có một dáng Regular, nên đừng đặt font-weight đậm cho phần tử dùng nó:
   trình duyệt sẽ tự bôi đậm giả, nét bị nhoè. */
@font-face{
  font-family:'SVN-Janelotus';
  src:url('../fonts/SVN-Janelotus.otf') format('opentype');
  font-weight:400;
  font-style:normal;
  font-display:swap;
}
/* Font tự host cho mọi chữ lớn: Save / Date, số ngày, tên địa điểm, tiêu đề
   mục, tên riêng. Cũng chỉ có một dáng Regular — xem lưu ý về bôi đậm giả ở
   khối trên. Thiếu file thì lùi về Georgia, trang vẫn đọc được. */
@font-face{
  font-family:'SVN-BonVoyage';
  src:url('../fonts/SVN-BonVoyage-Regular.otf') format('opentype');
  font-weight:400;
  font-style:normal;
  font-display:swap;
}
*,*::before,*::after{box-sizing:border-box;}

/* ---------- KHOÁ MỘT BỘ MÀU DUY NHẤT, KỆ CHẾ ĐỘ TỐI CỦA MÁY ----------
   Toàn bộ màu trong file này đều viết tay nên KHÔNG tự đổi theo chế độ tối
   (không có khối @media (prefers-color-scheme) nào). Nhưng vẫn còn những phần
   do CHÍNH TRÌNH DUYỆT vẽ, không nằm dưới quyền của CSS màu thường:
     - ruột ô nhập, nút tăng/giảm của <input type="number">
     - danh sách xổ xuống của <select>
     - thanh cuộn
     - nền ô nhập khi trình duyệt tự điền (autofill)
     - chế độ "tự động tối" của Chrome trên Android, đảo màu cả trang
   color-scheme báo cho trình duyệt biết trang này CHỈ có bản sáng. Dùng
   "only light" chứ không chỉ "light": từ khoá only là mức chặn mạnh hơn, nói
   luôn rằng đừng tự ý đảo màu trang kể cả khi máy bật chế độ tối cưỡng bức. */
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;color-scheme:only light;}

body{
  margin:0;
  font-family:var(--font-body);
  font-weight:300;
  font-size:15px;
  line-height:1.7;
  color:var(--color-base-content);
  background:var(--color-base);
  overflow-x:hidden;
}
body.is-locked{overflow:hidden;height:100dvh;}

img{display:block;max-width:100%;height:auto;}
h1,h2,h3,p{margin:0;}
button{font:inherit;color:inherit;cursor:pointer;}
a{color:inherit;text-decoration:none;}
[hidden]{display:none !important;}

.font-script{font-family:var(--font-script);}

.container-xs{width:100%;max-width:var(--container-xs);margin-inline:auto;padding-inline:var(--pad);}
.container-sm{width:100%;max-width:var(--container-sm);margin-inline:auto;padding-inline:var(--pad);}

/* Đồng bộ với tiêu đề mục RSVP: mọi tiêu đề mục dùng --font-cover
   (SVN-BonVoyage), giống bản mẫu chỉ có một font tiêu đề duy nhất. */
.section-title{
  font-family:var(--font-cover);
  font-weight:500;
  font-size:clamp(1.5rem,5vw,1.9rem);
  line-height:1.3;
  color:var(--color-base-content);
  text-align:center;
}

.hairline{width:1px;height:2.5rem;margin-inline:auto;background:currentColor;opacity:.6;}

/* Ngăn cách hai phần nội dung: cùng mô-típ đường kẻ dọc với .hairline ở màn
   hình mở thiệp, thêm viên kim cương nhỏ ở giữa. Hai đầu kẻ mờ dần để không
   thành một vạch cứng cắt ngang trang. */
.divider{
  display:flex;flex-direction:column;align-items:center;gap:.55rem;
  padding-block:.5rem;
  color:var(--color-primary);
}
.divider__line{
  width:1px;height:2.25rem;
  background:linear-gradient(to bottom,transparent,currentColor);
  opacity:.45;
}
.divider__line:last-child{background:linear-gradient(to top,transparent,currentColor);}
.divider__gem{
  width:.42rem;height:.42rem;
  background:currentColor;
  transform:rotate(45deg);
  opacity:.6;
}

/* ---------- Nút ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.5rem;
  min-height:2.75rem;padding:0 1.25rem;
  border:1px solid var(--color-primary);
  border-radius:var(--radius-button);
  background:var(--color-primary);color:var(--color-primary-content);
  font-size:.875rem;font-weight:500;
  transition:opacity .32s var(--ease),transform .32s var(--ease);
}
.btn:hover{opacity:.85;}
.btn:active{transform:scale(.98);}
.btn--block{width:100%;}
.btn--ghost{background:transparent;color:var(--color-primary);}
:focus-visible{outline:2px solid currentColor;outline-offset:3px;}

/* =============================================================
   HIỆU ỨNG XUẤT HIỆN KHI CUỘN (thay cho AOS)
   ============================================================= */
/* Chậm thêm một nấc nữa so với 1.35s trước đó (~1.4x). Riêng lớp phủ RSVP
   (.wish__scrim) và số ngày ở thiệp mời (.icd__day, khớp đúng 2s của bản mẫu)
   đã tự ghi đè transition-duration riêng ở dưới, không bị ăn theo giá trị
   này. */
[data-reveal]{opacity:0;transition:opacity 1.9s var(--ease),transform 1.9s var(--ease);will-change:opacity,transform;}
/* fade-in: chỉ mờ dần, KHÔNG dịch chuyển — không cần khai báo transform vì
   [data-reveal] đã đặt opacity:0 sẵn. Dùng cho lớp phủ tối phủ kín section,
   nếu dùng zoom-in thì lớp phủ phóng to thu nhỏ sẽ lộ mép ảnh nền. */
[data-reveal="fade-in"]{transform:none;}
[data-reveal="fade-up"]{transform:translateY(36px);}
[data-reveal="fade-down"]{transform:translateY(-36px);}
[data-reveal="fade-left"]{transform:translateX(36px);}
[data-reveal="fade-right"]{transform:translateX(-36px);}
[data-reveal="zoom-in"]{transform:scale(.85);}
[data-reveal="flip-up"]{transform:perspective(800px) rotateX(60deg);}
[data-reveal="flip-right"]{transform:perspective(800px) rotateY(60deg);}
[data-reveal].is-in{opacity:1;transform:none;}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto;}
  [data-reveal]{opacity:1 !important;transform:none !important;transition:none;}
  /* Hai tên dọc phải giữ transform căn giữa/quay, không reset về none */
  [data-reveal].about__vname--r{transform:translateY(-50%) !important;}
  [data-reveal].about__vname--l{transform:translateY(-50%) rotate(180deg) !important;}
  *{animation-duration:.01ms !important;}
}

/* =============================================================
   1. MÀN HÌNH MỞ THIỆP
   ============================================================= */
.preload{
  position:fixed;inset:0;z-index:9999;
  display:flex;flex-direction:column;justify-content:flex-end;
  overflow:hidden;
  color:var(--color-primary-content);
  transition:opacity 1.6s var(--ease),visibility 1.6s;
}
/* Sau khi mở thiệp: cover thoát khỏi lớp phủ fixed và trở thành phần đầu
   của luồng cuộn, nên cuộn ngược lên vẫn xem lại được */
.preload.is-inflow{
  position:relative;inset:auto;z-index:1;
  min-height:100vh;min-height:100dvh;
  transition:none;
}

.preload__bg{position:absolute;inset:0;background-size:cover;background-position:center 35%;background-color:#2a2a2a;}
.preload__scrim{position:absolute;inset:0;background:linear-gradient(to top,var(--color-primary) 0%,rgba(0,0,0,.35) 45%,transparent 70%);}

/* Màn hình rất cao và hẹp (điện thoại dựng đứng): ảnh 2:3 mà dùng cover thì
   bị cắt mất 31% chiều ngang. Đổi sang contain để thấy trọn ảnh, phần trống
   dưới đáy được lớp phủ đen đặc che nên không lộ đường cắt. */
@media (max-aspect-ratio: 3/5){
  .preload__bg{
    background-size:contain;
    background-position:top center;
    background-repeat:no-repeat;
    background-color:var(--color-primary);
  }
  .preload__scrim{
    background:linear-gradient(to top,var(--color-primary) 0%,var(--color-primary) 32%,rgba(0,0,0,.45) 55%,transparent 80%);
  }
}

.preload__inner{position:relative;padding-bottom:5.5rem;}
.preload__content{display:flex;flex-direction:column;gap:.75rem;text-align:center;}

.save-the-date{font-family:var(--font-cover);line-height:.8;}
/* 4.5rem = text-7xl của template gốc, khớp với tỉ lệ đo trên ảnh mẫu:
   cao chữ hoa "Save" / cao số ngày = 0,88. */
.std__l1,.std__l2{font-size:clamp(3.25rem,17vw,4.5rem);}
/* Chỉ riêng chữ "The" dùng --font-accent (SVN-Janelotus). Đồng hồ đếm ngược
   (.cd__cell b) dùng --font-cover, không bị ảnh hưởng bởi dòng này. */
.std__l2 .font-script{
  font-family:var(--font-accent);
  /* Khớp ảnh mẫu: chữ "The" cỡ 1.05em, chân chữ ngang chân chữ "Date" (không
     dịch dọc) nên nét móc chữ T cắt qua đáy chữ "Save" — đúng như bản mẫu.
     line-height:0 là bản CSS thuần của class leading-0 mà template dùng. */
  font-size:1.05em;
  line-height:0;
  position:relative;      /* bắt buộc, không có dòng này thì top/left vô tác dụng */
  bottom: 0;                  /* + xuống dưới, − lên trên */
  right:0.05em;                 /* + sang phải, − sang trái */
}

.preload__names{
  display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:.75rem;
  font-family:var(--font-cover);text-transform:uppercase;letter-spacing:.12em;
  /* Rộng cần thiết của dòng này = 18,44 x cỡ chữ (số đo thực). Chỗ khả dụng
     là 100vw - 2rem, chia cho 19,5 để chừa ~5% dư -> luôn nằm 1 dòng: máy
     >=422px được đủ 20px, 390px -> 18,4px, 375px -> 17,6px, 320px -> 14,8px.
     Đổi tên trong config sang tên dài hơn thì phải tính lại số 19,5. */
  font-size:clamp(14px,calc((100vw - 2rem) / 19.5),20px);
  /* Khoảng cách quanh dòng tên: .preload__content đã có gap .75rem, thêm
     margin-block .75rem nữa cho dòng này thoáng hơn hai bên trên/dưới. */
  margin-block:.75rem;
}
/* Ở màn hẹp, cỡ 20px không đủ chỗ cho cả hai tên trên một dòng. Cho phép
   xuống dòng ở khoảng trắng GIỮA các tên (flex-wrap) và cấm ngắt bên trong
   từng tên (nowrap), kẻo thành "ANH / PHƯƠNG". */
.preload__names p{white-space:nowrap;}

.preload__date{display:flex;align-items:center;justify-content:space-evenly;text-align:center;}
.pd__side{flex-basis:33.33%;border-top:1px solid currentColor;border-bottom:1px solid currentColor;padding-block:.15rem;font-size:.9rem;}
.pd__side--l{text-align:right;}
.pd__side--r{text-align:left;}
.pd__day{flex-basis:33.33%;font-family:var(--font-cover);font-size:3.75rem;line-height:1;}

.pv__name{font-family:var(--font-cover);font-size:20px;}
/* Ở 16px, địa chỉ phải xuống dòng trên máy hẹp. pretty giữ nguyên tên riêng
   ("Cổ Đô" không bị cắt đôi) — balance thì chia đều hai dòng nhưng cắt ngang
   tên xã, nhìn tệ hơn là để "Hà Nội" xuống dòng. */
.pv__addr{font-style:italic;font-size:16px;opacity:.9;text-wrap:pretty;}
/* ---------- BÌA TRÊN MÀN HÌNH THẤP ----------
   Khối chữ trên bìa cao ~470px và trước đây không phản ứng gì với chiều cao
   màn hình, nên trên máy ngắn nó đè lên mặt hai người (và ở 320x454 thì chữ
   "Save" bị cắt mất hẳn). Hai bậc dưới đây nén dần khối chữ lại.
   Dùng svh chứ không dùng vh: trên Safari vh tính theo lúc đã ẩn thanh địa
   chỉ, nên vh vẫn tràn ở lần mở đầu. Trình duyệt chưa hiểu svh thì bỏ qua
   dòng font-size và vẫn được phần nén khoảng cách.
   padding-bottom phải >= 4.5rem: nút mũi tên cao 3rem, cách đáy 1.25rem,
   thấp hơn là nó đè lên chữ.
   Thứ tự hai khối không được đổi: khối 620px phải nằm sau để thắng khi máy
   vừa thấp lại vừa rất thấp. */

/* Bậc 1 — máy vừa thấp (iPhone 12-15, vùng hiển thị ~664px): nén khoảng cách
   và hạ trần cỡ chữ, nhưng GIỮ tên địa điểm. */
@media (max-height: 720px){
  .std__l1,.std__l2{font-size:min(clamp(3.25rem,17vw,4.5rem),9svh);}
  .pd__day{font-size:min(3.75rem,7.5svh);}
  .preload__content{gap:.5rem;}
  .preload__content .hairline{height:2rem;}
  .preload__names{margin-block:.4rem;}
  .preload__inner{padding-bottom:4.5rem;}
}

/* Bậc 2 — máy rất thấp (iPhone SE/8, hoặc điện thoại nằm ngang): nén nữa vẫn
   không đủ chỗ, phải bỏ tên địa điểm và đường kẻ dọc. Thông tin này có lại
   đầy đủ ở phần thiệp mời bên dưới nên không mất gì. */
@media (max-height: 620px){
  .preload__content .hairline,
  .preload__venue{display:none;}
  .preload__names{margin-block:.25rem;}
}


.preload__cta{position:absolute;left:50%;bottom:1.25rem;transform:translateX(-50%);z-index:2;}
.btn-open{
  display:grid;place-items:center;width:3rem;height:3rem;
  border-radius:999px;border:1px solid rgba(255,255,255,.6);
  background:rgba(0,0,0,.55);color:#fff;backdrop-filter:blur(4px);
  animation:bounce 3s infinite;
}
@keyframes bounce{0%,100%{transform:translateY(0);}50%{transform:translateY(-9px);}}

/* =============================================================
   2. ABOUT
   ============================================================= */
#about{padding-block:2.5rem 3rem;}
#about .section-title{margin-bottom:1.5rem;}

.about__media{position:relative;display:grid;gap:0;}
.about__card{position:relative;margin:0;}
.about__card--groom{margin-top:-3.5rem;display:flex;justify-content:flex-end;}

.frame{
  position:relative;width:85.7%;aspect-ratio:4/5;overflow:hidden;
  border-radius:var(--radius-box);box-shadow:0 6px 20px rgba(0,0,0,.14);
}
.frame img{width:100%;height:100%;object-fit:cover;}
.frame__tag{
  position:absolute;font-family:var(--font-title);font-size:1.4rem;color:#fff;
  text-shadow:0 1px 8px rgba(0,0,0,.45);
}
.frame__tag--tr{top:.9rem;right:1rem;}
.frame__tag--bl{bottom:.9rem;left:1rem;}

.about__vname{
  position:absolute;top:50%;
  writing-mode:vertical-rl;
  font-family:var(--font-title);font-size:1.75rem;white-space:nowrap;
  color:var(--color-base-content);
}
.about__vname--r{right:.25rem;}
.about__vname--l{left:.25rem;}
/* Hai tên dọc dùng transform để tự căn giữa (chú rể còn quay 180deg), nên
   [data-reveal].is-in{transform:none} sẽ xoá luôn phần căn giữa/quay — tên
   chú rể không lật được. Khai báo riêng trạng thái đầu/cuối cho từng bên:
   giữ transform gốc, chỉ thêm phần lật. rotateY ngược dấu ở bên chú rể để
   sau khi quay 180deg thì hướng lật trên màn hình giống cô dâu. */
[data-reveal].about__vname--r{transform:translateY(-50%) perspective(800px) rotateY(60deg);}
[data-reveal].about__vname--l{transform:translateY(-50%) rotate(180deg) perspective(800px) rotateY(-60deg);}
[data-reveal].about__vname--r.is-in{transform:translateY(-50%);}
[data-reveal].about__vname--l.is-in{transform:translateY(-50%) rotate(180deg);}

.about__desc{margin-top:1.75rem;display:grid;gap:1.5rem;}
.about__col{width:85.7%;text-align:justify;font-size:.9rem;}
.about__col--groom{margin-left:auto;}
/* Tên đầy đủ đứng đầu mỗi cột, thay chỗ của social pill đã gỡ */
.about__name{
  font-family:var(--font-title);font-size:1.35rem;font-weight:500;
  line-height:1.3;color:var(--color-primary);
  padding-bottom:.5rem;margin-bottom:.75rem;
  border-bottom:1px solid var(--color-line);
  text-align:left;
}
.about__col--groom .about__name{text-align:right;}
.about__social{margin-bottom:.5rem;}
.about__social--right{text-align:right;}
.social-pill{
  display:inline-flex;align-items:center;gap:.4rem;
  padding:.4rem .9rem;border:1px solid var(--color-primary);
  border-radius:var(--radius-button);font-size:.8rem;
}

/* Câu quote chung của hai người, thay cho hai đoạn bio riêng.

   max-width 44rem chỉ là chốt chặn phòng xa: .container-xs bọc ngoài đã ép
   xuống 512px (560 trừ padding), đo ra 52 ký tự mỗi dòng trên desktop — nằm
   trong ngưỡng dễ đọc nên không cần phá khung ra rộng hơn.

   Canh TRÁI chứ không canh giữa: canh giữa hợp với câu ngắn vài dòng, còn
   đoạn dài canh giữa thì hai mép đều lởm chởm, đọc mệt. Khung + hai dấu
   ngoặc kép đã đủ báo cho người đọc biết đây là câu trích. */
.about__quote{
  position:relative;
  max-width:44rem;
  margin:clamp(2.25rem,6vw,3.25rem) auto 0;
  padding:clamp(2.25rem,7vw,3rem) clamp(1.5rem,5vw,3.25rem);
  border:1px solid var(--color-line);
  border-radius:var(--radius-box);
  /* Nền chìm rất nhạt, đậm ở trên nhạt dần xuống, để khung nổi khỏi nền trắng
     mà không thành một cái hộp xám đóng khung cứng nhắc. */
  background:linear-gradient(180deg,rgba(0,0,0,.028),rgba(0,0,0,0) 65%);
  /* Dùng font THÂN BÀI chứ không phải --font-title như các tiêu đề khác:
     --font-title giờ là SVN-BonVoyage, một font chữ trang trí chỉ hợp với vài
     từ. Đổ 414 ký tự vào đó thì không ai đọc nổi. */
  font-family:var(--font-body);
  /* Co giãn theo bề ngang màn hình, TRẦN đúng 1rem (=16px) trên desktop.
     Bản cũ clamp(1.02rem,.92rem + .5vw,1.2rem) chạy từ ~16.3px lên tới
     19.2px — to hơn hẳn cỡ chữ thân bài, đoạn 414 ký tự này nhìn nặng nề.

     Ba mốc của clamp dưới đây:
       .9rem       sàn  = 14.4px, áp dụng từ khoảng 356px đổ xuống
       .8rem+.45vw phần co giãn ở giữa
       1rem        trần = 16px, đạt từ khoảng 711px trở lên (tablet, desktop)

     Dùng rem chứ không dùng px để cỡ chữ còn nở theo thiết lập cỡ chữ mặc
     định của trình duyệt — khách để chữ to cho dễ đọc thì đoạn này to theo. */
  font-size:clamp(.9rem,.8rem + .45vw,1rem);
  font-style:italic;
  line-height:1.95;
  text-align:left;
  text-wrap:pretty;
  color:var(--color-base-content);
}
.about__quote p{margin:0;}

/* Hai dấu ngoặc kép cỡ lớn nằm chéo nhau ở hai góc. Mờ 14% để làm nền cho chữ
   chứ không tranh chỗ đọc. pointer-events:none kẻo chúng nuốt cú bôi đen chữ. */
.about__quote::before,
.about__quote::after{
  position:absolute;
  font-family:var(--font-title);
  font-style:normal;
  font-size:clamp(3.25rem,9vw,4.75rem);
  line-height:1;
  color:var(--color-primary);
  opacity:.14;
  pointer-events:none;
  user-select:none;
}
/* Glyph ngoặc kép nằm lệch hẳn lên đỉnh ô em, nên phải kéo xuống bằng translate
   chứ căn theo top/bottom thôi sẽ thấy nó lửng lơ. */
.about__quote::before{
  content:"\201C";
  top:0;left:clamp(.5rem,2.5vw,1.25rem);
  transform:translateY(.35em);
}
.about__quote::after{
  content:"\201D";
  bottom:0;right:clamp(.5rem,2.5vw,1.25rem);
  transform:translateY(-.15em);
}

/* =============================================================
   3. ALBUM
   ============================================================= */
#album{padding:2.5rem 1rem 3rem;}
.album__head{max-width:600px;margin:0 auto 1.75rem;text-align:center;}
.album__head p{margin-top:.6rem;font-size:.9rem;}

/* CSS multi-column cân bằng chiều cao trước rồi mới đổ ảnh lần lượt, nên cột
   cuối sẽ RỖNG nếu ceil(số_ảnh / số_cột) * (số_cột - 1) >= số_ảnh.
   Đang dùng 8 ảnh, an toàn ở cả ba mốc:
     2 cột -> ceil(8/2)=4, 4*1=4 < 8  -> 4+4
     3 cột -> ceil(8/3)=3, 3*2=6 < 8  -> 3+3+2
     4 cột -> ceil(8/4)=2, 2*3=6 < 8  -> 2+2+2+2
   Đổi số ảnh thì kiểm lại công thức trên, nếu không cột cuối sẽ trống trơn
   (9 ảnh với 4 cột từng chừa 350px trống bên phải). */
.album__grid{columns:2;column-gap:.5rem;}
@media (min-width:768px){.album__grid{columns:3;}}
@media (min-width:1024px){.album__grid{columns:4;}}

.album__item{
  display:block;width:100%;margin:0 0 .5rem;padding:0;border:0;background:none;
  border-radius:var(--radius-box);overflow:hidden;break-inside:avoid;
}
/* Khai riêng transition-property/duration bằng longhand thay vì shorthand
   "transition:...": trước đây viết "transition:transform .5s,filter .5s"
   ngay trên nền tảng .album__item — cùng độ đặc thù (0,1,0) với quy tắc
   [data-reveal] chung nhưng đứng SAU trong file nên thắng, mà shorthand
   thắng thì THAY THẾ TOÀN BỘ danh sách chứ không cộng dồn: opacity biến mất
   khỏi danh sách transition (ảnh hiện ra tức thì, không mờ dần) và transform
   chạy theo .5s thay vì theo tốc độ hiệu ứng cuộn chung — hiệu ứng "nhảy vào"
   của album vì vậy nhanh và cộc hơn hẳn phần còn lại của trang, cũng chính là
   lý do trông "chưa đủ chậm". Khai đủ ba thuộc tính theo đúng thứ tự cùng
   một chỗ thì opacity/transform dùng tốc độ RIÊNG cho mục này (chậm hơn cả
   mức chung 1.9s của toàn trang), còn filter (chỉ dùng lúc rê chuột) vẫn
   nhanh .5s như cũ. */
.album__item[data-reveal]{
  transition-property:opacity,transform,filter;
  transition-duration:2.2s,2.2s,.5s;
  transition-timing-function:var(--ease),var(--ease),var(--ease);
}
.album__item img{width:100%;height:auto;}
.album__item:hover{transform:translateY(-3px);filter:brightness(1.05);}

/* =============================================================
   4. INVITATION (đếm ngược + thiệp + lịch trình)
   ============================================================= */
.inv__grid{display:grid;}
@media (min-width:1024px){.inv__grid{grid-template-columns:1fr 1fr;align-items:start;}}

/* --- Đếm ngược --- */
.countdown{
  position:relative;isolation:isolate;overflow:hidden;
  min-height:70dvh;
  color:#fff;
  /* .countdown__inner định vị tuyệt đối theo bốn cạnh (xem dưới) thay vì
     padding trực tiếp ở đây, để chốt chiều cao của nó dứt khoát bằng đúng
     khoảng cách top/bottom — không còn tính qua padding + flex-stretch nữa. */
}
.countdown__inner{
  position:absolute;inset:2rem 1rem;
  width:auto;text-align:center;
}
@media (min-width:1024px){
  .inv__left{position:sticky;top:0;}
  .countdown{height:100dvh;min-height:0;}
  .countdown__inner{inset:2.5rem 2.5rem;}
}
.countdown__bg{position:absolute;inset:0;z-index:-2;}
.countdown__bg img{width:100%;height:100%;object-fit:cover;}
.countdown__scrim{position:absolute;inset:0;z-index:-1;background:rgba(0,0,0,.3);}

/* Ghim thẳng vào đáy .countdown__inner bằng định vị tuyệt đối, KHÔNG dùng
   flex + justify-content:space-between nữa. Lý do: .countdown__des là văn
   bản tự xuống dòng theo bề ngang — chiều cao của nó phụ thuộc bề ngang được
   cấp. Đo thực tế phát hiện .countdown__inner (flex-column, space-between)
   có scrollHeight cao hơn clientHeight đúng 36px, tức trình duyệt tính toán
   khoảng trống cần chia dựa trên một lượt đo bề ngang/chiều cao TRUNG GIAN
   khác với lượt vẽ cuối cùng — sai lệch chỉ lộ ra ở màn hình hẹp/thấp, nơi
   đoạn văn xuống nhiều dòng. Định vị tuyệt đối bỏ qua hẳn bước "chia khoảng
   trống" đó: .cd luôn có toạ độ đáy tuyệt đối, .countdown__des ở dòng chảy
   bình thường ngay phía trên, hai bên không còn phụ thuộc lẫn nhau. */
.cd{
  position:absolute;left:0;right:0;bottom:0;
  display:grid;grid-template-columns:repeat(4,1fr);gap:.5rem;
}
@media (min-width:768px){.cd{gap:1.25rem;}}
.cd__cell{
  padding:.9rem .25rem;border-radius:.5rem;
  background:rgba(0,0,0,.25);backdrop-filter:blur(8px);
  display:grid;gap:.15rem;
}
/* Số đếm ngược chuyển sang --font-cover (Bon Voyage) cho khớp với số ngày lớn
   ở thiệp mời và ở màn bìa. Bỏ font-weight:700 vì font này chỉ có Regular —
   để 700 thì trình duyệt bôi đậm giả, số bị nhoè dính nét. */
.cd__cell b{font-family:var(--font-cover);font-size:2.1rem;line-height:1.1;font-weight:400;}
.cd__cell span{font-size:.75rem;opacity:.9;}
/* Khớp bản mẫu: font-family --font-title (bên mẫu là slot font đã thay bằng
   SVN-BonVoyage), line-height --leading-normal = 1.5, margin-bottom .5rem.
   Bản mẫu KHÔNG đặt font-size cho phần tử này nên nó kế thừa 1rem = 16px;
   bên mình đang 1.05rem (16.8px) -> hạ về 1rem, vừa khớp mẫu vừa nhỏ đi.
   color #fff và text-align center đã kế thừa sẵn từ .countdown /
   .countdown__inner nên không cần khai báo lại.
   max-width 480px là của mình, giữ để dòng chữ không quá dài trên desktop. */
.countdown__des{
  font-family:var(--font-cover);
  font-size:1rem;
  line-height:1.5;
  /* Nới rộng hai bên: 480px cũ chỉ chiếm hơn nửa cột trên desktop, chữ dồn
     vào giữa co lại thành khối hẹp. 640px vẫn tự động co theo màn hình hẹp
     (mobile luôn hẹp hơn 640 nên không đổi gì ở đó), chỉ thật sự nới ra ở màn
     hình từ máy tính bảng trở lên. */
  max-width:640px;
  margin-inline:auto;
  /* .cd giờ định vị tuyệt đối (xem dưới), không còn phụ thuộc lẫn nhau qua
     flex nữa — margin-bottom chỉ còn tác dụng chừa khoảng cách với .cd trên
     màn hình thấp/nội dung dài, tránh hai khối nhìn dính sát nhau. */
  margin-bottom:1.5rem;
}
/* Hiện từng chữ chạy chậm: main.js tách chuỗi trong data-text thành từng
   TỪ (không phải từng ký tự Latin đơn lẻ — tiếng Việt có dấu, cắt theo ký tự
   dễ đứt giữa một cụm dấu tổ hợp; cắt theo từ vừa an toàn vừa đúng cảm giác
   "đánh máy" mà không vỡ chữ) và bọc mỗi từ trong một span. Mỗi span tự chạy
   opacity 0->1 kèm dịch nhẹ, span sau trễ hơn span trước một khoảng cố định
   (đặt bằng JS qua transition-delay), tạo hiệu ứng chữ chạy ra lần lượt.
   display:inline-block để mỗi từ không bị tách rời qua translateY. */
.countdown__des .tu{
  display:inline-block;
  opacity:0;transform:translateY(.5em);
  transition:opacity 1.1s var(--ease),transform 1.1s var(--ease);
}
.countdown__des.is-in .tu{opacity:1;transform:none;}
/* [data-reveal] gốc đặt opacity:0 cho MỌI phần tử có thuộc tính này, kể cả
   biến thể "words". Nhưng ở đây bản thân đoạn <p> phải LUÔN hiện — chỉ các
   .tu con bên trong mới ẩn/hiện — nên đè lại riêng cho biến thể này. Đứng sau
   quy tắc gốc trong file nên thắng dù cùng độ đặc thù (0,1,0). */
[data-reveal="words"]{opacity:1;transition:none;}

/* --- Thiệp mời --- */
.inv__right{padding:2.5rem 1rem;text-align:center;}
.invite-card{
  position:relative;isolation:isolate;overflow:hidden;
  margin-top:1.5rem;padding:2.5rem 1.25rem 1.5rem;
  border-left:1px solid var(--color-primary);
  border-top:1px solid var(--color-primary);
  border-top-left-radius:120px;
  background:var(--color-primary-content);
  box-shadow:0 10px 30px rgba(0,0,0,.12);
}
@media (min-width:768px){.invite-card{padding:2.5rem 1.5rem;}}
.invite-card__bg{
  position:absolute;inset:0;z-index:-1;opacity:.3;
  background-size:cover;background-position:center 40%;
  border-top-left-radius:120px;
}
.invite-card__title{font-family:var(--font-title);font-size:2.1rem;}
.invite-card__time{margin-top:1rem;font-size:1.4rem;font-weight:700;color:var(--color-primary);}

.invite-card__date{display:flex;justify-content:center;align-items:center;margin-top:1.25rem;color:var(--color-primary);}
/* Khớp bản mẫu: phần tử này bên mẫu là font-size text-8xl (6rem), line-height 1
   và font-family --font-title — mà --font-title bên mẫu chính là slot font đã
   thay bằng SVN-BonVoyage ở bìa, nên ở đây dùng --font-cover.
   Bản mẫu còn cho riêng phần tử này transition 2s ease-in-out (mặc định của
   trang là 1.35s var(--ease)); ghi đè tại chỗ để không đụng hiệu ứng cuộn của
   các phần khác. Hai dòng longhand phải đứng SAU shorthand của [data-reveal],
   file này đã đúng thứ tự đó. */
.icd__day{
  font-family:var(--font-cover);
  font-size:6rem;
  line-height:1;
  transition-duration:2s;
  transition-timing-function:ease-in-out;
}
/* Đường kẻ dọc bám theo cỡ số ngày, đổi 5rem -> 6rem cho khỏi hụt */
.icd__rule{width:1px;height:6rem;margin-inline:1rem;background:currentColor;}
.icd__meta{text-align:left;line-height:1.5;}
.icd__wd{font-weight:700;font-size:1.05rem;}

.invite-card__loc{margin-top:2rem;color:var(--color-primary);}
.loc-icon{margin:0 auto .75rem;color:var(--color-primary);}
.ivl__name{font-family:var(--font-title);font-size:1.4rem;}
.ivl__addr{font-size:.9rem;margin-bottom:1.25rem;}
/* Hai nút bản đồ nằm cạnh nhau, tự xuống hàng khi hết chỗ.
   flex:0 0 auto — KHÔNG kéo giãn, mỗi nút chỉ rộng vừa đúng phần chữ cộng
   chút đệm hai bên. Cũng vì vậy mà nút "Nhà trai" nhỉnh hơn "Nhà gái" vài
   pixel (chữ dài hơn một nét) — đó là hệ quả tất yếu của việc ôm sát chữ,
   muốn hai nút bằng chằn chặn thì phải quay lại kiểu kéo giãn chia đều.
   Nút ở đây cố tình nhỏ hơn nút chung của trang: thấp hơn (2.25rem so với
   2.75rem), đệm hẹp hơn, chữ và icon nhỏ hơn một nấc. */
.ivl__maps{display:flex;flex-wrap:wrap;justify-content:center;gap:.5rem;}
.ivl__maps .btn{
  flex:0 0 auto;
  min-height:2.25rem;
  padding:0 .85rem;
  gap:.35rem;
  font-size:.8rem;
}
.ivl__maps .btn svg{width:14px;height:14px;}

/* --- Lịch trình --- */
.event{margin-top:3.5rem;}
.event__list{position:relative;display:grid;gap:2rem;margin-top:2rem;}
.event__list::before{
  content:"";position:absolute;top:0;bottom:0;left:20%;margin-left:.4rem;
  width:2px;background:var(--color-base-content);opacity:.25;
}
.event-item{display:flex;gap:1.25rem;position:relative;}
.event-item__time{flex:0 0 20%;font-weight:700;font-size:1.05rem;color:var(--color-primary);text-align:center;}
.event-item__body{flex:1 1 80%;text-align:left;padding-left:.75rem;}
.event-item__title{font-size:1.05rem;font-weight:700;margin-bottom:.2rem;}
.event-item__desc{font-size:.875rem;}

/* Tiêu đề ngày trong lịch trình. Kéo tràn qua vạch dọc của .event__list
   để vạch không xuyên qua chữ, và nới khoảng cách trước mỗi ngày mới. */
.event-day{
  position:relative;z-index:1;
  margin:1.5rem 0 -.5rem;padding:.35rem 0;
  text-align:center;
  background:var(--color-base);
}
.event-day:first-child{margin-top:0;}
.event-day__date{
  font-family:var(--font-title);font-size:1.5rem;letter-spacing:.04em;
  color:var(--color-primary);
}
.event-day__note{font-size:.8rem;font-style:italic;opacity:.75;margin-top:.1rem;}

/* =============================================================
   5. WISH / RSVP
   ============================================================= */
/* Bản mẫu dùng py-40 = 10rem cho cả hai đầu. Trên điện thoại 10rem trên +
   10rem dưới là 320px trống, lệch hẳn nhịp với các mục khác (2.5-3rem), nên
   giữ 5.5rem ở mobile và chỉ áp 10rem từ 1024px như bố cục desktop của mẫu. */
/* ┌────────────────────────────────────────────────────────────────────┐
   │  ĐỘ DÀI MẢNG PHỦ MỜ Ở MỤC RSVP — SỬA HAI SỐ --wish-pad DƯỚI ĐÂY    │
   │      số càng lớn  ->  mảng tối càng dài, thấy nhiều ảnh nền hơn    │
   └────────────────────────────────────────────────────────────────────┘
   Cả .wish__bg (ảnh nền) lẫn .wish__scrim (lớp phủ tối) đều phủ inset:0,
   nghĩa là luôn đúng bằng khung #wish — không có kích thước riêng để chỉnh.
   Nên muốn lớp phủ dài thêm thì phải nới chính khung này ra, và đệm trên/dưới
   (padding-block) là chỗ điều khiển. Nội dung form vẫn nằm giữa, phần nới
   thêm biến thành khoảng ảnh-nền-phủ-tối ở trên và dưới form.

   KHÔNG nới bằng cách cho .wish__scrim tràn ra ngoài khung (inset âm): #wish
   có isolation:isolate và mục #thankyou ngay dưới cũng tạo lớp chồng riêng,
   nên phần tràn ra sẽ bị mục dưới che mất, không hiện được. */
#wish{
  position:relative;isolation:isolate;color:#fff;
  --wish-pad:8rem;
  padding-block:var(--wish-pad);
}
@media (min-width:1024px){#wish{--wish-pad:14rem;}}
.wish__bg{position:absolute;inset:0;z-index:-2;background-size:cover;background-position:center 20%;background-color:#222;}
/* Lớp phủ mờ dần: rút riêng thời lượng xuống .4s (mặc định của thư viện AOS
   mà bản mẫu dùng) thay vì 1.35s dùng chung của trang. Để 1.35s thì có gần
   một giây rưỡi chữ trắng nằm trên ảnh nền sáng, viền ô nhập chìm hẳn. */
.wish__scrim{position:absolute;inset:0;z-index:-1;background:rgba(0,0,0,.7);}
.wish__scrim[data-reveal]{transition-duration:.4s;}
/* Khớp mẫu: font-title (slot Bon Voyage), text-3xl 1.875rem / line-height
   calc(2.25/1.875)=1.2; từ lg (1024px) lên text-4xl 2.25rem / calc(2.5/2.25).
   Mẫu không đặt font-weight nên là 400, không phải 500. */
.wish__title{
  font-family:var(--font-cover);
  font-weight:400;
  font-size:1.875rem;
  line-height:1.2;
  text-align:center;
}
@media (min-width:1024px){.wish__title{font-size:2.25rem;line-height:1.111;}}

/* Mẫu: grid gap-6 = 1.5rem, form cách tiêu đề mt-6 = 1.5rem */
.form{display:grid;gap:1.5rem;margin-top:1.5rem;}
.field{display:grid;gap:.4rem;}
.field label{font-size:.875rem;}
.field input,.field select,.field textarea{
  width:100%;padding:.75rem 1rem;
  font:inherit;font-size:.95rem;color:#fff;
  background:rgba(0,0,0,.4);
  border:1px solid rgba(255,255,255,.25);
  border-radius:var(--radius-button);
  appearance:none;
}
.field select{
  padding-right:2.5rem;
  background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-position:calc(100% - 20px) calc(50% + 1px),calc(100% - 16px) calc(50% + 1px);
  background-size:4px 4px,4px 4px;
  background-repeat:no-repeat;
}
.field select option{color:#111;background:#fff;}
.field textarea{resize:vertical;min-height:6rem;}

/* --- Ba chỗ trình duyệt vẫn tự quyết màu, phải chặn riêng --- */

/* 1. Chữ gợi ý trong ô ("Nhập số"). Không khai màu thì trình duyệt lấy màu
      mặc định của nó — sáng/tối khác nhau, mà nền ô ở đây luôn tối nên bản
      màu tối sẽ chìm nghỉm. */
.field input::placeholder,
.field textarea::placeholder{color:rgba(255,255,255,.55);opacity:1;}

/* 2. Ô được trình duyệt TỰ ĐIỀN (autofill). Chrome/Safari vẽ đè một nền
      riêng (xanh nhạt ở chế độ sáng, xanh đen ở chế độ tối) và bỏ qua thuộc
      tính background thông thường. Cách duy nhất đè lại được là dùng
      box-shadow inset dày phủ kín ruột ô, kèm -webkit-text-fill-color cho
      phần chữ. transition-delay dài để nền autofill không kịp nháy lên. */
.field input:-webkit-autofill,
.field input:-webkit-autofill:hover,
.field input:-webkit-autofill:focus,
.field textarea:-webkit-autofill{
  -webkit-text-fill-color:#fff;
  -webkit-box-shadow:inset 0 0 0 1000px rgba(0,0,0,.4);
  caret-color:#fff;
  transition:background-color 100000s ease 0s;
}

/* 3. Nút tăng/giảm của <input type="number">. appearance:none phía trên đã
      bỏ được ở Chrome/Safari, Firefox cần thêm khai báo riêng — để nguyên thì
      Firefox vẫn vẽ cặp mũi tên theo màu hệ thống. */
.field input[type="number"]{-moz-appearance:textfield;}
.field input[type="number"]::-webkit-outer-spin-button,
.field input[type="number"]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0;}
.field input:focus,.field select:focus,.field textarea:focus{outline:2px solid rgba(255,255,255,.6);outline-offset:1px;}
.field.is-error input{border-color:#ff8b8b;}
/* Chọn "không tham dự" thì ô số người khoá ở 0 chứ không biến mất: ô mất chỗ
   là mục thấp đi, kéo theo ảnh nền phủ inset:0 bị cắt lại khác đi. Làm mờ cả
   nhãn lẫn ô để thấy rõ là đang khoá chủ đích, không phải hỏng. */
.field.is-locked label{opacity:.5;}
.field select:disabled{opacity:.5;cursor:not-allowed;}
/* Ô chọn và ô tự điền xếp cùng một hàng: hiện/ẩn ô tự điền không đổi chiều cao
   hàng, nên mục giữ nguyên độ cao và ảnh nền không bị cắt lại. */
.field__row{display:flex;gap:.5rem;}
.field__row select{flex:1 1 auto;min-width:0;}
.field__row input{flex:0 0 38%;min-width:0;}
.field.is-error input{border-color:#ff8b8b;}

/* Mẫu: p-4 = 1rem, bg-black/10, backdrop-blur-md = 12px, rounded-box = 18px */
.form__msg{
  padding:1rem;border-radius:var(--radius-box);text-align:center;font-style:italic;
  background:rgba(0,0,0,.1);backdrop-filter:blur(12px);
}
.form__msg.is-ok{color:#22c55e;}   /* text-success cua mau */
.form__msg.is-err{color:#ffb0b0;}

.form .btn{background:#fff;color:#111;border-color:#fff;}

/* Mẫu: mt-10 = 2.5rem, gap-y-6 = 1.5rem, max-h-[600px] */
/* Cao CỐ ĐỊNH chứ không phải max-height: có 1 hay 50 lời chúc thì khối này vẫn
   đúng chừng đó, mục không dài ra nên ảnh nền phủ inset:0 khỏi bị cắt lại.
   align-content:start để vài lời chúc đầu tiên không bị kéo giãn cho đầy khung. */
.wish-list{
  margin-top:2.5rem;display:grid;gap:1.5rem;align-content:start;
  height:20rem;overflow-y:auto;padding-right:.5rem;
  scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.3) transparent;
}
.wish-list__empty{opacity:.65;font-style:italic;text-align:center;padding-block:2rem;}
.wish-item{padding:1rem;border-radius:var(--radius-box);background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.14);}
.wish-item__name{font-weight:600;}
/* Quy tắc .wish-item__meta (dòng "Sẽ tham dự · N người") đã bỏ: main.js không
   còn dựng phần tử đó nữa, chỉ hiện tên và lời chúc. */
/* Cắt còn 6 dòng: đo dữ liệu thật thấy một lời chúc dán đi dán lại cao tới
   649px, gấp đôi cả khung xem trước, nuốt trọn lời chúc của mọi người khác.
   Mở ra thì trả display về block, bỏ hẳn cơ chế cắt dòng. */
.wish-item__msg{
  margin-top:.35rem;font-size:.9rem;font-style:italic;
  display:-webkit-box;-webkit-box-orient:vertical;
  -webkit-line-clamp:6;line-clamp:6;overflow:hidden;
}
.wish-item.is-open .wish-item__msg{display:block;}
.wish-item__more{
  margin-top:.4rem;padding:0;border:0;background:none;
  color:inherit;font-size:.75rem;opacity:.75;text-decoration:underline;
}

/* =============================================================
   6. THANK YOU
   ============================================================= */
/* min-height dùng svh chứ không phải dvh — đây chính là chỗ gây ra hiện
   tượng "giật zoom" khi vừa bắt đầu cuộn tới mục này. dvh đổi giá trị MỖI
   LẦN trình duyệt di động ẩn/hiện thanh địa chỉ (chính là lúc đang cuộn),
   khiến khung #thankyou đổi chiều cao ngay giữa lúc cuộn, mà .thanks__bg lại
   background-size:cover theo đúng khung đó — khung đổi cao là ảnh phải tính
   lại tỉ lệ phóng để phủ kín, nhìn như ảnh phóng to/thu nhỏ đột ngột đúng lúc
   "Lời cảm ơn" đang hiện ra. svh là chiều cao ỨNG VỚI LÚC THANH ĐỊA CHỈ CÒN
   HIỆN ĐỦ (nhỏ nhất, không đổi trong lúc cuộn) nên khung và ảnh đứng yên
   suốt — đúng bằng kích thước ảnh sau khi đã "ổn định" mà trước đó mắt nhìn
   thấy lúc cuộn xong. Cái giá: nếu về sau thanh địa chỉ ẩn hẳn, phần dưới
   khung có thể hụt vài chục pixel so với mép màn hình thật — không đáng kể
   vì đây là section cuối trang. */
#thankyou{position:relative;isolation:isolate;min-height:100vh;min-height:100svh;display:grid;place-items:center;padding:3rem 1rem;color:#fff;text-align:center;}
.thanks__bg{position:absolute;inset:0;z-index:-2;background-size:cover;background-position:center 45%;background-color:#222;}
/* Mục này và mục RSVP ngay phía trên dùng hai tấm ảnh chụp CÙNG bối cảnh
   (rèm xanh, hoa sen) nhưng độ phủ tối chênh nhau gấp đôi (.7 so với .35),
   nên chỗ giáp ranh thành một đường cắt ngang rõ rệt — nhìn như lớp phủ của
   mục trên bị hụt mất phần đáy. Cho 200px đầu của mục này chuyển dần từ .7
   xuống .35 để hoà mép, phần còn lại vẫn giữ .35 như cũ. */
.thanks__scrim{
  position:absolute;inset:0;z-index:-1;
  background:linear-gradient(to bottom,rgba(0,0,0,.7),rgba(0,0,0,.35) 200px);
}
/* ┌────────────────────────────────────────────────────────────────────┐
   │  CHỈNH VỊ TRÍ CỤM CHỮ "LỜI CẢM ƠN" — SỬA ĐÚNG MỘT SỐ Ở DÒNG DƯỚI   │
   │      --thanks-shift:  60px  ->  dịch XUỐNG 60px                    │
   │                      -60px  ->  dịch LÊN 60px                      │
   │                          0  ->  đúng giữa màn hình (mặc định cũ)   │
   └────────────────────────────────────────────────────────────────────┘
   Dịch bằng transform chứ KHÔNG dùng margin-top / top / padding: transform
   không làm đổi chiều cao khung #thankyou, nên ảnh nền (background-size:
   cover) không phải tính lại tỉ lệ phủ — tránh đúng cái lỗi ảnh giật zoom
   lúc cuộn đã xử lý trước đó.

   Đặt trên .thanks__inner (CẢ CỤM: tiêu đề + đoạn văn) chứ không đặt riêng
   trên h2 — đặt trên h2 thì chỉ mỗi dòng tiêu đề trôi xuống, đoạn văn đứng
   nguyên, hai phần đè lên nhau. */
.thanks__inner{
  max-width:480px;
  --thanks-shift:60px;
  transform:translateY(var(--thanks-shift));
}
/* chia đều độ dài các dòng thay vì để dòng cuối cụt lủn; trình duyệt cũ
   không hiểu thì rơi về cách xuống dòng thường, vẫn đọc tốt */
.thanks__inner p{text-wrap:balance;}
.thanks__inner h2{font-family:var(--font-cover);font-weight:500;font-size:clamp(2.75rem,10vw,3.75rem);margin-bottom:.5rem;}

/* =============================================================
   7. NÚT NỔI + MODAL + LIGHTBOX
   ============================================================= */
.fab{position:fixed;z-index:60;}
.fab--music{top:1rem;right:1rem;}
/* Cô dâu chú rể đứng hai bên nút: xếp hàng ngang, canh theo MÉP DƯỚI để cả
   ba cùng đứng trên một đường, không bị so le đầu. */
.fab--gift{bottom:1.25rem;right:1rem;display:flex;align-items:flex-end;gap:.15rem;pointer-events:none;}
/* Khung chứa rộng gấp ba lần nút, để bắt chuột thì cả vùng trống hai bên cũng
   chắn mất nội dung phía dưới — tắt ở khung, bật lại đúng cái nút. */
.fab--gift .btn-gift{pointer-events:auto;}

/* Ảnh chỉ trang trí nên phải cho xuyên chuột qua, kẻo phần rìa trong suốt của
   ảnh vẫn nuốt mất cú chạm lẽ ra rơi vào nút hoặc vào nội dung bên dưới.
   Cao cố định, rộng tự co theo tỉ lệ nên hai ảnh khác khổ vẫn cân nhau. */
.fab-chibi{
  height:4.25rem;width:auto;pointer-events:none;user-select:none;
  filter:drop-shadow(0 3px 5px rgba(0,0,0,.18));
  animation:bounce 3.8s infinite;
}
/* Lệch pha nhịp nảy để ba thứ không nhấp nhô cùng lúc như một khối. Delay
   scale theo đúng tỉ lệ cũ (34% / 68% chu kỳ) khi chu kỳ tăng từ 2.8s lên
   3.8s, để .btn-gift (0%) và hai ảnh này vẫn giữ đúng độ lệch ba nấc đều
   nhau chứ không lệch tỉ lệ. */
.fab-chibi--groom{animation-delay:-1.3s;}
.fab-chibi--bride{animation-delay:-2.6s;}

/* Máy hẹp: cụm ba món chiếm gần nửa bề ngang màn hình, thu nhân vật nhỏ lại
   để nút mừng cưới không bị đẩy sát mép trái. */
@media (max-width:400px){
  .fab-chibi{height:3.25rem;}
  .fab--gift{gap:0;}
}

.btn-music,.btn-gift{
  display:grid;place-items:center;border:0;border-radius:999px;color:#fff;
  box-shadow:0 4px 14px rgba(0,0,0,.25);
  transition:transform .32s var(--ease);
}
.btn-music{width:2.5rem;height:2.5rem;background:linear-gradient(135deg,#ec4899,#818cf8);}
.btn-music[aria-pressed="true"] svg{animation:spin 7.5s linear infinite;}
/* Cùng chu kỳ 3.8s với .fab-chibi ở trên (không delay = pha 0%, mốc để hai
   ảnh hai bên lệch theo). Đổi một bên mà quên đổi bên kia thì ba thứ tự động
   trật nhịp với nhau. */
.btn-gift{width:3.25rem;height:3.25rem;background:linear-gradient(135deg,#ef4444,#fed7aa);animation:bounce 3.8s infinite;}
.btn-music:hover,.btn-gift:hover{transform:scale(1.06);}
@keyframes spin{to{transform:rotate(360deg);}}

.modal{position:fixed;inset:0;z-index:100;display:grid;place-items:center;padding:1rem;}
.modal__backdrop{position:absolute;inset:0;background:rgba(0,0,0,.6);backdrop-filter:blur(2px);}
.modal__dialog{
  position:relative;width:100%;max-width:420px;max-height:85dvh;overflow-y:auto;
  padding:1.75rem 1.25rem;border-radius:var(--radius-box);
  background:#fff;color:var(--color-base-content);text-align:center;
  animation:pop .6s var(--ease);
}
@keyframes pop{from{opacity:0;transform:scale(.94);}}
.modal__close{position:absolute;top:.5rem;right:.75rem;border:0;background:none;font-size:1.75rem;line-height:1;}
.modal__title{font-family:var(--font-title);font-size:1.75rem;font-weight:500;}
.modal__lede{margin-top:.5rem;font-size:.875rem;}

.gift-list{display:grid;gap:1.25rem;margin-top:1.5rem;}
.gift-card{padding:1rem;border:1px solid var(--color-line);border-radius:var(--radius-box);}
/* Tên bên nằm giữa hai nhân vật: canh theo mép dưới để chân nhân vật và chân
   chữ cùng nằm trên một đường, canh giữa thì chữ bị trôi lên lưng chừng. */
.gift-card__side{
  display:flex;align-items:flex-end;justify-content:center;gap:.4rem;
  font-family:var(--font-title);font-size:1.25rem;
}
.gift-card__chibi{height:3rem;width:auto;}
/* Lật ngang bản bên phải để hai nhân vật quay mặt vào nhau thay vì cùng nhìn
   một hướng như đang xếp hàng. */
.gift-card__chibi--flip{transform:scaleX(-1);}

/* Nút bọc ngoài ảnh QR: bấm vào mở lightbox phóng to. Kích thước chuyển hết
   lên nút, ảnh bên trong chỉ việc lấp đầy. */
.gift-card__qrbtn{
  display:block;width:170px;margin:.75rem auto;padding:0;
  border:0;background:none;cursor:zoom-in;
}
.gift-card__qr{display:block;width:100%;border-radius:.5rem;}
/* Nút tải ảnh QR, nằm ngay dưới ảnh, trước hàng thông tin ngân hàng. */
.gift-card__dl{
  display:inline-flex;align-items:center;gap:.35rem;margin:0 0 .75rem;
  padding:.3rem .7rem;border:1px solid var(--color-line);border-radius:999px;
  background:none;font-size:.78rem;color:inherit;
}
.gift-card__dl:hover{background:rgba(0,0,0,.05);}
.gift-card__row{font-size:.9rem;}
.gift-card__acc{font-weight:600;letter-spacing:.04em;}
.btn-copy{margin-top:.6rem;padding:.4rem .9rem;border:1px solid var(--color-primary);border-radius:var(--radius-button);background:none;font-size:.8rem;}

.lb{position:fixed;inset:0;z-index:110;display:grid;place-items:center;background:rgba(0,0,0,.92);padding:2.5rem 1rem;}
/* touch-action:none để trình duyệt nhả cử chỉ chụm hai ngón cho mình tự xử lý;
   để mặc định thì trình duyệt tự phóng cả trang, ảnh đứng im.
   Ảnh có transform nên được vẽ như phần tử đã định vị: không đặt z-index thì
   nó đè lên nút đóng và mũi tên trái đứng trước nó trong DOM. */
.lb__img{
  position:relative;z-index:1;
  max-width:100%;max-height:80dvh;object-fit:contain;border-radius:.5rem;
  touch-action:none;cursor:zoom-in;will-change:transform;
}
.lb__img.is-zoomed{cursor:grab;}
.lb__img.is-zoomed:active{cursor:grabbing;}
.lb__close,.lb__nav,.lb__count{z-index:2;}
.lb__close{position:absolute;top:.75rem;right:1rem;border:0;background:none;color:#fff;font-size:2.25rem;line-height:1;}
.lb__nav{position:absolute;top:50%;transform:translateY(-50%);border:0;background:rgba(255,255,255,.12);color:#fff;font-size:2rem;line-height:1;width:2.75rem;height:2.75rem;border-radius:999px;}
.lb__nav--prev{left:.75rem;}
.lb__nav--next{right:.75rem;}
.lb__count{position:absolute;bottom:1rem;left:0;right:0;text-align:center;color:#fff;font-size:.85rem;}

/* Ảnh lỗi/thiếu -> nền xám nhạt thay vì icon vỡ */
.img-fallback{min-height:160px;background:repeating-linear-gradient(45deg,#e9e9e9,#e9e9e9 12px,#f4f4f4 12px,#f4f4f4 24px);}
