/**
 * ProductCard — the site's one reusable card, shared by every product grid
 * (homepage, shop, wishlist). Image-dominant, no card shell (no border/
 * shadow/rounded box), a portrait crop, and an always-visible full-width
 * Add to Cart button with real loading/success/error micro-states — never
 * a hover-only action. See inc/template-tags.php:qg_render_product_card()
 * for the markup and components/product-grid/component.js for the button
 * behaviour (WooCommerce Store API, no page reload).
 */

.qg-product-grid__list {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--qg-space-5) var(--qg-space-3);
	list-style: none;
	margin: 0;
	padding: 0;
}

/* Mobile only: a tighter gap alongside the shop page's own tighter side
   padding (see #primary.content-area in components/shop/component.css) —
   together they let each card claim more of a small screen's width. */
@media (max-width: 639px) {
	.qg-product-grid__list {
		gap: var(--qg-space-4) 0.6rem;
	}
}

@media (min-width: 640px) {
	.qg-product-grid__list {
		grid-template-columns: repeat(3, 1fr);
	}
}

/* One column fewer than the shop page's own ul.products grid (see
   components/shop/component.css) at the wide breakpoints specifically —
   the homepage sections (New Arrivals, Best Sellers, …) are a curated
   handful of products, not the full catalog, so each card gets to be a
   little bigger instead of matching the shop's denser grid. */
@media (min-width: 1024px) {
	.qg-product-grid__list {
		grid-template-columns: repeat(3, 1fr);
	}
}

@media (min-width: 1440px) {
	.qg-product-grid__list {
		grid-template-columns: repeat(4, 1fr);
	}
}

/* Homepage cards only: show the whole product photo (object-fit: contain)
   instead of the shop grid's full-bleed cover crop — on a mix of product
   photo aspect ratios, cover was cropping/zooming into some images rather
   than showing the product whole. */
.qg-product-grid__list .qg-product-card__img {
	object-fit: contain;
}

.qg-product-card {
	position: relative;
	display: flex;
	flex-direction: column;
	container-type: inline-size;
}

.qg-product-card__media {
	position: relative;
	aspect-ratio: 4 / 5;
	border-radius: var(--qg-radius-sharp);
	background: var(--qg-color-bg);
	border: 1px solid var(--qg-color-line);
	overflow: hidden;
}

.qg-product-card__media-link {
	position: absolute;
	inset: 0;
	z-index: 1;
	display: block;
}

.qg-product-card__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.5s var(--qg-ease), opacity 0.4s var(--qg-ease);
}

.qg-product-card__img--secondary {
	opacity: 0;
}

@media (hover: hover) and (pointer: fine) {
	.qg-product-card:hover .qg-product-card__img--primary {
		transform: scale(1.02);
	}

	.qg-product-card:hover .qg-product-card__img--secondary {
		opacity: 1;
	}
}

/* A real rubber-stamp look — "Sale"/"New" read as ink pressed onto the
   photo, not a solid digital sticker: a translucent disc (the product
   image shows through) ringed by a double border, both badges sharing the
   same site accent ink color so "Sale" and "New" read as one consistent
   stamp family rather than two different brand colors. Low opacity keeps
   it from blocking the product shot underneath. A faint rotation is the
   small imperfection that reads as "stamped on" rather than a perfect
   digital pill. A slow, quiet pulse on the outer halo keeps it feeling
   alive without being a distraction (respects prefers-reduced-motion). */

.qg-product-card__badge {
	position: absolute;
	top: var(--qg-space-2);
	left: var(--qg-space-2);
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 38px;
	height: 38px;
	border-radius: 50%;
	background: rgba(255, 74, 31, 0.14);
	opacity: 0.8;
	transform: rotate(-9deg);
	border: 1.5px solid rgba(255, 74, 31, 0.75);
	box-shadow: inset 0 0 0 3px rgba(255, 74, 31, 0.12);
	color: var(--qg-color-accent);
	font-family: var(--qg-font-body);
	font-size: 0.56rem;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.03em;
	line-height: 1;
}

.qg-product-card__badge::before {
	content: '';
	position: absolute;
	inset: -5px;
	border-radius: 50%;
	border: 1px solid rgba(255, 74, 31, 0.4);
	animation: qg-badge-stamp-pulse 2.4s var(--qg-ease) infinite;
}

.qg-product-card__badge--new {
	transform: rotate(8deg);
}

@keyframes qg-badge-stamp-pulse {
	0% {
		transform: scale(0.92);
		opacity: 0.8;
	}
	70%,
	100% {
		transform: scale(1.25);
		opacity: 0;
	}
}

@media (prefers-reduced-motion: reduce) {
	.qg-product-card__badge::before {
		animation: none;
		opacity: 0.6;
	}
}

/* Wishlist — a flat solid-color circle button (same floating-icon language
   as the add-to-cart button on the opposite corner), not a bare stroke icon
   with a drop-shadow filter — that filter was the "3D" look: a soft blur
   under the glyph itself, floating disconnected from any real surface.
   Flat here means a crisp single-tone circle + a restrained ambient shadow
   on the button as a whole, never on the icon. Always visible (never
   hover-only), per the brief. */

.qg-product-card__wishlist {
	position: absolute;
	top: var(--qg-space-2);
	right: var(--qg-space-2);
	z-index: 2;
}

.qg-product-card__wishlist .yith-wcwl-add-to-wishlist {
	margin: 0;
}

.qg-product-card__wishlist a {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	border-radius: 50%;
	/* No background/border/shadow at rest — just the heart glyph, on
	   whatever photo sits behind it. Black (not white): most product
	   photos in this catalog sit on a white/light background (see
	   .qg-product-card__media), where a white heart all but disappears;
	   black reads clearly there and still holds up against darker photos
	   with the drop-shadow on the icon itself (see the ::after rule
	   below). A background only ever appears once the product is
	   actually liked (.wishlist-in-list-icon etc. below) or on hover as
	   a preview of that same state. */
	background: none;
	border: none;
	color: var(--qg-color-ink);
	text-decoration: none;
	font-size: 0;
	transition: background-color 0.2s var(--qg-ease), border-color 0.2s var(--qg-ease), color 0.2s var(--qg-ease), transform 0.2s var(--qg-ease), box-shadow 0.2s var(--qg-ease);
}

@media (hover: hover) and (pointer: fine) {
	.qg-product-card__wishlist a:hover {
		background: var(--qg-gradient-cta);
		border-color: transparent;
		color: #fff;
		transform: scale(1.08);
		box-shadow: 0 6px 16px -4px rgba(255, 48, 48, 0.55);
	}

	.qg-product-card__wishlist a:hover::after {
		filter: none;
	}
}

.qg-product-card__wishlist a:active {
	transform: scale(0.9);
}

/* YITH renders its own heart glyph plus a text label ("Add to wishlist" /
   "Remove from list") as TWO siblings inside the button
   (.yith-wcwl-icon-svg and .yith-wcwl-add-to-wishlist-button__label). The
   label's font-size:0 from the shared a{font-size:0} rule above made its
   TEXT invisible, but the <span> itself was still a normal, visible-sized
   flex item sitting next to our own icon, pulling the pair off-center as a
   group — that was the "leaning/off-center" bug, not the icon glyph
   itself. The icon is purely decorative once our own ::after heart is
   painted on top, so it's fully hidden; the label is the button's only
   accessible name (YITH doesn't set aria-label), so it's visually hidden
   instead — taken out of flex layout via absolute positioning, but still
   readable by screen readers. This theme's own heart (a CSS mask on
   ::after, in `currentColor`, centered by the same flex rule as everything
   else in this button) is the only VISIBLE flex child left — dead-center
   every time, independent of whatever YITH's own markup does under the
   hood. Same masking technique as the share buttons in
   components/shop/component.css. */
.qg-product-card__wishlist a .yith-wcwl-icon-svg,
.qg-product-card__wishlist a i {
	display: none;
}

.qg-product-card__wishlist a .yith-wcwl-add-to-wishlist-button__label {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.qg-product-card__wishlist a::after {
	content: '';
	display: block;
	width: 15px;
	height: 15px;
	background-color: currentColor;
	-webkit-mask: url(../../assets/icons/heart.svg) no-repeat center / contain;
	mask: url(../../assets/icons/heart.svg) no-repeat center / contain;
	/* A light shadow, not dark — the glyph itself is black now, so a
	   dark shadow would just blend in on a dark photo; this is what
	   keeps it visible there instead. */
	filter: drop-shadow(0 1px 3px rgba(255, 255, 255, 0.55));
	transition: transform 0.3s var(--qg-ease), filter 0.2s var(--qg-ease);
}

.qg-product-card__wishlist a.wishlist-in-list-icon,
.qg-product-card__wishlist a.exists,
.qg-product-card__wishlist a.yith-wcwl-add-to-wishlist-button--added {
	background: var(--qg-gradient-cta);
	border-color: transparent;
	color: #fff;
	animation: qg-wishlist-pop 0.4s var(--qg-ease);
}

.qg-product-card__wishlist a.wishlist-in-list-icon::after,
.qg-product-card__wishlist a.exists::after,
.qg-product-card__wishlist a.yith-wcwl-add-to-wishlist-button--added::after {
	filter: none;
}

.qg-product-card__wishlist a.wishlist-in-list-icon::after,
.qg-product-card__wishlist a.exists::after,
.qg-product-card__wishlist a.yith-wcwl-add-to-wishlist-button--added::after {
	-webkit-mask-image: url(../../assets/icons/heart-filled.svg);
	mask-image: url(../../assets/icons/heart-filled.svg);
}

/* Premium click feedback: a soft accent ring bursts outward from the heart
   the instant it's liked, on top of the existing icon pop — the kind of
   "felt" micro-interaction a bare scale-up alone doesn't give. Fires once,
   same moment the --added class lands. */
.qg-product-card__wishlist a.wishlist-in-list-icon::before,
.qg-product-card__wishlist a.exists::before,
.qg-product-card__wishlist a.yith-wcwl-add-to-wishlist-button--added::before {
	content: '';
	position: absolute;
	inset: -2px;
	border-radius: 50%;
	background: var(--qg-gradient-cta);
	z-index: -1;
	animation: qg-wishlist-burst 0.55s var(--qg-ease);
}

@keyframes qg-wishlist-pop {
	0% {
		transform: scale(0.7);
	}
	55% {
		transform: scale(1.25);
	}
	100% {
		transform: scale(1);
	}
}

@keyframes qg-wishlist-burst {
	0% {
		transform: scale(0.3);
		opacity: 0.55;
	}
	100% {
		transform: scale(2.4);
		opacity: 0;
	}
}

@media (prefers-reduced-motion: reduce) {
	.qg-product-card__wishlist a.wishlist-in-list-icon::before,
	.qg-product-card__wishlist a.exists::before,
	.qg-product-card__wishlist a.yith-wcwl-add-to-wishlist-button--added::before {
		animation: none;
		display: none;
	}
}

/* "Added to wishlist" toast — the real YITH feedback message (its own
   React-rendered element; only the stable, documented classes below are
   restyled, never the hashed lapilliUI-* ones). Ships as a plain white
   dead-center popup by default; moved to a top toast position with the
   site's own font/color language and a check icon instead. */

.yith-wcwl-feedback-messages-container {
	top: calc(var(--qg-space-5) + env(safe-area-inset-top, 0px)) !important;
	bottom: auto !important;
	left: 50% !important;
	transform: translateX(-50%) !important;
}

.yith-wcwl-feedback-messages-container .yith-wcwl-add-to-wishlist__feedback {
	display: flex !important;
	align-items: flex-start;
	gap: 0.65rem;
	width: auto !important;
	max-width: min(340px, 88vw) !important;
	padding: 0.9rem 1.2rem !important;
	background: var(--qg-color-ink) !important;
	color: var(--qg-color-surface) !important;
	border-radius: var(--qg-radius-lg) !important;
	border: none !important;
	font-family: var(--qg-font-body);
	font-size: 0.85rem !important;
	font-weight: 600;
	line-height: 1.5;
	text-align: left !important;
	box-shadow: var(--qg-shadow-md);
	animation: qg-wishlist-toast-in 0.4s var(--qg-ease) !important;
}

.yith-wcwl-feedback-messages-container .yith-wcwl-add-to-wishlist__feedback.yith-wcwl-fade-out {
	animation: qg-wishlist-toast-out 0.35s var(--qg-ease) forwards !important;
}

.yith-wcwl-feedback-messages-container .yith-wcwl-add-to-wishlist__feedback::before {
	content: '';
	flex-shrink: 0;
	margin-top: 0.15rem;
	width: 19px;
	height: 19px;
	background-color: var(--qg-color-accent);
	-webkit-mask: url('../../assets/icons/check-circle.svg') center / contain no-repeat;
	mask: url('../../assets/icons/check-circle.svg') center / contain no-repeat;
}

.yith-wcwl-feedback-messages-container .yith-wcwl-add-to-wishlist__feedback--error {
	background: var(--qg-color-danger, #b3261e) !important;
}

.yith-wcwl-feedback-messages-container .yith-wcwl-add-to-wishlist__feedback--error::before {
	background-color: var(--qg-color-surface);
	-webkit-mask-image: url('../../assets/icons/heart.svg');
	mask-image: url('../../assets/icons/heart.svg');
}

@keyframes qg-wishlist-toast-in {
	0% {
		transform: translateY(-14px);
		opacity: 0;
	}
	100% {
		transform: translateY(0);
		opacity: 1;
	}
}

@keyframes qg-wishlist-toast-out {
	0% {
		transform: translateY(0);
		opacity: 1;
	}
	100% {
		transform: translateY(-10px);
		opacity: 0;
	}
}

@media (prefers-reduced-motion: reduce) {
	.yith-wcwl-feedback-messages-container .yith-wcwl-add-to-wishlist__feedback,
	.yith-wcwl-feedback-messages-container .yith-wcwl-add-to-wishlist__feedback.yith-wcwl-fade-out {
		animation: none !important;
	}
}

.qg-product-card__body {
	display: flex;
	flex-direction: column;
	gap: 0.3rem;
	padding-top: 0.85rem;
}

.qg-product-card__title {
	font-family: var(--qg-font-body);
	font-size: 0.88rem;
	font-weight: 450;
	line-height: 1.4;
	/* Reserves space for two full lines regardless of how many the actual
	   title needs — a short title ("Bowl Rack") and a long one ("toilet
	   rack/washing machin rack") then occupy identical height, so every
	   card in a row bottoms out at the same line instead of the shorter
	   ones leaving a gap under the price. */
	min-height: calc(1.4em * 2);
	text-decoration: none;
	color: var(--qg-color-ink);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	transition: color 0.2s var(--qg-ease);
}

.qg-product-card__title:hover {
	color: var(--qg-color-ink-soft);
}

.qg-product-card__price {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 0.4rem;
	margin-top: 0.1rem;
	font-family: var(--qg-font-body);
	font-size: 0.96rem;
	font-weight: 700;
	color: var(--qg-color-ink);
	letter-spacing: 0.005em;
}

/* Price-on-image — a frosted pill sitting over the bottom-left corner of
   the photo (the add-to-cart "+" already owns the bottom-right), so the
   price reads immediately against the product itself instead of waiting
   below the title. White/blurred background keeps it legible over any
   photo; the sale-price accent still pops inside it. */

.qg-product-card__price--on-image {
	position: absolute;
	left: var(--qg-space-2);
	bottom: var(--qg-space-2);
	/* Leaves room for the add-to-cart circle at the opposite corner (see
	   .qg-product-card__cart-btn, 38px + its own right/bottom spacing) —
	   without this the pill could grow wide enough on a narrow/2-up mobile
	   card to run under the button, which is what was actually making the
	   "+" look like it had disappeared on some products. */
	max-width: calc(100% - 52px);
	z-index: 2;
	margin-top: 0;
	padding: 0.4rem 0.7rem;
	background: rgba(255, 255, 255, 0.92);
	backdrop-filter: blur(6px) saturate(140%);
	-webkit-backdrop-filter: blur(6px) saturate(140%);
	border-radius: 999px;
	box-shadow: 0 2px 10px -2px rgba(22, 19, 15, 0.25);
	font-size: 0.86rem;
}

/* The struck-through original price only below the sale price added real
   width (see the fix above) for little benefit — the "Sale" ribbon badge
   (top-left of the same image) already signals the discount, so the
   on-image pill shows just the current price, same as a regular card. */
.qg-product-card__price--on-image del {
	display: none;
}

.qg-product-card__price del {
	order: 2;
	font-weight: 500;
	color: var(--qg-color-muted);
	margin-right: 0;
	font-size: 0.76rem;
	text-decoration: line-through;
}

.qg-product-card__price ins {
	order: 1;
	text-decoration: none;
	color: var(--qg-color-accent-dark);
	font-weight: 700;
}

.qg-product-card__swatches {
	display: flex;
	align-items: center;
	gap: 0.35rem;
	margin-top: 0.15rem;
}

.qg-product-card__swatch {
	width: 10px;
	height: 10px;
	border-radius: 50%;
	border: 1px solid rgba(22, 19, 15, 0.12);
}

/* Add to Cart — a floating circular button on the product image itself
   (bottom-right corner, mirroring the wishlist heart's top-right position),
   rather than a full-width bar competing with the card body for space.
   State transitions (loading → success/error → idle) are driven by
   component.js purely through CSS classes; the label stays in the markup
   for assistive tech (visually-hidden) since the button is icon-only. */

.qg-add-btn {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 0.2s var(--qg-ease), color 0.2s var(--qg-ease), border-color 0.2s var(--qg-ease), transform 0.2s var(--qg-ease), box-shadow 0.2s var(--qg-ease);
}

.qg-product-card__cart-btn {
	position: absolute;
	right: var(--qg-space-2);
	bottom: var(--qg-space-2);
	z-index: 2;
	width: 38px;
	height: 38px;
	border-radius: 50%;
	border: none;
	background: var(--qg-gradient-cta);
	color: #fff;
	box-shadow: 0 3px 10px -2px rgba(255, 48, 48, 0.4);
	/* Redeclares .qg-add-btn's transition list (shorthand — a second
	   `transition` here would otherwise replace it, not merge with it) with
	   opacity added, for the hide-on-scroll/reveal-on-hover fade below. */
	transition: background-color 0.2s var(--qg-ease), color 0.2s var(--qg-ease), border-color 0.2s var(--qg-ease), transform 0.2s var(--qg-ease), box-shadow 0.2s var(--qg-ease), opacity 0.2s var(--qg-ease);
}

@media (hover: hover) and (pointer: fine) {
	.qg-product-card__cart-btn:hover {
		background: var(--qg-gradient-cta-hover);
		transform: scale(1.08);
		box-shadow: 0 6px 16px -4px rgba(255, 48, 48, 0.55);
	}
}

.qg-product-card__cart-btn:active {
	transform: scale(0.92);
}

/* Hide-on-scroll / reveal-on-hover (see the `qg-is-scrolling` toggle in
   component.js). Hover-capable devices: the button stays hidden until the
   shopper actually hovers/focuses that card, and is force-hidden while the
   page is mid-scroll even if the pointer happens to be resting over a card
   when a wheel/trackpad scroll fires. Touch devices have no hover to reveal
   it with, so there it just stays visible normally and only hides for the
   brief window the page is actively scrolling. Either way, a button that's
   mid add-to-cart (loading/success) always stays visible, so tapping it and
   then scrolling never hides its own feedback. */

@media (hover: hover) and (pointer: fine) {
	.qg-product-card__cart-btn {
		opacity: 0;
		transform: scale(0.85);
	}

	.qg-product-card:hover .qg-product-card__cart-btn,
	.qg-product-card:focus-within .qg-product-card__cart-btn {
		opacity: 1;
		transform: scale(1);
	}

	.qg-product-card__cart-btn:hover {
		transform: scale(1.08);
	}

	body.qg-is-scrolling .qg-product-card__cart-btn {
		opacity: 0;
		transform: scale(0.85);
	}
}

@media (hover: none) {
	body.qg-is-scrolling .qg-product-card__cart-btn {
		opacity: 0;
		transform: scale(0.85);
	}
}

.qg-product-card__cart-btn.is-loading,
.qg-product-card__cart-btn.is-success {
	opacity: 1 !important;
	transform: none !important;
}

@media (prefers-reduced-motion: reduce) {
	.qg-product-card__cart-btn {
		transition: none;
	}
}

.qg-add-btn__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	position: absolute;
	inset: 0;
	opacity: 1;
	transform: scale(1);
	transition: opacity 0.2s var(--qg-ease), transform 0.2s var(--qg-ease);
}

.qg-add-btn__icon .qg-icon {
	width: 17px;
	height: 17px;
	stroke-width: 1.8;
}

.qg-add-btn__icon--success {
	opacity: 0;
	transform: scale(0.5);
}

.qg-add-btn__label {
	white-space: nowrap;
}

.qg-add-btn__spinner {
	position: absolute;
	width: 15px;
	height: 15px;
	border-radius: 50%;
	border: 1.5px solid currentColor;
	border-top-color: transparent;
	opacity: 0;
	transition: opacity 0.15s var(--qg-ease);
}

.qg-add-btn.is-loading .qg-add-btn__icon--idle {
	opacity: 0;
	transform: scale(0.5);
}

.qg-add-btn.is-loading .qg-add-btn__spinner {
	opacity: 1;
	animation: qg-spin 0.7s linear infinite;
}

.qg-add-btn.is-success .qg-product-card__cart-btn,
.qg-product-card__cart-btn.is-success {
	background: var(--qg-color-success);
}

.qg-add-btn.is-success .qg-add-btn__icon--idle {
	opacity: 0;
	transform: scale(0.5);
}

.qg-add-btn.is-success .qg-add-btn__icon--success {
	opacity: 1;
	transform: scale(1);
}

.qg-add-btn.is-error {
	background: var(--qg-color-accent);
}

.qg-add-btn--disabled {
	background: rgba(246, 242, 236, 0.85);
	color: var(--qg-color-muted);
	box-shadow: 0 2px 6px -2px rgba(22, 19, 15, 0.25);
	cursor: not-allowed;
}

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

/* ------------------------------------------------------------------------
 * Quick-add panel — variable/grouped products. A compact centered modal
 * (not a full page, not a dead click), built by component.js from the
 * product's real Store API attributes/variations.
 * ---------------------------------------------------------------------- */

.qg-quickadd {
	position: fixed;
	inset: 0;
	z-index: 320;
}

.qg-quickadd[hidden] {
	display: none;
}

.qg-quickadd__backdrop {
	position: absolute;
	inset: 0;
	background: rgba(16, 14, 10, 0.5);
	opacity: 0;
	transition: opacity 0.3s var(--qg-ease);
}

.qg-quickadd[data-open] .qg-quickadd__backdrop {
	opacity: 1;
}

.qg-quickadd__panel {
	position: absolute;
	top: 50%;
	left: 50%;
	width: min(420px, calc(100% - 32px));
	max-height: calc(100% - 64px);
	overflow-y: auto;
	background: var(--qg-color-surface);
	transform: translate(-50%, -46%);
	opacity: 0;
	transition: opacity 0.3s var(--qg-ease), transform 0.3s var(--qg-ease);
}

.qg-quickadd[data-open] .qg-quickadd__panel {
	opacity: 1;
	transform: translate(-50%, -50%);
}

.qg-quickadd__close {
	position: absolute;
	top: var(--qg-space-3);
	right: var(--qg-space-3);
	z-index: 1;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border: 0;
	background: var(--qg-color-surface);
	color: var(--qg-color-ink);
	cursor: pointer;
}

.qg-quickadd__close .qg-icon {
	width: 16px;
	height: 16px;
}

.qg-quickadd__media {
	aspect-ratio: 4 / 3;
	background: var(--qg-color-paper);
	overflow: hidden;
}

.qg-quickadd__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.qg-quickadd__body {
	padding: var(--qg-space-4);
}

.qg-quickadd__name {
	margin: 0 0 0.2rem;
	font-family: var(--qg-font-body);
	font-size: 0.98rem;
	font-weight: 500;
	color: var(--qg-color-ink);
}

.qg-quickadd__price {
	margin: 0 0 var(--qg-space-3);
	font-family: var(--qg-font-body);
	font-size: 0.9rem;
	font-weight: 600;
	color: var(--qg-color-ink);
}

.qg-quickadd__group {
	margin-bottom: var(--qg-space-3);
}

.qg-quickadd__group-title {
	margin: 0 0 0.5rem;
	font-family: var(--qg-font-body);
	font-size: 0.7rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: var(--qg-tracking-label);
	color: var(--qg-color-muted);
}

.qg-quickadd__pills {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
}

.qg-quickadd__pill {
	padding: 0.5rem 0.9rem;
	border: 1px solid var(--qg-color-line);
	border-radius: var(--qg-radius-sharp);
	background: var(--qg-color-surface);
	color: var(--qg-color-ink);
	font-family: var(--qg-font-body);
	font-size: 0.82rem;
	cursor: pointer;
	transition: border-color 0.2s var(--qg-ease), background-color 0.2s var(--qg-ease), color 0.2s var(--qg-ease);
}

.qg-quickadd__pill:hover {
	border-color: var(--qg-color-ink);
}

.qg-quickadd__pill.is-selected {
	background: var(--qg-color-ink);
	border-color: var(--qg-color-ink);
	color: var(--qg-color-surface);
}

.qg-quickadd__hint {
	margin: 0 0 var(--qg-space-3);
	font-size: 0.8rem;
	color: var(--qg-color-accent);
}

/* The quick-add modal's submit reuses .qg-add-btn's state machine (loading/
   success/error classes, the label + spinner elements) but is a normal
   full-width text button, not the card's floating icon circle — its own
   shape/typography lives here rather than on the shared base rule. */
.qg-quickadd__submit {
	position: relative;
	width: 100%;
	height: 46px;
	margin-top: 0;
	padding: 0 var(--qg-space-3);
	border: 1px solid var(--qg-color-ink);
	border-radius: var(--qg-radius-sharp);
	background: var(--qg-color-surface);
	color: var(--qg-color-ink);
	overflow: hidden;
}

.qg-quickadd__submit:hover {
	background: var(--qg-color-ink);
	color: var(--qg-color-surface);
}

.qg-quickadd__submit .qg-add-btn__label {
	font-family: var(--qg-font-body);
	font-size: 0.78rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	transition: opacity 0.15s var(--qg-ease);
}

.qg-quickadd__submit.is-loading .qg-add-btn__label {
	opacity: 0;
}

.qg-quickadd__submit.is-success {
	background: var(--qg-color-ink);
	color: var(--qg-color-surface);
	border-color: var(--qg-color-ink);
}

.qg-quickadd__submit:disabled {
	opacity: 0.4;
	cursor: default;
}

.qg-quickadd__submit:disabled:hover {
	background: var(--qg-color-surface);
	color: var(--qg-color-ink);
}

@media (prefers-reduced-motion: reduce) {
	.qg-product-card__img,
	.qg-product-card__wishlist a,
	.qg-product-card__title,
	.qg-add-btn,
	.qg-add-btn__spinner,
	.qg-quickadd__backdrop,
	.qg-quickadd__panel {
		transition: none;
		animation: none;
	}
}
