/**
 * Clever Tickets embed styles.
 *
 * Everything is scoped to .ct-embed* classes. The iframe height is driven
 * by JS (CT_RESIZE messages); CSS only guarantees full width, no borders,
 * and no horizontal overflow at any viewport width.
 */

.ct-embed {
	position: relative;
	width: 100%;
	max-width: 100%;
	margin: 0 0 1.5em;
}

.ct-embed__frame {
	display: block;
	width: 100%;
	max-width: 100%;
	border: 0;
	/* The embedded surfaces render on a plain white canvas and carry no branded
	   top bar, so the frame never has to blend into a theme's own background.
	   Painting white here also covers the load window, before the embedded
	   document has painted anything of its own. */
	background: #ffffff;
	/* JS drives the iframe's height from the app's own content (CT_RESIZE).
	   Suppress the native scrollbar the browser would otherwise draw during
	   the load window, before the first resize lands. */
	overflow: hidden;
}

/* Loading overlay
   ------------------------------------------------------------------ */

.ct-embed__loading {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 12px;
	text-align: center;
	background: #ffffff;
	pointer-events: none;
	opacity: 1;
	visibility: visible;
	transition: opacity 0.25s ease, visibility 0.25s ease;
}

.ct-embed--ready .ct-embed__loading,
.ct-embed--error .ct-embed__loading {
	opacity: 0;
	visibility: hidden;
}

.ct-embed__spinner {
	display: inline-block;
	width: 28px;
	height: 28px;
	border-radius: 50%;
	border: 3px solid rgba(128, 128, 128, 0.25);
	border-top-color: rgba(96, 96, 96, 0.9);
	animation: ct-embed-spin 0.8s linear infinite;
}

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

.ct-embed__loading-text {
	font-size: 14px;
	line-height: 1.4;
	color: #6b7280;
}

/* Error panel
   ------------------------------------------------------------------ */

.ct-embed__error {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 12px;
	box-sizing: border-box;
	padding: 24px;
	text-align: center;
	background: #ffffff;
	border: 1px solid #d1d5db;
	border-radius: 4px;
	color: #374151;
}

.ct-embed__error[hidden] {
	display: none;
}

.ct-embed__error p {
	margin: 0;
	font-size: 15px;
	line-height: 1.5;
	color: #374151;
}

.ct-embed__retry {
	display: inline-block;
	padding: 8px 18px;
	font-size: 14px;
	line-height: 1.4;
	color: #1f2937;
	background: #f3f4f6;
	border: 1px solid #9ca3af;
	border-radius: 4px;
	cursor: pointer;
}

.ct-embed__retry:hover,
.ct-embed__retry:focus {
	background: #e5e7eb;
}

/* Link overlay
   ------------------------------------------------------------------
   Opens a Clever Tickets link over the page the visitor is already on,
   instead of navigating away from a custom storefront design. Two
   presentations share one DOM: a centered modal (default) and a
   right-hand slideover, selected by a class on the root.

   Deliberately theme-agnostic: no theme's colors, fonts, or radii are
   assumed, and everything is scoped under .ct-modal so a theme's own
   dialog styles cannot reach in. */

.ct-modal {
	position: fixed;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	/* Above the WordPress admin bar (99999) and above the consent managers
	   that routinely claim the top of the stack. */
	z-index: 2147483000;
	display: flex;
	box-sizing: border-box;
}

.ct-modal[hidden] {
	display: none;
}

.ct-modal * {
	box-sizing: border-box;
}

/* The SAME dim as .ct-page-dim and the corner cart panel — rgba(15,23,42,0.4),
   Tailwind's slate-900/40, which is what the application paints inside its own
   iframes. All three host popups darken the page identically, so a visitor who
   opens the cart and then checks out sees one continuous backdrop rather than
   the page stepping darker underneath them. */
.ct-modal__backdrop {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	background: rgba(15, 23, 42, 0.4);
	animation: ct-modal-fade 0.18s ease-out;
}

.ct-modal__panel {
	position: relative;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background: #ffffff;
	box-shadow: 0 24px 60px rgba(15, 23, 42, 0.28);
}

/* Brand accent (1.11.0)
   A hairline of the event's own color across the top of the panel, so the
   popup reads as part of the site that opened it rather than a white sheet
   floating over it. The color arrives with CT_CART and is set as --ct-accent
   on the panel; with no color known the bar has no size and nothing shows,
   which is also what happens on the first visit before any cart report. */
.ct-modal__panel::before {
	content: "";
	display: block;
	flex: 0 0 var(--ct-accent-size, 0);
	background: var(--ct-accent, transparent);
}

/* Centered modal (default) */

.ct-modal--modal {
	align-items: center;
	justify-content: center;
	padding: 24px;
}

.ct-modal--modal .ct-modal__panel {
	width: 100%;
	max-width: 1040px;
	max-height: 100%;
	border-radius: 10px;
	animation: ct-modal-pop 0.18s ease-out;
}

/* Narrow variant — checkout (1.11.0)
   ------------------------------------------------------------------
   Checkout is a single form column of roughly 600px. Centering it inside the
   1040px panel the product overlay uses left a wide white margin either side,
   and that slab of unused white around a narrow form is most of what made the
   popup read as an application window dropped on the page instead of part of
   it. Sized to the content, the frame all but disappears.

   Product overlays keep the full width — they lay out an image beside the
   details and genuinely use it.

   Specificity note: this has to tie with the base rule above and win on order,
   so it must stay ABOVE the max-width:640px block, which drops the constraint
   entirely for phones. */
.ct-modal--modal .ct-modal__panel--narrow {
	max-width: 620px;
	/* Content height arrives asynchronously (CT_RESIZE), so without a floor the
	   panel opens as a small centered box around the spinner and then jumps to
	   full height under the visitor's cursor. This is roughly a populated cart's
	   height: tall enough that the common case grows into it rather than
	   snapping, still a max-height away from overflowing a short window. */
	min-height: min(560px, 100%);
}

/* Right-hand slideover */

.ct-modal--slideover {
	align-items: stretch;
	justify-content: flex-end;
}

.ct-modal--slideover .ct-modal__panel {
	width: 100%;
	max-width: 480px;
	height: 100%;
	animation: ct-modal-slide 0.22s ease-out;
}

/* Panel chrome
   ------------------------------------------------------------------ */

/* The overlay has no header bar of its own (1.7.0). The embedded page already
   renders its title and its "Keep shopping" control, and a host header stacked
   above them duplicated both — with a close button every theme restyled as one
   of its own. The backdrop and Escape remain the host-level exits. */

.ct-modal__panel:focus {
	outline: none;
}

/* The scroll container. The iframe inside is sized to its full content
   height by CT_RESIZE, so this is what actually scrolls — never the
   iframe, which has no scrollbar of its own. */
.ct-modal__body {
	flex: 1 1 auto;
	min-height: 0;
	overflow-x: hidden;
	overflow-y: auto;
	/* Stop a scroll that reaches either end from chaining to the page
	   behind the overlay. */
	overscroll-behavior: contain;
	-webkit-overflow-scrolling: touch;
}

.ct-modal__body .ct-embed {
	margin: 0;
}

/* Scroll lock for the page behind the overlay.

   overflow:hidden alone does not hold on iOS Safari, so the body is also
   pinned in place. lockScroll() stores the offset in an inline `top` and
   unlockScroll() scrolls back to it, which is what keeps the pin from
   being visible to the visitor. */
.ct-modal-open,
.ct-modal-open body {
	overflow: hidden;
}

.ct-modal-open body {
	position: fixed;
	width: 100%;
}

@keyframes ct-modal-fade {
	from {
		opacity: 0;
	}
}

@keyframes ct-modal-pop {
	from {
		opacity: 0;
		transform: translateY(8px) scale(0.985);
	}
}

@keyframes ct-modal-slide {
	from {
		transform: translateX(100%);
	}
}

@media (max-width: 640px) {
	.ct-modal--modal {
		padding: 0;
	}

	.ct-modal--modal .ct-modal__panel {
		max-width: none;
		height: 100%;
		border-radius: 0;
	}

	.ct-modal--slideover .ct-modal__panel {
		max-width: none;
	}
}

/* Page dim (1.4.0)
   ------------------------------------------------------------------
   Raised while an INLINE store embed's cart popover is open (CT_MODAL). The
   embed can only darken its own iframe box, so the host darkens everything
   else in the SAME color the app uses inside — rgba(15,23,42,0.4), Tailwind's
   slate-900/40 — and lifts the embed above the dim. One uniform backdrop; no
   visible iframe seam. */

.ct-page-dim {
	position: fixed;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 2147482990;
	background: rgba(15, 23, 42, 0.4);
	animation: ct-modal-fade 0.18s ease-out;
}

.ct-embed--raised {
	position: relative;
	z-index: 2147482995;
}

/* Corner cart panel (1.4.0)
   ------------------------------------------------------------------
   The cart card a ct-add link opens over a CUSTOM storefront page: full-page
   dim plus a small card pinned bottom-right, visually identical to the cart
   popover inside the default store embed. The card paints the chrome (white,
   rounded corners, shadow); the borderless iframe inside is the app's compact
   cart panel document. */

.ct-cartpop {
	position: fixed;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 2147483000;
	box-sizing: border-box;
}

.ct-cartpop[hidden] {
	display: none;
}

.ct-cartpop * {
	box-sizing: border-box;
}

.ct-cartpop__backdrop {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	background: rgba(15, 23, 42, 0.4);
	animation: ct-modal-fade 0.18s ease-out;
}

/* Clears the cart button below it (1.7.0) — the same stacking the default
   store's own popover uses, so the button stays visible under the open card
   instead of being covered by it. */
.ct-cartpop__card {
	position: absolute;
	right: 24px;
	bottom: 96px;
	width: 384px;
	max-width: calc(100vw - 48px);
	overflow: hidden;
	background: #ffffff;
	border: 1px solid #e2e8f0;
	border-radius: 16px;
	box-shadow: 0 25px 50px -12px rgba(15, 23, 42, 0.25);
	transform-origin: bottom right;
	animation: ct-cartpop-in 0.32s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.ct-cartpop__card .ct-embed {
	margin: 0;
}

@keyframes ct-cartpop-in {
	from {
		opacity: 0;
		transform: translateY(24px) scale(0.85);
	}
}

@media (max-width: 640px) {
	.ct-cartpop__card {
		right: 16px;
		bottom: 84px;
		max-width: calc(100vw - 32px);
	}
}

/* Cart button (1.7.0)
   ------------------------------------------------------------------
   Lives on the HOST page, outside every iframe. That is the whole point: an
   embedded frame is auto-resized to its full content height, so `position:
   fixed` INSIDE it anchors to that tall internal box rather than the visitor's
   window — the button could only ever be pinned correctly from out here. It is
   also why it works on pages that embed nothing at all (a custom storefront
   built from links), and why it survives any iframe placement or screen size.

   Every property is stated explicitly, because a theme's own `button` rules
   would otherwise repaint it (the same way they repainted the overlay's old
   close button). It deliberately sits BELOW the dim so an open cart darkens it
   exactly as the default store's own popover does. */

.ct-cartbtn {
	position: fixed;
	right: 24px;
	bottom: 24px;
	z-index: 2147482900;
	/* Geometry, border, and box model are !important so a host THEME's own button
	   rules cannot repaint this into a bordered square — the exact bug a theme
	   forcing `border-radius: 3px`, a `1px` border, and `width: auto` onto buttons
	   produced (seen on clever.garetii.com). Stating every property explicitly is
	   NOT enough on its own: a theme rule wins on specificity or source order, and
	   only !important outranks a non-!important theme rule regardless of either.
	   Two properties are deliberately left non-!important: `background`, which the
	   JS sets inline to the event's color (a stylesheet !important would outrank
	   that inline value and lose the tint), and `bottom`, which the JS drives to
	   lift the button over a reCAPTCHA badge or cookie bar (1.8.0). */
	box-sizing: border-box !important;
	display: flex !important;
	align-items: center !important;
	justify-content: center !important;
	width: 60px !important;
	height: 60px !important;
	min-width: 0 !important;
	margin: 0 !important;
	padding: 0 !important;
	font: inherit;
	line-height: 1 !important;
	color: #ffffff !important;
	text-decoration: none !important;
	cursor: pointer;
	background: #0f172a;
	border: 0 !important;
	border-radius: 9999px !important;
	/* A solid disc in the event's own color — no ring, no gloss — matching the
	   store's "Add to cart" button. The two drop shadows (one broad and soft,
	   one tight) keep it reading as raised at every size. */
	box-shadow:
		0 10px 28px rgba(15, 23, 42, 0.4),
		0 3px 8px rgba(15, 23, 42, 0.3);
	appearance: none !important;
	-webkit-appearance: none !important;
	transition: transform 0.18s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.18s ease;
	animation: ct-cartbtn-enter 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) 0.1s backwards;
}

.ct-cartbtn[hidden] {
	display: none;
}

.ct-cartbtn:hover,
.ct-cartbtn:focus-visible {
	color: #ffffff;
	transform: translateY(-2px) scale(1.05);
	box-shadow:
		0 16px 36px rgba(15, 23, 42, 0.45),
		0 4px 10px rgba(15, 23, 42, 0.3);
}

.ct-cartbtn:active {
	transform: translateY(0) scale(0.92);
}

@keyframes ct-cartbtn-enter {
	from {
		opacity: 0;
		transform: translateY(16px) scale(0.5);
	}
	70% {
		opacity: 1;
		transform: translateY(-4px) scale(1.06);
	}
	to {
		opacity: 1;
		transform: translateY(0) scale(1);
	}
}

.ct-cartbtn__icon {
	display: block;
	width: 26px;
	height: 26px;
	pointer-events: none;
}

/* The count. Hidden at zero rather than showing "0" — the button itself is
   already the affordance, and a zero badge reads as an error. */
.ct-cartbtn__count {
	position: absolute;
	top: -4px;
	right: -4px;
	/* Same theme-override hardening as the button, so a theme cannot square the
	   pill or wrap it in a border. `color` stays non-!important — the JS tints it
	   to the event color inline, exactly like the button's background. */
	box-sizing: border-box !important;
	display: flex !important;
	align-items: center !important;
	justify-content: center !important;
	min-width: 24px !important;
	height: 24px !important;
	padding: 0 7px !important;
	font-family: inherit;
	font-size: 12px;
	font-weight: 700;
	line-height: 1 !important;
	color: #0f172a;
	background: #ffffff !important;
	border: 0 !important;
	border-radius: 9999px !important;
	box-shadow: 0 2px 6px rgba(15, 23, 42, 0.3);
	font-variant-numeric: tabular-nums;
	pointer-events: none;
}

.ct-cartbtn__count[hidden] {
	display: none;
}

/* One pop when something goes in — re-triggered from JS per increase. */
.ct-cartbtn__count--bump {
	animation: ct-cartbtn-bump 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes ct-cartbtn-bump {
	30% {
		transform: scale(1.35);
	}
}

@media (max-width: 640px) {
	.ct-cartbtn {
		right: 16px;
		bottom: 16px;
		/* !important for the same theme-override reason as the base rule — otherwise
		   the desktop base width/height (also !important) would win on phones too. */
		width: 56px !important;
		height: 56px !important;
	}
}

/* The zero-size frame that tells the button how many tickets are in the cart
   on a page that embeds nothing else. Never visible, never focusable. */
.ct-cart-count-frame {
	position: absolute;
	top: 0;
	left: -9999px;
	width: 1px;
	height: 1px;
	border: 0;
	opacity: 0;
	pointer-events: none;
}

/* Config notice (editors/admins only)
   ------------------------------------------------------------------ */

.ct-embed-config-notice {
	box-sizing: border-box;
	width: 100%;
	max-width: 100%;
	margin: 0 0 1.5em;
	padding: 12px 16px;
	background: #fffbeb;
	border: 1px solid #fde68a;
	border-left: 4px solid #d97706;
	border-radius: 2px;
	color: #78350f;
}

.ct-embed-config-notice p {
	margin: 0 0 6px;
	font-size: 14px;
	line-height: 1.5;
}

.ct-embed-config-notice p:last-child {
	margin-bottom: 0;
}

.ct-embed-config-notice__meta {
	font-size: 12px;
	opacity: 0.8;
}

/* Reduced motion
   ------------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
	.ct-embed__spinner {
		animation: none;
	}

	.ct-embed__loading {
		transition: none;
	}

	.ct-modal__backdrop,
	.ct-modal__panel,
	.ct-page-dim,
	.ct-cartpop__backdrop,
	.ct-cartpop__card {
		animation: none;
	}

	.ct-cartbtn {
		transition: none;
		animation: none;
	}

	.ct-cartbtn:hover,
	.ct-cartbtn:focus-visible,
	.ct-cartbtn:active {
		transform: none;
	}

	.ct-cartbtn__count--bump {
		animation: none;
	}
}
