commit aa24ed3be9849c80181e8069e172bdbf2b114309 Author: Mark Poljanšek Date: Tue Sep 16 12:38:57 2025 -0500 Initial commit on develop branch diff --git a/chatbot.js b/chatbot.js new file mode 100644 index 0000000..ee34f3f --- /dev/null +++ b/chatbot.js @@ -0,0 +1,162 @@ +/* + DEDICATED JAVASCRIPT FOR AIMOJSTER.SI CHATBOT WIDGET + Last Updated: 16. September 2025 (v8.0 - Final Production Version) + Author: Gemini AI for AIMojster.si + + This is the final, clean production version of the chatbot script. + It reliably creates, stores (per session), and sends a unique session ID with every user message, + ensuring that the n8n workflow functions correctly. +*/ + +document.addEventListener('DOMContentLoaded', function() { + + // --- DOM ELEMENTI --- + const chatWidgetButton = document.getElementById('chat-widget-button'); + const chatContainer = document.getElementById('chat-widget-container'); + const closeChatBtn = document.getElementById('close-chat-btn'); + const chatMessagesContainer = document.getElementById('chat-messages'); + const chatInputForm = document.getElementById('chat-input-form'); + const chatInputField = document.getElementById('chat-input'); + + // --- KONFIGURACIJA --- + const N8N_WEBHOOK_URL = 'https://n8n.spletnimojster.si/webhook/joze/chat'; + + // Preverimo, ali obstajajo vsi potrebni HTML elementi za delovanje. + if (!chatWidgetButton || !chatContainer || !chatInputForm) { + console.error("Chatbot HTML elements could not be found. The script will not initialize."); + return; + } + + // ====================================================================== // + // === UPRAVLJANJE S SEJO (SESSION ID MANAGEMENT) === // + // ====================================================================== // + + /** + * Zanesljivo pridobi ali ustvari unikaten Session ID za trenutni pogovor. + * Uporablja `sessionStorage`, kar pomeni, da ID obstane med osveževanjem strani, + * a se ponastavi, ko uporabnik zapre zavihek brskalnika. + * @returns {string} The unique session ID for the current chat session. + */ + function getSessionId() { + const SESSION_KEY = 'aimojster_chatbot_session_id'; // Uporabimo unikatno ime ključa + let sessionId = sessionStorage.getItem(SESSION_KEY); + + if (!sessionId) { + // crypto.randomUUID() je moderen, varen in standarden način za generiranje UUID-jev. + sessionId = crypto.randomUUID(); + sessionStorage.setItem(SESSION_KEY, sessionId); + } + return sessionId; + } + + // ====================================================================== // + // === KOMUNIKACIJA Z N8N === // + // ====================================================================== // + + /** + * Sestavi in pošlje uporabnikovo sporočilo skupaj s session ID-jem na n8n webhook. + * @param {string} userMessage - Sporočilo, ki ga je vnesel uporabnik. + */ + async function sendMessageToBot(userMessage) { + showTypingIndicator(); + + // Pridobimo ali ustvarimo session ID za to sejo. + const currentSessionId = getSessionId(); + + // Sestavimo pravilen objekt (payload), ki ga n8n pričakuje. + const payload = { + sessionId: currentSessionId, + chatInput: userMessage, + action: "sendMessage" + }; + + try { + const response = await fetch(N8N_WEBHOOK_URL, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(payload) + }); + + if (!response.ok) { + throw new Error(`Server returned status: ${response.status}`); + } + + const data = await response.json(); + const botReply = data.output; + + if (botReply) { + addBotMessageToUI(botReply); + } else { + // To se zgodi, če n8n vrne prazen odgovor ali napačno strukturo. + console.error("Response from bot was empty or in a malformed structure.", data); + throw new Error("Malformed response from server."); + } + + } catch (error) { + console.error('Error communicating with the chatbot API:', error); + addBotMessageToUI("Oprostite, prišlo je do tehnične napake. Poskusite znova kasneje."); + } + } + + // ====================================================================== // + // === UPRAVLJANJE Z UI IN DOGODKI === // + // ====================================================================== // + + // --- Pomožne UI funkcije --- + function openChatWidget() { + chatContainer.classList.remove('hidden'); + chatInputField.focus(); + } + + function closeChatWidget() { + chatContainer.classList.add('hidden'); + } + + function addMessageToUI(text, sender) { + const messageElement = document.createElement('div'); + messageElement.classList.add('chat-message', `${sender}-message`); + messageElement.textContent = text; + chatMessagesContainer.appendChild(messageElement); + chatMessagesContainer.scrollTop = chatMessagesContainer.scrollHeight; + } + + function showTypingIndicator() { + if (chatMessagesContainer.querySelector('.typing-indicator')) return; + const indicator = document.createElement('div'); + indicator.classList.add('chat-message', 'bot-message', 'typing-indicator'); + indicator.innerHTML = '...'; + chatMessagesContainer.appendChild(indicator); + chatMessagesContainer.scrollTop = chatMessagesContainer.scrollHeight; + } + + function hideTypingIndicator() { + const indicator = chatMessagesContainer.querySelector('.typing-indicator'); + if (indicator) indicator.remove(); + } + + const addUserMessageToUI = (message) => addMessageToUI(message, 'user'); + const addBotMessageToUI = (message) => { + hideTypingIndicator(); + addMessageToUI(message, 'bot'); + }; + + // --- Glavni Event Listener za oddajo sporočila --- + chatInputForm.addEventListener('submit', function(event) { + event.preventDefault(); + const userMessage = chatInputField.value.trim(); + + if (userMessage) { + addUserMessageToUI(userMessage); + sendMessageToBot(userMessage); + chatInputField.value = ''; + } + }); + + // --- Event Listenerji za odpiranje in zapiranje okna --- + chatWidgetButton.addEventListener('click', openChatWidget); + closeChatBtn.addEventListener('click', closeChatWidget); + + console.log("Chatbot v8.0 (Final Production) initialized successfully."); +}); \ No newline at end of file diff --git a/code_export.txt b/code_export.txt new file mode 100644 index 0000000..6fedd9f --- /dev/null +++ b/code_export.txt @@ -0,0 +1,2153 @@ +"./chatbot.js" : +""" +/* + DEDICATED JAVASCRIPT FOR AIMOJSTER.SI CHATBOT WIDGET + Last Updated: 16. September 2025 (v5.0 - FINAL DIAGNOSTIC VERSION WITH ALERTS) + Author: Gemini AI for AIMojster.si +*/ + +// ================================================================================= // +// === KORAK 1: DOKAZ, DA SE NALAGA PRAVA DATOTEKA === // +// To opozorilno okno MORATE videti, ko se stran naloži. // +// Če ga ne vidite, se ta datoteka sploh ne nalaga. // +// ================================================================================= // +alert("DIAGNOSTIC CHATBOT.JS v5.0 SE NALAGA!"); + + +document.addEventListener('DOMContentLoaded', function() { + + // --- DOM ELEMENTI --- + const chatWidgetButton = document.getElementById('chat-widget-button'); + const chatContainer = document.getElementById('chat-widget-container'); + const chatInputForm = document.getElementById('chat-input-form'); + const N8N_WEBHOOK_URL = 'https://n8n.spletnimojster.si/webhook/joze/chat'; + + // --- UPRAVLJANJE S SEJO --- + function getSessionId() { + let sessionId = sessionStorage.getItem('chatbot_session_id_v5'); + if (!sessionId) { + sessionId = crypto.randomUUID(); + sessionStorage.setItem('chatbot_session_id_v5', sessionId); + } + return sessionId; + } + + // --- POŠILJANJE SPOROČILA --- + async function sendMessageToBot(userMessage) { + + const currentSessionId = getSessionId(); + + const payload = { + sessionId: currentSessionId, + chatInput: userMessage, + action: "sendMessage" + }; + + // ================================================================================= // + // === KORAK 2: DOKAZ, KAJ SE POŠILJA === // + // To opozorilno okno se MORA prikazati, preden se sporočilo pošlje. // + // V njem boste videli TOČNO vsebino, ki se pošilja. // + // ================================================================================= // + alert("DIAGNOSTIKA: PODATKI ZA POŠILJANJE:\n\n" + JSON.stringify(payload, null, 2)); + + try { + // Dejansko pošiljanje je v tej verziji zakomentirano, da se osredotočimo na podatke. + // Odkomentirajte spodnje vrstice, ko potrdite, da je `payload` pravilen. + + /* + const response = await fetch(N8N_WEBHOOK_URL, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload) + }); + + if (!response.ok) { + throw new Error(`Server returned status ${response.status}`); + } + const data = await response.json(); + // ... obdelava odgovora ... + */ + + } catch (error) { + console.error('API Error:', error); + alert("Prišlo je do napake pri pošiljanju. Poglejte konzolo."); + } + } + + // --- EVENT LISTENERS --- + function handleFormSubmit(event) { + event.preventDefault(); + const chatInputField = document.getElementById('chat-input'); + const userMessage = chatInputField.value.trim(); + if (userMessage) { + // Dodajmo sporočilo v UI, da vidimo, da se je dogodek sprožil + const chatMessagesContainer = document.getElementById('chat-messages'); + const messageElement = document.createElement('div'); + messageElement.classList.add('chat-message', 'user-message'); + messageElement.textContent = userMessage; + chatMessagesContainer.appendChild(messageElement); + chatMessagesContainer.scrollTop = chatMessagesContainer.scrollHeight; + + sendMessageToBot(userMessage); + chatInputField.value = ''; + } + } + + chatInputForm.addEventListener('submit', handleFormSubmit); + + // Ostale UI funkcije za odpiranje/zapiranje (poenostavljeno) + chatWidgetButton.addEventListener('click', () => chatContainer.classList.remove('hidden')); + document.getElementById('close-chat-btn').addEventListener('click', () => chatContainer.classList.add('hidden')); + + console.log("Chatbot v5.0 (DIAGNOSTIC) initialized."); +});""" + + +"./debug_webhook.html" : +""" + + + + + n8n Webhook Debugger (Popravljena Verzija) + + + + +

n8n Webhook Debugger (Popravljena Verzija)

+

Ta stran bo testirala klic na vaš n8n webhook s pravilnim formatom podatkov.

+

Pričakujemo, da bo Test 1 zdaj uspešen in vrnil `Status: 200 OK`.

+ +
+ + + +
+ +

Rezultati:

+

+
+    
+
+"""
+
+
+"./index.html" : 
+"""
+
+
+
+    
+    
+    
+    
+    AI Mojster - AI Chatboti in Avtomatizacija za Vaše Podjetje
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+    
+    
+    
+    
+    
+    
+
+
+    
+ +
+ +
+
+

Preobrazite Svoje Poslovanje z Močjo Umetne Inteligence

+

Nudimo napredne AI chatbote in avtomatizacijo po meri, ki znižujejo stroške, povečujejo prodajo in zagotavljajo podporo 24/7.

+
+
+ + Podpora 24/7 +
+
+ + Povečana Prodaja +
+
+ + Avtomatizacija Procesov +
+
+ + Znižanje Stroškov +
+
+ Odkrijte Svojo AI Rešitev +
+ +
+
+

Naše Rešitve za Vaš Uspeh

+

Specializirani smo za dve ključni področji, ki prinašata takojšnje in merljive rezultate za vaše podjetje.

+
+
+

AI Chatboti po Meri

+

Pozabite na generične odgovore. Razvijemo inteligentne chatbote, ki razumejo vaše stranke, odgovarjajo na njihova vprašanja v realnem času, zbirajo povpraševanja in jih vodijo skozi nakupni proces. Izboljšajte uporabniško izkušnjo in pretvorite obiskovalce v zveste stranke.

+
+
+

AI Avtomatizacija Procesov

+

Osvobodite svojo ekipo ponavljajočih se nalog. Povežemo vaše aplikacije (CRM, e-pošta, socialna omrežja) v pametne delovne tokove, ki delujejo samodejno. Od avtomatiziranega pošiljanja ponudb do sinhronizacije podatkov – prihranite čas, zmanjšajte napake in se osredotočite na rast.

+
+
+
+
+ +
+

Izberite Paket, ki Poganja Vašo Rast

+

Pregledne cene, brez skritih stroškov. Naložba v AI se vam bo večkratno povrnila.

+
+ Mesečni najem + + Letni najem Prihranite do 20% +
+
+
+

AI Asistent

+

Za podjetja, ki želijo avtomatizirati podporo in zbirati kontakte.

+
+
39 €/mesec
+ 47,58 € z DDV +
+
    +
  • Chatbot z odgovori na pogosta vprašanja
  • +
  • Zbiranje kontaktnih podatkov (leadov)
  • +
  • Namestitev na vašo spletno stran
  • +
  • Osnovno poročanje o pogovorih
  • +
  • E-mail podpora
  • +
+ Izberi Asistenta +
+ + + +
+

AI Avtomatizacija

+

Za podjetja, ki želijo celovito avtomatizacijo internih in zunanjih procesov.

+
+
149 €/mesec
+ 181,78 € z DDV +
+
    +
  • Vse iz paketa AI Partner
  • +
  • Kompleksni avtomatizacijski tokovi (n8n)
  • +
  • API integracije po meri
  • +
  • Povezava z e-poštnimi orodji
  • +
  • Avtomatizirano upravljanje s podatki
  • +
  • Prioritetna tehnična podpora
  • +
+ Izberi Avtomatizacijo +
+
+
+ +
+
+

Prednosti Umetne Inteligence za Vas

+

To niso le tehnične rešitve. To so konkretne koristi, ki jih bo vaše podjetje občutilo takoj.

+
+
+
+

Neprekinjena Dosegljivost 24/7

+

Vaš AI asistent nikoli ne spi. Strankam je na voljo podnevi in ponoči, med vikendi in prazniki, kar zagotavlja takojšnjo podporo in večje zadovoljstvo.

+
+
+
+

Takojšnji Prihranki

+

Zmanjšajte stroške za podporo strankam za do 30%. Avtomatizirajte odgovore na ponavljajoča se vprašanja in sprostite svojo ekipo za naloge, ki prinašajo večjo vrednost.

+
+
+
+

Povečana Prodaja in Leadi

+

AI chatbot aktivno nagovarja obiskovalce, jih kvalificira in zbira njihove podatke. Nikoli več ne zamudite priložnosti za posel, tudi ko niste na voljo.

+
+
+
+

Inteligentno Zbiranje Podatkov

+

Spoznajte svoje stranke bolje kot kdajkoli prej. Chatbot zbira ključne informacije o njihovih željah in težavah, kar vam omogoča sprejemanje pametnejših poslovnih odločitev.

+
+
+
+

Nič Več Ponavljajočega Dela

+

Ročno prepisovanje podatkov, pošiljanje istih e-mailov in ostala dolgočasna opravila postanejo preteklost. Osredotočite se na tisto, kar je resnično pomembno – rast vašega posla.

+
+
+
+

Izjemna Uporabniška Izkušnja

+

Stranke cenijo hitre in natančne odgovore. Z AI zagotovite dosledno in profesionalno komunikacijo, ki gradi zaupanje in lojalnost vaši blagovni znamki.

+
+
+
+
+ +
+
+

Od Ideje do Rezultatov v 4 Korakih

+

Naš proces je preprost, pregleden in osredotočen na doseganje vaših ciljev.

+
+
+
1
+

Posvet in Analiza

+

Skupaj definiramo vaše cilje in analiziramo procese, ki so zreli za avtomatizacijo.

+
+
+
2
+

Načrtovanje in Razvoj

+

Zasnovo chatbota ali avtomatizacije prilagodimo vašim specifičnim potrebam in blagovni znamki.

+
+
+
3
+

Implementacija in Testiranje

+

Rešitev integriramo v vaše okolje in jo temeljito stestiramo za brezhibno delovanje.

+
+
+
4
+

Zagon in Optimizacija

+

Po zagonu spremljamo delovanje in ga nenehno izboljšujemo za doseganje maksimalnih rezultatov.

+
+
+
+
+ +
+
+

Kdo Smo?

+
+
+

Vaši Strokovnjaki za Umetno Inteligenco

+

Smo ekipa navdušencev nad tehnologijo, ki verjame, da umetna inteligenca ni več prihodnost, ampak sedanjost. Naše poslanstvo je, da napredne AI rešitve približamo podjetjem vseh velikosti in jim pomagamo postati učinkovitejši, bolj konkurenčni in uspešnejši.

+ +

Zaupajo nam uspešni:

+ + + Naredimo korak naprej skupaj! +
+
+
+ +

Strateško Načrtovanje

+

Ne prodajamo le tehnologije, ampak celovite rešitve, ki rešujejo vaše poslovne izzive.

+
+
+ +

Razvoj po Meri

+

Vsak chatbot in avtomatizacija sta 100% prilagojena vašemu poslu in ciljem.

+
+
+ +

Zanesljiva Podpora

+

Smo vaš dolgoročni partner. Nudimo redno vzdrževanje, optimizacijo in tehnično podporo.

+
+
+
+
+
+ +
+

Pripravljeni na Prihodnost?

+

Naredite prvi korak k pametnejšemu poslovanju. Kontaktirajte nas za neobvezujoč pogovor in odkrijte, kako lahko AI pomaga tudi vam.

+

Izpolnite obrazec ali nam pišite na info@aimojster.si

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+ + + + + + + + + + + + +""" + + +"./script.js" : +""" +/* + GENERAL JAVASCRIPT FOR AIMOJSTER.SI + Last Updated: 16. September 2025 + Author: Gemini AI for AIMojster.si + + This script handles general functionalities for the website, including: + - Mobile navigation menu. + - Smooth scrolling for anchor links. + - Billing toggle (monthly/yearly) for pricing packages. + - Contact form submission. + - Intersection Observer for animations. +*/ + +document.addEventListener('DOMContentLoaded', function() { + + //====================================================================== + // 1. MOBILNI MENI (NAVIGATION) + //====================================================================== + const menuToggle = document.querySelector('.menu-toggle'); + const navLinks = document.querySelector('.nav-links'); + + if (menuToggle && navLinks) { + menuToggle.addEventListener('click', function(e) { + e.stopPropagation(); + navLinks.classList.toggle('active'); + const icon = menuToggle.querySelector('i'); + if (icon) { + icon.classList.toggle('fa-bars'); + icon.classList.toggle('fa-times'); + } + }); + + document.addEventListener('click', function(e) { + const isClickInsideNav = navLinks.contains(e.target); + const isClickOnToggle = menuToggle.contains(e.target); + if (!isClickInsideNav && !isClickOnToggle && navLinks.classList.contains('active')) { + navLinks.classList.remove('active'); + const icon = menuToggle.querySelector('i'); + if (icon) { + icon.classList.remove('fa-times'); + icon.classList.add('fa-bars'); + } + } + }); + + navLinks.querySelectorAll('a').forEach(link => { + link.addEventListener('click', () => { + if (navLinks.classList.contains('active')) { + navLinks.classList.remove('active'); + const icon = menuToggle.querySelector('i'); + if (icon) { + icon.classList.remove('fa-times'); + icon.classList.add('fa-bars'); + } + } + }); + }); + } + + //====================================================================== + // 2. GLADKO DRSENJE (SMOOTH SCROLLING) + //====================================================================== + document.querySelectorAll('a[href^="#"]').forEach(anchor => { + anchor.addEventListener('click', function (e) { + e.preventDefault(); + const targetId = this.getAttribute('href'); + const targetElement = document.querySelector(targetId); + + if (targetElement) { + targetElement.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + } + }); + }); + + + //====================================================================== + // 3. PREKLOP MED MESEČNIM IN LETNIM NAJEMOM (BILLING TOGGLE) + //====================================================================== + const billingToggle = document.getElementById('billing-toggle'); + if (billingToggle) { + const packagePrices = { + 'asistent': { monthly: 39, yearly: 29 }, + 'partner': { monthly: 89, yearly: 69 }, + 'avtomatizacija': { monthly: 149, yearly: 119 } + }; + + const updatePrices = (isYearly) => { + document.querySelectorAll('.package-card').forEach(card => { + const packageName = card.dataset.package; + if (!packageName || !packagePrices[packageName]) return; + + const priceValue = isYearly ? packagePrices[packageName].yearly : packagePrices[packageName].monthly; + const priceWithVat = (priceValue * 1.22).toFixed(2).replace('.', ','); + + const priceElement = card.querySelector('.price'); + const vatElement = card.querySelector('.vat-price'); + + if (priceElement) { + priceElement.innerHTML = `${priceValue} €/mesec`; + } + if (vatElement) { + vatElement.textContent = `${priceWithVat} € z DDV`; + } + }); + updateContactFormPackageOptions(isYearly); + }; + + const updateContactFormPackageOptions = (isYearly) => { + const packageSelect = document.getElementById('package'); + if (!packageSelect) return; + + Array.from(packageSelect.options).forEach(option => { + const packageName = option.value; + if (packageName && packagePrices[packageName]) { + const price = isYearly ? packagePrices[packageName].yearly : packagePrices[packageName].monthly; + const packageTitle = option.text.split(' - ')[0]; + option.text = `${packageTitle} - ${price}€/mesec`; + } + }); + }; + + updatePrices(billingToggle.checked); + billingToggle.addEventListener('change', (e) => { + updatePrices(e.target.checked); + }); + } + + //====================================================================== + // 4. IZBIRA PAKETA IN POSODOBITEV KONTAKTNEGA OBRAZCA + //====================================================================== + document.querySelectorAll('.package-button').forEach(button => { + button.addEventListener('click', function() { + const packageCard = this.closest('.package-card'); + if (packageCard) { + const selectedPackage = packageCard.dataset.package; + const contactFormPackageSelect = document.getElementById('package'); + if (contactFormPackageSelect) { + contactFormPackageSelect.value = selectedPackage; + } + } + }); + }); + + + //====================================================================== + // 5. POŠILJANJE KONTAKTNEGA OBRAZCA (FORM SUBMISSION) + //====================================================================== + const contactForm = document.getElementById('contact-form'); + if (contactForm) { + contactForm.addEventListener('submit', async function(e) { + e.preventDefault(); + const name = document.getElementById('name').value.trim(); + const email = document.getElementById('email').value.trim(); + const message = document.getElementById('message').value.trim(); + const selectedPackage = document.getElementById('package').value; + const submitButton = this.querySelector('.submit-button'); + + if (!name || !email || !message || !selectedPackage) { + alert('Prosimo, izpolnite vsa obvezna polja.'); + return; + } + + const originalButtonText = submitButton.textContent; + submitButton.textContent = 'Pošiljanje...'; + submitButton.disabled = true; + + const formData = { + name: name, + email: email, + phone: document.getElementById('phone').value.trim(), + package: selectedPackage, + message: message + }; + + try { + const response = await fetch('send_email.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(formData) + }); + + if (!response.ok) throw new Error('Težava z omrežno povezavo.'); + + const result = await response.json(); + if (result.success) { + alert('Hvala za vaše sporočilo! Odgovorili vam bomo v najkrajšem možnem času.'); + contactForm.reset(); + } else { + throw new Error(result.error || 'Prišlo je do napake pri pošiljanju sporočila.'); + } + } catch (error) { + console.error('Error:', error); + alert('Napaka: ' + error.message); + } finally { + submitButton.textContent = originalButtonText; + submitButton.disabled = false; + } + }); + } + + //====================================================================== + // 6. ANIMACIJE OB DRSENJU (INTERSECTION OBSERVER) + //====================================================================== + const animatedElements = document.querySelectorAll('.fade-in'); + if ('IntersectionObserver' in window) { + const observer = new IntersectionObserver((entries, observer) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + entry.target.classList.add('visible'); + observer.unobserve(entry.target); + } + }); + }, { threshold: 0.1 }); + animatedElements.forEach(el => observer.observe(el)); + } else { + animatedElements.forEach(el => el.classList.add('visible')); + } + +});""" + + +"./send_email.php" : +""" + false, 'error' => 'Napačna metoda zahteve. Dovoljena je samo metoda POST.']); + exit; // Takoj prekinemo izvajanje skripte. +} + +//====================================================================== +// 2. SPREJEM IN DEKODIRANJE PODATKOV +//====================================================================== + +// Preberemo необdelane podatke iz telesa zahteve (request body). +// To je potrebno, ker JavaScript pošilja podatke kot JSON, ne kot klasičen form-data. +$json_payload = file_get_contents('php://input'); + +// Dekodiramo JSON niz v PHP asociativno polje. +// Drugi parameter `true` zagotovi, da dobimo polje namesto objekta. +$data = json_decode($json_payload, true); + +// Preverimo, ali je prišlo do napake pri dekodiranju JSON-a. +if (json_last_error() !== JSON_ERROR_NONE) { + http_response_code(400); // Bad Request + echo json_encode(['success' => false, 'error' => 'Neveljaven JSON format podatkov.']); + exit; +} + +//====================================================================== +// 3. VALIDACIJA PREJETIH PODATKOV +//====================================================================== + +// Definiramo obvezna polja. +$required_fields = ['name', 'email', 'message', 'package']; +$errors = []; + +foreach ($required_fields as $field) { + if (empty($data[$field])) { + $errors[] = "Polje '{$field}' je obvezno."; + } +} + +// Posebej preverimo veljavnost e-poštnega naslova. +if (!empty($data['email']) && !filter_var($data['email'], FILTER_VALIDATE_EMAIL)) { + $errors[] = "Vneseni e-poštni naslov ni v veljavni obliki."; +} + +// Če so se pojavile napake pri validaciji, jih vrnemo odjemalcu. +if (!empty($errors)) { + http_response_code(400); // Bad Request + echo json_encode(['success' => false, 'error' => implode(' ', $errors)]); + exit; +} + +//====================================================================== +// 4. SANITIZACIJA PODATKOV IN PRIPRAVA SPREMENLJIVK +//====================================================================== + +// Sanitiziramo vse prejete podatke, da preprečimo XSS napade in druge zlorabe. +// Uporabimo htmlspecialchars za kodiranje posebnih znakov in trim za odstranitev presledkov. +$name = htmlspecialchars(trim($data['name'])); +$email = filter_var(trim($data['email']), FILTER_SANITIZE_EMAIL); +$phone = isset($data['phone']) ? htmlspecialchars(trim($data['phone'])) : 'Ni vneseno'; +$package = htmlspecialchars(trim($data['package'])); +$message = htmlspecialchars(trim($data['message'])); + + +//====================================================================== +// 5. SESTAVLJANJE IN POŠILJANJE E-POŠTNEGA SPOROČILA +//====================================================================== + +// --- Nastavitve E-pošte --- +$to_email = 'info@aimojster.si'; // **POMEMBNO: Vnesite vaš pravi e-poštni naslov!** +$subject = 'Novo povpraševanje s spletne strani AIMojster.si'; + +// --- Telo sporočila (Email Body) --- +// Uporabimo jasne oznake za preglednost. +$email_body = "Prejeli ste novo povpraševanje preko kontaktnega obrazca na spletni strani AIMojster.si.\n\n"; +$email_body .= "--------------------------------------------------\n"; +$email_body .= "Ime in priimek: " . $name . "\n"; +$email_body .= "E-poštni naslov: " . $email . "\n"; +$email_body .= "Telefonska številka: " . $phone . "\n"; +$email_body .= "Izbrani paket: " . $package . "\n\n"; +$email_body .= "Sporočilo:\n" . $message . "\n"; +$email_body .= "--------------------------------------------------\n"; +$email_body .= "To sporočilo je bilo poslano samodejno."; + +// --- Glave sporočila (Email Headers) --- +// Pravilno nastavljene glave so ključne za zanesljivo dostavo in preprečevanje, da bi sporočilo končalo v vsiljeni pošti. +$headers = "From: no-reply@aimojster.si\r\n"; // Uporabite naslov z vaše domene. +$headers .= "Reply-To: " . $email . "\r\n"; // To vam omogoča, da direktno odgovorite pošiljatelju. +$headers .= "Content-Type: text/plain; charset=UTF-8\r\n"; +$headers .= "X-Mailer: PHP/" . phpversion(); + +// --- Pošiljanje --- +// Uporabimo PHP funkcijo mail(). Če je pošiljanje uspešno, vrne true. +if (mail($to_email, $subject, $email_body, $headers)) { + // Pošiljanje je uspelo, vrnemo pozitiven odgovor. + echo json_encode(['success' => true]); +} else { + // Pošiljanje ni uspelo. Vrnemo napako. + http_response_code(500); // Internal Server Error + echo json_encode(['success' => false, 'error' => 'Napaka strežnika pri pošiljanju sporočila. Prosimo, poskusite kasneje.']); +} + +exit; // Zaključimo izvajanje skripte. + +?>""" + + +"./style.css" : +""" +/* + STYLESHEET FOR AIMOJSTER.SI + Last Updated: 16. September 2025 + Author: Gemini AI for AIMojster.si +*/ + +:root { + /* Tech & AI Inspired Color Scheme */ + --primary-color: #7B2DFF; /* Vibrant Purple */ + --secondary-color: #9A5BFF; /* Lighter Violet */ + --accent-color: #00F5D4; /* Bright Teal/Cyan */ + --accent-light: #70F8E3; /* Light Teal */ + --text-color: #1D2B48; /* Deep Blue-Black */ + --light-text: #6B7C93; /* Muted Gray-Blue */ + --background: #ffffff; /* Pure White */ + --light-background: #F9F7FF; /* Very Light Purple Tint */ + --border-color: #EAE6FF; /* Light Purple-Gray Border */ + --success-color: #4CD5B0; /* Minty Green */ + + --shadow: 0 4px 10px rgba(123, 45, 255, 0.08); + --shadow-lg: 0 10px 25px rgba(123, 45, 255, 0.12); + + --gradient-primary: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + --gradient-accent: linear-gradient(135deg, var(--accent-color), var(--accent-light)); +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + font-family: 'Montserrat', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; + line-height: 1.6; + color: var(--text-color); + background-color: var(--background); +} + +/* --- Header & Navigation --- */ +.header { + background: var(--background); + box-shadow: var(--shadow); + position: fixed; + width: 100%; + top: 0; + z-index: 1000; +} + +.navbar { + max-width: 1200px; + margin: 0 auto; + padding: 1rem 1.5rem; + display: flex; + justify-content: space-between; + align-items: center; +} + +.logo { + height: 32px; + display: flex; + align-items: center; +} + +.logo a { + height: 100%; + display: flex; + align-items: center; + text-decoration: none; +} + +.logo img { + height: 100%; + width: auto; +} + +.nav-links { + display: flex; + gap: 2rem; + align-items: center; +} + +.nav-links a { + text-decoration: none; + color: var(--text-color); + font-weight: 500; + transition: color 0.3s ease; + position: relative; + padding: 5px 0; +} + +.nav-links a::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 0; + height: 2px; + background: var(--accent-color); + transition: width 0.3s ease; +} + +.nav-links a:hover { + color: var(--primary-color); +} + +.nav-links a:hover::after { + width: 100%; +} + +.phone-number { + font-weight: 600; + color: var(--primary-color); + display: flex; + align-items: center; + gap: 0.5rem; +} + +.language-switch { + display: flex; + align-items: center; + justify-content: center; + background: var(--light-background); + color: var(--primary-color); + border-radius: 2rem; + padding: 0.5rem 1rem; + font-weight: 600; + transition: all 0.3s ease; + margin-left: 0.5rem; +} + +.language-switch i { + margin-right: 0.5rem; +} + +.language-switch:hover { + background: var(--primary-color); + color: white; + transform: translateY(-2px); + box-shadow: var(--shadow); +} + +/* --- Hero Section --- */ +.hero { + padding: 8rem 1rem 4rem; + text-align: center; + background: linear-gradient(rgba(29, 43, 72, 0.7), rgba(29, 43, 72, 0.6)), url('images/hero-bg-ai.webp'); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + min-height: 90vh; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 2.5rem; + position: relative; + overflow: hidden; +} + +.hero h1 { + font-size: 4.5rem; + max-width: 900px; + margin: 0 auto; + line-height: 1.2; + color: white; + font-weight: 800; + letter-spacing: -1px; + animation: fadeInUp 1s ease-out; +} + +.hero-text { + max-width: 800px; + margin: 0 auto; + font-size: 1.5rem; + color: rgba(255, 255, 255, 0.9); + line-height: 1.8; + font-weight: 400; + animation: fadeInUp 1s ease-out 0.2s backwards; +} + +.hero-features { + display: flex; + gap: 2rem; + margin-top: 2rem; + flex-wrap: wrap; + justify-content: center; + animation: fadeInUp 1s ease-out 0.6s backwards; +} + +.hero-feature { + display: flex; + align-items: center; + gap: 0.75rem; + color: var(--text-color); + font-weight: 500; + padding: 0.75rem 1.5rem; + background: rgba(255, 255, 255, 0.95); + border: 1px solid rgba(255, 255, 255, 0.2); + border-radius: 1rem; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); + backdrop-filter: blur(10px); + transition: all 0.3s ease; +} + +.hero-feature:hover { + transform: translateY(-5px) scale(1.05); + box-shadow: 0 6px 30px rgba(0, 0, 0, 0.15); +} + +.hero-feature i { + color: var(--primary-color); + font-size: 1.5rem; +} + +.hero .cta-button { + font-size: 1.2rem; + padding: 1.2rem 3.5rem; + border-radius: 50px; + background: var(--gradient-primary); + color: white; + text-decoration: none; + box-shadow: var(--shadow); + animation: fadeInUp 1s ease-out 0.4s backwards; + transition: all 0.3s ease; + border: none; + font-weight: 600; +} + +.hero .cta-button:hover { + transform: translateY(-3px); + box-shadow: var(--shadow-lg); + background: var(--gradient-accent); + color: var(--text-color); +} + +/* --- General Section Styling --- */ +section { + padding: 6rem 1.5rem; +} + +.container { + max-width: 1200px; + margin: 0 auto; +} + +h2 { + text-align: center; + margin-bottom: 1.5rem; + font-size: 2.8rem; + color: var(--text-color); + font-weight: 700; +} + +.section-subtitle { + text-align: center; + color: var(--light-text); + font-size: 1.2rem; + max-width: 700px; + margin: 0 auto 4rem; + line-height: 1.6; +} + + +/* --- Packages Section --- */ +.packages { + background: var(--light-background); +} + +.billing-toggle { + text-align: center; + margin-bottom: 3rem; + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; +} + +.billing-toggle span { + font-weight: 500; +} + +.toggle-switch { + position: relative; + display: inline-block; + width: 60px; + height: 30px; +} + +.toggle-switch input { + opacity: 0; + width: 0; + height: 0; +} + +.toggle-slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: var(--secondary-color); + transition: .4s; + border-radius: 34px; +} + +.toggle-slider:before { + position: absolute; + content: ""; + height: 22px; + width: 22px; + left: 4px; + bottom: 4px; + background-color: white; + transition: .4s; + border-radius: 50%; +} + +input:checked + .toggle-slider { + background: var(--gradient-accent); +} + +input:checked + .toggle-slider:before { + transform: translateX(30px); +} + +.yearly-discount { + background: var(--gradient-accent); + color: var(--text-color); + padding: 0.4rem 1rem; + border-radius: 1rem; + font-size: 0.8rem; + margin-left: 0.5rem; + font-weight: 600; +} + +.package-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 2rem; + max-width: 1200px; + margin: 0 auto; +} + +.package-card { + background: white; + border: 1px solid var(--border-color); + border-radius: 1.5rem; + padding: 2.5rem 2rem; + text-align: center; + position: relative; + transition: all 0.3s ease; + display: flex; + flex-direction: column; + box-shadow: var(--shadow); +} + +.package-card:hover { + transform: translateY(-10px); + box-shadow: var(--shadow-lg); + border-color: var(--primary-color); +} + +.package-card h3 { + font-size: 1.8rem; + color: var(--text-color); +} + +.package-card .subtitle { + font-size: 1.1rem; + color: var(--light-text); + margin: 0.5rem 0 1rem; + min-height: 44px; /* Align heights */ +} + +.price-period { + margin: 1rem 0; +} + +.price { + font-size: 3.5rem; + font-weight: 700; + color: var(--primary-color); + line-height: 1; +} + +.price span { + font-size: 1.2rem; + color: var(--light-text); + margin-left: 0.3rem; + font-weight: 400; +} + +.vat-price { + font-size: 0.9rem; + color: var(--light-text); + display: block; + margin-top: 0.5rem; +} + +.package-card ul { + list-style: none; + margin: 1.5rem 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 1rem; + text-align: left; + flex-grow: 1; +} + +.package-card li { + font-size: 1rem; + color: var(--text-color); + display: flex; + align-items: flex-start; + gap: 0.75rem; + line-height: 1.4; +} + +.package-card li::before { + content: "✓"; + color: var(--success-color); + font-weight: bold; + font-size: 1.2rem; + min-width: 20px; +} + +.package-button { + display: inline-block; + padding: 1rem 2.5rem; + background: var(--gradient-primary); + color: white; + text-decoration: none; + border-radius: 50px; + font-weight: 600; + font-size: 1.1rem; + transition: all 0.3s ease; + margin-top: auto; + border: none; +} + +.package-button:hover { + background: var(--gradient-accent); + color: var(--text-color); + transform: translateY(-2px); + box-shadow: var(--shadow); +} + +.package-card.featured { + border: 2px solid var(--primary-color); + transform: scale(1.05); + z-index: 2; +} + +.package-card.featured .package-button { + background: var(--gradient-primary); +} + +.popular-badge { + position: absolute; + top: -15px; + left: 50%; + transform: translateX(-50%); + background: var(--gradient-primary); + color: white; + padding: 0.7rem 2rem; + border-radius: 50px; + font-size: 1rem; + font-weight: 600; + white-space: nowrap; + box-shadow: var(--shadow); +} + +/* --- Why Us / Benefits Section --- */ +.why-us { + background: var(--background); +} + +.benefits-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: 2rem; +} + +.benefit-card { + background: var(--light-background); + border: 1px solid var(--border-color); + border-radius: 1.5rem; + padding: 2rem; + transition: all 0.3s ease; +} + +.benefit-card:hover { + transform: translateY(-5px); + box-shadow: var(--shadow); + background: white; +} + +.benefit-icon { + width: 70px; + height: 70px; + background: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 1.5rem; + box-shadow: var(--shadow); +} + +.benefit-icon i { + font-size: 2rem; + color: var(--primary-color); +} + +.benefit-card h3 { + color: var(--text-color); + font-size: 1.5rem; + margin-bottom: 0.5rem; +} + +.benefit-card p { + color: var(--light-text); + font-size: 1.1rem; + line-height: 1.6; +} + +/* --- Process Section --- */ +.process { + background: var(--light-background); +} + +.process-steps { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 2rem; + max-width: 1200px; + margin: 0 auto; + position: relative; +} + +.step { + text-align: center; + padding: 2rem; +} + +.step-number { + width: 4.5rem; + height: 4.5rem; + background: var(--gradient-accent); + color: var(--text-color); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 1.5rem; + font-size: 2rem; + font-weight: 700; + box-shadow: var(--shadow); + transition: transform 0.3s ease; +} + +.step:hover .step-number { + transform: scale(1.1) rotate(10deg); +} + +.step h3 { + font-size: 1.4rem; + margin-bottom: 0.5rem; +} + +.step p { + color: var(--light-text); +} + +/* --- About Section --- */ +.about { + background: white; +} + +.about-content { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 4rem; + align-items: center; +} + +.about-text h3 { + font-size: 1.8rem; + color: var(--primary-color); + margin-bottom: 1rem; +} + +.about-text p { + font-size: 1.1rem; + line-height: 1.8; + color: var(--light-text); + margin-bottom: 1.5rem; +} + +.client-list { + list-style: none; + padding: 0; + margin-top: 2rem; +} + +.client-list li { + margin-bottom: 1rem; + font-size: 1.1rem; +} + +.client-list a { + color: var(--primary-color); + text-decoration: none; + font-weight: 600; +} + +.about-cta { + display: inline-block; + margin-top: 1.5rem; + padding: 1rem 2rem; + background: var(--gradient-primary); + color: white; + text-decoration: none; + border-radius: 50px; + font-weight: 600; + transition: all 0.3s ease; +} + +.about-cta:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-lg); +} + +/* --- Contact Section --- */ +.contact { + background: var(--light-background); +} + +.contact-text { + max-width: 600px; + margin: 0 auto 2rem; + font-size: 1.2rem; + line-height: 1.8; + color: var(--light-text); +} + +.contact-options { + text-align: center; + margin-bottom: 2rem; + color: var(--light-text); +} + +.contact-options a { + color: var(--primary-color); + text-decoration: none; + font-weight: 500; + transition: color 0.3s ease; +} + +.contact-options a:hover { + color: var(--accent-color); +} + +.contact-form { + max-width: 600px; + margin: 0 auto; + padding: 3rem; + background: var(--background); + border-radius: 20px; + box-shadow: var(--shadow-lg); + display: grid; + gap: 1.5rem; + border: 1px solid var(--border-color); +} + +.form-group { + text-align: left; +} + +.form-group label { + display: block; + margin-bottom: 0.5rem; + color: var(--text-color); + font-weight: 500; +} + +.form-group input, +.form-group select, +.form-group textarea { + width: 100%; + padding: 1rem; + border: 1px solid var(--border-color); + border-radius: 12px; + font-size: 1rem; + color: var(--text-color); + background: var(--light-background); + transition: all 0.3s ease; +} + +.form-group input:focus, +.form-group select:focus, +.form-group textarea:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(123, 45, 255, 0.1); + background: white; +} + +.form-group textarea { + min-height: 150px; + resize: vertical; +} + +.submit-button { + padding: 1.2rem 2.5rem; + background: var(--gradient-primary); + color: white; + border: none; + border-radius: 12px; + font-weight: 600; + font-size: 1.1rem; + cursor: pointer; + transition: all 0.3s ease; + margin-top: 1rem; +} + +.submit-button:hover { + background: var(--gradient-accent); + color: var(--text-color); + transform: translateY(-2px); + box-shadow: var(--shadow); +} + + +/* --- Footer --- */ +.footer { + background: var(--text-color); + color: white; + padding: 4rem 2rem 2rem; +} + +.footer-content { + max-width: 1200px; + margin: 0 auto; + display: grid; + grid-template-columns: 2fr 1fr 1.5fr; + gap: 4rem; + margin-bottom: 3rem; +} + +.footer-logo img { + height: 40px; + margin-bottom: 1rem; +} + +.footer-logo p { + color: rgba(255, 255, 255, 0.8); +} + +.footer h4 { + color: white; + font-size: 1.1rem; + margin-bottom: 1.5rem; + font-weight: 600; +} + +.footer-links { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.footer-links a { + color: rgba(255, 255, 255, 0.8); + text-decoration: none; + transition: color 0.3s ease; +} + +.footer-links a:hover { + color: var(--accent-color); +} + +.contact-methods a { + color: rgba(255, 255, 255, 0.8); + text-decoration: none; + transition: color 0.3s ease; + display: flex; + align-items: center; + gap: 0.75rem; + margin-bottom: 0.75rem; +} + +.contact-methods a:hover { + color: var(--accent-color); +} + +.footer-bottom { + max-width: 1200px; + margin: 0 auto; + padding-top: 2rem; + border-top: 1px solid rgba(255, 255, 255, 0.1); + display: flex; + justify-content: space-between; + align-items: center; + color: rgba(255, 255, 255, 0.6); + font-size: 0.9rem; +} + +.legal-links { + display: flex; + gap: 2rem; +} + +.legal-links a { + color: rgba(255, 255, 255, 0.6); + text-decoration: none; + transition: color 0.3s ease; +} + +.legal-links a:hover { + color: white; +} + +/* --- Chatbot Widget --- */ +#chat-widget-button { + position: fixed; + bottom: 25px; + right: 25px; + width: 60px; + height: 60px; + background: var(--gradient-primary); + border-radius: 50%; + border: none; + cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); + z-index: 998; + transition: transform 0.3s ease, box-shadow 0.3s ease; +} + +#chat-widget-button:hover { + transform: scale(1.1); + box-shadow: var(--shadow-lg); +} + +#chat-widget-button img { + width: 32px; + height: 32px; +} + +#chat-widget-container { + position: fixed; + bottom: 100px; + right: 25px; + width: 370px; + max-width: 90vw; + height: 70vh; + max-height: 600px; + background: white; + border-radius: 15px; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); + display: flex; + flex-direction: column; + overflow: hidden; + z-index: 999; + transform-origin: bottom right; + transition: transform 0.3s ease, opacity 0.3s ease; +} + +#chat-widget-container.hidden { + transform: scale(0); + opacity: 0; + pointer-events: none; +} + +.chat-header { + background: var(--gradient-primary); + color: white; + padding: 1rem; + display: flex; + justify-content: space-between; + align-items: center; +} + +.chat-header h3 { + font-size: 1.1rem; + font-weight: 600; + margin: 0; +} + +#close-chat-btn { + background: none; + border: none; + color: white; + font-size: 1.8rem; + cursor: pointer; + line-height: 1; + opacity: 0.8; + transition: opacity 0.2s ease; +} + +#close-chat-btn:hover { + opacity: 1; +} + +#chat-messages { + flex-grow: 1; + padding: 1rem; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.chat-message { + padding: 0.75rem 1rem; + border-radius: 18px; + max-width: 80%; + line-height: 1.5; +} + +.bot-message { + background-color: var(--light-background); + color: var(--text-color); + border-bottom-left-radius: 4px; + align-self: flex-start; +} + +.user-message { + background-color: var(--primary-color); + color: white; + border-bottom-right-radius: 4px; + align-self: flex-end; +} + +.typing-indicator { + align-self: flex-start; + color: var(--light-text); + font-style: italic; + font-size: 0.9rem; +} + +#chat-input-form { + display: flex; + padding: 1rem; + border-top: 1px solid var(--border-color); +} + +#chat-input { + flex-grow: 1; + border: 1px solid var(--border-color); + border-radius: 50px; + padding: 0.75rem 1rem; + font-size: 1rem; + transition: border-color 0.2s; +} + +#chat-input:focus { + outline: none; + border-color: var(--primary-color); +} + +#chat-input-form button { + background: var(--primary-color); + color: white; + border: none; + border-radius: 50%; + width: 45px; + height: 45px; + margin-left: 0.5rem; + cursor: pointer; + font-size: 1.2rem; + transition: background-color 0.2s; +} + +#chat-input-form button:hover { + background-color: var(--secondary-color); +} + + +/* --- Mobile Menu & Responsive --- */ +.menu-toggle { + display: none; + font-size: 1.5rem; + color: var(--text-color); + cursor: pointer; +} + +@media (max-width: 992px) { + .package-grid { + grid-template-columns: 1fr 1fr; + } + .package-card.featured { + grid-column: 1 / -1; + max-width: 500px; + margin: 0 auto; + transform: scale(1); + } +} + +@media (max-width: 768px) { + body { + font-size: 16px; + } + + h2 { + font-size: 2.2rem; + } + + .section-subtitle { + font-size: 1.1rem; + } + + .navbar { + padding: 1rem; + } + + .menu-toggle { + display: block; + z-index: 1001; + } + + .nav-links { + display: flex; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100vh; + background: white; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 2rem; + transform: translateX(100%); + transition: transform 0.3s ease-in-out; + z-index: 1000; + } + + .nav-links.active { + transform: translateX(0); + } + + .hero { + padding: 6rem 1rem 4rem; + min-height: 80vh; + } + + .hero h1 { + font-size: 2.5rem; + } + + .hero-text { + font-size: 1.2rem; + } + + .hero-features { + flex-direction: column; + gap: 1rem; + } + + .package-grid { + grid-template-columns: 1fr; + } + + .package-card.featured { + max-width: 100%; + transform: scale(1); + } + + .benefits-grid { + grid-template-columns: 1fr; + } + + .process-steps { + grid-template-columns: 1fr; + } + + .about-content { + grid-template-columns: 1fr; + } + + .footer-content { + grid-template-columns: 1fr; + text-align: center; + } + + .footer-bottom { + flex-direction: column; + gap: 1rem; + } + + #chat-widget-container { + width: 100%; + height: 100%; + bottom: 0; + right: 0; + border-radius: 0; + max-height: 100%; + } + + #chat-widget-button { + bottom: 20px; + right: 20px; + } +} + +/* --- Animations --- */ +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +}""" + + diff --git a/debug_webhook.html b/debug_webhook.html new file mode 100644 index 0000000..17028db --- /dev/null +++ b/debug_webhook.html @@ -0,0 +1,155 @@ + + + + + n8n Webhook Debugger (Popravljena Verzija) + + + + +

n8n Webhook Debugger (Popravljena Verzija)

+

Ta stran bo testirala klic na vaš n8n webhook s pravilnim formatom podatkov.

+

Pričakujemo, da bo Test 1 zdaj uspešen in vrnil `Status: 200 OK`.

+ +
+ + + +
+ +

Rezultati:

+

+
+    
+
+
\ No newline at end of file
diff --git a/export_code.sh b/export_code.sh
new file mode 100755
index 0000000..1a37df6
--- /dev/null
+++ b/export_code.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+# Nastavitev imena izhodne datoteke
+OUTPUT_FILE="code_export.txt"
+
+# Odstrani izhodno datoteko, če že obstaja, da začnemo s čisto datoteko
+if [ -f "$OUTPUT_FILE" ]; then
+    rm "$OUTPUT_FILE"
+fi
+
+# Poišči vse datoteke, razen skritih datotek in določenih map (npr. node_modules).
+# Dodane so izjeme za slike, videoposnetke, PDF-je, arhive in druge binarne datoteke
+# neposredno v ukaz 'find' za boljšo zmogljivost.
+find . -type f \
+    -not -path "*/\.*" \
+    -not -path "*node_modules*" \
+    -not -path "*vendor*" \
+    -not -path "*dist*" \
+    -not -path "*build*" \
+    -not -path "*/images/*" \
+    -not -iname "*.jpg" -not -iname "*.jpeg" \
+    -not -iname "*.png" -not -iname "*.gif" \
+    -not -iname "*.bmp" -not -iname "*.tiff" \
+    -not -iname "*.svg" -not -iname "*.ico" \
+    -not -iname "*.webp" \
+    -not -iname "*.mp4" -not -iname "*.mov" \
+    -not -iname "*.avi" -not -iname "*.mkv" \
+    -not -iname "*.webm" \
+    -not -iname "*.mp3" -not -iname "*.wav" \
+    -not -iname "*.ogg" -not -iname "*.flac" \
+    -not -iname "*.pdf" \
+    -not -iname "*.zip" \
+    -not -iname "*.tar" \
+    -not -iname "*.gz" \
+    -not -iname "*.bz2" \
+    -not -iname "*.rar" \
+    -not -iname "*.7z" \
+    -not -iname "*.doc" -not -iname "*.docx" \
+    -not -iname "*.xls" -not -iname "*.xlsx" \
+    -not -iname "*.ppt" -not -iname "*.pptx" \
+    -not -iname "*.eot" -not -iname "*.ttf" \
+    -not -iname "*.woff" -not -iname "*.woff2" \
+    | sort | while read -r file; do
+    
+    # Preskoči samo izhodno datoteko in to skripto
+    if [[ "$file" == "./$OUTPUT_FILE" || "$file" == "./export_code.sh" ]]; then
+        continue
+    fi
+    
+    # Dodatna varnostna preverba: preskoči slikovne datoteke po MIME tipu
+    if file --mime-type -b "$file" | grep -qiE '^(image)/'; then
+        continue
+    fi
+    
+    # Dodaj ime datoteke in njeno vsebino v izhodno datoteko
+    echo "\"$file\" : " >> "$OUTPUT_FILE"
+    echo "\"\"\""  >> "$OUTPUT_FILE"
+    cat "$file" >> "$OUTPUT_FILE"
+    echo "\"\"\""  >> "$OUTPUT_FILE"
+    echo "" >> "$OUTPUT_FILE"
+    echo "" >> "$OUTPUT_FILE"
+done
+
+echo "Izvoz kode končan. Vsebina je shranjena v datoteko $OUTPUT_FILE"
diff --git a/images/hero-bg-ai.webp b/images/hero-bg-ai.webp
new file mode 100644
index 0000000..970382c
Binary files /dev/null and b/images/hero-bg-ai.webp differ
diff --git a/images/logo-white.png b/images/logo-white.png
new file mode 100644
index 0000000..3cf08c7
Binary files /dev/null and b/images/logo-white.png differ
diff --git a/images/logo.png b/images/logo.png
new file mode 100644
index 0000000..8dfc2ef
Binary files /dev/null and b/images/logo.png differ
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..f3bc894
--- /dev/null
+++ b/index.html
@@ -0,0 +1,397 @@
+
+
+
+    
+    
+    
+    
+    AI Mojster - AI Chatboti in Avtomatizacija za Vaše Podjetje
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+    
+    
+    
+    
+    
+    
+
+
+    
+ +
+ +
+
+

Preobrazite Svoje Poslovanje z Močjo Umetne Inteligence

+

Nudimo napredne AI chatbote in avtomatizacijo po meri, ki znižujejo stroške, povečujejo prodajo in zagotavljajo podporo 24/7.

+
+
+ + Podpora 24/7 +
+
+ + Povečana Prodaja +
+
+ + Avtomatizacija Procesov +
+
+ + Znižanje Stroškov +
+
+ Odkrijte Svojo AI Rešitev +
+ +
+
+

Naše Rešitve za Vaš Uspeh

+

Specializirani smo za dve ključni področji, ki prinašata takojšnje in merljive rezultate za vaše podjetje.

+
+
+

AI Chatboti po Meri

+

Pozabite na generične odgovore. Razvijemo inteligentne chatbote, ki razumejo vaše stranke, odgovarjajo na njihova vprašanja v realnem času, zbirajo povpraševanja in jih vodijo skozi nakupni proces. Izboljšajte uporabniško izkušnjo in pretvorite obiskovalce v zveste stranke.

+
+
+

AI Avtomatizacija Procesov

+

Osvobodite svojo ekipo ponavljajočih se nalog. Povežemo vaše aplikacije (CRM, e-pošta, socialna omrežja) v pametne delovne tokove, ki delujejo samodejno. Od avtomatiziranega pošiljanja ponudb do sinhronizacije podatkov – prihranite čas, zmanjšajte napake in se osredotočite na rast.

+
+
+
+
+ +
+

Izberite Paket, ki Poganja Vašo Rast

+

Pregledne cene, brez skritih stroškov. Naložba v AI se vam bo večkratno povrnila.

+
+ Mesečni najem + + Letni najem Prihranite do 20% +
+
+
+

AI Asistent

+

Za podjetja, ki želijo avtomatizirati podporo in zbirati kontakte.

+
+
39 €/mesec
+ 47,58 € z DDV +
+
    +
  • Chatbot z odgovori na pogosta vprašanja
  • +
  • Zbiranje kontaktnih podatkov (leadov)
  • +
  • Namestitev na vašo spletno stran
  • +
  • Osnovno poročanje o pogovorih
  • +
  • E-mail podpora
  • +
+ Izberi Asistenta +
+ + + +
+

AI Avtomatizacija

+

Za podjetja, ki želijo celovito avtomatizacijo internih in zunanjih procesov.

+
+
149 €/mesec
+ 181,78 € z DDV +
+
    +
  • Vse iz paketa AI Partner
  • +
  • Kompleksni avtomatizacijski tokovi (n8n)
  • +
  • API integracije po meri
  • +
  • Povezava z e-poštnimi orodji
  • +
  • Avtomatizirano upravljanje s podatki
  • +
  • Prioritetna tehnična podpora
  • +
+ Izberi Avtomatizacijo +
+
+
+ +
+
+

Prednosti Umetne Inteligence za Vas

+

To niso le tehnične rešitve. To so konkretne koristi, ki jih bo vaše podjetje občutilo takoj.

+
+
+
+

Neprekinjena Dosegljivost 24/7

+

Vaš AI asistent nikoli ne spi. Strankam je na voljo podnevi in ponoči, med vikendi in prazniki, kar zagotavlja takojšnjo podporo in večje zadovoljstvo.

+
+
+
+

Takojšnji Prihranki

+

Zmanjšajte stroške za podporo strankam za do 30%. Avtomatizirajte odgovore na ponavljajoča se vprašanja in sprostite svojo ekipo za naloge, ki prinašajo večjo vrednost.

+
+
+
+

Povečana Prodaja in Leadi

+

AI chatbot aktivno nagovarja obiskovalce, jih kvalificira in zbira njihove podatke. Nikoli več ne zamudite priložnosti za posel, tudi ko niste na voljo.

+
+
+
+

Inteligentno Zbiranje Podatkov

+

Spoznajte svoje stranke bolje kot kdajkoli prej. Chatbot zbira ključne informacije o njihovih željah in težavah, kar vam omogoča sprejemanje pametnejših poslovnih odločitev.

+
+
+
+

Nič Več Ponavljajočega Dela

+

Ročno prepisovanje podatkov, pošiljanje istih e-mailov in ostala dolgočasna opravila postanejo preteklost. Osredotočite se na tisto, kar je resnično pomembno – rast vašega posla.

+
+
+
+

Izjemna Uporabniška Izkušnja

+

Stranke cenijo hitre in natančne odgovore. Z AI zagotovite dosledno in profesionalno komunikacijo, ki gradi zaupanje in lojalnost vaši blagovni znamki.

+
+
+
+
+ +
+
+

Od Ideje do Rezultatov v 4 Korakih

+

Naš proces je preprost, pregleden in osredotočen na doseganje vaših ciljev.

+
+
+
1
+

Posvet in Analiza

+

Skupaj definiramo vaše cilje in analiziramo procese, ki so zreli za avtomatizacijo.

+
+
+
2
+

Načrtovanje in Razvoj

+

Zasnovo chatbota ali avtomatizacije prilagodimo vašim specifičnim potrebam in blagovni znamki.

+
+
+
3
+

Implementacija in Testiranje

+

Rešitev integriramo v vaše okolje in jo temeljito stestiramo za brezhibno delovanje.

+
+
+
4
+

Zagon in Optimizacija

+

Po zagonu spremljamo delovanje in ga nenehno izboljšujemo za doseganje maksimalnih rezultatov.

+
+
+
+
+ +
+
+

Kdo Smo?

+
+
+

Vaši Strokovnjaki za Umetno Inteligenco

+

Smo ekipa navdušencev nad tehnologijo, ki verjame, da umetna inteligenca ni več prihodnost, ampak sedanjost. Naše poslanstvo je, da napredne AI rešitve približamo podjetjem vseh velikosti in jim pomagamo postati učinkovitejši, bolj konkurenčni in uspešnejši.

+ +

Zaupajo nam uspešni:

+ + + Naredimo korak naprej skupaj! +
+
+
+ +

Strateško Načrtovanje

+

Ne prodajamo le tehnologije, ampak celovite rešitve, ki rešujejo vaše poslovne izzive.

+
+
+ +

Razvoj po Meri

+

Vsak chatbot in avtomatizacija sta 100% prilagojena vašemu poslu in ciljem.

+
+
+ +

Zanesljiva Podpora

+

Smo vaš dolgoročni partner. Nudimo redno vzdrževanje, optimizacijo in tehnično podporo.

+
+
+
+
+
+ +
+

Pripravljeni na Prihodnost?

+

Naredite prvi korak k pametnejšemu poslovanju. Kontaktirajte nas za neobvezujoč pogovor in odkrijte, kako lahko AI pomaga tudi vam.

+

Izpolnite obrazec ali nam pišite na info@aimojster.si

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..d65e6b0 --- /dev/null +++ b/script.js @@ -0,0 +1,222 @@ +/* + GENERAL JAVASCRIPT FOR AIMOJSTER.SI + Last Updated: 16. September 2025 + Author: Gemini AI for AIMojster.si + + This script handles general functionalities for the website, including: + - Mobile navigation menu. + - Smooth scrolling for anchor links. + - Billing toggle (monthly/yearly) for pricing packages. + - Contact form submission. + - Intersection Observer for animations. +*/ + +document.addEventListener('DOMContentLoaded', function() { + + //====================================================================== + // 1. MOBILNI MENI (NAVIGATION) + //====================================================================== + const menuToggle = document.querySelector('.menu-toggle'); + const navLinks = document.querySelector('.nav-links'); + + if (menuToggle && navLinks) { + menuToggle.addEventListener('click', function(e) { + e.stopPropagation(); + navLinks.classList.toggle('active'); + const icon = menuToggle.querySelector('i'); + if (icon) { + icon.classList.toggle('fa-bars'); + icon.classList.toggle('fa-times'); + } + }); + + document.addEventListener('click', function(e) { + const isClickInsideNav = navLinks.contains(e.target); + const isClickOnToggle = menuToggle.contains(e.target); + if (!isClickInsideNav && !isClickOnToggle && navLinks.classList.contains('active')) { + navLinks.classList.remove('active'); + const icon = menuToggle.querySelector('i'); + if (icon) { + icon.classList.remove('fa-times'); + icon.classList.add('fa-bars'); + } + } + }); + + navLinks.querySelectorAll('a').forEach(link => { + link.addEventListener('click', () => { + if (navLinks.classList.contains('active')) { + navLinks.classList.remove('active'); + const icon = menuToggle.querySelector('i'); + if (icon) { + icon.classList.remove('fa-times'); + icon.classList.add('fa-bars'); + } + } + }); + }); + } + + //====================================================================== + // 2. GLADKO DRSENJE (SMOOTH SCROLLING) + //====================================================================== + document.querySelectorAll('a[href^="#"]').forEach(anchor => { + anchor.addEventListener('click', function (e) { + e.preventDefault(); + const targetId = this.getAttribute('href'); + const targetElement = document.querySelector(targetId); + + if (targetElement) { + targetElement.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + } + }); + }); + + + //====================================================================== + // 3. PREKLOP MED MESEČNIM IN LETNIM NAJEMOM (BILLING TOGGLE) + //====================================================================== + const billingToggle = document.getElementById('billing-toggle'); + if (billingToggle) { + const packagePrices = { + 'asistent': { monthly: 39, yearly: 29 }, + 'partner': { monthly: 89, yearly: 69 }, + 'avtomatizacija': { monthly: 149, yearly: 119 } + }; + + const updatePrices = (isYearly) => { + document.querySelectorAll('.package-card').forEach(card => { + const packageName = card.dataset.package; + if (!packageName || !packagePrices[packageName]) return; + + const priceValue = isYearly ? packagePrices[packageName].yearly : packagePrices[packageName].monthly; + const priceWithVat = (priceValue * 1.22).toFixed(2).replace('.', ','); + + const priceElement = card.querySelector('.price'); + const vatElement = card.querySelector('.vat-price'); + + if (priceElement) { + priceElement.innerHTML = `${priceValue} €/mesec`; + } + if (vatElement) { + vatElement.textContent = `${priceWithVat} € z DDV`; + } + }); + updateContactFormPackageOptions(isYearly); + }; + + const updateContactFormPackageOptions = (isYearly) => { + const packageSelect = document.getElementById('package'); + if (!packageSelect) return; + + Array.from(packageSelect.options).forEach(option => { + const packageName = option.value; + if (packageName && packagePrices[packageName]) { + const price = isYearly ? packagePrices[packageName].yearly : packagePrices[packageName].monthly; + const packageTitle = option.text.split(' - ')[0]; + option.text = `${packageTitle} - ${price}€/mesec`; + } + }); + }; + + updatePrices(billingToggle.checked); + billingToggle.addEventListener('change', (e) => { + updatePrices(e.target.checked); + }); + } + + //====================================================================== + // 4. IZBIRA PAKETA IN POSODOBITEV KONTAKTNEGA OBRAZCA + //====================================================================== + document.querySelectorAll('.package-button').forEach(button => { + button.addEventListener('click', function() { + const packageCard = this.closest('.package-card'); + if (packageCard) { + const selectedPackage = packageCard.dataset.package; + const contactFormPackageSelect = document.getElementById('package'); + if (contactFormPackageSelect) { + contactFormPackageSelect.value = selectedPackage; + } + } + }); + }); + + + //====================================================================== + // 5. POŠILJANJE KONTAKTNEGA OBRAZCA (FORM SUBMISSION) + //====================================================================== + const contactForm = document.getElementById('contact-form'); + if (contactForm) { + contactForm.addEventListener('submit', async function(e) { + e.preventDefault(); + const name = document.getElementById('name').value.trim(); + const email = document.getElementById('email').value.trim(); + const message = document.getElementById('message').value.trim(); + const selectedPackage = document.getElementById('package').value; + const submitButton = this.querySelector('.submit-button'); + + if (!name || !email || !message || !selectedPackage) { + alert('Prosimo, izpolnite vsa obvezna polja.'); + return; + } + + const originalButtonText = submitButton.textContent; + submitButton.textContent = 'Pošiljanje...'; + submitButton.disabled = true; + + const formData = { + name: name, + email: email, + phone: document.getElementById('phone').value.trim(), + package: selectedPackage, + message: message + }; + + try { + const response = await fetch('send_email.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(formData) + }); + + if (!response.ok) throw new Error('Težava z omrežno povezavo.'); + + const result = await response.json(); + if (result.success) { + alert('Hvala za vaše sporočilo! Odgovorili vam bomo v najkrajšem možnem času.'); + contactForm.reset(); + } else { + throw new Error(result.error || 'Prišlo je do napake pri pošiljanju sporočila.'); + } + } catch (error) { + console.error('Error:', error); + alert('Napaka: ' + error.message); + } finally { + submitButton.textContent = originalButtonText; + submitButton.disabled = false; + } + }); + } + + //====================================================================== + // 6. ANIMACIJE OB DRSENJU (INTERSECTION OBSERVER) + //====================================================================== + const animatedElements = document.querySelectorAll('.fade-in'); + if ('IntersectionObserver' in window) { + const observer = new IntersectionObserver((entries, observer) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + entry.target.classList.add('visible'); + observer.unobserve(entry.target); + } + }); + }, { threshold: 0.1 }); + animatedElements.forEach(el => observer.observe(el)); + } else { + animatedElements.forEach(el => el.classList.add('visible')); + } + +}); \ No newline at end of file diff --git a/send_email.php b/send_email.php new file mode 100644 index 0000000..396be44 --- /dev/null +++ b/send_email.php @@ -0,0 +1,127 @@ + false, 'error' => 'Napačna metoda zahteve. Dovoljena je samo metoda POST.']); + exit; // Takoj prekinemo izvajanje skripte. +} + +//====================================================================== +// 2. SPREJEM IN DEKODIRANJE PODATKOV +//====================================================================== + +// Preberemo необdelane podatke iz telesa zahteve (request body). +// To je potrebno, ker JavaScript pošilja podatke kot JSON, ne kot klasičen form-data. +$json_payload = file_get_contents('php://input'); + +// Dekodiramo JSON niz v PHP asociativno polje. +// Drugi parameter `true` zagotovi, da dobimo polje namesto objekta. +$data = json_decode($json_payload, true); + +// Preverimo, ali je prišlo do napake pri dekodiranju JSON-a. +if (json_last_error() !== JSON_ERROR_NONE) { + http_response_code(400); // Bad Request + echo json_encode(['success' => false, 'error' => 'Neveljaven JSON format podatkov.']); + exit; +} + +//====================================================================== +// 3. VALIDACIJA PREJETIH PODATKOV +//====================================================================== + +// Definiramo obvezna polja. +$required_fields = ['name', 'email', 'message', 'package']; +$errors = []; + +foreach ($required_fields as $field) { + if (empty($data[$field])) { + $errors[] = "Polje '{$field}' je obvezno."; + } +} + +// Posebej preverimo veljavnost e-poštnega naslova. +if (!empty($data['email']) && !filter_var($data['email'], FILTER_VALIDATE_EMAIL)) { + $errors[] = "Vneseni e-poštni naslov ni v veljavni obliki."; +} + +// Če so se pojavile napake pri validaciji, jih vrnemo odjemalcu. +if (!empty($errors)) { + http_response_code(400); // Bad Request + echo json_encode(['success' => false, 'error' => implode(' ', $errors)]); + exit; +} + +//====================================================================== +// 4. SANITIZACIJA PODATKOV IN PRIPRAVA SPREMENLJIVK +//====================================================================== + +// Sanitiziramo vse prejete podatke, da preprečimo XSS napade in druge zlorabe. +// Uporabimo htmlspecialchars za kodiranje posebnih znakov in trim za odstranitev presledkov. +$name = htmlspecialchars(trim($data['name'])); +$email = filter_var(trim($data['email']), FILTER_SANITIZE_EMAIL); +$phone = isset($data['phone']) ? htmlspecialchars(trim($data['phone'])) : 'Ni vneseno'; +$package = htmlspecialchars(trim($data['package'])); +$message = htmlspecialchars(trim($data['message'])); + + +//====================================================================== +// 5. SESTAVLJANJE IN POŠILJANJE E-POŠTNEGA SPOROČILA +//====================================================================== + +// --- Nastavitve E-pošte --- +$to_email = 'info@aimojster.si'; // **POMEMBNO: Vnesite vaš pravi e-poštni naslov!** +$subject = 'Novo povpraševanje s spletne strani AIMojster.si'; + +// --- Telo sporočila (Email Body) --- +// Uporabimo jasne oznake za preglednost. +$email_body = "Prejeli ste novo povpraševanje preko kontaktnega obrazca na spletni strani AIMojster.si.\n\n"; +$email_body .= "--------------------------------------------------\n"; +$email_body .= "Ime in priimek: " . $name . "\n"; +$email_body .= "E-poštni naslov: " . $email . "\n"; +$email_body .= "Telefonska številka: " . $phone . "\n"; +$email_body .= "Izbrani paket: " . $package . "\n\n"; +$email_body .= "Sporočilo:\n" . $message . "\n"; +$email_body .= "--------------------------------------------------\n"; +$email_body .= "To sporočilo je bilo poslano samodejno."; + +// --- Glave sporočila (Email Headers) --- +// Pravilno nastavljene glave so ključne za zanesljivo dostavo in preprečevanje, da bi sporočilo končalo v vsiljeni pošti. +$headers = "From: no-reply@aimojster.si\r\n"; // Uporabite naslov z vaše domene. +$headers .= "Reply-To: " . $email . "\r\n"; // To vam omogoča, da direktno odgovorite pošiljatelju. +$headers .= "Content-Type: text/plain; charset=UTF-8\r\n"; +$headers .= "X-Mailer: PHP/" . phpversion(); + +// --- Pošiljanje --- +// Uporabimo PHP funkcijo mail(). Če je pošiljanje uspešno, vrne true. +if (mail($to_email, $subject, $email_body, $headers)) { + // Pošiljanje je uspelo, vrnemo pozitiven odgovor. + echo json_encode(['success' => true]); +} else { + // Pošiljanje ni uspelo. Vrnemo napako. + http_response_code(500); // Internal Server Error + echo json_encode(['success' => false, 'error' => 'Napaka strežnika pri pošiljanju sporočila. Prosimo, poskusite kasneje.']); +} + +exit; // Zaključimo izvajanje skripte. + +?> \ No newline at end of file diff --git a/style.css b/style.css new file mode 100644 index 0000000..12c7a04 --- /dev/null +++ b/style.css @@ -0,0 +1,1127 @@ +/* + STYLESHEET FOR AIMOJSTER.SI + Last Updated: 16. September 2025 + Author: Gemini AI for AIMojster.si +*/ + +:root { + /* Tech & AI Inspired Color Scheme */ + --primary-color: #7B2DFF; /* Vibrant Purple */ + --secondary-color: #9A5BFF; /* Lighter Violet */ + --accent-color: #00F5D4; /* Bright Teal/Cyan */ + --accent-light: #70F8E3; /* Light Teal */ + --text-color: #1D2B48; /* Deep Blue-Black */ + --light-text: #6B7C93; /* Muted Gray-Blue */ + --background: #ffffff; /* Pure White */ + --light-background: #F9F7FF; /* Very Light Purple Tint */ + --border-color: #EAE6FF; /* Light Purple-Gray Border */ + --success-color: #4CD5B0; /* Minty Green */ + + --shadow: 0 4px 10px rgba(123, 45, 255, 0.08); + --shadow-lg: 0 10px 25px rgba(123, 45, 255, 0.12); + + --gradient-primary: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + --gradient-accent: linear-gradient(135deg, var(--accent-color), var(--accent-light)); +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + font-family: 'Montserrat', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; + line-height: 1.6; + color: var(--text-color); + background-color: var(--background); +} + +/* --- Header & Navigation --- */ +.header { + background: var(--background); + box-shadow: var(--shadow); + position: fixed; + width: 100%; + top: 0; + z-index: 1000; +} + +.navbar { + max-width: 1200px; + margin: 0 auto; + padding: 1rem 1.5rem; + display: flex; + justify-content: space-between; + align-items: center; +} + +.logo { + height: 20px; + display: flex; + align-items: center; +} + +.logo a { + height: 100%; + display: flex; + align-items: center; + text-decoration: none; +} + +.logo img { + height: 100%; + width: auto; +} + +.nav-links { + display: flex; + gap: 2rem; + align-items: center; +} + +.nav-links a { + text-decoration: none; + color: var(--text-color); + font-weight: 500; + transition: color 0.3s ease; + position: relative; + padding: 5px 0; +} + +.nav-links a::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 0; + height: 2px; + background: var(--accent-color); + transition: width 0.3s ease; +} + +.nav-links a:hover { + color: var(--primary-color); +} + +.nav-links a:hover::after { + width: 100%; +} + +.phone-number { + font-weight: 600; + color: var(--primary-color); + display: flex; + align-items: center; + gap: 0.5rem; +} + +.language-switch { + display: flex; + align-items: center; + justify-content: center; + background: var(--light-background); + color: var(--primary-color); + border-radius: 2rem; + padding: 0.5rem 1rem; + font-weight: 600; + transition: all 0.3s ease; + margin-left: 0.5rem; +} + +.language-switch i { + margin-right: 0.5rem; +} + +.language-switch:hover { + background: var(--primary-color); + color: white; + transform: translateY(-2px); + box-shadow: var(--shadow); +} + +/* --- Hero Section --- */ +.hero { + padding: 8rem 1rem 4rem; + text-align: center; + background: linear-gradient(rgba(29, 43, 72, 0.7), rgba(29, 43, 72, 0.6)), url('images/hero-bg-ai.webp'); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + min-height: 90vh; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 2.5rem; + position: relative; + overflow: hidden; +} + +.hero h1 { + font-size: 4.5rem; + max-width: 900px; + margin: 0 auto; + line-height: 1.2; + color: white; + font-weight: 800; + letter-spacing: -1px; + animation: fadeInUp 1s ease-out; +} + +.hero-text { + max-width: 800px; + margin: 0 auto; + font-size: 1.5rem; + color: rgba(255, 255, 255, 0.9); + line-height: 1.8; + font-weight: 400; + animation: fadeInUp 1s ease-out 0.2s backwards; +} + +.hero-features { + display: flex; + gap: 2rem; + margin-top: 2rem; + flex-wrap: wrap; + justify-content: center; + animation: fadeInUp 1s ease-out 0.6s backwards; +} + +.hero-feature { + display: flex; + align-items: center; + gap: 0.75rem; + color: var(--text-color); + font-weight: 500; + padding: 0.75rem 1.5rem; + background: rgba(255, 255, 255, 0.95); + border: 1px solid rgba(255, 255, 255, 0.2); + border-radius: 1rem; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); + backdrop-filter: blur(10px); + transition: all 0.3s ease; +} + +.hero-feature:hover { + transform: translateY(-5px) scale(1.05); + box-shadow: 0 6px 30px rgba(0, 0, 0, 0.15); +} + +.hero-feature i { + color: var(--primary-color); + font-size: 1.5rem; +} + +.hero .cta-button { + font-size: 1.2rem; + padding: 1.2rem 3.5rem; + border-radius: 50px; + background: var(--gradient-primary); + color: white; + text-decoration: none; + box-shadow: var(--shadow); + animation: fadeInUp 1s ease-out 0.4s backwards; + transition: all 0.3s ease; + border: none; + font-weight: 600; +} + +.hero .cta-button:hover { + transform: translateY(-3px); + box-shadow: var(--shadow-lg); + background: var(--gradient-accent); + color: var(--text-color); +} + +/* --- General Section Styling --- */ +section { + padding: 6rem 1.5rem; +} + +.container { + max-width: 1200px; + margin: 0 auto; +} + +h2 { + text-align: center; + margin-bottom: 1.5rem; + font-size: 2.8rem; + color: var(--text-color); + font-weight: 700; +} + +.section-subtitle { + text-align: center; + color: var(--light-text); + font-size: 1.2rem; + max-width: 700px; + margin: 0 auto 4rem; + line-height: 1.6; +} + + +/* --- Packages Section --- */ +.packages { + background: var(--light-background); +} + +.billing-toggle { + text-align: center; + margin-bottom: 3rem; + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; +} + +.billing-toggle span { + font-weight: 500; +} + +.toggle-switch { + position: relative; + display: inline-block; + width: 60px; + height: 30px; +} + +.toggle-switch input { + opacity: 0; + width: 0; + height: 0; +} + +.toggle-slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: var(--secondary-color); + transition: .4s; + border-radius: 34px; +} + +.toggle-slider:before { + position: absolute; + content: ""; + height: 22px; + width: 22px; + left: 4px; + bottom: 4px; + background-color: white; + transition: .4s; + border-radius: 50%; +} + +input:checked + .toggle-slider { + background: var(--gradient-accent); +} + +input:checked + .toggle-slider:before { + transform: translateX(30px); +} + +.yearly-discount { + background: var(--gradient-accent); + color: var(--text-color); + padding: 0.4rem 1rem; + border-radius: 1rem; + font-size: 0.8rem; + margin-left: 0.5rem; + font-weight: 600; +} + +.package-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 2rem; + max-width: 1200px; + margin: 0 auto; +} + +.package-card { + background: white; + border: 1px solid var(--border-color); + border-radius: 1.5rem; + padding: 2.5rem 2rem; + text-align: center; + position: relative; + transition: all 0.3s ease; + display: flex; + flex-direction: column; + box-shadow: var(--shadow); +} + +.package-card:hover { + transform: translateY(-10px); + box-shadow: var(--shadow-lg); + border-color: var(--primary-color); +} + +.package-card h3 { + font-size: 1.8rem; + color: var(--text-color); +} + +.package-card .subtitle { + font-size: 1.1rem; + color: var(--light-text); + margin: 0.5rem 0 1rem; + min-height: 44px; /* Align heights */ +} + +.price-period { + margin: 1rem 0; +} + +.price { + font-size: 3.5rem; + font-weight: 700; + color: var(--primary-color); + line-height: 1; +} + +.price span { + font-size: 1.2rem; + color: var(--light-text); + margin-left: 0.3rem; + font-weight: 400; +} + +.vat-price { + font-size: 0.9rem; + color: var(--light-text); + display: block; + margin-top: 0.5rem; +} + +.package-card ul { + list-style: none; + margin: 1.5rem 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 1rem; + text-align: left; + flex-grow: 1; +} + +.package-card li { + font-size: 1rem; + color: var(--text-color); + display: flex; + align-items: flex-start; + gap: 0.75rem; + line-height: 1.4; +} + +.package-card li::before { + content: "✓"; + color: var(--success-color); + font-weight: bold; + font-size: 1.2rem; + min-width: 20px; +} + +.package-button { + display: inline-block; + padding: 1rem 2.5rem; + background: var(--gradient-primary); + color: white; + text-decoration: none; + border-radius: 50px; + font-weight: 600; + font-size: 1.1rem; + transition: all 0.3s ease; + margin-top: auto; + border: none; +} + +.package-button:hover { + background: var(--gradient-accent); + color: var(--text-color); + transform: translateY(-2px); + box-shadow: var(--shadow); +} + +.package-card.featured { + border: 2px solid var(--primary-color); + transform: scale(1.05); + z-index: 2; +} + +.package-card.featured .package-button { + background: var(--gradient-primary); +} + +.popular-badge { + position: absolute; + top: -15px; + left: 50%; + transform: translateX(-50%); + background: var(--gradient-primary); + color: white; + padding: 0.7rem 2rem; + border-radius: 50px; + font-size: 1rem; + font-weight: 600; + white-space: nowrap; + box-shadow: var(--shadow); +} + +/* --- Why Us / Benefits Section --- */ +.why-us { + background: var(--background); +} + +.benefits-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: 2rem; +} + +.benefit-card { + background: var(--light-background); + border: 1px solid var(--border-color); + border-radius: 1.5rem; + padding: 2rem; + transition: all 0.3s ease; +} + +.benefit-card:hover { + transform: translateY(-5px); + box-shadow: var(--shadow); + background: white; +} + +.benefit-icon { + width: 70px; + height: 70px; + background: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 1.5rem; + box-shadow: var(--shadow); +} + +.benefit-icon i { + font-size: 2rem; + color: var(--primary-color); +} + +.benefit-card h3 { + color: var(--text-color); + font-size: 1.5rem; + margin-bottom: 0.5rem; +} + +.benefit-card p { + color: var(--light-text); + font-size: 1.1rem; + line-height: 1.6; +} + +/* --- Process Section --- */ +.process { + background: var(--light-background); +} + +.process-steps { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 2rem; + max-width: 1200px; + margin: 0 auto; + position: relative; +} + +.step { + text-align: center; + padding: 2rem; +} + +.step-number { + width: 4.5rem; + height: 4.5rem; + background: var(--gradient-accent); + color: var(--text-color); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 1.5rem; + font-size: 2rem; + font-weight: 700; + box-shadow: var(--shadow); + transition: transform 0.3s ease; +} + +.step:hover .step-number { + transform: scale(1.1) rotate(10deg); +} + +.step h3 { + font-size: 1.4rem; + margin-bottom: 0.5rem; +} + +.step p { + color: var(--light-text); +} + +/* --- About Section --- */ +.about { + background: white; +} + +.about-content { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 4rem; + align-items: center; +} + +.about-text h3 { + font-size: 1.8rem; + color: var(--primary-color); + margin-bottom: 1rem; +} + +.about-text p { + font-size: 1.1rem; + line-height: 1.8; + color: var(--light-text); + margin-bottom: 1.5rem; +} + +.client-list { + list-style: none; + padding: 0; + margin-top: 2rem; +} + +.client-list li { + margin-bottom: 1rem; + font-size: 1.1rem; +} + +.client-list a { + color: var(--primary-color); + text-decoration: none; + font-weight: 600; +} + +.about-cta { + display: inline-block; + margin-top: 1.5rem; + padding: 1rem 2rem; + background: var(--gradient-primary); + color: white; + text-decoration: none; + border-radius: 50px; + font-weight: 600; + transition: all 0.3s ease; +} + +.about-cta:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-lg); +} + +/* --- Contact Section --- */ +.contact { + background: var(--light-background); +} + +.contact-text { + max-width: 600px; + margin: 0 auto 2rem; + font-size: 1.2rem; + line-height: 1.8; + color: var(--light-text); +} + +.contact-options { + text-align: center; + margin-bottom: 2rem; + color: var(--light-text); +} + +.contact-options a { + color: var(--primary-color); + text-decoration: none; + font-weight: 500; + transition: color 0.3s ease; +} + +.contact-options a:hover { + color: var(--accent-color); +} + +.contact-form { + max-width: 600px; + margin: 0 auto; + padding: 3rem; + background: var(--background); + border-radius: 20px; + box-shadow: var(--shadow-lg); + display: grid; + gap: 1.5rem; + border: 1px solid var(--border-color); +} + +.form-group { + text-align: left; +} + +.form-group label { + display: block; + margin-bottom: 0.5rem; + color: var(--text-color); + font-weight: 500; +} + +.form-group input, +.form-group select, +.form-group textarea { + width: 100%; + padding: 1rem; + border: 1px solid var(--border-color); + border-radius: 12px; + font-size: 1rem; + color: var(--text-color); + background: var(--light-background); + transition: all 0.3s ease; +} + +.form-group input:focus, +.form-group select:focus, +.form-group textarea:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(123, 45, 255, 0.1); + background: white; +} + +.form-group textarea { + min-height: 150px; + resize: vertical; +} + +.submit-button { + padding: 1.2rem 2.5rem; + background: var(--gradient-primary); + color: white; + border: none; + border-radius: 12px; + font-weight: 600; + font-size: 1.1rem; + cursor: pointer; + transition: all 0.3s ease; + margin-top: 1rem; +} + +.submit-button:hover { + background: var(--gradient-accent); + color: var(--text-color); + transform: translateY(-2px); + box-shadow: var(--shadow); +} + + +/* --- Footer --- */ +.footer { + background: var(--text-color); + color: white; + padding: 4rem 2rem 2rem; +} + +.footer-content { + max-width: 1200px; + margin: 0 auto; + display: grid; + grid-template-columns: 2fr 1fr 1.5fr; + gap: 4rem; + margin-bottom: 3rem; +} + +.footer-logo img { + height: 20px; + margin-bottom: 1rem; +} + +.footer-logo p { + color: rgba(255, 255, 255, 0.8); +} + +.footer h4 { + color: white; + font-size: 1.1rem; + margin-bottom: 1.5rem; + font-weight: 600; +} + +.footer-links { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.footer-links a { + color: rgba(255, 255, 255, 0.8); + text-decoration: none; + transition: color 0.3s ease; +} + +.footer-links a:hover { + color: var(--accent-color); +} + +.contact-methods a { + color: rgba(255, 255, 255, 0.8); + text-decoration: none; + transition: color 0.3s ease; + display: flex; + align-items: center; + gap: 0.75rem; + margin-bottom: 0.75rem; +} + +.contact-methods a:hover { + color: var(--accent-color); +} + +.footer-bottom { + max-width: 1200px; + margin: 0 auto; + padding-top: 2rem; + border-top: 1px solid rgba(255, 255, 255, 0.1); + display: flex; + justify-content: space-between; + align-items: center; + color: rgba(255, 255, 255, 0.6); + font-size: 0.9rem; +} + +.legal-links { + display: flex; + gap: 2rem; +} + +.legal-links a { + color: rgba(255, 255, 255, 0.6); + text-decoration: none; + transition: color 0.3s ease; +} + +.legal-links a:hover { + color: white; +} + +/* --- Chatbot Widget --- */ +#chat-widget-button { + position: fixed; + bottom: 25px; + right: 25px; + width: 60px; + height: 60px; + background: var(--gradient-primary); + border-radius: 50%; + border: none; + cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); + z-index: 998; + transition: transform 0.3s ease, box-shadow 0.3s ease; +} + +#chat-widget-button:hover { + transform: scale(1.1); + box-shadow: var(--shadow-lg); +} + +#chat-widget-button img { + width: 32px; + height: 32px; +} + +#chat-widget-container { + position: fixed; + bottom: 100px; + right: 25px; + width: 370px; + max-width: 90vw; + height: 70vh; + max-height: 600px; + background: white; + border-radius: 15px; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); + display: flex; + flex-direction: column; + overflow: hidden; + z-index: 999; + transform-origin: bottom right; + transition: transform 0.3s ease, opacity 0.3s ease; +} + +#chat-widget-container.hidden { + transform: scale(0); + opacity: 0; + pointer-events: none; +} + +.chat-header { + background: var(--gradient-primary); + color: white; + padding: 1rem; + display: flex; + justify-content: space-between; + align-items: center; +} + +.chat-header h3 { + font-size: 1.1rem; + font-weight: 600; + margin: 0; +} + +#close-chat-btn { + background: none; + border: none; + color: white; + font-size: 1.8rem; + cursor: pointer; + line-height: 1; + opacity: 0.8; + transition: opacity 0.2s ease; +} + +#close-chat-btn:hover { + opacity: 1; +} + +#chat-messages { + flex-grow: 1; + padding: 1rem; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.chat-message { + padding: 0.75rem 1rem; + border-radius: 18px; + max-width: 80%; + line-height: 1.5; +} + +.bot-message { + background-color: var(--light-background); + color: var(--text-color); + border-bottom-left-radius: 4px; + align-self: flex-start; +} + +.user-message { + background-color: var(--primary-color); + color: white; + border-bottom-right-radius: 4px; + align-self: flex-end; +} + +.typing-indicator { + align-self: flex-start; + color: var(--light-text); + font-style: italic; + font-size: 0.9rem; +} + +#chat-input-form { + display: flex; + padding: 1rem; + border-top: 1px solid var(--border-color); +} + +#chat-input { + flex-grow: 1; + border: 1px solid var(--border-color); + border-radius: 50px; + padding: 0.75rem 1rem; + font-size: 1rem; + transition: border-color 0.2s; +} + +#chat-input:focus { + outline: none; + border-color: var(--primary-color); +} + +#chat-input-form button { + background: var(--primary-color); + color: white; + border: none; + border-radius: 50%; + width: 45px; + height: 45px; + margin-left: 0.5rem; + cursor: pointer; + font-size: 1.2rem; + transition: background-color 0.2s; +} + +#chat-input-form button:hover { + background-color: var(--secondary-color); +} + + +/* --- Mobile Menu & Responsive --- */ +.menu-toggle { + display: none; + font-size: 1.5rem; + color: var(--text-color); + cursor: pointer; +} + +@media (max-width: 992px) { + .package-grid { + grid-template-columns: 1fr 1fr; + } + .package-card.featured { + grid-column: 1 / -1; + max-width: 500px; + margin: 0 auto; + transform: scale(1); + } +} + +@media (max-width: 768px) { + body { + font-size: 16px; + } + + h2 { + font-size: 2.2rem; + } + + .section-subtitle { + font-size: 1.1rem; + } + + .navbar { + padding: 1rem; + } + + .menu-toggle { + display: block; + z-index: 1001; + } + + .nav-links { + display: flex; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100vh; + background: white; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 2rem; + transform: translateX(100%); + transition: transform 0.3s ease-in-out; + z-index: 1000; + } + + .nav-links.active { + transform: translateX(0); + } + + .hero { + padding: 6rem 1rem 4rem; + min-height: 80vh; + } + + .hero h1 { + font-size: 2.5rem; + } + + .hero-text { + font-size: 1.2rem; + } + + .hero-features { + flex-direction: column; + gap: 1rem; + } + + .package-grid { + grid-template-columns: 1fr; + } + + .package-card.featured { + max-width: 100%; + transform: scale(1); + } + + .benefits-grid { + grid-template-columns: 1fr; + } + + .process-steps { + grid-template-columns: 1fr; + } + + .about-content { + grid-template-columns: 1fr; + } + + .footer-content { + grid-template-columns: 1fr; + text-align: center; + } + + .footer-bottom { + flex-direction: column; + gap: 1rem; + } + + #chat-widget-container { + width: 100%; + height: 100%; + bottom: 0; + right: 0; + border-radius: 0; + max-height: 100%; + } + + #chat-widget-button { + bottom: 20px; + right: 20px; + } +} + +/* --- Animations --- */ +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} \ No newline at end of file