/*
 * Sitewide product card (shop, category archives, related products, home
 * page picks) - matches Figma node 1:236 "product-card" exactly. Not scoped
 * under .davi-home: this renders on pages that don't have that wrapper
 * (shop, category archives), so every value here comes from :root tokens
 * (tokens.css) instead of .davi-home-scoped ones.
 */

.davi-product-card {
	position: relative;
	display: flex;
	flex-direction: column;
	/* height:100% (2026-09-29, client: "kafelki nie są tej samej wysokości
	   w rzędzie") - real cause confirmed live: cards with a catalog price
	   (an extra, conditional line) are genuinely taller by content alone
	   (535.5px vs 510.7px measured on a real category page); CSS Grid
	   already stretches each .col-inner grid cell to match the tallest
	   row-mate (its own default `align-items: stretch`), but this element
	   itself never filled that taller cell - it just sat at its own
	   content height inside it, so the shorter cards' borders/backgrounds
	   stopped short instead of lining up. */
	height: 100%;
	/* This alone was still not enough (client, 2026-09-29 round 2: "kafelki
	   nadal nie są równe") - confirmed live via getBoundingClientRect() on
	   the actual server: Flatsome's own `.products.row` IS a flex row and
	   DOES correctly stretch every `.col` to a uniform height per row
	   (measured 523.125px identically for every column in a row, stable
	   over time - not a lazy-load/timing issue). But `.col-inner` (a plain
	   block child of `.col`, not itself a flex item) never inherits that
	   stretched height - it just sits at its own content height inside the
	   taller `.col` box, so this card's own height:100% had nothing tall
	   enough to resolve against one level up. Scoped to `.products.row`
	   (WooCommerce's own real loop-wrapper class) rather than a bare
	   `.col-inner` - that class is used by many unrelated Flatsome page-
	   builder rows across the site that have nothing to do with product
	   cards and must not be touched here. */
	background: #fff;
	border: 1px solid rgb(var(--card-border));
	border-radius: var(--card-radius);
	overflow: hidden;
	font-family: 'Onest', sans-serif;
	transition: box-shadow var(--motion, 0.3s ease-out), transform var(--motion, 0.3s ease-out);
}

/* Not in Figma - a subtle whole-card hover requested separately
   (2026-09-18). Only on devices that actually have hover, so it doesn't
   leave a stuck/lingering shadow after a tap on touch devices. */
@media (hover: hover) {
	.davi-product-card:hover {
		box-shadow: 0 8px 24px rgba(var(--base), 0.1);
		transform: translateY(-2px);
	}
}

@media (prefers-reduced-motion: reduce) {
	.davi-product-card {
		transition: none;
	}
}

.products.row > .col > .col-inner {
	height: 100%;
}

.davi-product-card__media {
	position: relative;
	width: 100%;
	/* Mobile card (node 2:10, "mobile-showcase") is a FIXED 215px slider
	   card - the real Figma mobile geometry, not an earlier guess - so its
	   media box is just the real fixed 220px height to match. Desktop
	   (node 1:236) is a fluid grid column, so aspect-ratio (280:220, the
	   real desktop ratio) scales it correctly there instead of a height
	   that would look wrong at whatever column width the grid gives it. */
	height: 220px;
	/* White, not the cream --background token - Figma's own value
	   (node 1:237/2:56 "image-container" is bg-white), a real mistake, not
	   a stylistic choice (2026-09-18). */
	background: #fff;
}

@media (min-width: 782px) {
	.davi-product-card__media {
		height: auto;
		aspect-ratio: 280 / 220;
	}
}

.davi-product-card__image {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	/* object-contain, not cover - Figma's own value (the product photo
	   shouldn't be cropped, the whole bike must stay visible). */
	object-fit: contain;
}

.davi-product-card__image--primary {
	opacity: 1;
}

.davi-product-card__image--secondary {
	opacity: 0;
	transition: opacity var(--motion, 0.3s ease-out);
}

/* Hover swap to the product's own first gallery photo - real asset, not a
   fabricated "alt view". Only ever visible if a secondary image exists at
   all (inc/product-card.php only renders it when the product has a gallery
   image), so this never shows a blank/broken state. */
@media (hover: hover) {
	.davi-product-card:hover .davi-product-card__image--primary {
		opacity: 0;
	}

	.davi-product-card:hover .davi-product-card__image--secondary {
		opacity: 1;
	}
}

/* Touch devices have no hover, so the secondary image just never shows
   there (2026-09-21 correction) - an earlier version auto-cycled the two
   images on a timer to give touch "some way" to see it, which was my own
   improvised idea, not a real UX pattern or something asked for; unprompted
   automatic motion is a real anti-pattern (surprising, easy to mistake for
   the page glitching, doesn't communicate interactivity the way hover
   does). Removed entirely rather than defended. */

@media (prefers-reduced-motion: reduce) {
	.davi-product-card__image--primary,
	.davi-product-card__image--secondary {
		transition: none !important;
	}
}







/* Mobile-first: real per-breakpoint values (node 2:55 mobile vs 1:236
   desktop) - padding 16px/title 16px on mobile, 20px/15px from 782px up. */
.davi-product-card__body {
	display: flex;
	flex-direction: column;
	gap: 12px;
	padding: 16px;
}

.davi-product-card__heading {
	display: flex;
	flex-direction: column;
}

.davi-product-card__title {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
	font-weight: 700;
	font-size: 16px;
	color: rgb(var(--base));
	text-decoration: none;
}

@media (min-width: 782px) {
	.davi-product-card__body {
		padding: 20px;
	}

	.davi-product-card__title {
		font-size: 15px;
	}
}

.davi-product-card__spec {
	margin: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-weight: 400;
	font-size: 13px;
	color: rgb(var(--gray-caption));
}

/* Real TrustMate "multihornet" widget now (2026-09-29, inc/product-card.php)
   - empty until its own <script> (wp_footer, sitewide) fills it in, so a
   min-height keeps this row from collapsing to 0 and then jumping once
   stars render, same reason the old placeholder span had an explicit
   height. Removed the placeholder itself along with its now-inaccurate
   "not wired in yet" comment - only a no-op today because the widget
   isn't turned on yet in TrustMate's own plugin settings (a real account
   setting, not a code gap), not because nothing here calls it. */
/* Explicit visual order (2026-09-29, client: "gwiazdki powinny być nad
   ceną") - the multihornet widget's own script inserts its real star
   markup (.tm-multihornet) as a DOM sibling positioned by ITS OWN logic
   (`data-target='.price'`), landing it AFTER .davi-product-card__price
   in the actual DOM regardless of where the empty .davi-product-card__
   rating wrapper sits - confirmed live (real inserted markup appears
   between .price and .davi-product-card__catalog-price, not inside the
   wrapper at all, which stays permanently empty). Since .davi-product-
   card__body is already a flex column, `order` re-positions it visually
   without needing to fight the widget's own DOM insertion point. */
.davi-product-card__heading {
	order: 0;
}

/* Client (2026-09-29): "gwiazdki nadal są w osobnym kontenerze, czyli są
   dwa kontenery i dwa gapy między nimi" - real, confirmed bug: this
   wrapper stays PERMANENTLY EMPTY (the widget never fills it - it
   inserts .tm-multihornet as a separate real sibling elsewhere, per the
   comment above), yet it still had its own box (min-height:20px,
   display:flex) AND still counted as its own flex item, so
   .davi-product-card__body's 12px gap applied on BOTH sides of it -
   a fully empty 20px block plus two extra 12px gaps that did nothing
   but push everything else down.
   `display:contents` was NOT actually enough here (client, follow-up:
   "w kafelu dodajesz div rating ale oceny są dodawane gdzie indziej
   przez co jest podwójny gap") - confirmed live via real
   getBoundingClientRect() measurements: `display:contents` only removes
   THIS element's own box, but its CHILD (the empty tm-widget-hornet-
   wrapper div the plugin reads data-product-id from) then "unwraps" up
   and becomes a flex item OF .body ITSELF, still zero height but still
   sitting between two real 12px gaps (24px total instead of 12px between
   the heading and the stars - measured directly, not assumed). Taking
   `.davi-product-card__rating` fully out of flow with `position:
   absolute` (rather than trying to also neutralise its child) removes
   it from flex layout at the SOURCE - it and its child never become
   flex items at all, so no gap is ever generated around either of
   them - while it stays connected to the DOM exactly as before, which
   is all the plugin's own attribute-based lookup needs. */
.davi-product-card__rating {
	position: absolute;
	width: 0;
	height: 0;
	overflow: hidden;
}

.davi-product-card .tm-multihornet {
	order: 1;
}

/* Client (2026-09-29): "wyrównaj gwiazdki na kafelkach do lewej" - the
   widget's own inner wrapper (tm-multihornet__wrapper, not something this
   theme renders) sets justify-content:center on itself, centering the
   stars+rating group inside the full-width outer div instead of sitting
   at the card's left edge like every other row on the card. */
.davi-product-card .tm-multihornet__wrapper {
	justify-content: flex-start;
}

.davi-product-card__price {
	order: 2;
}

.davi-product-card__catalog-price {
	order: 3;
}

.davi-product-card .thunk-compare {
	order: 4;
}

.davi-product-card__price {
	display: flex;
	gap: 8px;
	align-items: baseline;
	flex-wrap: wrap;
}

.davi-product-card__price ins {
	text-decoration: none;
	font-weight: 900;
	font-size: 18px;
	color: rgb(var(--base));
}

.davi-product-card__price del {
	/* Explicit line-through (2026-09-29, client: "nie ma cen
	   promocyjnych") - real regular price was always in the DOM
	   (confirmed live via a real <del> element), just invisible AS a
	   crossed-out price: something sitewide resets <del>'s own browser-
	   default text-decoration to none (confirmed live computed style),
	   so without this it read as a second, unexplained plain number
	   instead of a struck-through "was" price. */
	text-decoration: line-through;
	font-family: 'Instrument Sans', sans-serif;
	font-weight: 400;
	font-size: 13px;
	color: rgb(var(--gray-caption));
}

/* A simple (not on sale) product has no <ins>/<del> - get_price_html()
   returns one plain amount instead. Match the "current price" style. */
.davi-product-card__price:not(:has(ins)) {
	font-weight: 900;
	font-size: 18px;
	color: rgb(var(--base));
}

/* Real, optional MSRP-style reference price (2026-09-29, client:
   "w szarym kolorze") - same gray/size treatment .davi-product-card__spec
   already uses on this card, not a new muted-text style invented for one
   more line.
   The earlier -8px negative margin-top (2026-09-29, client: "bliżej
   ceny regularnej") pulled this line up so close to the price row that
   it read as ambiguous once the stars widget was also added above the
   price - the del price (regular/pre-sale, same gray tone, similar
   size) sits right there too, and at a glance the two gray lines blur
   into "one price block with an extra label", not two clearly separate
   rows (client, 2026-09-29: "wciąż widnieje przy cenie promocyjnej
   cena katalogowa" - confirmed via real position/innerText checks:
   there is no duplicate markup, just a legibility problem from the
   tight spacing + matching styles). Back to the shared 12px gap - real
   separation instead of a tighter one that reads as attached. */
.davi-product-card__catalog-price {
	margin: 0;
	font-size: 13px;
	color: rgb(var(--gray-caption));
}

/* th-product-compare-pro's real "Porównaj" checkbox (2026-09-29, client:
   brought back on the card too) - checkbox/checkmark styling
   (::before/::after) is the plugin's own real, working CSS
   (fstyle.css, .checkbox_type), left alone; only font/color/spacing
   pulled in line with the rest of the card instead of the plugin's own
   default Arial-ish 14px black. */
.davi-product-card .th-product-compare-btn.checkbox_type {
	padding: 0;
	font-family: 'Onest', sans-serif;
}

/* Client (2026-09-29): "porównaj ma za dużo marginesów... zajmuje dużo
   miejsca" - real cause: the plugin's OWN base class (`.th-product-
   compare-btn`, fstyle.css, separate from `.checkbox_type` above) sets
   `margin: 10px 0`, never overridden before now - stacking on top of
   .davi-product-card__body's own 12px flex gap gave this row ~34px of
   real empty space around it instead of the intended 12px like every
   other row on the card. */
.davi-product-card .th-product-compare-btn {
	margin: 0;
}

.davi-product-card .th-product-compare-btn.checkbox_type > span {
	font-size: 13px;
	color: rgb(var(--gray-caption));
}

/* Real, live bug (client, 2026-09-29, screenshot: checkmark sitting
   noticeably left of center in the green box) - the plugin's own CSS
   (fstyle.css) positions the checkmark with a fixed `left: 5px`,
   assuming its own glyph's rendered width at its own default font;
   once font-family is overridden to Onest (above, and the matching PDP
   rule in davi-pdp.css), the same character renders a different
   width/position in that font, throwing the fixed offset off. Not
   scoped to .davi-product-card specifically - this is the plugin's
   shared checkbox markup, same fix needed everywhere it renders (PDP's
   own .davi-pdp__actions included), so it's unscoped here. True
   centering via flex on a box matching ::before's own exact 18x18px
   size, instead of a font-dependent fixed left offset - correct
   regardless of which font renders the checkmark. */
.th-compare-checkbox:checked + span::after {
	display: flex;
	align-items: center;
	justify-content: center;
	left: 0;
	width: 18px;
	height: 18px;
}
