/**
 * gcc-ratio.css — Bộ chọn khổ thiệp, và bố cục thiệp theo từng HỌ KHỔ.
 *
 * ─── VÌ SAO TỆP NÀY KHÔNG CÒN CHỖ NÀO ĐÈ ─────────────────────────────────────
 * Bộ template được vẽ khi hệ thống chỉ có một khổ 9:16, nên chúng đặt luôn
 * position / width / margin / flex cho các khối bên trong thẻ, phần lớn kèm
 * !important. Bản trước của tệp này phải viết class hai lần và rải !important
 * để đè lại — đè được hôm nay, nhưng mỗi template viết thêm về sau lại là một
 * chỗ có thể đè hụt, và không ai đọc nổi.
 *
 * Đã gỡ ở gốc thay vì đè: codemod (webapp/tools/codemod-template-family.py)
 * tách mỗi luật của khối bên trong làm hai — phần trang trí giữ nguyên bộ chọn,
 * phần bố cục nhận thêm :not(.gcc-fam-wide). Ở khổ ngang, luật bố cục của
 * template KHÔNG áp. Nên mọi luật dưới đây viết bằng độ đặc hiệu thường.
 *
 * Ba HỌ KHỔ, do gcc-ratio.js gắn theo tỉ lệ thật:
 *   gcc-fam-portrait  (≤ 0.87)   khổ đứng — đúng thứ template được vẽ cho
 *   gcc-fam-square    (0.87–1.15)
 *   gcc-fam-wide      (≥ 1.15)   khổ ngang — bố cục do tệp này quyết định
 * và gcc-aspect-cover (≥ 1.35) cho khổ rất ngang: ảnh làm nền tràn viền.
 */

.gcc-ratio-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    gap: 8px;
    overflow-y: auto;
    min-height: 0;
    scrollbar-width: none;
}

.gcc-ratio-grid::-webkit-scrollbar { width: 0; height: 0; }

.gcc-ratio-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    padding: 10px 6px;
    border: 1px solid transparent;
    border-radius: 10px;
    background: rgba(127, 127, 127, .12);
    color: inherit;
    font: inherit;
    cursor: pointer;
}

.gcc-ratio-item:hover { background: rgba(127, 127, 127, .22); }
.gcc-ratio-item.is-active {
    background: rgba(127, 127, 127, .28);
    border-color: currentColor;
}

/* Ô xem trước vẽ đúng tỉ lệ — người dùng thấy HÌNH DẠNG, không phải đọc hai
   con số rồi tự hình dung. Cao cố định để mọi ô cùng một hàng ngang bằng
   nhau; bề rộng do aspect-ratio quyết định. */
.gcc-ratio-box {
    height: 34px;
    border: 1.5px solid currentColor;
    border-radius: 4px;
    opacity: .75;
}

.gcc-ratio-label { font-size: 11px; font-weight: 600; }
.gcc-ratio-num   { font-size: 10px; opacity: .5; }

.gcc-ratio-custom {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    padding-top: 10px;
    border-top: 1px solid var(--gcc-pnl-line, rgba(127, 127, 127, .25));
}

.gcc-ratio-custom-label { font-size: 12px; opacity: .7; margin-right: 2px; }

.gcc-ratio-custom input {
    width: 58px;
    min-height: 30px;
    box-sizing: border-box;
    padding: 5px 8px;
    border: 1px solid var(--gcc-pnl-line, rgba(127, 127, 127, .3));
    border-radius: 8px;
    background: rgba(127, 127, 127, .12);
    color: inherit;
    font: inherit;
    font-size: 13px;
    text-align: center;
}

.gcc-ratio-custom input:focus { outline: none; border-color: rgba(127, 127, 127, .6); }
.gcc-ratio-x { opacity: .5; }

/* Báo lỗi ngay tại hai ô đang nhìn, không dùng hộp thoại chặn ngang. */
.gcc-ratio-custom.is-loi input { border-color: #e05c50; }

.gcc-ratio-custom .gcc-chat-btn { min-height: 30px; padding: 5px 12px; font-size: 12px; }


/* ══════════════════════════════════════════════════════════════════════════
 * CHUNG CHO MỌI KHỔ
 * ══════════════════════════════════════════════════════════════════════════ */

/* Thẻ thành cột flex để aspect-ratio quyết định được chiều cao — aspect-ratio
   bị bỏ qua với hộp khối mà nội dung cao hơn.
   overflow: hidden mới là thứ làm tỉ lệ có hiệu lực: không cắt thì phần nội
   dung thừa vẫn đẩy khung cao lên. Luật `overflow: visible` của
   gcc-live-preview.css đã tự loại thẻ có khổ ra, nên ở đây không cần đè. */
/* Thiệp cưới khổ ngang KHÔNG vào đây: bố cục gốc của nó là lưới hai cột
   (gcc-wedding-preview.css mục 6a). Ép display:flex là bẻ nát lưới ấy. */
.gcc-preview-card.gcc-has-aspect,
.gcc-preview-wedding-card.gcc-has-aspect:not(.gcc-fam-wide),
.gcc-wedding-card.gcc-has-aspect:not(.gcc-fam-wide) {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    position: relative;
}

/* Vùng ảnh: SÀN TỐI THIỂU theo phần trăm chiều cao thẻ, không phải "phần còn
   thừa". Cho nó nhận phần thừa là sai ở khổ ngang: tiêu đề, lời chúc và chữ ký
   chiếm chiều cao gần như cố định, nên thẻ 3:2 cao 290px chỉ còn hơn 100px cho
   ảnh — ảnh co thành một dải mỏng.
   Dùng % chứ không px: chiều cao thẻ đổi theo từng khổ. */
/* KHÔNG áp cho .wedding-photo-section: khung chân dung của thiệp cưới là một
   vòng tròn cỡ cố định giữa hai cái tên, không phải băng ảnh chiếm phần chính
   của thiệp. Cho nó "sàn 52% và nhận phần thừa" thì nó kéo dài thành bầu dục —
   đo được 110×340 trong thẻ 9:16. */
.gcc-has-aspect > .gcc-preview-media {
    flex: 1 1 auto;
    min-height: 52%;
    overflow: hidden;
}

/* VÙNG NỘI DUNG CỦA THIỆP CƯỚI KHÔNG CÓ SÀN 52%.
   Sàn ấy hợp với BĂNG ẢNH của thiệp thường — vùng ảnh phải chiếm phần chính
   của tấm thiệp. Nhưng vùng nội dung thiệp cưới còn có ảnh chân dung, hai vạch
   hoạ tiết, tên, cha mẹ, chân trang và chữ ký cùng chia chiều cao. Đòi 52% của
   thẻ 640px là đòi 333px, cộng những khối kia thì vượt quá 640 — phần thừa rơi
   xuống đáy và bị overflow:hidden của thẻ cắt. Đo trên trang thật ở khổ 9:16:
   chân trang lòi 4px, CHỮ KÝ lòi 49px, tức mất hẳn khỏi tấm thiệp.
   Cho nó co tự do (min-height: 0) và cuộn khi chữ dài. Chân trang với chữ ký
   flex: 0 0 auto để không bao giờ bị bóp nhường chỗ. */
.gcc-preview-wedding-card.gcc-has-aspect:not(.gcc-fam-wide) > .wedding-content,
.gcc-wedding-card.gcc-has-aspect:not(.gcc-fam-wide) > .wedding-content {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: none;
}

.gcc-preview-wedding-card.gcc-has-aspect:not(.gcc-fam-wide) > .wedding-footer,
.gcc-wedding-card.gcc-has-aspect:not(.gcc-fam-wide) > .wedding-footer,
.gcc-preview-wedding-card.gcc-has-aspect:not(.gcc-fam-wide) > .gcc-signature,
.gcc-wedding-card.gcc-has-aspect:not(.gcc-fam-wide) > .gcc-signature {
    flex: 0 0 auto;
}

/* CHE NHỊP DỰNG LẠI.
   Đổi hướng, đổi mẫu, đổi loại thiệp đều làm thẻ bị dựng lại từ đầu. Thẻ mới
   hiện ra ở bố cục mặc định trước, rồi mới nhận khổ — khổ chỉ đo được sau khi
   thẻ đã nằm trong DOM, nên không có cách nào áp sớm hơn. Khoảng giữa hai nhịp
   ấy mắt bắt được: các khối chồng lên nhau một thoáng.
   Mờ đi 60ms rồi hiện lại thì cú nhảy nằm gọn trong lúc thẻ đang mờ.
   Chỉ mờ, KHÔNG dùng visibility hay display: thẻ phải còn chiếm chỗ và còn đo
   được, vì chính lúc này JS đang đo nó để tính khổ. */
/* Viết kèm .gcc-has-aspect để ngang cơ với `.gcc-col--preview .gcc-preview-card`
   bên gcc-live-preview.css — luật đó cũng đặt transition, và một dòng
   `transition` ghi đè CẢ danh sách chứ không cộng thêm. Nên phải chép lại ba
   hiệu ứng của họ, nếu không thẻ có khổ sẽ đổi nền giật cục khi đổi theme. */
.gcc-preview-card.gcc-has-aspect,
.gcc-preview-wedding-card.gcc-has-aspect,
.gcc-wedding-card.gcc-has-aspect {
    transition: opacity .14s ease, background-color .4s ease, color .4s ease,
                box-shadow .4s ease;
}

.gcc-preview-card.gcc-kho-dang-dung,
.gcc-preview-wedding-card.gcc-kho-dang-dung,
.gcc-wedding-card.gcc-kho-dang-dung {
    opacity: 0;
    /* Không cho bấm trúng thứ đang nhảy chỗ. */
    pointer-events: none;
}

/* KHOẢNG THỞ — các hộp không chạm nhau và không chạm viền thẻ.
   Lề giữa các khối vốn do template đặt, mà lề là bố cục nên codemod đã tách nó
   ra khỏi những họ khổ này — không cấp lại thì ở khung hẹp các hộp dính sát
   nhau thành một mảng đặc, và dính luôn vào mép thẻ.
   Đo bằng cqw (1% bề rộng thẻ) chứ không bằng px: cùng một khoảng cách phải
   trông cân ở thẻ 244px cao lẫn thẻ 680px cao. clamp() chặn hai đầu để khe
   không mảnh như sợi chỉ ở thẻ bé, cũng không hoác ra ở thẻ lớn. */
.gcc-preview-card.gcc-fam-relayout,
.gcc-preview-wedding-card.gcc-fam-relayout {
    padding: clamp(7px, 2.2cqw, 15px);
    gap: clamp(6px, 1.7cqw, 12px);
}

/* HUỶ aspect-ratio 1/1 của vùng ảnh khi hệ khổ nắm bố cục.
   gcc-generate-card-preview-base.css và gcc-live-preview.css đều đặt
   `aspect-ratio: 1 / 1` cho .gcc-preview-media — hợp lý khi thẻ luôn là khổ
   đứng cao, vùng ảnh vuông nằm gọn ở giữa. Nhưng trong thẻ VUÔNG thì vùng ảnh
   vuông cao đúng bằng bề rộng thẻ, cộng thêm tiêu đề và lời chúc phía trên là
   tràn khỏi khung: đo được thẻ 435×435, vùng ảnh cao 387 bắt đầu ở 114 — thừa
   66px, và vì thẻ có khổ thì phải cắt, nên 66px đó mất luôn.
   Bỏ tỉ lệ cứng thì chiều cao vùng ảnh do hộp flex quyết định: nó lấy đúng
   phần còn lại của thẻ, không thừa không thiếu. */
.gcc-fam-relayout > .gcc-preview-media,
.gcc-fam-relayout:not(.gcc-fam-wide) > .wedding-photo-section {
    aspect-ratio: auto;
    height: auto;
}

/* TIÊU ĐỀ KHÔNG BAO GIỜ BỊ CẮT. Bản trước cho nó co, kết quả ở khổ 3:2 là tiêu
   đề cụt mất nửa dòng — mất chữ tệ hơn ảnh nhỏ. */
.gcc-has-aspect > .gcc-preview-header,
.gcc-has-aspect > .wedding-header,
.gcc-has-aspect > .gcc-signature {
    flex: 0 0 auto;
}

/* Lời chúc: CUỘN được thay vì bị cắt. Cắt là mất chữ vĩnh viễn — người nhận
   không có cách nào đọc phần còn lại. Ẩn thanh cuộn theo quy ước của cả trang;
   khả năng cuộn giữ nguyên, kể cả bánh xe chuột, vuốt và bàn phím.
   Vệt mờ ở mép dưới thay cho thanh cuộn đã ẩn — không có dấu hiệu nào thì
   người đọc tưởng chữ hết ở đó. */
.gcc-has-aspect > .gcc-preview-caption {
    flex: 0 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 18px), transparent);
    mask-image: linear-gradient(to bottom, #000 calc(100% - 18px), transparent);
}

.gcc-has-aspect > .gcc-preview-caption::-webkit-scrollbar { width: 0; height: 0; }

/* ẢNH PHỦ KÍN Ô, KHÔNG CHỪA VIỀN.
   Hai lớp bọc slideshow đều mang `padding: 1em` (CSS nền đặt, template đặt lại
   lần nữa), và <img> thì `width: auto; height: auto`. Kết quả đo được trong ô
   ảnh 441×263: tấm ảnh chỉ 414×236 và nằm thụt vào, để hở một viền nền vàng
   quanh bốn cạnh — trông như ảnh bị lồng khung chứ không phải ảnh của thiệp.
   Lề trong ấy hợp lý khi ô ảnh tự co theo ảnh; nhưng khi thẻ đã có khổ thì ô
   ảnh có kích thước do hệ khổ định, và ảnh phải lấp đầy đúng ô đó. */
.gcc-has-aspect > .gcc-preview-media > .gcc-slider,
.gcc-has-aspect > .gcc-preview-media .gcc-slide,
.gcc-has-aspect > .wedding-photo-section .gcc-slide {
    padding: 0;
    margin: 0;
}

.gcc-has-aspect .gcc-preview-media img,
.gcc-has-aspect .gcc-preview-media video,
.gcc-has-aspect .gcc-slide img,
.gcc-has-aspect .gcc-slide video {
    width: 100%;
    height: 100%;
    max-width: none;
    max-height: none;
    object-fit: cover;
}

/* BO GÓC ĐỒNG BỘ SUỐT CẢ CHỒNG LỚP.
   Vùng ảnh có bốn tầng lồng nhau — .gcc-preview-media > .gcc-slider > .gcc-slide
   > <img> — và trước đây mỗi tầng một bán kính: vùng ảnh 17.7px, còn slide và
   ảnh đều 0. Tầng ngoài cắt được phần thừa, nhưng chỉ cần một tầng giữa đổi
   overflow hoặc dựng tầng hợp thành riêng (transform, filter, opacity) là góc
   vuông của tấm ảnh lòi ra ngoài đường bo của template.
   Nối bằng `inherit` để cả chồng lớp luôn cùng một giá trị: sửa ở gốc thì mọi
   tầng đi theo, không phải nhớ cập nhật bốn chỗ.
   --gcc-media-r do JS đo từ bo góc THẬT của thẻ, trừ đi viền và lề trong để hai
   đường cong đồng tâm; mỗi template một bo góc khác nhau nên không viết cứng
   được. */
.gcc-has-aspect > .gcc-preview-media,
.gcc-has-aspect > .wedding-photo-section {
    border-radius: var(--gcc-media-r, 12px);
    overflow: hidden;
}

.gcc-has-aspect > .gcc-preview-media > .gcc-slider,
.gcc-has-aspect > .gcc-preview-media .gcc-slide,
.gcc-has-aspect > .gcc-preview-media img,
.gcc-has-aspect > .gcc-preview-media video,
.gcc-has-aspect > .wedding-photo-section img {
    border-radius: inherit;
}


/* ══════════════════════════════════════════════════════════════════════════
 * THẺ THẤP — siết khoảng trắng
 * ══════════════════════════════════════════════════════════════════════════
 * JS gắn class này khi chiều cao thật dưới 340px. Nén khoảng cách bao giờ cũng
 * đỡ hơn cắt nội dung. */

.gcc-preview-card.gcc-aspect-short,
.gcc-preview-wedding-card.gcc-aspect-short { padding: 6px; }

.gcc-aspect-short > .gcc-preview-header { padding-block: 2px; }
.gcc-aspect-short > .gcc-preview-caption {
    padding-block: 2px;
    font-size: .92em;
    line-height: 1.35;
}

.gcc-aspect-short > .gcc-signature {
    margin: 6px 8px 2px;
    padding-top: 5px;
    font-size: 10px;
}

.gcc-aspect-short .gcc-signature-avatar { width: 15px; height: 15px; }


/* ══════════════════════════════════════════════════════════════════════════
 * HỌ KHỔ NGANG VỪA (1.15 – 1.35) — HAI CỘT
 * ══════════════════════════════════════════════════════════════════════════
 * 4:3 và 5:4 quá ngang để xếp dọc — chia ba theo chiều cao thì ảnh ra một dải
 * mỏng — nhưng chưa đủ ngang để chữ nằm đè lên ảnh mà vẫn thoáng. Nên xếp
 * NGANG: ảnh một bên, chữ một bên. Đây là bố cục riêng của khổ ngang, không
 * phải bản co lại của khổ đứng.
 */

.gcc-preview-card.gcc-fam-wide:not(.gcc-aspect-cover) {
    display: grid;
    grid-template-columns: 46% 1fr;
    grid-template-rows: auto minmax(0, 1fr) auto;
    align-items: start;
    /* Khe giữa hai cột và giữa các hàng lấy chung từ luật KHOẢNG THỞ ở trên. */
}

.gcc-fam-wide:not(.gcc-aspect-cover) > .gcc-preview-media {
    /* Ảnh chiếm trọn cột trái, cao suốt hai hàng trên. min-height: 0 để nó
       nghe theo hàng lưới thay vì theo chiều cao nội dung. */
    grid-column: 1;
    grid-row: 1 / 3;
    height: 100%;
    min-height: 0;
    margin: 0;
    aspect-ratio: auto;
    overflow: hidden;
}

.gcc-fam-wide:not(.gcc-aspect-cover) > .gcc-preview-media img,
.gcc-fam-wide:not(.gcc-aspect-cover) > .gcc-preview-media video,
.gcc-fam-wide:not(.gcc-aspect-cover) .gcc-slide img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.gcc-fam-wide:not(.gcc-aspect-cover) > .gcc-preview-header {
    grid-column: 2;
    grid-row: 1;
    width: auto;
    margin: 0;
}

.gcc-fam-wide:not(.gcc-aspect-cover) > .gcc-preview-caption {
    grid-column: 2;
    grid-row: 2;
    width: auto;
    margin: 0;
    min-height: 0;
    align-self: stretch;
}

/* Chữ ký chạy hết bề ngang dưới cùng — nó là nhãn của cả tấm thiệp, không
   thuộc riêng cột nào. */
.gcc-fam-wide:not(.gcc-aspect-cover) > .gcc-signature {
    grid-column: 1 / -1;
    grid-row: 3;
    margin: 0;
}


/* ══════════════════════════════════════════════════════════════════════════
 * THIỆP CƯỚI Ở KHỔ NGANG
 * ══════════════════════════════════════════════════════════════════════════
 * KHÔNG dựng lưới riêng ở đây. gcc-wedding-preview.css (mục 6a) đã có sẵn một
 * bố cục hai cột cho thiệp cưới khổ ngang: 34%/66%, chân dung tròn cột trái,
 * phần thông tin cột phải. Bản trước tôi dựng thêm một lưới nữa trong tệp này
 * và hai bên trộn vào nhau — đo được trên trang thật: cột phải nhận grid-row
 * của tệp kia còn số hàng nhận của tệp này, thành ra chân trang chen ngang
 * giữa thiệp và khối WHEN/WHERE bị cắt cụt.
 *
 * Việc của hệ khổ chỉ là ba điều bố cục gốc không biết trước:
 *   1. chữ ký (phần tử dựng lúc chạy) phải nằm hết bề ngang, dưới cùng
 *   2. không khối nào được CẮT chữ — thẻ giờ cao theo tỉ lệ, không cao theo
 *      nội dung, nên phần dài phải cuộn được
 *   3. chân dung co giãn theo cỡ thẻ, vì thẻ nay mở tới hơn 1000px
 */

/* 1. Chữ ký: hàng RIÊNG dưới cùng, hết bề ngang.
      Chỉ trải cột là chưa đủ — bố cục gốc khai ba hàng và đặt chân trang ở hàng
      ba, còn chữ ký không được chỉ hàng nên bộ tự xếp thả nó vào ô trống CÙNG
      hàng ấy: đo được hai khối trùng khít nhau tại [16,403,848,44]. Chỉ rõ hàng
      thứ tư (hàng ngầm, sinh thêm sau ba hàng khai sẵn) thì chữ ký nằm hẳn dưới
      chân trang. */
.gcc-preview-wedding-card.gcc-fam-wide > .gcc-signature,
.gcc-wedding-card.gcc-fam-wide > .gcc-signature {
    grid-column: 1 / -1;
    grid-row: 6;
}

/* 1b. CHIA LẠI BỀ RỘNG HAI CỘT: 42/58 thay cho 34/66 của bố cục gốc.
      Tỉ lệ 34/66 hợp khi cột phải chứa nhiều mục sự kiện. Thực tế thiệp chỉ có
      lời mời + WHEN + WHERE, nên cột phải thừa chỗ trống trong khi cột trái
      chật đến mức tên chú rể bị cắt thành "Nguyễn Minh K…" — đo được: chữ cần
      131px mà ô chỉ 129px.
      Đây là chỗ duy nhất tôi đụng vào kích thước lưới gốc, và chỉ khi thẻ đã
      đặt khổ. */
.gcc-preview-wedding-card.gcc-fam-wide,
.gcc-wedding-card.gcc-fam-wide {
    grid-template-columns: 42% 58%;
}

/* 1c. Tên hai người được XUỐNG DÒNG thay vì cắt bằng dấu ba chấm.
      Tên là thứ không được phép mất chữ; cột rộng thêm vẫn không cứu nổi mọi
      cái tên dài. Cho cụm tên gãy dòng khi chật, và bỏ ellipsis ở từng tên. */
.gcc-fam-wide .couple-names,
.gcc-fam-wide .wedding-couple-names {
    flex-wrap: wrap;
    justify-content: center;
}

.gcc-fam-wide .groom-name,
.gcc-fam-wide .bride-name {
    overflow: visible;
    text-overflow: clip;
    white-space: normal;
    min-width: 0;
}

/* Phần thông tin dồn LÊN TRÊN thay vì giãn đều: khối WHEN/WHERE bị kéo cao
   gấp đôi nội dung của nó chỉ vì cột còn trống, trông rỗng ruột. */
.gcc-fam-wide > .wedding-content { justify-content: flex-start; }

/* 1d. HAI VẠCH HOẠ TIẾT VỀ ĐÚNG CHỖ CỦA CHÚNG.
      Chúng là hoạ tiết ngăn cách của lối xếp DỌC: vạch nhẫn giữa ảnh và tên,
      vạch trái tim giữa tên và phần thông tin. Ở lưới hai cột chúng không được
      chỉ ô nào nên bộ tự xếp thả xuống tận đáy thẻ, nằm dưới cả chữ ký — trôi
      nổi, không ngăn cách gì cả.
      Nên khai lại hàng cho cột trái: ảnh · vạch · tên · vạch. Cột phải trải hết
      bốn hàng ấy. Đây là lần thứ hai và cũng là lần cuối tôi đụng vào lưới gốc,
      và chỉ khi thẻ đã đặt khổ.
      Bộ chọn kèm class thẻ để đạt ba bậc — luật gốc là
      `.gcc-wedding-card[data-orientation="landscape"] .wedding-content` cũng ba
      bậc, ngang cơ thì luật viết sau thắng. */
.gcc-preview-wedding-card.gcc-fam-wide,
.gcc-wedding-card.gcc-fam-wide {
    /* Hàng TÊN dùng minmax(min-content, 1fr), KHÔNG phải minmax(0, 1fr).
       Cột phải trải suốt bốn hàng này, nên khi khối lời mời được phép giãn
       nó đòi thêm chiều cao và hàng 1fr là hàng duy nhất nhường được — hàng
       tên bị bóp xuống 65px trong khi nội dung cần 126px, tên cô dâu chú rể
       cao 0px, mất trắng. min-content đặt sàn đúng bằng chỗ chữ cần.
       Hàng 5 (chân trang) KHÔNG còn ghim cứng 44px. Ghim cứng thì tổng sáu
       hàng đòi 494px trong khi thẻ
       khoá theo tỉ lệ chỉ có 458px, và phần thừa rơi đúng vào hàng cuối:
       chữ ký bị overflow:hidden của thẻ CẮT MẤT. Đo trên thiệp thật:
       chữ ký ở đáy 640px còn thẻ hết ở 620px. Để hai hàng này co được thì
       Hàng 5 (chân trang) là min-content, KHÔNG phải auto. Track auto bị bóp
       lại khi lưới thiếu chỗ: đo được chân trang chỉ còn 2px trong khi chữ
       "Reception to follow · Black tie optional · RSVP by 30 November" vẫn nằm
       trong DOM — chữ có đủ mà người nhận không đọc được dòng nào. Track
       min-content thì không bao giờ bị bóp, và chỗ thiếu được lấy từ hàng ảnh
       (xem luật dưới).
       Hàng ẢNH thì KHÔNG cho co bằng minmax(0, auto): ảnh bên trong cao
       height:100%, mà phần trăm tính theo ô — ô co về 0 thì ảnh cũng 0 và
       tấm hình BIẾN MẤT khỏi khung soạn. Đã đo: hàng 1 = 0px. Muốn ảnh
       nhường chỗ thì chặn bằng trần tuyệt đối ở luật dưới, không phải
       bằng sàn 0. */
    grid-template-rows: auto auto minmax(min-content, 1fr) auto min-content auto;
}

.gcc-preview-wedding-card.gcc-fam-wide > .wedding-photo-section,
.gcc-wedding-card.gcc-fam-wide > .wedding-photo-section { grid-column: 1; grid-row: 1; }



.gcc-preview-wedding-card.gcc-fam-wide > .wedding-divider--top,
.gcc-wedding-card.gcc-fam-wide > .wedding-divider--top { grid-column: 1; grid-row: 2; }

.gcc-preview-wedding-card.gcc-fam-wide > .wedding-header,
.gcc-wedding-card.gcc-fam-wide > .wedding-header { grid-column: 1; grid-row: 3; }

.gcc-preview-wedding-card.gcc-fam-wide > .wedding-divider--bottom,
.gcc-wedding-card.gcc-fam-wide > .wedding-divider--bottom { grid-column: 1; grid-row: 4; }

.gcc-preview-wedding-card.gcc-fam-wide > .wedding-content,
.gcc-wedding-card.gcc-fam-wide > .wedding-content { grid-column: 2; grid-row: 1 / 5; }

/* KHOẢNG THỞ TRƯỚC CHÂN TRANG.
   Chân trang mang `border-top: 2px dashed`, còn hộp WHEN/WHERE ngay trên nó
   cũng có viền nét đứt. Đo được khoảng cách giữa hai khối = 0px: hai đường
   nét đứt dính làm một, trông như hộp bị kẻ hai lần chứ không phải một
   đường phân cách. Dùng cqw để khe giãn theo cỡ thẻ, y như mọi khoảng cách
   khác trong tệp này. */
/* Cả hai khổ, và KHÔNG bám vào .gcc-has-aspect.
   Lớp đó chỉ có khi người tạo đã chọn khổ thiệp; thiệp chưa chọn khổ thì
   luật không áp và khe vẫn -2px — đo được đúng như vậy ở khung soạn.
   Dùng [data-orientation] để đủ ba bậc, ngang cơ với luật gốc
   `.gcc-wedding-card[data-orientation="portrait"] .wedding-footer`; ngang cơ
   thì tệp nạp sau thắng, mà tệp này nạp sau. */
.gcc-preview-wedding-card[data-orientation] > .wedding-footer,
.gcc-wedding-card[data-orientation] > .wedding-footer {
    margin-top: clamp(6px, 1.4cqw, 14px);
}

/* ══════════════════════════════════════════════════════════════════════
 * HAI BỐ CỤC CÓ CẤU TRÚC KHÁC HẲN: modern và elegant
 * ══════════════════════════════════════════════════════════════════════
 * Lưới sáu hàng ở trên được dựng theo hình dạng của bố cục classic: bảy con,
 * mỗi con một hàng. Hai bố cục này chỉ có BA con, và toàn bộ nội dung nằm gọn
 * trong MỘT khối bọc:
 *   modern  : .wedding-photo-sidebar + .wedding-content-section + chữ ký
 *   elegant : .wedding-background-photo + .wedding-content-overlay + chữ ký
 *
 * Khối bọc ấy không được chỉ ô nào nên bộ tự xếp thả nó vào hàng 1, và hàng 1
 * là hàng `auto` — nó phình đúng bằng nội dung, 504px, trong khi cả thẻ chỉ
 * có 458px. Hàng 6 của chữ ký bị đẩy ra ngoài, đo được lòi 296px.
 *
 * Nên KHAI LẠI LƯỚI cho riêng hai bố cục này: đúng hai hàng — nội dung
 * `minmax(0, 1fr)` (co được tới 0, không có sàn nội dung kéo lên) và chữ ký
 * `min-content` (không bao giờ bị bóp). Nhận diện bằng :has() vì khác biệt nằm
 * ở CON của thẻ, không có thuộc tính nào trên chính thẻ nói ra điều đó.
 *
 * Đã thử cách nhẹ tay hơn — giữ lưới sáu hàng, cho khối bọc trải 1→5 và đặt
 * min-height: 0 — nhưng vẫn lòi: modern 29px, elegant 4px. Vì các hàng bị trải
 * qua vẫn tự đo theo nội dung, mà chính nội dung ấy lại đang xin chiều cao từ
 * chúng: vòng luẩn quẩn. Chỉ khai thẳng minmax(0, 1fr) mới cắt được vòng ấy.
 * Đo sau khi sửa: cả hai còn dư 9px trong thẻ, đúng bằng classic. */
.gcc-preview-wedding-card.gcc-fam-wide:has(> .wedding-content-section),
.gcc-wedding-card.gcc-fam-wide:has(> .wedding-content-section),
.gcc-preview-wedding-card.gcc-fam-wide:has(> .wedding-content-overlay),
.gcc-wedding-card.gcc-fam-wide:has(> .wedding-content-overlay) {
    grid-template-rows: minmax(0, 1fr) min-content;
}

/* Cả bốn khối bọc đều nằm hàng 1. Cột thì mỗi bố cục một kiểu: modern chia
   hai cột (ảnh dải dọc | nội dung), elegant phủ kín cả hai cột. */
.gcc-preview-wedding-card.gcc-fam-wide > .wedding-photo-sidebar,
.gcc-wedding-card.gcc-fam-wide > .wedding-photo-sidebar {
    grid-column: 1;
    grid-row: 1;
    /* Ảnh cột bên là DẢI DỌC, không phải chân dung tròn — huỷ cỡ vuông mà
       luật chung của .wedding-photo-section vừa cấp cho nó. */
    height: auto;
    aspect-ratio: auto;
    align-self: stretch;
}

.gcc-preview-wedding-card.gcc-fam-wide > .wedding-content-section,
.gcc-wedding-card.gcc-fam-wide > .wedding-content-section {
    grid-column: 2;
    grid-row: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: none;
}

.gcc-preview-wedding-card.gcc-fam-wide > .wedding-background-photo,
.gcc-wedding-card.gcc-fam-wide > .wedding-background-photo,
.gcc-preview-wedding-card.gcc-fam-wide > .wedding-content-overlay,
.gcc-wedding-card.gcc-fam-wide > .wedding-content-overlay {
    grid-column: 1 / -1;
    grid-row: 1;
    min-height: 0;
}

.gcc-preview-wedding-card.gcc-fam-wide > .wedding-content-overlay,
.gcc-wedding-card.gcc-fam-wide > .wedding-content-overlay {
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: none;
}

/* Chữ ký về hàng 2 của lưới hai hàng (hàng 6 chỉ tồn tại ở lưới của classic). */
.gcc-preview-wedding-card.gcc-fam-wide:has(> .wedding-content-section) > .gcc-signature,
.gcc-wedding-card.gcc-fam-wide:has(> .wedding-content-section) > .gcc-signature,
.gcc-preview-wedding-card.gcc-fam-wide:has(> .wedding-content-overlay) > .gcc-signature,
.gcc-wedding-card.gcc-fam-wide:has(> .wedding-content-overlay) > .gcc-signature {
    grid-row: 2;
    grid-column: 1 / -1;
}

.gcc-preview-wedding-card.gcc-fam-wide > .wedding-footer,
.gcc-wedding-card.gcc-fam-wide > .wedding-footer { grid-column: 1 / -1; grid-row: 5; }

/* 1e. LỜI MỜI NHẬN PHẦN THỪA, KHỐI WHEN/WHERE CO VỀ ĐÚNG NỘI DUNG.
      Bố cục gốc ghim ngược lại: lời mời `flex: 0 0 40%` (cứng 40% chiều cao)
      còn khối sự kiện `flex: 1 1 0` (nuốt sạch phần còn lại). Với thiệp chỉ có
      WHEN và WHERE — hai dòng ngắn mặc định — khối ấy bị kéo cao 182px trong
      khi chữ chỉ chiếm chừng một phần ba, để lại một mảng đen rỗng, còn lời mời
      thì bị bó trong 40%.
      Bộ chọn kèm class thẻ cho đủ ba bậc, ngang cơ với luật gốc
      `.gcc-wedding-card[data-orientation="landscape"] .invitation-message`;
      ngang cơ thì luật viết sau thắng. */
.gcc-preview-wedding-card.gcc-fam-wide .invitation-message,
.gcc-preview-wedding-card.gcc-fam-wide .wedding-message,
.gcc-wedding-card.gcc-fam-wide .invitation-message,
.gcc-wedding-card.gcc-fam-wide .wedding-message {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Khối sự kiện chỉ cao bằng nội dung. Thiệp nào khai nhiều mục hơn (lễ, tiệc,
   dress code…) thì nó tự cao lên theo, và lúc ấy lời mời nhường lại. */
.gcc-preview-wedding-card.gcc-fam-wide .wedding-event-details,
.gcc-wedding-card.gcc-fam-wide .wedding-event-details {
    flex: 0 0 auto;
}

/* Các dòng trong khối tên không được co: chúng là chữ, co thì thành 0. */
.gcc-fam-wide > .wedding-header > * { flex-shrink: 0; }

/* 2. Cuộn thay vì cắt. Bố cục gốc đặt overflow: hidden cho hai khối này — hợp
      lý khi thẻ cao cố định 447px và nội dung được cân sẵn, nhưng sai khi
      chiều cao do tỉ lệ quyết định: chữ dài hơn là mất hẳn phần đuôi.
      Ẩn thanh cuộn theo quy ước chung của cả trang. */
.gcc-fam-wide > .wedding-header,
.gcc-fam-wide > .wedding-content {
    overflow-y: auto;
    overflow-x: hidden;
    min-height: 0;
    scrollbar-width: none;
    -ms-overflow-style: none;
    overscroll-behavior: contain;
}

.gcc-fam-wide > .wedding-header::-webkit-scrollbar,
.gcc-fam-wide > .wedding-content::-webkit-scrollbar { width: 0; height: 0; }

/* 3. Chân dung đo theo BỀ RỘNG THẺ (cqw = 1% bề rộng). Con số cứng của bố cục
      gốc hợp với thẻ 794px in ra giấy; trên màn hình thẻ mở tới 1100px thì
      vòng tròn 92px trông như hạt cúc áo, còn thẻ nhỏ 435px thì 190px lại
      chiếm hết chỗ. clamp() chặn hai đầu. */
.gcc-preview-wedding-card.gcc-fam-wide > .wedding-photo-section,
.gcc-wedding-card.gcc-fam-wide > .wedding-photo-section {
    /* 11cqw chứ không 17cqw. Hàng ảnh là hàng DUY NHẤT nhường được chỗ: thẻ
       16:9 có 428px lòng trong mà sáu hàng đòi 472px. Để ảnh 141px thì phần
       thiếu bị lấy của hàng chân trang — đo được chân trang còn 2px, chữ
       "Reception to follow…" nằm trong DOM mà người nhận không đọc được. */
    height: clamp(56px, 11cqw, 150px);
    width: auto;
    min-width: 0;
    min-height: 0;
    max-width: 100%;
    max-height: 100%;
    aspect-ratio: 1;
}

.gcc-fam-wide > .wedding-photo-section > * {
    width: 100%;
    height: 100%;
    min-width: 0;
    min-height: 0;
    object-fit: cover;
}


/* ══════════════════════════════════════════════════════════════════════════
 * HỌ KHỔ RẤT NGANG (≥ 1.35) — ẢNH TRÀN VIỀN LÀM NỀN
 * ══════════════════════════════════════════════════════════════════════════
 * Ảnh phủ kín thẻ, chữ đè lên trên. Cách xếp dọc thông thường chia chiều cao
 * làm ba, mà khổ này vốn đã thấp — ảnh luôn ra một dải mỏng.
 */

/* Vùng ảnh rời khỏi dòng chảy và phủ kín thẻ.
   inset: 0 là ĐỦ: vùng chứa của phần tử định vị tuyệt đối là HỘP PADDING của
   thẻ, mà hộp padding bắt đầu ngay tại mép viền chứ không phải sau lề trong.
   aspect-ratio phải huỷ: hai stylesheet nền đặt 1/1 cho .gcc-preview-media, khi
   đó chiều cao tính theo bề rộng chứ không theo khung thẻ — đo được thẻ
   435×245 mà vùng ảnh 435×435. */
.gcc-aspect-cover > .gcc-preview-media,
.gcc-aspect-cover > .wedding-photo-section {
    position: absolute;
    inset: 0;
    z-index: 0;
    width: auto;
    height: auto;
    max-width: none;
    min-height: 0;
    aspect-ratio: auto;
    margin: 0;
    padding: 0;
    overflow: hidden;
}

.gcc-aspect-cover > .gcc-preview-media img,
.gcc-aspect-cover > .gcc-preview-media video,
.gcc-aspect-cover .gcc-slide,
.gcc-aspect-cover .gcc-slide img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Bo góc lấy từ luật đồng bộ ở phần chung — KHÔNG đặt 0 ở đây. Ảnh nền phủ
       kín thẻ nên góc vuông của nó chìa ra đúng chỗ mép cong của template. */
    border-radius: inherit;
}

/* Màn phủ tối để chữ đọc được trên ẢNH BẤT KỲ — ta không biết trước người dùng
   chọn ảnh gì. Phủ ĐỀU, không dốc về một phía: dốc một phía là áp đặt bố cục
   "chữ bên trái", trong khi các vùng nội dung phải giữ nguyên chỗ của chúng. */
.gcc-aspect-cover::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    border-radius: inherit;
    /* Chữ để trần nên màn phủ này là chỗ dựa tương phản DUY NHẤT cho nó, cùng
       với viền bóng của chữ. Đủ đậm để chữ trắng đứng được trên vùng ảnh sáng,
       đủ nhạt để còn nhìn ra tấm ảnh. */
    background: rgba(8, 12, 20, .38);
    pointer-events: none;
}

/* Chữ nằm trên màn phủ. KHÔNG đụng vào vị trí hay bề rộng của các vùng nội
   dung — chúng giữ đúng chỗ. Chỉ đổi MÀU CHỮ, vì nền không còn là nền giấy của
   template mà là ảnh người dùng chọn. */
.gcc-aspect-cover > .gcc-preview-header,
.gcc-aspect-cover > .gcc-preview-caption,
.gcc-aspect-cover > .gcc-signature,
.gcc-aspect-cover > .wedding-header,
.gcc-aspect-cover > .wedding-content {
    position: relative;
    z-index: 2;
}

.gcc-aspect-cover > .gcc-preview-header,
.gcc-aspect-cover > .gcc-preview-header *,
.gcc-aspect-cover > .gcc-preview-caption,
.gcc-aspect-cover > .gcc-preview-caption * {
    color: #ffffff;
    /* Viền bóng quanh chữ: không còn tấm nền nào bên dưới, nên nét chữ phải tự
       tách khỏi ảnh. Một lớp sát nét cho đường viền, một lớp toả rộng cho khối. */
    text-shadow: 0 1px 2px rgba(0, 0, 0, .75), 0 2px 10px rgba(0, 0, 0, .5);
}

/* CHỮ ĐỂ TRẦN TRÊN ẢNH — không hộp, không viền, không kính mờ.
   Codemod đã tách nền/viền/đổ bóng của khối nội dung ra khỏi chế độ này, nên
   không cần khai báo gì để "gỡ" chúng: mặc định đã là trong suốt. Ở đây chỉ
   xoá phần nền của CSS nền và của bảng typography, những chỗ nằm ngoài tầm
   codemod.
   Tương phản trông cậy vào màn phủ toàn thẻ và viền bóng của chữ. */
.gcc-aspect-cover > .gcc-preview-header,
.gcc-aspect-cover > .gcc-preview-caption {
    background: none;
    border: 0;
    box-shadow: none;
}


.gcc-aspect-cover > .gcc-signature {
    border-top-color: rgba(255, 255, 255, .35);
    color: #ffffff;
    opacity: .7;
}

/* Lớp trang trí vẫn nằm trên cùng. */
.gcc-aspect-cover > .gcc-deco-layer { z-index: 3; }

/* Chữ ký (và vạch ngang của nó) GHIM ĐÁY thẻ. Trước đây nó nằm trong dòng chảy
   nên trôi theo độ dài lời chúc — cùng một thiệp, đổi vài chữ là vạch ngang
   nhảy chỗ. Nó là nhãn cố định của nền tảng, vị trí phải cố định. */
.gcc-aspect-cover > .gcc-signature {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    margin: 0;
    padding: 6px 12px 8px;
    z-index: 4;
}

/* Lời chúc chừa chỗ cho chữ ký, nếu không dòng cuối chui xuống dưới nó. */
.gcc-aspect-cover > .gcc-preview-caption {
    padding-bottom: calc(var(--gcc-sig-h, 32px) + 6px);
}

/* Chấm chỉ slide nằm TRÊN chữ ký — đo được trước khi sửa: chữ ký chiếm
   261→282, chấm 270→280, chữ ký đè lên chấm nên bấm không trúng.
   position: absolute là bắt buộc: hàng chấm vốn tĩnh, mà `bottom` không có tác
   dụng với phần tử tĩnh. --gcc-sig-h do JS đo từ chiều cao thật của khối chữ
   ký; cỡ chữ khối này đổi theo thẻ cao hay thấp nên không viết cứng được. */
.gcc-aspect-cover .gcc-dots,
.gcc-aspect-cover .gcc-slider-dots {
    position: absolute;
    left: 0;
    right: 0;
    bottom: calc(var(--gcc-sig-h, 32px) + 8px);
    z-index: 3;
}


/* ══════════════════════════════════════════════════════════════════════════
 * THẺ LÀ MỘT CONTAINER — nền tảng cho hoạ tiết co giãn theo khổ
 * ══════════════════════════════════════════════════════════════════════════
 * Codemod đã đổi kích thước hoạ tiết trong tệp template từ px sang cqw
 * (webapp/tools/codemod-template-scale.py). Đơn vị đó chỉ có nghĩa khi có một
 * container để đo — THIẾU khai báo này thì cqw rơi về đơn vị theo KHUNG NHÌN,
 * và một chấm 0.417cqw sẽ to nhỏ theo cửa sổ trình duyệt thay vì theo thẻ.
 *
 * inline-size chứ không phải size: `container-type: size` bắt buộc phần tử có
 * chiều cao xác định, mà thẻ không đặt khổ thì chiều cao do nội dung quyết
 * định — dùng size ở đó là thẻ sập còn cao 0.
 */
.gcc-preview-card,
.gcc-preview-wedding-card,
.gcc-wedding-card {
    container-type: inline-size;
}
