/**
 * HVShop Voucher - frontend styles.
 *
 * @package Hvshop_Voucher
 */

:root {
	--hvshop-voucher-accent: #d9534f;
}

.hvshop-voucher {
	--hvshop-voucher-bg: #ffffff;
	--hvshop-voucher-border: #e4e7ec;
	--hvshop-voucher-text: #1f2430;
	--hvshop-voucher-muted: #6b7280;
	--hvshop-voucher-soft: #f7f8fa;
	--hvshop-voucher-radius: 10px;
	--hvshop-voucher-gap: 12px;
	--hvshop-voucher-cols: 3;

	/* Narrowest a card may get before the grid drops a column. Keeps the block
	   readable inside a sidebar or a product summary column, where the viewport
	   width says nothing about the space actually available. */
	--hvshop-voucher-min: 230px;

	box-sizing: border-box;
	margin: 0 0 22px;
	width: 100%;
	color: var(--hvshop-voucher-text);
	font-size: 14px;
	line-height: 1.5;
}

.hvshop-voucher *,
.hvshop-voucher *::before,
.hvshop-voucher *::after {
	box-sizing: border-box;
}

.hvshop-voucher :focus-visible {
	outline: 2px solid var(--hvshop-voucher-accent);
	outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
 * Header
 * ------------------------------------------------------------------------ */

.hvshop-voucher__header {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 7px;
	margin-bottom: 10px;
}

.hvshop-voucher__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 24px;
	height: 24px;
	border-radius: 7px;
	color: var(--hvshop-voucher-accent);
	background: color-mix(in srgb, var(--hvshop-voucher-accent) 12%, transparent);
	flex: 0 0 auto;
}

.hvshop-voucher .hvshop-voucher__title {
	/* `width: auto` undoes Flatsome's `h1, h2, h3, h4, h5, h6 { width: 100% }`:
	   as a flex item that width becomes the base size, so the heading claims the
	   whole row and pushes the "Xem tất cả" button onto a line of its own.
	   `min-width: 0` then lets it wrap instead of shoving the button out of the
	   block. */
	flex: 0 1 auto;
	width: auto;
	min-width: 0;
	margin: 0;
	padding: 0;
	font-size: 16px;
	font-weight: 700;
	line-height: 1.3;
	color: var(--hvshop-voucher-text);
	text-transform: none;
	letter-spacing: 0;
}

/* ---------------------------------------------------------------------------
 * Layout
 * ------------------------------------------------------------------------ */

.hvshop-voucher__list {
	display: grid;
	gap: var(--hvshop-voucher-gap);
	grid-template-columns: repeat(var(--hvshop-voucher-cols), minmax(0, 1fr));
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Two classes on purpose: Flatsome indents list items with
   `.entry-summary ul li { margin-left: 1.3em }` (0,1,2), which outranks a
   single-class selector and pushes every card off its own grid track. */
.hvshop-voucher .hvshop-voucher__list > li {
	list-style: none;
	margin: 0;
}

.hvshop-voucher--cols-1 { --hvshop-voucher-cols: 1; }
.hvshop-voucher--cols-2 { --hvshop-voucher-cols: 2; }
.hvshop-voucher--cols-3 { --hvshop-voucher-cols: 3; }
.hvshop-voucher--cols-4 { --hvshop-voucher-cols: 4; }
.hvshop-voucher--cols-5 { --hvshop-voucher-cols: 5; }
.hvshop-voucher--cols-6 { --hvshop-voucher-cols: 6; }

.hvshop-voucher--list .hvshop-voucher__list {
	--hvshop-voucher-cols: 1;
}

/* The configured column count is a maximum, not a promise: a track never gets
   narrower than --hvshop-voucher-min, so the grid sheds columns on its own when the
   *container* is small — no viewport media query can know that. */
@supports (width: max(1px, 1%)) {
	.hvshop-voucher__list {
		grid-template-columns: repeat(
			auto-fill,
			minmax(
				max(
					min(100%, var(--hvshop-voucher-min)),
					calc((100% - (var(--hvshop-voucher-cols) - 1) * var(--hvshop-voucher-gap)) / var(--hvshop-voucher-cols))
				),
				1fr
			)
		);
	}
}

/* Fallback for browsers without min()/max() in track sizing. */
@supports not (width: max(1px, 1%)) {
	@media (max-width: 1024px) {
		.hvshop-voucher--cols-4 .hvshop-voucher__list,
		.hvshop-voucher--cols-5 .hvshop-voucher__list,
		.hvshop-voucher--cols-6 .hvshop-voucher__list {
			--hvshop-voucher-cols: 3;
		}
	}

	@media (max-width: 782px) {
		.hvshop-voucher__list {
			--hvshop-voucher-cols: 2;
		}
	}

	@media (max-width: 560px) {
		.hvshop-voucher__list {
			--hvshop-voucher-cols: 1;
		}
	}
}

/* ---------------------------------------------------------------------------
 * Groups
 * ------------------------------------------------------------------------ */

.hvshop-voucher__group + .hvshop-voucher__group {
	margin-top: 14px;
}

.hvshop-voucher .hvshop-voucher__group-title {
	display: flex;
	align-items: center;
	gap: 6px;
	margin: 0 0 7px;
	padding: 0;
	font-size: 13px;
	font-weight: 700;
	line-height: 1.3;
	color: var(--hvshop-voucher-muted);
	text-transform: uppercase;
	letter-spacing: .3px;
}

.hvshop-voucher__group-count {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 18px;
	height: 18px;
	padding: 0 5px;
	border-radius: 999px;
	background: var(--hvshop-voucher-soft);
	color: var(--hvshop-voucher-muted);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0;
}

/* ---------------------------------------------------------------------------
 * Collapse ("Xem thêm N mã")
 * ------------------------------------------------------------------------ */

.hvshop-voucher:not(.is-expanded) .hvshop-voucher__list > li.hvshop-voucher-card.is-collapsed,
.hvshop-voucher:not(.is-expanded) .hvshop-voucher__group.is-collapsed {
	display: none;
}

.hvshop-voucher .hvshop-voucher__more {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 5px;
	margin: 10px 0 0;
	padding: 6px 14px;
	min-height: 0;
	border: 1px solid var(--hvshop-voucher-border);
	border-radius: 999px;
	background: #fff;
	color: var(--hvshop-voucher-muted);
	font-size: 13px;
	font-weight: 600;
	line-height: 1.3;
	text-transform: none;
	letter-spacing: 0;
	cursor: pointer;
	box-shadow: none;
	transition: color .15s ease, border-color .15s ease;
}

.hvshop-voucher .hvshop-voucher__more:hover,
.hvshop-voucher .hvshop-voucher__more:focus {
	color: var(--hvshop-voucher-accent);
	border-color: var(--hvshop-voucher-accent);
	background: #fff;
}

/* Themes that style every element inside `.button`-like controls also reach
   the chevron, so the rotation is scoped and forced the same way the spinner
   is (see the action button below). */
.hvshop-voucher .hvshop-voucher__more .hvshop-voucher__more-icon {
	display: block !important;
	flex: 0 0 auto;
	transition: transform .18s ease;
}

.hvshop-voucher.is-expanded .hvshop-voucher__more .hvshop-voucher__more-icon {
	transform: rotate(180deg);
}

/* ---------------------------------------------------------------------------
 * Card
 * ------------------------------------------------------------------------ */

.hvshop-voucher-card {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 8px;
	padding: 11px 12px;
	background: var(--hvshop-voucher-bg);
	border: 1px solid var(--hvshop-voucher-border);
	border-radius: var(--hvshop-voucher-radius);
	overflow: hidden;
	transition: box-shadow .18s ease, border-color .18s ease;
}

.hvshop-voucher-card:hover {
	border-color: color-mix(in srgb, var(--hvshop-voucher-accent) 45%, var(--hvshop-voucher-border));
	box-shadow: 0 4px 14px rgba(16, 24, 40, .07);
}

.hvshop-voucher-card.is-applied {
	border-color: var(--hvshop-voucher-accent);
	background: color-mix(in srgb, var(--hvshop-voucher-accent) 4%, #fff);
	padding-left: 15px;
}

.hvshop-voucher-card.is-applied::before {
	content: "";
	position: absolute;
	inset: 0 auto 0 0;
	width: 3px;
	background: var(--hvshop-voucher-accent);
}

/* Hết hạn / hết lượt: chỉ hiển thị tham khảo. */

.hvshop-voucher-card.is-unusable {
	opacity: .62;
	filter: grayscale(1);
}

.hvshop-voucher-card.is-unusable:hover {
	border-color: var(--hvshop-voucher-border);
	box-shadow: none;
}

/* Giới hạn cho sản phẩm/danh mục khác: chỉ hiển thị tham khảo khi cài đặt
   "Mã không dùng được cho sản phẩm" để ở chế độ làm mờ. */

.hvshop-voucher-card.is-irrelevant {
	opacity: .72;
}

/* Giỏ hàng đang có mã "chỉ dùng riêng": WooCommerce sẽ từ chối mọi mã khác.
   Trạng thái này bật/tắt liên tục theo thao tác của khách nên chỉ làm mờ, không
   bao giờ ẩn thẻ — ẩn rồi thì JS không dựng lại được lúc khách gỡ mã ra. */

.hvshop-voucher-card.is-locked {
	opacity: .72;
}

.hvshop-voucher-card.is-locked:hover {
	border-color: var(--hvshop-voucher-border);
	box-shadow: none;
}

/* Mã lời nhất trong khối: viền đậm hơn một chút để mắt dừng lại đúng chỗ, nhưng
   nhạt hơn viền của thẻ đang áp dụng — hai trạng thái phải phân biệt được. Dùng
   :not() thay vì xếp thứ tự khai báo để thẻ vừa "tốt nhất" vừa "đang áp dụng"
   luôn hiện đúng kiểu thứ hai, bất kể sau này rule được dời đi đâu. */

.hvshop-voucher-card.is-best:not(.is-applied):not(.is-unusable):not(.is-locked):not(.is-irrelevant) {
	border-color: color-mix(in srgb, var(--hvshop-voucher-accent) 55%, var(--hvshop-voucher-border));
}

/* Mã cần có hàng trong giỏ mới áp được (giới hạn theo sản phẩm/danh mục, hoặc có
   đơn tối thiểu). Cùng kiểu trạng thái với .is-locked: đổi liên tục theo giỏ của
   từng khách nên chỉ làm mờ, và luôn do JS bật vì trang sản phẩm cache được. */

.hvshop-voucher-card.is-need-cart {
	opacity: .72;
}

.hvshop-voucher-card.is-need-cart:hover {
	border-color: var(--hvshop-voucher-border);
	box-shadow: none;
}

/* Dòng giải thích luôn có sẵn trong HTML (để trang cache được và JS chỉ phải bật
   một class), chỉ hiện khi thẻ đang ở đúng trạng thái đó. */

.hvshop-voucher .hvshop-voucher-card__lock,
.hvshop-voucher .hvshop-voucher-card__need-cart {
	display: none;
}

.hvshop-voucher .hvshop-voucher-card.is-locked .hvshop-voucher-card__lock,
.hvshop-voucher .hvshop-voucher-card.is-need-cart .hvshop-voucher-card__need-cart {
	display: block;
	margin: 4px 0 0;
	padding: 0;
	font-size: 12px;
	line-height: 1.35;
	color: var(--hvshop-voucher-muted);
}

/* Main (thumbnail + text) -------------------------------------------------*/

.hvshop-voucher-card__main {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	min-width: 0;
}

.hvshop-voucher-card__thumb {
	flex: 0 0 auto;
	width: 40px;
	height: 40px;
	padding: 3px;
	object-fit: contain;
	border-radius: 8px;
	background: var(--hvshop-voucher-soft);
}

.hvshop-voucher--no-image .hvshop-voucher-card__thumb {
	display: none;
}

.hvshop-voucher-card__info {
	flex: 1 1 auto;
	min-width: 0;
}

.hvshop-voucher .hvshop-voucher-card__discount {
	margin: 0;
	padding: 0;
	font-size: 15px;
	font-weight: 700;
	line-height: 1.35;
	color: var(--hvshop-voucher-accent);
	overflow-wrap: anywhere;
}

.hvshop-voucher-card__discount .woocommerce-Price-amount,
.hvshop-voucher-card__discount bdi {
	color: inherit;
	font-weight: inherit;
}

.hvshop-voucher .hvshop-voucher-card__expiry {
	display: flex;
	align-items: center;
	gap: 4px;
	margin: 2px 0 0;
	padding: 0;
	font-size: 12.5px;
	line-height: 1.4;
	color: var(--hvshop-voucher-muted);
}

.hvshop-voucher-card__expiry svg {
	flex: 0 0 auto;
}

/* Badges ------------------------------------------------------------------*/

.hvshop-voucher .hvshop-voucher-card__badges {
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
	margin: 4px 0 0;
	padding: 0;
	line-height: 1;
}

.hvshop-voucher-card__badge {
	display: inline-block;
	padding: 2px 6px;
	border-radius: 4px;
	background: var(--hvshop-voucher-soft);
	color: var(--hvshop-voucher-muted);
	font-size: 11px;
	font-weight: 600;
	line-height: 1.5;
	letter-spacing: 0;
	white-space: nowrap;
}

.hvshop-voucher-card__badge--expiring,
.hvshop-voucher-card__badge--usage {
	background: rgba(180, 35, 24, .09);
	color: #b42318;
}

.hvshop-voucher-card__badge--gap {
	background: rgba(180, 111, 0, .1);
	color: #b76f00;
}

/* "Lựa chọn tốt nhất": mã giảm được nhiều tiền nhất trong khối. Đây là nhãn duy
   nhất tô đặc màu nhấn — các nhãn khác chỉ chú thích thêm cho ưu đãi, còn nhãn
   này trả lời thẳng câu khách đang hỏi nên phải bắt mắt hơn hẳn. */

.hvshop-voucher-card__badge--best {
	background: var(--hvshop-voucher-accent);
	color: #fff;
	font-weight: 700;
}

/* Ba trạng thái này JS bật/tắt ngay trên trang sau khi khách đổi giỏ hàng, lúc
   đó thẻ đã bị làm mờ và nút đã bị chặn — giới thiệu nó là "tốt nhất" nữa thì
   chỉ dẫn khách vào một thông báo lỗi. Ẩn bằng CSS nên JS không phải biết gì
   thêm về nhãn này. */

.hvshop-voucher-card.is-unusable .hvshop-voucher-card__badge--best,
.hvshop-voucher-card.is-locked .hvshop-voucher-card__badge--best,
.hvshop-voucher-card.is-irrelevant .hvshop-voucher-card__badge--best {
	display: none;
}

/* Auto generated terms (đơn tối thiểu, số sản phẩm áp dụng…) ---------------*/

.hvshop-voucher .hvshop-voucher-card__terms {
	margin: 3px 0 0;
	padding: 0;
	font-size: 12.5px;
	line-height: 1.4;
	color: var(--hvshop-voucher-muted);
	overflow-wrap: anywhere;
}

/* Condition ---------------------------------------------------------------*/

.hvshop-voucher-card__condition {
	margin-top: 4px;
	font-size: 12.5px;
	line-height: 1.5;
	color: var(--hvshop-voucher-muted);
}

/* Clamped to two lines so every card in a row keeps the same height and the
   text ends with an ellipsis instead of a chopped word. */
.hvshop-voucher-card__condition-inner {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	overflow: hidden;
}

/* Switching `display` back is not enough: browsers that implement the modern
   `line-clamp` keep clamping until the line count itself is cleared. */
.hvshop-voucher-card__condition.is-open .hvshop-voucher-card__condition-inner {
	display: block;
	-webkit-line-clamp: none;
	line-clamp: none;
	overflow: visible;
}

.hvshop-voucher .hvshop-voucher-card__condition-inner p {
	margin: 0 0 4px;
	padding: 0;
	line-height: 1.5;
}

.hvshop-voucher .hvshop-voucher-card__condition-inner p:last-child {
	margin-bottom: 0;
}

.hvshop-voucher .hvshop-voucher-card__condition-inner ul,
.hvshop-voucher .hvshop-voucher-card__condition-inner ol {
	margin: 0 0 4px;
	padding-left: 16px;
}

.hvshop-voucher .hvshop-voucher-card__toggle {
	display: none;
	margin: 2px 0 0;
	padding: 0;
	min-height: 0;
	border: 0;
	border-radius: 0;
	background: none;
	color: var(--hvshop-voucher-accent);
	font-size: 12px;
	font-weight: 600;
	line-height: 1.4;
	text-transform: none;
	letter-spacing: 0;
	cursor: pointer;
}

.hvshop-voucher .hvshop-voucher-card__toggle:hover {
	text-decoration: underline;
}

/* Actions (code + button) -------------------------------------------------*/

.hvshop-voucher-card__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin-top: auto;
}

.hvshop-voucher-card__code-row {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	flex: 1 1 auto;
	min-width: 0;
}

.hvshop-voucher-card__code {
	display: inline-block;
	padding: 3px 8px;
	border: 1px dashed color-mix(in srgb, var(--hvshop-voucher-accent) 55%, var(--hvshop-voucher-border));
	border-radius: 6px;
	background: color-mix(in srgb, var(--hvshop-voucher-accent) 7%, #fff);
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 13px;
	font-weight: 700;
	line-height: 1.4;
	letter-spacing: .3px;
	text-transform: uppercase;
	color: var(--hvshop-voucher-text);
	overflow-wrap: anywhere;
}

.hvshop-voucher .hvshop-voucher-card__copy {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	min-height: 0;
	padding: 0;
	margin: 0;
	flex: 0 0 auto;
	border: 1px solid var(--hvshop-voucher-border);
	border-radius: 6px;
	background: #fff;
	color: var(--hvshop-voucher-muted);
	cursor: pointer;
	line-height: 1;
	transition: color .15s ease, border-color .15s ease, background .15s ease;
	box-shadow: none;
}

.hvshop-voucher .hvshop-voucher-card__copy:hover,
.hvshop-voucher .hvshop-voucher-card__copy:focus {
	color: var(--hvshop-voucher-accent);
	border-color: var(--hvshop-voucher-accent);
	background: color-mix(in srgb, var(--hvshop-voucher-accent) 8%, #fff);
}

.hvshop-voucher-card__copy svg {
	display: block;
	pointer-events: none;
}

/* Copy confirmation: the toast can be missed, the icon swap cannot. */
.hvshop-voucher-card__copy .hvshop-voucher-card__copy-done,
.hvshop-voucher-card__copy.is-copied .hvshop-voucher-card__copy-icon {
	display: none;
}

.hvshop-voucher-card__copy.is-copied .hvshop-voucher-card__copy-done {
	display: block;
}

.hvshop-voucher .hvshop-voucher-card__copy.is-copied {
	color: #12805c;
	border-color: #12805c;
	background: rgba(18, 128, 92, .08);
}

/* Action button -----------------------------------------------------------*/

.hvshop-voucher .hvshop-voucher-card__action {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 7px;
	flex: 1 1 96px;
	min-height: 34px;
	margin: 0;
	padding: 6px 14px;
	border: 1px solid var(--hvshop-voucher-accent);
	border-radius: 8px;
	background: var(--hvshop-voucher-accent);
	color: #fff;
	font-size: 13.5px;
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: 0;
	text-align: center;
	text-decoration: none;
	text-transform: none;
	white-space: nowrap;
	cursor: pointer;
	box-shadow: none;
	transition: opacity .15s ease, background .15s ease, color .15s ease;
}

.hvshop-voucher .hvshop-voucher-card__action:hover,
.hvshop-voucher .hvshop-voucher-card__action:focus {
	opacity: .9;
	color: #fff;
	background: var(--hvshop-voucher-accent);
}

.hvshop-voucher .hvshop-voucher-card__action.is-remove {
	background: #fff;
	color: var(--hvshop-voucher-accent);
}

.hvshop-voucher .hvshop-voucher-card__action.is-remove:hover,
.hvshop-voucher .hvshop-voucher-card__action.is-remove:focus {
	background: color-mix(in srgb, var(--hvshop-voucher-accent) 8%, #fff);
	color: var(--hvshop-voucher-accent);
}

/* `:not(.is-loading)`: the button is disabled while a request is in flight too,
   but it must keep its colour there instead of flashing the grey style. */
.hvshop-voucher .hvshop-voucher-card__action[disabled]:not(.is-loading),
.hvshop-voucher .hvshop-voucher-card__action[disabled]:not(.is-loading):hover {
	cursor: not-allowed;
	opacity: .7;
	background: var(--hvshop-voucher-soft);
	border-color: var(--hvshop-voucher-border);
	color: var(--hvshop-voucher-muted);
}

.hvshop-voucher .hvshop-voucher-card__action.is-loading {
	cursor: default;
	opacity: .75;
}

/* The spinner is taken out of flow and centred instead of sitting next to the
   label, so the button is exactly as wide while loading as it is at rest.
   Laid out inline it added 14px + the 7px gap on top of a longer label, which
   overflowed the rounded edge whenever the code chip and the button shared a
   row (cards around 250px wide). Centring uses margins, not `transform`,
   because `transform` belongs to the spin animation. */
/* Themes such as Flatsome style every span inside `.button`
   (`.button span { display: inline-block }`), which beats a single class
   selector. Keep the spinner rules scoped and forced. */
.hvshop-voucher .hvshop-voucher-card__action .hvshop-voucher-card__spinner {
	position: absolute;
	top: 50%;
	left: 50%;
	display: none !important;
	width: 14px;
	height: 14px;
	margin: -7px 0 0 -7px;
	border: 2px solid currentColor;
	border-right-color: transparent;
	border-radius: 50%;
	animation: hvshop-voucher-spin .7s linear infinite;
}

.hvshop-voucher .hvshop-voucher-card__action.is-loading .hvshop-voucher-card__spinner {
	display: block !important;
}

/* `visibility` rather than `display`, so the hidden label keeps reserving its
   own width and the button cannot shrink under the spinner. The label text is
   never swapped while loading — see `setLoading()` in the public script. */
.hvshop-voucher .hvshop-voucher-card__action.is-loading .hvshop-voucher-card__action-text {
	visibility: hidden;
}

@keyframes hvshop-voucher-spin {
	to { transform: rotate(360deg); }
}

/* List layout -------------------------------------------------------------*/

/* One card per row; the content sits on a single line and wraps by itself when
   the container is too narrow — again without asking the viewport. */
.hvshop-voucher--list .hvshop-voucher-card {
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 14px;
}

.hvshop-voucher--list .hvshop-voucher-card__main {
	flex: 1 1 240px;
}

.hvshop-voucher--list .hvshop-voucher-card__actions {
	flex: 0 1 auto;
	margin-top: 0;
}

.hvshop-voucher--list .hvshop-voucher-card__action {
	flex: 0 0 auto;
	min-width: 110px;
}

/* ---------------------------------------------------------------------------
 * Ticket layout
 *
 * A compact strip of two-panel tickets with the rest of the offers behind a
 * dialog. Everything reuses the `hvshop-voucher-card*` hooks so the apply /
 * remove / copy scripts keep working untouched; only the presentation differs.
 * ------------------------------------------------------------------------ */

.hvshop-voucher--ticket {
	--hvshop-voucher-gap: 10px;
	--hvshop-voucher-stub: 78px;

	/* A ticket needs this much room before a second column is worth having. */
	--hvshop-voucher-min: 230px;

	/* Ceiling for one ticket on the strip. The headline is clamped to a single
	   line and everything else lives in the "Xem thể lệ" dialog, so extra width
	   buys nothing: past this point a ticket only looks stretched. Wide blocks
	   therefore get two compact tickets instead of two half-empty ones. */
	--hvshop-voucher-ticket-max: 280px;
}

/* The block on the page reads as one box: light frame, light fill, white
   tickets inside. The dialog brings its own chrome, so it is left out. */
.hvshop-voucher--ticket:not(.hvshop-voucher-modal) {
	/* Two tickets, the gap between them, and the box's own padding and border.
	   A wider frame on a full-width page (cart, shortcode) would only draw an
	   empty half to the right of the strip. */
	max-width: calc(2 * var(--hvshop-voucher-ticket-max) + var(--hvshop-voucher-gap) + 28px);
	padding: 12px 13px 13px;
	border: 1px solid var(--hvshop-voucher-border);
	border-radius: 12px;
	background: var(--hvshop-voucher-soft);
}

/* Two tickets side by side at most, and only while both stay above
   --hvshop-voucher-min; the shared track formula below sheds the second column
   on its own in a sidebar or on a phone. */
.hvshop-voucher--ticket .hvshop-voucher__list {
	--hvshop-voucher-cols: 2;
}

/* One ticket per row inside the dialog. Two columns is right for the strip,
   where the point is to fit a teaser into the page; the dialog is a list to
   read down, and a full-width row is what the customer already knows from
   v1.2.1. Written with both classes so it outranks the rule above wherever
   this file ends up being concatenated. */
.hvshop-voucher--ticket.hvshop-voucher-modal .hvshop-voucher__list {
	--hvshop-voucher-cols: 1;
}

.hvshop-voucher--ticket .hvshop-voucher__header {
	margin-bottom: 9px;
}

/* The teaser strip is one row. When only a single column fits, the second
   ticket would start a second row, so it is dropped instead — everything it
   held is one tap away in the dialog. */
.hvshop-voucher__list--strip {
	container-type: inline-size;
	container-name: hvshop-voucher-strip;
}

/* The shared track formula lays out two columns whether or not there is a second
   ticket to put in one, so a block holding a single coupon would sit in the left
   half of its box with the right half empty. */
.hvshop-voucher__list--strip:not(:has(> li + li)) {
	grid-template-columns: 1fr;
}

/* 470px = 2 × --hvshop-voucher-min (230) + --hvshop-voucher-gap (10), i.e. the
   exact width at which the track formula above stops giving a second column.
   Written as `not (min-width: …)` so the two never disagree on the boundary. */
@container hvshop-voucher-strip not (min-width: 470px) {
	.hvshop-voucher__list--strip > li:nth-child(n+2) {
		display: none;
	}
}

/* Above the same boundary the ticket stops growing with the block. Below it the
   strip holds a single ticket, which keeps filling the row: a capped ticket on a
   phone would leave a lopsided gap on its right. `:has()` makes the same point
   about a block that only ever had one coupon to show. */
@container hvshop-voucher-strip (min-width: 470px) {
	.hvshop-voucher__list--strip:has(> li + li) > li {
		max-width: var(--hvshop-voucher-ticket-max);
	}
}

/* Same two rules for browsers without container queries, keyed on the viewport. */
@supports not (container-type: inline-size) {
	@media (max-width: 640px) {
		.hvshop-voucher__list--strip > li:nth-child(n+2) {
			display: none;
		}
	}

	@media (min-width: 641px) {
		.hvshop-voucher__list--strip:has(> li + li) > li {
			max-width: var(--hvshop-voucher-ticket-max);
		}
	}
}

.hvshop-voucher .hvshop-voucher__all {
	display: inline-flex;

	/* Never let the heading squeeze this button below its own content: the
	   chevron would spill past the edge of the block. */
	flex: 0 0 auto;
	align-items: center;
	gap: 2px;
	margin: 0 0 0 auto;
	padding: 2px 0 2px 8px;
	min-height: 0;
	border: 0;
	border-radius: 0;
	background: none;
	color: var(--hvshop-voucher-accent);
	font-size: 13px;
	font-weight: 600;
	line-height: 1.3;
	text-transform: none;
	letter-spacing: 0;
	white-space: nowrap;
	cursor: pointer;
	box-shadow: none;
}

.hvshop-voucher .hvshop-voucher__all:hover,
.hvshop-voucher .hvshop-voucher__all:focus {
	background: none;
	color: var(--hvshop-voucher-accent);
	text-decoration: underline;
	text-underline-offset: 2px;
}

/* Themes that style every element inside a control also reach this chevron. */
.hvshop-voucher .hvshop-voucher__all .hvshop-voucher__all-icon {
	display: block !important;
	flex: 0 0 auto;
}

/* Ticket body -------------------------------------------------------------*/

.hvshop-voucher--ticket .hvshop-voucher-card {
	flex-direction: row;
	align-items: stretch;
	gap: 0;
	padding: 0;

	/* Makes the ticket itself the reference for the container query below: the
	   block can sit in a sidebar or a product column, where the viewport width
	   says nothing about the room a ticket actually has. */
	container-type: inline-size;
}

.hvshop-voucher--ticket .hvshop-voucher-card.is-applied {
	padding-left: 0;
	border-color: var(--hvshop-voucher-accent);
}

/* The coloured stub already marks the ticket, so the accent bar the grid card
   draws on its left edge would only sit on top of it. */
.hvshop-voucher--ticket .hvshop-voucher-card.is-applied::before {
	content: none;
}

.hvshop-voucher-ticket__stub {
	position: relative;
	display: flex;
	flex: 0 0 var(--hvshop-voucher-stub);
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 1px;

	/* Without this the automatic minimum size of a flex item lets the stub grow
	   past its own basis to fit a value that must not wrap, and a long label
	   would eat the ticket instead of being cut short. */
	min-width: 0;
	padding: 10px 5px;
	background: var(--hvshop-voucher-accent);
	color: #fff;
	text-align: center;
}

/* Perforation. A dashed line rather than punched-out circles: a notch would
   have to be filled with the page background, and the block can sit on any
   colour the theme happens to use. */
.hvshop-voucher-ticket__stub::after {
	content: "";
	position: absolute;
	top: 7px;
	right: 0;
	bottom: 7px;
	border-right: 1px dashed rgba(255, 255, 255, .5);
}

.hvshop-voucher-ticket__stub-prefix {
	max-width: 100%;
	font-size: 11.5px;
	font-weight: 500;
	line-height: 1.2;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	opacity: .92;
}

/* The amount is the one thing a customer reads first, so it never breaks: "200K"
   split into "200" and "K" reads as two different numbers. Long values step the
   font down instead (see the `is-*` classes below), which the template picks by
   counting characters. */
.hvshop-voucher-ticket__stub-value {
	max-width: 100%;
	font-size: 18px;
	font-weight: 800;
	line-height: 1.15;
	letter-spacing: -.2px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* "1.234K", "999,9K" — six or seven characters. */
.hvshop-voucher-ticket__stub-value.is-long {
	font-size: 15px;
	letter-spacing: -.1px;
}

/* Anything a translation or the `hvshop_voucher_short_discount` filter makes
   longer still; better small than cut off. */
.hvshop-voucher-ticket__stub-value.is-longer {
	font-size: 12.5px;
	letter-spacing: 0;
}

.hvshop-voucher-ticket__body {
	display: flex;
	flex: 1 1 auto;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: 7px 10px;
	min-width: 0;
	padding: 9px 11px;
}

.hvshop-voucher-ticket__text {
	flex: 1 1 130px;
	min-width: 0;
}

/* One line, cut with an ellipsis. A campaign name can run to a whole sentence,
   and letting it wrap was what made the ticket wide: the full text is one tap
   away under "Xem thể lệ", which prints it as the dialog heading. */
.hvshop-voucher .hvshop-voucher-ticket__title {
	margin: 0;
	padding: 0;
	font-size: 14px;
	font-weight: 700;
	line-height: 1.35;
	color: var(--hvshop-voucher-text);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* Two lines keep every ticket in the strip the same height. */
.hvshop-voucher .hvshop-voucher-ticket__terms {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	overflow: hidden;
	margin: 2px 0 0;
	padding: 0;
	font-size: 12.5px;
	line-height: 1.4;
	color: var(--hvshop-voucher-muted);
	overflow-wrap: anywhere;
}

.hvshop-voucher .hvshop-voucher-ticket__expiry {
	margin: 2px 0 0;
	padding: 0;
	font-size: 12px;
	line-height: 1.4;
	color: var(--hvshop-voucher-muted);
}

/* Vé chỉ rộng 280px nên dòng khoá cũng cắt 1 dòng như tên chương trình, tránh
   làm vé cao thêm khi khách áp một mã "chỉ dùng riêng". */
.hvshop-voucher--ticket .hvshop-voucher-card.is-locked .hvshop-voucher-card__lock,
.hvshop-voucher--ticket .hvshop-voucher-card.is-need-cart .hvshop-voucher-card__need-cart {
	margin-top: 2px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.hvshop-voucher--ticket .hvshop-voucher-card__badges {
	margin-top: 5px;
}

.hvshop-voucher-ticket__cta {
	display: flex;
	flex: 0 0 auto;
	flex-direction: column;
	align-items: stretch;
	gap: 3px;
	margin-left: auto;
}

.hvshop-voucher--ticket .hvshop-voucher-card__action {
	flex: 0 0 auto;
	min-width: 94px;
	min-height: 32px;
	padding: 5px 12px;
	font-size: 13px;
}

.hvshop-voucher .hvshop-voucher-ticket__rules {
	display: block;
	margin: 0;
	padding: 0;
	min-height: 0;
	border: 0;
	border-radius: 0;
	background: none;
	color: var(--hvshop-voucher-muted);
	font-size: 12px;
	font-weight: 500;
	line-height: 1.4;
	text-align: center;
	text-transform: none;
	text-decoration: underline;
	text-underline-offset: 2px;
	letter-spacing: 0;
	white-space: nowrap;
	cursor: pointer;
	box-shadow: none;
}

.hvshop-voucher .hvshop-voucher-ticket__rules:hover,
.hvshop-voucher .hvshop-voucher-ticket__rules:focus {
	background: none;
	color: var(--hvshop-voucher-accent);
}

/* Very narrow tickets (sidebar, mobile product column): the call to action drops
   under the text instead of squeezing the headline to two words. Browsers
   without container queries fall back to the wrap already allowed by
   `.hvshop-voucher-ticket__body`, which right-aligns the button on its own row. */
@container (max-width: 340px) {
	.hvshop-voucher-ticket__cta {
		flex-direction: row;
		align-items: center;
		gap: 10px;
		width: 100%;
		margin-left: 0;
	}

	/* The call to action already costs a row here, so the terms give one back. */
	.hvshop-voucher .hvshop-voucher-ticket__terms {
		-webkit-line-clamp: 1;
		line-clamp: 1;
	}

	.hvshop-voucher .hvshop-voucher-ticket__rules {
		margin-left: auto;
		text-align: right;
	}
}

/* ---------------------------------------------------------------------------
 * Dialogs ("Xem tất cả", "Xem thể lệ")
 * ------------------------------------------------------------------------ */

/* --hvshop-voucher-safe-bottom is measured by the script: the height of whatever
   bar the theme or another plugin pins to the bottom edge (a mobile toolbar, a
   sticky add-to-cart). Those bars paint above the dialog on a phone and would
   cover its last ticket, so the dialog simply stops short of them. */
.hvshop-voucher-modal {
	position: fixed;
	inset: 0;
	z-index: 999990;
	display: none;
	margin: 0;
	padding: 16px 12px;
	padding-bottom: calc(16px + var(--hvshop-voucher-safe-bottom, 0px));
	width: auto;
	overflow: hidden;
	-webkit-overflow-scrolling: touch;
}

/* Centred both ways, on every screen size. The dialog never outgrows the
   viewport because its own body scrolls, so nothing ends up above the top
   edge where centring would put it out of reach. */
.hvshop-voucher-modal.is-open {
	display: flex;
	align-items: center;
	justify-content: center;
}

/* The rules dialog is opened from inside the list dialog, so it has to paint
   above it. Toasts stay above both (999999). */
.hvshop-voucher-modal--rules {
	z-index: 999995;
}

.hvshop-voucher-modal__backdrop {
	position: fixed;
	inset: 0;
	background: rgba(16, 24, 40, .55);
}

.hvshop-voucher-modal__dialog {
	position: relative;
	display: flex;
	flex-direction: column;
	width: min(560px, 100%);
	max-height: 100%;
	margin: 0;
	border-radius: 14px;
	background: #fff;
	box-shadow: 0 20px 50px rgba(16, 24, 40, .25);
	overflow: hidden;
}

.hvshop-voucher-modal--rules .hvshop-voucher-modal__dialog {
	width: min(480px, 100%);
}

.hvshop-voucher-modal__head {
	display: flex;
	flex: 0 0 auto;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	padding: 13px 16px;
	border-bottom: 1px solid var(--hvshop-voucher-border);
}

.hvshop-voucher .hvshop-voucher-modal__title {
	margin: 0;
	padding: 0;
	font-size: 15.5px;
	font-weight: 700;
	line-height: 1.35;
	color: var(--hvshop-voucher-text);
	overflow-wrap: anywhere;
}

.hvshop-voucher .hvshop-voucher-modal__close {
	display: inline-flex;
	flex: 0 0 auto;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	min-height: 0;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 8px;
	background: var(--hvshop-voucher-soft);
	color: var(--hvshop-voucher-muted);
	line-height: 1;
	cursor: pointer;
	box-shadow: none;
}

.hvshop-voucher .hvshop-voucher-modal__close:hover,
.hvshop-voucher .hvshop-voucher-modal__close:focus {
	background: var(--hvshop-voucher-soft);
	color: var(--hvshop-voucher-accent);
}

.hvshop-voucher-modal__close svg {
	display: block;
	pointer-events: none;
}

.hvshop-voucher-modal__body {
	flex: 1 1 auto;
	padding: 13px 16px 16px;
	overflow-y: auto;
}

.hvshop-voucher-modal__body .hvshop-voucher__group + .hvshop-voucher__group {
	margin-top: 16px;
}

/* Phones get the same centred dialog, only tighter: a bottom sheet would put
   the close button under the thumb bar on short screens. */
@media (max-width: 600px) {
	.hvshop-voucher-modal {
		padding: 12px 10px;
		padding-bottom: calc(12px + var(--hvshop-voucher-safe-bottom, 0px));
	}

	.hvshop-voucher-modal__head {
		padding: 12px 13px;
	}

	.hvshop-voucher-modal__body {
		padding: 12px 13px 14px;
	}
}

/* Rules content -----------------------------------------------------------*/

.hvshop-voucher-rules__code-row {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-bottom: 12px;
}

.hvshop-voucher .hvshop-voucher-rules__meta {
	margin: 0 0 12px;
	padding: 0;
}

.hvshop-voucher-rules__row {
	display: flex;
	gap: 10px;
	padding: 6px 0;
	border-bottom: 1px dashed var(--hvshop-voucher-border);
}

.hvshop-voucher .hvshop-voucher-rules__row dt {
	flex: 0 0 88px;
	margin: 0;
	padding: 0;
	font-size: 13px;
	font-weight: 500;
	line-height: 1.45;
	color: var(--hvshop-voucher-muted);
}

.hvshop-voucher .hvshop-voucher-rules__row dd {
	flex: 1 1 auto;
	margin: 0;
	padding: 0;
	font-size: 13px;
	font-weight: 600;
	line-height: 1.45;
	color: var(--hvshop-voucher-text);
	overflow-wrap: anywhere;
}

.hvshop-voucher-rules__row dd .woocommerce-Price-amount,
.hvshop-voucher-rules__row dd bdi {
	color: inherit;
	font-weight: inherit;
}

.hvshop-voucher-rules__section + .hvshop-voucher-rules__section {
	margin-top: 13px;
}

.hvshop-voucher .hvshop-voucher-rules__heading {
	margin: 0 0 4px;
	padding: 0;
	font-size: 13px;
	font-weight: 700;
	line-height: 1.4;
	color: var(--hvshop-voucher-text);
}

.hvshop-voucher .hvshop-voucher-rules__terms {
	margin: 0;
	padding-left: 18px;
	font-size: 13px;
	line-height: 1.55;
	color: var(--hvshop-voucher-muted);
}

.hvshop-voucher .hvshop-voucher-rules__terms li {
	margin: 0 0 2px;
	list-style: disc;
}

.hvshop-voucher .hvshop-voucher-rules__content {
	font-size: 13px;
	line-height: 1.6;
	color: var(--hvshop-voucher-muted);
}

.hvshop-voucher .hvshop-voucher-rules__content p {
	margin: 0 0 6px;
	padding: 0;
}

.hvshop-voucher .hvshop-voucher-rules__content p:last-child {
	margin-bottom: 0;
}

.hvshop-voucher .hvshop-voucher-rules__content ul,
.hvshop-voucher .hvshop-voucher-rules__content ol {
	margin: 0 0 6px;
	padding-left: 18px;
}

/* Set while any dialog is open so the page behind it cannot scroll away. */
body.hvshop-voucher-modal-open {
	overflow: hidden;
}

/* ---------------------------------------------------------------------------
 * Toasts
 * ------------------------------------------------------------------------ */

/* Lifted above a bottom bar for the same reason as the dialog. */
.hvshop-voucher-toasts {
	position: fixed;
	left: 50%;
	bottom: calc(28px + var(--hvshop-voucher-safe-bottom, 0px));
	transform: translateX(-50%);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	z-index: 999999;
	pointer-events: none;
	max-width: 92vw;
}

.hvshop-voucher-toast {
	padding: 10px 18px;
	border-radius: 999px;
	background: #1f2430;
	color: #fff;
	font-size: 14px;
	font-weight: 500;
	line-height: 1.4;
	text-align: center;
	box-shadow: 0 8px 24px rgba(16, 24, 40, .18);
	opacity: 0;
	transform: translateY(12px);
	transition: opacity .25s ease, transform .25s ease;
}

.hvshop-voucher-toast.is-visible {
	opacity: 1;
	transform: translateY(0);
}

.hvshop-voucher-toast--error {
	background: #b42318;
}

/* Screen reader helper (some themes do not define it). */
.hvshop-voucher .screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* ---------------------------------------------------------------------------
 * Dòng giảm giá thêm vào ngăn giỏ hàng nhỏ
 * ------------------------------------------------------------------------ */

/* Các dòng này đã mang sẵn class `woocommerce-mini-cart__total total` của chính
   giao diện nên tự thừa hưởng cỡ chữ, khoảng cách, đường kẻ và **cả cách dàn hàng**
   của dòng tổng phụ ngay phía trên — Flatsome chẳng hạn đã đặt sẵn
   `display:flex; gap:15px; justify-content:space-between` cho class đó. Vì thế ở
   đây cố ý KHÔNG khai báo lại display/gap/căn lề: khai lại thì hoặc thua vì thứ tự
   nạp file, hoặc thắng và làm dòng mới lệch khỏi dòng cũ. Phần dưới chỉ là tô điểm
   — ngăn giỏ hàng đi theo khách sang cả những trang không nạp file CSS này, ở đó
   nó vẫn phải trông tử tế.

   Màu chữ và độ đậm của số tiền cũng cố ý để nguyên: giao diện đã tô cho phần tử
   `.woocommerce-Price-amount` nằm bên trong rồi (Flatsome ở đây tô đỏ đậm), đè lên
   chỉ làm dòng mới khác dòng cũ ở những trang có nạp file này. Đo trên trang chủ
   (không nạp file này) và trang sản phẩm (có nạp): cả ba dòng đều đỏ đậm như nhau. */
.hvshop-voucher-mini-cart__amount {
	white-space: nowrap;
}

.hvshop-voucher-mini-cart__note {
	margin: -4px 0 10px;
	font-size: 12px;
	line-height: 1.4;
	opacity: .75;
}

/* ---------------------------------------------------------------------------
 * Preferences
 * ------------------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
	.hvshop-voucher-card,
	.hvshop-voucher .hvshop-voucher-card__action,
	.hvshop-voucher .hvshop-voucher-card__copy,
	.hvshop-voucher .hvshop-voucher__more,
	.hvshop-voucher .hvshop-voucher__more .hvshop-voucher__more-icon,
	.hvshop-voucher .hvshop-voucher__all,
	.hvshop-voucher .hvshop-voucher-modal__close,
	.hvshop-voucher-toast {
		transition: none;
	}

	.hvshop-voucher .hvshop-voucher-card__action .hvshop-voucher-card__spinner {
		animation-duration: 2.4s;
	}
}

/* Fallback for browsers without color-mix() support. */
@supports not (color: color-mix(in srgb, red 50%, blue)) {
	.hvshop-voucher__icon {
		background: rgba(0, 0, 0, .06);
	}

	.hvshop-voucher-card__code {
		background: rgba(0, 0, 0, .03);
		border-color: var(--hvshop-voucher-border);
	}

	.hvshop-voucher-card.is-applied {
		background: #fff;
	}

	.hvshop-voucher--ticket .hvshop-voucher-card:hover {
		border-color: var(--hvshop-voucher-border);
	}
}
