.elementor-kit-502{--e-global-color-primary:#6EC1E4;--e-global-color-secondary:#54595F;--e-global-color-text:#7A7A7A;--e-global-color-accent:#61CE70;--e-global-color-c717502:#2D943B;--e-global-color-72c4825:#09D608;--e-global-color-8561e6f:#1F2933;--e-global-color-8765225:#FFFFFF;--e-global-color-3e8c43c:#FF0000;--e-global-color-9ee9b9e:#DB0000;--e-global-color-c52fce9:#F4F3F8;--e-global-color-46dd9dd:#0800FF;--e-global-color-217dd7d:#3252CC;--e-global-typography-primary-font-family:"Roboto";--e-global-typography-primary-font-weight:600;--e-global-typography-secondary-font-family:"Roboto Slab";--e-global-typography-secondary-font-weight:400;--e-global-typography-text-font-family:"Roboto";--e-global-typography-text-font-weight:400;--e-global-typography-accent-font-family:"Roboto";--e-global-typography-accent-font-weight:500;}.elementor-kit-502 e-page-transition{background-color:#FFBC7D;}.elementor-kit-502 button,.elementor-kit-502 input[type="button"],.elementor-kit-502 input[type="submit"],.elementor-kit-502 .elementor-button{border-radius:999px 999px 999px 999px;padding:20px 40px 20px 40px;}.elementor-kit-502 button:hover,.elementor-kit-502 button:focus,.elementor-kit-502 input[type="button"]:hover,.elementor-kit-502 input[type="button"]:focus,.elementor-kit-502 input[type="submit"]:hover,.elementor-kit-502 input[type="submit"]:focus,.elementor-kit-502 .elementor-button:hover,.elementor-kit-502 .elementor-button:focus{border-radius:999px 999px 999px 999px;}.elementor-section.elementor-section-boxed > .elementor-container{max-width:1300px;}.e-con{--container-max-width:1300px;}.elementor-widget:not(:last-child){margin-block-end:20px;}.elementor-element{--widgets-spacing:20px 20px;--widgets-spacing-row:20px;--widgets-spacing-column:20px;}{}h1.entry-title{display:var(--page-title-display);}@media(max-width:1024px){.elementor-kit-502 button,.elementor-kit-502 input[type="button"],.elementor-kit-502 input[type="submit"],.elementor-kit-502 .elementor-button{padding:17px 40px 17px 40px;}.elementor-section.elementor-section-boxed > .elementor-container{max-width:1024px;}.e-con{--container-max-width:1024px;}}@media(max-width:767px){.elementor-kit-502 button,.elementor-kit-502 input[type="button"],.elementor-kit-502 input[type="submit"],.elementor-kit-502 .elementor-button{padding:17px 40px 17px 40px;}.elementor-section.elementor-section-boxed > .elementor-container{max-width:767px;}.e-con{--container-max-width:767px;}}/* Start custom CSS */<!doctype html>
<html lang="en">
	<head>
		<script type="module">import { injectIntoGlobalHook } from "/@react-refresh";
injectIntoGlobalHook(window);
window.$RefreshReg$ = () => {};
window.$RefreshSig$ = () => (type) => type;</script>

		<script type="module" src="/@vite/client"></script>

		<meta charset="UTF-8" />
		<link rel="icon" type="image/svg+xml" href="/vite.svg" />
		<meta name="generator" content="Hostinger Horizons" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>Hostinger Horizons</title>
		<style>
  #root[data-edit-mode-enabled="true"] [data-edit-id] {
    cursor: pointer; 
    outline: 1px dashed #357DF9; 
    outline-offset: 2px;
    min-height: 1em;
  }
  #root[data-edit-mode-enabled="true"] {
    cursor: pointer;
  }
  #root[data-edit-mode-enabled="true"] [data-edit-id]:hover {
    background-color: #357DF933;
    outline-color: #357DF9; 
  }

  @keyframes fadeInTooltip {
    from {
      opacity: 0;
      transform: translateY(5px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  #inline-editor-disabled-tooltip {
    display: none; 
    opacity: 0; 
    position: absolute;
    background-color: #1D1E20;
    color: white;
    padding: 4px 8px;
    border-radius: 8px;
    z-index: 10001;
    font-size: 14px;
    border: 1px solid #3B3D4A;
    max-width: 184px;
    text-align: center;
  }

  #inline-editor-disabled-tooltip.tooltip-active {
    display: block;
    animation: fadeInTooltip 0.2s ease-out forwards;
  }
</style>
		<script type="module">
window.onerror = (message, source, lineno, colno, errorObj) => {
	const errorDetails = errorObj ? JSON.stringify({
		name: errorObj.name,
		message: errorObj.message,
		stack: errorObj.stack,
		source,
		lineno,
		colno,
	}) : null;

	window.parent.postMessage({
		type: 'horizons-runtime-error',
		message,
		error: errorDetails
	}, '*');
};
</script>
		<script type="module">
const observer = new MutationObserver((mutations) => {
	for (const mutation of mutations) {
		for (const addedNode of mutation.addedNodes) {
			if (
				addedNode.nodeType === Node.ELEMENT_NODE &&
				(
					addedNode.tagName?.toLowerCase() === 'vite-error-overlay' ||
					addedNode.classList?.contains('backdrop')
				)
			) {
				handleViteOverlay(addedNode);
			}
		}
	}
});

observer.observe(document.documentElement, {
	childList: true,
	subtree: true
});

function handleViteOverlay(node) {
	if (!node.shadowRoot) {
		return;
	}

	const backdrop = node.shadowRoot.querySelector('.backdrop');

	if (backdrop) {
		const overlayHtml = backdrop.outerHTML;
		const parser = new DOMParser();
		const doc = parser.parseFromString(overlayHtml, 'text/html');
		const messageBodyElement = doc.querySelector('.message-body');
		const fileElement = doc.querySelector('.file');
		const messageText = messageBodyElement ? messageBodyElement.textContent.trim() : '';
		const fileText = fileElement ? fileElement.textContent.trim() : '';
		const error = messageText + (fileText ? ' File:' + fileText : '');

		window.parent.postMessage({
			type: 'horizons-vite-error',
			error,
		}, '*');
	}
}
</script>
		<script type="module">
const originalConsoleError = console.error;
console.error = function(...args) {
	originalConsoleError.apply(console, args);

	let errorString = '';

	for (let i = 0; i < args.length; i++) {
		const arg = args[i];
		if (arg instanceof Error) {
			errorString = arg.stack || `${arg.name}: ${arg.message}`;
			break;
		}
	}

	if (!errorString) {
		errorString = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' ');
	}

	window.parent.postMessage({
		type: 'horizons-console-error',
		error: errorString
	}, '*');
};
</script>
		<script type="module">
const originalFetch = window.fetch;

window.fetch = function(...args) {
	const url = args[0] instanceof Request ? args[0].url : args[0];

	// Skip WebSocket URLs
	if (url.startsWith('ws:') || url.startsWith('wss:')) {
		return originalFetch.apply(this, args);
	}

	return originalFetch.apply(this, args)
		.then(async response => {
			const contentType = response.headers.get('Content-Type') || '';

			// Exclude HTML document responses
			const isDocumentResponse =
				contentType.includes('text/html') ||
				contentType.includes('application/xhtml+xml');

			if (!response.ok && !isDocumentResponse) {
					const responseClone = response.clone();
					const errorFromRes = await responseClone.text();
					const requestUrl = response.url;
					console.error(`Fetch error from ${requestUrl}: ${errorFromRes}`);
			}

			return response;
		})
		.catch(error => {
			if (!url.match(/.html?$/i)) {
				console.error(error);
			}

			throw error;
		});
};
</script>
	</head>
	<body>
		<div id="root"></div>
		<script type="module" src="/src/main.jsx"></script>
		<script type="module">import { POPUP_STYLES } from './plugins/visual-editor/visual-editor-config.js';

const PLUGIN_APPLY_EDIT_API_URL = '/api/apply-edit';

const ALLOWED_PARENT_ORIGINS = [
	'https://horizons.hostinger.com',
	'https://horizons.hostinger.dev',
	'https://horizons-frontend-local.hostinger.dev',
	'http://localhost:4000',
];

let disabledTooltipElement = null;
let currentDisabledHoverElement = null;

let translations = {
  disabledTooltipText: "This text can be changed only through chat.",
  disabledTooltipTextImage: "This image can only be changed through chat."
};

let areStylesInjected = false;

let globalEventHandlers = null;

let currentEditingInfo = null;

function injectPopupStyles() {
  if (areStylesInjected) return;

  const styleElement = document.createElement('style');
  styleElement.id = 'inline-editor-styles';
  styleElement.textContent = POPUP_STYLES;
  document.head.appendChild(styleElement);
  areStylesInjected = true;
}

function findEditableElementAtPoint(event) {
  let editableElement = event.target.closest('[data-edit-id]');
  
  if (editableElement) {
    return editableElement;
  }
  
  const elementsAtPoint = document.elementsFromPoint(event.clientX, event.clientY);
  
  const found = elementsAtPoint.find(el => el !== event.target && el.hasAttribute('data-edit-id'));
  if (found) return found;
  
  return null;
}

function findDisabledElementAtPoint(event) {
  const direct = event.target.closest('[data-edit-disabled]');
  if (direct) return direct;
  const elementsAtPoint = document.elementsFromPoint(event.clientX, event.clientY);
  const found = elementsAtPoint.find(el => el !== event.target && el.hasAttribute('data-edit-disabled'));
  if (found) return found;
  return null;
}

function showPopup(targetElement, editId, currentContent, isImage = false) {
 currentEditingInfo = { editId, targetElement };

 const parentOrigin = getParentOrigin();

 if (parentOrigin && ALLOWED_PARENT_ORIGINS.includes(parentOrigin)) {
   const eventType = isImage ? 'imageEditEnter' : 'editEnter';
   
   window.parent.postMessage({
     type: eventType,
     payload: { currentText: currentContent }
   }, parentOrigin);
 }
}

function handleGlobalEvent(event) {
  if (!document.getElementById('root')?.getAttribute('data-edit-mode-enabled')) {
    return;
  }

  if (event.target.closest('#inline-editor-popup')) {
    return;
  }

  const editableElement = findEditableElementAtPoint(event);

  if (editableElement) {
    event.preventDefault();
    event.stopPropagation();
    event.stopImmediatePropagation();

    if (event.type === 'click') {
      const editId = editableElement.getAttribute('data-edit-id');
      if (!editId) {
        console.warn('[INLINE EDITOR] Clicked element missing data-edit-id');
        return;
      }

      const isImage = editableElement.tagName.toLowerCase() === 'img';
      let currentContent = '';
      
      if (isImage) {
        currentContent = editableElement.getAttribute('src') || '';
      } else {
        currentContent = editableElement.textContent || '';
      }
      
      showPopup(editableElement, editId, currentContent, isImage);
    }
  } else {
    event.preventDefault();
    event.stopPropagation();
    event.stopImmediatePropagation();
  }
}

function getParentOrigin() {
  if (window.location.ancestorOrigins && window.location.ancestorOrigins.length > 0) {
    return window.location.ancestorOrigins[0];
  }
  
  if (document.referrer) {
    try {
      return new URL(document.referrer).origin;
    } catch (e) {
      console.warn('Invalid referrer URL:', document.referrer);
    }
  }
  
  return null;
}

async function handleEditSave(updatedText) {
  const newText = updatedText
  // Replacing characters that cause Babel parser to crash
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/{/g, '&#123;')
    .replace(/}/g, '&#125;')

  const { editId } = currentEditingInfo;

  try {
    const response = await fetch(PLUGIN_APPLY_EDIT_API_URL, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        editId: editId,
        newFullText: newText
      }),
    });

    const result = await response.json();
    if (result.success) {
      const parentOrigin = getParentOrigin();
      if (parentOrigin && ALLOWED_PARENT_ORIGINS.includes(parentOrigin)) {
        window.parent.postMessage({
          type: 'editApplied',
          payload: {
            editId: editId,
            fileContent: result.newFileContent,
            beforeCode: result.beforeCode,
            afterCode: result.afterCode,
          }
        }, parentOrigin);
      } else {
        console.error('Unauthorized parent origin:', parentOrigin);
      }
    } else {
      console.error(`[vite][visual-editor] Error saving changes: ${result.error}`);
    }
  } catch (error) {
    console.error(`[vite][visual-editor] Error during fetch for ${editId}:`, error);
  }
}

function createDisabledTooltip() {
  if (disabledTooltipElement) return;

  disabledTooltipElement = document.createElement('div');
  disabledTooltipElement.id = 'inline-editor-disabled-tooltip';
  document.body.appendChild(disabledTooltipElement);
}

function showDisabledTooltip(targetElement, isImage = false) {
  if (!disabledTooltipElement) createDisabledTooltip();

  disabledTooltipElement.textContent = isImage ? translations.disabledTooltipTextImage : translations.disabledTooltipText;
  
  if (!disabledTooltipElement.isConnected) {
    document.body.appendChild(disabledTooltipElement);
  }
  disabledTooltipElement.classList.add('tooltip-active');

  const tooltipWidth = disabledTooltipElement.offsetWidth;
  const tooltipHeight = disabledTooltipElement.offsetHeight;
  const rect = targetElement.getBoundingClientRect();

  // Ensures that tooltip is not off the screen with 5px margin
  let newLeft = rect.left + window.scrollX + (rect.width / 2) - (tooltipWidth / 2);
  let newTop = rect.bottom + window.scrollY + 5;

  if (newLeft < window.scrollX) {
    newLeft = window.scrollX + 5; 
  }
  if (newLeft + tooltipWidth > window.innerWidth + window.scrollX) {
    newLeft = window.innerWidth + window.scrollX - tooltipWidth - 5; 
  }
  if (newTop + tooltipHeight > window.innerHeight + window.scrollY) {
    newTop = rect.top + window.scrollY - tooltipHeight - 5; 
  }
  if (newTop < window.scrollY) {
    newTop = window.scrollY + 5; 
  }

  disabledTooltipElement.style.left = `${newLeft}px`;
  disabledTooltipElement.style.top = `${newTop}px`;
}

function hideDisabledTooltip() {
  if (disabledTooltipElement) {
    disabledTooltipElement.classList.remove('tooltip-active');
  }
}

function handleDisabledElementHover(event) {
  const isImage = event.currentTarget.tagName.toLowerCase() === 'img';

  showDisabledTooltip(event.currentTarget, isImage);
}

function handleDisabledElementLeave() {
  hideDisabledTooltip();
}

function handleDisabledGlobalHover(event) {
  const disabledElement = findDisabledElementAtPoint(event);
  if (disabledElement) {
    if (currentDisabledHoverElement !== disabledElement) {
      currentDisabledHoverElement = disabledElement;
      const isImage = disabledElement.tagName.toLowerCase() === 'img';
      showDisabledTooltip(disabledElement, isImage);
    }
  } else {
    if (currentDisabledHoverElement) {
      currentDisabledHoverElement = null;
      hideDisabledTooltip();
    }
  }
}

function enableEditMode() {
  document.getElementById('root')?.setAttribute('data-edit-mode-enabled', 'true');
  
  injectPopupStyles(); 
  
  if (!globalEventHandlers) {
    globalEventHandlers = {
      mousedown: handleGlobalEvent,
      pointerdown: handleGlobalEvent,
      click: handleGlobalEvent
    };
    
    Object.entries(globalEventHandlers).forEach(([eventType, handler]) => {
      document.addEventListener(eventType, handler, true);
    });
  }
  
  document.addEventListener('mousemove', handleDisabledGlobalHover, true);
  
  document.querySelectorAll('[data-edit-disabled]').forEach(el => {
    el.removeEventListener('mouseenter', handleDisabledElementHover);
    el.addEventListener('mouseenter', handleDisabledElementHover);
    el.removeEventListener('mouseleave', handleDisabledElementLeave);
    el.addEventListener('mouseleave', handleDisabledElementLeave);
  });
}

function disableEditMode() {
  document.getElementById('root')?.removeAttribute('data-edit-mode-enabled');

  hideDisabledTooltip();

  if (globalEventHandlers) {
    Object.entries(globalEventHandlers).forEach(([eventType, handler]) => {
      document.removeEventListener(eventType, handler, true);
    });
    globalEventHandlers = null;
  }
  
  document.removeEventListener('mousemove', handleDisabledGlobalHover, true);
  currentDisabledHoverElement = null;
  
  document.querySelectorAll('[data-edit-disabled]').forEach(el => {
    el.removeEventListener('mouseenter', handleDisabledElementHover);
    el.removeEventListener('mouseleave', handleDisabledElementLeave);
  });
}

window.addEventListener("message", function(event) {
  if (event.data?.type === "edit-save") {
    handleEditSave(event.data?.payload?.newText);
  }
  if (event.data?.type === "enable-edit-mode") {
    if (event.data?.translations) {
      translations = { ...translations, ...event.data.translations };
  }

    enableEditMode();
  }
  if (event.data?.type === "disable-edit-mode") {
    disableEditMode();
  }
}); 
</script>
	</body>
</html>/* End custom CSS */