/*
 * Direct Checkout Optimizer — Frontend Styles
 * Minimal base styles. Sticky / Popup styles are in separate files (loaded on demand).
 */

/* =====================================================================
   Buy Now button (base)
   Actual colours are set via inline CSS generated from plugin settings.
   ===================================================================== */

.dco-buy-now-btn {
	display: inline-block;
	margin-top: 2px;
	padding: 12px 24px;
	font-size: 1em;
	font-weight: 600;
	line-height: 1.4;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
	border: none;
	border-radius: 4px;
	transition: opacity 0.2s ease, transform 0.1s ease;
	width: auto;
	max-width: 100%;
}

.dco-buy-now-btn:hover {
	opacity: 0.88;
}

.dco-buy-now-btn:active {
	transform: scale(0.98);
}

.dco-buy-now-btn:disabled,
.dco-buy-now-btn.dco-loading {
	opacity: 0.6;
	cursor: not-allowed;
}

/* Position helpers injected via JS */
.dco-buy-now-wrap {
	clear: both;
}

/*
 * Themes vary in whether they leave any room under the add-to-cart form.
 * Hello Elementor leaves none, so our buttons sat against it. This adds the
 * gap from our side rather than relying on the theme's.
 */
form.cart + .dco-buy-now-wrap,
form.cart + .dco-popup-trigger-wrap {
	margin-top: 16px;
}

/* =====================================================================
   No-script notice
   ===================================================================== */

.dco-noscript-notice {
	font-size: 0.875em;
	color: #555;
	margin: 8px 0 0;
}

/* =====================================================================
   AJAX spinner
   ===================================================================== */

.dco-spinner {
	display: inline-block;
	width: 16px;
	height: 16px;
	margin-left: 6px;
	vertical-align: middle;
	border: 2px solid rgba(255,255,255,0.4);
	border-top-color: #fff;
	border-radius: 50%;
	animation: dco-spin 0.7s linear infinite;
}

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

/* =====================================================================
   Buy Now error message
   ===================================================================== */

.dco-buy-now-error {
	color: #d63638;
	font-size: 0.875em;
	margin: 4px 0 0;
	padding: 0;
}

/* =====================================================================
   Variable product — disabled state
   ===================================================================== */

.dco-buy-now-btn--variable.disabled {
	opacity: 0.5;
	cursor: not-allowed;
	pointer-events: none;
}

/* =====================================================================
   Body scroll lock (when popup is open)
   ===================================================================== */

body.dco-noscroll {
	overflow: hidden;
}

/* Buy Now button rendered via [dco_buy_now] shortcode. */
.dco-buy-now-btn--shortcode {
	display: inline-block;
}

/* ── Buy Now button size variants (buy_now_size) ────────────────────────── */
.dco-buy-now-btn--small {
	padding: 6px 14px;
}

.dco-buy-now-btn--medium {
	padding: 10px 20px;
}

.dco-buy-now-btn--large {
	padding: 14px 28px;
}

/* Icon (buy_now_icon) */
/*
 * Both buttons are flex containers, so vertical-align on the icon has no
 * effect — the two were set to different values and neither was doing
 * anything, while the differing margins made the labels start at different
 * points. One rule for both.
 */
.dco-buy-now-btn__icon,
.dco-popup-trigger__icon {
	display: inline-block;
	flex-shrink: 0;
	margin-right: 6px;
	vertical-align: middle;
}

/* =====================================================================
   Replace Add to Cart
   The body class was being added but nothing ever used it, so the setting
   changed nothing anywhere. Hidden rather than removed, so the form still
   posts and any theme or plugin reading it still finds it.
   ===================================================================== */

/* Single product: the form's own button. */
.dco-replace-add-to-cart .single_add_to_cart_button,
.dco-replace-add-to-cart form.cart .single_add_to_cart_button {
	display: none !important;
}

/*
 * Shop, category and related-product listings.
 *
 * Scoped to cards that actually received our button. Matching `.products`
 * alone would also hit the related-products loop on a product page, where our
 * button only appears if Show on Related Products is on — hiding the theme's
 * button there would leave a card with no way to buy at all.
 *
 * Themes name this button differently, so the common ones are all listed.
 */
.dco-replace-add-to-cart .dco-has-buy-now .add_to_cart_button,
.dco-replace-add-to-cart .dco-has-buy-now .product_type_simple,
.dco-replace-add-to-cart .dco-has-buy-now .ajax_add_to_cart,
.dco-replace-add-to-cart .dco-has-buy-now .wp-block-button__link {
	display: none !important;
}

/* Our own button must survive those rules — it carries some of the same
   classes so that themes style it consistently. */
.dco-replace-add-to-cart .dco-buy-now-btn {
	display: inline-block !important;
}

/* =====================================================================
   Buy Now and Quick Order together
   The two buttons are rendered by separate classes that know nothing of
   each other, so the pair is arranged here from a body class.
   ===================================================================== */

/*
 * Stacked, the default.
 *
 * This was written as an adjacent-sibling rule, which only applies when the
 * two wrappers are next to each other — anything a theme printed between them
 * removed the gap without trace. Each wrapper now carries its own spacing, so
 * it holds wherever they land.
 */
/* ── Stacked, the default ───────────────────────────────────────────────── */
.dco-buy-now-wrap,
.dco-popup-trigger-wrap {
	margin-top: 14px;
	margin-bottom: 10px;
	/* Take a full line inside a flex or grid cart form. The button inside is
	   still auto-width, so this changes where they sit, not how wide. */
	flex-basis: 100%;
}

/*
 * Also on the buttons, since a theme template can drop the wrapper.
 *
 * Spacing only. An earlier version set display and width here too, which
 * stretched both buttons across the full page — the theme decides how wide its
 * buttons are, and this has no business changing that.
 */
.dco-buy-now-btn--single,
.dco-popup-trigger--single {
	display: block;
	width: auto;
	margin-top: 10px;
}

/*
 * Several themes make the cart form a flex or grid container. In those the
 * wrappers become flex items, and the margin between siblings is not what
 * separates them — the container's gap is.
 *
 * Scoped with :has() to forms this plugin added a button to, so a theme laying
 * out its quantity field or variation rows with flex is not affected. Browsers
 * without :has() fall back to the margins above, which is the previous
 * behaviour rather than a regression.
 */
form.cart:has( .dco-buy-now-wrap ),
form.cart:has( .dco-popup-trigger-wrap ) {
	row-gap: 10px;
}

/* Side by side. Wrapping is allowed, so a narrow phone drops the second
   button below rather than squeezing both. */
.dco-buttons-inline .dco-buy-now-wrap,
.dco-buttons-inline .dco-popup-trigger-wrap {
	display: inline-flex;
	vertical-align: top;
	margin-right: 10px;
	margin-bottom: 0;
	clear: none;
	flex-basis: auto;
}

.dco-buttons-inline .dco-buy-now-wrap + .dco-popup-trigger-wrap,
.dco-buttons-inline .dco-popup-trigger-wrap + .dco-buy-now-wrap {
	margin-right: 0;
}

/*
 * Side by side, stated on the buttons.
 *
 * The wrapper rules above cover themes that keep the wrapper; this covers the
 * ones that do not, which is the same reason the stacked spacing had to move
 * onto the buttons. Both are inline-block by default, so removing the stacked
 * top margin and putting the space to the side is all that is needed.
 */
.dco-buttons-inline .dco-buy-now-btn--single,
.dco-buttons-inline .dco-popup-trigger--single {
	display: inline-block;
	width: auto;
	margin-top: 0;
	margin-right: 10px;
	vertical-align: top;
}

@media ( max-width: 480px ) {
	/* Two buttons side by side on a phone leaves each too narrow to read,
	   so they stack regardless of the setting. */
	.dco-buttons-inline .dco-buy-now-wrap,
	.dco-buttons-inline .dco-popup-trigger-wrap {
		display: block;
		margin-right: 0;
	}

	.dco-buttons-inline .dco-buy-now-btn--single,
	.dco-buttons-inline .dco-popup-trigger--single {
		display: block;
		margin-top: 10px;
		margin-right: 0;
	}
}

/* =====================================================================
   Buttons inside a product listing

   Several shop themes reveal their Add to Cart button as an overlay on the
   product image — absolutely positioned, often only on hover. A button this
   plugin adds nearby inherits that positioning context and lands on top of
   the image with it. These rules put ours back in the normal flow, below the
   card's content, where a listing button belongs.
   ===================================================================== */
.dco-buy-now-wrap:has( .dco-buy-now-btn--loop ),
.dco-popup-trigger-wrap--loop {
	position: relative;
}

/*
 * Match the two in a listing.
 *
 * The Buy Now button carries a size class from its setting; the trigger has no
 * such setting and was falling back to the theme's padding, so the pair came
 * out at two different heights. In a product card they read as one control,
 * so the trigger follows the button.
 */
.dco-popup-trigger--loop,
.dco-popup-trigger--single {
	font-size: 1em;
	line-height: 1.4;
	font-weight: 600;
	border: none;
	border-radius: 4px;
	cursor: pointer;
}

.dco-buy-now-btn--loop,
.dco-popup-trigger--loop {
	position: static;
	width: 100%;
	opacity: 1;
	visibility: visible;
	transform: none;
	top: auto;
	right: auto;
	bottom: auto;
	left: auto;
}

/* Themes that only reveal the card's buttons on hover often animate them from
   a transform or an opacity of zero. Ours should not be hidden until hovered. */
li.product .dco-buy-now-btn--loop,
li.product .dco-popup-trigger--loop,
.wc-block-grid__product .dco-buy-now-btn--loop,
.wc-block-grid__product .dco-popup-trigger--loop {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
}

/*
 * One is an <a> and the other a <button>, with different default line-height
 * and vertical alignment. Stacked that is invisible; where a theme lays the
 * card out as a row it shows as one button sitting higher than the other.
 */
.dco-buy-now-btn--loop,
.dco-popup-trigger--loop {
	display: flex;
	align-items: center;
	justify-content: center;
	line-height: 1.4;
	box-sizing: border-box;
}

/*
 * Spacing between the two.
 *
 * This used to come from whitespace in the markup — which was also what pushed
 * them out of line with each other. Removing that fixed the alignment and left
 * them touching, so the gap is stated here instead: a margin for a card laid
 * out as a column, and a gap for one laid out as a row, where margins on the
 * children are not what separates them.
 */
.dco-buy-now-wrap:has( .dco-buy-now-btn--loop ),
.dco-popup-trigger-wrap--loop {
	margin: 8px 0 0;
}

/*
 * Between our own two, not on the card. A gap on the card would respace the
 * title, price and rating as well, on every theme already working.
 */
.dco-buy-now-wrap:has( .dco-buy-now-btn--loop ) + .dco-popup-trigger-wrap--loop,
.dco-popup-trigger-wrap--loop + .dco-buy-now-wrap:has( .dco-buy-now-btn--loop ) {
	margin-left: 8px;
}

/*
 * Equal height where the card lays them out as a row. `align-self` means
 * nothing inside a block container, so this is inert on the majority of themes
 * and applies only where the two genuinely sit side by side.
 */
.dco-buy-now-wrap:has( .dco-buy-now-btn--loop ),
.dco-popup-trigger-wrap--loop {
	align-self: stretch;
}

.dco-buy-now-wrap:has( .dco-buy-now-btn--loop ) > .dco-buy-now-btn--loop,
.dco-popup-trigger-wrap--loop > .dco-popup-trigger--loop {
	height: 100%;
}

.dco-buy-now-btn--loop,
.dco-popup-trigger--loop {
	margin: 0;
}

/* The row that holds both single-product buttons when side by side is chosen.
   One child of the cart form, so a form laid out as a column cannot separate
   them; this element decides how they sit. */
.dco-buttons-row {
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
	gap: 10px;
	width: 100%;
	margin: 14px 0 10px;
}

@media screen and ( max-width: 480px ) {
	/* Two buttons across a phone leaves each too narrow to read, so let them
	   wrap here — the one case where stacking is the better answer. */
	.dco-buttons-row {
		flex-wrap: wrap;
	}

	.dco-buttons-row > * {
		flex-basis: 100%;
	}
}

/* Row children: no margins of their own, and able to shrink. */
.dco-buttons-row > * {
	margin: 0;
	flex: 0 1 auto;
	min-width: 0;
}

/*
 * The buttons themselves, whether they are a direct child of the row or sit
 * inside a wrapper. One is an <a> and the other a <button>, and browsers give
 * the two different default line-height, vertical alignment and box sizing —
 * in a row that reads as one sitting higher than its neighbour.
 */
.dco-buttons-row .dco-buy-now-btn,
.dco-buttons-row .dco-popup-trigger {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	line-height: 1.4;
	vertical-align: middle;
	box-sizing: border-box;
	margin: 0;
}

/* A wrapper should not add height of its own around the button. */
.dco-buttons-row > .dco-buy-now-wrap,
.dco-buttons-row > .dco-popup-trigger-wrap {
	display: flex;
	align-items: stretch;
}

/*
 * When the pair is tight, give up horizontal padding before anything else.
 * Truncating the label would leave a shopper reading "Popup Checkout M…",
 * which is worse than a narrower button with the words intact.
 */
.dco-buttons-row .dco-buy-now-btn,
.dco-buttons-row .dco-popup-trigger {
	padding-left: clamp( 10px, 3vw, 24px ) !important;
	padding-right: clamp( 10px, 3vw, 24px ) !important;
	white-space: normal;
	text-align: center;
}
