/*!
 * Camerce Popup Campaigns — front-end styles.
 *
 * Everything here is fixed or absolute, so nothing this file does can move the
 * host page. Sizing comes from the --camerce-popups-* custom properties the renderer puts
 * on each campaign root; this file only decides how they are used.
 */

.camerce-popups-campaign {
	--camerce-popups-width: 480px;
	--camerce-popups-padding: 32px;
	--camerce-popups-radius: 12px;
	--camerce-popups-bg: #fff;
	--camerce-popups-text: #101f1d;
	--camerce-popups-overlay: #0b1615;
	--camerce-popups-overlay-opacity: 0.55;
	--camerce-popups-duration: 320ms;
	--camerce-popups-close: 44px;
	--camerce-popups-gutter: 24px;

	position: fixed;
	inset: 0;
	z-index: 99990;
	display: flex;
	visibility: hidden;
	box-sizing: border-box;
	padding: var(--camerce-popups-gutter);
	color: var(--camerce-popups-text);
	pointer-events: none;
	-webkit-font-smoothing: antialiased;
}

.camerce-popups-campaign *,
.camerce-popups-campaign *::before,
.camerce-popups-campaign *::after {
	box-sizing: border-box;
}

.camerce-popups-campaign.is-open {
	visibility: visible;
}

/* --- overlay --- */

.camerce-popups-campaign__overlay {
	position: absolute;
	inset: 0;
	background: var(--camerce-popups-overlay);
	opacity: 0;
	pointer-events: auto;
	transition: opacity var(--camerce-popups-duration) ease;
}

.camerce-popups-campaign.is-open > .camerce-popups-campaign__overlay {
	opacity: var(--camerce-popups-overlay-opacity);
}

/* --- panel --- */

.camerce-popups-campaign__panel {
	position: relative;
	z-index: 1;
	width: 100%;
	max-width: var(--camerce-popups-width);
	max-height: calc(100vh - (var(--camerce-popups-gutter) * 2));
	padding: var(--camerce-popups-padding);
	overflow: auto;
	background-color: var(--camerce-popups-bg);
	/*
	 * Two background layers over that colour: the tint on top, the campaign's
	 * image below it, --camerce-popups-bg underneath both — so a transparent PNG still
	 * sits on the chosen colour.
	 *
	 * The tint is a flat gradient rather than a pseudo-element or a DOM node.
	 * The markup contract is shared with the builder canvas, so a node is out;
	 * and a positioned pseudo-element would scroll away from a background that
	 * does not, once the content is taller than the panel. The tint layer is
	 * always cover/repeat, whatever the image is set to, because its job is to
	 * keep the text legible everywhere, not only where the photo reaches.
	 *
	 * None of these properties are printed unless a campaign has an image, so
	 * each falls back to the value that paints nothing.
	 */
	background-image:
		linear-gradient(var(--camerce-popups-bg-tint, transparent), var(--camerce-popups-bg-tint, transparent)),
		var(--camerce-popups-bg-image, none);
	background-position: 0 0, var(--camerce-popups-bg-position, center center);
	background-size: cover, var(--camerce-popups-bg-size, cover);
	background-repeat: repeat, var(--camerce-popups-bg-repeat, no-repeat);
	/*
	 * --camerce-popups-font is only printed when the campaign picked one; with no value
	 * the panel inherits the theme's font, which is the default.
	 */
	font-family: var(--camerce-popups-font, inherit);
	border-radius: var(--camerce-popups-radius);
	opacity: 0;
	pointer-events: auto;
	transform: var(--camerce-popups-from, none);
	transition:
		opacity var(--camerce-popups-duration) ease,
		transform var(--camerce-popups-duration) cubic-bezier(0.2, 0.7, 0.3, 1);
	-webkit-overflow-scrolling: touch;
}

.camerce-popups-campaign.is-open > .camerce-popups-campaign__panel {
	opacity: 1;
	transform: none;
}

.camerce-popups-campaign.is-shadowed > .camerce-popups-campaign__panel {
	box-shadow: 0 8px 20px -12px rgba(6, 20, 18, 0.4), 0 32px 60px -30px rgba(6, 20, 18, 0.5);
}

.camerce-popups-campaign__content > *:first-child {
	margin-top: 0;
}

.camerce-popups-campaign__content > *:last-child {
	margin-bottom: 0;
}

/* --- close --- */

/*
 * The hit area stays at --camerce-popups-close (44px, WCAG 2.5.5) but the *visible*
 * control is a smaller disc drawn by ::before. A 44px circle sitting 8px
 * inside a panel with an 18px corner radius reads as hanging off the corner,
 * and a bare glyph disappears entirely over a full-bleed image -- which is
 * what the image templates put directly behind it.
 */
/*
 * `sticky`, not `absolute`. The panel is the scroll container, so an absolutely
 * positioned close button scrolled away with the content: on a short viewport
 * the only visible way out ended up above the top of the panel. Sticky keeps it
 * pinned to the panel's top-right while the content scrolls under it.
 *
 * The button is the panel's first child, so floating it right takes it out of
 * vertical flow -- the content still starts at the top of the panel rather than
 * below the button -- while `sticky` keeps it in flow enough to pin.
 */
.camerce-popups-campaign__close {
	position: sticky;
	float: right;
	top: 6px;
	right: 6px;
	/* Cancels the space the float would otherwise reserve on the line. */
	margin-bottom: calc(var(--camerce-popups-close) * -1);
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	width: var(--camerce-popups-close);
	height: var(--camerce-popups-close);
	margin: 0;
	padding: 0;
	color: inherit;
	background: transparent;
	border: 0;
	border-radius: 50%;
	opacity: 0.75;
	cursor: pointer;
	appearance: none;
	transition: opacity 150ms ease;
}

/*
 * The disc. Sized independently of the hit area.
 *
 * It used to be solid white, which assumed the panel behind it was light. The
 * glyph is drawn in `currentColor`, so on a dark campaign -- a mat, a dark bar,
 * any popup with a dark background -- it was white-on-white and the cross
 * disappeared entirely.
 *
 * Tinting with `currentColor` instead makes the disc follow the panel: a faint
 * dark circle under a dark glyph, a faint light circle under a light one. It
 * stays subtle enough that the glyph still reads against it, while giving the
 * cross something to sit on over a background image. The rgba line is the
 * fallback for browsers without color-mix().
 */
.camerce-popups-campaign__close::before {
	content: "";
	position: absolute;
	width: 30px;
	height: 30px;
	border-radius: 50%;
	background: rgba(127, 127, 127, 0.18);
	background: color-mix(in srgb, currentColor 16%, transparent);
	transition: background-color 150ms ease;
}

/* Keep the glyph above its own disc. */
.camerce-popups-campaign__close > svg {
	position: relative;
	z-index: 1;
}

.camerce-popups-campaign__close:hover,
.camerce-popups-campaign__close:focus-visible {
	opacity: 1;
}

.camerce-popups-campaign__close:hover::before,
.camerce-popups-campaign__close:focus-visible::before {
	background: rgba(127, 127, 127, 0.3);
	background: color-mix(in srgb, currentColor 28%, transparent);
}

/*
 * The ring is drawn *inside* the hit area. Offset outwards it was wider than
 * the button, so it crossed the panel's rounded corner and looked like a
 * detached circle floating off the edge. The runtime also moves focus into the
 * campaign when it opens, so a plain :focus ring would greet every visitor --
 * :focus-visible keeps it for keyboard users, where it belongs.
 */
.camerce-popups-campaign__close:focus {
	outline: none;
}

.camerce-popups-campaign__close:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: -7px;
}

/* Outside the panel, for designs that would rather not lose the corner. */
.camerce-popups-campaign__close--outside {
	top: calc(var(--camerce-popups-close) * -1 - 6px);
	right: 0;
	color: #fff;
	opacity: 0.9;
}

/* Over the dimmed overlay rather than the panel, so the disc inverts. */
.camerce-popups-campaign__close--outside::before {
	background: rgba(16, 32, 30, 0.45);
	box-shadow: none;
}

.camerce-popups-campaign__close--outside:hover::before,
.camerce-popups-campaign__close--outside:focus-visible::before {
	background: rgba(16, 32, 30, 0.65);
}

/* --- placement --- */

.camerce-popups-campaign--pos-center {
	align-items: center;
	justify-content: center;
}

.camerce-popups-campaign--pos-top {
	align-items: flex-start;
	justify-content: center;
}

.camerce-popups-campaign--pos-bottom {
	align-items: flex-end;
	justify-content: center;
}

.camerce-popups-campaign--pos-left {
	align-items: center;
	justify-content: flex-start;
}

.camerce-popups-campaign--pos-right {
	align-items: center;
	justify-content: flex-end;
}

.camerce-popups-campaign--pos-top-left {
	align-items: flex-start;
	justify-content: flex-start;
}

.camerce-popups-campaign--pos-top-right {
	align-items: flex-start;
	justify-content: flex-end;
}

.camerce-popups-campaign--pos-bottom-left {
	align-items: flex-end;
	justify-content: flex-start;
}

.camerce-popups-campaign--pos-bottom-right {
	align-items: flex-end;
	justify-content: flex-end;
}

/* --- campaign types --- */

/* Slide-in: a corner card, defaults to bottom right when unpositioned. */
.camerce-popups-campaign--slide_in {
	--camerce-popups-gutter: 20px;

	align-items: flex-end;
	justify-content: flex-end;
}

.camerce-popups-campaign--slide_in.camerce-popups-campaign--pos-center {
	align-items: center;
	justify-content: center;
}

.camerce-popups-campaign--slide_in.camerce-popups-campaign--pos-top-left,
.camerce-popups-campaign--slide_in.camerce-popups-campaign--pos-bottom-left {
	justify-content: flex-start;
}

.camerce-popups-campaign--slide_in.camerce-popups-campaign--pos-top-left,
.camerce-popups-campaign--slide_in.camerce-popups-campaign--pos-top-right {
	align-items: flex-start;
}

.camerce-popups-campaign--slide_in .camerce-popups-campaign__panel {
	max-width: min(var(--camerce-popups-width), 92vw);
}

/* Notification bar: full width, no gutter, sits above or below everything. */
.camerce-popups-campaign--bar {
	--camerce-popups-gutter: 0px;

	align-items: flex-start;
	justify-content: center;
	z-index: 99991;
}

.camerce-popups-campaign--bar.camerce-popups-campaign--pos-bottom {
	align-items: flex-end;
}

/*
 * The WordPress admin bar.
 *
 * Core pushes the page down with `html { margin-top: 32px !important }`, but
 * this root is `position: fixed`, so it is positioned against the viewport and
 * ignores that margin entirely -- a top bar rendered underneath the admin bar,
 * half of it hidden, for every logged-in author previewing their own campaign.
 * Only the top edge needs moving; a bottom bar is unaffected.
 */
body.admin-bar .camerce-popups-campaign--bar.camerce-popups-campaign--pos-top,
body.admin-bar .camerce-popups-campaign--modal,
body.admin-bar .camerce-popups-campaign--slide_in {
	top: var(--wp-admin--admin-bar--height, 32px);
}

@media screen and (max-width: 782px) {
	body.admin-bar .camerce-popups-campaign--bar.camerce-popups-campaign--pos-top,
	body.admin-bar .camerce-popups-campaign--modal,
	body.admin-bar .camerce-popups-campaign--slide_in {
		top: var(--wp-admin--admin-bar--height, 46px);
	}
}

.camerce-popups-campaign--bar .camerce-popups-campaign__panel {
	max-width: none;
	max-height: none;
	padding: clamp(10px, calc(var(--camerce-popups-padding) / 2), 28px) var(--camerce-popups-padding);
	border-radius: 0;
	text-align: center;
}

.camerce-popups-campaign--bar .camerce-popups-campaign__close {
	top: 50%;
	right: 6px;
	transform: translateY(-50%);
}

/* --- animations --- */

.camerce-popups-campaign--anim-fade {
	--camerce-popups-from: none;
}

.camerce-popups-campaign--anim-fade-up {
	--camerce-popups-from: translate3d(0, 16px, 0);
}

.camerce-popups-campaign--anim-slide-up {
	--camerce-popups-from: translate3d(0, 100%, 0);
}

.camerce-popups-campaign--anim-slide-down {
	--camerce-popups-from: translate3d(0, -100%, 0);
}

.camerce-popups-campaign--anim-slide-left {
	--camerce-popups-from: translate3d(110%, 0, 0);
}

.camerce-popups-campaign--anim-slide-right {
	--camerce-popups-from: translate3d(-110%, 0, 0);
}

.camerce-popups-campaign--anim-zoom {
	--camerce-popups-from: scale3d(0.92, 0.92, 1);
}

.camerce-popups-campaign--anim-none {
	--camerce-popups-from: none;
	--camerce-popups-duration: 0ms;
}

/* The bar slides from its own edge whatever the chosen animation. */
.camerce-popups-campaign--bar.camerce-popups-campaign--anim-slide-up,
.camerce-popups-campaign--bar.camerce-popups-campaign--pos-bottom.camerce-popups-campaign--anim-fade-up {
	--camerce-popups-from: translate3d(0, 100%, 0);
}

.camerce-popups-campaign--bar.camerce-popups-campaign--pos-top.camerce-popups-campaign--anim-fade-up {
	--camerce-popups-from: translate3d(0, -100%, 0);
}

/* --- open triggers --- */

.camerce-popups-open {
	font: inherit;
	color: inherit;
	background: none;
	border: 0;
	padding: 0;
	cursor: pointer;
	text-decoration: underline;
}

.camerce-popups-open:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

/* --- scroll lock --- */

/* Padding replaces the scrollbar, so locking the page shifts nothing. */
.camerce-popups-locked,
.camerce-popups-locked body {
	overflow: hidden;
}

.camerce-popups-locked body {
	padding-right: var(--camerce-popups-gap, 0px);
}

/* --- mobile --- */

@media (max-width: 767px) {
	.camerce-popups-campaign {
		--camerce-popups-gutter: 12px;
		--camerce-popups-padding: max(20px, calc(var(--camerce-popups-padding) * 0.7));
	}

	.camerce-popups-campaign:not(.camerce-popups-campaign--bar) .camerce-popups-campaign__panel {
		max-width: var(--camerce-popups-mobile-width, 100%);
	}

	.camerce-popups-campaign--m-bottom:not(.camerce-popups-campaign--bar) {
		align-items: flex-end;
		justify-content: center;
	}

	.camerce-popups-campaign--m-top:not(.camerce-popups-campaign--bar) {
		align-items: flex-start;
		justify-content: center;
	}

	.camerce-popups-campaign--m-center:not(.camerce-popups-campaign--bar) {
		align-items: center;
		justify-content: center;
	}

	.camerce-popups-campaign--mw-full .camerce-popups-campaign__panel {
		max-width: 100%;
	}

	.camerce-popups-campaign--bar .camerce-popups-campaign__panel {
		max-width: none;
	}
}

/* --- reduced motion --- */

/*
 * The only !important rules in this file. A visitor who has asked their OS to
 * stop animating things outranks every campaign setting, and outranks any
 * inline --camerce-popups-duration the renderer wrote onto the element.
 */
@media (prefers-reduced-motion: reduce) {
	.camerce-popups-campaign,
	.camerce-popups-campaign__panel,
	.camerce-popups-campaign__overlay,
	.camerce-popups-campaign__close {
		transition: none !important;
		animation: none !important;
	}

	.camerce-popups-campaign__panel {
		transform: none !important;
	}
}

.camerce-popups-campaign.camerce-popups-reduced,
.camerce-popups-campaign.camerce-popups-reduced .camerce-popups-campaign__panel,
.camerce-popups-campaign.camerce-popups-reduced .camerce-popups-campaign__overlay {
	transition-duration: 1ms;
}

.camerce-popups-campaign.camerce-popups-reduced .camerce-popups-campaign__panel {
	transform: none;
}

/* A submitted form is done: the fields are hidden, so the confirmation stands
   alone instead of sitting under a live Subscribe button. `[hidden]` is
   restated because any `display` rule outranks the UA sheet's. */
.camerce-popups-form.is-done [hidden] {
	display: none !important;
}

.camerce-popups-form.is-done .camerce-popups-form__message {
	margin-top: 0;
}
