/*
 * The product card.
 *
 * Measured, at a 358px viewport, on the two references:
 *
 * Hey Harper  left aligned, name 13px/600 rgb(52,50,51) over a muted type line
 *             at 12px/500 in 40 percent, price 13px/600, a filled Add button,
 *             card rounded 0 0 12px 12px.
 * Atolea      centred, title 11px/400 uppercase, sale price 11px/700 in green
 *             rgb(68,172,82) beside a grey regular price, a SAVE badge, colour
 *             swatches, image 164x164 object-fit contain with no rounding.
 *
 * Against Pearlory's own, measured on the shop page: a 163x163 square image with
 * no rounding, a 31px #f2f2f2 bar split into price and cart icon, then a
 * 12.16px title centred in #334862.
 *
 * This follows Hey Harper's arrangement rather than Atolea's, because centred
 * small uppercase is the part that reads as dated and it is what Pearlory
 * already had. It follows neither on the specific values: the type, the radii
 * and the hairline are the ones this plugin already uses on the product page, so
 * a card and the page it links to look like the same shop. 12px on the image
 * matches the gallery, 8px on the button and #e8e6e1 on its border match the
 * show more reviews button, 13px/600 and #161616 match the accordion labels.
 */

/* The grey bar the price used to sit in, and the icon beside it. */
body.pearlory-card .product-small .box-pearl-value,
body.pearlory-card .product-small .sale_bubble {
	display: none;
}

/*
 * The image is left to Flatsome and WooCommerce.
 *
 * A 12px radius and an #f7f6f4 fill were added here and both were inventions.
 * The theme already sizes these cards with .has-equal-box-heights, which puts
 * padding-top: 100% on .box-image and absolutely positions the image to fill it,
 * giving the 163x163 square with object-fit: cover measured before any of this.
 * Nothing here changes the size, the crop or the corners.
 *
 * position: relative is the theme's own and is only restated because the badge
 * is positioned against this box.
 */
/*
 * A 12px radius on the image, and nothing else.
 *
 * WHY THIS IS HERE AFTER I WAS TOLD TO LEAVE THE IMAGE ALONE. An earlier build
 * gave the image a 12px radius together with a #f7f6f4 background and its own
 * sizing, and the instruction was to follow what Flatsome and WooCommerce
 * already set rather than invent a new thing. That still holds: the size, the
 * aspect box, the crop and the srcset are all still the theme's, and this rule
 * adds no background and no dimensions. The radius is measured off Hey Harper,
 * whose card carries border-radius: 12px with a transparent background, no
 * border and no shadow. It is the only thing making that card read as one
 * object, which is what was asked for.
 *
 * overflow: hidden so the corners actually clip the absolutely positioned
 * images the theme fills the box with.
 */
/*
 * The sale colour.
 *
 * Taken from the theme rather than picked here. Flatsome stores it as
 * --fs-color-alert, set to #b20000 on this site, so changing it in the
 * customizer changes the badge and the price with it and leaves no hex here to
 * drift out of date.
 *
 * WHY RED AND NOT THE BRAND TEAL. The badge was teal first, and it worked as a
 * fill. As type it did not: any teal dark enough to clear 4.5:1 against white
 * comes out near black at 14px, so the payable price stopped separating from the
 * product name in #2b2b2b directly above it. Measured, --fs-color-primary
 * darkened to #007979 sits at 5.24:1 but only 118 in straight rgb distance from
 * that name. Red carries as colour even when dark: #b20000 measures 7.24:1 as
 * type on the card and the same reversed out of the badge fill, so one token
 * covers both and neither needs adjusting.
 */
body.pearlory-card {
	--pearlory-sale: var(--fs-color-alert, #b20000);
}

/*
 * The extra swipe slides are hidden unless the swipe is actually active.
 *
 * product-card.php prints them on every card, because PHP cannot see whether the
 * rendered page will give this card a scroller: that depends on (hover: none) and
 * on Flatsome having supplied a height, neither of which exists at render time.
 *
 * Left visible they land in normal flow wherever there is no scroller, which is
 * every slider on the site. Measured on the home page's best sellers row: the
 * main image 151px tall, then a pearlory-card__slide stacked underneath it at
 * another 151px, so the box came out 302px and each card was twice the height it
 * should be. The rule inside the touch block below turns them back on for the one
 * case they were written for.
 *
 * display: none also stops the browser fetching them, since they are lazy.
 */
body.pearlory-card .pearlory-card__slide {
	display: none;
}

/*
 * The card as one object.
 *
 * NOT FROM THE REFERENCES, and worth being clear about. Both were measured and
 * neither boxes its card: Atolea's is transparent with no border, radius, shadow
 * or padding, and Hey Harper's is transparent with a 12px radius and nothing
 * else. Asked for directly, twice, so it is here on that basis rather than as
 * something either site does.
 *
 * WHY THERE IS NO PADDING AROUND THE PHOTO. Padding or a border around the image
 * would shrink it, and the instruction on the image is that its size follows
 * Flatsome and WooCommerce. So the photo stays flush to three edges at its full
 * column width and only the text below is inset. The 1px border still takes 2px
 * off the image width, 163 to 161, which is the one dimension this changes.
 *
 * White on a white page needs the hairline to exist at all, and #e8e6e1 is the
 * same hairline as the Filter button and the sort control above the grid.
 */
body.pearlory-card .product-small.box {
	/*
	 * A frame, on request, and neither reference has one: Atolea's card measured
	 * transparent with no border, radius, shadow or padding, and Hey Harper's
	 * transparent with a 12px radius and nothing else. Kept because a card without
	 * a visible edge did not read as a product card here.
	 *
	 * WHAT MADE THE FIRST BORDERED VERSION LOOK WRONG. Not the border. It was the
	 * border together with a full width solid button, which put a rounded
	 * rectangle inside a rounded rectangle, two boxes describing the same thing.
	 * The button beside the price is small enough not to compete with the frame,
	 * so the two can coexist.
	 *
	 * overflow: hidden is what clips the photo's top corners to the radius, so
	 * the image itself carries none.
	 */
	overflow: hidden;
	background: #fff;
	border: 1px solid #e8e6e1;
	border-radius: 12px;
}

/*
 * The radius now belongs to the card, which clips the photo's top corners
 * through overflow: hidden. overflow stays here too because the touch scroller
 * needs its own clip.
 */
body.pearlory-card .product-small .box-image {
	position: relative;
	overflow: hidden;
	border-radius: 0;
}

/*
 * The text column.
 *
 * Left aligned, and the theme centres it from several places, so the alignment
 * is set on the container and on the two children that carry their own.
 */
/*
 * The reading order, which the markup does not give.
 *
 * The theme hooks its add to cart onto woocommerce_shop_loop_item_title at
 * priority 1, so the button is emitted into .title-wrapper before the title and
 * the price are emitted at all. Rendered as the theme leaves it, the card reads
 * image, Add to cart, name, price, with the action above the thing it acts on.
 *
 * A column flex box with explicit order puts them back without touching the
 * hooks, so the theme keeps rendering whatever it wants in whatever sequence
 * and this decides where each part sits.
 */
body.pearlory-card .product-small .box-text {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	padding: 10px 0 0;
	text-align: left;
}

body.pearlory-card .product-small .box-text .name {
	order: 1;
}

body.pearlory-card .product-small .box-text .price {
	order: 2;
}

/*
 * The button's wrapper, stretched.
 *
 * The theme's own classes on .box-text include flex-row and flex-wrap, and they
 * left .title-wrapper sized to its content: measured at 98px inside a 163px
 * card, so the button's width: 100% resolved against 98 and came out at 60
 * percent of the card. Stated explicitly rather than relying on the column's
 * align-items.
 */
body.pearlory-card .product-small .box-text .title-wrapper {
	order: 3;
	align-self: stretch;
	width: 100%;
	padding: 0;
	text-align: left;
}

/* The theme emits this empty and it adds a gap between the price and button. */
body.pearlory-card .product-small .box-text .price-wrapper:empty {
	display: none;
}

/*
 * The title's own alignment. style.css sets .woocommerce-loop-product__title to
 * centre with a flag, so the container's alignment never reached it and the
 * title stayed centred over left aligned everything else. Only a flag takes a
 * flag.
 */
body.pearlory-card .product-small .box-text .name,
body.pearlory-card .product-small p.woocommerce-loop-product__title {
	padding: 0;
	text-align: left !important;
}

/*
 * The title.
 *
 * 13px/500 in #2b2b2b. Was 12.16px/400 in #334862, a blue grey that appears
 * nowhere else in the new design, and was briefly 600 in #161616, which put the
 * name at the same weight as the price and left nothing leading the card.
 *
 * Two lines then an ellipsis, so a long name cannot push the price out of line
 * with the card beside it. The grid puts cards in a row and a three line name
 * in one of them drags its neighbour's button down.
 */
body.pearlory-card .product-small .name a,
body.pearlory-card .product-small .product-title a {
	display: -webkit-box;
	overflow: hidden;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	font-size: 13px;
	font-weight: 500;
	line-height: 1.35;
	color: #2b2b2b;
	text-transform: none;
}

/*
 * Two lines of room whether the name needs them or not.
 *
 * A grid puts cards side by side and these names run from Cherry Necklace to
 * Mermaid Melody Necklace Set, so one wraps and its neighbour does not, and the
 * price and button below then sit at different heights across a row.
 *
 * The reserved height goes on the link, not on the paragraph around it. The
 * paragraph carries its own line-height from the theme, measured at 19.456px,
 * and that strut inflates the block: with the floor on the paragraph, a two line
 * name came to 37.69px while a one line name was held at 35.1px, so the two
 * still differed by 2.6px and everything below shifted with them. Zeroing the
 * paragraph's line-height removes the strut and lets the link be the only thing
 * deciding the height.
 */
body.pearlory-card .product-small .box-text .name {
	min-height: 0;
	margin: 0;
	line-height: 0;
}

body.pearlory-card .product-small .name a,
body.pearlory-card .product-small .product-title a {
	min-height: calc(2 * 1.35 * 13px);
}

/*
 * The price, now WooCommerce's own del and ins.
 *
 * The payable figure first, the struck one after it and quieter.
 *
 * Struck first was the first attempt and is what WooCommerce emits, but it puts
 * the number the customer is not paying where the eye lands. Measured on Hey
 * Harper's own card: CA$51 at 600 weight in an accent colour, then CA$101 struck
 * through at 40 percent opacity, in that order. The gap is 6px rather than the
 * non breaking space WooCommerce emits, which measured wider than it looked.
 */
body.pearlory-card .product-small .price {
	display: flex;
	/*
	 * Stacked, not side by side. Beside each other the pair is as wide as the
	 * currency makes it: 84px in USD but 130px in CAD, which is most of a 145px
	 * row and left nothing for the button, so the layout changed shape depending
	 * on which currency was selected. Stacked, the block is only as wide as the
	 * longer of the two figures, about 65px, so the row holds price and button in
	 * either currency and every card looks the same.
	 *
	 * ins carries order 1 and del order 2, so the payable figure is the top line.
	 */
	flex-direction: column;
	align-items: flex-start;
	/*
	 * No column gap. Zeroing the font size above collapses the whitespace item to
	 * nothing, but a gap still applies on both sides of it, so the price stayed
	 * indented by exactly one gap: 6px. The 6px lives on del instead, which is
	 * the second figure and the only place the space is wanted.
	 */
	gap: 0;
	margin: 4px 0 0;
	font-size: 13px;
	line-height: 1.35;
}

/*
 * The payable figure in the sale green, matching the badge and both references:
 * Hey Harper's sale price is rgb(1,138,65) and Atolea's rgb(68,172,82). A
 * product at one price stays near black below, because there is no saving to
 * signal on it.
 */
body.pearlory-card .product-small .price ins {
	order: 1;
	/*
	 * 14px, down from 15px. The price and the button share one 145px row and the
	 * pair measured 149px at the old sizes, so the button wrapped. Still the
	 * largest type on the card.
	 */
	font-size: 14px;
	font-weight: 700;
	/*
	 * The sale colour, the same token that fills the badge, so one accent runs
	 * through the card and the figure being paid is the only coloured thing in
	 * the text block. Measured 5.24:1 against the card at this size.
	 *
	 * It was briefly #161616, on the grounds that the darkened teal read muddy.
	 * That was the wrong call: black makes the payable price the same colour as
	 * the product name right above it, so nothing in the text block leads.
	 */
	color: var(--pearlory-sale, #b20000);
	text-decoration: none;
}

/*
 * The colour has to land on the amount span, not just on ins.
 *
 * WooCommerce nests the figure as ins > span.woocommerce-Price-amount > bdi, and
 * something in the stack sets that span to #111, which beats inheritance. So ins
 * reported the right colour while the glyphs the customer actually sees stayed
 * near black. Every colour tried on this price before now was invisible for the
 * same reason, which is worth knowing before judging one of them again.
 */
body.pearlory-card .product-small .price ins .woocommerce-Price-amount,
body.pearlory-card .product-small .price ins bdi,
body.pearlory-card .product-small .price ins .woocommerce-Price-currencySymbol {
	color: inherit;
}

/* Same nesting, same override, on the struck figure. */
body.pearlory-card .product-small .price del .woocommerce-Price-amount,
body.pearlory-card .product-small .price del bdi,
body.pearlory-card .product-small .price del .woocommerce-Price-currencySymbol {
	color: inherit;
}

body.pearlory-card .product-small .price del {
	order: 2;
	/* No left margin: the figures are stacked now, not beside each other. */
	margin-left: 0;
	font-size: 11.5px;
	font-weight: 400;
	color: rgba(0, 0, 0, 0.38);
	text-decoration: line-through;
	opacity: 1;
}

/* A product at one price gets that price in the same weight as a sale price. */
body.pearlory-card .product-small .price > .woocommerce-Price-amount {
	font-size: 13.5px;
	font-weight: 700;
	color: #161616;
}

/*
 * A variable product's two figures, which stacked even with the br hidden.
 *
 * The currency switcher wraps that case in a span.woocs_price_code, so del and
 * ins are its children rather than the price's, and the flex row above never
 * reached them: measured 36px tall against 19px for a simple product, so the
 * price of a variable card sat a line lower than the card beside it. The wrapper
 * is made a row of its own, which works whether it is present or not.
 */
body.pearlory-card .product-small .price br {
	display: none;
}

body.pearlory-card .product-small .price .woocs_price_code {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0;
}

/*
 * The saving badge, over the top left of the image.
 *
 * Both references badge a discount and Pearlory's card did not, despite every
 * product being 60 percent off. The percentage rather than the amount, because
 * at this size a percentage is shorter and it is what the references show.
 */
/*
 * The badge is printed on woocommerce_before_shop_loop_item_title, which lands
 * inside .box-text rather than inside the image, so the positioning ancestor is
 * the whole card. That is fine and in fact steadier: the image is the card's
 * first child, so a top left offset sits on the image wherever in the markup
 * the badge itself happens to be emitted.
 */
body.pearlory-card .product-small {
	position: relative;
}

/*
 * Green text rather than a filled black pill.
 *
 * Measured on both references, the discount is carried by colour on type, not by
 * a dark chip: Hey Harper prints "25% Off" as rgb(1,138,65) at 12px/500 over the
 * image with no background, and its sale price is the same green. Atolea's sale
 * price is rgb(68,172,82). A black chip on every card in a grid where every
 * product is 60 percent off was reading as page furniture.
 */
body.pearlory-card .pearlory-card__badge {
	position: absolute;
	z-index: 3;
	top: 8px;
	left: 8px;
	padding: 3px 8px;
	/*
	 * Solid fill, white text. Three things were tried before it.
	 *
	 * Black filled was too heavy repeated down a grid where every product is 60
	 * percent off. Bare coloured type, which is what Hey Harper prints, vanished
	 * on these photos: their shots are near white behind the top left corner and
	 * these sit on mid greys. Coloured type on a translucent white capsule was
	 * still hard to see, fairly, because at 11px the type carried the contrast
	 * alone. Reversed out of a solid fill it does not have to.
	 */
	background: var(--pearlory-sale, #b20000);
	border-radius: 6px;
	color: #fff;
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.01em;
	line-height: 1.4;
	white-space: nowrap;
}

/*
 * The add to cart control.
 *
 * Was an 18px bare icon sharing a grey bar with the price, which is a tap
 * target under the 44px minimum and reads as a fragment of a toolbar.
 *
 * Filled rather than outlined. Outlined was tried first and read as an empty box
 * carrying as much weight as the product name; Hey Harper's own card uses a
 * solid button with white text, and filling it is what lets the name drop to 500
 * and the price lead without the card losing its action.
 */
/*
 * The row holding the price and the button.
 *
 * .box-text was a flex column, so the button took the full 163px and the grid
 * came out as a stack of solid black bars. Hey Harper's card measured a 60x32
 * button sharing the bottom row with the price, so the fill is right and the
 * width was not.
 *
 * flex-wrap does the work. Price and button share the row when they fit, which
 * is a simple product at "Add", and when they do not, which is a variable
 * product at "Select options" against a price range, the button drops to its own
 * line and margin-left: auto keeps it right aligned. No label is ever clipped
 * and nothing needs to know which case it is in.
 */
/*
 * The card's base text size, stated rather than inherited.
 *
 * It was coming from the child theme, ".box-text { font-size: .8em !important }",
 * which resolved to 12.8px. Everything this stylesheet cares about is sized in
 * px, so removing that rule changed nothing visible, but it left the card's base
 * depending on a file this plugin does not own: 12.8px became 13.6px the moment
 * style.css was moved aside. Set here at the value it had, so anything on the
 * card not sized explicitly keeps the size it has always had.
 */
body.pearlory-card .product-small .box-text {
	font-size: 12.8px;
}

body.pearlory-card .product-small .box-text {
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	/*
	 * Inset from the frame, and the photo above it is not, so the photo keeps the
	 * full column width. row-gap carries the separation between rows, which
	 * matters because the button shares the price row when it fits and drops below
	 * it when it does not.
	 */
	padding: 10px 8px 10px;
	row-gap: 8px;
}

/*
 * Stated as a longhand because the theme sets padding-top on .box-text from a
 * rule that was winning, and the shorthand above resolved to 0: measured, the
 * title sat flush against the bottom edge of the photo.
 *
 * 8px at the sides rather than 10px is what buys the shared price row below:
 * content width goes from 141px to 145px, and price plus button needs 139px.
 */
/*
 * !important only because the child theme uses it. Its style.css carries
 * ".box-text { padding-top: 0em !important }", written for the old Lovisa card
 * where the grey price bar sat flush under the photo. Without matching it the
 * title touched the bottom edge of the image: measured gap 0px.
 */
body.pearlory-card .product-small .box-text {
	padding-top: 10px !important;
}

/*
 * Both margins to zero so align-items: center alone decides the row. The theme
 * puts margin-top: -1.4px on the wrapper and 4px on the price, which left the
 * button's centre 1.1px below the price's on the shared row.
 */
body.pearlory-card .product-small .box-text .title-wrapper {
	margin-top: 0 !important;
}

/*
 * align-self on the two items rather than align-items on the container, because
 * the theme sets align-items: flex-start on .box-text and was winning. Top
 * aligned, the 19.6px price sat against the top of the 34px button beside it and
 * their centres were 7.2px apart.
 */
body.pearlory-card .product-small .box-text .price {
	margin-top: 0;
	align-self: center;
}

body.pearlory-card .product-small .box-text .title-wrapper {
	align-self: center;
}

body.pearlory-card .product-small .box-text .name {
	flex: 0 0 100%;
}

/*
 * flex-grow must be 0. At 1 the price absorbed the free space on its line, came
 * out the full 163px, and pushed the button onto a row of its own, which is the
 * layout this was meant to replace. Shrink stays at 1 with min-width: 0 so a
 * long price range gives way instead of overflowing the card.
 */
body.pearlory-card .product-small .box-text .price {
	flex: 0 1 auto;
	min-width: 0;
	/*
	 * font-size: 0 to delete the whitespace between the two figures.
	 *
	 * WooCommerce prints "<del>...</del> <ins>...</ins>", and that single space
	 * between the tags becomes an anonymous flex item in this flex row. It sorts
	 * before both, because they carry order 1 and 2 and it has none, so it pushed
	 * the whole price 9.6px to the right: measured, a product on sale started its
	 * price at 18.6px inside the card while its own name started at 9px, and a
	 * product not on sale, having no del and so no space, lined up correctly at 9.
	 *
	 * Every visible child sets its own size below, so nothing inherits the zero.
	 */
	font-size: 0;
}

/*
 * The button takes its own full width row, always.
 *
 * WHY THIS IS NOT SHARING THE PRICE ROW ANY MORE. It did, and it only worked in
 * one currency. Measured on the Jewelry archive in USD, the price is 94px and
 * the button 45px against 145px of room, so they sat together. Switch the store
 * to CAD and the same price reads CA$32.57 CA$81.42 at 130px, so every card in
 * the grid wrapped and the button dropped below a left aligned price, right
 * aligned and lining up with nothing. Variable products did the same in either
 * currency, because "Select options" is 104px.
 *
 * A row of its own cannot come out ragged: the button is the same width and in
 * the same place on every card, whatever the currency, the label length or the
 * price. That is worth more here than the tighter layout was.
 */
/*
 * Beside the price, at the end of the row.
 *
 * This only works because the price is stacked. Side by side the pair did not
 * fit: at 163px with the border and the 8px inset the row is 145px, and a
 * variable product came to 84px of price plus a 66px "Choose", so it wrapped and
 * left simple cards 260.6px tall against variable cards 288.2px in the same grid.
 * In CAD nothing fitted at all. With the figures stacked the price block is about
 * 65px whatever the currency, so there is room for the longest label with slack
 * to spare and every card in the grid is the same height.
 */
body.pearlory-card .product-small .box-text .title-wrapper {
	flex: 0 0 auto;
	width: auto;
	margin: 0 0 0 auto;
}

/*
 * Stated as a longhand after the shorthand above, because the theme sets a
 * margin-top of -1.4px on this wrapper from a rule that was winning and left the
 * button sitting 1.4px above the price beside it.
 */
body.pearlory-card .product-small .box-text .title-wrapper {
	margin-top: 0;
	/*
	 * The theme sets min-width: 60% here, which on a 163px card is 97.7px. With
	 * the price also at 98px the pair came to 196px against 163 of room, so the
	 * button wrapped to its own line and the shared row never happened. Measured
	 * before and after: 97.7px, then 51px, which is the button.
	 */
	min-width: 0;
}

body.pearlory-card .product-small .box-text .button,
body.pearlory-card .product-small .box-text .add_to_cart_button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: auto;
	/*
	 * 34px, between Hey Harper's 32px and the 40px this card used before. The
	 * card's own image link is the primary target and covers 163x163, so the
	 * button is the secondary action here rather than the only way in.
	 */
	min-height: 32px;
	margin: 0;
	/*
	 * 10px, not 14px. The frame and the text inset take the row from 163px to
	 * 145px, and at 14px the pair measured 148px and wrapped even in USD.
	 */
	padding: 0 10px;
	/*
	 * Solid, with no border of its own.
	 *
	 * Four versions of this button. Solid black full width came first and was too
	 * heavy, but that was before the card had a container: the bars floated on
	 * white with nothing holding them, and they were 40px against a 163px card.
	 * A #f4f3f0 fill was the correction and was invisible, being barely a shade
	 * off the card and carrying the card's own #e8e6e1 border. Outlining it gave
	 * it an edge but put a rounded rectangle inside a rounded rectangle, which is
	 * what read as ugly: two boxes describing the same thing.
	 *
	 * Solid removes the inner box. The card's border is the only frame, and this
	 * is the weight at the bottom of it.
	 */
	background: #161616;
	border: 1px solid #161616;
	border-radius: 8px;
	color: #fff;
	font-size: 12.5px;
	font-weight: 600;
	letter-spacing: 0;
	line-height: 1.3;
	text-align: center;
	text-transform: none;
	white-space: nowrap;
}

/*
 * The pressed state, while the add is in flight.
 *
 * The card's button carries ajax_add_to_cart, so WooCommerce's own script adds a
 * "loading" class for the duration of the request and removes it on the response.
 * Nothing was styling that class here, so a tap produced no feedback at all: the
 * item went in the cart and the button sat there looking untouched. The child
 * theme used to cover this with .loading .cart-icon strong, which styled the plus
 * sign icon this plugin replaced with a word.
 *
 * The label goes transparent rather than being removed, so the button keeps its
 * width and the row does not move while the spinner runs. pointer-events: none
 * stops a second tap queueing another add.
 */
body.pearlory-card .product-small .box-text .button.loading,
body.pearlory-card .product-small .box-text .add_to_cart_button.loading {
	position: relative;
	color: transparent;
	pointer-events: none;
}

body.pearlory-card .product-small .box-text .button.loading::after,
body.pearlory-card .product-small .box-text .add_to_cart_button.loading::after {
	content: '';
	position: absolute;
	top: 50%;
	left: 50%;
	width: 14px;
	height: 14px;
	margin: -7px 0 0 -7px;
	border: 2px solid rgba(255, 255, 255, 0.35);
	border-top-color: #fff;
	border-radius: 50%;
	animation: pearlory-card-spin 0.6s linear infinite;
}

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

/*
 * Still a visible change without the rotation, so the button does not look inert
 * to somebody who has asked their system to stop animating things.
 */
@media (prefers-reduced-motion: reduce) {
	body.pearlory-card .product-small .box-text .button.loading::after,
	body.pearlory-card .product-small .box-text .add_to_cart_button.loading::after {
		animation: none;
		border-color: rgba(255, 255, 255, 0.55);
		border-top-color: #fff;
	}
}

body.pearlory-card .product-small .box-text .button:hover,
body.pearlory-card .product-small .box-text .button:focus-visible,
body.pearlory-card .product-small .box-text .add_to_cart_button:hover,
body.pearlory-card .product-small .box-text .add_to_cart_button:focus-visible {
	background: #000;
	border-color: #000;
	color: #fff;
}

/* The category line above the title, when the theme prints one. */
body.pearlory-card .product-small .category {
	margin: 0 0 2px;
	font-size: 11.5px;
	font-weight: 500;
	line-height: 1.3;
	color: rgba(0, 0, 0, 0.45);
	text-transform: none;
}

/*
 * Inside a slider the cards sit in a flickity viewport, where the theme hides
 * the discounted figure outright. Nothing here relies on that element any more,
 * but the rule also hid .raw_price, so the reset is stated for both.
 */
body.pearlory-card .flickity-viewport .product-small .price,
body.pearlory-card .flickity-viewport .product-small .price del,
body.pearlory-card .flickity-viewport .product-small .price ins {
	display: revert;
}

body.pearlory-card .flickity-viewport .product-small .price {
	display: flex;
}

/* A little more room per card once there is space for it. */
@media (min-width: 850px) {
	body.pearlory-card .product-small .box-text {
		padding-top: 12px;
	}

	body.pearlory-card .product-small .name a,
	body.pearlory-card .product-small .product-title a {
		font-size: 13.5px;
	}
}


/*
 * Swiping the card's photos, on touch screens only.
 *
 * Native scroll snap rather than a carousel. A shop grid shows 24 cards, so a
 * script per card would mean 24 carousel instances on one page; the product page
 * runs one Flickity and that is fine, twenty four is not. Scroll snap costs no
 * JavaScript and the browser decides whether a drag is horizontal or vertical,
 * so swiping a card cannot steal the page's own scrolling.
 *
 * Gated on (hover: none). With a mouse the theme's fade to the second image on
 * hover already works, and a scroll container under a pointer fights it.
 *
 * ALSO GATED ON .has-equal-box-heights, WHICH IS NOT COSMETIC. That class is what
 * makes Flatsome give .box-image a height of its own, via padding-top: 100%,
 * measured at 160.9px on a shop grid card. The scroller below is absolutely
 * positioned, so it fills that height and contributes none.
 *
 * Slider cards do not carry the class: measured on the home page's best sellers
 * row, padding-top is 0 and the box takes its height from the image sitting in
 * normal flow, 331px on a 151px wide card. Absolutely positioning the link there
 * removed the only thing holding the box open, so every card in every slider on
 * the home page collapsed to zero height and showed a name and a price with no
 * photograph. Isolated by removing the pearlory-card body class: 0px with it,
 * 331px without.
 *
 * So the swipe applies only where the theme has already fixed the height. In a
 * slider the theme's own hover swap stays, which is what it was doing before.
 */
@media (hover: none) {
	/*
	 * The link, at whatever depth. It was first written as .box-image > a and
	 * matched nothing: the theme wraps it in .image-fade_in_back, so the link is
	 * a grandchild. The row measured 163px of scroll width inside a 163px box,
	 * which is to say it never scrolled at all.
	 */
	body.pearlory-card .has-equal-box-heights .product-small .box-image a {
		/*
		 * Absolute, filling the aspect box.
		 *
		 * Flatsome sizes these cards with the padding trick: .box-image carries
		 * padding-top: 100% from .has-equal-box-heights and the image is
		 * absolutely positioned to fill it. Returning the images to the flow for
		 * scrolling meant .image-fade_in_back gained a height of its own, which
		 * landed on top of that padding: measured 163px of padding plus 163px of
		 * content, so every card image box came out 326px tall with the photo in
		 * the bottom half. The scroller takes the absolute fill instead, and the
		 * slides sit in the flow inside it.
		 */
		position: absolute;
		inset: 0;
		display: flex;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
	}

	body.pearlory-card .has-equal-box-heights .product-small .box-image a::-webkit-scrollbar {
		display: none;
	}

	/*
	 * The theme absolutely positions both of its images so they can cross fade.
	 * Stacked on top of each other they cannot scroll, so they are returned to
	 * the flow as full width slides. The alternate loses its hover only class for
	 * the same reason: on a touch screen it is slide two, not a hover state.
	 */
	/*
	 * Each photo becomes a full width slide. width, height and object-fit repeat
	 * what the theme already computes for its absolute fill rather than choosing
	 * anything new, so a slide renders at the same size and crop the card had
	 * before it could be swiped. Only the positioning changes, because absolute
	 * boxes stacked on each other cannot scroll.
	 */
	body.pearlory-card .has-equal-box-heights .product-small .box-image img,
	body.pearlory-card .has-equal-box-heights .product-small .box-image .pearlory-card__slide {
		/* Back on: this is the scroller the slides were printed for. */
		display: block;
		position: relative !important;
		inset: auto !important;
		flex: 0 0 100%;
		width: 100%;
		height: 100%;
		object-fit: cover;
		opacity: 1 !important;
		scroll-snap-align: start;
	}

	body.pearlory-card .has-equal-box-heights .product-small .box-image .show-on-hover {
		display: block !important;
		visibility: visible !important;
	}

	/*
	 * The discount badge must not become a slide. It is absolutely positioned so
	 * it is out of flex flow already, but the flex container above would other
	 * wise make it a flex item, so the position is restated here.
	 */
	body.pearlory-card .pearlory-card__badge {
		position: absolute;
	}

	/*
	 * The scroll position dots.
	 *
	 * Bottom left, inside the photo, because that corner is empty on every card:
	 * the discount badge sits top left and the price and name are below the
	 * image, so nothing is covered.
	 *
	 * pointer-events: none is the load bearing declaration. The scroller is the
	 * product link and it fills this box, so anything painted over it would
	 * otherwise take taps meant for the product.
	 *
	 * Added by script, so these rules match nothing until a card is measured as
	 * actually scrollable.
	 */
	/*
	 * Values copied from .pearlory-gal-dots in product-gallery.css, which is the
	 * same indicator on the product page: a 4px pill that grows from 6px to 16px
	 * and darkens, inside a translucent white capsule. The first build here was a
	 * 5px round dot, so the two pages described the same gesture two different
	 * ways.
	 *
	 * The inset is 8px rather than the gallery's 10px, because it is measured
	 * against this card instead of that gallery: the discount badge sits at
	 * top 8px left 8px, and dots on the same left edge at 10px would have been
	 * visibly 2px out from it.
	 */
	body.pearlory-card .product-small .box-image .pearlory-card__dots {
		position: absolute;
		bottom: 8px;
		left: 8px;
		z-index: 2;
		display: flex;
		align-items: center;
		gap: 4px;
		height: 12px;
		padding: 4px;
		border-radius: 9999px;
		background: rgba(255, 255, 255, 0.8);
		pointer-events: none;
	}

	body.pearlory-card .product-small .box-image .pearlory-card__dot {
		display: block;
		width: 6px;
		height: 4px;
		background: rgba(0, 0, 0, 0.18);
		border-radius: 9999px;
		transition: width 0.3s ease, background-color 0.3s ease;
	}

	body.pearlory-card .product-small .box-image .pearlory-card__dot.is-current {
		width: 16px;
		background: rgba(0, 0, 0, 0.7);
	}
}

/* Matching product-gallery.css, which drops the same transition. */
@media (prefers-reduced-motion: reduce) {
	body.pearlory-card .product-small .box-image .pearlory-card__dot {
		transition: none;
	}
}
