/**
 * Novixa Addons — Front-end widget styles.
 * Every class lives under the novixa-addons- namespace.
 */

.novixa-addons-heading__title {
	margin: 0 !important;
	padding: 0 !important;
	transition-property: color;
}

.novixa-addons-heading__subtitle {
	margin-top: 6px;
	opacity: 0.75;
	font-size: 0.85em;
}

/* Prevent the widget from stretching taller than its own content when
   the parent Elementor Container's cross-axis alignment is "Stretch"
   (the default) — without this, the widget's root box can inherit
   the leftover height of a taller sibling/column and leave visible
   empty space below the text, even though nothing is actually set on
   the widget itself. !important guards against theme/customizer
   global heading rules (e.g. Astra's Customizer > Typography adding
   site-wide h1–h6 margin/line-height) beating this reset. */
.elementor-widget-novixa-addons-heading,
.elementor-widget-novixa-addons-dual-color-heading {
	margin: 0 !important;
	padding: 0 !important;
}

.elementor-widget-novixa-addons-heading > .elementor-widget-container,
.elementor-widget-novixa-addons-dual-color-heading > .elementor-widget-container {
	align-self: flex-start !important;
	height: auto !important;
	min-height: 0 !important;
	margin: 0 !important;
	padding: 0 !important;
}

.novixa-addons-heading,
.novixa-addons-dual-color-heading {
	margin: 0 !important;
	line-height: normal;
}

.novixa-addons-dual-color-heading__title {
	margin: 0 !important;
	padding: 0 !important;
}

.novixa-addons-dual-color-heading__part-one,
.novixa-addons-dual-color-heading__part-two {
	display: inline;
	transition-property: color;
}

/* Layout: Second Part on New Line — part two drops below part one and
   the inline "Gap Between Parts" margin (which only makes sense when
   both parts share a line) no longer applies. */
.novixa-addons-dual-color-heading--layout-block .novixa-addons-dual-color-heading__part-one {
	margin-right: 0 !important;
}

.novixa-addons-dual-color-heading--layout-block .novixa-addons-dual-color-heading__part-two {
	display: block;
	margin-top: 4px;
}

.novixa-addons-text-editor__content {
	line-height: 1.75;
}

.novixa-addons-text-editor__content a {
	transition: color 0.2s ease;
}

.novixa-addons-drop-cap-yes .novixa-addons-text-editor__content::first-letter {
	float: left;
	font-size: 3.2em;
	line-height: 1;
	padding: 6px 8px 0 0;
	font-weight: 700;
}

/* ==================================== */
/* Icon Box                              */
/* ==================================== */
.novixa-addons-icon-box {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 18px;
	padding: 32px 26px;
	background: #fff;
	text-decoration: none;
	color: inherit;
	transition: transform 0.25s ease, box-shadow 0.25s ease, background-color 0.25s ease;
}

.novixa-addons-icon-box--lift-yes:hover .novixa-addons-icon-box {
	transform: translateY(-6px);
	box-shadow: 0 18px 40px rgba(20, 10, 50, 0.1);
}

.novixa-addons-icon-box--position-left,
.novixa-addons-icon-box--position-right {
	flex-direction: row;
	text-align: left;
	align-items: flex-start;
}

.novixa-addons-icon-box--position-right {
	flex-direction: row-reverse;
	text-align: right;
}

.novixa-addons-icon-box__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 68px;
	height: 68px;
	flex-shrink: 0;
	color: #7c5cff;
	background: rgba(124, 92, 255, 0.12);
	transition: transform 0.25s ease, color 0.25s ease, background-color 0.25s ease;
}

.novixa-addons-icon-box__icon-shape-circle .novixa-addons-icon-box__icon {
	border-radius: 50%;
}

.novixa-addons-icon-box__icon-shape-square .novixa-addons-icon-box__icon {
	border-radius: 16px;
}

.novixa-addons-icon-box__icon-shape-none .novixa-addons-icon-box__icon {
	width: auto;
	height: auto;
	background: none !important;
}

.novixa-addons-icon-box__icon i,
.novixa-addons-icon-box__icon svg {
	font-size: 26px;
	width: 26px;
	height: 26px;
	fill: currentColor;
}

.novixa-addons-icon-box__number {
	font-size: 26px;
	font-weight: 700;
	line-height: 1;
}

.novixa-addons-icon-box__content {
	display: flex;
	flex-direction: column;
}

.novixa-addons-icon-box__title {
	margin: 0 0 10px;
	font-size: 19px;
	font-weight: 700;
}

.novixa-addons-icon-box__description {
	margin: 0;
	font-size: 14px;
	line-height: 1.7;
	color: #6f6c7d;
}

/* "Reveal Description On Hover" — the description starts collapsed
   (0 height, hidden) and expands open on hover/focus, matching the
   service-card "Marketing / Content Writing / Web Design" pattern.
   max-height (not display:none) is used so the transition can
   animate, and a generous cap (200px) comfortably fits normal
   description lengths without clipping. */
.novixa-addons-icon-box--reveal-hover .novixa-addons-icon-box__description {
	max-height: 0;
	opacity: 0;
	overflow: hidden;
	transition: max-height 0.35s ease, opacity 0.35s ease, margin-top 0.35s ease;
}

.novixa-addons-icon-box--reveal-hover:hover .novixa-addons-icon-box__description,
.novixa-addons-icon-box--reveal-hover:focus-within .novixa-addons-icon-box__description {
	max-height: 200px;
	opacity: 1;
	margin-top: 8px;
}

/* ==================================== */
/* Diamond Icon Box                      */
/* Same layout system as Icon Box above, */
/* plus a rotated-outline "diamond" icon */
/* shape option.                         */
/* ==================================== */
.novixa-addons-diamond-icon-box {
	--novixa-lift-distance: -6px;
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 18px;
	padding: 32px 26px;
	background: #fff;
	box-sizing: border-box;
	text-decoration: none;
	color: inherit;
	transition: transform 0.25s ease, box-shadow 0.25s ease, background-color 0.25s ease, border-color 0.25s ease;
}

/* The "--lift-yes" class is added by Elementor to the widget's OUTER
   wrapper (not to this element), so the hover state has to be matched
   as a descendant selector — targeting the rule directly at
   ".novixa-addons-diamond-icon-box--lift-yes:hover" would move/shadow
   the invisible outer wrapper instead of the visible card. */
.novixa-addons-diamond-icon-box--lift-yes:hover .novixa-addons-diamond-icon-box {
	transform: translateY(var(--novixa-lift-distance, -6px));
	box-shadow: 0 18px 40px rgba(20, 10, 50, 0.1);
}

.novixa-addons-diamond-icon-box--position-left,
.novixa-addons-diamond-icon-box--position-right {
	flex-direction: row;
	text-align: left;
	align-items: flex-start;
}

.novixa-addons-diamond-icon-box--position-right {
	flex-direction: row-reverse;
	text-align: right;
}

.novixa-addons-diamond-icon-box__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 68px;
	height: 68px;
	flex-shrink: 0;
	color: #4f3ff0;
	background: rgba(79, 63, 240, 0.08);
	transition: transform 0.25s ease, color 0.25s ease, background-color 0.25s ease, border-color 0.25s ease;
}

.novixa-addons-diamond-icon-box__icon-shape-circle .novixa-addons-diamond-icon-box__icon {
	border-radius: 50%;
}

.novixa-addons-diamond-icon-box__icon-shape-square .novixa-addons-diamond-icon-box__icon {
	border-radius: 16px;
}

.novixa-addons-diamond-icon-box__icon-shape-none .novixa-addons-diamond-icon-box__icon {
	width: auto;
	height: auto;
	background: none !important;
}

/* Diamond = a square rotated 45°, outlined rather than filled; the
   icon/number inside is counter-rotated so it stays upright. */
.novixa-addons-diamond-icon-box__icon-shape-diamond .novixa-addons-diamond-icon-box__icon {
	background: transparent !important;
	border: 2px solid currentColor;
	border-radius: 8px;
	transform: rotate(45deg);
}

.novixa-addons-diamond-icon-box__icon-shape-diamond .novixa-addons-diamond-icon-box__icon i,
.novixa-addons-diamond-icon-box__icon-shape-diamond .novixa-addons-diamond-icon-box__icon svg,
.novixa-addons-diamond-icon-box__icon-shape-diamond .novixa-addons-diamond-icon-box__number {
	transform: rotate(-45deg);
}

.novixa-addons-diamond-icon-box__icon i,
.novixa-addons-diamond-icon-box__icon svg {
	font-size: 26px;
	width: 26px;
	height: 26px;
	fill: currentColor;
}

.novixa-addons-diamond-icon-box__number {
	font-size: 26px;
	font-weight: 700;
	line-height: 1;
}

.novixa-addons-diamond-icon-box__content {
	display: flex;
	flex-direction: column;
}

.novixa-addons-diamond-icon-box__title {
	position: relative;
	display: inline-block;
	margin: 0 0 10px;
	padding-bottom: 10px;
	font-size: 19px;
	font-weight: 700;
}

.novixa-addons-diamond-icon-box--underline-yes .novixa-addons-diamond-icon-box__title::after {
	content: '';
	position: absolute;
	left: 50%;
	bottom: 0;
	width: var(--novixa-underline-width, 32px);
	height: var(--novixa-underline-thickness, 2px);
	background: var(--novixa-underline-color, #4f3ff0);
	transform: translateX(-50%) scaleX(0);
	transition: transform 0.3s ease;
}

.novixa-addons-diamond-icon-box--underline-yes:hover .novixa-addons-diamond-icon-box__title::after {
	transform: translateX(-50%) scaleX(1);
}

.novixa-addons-diamond-icon-box__description {
	margin: 0;
	font-size: 14px;
	line-height: 1.7;
	color: #6f6c7d;
}

.novixa-addons-diamond-icon-box__button {
	display: inline-block;
	margin-top: 16px;
	padding: 10px 24px;
	border-radius: 4px;
	background-color: #4f3ff0;
	color: #fff;
	font-size: 14px;
	font-weight: 600;
	line-height: 1.4;
	text-decoration: none;
	border: 2px solid transparent;
	cursor: pointer;
	transition: color 0.25s ease, background-color 0.25s ease, border-color 0.25s ease;
}

/* ==================================== */
/* Image Box                             */
/* ==================================== */
.novixa-addons-image-box {
	display: flex;
	flex-direction: column;
	background: #fff;
	border-radius: 16px;
	overflow: hidden;
	transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.novixa-addons-image-box--lift-yes:hover .novixa-addons-image-box {
	transform: translateY(-6px);
	box-shadow: 0 18px 40px rgba(20, 10, 50, 0.1);
}

.novixa-addons-image-box--position-left,
.novixa-addons-image-box--position-right {
	flex-direction: row;
	align-items: center;
}

.novixa-addons-image-box--position-right {
	flex-direction: row-reverse;
}

.novixa-addons-image-box__media {
	display: block;
	overflow: hidden;
	line-height: 0;
	flex-shrink: 0;
}

.novixa-addons-image-box__media img {
	display: block;
	width: 100%;
	height: auto;
	transition: transform 0.4s ease, filter 0.4s ease;
}

.novixa-addons-image-box__hover-zoom:hover .novixa-addons-image-box__media img {
	transform: scale(1.06);
}

.novixa-addons-image-box__hover-grayscale .novixa-addons-image-box__media img {
	filter: grayscale(100%);
}

.novixa-addons-image-box__hover-grayscale:hover .novixa-addons-image-box__media img {
	filter: grayscale(0%);
}

.novixa-addons-image-box__content {
	padding: 22px 24px;
}

.novixa-addons-image-box__title {
	margin: 0 0 8px;
	font-size: 18px;
	font-weight: 700;
}

.novixa-addons-image-box__description {
	margin: 0;
	font-size: 14px;
	line-height: 1.7;
	color: #6f6c7d;
}


/* ---------------------------------- */
/* Button widget               */
/* Design credit: Uiverse.io by Randdose */
/* Everything else for this widget is written inline by PHP/JS on   */
/* purpose — see modules/button/class-widget-button.php             */
/* ---------------------------------- */
.novixa-addons-btn__wrap {
	text-align: left;
}

/* ==================================== */
/* Overlay Button                        */
/* Color/hover/chip-position CSS for this widget is printed inline   */
/* per-instance by modules/overlay-button/class-widget-overlay-button.php */
/* (scoped to a unique #id) so it never depends on this stylesheet   */
/* having reloaded after an update. Only non-critical baseline rules */
/* live here.                                                        */
/* ==================================== */
.novixa-addons-overlay-btn__wrap {
	text-align: left;
}

.novixa-addons-overlay-btn {
	font-weight: 600;
	line-height: 1.4;
}

.novixa-addons-overlay-btn__text {
	position: relative;
	z-index: 2;
}

.novixa-addons-overlay-btn__chip {
	position: absolute;
	z-index: 1;
	pointer-events: none;
}

/* ==================================== */
/* Icon Accordion                        */
/* Open/close is controlled directly by JavaScript setting each      */
/* item's `content.style.display` (see render() in                  */
/* class-widget-icon-accordion.php) — an inline style always wins    */
/* over any external stylesheet, so a theme's CSS can never leave    */
/* an item stuck open. This file only styles appearance/animation,   */
/* never the open/closed state itself.                                */
/* ==================================== */
.novixa-addons-icon-accordion__item {
	position: relative;
}

.novixa-addons-icon-accordion__header {
	display: block;
	cursor: pointer;
	outline: none;
}

.novixa-addons-icon-accordion__header-inner {
	display: flex;
	align-items: center;
	gap: 14px;
	transition: background-color 0.25s ease;
}

.novixa-addons-icon-accordion__icon {
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

.novixa-addons-icon-accordion__icon i,
.novixa-addons-icon-accordion__icon svg {
	line-height: 1;
}

.novixa-addons-icon-accordion__title {
	flex: 1 1 auto;
	margin: 0;
	font-weight: 700;
}

.novixa-addons-icon-accordion__expand {
	flex-shrink: 0;
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

.novixa-addons-icon-accordion__expand-open,
.novixa-addons-icon-accordion__expand-close {
	display: inline-flex;
}

.novixa-addons-icon-accordion__expand-close {
	display: none;
}

.novixa-addons-icon-accordion__item--open .novixa-addons-icon-accordion__expand-open {
	display: none;
}

.novixa-addons-icon-accordion__item--open .novixa-addons-icon-accordion__expand-close {
	display: inline-flex;
}

.novixa-addons-icon-accordion__content-inner > *:first-child {
	margin-top: 0;
}

.novixa-addons-icon-accordion__content-inner > *:last-child {
	margin-bottom: 0;
}

/* ==================================== */
/* Accordion (plain, no icon box)        */
/* Same JS-driven open/close approach as Icon Accordion — see the      */
/* render() note in class-widget-accordion.php.                        */
/* ==================================== */
.novixa-addons-accordion__item {
	position: relative;
}

.novixa-addons-accordion__header {
	display: block;
	cursor: pointer;
	outline: none;
}

.novixa-addons-accordion__header-inner {
	display: flex;
	align-items: center;
	gap: 12px;
}

.novixa-addons-accordion__title {
	flex: 1 1 auto;
	margin: 0;
	font-weight: 600;
}

.novixa-addons-accordion__expand {
	flex-shrink: 0;
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

.novixa-addons-accordion__expand-open,
.novixa-addons-accordion__expand-close {
	display: inline-flex;
}

.novixa-addons-accordion__expand-close {
	display: none;
}

.novixa-addons-accordion__item--open .novixa-addons-accordion__expand-open {
	display: none;
}

.novixa-addons-accordion__item--open .novixa-addons-accordion__expand-close {
	display: inline-flex;
}

.novixa-addons-accordion__content-inner > *:first-child {
	margin-top: 0;
}

.novixa-addons-accordion__content-inner > *:last-child {
	margin-bottom: 0;
}

/* ==================================== */
/* Tabs                                  */
/* Tab switching is handled by the shared document-level delegation   */
/* in assets/js/frontend.js — see the render() note in                */
/* class-widget-tabs.php.                                              */
/* ==================================== */
.novixa-addons-tabs {
	display: flex;
	flex-direction: column;
}

.novixa-addons-tabs__nav {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
}

.novixa-addons-tabs__nav-item {
	appearance: none;
	border: none;
	cursor: pointer;
	font: inherit;
	background-color: #f2f1fb;
	color: #4a4767;
	transition: background-color 0.2s ease, color 0.2s ease;
}

/* Fallback so the active tab is visually distinguishable even if
   Elementor's dynamic per-control CSS (Normal/Active colors from the
   Style tab) hasn't been generated/printed yet for some reason —
   mirrors the equivalent rule for the Nested Tabs widget below. */
.novixa-addons-tabs__nav-item--active {
	background-color: #4f3ff0;
	color: #ffffff;
}

.novixa-addons-tabs__panels {
	position: relative;
}

.novixa-addons-tabs__panel-inner > *:first-child {
	margin-top: 0;
}

.novixa-addons-tabs__panel-inner > *:last-child {
	margin-bottom: 0;
}

/* Direction: Bottom — nav row after the panels. */
.novixa-addons-tabs--direction-bottom .novixa-addons-tabs {
	flex-direction: column-reverse;
}

/* Direction: Start — nav column on the left of the panels. */
.novixa-addons-tabs--direction-start .novixa-addons-tabs {
	flex-direction: row;
	align-items: flex-start;
}

.novixa-addons-tabs--direction-start .novixa-addons-tabs__nav {
	flex-direction: column;
	flex-shrink: 0;
}

.novixa-addons-tabs--direction-start .novixa-addons-tabs__panels {
	flex: 1 1 auto;
}

/* Direction: End — nav column on the right of the panels. */
.novixa-addons-tabs--direction-end .novixa-addons-tabs {
	flex-direction: row-reverse;
	align-items: flex-start;
}

.novixa-addons-tabs--direction-end .novixa-addons-tabs__nav {
	flex-direction: column;
	flex-shrink: 0;
}

.novixa-addons-tabs--direction-end .novixa-addons-tabs__panels {
	flex: 1 1 auto;
}

/* ==================================== */
/* Nested Tabs (Experimental)            */
/* Shares the exact same nav/panel class names and JS delegation as   */
/* the plain Tabs widget (see class-widget-nested-tabs.php) — only    */
/* the PHP rendering differs (real containers instead of WYSIWYG      */
/* text per panel).                                                    */
/* ==================================== */
.novixa-addons-nested-tabs {
	display: flex;
	flex-direction: column;
}

.novixa-addons-nested-tabs__nav {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	gap: 6px;
}

.novixa-addons-nested-tabs__nav-item {
	appearance: none;
	border: none;
	cursor: pointer;
	font: inherit;
	padding: 14px 24px;
	background-color: #f2f1fb;
	color: #4a4767;
	border-radius: 6px;
	transition: background-color 0.2s ease, color 0.2s ease;
}

.novixa-addons-nested-tabs__nav-item--active {
	background-color: #4f3ff0;
	color: #ffffff;
}

.novixa-addons-nested-tabs__panels {
	position: relative;
	background: #ffffff;
}

/* Direction: Bottom — nav row after the panels. */
.novixa-addons-nested-tabs--direction-bottom .novixa-addons-nested-tabs {
	flex-direction: column-reverse;
}

/* Direction: Start — nav column on the left of the panels. */
.novixa-addons-nested-tabs--direction-start .novixa-addons-nested-tabs {
	flex-direction: row;
	align-items: flex-start;
}

.novixa-addons-nested-tabs--direction-start .novixa-addons-nested-tabs__nav {
	flex-direction: column;
	flex-shrink: 0;
}

.novixa-addons-nested-tabs--direction-start .novixa-addons-nested-tabs__panels {
	flex: 1 1 auto;
}

/* Direction: End — nav column on the right of the panels. */
.novixa-addons-nested-tabs--direction-end .novixa-addons-nested-tabs {
	flex-direction: row-reverse;
	align-items: flex-start;
}

.novixa-addons-nested-tabs--direction-end .novixa-addons-nested-tabs__nav {
	flex-direction: column;
	flex-shrink: 0;
}

.novixa-addons-nested-tabs--direction-end .novixa-addons-nested-tabs__panels {
	flex: 1 1 auto;
}

/* ==================================== */
/* Gradient Text Effect                  */
/* ==================================== */
.novixa-addons-gradient-text.novixa-addons-gradient-text {
	margin: 0;
	padding: 0;
}

.novixa-addons-gradient-text {
	margin: 0;
	line-height: 1.3;
}

.novixa-addons-gradient-text__gradient {
	--novixa-gradient-c1: #4f3ff0;
	--novixa-gradient-c2: #b026ff;
	--novixa-gradient-angle: 90deg;
	background-image: linear-gradient(var(--novixa-gradient-angle), var(--novixa-gradient-c1), var(--novixa-gradient-c2));
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: transparent;
	display: inline;
}

/* ==================================== */
/* Image Caption Card — Premium/Luxury   */
/* ==================================== */
.novixa-addons-image-caption-card {
	display: block;
	text-decoration: none;
	color: inherit;
}

.novixa-addons-image-caption-card__media {
	position: relative;
	width: 100%;
	height: 460px;
	overflow: hidden;
	border-radius: 18px;
	box-shadow: 0 20px 45px rgba(20, 16, 8, 0.22), 0 2px 8px rgba(20, 16, 8, 0.12);
	transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

.novixa-addons-image-caption-card:hover .novixa-addons-image-caption-card__media {
	transform: translateY(-6px);
	box-shadow: 0 30px 60px rgba(20, 16, 8, 0.3), 0 6px 16px rgba(20, 16, 8, 0.16);
}

.novixa-addons-image-caption-card__media img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1), filter 0.5s ease;
}

/* "Hover Animation" control - exactly one of these applies at a time,
   picked via the novixa-addons-image-caption-card__anim-* prefix class
   on the widget root. "Zoom In" is the default, matching the original
   always-on behaviour, so existing cards look the same until changed. */
.novixa-addons-image-caption-card__anim-zoom-in:hover .novixa-addons-image-caption-card__media img {
	transform: scale(1.06);
}

.novixa-addons-image-caption-card__anim-zoom-out .novixa-addons-image-caption-card__media img {
	transform: scale(1.08);
}

.novixa-addons-image-caption-card__anim-zoom-out:hover .novixa-addons-image-caption-card__media img {
	transform: scale(1);
}

.novixa-addons-image-caption-card__anim-pan:hover .novixa-addons-image-caption-card__media img {
	transform: scale(1.1) translateX(-3%);
}

.novixa-addons-image-caption-card__anim-grayscale .novixa-addons-image-caption-card__media img {
	filter: grayscale(1);
}

.novixa-addons-image-caption-card__anim-grayscale:hover .novixa-addons-image-caption-card__media img {
	filter: grayscale(0);
	transform: scale(1.04);
}

.novixa-addons-image-caption-card__anim-blur .novixa-addons-image-caption-card__media img {
	filter: blur(6px);
}

.novixa-addons-image-caption-card__anim-blur:hover .novixa-addons-image-caption-card__media img {
	filter: blur(0);
	transform: scale(1.04);
}

/* "None" needs no rule - the base .media img above already has no
   hover transform unless one of the classes above adds it. */

.novixa-addons-image-caption-card__overlay {
	--novixa-overlay-color: rgba(12, 10, 8, 0.65);
	--novixa-overlay-height: 62%;
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: var(--novixa-overlay-height);
	background: linear-gradient(to top, var(--novixa-overlay-color), transparent);
	pointer-events: none;
}

.novixa-addons-image-caption-card__content {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	padding: 34px 30px;
	z-index: 1;
}

.novixa-addons-image-caption-card__caption {
	display: inline-block;
	max-width: 100%;
	margin: 0;
	font-weight: 600;
	font-size: 28px;
	letter-spacing: 0.3px;
	color: #ffffff;
	text-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
	position: relative;
	padding-top: 16px;
}

.novixa-addons-image-caption-card__caption::before {
	content: '';
	position: absolute;
	top: 0;
	left: 0;
	width: 42px;
	height: 2px;
	background: linear-gradient(90deg, #d9b877, #f3e3b8);
}

/* CTA description + button — only present when "Show Description" /
   "Show Button" are switched on, otherwise the card stays a plain
   image + caption as before. */
.novixa-addons-image-caption-card__description.novixa-addons-image-caption-card__description {
	margin: 10px 0 0;
}

.novixa-addons-image-caption-card__description {
	display: inline-block;
	color: rgba(255, 255, 255, 0.82);
	font-size: 14.5px;
	line-height: 1.7;
	letter-spacing: 0.15px;
	max-width: 34ch;
}

.novixa-addons-image-caption-card__button {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	margin-top: 22px;
	padding: 13px 26px;
	border-radius: 999px;
	background-color: transparent;
	border: 1px solid rgba(217, 184, 119, 0.75);
	color: #f3e3b8;
	font-weight: 600;
	font-size: 13px;
	letter-spacing: 0.6px;
	text-transform: uppercase;
	text-decoration: none;
	line-height: 1.4;
	backdrop-filter: blur(2px);
	transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease, transform 0.3s ease;
}

.novixa-addons-image-caption-card__button i,
.novixa-addons-image-caption-card__button svg {
	width: 0.9em;
	height: 0.9em;
	flex-shrink: 0;
	transition: transform 0.3s ease;
}

.novixa-addons-image-caption-card:hover .novixa-addons-image-caption-card__button {
	background: linear-gradient(90deg, #d9b877, #f3e3b8);
	border-color: transparent;
	color: #1a1608;
}

.novixa-addons-image-caption-card:hover .novixa-addons-image-caption-card__button i,
.novixa-addons-image-caption-card:hover .novixa-addons-image-caption-card__button svg {
	transform: translateX(3px);
}

.novixa-addons-image-caption-card__accent {
	height: 4px;
	width: 108%;
	max-width: 100vw;
	margin: 0 auto;
	background-color: #c9a86a;
}

/* Caption Position modifiers — prefix_class lands on the OUTER
   Elementor wrapper, so these are written as descendant selectors
   (ancestor with the modifier class > our own .content element). */
.novixa-addons-image-caption-card__position-top-left .novixa-addons-image-caption-card__content {
	top: 0;
	bottom: auto;
}

.novixa-addons-image-caption-card__position-top-left .novixa-addons-image-caption-card__overlay {
	top: 0;
	bottom: auto;
	background: linear-gradient(to bottom, var(--novixa-overlay-color), transparent);
}

.novixa-addons-image-caption-card__position-center .novixa-addons-image-caption-card__content {
	top: 0;
	bottom: 0;
	display: flex;
	flex-direction: column;
	justify-content: center;
}

.novixa-addons-image-caption-card__position-center .novixa-addons-image-caption-card__overlay {
	top: 0;
	height: 100%;
	background: var(--novixa-overlay-color);
}

/* ==================================== */
/* Content Reveal on Hover                */
/* Background-image box: title sits low, */
/* text/buttons/badge are collapsed until */
/* the box is hovered, then everything    */
/* fades & slides into view together with */
/* a darkening overlay scrim.             */
/* ==================================== */
.novixa-addons-content-reveal-hover {
	position: relative;
	display: block;
	width: 100%;
	height: 420px;
	overflow: hidden;
	isolation: isolate;
}

.novixa-addons-content-reveal-hover__media {
	position: absolute;
	inset: 0;
	z-index: 0;
}

.novixa-addons-content-reveal-hover__media img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center center;
}

.novixa-addons-content-reveal-hover__overlay {
	position: absolute;
	inset: 0;
	z-index: 1;
	opacity: 0.55;
	background: linear-gradient(0deg, rgba(10, 10, 30, 0.9) 0%, transparent 65%);
	transition: opacity var(--novixa-crh-overlay-transition, 0.35s) ease;
	pointer-events: none;
}

.novixa-addons-content-reveal-hover:hover .novixa-addons-content-reveal-hover__overlay,
.novixa-addons-content-reveal-hover:focus-within .novixa-addons-content-reveal-hover__overlay {
	opacity: 1;
}

.novixa-addons-content-reveal-hover__badge {
	position: absolute;
	top: 16px;
	right: 16px;
	z-index: 3;
	padding: 4px 12px;
	border-radius: 999px;
	background: #ffffff;
	color: #1a1a2e;
	font-size: 12px;
	font-weight: 700;
	line-height: 1.6;
}

.novixa-addons-content-reveal-hover__content {
	position: absolute;
	inset: 0;
	z-index: 2;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	align-items: flex-start;
	text-align: left;
	padding: 28px;
}

.novixa-addons-content-reveal-hover__icon {
	margin: 0 0 12px;
	font-size: 28px;
	color: #ffffff;
	line-height: 1;
}

.novixa-addons-content-reveal-hover__icon i,
.novixa-addons-content-reveal-hover__icon svg {
	width: 1em;
	height: 1em;
}

.novixa-addons-content-reveal-hover__title.novixa-addons-content-reveal-hover__title {
	margin: 0;
	padding: 0;
}

.novixa-addons-content-reveal-hover__title {
	color: #ffffff;
	font-size: 24px;
	font-weight: 700;
	line-height: 1.3;
	transition: transform var(--novixa-crh-transition, 0.35s) ease;
}

/* The description and buttons stay collapsed until the box is
   hovered/focused, then expand together as a single smooth block —
   the core "reveal on hover" behaviour this widget is named for.
   Uses the CSS Grid "0fr -> 1fr" trick (not max-height) so the
   animation is always smooth regardless of how tall the actual
   content is — animating max-height to a fixed cap makes short
   content "snap" open instead of gliding. */
.novixa-addons-content-reveal-hover__reveal-group {
	display: grid;
	grid-template-rows: 0fr;
	transition: grid-template-rows var(--novixa-crh-transition, 0.35s) ease;
}

.novixa-addons-content-reveal-hover__reveal-group-inner {
	min-height: 0;
	overflow: hidden;
	opacity: 0;
	transform: translateY(6px);
	transition: opacity var(--novixa-crh-transition, 0.35s) ease,
		transform var(--novixa-crh-transition, 0.35s) ease;
}

.novixa-addons-content-reveal-hover:hover .novixa-addons-content-reveal-hover__reveal-group,
.novixa-addons-content-reveal-hover:focus-within .novixa-addons-content-reveal-hover__reveal-group {
	grid-template-rows: 1fr;
}

.novixa-addons-content-reveal-hover:hover .novixa-addons-content-reveal-hover__reveal-group-inner,
.novixa-addons-content-reveal-hover:focus-within .novixa-addons-content-reveal-hover__reveal-group-inner {
	opacity: 1;
	transform: translateY(0);
}

.novixa-addons-content-reveal-hover__text {
	margin: 0;
	color: rgba(255, 255, 255, 0.85);
	font-size: 14px;
	line-height: 1.7;
}

.novixa-addons-content-reveal-hover__buttons {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 12px;
	margin-top: 16px;
}

.novixa-addons-content-reveal-hover__button {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 10px 20px;
	border-radius: 6px;
	background-color: #ffffff;
	color: #1a1a2e;
	font-weight: 600;
	font-size: 14px;
	text-decoration: none;
	line-height: 1.4;
	white-space: nowrap;
	transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.novixa-addons-content-reveal-hover__button svg,
.novixa-addons-content-reveal-hover__button i {
	flex-shrink: 0;
	width: 1em;
	height: 1em;
}

.novixa-addons-content-reveal-hover__button--secondary {
	background-color: transparent;
	color: #ffffff;
	border: 1px solid rgba(255, 255, 255, 0.6);
}

/* ==================================== */
/* Counter — Premium/Luxury              */
/* ==================================== */
.novixa-addons-counter {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 18px;
	padding: 42px 30px;
	transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}

.novixa-addons-counter__content {
	display: flex;
	flex-direction: column;
	align-items: center;
	min-width: 0;
}

.novixa-addons-counter:hover {
	box-shadow: none;
}

.novixa-addons-counter__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	width: 64px;
	height: 64px;
	border-radius: 50%;
	background: linear-gradient(150deg, #d9b877, #f3e3b8);
	color: #1a1608;
	box-shadow: 0 10px 22px rgba(217, 184, 119, 0.35);
}

.novixa-addons-counter__icon i,
.novixa-addons-counter__icon svg {
	font-size: 26px;
	width: 26px;
	height: 26px;
}

.novixa-addons-counter__number-wrap {
	display: inline-flex;
	align-items: baseline;
	gap: 2px;
	margin-bottom: 8px;
	font-weight: 700;
	font-size: 46px;
	line-height: 1.1;
	color: #1a1a2e;
	font-variant-numeric: tabular-nums;
}

.novixa-addons-counter__prefix,
.novixa-addons-counter__suffix {
	font-weight: 600;
	font-size: 0.55em;
	color: #d9b877;
}

.novixa-addons-counter__title {
	font-weight: 500;
	font-size: 14px;
	letter-spacing: 0.4px;
	text-transform: uppercase;
	color: #6a6a7a;
}

/* ==================================== */
/* Liquid Counter — Premium/Luxury       */
/* ==================================== */
.novixa-addons-liquid-counter {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 18px;
}

.novixa-addons-liquid-counter__circle {
	position: relative;
	width: 140px;
	height: 140px;
	flex-shrink: 0;
	border-radius: 50%;
	overflow: hidden;
	background-color: #faf7f0;
	border: 2px solid #e8d4a0;
	box-sizing: border-box;
	display: flex;
	align-items: center;
	justify-content: center;
}

.novixa-addons-liquid-counter__wave-wrap {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 0%;
	overflow: hidden;
	transition: height 1.4s cubic-bezier(0.22, 1, 0.36, 1);
}

.novixa-addons-liquid-counter__wave {
	position: absolute;
	left: -25%;
	bottom: -60%;
	width: 250%;
	height: 220%;
	border-radius: 45%;
	background-color: #d9b877;
	will-change: transform;
	animation-name: novixa-liquid-counter-rotate;
	animation-timing-function: linear;
	animation-iteration-count: infinite;
}

.novixa-addons-liquid-counter__wave--1 {
	opacity: 0.9;
	animation-duration: 7s;
}

.novixa-addons-liquid-counter__wave--2 {
	opacity: 0.55;
	background-color: #c9a15f;
	animation-duration: 11s;
	animation-direction: reverse;
}

@keyframes novixa-liquid-counter-rotate {
	from {
		transform: rotate(0deg);
	}
	to {
		transform: rotate(360deg);
	}
}

@media ( prefers-reduced-motion: reduce ) {
	.novixa-addons-liquid-counter__wave-wrap {
		transition: none;
	}

	.novixa-addons-liquid-counter__wave {
		animation: none;
	}
}

.novixa-addons-liquid-counter__number-wrap {
	position: relative;
	z-index: 1;
	display: inline-flex;
	align-items: baseline;
	gap: 1px;
	font-variant-numeric: tabular-nums;
}

.novixa-addons-liquid-counter__number {
	font-weight: 700;
	font-size: 26px;
	color: #1a1a2e;
}

.novixa-addons-liquid-counter__prefix,
.novixa-addons-liquid-counter__suffix {
	font-weight: 600;
	font-size: 0.6em;
	color: #1a1a2e;
}

.novixa-addons-liquid-counter__description {
	font-size: 14px;
	line-height: 1.5;
	color: #6a6a7a;
	max-width: 22ch;
}

/* ==================================== */
/* List Marquee                          */
/* ==================================== */
.novixa-addons-list-marquee {
	position: relative;
	width: 100%;
	overflow: hidden;
	background-color: #4640de;
	/* Fade the very edges so items don't appear to "cut off" abruptly
	   as they enter/exit — a soft mask reads as more polished than a
	   hard clip. */
	-webkit-mask-image: linear-gradient(90deg, transparent 0, #000 4%, #000 96%, transparent 100%);
	mask-image: linear-gradient(90deg, transparent 0, #000 4%, #000 96%, transparent 100%);
}

.novixa-addons-list-marquee__track {
	display: flex;
	width: max-content;
	animation-name: novixa-list-marquee-scroll;
	animation-duration: var(--novixa-marquee-duration, 25s);
	animation-timing-function: linear;
	animation-iteration-count: infinite;
}

.novixa-addons-list-marquee--reverse .novixa-addons-list-marquee__track {
	animation-direction: reverse;
}

.novixa-addons-list-marquee--pause-on-hover:hover .novixa-addons-list-marquee__track {
	animation-play-state: paused;
}

@keyframes novixa-list-marquee-scroll {
	from {
		transform: translateX(0);
	}
	to {
		/* The track holds two identical copies of the item list back
		   to back (see render_group() in the widget class), so
		   sliding exactly half the track's width is what makes the
		   loop seamless — the instant copy #1 scrolls fully out,
		   copy #2 is sitting exactly where copy #1 started. */
		transform: translateX(-50%);
	}
}

@media ( prefers-reduced-motion: reduce ) {
	.novixa-addons-list-marquee__track {
		animation: none;
	}
}

.novixa-addons-list-marquee__group {
	display: flex;
	align-items: center;
	flex-shrink: 0;
	gap: 28px;
	/* Matches `gap` on purpose: this is what makes copy #2's own
	   starting position land exactly at -50% of the doubled track's
	   width (see the @keyframes comment below) — if this were
	   different from `gap`, the two groups wouldn't be the same total
	   width and the loop would visibly "jump" once per cycle. Both
	   values are driven from the same "Gap Between Items" control for
	   exactly this reason — see register_item_style_controls(). */
	padding-right: 28px;
}

.novixa-addons-list-marquee__item {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	white-space: nowrap;
	color: #ffffff;
	font-weight: 500;
	font-size: 15px;
	text-decoration: none;
}

a.novixa-addons-list-marquee__item:hover {
	text-decoration: underline;
}

.novixa-addons-list-marquee__icon {
	display: inline-flex;
	align-items: center;
	color: #d9b877;
	font-size: 14px;
}

.novixa-addons-list-marquee__icon i,
.novixa-addons-list-marquee__icon svg {
	width: 1em;
	height: 1em;
}

.novixa-addons-list-marquee__separator {
	color: rgba(255, 255, 255, 0.6);
	flex-shrink: 0;
}

/* ==================================== */
/* Logo Marquee                          */
/* ==================================== */
.novixa-addons-logo-marquee {
	position: relative;
	width: 100%;
	overflow: hidden;
	background-color: #f5a623;
}

.novixa-addons-logo-marquee--edge-fade {
	/* Softly fades the left/right edges so cards don't appear to
	   "cut off" abruptly as they enter/exit. Opt-in via the "Edge
	   Fade" style control — off by default for a clean hard edge. */
	-webkit-mask-image: linear-gradient(90deg, transparent 0, #000 4%, #000 96%, transparent 100%);
	mask-image: linear-gradient(90deg, transparent 0, #000 4%, #000 96%, transparent 100%);
}

.novixa-addons-logo-marquee__track {
	display: flex;
	width: max-content;
	animation-name: novixa-logo-marquee-scroll;
	animation-duration: var(--novixa-marquee-duration, 30s);
	animation-timing-function: linear;
	animation-iteration-count: infinite;
}

.novixa-addons-logo-marquee--reverse .novixa-addons-logo-marquee__track {
	animation-direction: reverse;
}

.novixa-addons-logo-marquee--pause-on-hover:hover .novixa-addons-logo-marquee__track {
	animation-play-state: paused;
}

@keyframes novixa-logo-marquee-scroll {
	from {
		transform: translateX(0);
	}
	to {
		/* The track holds two identical copies of the card list back
		   to back (see render_group() in the widget class), so
		   sliding exactly half the track's width is what makes the
		   loop seamless — the instant copy #1 scrolls fully out,
		   copy #2 is sitting exactly where copy #1 started. */
		transform: translateX(-50%);
	}
}

@media ( prefers-reduced-motion: reduce ) {
	.novixa-addons-logo-marquee__track {
		animation: none;
	}
}

/* --- Vertical orientation ---
   Same seamless double-copy trick as the default horizontal mode,
   just rotated onto the Y axis: the track stacks into a column,
   sizes to its own content height (instead of width), and slides
   translateY(0 -> -50%) instead of translateX. A fixed viewport
   height (the "Track Height" control) plus overflow: hidden on the
   outer wrapper is what turns that into a scrolling window. */
.novixa-addons-logo-marquee--vertical .novixa-addons-logo-marquee__track {
	flex-direction: column;
	width: 100%;
	height: max-content;
	animation-name: novixa-logo-marquee-scroll-vertical;
}

@keyframes novixa-logo-marquee-scroll-vertical {
	from {
		transform: translateY(0);
	}
	to {
		transform: translateY(-50%);
	}
}

.novixa-addons-logo-marquee--vertical .novixa-addons-logo-marquee__group {
	flex-direction: column;
	width: 100%;
}

.novixa-addons-logo-marquee--vertical.novixa-addons-logo-marquee--edge-fade {
	-webkit-mask-image: linear-gradient(180deg, transparent 0, #000 4%, #000 96%, transparent 100%);
	mask-image: linear-gradient(180deg, transparent 0, #000 4%, #000 96%, transparent 100%);
}

.novixa-addons-logo-marquee__group {
	display: flex;
	align-items: stretch;
	flex-shrink: 0;
	gap: 20px;
	/* Matches `gap` on purpose — same reasoning as List Marquee's
	   `__group`: both copies of the track need to be the exact same
	   total width (trailing space included) for the -50% loop above
	   to stay seamless. Driven by the "Gap Between Cards" control. */
	padding-right: 20px;
}

.novixa-addons-logo-marquee__item {
	display: flex;
	flex-direction: column;
	align-items: center;
	flex-shrink: 0;
	gap: 10px;
}

.novixa-addons-logo-marquee__card {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 200px;
	height: 140px;
	background-color: #ffffff;
	border-radius: 16px;
	padding: 20px;
	box-sizing: border-box;
	text-decoration: none;
	transition: transform 0.25s ease;
}

a.novixa-addons-logo-marquee__card:hover {
	transform: translateY(-4px);
}

.novixa-addons-logo-marquee__logo {
	max-width: 80%;
	max-height: 70px;
	width: auto;
	height: auto;
	object-fit: contain;
	transition: filter 0.25s ease, opacity 0.25s ease;
}

.novixa-addons-logo-marquee--grayscale-hover .novixa-addons-logo-marquee__logo {
	filter: grayscale(100%);
	opacity: 0.7;
}

.novixa-addons-logo-marquee--grayscale-hover .novixa-addons-logo-marquee__card:hover .novixa-addons-logo-marquee__logo {
	filter: grayscale(0%);
	opacity: 1;
}

.novixa-addons-logo-marquee__caption {
	font-size: 13px;
	font-weight: 500;
	color: #4a4a4a;
	text-align: center;
}

/* ==================================== */
/* Images Marquee                        */
/* ==================================== */
.novixa-addons-images-marquee {
	position: relative;
	width: 100%;
	overflow: hidden;
}

.novixa-addons-images-marquee--edge-fade {
	/* Softly fades the leading/trailing edges so images don't appear
	   to "cut off" abruptly as they enter/exit. Opt-in via the "Edge
	   Fade" style control — off by default for a clean hard edge. */
	-webkit-mask-image: linear-gradient(90deg, transparent 0, #000 4%, #000 96%, transparent 100%);
	mask-image: linear-gradient(90deg, transparent 0, #000 4%, #000 96%, transparent 100%);
}

.novixa-addons-images-marquee--vertical.novixa-addons-images-marquee--edge-fade {
	-webkit-mask-image: linear-gradient(180deg, transparent 0, #000 4%, #000 96%, transparent 100%);
	mask-image: linear-gradient(180deg, transparent 0, #000 4%, #000 96%, transparent 100%);
}

.novixa-addons-images-marquee__track {
	display: flex;
	width: max-content;
	animation-name: novixa-images-marquee-scroll;
	animation-duration: var(--novixa-marquee-duration, 35s);
	animation-timing-function: linear;
	animation-iteration-count: infinite;
}

.novixa-addons-images-marquee--reverse .novixa-addons-images-marquee__track {
	animation-direction: reverse;
}

.novixa-addons-images-marquee--pause-on-hover:hover .novixa-addons-images-marquee__track {
	animation-play-state: paused;
}

@keyframes novixa-images-marquee-scroll {
	from {
		transform: translateX(0);
	}
	to {
		/* The track holds two identical copies of the image list back
		   to back (see render_group() in the widget class), so
		   sliding exactly half the track's width is what makes the
		   loop seamless — the instant copy #1 scrolls fully out,
		   copy #2 is sitting exactly where copy #1 started. */
		transform: translateX(-50%);
	}
}

@media ( prefers-reduced-motion: reduce ) {
	.novixa-addons-images-marquee__track {
		animation: none;
	}
}

/* --- Vertical orientation ---
   Same seamless double-copy trick as the default horizontal mode,
   just rotated onto the Y axis: the track stacks into a column,
   sizes to its own content height (instead of width), and slides
   translateY(0 -> -50%) instead of translateX. A fixed viewport
   height (the "Track Height" control) plus overflow: hidden on the
   outer wrapper is what turns that into a scrolling window. */
.novixa-addons-images-marquee--vertical .novixa-addons-images-marquee__track {
	flex-direction: column;
	width: 100%;
	height: max-content;
	animation-name: novixa-images-marquee-scroll-vertical;
}

@keyframes novixa-images-marquee-scroll-vertical {
	from {
		transform: translateY(0);
	}
	to {
		transform: translateY(-50%);
	}
}

.novixa-addons-images-marquee--vertical .novixa-addons-images-marquee__group {
	flex-direction: column;
	width: 100%;
}

.novixa-addons-images-marquee__group {
	display: flex;
	align-items: stretch;
	flex-shrink: 0;
	gap: 16px;
	/* Matches `gap` on purpose — same reasoning as the other marquee
	   widgets: both copies of the track need to be the exact same
	   total size (trailing space included) for the -50% loop above
	   to stay seamless. Driven by the "Gap Between Images" control. */
	padding-right: 16px;
}

.novixa-addons-images-marquee__item {
	display: flex;
	flex-direction: column;
	align-items: center;
	flex-shrink: 0;
	gap: 8px;
}

.novixa-addons-images-marquee__frame {
	display: block;
	width: 260px;
	height: 180px;
	border-radius: 12px;
	overflow: hidden;
	text-decoration: none;
}

.novixa-addons-images-marquee__frame img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: filter 0.25s ease, opacity 0.25s ease, transform 0.35s ease;
}

a.novixa-addons-images-marquee__frame:hover img {
	transform: scale(1.05);
}

.novixa-addons-images-marquee--grayscale-hover .novixa-addons-images-marquee__frame img {
	filter: grayscale(100%);
	opacity: 0.8;
}

.novixa-addons-images-marquee--grayscale-hover .novixa-addons-images-marquee__frame:hover img {
	filter: grayscale(0%);
	opacity: 1;
}

.novixa-addons-images-marquee__caption {
	font-size: 13px;
	font-weight: 500;
	color: #4a4a4a;
	text-align: center;
}

/* ==================================== */
/* Feature Card                          */
/* ==================================== */
.novixa-addons-feature-card {
	position: relative;
	overflow: visible;
	background-color: #141414;
	border-radius: 22px;
	padding: 32px;
	box-sizing: border-box;
	box-shadow: 0 20px 40px rgba(0, 0, 0, 0.18);
	text-align: left;
}

.novixa-addons-feature-card__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 56px;
	height: 56px;
	margin-bottom: 22px;
	background-color: #f4511e;
	border-radius: 16px;
	flex-shrink: 0;
}

.novixa-addons-feature-card__icon i,
.novixa-addons-feature-card__icon svg {
	font-size: 24px;
	width: 24px;
	height: 24px;
	color: #ffffff;
}

.novixa-addons-feature-card__body {
	display: block;
}

.novixa-addons-feature-card__title {
	margin: 0 0 14px;
	color: #ffffff;
	font-size: 22px;
	font-weight: 700;
	line-height: 1.3;
}

.novixa-addons-feature-card__description {
	margin: 0;
	color: #c7c7c7;
	font-size: 15px;
	line-height: 1.6;
}

.novixa-addons-feature-card__button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	margin-top: 24px;
	padding: 12px 24px;
	background-color: #f4511e;
	color: #141414;
	border-radius: 50px;
	font-size: 15px;
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
	box-sizing: border-box;
	transition: background-color 0.25s ease, color 0.25s ease, transform 0.25s ease;
}

a.novixa-addons-feature-card__button:hover {
	transform: translateY(-2px);
}

.novixa-addons-feature-card__button i,
.novixa-addons-feature-card__button svg {
	font-size: 1em;
	width: 1em;
	height: 1em;
}

/* --- Overlap Bottom-Right Corner mode ---
   The button leaves normal document flow and is pinned to the
   bottom-right corner of the card, inset by the "Right Offset" /
   "Bottom Offset" style controls so it stays fully inside the
   card's boundary - never spilling past the edge. */
.novixa-addons-feature-card--overlap-button .novixa-addons-feature-card__button {
	position: absolute;
	right: 0;
	bottom: 0;
	margin-top: 0;
	z-index: 1;
}


/* ==========================================================================
   Before / After (image comparison slider)
   ==========================================================================
   Both images are painted at the FULL frame size (position:absolute;
   inset:0) - the "before" layer is only visually restricted to part
   of the frame via clip-path on its own wrapper, not by shrinking its
   width. That keeps both images cropped/scaled identically regardless
   of where the handle sits, which is what makes a naive
   width-percentage approach look wrong (the narrower layer would
   otherwise appear zoomed in relative to the other one). */

.novixa-addons-before-after {
	--novixa-ba-line-size: 3px;
	--novixa-ba-label-offset: 16px;
	--novixa-ba-before-label-opacity: 1;
	--novixa-ba-after-label-opacity: 1;
	position: relative;
}

/* Registering the custom property lets the browser smoothly animate
   it like any normal numeric property, so a plain CSS transition can
   ease the handle into position on a click-to-jump (and, as a nice
   side effect, adds a small touch of premium "weight" to every drag
   update too). Browsers without @property support simply skip the
   transition and jump straight there - fully functional either way. */
@property --novixa-ba-pos {
	syntax: '<percentage>';
	inherits: true;
	initial-value: 50%;
}

.novixa-addons-before-after__frame {
	position: relative;
	overflow: hidden;
	width: 100%;
	height: 400px;
	user-select: none;
	-webkit-user-select: none;
	touch-action: none;
	transition: --novixa-ba-pos 0.12s cubic-bezier( 0.22, 1, 0.36, 1 );
}

.novixa-addons-before-after__layer {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
}

.novixa-addons-before-after__layer img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	pointer-events: none;
	-webkit-user-drag: none;
}

.novixa-addons-before-after__layer--before {
	clip-path: inset( 0 calc( 100% - var( --novixa-ba-pos, 50% ) ) 0 0 );
	will-change: clip-path;
}

.novixa-addons-before-after--vertical .novixa-addons-before-after__layer--before {
	clip-path: inset( 0 0 calc( 100% - var( --novixa-ba-pos, 50% ) ) 0 );
}

/* --- Handle --- */
.novixa-addons-before-after__handle {
	position: absolute;
	top: 0;
	left: var( --novixa-ba-pos, 50% );
	height: 100%;
	width: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	transform: translateX( -50% );
	cursor: ew-resize;
	z-index: 2;
	outline: none;
}

.novixa-addons-before-after--vertical .novixa-addons-before-after__handle {
	top: var( --novixa-ba-pos, 50% );
	left: 0;
	width: 100%;
	height: 0;
	transform: translateY( -50% );
	cursor: ns-resize;
}

.novixa-addons-before-after__handle-line {
	position: absolute;
	top: 0;
	left: 50%;
	width: var( --novixa-ba-line-size );
	height: 100%;
	background-color: #ffffff;
	transform: translateX( -50% );
	box-shadow: 0 0 6px rgba( 0, 0, 0, 0.35 );
	pointer-events: none;
}

.novixa-addons-before-after--vertical .novixa-addons-before-after__handle-line {
	top: 50%;
	left: 0;
	width: 100%;
	height: var( --novixa-ba-line-size );
	transform: translateY( -50% );
}

.novixa-addons-before-after__handle-circle {
	position: relative;
	width: 48px;
	height: 48px;
	border-radius: 50%;
	background-color: #ffffff;
	color: #141414;
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow: 0 4px 14px rgba( 0, 0, 0, 0.3 );
	flex-shrink: 0;
	transition: transform 0.2s ease, box-shadow 0.2s ease;
	animation: novixaBaPulse 2.4s ease-in-out infinite;
}

.novixa-addons-before-after__handle:hover .novixa-addons-before-after__handle-circle,
.novixa-addons-before-after__handle:focus-visible .novixa-addons-before-after__handle-circle,
.novixa-addons-before-after__handle:active .novixa-addons-before-after__handle-circle {
	animation-play-state: paused;
	transform: scale( 1.08 );
	box-shadow: 0 6px 20px rgba( 0, 0, 0, 0.35 );
}

@keyframes novixaBaPulse {
	0%,
	100% {
		box-shadow: 0 4px 14px rgba( 0, 0, 0, 0.3 ), 0 0 0 0 rgba( 255, 255, 255, 0.35 );
	}
	50% {
		box-shadow: 0 4px 14px rgba( 0, 0, 0, 0.3 ), 0 0 0 10px rgba( 255, 255, 255, 0 );
	}
}

@media ( prefers-reduced-motion: reduce ) {
	.novixa-addons-before-after__handle-circle {
		animation: none;
	}
}

.novixa-addons-before-after--vertical .novixa-addons-before-after__handle-circle svg {
	transform: rotate( 90deg );
}

/* --- Labels ---
   Pinned to fixed corners regardless of handle position, which is
   the simplest and most common approach for these sliders (labels
   that tracked the clip boundary would need to hide themselves once
   the handle passed over them, which adds a lot of complexity for
   little practical benefit). */
.novixa-addons-before-after__label {
	position: absolute;
	top: var( --novixa-ba-label-offset, 16px );
	background-color: rgba( 20, 20, 20, 0.65 );
	color: #ffffff;
	padding: 6px 14px;
	border-radius: 4px;
	font-size: 13px;
	line-height: 1.4;
	font-weight: 600;
	letter-spacing: 0.02em;
	z-index: 1;
	pointer-events: none;
	white-space: nowrap;
	backdrop-filter: blur( 6px );
	-webkit-backdrop-filter: blur( 6px );
	border: 1px solid rgba( 255, 255, 255, 0.18 );
	box-shadow: 0 4px 14px rgba( 0, 0, 0, 0.2 );
}

.novixa-addons-before-after__label--before {
	left: var( --novixa-ba-label-offset, 16px );
	opacity: var( --novixa-ba-before-label-opacity, 1 );
}

.novixa-addons-before-after__label--after {
	right: var( --novixa-ba-label-offset, 16px );
	opacity: var( --novixa-ba-after-label-opacity, 1 );
}

.novixa-addons-before-after--vertical .novixa-addons-before-after__label--before {
	top: var( --novixa-ba-label-offset, 16px );
	left: 50%;
	transform: translateX( -50% );
}

.novixa-addons-before-after--vertical .novixa-addons-before-after__label--after {
	top: auto;
	bottom: var( --novixa-ba-label-offset, 16px );
	right: auto;
	left: 50%;
	transform: translateX( -50% );
}


/* ==========================================================================
   Image Gallery (filterable grid/masonry gallery + lightbox)
   ==========================================================================
   Grid uses CSS Grid (equal-height cells). Masonry is positioned by JS
   (see galLayoutMasonryGrid() in frontend.js) - each item goes into
   whichever column is currently shortest, like a Pinterest-style
   layout - because plain CSS `columns:` balances unpredictably across
   browsers with a small number of items. The `columns:` rule below is
   kept only as a no-JS fallback. The lightbox markup is generated by
   JS and inserted as a sibling right after the widget's own wrapper
   (see frontend.js), which is why its style selectors below use
   "{{WRAPPER}} ~ .novixa-addons-gallery-lightbox" rather than a
   descendant selector. */

.novixa-addons-gallery {
	--novixa-gallery-columns: 3;
	--novixa-gallery-gap: 20px;
}

/* --- Filter bar --- */
.novixa-addons-gallery__filter {
	display: flex;
	flex-wrap: wrap;
	gap: 10px 28px;
	margin-bottom: 28px;
}

.novixa-addons-gallery__filter-btn {
	position: relative;
	background: none;
	border: none;
	padding: 0 0 8px;
	margin: 0;
	font-size: 14px;
	font-weight: 600;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	cursor: pointer;
	color: #6b6b6b;
	transition: color 0.25s ease;
}

.novixa-addons-gallery__filter-btn:hover {
	color: #141414;
}

.novixa-addons-gallery__filter-btn::after {
	content: '';
	position: absolute;
	left: 0;
	right: 100%;
	bottom: 0;
	height: 2px;
	background-color: #c9a15f;
	transition: right 0.3s ease;
}

.novixa-addons-gallery__filter-btn--active::after {
	right: 0;
}

/* --- Grid / Masonry --- */
.novixa-addons-gallery__grid--grid {
	display: grid;
	grid-template-columns: repeat( var( --novixa-gallery-columns, 3 ), 1fr );
	gap: var( --novixa-gallery-gap, 20px );
}

.novixa-addons-gallery__grid--masonry {
	position: relative;
	columns: var( --novixa-gallery-columns, 3 );
	column-gap: var( --novixa-gallery-gap, 20px );
}

.novixa-addons-gallery__grid--masonry .novixa-addons-gallery__item {
	break-inside: avoid;
	margin-bottom: var( --novixa-gallery-gap, 20px );
}

.novixa-addons-gallery__item {
	transition: opacity 0.25s ease, transform 0.25s ease;
}

.novixa-addons-gallery__item--hidden {
	display: none;
}

/* --- Thumb / image / hover zoom --- */
.novixa-addons-gallery__thumb {
	--novixa-gallery-zoom: 110%;
	position: relative;
	display: block;
	width: 100%;
	overflow: hidden;
	border: none;
	padding: 0;
	margin: 0;
	background-color: #f2f2f2;
	aspect-ratio: 1 / 1;
	cursor: pointer;
}

.novixa-addons-gallery__grid--masonry .novixa-addons-gallery__thumb {
	aspect-ratio: auto;
}

.novixa-addons-gallery__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.5s cubic-bezier( 0.22, 1, 0.36, 1 );
}

.novixa-addons-gallery__grid--masonry .novixa-addons-gallery__image {
	height: auto;
}

.novixa-addons-gallery__grid--zoom .novixa-addons-gallery__thumb:hover .novixa-addons-gallery__image {
	transform: scale( calc( var( --novixa-gallery-zoom, 110% ) / 100 ) );
}

/* --- Hover overlay --- */
.novixa-addons-gallery__overlay {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 14px;
	text-align: center;
	padding: 20px;
	background-color: rgba( 20, 20, 20, 0.72 );
	opacity: 0;
	transition: opacity 0.3s ease;
}

.novixa-addons-gallery__thumb:hover .novixa-addons-gallery__overlay,
.novixa-addons-gallery__thumb:focus-visible .novixa-addons-gallery__overlay {
	opacity: 1;
}

.novixa-addons-gallery__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	border-radius: 50%;
	background-color: #c9a15f;
	color: #141414;
	transform: scale( 0.7 );
	transition: transform 0.3s ease;
}

.novixa-addons-gallery__icon svg {
	width: 20px;
	height: 20px;
	flex-shrink: 0;
}

.novixa-addons-gallery__thumb:hover .novixa-addons-gallery__icon {
	transform: scale( 1 );
}

.novixa-addons-gallery__overlay-title {
	color: #ffffff;
	font-size: 16px;
	font-weight: 600;
	letter-spacing: 0.02em;
}

.novixa-addons-gallery__overlay-caption {
	color: #ffffff;
	font-size: 13px;
	opacity: 0.85;
}

/* --- Caption below image --- */
.novixa-addons-gallery__caption-below {
	padding-top: 12px;
	text-align: center;
}

.novixa-addons-gallery__caption-title {
	color: #141414;
	font-size: 15px;
	font-weight: 600;
}

.novixa-addons-gallery__caption-text {
	color: #6b6b6b;
	font-size: 13px;
	margin-top: 4px;
}

@media ( prefers-reduced-motion: reduce ) {
	.novixa-addons-gallery__image,
	.novixa-addons-gallery__icon,
	.novixa-addons-gallery__overlay,
	.novixa-addons-gallery__item {
		transition: none;
	}
}

/* --- Lightbox ---
   Inserted by JS as a direct sibling right after the gallery wrapper,
   fixed to the viewport, and reused/repopulated in place every time an
   image is opened rather than rebuilt per click. */
.novixa-addons-gallery-lightbox {
	position: fixed;
	inset: 0;
	z-index: 100000;
	display: flex;
	align-items: center;
	justify-content: center;
	background-color: rgba( 10, 10, 10, 0.95 );
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.3s ease;
}

.novixa-addons-gallery-lightbox--open {
	opacity: 1;
	pointer-events: auto;
}

.novixa-addons-gallery-lightbox__inner {
	position: relative;
	max-width: 90vw;
	max-height: 88vh;
	display: flex;
	flex-direction: column;
	align-items: center;
}

.novixa-addons-gallery-lightbox__image {
	max-width: 90vw;
	max-height: 76vh;
	width: auto;
	height: auto;
	object-fit: contain;
	border-radius: 4px;
	box-shadow: 0 20px 60px rgba( 0, 0, 0, 0.5 );
	opacity: 0;
	transform: scale( 0.97 );
	transition: opacity 0.25s ease, transform 0.25s ease;
}

.novixa-addons-gallery-lightbox__image--visible {
	opacity: 1;
	transform: scale( 1 );
}

.novixa-addons-gallery-lightbox__meta {
	margin-top: 16px;
	text-align: center;
	max-width: 70vw;
}

.novixa-addons-gallery-lightbox__caption {
	color: #ffffff;
	font-size: 14px;
	line-height: 1.5;
}

.novixa-addons-gallery-lightbox__counter {
	color: #c9a15f;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	margin-top: 6px;
}

.novixa-addons-gallery-lightbox__close,
.novixa-addons-gallery-lightbox__nav {
	position: absolute;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 46px;
	height: 46px;
	border-radius: 50%;
	border: none;
	cursor: pointer;
	color: #ffffff;
	background-color: rgba( 255, 255, 255, 0.16 );
	transition: background-color 0.2s ease;
	z-index: 3;
}

/* No backdrop-filter here on purpose: it previously created its own
   compositing layer that, on some browsers, painted this button's
   <svg> icon *underneath* the blur instead of on top of it - the
   circle showed but the icon inside never did. A plain translucent
   background avoids that class of bug entirely. The icon still gets
   its own stacking context below as a second safeguard. */
.novixa-addons-gallery-lightbox__close svg,
.novixa-addons-gallery-lightbox__nav svg {
	position: relative;
	z-index: 4;
	display: block;
	flex-shrink: 0;
	pointer-events: none;
}

.novixa-addons-gallery-lightbox__close:hover,
.novixa-addons-gallery-lightbox__nav:hover {
	background-color: rgba( 255, 255, 255, 0.24 );
}

.novixa-addons-gallery-lightbox__close {
	top: 20px;
	right: 20px;
}

.novixa-addons-gallery-lightbox__nav--prev {
	left: 20px;
	top: 50%;
	transform: translateY( -50% );
}

.novixa-addons-gallery-lightbox__nav--next {
	right: 20px;
	top: 50%;
	transform: translateY( -50% );
}

body.novixa-addons-gallery-lightbox-open {
	overflow: hidden;
}

@media ( max-width: 767px ) {
	.novixa-addons-gallery-lightbox__nav {
		width: 38px;
		height: 38px;
	}

	.novixa-addons-gallery-lightbox__nav--prev {
		left: 8px;
	}

	.novixa-addons-gallery-lightbox__nav--next {
		right: 8px;
	}
}

/* ==================================== */
/* Numbered Feature Box                  */
/* ==================================== */
.novixa-addons-numbered-feature-box {
	position: relative;
	background-color: #1a1a2e;
	border-radius: 18px;
	padding: 28px;
	min-height: 260px;
	box-sizing: border-box;
	text-align: left;
	overflow: hidden;
	transition: background-color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
}

.novixa-addons-numbered-feature-box__top-row {
	position: relative;
	z-index: 1;
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 12px;
}

.novixa-addons-numbered-feature-box__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 56px;
	height: 56px;
	background-color: #4f3ff0;
	border-radius: 14px;
	flex-shrink: 0;
	transition: background-color 0.3s ease, border-color 0.3s ease;
}

.novixa-addons-numbered-feature-box__icon i,
.novixa-addons-numbered-feature-box__icon svg {
	font-size: 24px;
	width: 24px;
	height: 24px;
	color: #ffffff;
	transition: color 0.3s ease, fill 0.3s ease;
}

.novixa-addons-numbered-feature-box__number {
	position: relative;
	z-index: 1;
	color: rgba(255, 255, 255, 0.08);
	font-size: 48px;
	font-weight: 800;
	line-height: 1;
	transition: color 0.3s ease;
}

.novixa-addons-numbered-feature-box__title.novixa-addons-numbered-feature-box__title {
	margin: 0;
	padding: 0;
}

.novixa-addons-numbered-feature-box__title {
	position: relative;
	z-index: 1;
	margin-top: 24px;
	color: #ffffff;
	font-size: 20px;
	font-weight: 700;
	line-height: 1.4;
	transition: color 0.3s ease;
}

.novixa-addons-numbered-feature-box__description {
	position: relative;
	z-index: 1;
	margin-top: 12px;
	color: #c7c7c7;
	font-size: 15px;
	line-height: 1.7;
	transition: color 0.3s ease;
}

/* ---- Style: Flip (Left / Right / Top / Bottom) ----
   A second "back" panel (its own icon/title/description) sits on
   top of the front content and starts translated fully off one
   edge of the card. On hover it slides in to cover the front. The
   edge it starts from is baked into the style modifier itself
   (--style-flip-left / --style-flip-right / --style-flip-top /
   --style-flip-bottom). */
.novixa-addons-numbered-feature-box__front {
	position: relative;
	z-index: 1;
}

.novixa-addons-numbered-feature-box__back {
	position: absolute;
	inset: 0;
	z-index: 2;
	display: flex;
	flex-direction: column;
	align-items: start;
	justify-content: center;
	padding: 28px;
	box-sizing: border-box;
	background-color: #4f3ff0;
	text-align: left;
	transition: transform 0.45s ease;
}

.novixa-addons-numbered-feature-box--style-flip-left .novixa-addons-numbered-feature-box__back {
	transform: translateX(-100%);
}

.novixa-addons-numbered-feature-box--style-flip-right .novixa-addons-numbered-feature-box__back {
	transform: translateX(100%);
}

.novixa-addons-numbered-feature-box--style-flip-top .novixa-addons-numbered-feature-box__back {
	transform: translateY(-100%);
}

.novixa-addons-numbered-feature-box--style-flip-bottom .novixa-addons-numbered-feature-box__back {
	transform: translateY(100%);
}

.novixa-addons-numbered-feature-box--style-flip-left:hover .novixa-addons-numbered-feature-box__back,
.novixa-addons-numbered-feature-box--style-flip-left:focus-within .novixa-addons-numbered-feature-box__back,
.novixa-addons-numbered-feature-box--style-flip-right:hover .novixa-addons-numbered-feature-box__back,
.novixa-addons-numbered-feature-box--style-flip-right:focus-within .novixa-addons-numbered-feature-box__back,
.novixa-addons-numbered-feature-box--style-flip-top:hover .novixa-addons-numbered-feature-box__back,
.novixa-addons-numbered-feature-box--style-flip-top:focus-within .novixa-addons-numbered-feature-box__back,
.novixa-addons-numbered-feature-box--style-flip-bottom:hover .novixa-addons-numbered-feature-box__back,
.novixa-addons-numbered-feature-box--style-flip-bottom:focus-within .novixa-addons-numbered-feature-box__back {
	transform: translate(0, 0);
}

.novixa-addons-numbered-feature-box__back-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 56px;
	height: 56px;
	background-color: rgba(255, 255, 255, 0.15);
	border-radius: 14px;
	margin-bottom: 16px;
	flex-shrink: 0;
}

.novixa-addons-numbered-feature-box__back-icon i,
.novixa-addons-numbered-feature-box__back-icon svg {
	font-size: 24px;
	width: 24px;
	height: 24px;
	color: #ffffff;
}

.novixa-addons-numbered-feature-box__back-title {
	margin: 0;
	color: #ffffff;
	font-size: 20px;
	font-weight: 700;
	line-height: 1.4;
}

.novixa-addons-numbered-feature-box__back-description {
	margin-top: 10px;
	color: rgba(255, 255, 255, 0.85);
	font-size: 15px;
	line-height: 1.7;
}

/* ==========================================================================
   Logo Carousel (paginated card slider - scroll-snap based, no JS
   transform math and no external library)
   ==========================================================================
   .track holds the two arrows + the scrollable .viewport side by side;
   .viewport is the actual `overflow-x:auto; scroll-snap-type:x` strip.
   Each .item's flex-basis is computed from --novixa-carousel-items (set
   responsively by the "Slides to Show" control), so this reflows to a
   different logos-per-page count at each breakpoint automatically. */

.novixa-addons-logo-carousel {
	--novixa-carousel-items: 3;
	--novixa-carousel-gap: 24px;
	--novixa-carousel-3d-perspective: 1200px;
	--novixa-carousel-3d-angle: 25deg;
	--novixa-carousel-3d-scale: 0.85;
	--novixa-carousel-3d-opacity: 0.6;
}

/* "Make 3D": perspective lives on the viewport (the scrolling strip)
   so it applies to every card inside it; each item's own rotateY/
   translateZ/scale transform is computed and applied by frontend.js
   (lc3DUpdate) based on live distance from the active/centered item -
   that per-item math can't be expressed with static CSS alone. */
.novixa-addons-logo-carousel--3d .novixa-addons-logo-carousel__viewport {
	perspective: var( --novixa-carousel-3d-perspective, 1200px );
}

.novixa-addons-logo-carousel--3d .novixa-addons-logo-carousel__item {
	transition: transform 0.4s ease, opacity 0.4s ease;
	will-change: transform, opacity;
}

.novixa-addons-logo-carousel--3d .novixa-addons-logo-carousel__card {
	transform-style: preserve-3d;
}

.novixa-addons-logo-carousel__track {
	position: relative;
	display: flex;
	align-items: center;
	gap: 12px;
}

.novixa-addons-logo-carousel__viewport {
	flex: 1 1 auto;
	display: flex;
	gap: var( --novixa-carousel-gap, 24px );
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
	-ms-overflow-style: none;
}

.novixa-addons-logo-carousel__viewport::-webkit-scrollbar {
	display: none;
}

/* Scroll Snap is temporarily switched off while lcAnimateScroll() is
   driving the scroll position itself (see the JS comment there) so
   the browser's own snap-correction can't fight our easing frame by
   frame - it's restored the instant the animation settles, so
   touch/swipe/drag still snaps to each card as expected. */
.novixa-addons-logo-carousel__viewport--animating {
	scroll-snap-type: none;
}

.novixa-addons-logo-carousel__item {
	flex: 0 0 calc( ( 100% - ( var( --novixa-carousel-items, 3 ) - 1 ) * var( --novixa-carousel-gap, 24px ) ) / var( --novixa-carousel-items, 3 ) );
	scroll-snap-align: start;
}

/* "Center Active Slide": the JS scrolls to each item's own center
   rather than a page boundary (see lcScrollToIndex's centering math),
   and this just switches the browser's own snap target to match, so
   momentum/keyboard scrolling settles on the same position JS aims for. */
.novixa-addons-logo-carousel--center .novixa-addons-logo-carousel__item {
	scroll-snap-align: center;
}

.novixa-addons-logo-carousel__card {
	display: flex;
	align-items: center;
	justify-content: center;
	background-color: #ffffff;
	border-radius: 16px;
	padding: 32px 24px;
	text-decoration: none;
}

.novixa-addons-logo-carousel__logo {
	display: block;
	max-width: 100%;
	max-height: 90px;
	width: auto;
	height: auto;
	object-fit: contain;
	filter: grayscale( 0 );
	transition: filter 0.25s ease, opacity 0.25s ease, max-height 0.2s ease;
}

.novixa-addons-logo-carousel-grayscale-yes .novixa-addons-logo-carousel__logo {
	filter: grayscale( 1 );
	opacity: 0.7;
}

.novixa-addons-logo-carousel-grayscale-yes .novixa-addons-logo-carousel__card:hover .novixa-addons-logo-carousel__logo {
	filter: grayscale( 0 );
	opacity: 1;
}

.novixa-addons-logo-carousel__caption {
	margin-top: 10px;
	text-align: center;
	color: #4a4a4a;
	font-size: 14px;
}

/* --- Nav Arrows ---
   Unlike a flex-inline layout, these sit as an absolute overlay on top
   of .track: "Nav Arrow Spacing" (control) sets left/right inset,
   "Nav Arrow Position" sets the `top` offset, and the translateY(-50%)
   below keeps the button vertically centered on whatever `top` value
   that resolves to, at any breakpoint. */
.novixa-addons-logo-carousel__arrow {
	position: absolute;
	top: 50%;
	left: 0;
	transform: translateY( -50% );
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	border: none;
	cursor: pointer;
	box-shadow: 0 4px 14px rgba( 0, 0, 0, 0.12 );
	transition: transform 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease, color 0.2s ease;
	--novixa-carousel-arrow-icon-size: 18px;
}

.novixa-addons-logo-carousel__arrow--next {
	left: auto;
	right: 0;
}

/* Both the custom Font Awesome <i> icon and our fallback <svg> chevron
   are sized from the same var (set by "Nav Arrow Icon Size" above)
   instead of a fixed 18px - a custom icon or a resized button used to
   end up mismatched/oversized. */
.novixa-addons-logo-carousel__arrow i,
.novixa-addons-logo-carousel__arrow svg {
	flex: 0 0 auto;
	width: var( --novixa-carousel-arrow-icon-size, 18px );
	height: var( --novixa-carousel-arrow-icon-size, 18px );
	font-size: var( --novixa-carousel-arrow-icon-size, 18px );
	line-height: 1;
}

/* Forces the icon's fill/stroke to track the button's own `color`
   (set by "Nav Arrow Icon Color" / "... Hover" above) even when
   Elementor's "Font Icon SVG" experiment has converted the icon into
   an inline <svg> - that conversion can bake a literal fill color
   onto the inner <path>/<use> instead of leaving it as `currentColor`,
   which silently breaks the hover color swap without this override.
   fill is skipped on anything explicitly marked fill="none" (like our
   own default outline chevron) so outline-style icons don't turn into
   solid shapes. */
.novixa-addons-logo-carousel__arrow svg,
.novixa-addons-logo-carousel__arrow svg * {
	stroke: currentColor;
}

.novixa-addons-logo-carousel__arrow svg:not( [ fill='none' ] ),
.novixa-addons-logo-carousel__arrow svg *:not( [ fill='none' ] ) {
	fill: currentColor;
}

.novixa-addons-logo-carousel__arrow:hover {
	transform: translateY( calc( -50% - 2px ) );
	box-shadow: 0 8px 20px rgba( 0, 0, 0, 0.16 );
}

.novixa-addons-logo-carousel__arrow:disabled {
	opacity: 0.35;
	cursor: default;
	transform: translateY( -50% );
	box-shadow: none;
}

/* --- Nav Dots --- */
.novixa-addons-logo-carousel__dots {
	display: flex;
	align-items: center;
	justify-content: center;
}

.novixa-addons-logo-carousel__dot {
	width: 10px;
	height: 10px;
	border-radius: 50%;
	border: none;
	padding: 0;
	cursor: pointer;
	background-color: #d8d8d8;
	transition: background-color 0.2s ease, transform 0.2s ease;
}

.novixa-addons-logo-carousel__dot:hover {
	transform: scale( 1.15 );
}

.novixa-addons-logo-carousel__dot--active {
	background-color: #141414;
}

/* Nav Arrow Background Size / Icon Size / Spacing / Position are all
   responsive controls now (see register_arrow_style_controls), so
   there's no hardcoded mobile override here any more - Elementor
   prints the tablet/mobile breakpoint CSS for those directly. */

/* ==========================================================================
   Shared "Hide On Desktop / Tablet / Mobile" utility classes
   ==========================================================================
   Added to a widget's own wrapper element by
   Novixa_Addons_Widget_Base::get_visibility_classes() when the matching
   switcher (Advanced > Visibility) is turned on. Breakpoints match
   Elementor's own default Desktop / Tablet (1024px) / Mobile (767px)
   device breakpoints. */

@media ( min-width: 1025px ) {
	.novixa-addons-hidden-desktop {
		display: none !important;
	}
}

@media ( min-width: 768px ) and ( max-width: 1024px ) {
	.novixa-addons-hidden-tablet {
		display: none !important;
	}
}

@media ( max-width: 767px ) {
	.novixa-addons-hidden-mobile {
		display: none !important;
	}
}
