/* ==========================================================================
   Ascension product cards  (Session B)

   Owns woocommerce/content-product.php. Printed at wp_head 113, i.e. after
   asc-ui.css (110), asc-header.css (111) and therefore after the Customizer
   blob (101), so equal specificity ties resolve here. `.asc-ui` on <body> is
   the second lever: every rule is (0,2,0) or better.

   Geometry is Evo Aminoz's .pcard copied verbatim from
   ~/Desktop/WooCommerce Stores/evo-aminoz/theme/evo-aminoz/assets/css/evo.css
   lines 299-323 and 1385-1394. Only the surface and the buttons change: the
   card has NO surface (transparent, hairline border, everything light-on-dark
   against the site's true black) and the primary button is Ascension gold.

   MEASURED, not guessed:
   - Type inherits Instrument Sans from <body>, which is what the live shop
     product titles compute to (Instrument Sans / 15px / 600). No font-family
     is declared here, so nothing can drift.
   - Contrast on #000: #ffffff 21:1, --asc-muted #9a9a9a 6.4:1, gold with
     black ink 6.12:1 at its darkest stop. All clear WCAG AA.
   - The vial's alpha box in a 400x533 render is x 121-278, y 101-442. A 4/5
     media box crops ~16px off the top and bottom, which is empty margin, so
     object-fit: cover never clips the product.
   - Card content box is 263.3px on the 3-column shop grid at 1440
     (li.product is 293.3px wide with 15px of side padding).

   DO NOT add a substring class selector to this file. [class*="quick-view"]
   matched the grid <ul> (mobile-quick-view-button--hidden) and blanked the
   whole page once already.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. The card
   -------------------------------------------------------------------------- */
.asc-ui li.asc-card-li {
	list-style: none;
}

/* No card surface. The product sits directly on the page's true black, and the
   card is defined by a hairline border alone: depth from a 1px line, not from
   a filled panel or a shadow, which on #000 would be invisible anyway.
   Everything inside therefore runs light-on-dark. Contrast measured on #000:
     #ffffff (name, price, ADD TO CART) ..... 21:1
     #9a9a9a (FROM label, --asc-muted) ...... 6.4:1
     gold gradient with black ink ........... 6.12:1 at its darkest stop
   All clear WCAG AA. */
.asc-ui .pcard {
	display: flex;
	flex-direction: column;
	min-width: 0;
	height: 100%;
	background: transparent;
	border: 1px solid var(--asc-line);
	border-radius: 20px;
	overflow: hidden;
	transition: border-color .16s ease, transform .16s ease;
}

.asc-ui .pcard:hover {
	border-color: var(--asc-line-strong);
	transform: translateY(-2px);
}

/* --------------------------------------------------------------------------
   2. Media
   -------------------------------------------------------------------------- */
/* Transparent, per Hamza. The product renders are cut-out PNGs (colour type 6),
   so with no fill behind them the vial sits straight on the page's black.
   The 11.0% of opaque pixels that measure above 235 luminance now read at full
   strength instead of being flattened against a light panel. */
.asc-ui .pcard .pcard-media {
	display: block;
	position: relative;
	aspect-ratio: 4 / 5;
	overflow: hidden;
	background: transparent;
}

.asc-ui .pcard .pcard-media img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	transition: transform .28s ease;
}

.asc-ui .pcard:hover .pcard-media img {
	transform: scale(1.05);
}

/* Sold-out flag: hairline border + faint same-hue fill, no glow, no shadow.
   Light-on-dark now that the card has no surface behind it. */
.asc-ui .pcard .pcard-flag {
	position: absolute;
	top: 12px;
	left: 12px;
	display: inline-flex;
	align-items: center;
	height: 22px;
	padding: 0 9px;
	border: 1px solid var(--asc-line-strong);
	border-radius: 4px;
	background: rgba(255, 255, 255, .07);
	color: #ffffff;
	font-size: 10px;
	font-weight: 600;
	line-height: 1;
	letter-spacing: .06em;
	text-transform: uppercase;
}

.asc-ui .pcard--soldout .pcard-media img {
	opacity: .55;
}

/* --------------------------------------------------------------------------
   3. Body
   -------------------------------------------------------------------------- */
.asc-ui .pcard .pcard-body {
	display: flex;
	flex-direction: column;
	flex: 1;
	min-width: 0;
	padding: 15px 16px 17px;
	background: transparent;
}

.asc-ui .pcard .pname {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	min-width: 0;
	min-height: 2.4em;
	color: #ffffff;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -.01em;
	text-decoration: none;
}

/* glozin ships a blanket `a:active,a:hover{color:var(--gz-link-color-hover)}`
   in base.min.css. Beaten here at (0,3,0) rather than per-property later. */
.asc-ui .pcard a:hover,
.asc-ui .pcard a:active,
.asc-ui .pcard a:focus {
	text-decoration: none;
}

.asc-ui .pcard .pname:hover,
.asc-ui .pcard .pname:active,
.asc-ui .pcard .pname:focus {
	color: #ffffff;
}

.asc-ui .pcard .pprice {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 6px;
	margin-top: 7px;
}

.asc-ui .pcard .pfrom {
	color: var(--asc-muted);
	font-size: 11px;
	line-height: 1.1;
	letter-spacing: .04em;
	text-transform: uppercase;
}

.asc-ui .pcard .pamt,
.asc-ui .pcard .pamt .amount,
.asc-ui .pcard .pamt .woocommerce-Price-amount {
	color: #ffffff;
	font-size: 18px;
	font-weight: 700;
	line-height: 1.15;
}

.asc-ui .pcard .pamt del {
	color: var(--asc-muted);
	font-size: .8em;
	font-weight: 400;
}

/* The price row is the last thing before the buttons now: the category line
   under it was removed at Hamza's request, since every card on this shop read
   "Peptides". */
.asc-ui .pcard .pprice {
	margin-bottom: 16px;
}

/* Woo hides its own "Price" label this way; repeated so the label never
   prints inside the card if a filter reintroduces it. */
.asc-ui .pcard .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;
}

/* --------------------------------------------------------------------------
   4. Buttons

   The two forms are flex children so the pair behaves exactly like the
   reference's two-button row. The secondary deliberately does NOT carry
   .single_add_to_cart_button or .button: asc-ui.css paints both gold at 56px
   with !important, and only BUY NOW may be gold.
   -------------------------------------------------------------------------- */
/* Always stacked. Measured: the shop grid gives the card 263px at 1440 and
   149px at 768/1024 (the category rail keeps its column), so a side-by-side
   pair would sit at or under its 104px-per-button minimum at every width this
   grid actually produces. One rule, no breakpoints, nothing to drift. */
.asc-ui .pcard .pbtns {
	display: flex;
	flex-direction: column;
	gap: 8px;
	margin-top: auto;
}

/* Every card carries exactly TWO buttons, so the rhythm is identical across
   the grid. Only the primary changes with what you can actually do:
     buyable    BUY NOW (gold)   + ADD TO CART (outlined)
     multi-dose SELECT MG (gold) + VIEW LAB REPORT (outlined)
     sold out   SOLD OUT (dead)  + VIEW DETAILS (outlined)
   The second button always goes somewhere the first does not, so the pair is
   never two links to the same page. */

.asc-ui .pcard .pbtns > form {
	display: flex;
	flex: 1 1 0;
	min-width: 0;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
}

.asc-ui .pcard .pbtn {
	display: flex;
	flex: 1 1 auto;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 42px;
	min-height: 0;
	padding: 0 8px;
	border-radius: 50rem;
	font-size: 12px;
	font-weight: 700;
	line-height: 1;
	letter-spacing: .04em;
	text-transform: uppercase;
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
	/* background-COLOR, not the `background` shorthand: the shorthand drags
	   background-image into the transition, and a gradient cannot be
	   interpolated, so the paint lands in one frame however long the duration
	   says. 180ms ease-out per the house motion rule (120-200ms, ease-out). */
	transition: background-color .18s ease-out, color .18s ease-out, border-color .18s ease-out, filter .18s ease-out;
}

/* Single-button cards (SELECT MG / VIEW DETAILS).
   This used to be `flex: 1 1 100%`, which was written for a side-by-side row.
   The row stacks into a column, where flex-basis resolves against the CROSS
   axis, so 100% became a HEIGHT basis and the shrink factor squashed the
   button into a thin bar. Sizing it explicitly keeps it identical to the
   two-button pair. */
.asc-ui .pcard .pbtn-wide {
	flex: 0 0 auto;
	width: 100%;
}

/* Primary: Ascension gold. Black ink measures 6.12:1 at the darkest stop of
   the gradient (see the token block in asc-ui.css), clearing WCAG AA. */
/* !important on background-image, and only there.
   Elementor's lazy-load optimisation ships

     .e-con.e-parent:nth-of-type(n+3):not(.e-lazyloaded):not(.e-no-lazyload),
     .e-con.e-parent:nth-of-type(n+3):not(.e-lazyloaded):not(.e-no-lazyload) *
       { background-image: none !important }

   and that trailing `*` matches this button. On the homepage, where the
   Bestsellers row sits inside a below-the-fold container, it stripped the gold
   gradient and left a bordered black pill with black text: measured
   background-image "none" before this. Elementor restores it when the
   container scrolls in and gains .e-lazyloaded, so the button was invisible
   until then rather than permanently broken. This matches Elementor's
   !important on the same property, which is the only case this file allows. */
.asc-ui .pcard .pbtn-gold {
	background-color: transparent;
	background-image: var(--asc-gold-grad) !important;
	border: 1px solid var(--asc-gold-1);
	color: var(--asc-gold-ink);
	box-shadow: none;
}

/* DARKENED in place, not swapped for a second gradient. Two gradients cannot
   cross-fade, so the old swap snapped to its hover state in one frame however
   long the transition said. `filter` interpolates, so this actually eases over
   the full 180ms, and darkening is the direction that reads as "pressed"
   rather than "glowing".

   0.9 is the floor, checked rather than picked: brightness() runs in sRGB, so
   the gradient's darkest stop #a8862e becomes rgb(151,121,41), against which
   the button's black ink measures 5.08:1. Still clears WCAG AA. Going to 0.85
   would drop it under 4.5:1.

   :focus-visible, never :focus. A plain :focus kept the button lit for as long
   as it held focus after a mouse click, which read as the button being stuck.
   Keyboard users still get the state. */
.asc-ui .pcard .pbtn-gold:hover,
.asc-ui .pcard .pbtn-gold:focus-visible {
	border-color: var(--asc-gold-3);
	filter: brightness(.9);
}

/* Secondary: light outline. Contrasts with the gold without competing with it,
   and fills to solid on hover instead of scaling or glowing. Inverted from the
   original ink version now that the card has no white surface behind it. */
.asc-ui .pcard .pbtn-ink {
	background-color: transparent;
	border: 1px solid rgba(255, 255, 255, .38);
	color: #ffffff;
}

/* Hover has to be obvious without being a snap.

   The first version flipped background transparent -> #ffffff while the label
   went #ffffff -> #000000 in the same 160ms, so the text inverted mid-fade and
   the whole thing read as a hard flash. Dropping to a 10% wash fixed the flash
   but was then too faint to tell the button was under the cursor.

   22% white lands between the two: on #000 the fill resolves to rgb(56,56,56),
   a clear step off transparent, and the border goes 38% -> 100% white at the
   same time. The label stays white throughout, so there is nothing to invert
   and nothing to flash. */
.asc-ui .pcard .pbtn-ink:hover,
.asc-ui .pcard .pbtn-ink:focus-visible {
	background-color: rgba(255, 255, 255, .22);
	border-color: #ffffff;
	color: #ffffff;
}

/* Sold out: holds the primary slot so the two-button rhythm survives, but is
   plainly not a control. Not a <button disabled>, because it is a <span> with
   aria-disabled: there is nothing to press and nothing to focus. #8f8f8f on
   #000 measures 5.3:1, so the word stays readable rather than fading out. */
.asc-ui .pcard .pbtn-dead {
	background-color: transparent;
	border: 1px dashed rgba(255, 255, 255, .22);
	color: #8f8f8f;
	cursor: default;
}

.asc-ui .pcard .pbtn:active {
	filter: brightness(.96);
}

.asc-ui .pcard .pbtn:focus-visible {
	outline: 2px solid #ffffff;
	outline-offset: 2px;
}

/* A mouse click on a submit button leaves it focused, and Chrome will promote
   that to :focus-visible when the form's submit is preventDefault'd, which is
   exactly what the cart drawer does. Belt to the JS braces in asc-cards.js. */
.asc-ui .pcard .pbtn:focus:not(:focus-visible) {
	outline: none;
}

/* Busy: the click has landed, the server has not answered yet.

   Measured on the local mirror: wc-ajax=asc_cart_add takes ~1200ms to respond
   and the drawer only opens when it does, so without this the button looked
   completely untouched for over a second. That reads as a dropped click, and
   people press again and add the item twice. asc-cards.js sets this at click
   time, so acknowledgement is instant regardless of how slow the round trip
   is, and it swallows the second press. */
.asc-ui .pcard .pbtn.is-busy {
	cursor: progress;
	color: transparent;
}

.asc-ui .pcard .pbtn.is-busy::after {
	content: "";
	position: absolute;
	width: 15px;
	height: 15px;
	border: 2px solid currentcolor;
	border-radius: 50%;
	/* The ring is drawn in the button's own ink, with three quarters of it
	   made transparent so the rotation is legible. */
	border-color: var(--asc-gold-ink) transparent transparent transparent;
	animation: ascCardSpin .62s linear infinite;
}

.asc-ui .pcard .pbtn-ink.is-busy::after {
	border-color: #ffffff transparent transparent transparent;
}

.asc-ui .pcard .pbtn {
	position: relative;
}

@keyframes ascCardSpin {
	to { transform: rotate(360deg); }
}

.asc-ui .pcard .pcard-media:focus-visible,
.asc-ui .pcard .pname:focus-visible {
	outline: 2px solid #ffffff;
	outline-offset: -3px;
}

/* --------------------------------------------------------------------------
   5. Narrow cards

   Sized off the CARD, which the viewport does not predict: the shop grid's
   category rail keeps its column, so a 768px viewport yields a 149px card and
   1440 yields 263px. Rather than key off either number, the card is built to
   hold at its narrowest measured width (135px at 1024) and simply scales:
   the name is clamped to two lines, the price row wraps, and the buttons are
   always stacked. No breakpoints, so nothing can resolve wrong.

   (An earlier revision used @container here. It did not evaluate reliably in
   this stack -- a min-width probe that should have matched a 263px card did
   not fire -- and an unverifiable rule is worse than no rule.)
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   6. Motion
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	.asc-ui .pcard,
	.asc-ui .pcard .pcard-media img,
	.asc-ui .pcard .pbtn {
		transition: none;
	}

	/* The busy state still has to be visible without spinning, or a
	   reduced-motion visitor gets the blank button this was added to fix. */
	.asc-ui .pcard .pbtn.is-busy::after {
		animation: none;
		border-color: currentcolor;
		opacity: .55;
	}

	.asc-ui .pcard .pbtn.is-busy {
		color: inherit;
		opacity: .6;
	}

	.asc-ui .pcard .pbtn.is-busy::after {
		display: none;
	}

	.asc-ui .pcard:hover {
		transform: none;
	}

	.asc-ui .pcard:hover .pcard-media img {
		transform: none;
	}
}

/* ==========================================================================
   7. Site-wide: the white hairline under the header

   A near-white 1px line ran across the top of every page on a true-black site.

   CROSS-SESSION NOTE: the header belongs to Session A (inc/header.php +
   assets/css/asc-header.css). Their file was checked first and does not touch
   this border -- their only border-bottom is on .asc-anno, the marquee. This
   rule lives here because asc-cards.css is the stylesheet this session
   registers site-wide; it should move into asc-header.css when Session A's
   header work lands, and it is three selectors so the move is trivial.

   WHAT ACTUALLY DRAWS IT: not glozin's own
   `.header-mobile-main { border-bottom: 1px solid var(--gz-header-mobile-main-border-color) }`,
   which is the obvious suspect, but the Elementor header template's per-page
   stylesheet (post-1000073.css):

     body.elementor-page-1000073 .site-header__section .header-contents:last-child,
     body.elementor-page-1000073 .site-header__section .header-mobile-contents:last-child
       { border-bottom-color: currentcolor }

   `currentcolor` on a header whose text is white resolves to pure white, which
   is why it measured rgb(255,255,255) rather than glozin's #ebebeb. That
   selector is (0,4,1), so a plain `.asc-ui .header-mobile-main` rule (0,2,0)
   loses to it. Matched at (0,4,1) here and won on source order (Elementor's
   sheet prints at wp_head ~8, this one at 113), with the element's own
   .header-mobile-main class added on the second selector for headroom.

   Deliberately NOT scoped to the Elementor post id: that id changes per page
   template, and Hamza asked for the line gone on every page.
   ========================================================================== */
body.asc-ui .site-header__section .header-contents:last-child,
body.asc-ui .site-header__section .header-mobile-contents:last-child,
body.asc-ui .site-header__section .header-mobile-contents.header-mobile-main:last-child {
	border-bottom-color: transparent;
}

/* ==========================================================================
   8. Best Sellers banner: slow the gloss sweep

   asc-ui.css section 26 runs `ascBannerShine 3s`, whose keyframes put the
   whole travel in the first 45% of the cycle -- so the highlight actually
   crosses the banner in 1.35s and then rests. Hamza asked for slightly
   slower. 4.4s stretches the travel to 1.98s (about 1.5x) and lengthens the
   rest to 2.42s, without touching the keyframes.

   CROSS-SESSION NOTE: this is one declaration overriding asc-ui.css, which
   this session is instructed not to edit. It belongs in section 26 of that
   file; move it there when asc-ui.css is next open, and delete this block.
   ========================================================================== */
.asc-ui .apex-banner-shine {
	animation-duration: 4.4s;
}

/* ==========================================================================
   9. Cart drawer: the remove control is gold, not red

   asc-ui.css line 779 gives `.ascd-item-remove:hover { color: var(--asc-danger) }`,
   which is #dc3545. Hamza wants gold. Removing a line from a cart is a normal
   action, not a destructive one worth a danger colour, so gold is also the
   more honest signal.

   CROSS-SESSION NOTE: the drawer is inc/cart-drawer.php + asc-ui.css, which
   this session does not edit. Same specificity (0,1,1) as the rule it
   replaces, so it wins purely on source order: asc-ui.css prints at wp_head
   110, this file at 113. Move it into asc-ui.css section for the drawer when
   that file is next open, and delete this block.
   ========================================================================== */
.ascd-item-remove:hover,
.ascd-coupon-remove:hover {
	color: var(--asc-gold-1);
}

/* ==========================================================================
   10. Homepage Bestsellers grid

   The cards themselves are the shop's cards, rendered through the same
   content-product.php, so nothing about them is restyled here. This only
   supplies the grid the homepage section needs, because ul.products gets its
   column widths from glozin's shop CSS, which does not apply off the shop.
   ========================================================================== */
.asc-ui .asc-bestsellers {
	padding: 80px 40px;
	background: var(--asc-black);
}

.asc-ui .asc-bestsellers-wrap {
	max-width: 1400px;
	margin: 0 auto;
}

.asc-ui .asc-bestsellers-head {
	margin: 0 0 40px;
	color: #ffffff;
	font-size: clamp(28px, 4vw, 44px);
	font-weight: 800;
	line-height: 1.1;
	letter-spacing: -.02em;
}

.asc-ui ul.products.asc-bestsellers-grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 22px;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* The shop grid's li carries glozin's 15px side padding and 30px bottom
   margin. Inside a real grid those become double gutters. */
.asc-ui ul.products.asc-bestsellers-grid > li.product {
	width: auto;
	max-width: none;
	margin: 0;
	padding: 0;
	float: none;
}

@media (max-width: 1100px) {
	.asc-ui ul.products.asc-bestsellers-grid {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

@media (max-width: 820px) {
	.asc-ui .asc-bestsellers { padding: 56px 20px; }
	.asc-ui ul.products.asc-bestsellers-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 16px;
	}
}

/* ==========================================================================
   11. Same card size on every shop surface

   The shop page and the category archives rendered at different scales, which
   read as the page zooming in and out when you moved between them. Measured at
   1440x900, both 3 columns:

     /shop-page/                  container 1180  ->  card 263px
     /product-category/peptides/  container 1280  ->  card 297px

   Not a grid or column difference. `.asc-shop-2col` already asks for
   max-width: 1280px on both, but on the shop page its Elementor parent
   `.elementor-widget-container` carries `padding: 0 100px`, so only 1180px of
   its 1380px box is left and the grid never reaches the width it asked for.
   The archives have no such wrapper and get the full 1280.

   Zeroing that padding lets both land on 1280, so the cards are identical
   everywhere, Aminos included (the archives all share one template).

   :has() rather than a hardcoded Elementor element id, which would break the
   moment the page is re-saved. Verified resolving in this stack before use --
   unlike the container queries that were tried and removed earlier.

   CROSS-SESSION NOTE: the shop rail and its 2-col layout are inc/shop.php's.
   This is one padding reset that belongs beside `.asc-shop-2col` when that
   session next opens the file.

   Specificity note: Elementor's own rule is
   `.elementor-1000073 .elementor-element.elementor-element-f5fee3c > .elementor-widget-container`
   at (0,4,0), and :has() only contributes its argument's specificity, so the
   obvious `.asc-ui .elementor-widget-container:has(...)` sits at (0,3,0) and
   loses. Matched at (0,4,1) here. */
body.asc-ui .elementor-element > .elementor-widget-container:has(> .asc-shop-2col) {
	padding-left: 0;
	padding-right: 0;
}
