/* ============================================================
   catalog.css — Đi kèm assets/js/catalog.js
   Bộ lọc + phân trang dùng chung, cộng lưới masonry của Thư viện ảnh.
   Nạp SAU common.css, TRƯỚC file css riêng của trang.

   BUILD.md §2.1 cấm thêm vào common.css, nên các component dùng chung
   phát sinh trong pass này nằm hết ở đây. Khi gom về design system, cả
   file này là một khối chuyển nguyên vẹn.
   ============================================================ */

/* ===== 1 · MỤC BỊ LỌC / BỊ PHÂN TRANG ẨN =====
   catalog.js ẩn bằng thuộc tính [hidden]. UA style `[hidden]{display:none}`
   thua author style `.grid-3{display:grid}` nên phải khai báo lại — cùng lý do
   library.css đã phải làm cho [data-tab-panel]. */
[data-catalog-items] > [hidden] { display: none !important; }

/* ===== 2 · TRẠNG THÁI RỖNG ===== */
.catalog-empty {
  grid-column: 1 / -1;
  margin: clamp(32px, 5vw, 64px) auto;
  max-width: 42ch;
  /* Xếp cột thay vì để chảy inline. Thẻ gốc là <p>, mà catalog.js còn chèn nút
     "Đặt lại bộ lọc" vào chính thẻ này — nút là hộp inline-flex nên nằm chung
     line box với câu gợi ý, làm câu bị ngắt giữa chừng rồi nút dính vào cuối
     dòng cuối ("…hoặc bấm nút đặt lại để xem toàn / bộ danh sách. [nút]").
     Cột hoá thì tiêu đề · gợi ý · nút mỗi thứ một hàng, và không phụ thuộc
     việc JS chèn nút vào lúc nào. */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  text-align: center;
  color: var(--c-body);
}
.catalog-empty__title {
  font-size: clamp(17px, 1.5vw, 20px);
  color: var(--c-ink);
}
.catalog-empty__hint {
  font-size: var(--fs-xs);
  line-height: 1.7;
  /* Câu gợi ý gọn hơn khung chung để không xuống 3 dòng ở khổ hẹp. */
  max-width: 36ch;
}
.catalog-empty[hidden] { display: none; }

/* Nút đặt lại do catalog.js chèn vào cuối khối rỗng. Đã là flex item nên chỉ
   cần nới thêm khoảng cách so với gap 8px chung của khối. */
.catalog-empty__action { margin-top: 10px; }

/* ===== 3 · PHÂN TRANG =====
   Dáng cơ bản ở common.css §15.8. Đây chỉ là phần catalog.js cần thêm. */

/* Nav rỗng (một trang duy nhất) vẫn chiếm margin-top nếu chỉ đặt [hidden]
   — common.css cho .pagination display:flex. */
.pagination[hidden] { display: none !important; }

/* Vùng bấm 38px là dưới ngưỡng 44px của WCAG 2.5.8. Nới vùng chạm ra bằng
   pseudo-element để không phá bố cục vòng tròn đang có. */
.pagination a { position: relative; }
.pagination a::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: 44px; height: 44px;
}
.pagination a:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
}

/* ===== 4 · SỐ KẾT QUẢ =====
   .count đã có trong common.css; ở đây chỉ cho nó đổi mượt khi lọc lại. */
[data-catalog-count] { transition: opacity var(--dur) var(--ease); }

/* ===== 4b · TIÊU CHÍ ĐANG ĐƯỢC DÙNG =====
   Trạng thái chưa-chọn / đang-mở / đã-chọn của .re-select-main--field ĐÃ CHUYỂN
   lên common.css §10b ở pass phản hồi 30/07/2026 — chúng cần có mặt cả trên
   index.html và he-thong-phan-phoi.html, là hai trang KHÔNG nạp file này.
   Đừng khai lại ở đây, sẽ thành hai nguồn sự thật lệch nhau.

   Còn lại ở đây là phần chỉ trang có bộ lọc catalog mới dùng. */

/* Trạng thái "đã tick" của accordion lọc (viền + nhãn sáng lên) nay đọc thẳng
   từ :checked ở common.css §15.7 — không khai lại ở đây. Class .is-checked mà
   catalog.js/sanitary.js gắn lên <label> được giữ để markup cũ không gãy. */

/* Nút đặt lại chỉ đáng chú ý khi thật sự có gì để đặt lại.
   Bắt ở cấp .filter vì nút nằm trong .filter__head, ĐỨNG TRƯỚC .filter__fields
   — không có tổ hợp anh em nào đi ngược lên được.

   Chỉ đổi màu, KHÔNG thêm ::after làm chấm báo: common.css §8b đã dùng
   `.filter__reset::after` để nới vùng chạm lên 44×44, ghi đè vào đó là bóp vùng
   chạm xuống còn 6px.
   (Chú thích cũ ghi "§16 … trên mobile" — pass "canh lề" đã chuyển rule đó lên
   §8b và bỏ khung @media, nay nó áp ở MỌI khổ chứ không riêng mobile.) */
.filter:has([data-value]) .filter__reset,
.filter:has(input:checked) .filter__reset { color: var(--c-primary); }

/* ===== 5 · LƯỚI MASONRY (thu-vien.html) =====
   Dùng CSS columns thay vì grid: ảnh cao thấp khác nhau xếp so le không cần
   JS đo chiều cao, và không có thư viện masonry nào phải nạp thêm.
   Đánh đổi: thứ tự đọc chạy theo CỘT (1,2,3 rồi 4,5,6) chứ không theo hàng.
   Với dải ảnh không có thứ tự ngữ nghĩa thì chấp nhận được. */
.masonry {
  columns: 3;
  column-gap: clamp(14px, 1.6vw, 24px);
}
.masonry > * {
  break-inside: avoid;             /* không cắt một ảnh làm đôi qua hai cột */
  margin-bottom: clamp(14px, 1.6vw, 24px);
  display: block;
}

/* Không ép aspect-ratio: để ảnh giữ tỉ lệ gốc, đó mới là điểm của masonry. */
.masonry .l-gallery__item {
  aspect-ratio: auto;
  height: auto;
}
.masonry .l-gallery__item img {
  height: auto;
  display: block;
}

@media (max-width: 1024px) { .masonry { columns: 2; } }
/* Giữ 2 cột ở khổ điện thoại thay vì tụt về 1: ảnh masonry cao thấp khác nhau,
   xếp một cột thì thư viện dài gấp đôi và người dùng phải cuộn rất lâu mới hết
   — đúng phản hồi "thư viện ảnh ở điện thoại hơi dài". Hai cột vẫn đủ to để
   nhận ra nội dung ảnh, mà tổng chiều dài giảm một nửa.
   Gap co lại cho hai cột không bị bóp quá hẹp. */
@media (max-width: 640px)  { .masonry { columns: 2; column-gap: 10px; } }
@media (max-width: 640px)  { .masonry > * { margin-bottom: 10px; } }

/* ===== 6 · CHUYỂN CẢNH KHI ĐỔI TRANG / ĐỔI BỘ LỌC =====
   Lưới thay nội dung đột ngột trông như trang bị giật. Một nhịp mờ rất ngắn
   đủ để mắt hiểu "danh sách vừa đổi" mà không làm chậm thao tác. */
@media (prefers-reduced-motion: no-preference) {
  [data-catalog-items] > *:not([hidden]) {
    animation: catalog-in var(--dur-fast) var(--ease) both;
  }
}
@keyframes catalog-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
