/**
 * 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;
	transform: rotate(var(--novixa-icon-rotate, 0deg));
	transition: transform 0.3s ease;
}

/* Forces the icon's fill/stroke to track the button's own `color`
   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 Icon Color control
   above (and its Hover counterpart) without this override. fill is
   skipped on anything explicitly marked fill="none" so outline-style
   icons don't turn into solid shapes. */
.novixa-addons-image-caption-card__button svg,
.novixa-addons-image-caption-card__button svg * {
	stroke: currentColor;
}

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

.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) rotate(var(--novixa-icon-rotate, 0deg));
}

.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;
}

/* Forces the icon's fill/stroke to track the button's own `color`
   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 Icon Color control (and
   its Hover counterpart) without this override. fill is skipped on
   anything explicitly marked fill="none" so outline-style icons
   don't turn into solid shapes. */
.novixa-addons-content-reveal-hover__button svg,
.novixa-addons-content-reveal-hover__button svg * {
	stroke: currentColor;
}

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

.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. */

/* ==================================== */
/* Icon Badge Button                     */
/* ==================================== */
.novixa-addons-icon-badge-button {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 18px;
	padding: 8px 8px 8px 24px;
	min-height: calc( var( --novixa-badge-fill-size, 40px ) + 16px );
	box-sizing: border-box;
	border-radius: 999px;
	background-color: #141414;
	color: #ffffff;
	font-weight: 600;
	font-size: 15px;
	text-decoration: none;
	line-height: 1.4;
	overflow: hidden;
	isolation: isolate;
	transition: color 0.35s ease, background-color 0.35s ease;
}

.novixa-addons-icon-badge-button--badge-start {
	flex-direction: row-reverse;
}

.novixa-addons-icon-badge-button__text {
	position: relative;
	z-index: 1;
}

.novixa-addons-icon-badge-button__badge {
	position: relative;
	z-index: 1;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	width: 40px;
	height: 40px;
	border-radius: 50%;
	background-color: #ee4b3f;
	color: #ffffff;
}

.novixa-addons-icon-badge-button__badge i,
.novixa-addons-icon-badge-button__badge svg {
	font-size: 16px;
	width: 16px;
	height: 16px;
}

/* Forces the icon's fill/stroke to track "Icon Color" 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 control without this
   override. fill is skipped on anything explicitly marked
   fill="none" so outline-style icons don't turn into solid shapes. */
.novixa-addons-icon-badge-button__badge svg,
.novixa-addons-icon-badge-button__badge svg * {
	stroke: currentColor;
}

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

/* Icon slide-swap - the same "duplicate slides in as the original
   slides out" technique used for the text above, applied to the
   badge icon. icon-window is sized to exactly one icon (via
   --badge-icon-size control) and clips anything outside it, so the
   two icons swap places cleanly instead of just nudging in place. */
.novixa-addons-icon-badge-button__icon-window {
	position: relative;
	display: inline-flex;
	overflow: hidden;
	width: 16px;
	height: 16px;
}

.novixa-addons-icon-badge-button__icon,
.novixa-addons-icon-badge-button__icon-dupe {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	transition: transform 0.35s ease;
}

.novixa-addons-icon-badge-button__icon-dupe {
	position: absolute;
	top: 0;
	left: 0;
	transform: translateX( 100% );
}

.novixa-addons-icon-badge-button--hover-nudge:hover .novixa-addons-icon-badge-button__icon,
.novixa-addons-icon-badge-button--hover-fill:hover .novixa-addons-icon-badge-button__icon,
.novixa-addons-icon-badge-button--hover-text-top:hover .novixa-addons-icon-badge-button__icon,
.novixa-addons-icon-badge-button--hover-text-bottom:hover .novixa-addons-icon-badge-button__icon,
.novixa-addons-icon-badge-button--hover-text-left:hover .novixa-addons-icon-badge-button__icon {
	transform: translateX( -100% );
}

.novixa-addons-icon-badge-button--hover-nudge:hover .novixa-addons-icon-badge-button__icon-dupe,
.novixa-addons-icon-badge-button--hover-fill:hover .novixa-addons-icon-badge-button__icon-dupe,
.novixa-addons-icon-badge-button--hover-text-top:hover .novixa-addons-icon-badge-button__icon-dupe,
.novixa-addons-icon-badge-button--hover-text-bottom:hover .novixa-addons-icon-badge-button__icon-dupe,
.novixa-addons-icon-badge-button--hover-text-left:hover .novixa-addons-icon-badge-button__icon-dupe {
	transform: translateX( 0 );
}

/* Badge Position "Start" mirrors the whole layout (row-reverse), so
   the icon should swap toward the button's leading edge too - the
   opposite direction from the default "End" position above. */
.novixa-addons-icon-badge-button--badge-start .novixa-addons-icon-badge-button__icon-dupe {
	transform: translateX( -100% );
}

.novixa-addons-icon-badge-button--badge-start.novixa-addons-icon-badge-button--hover-nudge:hover .novixa-addons-icon-badge-button__icon,
.novixa-addons-icon-badge-button--badge-start.novixa-addons-icon-badge-button--hover-fill:hover .novixa-addons-icon-badge-button__icon,
.novixa-addons-icon-badge-button--badge-start.novixa-addons-icon-badge-button--hover-text-top:hover .novixa-addons-icon-badge-button__icon,
.novixa-addons-icon-badge-button--badge-start.novixa-addons-icon-badge-button--hover-text-bottom:hover .novixa-addons-icon-badge-button__icon,
.novixa-addons-icon-badge-button--badge-start.novixa-addons-icon-badge-button--hover-text-left:hover .novixa-addons-icon-badge-button__icon {
	transform: translateX( 100% );
}

.novixa-addons-icon-badge-button--badge-start.novixa-addons-icon-badge-button--hover-nudge:hover .novixa-addons-icon-badge-button__icon-dupe,
.novixa-addons-icon-badge-button--badge-start.novixa-addons-icon-badge-button--hover-fill:hover .novixa-addons-icon-badge-button__icon-dupe,
.novixa-addons-icon-badge-button--badge-start.novixa-addons-icon-badge-button--hover-text-top:hover .novixa-addons-icon-badge-button__icon-dupe,
.novixa-addons-icon-badge-button--badge-start.novixa-addons-icon-badge-button--hover-text-bottom:hover .novixa-addons-icon-badge-button__icon-dupe,
.novixa-addons-icon-badge-button--badge-start.novixa-addons-icon-badge-button--hover-text-left:hover .novixa-addons-icon-badge-button__icon-dupe {
	transform: translateX( 0 );
}

/* "Badge Fills Button" - a pseudo-element (not the badge itself,
   which needs to stay a fixed circle for its own hover-nudge above)
   scales up from the badge's position/size until it covers the
   whole pill, becoming the button's new background. The button's
   own overflow:hidden + border-radius clips it back into the pill
   shape throughout the animation. */
.novixa-addons-icon-badge-button--hover-fill::before {
	content: '';
	position: absolute;
	top: 8px;
	right: 8px;
	width: var( --novixa-badge-fill-size, 40px );
	height: var( --novixa-badge-fill-size, 40px );
	border-radius: 50%;
	background-color: var( --novixa-badge-fill-color, #ee4b3f );
	transform: scale( 1 );
	transform-origin: center;
	transition: transform 0.45s ease;
	z-index: 0;
}

.novixa-addons-icon-badge-button--badge-start.novixa-addons-icon-badge-button--hover-fill::before {
	right: auto;
	left: 8px;
}

.novixa-addons-icon-badge-button--hover-fill:hover::before {
	transform: scale( 12 );
}

/* --- Text Slide (Top/Bottom/Left) ---
   Two stacked copies of the label - the real one and an
   aria-hidden duplicate - live inside an overflow:hidden window
   exactly one line tall/wide. Only one is ever visible at a time;
   hovering slides both together so the original exits one edge as
   the duplicate enters from the other, while the button's own
   Background/Text Color Hover controls (above) handle the color
   change simultaneously. */
.novixa-addons-icon-badge-button__text-wrap {
	position: relative;
	display: inline-block;
	overflow: hidden;
	vertical-align: middle;
}

.novixa-addons-icon-badge-button__text-dupe {
	display: none;
}

.novixa-addons-icon-badge-button--hover-text-top .novixa-addons-icon-badge-button__text-dupe,
.novixa-addons-icon-badge-button--hover-text-bottom .novixa-addons-icon-badge-button__text-dupe,
.novixa-addons-icon-badge-button--hover-text-left .novixa-addons-icon-badge-button__text-dupe {
	position: absolute;
	top: 0;
	left: 0;
	display: block;
	white-space: nowrap;
}

.novixa-addons-icon-badge-button--hover-text-top .novixa-addons-icon-badge-button__text,
.novixa-addons-icon-badge-button--hover-text-bottom .novixa-addons-icon-badge-button__text,
.novixa-addons-icon-badge-button--hover-text-left .novixa-addons-icon-badge-button__text {
	display: block;
	transition: transform 0.35s ease;
}

.novixa-addons-icon-badge-button--hover-text-top .novixa-addons-icon-badge-button__text-dupe,
.novixa-addons-icon-badge-button--hover-text-bottom .novixa-addons-icon-badge-button__text-dupe,
.novixa-addons-icon-badge-button--hover-text-left .novixa-addons-icon-badge-button__text-dupe {
	transition: transform 0.35s ease;
}

/* Top: original exits upward, duplicate enters from below. */
.novixa-addons-icon-badge-button--hover-text-top .novixa-addons-icon-badge-button__text-dupe {
	transform: translateY( 100% );
}

.novixa-addons-icon-badge-button--hover-text-top:hover .novixa-addons-icon-badge-button__text {
	transform: translateY( -100% );
}

.novixa-addons-icon-badge-button--hover-text-top:hover .novixa-addons-icon-badge-button__text-dupe {
	transform: translateY( 0 );
}

/* Bottom: original exits downward, duplicate enters from above. */
.novixa-addons-icon-badge-button--hover-text-bottom .novixa-addons-icon-badge-button__text-dupe {
	transform: translateY( -100% );
}

.novixa-addons-icon-badge-button--hover-text-bottom:hover .novixa-addons-icon-badge-button__text {
	transform: translateY( 100% );
}

.novixa-addons-icon-badge-button--hover-text-bottom:hover .novixa-addons-icon-badge-button__text-dupe {
	transform: translateY( 0 );
}

/* Left: original exits to the left, duplicate enters from the right. */
.novixa-addons-icon-badge-button--hover-text-left .novixa-addons-icon-badge-button__text-dupe {
	transform: translateX( 100% );
}

.novixa-addons-icon-badge-button--hover-text-left:hover .novixa-addons-icon-badge-button__text {
	transform: translateX( -100% );
}

.novixa-addons-icon-badge-button--hover-text-left:hover .novixa-addons-icon-badge-button__text-dupe {
	transform: translateX( 0 );
}

/* ==================================== */
/* Post List                             */
/* ==================================== */
.novixa-addons-post-list__grid {
	display: grid;
	grid-template-columns: repeat( 3, 1fr );
	gap: 28px;
}

.novixa-addons-post-list--skin-list .novixa-addons-post-list__grid {
	grid-template-columns: 1fr;
}

.novixa-addons-post-list--masonry .novixa-addons-post-list__grid {
	display: block;
	column-count: 3;
	column-gap: 28px;
}

.novixa-addons-post-list--masonry .novixa-addons-post-list__card {
	break-inside: avoid;
	margin-bottom: 28px;
}

.novixa-addons-post-list__card {
	display: flex;
	flex-direction: column;
	background-color: #ffffff;
	border-radius: 12px;
	overflow: hidden;
	transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
}

.novixa-addons-post-list--skin-list .novixa-addons-post-list__card {
	flex-direction: row;
	align-items: stretch;
}

.novixa-addons-post-list--skin-list .novixa-addons-post-list__image-wrap {
	flex: 0 0 240px;
}

.novixa-addons-post-list--skin-minimal .novixa-addons-post-list__card {
	background: none;
	border-radius: 0;
	padding-bottom: 20px;
	border-bottom: 1px solid #e4e4e7;
}

/* Cards: the polished treatment - a large avatar overlapping the
   image's bottom edge, and the date/comments meta moved below Read
   More instead of above the title (Classic, List and Minimal all
   keep the plain meta-above-title layout instead) - see
   render_posts_loop()'s $use_overlap_layout and render_meta()'s
   $position param for the markup this styles. */
/* The extra chained ".novixa-addons-post-list__avatar" (same class
   twice) raises this selector's specificity above the "Avatar Size"
   control's own {{WRAPPER}} .avatar selector, which has equal
   specificity to a plain (undoubled) version of this rule - without
   this, whichever of the two loads later in the page wins, which is
   normally the control (Elementor's per-widget CSS loads after this
   static stylesheet), silently locking the Card skin's avatar to the
   Avatar Size control's default instead of this design's fixed 64px
   overlap size. */
.novixa-addons-post-list--skin-cards .novixa-addons-post-list__avatar.novixa-addons-post-list__avatar {
	width: 64px;
	height: 64px;
	margin-top: -32px;
	margin-bottom: 0;
	margin-left: 20px;
	border: 4px solid #ffffff;
	box-shadow: 0 2px 8px rgba( 0, 0, 0, 0.12 );
	position: relative;
	z-index: 2;
}

.novixa-addons-post-list--skin-cards .novixa-addons-post-list__meta--bottom {
	margin-top: 18px;
	margin-bottom: 0;
	padding-top: 16px;
	border-top: 1px solid #e4e4e7;
	width: 100%;
}

/* Card > Hover Effect (prefix_class) */
.novixa-addons-post-list--hover-lift:hover .novixa-addons-post-list__card {
	transform: translateY( -6px );
	box-shadow: 0 20px 45px rgba( 0, 0, 0, 0.12 );
}

.novixa-addons-post-list--hover-glow:hover .novixa-addons-post-list__card {
	border-color: #4f3ff0;
}

.novixa-addons-post-list--hover-gradient .novixa-addons-post-list__image-wrap::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient( 0deg, rgba( 0, 0, 0, 0.65 ) 0%, transparent 55% );
	opacity: 0;
	transition: opacity 0.3s ease;
	pointer-events: none;
}

.novixa-addons-post-list--hover-gradient:hover .novixa-addons-post-list__image-wrap::after {
	opacity: 1;
}

.novixa-addons-post-list__image-wrap {
	position: relative;
	display: block;
	overflow: hidden;
	aspect-ratio: 1 / 0.66;
	text-decoration: none;
}

.novixa-addons-post-list__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.4s ease, filter 0.4s ease;
}

/* Image > Hover Effect (prefix_class); default is "zoom" */
.novixa-addons-post-list--image-hover-zoom .novixa-addons-post-list__card:hover .novixa-addons-post-list__image {
	transform: scale( 1.05 );
}

.novixa-addons-post-list--image-hover-grayscale .novixa-addons-post-list__image {
	filter: grayscale( 1 );
}

.novixa-addons-post-list--image-hover-grayscale .novixa-addons-post-list__card:hover .novixa-addons-post-list__image {
	filter: grayscale( 0 );
}

.novixa-addons-post-list--image-hover-darken .novixa-addons-post-list__card:hover .novixa-addons-post-list__image {
	filter: brightness( 0.75 );
}

.novixa-addons-post-list__badge {
	position: absolute;
	top: 14px;
	left: 14px;
	padding: 4px 12px;
	border-radius: 999px;
	background-color: #4f3ff0;
	color: #ffffff;
	font-size: 12px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.03em;
}

.novixa-addons-post-list__card-content {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	padding: 20px;
}

.novixa-addons-post-list--buttons-aligned .novixa-addons-post-list__card-content {
	height: 100%;
}

/* Alignment (Style > Layout) - prefix_class lands the modifier on
   Elementor's own outer wrapper, so this is written as a descendant
   selector (ancestor with the modifier class > our own element) -
   safe regardless of exactly which element carries the class.
   text-align covers the title/excerpt/read-more text; align-items
   covers the meta row and read-more link, which are their own
   flex/inline-flex boxes that don't automatically follow text-align. */
.novixa-addons-post-list--align-left .novixa-addons-post-list__card-content {
	text-align: left;
	align-items: flex-start;
}

.novixa-addons-post-list--align-center .novixa-addons-post-list__card-content {
	text-align: center;
	align-items: center;
}

.novixa-addons-post-list--align-right .novixa-addons-post-list__card-content {
	text-align: right;
	align-items: flex-end;
}

.novixa-addons-post-list--buttons-aligned .novixa-addons-post-list__read-more {
	margin-top: auto;
}

.novixa-addons-post-list__meta {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	margin-bottom: 10px;
	color: #9a97a8;
	font-size: 13px;
}

.novixa-addons-post-list--meta-border-yes .novixa-addons-post-list__meta {
	display: flex;
	width: 100%;
	border-top: 1px solid #e4e4e7;
	padding-top: 14px;
	margin-top: 6px;
}

.novixa-addons-post-list__avatar {
	display: block;
	width: 28px;
	height: 28px;
	border-radius: 50%;
	object-fit: cover;
	flex-shrink: 0;
}

.novixa-addons-post-list__meta-sep {
	opacity: 0.6;
}

.novixa-addons-post-list__title.novixa-addons-post-list__title {
	margin: 0;
	padding: 0;
}

.novixa-addons-post-list__title {
	font-size: 19px;
	font-weight: 700;
	line-height: 1.4;
}

.novixa-addons-post-list__title a {
	color: #1a1a2e;
	text-decoration: none;
	transition: color 0.2s ease;
}

.novixa-addons-post-list__title a:hover {
	color: #4f3ff0;
}

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

.novixa-addons-post-list__read-more {
	display: inline-flex;
	align-items: center;
	margin-top: 14px;
	color: #4f3ff0;
	font-weight: 600;
	font-size: 14px;
	text-decoration: none;
	transition: color 0.2s ease;
}

.novixa-addons-post-list__read-more:hover {
	color: #1a1a2e;
}

.novixa-addons-post-list__empty {
	text-align: center;
	color: #6f6c7d;
	padding: 40px 0;
}

.novixa-addons-post-list__pagination {
	display: flex;
	justify-content: center;
	align-items: center;
	gap: 6px;
	margin-top: 32px;
}

.novixa-addons-post-list__pagination a,
.novixa-addons-post-list__pagination span {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 36px;
	height: 36px;
	padding: 0 8px;
	border-radius: 8px;
	color: #1a1a2e;
	text-decoration: none;
	font-size: 14px;
	transition: background-color 0.2s ease, color 0.2s ease;
}

.novixa-addons-post-list__pagination a:hover {
	background-color: #f2f1fb;
}

.novixa-addons-post-list__pagination .current {
	background-color: #4f3ff0;
	color: #ffffff;
	font-weight: 700;
}

/* --- Load on Click / Infinite Scroll --- */
.novixa-addons-post-list__ajax-pagination {
	display: flex;
	justify-content: center;
	margin-top: 32px;
}

.novixa-addons-post-list__load-more-btn {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	border: none;
	border-radius: 999px;
	padding: 12px 28px;
	background-color: #4f3ff0;
	color: #ffffff;
	font-size: 14px;
	font-weight: 600;
	cursor: pointer;
	transition: background-color 0.2s ease, transform 0.2s ease;
}

.novixa-addons-post-list__load-more-btn:hover {
	background-color: #3f31c9;
	transform: translateY( -1px );
}

.novixa-addons-post-list__spinner {
	display: none;
	width: 14px;
	height: 14px;
	border-radius: 50%;
	border: 2px solid rgba( 255, 255, 255, 0.4 );
	border-top-color: #ffffff;
	animation: novixa-post-list-spin 0.7s linear infinite;
}

.novixa-addons-post-list__ajax-pagination--loading .novixa-addons-post-list__spinner {
	display: inline-block;
}

.novixa-addons-post-list__ajax-pagination--loading .novixa-addons-post-list__load-more-btn {
	opacity: 0.75;
	pointer-events: none;
}

.novixa-addons-post-list__ajax-pagination--done {
	display: none;
}

@keyframes novixa-post-list-spin {
	to {
		transform: rotate( 360deg );
	}
}

/* Infinite scroll: the sentinel is an invisible trigger the
   IntersectionObserver watches; only the spinner (shown while a
   fetch is in flight) is ever visible to the person scrolling. */
.novixa-addons-post-list--infinite .novixa-addons-post-list__scroll-sentinel {
	width: 100%;
	height: 1px;
}

.novixa-addons-post-list--infinite .novixa-addons-post-list__loading {
	display: none;
	justify-content: center;
	padding: 12px 0;
}

.novixa-addons-post-list--infinite.novixa-addons-post-list__ajax-pagination--loading .novixa-addons-post-list__loading {
	display: flex;
}

.novixa-addons-post-list--infinite .novixa-addons-post-list__spinner {
	border-color: rgba( 79, 63, 240, 0.25 );
	border-top-color: #4f3ff0;
}

@media ( max-width: 1024px ) {
	.novixa-addons-post-list__grid {
		grid-template-columns: repeat( 2, 1fr );
	}

	.novixa-addons-post-list--masonry .novixa-addons-post-list__grid {
		column-count: 2;
	}
}

@media ( max-width: 767px ) {
	.novixa-addons-post-list__grid {
		grid-template-columns: 1fr;
	}

	.novixa-addons-post-list--masonry .novixa-addons-post-list__grid {
		column-count: 1;
	}

	.novixa-addons-post-list--skin-list .novixa-addons-post-list__card {
		flex-direction: column;
	}

	.novixa-addons-post-list--skin-list .novixa-addons-post-list__image-wrap {
		flex-basis: auto;
	}
}

/* ==========================================================================
   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;
	}
}
