/* ==========================================================================
   dearing.cloud — trang chủ
   T1 · Design token "Atelier ánh nến" + reset + lưới mobile-first

   Đọc theo thứ tự: 1) Token → 2) Reset → 3) Typography → 4) Layout
   → 5) Tiện ích → 6) Component cơ sở.
   Mọi khối từ T2 trở đi CHỈ dùng biến ở mục 1 — không viết hex rời rạc,
   để đổi tông cả trang chỉ cần sửa một chỗ.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. DESIGN TOKEN
   -------------------------------------------------------------------------- */
:root {
  /* --- Màu (mã hex chốt trong noi_dung_trang_chu.md, mục A) --- */
  --c-cream:      #F7F3EC; /* nền chính, cũng là màu chữ trên nền tối */
  --c-dark:       #2B2723; /* nền section tối (CTA cuối, footer) */
  --c-ink:        #2A2622; /* chữ chính */
  --c-gold:       #B08D57; /* nhũ vàng đồng — đường kẻ, chi tiết, nút Zalo */
  /* Nhũ vàng sáng hơn, DÀNH RIÊNG cho chữ nằm trên nền tối/ảnh động.
     Vàng gốc #B08D57 chỉ đạt ~2.8:1 trên những khung hình sáng của video nền —
     mà nền là video nên độ sáng đổi liên tục, không thể trông vào màn lọc.
     Bản sáng này giữ nguyên sắc, chỉ nâng độ sáng để luôn dư ngưỡng. */
  --c-gold-on-dark: #D8BC8B;
  /* Nhũ vàng SÂU, dành cho nút đặc có chữ kem đè lên.
     Chữ kem #F7F3EC trên vàng gốc #B08D57 chỉ được 2.79:1 — trượt xa ngưỡng
     4.5:1 của chữ thường. Bản sâu này đo được 4.51:1, giữ đúng sắc đồng, chỉ
     hạ độ sáng vừa đủ qua ngưỡng. Cũng là màu chân của con dấu sáp. */
  --c-gold-deep: #8A6A3C;
  --c-terracotta: #C98474; /* hồng đất — CTA phụ, điểm nhấn ấm */

  /* Biến thể pha sẵn: nền kem hơi ngả trắng cho thẻ nổi lên khỏi nền section.
     Dùng màu pha thay vì bóng đổ đậm — bóng nặng làm mất cảm giác "giấy mịn". */
  --c-surface:      #FDFBF7;
  --c-surface-warm: #F1EADE; /* nền xen kẽ, tách hai section liền nhau mà không cần kẻ */

  /* Chữ phụ: pha loãng chữ chính thay vì chọn màu xám riêng, giữ tông ấm đồng nhất */
  --c-ink-soft:  rgba(42, 38, 34, 0.72);
  --c-ink-faint: rgba(42, 38, 34, 0.52);
  --c-cream-soft: rgba(247, 243, 236, 0.76); /* chữ phụ trên nền tối */

  /* Đường kẻ mảnh bằng vàng pha loãng — "nhũ vàng dùng tiết chế" theo brief */
  --c-line:        rgba(176, 141, 87, 0.28);
  --c-line-strong: rgba(176, 141, 87, 0.55);
  --c-line-dark:   rgba(247, 243, 236, 0.18); /* kẻ trên nền tối */

  /* --- Typography --- */
  --ff-display: "Fraunces", "Times New Roman", serif;
  --ff-body: "Be Vietnam Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  /* Thang cỡ chữ co giãn theo màn hình (clamp) thay vì nhảy bậc ở breakpoint:
     chữ mượt từ iPhone SE tới desktop, không có cỡ nào "hụt" ở khoảng giữa. */
  --fs-hero:  clamp(2.375rem, 1.3rem + 5.2vw, 4.75rem);
  --fs-h2:    clamp(1.75rem, 1.25rem + 2.4vw, 2.75rem);
  --fs-h3:    clamp(1.1875rem, 1.05rem + 0.7vw, 1.5rem);
  --fs-lead:  clamp(1.0625rem, 1rem + 0.5vw, 1.25rem);
  --fs-body:  1rem;
  --fs-sm:    0.9375rem;
  --fs-xs:    0.8125rem;

  --lh-tight: 1.12; /* heading serif cỡ lớn cần dòng sát để giữ khối chữ chắc */
  --lh-snug:  1.35;
  --lh-body:  1.7;  /* thoáng — body có dấu tiếng Việt cần chỗ cho dấu mũ/thanh */

  --ls-wide: 0.14em; /* eyebrow/nhãn viết hoa: giãn chữ mới sang, không bị "dồn cục" */

  /* --- Khoảng cách (bậc 4px, nhảy dần cho khoảng lớn) --- */
  --sp-2xs: 0.25rem;
  --sp-xs:  0.5rem;
  --sp-sm:  0.75rem;
  --sp-md:  1rem;
  --sp-lg:  1.5rem;
  --sp-xl:  2rem;
  --sp-2xl: 3rem;
  --sp-3xl: 4rem;
  --sp-4xl: 6rem;

  /* Khoảng thở của section co giãn — "khoảng trắng hào phóng là ngôn ngữ cao cấp",
     nhưng trên điện thoại mà để 6rem thì khách phải cuộn rỗng quá lâu. */
  --sp-section: clamp(3.5rem, 2rem + 7vw, 7rem);

  /* --- Khung & bo góc --- */
  --w-container: 1160px;
  --w-measure: 62ch; /* bề rộng đọc thoải mái cho đoạn văn dài (FAQ, phụ đề) */
  --pad-inline: clamp(1.25rem, 5vw, 2.5rem);

  --r-sm: 6px;
  --r-md: 12px;
  --r-lg: 20px;
  --r-pill: 999px;

  /* --- Bóng đổ: pha nâu của chữ chính, KHÔNG dùng đen thuần.
     Bóng đen trên nền kem ngả xám bẩn, phá tông ấm. --- */
  --sh-sm: 0 1px 2px rgba(42, 38, 34, 0.05), 0 2px 8px rgba(42, 38, 34, 0.05);
  --sh-md: 0 2px 6px rgba(42, 38, 34, 0.06), 0 10px 28px rgba(42, 38, 34, 0.08);
  --sh-lg: 0 4px 12px rgba(42, 38, 34, 0.07), 0 22px 48px rgba(42, 38, 34, 0.12);

  /* --- Chuyển động: chậm, mượt, có chủ đích (brief mục 4) ---
     Ease "ra nhanh vào chậm" cho cảm giác nhẹ tay, không giật/nảy. */
  --ease: cubic-bezier(0.22, 0.61, 0.24, 1);
  --dur-fast: 180ms;
  --dur: 280ms;
  --dur-slow: 620ms; /* fade-up khi cuộn */

  /* Chiều cao header — dùng chung cho scroll-padding của neo và offset sticky */
  /* 48px — đo thẳng trên apple.com: thanh điều hướng của họ cao 48px ở mobile
     và 44px ở desktop. Thanh mỏng làm nội dung trông rộng ra và bớt cảm giác
     "có một thanh công cụ dán trên đầu trang". Trước đây 64px. */
  --h-header: 48px;
  /* Logo giữ ở ~45% chiều cao header. Cao hơn nữa là hết lề thở và biểu tượng
     (khối đặc, tương phản cao) sẽ át cả tên thương hiệu bên cạnh. */
  --h-logo: 24px;

  --z-header: 100;
  --z-float: 200;  /* nút Zalo phải nổi trên mọi thứ, kể cả header */
  --z-modal: 300;
}

@media (min-width: 900px) {
  /* Desktop 52 chứ không 44 như Apple: wordmark của trang là chữ serif có
     chân, cần nhiều chiều cao hơn chữ sans của họ mới không bị bí. */
  :root { --h-header: 52px; --h-logo: 26px; }
}

/* --------------------------------------------------------------------------
   2. RESET (gọn — chỉ chỉnh những gì thật sự cản trở)
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

/* Bỏ margin mặc định: mọi khoảng cách dọc do layout quyết định, tránh margin
   thừa của trình duyệt phá nhịp khoảng trắng đã tính. */
body, h1, h2, h3, h4, p, figure, blockquote, dl, dd, ul, ol { margin: 0; }
ul[class], ol[class] { list-style: none; padding: 0; }

html {
  /* Neo (#mau-thiep…) không bị header dính che mất tiêu đề khối */
  scroll-padding-top: calc(var(--h-header) + var(--sp-md));
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%; /* iOS Safari tự phóng chữ khi xoay ngang */
}

body {
  min-height: 100vh;
  background-color: var(--c-cream);
  color: var(--c-ink);
  font-family: var(--ff-body);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden; /* chặn tràn ngang do mockup nghiêng/parallax ở hero (T3) */
}

img, picture, svg, video {
  display: block;
  max-width: 100%;
  height: auto;
}

input, button, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }

a { color: inherit; text-decoration: none; }

/* Viền focus bằng vàng thương hiệu — chỉ hiện khi điều hướng bàn phím,
   giữ khả năng tiếp cận mà không làm bẩn giao diện lúc bấm chuột. */
:focus-visible {
  outline: 2px solid var(--c-gold);
  outline-offset: 3px;
  border-radius: var(--r-sm);
}

::selection { background: var(--c-terracotta); color: var(--c-cream); }

/* Tôn trọng người tắt hiệu ứng (say chuyển động / tiết kiệm pin) */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------------------------------------------------
   3. TYPOGRAPHY
   -------------------------------------------------------------------------- */
h1, h2, h3, .u-display {
  font-family: var(--ff-display);
  font-weight: 600;
  line-height: var(--lh-tight);
  /* Trục opsz của Fraunces đẩy lên MỨC CAO NHẤT (144 = bản dành cho cỡ chữ lớn).
     Cùng một font, nhưng ở mức này nét thanh mảnh hẳn đi còn nét đậm dày lên —
     độ tương phản tách bạch là thứ làm một tiêu đề trông "đắt". Mức 120 cũ vẫn
     còn hơi hướng chữ đọc, chưa ra dáng chữ trưng bày. */
  font-variation-settings: "opsz" 144;
  /* Siết chữ để khối heading đặc lại. Giữ mức rất nhẹ ở đây vì trên màn hẹp
     cỡ chữ nhỏ, siết mạnh là dấu tiếng Việt dính vào nhau. */
  letter-spacing: -0.008em;
  text-wrap: balance; /* tránh heading rơi một chữ lẻ xuống dòng cuối */
}

/* Chữ càng to càng phải siết chặt hơn: cùng một khoảng cách tính theo em, ở cỡ
   lớn mắt thấy rời rạc. Chỉ áp từ 900px trở lên, dưới đó cỡ chữ nhỏ và dấu
   tiếng Việt cần chỗ thở. */
@media (min-width: 900px) {
  h1, h2, .u-display { letter-spacing: -0.022em; }
}

/* Vế sau của tiêu đề chuyển sang italic — nhịp roman → italic trong CÙNG một
   dòng là cách chia câu kinh điển của tạp chí thời trang và nhà thiệp cưới cao
   cấp: vế đầu là lời khẳng định, vế sau hạ giọng thành lời mời. Mắt bắt được
   chỗ đổi dáng chữ trước khi kịp đọc xong, nên câu tự có nhịp.

   Dùng <i> chứ không phải <em>: đây là đổi DÁNG chữ thuần tuý, không phải nhấn
   mạnh ngữ nghĩa — trình đọc màn hình không nên đọc nhấn ở đây. */
h1 i, h2 i, .u-display i {
  font-style: italic;
  /* Italic của Fraunces vốn đã nghiêng và hẹp hơn; nới lại một chút cho hai vế
     nhìn cùng mật độ, không thì vế nghiêng trông chật hơn vế đứng. */
  letter-spacing: -0.005em;
}

h1 { font-size: var(--fs-hero); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); font-weight: 600; }

p { text-wrap: pretty; }

/* Nhãn nhỏ viết hoa trên mỗi tiêu đề khối — dấu hiệu "biên tập", rẻ mà sang */
.eyebrow {
  font-family: var(--ff-body);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--c-gold);
}

/* Câu dẫn dưới tiêu đề khối */
.lead {
  font-size: var(--fs-lead);
  line-height: var(--lh-snug);
  color: var(--c-ink-soft);
  max-width: var(--w-measure);
}

/* Be Vietnam Pro KHÔNG nạp bản italic, nên <em> trong đoạn chữ đang bị trình
   duyệt bẻ nghiêng giả — thực chất là chữ đứng kéo xiên, nét bị méo và dấu
   tiếng Việt lệch theo. Chuyển sang italic THẬT của Fraunces: vừa hết chữ giả,
   vừa thành một điểm nhấn có chủ đích thay vì một chỗ trông như lỗi.
   Chỉnh cỡ lên 1.06 vì serif ở cùng cỡ px nhìn nhỏ hơn sans. */
.lead em {
  font-family: var(--ff-display);
  font-style: italic;
  font-size: 1.06em;
  font-variation-settings: "opsz" 72;
}

/* --------------------------------------------------------------------------
   4. LAYOUT
   -------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--w-container);
  margin-inline: auto;
  padding-inline: var(--pad-inline);
}

/* Khung hẹp cho khối đọc nhiều chữ (FAQ, CTA cuối) */
.container--narrow { max-width: 760px; }

section { padding-block: var(--sp-section); }

/* Nền xen kẽ để hai khối liền nhau không dính thành một mảng kem dài */
.section--warm { background-color: var(--c-surface-warm); }

.section--dark {
  background-color: var(--c-dark);
  color: var(--c-cream);
}
.section--dark .lead { color: var(--c-cream-soft); }
.section--dark .eyebrow { color: var(--c-terracotta); } /* vàng trên nền nâu tối kém tương phản */

/* Đầu khối: eyebrow + h2 + lead, canh giữa mặc định */
.section-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-sm);
  text-align: center;
  margin-bottom: var(--sp-2xl);
}
/* balance chia đều chữ cho các dòng thay vì nhồi đầy dòng trên rồi vứt hai ba
   chữ xuống dòng dưới. Phụ đề canh giữa mà rớt chữ lẻ thì nhìn như lỗi.
   Trình duyệt cũ không hiểu thì xuống dòng như cũ, không hỏng gì. */
.section-head .lead {
  margin-inline: auto;
  text-wrap: balance;
}

/* --- Lưới: mobile-first, mặc định 1 cột, tự lên cột ở màn rộng ---
   Điều khiển bằng biến --cols để markup chỉ cần class .grid + biến thể. */
.grid {
  display: grid;
  gap: var(--sp-lg);
  grid-template-columns: repeat(var(--cols, 1), minmax(0, 1fr));
}

/* Lưới 2 cột đôi (tính năng): 2 cột ngay trên mobile vì mỗi ô chỉ 1 icon + 1 dòng */
.grid--pairs { --cols: 2; gap: var(--sp-md); }

@media (min-width: 640px) {
  .grid--2 { --cols: 2; }
  .grid--3 { --cols: 2; }
  .grid--4 { --cols: 2; }
}

@media (min-width: 900px) {
  .grid { gap: var(--sp-xl); }
  .grid--3 { --cols: 3; }
  .grid--4 { --cols: 4; }
  .grid--pairs { --cols: 4; gap: var(--sp-lg); }
}

/* Xếp chồng dọc có nhịp đều — dùng cho nội dung trong thẻ */
.stack { display: flex; flex-direction: column; gap: var(--sp-md); }
.stack--sm { gap: var(--sp-xs); }
.stack--lg { gap: var(--sp-lg); }

/* Thẻ nền sáng dùng chung cho giá / cam kết / tính năng */
.card {
  background-color: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: var(--r-lg);
  padding: var(--sp-lg);
  box-shadow: var(--sh-sm);
}

@media (min-width: 900px) {
  .card { padding: var(--sp-xl); }
}

/* --------------------------------------------------------------------------
   5. TIỆN ÍCH
   -------------------------------------------------------------------------- */
.u-center { text-align: center; }
.u-measure { max-width: var(--w-measure); }
.u-narrow { max-width: 42rem; margin-inline: auto; }
.u-muted { color: var(--c-ink-soft); }
.u-faint { color: var(--c-ink-faint); font-size: var(--fs-sm); }
.u-gold { color: var(--c-gold); }

.u-mt-sm { margin-top: var(--sp-sm); }
.u-mt-md { margin-top: var(--sp-md); }
.u-mt-lg { margin-top: var(--sp-lg); }
.u-mt-xl { margin-top: var(--sp-xl); }
.u-mt-2xl { margin-top: var(--sp-2xl); }

/* Ẩn với mắt, vẫn đọc được bằng trình đọc màn hình (nhãn "mở tab mới"…) */
.u-visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Đường kẻ vàng mảnh phân cách — chi tiết trang trí duy nhất được dùng lặp */
.rule {
  width: 56px; height: 1px;
  background-color: var(--c-line-strong);
  border: 0;
}

/* --------------------------------------------------------------------------
   6. COMPONENT CƠ SỞ — nút
   Định nghĩa ở T1 vì nút Zalo xuất hiện ở gần như mọi khối (T2→T8);
   gom một chỗ để mọi CTA giống hệt nhau.
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-xs);
  /* min-height 48px: vùng chạm ngón tay tối thiểu 44px theo brief, cộng đệm */
  min-height: 48px;
  padding: 0.75rem 1.5rem;
  border-radius: var(--r-pill);
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  border: 1px solid transparent;
  transition:
    background-color var(--dur) var(--ease),
    border-color var(--dur) var(--ease),
    color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease),
    transform var(--dur) var(--ease);
}

/* CTA chính = Zalo. Bọc trong nhũ vàng thương hiệu, KHÔNG dùng xanh Zalo chói
   (yêu cầu rõ trong brief: nút chốt không được phá tông cao cấp). */
.btn--zalo {
  background-color: var(--c-gold);
  color: var(--c-cream);
  box-shadow: var(--sh-sm);
}
.btn--zalo:hover { background-color: #9C7B49; box-shadow: var(--sh-md); }

/* CTA phụ: viền mảnh, nền trong suốt — nhường sự chú ý cho nút Zalo */
.btn--ghost {
  border-color: var(--c-line-strong);
  color: var(--c-ink);
}
.btn--ghost:hover { border-color: var(--c-gold); background-color: rgba(176, 141, 87, 0.08); }

/* Nút phụ trên nền tối (CTA cuối, footer) */
.section--dark .btn--ghost {
  border-color: var(--c-line-dark);
  color: var(--c-cream);
}
.section--dark .btn--ghost:hover {
  border-color: var(--c-cream-soft);
  background-color: rgba(247, 243, 236, 0.08);
}

/* Nhấc 1px khi hover — đủ để thấy "sống", không đủ để thành nảy */
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn--lg { min-height: 56px; padding: 1rem 2rem; font-size: var(--fs-body); }
.btn--sm { min-height: 40px; padding: 0.5rem 1.125rem; font-size: var(--fs-xs); }
.btn--block { width: 100%; }

/* --------------------------------------------------------------------------
   7. HIỆU ỨNG CUỘN — fade-up
   Khai báo sẵn ở T1; JS (T2+) chỉ việc gắn class .reveal và gỡ .is-in.
   -------------------------------------------------------------------------- */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity var(--dur-slow) var(--ease),
    transform var(--dur-slow) var(--ease);
  /* Phần tử trong cùng một khối gắn --i tăng dần sẽ hiện lần lượt.
     Trần 6 bậc: item thứ 8 mà chờ 560ms là đã thành chậm chạp, không còn sang. */
  transition-delay: calc(min(var(--i, 0), 6) * 70ms);
}
.reveal.is-in { opacity: 1; transform: none; }

/* Không có JS thì nội dung vẫn phải đọc được — an toàn hơn là ẩn vĩnh viễn */
.no-js .reveal { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------
   8. HEADER + ĐIỀU HƯỚNG (T2)
   -------------------------------------------------------------------------- */

/* Bàn phím Tab lần đầu sẽ chạm nút này; bình thường nó nằm ngoài màn hình */
.skip-link {
  position: absolute;
  top: var(--sp-xs);
  left: var(--sp-xs);
  z-index: calc(var(--z-float) + 1);
  padding: var(--sp-xs) var(--sp-md);
  background-color: var(--c-ink);
  color: var(--c-cream);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  transform: translateY(-200%);
  transition: transform var(--dur) var(--ease);
}
.skip-link:focus { transform: translateY(0); }

.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  /* Trong suốt khi còn nằm trên hero (nền ảnh tối), chỉ đặc lại khi đã cuộn qua */
  background-color: transparent;
  border-bottom: 1px solid transparent;
  transition:
    background-color var(--dur) var(--ease),
    border-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}

/* Khi menu mobile mở, header cần một nền thật để logo/nút đóng luôn đủ tương
   phản dù phía sau đang là ảnh hero sáng hay tối. */
.site-header.is-nav-open {
  background-color: var(--c-surface);
  color: var(--c-ink);
  border-bottom-color: transparent;
  box-shadow: none;
}
.site-header.is-nav-open:not(.is-stuck) { color: var(--c-ink); }
.site-header.is-nav-open .brand__tag { color: var(--c-ink-faint); }
.site-header.is-nav-open .nav-toggle__bar { background-color: var(--c-ink); }

/* .is-stuck do JS gắn sau khi cuộn ~1 chiều cao header — tách header khỏi nội dung
   chạy bên dưới, nhưng vẫn giữ nền mờ để không thành một thanh nặng nề. */
/* Chất liệu kính mờ lấy đúng công thức đo được trên apple.com:
   saturate(180%) + blur(20px), nền để 0,72 chứ không 0,9.

   Vì sao phải có saturate: chỉ blur không thôi thì phần nền lọt qua bị nhạt
   màu, thanh trông như một mảng xám bẩn. Đẩy bão hoà lên 180% trả lại màu cho
   thứ nằm dưới, nên thanh đọc ra là KÍNH — thấy được cái gì đang trôi qua bên
   dưới. Đó mới là "trong suốt" theo nghĩa Apple làm, không phải giảm alpha.

   Nền 0,72 vì blur đã mạnh gấp đôi: mờ nhiều thì không cần đặc nhiều, và để
   đặc quá thì chẳng còn thấy gì trôi qua nữa. */
.site-header.is-stuck {
  background-color: rgba(247, 243, 236, 0.72);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom-color: var(--c-line);
  box-shadow: var(--sh-sm);
}

/* Khi header đang nằm trên hero: chữ và vạch hamburger đổi sang kem, nếu không
   chữ nâu than trên tranh tối sẽ mất hút. JS gắn .is-stuck khi cuộn hết hero. */
.site-header:not(.is-stuck) { color: var(--c-cream); }
.site-header:not(.is-stuck) .nav__link { color: rgba(247, 243, 236, 0.82); }
.site-header:not(.is-stuck) .nav__link:hover { color: var(--c-cream); }
.site-header:not(.is-stuck) .brand__tag { color: rgba(247, 243, 236, 0.62); }
.site-header:not(.is-stuck) .nav-toggle__bar { background-color: var(--c-cream); }

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-md);
  min-height: var(--h-header);
}

/* --- Logo: biểu tượng + chữ --- */
.brand {
  display: flex;
  align-items: center;
  /* Đệm dọc + lề âm bù lại: vùng chạm cao 40px trong khi vị trí hiển thị không
     đổi một pixel. Cần từ khi thanh header rút còn 48px và logo còn 24px —
     lúc đó vùng chạm của cả khối thương hiệu cũng chỉ còn 24px, quá nhỏ cho
     ngón tay. */
  padding-block: 8px;
  margin-block: -8px;
  /* gap 0: khoảng thở giữa biểu tượng và chữ nằm ở padding-left của
     .brand__text, để khi chữ thu về 0 thì khoảng đó biến mất theo — còn gap
     thì nó ở lại thành một mảng trống lơ lửng cạnh logo. */
  gap: 0;
  line-height: 1;
}

/* Chiều rộng auto theo tỉ lệ gốc 113:120. Cỡ lấy từ --h-logo để luôn ăn theo
   chiều cao header, đổi một chỗ là cả hai khớp nhau. */
.brand__mark {
  height: var(--h-logo);
  width: auto;
  flex: none;
}

/* Chữ nằm NGANG cạnh nhau thay vì xếp chồng: header chỉ cao 64–76px, xếp dọc
   là cụm chữ chiếm trọn chiều cao và đẩy logo phải nhỏ theo. Nằm ngang thì cả
   cụm chỉ cao bằng một dòng, logo được thở. */
/* Biểu tượng đã là chữ "d" nên phần chữ chỉ còn "earing", đặt sát vào để hai
   thứ đọc thành một từ. 3px là khoảng hở nhỏ nhất mà nét cuối của biểu tượng
   không dính vào thân chữ e. */
.brand__text {
  display: flex;
  align-items: baseline;
  gap: var(--sp-sm);
  padding-left: 3px;

  /* Cuộn qua hero thì chữ thu lại, chỉ còn biểu tượng. Thu bằng max-width chứ
     không phải display:none để nó trượt vào mượt, và overflow:hidden cắt gọn
     phần chữ trong lúc trượt. */
  max-width: 22rem;
  overflow: hidden;
  white-space: nowrap;
  transition:
    max-width var(--dur) var(--ease),
    opacity var(--dur-fast) var(--ease),
    padding-left var(--dur) var(--ease);
}

/* .is-stuck do JS gắn khi đã cuộn qua hết hero (mục 1 main.js) — cuộn ngược về
   hero là lớp này bị gỡ và chữ trở lại. */
.site-header.is-stuck .brand__text {
  max-width: 0;
  padding-left: 0;
  opacity: 0;
}

.brand__name {
  display: block;
  font-family: var(--ff-display);
  /* 1.125rem cho vừa thanh 48px — 1.375rem cũ được đo cho thanh 64px. */
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

/* Dòng định vị bên phải tên: rất nhỏ, viết hoa giãn chữ — chi tiết atelier.
   Ẩn dưới 1024px: nằm ngang nên nó ăn thêm ~190px bề rộng, cộng menu và nút
   Zalo là header chật. Từ 1024px trở lên mới đủ chỗ. */
.brand__tag {
  display: none;
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--c-ink-faint);
}

@media (min-width: 1024px) {
  /* Gạch đứng mảnh ngăn tên và dòng định vị — nhẹ hơn dấu chấm giữa */
  .brand__tag {
    display: block;
    padding-left: var(--sp-sm);
    border-left: 1px solid var(--c-line);
  }
}

/* --- Menu --- */
.nav__list {
  display: flex;
  gap: var(--sp-lg);
  margin: 0;
}

.nav__link {
  position: relative;
  display: inline-block;
  padding-block: var(--sp-xs);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--c-ink-soft);
  transition: color var(--dur) var(--ease);
}

/* Gạch chân vàng chạy ra từ giữa khi hover — chuyển động khẽ, đúng tinh thần "ít mà chất" */
.nav__link::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background-color: var(--c-gold);
  transform: scaleX(0);
  transition: transform var(--dur) var(--ease);
}
.nav__link:hover { color: var(--c-ink); }
.nav__link:hover::after { transform: scaleX(1); }

.site-header__actions {
  display: flex;
  align-items: center;
  gap: var(--sp-sm);
}

/* --- Nút hamburger --- */
.nav-toggle {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  /* 44×44: ngưỡng vùng chạm tối thiểu, dù vạch bên trong chỉ rộng 22px */
  width: 44px;
  height: 44px;
  padding: 11px;
}

.nav-toggle__bar {
  display: block;
  width: 22px;
  height: 1.5px;
  background-color: var(--c-ink);
  border-radius: 2px;
  transition: transform var(--dur) var(--ease), opacity var(--dur-fast) var(--ease);
}

/* Ba vạch biến thành dấu X khi mở — phản hồi rõ trạng thái, không cần đổi icon */
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

.nav__mobile-head,
.nav__mobile-cta { display: none; }

/* --- MOBILE: bảng điều hướng chiếm phần màn hình còn lại dưới header --- */
@media (max-width: 899px) {
  body.is-nav-open { overflow: hidden; }

  .site-header__inner {
    gap: var(--sp-xs);
    padding-left: max(var(--pad-inline), env(safe-area-inset-left, 0px));
    padding-right: max(var(--pad-inline), env(safe-area-inset-right, 0px));
  }

  /* Ghi đè trạng thái chữ kem của header trong suốt: khi panel mở, toàn bộ
     header và menu đều nằm trên nền kem nên phải trở về màu mực. */
  .site-header.is-nav-open,
  .site-header.is-nav-open:not(.is-stuck) { color: var(--c-ink); }
  .site-header.is-nav-open .nav__link { color: var(--c-ink); }
  .site-header.is-nav-open .nav-toggle__bar { background-color: var(--c-ink); }

  .nav {
    position: fixed;
    top: var(--h-header);
    left: 0;
    right: 0;
    height: calc(100dvh - var(--h-header));
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding:
      clamp(1.5rem, 6vh, 3.5rem)
      max(var(--pad-inline), env(safe-area-inset-right, 0px))
      max(1.25rem, env(safe-area-inset-bottom, 0px))
      max(var(--pad-inline), env(safe-area-inset-left, 0px));
    background-color: var(--c-surface);
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Dùng visibility + opacity thay vì display:none để còn chuyển động được;
       visibility:hidden cũng loại link khỏi thứ tự Tab khi menu đóng. */
    visibility: hidden;
    opacity: 0;
    transform: translateY(-12px);
    transition:
      opacity var(--dur) var(--ease),
      transform var(--dur) var(--ease),
      visibility 0s linear var(--dur);
  }

  .site-header.is-nav-open .nav {
    visibility: visible;
    opacity: 1;
    transform: translateY(0);
    transition-delay: 0s;
  }

  .nav__mobile-head { display: block; }

  .nav__mobile-eyebrow {
    display: block;
    margin-bottom: var(--sp-sm);
    color: var(--c-gold-deep);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: var(--ls-wide);
    text-transform: uppercase;
  }

  .nav__mobile-title {
    display: block;
    max-width: 13ch;
    color: var(--c-ink);
    font-family: var(--ff-display);
    font-size: clamp(1.75rem, 7.7vw, 2.35rem);
    font-weight: 600;
    line-height: var(--lh-tight);
  }

  .nav__list {
    flex-direction: column;
    gap: 0;
    width: 100%;
    margin-top: clamp(1.25rem, 4vh, 2.5rem);
    padding: 0;
    border-top: 1px solid var(--c-line);
  }

  .nav__list li + li { border-top: 1px solid var(--c-line); }

  .nav__link {
    display: block;
    min-height: 52px;
    padding-block: 0.875rem;
    font-family: var(--ff-display);
    font-size: clamp(1.05rem, 4.6vw, 1.25rem);
    font-weight: 600;
    color: var(--c-ink);
  }
  .nav__link::after { display: none; } /* gạch chân hover vô nghĩa trên cảm ứng */

  .nav__mobile-cta {
    display: inline-flex;
    margin-top: auto;
    min-height: 52px;
  }

  /* Nút Zalo trên thanh header vẫn hữu ích khi menu đóng; lúc menu mở CTA lớn
     đã nằm dưới bảng điều hướng nên ẩn nút nhỏ để góc phải chỉ còn nút đóng. */
  .site-header.is-nav-open .site-header__actions > .btn { display: none; }
}

@media (max-width: 359px) {
  .brand { gap: 0.4rem; }
  .brand__name { font-size: 1.125rem; }
  .site-header__actions { gap: 0.25rem; }
  .site-header__actions > .btn {
    min-height: 38px;
    padding-inline: 0.75rem;
  }
  .nav { padding-top: 1.25rem; }
  .nav__mobile-title { font-size: 1.65rem; }
  .nav__list { margin-top: 1rem; }
  .nav__link { min-height: 48px; padding-block: 0.7rem; }
}

@media (min-width: 900px) {
  .nav-toggle { display: none; }

  /* Cụm bên phải chỉ còn mỗi nút hamburger, mà hamburger đã ẩn ở desktop —
     để lại một thẻ rỗng thì flex vẫn chừa khoảng cách cho nó, menu bị đẩy
     lệch khỏi mép phải. */
  .site-header__actions { display: none; }
}

/* --------------------------------------------------------------------------
   9. HERO — nền nghệ thuật tràn viền (H1)

   Ba lớp chồng nhau: nền (ảnh/video) → màn lọc tối → chữ.
   Màn lọc không phải để "cho đẹp": chữ kem đè lên ảnh bất kỳ sẽ có chỗ đọc
   được chỗ không, nên phải có một lớp tối ĐỦ ĐẬM ở đúng vùng đặt chữ.
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  /* Header là sticky nên chiếm một dải riêng ở đầu luồng. Kéo hero lên đúng
     chiều cao đó để tranh chạy tràn lên tận đỉnh màn hình và header nổi ĐÈ lên,
     rồi đệm lại bằng padding-top để chữ không chui xuống dưới header.
     svh (chứ không phải vh) để thanh địa chỉ trên iOS không cắt mất CTA. */
  margin-top: calc(var(--h-header) * -1);
  padding-top: var(--h-header);
  min-height: 100vh;
  min-height: 100svh;
  min-height: 100dvh;
  display: flex;
  align-items: flex-end; /* mobile: chữ dồn xuống đáy, nhường phần trên cho tranh */
  overflow: hidden;
  isolation: isolate;
  color: var(--c-cream);
  background-color: var(--c-dark); /* màu chờ trong lúc ảnh chưa tải, không chớp trắng */
}

/* --- Lớp 1: nền --- */
.hero__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  /* Phóng nhẹ để parallax có chỗ trôi mà không hở mép trên/dưới */
  scale: 1.06;
}

.hero__bg img,
.hero__bg video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.hero__poster {
  display: block;
  width: 100%;
  height: 100%;
}

/* Video nằm ĐÈ lên poster chứ không thay thế: poster vẫn ở dưới làm nền, nên
   nếu video lỗi giữa chừng khách cũng không bao giờ thấy một khung trống. */
.hero__video {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 900ms var(--ease);
}
.hero__video.is-ready { opacity: 1; }

/* --- Lớp 2: màn lọc tối ---

   Nền hero là VIDEO, và clip còn được thay. Nghĩa là không bao giờ biết trước
   sau lưng chữ đang có gì: khung này tối, khung sau có thể là mảng trời trắng.
   Nên màn lọc không phải một lớp tối phẳng mà ba lớp có việc riêng:

     1. VŨNG TỐI dưới chữ — bám theo đúng chỗ đặt chữ, rất loe nên không bao
        giờ đọc ra thành một hình. Đây là lớp bảo đảm chữ đọc được với BẤT KỲ
        clip nào, và là lý do bỏ được bóng chữ.

        ĐO THỬ TRƯỜNG HỢP TỆ NHẤT (dựng lại đúng ba lớp này trên nền TRẮNG
        TINH, tức khung hình sáng nhất có thể xảy ra):
          mobile  — chữ kem 10,0:1 · chữ vàng 6,1:1
          desktop — chữ kem  9,7:1 · chữ vàng 5,9:1
        Đều dư ngưỡng 4,5:1. Bản đầu của vũng tối này chỉ đạt 2,7:1 cho chữ
        vàng trên mobile — trượt cả ngưỡng 3:1 của chữ cỡ lớn. Nếu sau này
        đổi sang clip sáng mà thấy chữ đuối, CHỖ VẶN LÀ ĐÂY: nâng hai mức
        0.95/0.88 hoặc kéo rộng bán kính, đừng thêm bóng chữ.
     2. HƯỚNG SÁNG của khung — tối ở phía có chữ, mở dần về phía kia để clip
        còn được nhìn.
     3. VIGNETTE — tối rìa khung. Thứ làm một khung hình ra dáng phim chứ
        không phải ảnh chụp màn hình.
*/
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  /* Mobile: chữ nằm đáy nên vũng tối đặt ở đáy-trái. Dải tối mỏng trên cùng
     giữ cho logo và menu của header trong suốt vẫn đọc được. */
  background-image:
    radial-gradient(140% 80% at 20% 104%,
      rgba(20, 17, 14, 0.95) 0%,
      rgba(20, 17, 14, 0.88) 32%,
      rgba(20, 17, 14, 0.58) 60%,
      rgba(20, 17, 14, 0) 88%),
    linear-gradient(to bottom,
      rgba(20, 17, 14, 0.52) 0%,
      rgba(20, 17, 14, 0.18) 16%,
      rgba(20, 17, 14, 0.50) 44%,
      rgba(20, 17, 14, 0.80) 100%),
    radial-gradient(125% 95% at 50% 38%,
      rgba(12, 10, 8, 0) 42%,
      rgba(12, 10, 8, 0.52) 100%);
}

/* Hạt phim. Nằm giữa màn lọc và chữ: phủ lên nền cho video hết vẻ nhựa, nhưng
   KHÔNG phủ lên chữ — hạt đè lên nét serif mảnh là chữ trông bẩn.
   Dựng bằng feTurbulence inline nên không thêm một file nào. */
.hero__grain {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0.13;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* --- Lớp 3: chữ --- */
.hero__inner {
  position: relative;
  z-index: 3;
  width: 100%;
  padding-block: var(--sp-2xl) var(--sp-3xl);
}

.hero__copy { max-width: 34rem; }

/* Vạch tóc mở đầu khối chữ */
.hero__mark {
  width: 64px;
  height: 1px;
  margin-bottom: 1.75rem;
  background-color: rgba(216, 188, 139, 0.55);
  transform-origin: left center;
}

.hero__title {
  /* Nét 400 thay cho 600 của các heading khác. Ở opsz 144, hạ nét xuống 400 là
     nét thanh mảnh hẳn còn nét đậm vẫn dày — độ tương phản tách bạch chính là
     thứ làm chữ trông được KHẮC chứ không phải được bôi đậm. Nét 600 trên nền
     video còn bị bè thêm vì rìa chữ sáng ăn vào nét. */
  font-weight: 400;
  /* Nhỏ hơn thang --fs-hero cũ (đỉnh 4,75rem) khoảng một phần ba. Chữ to hết
     cỡ là ngôn ngữ của biển giảm giá; ở đây thứ đắt là cái clip phía sau, chữ
     chỉ cần đủ để đọc và nhường chỗ trống lại cho khung hình. */
  font-size: clamp(2rem, 1rem + 3.4vw, 3.4rem);
  /* Ngắt dòng đã cứng trong HTML nên đây chỉ là hàng rào: chặn câu chạy dài
     nếu sau này có ai bỏ ngắt dòng đi. */
  max-width: 20ch;
  /* Canh lề quang học: chữ Đ có khoảng đệm hai bên, không kéo lại thì khối chữ
     trông thụt vào so với logo ngay phía trên. */
  text-indent: -0.03em;
  /* KHÔNG text-shadow. Bóng dưới nét serif là dấu hiệu nghiệp dư thấy ngay;
     việc giữ chữ đọc được đã có vũng tối ở màn lọc lo. */
}

/* Vế sau của câu: nghiêng + nhũ vàng, xuống hàng riêng.
   Cùng nhịp roman–italic với tiêu đề các khối bên dưới ("Bảy phong cách —
   chọn gu của hai bạn"), nên hero không thành một ngôn ngữ riêng lẻ loi. */
.hero__title-alt {
  display: block;
  font-style: italic;
  color: var(--c-gold-on-dark);
}

/* Dòng nói việc dưới H1. Sans + nhỏ + nhạt, ngược hẳn với serif lớn phía
   trên: chênh lệch giọng chính là thứ làm nó đọc được mà không phải to lên.
   Không dùng --fs-body (1rem) mà nhỏ hơn một nấc — nó là chú thích cho câu
   lớn, không phải một tuyên bố thứ hai. */
.hero__lead {
  margin-top: 1.25rem;
  max-width: 42ch;
  font-size: 0.9375rem;
  line-height: var(--lh-snug);
  color: var(--c-cream-soft);
}

/* Ngắt dòng CHỈ dành cho máy hẹp — từ 600px trở lên câu nằm trọn một dòng nên
   thẻ này tắt. Khoảng trắng trước nó nằm trong HTML, tắt br đi vẫn còn dấu
   cách giữa "—" và "bạn". */
.hero__lead-break { display: none; }

/* --- Vào màn: từng dòng trượt lên khỏi khung cắt ---
   Cách một tấm bìa phim hiện tên: chữ đi lên từ mép dưới, không phải hiện dần
   từ mờ. Ba dòng lệch nhau 110ms để mắt đọc thành ba nhịp đúng như khi ngắt
   dòng. Khối .u-motion-guard ở mục 2 đã tắt hết animation khi khách bật giảm
   chuyển động, nên ở đây không cần khai lại. */
.hero__line {
  display: block;
  overflow: hidden;
  /* Nét chữ có phần nhô lên trên/thò xuống dưới; cắt sát quá là mất dấu mũ và
     dấu nặng. Nới khung cắt rồi kéo lại bằng margin âm. */
  padding-block: 0.06em 0.12em;
  margin-block: -0.06em -0.12em;
}

.hero__line-in {
  display: block;
  animation: hero-line 1000ms cubic-bezier(0.16, 1, 0.3, 1) backwards;
}

.hero__title > .hero__line .hero__line-in { animation-delay: 80ms; }
.hero__title-alt .hero__line:nth-child(1) .hero__line-in { animation-delay: 190ms; }
.hero__title-alt .hero__line:nth-child(2) .hero__line-in { animation-delay: 300ms; }

@keyframes hero-line {
  from { transform: translateY(112%); }
  to   { transform: translateY(0); }
}

/* Dòng nói việc vào sau ba dòng chữ lớn: nó là lời giải thích, phải đến sau
   câu nó giải thích. Mờ dần + nhích lên, không trượt như H1 — hai kiểu chuyển
   động khác nhau giữ đúng thứ bậc giữa hai khối chữ. */
.hero__lead {
  animation: hero-lead 900ms cubic-bezier(0.16, 1, 0.3, 1) 430ms backwards;
}
@keyframes hero-lead {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Vạch tóc kẻ ra trước, chữ theo sau — như người ta gạch một nét rồi mới viết */
.hero__mark { animation: hero-mark 900ms cubic-bezier(0.16, 1, 0.3, 1) backwards; }
@keyframes hero-mark {
  from { transform: scaleX(0); opacity: 0; }
  to   { transform: scaleX(1); opacity: 1; }
}

/* Gợi ý cuộn: một vạch dọc mảnh, điểm sáng trôi từ trên xuống rồi tắt.
   Đứng thẳng dưới khối chữ (không dán đáy màn) để trên điện thoại nó không
   đè lên dòng chữ cuối, và vẫn nằm đúng cột chữ trên desktop. */
.hero__scroll-cue {
  /* Chiều dài vạch nằm trong một biến vì keyframe phía dưới cũng cần đúng con
     số đó; đổi ở breakpoint chỉ sửa một chỗ, điểm sáng không dừng giữa chừng. */
  --cue-h: 52px;
  /* Hiện sau cùng, khi ba dòng chữ đã đứng yên: mời cuộn trong lúc khách còn
     đang đọc là chen ngang. */
  animation: hero-cue-in 900ms var(--ease) 900ms backwards;
  position: relative;
  width: 1px;
  height: var(--cue-h);
  margin-top: var(--sp-2xl);
  overflow: hidden;
  background-image: linear-gradient(to bottom,
    rgba(216, 188, 139, 0.42) 0%,
    rgba(216, 188, 139, 0.10) 100%);
}

.hero__scroll-cue::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 14px;
  background-image: linear-gradient(to bottom,
    rgba(216, 188, 139, 0) 0%,
    var(--c-gold-on-dark) 100%);
  animation: hero-cue 2600ms var(--ease) infinite;
}

/* Trôi hết vạch rồi nghỉ một nhịp: chạy liên tục không ngắt sẽ thành thanh
   loading, mà loading thì trông như trang đang bận. */
@keyframes hero-cue {
  0%        { transform: translateY(-100%); opacity: 0; }
  18%       { opacity: 1; }
  62%, 100% { transform: translateY(var(--cue-h)); opacity: 0; }
}

@keyframes hero-cue-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .hero__scroll-cue::after { animation: none; opacity: 0.6; }

  /* Khối chống chuyển động ở mục 2 rút hết THỜI LƯỢNG animation nhưng không
     đụng tới ĐỘ TRỄ. Không gỡ độ trễ ở đây thì người tắt hiệu ứng phải nhìn
     một hero khuyết chữ suốt 0,9 giây rồi mọi thứ bật ra cùng lúc — đúng cái
     giật mình mà họ tắt hiệu ứng để tránh.
     Dùng !important vì độ trễ ba dòng chữ được đặt bằng selector đặc hiệu hơn
     (.hero__title > .hero__line .hero__line-in) — viết thường ở đây là thua. */
  .hero__mark,
  .hero__line-in,
  .hero__lead,
  .hero__scroll-cue { animation-delay: 0ms !important; }
}

/* Mobile là bố cục gốc của hero: khối chữ gọn, CTA đủ lớn để chạm và phần đáy
   chừa đúng safe-area. Background chỉ là một media slot; không phụ thuộc nội
   dung clip sau này nên đổi video không làm xô lệch layout. */
@media (max-width: 599px) {
  .hero {
    /* Safari iPhone đặt thanh công cụ dưới dạng lớp trong suốt ĐÈ lên website.
       100dvh/svh chỉ kết thúc phía trên lớp đó, nên section kế tiếp vẫn nhìn
       xuyên qua thanh công cụ. 100lvh giữ hero kéo dài vào vùng phía sau browser
       chrome; fallback 100vh dành cho trình duyệt cũ chưa hỗ trợ lvh. */
    min-height: 100vh;
    min-height: 100lvh;
  }

  .hero__bg { scale: 1.02; }

  /* Chế độ duyệt clip ngang trên điện thoại: ưu tiên thấy đủ 100% video thay
     vì crop mất hai bên. Nền tối lấp phần chênh tỷ lệ; khi có clip dọc 9:16,
     bỏ data-hero-mobile-fit để quay về `cover` toàn màn hình. */
  .hero__bg--mobile-contain {
    scale: 1;
    background:
      radial-gradient(circle at 50% 42%, rgba(176, 141, 87, 0.14), transparent 48%),
      var(--c-dark);
  }

  .hero__bg--mobile-contain .hero__poster { opacity: 0.16; }

  .hero__bg--mobile-contain .hero__video {
    object-fit: contain;
    object-position: center;
  }

  .hero__inner {
    padding-top: clamp(5.5rem, 18svh, 8.5rem);
    padding-bottom: max(clamp(1.75rem, 6svh, 3.25rem), env(safe-area-inset-bottom, 0px));
  }

  .hero__copy { max-width: 31rem; }

  .hero__mark {
    width: 44px;
    margin-bottom: 1.25rem;
  }

  /* Dòng dài nhất là "cho ngày trọng đại" (18 ký tự có dấu). 8,6vw giữ nó cách
     mép phải một khoảng thở trên iPhone hẹp — nét 400 mảnh nên cỡ này vẫn đọc
     tốt, mà khối chữ thôi lấn hết bề ngang khung hình. */
  .hero__title {
    max-width: none;
    font-size: clamp(1.75rem, 8.6vw, 2.6rem);
    line-height: 1.12;
  }

  .hero__lead {
    margin-top: 1rem;
    font-size: 0.875rem;
  }

  /* Ngắt đúng chỗ dấu gạch ngang: "Thiệp cưới online —" một dòng, vế làm hộ
     một dòng. Để tự xuống hàng thì "trọn gói." rơi xuống nằm lẻ một mình.
     Chặn bằng max-width không ăn thua — đơn vị ch của Be Vietnam Pro đo theo
     bề ngang chữ số, rộng hơn hẳn chữ thường có dấu, nên số nào cũng lệch. */
  .hero__lead-break { display: block; }

  .hero__scroll-cue {
    --cue-h: 40px;
    margin-top: 1.5rem;
  }

  .hero__scroll-cue::after { height: 12px; }
}

/* Điện thoại thấp/xoay ngang: ba dòng H1 cỡ lớn cộng vạch cuộn không lọt một
   màn 620px, nên hạ cỡ chữ và rút vạch lại thay vì để chữ bị cắt. */
@media (max-width: 899px) and (max-height: 620px) {
  .hero {
    min-height: 100vh;
    min-height: 100lvh;
  }

  .hero__inner {
    padding-top: calc(var(--h-header) + 1rem);
    padding-bottom: max(1rem, env(safe-area-inset-bottom, 0px));
  }

  .hero__title { font-size: clamp(1.6rem, 7.4vw, 2.2rem); }

  .hero__mark { margin-bottom: 0.875rem; }

  .hero__lead { margin-top: 0.75rem; }

  .hero__scroll-cue {
    --cue-h: 30px;
    margin-top: 0.875rem;
  }
}

/* --- Desktop: chữ canh giữa theo chiều dọc, dồn về trái --- */
@media (min-width: 900px) {
  .hero { align-items: center; }

  .hero__inner { padding-block: var(--sp-3xl); }

  .hero__copy { max-width: 38rem; }

  /* Ảnh nền dịch sang phải để nhân vật/ánh nến không nằm sau chữ */
  .hero__bg img,
  .hero__bg video { object-position: 68% 50%; }

  /* Cùng ba lớp như mobile nhưng xoay trục: chữ nằm giữa-trái nên vũng tối dời
     về đó, hướng sáng chuyển thành đậm-trái nhạt-phải để nửa phải của clip
     còn nguyên. Vignette giữ nguyên vai trò làm rìa khung. */
  .hero__scrim {
    background-image:
      radial-gradient(58% 76% at 24% 50%,
        rgba(20, 17, 14, 0.88) 0%,
        rgba(20, 17, 14, 0.60) 42%,
        rgba(20, 17, 14, 0) 80%),
      linear-gradient(to right,
        rgba(20, 17, 14, 0.70) 0%,
        rgba(20, 17, 14, 0.44) 40%,
        rgba(20, 17, 14, 0.08) 72%,
        rgba(20, 17, 14, 0) 100%),
      radial-gradient(115% 90% at 50% 45%,
        rgba(12, 10, 8, 0) 45%,
        rgba(12, 10, 8, 0.58) 100%);
  }

  .hero__mark { margin-bottom: 2rem; }

  /* Desktop rộng rãi nên để câu nằm trọn MỘT dòng: cụm khoá và vế làm hộ đứng
     cạnh nhau, mắt bắt cả hai trong một lần lướt. */
  .hero__lead {
    margin-top: 1.5rem;
    max-width: none;
    font-size: 1rem;
  }
}

/* Parallax khẽ: JS ghi --parallax theo vị trí cuộn, nền trôi chậm hơn trang.
   Tắt trên mobile (cuộn bằng ngón tay, dịch chuyển liên tục dễ thành rung giật)
   và khi khách bật giảm chuyển động. */
@media (min-width: 900px) and (prefers-reduced-motion: no-preference) {
  .hero__bg { translate: 0 calc(var(--parallax, 0) * 1px); }
}

/* --------------------------------------------------------------------------
   10. DANH MỤC 7 MẪU
   -------------------------------------------------------------------------- */
/* Nền riêng + nằm trên: khối cinematic phía trên được ghim bằng ScrollTrigger
   nên lớp sân khấu của nó còn cố định phía sau. Không có nền thì bầu trời lọt
   xuyên qua danh mục. */
/* Mép trên TAN DẦN thay vì cắt ngang.

   Danh mục trượt lên đè lên sân khấu cinematic đang ghim, nên mép trên của nó
   quét qua cảnh như một đường kẻ thẳng — lộ rõ nhất đúng lúc cú loé sáng đang
   diễn, và đó là chỗ khách thấy hai khối rời nhau.

   Cách sửa: tách nền ra một lớp riêng (::before) rồi che lớp đó bằng mask dọc.
   Nền kem đặc dần từ trong suốt nên không còn mép nào để thấy, cảnh phía sau
   tan vào nền danh mục. Mask CHỈ áp cho lớp nền, chữ và thẻ không hề mờ đi. */
.gallery {
  position: relative;
  z-index: 1;
  --gallery-fade: 15rem;
  /* Chừa chỗ cho dải tan: tiêu đề phải rơi xuống dưới vùng mask, nếu không chữ
     hiện lên trong lúc sau lưng nó vẫn còn là bầu trời. */
  padding-top: calc(var(--sp-section) + var(--gallery-fade) * 0.7);
}

.gallery::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: var(--c-cream);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 var(--gallery-fade));
  mask-image: linear-gradient(to bottom, transparent 0, #000 var(--gallery-fade));
}

/* Màn hẹp: dải tan ngắn lại, nếu không nó ăn gần hết một màn hình. */
@media (max-width: 899px) {
  .gallery {
    /* 8rem thay vì 10: dải tan sinh ra để nền kem không lộ mép khi phía sau
       vẫn còn là bầu trời. Giờ cảnh cinematic kết thúc bằng một màn KEM ĐẶC
       (cú chói sáng), tức nền danh mục tan vào một nền cùng màu — dải dài
       không còn tác dụng gì ngoài việc đẩy tiêu đề xuống thấp. */
    --gallery-fade: 4rem;

    /* padding-top được TÍNH TỪ --gallery-fade (xem rule gốc phía trên) nên rút
       dải tan xuống 4rem là padding tự co theo: 145px → 101px, dòng chữ đầu
       tiên lên gần 45px mà không phải đụng vào công thức. */

    /* Kéo khối danh mục trồi lên ăn vào đuôi cảnh cinematic.
       Sân khấu là sticky cao trọn màn hình nên sau khi cảnh hết, nó BUỘC phải
       cuộn đi mất đúng một màn — không có cách nào hiện ngay khối danh mục nếu
       khối đó nằm nguyên chỗ cũ. Kéo lên là cách duy nhất, và mức kéo bị chặn
       bởi lúc màn hình thành kem: kéo quá thì có vệt kem bò lên che bầu trời
       trước khi loé. Đẩy cú loé sớm lên mốc 0.70 (main.js) chính là để nới
       trần đó từ 130 lên 250px. */
    margin-top: -250px;

    /* Neo #mau-thiep: con số này KHÔNG bằng mức kéo ở trên.
       scroll-margin âm đẩy điểm ngắm xuống dưới mép khối, nên trình duyệt cuộn
       sâu thêm đúng chừng ấy. Bù nguyên 250 thì tiêu đề bị đẩy lên trên mép
       màn hình (đo được: nhãn ở y=-66). -80 đưa mép khối về đúng đỉnh khung
       nhìn, nhãn rơi xuống ~104 — ngay dưới header cao 64. */
    scroll-margin-top: -80px;
  }
}

/* Desktop cũng kéo khối danh mục lên ăn vào đuôi cảnh, cùng lý do như bản
   mobile (xem khối @media max-width: 899px phía trên).
   Đo trước khi sửa: lúc cú loé vừa xong, nhãn "Bộ sưu tập" còn nằm 298px DƯỚI
   đáy màn — khách cuộn qua chừng ấy pixel kem trống mới thấy chữ đầu tiên.
   300px là mức tối đa an toàn: cú loé bắt đầu ở mốc 0.78, lúc đó mép khối còn
   ở 1138px, kéo 300 thì nó mới chạm 838 — nằm trong vùng dải tan gần như
   trong suốt, không lộ vệt kem nào đè lên bầu trời. */
@media (min-width: 900px) {
  .gallery {
    --gallery-fade: 8rem;
    margin-top: -300px;
    scroll-margin-top: -180px;
  }
}

.tpl-grid {
  display: grid;
  gap: var(--sp-xl);
  grid-template-columns: 1fr;
}

/* Giữ chỗ khi đang chờ fetch — tránh trang giật nảy lúc 7 thẻ đổ vào */
.tpl-grid[aria-busy="true"] { min-height: 70vh; }

@media (min-width: 600px) { .tpl-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 980px) { .tpl-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* --- Thẻ: KHÔNG còn là "thẻ" ---
   Bỏ hết viền, nền, đổ bóng, góc bo. Ba trang bán thiệp điện tử và mẫu web đầu
   ngành (Paperless Post, Zola, Framer) đều không đóng khung sản phẩm: thứ duy
   nhất được nhìn là món hàng. Có khung thì bảy ô đọc ra như bảy bài blog. */
.tpl-card {
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  overflow: visible;
}

.tpl-card__link {
  display: flex;
  flex-direction: column;
  height: 100%;
  text-align: center;
}

/* --- Khung ghép hai ảnh ---
   Màn phong bì xoè chéo phía sau, màn bên trong đứng trước và thấp hơn — đọc
   ra ngay là tấm thiệp vừa rút khỏi phong bì.

   Lý do phải ghép: bảy màn phong bì nhìn na ná nhau, vì phong bì thì mẫu nào
   cũng là phong bì. Thứ phân biệt bảy phong cách nằm ở RUỘT — ảnh cưới, bộ
   chữ, cách đặt tên. Chỉ bày phong bì là bắt khách đoán. */
.tpl-shot {
  position: relative;
  display: block;
  /* Hai lớp cao 93% bề ngang, lệch nhau theo chiều dọc 19% -> khung 1:1.12 */
  aspect-ratio: 1 / 1.12;
  margin-bottom: var(--sp-md);

  /* --- Hai số điều khiển toàn bộ bố cục ghép ---
     --lop   : bề ngang mỗi lớp
     --chong : hai lớp chồng lên nhau bao nhiêu

     Chồng ÍT thì bộ đôi banh rộng ra hai bên, bảy ô đứng cạnh nhau thành một
     dãy hình chi chít, mắt không biết đâu là một sản phẩm. Chồng NHIỀU thì
     mỗi ô co lại thành một khối gọn, bảy khối tách bạch hẳn.

     Lề trái/phải suy ra từ hai số trên để bộ đôi luôn nằm giữa khung: dịch
     lớp sau vào trong mà không kéo lề theo thì cả cụm lệch sang trái. */
  --lop: 56%;
  --chong: 26%;
  --le: calc((100% - (2 * var(--lop) - var(--chong))) / 2);
}

.tpl-shot__back,
.tpl-shot__front {
  position: absolute;
  display: block;
  width: var(--lop);
  aspect-ratio: 3 / 5;
  overflow: hidden;
  border-radius: 12px;
  background-color: var(--c-surface-warm);
  transition:
    transform var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}

.tpl-shot__back {
  right: var(--le);
  top: 0;
  z-index: 1;
  transform: rotate(6deg);
  box-shadow: 0 8px 20px rgba(42, 38, 34, 0.16);
}

/* Lớp trước để THẲNG. Nghiêng cả hai thì bộ đôi đọc ra như hai tấm ảnh vứt
   trên bàn; một cái thẳng một cái xiên mới ra "tấm thiệp vừa rút khỏi phong
   bì đặt nghiêng sau lưng". */
.tpl-shot__front {
  left: var(--le);
  bottom: 0;
  z-index: 2;
  box-shadow: 0 14px 34px rgba(42, 38, 34, 0.26);
}

.tpl-shot__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Hai lớp canh dọc riêng: phong bì và ruột đặt nội dung ở hai độ cao khác nhau */
.tpl-shot__img--back  { object-position: 50% var(--tpl-focus, 50%); }
.tpl-shot__img--front { object-position: 50% var(--tpl-focus-in, 50%); }

/* Nhãn "web thật" nằm TRONG lớp trước — nói thẳng đây không phải ảnh dựng,
   và đặt trên đúng cái ảnh chứng minh điều đó. */
.tpl-card__live {
  position: absolute;
  z-index: 1;
  top: var(--sp-xs);
  left: var(--sp-xs);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px 4px 8px;
  border-radius: var(--r-pill);
  background-color: rgba(26, 22, 19, 0.62);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: var(--c-cream);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
}
.tpl-card__live::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background-color: #7BC47F;
}

.tpl-card__body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2xs);
  flex: 1;
}

.tpl-card__name {
  font-family: var(--ff-display);
  font-size: 1.625rem;
  font-weight: 600;
  line-height: 1.15;
}

.tpl-card__tagline {
  font-size: var(--fs-sm);
  color: var(--c-ink-soft);
  margin-bottom: var(--sp-md);
}

/* --- Nút Mở thiệp ---
   Vàng SÂU chứ không phải vàng gốc: chữ kem trên #B08D57 chỉ đo được 2.79:1,
   trượt xa ngưỡng 4.5:1 — mà đây đúng là nút quyết định cả trang có tác dụng
   hay không. Bản sâu đo được 4.51:1. */
.tpl-card__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-xs);
  align-self: center;
  margin-top: auto;
  min-height: 44px;
  padding: 0.625rem 1.375rem;
  border-radius: var(--r-pill);
  background-color: var(--c-gold-deep);
  color: var(--c-cream);
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.2;
  box-shadow: var(--sh-sm);
  transition:
    background-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}
.tpl-card__cta svg {
  width: 15px; height: 15px;
  transition: transform var(--dur) var(--ease);
}

@media (hover: hover) {
  /* Rê chuột thì tấm thiệp NHẤC RA khỏi phong bì: lớp trước thẳng lên và trồi
     lên, phong bì xoè rộng thêm và lùi ra sau. Đây là cử chỉ của chính sản
     phẩm, không phải một hiệu ứng dán thêm. */
  .tpl-card:hover .tpl-shot__front {
    transform: translateY(-10px);
    box-shadow: 0 24px 48px rgba(42, 38, 34, 0.32);
  }
  .tpl-card:hover .tpl-shot__back {
    transform: rotate(10deg) translate(8px, -6px);
    box-shadow: 0 12px 28px rgba(42, 38, 34, 0.2);
  }

  /* Chữ đã là màu kem trên nền vàng, đổi màu chữ nữa là mất tương phản —
     phản hồi rê chuột chuyển sang làm nền đậm lại. */
  .tpl-card:hover .tpl-card__cta {
    background-color: #74582E; /* đậm thêm một nấc, 5.97:1 */
    box-shadow: var(--sh-md);
  }
  .tpl-card:hover .tpl-card__cta svg { transform: translate(2px, -2px); }
}

/* --- Thẻ cuối trải rộng ---
   7 mẫu không chia hết cho 2 hay 3 cột nên thẻ cuối luôn đứng lẻ. Trải nó ra
   hết hàng thành thẻ nổi bật — biến điểm yếu của lưới thành chủ đích. */
@media (min-width: 600px) {
  .tpl-card:last-child { grid-column: 1 / -1; }
  .tpl-card:last-child .tpl-card__link {
    flex-direction: row;
    align-items: center;
    gap: var(--sp-2xl);
    text-align: left;
  }
  .tpl-card:last-child .tpl-shot {
    flex: 0 0 42%;
    margin-bottom: 0;
  }
  .tpl-card:last-child .tpl-card__body {
    align-items: flex-start;
    justify-content: center;
    flex: 1;
  }
  .tpl-card:last-child .tpl-card__name { font-size: 2.125rem; }
  .tpl-card:last-child .tpl-card__cta { margin-top: var(--sp-md); }
}

/* --- MOBILE: MỘT Ô LỚN + LƯỚI HAI CỘT ---

   Thay cho carousel vuốt ngang dùng tới 13/08/2026. Lý do bỏ carousel, đo và
   tra được:
     · khung cuộn ngang dài 2.243px trên máy 390px — phải VUỐT 6 LẦN mới tới
       mẫu thứ bảy, trong khi NN/g đo được người dùng bỏ cuộc sau 3–4 mục và
       đặt nguyên tắc "chạm tới mục cuối trong 3–4 bước";
     · NN/g: tỉ lệ bấm vào slide sau slide đầu chỉ khoảng 1%;
     · Baymard: carousel bị cắt cụt khiến người dùng mặc định thứ đang thấy là
       TẤT CẢ — tức sáu mẫu còn lại coi như không tồn tại;
     · không đối thủ nào trong ngành (Vesey, CineLove, Zola) bày mẫu kiểu
       một-lần-một-cái; tất cả đều dùng lưới.

   Vì sao MỘT Ô LỚN rồi mới tới lưới, chứ không lưới đều: Baymard cũng chỉ ra
   với ngành hàng nhìn-để-chọn thì phóng to ô sản phẩm giúp khách thẩm được
   thẩm mỹ chi tiết hơn hẳn. Hai điều đó kéo ngược nhau, nên ô đầu để nguyên
   khổ (đúng tỉ lệ một chiếc điện thoại — thứ đang bán CHÍNH LÀ web trên điện
   thoại) rồi sáu ô lưới để quét nhanh. Tổng ~2,3 màn, và không phải vuốt
   ngang lần nào. */
@media (max-width: 599px) {
  .tpl-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-xl) var(--sp-md);
  }

  .tpl-card:first-child { grid-column: 1 / -1; }

  /* Ô lớn GIỮ bố cục ghép phong bì + ruột: ở 350px mỗi lớp còn ~210px, rộng
     hơn cả thẻ carousel cũ, nên chi tiết vẫn đọc được. */
  .tpl-card:first-child .tpl-shot {
    aspect-ratio: 1 / 1.15;
    --lop: 60%;
  }

  /* Sáu ô lưới chỉ còn ẢNH RUỘT. Ở bề ngang 167px mà ghép hai lớp thì mỗi tấm
     còn ~100px — không đọc nổi. Và chính ruột mới là thứ phân biệt bảy phong
     cách (xem ghi chú ở .tpl-shot), phong bì thì mẫu nào cũng na ná. */
  .tpl-card:not(:first-child) .tpl-shot { aspect-ratio: auto; }
  .tpl-card:not(:first-child) .tpl-shot__back { display: none; }

  .tpl-card:not(:first-child) .tpl-shot__front {
    position: relative;
    left: auto;
    bottom: auto;
    width: 100%;
  }

  /* Chữ trong ô hẹp phải nhỏ lại, nếu không tên mẫu chiếm hai dòng và đẩy
     nút xuống lệch hàng giữa các ô. */
  .tpl-card:not(:first-child) .tpl-card__name { font-size: 1.125rem; }
  .tpl-card:not(:first-child) .tpl-card__tagline {
    font-size: 0.8125rem;
    margin-bottom: var(--sp-sm);
  }
  .tpl-card:not(:first-child) .tpl-card__cta {
    min-height: 40px;
    padding: 0.5rem 0.875rem;
    font-size: 0.8125rem;
  }
  .tpl-card:not(:first-child) .tpl-card__live {
    font-size: 0.625rem;
    padding: 3px 8px 3px 6px;
  }
}

/* --- Dự phòng khi tắt JS / fetch hỏng --- */
.tpl-fallback { display: grid; gap: var(--sp-sm); list-style: none; padding: 0; margin: 0; }
.tpl-fallback a {
  display: block;
  padding: var(--sp-md);
  background-color: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  font-weight: 600;
}
.tpl-fallback a:hover { border-color: var(--c-gold); }
/* --------------------------------------------------------------------------
   11. NÚT ZALO NỔI / THANH CTA DÍNH ĐÁY (T2)
   -------------------------------------------------------------------------- */
.zalo-float {
  position: fixed;
  z-index: var(--z-float);
  /* Ẩn mặc định, JS gắn .is-visible sau khi khách cuộn qua hero — hiện sớm sẽ
     che mất chính hero, mà hero là chỗ định vị thương hiệu trong 3 giây đầu. */
  opacity: 0;
  visibility: hidden;
  transform: translateY(16px);
  transition:
    opacity var(--dur) var(--ease),
    transform var(--dur) var(--ease),
    visibility 0s linear var(--dur);
}

.zalo-float.is-visible {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition-delay: 0s;
}

.zalo-float__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-xs);
  background-color: var(--c-gold);
  color: var(--c-cream);
  font-weight: 600;
  transition: background-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.zalo-float__btn:hover { background-color: #9C7B49; }

.zalo-float__icon { width: 22px; height: 22px; flex: none; }

/* --- MOBILE: thanh dính đáy full-width --- */
@media (max-width: 899px) {
  .zalo-float {
    left: 0;
    right: 0;
    bottom: 0;
    /* env(safe-area-inset-bottom): iPhone có thanh gạt home, nút phải nằm trên nó */
    padding: var(--sp-sm) var(--pad-inline) calc(var(--sp-sm) + env(safe-area-inset-bottom, 0px));
    background-color: rgba(247, 243, 236, 0.92);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border-top: 1px solid var(--c-line);
  }

  .zalo-float__btn {
    width: 100%;
    min-height: 52px;
    border-radius: var(--r-pill);
    font-size: var(--fs-body);
  }

  .zalo-float__label--desktop { display: none; }

  /* Chừa chỗ ở đáy trang đúng lúc thanh hiện ra, để nó không đè nội dung cuối
     (dòng bản quyền ở footer). Class do JS gắn cùng lúc với .is-visible. */
  body.has-sticky-cta { padding-bottom: calc(76px + env(safe-area-inset-bottom, 0px)); }
}

/* --- DESKTOP: nút nổi góc phải dưới --- */
@media (min-width: 900px) {
  .zalo-float {
    right: var(--sp-xl);
    bottom: var(--sp-xl);
  }

  .zalo-float__btn {
    min-height: 52px;
    padding: 0.75rem 1.5rem;
    border-radius: var(--r-pill);
    font-size: var(--fs-sm);
    box-shadow: var(--sh-lg);
  }

  .zalo-float__label--mobile { display: none; }
}

/* --------------------------------------------------------------------------
   12. TÍNH NĂNG — ba hồi theo dòng thời gian đám cưới

   Bản cũ là lưới 8 ô y hệt nhau, mỗi ô một icon vẽ. Ba lỗi:
     · không có thứ bậc — "Xác nhận tham dự" (thứ quyết định mua) và "Thả tim
       ảnh" (thứ có cũng được) cùng cỡ chữ, cùng khung;
     · icon chỉ DÁN NHÃN tính năng chứ không CHO THẤY nó, trong khi điểm mạnh
       duy nhất của trang là "web thật";
     · 8 mục rời vượt ngưỡng quét mắt, trên điện thoại thành tường 2×4.

   Xếp lại theo đúng dòng thời gian của cặp đôi: khách mở thiệp -> những ngày
   chờ -> ngày cưới và sau đó. 8 mục gom còn 3 nhóm, và mạch kết ở "đọc lại
   nhiều năm sau" chứ không kết ở chỗ liệt kê nốt.
   -------------------------------------------------------------------------- */

/* Icon khối Tính năng. Trước đây dùng chung với khối Cam kết; khối đó đã xoá
   ngày 21/08/2026 vì trùng hoàn toàn với khối Quy trình. */
.feature__icon {
  width: 32px;
  height: 32px;
  /* Icon vẽ bằng nét, không tô: nhũ vàng mảnh giữ được vẻ thanh, tô đặc sẽ
     thành mảng màu nặng và phá tông "ít mà chất". */
  fill: none;
  stroke: var(--c-gold);
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Ba nhãn nhóm đổi từ <p> sang <h3> ngày 15/08/2026 để trang có cấu trúc
   heading cho máy tìm kiếm đọc — trước đó cả khối chỉ có đúng một <h2>.
   Hình thức phải KHÔNG đổi một chút nào: .eyebrow đã lo cỡ chữ, bộ chữ, giãn
   chữ và màu; ba thứ dưới đây là phần <h3> mang theo từ quy tắc tiêu đề chung
   mà .eyebrow không phủ tới. */
.act__eyebrow {
  line-height: var(--lh-snug);
  font-variation-settings: normal;
  letter-spacing: var(--ls-wide);
}

.acts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3xl);
}

.act {
  display: grid;
  gap: var(--sp-xl);
  align-items: center;
}

/* --- Khung ảnh: điện thoại, không phải thẻ ---
   Mỗi hồi lấy ảnh từ MỘT khuôn khác nhau. Không nói ra, nhưng ba lần thấy ba
   phong cách khác nhau là ba lần nhắc "bảy mẫu" và "web thật". */
.act__shot {
  position: relative;
  margin: 0;
  border-radius: 14px;
  overflow: hidden;
  background-color: var(--c-surface-warm);
  /* Viền tóc bên trong + bóng đổ. Viền là thứ BẮT BUỘC, không phải trang trí:
     ảnh chụp của mẫu Minimalist là kem nhạt trên nền kem — đo được chênh đúng
     7/255 so với nền trang, tức tấm ảnh tàng hình, cụm ba tấm nhìn ra chỉ còn
     hai. Bóng đổ không cứu được vì nó chỉ nằm quanh mép.
     Dùng inset box-shadow chứ không outline: nó ăn theo border-radius ở mọi
     trình duyệt, outline thì tuỳ phiên bản. */
  box-shadow:
    inset 0 0 0 1px rgba(42, 38, 34, 0.14),
    0 14px 34px rgba(42, 38, 34, 0.22);
}

.act__shot img {
  display: block;
  width: 100%;
  height: auto;
}

.act__body { min-width: 0; }

/* Câu dẫn của hồi: chữ hiển thị, cỡ nhỉnh hơn phần liệt kê bên dưới — đây là
   chỗ kể chuyện, còn danh sách chỉ là chỗ tra. */
.act__line {
  font-family: var(--ff-display);
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: var(--lh-tight);
  font-variation-settings: "opsz" 96;
  margin-top: var(--sp-2xs);
  margin-bottom: var(--sp-lg);
  text-wrap: balance;
}

/* Danh sách tính năng trong hồi: tên đậm đứng trước để LIẾC là thấy, mô tả
   nhạt hơn theo sau. Người đi tìm "có RSVP không?" phải bắt được bằng mắt mà
   không cần đọc cả câu. */
.act__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--sp-md);
}

.act__item {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  gap: var(--sp-sm);
  align-items: start;
}

.act__item .feature__icon {
  width: 22px;
  height: 22px;
  margin: 2px 0 0;
}

.act__name {
  display: block;
  font-weight: 600;
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
}

.act__desc {
  display: block;
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  color: var(--c-ink-soft);
}

/* --- MOBILE: MỘT CỤM ẢNH + BẢNG KÊ ---

   Đo bản cũ: khối này cao 2.736px = 3,2 màn hình, chiếm 22% cả trang và dài
   hơn khối bảng giá 65%. Riêng ba tấm ảnh ăn 1.401px — quá nửa khối.

   Vì sao cắt được: từ 13/08/2026 khối danh mục đã có nút mở DEMO THẬT. Ai bấm
   "Mở thiệp" là thấy đủ tám tính năng đang chạy sống. Nên nhiệm vụ của khối
   này không còn là CHỨNG MINH nữa mà là BẢO ĐẢM ĐỦ — đúng như tiêu đề nó tự
   nói. Một lời bảo đảm đọc trong một cái liếc, không cần ba màn ảnh chụp.

   Vẫn giữ MỘT cụm ảnh chứ không bỏ sạch: NN/g đo được 84% người chỉ quét chứ
   không đọc, và thứ phá được kiểu quét F là tín hiệu thị giác. Một khối toàn
   chữ sẽ bị lướt qua.

   Ba ảnh cũ không bị thay bằng asset mới — chúng được xoè thành một cụm ba
   màn hình chồng chéo, cùng ngôn ngữ với bố cục ghép ở khối danh mục.
   DOM không đổi một dòng: desktop vẫn đọc ra ba hồi như cũ. */
@media (max-width: 899px) {
  .acts {
    position: relative;
    gap: var(--sp-xl);
  }

  /* Ô giữ chỗ cho cụm ảnh. Dùng aspect-ratio chứ không px cứng để chiều cao
     tự co theo bề ngang máy — ba tấm ảnh bên dưới cũng ăn theo phần trăm. */
  .acts::before {
    content: "";
    display: block;
    width: 100%;
    /* Từ khi tấm giữa hạ xuống 52%, tấm CHẠM ĐÁY SÂU NHẤT không còn là nó nữa
       mà là hai tấm bên: tuy hẹp hơn nhưng chúng bị đẩy xuống 34px và xoay 7 độ.
       Đo ở máy 390 (khung .acts rộng 350): hai tấm bên chạm 248px, tấm giữa
       243px. Lấy 0,755 -> 264px, dư 16px cho bóng đổ, đúng mức dư của bản cũ. */
    aspect-ratio: 1 / 0.755;
    margin-bottom: var(--sp-md);
  }

  /* Ba tấm xoè như bộ bài, nhưng KHÔNG bằng vai nhau: tấm giữa nhỉnh hơn một
     chút (52% so với 44%) để mắt biết đâu là tấm chính, hai tấm kia lùi ra sau.

     52% chứ không phải 68% như bản trước: ở 68% tấm giữa che của mỗi tấm bên
     gần hai phần ba, cụm ba tấm nhìn ra chỉ còn một tấm rưỡi. Hạ xuống 52% thì
     mỗi tấm bên hở ra 55% thân mình thay vì 36% — vẫn thấy rõ thứ bậc mà không
     nuốt mất hai tấm sau.

     Bản 68% cũ sinh ra khi tấm giữa là ảnh trang quản trị, cần cỡ lớn mới đọc
     nổi bốn con số bé. Giờ tấm giữa là màn mở thiệp: dấu sáp và tên cặp đôi là
     hình khối lớn, thu nhỏ vẫn nhận ra, nên không cần ưu ái bề ngang nữa.

     Lệch dọc dùng px cứng chứ không phần trăm: top:% của phần tử tuyệt đối
     tính theo chiều cao .acts — mà .acts cao bao nhiêu lại tuỳ số mục trong
     bảng kê. Thêm một tính năng là cụm ảnh tự lệch, đúng lỗi đã xảy ra khi
     thêm mục thứ 9. */
  .act__shot {
    position: absolute;
    top: 34px;
    width: 46%;
    margin: 0;
    opacity: 0.88;
  }

  /* Bóng đậm hơn bản gốc: hai tấm này nằm trên nền kem và một trong hai là
     ảnh kem nhạt, cần mép tối rõ hơn mới đọc ra là "có một tấm nữa ở đây". */
  .act:nth-child(1) .act__shot,
  .act:nth-child(3) .act__shot {
    box-shadow:
      inset 0 0 0 1px rgba(42, 38, 34, 0.16),
      0 10px 26px rgba(42, 38, 34, 0.26);
  }

  /* Hai tấm bên nằm TRỌN trong khung, không tràn ra ngoài mép nữa.
     Lý do: khi tấm 3 tràn ra (left 62% + rộng 46% = chạm 108%), phần nhìn
     thấy của nó là GIỮA THÂN ảnh còn mép phải thì ở ngoài màn hình. Ảnh mẫu
     Minimalist vốn kem nhạt, giữa thân không có cạnh nào — đo được chênh đúng
     7/255 với nền trang, tức tấm ảnh biến mất, cụm ba tấm nhìn ra chỉ còn hai.
     Kéo vào 0% và 56% thì mỗi tấm hở ra một CẠNH thật, có viền và bóng — mắt
     đọc ngay ra "còn một tấm nữa ở đây" dù ruột ảnh nhạt màu. */
  .act:nth-child(1) .act__shot { left: 0;   width: 44%; z-index: 1; transform: rotate(-7deg); }
  .act:nth-child(3) .act__shot { left: 56%; width: 44%; z-index: 2; transform: rotate(7deg); }

  .act:nth-child(2) .act__shot {
    left: 24%;
    top: 0;
    width: 52%;
    z-index: 3;
    opacity: 1;
    /* Bóng sâu + một quầng nhũ vàng rất loe: tấm ảnh bật hẳn khỏi nền kem và
       trông như được rọi đèn, thay vì dán phẳng lên trang. Dùng box-shadow chứ
       không thêm thẻ phát sáng riêng — lớp ảnh đang overflow:hidden nên mọi
       thứ vẽ bên trong đều bị cắt. */
    box-shadow:
      inset 0 0 0 1px rgba(42, 38, 34, 0.14),
      0 18px 44px rgba(42, 38, 34, 0.30),
      0 0 60px -10px rgba(176, 141, 87, 0.50);
  }

  /* Câu dẫn của từng hồi là chữ hiển thị cỡ h3, ba câu ăn gần 180px và cắt
     ngang nhịp quét của bảng kê. Mạch ba hồi vẫn còn nguyên ở ba cái nhãn
     nhỏ phía trên mỗi nhóm — giữ được câu chuyện với 4% chi phí. */
  .act__line { display: none; }

  .act__body { margin-top: calc(var(--sp-xs) * -1); }

  /* .act mang class .reveal, mà .reveal dùng transform: translateY(18px) để
     trượt lên khi hiện. Một phần tử CÓ TRANSFORM sẽ trở thành khung neo cho
     mọi con định vị tuyệt đối — nên ba tấm ảnh bám vào ba .act khác nhau thay
     vì vào .acts, và xoè ra cách nhau gần 500px thay vì chồng lên nhau.

     Bỏ phần trượt CHỈ cho ba mục này trên mobile; hiệu ứng hiện dần vẫn còn
     nguyên vì nó chạy bằng opacity, không phải transform. */
  .act.reveal { transform: none; }
}

@media (min-width: 900px) {
  .act {
    grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr);
    gap: var(--sp-3xl);
  }

  /* Xen kẽ trái–phải để mắt có nhịp: ba hồi cùng một bên thì đọc như một bảng
     biểu. Đổi thứ tự bằng grid-column chứ không đổi thứ tự trong HTML — trình
     đọc màn hình và bàn phím vẫn đi đúng mạch ảnh trước, chữ sau.

     PHẢI đảo cả kích thước cột theo. Chỉ đổi grid-column mà giữ nguyên
     0.62fr–1fr thì ở hồi chẵn tấm ảnh rơi vào cột rộng còn chữ bị nhét vào cột
     hẹp — hai hồi cạnh nhau lệch hẳn tỉ lệ. */
  .act:nth-child(even) { grid-template-columns: minmax(0, 1fr) minmax(0, 0.62fr); }
  .act:nth-child(even) .act__shot { grid-column: 2; grid-row: 1; }
  .act:nth-child(even) .act__body { grid-column: 1; grid-row: 1; }

  /* Hai cột cho hồi nào có từ 3 tính năng trở lên, khỏi thành một cột dài
     lêu nghêu bên cạnh tấm ảnh cao. */
  .act__list--doi { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-lg); }
}

/* --------------------------------------------------------------------------
   13. QUY TRÌNH 4 BƯỚC (T5)
   -------------------------------------------------------------------------- */
.process-list {
  display: grid;
  gap: var(--sp-xl);
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: none;
}

.process-step {
  position: relative;
  padding-left: 60px; /* chừa chỗ cho vòng số + đường nối bên trái */
}

.process-step__num {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--c-line-strong);
  border-radius: 50%;
  background-color: var(--c-cream);
  font-family: var(--ff-display);
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--c-gold);
  /* Cormorant mặc định dùng chữ số kiểu cũ (cao thấp so le) — đẹp trong đoạn văn
     nhưng làm bốn con số mốc trông lệch nhau. Ép về chữ số đều hàng. */
  font-variant-numeric: lining-nums;
}

/* Đường nối mảnh chạy dọc giữa các mốc — dấu hiệu "một dòng chảy", cho thấy
   quy trình liền mạch chứ không phải bốn việc rời rạc. */
.process-step::before {
  content: "";
  position: absolute;
  left: 20px;
  top: 46px;
  bottom: calc(var(--sp-xl) * -1 - 6px);
  width: 1px;
  background-color: var(--c-line);
}
.process-step:last-child::before { display: none; }

.process-step__name {
  font-family: var(--ff-body);
  font-size: var(--fs-body);
  font-weight: 600;
  letter-spacing: 0;
  margin-bottom: var(--sp-2xs);
}

.process-step__desc {
  font-size: var(--fs-sm);
  color: var(--c-ink-soft);
  line-height: var(--lh-snug);
}

/* Desktop: bốn mốc nằm ngang, đường nối chuyển thành đường ngang chạy qua các số */
@media (min-width: 900px) {
  .process-list {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--sp-xl);
  }

  .process-step {
    padding-left: 0;
    padding-top: 60px;
  }

  .process-step::before {
    left: 46px;
    /* Kéo dài qua khe gap sang mốc kế tiếp; -1px để đường chạm sát vòng số sau */
    right: calc(var(--sp-xl) * -1 - 1px);
    top: 20px;
    bottom: auto;
    width: auto;
    height: 1px;
  }
}

/* --------------------------------------------------------------------------
   14. BẢNG GIÁ (T6)
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   LỚP 1+2 · NỀN KHỐI GIÁ
   Bản trước dùng đúng #2B2723 phẳng tuyệt đối — trùng y hệt khối liên hệ và
   footer. Ba mảng tối cùng một tông, nên khối quan trọng nhất trang không có
   dấu hiệu thị giác nào của riêng nó. Đo được: khối này chỉ chiếm 8,4% chiều
   dài trang và ngắn hơn khối liền kề 2,3 lần.

   KHÔNG kéo nó dài ra — ở 880px nó lọt TRỌN một màn desktop, giá và nút cùng
   trong tầm mắt, đó là thứ hiếm không được đánh đổi. Chỉ làm nó KHÁC ĐI.

   Ba lớp chồng lên cùng một mã màu: dải tan xuống nền kem ở đáy (đỉnh giữ cắt
   phũ — cú cắt đó là "bước vào phòng tối", nó đang làm việc tốt), quầng đèn
   rọi, và hạt phim. Không thêm file nào: hạt phim là data-URI y hệt .hero__grain.
   -------------------------------------------------------------------------- */
.pricing {
  position: relative;
  isolation: isolate;
  /* BẮT BUỘC: khung tia sáng tràn ra hai mép (inset: 0 -45%) để skewX không để
     lộ tam giác trống ở góc. Không chặn ở đây thì phần tràn đó đẩy chiều rộng
     tài liệu ra và CẢ TRANG cuộn ngang được — đã đo thấy đúng lỗi này. */
  overflow: hidden;
  /* PHƯƠNG ÁN A · SÂN KHẤU ĐEN (20/08/2026).
     Đo bản trước: nền khối L* 15,9 · thân thẻ L* 12,1 -> chênh 3,9, trong khi
     mắt cần khoảng 8 mới đọc ra một mép rõ. Nguyên nhân gốc: thẻ đang TỐI HƠN
     nền, nên nửa dưới nó chìm hẳn xuống. Thẻ mẫu ở 21st.dev làm ngược lại —
     nền gần đen tuyệt đối, thẻ sáng hơn nền.

     Hạ riêng khối này xuống #15110E còn được thêm một thứ: bốn khối tối của
     trang vốn dùng chung #2B2723 (hero · bảng giá · liên hệ · footer). Giờ khối
     giá thành mảng tối SÂU NHẤT trang, tự tách khỏi ba khối kia. */
  background-color: #15110E;
  /* Vũng sáng góc trên-trái + lưới chấm rất mờ, hai lớp lấy từ mẫu Elegant Dark
     Pattern. Bản gốc dùng xám trung tính rgb(46,46,46) và chấm trắng 50%; ở đây
     đổi sang xám ẤM và chấm kem rất nhạt — xám trung tính trên trang toàn kem
     với nhũ vàng sẽ đọc ra một mảng chì lạc lõng.
     Lớp hạt nhiễu của bản gốc nạp một PNG từ framerusercontent.com; bỏ, vì
     trang này đã có hạt phim dựng bằng feTurbulence inline — không thêm một
     request nào, mà lại không phụ thuộc máy chủ của bên thứ ba. */
  background-image:
    radial-gradient(circle at 1px 1px, rgba(247, 243, 236, 0.055) 1px, transparent 0),
    radial-gradient(125% 100% at 0% 0%, rgba(96, 84, 68, 0.34) 0%, transparent 72%);
  background-size: 22px 22px, auto;
}

/* Dải tan ở đáy sang nền kem ấm của khối quy trình. Tách ra một phần tử riêng
   chứ không nhập vào chồng nền của .pricing: nó phải nằm TRÊN cả tia sáng lẫn
   hạt phim, nếu không mấy lớp đó vẽ đè lên dải tan và chỗ giao với khối dưới
   lại hiện thành một đường kẻ. */
.pricing::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 100px;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent, var(--c-surface-warm));
}

/* Quầng đèn rọi. Lệch lên trên vì con số nằm ở nửa trên của thẻ. */
.pricing__glow {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  /* Hạ từ 0,13 xuống 0,05 sau khi thẻ tự có quầng riêng ở đỉnh: hai nguồn sáng
     cùng độ mạnh thì cả khối bị rửa thành một mảng nâu đục, và thẻ mất hẳn vai
     "vật duy nhất được rọi". Giữ lại một chút để vùng sau thẻ không chết cứng. */
  background: radial-gradient(
    70% 55% at 50% 38%,
    rgba(176, 141, 87, 0.05),
    transparent 62%
  );
}
/* .reveal mặc định mờ-và-trượt-lên; ở đây thay bằng nở ra, chậm hơn thẻ một
   nhịp để mắt kịp thấy đèn bật rồi mới thấy vật được rọi. */
.pricing__glow.reveal {
  opacity: 0;
  transform: scale(0.92);
  transition:
    opacity 1.4s var(--ease) 0.2s,
    transform 1.4s var(--ease) 0.2s;
}
.pricing__glow.reveal.is-in { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------
   TIA SÁNG XIÊN — port từ "Elegant Dark Pattern"
   Mỗi tia: một dải nhũ vàng nhạt dần từ trên xuống, bị mask ngang cắt thành
   những vệt rộng hẹp không đều, rồi cả khối nghiêng 45 độ.
   Khung tia phải tràn ra ngoài khối (inset âm) vì skewX kéo hình chéo đi, không
   nới ra thì hai mép trái phải lộ tam giác trống.
   -------------------------------------------------------------------------- */
.pricing__rays {
  position: absolute;
  inset: 0 -45%;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  /* LỚP TÔI BỎ SÓT Ở BẢN TRƯỚC. Bản gốc bọc năm tia trong một thẻ cha có mask
     radial từ góc trên-trái, nên tia mạnh ở góc đó rồi TAN DẦN khi ra xa. Tôi
     chỉ lấy cái radial ấy làm nền cho .pricing mà quên nó còn là mask của cụm
     tia — thiếu nó thì tia sáng đều khắp khối, và khi đủ mạnh để nhìn thấy thì
     nó rọi luôn lên chỗ đặt thẻ, làm thẻ chìm trở lại (đo được: chênh L* tụt
     từ 9,6 xuống 5,7) và kéo đoạn dẫn xuống 4,53:1, sát ngưỡng AA.
     Có mask thì ánh sáng vẫn thấy rõ ở nửa trên-trái mà vùng quanh thẻ bên
     phải giữ được độ tối. */
     Bán kính ngang phải tính theo KHUNG TIA chứ không theo khối: khung rộng 190%
     khối (inset -45% hai bên), nên "125%" hoá ra ~3400px — gần như không tắt,
     ánh sáng tràn sang tận cột phải và rọi thẳng lên chỗ đặt thẻ. Đo được: nền
     ngay cạnh mép TRÊN của thẻ sáng L* 17-19, tức phần đầu thẻ (tên gói + con
     số, chỗ mắt bắt vào trước nhất) gần như không tách khỏi nền.
     32% khung = ~880px: sáng gom trong nửa trái nơi có phần kể chuyện, tắt hẳn
     trước cột phải. */
  -webkit-mask-image: radial-gradient(38% 115% at 22% 0%, #000 0%, rgba(0,0,0,0.30) 55%, transparent 85%);
  mask-image: radial-gradient(38% 115% at 22% 0%, #000 0%, rgba(0,0,0,0.30) 55%, transparent 85%);
}
.pricing__ray {
  position: absolute;
  inset: 0;
  transform: skewX(45deg);
  /* Màu ĐỤC HOÀN TOÀN ở đỉnh rồi tan xuống đáy, cường độ do opacity của lớp
     quyết định — đúng cấu trúc bản gốc. Bản trước tôi vừa hạ alpha của màu
     xuống 0,55 vừa hạ opacity xuống 0,14, thành đỉnh 0,077: yếu hơn bản gốc
     2,6 lần, nên ánh sáng từ trên rọi xuống có trong mã mà không thấy trên màn.
     Về đúng 0,20 như bản gốc. Ba lớp chồng vẫn nhẹ hơn năm lớp của bản gốc. */
  background: linear-gradient(rgb(216, 188, 139) 0%, rgba(216, 188, 139, 0) 100%);
  opacity: 0.2;
}
/* Ba mask ngang khác nhau -> ba nhịp vệt lệch nhau, chồng lên thành ánh sáng
   loang không đều. Dùng đúng cách bản gốc làm, chỉ rút từ năm lớp xuống ba. */
.pricing__ray--1 {
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 20%, transparent 36%, #000 55%, rgba(0,0,0,0.13) 67%, #000 78%, transparent 97%);
  mask-image: linear-gradient(90deg, transparent 0%, #000 20%, transparent 36%, #000 55%, rgba(0,0,0,0.13) 67%, #000 78%, transparent 97%);
}
.pricing__ray--2 {
  -webkit-mask-image: linear-gradient(90deg, transparent 11%, #000 25%, rgba(0,0,0,0.55) 41%, rgba(0,0,0,0.13) 67%, #000 78%, transparent 97%);
  mask-image: linear-gradient(90deg, transparent 11%, #000 25%, rgba(0,0,0,0.55) 41%, rgba(0,0,0,0.13) 67%, #000 78%, transparent 97%);
}
.pricing__ray--3 {
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 17%, rgba(0,0,0,0.55) 26%, #000 35%, transparent 47%, rgba(0,0,0,0.13) 69%, #000 79%, transparent 97%);
  mask-image: linear-gradient(90deg, transparent 0%, #000 17%, rgba(0,0,0,0.55) 26%, #000 35%, transparent 47%, rgba(0,0,0,0.13) 69%, #000 79%, transparent 97%);
}

/* Hạt phim: làm mảng tối bớt chết, thành mặt nhung thay vì mặt sơn. */
.pricing::after {
  content: "";
  position: absolute;
  /* Dừng trước dải tan 100px ở đáy. Để hạt chạy hết khối thì 100px cuối có hạt
     phủ lên nền kem, trong khi khối quy trình ngay dưới không có — chênh lệch
     bề mặt đó hiện thành một đường kẻ ngang ngay chỗ đáng lẽ phải liền mạch. */
  inset: 0 0 100px;
  z-index: 0;
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Nội dung phải nổi lên trên hai lớp nền */
.pricing__inner { position: relative; z-index: 1; }

/* Bố cục hai cột lệch trên desktop: trái kể chuyện, phải là lời chào giá.
   Bản cũ để MỘT thẻ 460px giữa một biển kem rộng 1200 — thẻ trôi lơ lửng, cả
   khối không có sức nặng nào. Chia hai cột thì mắt đọc đúng thứ tự cần đọc:
   hiểu vì sao -> thấy giá -> bấm. Mobile vẫn xếp dọc. */
.pricing__inner {
  display: flex;
  flex-direction: column;
  gap: var(--sp-xl);
}

@media (min-width: 940px) {
  /* Hai hàng 1fr + align-self end/start đã bỏ cùng lúc với dòng Atelier: cơ chế
     đó tồn tại chỉ để kẹp cụm chữ trái vào giữa thẻ khi cột trái có HAI khối
     nằm ở hai hàng. Cột trái giờ còn một khối, giữ lại thì nó dính đáy nửa trên
     và chừa một mảng trống dưới. Một hàng + align-items:center cho đúng kết quả
     mong muốn bằng ít luật hơn. */
  .pricing__inner {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 460px;
    gap: 0 var(--sp-3xl);
    align-items: center;
  }
}

.pricing__intro { text-align: center; }

@media (min-width: 940px) {
  .pricing__intro { text-align: left; }
}

/* --------------------------------------------------------------------------
   Tiêu đề hiện theo dòng
   Cùng cơ chế .hero__line/.hero__line-in: mỗi dòng là một khung cắt, phần chữ
   bên trong nằm sẵn dưới đáy rồi trượt lên. Hai khối quan trọng nhất trang vì
   thế chuyển động cùng một ngôn ngữ.
   -------------------------------------------------------------------------- */
.pricing__title {
  margin-top: var(--sp-sm);
  text-wrap: balance;
}
/* h2 mang .reveal chỉ để BỘ QUAN SÁT gắn .is-in cho nó — phần nhìn thấy do hai
   màn cắt bên trong lo. Vô hiệu hoá lớp mờ-và-trượt mặc định của .reveal, nếu
   không cả khối chữ vừa mờ dần vừa trượt lên trong khi từng dòng cũng đang
   trượt: hai chuyển động chồng nhau, đọc ra rung chứ không ra mượt. */
.pricing__title.reveal {
  opacity: 1;
  transform: none;
  transition: none;
}

.pricing__line {
  display: block;
  overflow: hidden;
  /* Fraunces có phần nhô dưới ở g/y; chừa 0,08em kẻo màn cắt xén mất đuôi chữ */
  padding-bottom: 0.08em;
  margin-bottom: -0.08em;
}
.pricing__line-in {
  display: block;
  transform: translateY(105%);
  transition: transform 0.8s var(--ease);
}
.pricing__title.is-in .pricing__line-in { transform: none; }
/* Dòng hai chờ dòng một đi được một nửa rồi mới lên — đọc thành một câu chảy,
   không phải hai mảnh bật ra cùng lúc. */
.pricing__title.is-in .pricing__line:nth-child(2) .pricing__line-in {
  transition-delay: 0.12s;
}
.no-js .pricing__line-in { transform: none; }

/* --------------------------------------------------------------------------
   THẺ GIÁ — dựng theo mẫu thẻ "Pro $99" (21st.dev / mikolajdobrucki)
   Thẻ TỐI với quầng ấm dồn ở đỉnh rồi tan xuống đáy, chữ CĂN TRÁI, và nút đặt
   ngay dưới giá thay vì tận đáy.
   -------------------------------------------------------------------------- */
.price-card {
  position: relative;
  max-width: 460px;
  width: 100%;
  margin-inline: auto;
  padding: var(--sp-xl);
  border-radius: var(--r-lg);
  text-align: left;
  color: var(--c-cream);
  /* Viền vẽ bằng một lớp nền gradient chứ không phải border-color: viền một sắc
     đều tăm tắp đọc ra đường kẻ in, còn nhũ thật thì sáng ở mép hứng đèn.
     Quầng sáng ở đỉnh KHÔNG nằm trong chồng nền này nữa — xem .price-card::before. */
  border: 1px solid transparent;
  /* Thân thẻ: GỖ ÓC CHÓ ĐÁNH BÓNG, sáng ở đỉnh rồi trầm xuống đáy — không phải
     một mảng phẳng nữa. Bản trước để #2E2822 phẳng, chỉ hơn nền khối 11,2 L*:
     đủ để máy đo báo "tách", nhưng cùng một sắc nâu-đen với nền nên mắt vẫn đọc
     ra MỘT mặt phẳng hơi loang, không ra một vật đặt trên mặt bàn.
     Đỉnh #4A4038 hơn nền 22,5 L*, đáy #362E27 hơn 14,2 — gấp đôi khoảng cách cũ
     ở mép trên, chỗ mắt bắt vào thẻ đầu tiên. Chính độ dốc trong thân thẻ mới là
     thứ dựng khối: một vật có mặt hứng sáng và mặt khuất, nền thì không.
     Kiểm lại chữ trên nền sáng nhất (#4A4038): kem 9,12:1 · chữ phụ 6,07:1 ·
     vàng "đ" 5,52:1 · kẻ ngang chênh 13,5 L*. Đều còn dư trên ngưỡng AA. */
  background-image:
    linear-gradient(180deg, #4A4038 0%, #3E352D 46%, #362E27 100%),
    linear-gradient(180deg, rgba(214, 186, 138, 0.85) 0%, rgba(176, 141, 87, 0.26) 48%, rgba(138, 106, 60, 0.16) 100%);
  background-origin: border-box;
  background-clip: padding-box, border-box;
  /* Bóng đổ sâu hơn (0,45 -> 0,58): thẻ càng sáng thì càng cần bóng dày để không
     trôi lơ lửng, và chính viền bóng tối quanh thẻ mới cắt nó khỏi nền. */
  box-shadow:
    0 2px 6px rgba(0, 0, 0, 0.30),
    0 30px 70px rgba(0, 0, 0, 0.58);
  isolation: isolate;
  overflow: hidden;
}

@media (min-width: 700px) {
  .price-card { padding: var(--sp-2xl); }
}

/* --------------------------------------------------------------------------
   QUẦNG ĐỈNH THẺ — "cơ chế 1", port từ thẻ Pro $99 của Mikolaj Dobrucki.

   Bản trước tôi vẽ quầng bằng radial-gradient NGAY TRONG chồng nền của thẻ.
   Sai mô hình: gradient bao giờ cũng có một chỗ "hết" (transparent 62%), mắt
   bắt được cái biên đó và đọc ra MỘT MẢNG MÀU ĐƯỢC TÔ, không đọc ra một vật
   đang bị chiếu sáng.

   Bản gốc làm ngược: đặt hẳn một NGUỒN SÁNG ở NGOÀI thẻ rồi để overflow:hidden
   của thẻ xén đi. Hình bầu dục cao 128px nằm trọn phía trên mép thẻ (top:-128px,
   height:128px — mép dưới của nó chạm đúng mép trên vùng padding), nên phần
   ĐẶC của nó không bao giờ hiện; thứ lọt vào trong thẻ chỉ là cái đuôi nhoè của
   blur(72px). Đo trên bản gốc: trên mép thẻ 4px vẫn là nền nguyên vẹn L* 2,7,
   dưới mép thẻ 2px đã là L* 31,8 — cắt gãy gọn ở đúng đường viền, rồi tắt mềm
   theo đường Gauss xuống dưới.

   Hệ quả cần biết: HIỆU ỨNG NÀY SỐNG NHỜ blur. Không có filter thì hình bầu dục
   nằm trọn ngoài vùng xén và không hiện gì cả — mất quầng, không vỡ bố cục.
   blur() có từ Chrome 18 / Safari 9.1 / Firefox 35 nên không cần dự phòng.

   PHẢI NỚI HÌNH HỌC so với bản gốc, và đây là lý do — không phải tuỳ hứng.
   Bản gốc dùng top:-128 / height:128 / blur:72 trên một thân thẻ TỐI (L* 6,8).
   L* là thang căn bậc ba: đổ một chút sáng lên gần-đen thì L* nhảy rất nhiều,
   nên đuôi nhoè mảnh của họ vẫn đọc được tới +100px. Thân thẻ mình đã sáng sẵn
   L* 27,4 — cùng lượng sáng ấy gần như không nhúc nhích. Đo bằng đúng thông số
   bản gốc: đuôi sáng chết hẳn ở +160px, mới bằng một phần ba chiều cao thẻ, nên
   thẻ đọc ra "hơi sáng ở mép" chứ không ra "đang bị chiếu".
   Nới lên -150 / 170 / blur 110 (nguồn to hơn, đặt xa hơn, nhoè rộng hơn) thì
   đuôi kéo tới +340px, phủ hai phần ba thẻ:
     +10: 36,6 · +30: 35,2 · +60: 33,1 · +100: 30,1 · +160: 26,4 · +340: 21,8
   Đây là dịch cho đúng CẢM GIÁC của bản gốc trên một nền sáng hơn, không phải
   chép số. Muốn dùng lại đúng số của họ thì phải hạ tối thân thẻ trước
   (cơ chế 3), hai thứ đó đi liền nhau.

   Kiểm biên: ngoài mép thẻ 3px vẫn là L* 5,4 (nền nguyên vẹn), trong mép 10px
   đã 36,6 — cắt gãy gọn đúng đường viền, không rò một chút nào ra ngoài.
   -------------------------------------------------------------------------- */
.price-card::before {
  content: "";
  position: absolute;
  top: -150px;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  height: 170px;
  z-index: 0;
  pointer-events: none;
  border-radius: 50%;
  background-color: rgba(216, 188, 139, 0.9);
  filter: blur(110px);
}

.price-card > * { position: relative; z-index: 1; }

/* Vệt nhũ quét ngang MỘT LẦN khi thẻ vào màn. Không lặp: hàng cao cấp không
   nhấp nháy. */
.price-card::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    transparent 38%,
    rgba(255, 255, 255, 0.16) 50%,
    transparent 62%
  );
  transform: translateX(-120%);
  opacity: 0;
}
.price-card.is-in::after { animation: quet-nhu 1.1s var(--ease) 0.35s 1 both; }
@keyframes quet-nhu {
  0%   { transform: translateX(-120%); opacity: 0; }
  18%  { opacity: 1; }
  100% { transform: translateX(120%); opacity: 0; }
}

/* --- Tên gói + con dấu, hàng đầu tiên như thẻ mẫu --- */
.price-card__plan {
  font-family: var(--ff-display);
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--c-cream);
}

/* --- Con số --- */
.price-card__price {
  display: flex;
  align-items: baseline;
  gap: 0.14em;
  /* Dòng mô tả dưới tên gói đã gỡ, nên khoảng cách này giờ tính từ chính tên
     gói — nới lên sp-xl kẻo con số dính sát hàng chữ nhỏ phía trên. */
  margin-top: var(--sp-xl);
  font-family: var(--ff-display);
  font-size: clamp(2.6rem, 0.6rem + 9vw, 4.25rem);
  /* Nét 400 ở opsz 144: chân chữ mảnh và dài hẳn ra, ra dáng chữ KHẮC. Nét 600
     ở cỡ 68px đọc ra nặng và "phần mềm". Hero dùng đúng chiêu này. */
  font-weight: 400;
  font-variation-settings: "opsz" 144;
  line-height: 1;
  color: var(--c-cream);
  font-variant-numeric: lining-nums tabular-nums;
}
.price-card__mask {
  display: inline-block;
  overflow: hidden;
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}
.price-card__amount {
  display: inline-block;
  letter-spacing: -0.02em;
  transform: translateY(105%);
  transition: transform 0.85s var(--ease) 0.15s;
}
.price-card.is-in .price-card__amount { transform: none; }
.no-js .price-card__amount { transform: none; }

/* Đơn vị nhỏ hơn hẳn nhưng ĐỨNG TRÊN CÙNG ĐƯỜNG CHÂN với số: thả lên ngang vai
   thì ở cỡ đó nó đọc ra dấu chú thích (*) chứ không ra tiền tệ. Trên nền tối
   phải dùng --c-gold-on-dark, sắc vàng trầm không đủ tương phản.
   Giữ nguyên 0,38em như hồi còn chữ "đ" theo yêu cầu. Nhưng "VND" là BA CHỮ HOA,
   không phải một chữ thường: cần khe hở rộng hơn (0,04em -> 0,14em, đặt ở
   .price-card__price) kẻo nó dính vào số 0 cuối và đọc thành "000VND", cộng một
   chút giãn chữ cho ra dáng mã tiền tệ chứ không ra một từ viết tắt. */
.price-card__unit {
  font-size: 0.38em;
  line-height: 1;
  letter-spacing: 0.04em;
  color: var(--c-gold-on-dark);
}

/* Hai dòng phụ ngay dưới giá, như "one-time payment / plus local taxes" */
.price-card__note {
  margin-top: var(--sp-sm);
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  color: var(--c-cream-soft);
}

/* --- Nút: NGAY DƯỚI GIÁ, không phải tận đáy thẻ --- */
.price-card__actions { margin-top: var(--sp-lg); }

/* --- Danh sách, sau kẻ ngang ---
   Phải viết .price-card .price-card__feats chứ không phải .price-card__feats.
   Bản reset ở đầu file có `ul[class], ol[class] { padding: 0 }` — trọng số
   0-1-1, CAO HƠN một class đơn 0-1-0 — nên mọi padding đặt trên .price-card__feats
   đều bị nuốt lặng lẽ. Không có cảnh báo nào: DevTools chỉ hiện padding-top bị
   gạch, mà mắt thì đọc ra "kẻ ngang dính vào dòng chữ đầu tiên".
   Đây là lý do thật của khoảng cách chật, không phải do trị số đặt thiếu. */
.price-card .price-card__feats {
  display: flex;
  flex-direction: column;
  gap: var(--sp-sm);
  margin-top: var(--sp-lg);
  /* Dưới kẻ rộng hơn trên (32 vs 24): phía trên kẻ là khối nút vàng đặc, một
     mảng nặng nên 24px cạnh nó đã đọc ra thoáng; phía dưới là ba dòng chữ 14px,
     cùng 24px ấy so với cỡ chữ nhỏ lại đọc ra chật. Khoảng cách bằng nhau về số
     đo không cho ra khoảng cách bằng nhau về mắt. */
  padding-top: var(--sp-xl);
  border-top: 1px solid var(--c-line-dark);
  list-style: none;
}
.price-card__feat {
  position: relative;
  /* Khoảng hở rộng hơn dấu gạch cũ (20px): dấu tích chiếm chỗ vuông chứ không
     phải một vạch ngang, và thẻ mẫu để chữ lùi hẳn ra cho thoáng. */
  padding-left: 26px;
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  color: var(--c-cream);
}

/* Dấu tích lấy từ thẻ mẫu: NÉT MẢNH, ĐẦU BO TRÒN, GÓC MỞ RỘNG — không phải dấu
   tích nhọn hẹp thường gặp. Vì thế không dùng mẹo hai cạnh viền xoay 45 độ như
   bảng giá cũ của trang: mẹo đó cho góc vuông sắc và chữ V hẹp, sai cả hai đặc
   điểm. Dùng SVG inline có stroke-linecap="round", vẫn là data-URI nên không
   thêm một request nào.
   Màu phải ghim cứng trong SVG (background-image không nhận currentColor);
   dùng --c-gold-on-dark #D8BC8B — đúng sắc vàng đang dùng cho đơn vị "đ". */
.price-card__feat::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.15em;
  width: 15px;
  height: 15px;
  background-repeat: no-repeat;
  background-size: 15px 15px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23D8BC8B' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 8.6 6.3 12.2 13.5 4.4'/%3E%3C/svg%3E");
}

/* LỚP 6 · NÚT KIM LOẠI. Vạch sáng ở mép trên làm mặt nút cong lên như thỏi kim
   loại hứng đèn; quầng loe khiến nút tự phát sáng — mắt tìm thấy nó trước mọi
   thứ khác trong thẻ. Cả hai chỉ là box-shadow, không thẻ mới. */
.price-card__cta {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.28),
    0 0 40px -12px rgba(176, 141, 87, 0.9),
    var(--sh-sm);
}
.price-card__cta:hover {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.34),
    0 0 52px -10px rgba(176, 141, 87, 1),
    var(--sh-md);
}
@media (min-width: 700px) {
  .price-card__cta { min-height: 52px; }
}

@media (hover: hover) {
  .price-card__cta { position: relative; overflow: hidden; }
  .price-card__cta::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
      100deg,
      transparent 40%,
      rgba(255, 255, 255, 0.28) 50%,
      transparent 60%
    );
    transform: translateX(-110%);
    transition: transform 0.6s var(--ease);
  }
  .price-card__cta:hover::after { transform: translateX(110%); }
}

/* Khối siết nhịp dọc trên mobile đã bỏ ngày 20/08/2026: trật tự mới đặt nút
   ngay dưới giá nên đoạn từ "đồng ý" tới "bấm" vốn đã ngắn, không cần cắt thêm
   khoảng thở — mà khoảng thở chính là thứ làm nên cảm giác đắt. */

/* Người tắt hiệu ứng: bỏ sạch vệt quét và mọi màn cắt, hiện thẳng. Khối chống
   chuyển động ở mục 2 đã rút thời lượng animation về 0,01ms nhưng KHÔNG đụng
   tới transform khởi điểm — không gỡ ở đây thì con số giá và hai dòng tiêu
   đề nằm chìm ngoài màn cắt vĩnh viễn. */
@media (prefers-reduced-motion: reduce) {
  .price-card__amount,
  .pricing__glow.reveal,
  .pricing__line-in { transform: none !important; transition: none !important; }
  .price-card::after { display: none; }
  .price-card__cta::after { display: none; }
}

/* --------------------------------------------------------------------------
   16. FAQ (T7)
   -------------------------------------------------------------------------- */
.faq-list {
  border-top: 1px solid var(--c-line);
}

.faq-item {
  border-bottom: 1px solid var(--c-line);
}

.faq-item__q {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-md);
  /* Vùng chạm cao rộng: câu hỏi ngắn cũng phải dễ bấm bằng ngón cái */
  padding: var(--sp-lg) 0;
  font-weight: 600;
  line-height: var(--lh-snug);
  cursor: pointer;
  list-style: none; /* bỏ tam giác mặc định của <summary> */
  transition: color var(--dur) var(--ease);
}
.faq-item__q::-webkit-details-marker { display: none; } /* Safari */

.faq-item__q:hover { color: var(--c-gold); }

/* Dấu cộng vẽ bằng hai vạch, xoay thành dấu trừ khi mở — nhẹ hơn nhúng icon,
   và chuyển động xoay cho thấy rõ trạng thái vừa đổi. */
.faq-item__q::after {
  content: "";
  flex: none;
  width: 14px;
  height: 14px;
  margin-top: 5px;
  background-image:
    linear-gradient(var(--c-gold), var(--c-gold)),
    linear-gradient(var(--c-gold), var(--c-gold));
  background-size: 14px 1.5px, 1.5px 14px;
  background-position: center;
  background-repeat: no-repeat;
  transition: transform var(--dur) var(--ease);
}
.faq-item[open] .faq-item__q::after {
  /* Vạch dọc co về 0 tạo cảm giác dấu cộng khép lại thành dấu trừ */
  transform: rotate(90deg);
  background-size: 14px 1.5px, 0 14px;
}

.faq-item__a {
  padding-bottom: var(--sp-lg);
  color: var(--c-ink-soft);
  max-width: var(--w-measure);
}

/* Câu trả lời trôi nhẹ xuống khi mở. <details> không co giãn chiều cao mượt
   được nếu không dựng lại bằng JS, nên chỉ làm phần fade — đủ mềm mà vẫn giữ
   toàn bộ ưu điểm sẵn có của thẻ gốc (bàn phím, trình đọc màn hình, tắt JS). */
@media (prefers-reduced-motion: no-preference) {
  .faq-item[open] .faq-item__a {
    animation: faq-in var(--dur) var(--ease);
  }
}

@keyframes faq-in {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------------------
   17. CTA CUỐI (T8)
   -------------------------------------------------------------------------- */
.cta-final__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-md);
  text-align: center;
}

.cta-final__title { max-width: 20ch; }

.cta-final__inner .btn { margin-top: var(--sp-md); }

.cta-final__note {
  font-size: var(--fs-sm);
  color: var(--c-cream-soft);
}

/* --------------------------------------------------------------------------
   18. FOOTER (T8)
   -------------------------------------------------------------------------- */
.site-footer {
  /* Nối liền khối CTA cuối: cùng nền tối, chỉ một đường kẻ mảnh phân cách để
     mắt không thấy hai mảng đen chồng nhau. */
  background-color: var(--c-dark);
  color: var(--c-cream);
  padding-block: var(--sp-2xl);
  border-top: 1px solid var(--c-line-dark);
}

.site-footer__top {
  display: grid;
  gap: var(--sp-xl);
  grid-template-columns: 1fr;
}

@media (min-width: 720px) {
  .site-footer__top {
    grid-template-columns: 1.6fr 1fr 1.2fr;
    gap: var(--sp-2xl);
  }
}

.site-footer__tagline {
  margin-top: var(--sp-xs);
  max-width: 34ch;
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  color: var(--c-cream-soft);
}

/* Tiêu đề cột: là <h2> để sơ đồ heading không đứt quãng, nhưng cỡ nhỏ vì
   trong footer nó chỉ đóng vai nhãn cột. */
.site-footer__heading {
  font-family: var(--ff-body);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--c-terracotta);
  margin-bottom: var(--sp-sm);
}

.site-footer__nav ul,
.site-footer__contact ul {
  display: flex;
  flex-direction: column;
  gap: var(--sp-xs);
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: var(--fs-sm);
}

.site-footer__nav a,
.site-footer__contact a {
  color: var(--c-cream-soft);
  /* Vùng chạm 44px cho link footer trên điện thoại: chữ nhỏ mà sát nhau là
     nguồn bấm nhầm kinh điển. */
  display: inline-block;
  padding-block: var(--sp-2xs);
  transition: color var(--dur) var(--ease);
}
.site-footer__nav a:hover,
.site-footer__contact a:hover { color: var(--c-gold); }

.site-footer__cta { margin-top: var(--sp-md); }

.site-footer__bottom {
  margin-top: var(--sp-2xl);
  padding-top: var(--sp-lg);
  border-top: 1px solid var(--c-line-dark);
  font-size: var(--fs-sm);
  color: var(--c-cream-soft);
}

/* Logo trong footer: nhỉnh hơn header một chút vì đứng riêng, không phải chen
   chỗ với menu; xếp dọc trên chữ thay vì cạnh chữ. */
.site-footer__brand .brand__name { display: block; }
.brand__mark--footer {
  height: 46px;
  margin-bottom: var(--sp-sm);
}

/* Mục 19 (DẢI CAM KẾT dưới hero) đã gỡ ngày 13/08/2026 cùng ba chip của nó.
   Ba lời cam kết đó vẫn còn nguyên ở khối "Mình cam kết bằng chính sản phẩm"
   phía dưới, nên không mất thông tin nào. */

/* --------------------------------------------------------------------------
   20. CINEMATIC SCROLL — section độc lập ngay sau hero
   -------------------------------------------------------------------------- */
.cinematic {
  position: relative;
  /* Desktop ScrollTrigger cần được phép cộng pin-spacer vào chiều cao section.
     Khóa height + clip ở wrapper sẽ cắt spacer và làm section sau tràn lên khi
     cảnh chưa kết thúc. Việc cắt hình đã do stage đảm nhiệm. */
  min-height: 34rem;
  /* Reset padding mặc định của mọi <section>; nếu không sẽ có một dải trống
     --sp-section nằm giữa đáy hero và đầu sân khấu cinematic. */
  padding: 0;
  margin: 0;
  background: #8fc9e6;
  isolation: isolate;
}

.cinematic__stage {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  min-height: 34rem;
  overflow: hidden;
  background: #8fc9e6;
  contain: paint;
}

.cinematic__sky,
.cinematic__clouds,
.cinematic__transition-bg,
.cinematic__mist {
  position: absolute;
  inset: 0;
}

.cinematic__sky {
  z-index: 0;
  inset: 0;
  background-color: #3174b5;
  background-image: url("../assets/cinematic/sky-clouds-painterly-v2.webp");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  transform-origin: 50% 44%;
}

.cinematic__sky::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0.3;
  background: radial-gradient(ellipse at center, transparent 42%, rgba(15, 43, 72, 0.42) 118%);
  mix-blend-mode: soft-light;
}

.cinematic__sun-glow {
  position: absolute;
  width: min(54vw, 44rem);
  aspect-ratio: 1;
  left: 50%;
  top: 36%;
  translate: -50% -50%;
  border-radius: 50%;
  background: rgba(255, 247, 218, 0.3);
  filter: blur(54px);
}

.cinematic__clouds {
  pointer-events: none;
  transform-origin: center;
}

.cinematic__clouds img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* Tầng mây xa GỠ HẲN ở mọi bề ngang. Trước để opacity 0.32 (desktop) / 0.14
   (mobile) — mắt gần như không thấy, nhưng máy vẫn phải hợp thành và phóng một
   tấm ảnh cỡ nguyên màn hình ở mỗi khung hình. Đắt nhất trong những thứ không
   ai nhìn thấy. */
.cinematic__clouds--far { display: none; }

.cinematic__clouds--mid {
  z-index: 2;
  opacity: 0.82;
  -webkit-mask-image:
    radial-gradient(ellipse at 69% 61%, #000 0 22%, transparent 53%),
    radial-gradient(ellipse at 17% 79%, #000 0 16%, transparent 47%);
  mask-image:
    radial-gradient(ellipse at 69% 61%, #000 0 22%, transparent 53%),
    radial-gradient(ellipse at 17% 79%, #000 0 16%, transparent 47%);
}

.cinematic__transition-bg {
  z-index: 3;
  background:
    radial-gradient(circle at 50% 42%, #fffdf8 0%, var(--c-cream) 55%, var(--c-surface-warm) 100%);
  opacity: 0;
}

.cinematic__clouds--near {
  /* Nằm trước tấm Love Letters để một phần mây ôm lấy mép thiệp, tạo cảm giác
     thiệp thật sự xuất hiện trong không gian thay vì dán lên background. */
  z-index: 5;
  opacity: 0.94;
  -webkit-mask-image: linear-gradient(to top, #000 0 37%, rgba(0,0,0,0.82) 51%, transparent 76%);
  mask-image: linear-gradient(to top, #000 0 37%, rgba(0,0,0,0.82) 51%, transparent 76%);
}

.cinematic__mist {
  z-index: 6;
  inset: -12%;
  opacity: 0;
  background:
    radial-gradient(ellipse at 22% 58%, rgba(255,255,255,0.96) 0 18%, transparent 51%),
    radial-gradient(ellipse at 74% 44%, rgba(255,255,255,0.94) 0 21%, transparent 53%),
    rgba(248, 252, 251, 0.08);
}

/* Cảnh cuối của cinematic: tấm thiệp nằm giữa mây nền và mây tiền cảnh.
   Wrapper chỉ căn vị trí; toàn bộ transform dành riêng cho ảnh để GSAP không
   ghi đè lên phép căn giữa. */
.cinematic__letter {
  position: absolute;
  /* z-index 7: TRÊN mây (5) và sương (6), dưới rèm (8), trên lớp loé (3).
     Tấm thiệp trồi lên từ mép dưới mà mặt nạ mây gần lại đặc nhất ở đúng 37%
     dưới khung — tức đúng quãng đường nó đi qua. Để z-index 4 như bản đầu thì
     gần hết đoạn trồi lên bị mây nuốt. Lớp loé vẫn ở dưới nên thiệp trụ lại
     giữa vùng sáng rồi mới tan. */
  z-index: 7;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.cinematic__letter-img {
  display: block;
  width: min(82vw, 22rem);
  max-height: 78%;
  height: auto;
  object-fit: contain;
  opacity: 0;
  transform: translateY(12%) scale(0.86);
  transform-origin: 50% 52%;
  filter: drop-shadow(0 1.4rem 2.25rem rgba(42, 16, 16, 0.28));
}

@media (min-width: 900px) {
  .cinematic__letter-img { width: min(46vw, 34rem); }
}

/* --- HAI CÁNH MÀN ---

   Mobile: KHÔNG có màn. Bản dùng ảnh nhung bị bóp ngang 2,5 lần trên khung dọc
   (ảnh tỉ lệ 0,888 nhồi vào khung 0,357 bằng object-fit: fill) nên nếp nhung ra
   sọc dẹt; bản thay bằng hai tấm mực phẳng đã dựng rồi cũng gỡ theo yêu cầu
   ngày 13/08/2026 — Khoa muốn xem section 2 chỉ còn mây và Love Letters.

   Từ 15/08/2026 gỡ ở MỌI bề ngang: Khoa muốn desktop giống hệt mobile. Hai
   thẻ div vẫn nằm trong HTML để bản tĩnh (không JS / giảm chuyển động) và các
   quy tắc cũ không phải sửa theo; hai file curtain-*.webp giờ không còn ai
   dùng.
*/
.cinematic__curtain {
  display: none;
}



/* Trong lúc pin, giao diện chrome của trang lùi đi để sân khấu đủ 100dvh. */
body.is-cinematic-active .site-header {
  translate: 0 -105%;
}

body.is-cinematic-active .zalo-float {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

@media (max-width: 899px) {
  /* Section dài 175lvh, sân khấu chiếm 100lvh và bám ở đầu màn hình. Chênh
     lệch 75lvh là TOÀN BỘ quãng cuộn điều khiển cảnh.

     Lịch sử con số này: 185lvh thời còn tấm rèm → 210lvh khi rèm cần chỗ để
     mở từ từ → 175lvh sau khi gỡ hẳn rèm (13/08/2026). Không còn nhịp mở màn
     thì giữ 110lvh là bắt khách cuộn qua một quãng dài chỉ để xem mây phóng.

     Vẫn là sticky của CSS chứ KHÔNG phải pin của ScrollTrigger: khách vuốt
     nhanh là đi thẳng qua, không bao giờ bị giam lại trong cảnh. */
  .cinematic {
    height: 175vh;
    height: 175lvh;
    min-height: 0;
    overflow: visible;
  }

  .cinematic__stage {
    position: sticky;
    top: 0;
    height: 100vh;
    height: 100lvh;
    min-height: 0;
  }

  /* Asset trời ngang nhưng màn hình mobile dọc. Canh về cụm mây lớn bên phải
     thay vì crop đúng giữa, nhờ vậy vẫn còn cả trời xanh lẫn khối mây chủ đạo. */
  .cinematic__sky,
  .cinematic__clouds img {
    background-position: 67% center;
    object-position: 67% center;
  }

  .cinematic__sun-glow {
    width: 78vw;
    top: 31%;
    filter: blur(36px);
  }

  .cinematic__clouds--mid { opacity: 0.68; }
  .cinematic__clouds--near { opacity: 0.9; }

  .cinematic__mist {
    inset: -6%;
    background:
      radial-gradient(ellipse at 50% 55%, rgba(255,255,255,0.94) 0 23%, transparent 62%),
      rgba(248, 252, 251, 0.06);
  }

  .cinematic__letter {
    /* Hơi hạ tâm thị giác vì cụm mây lớn tập trung ở nửa dưới khung dọc. */
    padding-top: 4lvh;
  }

  /* Trên mobile cú loé chạy tới opacity 0.96, tức gần như phủ kín màn hình
     bằng chính lớp này. Mép ngoài của nó phải ĐÚNG bằng nền khối danh mục —
     để --c-surface-warm thì chỗ hai section gặp nhau lộ một vệt đổi tông
     ngang màn hình, đúng vào giây chuyển cảnh. */
  .cinematic__transition-bg {
    background: radial-gradient(circle at 50% 42%,
      #fffdf8 0%, var(--c-cream) 58%, var(--c-cream) 100%);
  }

}

/* Không có GSAP hoặc người dùng giảm chuyển động: luôn để lại một cảnh hoàn
   chỉnh có mây và Love Letters, không biến mất nội dung chính. */
.cinematic--static .cinematic__letter-img {
  opacity: 1;
  transform: none;
}

.cinematic--static {
  height: 100vh;
  height: 100svh;
  overflow: hidden;
}

.cinematic--static .cinematic__stage {
  position: relative;
  top: auto;
  height: 100%;
}

@media (prefers-reduced-motion: reduce) {
  .cinematic {
    height: min(72svh, 44rem);
    min-height: 28rem;
  }
  .cinematic__stage {
    height: 100%;
    min-height: 28rem;
  }
  .cinematic__clouds--near { transform: scale(1.15); opacity: 0.72; }
}
