/* ============================================================
   Vinpack — product-single.css
   CSS RIÊNG CỦA trang chi tiết sản phẩm (single-vp_product.php),
   Phase J Task 2. Chỉ nạp khi is_singular( 'vp_product' ).

   NẠP SAU global.css, layout.css VÀ taxonomy-danhmuc.css — inc/enqueue.php
   khai cả ba làm dependency của vinpack-product (style). `.art-wrap`/
   `.art-layout`/`.art-toc`/`.faq`/`.faq-box`/`.faq-list`/`.prod-card` ĐÃ CÓ
   SẴN trong taxonomy-danhmuc.css (Phase I/J Task 1) — file này CHỈ chứa các
   lớp `.pd-*` mới, không chép lại bất kỳ rule nào đã có.

   `.art-author` (khối tác giả tĩnh) ĐÃ DỜI sang taxonomy-danhmuc.css ở Phase M
   Task 2: single-vp_project.php cần NGUYÊN khối này, nên khi có NGƯỜI DÙNG THỨ
   HAI, nó chuyển sang file mà cả hai trang đều nạp — đúng lý lẽ đã áp dụng cho
   vinpack_primary_term() ở Phase M Task 1 (một khối dùng chung có ĐÚNG MỘT nơi
   chứa). File này không cần khai thêm dependency gì — 'vinpack-danhmuc' đã là
   dependency của 'vinpack-product' từ Phase J Task 2.

   BA LUẬT CỦA FILE NÀY — cùng ba luật page-nangluc.css/page-vechungtoi.css:
   1. KHÔNG khai custom property nào. Token thuộc về theme.json/global.css.
   2. KHÔNG dùng !important.
   3. KHÔNG khai `outline` ở bất kỳ đâu.

   VỀ `.crumb`: vinpack_breadcrumb() (inc/template-tags.php) LUÔN in
   `<div class="crumb">…</div>`, tên class cố định không đổi được. Mockup
   trang này dùng tên `.pd-crumb`, không có `.sp-banner` bao ngoài như trang
   danh mục/archive — single-vp_product.php bọc thêm một div `.pd-crumb`
   quanh lời gọi hàm, và file này TỰ CHÉP một bản `.crumb` riêng scope trong
   `.pd-crumb` (không có sẵn ở bất kỳ CSS nào đang nạp cùng trang), đúng cách
   page-vechungtoi.css đã tự chép thay vì ngầm phụ thuộc một stylesheet trang
   khác không được nạp ở đây.

   VỀ MÀU "SAO VÀNG" (#FFB020): không có token nào trong global.css tương
   ứng — đây là màu nhấn CHỈ DÙNG cho ngôi sao đánh giá, không thuộc bảng màu
   thương hiệu (navy/cobalt). Giữ nguyên literal, không đặt thành custom
   property mới (luật 1 ở trên).

   REDUCED-MOTION: global.css đã có khối universal `*, *::before, *::after`
   ép `transition-duration:.01ms !important` — mọi transition khai ở đây
   (thumbnail hover, nút CTA, link "sao") đã tự động bị khối đó vô hiệu hoá,
   không cần lặp lại một khối riêng trong file này.
   ============================================================ */

/*
 * MÉP TRÁI/PHẢI CỦA TOÀN TRANG (SỬA 07/09/2026, khách chốt "tất cả về 1180"
 * sau khi xem bảng đo).
 *
 * ĐO TRƯỚC KHI SỬA (viewport 1280): trang này có BA mép khác nhau —
 * breadcrumb + khối ảnh/thông tin (`.pd-crumb`, `.pd-top`) ở 75/1116, nội
 * dung bài `.art-wrap` ở 93/1080, khối "Sản phẩm liên quan" ở 43/1180. Ba
 * nguồn: `<div class="wrap">` và `<section class="wrap">` giữ padding-inline
 * 32px (--wrap-x) của rule `section.wrap` dùng chung, `.art-wrap` tự khoá
 * max-width 1080px (taxonomy-danhmuc.css), còn `.pd-related .section-head`
 * đã được đặt riêng ở --wrap-max từ trước.
 *
 * SỬA: lấy mép 1180 của khối "Sản phẩm liên quan" làm chuẩn cho cả trang —
 * bỏ padding-inline của hai wrap con TRỰC TIẾP trong <main>, và cho .art-wrap
 * nở đúng --wrap-max. Bộ nối `>` để không đụng các `.wrap` lồng bên trong
 * khối khác. File này chỉ nạp khi is_singular('vp_product') nên rule không rò
 * sang trang nào khác.
 *
 * DƯỚI 1180px: trả padding-inline var(--wrap-x) (32px, còn 24px từ mốc 900px)
 * cho cả hai — không có nhánh này thì `.wrap` chiếm trọn bề ngang và chữ chạm
 * sát mép màn hình trên tablet/điện thoại. `.pd-review-wrap` (max-width 860)
 * và `.pd-related .section-head` không đụng tới: cái trước là khối hẹp canh
 * giữa có chủ ý, cái sau vốn đã ở đúng mép chuẩn.
 */
#vp-main > .wrap,
#vp-main > section.wrap{ padding-inline:0; }
#vp-main > section.wrap > .art-wrap{ max-width:var(--wrap-max); }

@media (max-width:1179px){
	#vp-main > .wrap,
	#vp-main > section.wrap{ padding-inline:var(--wrap-x); }
}

/*
 * ---------- Breadcrumb ----------
 * SỬA (28/08/2026, khách yêu cầu "đồng bộ lại tất cả cùng 1 style" cho
 * breadcrumb): thêm margin-bottom + text-align:left còn thiếu so với bản
 * chuẩn `.cat-hero-info .crumb` (taxonomy-danhmuc.css) — màu/font-size đã
 * đúng sẵn, chỉ thiếu hai khai báo này (container không tự canh giữa nên
 * không đổi gì về vị trí NHÌN THẤY, chỉ khai tường minh cho nhất quán mã).
 */
.pd-crumb{ padding:20px 0 0; }
.pd-crumb .crumb{ font-size:13px; color:var(--text-muted); margin-bottom:var(--sp-4); text-align:left; }
.pd-crumb .crumb a{ color:var(--text-muted); }
.pd-crumb .crumb a:hover{ color:var(--navy); }

/* ---------- Top: gallery + thông tin ---------- */
/*
 * HAI CỘT ĐÚNG 50/50 — SỬA LẦN 2, ĐẢO NGƯỢC STT 28(b) CÓ CHỦ Ý.
 *
 * Khách (24/08/2026, kèm ảnh khoanh đỏ hai cột): "trong single product cho
 * column 50%/50% giữa gallery và info".
 *
 * STT 28(b) ĐỢT TRƯỚC yêu cầu NGƯỢC LẠI: "shape ảnh bìa a cho nhỏ lại tí,
 * ngang với button nhận báo giá". Cách giải khi đó là bóp cột gallery hẹp hơn
 * cột info (`@media(min-width:901px){ .pd-top{ grid-template-columns:0.73fr
 * 1fr } }`) — vì `.pd-main-swiper` vuông nên co bề rộng cột là ảnh tự thấp
 * xuống, không phải đặt `max-height` cứng gây méo ảnh. Đo thật khi đó ở
 * 1265px: 0.82fr còn thừa 46px, 0.73fr thì hai đáy ngang nhau.
 *
 * Nay khách đổi ý sang 50/50, nên khối media đó GỠ HẲN chứ không sửa số —
 * giữ lại một override bằng đúng giá trị của rule gốc là để lại CSS chết.
 *
 * HỆ QUẢ PHẢI BIẾT TRƯỚC, KHÔNG PHẢI LỖI: đáy ảnh sẽ KHÔNG còn ngang hàng nút
 * "Nhận báo giá ngay" nữa — đó chính là thứ STT 28(b) đã đánh đổi để có, và
 * 50/50 lấy lại bề rộng bằng cách bỏ nó. Đo trình duyệt thật ở 1280px trên
 * "Túi hột xoài trắng 25×40cm" (7 dòng thông số) TRƯỚC khi sửa: gallery 451px
 * (40.4%) / info 617px (55.3%), đáy gallery y=655 so với đáy CTA y=614. Sau
 * khi sửa hai cột đều 534px, ảnh vuông cao thêm ~83px nên thừa xuống dưới nút
 * CTA nhiều hơn. Docblock STT 28(b) cũ đã ghi sẵn rằng hai đáy này không thể
 * ngang nhau trên MỌI sản phẩm (phụ thuộc số dòng thông số biên tập viên
 * nhập) — 50/50 chỉ là chọn bỏ hẳn ràng buộc đó thay vì căn theo một sản phẩm.
 *
 * `minmax(0, 1fr)` chứ không phải `1fr` trần: `1fr` ngầm là `minmax(auto, 1fr)`
 * nên một chuỗi dài không ngắt được trong bảng thông số có thể đẩy cột phải
 * rộng ra và phá đúng tỉ lệ 50/50 vừa đặt. `minmax(0, ...)` cho phép cột co
 * dưới min-content, khoá tỉ lệ thật sự bằng nhau ở mọi nội dung.
 *
 * `align-items:stretch` — SỬA TIẾP, khách (25/08/2026, ảnh khoanh đỏ mũi tên
 * chỉ xuống khoảng trống dưới dải thumb): "check cái gallery sản phẩm sao cho
 * nó cân đối đều với cái info bên phải, lấy trang này làm chuẩn". Đo đúng
 * trang khách gửi TRƯỚC khi sửa (1280px): .pd-gallery cao 493px, .pd-info cao
 * 539px — lệch 46px, gallery ngắn hơn nên đáy hai cột không bằng nhau.
 *
 * TỪNG LÀ `align-items:start` (chủ ý, đặt lúc chuyển 50/50) vì lúc đó chưa có
 * lý do gì để hai cột PHẢI cao bằng nhau — chỉ cần bằng NHAU VỀ BỀ RỘNG. Đổi
 * sang `stretch` (mặc định của grid, viết tường minh cho rõ ý) để cả hai
 * item nhận đúng chiều cao của HÀNG (tức đúng chiều cao của cột cao hơn) —
 * bước bắt buộc để `.pd-gallery` có KHÔNG GIAN mà phân bổ (xem
 * `align-content:space-between` ở rule `.pd-gallery` ngay dưới). Không đổi gì
 * cho `.pd-info`: nó luôn là cột QUYẾT ĐỊNH chiều cao hàng trên các trang có
 * nhiều thông số (đúng ca phổ biến — mô tả sản phẩm là nội dung biến thiên,
 * ảnh gallery gần như cố định), nên stretch không đổi kích thước nhìn thấy
 * của nó.
 */
.pd-top{
	display:grid;
	grid-template-columns:minmax(0, 1fr) minmax(0, 1fr);
	gap:var(--sp-7);
	padding:28px 0 64px;
	align-items:stretch;
}

/*
 * Gallery: ảnh chính + dải thumb ngang dưới, dựng bằng Swiper.js (self-host,
 * assets/vendor/swiper/) — vendor CSS nạp làm dependency của file này (xem
 * inc/enqueue.php), khối dưới đây CHỈ ghi đè/bổ sung phần layout+màu riêng
 * của site, không chép lại CSS lõi Swiper (.swiper/.swiper-wrapper/
 * .swiper-slide đã có sẵn từ swiper-bundle.min.css).
 *
 * BỐ CỤC MỘT CỘT Ở MỌI BỀ RỘNG (khách yêu cầu): ảnh chính TRÊN, dải thumb
 * NẰM NGANG BÊN DƯỚI. DOM in main-swiper TRƯỚC thumbs-swiper (main cần load
 * ảnh 'large' sớm, alt/eager ở slide đầu) và thứ tự đó cũng đúng thứ tự hiển
 * thị, nhưng vẫn khai `order` tường minh cho khỏi phụ thuộc thứ tự DOM.
 *
 * Số thumb hiện mỗi khung do `slidesPerView` bên assets/js/product-single.js
 * quyết định (số nguyên, theo số ảnh thật, đổi theo breakpoint) — KHÔNG đặt
 * cứng bề rộng thumb ở CSS. Đây chính là điều kiện để thumb luôn TRỌN VẸN,
 * không bị xén nửa ở mép khung.
 *
 * LỊCH SỬ (đừng khôi phục nhầm): trước đây desktop là 2 cột — cột thumb DỌC
 * 92px bên trái + ảnh chính 1fr — và phải dùng `align-items:stretch` +
 * `height:0` + `min-height:100%` trên thumbs-swiper để cột dọc cao đúng bằng
 * ảnh chính ngay lúc layout đầu tiên. Một cột thì không còn hai item cùng
 * hàng nên toàn bộ kỹ thuật đó đã bỏ. tests/test-product-single.php khoá lại
 * bằng assertion PHỦ ĐỊNH để không ai dựng lại cột dọc cũ.
 */
/*
 * SỬA TIẾP — khách (25/08/2026, ảnh khoanh đỏ mũi tên chỉ vào khoảng trống
 * dưới dải thumb): "cân đối lại nó bị trống quá". `align-content:space-
 * between` (bản vừa rồi) ĐÚNG về mặt canh đáy — hai đáy khớp tuyệt đối — NHƯNG
 * dồn hết khoảng dư (61px đo được trên trang khách gửi) vào MỘT khe hở duy
 * nhất giữa ảnh chính và dải thumb, đọc như một lỗ trống vô cớ giữa hai khối
 * UI tách rời, không phải khoảng thở có chủ đích.
 *
 * ĐỔI CƠ CHẾ, không chỉ đổi số: `.pd-gallery` chuyển grid → `flex-direction:
 * column`, và khoảng dư nay chảy vào CHÍNH khung ảnh (`.pd-main-swiper` —
 * `flex:1 1 auto` ở rule của nó bên dưới) thay vì vào khoảng cách giữa hai
 * hàng. Ảnh vẫn KHÔNG bị kéo méo (object-fit:contain tự canh giữa, chỉ thêm
 * viền trắng đều hai bên trong CHÍNH khung ảnh — cùng nền --white/--img-bg
 * đã dùng, đọc như một khung ảnh rộng rãi có chủ đích, không phải một khoảng
 * trống lạc lõng). Dải thumb GIỮ NGUYÊN kích thước tự nhiên (`flex:0 0 auto`
 * ở rule của nó), khoảng cách ảnh↔thumb GIỮ NGUYÊN 14px cố định — không còn
 * co giãn theo khoảng dư như bản `align-content:space-between` vừa gỡ.
 *
 * Đo lại trên đúng trang khách gửi sau khi đổi (1280px): khung ảnh chính từ
 * 534×401 (đúng 4/3) lên 534×461, ảnh hiển thị vẫn 534×400 (không đổi, không
 * méo) NẰM GIỮA khung — viền trắng ~30px mỗi bên trên/dưới thay vì một khe
 * 75px trần trụi giữa ảnh và thumb. Hai đáy `.pd-gallery`/`.pd-info` VẪN khớp
 * tuyệt đối (`.pd-top{ align-items:stretch }` không đổi) — chỉ đổi khoảng dư
 * CHẢY VÀO ĐÂU, không đổi việc có cân đáy hay không.
 */
.pd-gallery{ display:flex; flex-direction:column; gap:14px; }

/*
 * TỈ LỆ 4/3 + contain — ĐỒNG BỘ VỚI `.prod-photo` CỦA LƯỚI SẢN PHẨM.
 *
 * Khách (24/08/2026, ảnh khoanh đỏ ảnh chính): "chỉnh tỉ lệ cái feature image
 * theo cái image trong grid luôn".
 *
 * CÙNG MỘT LỖI, CÙNG MỘT CÁCH CHỮA đã áp cho lưới sản phẩm (xem docblock dài
 * ở `.prod-photo` trong assets/css/taxonomy-danhmuc.css — phần đo 284 ảnh
 * thật nằm ở đó, không chép lại). Đo trên chính trang khách gửi
 * (/san-pham/tui-dung-rac-day-rut/, khung 445x445): cả năm ảnh gallery đều
 * 507x381 (tỉ lệ 1.331), khung vuông + cover CẮT ĐÚNG 24.9% BỀ RỘNG — đúng
 * chỗ logo "vinpack.vn" nằm, và trong ảnh khách gửi thấy rõ logo bị xén mất
 * một nửa ở mép trái.
 *
 * 4/3 khớp tỉ lệ ảnh thật nên ảnh lấp kín khung, không cắt cũng không chừa
 * viền. Nền trắng đặt trên <img> (không phải trên slide) để ca ảnh tỉ lệ khác
 * 4:3 letterbox vào nền trắng hoà với ảnh — y hệt cách `.prod-photo img` làm;
 * `--img-bg` giữ trên slide cho SVG giữ chỗ khi sản phẩm chưa có ảnh.
 *
 * HỆ QUẢ CÓ LỢI, ghi lại kẻo tưởng ngẫu nhiên: khung thấp đi (445x445 →
 * 445x334) nên cột gallery ngắn lại, bớt phần thò xuống dưới nút CTA mà đợt
 * chuyển hai cột về 50/50 đã tạo ra.
 */
.pd-main-swiper{
	order:1;
	width:100%;
	aspect-ratio:4 / 3;
	/*
	 * `flex:1 1 auto` — khung ảnh CÓ THỂ cao hơn 4/3 khi `.pd-gallery` (flex
	 * column) có khoảng dư để phân (xem docblock của `.pd-gallery` phía
	 * trên). `aspect-ratio` vẫn là kích thước TỰ NHIÊN/mặc định — không có
	 * khoảng dư (đáy hai cột vốn đã bằng nhau) thì khung giữ đúng 4/3 như cũ,
	 * không đổi gì. `min-height:0` (đã có sẵn ngay dưới, lý do gốc là chống
	 * bẫy tràn ngang Swiper) TRÙNG HỢP cũng là điều kiện flexbox cần để item
	 * co/giãn đúng thay vì bị khoá ở kích thước nội dung tối thiểu.
	 */
	flex:1 1 auto;
	border-radius:var(--r-lg);
	overflow:hidden;
	background:var(--img-bg);
	border:1px solid var(--border);
	/*
	 * width:100% + min-width/min-height:0 BẮT BUỘC: item lưới mặc định có
	 * min-size "auto" = kích thước NỘI DUNG — `.swiper-wrapper` của Swiper
	 * xếp tất cả slide hàng ngang (flex), N ảnh 1:1 xếp cạnh nhau khiến trình
	 * duyệt tính kích thước "auto" của chính `.swiper` (root) theo max-content
	 * của toàn bộ N slide thay vì stretch đúng theo track lưới cha khi kết
	 * hợp với `aspect-ratio` (đã đo thật: item rộng ĐÚNG BẰNG n × chiều rộng
	 * 1 ảnh, ví dụ 7 ảnh → ~2277px trên khung 327px — CÙNG BẪY tràn ngang đã
	 * gặp ở `.art-layout`/`.faq`, chỉ khác Swiper tự overflow:hidden bên
	 * trong nên không lộ ra ngoài `.pd-gallery`/trang, nhưng ảnh chính hiển
	 * thị SAI kích thước — không chỉ dựa vào `align-items:stretch` của lưới
	 * cha, phải khai `width:100%` tường minh ở đây).
	 */
	min-width:0;
	min-height:0;
}
.pd-main-swiper .swiper-slide{ display:flex; align-items:center; justify-content:center; background:var(--img-bg); }
.pd-main-swiper .swiper-slide svg{ width:80px; height:80px; color:var(--icon-muted); }
.pd-main-swiper .swiper-slide img{ width:100%; height:100%; object-fit:contain; background:var(--white); }

/* Nút prev/next trên ảnh chính — icon mặc định Swiper (font ::after), chỉ đổi màu/nền theo token site. */
.pd-main-swiper .swiper-button-prev,
.pd-main-swiper .swiper-button-next{
	width:38px;
	height:38px;
	margin-top:-19px;
	border-radius:var(--r-full);
	background:var(--white);
	opacity:.85;
	color:var(--navy);
	transition:opacity var(--dur-micro) var(--ease);
}
.pd-main-swiper .swiper-button-prev:hover,
.pd-main-swiper .swiper-button-next:hover{ opacity:1; }
.pd-main-swiper .swiper-button-prev:after,
.pd-main-swiper .swiper-button-next:after{ font-size:15px; font-weight:700; }
/* Icon SVG mặc định của Swiper (swiper-navigation-icon) bị vendor CSS ép width:100%;height:100% theo nút (38x38) -> vuông hoá, méo tỉ lệ gốc viewBox "0 0 11 20".
 * Ghi đè riêng ở đây (không sửa file vendor) để thu nhỏ icon, GIỮ đúng tỉ lệ 11:20 bằng width cố định + height:auto.
 * Độ đặc hiệu: 3 class + tag (.pd-main-swiper .swiper-button-prev/-next svg.swiper-navigation-icon) thắng rule vendor (2 class + tag). */
.pd-main-swiper .swiper-button-prev svg.swiper-navigation-icon,
.pd-main-swiper .swiper-button-next svg.swiper-navigation-icon{
	width:11px;
	height:auto;
}
/* 1 ảnh duy nhất -> Swiper tự gắn .swiper-button-disabled trên CẢ hai nút; ẩn hẳn thay vì chỉ mờ (mặc định của thư viện). */
.pd-main-swiper .swiper-button-disabled{ display:none; }

/*
 * Be rong tung thumb do Swiper tinh (slidesPerView so nguyen trong
 * assets/js/product-single.js), KHONG dat cung o day — dat cung thi Swiper
 * van chia khung theo slidesPerView roi cat mep, dung cai khach keu "thumb
 * bi cat".
 *
 * TỈ LỆ ĐỔI VUÔNG -> 4/3 cùng lượt với ảnh chính (khách 24/08/2026). Đây là
 * phần ĐI KÈM chứ khách chỉ nói "feature image", nên nói rõ lý do: thumb là
 * BẢN XEM TRƯỚC của đúng những ảnh đó. Để thumb cover-vuông trong khi ảnh
 * chính contain-4/3 thì cùng một tấm ảnh hiện hai khuôn hình khác nhau —
 * bấm vào thumb ra một bố cục khác thứ vừa nhìn thấy. Giữ `aspect-ratio`
 * (chỉ đổi giá trị) nên vẫn đúng lý lẽ gốc ở trên: chiều cao thumb do bề
 * rộng Swiper vừa chia quyết định, không đặt cứng px.
 */
/* `flex:0 0 auto` — giữ nguyên kích thước tự nhiên trong `.pd-gallery` (flex column), không nhận phần khoảng dư (khoảng dư chảy vào .pd-main-swiper, xem rule đó). */
.pd-thumbs-swiper{ order:2; width:100%; min-width:0; flex:0 0 auto; }
.pd-thumbs-swiper .swiper-slide{ aspect-ratio:4 / 3; height:auto; }
.pd-thumb{
	width:100%;
	height:100%;
	border-radius:var(--r-sm);
	overflow:hidden;
	cursor:pointer;
	background:var(--img-bg);
	border:2px solid var(--border);
	display:flex;
	align-items:center;
	justify-content:center;
	transition:border-color var(--dur-micro) var(--ease);
}
.pd-thumb svg{ width:30px; height:30px; color:var(--icon-muted); }
.pd-thumb img{ width:100%; height:100%; object-fit:contain; background:var(--white); }
.pd-thumb:hover{ border-color:var(--cobalt); }
/* Swiper Thumbs module tự gắn class này lên slide đang đồng bộ với main-swiper — thay cho .active thủ công cũ. */
.pd-thumb.swiper-slide-thumb-active{ border-color:var(--navy); }

/* Thông tin sản phẩm */
.pd-info h1{ font-size:30px; color:var(--navy); line-height:1.25; margin-bottom:10px; }
.pd-specs{ display:flex; flex-direction:column; gap:0; margin-bottom:28px; }
.pd-spec{
	display:grid;
	grid-template-columns:150px 1fr;
	gap:var(--sp-4);
	padding:var(--sp-3) 0;
	border-bottom:1px solid var(--border);
	font-size:14.5px;
}
.pd-spec:last-child{ border-bottom:none; }
/*
 * STT 28(a) feedback đợt 1: "cột này a chỉnh cho chữ lên 1 hàng giúp e" — nhãn
 * dài nhất ("Thời gian sản xuất") xuống 2 dòng trong cột nhãn 150px. KHÔNG
 * nowrap vô điều kiện (nhãn dài hơn thế + màn hẹp sẽ tràn ngang, đúng bẫy dự
 * án đã gặp nhiều lần) — chỉ ép 1 hàng ở bề rộng đủ chỗ (>=901px, cùng mốc
 * .pd-top chuyển 2 cột), đồng thời nới cột nhãn 150px -> 168px để "Thời gian
 * sản xuất" (nhãn dài nhất trong dữ liệu thật đang có) đủ chỗ một hàng ở mốc
 * đó — xem assertion CSS trong tests/test-product-single.php khoá cả hai.
 */
@media(min-width:901px){
	.pd-spec{ grid-template-columns:168px 1fr; }
	.pd-spec .k{ white-space:nowrap; }
}
.pd-spec .k{ color:var(--text-muted); display:flex; align-items:center; gap:9px; }
.pd-spec .k svg{ width:17px; height:17px; color:var(--cobalt); flex-shrink:0; }
.pd-spec .v{ color:var(--text); font-weight:600; }
.pd-cta-row{ display:flex; gap:14px; flex-wrap:wrap; }
.pd-cta{
	display:inline-flex;
	align-items:center;
	gap:9px;
	background:var(--navy);
	color:var(--white);
	font-weight:700;
	font-family:var(--font-head);
	padding:15px 30px;
	border-radius:var(--r-pill);
	text-decoration:none;
	font-size:15px;
	transition:background var(--dur-micro) var(--ease), transform var(--dur-micro) var(--ease);
}
.pd-cta:hover{ background:var(--navy-dark); transform:translateY(-2px); }
.pd-cta svg{ width:18px; height:18px; }
.pd-cta-ghost{
	display:inline-flex;
	align-items:center;
	gap:9px;
	background:var(--white);
	color:var(--navy);
	font-weight:700;
	font-family:var(--font-head);
	padding:15px 30px;
	border-radius:var(--r-pill);
	text-decoration:none;
	font-size:15px;
	border:1.5px solid var(--border);
	transition:border-color var(--dur-micro) var(--ease);
}
.pd-cta-ghost:hover{ border-color:var(--navy); }

/* ---------- Đánh giá khách hàng ---------- */
.pd-review{ background:var(--white); padding:64px var(--wrap-x); }
.pd-review-wrap{ max-width:860px; margin:0 auto; }
.pd-review .section-head{ text-align:left; margin:0 0 8px; }
.pd-review-head{
	display:flex;
	gap:var(--sp-4);
	align-items:center;
	margin-bottom:20px;
	padding-bottom:20px;
	border-bottom:1px solid var(--border);
}
.pd-rating-num{ font-family:var(--font-head); font-weight:800; font-size:38px; color:var(--navy); line-height:1; }
.pd-stars{ display:flex; gap:3px; }
.pd-stars svg{ width:18px; height:18px; }
.pd-star-full{ color:#FFB020; }
.pd-star-empty{ color:var(--border); }
.pd-rating-count{ font-size:13.5px; color:var(--text-muted); margin-top:3px; }
.pd-review-list{ display:flex; flex-direction:column; }
.pd-review-card{ padding:18px 0; border-bottom:1px solid var(--border); }
.pd-review-card:last-child{ border-bottom:none; }
.pd-review-card:first-child{ padding-top:0; }
.pd-review-top{ display:flex; align-items:center; gap:var(--sp-4); margin-bottom:10px; }
.pd-review-ava{
	width:48px;
	height:48px;
	border-radius:var(--r-full);
	flex-shrink:0;
	background:linear-gradient(140deg, var(--navy), var(--cobalt));
	display:flex;
	align-items:center;
	justify-content:center;
	color:var(--white);
	font-weight:700;
	font-family:var(--font-head);
	font-size:17px;
	text-transform:uppercase;
}
.pd-review-who .name{ font-weight:700; color:var(--navy); font-size:15.5px; font-family:var(--font-head); margin-bottom:4px; }
.pd-review-who .pd-stars svg{ width:15px; height:15px; }
.pd-review-card p{ color:var(--text-muted); font-size:15px; line-height:1.75; }

/*
 * STT 30 feedback đợt 1: nút "Xem thêm đánh giá" — CHỈ ẩn/hiện đúng những
 * dòng vượt VINPACK_PD_REVIEW_CAP (single-vp_product.php), không phải AJAX/
 * phân trang. `.is-review-more` bị JS (assets/js/product-single.js) gỡ khi
 * bấm nút — không có transition cầu kỳ, chỉ ẩn/hiện, đúng tinh thần "nút
 * thật, không phải trang trí".
 */
.pd-review-card.is-review-more{ display:none; }
.pd-review-more{
	display:inline-flex;
	align-items:center;
	gap:8px;
	margin-top:20px;
	padding:12px 26px;
	border-radius:var(--r-pill);
	border:1.5px solid var(--border);
	background:transparent;
	color:var(--navy);
	font-weight:700;
	font-family:var(--font-head);
	font-size:14.5px;
	cursor:pointer;
	transition:border-color var(--dur-micro) var(--ease);
}
.pd-review-more:hover{ border-color:var(--navy); }
.pd-review-more svg{ width:16px; height:16px; }

/* ---------- Sản phẩm liên quan ---------- */
.pd-related{ background:var(--white); padding:64px var(--wrap-x) 80px; }
.pd-related .section-head{ text-align:left; max-width:var(--wrap-max); margin:0 auto 40px; }
/*
 * SỬA — khách: "cho slide 6 cái đi". `.pd-related-grid` (CSS Grid tĩnh, cố
 * định 4 ô) đổi thành `.pd-related-swiper` — Swiper THẬT, cùng thư viện đã
 * tải cho `.pd-main-swiper` ở trên (assets/js/product-single.js). Bề rộng
 * mỗi `.swiper-slide` do JS tính (slidesPerView SỐ NGUYÊN, không freeMode —
 * cùng nguyên tắc "card luôn trọn vẹn, không cắt nửa ở mép" đã áp cho
 * `.pd-thumbs-swiper`), nên KHÔNG có `grid-template-columns` nào ở CSS —
 * ba mốc breakpoint bên dưới CHỈ khai lại đúng số cột cũ (4/2/1) làm tài
 * liệu tham chiếu cho JS, bản thân CSS không tự chia cột được nữa.
 *
 * `.prod-card` bên trong hoàn toàn KHÔNG đổi — vẫn đúng class dùng CHUNG với
 * lưới trang danh mục (taxonomy-danhmuc.css). Chỉ thêm `.swiper-slide` làm
 * lớp bọc mà Swiper yêu cầu.
 */
.pd-related-swiper{ max-width:var(--wrap-max); margin:0 auto; }
.pd-related-swiper .swiper-slide{ height:auto; }
.pd-related-swiper .swiper-slide .prod-card{ height:100%; }

/* Nút prev/next — CÙNG khuôn `.pd-main-swiper .swiper-button-prev/-next` phía trên (icon mặc định Swiper, chỉ đổi màu/nền theo token site). */
.pd-related-swiper .swiper-button-prev,
.pd-related-swiper .swiper-button-next{
	width:38px;
	height:38px;
	margin-top:-19px;
	border-radius:var(--r-full);
	background:var(--white);
	opacity:.85;
	color:var(--navy);
	transition:opacity var(--dur-micro) var(--ease);
}
.pd-related-swiper .swiper-button-prev:hover,
.pd-related-swiper .swiper-button-next:hover{ opacity:1; }
.pd-related-swiper .swiper-button-prev:after,
.pd-related-swiper .swiper-button-next:after{ font-size:15px; font-weight:700; }
/* Cùng lý do đã ghi ở .pd-main-swiper: icon SVG mặc định của Swiper bị vendor CSS ép vuông (width/height:100% theo nút 38x38), méo tỉ lệ gốc 11:20 — ghi đè riêng, KHÔNG sửa file vendor. */
.pd-related-swiper .swiper-button-prev svg.swiper-navigation-icon,
.pd-related-swiper .swiper-button-next svg.swiper-navigation-icon{
	width:11px;
	height:auto;
}
/* Đủ 6 ô nhưng khung hẹp (mobile) vẫn có thể không đủ để cuộn -> Swiper tự gắn .swiper-button-disabled; ẩn hẳn thay vì chỉ mờ, cùng quyết định đã áp cho .pd-main-swiper. */
.pd-related-swiper .swiper-button-disabled{ display:none; }

/* ===== Responsive ===== */
@media(max-width:900px){
	/*
	 * SỬA (27/08/2026, khách chụp /san-pham/bao-bi-xuc-xich/ trên mobile, báo
	 * "sửa mobi tất cả trang single product lỗi quá"): 1 cột ở đây từng khai
	 * `1fr` TRẦN — khác `.pd-top` bản gốc >=901px đã cố ý dùng
	 * `minmax(0, 1fr) minmax(0, 1fr)` (xem docblock STT 50/50 phía trên) để
	 * chống đúng lỗi "grid blowout": track `1fr` trần không tự co xuống dưới
	 * kích thước NỘI DUNG TỐI THIỂU của item — mà `.pd-gallery` (Swiper) nội
	 * bộ dàn các slide theo hàng ngang (flex) rộng bằng tổng slide, nên
	 * item co dãn theo `1fr` trần bị buộc phình ra bằng độ rộng NỘI DUNG đó
	 * (~2662px đo được ở viewport 375px) thay vì co về đúng bề rộng khung
	 * hiển thị — kéo sập toàn bộ layout .pd-top/.pd-info/.pd-specs theo, vì
	 * chúng là con bình thường bên trong item đã bị phình. Đổi sang
	 * `minmax(0, 1fr)` (một track vẫn = 100% do chỉ có 1 track, nhưng CÓ trần
	 * co nhỏ) — sửa dứt điểm, không phải vá triệu chứng từng khối con.
	 */
	.pd-top{ grid-template-columns:minmax(0, 1fr); gap:var(--sp-6); }
	.pd-review-list{ gap:var(--sp-4); }
	/* 2 cột ở khổ này — JS đọc breakpoint 601 (assets/js/product-single.js), dòng CSS này chỉ còn là tài liệu tham chiếu (xem docblock .pd-related-swiper). */
	.pd-review-head{ flex-wrap:wrap; }
}
@media(max-width:600px){
	/*
	 * Bo cuc mot cot (anh chinh tren, thumb ngang duoi) gio la MAC DINH o moi
	 * be rong — xem `.pd-gallery` o tren. O day chi con thu gon khoang cach.
	 * So thumb hien moi khung do slidesPerView trong JS quyet dinh theo
	 * breakpoint, khong dat cung be rong thumb o CSS nua.
	 */
	.pd-gallery{ gap:10px; }
	.pd-info h1{ font-size:24px; }
	.pd-spec{ grid-template-columns:130px 1fr; gap:10px; }
	/* 1 cột ở khổ này — JS đọc breakpoint mặc định slidesPerView:1 (assets/js/product-single.js), dòng CSS này chỉ còn là tài liệu tham chiếu. */
	/*
	 * SỬA LẦN 2 — khách (21/08/2026): "button liên hệ đang bị rớt chữ trên
	 * điện thoại chỉnh 2 hàng". Bản SỬA LẦN 1 (STT 32, ghi lại nguyên văn ở
	 * trên) đo và chốt "16px mỗi bên chừa 116px — đủ cho hai dòng" — ĐÚNG khi
	 * đo bằng trình duyệt tự động (Manrope tải thành công, `--font-head`
	 * mục 2 global.css). Trên ĐIỆN THOẠI THẬT của khách, 116px lại KHÔNG đủ:
	 * `--font-head: 'Manrope', system-ui, -apple-system, 'Segoe UI',
	 * sans-serif` — hễ Manrope tải chậm/lỗi (mạng di động, font-display),
	 * chữ rơi về font hệ thống, mà các font hệ thống KHÔNG cùng bề rộng ký tự
	 * với Manrope. Cùng 116px, một font rộng hơn vài phần trăm là đủ để
	 * "Nhận báo giá ngay" rớt sang dòng thứ BA (đúng chữ "rớt chữ" khách
	 * dùng) — lỗi CHỈ lộ ra tuỳ font đang tải, đúng loại lỗi lúc đo không
	 * thấy, lúc dùng thật mới thấy.
	 *
	 * THAY VÌ CÀNG SIẾT ĐỆM (dò tiếp một con số nhỏ hơn 16px, vẫn phụ thuộc
	 * đúng font nào đang render — không triệt để): bỏ hẳn layout CẠNH NHAU,
	 * XẾP CHỒNG hai nút thành 2 HÀNG riêng (đúng chữ khách dùng) — mỗi nút
	 * rộng gần HẾT `.pd-cta-row` (~295px sau padding, so với ~116px cũ),
	 * KHÔNG còn phụ thuộc font nào đang tải nữa: dư sức cho MỘT dòng chứ
	 * không chỉ hai, bất kể Manrope hay font hệ thống.
	 */
	.pd-cta-row{ flex-direction:column; }
	.pd-cta,.pd-cta-ghost{ justify-content:center; white-space:normal; text-align:center; line-height:1.3; padding-inline:20px; }
	.pd-cta svg,.pd-cta-ghost svg{ flex-shrink:0; }
}
