🚛 Βρείτε τον ιδανικό μεταφορέα!

Πείτε μας ποιον μεταφορέα αναζητάτε ή ζητήστε απευθείας προσφορά - το AI βοηθά!

10 015+
εγγεγραμμένος μεταφορέας
12 873+
εταιρικός πελάτης
526+
θετικά αξιολογημένος συνεργάτης
1 θέαση

Adimex πολλαπλό προφίλ

Εάν αναζητάτε μεταφορέα, μέσω της Αγγελίας Μεταφορών μπορείτε εύκολα, γρήγορα και χωρίς υποχρεώσεις να αποκτήσετε προσφορές από μεταφορείς. Με την υποβολή αιτήσεων προσφοράς μεταφορών μπορείτε να εξοικονομήσετε χρόνο και χρήματα. Μπορείτε να συγκρίνετε τις προσφορές που λάβατε και, εφόσον είναι κατάλληλο, να αποδεχθείτε την καλύτερη προσφορά.

Αίτηση προσφοράς για μεταφορά Μεταφορά εμπορευμάτων (παλέτες, κουτιά κ.λπ.) Μεταφορά αντικειμένων, εξοπλισμού Μεταφορά αυτοκινήτων Μετακόμιση

Értékelné a választ? 0 0

Tovább a kérdések-válaszok oldalra

MultiProfil - Επαγγελματική διαχείριση</div> <div id="company-21576-name" class="company-name">Adimex-Multiprofil Kft.</div> </div> <div style="text-align:right;"> <div class="company-card-meta">συμμετείχε πριν από περισσότερα από 8 χρόνια | <span class="user-feedback-badge" title="Η αξιολόγηση της αξιοπιστίας του συνεργάτη: δεν υπάρχει αρνητική πληροφορία"><i class="bi bi-star-fill" style="color: #d3d3d3;"></i><i class="bi bi-star-fill" style="color: #d3d3d3;"></i><i class="bi bi-star-fill" style="color: #d3d3d3;"></i><i class="bi bi-star-fill" style="color: #d3d3d3;"></i><i class="bi bi-star-fill" style="color: #d3d3d3;"></i> <span style="margin-left:6px; color:#6c757d; font-size:12px;">(0)</span></span></div> </div> </div> </div> <div class="company-location" aria-hidden="false"> <span style="font-weight:600;">1039 Budapest, Sinkovits I. u. 46.</span> </div> <div class="company-excerpt">www.multiprofil.gr</div> <div class="company-actions"> <a class="button bg-white" href="https://fuvarborze.hu/el/?link=company_box&id=21576" target="_blank"> <span class="mif-phone"></span> Επικοινωνία </a> </div> </article> </div> </div> <script type="text/javascript"> //document.getElementById('search-results').scrollIntoView(); </script> <div class='bubb'></div> <div class="search-list-trigger" id="search-list-trigger"></div> </div> <!-- új jobb oldali oldalsáv --> <aside class="calc-sidebar" aria-labelledby="sidebar-title"> <div class="sidebar-title" id="sidebar-title"> <i class="bi bi-award" style="color: #217af1; margin-right: 8px;"></i> Θετικές ανατροφοδοτήσεις </div> <div class="sidebar-intro bubb"> <div class="intro-text"> H περίπου 20 ετών Fuvarbörze προσφέρει χιλιάδες αξιόπιστους συνεργάτες μεταφορών. </div> <div class="intro-links"> <a href="https://fuvarborze.hu/el/?link=list&status=positive" class="sidebar-link"> <i class="bi bi-thumbs-up"></i> Προτεινόμενοι μεταφορείς </a> <a href="https://fuvarborze.hu/el/?link=list&status=positive" class="sidebar-link"> <i class="bi bi-target"></i> Πώς να φτάσετε εδώ; </a> </div> </div> <div class="feedback-list"> <div class="feedback-box bubb"> <a href="https://fuvarborze.hu/el?link=company_box&id=1986" class="feedback-item-link" target="_blank"> <div class="feedback-header"> <div class="fb-company"> <i class="bi bi-building" style="color: #217af1; margin-right: 6px;"></i> Smitték Kft </div> <div class="fb-rating"> <i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i> <div class="fb-stats"> <i class="bi bi-award"></i> 5 </div> </div> <div class="fb-date-container"> <span class="fb-ago">πάνω από 17 χρόνια μέλος</span> </div> </div> <div class="feedback-content"> <div class="feedback-text"> <i class="bi bi-quote" style="color: #217af1; margin-right: 6px; font-size: 0.9rem;"></i> Βρες λύση σε αποστολές φορτίων με σύντομη προθεσμία. Επικοινωνήστε με αυτοπεποίθηση. </div> <span class="fb-date"> <i class="bi bi-calendar3" style="margin-right: 3px;"></i> 2026-06-23 16:50:53 </span> <div class="feedback-author text-end"> <i class="bi bi-person" style="margin-right: 4px;"></i> <strong>Biofilt-air Kft</strong> </div> </div> </a> </div> <div class="feedback-box bubb"> <a href="https://fuvarborze.hu/el?link=company_box&id=31898" class="feedback-item-link" target="_blank"> <div class="feedback-header"> <div class="fb-company"> <i class="bi bi-building" style="color: #217af1; margin-right: 6px;"></i> Qualtect Bt. </div> <div class="fb-rating"> <i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i> <div class="fb-stats"> <i class="bi bi-award"></i> 5 </div> </div> <div class="fb-date-container"> <span class="fb-ago">προσήλθε πριν από περισσότερα από 6 χρόνια</span> </div> </div> <div class="feedback-content"> <div class="feedback-text"> <i class="bi bi-quote" style="color: #217af1; margin-right: 6px; font-size: 0.9rem;"></i> Πολύ αξιόπιστος, προσεκτικός στις λεπτομέρειες, υπομονετικός, αξιόπιστος. Μόνο καλά λόγια μπορώ να πω γι' αυτόν. Ευχαριστώ για τη βοήθειά και την υπομονή του. Τον προτείνω με εμπιστοσύνη! </div> <span class="fb-date"> <i class="bi bi-calendar3" style="margin-right: 3px;"></i> 2026-06-05 06:03:38 </span> <div class="feedback-author text-end"> <i class="bi bi-person" style="margin-right: 4px;"></i> <strong>Άγνωστος χρήστης</strong> </div> </div> </a> </div> <div class="feedback-box bubb"> <a href="https://fuvarborze.hu/el?link=company_box&id=23639" class="feedback-item-link" target="_blank"> <div class="feedback-header"> <div class="fb-company"> <i class="bi bi-building" style="color: #217af1; margin-right: 6px;"></i> Lovas Róbert Ciprián e.v. </div> <div class="fb-rating"> <i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i> <div class="fb-stats"> <i class="bi bi-award"></i> 5 </div> </div> <div class="fb-date-container"> <span class="fb-ago">συμμετείχε πριν από περισσότερα από 8 χρόνια</span> </div> </div> <div class="feedback-content"> <div class="feedback-text"> <i class="bi bi-quote" style="color: #217af1; margin-right: 6px; font-size: 0.9rem;"></i> Κλείσαμε συμφωνία και όλα ήταν εντάξει σχετικά με την ολοκλήρωση της μεταφοράς. </div> <span class="fb-date"> <i class="bi bi-calendar3" style="margin-right: 3px;"></i> 2026-06-04 08:06:02 </span> <div class="feedback-author text-end"> <i class="bi bi-person" style="margin-right: 4px;"></i> <strong>Meridian-Logistics Kft</strong> </div> </div> </a> </div> <div class="feedback-box bubb"> <a href="https://fuvarborze.hu/el?link=company_box&id=23639" class="feedback-item-link" target="_blank"> <div class="feedback-header"> <div class="fb-company"> <i class="bi bi-building" style="color: #217af1; margin-right: 6px;"></i> Lovas Róbert Ciprián e.v. </div> <div class="fb-rating"> <i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i> <div class="fb-stats"> <i class="bi bi-award"></i> 5 </div> </div> <div class="fb-date-container"> <span class="fb-ago">συμμετείχε πριν από περισσότερα από 8 χρόνια</span> </div> </div> <div class="feedback-content"> <div class="feedback-text"> <i class="bi bi-quote" style="color: #217af1; margin-right: 6px; font-size: 0.9rem;"></i> Άμεση και αξιόπιστη μεταφορά, με επιβεβαίωση φωτογραφίας για την παραλαβή των εμπορευμάτων, κάτι το οποίο δεν είχα ζητήσει καν. Για πρώτη φορά χρησιμοποίησα αυτήν την ιστοσελίδα και είμαι πολύ ικανοποιημένος με τον Lovas Róbert Ciprián. Συνιστώ σε όλους! </div> <span class="fb-date"> <i class="bi bi-calendar3" style="margin-right: 3px;"></i> 2026-06-04 06:59:06 </span> <div class="feedback-author text-end"> <i class="bi bi-person" style="margin-right: 4px;"></i> <strong>Άγνωστος χρήστης</strong> </div> </div> </a> </div> <div class="feedback-box bubb"> <a href="https://fuvarborze.hu/el?link=company_box&id=23639" class="feedback-item-link" target="_blank"> <div class="feedback-header"> <div class="fb-company"> <i class="bi bi-building" style="color: #217af1; margin-right: 6px;"></i> Lovas Róbert Ciprián e.v. </div> <div class="fb-rating"> <i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i> <div class="fb-stats"> <i class="bi bi-award"></i> 5 </div> </div> <div class="fb-date-container"> <span class="fb-ago">συμμετείχε πριν από περισσότερα από 8 χρόνια</span> </div> </div> <div class="feedback-content"> <div class="feedback-text"> <i class="bi bi-quote" style="color: #217af1; margin-right: 6px; font-size: 0.9rem;"></i> Πολύ καλός και αξιόπιστος επιχειρηματικός εταίρος, τον προτείνω με σιγουριά σε όλους. </div> <span class="fb-date"> <i class="bi bi-calendar3" style="margin-right: 3px;"></i> 2026-06-04 06:57:00 </span> <div class="feedback-author text-end"> <i class="bi bi-person" style="margin-right: 4px;"></i> <strong>Άγνωστος χρήστης</strong> </div> </div> </a> </div> <div class="feedback-box bubb"> <a href="https://fuvarborze.hu/el?link=company_box&id=11508" class="feedback-item-link" target="_blank"> <div class="feedback-header"> <div class="fb-company"> <i class="bi bi-building" style="color: #217af1; margin-right: 6px;"></i> Meridian-Logistics Kft </div> <div class="fb-rating"> <i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i> <div class="fb-stats"> <i class="bi bi-award"></i> 5 </div> </div> <div class="fb-date-container"> <span class="fb-ago">συνδέθηκε εδώ και περισσότερα από 14 χρόνια</span> </div> </div> <div class="feedback-content"> <div class="feedback-text"> <i class="bi bi-quote" style="color: #217af1; margin-right: 6px; font-size: 0.9rem;"></i> Αξιόπιστος πελάτης και φορτίο από την αρχή μέχρι το τέλος. </div> <span class="fb-date"> <i class="bi bi-calendar3" style="margin-right: 3px;"></i> 2026-06-04 06:45:28 </span> <div class="feedback-author text-end"> <i class="bi bi-person" style="margin-right: 4px;"></i> <strong>Lovas Róbert Ciprián e.v.</strong> </div> </div> </a> </div> <div class="feedback-box bubb"> <a href="https://fuvarborze.hu/el?link=company_box&id=31898" class="feedback-item-link" target="_blank"> <div class="feedback-header"> <div class="fb-company"> <i class="bi bi-building" style="color: #217af1; margin-right: 6px;"></i> Qualtect Bt. </div> <div class="fb-rating"> <i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i> <div class="fb-stats"> <i class="bi bi-award"></i> 5 </div> </div> <div class="fb-date-container"> <span class="fb-ago">προσήλθε πριν από περισσότερα από 6 χρόνια</span> </div> </div> <div class="feedback-content"> <div class="feedback-text"> <i class="bi bi-quote" style="color: #217af1; margin-right: 6px; font-size: 0.9rem;"></i> Ακρίβεια, αξιοπιστία και πολύ ευέλικτη εξυπηρέτηση. </div> <span class="fb-date"> <i class="bi bi-calendar3" style="margin-right: 3px;"></i> 2026-05-28 08:51:26 </span> <div class="feedback-author text-end"> <i class="bi bi-person" style="margin-right: 4px;"></i> <strong>Άγνωστος χρήστης</strong> </div> </div> </a> </div> <div class="feedback-box bubb"> <a href="https://fuvarborze.hu/el?link=company_box&id=41649" class="feedback-item-link" target="_blank"> <div class="feedback-header"> <div class="fb-company"> <i class="bi bi-building" style="color: #217af1; margin-right: 6px;"></i> Tegmon Trans Srl </div> <div class="fb-rating"> <i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i> <div class="fb-stats"> <i class="bi bi-award"></i> 5 </div> </div> <div class="fb-date-container"> <span class="fb-ago">προβλήθηκε περισσότερα από 3 χρόνια πριν</span> </div> </div> <div class="feedback-content"> <div class="feedback-text"> <i class="bi bi-quote" style="color: #217af1; margin-right: 6px; font-size: 0.9rem;"></i> Έφεραν σπίτι ένα τριβείο από τον Prümből. Πολύ εξυπηρετικοί και οικονομικοί. Με τη βεβαιότητα προτείνω και σε άλλους. Τον επόμενο μεταφορικό μου έργο επίσης σε αυτούς :) </div> <span class="fb-date"> <i class="bi bi-calendar3" style="margin-right: 3px;"></i> 2026-05-11 14:13:56 </span> <div class="feedback-author text-end"> <i class="bi bi-person" style="margin-right: 4px;"></i> <strong>Άγνωστος χρήστης</strong> </div> </div> </a> </div> <div class="feedback-box bubb"> <a href="https://fuvarborze.hu/el?link=company_box&id=46144" class="feedback-item-link" target="_blank"> <div class="feedback-header"> <div class="fb-company"> <i class="bi bi-building" style="color: #217af1; margin-right: 6px;"></i> LUNATRANS Hungary KFT </div> <div class="fb-rating"> <i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i> <div class="fb-stats"> <i class="bi bi-award"></i> 5 </div> </div> <div class="fb-date-container"> <span class="fb-ago">πλέον από 2 χρόνια συνδεδεμένος</span> </div> </div> <div class="feedback-content"> <div class="feedback-text"> <i class="bi bi-quote" style="color: #217af1; margin-right: 6px; font-size: 0.9rem;"></i> Είμαι απόλυτα ικανοποιημένος/η με αυτό, το συστήνω θερμά. </div> <span class="fb-date"> <i class="bi bi-calendar3" style="margin-right: 3px;"></i> 2026-05-07 10:45:32 </span> <div class="feedback-author text-end"> <i class="bi bi-person" style="margin-right: 4px;"></i> <strong>Άγνωστος χρήστης</strong> </div> </div> </a> </div> <div class="feedback-box bubb"> <a href="https://fuvarborze.hu/el?link=company_box&id=46144" class="feedback-item-link" target="_blank"> <div class="feedback-header"> <div class="fb-company"> <i class="bi bi-building" style="color: #217af1; margin-right: 6px;"></i> LUNATRANS Hungary KFT </div> <div class="fb-rating"> <i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i><i class="bi bi-star-fill" style="color: #ffc107;"></i> <div class="fb-stats"> <i class="bi bi-award"></i> 5 </div> </div> <div class="fb-date-container"> <span class="fb-ago">πλέον από 2 χρόνια συνδεδεμένος</span> </div> </div> <div class="feedback-content"> <div class="feedback-text"> <i class="bi bi-quote" style="color: #217af1; margin-right: 6px; font-size: 0.9rem;"></i> Κλείσαμε συμφωνία και όλα ήταν εντάξει σχετικά με την ολοκλήρωση της μεταφοράς. </div> <span class="fb-date"> <i class="bi bi-calendar3" style="margin-right: 3px;"></i> 2026-04-23 08:09:45 </span> <div class="feedback-author text-end"> <i class="bi bi-person" style="margin-right: 4px;"></i> <strong>Άγνωστος χρήστης</strong> </div> </div> </a> </div> </div> <div class="sidebar-footer"> <a href="https://fuvarborze.hu/el/?link=list" class="sidebar-cta"> <i class="bi bi-arrow-right-circle"></i> Περισσότεροι συνεργάτες μεταφορών </a> </div> </aside> </div> <script> let page = 1; const limit = 12; const gallery = document.querySelector('.search-list'); let isLoading = false; const observer = new IntersectionObserver(entries => { if (entries[0].isIntersecting && !isLoading) { isLoading = true; page++; const params = new URLSearchParams(window.location.search); params.set('page', page); fetch(`?${params.toString()}`) .then(response => response.text()) .then(data => { const parser = new DOMParser(); const doc = parser.parseFromString(data, 'text/html'); const newItems = doc.querySelectorAll('.search-list-item'); newItems.forEach(item => { if (!isDuplicate(item)) { gallery.appendChild(item); } }); isLoading = false; }) .catch(() => { isLoading = false; }); } }, { threshold: 0.5 }); // Csak akkor aktiválódik, ha az elem 50%-ban látható // Figyeljük az oldal alján lévő elem megjelenését const loadMoreTrigger = document.getElementById("search-list-trigger"); observer.observe(loadMoreTrigger); function isDuplicate(newItem) { const existingItems = gallery.querySelectorAll('.search-list-item'); for (let item of existingItems) { if (item.innerHTML === newItem.innerHTML) { return true; } } return false; } </script> <style> .list-container { display: flex; } .list-middle { width: 800px; } @media (max-width: 768px) { .list-container { display: block; } .list-middle { margin: 0 5px; } } .search-list { display: flex; flex-wrap: wrap; gap: 20px; justify-content: center; } .search-list-item { width: 100%; box-sizing: border-box; } .search-list-trigger { width: 100%; height: 50px; background: transparent; } </style> <style> /* Kompakt, modern kártya-stílus (sablon-specifikus) */ .search-list-item { background: #ffffff; border-radius: 12px; box-shadow: 0 6px 22px rgba(16, 24, 40, 0.06); padding: 14px; display: flex; flex-direction: column; gap: 10px; transition: transform .15s ease, box-shadow .15s ease; overflow: hidden; min-height: 160px; border: 1px dotted #8b9ec0ff; } .search-list-item:hover { transform: translateY(-6px); box-shadow: 0 14px 36px rgba(16, 24, 40, 0.10); } /* Fejléc: rövid reklámszöveg / cím és meta sor */ .company-card-head { display: flex; flex-direction: column; gap: 8px; } .company-card-head>div { display: flex; gap: 10px; align-items: flex-start; flex-direction: column; } .company-card-head>div>div:first-child { flex: 1; min-width: 0; } .company-card-meta { font-size: .85rem; color: #6b7280; margin-top: 4px; background: #f3f4f6; padding: 4px 8px; border-radius: 6px; } /* mini title */ .company-card-mini-title { font-size: .95rem; color: #0b3b66; font-weight: 700; margin: 0 0 4px 0; } /* Fő név — javítva: ne törjön karakterenként, normál sortörés */ .company-name { margin: 0; font-size: 1.1rem; color: #0b2540; font-weight: 700; line-height: 1.15; white-space: normal; /* engedi a sortörést */ overflow-wrap: anywhere; /* törje a hosszú szavakat szükség esetén */ word-break: normal; /* ne törjön karakterenként */ hyphens: auto; } /* Ország/székhely badge */ .company-location { display: inline-flex; gap: 8px; align-items: center; background: linear-gradient(90deg, #0f7bd7, #2979ff); color: #fff; padding: 6px 8px; border-radius: 6px; font-size: .9rem; } /* Leírás: vágás, de megjelenik a teljes tartalom a forrásban */ .company-excerpt { color: #374151; font-size: .95rem; line-height: 1.35; max-height: 6.4rem; /* ~4 sorra vág */ overflow: hidden; position: relative; } /* CTA gomb jobbra lent */ .company-actions { display: flex; gap: 8px; margin-top: auto; justify-content: flex-end; } .button.bg-white { background: #fff; border: 1px solid #e6e9ee; color: #0b3b66; padding: 8px 12px; border-radius: 8px; text-decoration: none; font-weight: 600; } .button.bg-white .mif-phone { margin-right: 6px; } /* Mobil reszponzív */ @media (max-width: 768) { .search-list-item { padding: 12px; min-height: auto; } .company-card-mini-title { font-size: .92rem; } .company-name { font-size: 1rem; } .company-excerpt { max-height: 5.2rem; } } </style> </div> </div> </div> </div> <style> .cookie-consent { position: fixed; bottom: 0; left: 0; width: 100%; background-color: rgba(255, 255, 255, 0.98); border-top: 1px solid #ddd; padding: 10px; text-align: center; z-index: 999999; border-radius: 10px 10px 0 0; box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05); } @media (max-width: 768px) { .cookie-consent { width: 100%; border-radius: 0; } } .cookie-consent span { color: #000; } .cookieButtons { margin-bottom: 30px; } .cookieButtons button { font-size: 20px; } .cookie-consent button { margin-left: 10px; } .miniclose { right: 10px; position: relative; top: -10px; } #calculatorModal { margin-top: 60px; } .calc-modal-close { margin-bottom: 50px; } </style> <!-- Cookie Consent --> <div class="cookie-consent" id="cookieConsent" style="display:none;"> <div> <a href='https://fuvarborze.hu/el' target='_top' class='sitelogo'><img src='https://fuvarborze.hu/images/fuvarborze-logo.png' width='350' border='0'></a> <h3>Σας καλωσορίζει η πλατφόρμα μεταφορών European Freight Exchange!</h3> </div> <div class="text-center cookieButtons"> <button class="btn btn-secondary btn-sm" id="declineCookies">❌ Απορρίπτεται</button> <button class="btn btn-primary btn-sm" id="acceptCookies">👍 Αποδοχή</button> </div> <div style="font-size: 12px;"> Αυτή η ιστοσελίδα χρησιμοποιεί cookies για να προσφέρει την καλύτερη εμπειρία χρήστη. Τα cookies βοηθούν στην εξατομίκευση του περιεχομένου, στην ανάλυση της συμπεριφοράς των επισκεπτών και στη βελτίωση των υπηρεσιών μας. Σύμφωνα με την ευρωπαϊκή νομοθεσία προστασίας δεδομένων (GDPR), σας ενημερώνουμε ότι ορισμένα cookies χρησιμοποιούνται μόνο με τη συγκατάθεσή σας. Χωρίς την αποδοχή, ορισμένες λειτουργίες ενδέχεται να μην λειτουργούν σωστά. Για περισσότερες πληροφορίες, παρακαλούμε διαβάστε την ειδοποίηση περί επεξεργασίας δεδομένων μας: <a href='https://fuvarborze.hu/el/?link=privacy'>Ενημέρωση για την επεξεργασία δεδομένων</a>! </div> </div> <!-- Google Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=G-5NV6QBDV2H"></script> <script> window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } gtag('js', new Date()); gtag('config', 'G-5NV6QBDV2H', { 'anonymize_ip': true }); </script> <script> // Cookie consent kezelése külön namespace-ben (function () { var cookieConsent = document.getElementById('cookieConsent'); var acceptCookies = document.getElementById('acceptCookies'); var declineCookies = document.getElementById('declineCookies'); // Check if cookies are already decided var consentVal = getCookie('cookies_accepted'); if (consentVal === 'true') { gtag('consent', 'update', { 'analytics_storage': 'granted' }); } else if (consentVal === 'false') { gtag('consent', 'update', { 'analytics_storage': 'denied' }); } else { // Not yet decided – show the bar cookieConsent.style.display = 'block'; } // Accept cookies - csak a cookie consent gombra if (acceptCookies) { acceptCookies.addEventListener('click', function (e) { e.preventDefault(); e.stopPropagation(); setCookie('cookies_accepted', 'true', 365); cookieConsent.style.display = 'none'; gtag('consent', 'update', { 'analytics_storage': 'granted' }); if (typeof window._barionGrantConsent === 'function') window._barionGrantConsent(); }); } // Decline cookies - csak a cookie consent gombra if (declineCookies) { declineCookies.addEventListener('click', function (e) { e.preventDefault(); e.stopPropagation(); setCookie('cookies_accepted', 'false', 365); cookieConsent.style.display = 'none'; gtag('consent', 'update', { 'analytics_storage': 'denied' }); }); } // Set cookie function setCookie(name, value, days) { var expires = ""; if (days) { var date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); expires = "; expires=" + date.toUTCString(); } document.cookie = name + "=" + (value || "") + expires + "; path=/"; } // Get cookie function getCookie(name) { var nameEQ = name + "="; var ca = document.cookie.split(';'); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') c = c.substring(1, c.length); if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); } return null; } })(); </script> <div class="languageSelection" > <div id="languagesContainer"> <div class="languageItem currentLanguage">🇬🇷</div> <div class="languageItem hide"><a href="https://fuvarborze.hu/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇭🇺</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/en/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇬🇧</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/zh/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇨🇳</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/sk/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇸🇰</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/hr/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇭🇷</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/sl/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇸🇮</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/pl/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇵🇱</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/de/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇩🇪</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/fr/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇫🇷</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/it/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇮🇹</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/es/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇪🇸</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/pt/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇵🇹</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/nl/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇳🇱</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/el/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇬🇷</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/bg/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇧🇬</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/ro/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇷🇴</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/cs/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇨🇿</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/da/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇩🇰</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/et/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇪🇪</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/fi/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇫🇮</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/lt/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇱🇹</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/lv/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇱🇻</a></div><div class="languageItem hide"><a href="https://fuvarborze.hu/sv/fuvaroz%C3%B3-c%C3%A9gek/adimex-multiprofil">🇸🇪</a></div> </div> </div> <script> $(document).ready(function () { // Helper to decide if a URL points to login/registration (supports pretty URLs as well) function isLoginOrRegHref(href) { try { var a = document.createElement('a'); a.href = href; var hostOk = (!a.host || a.host === window.location.host); var q = a.search || ''; var p = (a.pathname || '').toLowerCase(); if (q.indexOf('link=login') !== -1 || q.indexOf('link=reg') !== -1) return true; // Match common pretty paths in multiple languages var re = /(regisztracio|regisztráció|bejelentkezes|belepes|signin|anmelden|login|register)\/?$/; if (re.test(p)) return true; // also allow language-prefixed like /en/signin/ var parts = p.split('/').filter(Boolean); if (parts.length >= 2) { var last = parts[parts.length-1]; if (re.test('/'+last)) return true; } return false; } catch(_) { return false; } } // Intercept clicks on login/register links to open chat login overlay $(document).on('click', 'a', function (e) { // Allow ctrl/cmd click to open new tab if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return; var href = $(this).attr('href') || ''; if (!isLoginOrRegHref(href)) return; e.preventDefault(); e.stopImmediatePropagation(); try { $('#loader').hide(); } catch(_) {} // Create chat login overlay if doesn't exist if ($('#chatLoginOverlay').length === 0) { $('body').append('<div id="chatLoginOverlay" style="display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);z-index:9999;"><div id="chatLoginContainer" style="position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center;"><span id="closeChatLogin" style="position:absolute;top:20px;right:30px;color:#fff;font-size:40px;font-weight:bold;cursor:pointer;z-index:10000;">×</span><div id="chatLoginContent"></div></div></div>'); // Close on X click $('#closeChatLogin').click(function() { $('#chatLoginOverlay').fadeOut(300); }); // Close on background click $('#chatLoginOverlay').click(function(e) { if (e.target.id === 'chatLoginOverlay' || e.target.id === 'chatLoginContainer') { $('#chatLoginOverlay').fadeOut(300); } }); } // Load the chat login form $.get('/modules/pages/chat_login.php?lang=el', function (html) { $('#chatLoginContent').html(html); $('#chatLoginOverlay').fadeIn(300); }, 'html'); }); // Handle login form submit via AJAX inside modal $(document).on('submit', '#modalContent #loginForm', function (e) { e.preventDefault(); var $form = $(this); var data = $form.serialize(); var $btn = $form.find('input[type=submit], button[type=submit]').prop('disabled', true); $.post('/ajaxjobs/login.php', data, function (j) { if (j && j.ok) { // Success: close modal and refresh to reflect logged-in state $('#subscriptionNoticeModal').modal('hide'); // Emit a custom event in case pages want to hook in (chat continues without reload) $(document).trigger('user:loggedin', [j.user || null]); // On non-chat pages, reload to reflect login state if ($('#chatMessages').length === 0) { location.reload(); } } else { var msg = (j && j.error) ? j.error : 'Αποτυχία σύνδεσης.'; var $err = $('<div class="alert alert-danger" role="alert"></div>').text(msg); $form.prepend($err); } }, 'json').fail(function(){ var $err = $('<div class="alert alert-danger" role="alert"></div>').text('Σφάλμα δικτύου'); $form.prepend($err); }).always(function(){ $btn.prop('disabled', false); }); }); // Handle registration form submit via AJAX inside modal $(document).on('submit', '#modalContent #regForm', function (e) { e.preventDefault(); var $form = $(this); var data = $form.serialize(); var $submit = $form.find('button[type=submit], input[type=submit]'); $submit.prop('disabled', true); $.ajax({ url: '/modules/pages/reg.php', type: 'POST', data: data, dataType: 'html' }).done(function(resp){ // Replace modal content with the returned HTML (it already includes messages) $('#modalContent').html(resp); }).fail(function(){ var $err = $('<div class="alert alert-danger" role="alert"></div>').text('Σφάλμα δικτύου'); $form.prepend($err); }).always(function(){ $submit.prop('disabled', false); }); }); $('.currentLanguage').on('click', function (e) { $('.languageSelection .languageItem').toggle(); $('#languagesContainer').addClass('languagesContainer'); $(document).on('click', function (e) { if (!$(e.target).closest('.languageSelection').length) { $('#languagesContainer').removeClass('languagesContainer'); $('.languageSelection .languageItem').hide(); $('.currentLanguage').show(); } }); $(document).on('scroll', function (e) { if (!$(e.target).closest('.languageSelection').length) { $('#languagesContainer').removeClass('languagesContainer'); $('.languageSelection .languageItem').hide(); $('.currentLanguage').show(); } }); }); function lang_alert() { openModal('<div><p><span class="flag-with-badge"><img src="https://fuvarborze.hu//images/blank.png" class="flag flag-el" alt="EL" /><span class="country-badge">EL</span></span>: Η ιστοσελίδα εμφανίζεται σε γλώσσα διαφορετική από αυτή που χρησιμοποιεί ο περιηγητής. Μπορείτε να αλλάξετε γλώσσα στην κάτω δεξιά γωνία της σελίδας.</p><p><span class="flag-with-badge"><img src="https://fuvarborze.hu//images/blank.png" class="flag flag-" alt="" /><span class="country-badge"></span></span>: Η ιστοσελίδα εμφανίζεται σε γλώσσα διαφορετική από αυτή που χρησιμοποιεί ο περιηγητής. Μπορείτε να αλλάξετε γλώσσα στην κάτω δεξιά γωνία της σελίδας.</p></div>'); $.cookie('dif_lang_alert', '1', { expires: 30, path: '/' }); $('.modal').on('hidden.bs.modal', function () { $('.currentLanguage').click(); $('#languagesContainer').addClass('blinking') setTimeout(function () { $('#languagesContainer').removeClass('blinking'); }, 2500); }); } if ($.cookie('dif_lang_alert') == undefined) lang_alert(); }); </script> <script> // Kupon visszaszámláló – minden .coupon-countdown elemre fut, élő és dinamikusan betöltött üzenetekre is function initCouponCountdowns() { document.querySelectorAll('.coupon-countdown:not([data-timer-init])').forEach(function(el) { el.setAttribute('data-timer-init', '1'); var expires = parseInt(el.getAttribute('data-expires'), 10); function tick() { var left = Math.max(0, expires - Date.now()); var m = Math.floor(left / 60000); var s = Math.floor((left % 60000) / 1000); el.textContent = m + ':' + (s < 10 ? '0' : '') + s; if (left > 0) setTimeout(tick, 1000); else el.closest('.coupon-success-card') && (el.closest('.coupon-success-card').style.opacity = '0.5'); } tick(); }); } // Futtatás DOM betöltéskor és minden AJAX után document.addEventListener('DOMContentLoaded', initCouponCountdowns); if (window.MutationObserver) { new MutationObserver(initCouponCountdowns).observe(document.body, {childList: true, subtree: true}); } </script> <!-- MODAL HTML SECTION --> <div class="modal fade" id="subscriptionNoticeModal" tabindex="-1" role="dialog" aria-labelledby="subscriptionNoticeModalLabel" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered" role="document"> <div class="modal-content"> <div class="modal-header bg-blue text-white"> <div class="modal-title" id="subscriptionNoticeModalLabel"><a href='https://fuvarborze.hu/el' target='_top' class='sitelogo'><img src='https://fuvarborze.hu/images/fuvarborze-logo.png' width='350' border='0'></a></div> <button type="button" class="modal-close" data-dismiss="modal" aria-label="Κλείσιμο"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body" id="modalContent"></div> <div class="modal-footer"> <button type="button" class="btn btn-secondary modal-close" data-dismiss="modal">Κλείσιμο</button> </div> </div> </div> </div> <!-- CALCULATOR WIDGET (replacing the modal) --> <div id="calculatorWidget" class="calculator-widget"> <div class="calculator-header" id="calculatorHeader"> <div class="calculator-title"> <i class="bi bi-calculator"></i> Ταχύς υπολογιστής ναύλων φορτηγού </div> <div class="calculator-controls"> <button type="button" class="calc-minimize-btn" id="calcMinimizeBtn"> <i class="bi bi-dash"></i> </button> </div> </div> <div class="calculator-body" id="calculatorBody"> <div class="text-center"> <div class="spinner-border" role="status"> <span class="visually-hidden">Φόρτωση...</span> </div> </div> </div> </div> <button id="scrollToTopBtn">🔝</button> <script> $(document).ready(function () { function isPwaInstalled() { const isStandaloneMedia = window.matchMedia('(display-mode: standalone)').matches || window.matchMedia('(display-mode: fullscreen)').matches || window.matchMedia('(display-mode: minimal-ui)').matches; // iOS Safari saját jelzője (Home Screen-ről indítva true) const isIOSStandalone = typeof window.navigator.standalone === 'boolean' ? window.navigator.standalone : false; // Ellenőrizzük, hogy a push engedélyezve van-e let isPushEnabled = false; if ('Notification' in window && Notification.permission === 'granted') { isPushEnabled = true; } //return isStandaloneMedia || isIOSStandalone || isPushEnabled; return isPushEnabled; } if (isPwaInstalled()) { // ne mutasd a „Tedd a kezdőképernyőre” bannert } else { // mutasd az iOS/Android telepítési útmutatót if ($.cookie('cookival_pwa_banner') !== '1' && false && true && false) { var isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; var bannerText = isIOS ? "Εγκαταστήστε την εφαρμογή Fuvarbörze στη κινητή συσκευή σας και ενεργοποιήστε τις ειδοποιήσεις για πιο αποδοτική χρήση του Fuvarbörze!" : "Ενεργοποιήστε τις ειδοποιήσεις για την αποτελεσματική χρήση του Φορβαρζέ!"; var bannerHtml = '<div id="cookivalPwaBanner" style="position:fixed;bottom:80px;left:10px;right:10px;z-index:99999;background:#fff;border:1px solid #007bff;border-radius:10px;padding:15px;text-align:center;box-shadow:0 2px 10px rgba(0,0,0,0.15);">' + '<img src="https://fuvarborze.hu/images/icon-192.png" align="left"><span style="font-size:16px;color:#007bff;">' + bannerText + '</span><br>' + '<a href="https://fuvarborze.hu/el/?link=pushsub" class="btn btn-primary" style="margin-top:10px; color: #FFFFFF;">Συνέχεια</a>' + '<button id="closeCookivalPwaBanner" style="position:absolute;top:-20px;right:-20px;background:none;border:none;font-size:30px;color:#007bff;cursor:pointer;">🅧</button>' + '</div>'; $('body').append(bannerHtml); $('#closeCookivalPwaBanner').on('click', function () { $('#cookivalPwaBanner').remove(); $.cookie('cookival_pwa_banner', '1', { expires: 10, path: '/' }); }); } } // Calculator widget kezelése var calculatorWidget = $('#calculatorWidget'); var calculatorHeader = $('#calculatorHeader'); var calculatorBody = $('#calculatorBody'); var calculatorFooter = $('.calculator-footer'); var calcMinimizeBtn = $('#calcMinimizeBtn'); var calcCloseBtn = $('#calcCloseBtn'); // Widget állapotának betöltése cookie-ból var isWidgetOpen = getCalcCookie('calc_widget_open') === 'true'; var isWidgetClosed = getCalcCookie('calc_widget_closed') === 'true'; // Ha nincs még cookie beállítva (első látogatás), akkor nyitva legyen if (getCalcCookie('calc_widget_open') === null && getCalcCookie('calc_widget_closed') === null) { isWidgetOpen = true; } // Kalkulátor tartalom betöltése function loadCalculatorContent() { if ($('#calculatorBody .spinner-border').length > 0) { $('#calculatorBody').html("<style>\n\/* === CALCULATOR PROFESSIONAL DESIGN === *\/\n\n.calc-page {\n display: flex;\n gap: 30px;\n max-width: 1200px;\n margin: 20px auto;\n padding: 0 15px;\n}\n\n.calc-container {\n flex: 1;\n background: linear-gradient(135deg, #ffffff 0%, #f8fbff 100%);\n border-radius: 16px;\n box-shadow: 0 8px 32px rgba(11, 111, 179, 0.12);\n padding: 32px;\n border: 1px solid rgba(11, 111, 179, 0.08);\n position: relative;\n overflow: hidden;\n}\n\n.calc-container::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 4px;\n background: linear-gradient(90deg, #217af1, #01a0c6, #217af1);\n border-radius: 16px 16px 0 0;\n}\n\n\/* === OVERRIDE GLOBAL STYLES === *\/\n.calc-container input,\n.calc-container textarea,\n.calc-container select {\n padding: 12px 16px !important;\n border: 2px solid #e1eaf4 !important;\n border-radius: 10px !important;\n background: #ffffff !important;\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;\n font-size: 14px !important;\n color: #2c3e50 !important;\n transition: all 0.3s ease !important;\n width: 100% !important;\n box-sizing: border-box !important;\n}\n\n.calc-container input:focus,\n.calc-container textarea:focus,\n.calc-container select:focus {\n border-color: #217af1 !important;\n box-shadow: 0 0 0 3px rgba(33, 122, 241, 0.1) !important;\n outline: none !important;\n}\n\n.calc-container label {\n padding: 0 !important;\n margin: 0 0 8px 0 !important;\n background: transparent !important;\n border-radius: 0 !important;\n color: #2c3e50 !important;\n font-weight: 600 !important;\n font-size: 14px !important;\n display: block !important;\n}\n\n\/* Radio button and checkbox specific overrides *\/\n.calc-container input[type=\"radio\"],\n.calc-container input[type=\"checkbox\"] {\n width: auto !important;\n margin: 0 8px 0 0 !important;\n padding: 0 !important;\n display: inline-block !important;\n vertical-align: middle !important;\n}\n\n.calc-container .radio-group label,\n.calc-container .checkbox-group label {\n display: inline-block !important;\n margin: 0 15px 0 0 !important;\n font-weight: normal !important;\n cursor: pointer !important;\n vertical-align: middle !important;\n}\n\n\/* Header Design *\/\n.calc-header {\n text-align: center;\n margin-bottom: 40px;\n position: relative;\n}\n\n.calc-title {\n font-size: 2.2rem;\n font-weight: 700;\n color: #217af1;\n margin: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 15px;\n}\n\n.calc-title i {\n background: linear-gradient(135deg, #217af1, #01a0c6);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n}\n\n.calc-subtitle {\n color: #6c757d;\n font-size: 1.1rem;\n margin-top: 8px;\n font-weight: 400;\n}\n\n.free-badge {\n position: absolute;\n top: -8px;\n right: -10px;\n background: linear-gradient(135deg, #28a745, #20c997);\n color: white;\n font-size: 0.75rem;\n font-weight: 700;\n padding: 6px 14px;\n border-radius: 20px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n box-shadow: 0 4px 12px rgba(40, 167, 69, 0.25);\n border: 2px solid rgba(255, 255, 255, 0.3);\n}\n\n\/* Form Group Styling *\/\n.form-group {\n margin-bottom: 28px;\n position: relative;\n}\n\n.form-label {\n display: block;\n font-weight: 600;\n font-size: 1rem;\n color: #2c3e50;\n margin-bottom: 12px;\n padding: 8px 16px;\n background: linear-gradient(135deg, #217af1, #01a0c6);\n color: white;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(33, 122, 241, 0.2);\n position: relative;\n}\n\n.form-label::after {\n content: '';\n position: absolute;\n bottom: -4px;\n left: 16px;\n width: 0;\n height: 0;\n border-left: 6px solid transparent;\n border-right: 6px solid transparent;\n border-top: 4px solid #01a0c6;\n}\n\n\/* Input Styling *\/\n.form-control, .form-select {\n border: 2px solid #e9ecef;\n border-radius: 12px;\n padding: 14px 18px;\n font-size: 1rem;\n transition: all 0.3s ease;\n background: #ffffff;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);\n}\n\n.form-control:focus, .form-select:focus {\n border-color: #217af1;\n box-shadow: 0 0 0 3px rgba(33, 122, 241, 0.1);\n outline: none;\n transform: translateY(-1px);\n}\n\n.form-control::placeholder {\n color: #adb5bd;\n font-style: italic;\n}\n\n\/* Textarea Specific *\/\ntextarea.form-control {\n resize: vertical;\n min-height: 100px;\n}\n\n\/* Radio and Checkbox Groups *\/\n.options-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 12px;\n margin-top: 16px;\n}\n\n.option-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: #ffffff;\n border: 2px solid #e9ecef;\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.3s ease;\n position: relative;\n}\n\n.option-item:hover {\n border-color: #217af1;\n background: #f8fbff;\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(33, 122, 241, 0.1);\n}\n\n\/* Radio and checkbox input styling within option-item *\/\n.option-item input[type=\"radio\"],\n.option-item input[type=\"checkbox\"] {\n width: 18px !important;\n height: 18px !important;\n margin: 0 !important;\n padding: 0 !important;\n cursor: pointer !important;\n position: relative !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n border: 2px solid #e1eaf4 !important;\n background: #ffffff !important;\n border-radius: 4px !important;\n transition: all 0.3s ease !important;\n}\n\n.option-item input[type=\"radio\"] {\n border-radius: 50% !important;\n}\n\n.option-item input[type=\"radio\"]:checked,\n.option-item input[type=\"checkbox\"]:checked {\n background: #217af1 !important;\n border-color: #217af1 !important;\n}\n\n.option-item input[type=\"checkbox\"]:checked::before {\n content: '\u2713' !important;\n position: absolute !important;\n top: 50% !important;\n left: 50% !important;\n transform: translate(-50%, -50%) !important;\n color: white !important;\n font-size: 12px !important;\n font-weight: bold !important;\n line-height: 1 !important;\n display: block !important;\n}\n\n.option-item input[type=\"radio\"]:checked::before {\n content: '' !important;\n position: absolute !important;\n top: 50% !important;\n left: 50% !important;\n transform: translate(-50%, -50%) !important;\n width: 8px !important;\n height: 8px !important;\n background: white !important;\n border-radius: 50% !important;\n display: block !important;\n}\n\n.option-item label {\n margin: 0 !important;\n padding: 0 !important;\n background: transparent !important;\n color: #2c3e50 !important;\n font-weight: 500 !important;\n font-size: 14px !important;\n cursor: pointer !important;\n flex: 1 !important;\n line-height: 1.4 !important;\n border-radius: 0 !important;\n}\n\n.option-item input[type=\"radio\"]:checked + label,\n.option-item input[type=\"checkbox\"]:checked + label {\n color: #217af1;\n font-weight: 600;\n}\n\n.option-item input[type=\"radio\"]:checked,\n.option-item input[type=\"checkbox\"]:checked {\n accent-color: #217af1;\n}\n\n\/* Stand-alone checkboxes and radio buttons *\/\n.calc-container .form-check-input {\n width: 18px !important;\n height: 18px !important;\n margin: 0 8px 0 0 !important;\n padding: 0 !important;\n cursor: pointer !important;\n display: inline-block !important;\n vertical-align: middle !important;\n position: relative !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n border: 2px solid #e1eaf4 !important;\n background: #ffffff !important;\n border-radius: 4px !important;\n transition: all 0.3s ease !important;\n}\n\n.calc-container .form-check-input[type=\"radio\"] {\n border-radius: 50% !important;\n}\n\n.calc-container .form-check-input:checked {\n background: #217af1 !important;\n border-color: #217af1 !important;\n}\n\n.calc-container .form-check-input[type=\"checkbox\"]:checked::before {\n content: '\u2713' !important;\n position: absolute !important;\n top: 50% !important;\n left: 50% !important;\n transform: translate(-50%, -50%) !important;\n color: white !important;\n font-size: 12px !important;\n font-weight: bold !important;\n line-height: 1 !important;\n display: block !important;\n}\n\n.calc-container .form-check-input[type=\"radio\"]:checked::before {\n content: '' !important;\n position: absolute !important;\n top: 50% !important;\n left: 50% !important;\n transform: translate(-50%, -50%) !important;\n width: 8px !important;\n height: 8px !important;\n background: white !important;\n border-radius: 50% !important;\n display: block !important;\n}\n\n.calc-container .form-check-label {\n margin: 0 !important;\n padding: 0 !important;\n background: transparent !important;\n color: #2c3e50 !important;\n font-weight: 500 !important;\n font-size: 14px !important;\n cursor: pointer !important;\n display: inline-block !important;\n vertical-align: middle !important;\n border-radius: 0 !important;\n line-height: 1.4 !important;\n}\n\n.calc-container .form-check-input:checked + .form-check-label {\n color: #217af1 !important;\n font-weight: 600 !important;\n}\n\n\/* Form Select elements *\/\n.calc-container .form-select,\n.calc-container select {\n padding: 12px 16px !important;\n border: 2px solid #e1eaf4 !important;\n border-radius: 10px !important;\n background: #ffffff !important;\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;\n font-size: 14px !important;\n color: #2c3e50 !important;\n transition: all 0.3s ease !important;\n width: 100% !important;\n box-sizing: border-box !important;\n appearance: none !important;\n background-image: url(\"data:image\/svg+xml,%3csvg xmlns='http:\/\/www.w3.org\/2000\/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'\/%3e%3c\/svg%3e\") !important;\n background-position: right 12px center !important;\n background-repeat: no-repeat !important;\n background-size: 16px 12px !important;\n padding-right: 40px !important;\n}\n\n.calc-container .form-select:focus,\n.calc-container select:focus {\n border-color: #217af1 !important;\n box-shadow: 0 0 0 3px rgba(33, 122, 241, 0.1) !important;\n outline: none !important;\n}\n\n\/* Form Control elements *\/\n.calc-container .form-control {\n padding: 12px 16px !important;\n border: 2px solid #e1eaf4 !important;\n border-radius: 10px !important;\n background: #ffffff !important;\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;\n font-size: 14px !important;\n color: #2c3e50 !important;\n transition: all 0.3s ease !important;\n width: 100% !important;\n box-sizing: border-box !important;\n}\n\n.calc-container .form-control:focus {\n border-color: #217af1 !important;\n box-shadow: 0 0 0 3px rgba(33, 122, 241, 0.1) !important;\n outline: none !important;\n}\n\n\/* Form Labels *\/\n.calc-container .form-label {\n padding: 0 !important;\n margin: 0 0 8px 0 !important;\n background: transparent !important;\n border-radius: 0 !important;\n color: #2c3e50 !important;\n font-weight: 600 !important;\n font-size: 14px !important;\n display: block !important;\n line-height: 1.4 !important;\n}\n\n\/* Button overrides *\/\n.calc-container button,\n.calc-container .btn {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;\n font-weight: 600 !important;\n border-radius: 10px !important;\n transition: all 0.3s ease !important;\n border: none !important;\n cursor: pointer !important;\n}\n\n.form-check-input {\n width: 20px;\n height: 20px;\n margin: 0;\n border: 2px solid #dee2e6;\n flex-shrink: 0;\n}\n\n.form-check-label {\n margin: 0;\n font-size: 0.95rem;\n color: #495057;\n cursor: pointer;\n line-height: 1.4;\n}\n\n\/* Special Requirements *\/\n.special-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 10px;\n margin-top: 16px;\n}\n\n\/* Submit Button *\/\n.submit-section {\n margin-top: 40px;\n text-align: center;\n}\n\n.btn-submit {\n background: linear-gradient(135deg, #217af1, #01a0c6);\n color: white;\n border: none;\n padding: 16px 48px;\n font-size: 1.1rem;\n font-weight: 600;\n border-radius: 12px;\n cursor: pointer;\n transition: all 0.3s ease;\n box-shadow: 0 4px 16px rgba(33, 122, 241, 0.3);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n position: relative;\n overflow: hidden;\n}\n\n.btn-submit::before {\n content: '';\n position: absolute;\n top: 0;\n left: -100%;\n width: 100%;\n height: 100%;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);\n transition: left 0.5s;\n}\n\n.btn-submit:hover::before {\n left: 100%;\n}\n\n.btn-submit:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 24px rgba(33, 122, 241, 0.4);\n}\n\n.btn-submit:active {\n transform: translateY(0);\n}\n\n\/* Responsive Design *\/\n@media (max-width: 768px) {\n .calc-page {\n flex-direction: column;\n margin: 10px auto;\n padding: 0 10px;\n }\n \n .calc-container {\n padding: 24px 20px;\n }\n \n .calc-title {\n font-size: 1.8rem;\n }\n \n .options-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n \n .special-grid {\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n }\n \n .free-badge {\n position: static;\n display: inline-block;\n margin-top: 10px;\n }\n}\n\n\/* Success\/Error States *\/\n.form-group.success .form-control {\n border-color: #28a745;\n box-shadow: 0 0 0 3px rgba(40, 167, 69, 0.1);\n}\n\n.form-group.error .form-control {\n border-color: #dc3545;\n box-shadow: 0 0 0 3px rgba(220, 53, 69, 0.1);\n}\n\n\/* Loading State *\/\n.btn-submit.loading {\n pointer-events: none;\n opacity: 0.7;\n}\n\n.btn-submit.loading::after {\n content: '';\n position: absolute;\n width: 20px;\n height: 20px;\n margin: auto;\n border: 2px solid transparent;\n border-top-color: #ffffff;\n border-radius: 50%;\n animation: spin 1s ease infinite;\n}\n\n@keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n\/* Hidden Fields Animation *\/\n.form-group {\n opacity: 1;\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n.form-group.hidden {\n opacity: 0;\n max-height: 0;\n margin-bottom: 0;\n}\n<\/style>\n\n<div class=\"calc-page\">\n <div class=\"calc-container\">\n \n <form id=\"freightForm\">\n <div class=\"form-group\">\n <label class=\"form-label\">\u03a4\u03cd\u03c0\u03bf\u03c2 \u039c\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03ac\u03c2<\/label>\n <div class=\"options-grid\">\n <div class=\"option-item\">\n <input class=\"form-check-input\" type=\"radio\" name=\"cargoType\" id=\"cargoType_raklapos\"\n value=\"\u03c0\u03b1\u03bb\u03b5\u03c4\u03bf\u03c0\u03bf\u03b9\u03b7\u03bc\u03ad\u03bd\u03bf \u03b5\u03bc\u03c0\u03cc\u03c1\u03b5\u03c5\u03bc\u03b1\" required>\n <label class=\"form-check-label\" for=\"cargoType_raklapos\">\u03a0\u03c1\u03bf\u03ca\u03cc\u03bd\u03c4\u03b1 \u03c3\u03b5 \u03c0\u03b1\u03bb\u03ad\u03c4\u03b5\u03c2<\/label>\n <\/div>\n <div class=\"option-item\">\n <input class=\"form-check-input\" type=\"radio\" name=\"cargoType\" id=\"cargoType_omleszett\"\n value=\"\u03b1\u03bd\u03b5\u03c0\u03b5\u03af\u03c1\u03b1\u03c3\u03c4\u03b7 \u03c6\u03bf\u03c1\u03c4\u03af\u03b1\">\n <label class=\"form-check-label\" for=\"cargoType_omleszett\">\u03a7\u03cd\u03bc\u03b1 \u03b5\u03bc\u03c0\u03bf\u03c1\u03b5\u03cd\u03bc\u03b1\u03c4\u03b1<\/label>\n <\/div>\n <div class=\"option-item\">\n <input class=\"form-check-input\" type=\"radio\" name=\"cargoType\" id=\"cargoType_gabona\"\n value=\"\u03b4\u03b7\u03bc\u03b7\u03c4\u03c1\u03b9\u03b1\u03ba\u03ac\">\n <label class=\"form-check-label\" for=\"cargoType_gabona\">\u03a3\u03b9\u03c4\u03b7\u03c1\u03ac<\/label>\n <\/div>\n <div class=\"option-item\">\n <input class=\"form-check-input\" type=\"radio\" name=\"cargoType\" id=\"cargoType_koltoztetes\"\n value=\"\u03bc\u03b5\u03c4\u03b1\u03ba\u03cc\u03bc\u03b9\u03c3\u03b7\">\n <label class=\"form-check-label\" for=\"cargoType_koltoztetes\">\u039c\u03b5\u03c4\u03b1\u03ba\u03cc\u03bc\u03b9\u03c3\u03b7<\/label>\n <\/div>\n <div class=\"option-item\">\n <input class=\"form-check-input\" type=\"radio\" name=\"cargoType\" id=\"cargoType_jarmu\"\n value=\"\u03cc\u03c7\u03b7\u03bc\u03b1\">\n <label class=\"form-check-label\" for=\"cargoType_jarmu\">\u039f\u03c7\u03b7\u03bc\u03ac\u03c4\u03c9\u03bd, \u03bc\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03ac \u03b1\u03c5\u03c4\u03bf\u03ba\u03b9\u03bd\u03ae\u03c4\u03c9\u03bd<\/label>\n <\/div>\n <div class=\"option-item\">\n <input class=\"form-check-input\" type=\"radio\" name=\"cargoType\" id=\"cargoType_munkagep\"\n value=\"\u03c6\u03bf\u03c1\u03c4\u03b7\u03b3\u03cc \u03b5\u03c1\u03b3\u03bf\u03bb\u03ac\u03b2\u03bf\u03c5\">\n <label class=\"form-check-label\" for=\"cargoType_munkagep\">\u0395\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03bf \u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03c9\u03bd<\/label>\n <\/div>\n <div class=\"option-item\">\n <input class=\"form-check-input\" type=\"radio\" name=\"cargoType\" id=\"cargoType_gepberendezes\"\n value=\"\u03bc\u03b7\u03c7\u03b1\u03bd\u03ae\u03bc\u03b1\u03c4\u03b1 \u03ba\u03b1\u03b9 \u03b5\u03be\u03bf\u03c0\u03bb\u03b9\u03c3\u03bc\u03cc\u03c2\">\n <label class=\"form-check-label\" for=\"cargoType_gepberendezes\">\u0395\u03be\u03bf\u03c0\u03bb\u03b9\u03c3\u03bc\u03cc\u03c2 \u03bc\u03b7\u03c7\u03b1\u03bd\u03b7\u03bc\u03ac\u03c4\u03c9\u03bd<\/label>\n <\/div>\n <div class=\"option-item\">\n <input class=\"form-check-input\" type=\"radio\" name=\"cargoType\" id=\"cargoType_targyak\"\n value=\"\u03b1\u03bd\u03c4\u03b9\u03ba\u03b5\u03af\u03bc\u03b5\u03bd\u03b1-\u03b5\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03b1\">\n <label class=\"form-check-label\" for=\"cargoType_targyak\">\u0391\u03bd\u03c4\u03b9\u03ba\u03b5\u03af\u03bc\u03b5\u03bd\u03b1 \/ \u0395\u03c1\u03b3\u03b1\u03bb\u03b5\u03af\u03b1<\/label>\n <\/div>\n <div class=\"option-item\">\n <input class=\"form-check-input\" type=\"radio\" name=\"cargoType\" id=\"cargoType_egyeb\"\n value=\"\u03ac\u03bb\u03bb\u03b1\">\n <label class=\"form-check-label\" for=\"cargoType_egyeb\">\u0386\u03bb\u03bb\u03b1<\/label>\n <\/div>\n <\/div>\n <\/div>\n\n <div class=\"form-group\">\n <label for=\"from\" class=\"form-label\">\u0391\u03c0\u03cc \u03c0\u03bf\u03cd<\/label>\n <input type=\"text\" class=\"form-control\" id=\"from\" name=\"from\" \n placeholder=\"\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03ce \u03b5\u03b9\u03c3\u03ac\u03b3\u03b5\u03c4\u03b5 \u03c4\u03bf\u03bd \u03c4\u03cc\u03c0\u03bf \u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae\u03c2...\" required>\n <\/div>\n\n <div class=\"form-group\">\n <label for=\"to\" class=\"form-label\">\u03a0\u03bf\u03cd<\/label>\n <input type=\"text\" class=\"form-control\" id=\"to\" name=\"to\" \n placeholder=\"\u0395\u03b9\u03c3\u03ac\u03b3\u03b5\u03c4\u03b5 \u03c4\u03bf\u03bd \u03c0\u03c1\u03bf\u03bf\u03c1\u03b9\u03c3\u03bc\u03cc...\" required>\n <\/div>\n\n <div class=\"form-group\" id=\"weightGroup\">\n <label for=\"weight\" class=\"form-label\">\u0392\u03ac\u03c1\u03bf\u03c2 (kg)<\/label>\n <input type=\"number\" class=\"form-control\" id=\"weight\" name=\"weight\" \n placeholder=\"\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03bf\u03cd\u03bc\u03b5 \u03b5\u03b9\u03c3\u03ac\u03b3\u03b5\u03c4\u03b5 \u03c4\u03bf \u03b2\u03ac\u03c1\u03bf\u03c2 \u03c3\u03b5 \u03ba\u03b9\u03bb\u03ac...\">\n <\/div>\n\n <div class=\"form-group\" id=\"quantityGroup\">\n <label for=\"quantity\" class=\"form-label\">\u03a0\u03bf\u03c3\u03cc\u03c4\u03b7\u03c4\u03b1<\/label>\n <input type=\"number\" class=\"form-control\" id=\"quantity\" name=\"quantity\" \n placeholder=\"\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03ce \u03b5\u03b9\u03c3\u03ac\u03b3\u03b5\u03c4\u03b5 \u03c4\u03b7\u03bd \u03c0\u03bf\u03c3\u03cc\u03c4\u03b7\u03c4\u03b1...\">\n <\/div>\n\n <div class=\"form-group\" id=\"unitGroup\">\n <label for=\"unit\" class=\"form-label\">\u039c\u03bf\u03bd\u03ac\u03b4\u03b1 \u03a0\u03bf\u03c3\u03cc\u03c4\u03b7\u03c4\u03b1\u03c2<\/label>\n <select class=\"form-select\" id=\"unit\" name=\"unit\">\n <option value=\"\">\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03bc\u03bf\u03bd\u03ac\u03b4\u03b1...<\/option>\n <option value=\"\u03c0\u03b1\u03bb\u03ad\u03c4\u03b1\">\u03a0\u03b1\u03bb\u03ad\u03c4\u03b1<\/option>\n <option value=\"\u03ba\u03bf\u03bc\u03bc\u03ac\u03c4\u03b9\">\u03a4\u03b5\u03bc\u03ac\u03c7\u03b9\u03bf<\/option>\n <option value=\"\u03ba\u03c5\u03b2\u03b9\u03ba\u03cc \u03bc\u03ad\u03c4\u03c1\u03bf\">\u039a\u03cd\u03b2\u03bf\u03c2 \u03bc\u03ad\u03c4\u03c1\u03bf<\/option>\n <option value=\"\u03ba\u03bf\u03c5\u03c4\u03af\">\u039a\u03bf\u03c5\u03c4\u03af<\/option>\n <option value=\"\u03bc\u03bf\u03af\u03c1\u03b5\u03c2 \u00cf\u03c7\u03bd\u03b5\u03c5\u03bc\u03ac\u03c4\u03c9\u03bd\">\u0386\u03b4\u03b5\u03b9\u03b1\u03c3\u03bc\u03b1\u03bc\u03b5\u03c4\u03c1\u03b7\u03c4\u03ae\u03c2<\/option>\n <option value=\"\u03ac\u03bb\u03bb\u03b1\">\u0386\u03bb\u03bb\u03b1<\/option>\n <\/select>\n <\/div>\n\n <div class=\"form-group\" id=\"dimensionGroup\">\n <label for=\"dimensions\" class=\"form-label\">\u039c\u03ad\u03b3\u03b5\u03b8\u03bf\u03c2 (\u03bc\u03ae\u03ba\u03bf\u03c2 x \u03cd\u03c8\u03bf\u03c2 x \u03c0\u03bb\u03ac\u03c4\u03bf\u03c2, \u03b5\u03ba.)<\/label>\n <input type=\"text\" class=\"form-control\" id=\"dimensions\" name=\"dimensions\"\n placeholder=\"\u03c0.\u03c7. 120x80x150\">\n <div class=\"option-item\" style=\"margin-top: 12px;\">\n <input type=\"checkbox\" class=\"form-check-input\" id=\"dimensionCheckbox\" name=\"dimensionCheckbox\"\n value=\"\u03a0\u03c1\u03bf\u03b4\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae \u0395\u03c5\u03c1\u03c9\u03c0\u03b1\u03ca\u03ba\u03ae\u03c2 \u03c4\u03c5\u03c0\u03bf\u03c0\u03bf\u03b9\u03b7\u03bc\u03ad\u03bd\u03b7\u03c2 \u03c0\u03b1\u03bb\u03ad\u03c4\u03b1\u03c2 (120x80x150 \u03b5\u03ba.)\">\n <label class=\"form-check-label\"\n for=\"dimensionCheckbox\">\u03a0\u03c1\u03bf\u03b4\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae \u0395\u03c5\u03c1\u03c9\u03c0\u03b1\u03ca\u03ba\u03ae\u03c2 \u03c4\u03c5\u03c0\u03bf\u03c0\u03bf\u03b9\u03b7\u03bc\u03ad\u03bd\u03b7\u03c2 \u03c0\u03b1\u03bb\u03ad\u03c4\u03b1\u03c2 (120x80x150 \u03b5\u03ba.)<\/label>\n <\/div>\n <\/div>\n\n <div class=\"form-group\" id=\"vehicleGroup\">\n <label for=\"vehicle\" class=\"form-label\">\u0391\u03af\u03c4\u03b7\u03c3\u03b7 \u03bf\u03c7\u03ae\u03bc\u03b1\u03c4\u03bf\u03c2<\/label>\n <select class=\"form-select\" id=\"vehicle\" name=\"vehicle\">\n <option value=\"\">\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03cc\u03c7\u03b7\u03bc\u03b1<\/option>\n <option value=\"\u0394\u03b5\u03bd \u03be\u03ad\u03c1\u03c9 \u03c3\u03b5 \u03c4\u03b9 \u03bc\u03c0\u03bf\u03c1\u03ce \u03bd\u03b1 \u03c7\u03c9\u03c1\u03ad\u03c3\u03c9\">\u0394\u03b5\u03bd \u03be\u03ad\u03c1\u03c9 \u03c3\u03b5 \u03c4\u03b9 \u03bc\u03c0\u03bf\u03c1\u03ce \u03bd\u03b1 \u03c7\u03c9\u03c1\u03ad\u03c3\u03c9<\/option>\n <option value=\"3,5t \u03c6\u03bf\u03c1\u03c4\u03b7\u03b3\u03cc (1,2t \u03c9\u03c6\u03ad\u03bb\u03b9\u03bc\u03bf)\">3,5t \u03c6\u03bf\u03c1\u03c4\u03b7\u03b3\u03cc (1,2t \u03c9\u03c6\u03ad\u03bb\u03b9\u03bc\u03bf)<\/option>\n <option value=\"7,5\u03c4\u03bf\u03bd \u03c6\u03bf\u03c1\u03c4\u03b7\u03b3\u03cc (3\u03c4\u03bf\u03bd \u03c9\u03c6\u03ad\u03bb\u03b9\u03bc\u03bf)\">7,5\u03c4\u03bf\u03bd \u03c6\u03bf\u03c1\u03c4\u03b7\u03b3\u03cc (3\u03c4\u03bf\u03bd \u03c9\u03c6\u03ad\u03bb\u03b9\u03bc\u03bf)<\/option>\n <option value=\"12t \u03c6\u03bf\u03c1\u03c4\u03b7\u03b3\u03cc (6t \u03c9\u03c6\u03ad\u03bb\u03b9\u03bc\u03bf)\">12t \u03c6\u03bf\u03c1\u03c4\u03b7\u03b3\u03cc (6t \u03c9\u03c6\u03ad\u03bb\u03b9\u03bc\u03bf)<\/option>\n <option value=\"tandem (15\u03c4 \u03bb\u03bf\u03b3\u03b9\u03c3\u03c4\u03b9\u03ba\u03ae \u03b9\u03ba\u03b1\u03bd\u03cc\u03c4\u03b7\u03c4\u03b1)\">\u03a4\u03b5\u03c4\u03c1\u03ac\u03ba\u03c9\u03c0\u03bf (15t \u03c9\u03c6\u03ad\u03bb\u03b9\u03bc\u03bf)<\/option>\n <option value=\"24t \u03b7\u03bc\u03b9\u03c1\u03c5\u03bc\u03bf\u03c5\u03bb\u03ba\u03bf\u03cd\u03bc\u03b5\u03bd\u03bf (\u03c9\u03c6\u03ad\u03bb\u03b9\u03bc\u03bf\u03c5 \u03c6\u03bf\u03c1\u03c4\u03af\u03bf\u03c5)\">24t \u03b7\u03bc\u03b9\u03c1\u03c5\u03bc\u03bf\u03c5\u03bb\u03ba\u03bf\u03cd\u03bc\u03b5\u03bd\u03bf (\u03c9\u03c6\u03ad\u03bb\u03b9\u03bc\u03bf\u03c5 \u03c6\u03bf\u03c1\u03c4\u03af\u03bf\u03c5)<\/option>\n <\/select>\n <\/div>\n\n <div class=\"form-group\" id=\"specialGroup\">\n <label class=\"form-label\">\u0395\u03b9\u03b4\u03b9\u03ba\u03ad\u03c2 \u03b1\u03c0\u03b1\u03b9\u03c4\u03ae\u03c3\u03b5\u03b9\u03c2<\/label>\n <div class=\"special-grid\">\n <div class=\"option-item\">\n <input class=\"form-check-input\" type=\"checkbox\" name=\"special\" value=\"ADR\" id=\"adr\">\n <label class=\"form-check-label\" for=\"adr\">ADR<\/label>\n <\/div>\n <div class=\"option-item\">\n <input class=\"form-check-input\" type=\"checkbox\" name=\"special\" value=\"\u03b8\u03b5\u03c1\u03bc\u03b1\u03b9\u03bd\u03cc\u03bc\u03b5\u03bd\u03bf\u03c2\" id=\"temperalt\">\n <label class=\"form-check-label\" for=\"temperalt\">\u0398\u03b5\u03c1\u03bc\u03b1\u03b9\u03bd\u03cc\u03bc\u03b5\u03bd\u03bf<\/label>\n <\/div>\n <div class=\"option-item\">\n <input class=\"form-check-input\" type=\"checkbox\" name=\"special\" value=\"\u03b1\u03bd\u03c5\u03c8\u03c9\u03c4\u03b9\u03ba\u03cc \u03c4\u03ad\u03c1\u03bc\u03b1 \u03c6\u03bf\u03c1\u03c4\u03b7\u03b3\u03bf\u03cd\" id=\"emelohatfal\">\n <label class=\"form-check-label\" for=\"emelohatfal\">\u03b1\u03bd\u03c5\u03c8\u03c9\u03c4\u03b9\u03ba\u03cc \u03c0\u03bb\u03b1\u03ca\u03bd\u03cc \u03c6\u03bf\u03c1\u03c4\u03af\u03bf<\/label>\n <\/div>\n <div class=\"option-item\">\n <input class=\"form-check-input\" type=\"checkbox\" name=\"special\" value=\"\u03b1\u03bd\u03c5\u03c8\u03c9\u03c4\u03b9\u03ba\u03cc \u03cc\u03c7\u03b7\u03bc\u03b1\" id=\"darus\">\n <label class=\"form-check-label\" for=\"darus\">\u0393\u03b5\u03c1\u03b1\u03bd\u03cc\u03c2 \u03cc\u03c7\u03b7\u03bc\u03b1<\/label>\n <\/div>\n <div class=\"option-item\">\n <input class=\"form-check-input\" type=\"checkbox\" name=\"special\" value=\"\u03c7\u03b5\u03b9\u03c1\u03bf\u03ba\u03af\u03bd\u03b7\u03c4\u03bf\u03c2 \u03c6\u03cc\u03c1\u03c4\u03c9\u03c3\u03b7\u03c2\" id=\"kezi\">\n <label class=\"form-check-label\" for=\"kezi\">\u03a7\u03b5\u03b9\u03c1\u03bf\u03ba\u03af\u03bd\u03b7\u03c4\u03b7 \u03c6\u03cc\u03c1\u03c4\u03c9\u03c3\u03b7<\/label>\n <\/div>\n <\/div>\n <\/div>\n \n <div class=\"form-group\">\n <label for=\"moreinfo\" class=\"form-label\">\u03a0\u03b5\u03c1\u03b9\u03c3\u03c3\u03cc\u03c4\u03b5\u03c1\u03b5\u03c2 \u03c0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2<\/label>\n <textarea class=\"form-control\" id=\"moreinfo\" name=\"moreinfo\" rows=\"3\"\n placeholder=\"\u03a0\u03c1\u03bf\u03c3\u03b8\u03ad\u03c3\u03c4\u03b5 \u03c0\u03b5\u03c1\u03b9\u03c3\u03c3\u03cc\u03c4\u03b5\u03c1\u03b5\u03c2 \u03bb\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2 \u03c3\u03c7\u03b5\u03c4\u03b9\u03ba\u03ac \u03bc\u03b5 \u03c4\u03b9\u03c2 \u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ad\u03c2...\"><\/textarea>\n <\/div>\n \n <div class=\"submit-section\">\n <button type=\"submit\" class=\"btn-submit\">\n <i class=\"bi bi-send\"><\/i>\n \u0396\u03ae\u03c4\u03b7\u03c3\u03b7 \u03a5\u03c0\u03bf\u03bb\u03bf\u03b3\u03b9\u03c3\u03bc\u03bf\u03cd \u039c\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03b9\u03ba\u03bf\u03cd \u0395\u03b9\u03c3\u03b9\u03c4\u03b7\u03c1\u03af\u03bf\u03c5 <\/button>\n <\/div>\n <\/form>\n <\/div>\n <\/div>\n<script>\n \/\/ Smooth field visibility animations\n function toggleFields() {\n const type = $('input[name=\"cargoType\"]:checked').val();\n \n \/\/ Hide all optional groups first\n $('.form-group').removeClass('hidden');\n \n if (type === '\u03bc\u03b5\u03c4\u03b1\u03ba\u03cc\u03bc\u03b9\u03c3\u03b7') {\n $('#weightGroup, #quantityGroup, #unitGroup, #specialGroup, #dimensionGroup').addClass('hidden');\n $('#vehicleGroup').removeClass('hidden');\n } else if (type === '\u03cc\u03c7\u03b7\u03bc\u03b1' || type === '\u03c6\u03bf\u03c1\u03c4\u03b7\u03b3\u03cc \u03b5\u03c1\u03b3\u03bf\u03bb\u03ac\u03b2\u03bf\u03c5') {\n $('#quantityGroup, #unitGroup, #specialGroup, #vehicleGroup').addClass('hidden');\n $('#weightGroup, #dimensionGroup').removeClass('hidden');\n } else if (type === '\u03bc\u03b7\u03c7\u03b1\u03bd\u03ae\u03bc\u03b1\u03c4\u03b1 \u03ba\u03b1\u03b9 \u03b5\u03be\u03bf\u03c0\u03bb\u03b9\u03c3\u03bc\u03cc\u03c2') {\n $('#quantityGroup, #unitGroup, #specialGroup').addClass('hidden');\n $('#weightGroup, #dimensionGroup, #vehicleGroup').removeClass('hidden');\n } else if (type === '\u03b1\u03bd\u03b5\u03c0\u03b5\u03af\u03c1\u03b1\u03c3\u03c4\u03b7 \u03c6\u03bf\u03c1\u03c4\u03af\u03b1' || type === '\u03b4\u03b7\u03bc\u03b7\u03c4\u03c1\u03b9\u03b1\u03ba\u03ac') {\n $('#vehicleGroup, #dimensionGroup, #quantityGroup, #unitGroup, #specialGroup').addClass('hidden');\n $('#weightGroup').removeClass('hidden');\n } else {\n \/\/ Default: show all\n $('.form-group').removeClass('hidden');\n }\n }\n\n \/\/ EUR raklap m\u00e9ret checkbox functionality\n $('#dimensionCheckbox').on('change', function () {\n if ($(this).is(':checked')) {\n $('#dimensions').prop('disabled', true).addClass('disabled');\n } else {\n $('#dimensions').prop('disabled', false).removeClass('disabled');\n }\n });\n\n \/\/ Initialize\n $(document).ready(function() {\n \/\/ Radio button change handlers\n $('input[name=\"cargoType\"]').on('change', toggleFields);\n \n \/\/ Initial state\n toggleFields();\n \n \/\/ EUR checkbox initial state\n if ($('#dimensionCheckbox').is(':checked')) {\n $('#dimensions').prop('disabled', true).addClass('disabled');\n }\n \n \/\/ Form validation styling\n $('input[required], select[required]').on('blur', function() {\n const $group = $(this).closest('.form-group');\n if ($(this).val()) {\n $group.addClass('success').removeClass('error');\n } else {\n $group.addClass('error').removeClass('success');\n }\n });\n });\n\n \/\/ Form submission with enhanced UX\n $('#freightForm').submit(function (e) {\n e.preventDefault();\n \n const $submitBtn = $('.btn-submit');\n $submitBtn.addClass('loading').prop('disabled', true);\n \n \/\/ Collect form data\n const formData = $(this).serializeArray();\n let params = [];\n\n function getLabelText(name) {\n const $label = $(`[name=\"${name}\"]`).closest('.form-group').find('.form-label');\n if ($label.length) {\n return $label.text().trim();\n }\n if (name === 'special') {\n return '\u0395\u03b9\u03b4\u03b9\u03ba\u03ad\u03c2 \u03b1\u03c0\u03b1\u03b9\u03c4\u03ae\u03c3\u03b5\u03b9\u03c2';\n }\n return name;\n }\n\n $.each(formData, function (i, field) {\n if (field.value) {\n if (field.name === 'special') {\n params.push(field.value);\n } else {\n params.push(`${getLabelText(field.name)}: ${field.value}`);\n }\n }\n });\n\n const prompt = `\u0398\u03b1 \u03ae\u03b8\u03b5\u03bb\u03b1 \u03bd\u03b1 \u03b6\u03b7\u03c4\u03ae\u03c3\u03c9 \u03ac\u03bc\u03b5\u03c3\u03b7 \u03b5\u03ba\u03c4\u03af\u03bc\u03b7\u03c3\u03b7 \u03ba\u03bf\u03c3\u03c4\u03bf\u03bb\u03cc\u03b3\u03b7\u03c3\u03b7\u03c2 \u03bc\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03b9\u03ba\u03bf\u03cd \u03ba\u03cc\u03c3\u03c4\u03bf\u03c5\u03c2 \u03b3\u03b9\u03b1 \u03c4\u03b7\u03bd \u03c0\u03b1\u03c1\u03b1\u03ba\u03ac\u03c4\u03c9 \u03b1\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae: ${params.join(', ')}`;\n const url = `https:\/\/fuvarborze.hu\/chat\/?prompt=${encodeURIComponent(prompt)}`;\n \n \/\/ Simulate processing time for better UX\n setTimeout(() => {\n window.open(url, '_self');\n }, 500);\n });\n<\/script>\n"); } } // Widget megjelenítése function showCalculatorWidget() { calculatorWidget.addClass('show'); if (isWidgetOpen) { calculatorWidget.addClass('expanded'); calcMinimizeBtn.html('<i class="bi bi-dash"></i>'); } else { calculatorWidget.removeClass('expanded'); calcMinimizeBtn.html('<i class="bi bi-plus"></i>'); } loadCalculatorContent(); } // Widget elrejtése function hideCalculatorWidget() { return false; // Ha a felhasználó bejelölte, hogy ne jelenjen meg újra calculatorWidget.removeClass('show expanded'); setCalcCookie('calc_widget_closed', 'true', 1); } // Widget kinyitása/bezárása function toggleCalculatorWidget() { var isExpanded = calculatorWidget.hasClass('expanded'); if (isExpanded) { calculatorWidget.removeClass('expanded'); calcMinimizeBtn.html('<i class="bi bi-plus"></i>'); setCalcCookie('calc_widget_open', 'false', 30); } else { calculatorWidget.addClass('expanded'); calcMinimizeBtn.html('<i class="bi bi-dash"></i>'); setCalcCookie('calc_widget_open', 'true', 30); loadCalculatorContent(); } } // Eseménykezelők calculatorHeader.on('click', function (e) { if (!$(e.target).closest('.calculator-controls').length) { toggleCalculatorWidget(); } }); calcMinimizeBtn.on('click', function (e) { e.stopPropagation(); toggleCalculatorWidget(); }); calcCloseBtn.on('click', function (e) { e.stopPropagation(); if ($('#dontShowCalcWidgetAgain').is(':checked')) { setCalcCookie('dont_show_calc_widget', 'true', 1); } hideCalculatorWidget(); }); // Automatikus megjelenítés // Cookie funkciók function setCalcCookie(name, value, days) { var expires = ""; if (days) { var date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); expires = "; expires=" + date.toUTCString(); } document.cookie = name + "=" + (value || "") + expires + "; path=/"; } function getCalcCookie(name) { var nameEQ = name + "="; var ca = document.cookie.split(';'); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') c = c.substring(1, c.length); if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); } return null; } // Eredeti modal eseménykezelők (változatlan) $('.modal-close').on('click', function () { $('#subscriptionNoticeModal').modal('hide'); }); }); </script> <style> .calculator-widget { position: fixed; bottom: 0; right: 50px; width: 400px; max-width: calc(100vw - 40px); background: white; border: 1px solid #ddd; border-radius: 10px 10px 0 0; box-shadow: 0 -5px 15px rgba(0, 0, 0, 0.2); z-index: 9999; transform: translateY(100%); transition: transform 0.3s ease-in-out; display: none; } .calculator-widget.show { display: block; transform: translateY(calc(100% - 60px)); } .calculator-widget.expanded { transform: translateY(0); } .calculator-header { background: #007bff; color: white; padding: 15px 20px; border-radius: 10px 10px 0 0; cursor: pointer; display: flex; justify-content: space-between; align-items: center; user-select: none; height: 60px; box-sizing: border-box; } .calculator-title { font-weight: bold; font-size: 16px; } .calculator-controls { display: flex; gap: 5px; } .calc-minimize-btn, .calc-close-btn { background: rgba(255, 255, 255, 0.2); border: none; color: white; width: 30px; height: 30px; border-radius: 50%; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background-color 0.2s; } .calc-minimize-btn:hover, .calc-close-btn:hover { background: rgba(255, 255, 255, 0.3); } .calculator-body { padding: 20px; max-height: 400px; overflow-y: auto; } .calculator-footer { padding: 15px 20px; border-top: 1px solid #eee; background: #f8f9fa; } @media (max-width: 768px) { .calculator-widget { right: 10px; left: 10px; width: auto; max-width: none; } .calculator-header { padding: 12px 15px; height: 50px; } .calculator-widget.show { transform: translateY(calc(100% - 50px)); } .calculator-widget.expanded { transform: translateY(0) !important; } .calculator-title { font-size: 14px; } .calc-minimize-btn, .calc-close-btn { width: 25px; height: 25px; } } /* Eredeti modal CSS-ek eltávolítása/módosítása */ #calculatorModal { display: none !important; } </style> <div class="push-notification"></div> <script> $(document).ready(function () { var messages = [ "Γεια σας! Ψάχνετε για μεταφορέα;", "Ας υπολογίσουμε γρήγορα μια χρέωση μεταφοράς;", "Τι και πού θα πρέπει να μεταφερθεί;", "Ή μήπως είστε μεταφορέας;" ]; // Show alert once per day to everyone var alertKey = 'chat_daily_alert_shown'; var today = new Date().toISOString().slice(0, 10); // YYYY-MM-DD if ($.cookie(alertKey) !== today && 1==2) { var alertText = "<h3>Οδηγίες Ασφάλειας!</h3>Σημαντικό να θυμάστε ότι για την ασφάλειά σας ποτέ μην πληρώνετε το freight προκαταβολικά με μεταφορά! Οι μεταφορείς απαγορεύεται να ζητούν προκαταβολή του freight στη Fuvarbörze. Για να ανοίξετε τις οδηγίες ασφάλειας της Fuvarbörze, ΚΑΝΤΕ ΚΛΙΚ ΕΔΩ!"; $('.new-message').text('!'); $('.new-message').show(); $('.push-notification').show(); $('.push-notification').append('<div class="push-notification-alert" style="background: #e53935; color: #fff;">' + alertText + '<span class="push-notification-alert-close">✘</span></div>'); $('.push-notification-alert').on('click', function () { window.location.href = 'https://fuvarborze.hu/el/ai/kerdesek-es-valaszok/fuvarborze-biztonsagi-iranyelvek'; $.cookie(alertKey, today, { expires: 1, path: '/' }); }); $('.push-notification-alert-close').on('click', function () { $(this).parent().remove(); $.cookie(alertKey, today, { expires: 1, path: '/' }); }); } var index = 0; if ($.cookie('chat_welcome_message') > 0 && $.cookie('chat_welcome_push_off') < 1 && 1==2) { for (var i = 0; i < $.cookie('chat_welcome_message'); i++) { $('.new-message').text(i + 1); $('.new-message').show(); $('.push-notification').show(); var message = messages[i]; $('.push-notification').append('<div class="push-notification-alert">' + message + '<span class="push-notification-alert-close">✘</span></div>'); $('.push-notification-alert').on('click', function () { $.cookie('chat_welcome_push_off', 1, { expires: 360, path: '/' }); window.location.href = 'https://fuvarborze.hu/el/chat/'; }); $('.push-notification-alert-close').on('click', function () { $.cookie('chat_welcome_push_off', 1, { expires: 360, path: '/' }); $(this).parent().remove(); }); } } setInterval(function () { // Ha hangcsevegés folyamatban van, ne ellenőrizzünk és ne jelenítsünk meg értesítéseket if (window.fgptVoiceGlobal && window.fgptVoiceGlobal.running) { return; } $.get('/modules/chat/chatajax.php?proc=newmess_check&conversation_id=', function (data) { if (data.new_messages > 0) { if ($('.new-message').text() < 1) { var lastmessage_nr = 0; } else { var lastmessage_nr = parseInt($('.new-message').text()); } $('.new-message').text(data.new_messages); $('.new-message').show(); let currentLink = 'list'; if (currentLink != 'chat' && $.cookie('lastmessage_id') < data.lastmessage_id) { $('.push-notification').show(); for (var i = 0; i < data.messages.length; i++) { var message = data.messages[i].message; var message_id = data.messages[i].id; if (message_id > $.cookie('lastmessage_id')) { $('.push-notification').append('<div class="push-notification-item">' + message + '<span class="push-notification-item-close">✘</span></div>'); } } $.cookie('lastmessage_id', data.lastmessage_id, { expires: 360, path: '/' }); $('.push-notification-item').on('click', function () { window.location.href = 'https://fuvarborze.hu/el/chat/'; }); $('.push-notification-item-close').on('click', function () { $(this).parent().remove(); }); } } else if ($.cookie('chat_welcome_push_off') < 1 && 0 == 0 && 1==2) { if ($.cookie('chat_welcome_message') == undefined || $.cookie('chat_welcome_message') == null) { $.cookie('chat_welcome_message', 0, { expires: 360, path: '/' }); } if (index < messages.length && $.cookie('chat_welcome_message') < messages.length) { $('.new-message').show(); var message = messages[$.cookie('chat_welcome_message')]; index = parseInt($.cookie('chat_welcome_message')) + 1; $('.new-message').text(index); if (index > $.cookie('chat_welcome_message') && $.cookie('chat_welcome_message') < messages.length) { $('.push-notification').show(); $('.push-notification').append('<div class="push-notification-item">' + message + '<span class="push-notification-item-close">✘</span></div>'); $('.push-notification-item').on('click', function () { window.location.href = 'https://fuvarborze.hu/el/chat/'; }); $('.push-notification-item-close').on('click', function () { $(this).parent().remove(); }); $.cookie('chat_welcome_message', index, { expires: 360, path: '/' }); } } } }, 'json'); }, Math.floor(Math.random() * (30000 - 10000 + 1)) + 10000); // Poll every 10-30 seconds (was 2-10s, reduced MySQL load by ~70%) }); </script> <script> document.addEventListener('scroll', function () { var footerContent = document.getElementById('footerContent'); if (footerContent) { if (window.scrollY > 100) { footerContent.style.transform = 'translateY(100%)'; footerContent.style.transition = 'transform 0.3s ease-in-out'; } else { footerContent.style.transform = 'translateY(0)'; } } }); // Scroll to top gomb var scrollToTopBtn = document.getElementById('scrollToTopBtn'); if (scrollToTopBtn) { window.addEventListener('scroll', function () { if (window.pageYOffset > 300) { scrollToTopBtn.style.display = 'block'; } else { scrollToTopBtn.style.display = 'none'; } }); scrollToTopBtn.addEventListener('click', function () { window.scrollTo({ top: 0, behavior: 'smooth' }); }); } </script> <style> #scrollToTopBtn { position: fixed; bottom: 20px; left: 20px; background-color: #007bff; color: white; border: none; border-radius: 50%; width: 50px; height: 50px; font-size: 20px; cursor: pointer; display: none; z-index: 1000; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); transition: all 0.3s ease; } #scrollToTopBtn:hover { background-color: #0056b3; transform: scale(1.1); } @media (max-width: 768px) { #scrollToTopBtn { bottom: 80px; left: 10px; width: 40px; height: 40px; font-size: 16px; } .new-message { top: 0; } } @media (min-width: 768px) { .new-message { top: 90px; } } .new-message { position: absolute; right: 5px; top: 5px; background-color: red; color: white; font-weight: bold; border-radius: 50%; width: 25px; height: 25px; font-size: 12px; display: none; max-width: 25px; max-height: 25px; line-height: 21px; text-align: center; box-sizing: border-box; border: solid 2px #FFF; } .push-notification-alert { background: rgb(205, 246, 250); color: rgb(60, 108, 116); padding: 10px 15px; margin-top: 10px; border-radius: 5px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); font-size: 14px; cursor: pointer; } .push-notification-alert-close { float: right; font-size: 20px; color: #000; cursor: pointer; margin-left: 10px; } .push-notification { position: fixed; width: 300px; display: none; top: 100px; right: 20px; z-index: 10000; } .push-notification-item-close { float: right; font-size: 20px; color: #000; cursor: pointer; margin-left: 10px; } .push-notification-item { background: rgb(177, 213, 252); color: rgb(60, 108, 116); padding: 10px 15px; margin-top: 10px; border-radius: 5px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); font-size: 14px; cursor: pointer; } .blinking { animation: blink 1s infinite; } @keyframes blink { 0% { opacity: 1; } 50% { opacity: 0.5; } 100% { opacity: 1; } } </style> <style> @media screen and (max-width: 768px) { .languageSelection { position: fixed; bottom: 40px; left: 20px; background: #FFFFFF; padding: 0; border: none; border-radius: 50%; cursor: pointer; z-index: 9998; box-shadow: 0 2px 10px rgba(0,0,0,0.15); } .languageSelection .currentLanguage { width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; border-radius: 50%; font-size: 24px; } .languageSelection #languagesContainer.languagesContainer { position: absolute; bottom: 50px; left: 0; background: #fff; border-radius: 12px; padding: 10px; box-shadow: 0 4px 20px rgba(0,0,0,0.2); } } @media screen and (min-width: 768px) { .languageSelection { position: fixed; bottom: 40px; left: 20px; background: #FFFFFF; padding: 0; border: none; border-radius: 50%; cursor: pointer; z-index: 9998; box-shadow: 0 2px 10px rgba(0,0,0,0.15); } .languageSelection .currentLanguage { width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; border-radius: 50%; font-size: 28px; } .languageSelection #languagesContainer.languagesContainer { position: absolute; bottom: 55px; left: 0; background: #fff; border-radius: 12px; padding: 10px; box-shadow: 0 4px 20px rgba(0,0,0,0.2); } } .languagesContainer { grid-template-columns: repeat(4, 1fr); grid-gap: 8px; display: grid; } .languageItem { cursor: pointer; text-align: center; font-size: 24px; line-height: 1; } .languageItem a { text-decoration: none; display: block; padding: 4px; border-radius: 6px; transition: background 0.15s; } .languageItem a:hover { background: #f0f0f0; } .modal-title img { height: 50px; width: auto; } #scrollToTopBtn { position: fixed; bottom: -15px; left: 50%; transform: translateX(-50%); background-color: white; color: #007bff; border: 2px solid #007bff; border-radius: 50%; width: 50px; height: 50px; font-size: 20px; cursor: pointer; display: none; z-index: 1000; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); transition: all 0.3s ease; } #scrollToTopBtn:hover { background-color: #007bff; color: white; transform: translateX(-50%) scale(1.1); } @media (max-width: 768px) { #scrollToTopBtn { bottom: 40px; width: 40px; height: 40px; font-size: 16px; } } .footer-content { position: fixed; bottom: 0; left: 0; width: 100%; background-color: #f8f9fa; border-top: 1px solid #ddd; padding: 10px; text-align: left; z-index: 1000; } </style> <!-- FreightGPT intro video modal (50% black overlay) --> <style> .fgpt-video-modal { position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: none; align-items: center; justify-content: center; z-index: 200000; padding: 20px; box-sizing: border-box; } .fgpt-video-modal.show { display: flex; } .fgpt-video-inner { width: min(1100px, 95vw); max-width: 1100px; background: transparent; border-radius: 12px; position: relative; display:flex; align-items:center; justify-content:center; max-height: 90vh; box-sizing: border-box; } /* Ensure video never overflows viewport height */ .fgpt-video-inner video { max-width: 100%; width: auto; height: auto; max-height: calc(90vh - 40px); display: block; border-radius: 8px; background: #000; object-fit: contain; } /* Reposition close button to avoid iOS volume overlay & hardware button area */ .fgpt-video-close { position: fixed; top: calc(env(safe-area-inset-top, 0px) + 8px); right: calc(env(safe-area-inset-right, 0px) + 8px); width: 44px; height: 44px; border-radius: 50%; background: rgba(0,0,0,0.65); color: #fff; border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 22px; box-shadow: 0 6px 18px rgba(0,0,0,0.5); z-index: 200001; backdrop-filter: blur(2px); } .fgpt-video-close:active { transform: scale(0.92); } @supports (padding: env(safe-area-inset-top)) { .fgpt-video-close { top: calc(env(safe-area-inset-top) + 8px); right: calc(env(safe-area-inset-right) + 8px); } } /* Speaker hint overlay */ .fgpt-audio-hint { position: absolute; top: 50px; left: 50%; transform: translateX(-50%); display: none; align-items: center; gap: 8px; background: rgba(0,0,0,0.6); color: #fff; padding: 8px 12px; border-radius: 999px; cursor: pointer; z-index: 200001; user-select: none; box-shadow: 0 4px 12px rgba(0,0,0,0.3); } .fgpt-audio-hint .icon { width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; } .fgpt-audio-hint .text { font-size: 14px; line-height: 1; white-space: nowrap; } @media (max-width: 768px) { .fgpt-video-inner { width: 94vw; max-height: 86vh; } /* JAVÍTVA: a width: 100% helyett auto, hogy az object-fit helyesen működjön */ .fgpt-video-inner video { max-height: calc(86vh - 32px); width: auto; max-width: 100%; } .fgpt-audio-hint { top: 40px; padding: 10px 14px; } } </style> <div id="fgpt-video-modal" class="fgpt-video-modal" role="dialog" aria-modal="true" aria-label="FreightGPT bemutató videó"> <button id="fgpt-video-close" class="fgpt-video-close" aria-label="Bezár">×</button> <div class="fgpt-video-inner"> <video id="fgpt-video" playsinline webkit-playsinline muted autoplay controls preload="auto"> <source src="https://fuvarborze.hu/images/videos/freightgpt-video.mp4" type="video/mp4"> Ο περιηγητής σας δεν υποστηρίζει την αναπαραγωγή βίντεο. </video> <div id="fgpt-audio-hint" class="fgpt-audio-hint" role="button" tabindex="0" aria-label="Ενεργοποίηση ήχου"> <span class="icon" aria-hidden="true"> <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor" focusable="false" aria-hidden="true"> <path d="M3 10v4h4l5 5V5L7 10H3zm13.5 2c0-1.77-1.02-3.29-2.5-4.03v8.06c1.48-.74 2.5-2.26 2.5-4.03z"></path> <path d="M14 3.23v2.06c2.89 0.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-0.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"></path> </svg> </span> <span class="text">Φόρτωση...</span> </div> </div> </div> <script> (function(){ function setFgptCookie(name, value, days){ var expires = ''; if (days){ var d = new Date(); d.setTime(d.getTime() + (days*24*60*60*1000)); expires = '; expires=' + d.toUTCString(); } document.cookie = name + '=' + encodeURIComponent(value || '') + expires + '; path=/'; } function getFgptCookie(name){ var nameEQ = name + '='; var ca = document.cookie.split(';'); for (var i=0;i<ca.length;i++){ var c = ca[i].trim(); if (c.indexOf(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length)); } return null; } var cookieName = 'fgpt_video_closed'; // Global function to open video modal (called from DataImport) window.openFgptVideoModal = function() { var modal = document.getElementById('fgpt-video-modal'); var vid = document.getElementById('fgpt-video'); var hint = document.getElementById('fgpt-audio-hint'); if (!modal || !vid) return; modal.classList.add('show'); // Attempt to play try { var p = vid.play(); if (p && typeof p.then === 'function') { p.catch(function(){ /* ignore */ }); } } catch(_){ } // Android controls fix var isAndroid = /Android/i.test(navigator.userAgent); if (isAndroid) { function ensureControls() { if (!vid.hasAttribute('controls')) vid.setAttribute('controls',''); vid.style.pointerEvents = 'auto'; } vid.addEventListener('loadedmetadata', ensureControls, { once: true }); vid.addEventListener('play', ensureControls); vid.addEventListener('click', ensureControls); vid.addEventListener('touchstart', ensureControls, { once: true }); } // Unmute on first interaction function unmuteOnFirstInteraction(){ if (vid.muted) vid.muted = false; if (hint) hint.style.display = 'none'; vid.removeEventListener('click', unmuteOnFirstInteraction); vid.removeEventListener('touchstart', unmuteOnFirstInteraction); } vid.addEventListener('click', unmuteOnFirstInteraction); vid.addEventListener('touchstart', unmuteOnFirstInteraction); // Show hint if still muted setTimeout(function(){ if (vid.muted && hint) { hint.style.display = 'flex'; } }, 900); // Hint click activates sound if (hint) { var activateSound = function(e){ e.preventDefault(); e.stopPropagation(); try { if (vid.muted) { vid.muted = false; vid.play().catch(function(){}); } } catch(_){} hint.style.display = 'none'; }; hint.addEventListener('click', activateSound); hint.addEventListener('keydown', function(ev){ if (ev.key === 'Enter' || ev.key === ' ') { activateSound(ev); } }); } }; try { var closed = getFgptCookie(cookieName); // DON'T show modal automatically anymore - only via attachment button // if (closed !== '1') { ... } var modal = document.getElementById('fgpt-video-modal'); var vid = document.getElementById('fgpt-video'); var modal = document.getElementById('fgpt-video-modal'); var vid = document.getElementById('fgpt-video'); var hint = document.getElementById('fgpt-audio-hint'); if (!modal || !vid) return; // Close handler document.getElementById('fgpt-video-close').addEventListener('click', function(e){ try { vid.pause(); } catch(_){} modal.classList.remove('show'); setFgptCookie(cookieName, '1', 360); // 360 days }); // Close when clicking outside modal.addEventListener('click', function(ev){ if (ev.target === modal){ try{ vid.pause(); }catch(_){ } modal.classList.remove('show'); setFgptCookie(cookieName, '1', 360); // 360 days } }); } catch(_e){ /* ignore cookie errors */ } })(); </script> <!-- Unread chat messages badge updater --> <script> (function() { function updateUnreadBadge() { fetch('/ajaxjobs/get_unread_count.php') .then(function(r) { return r.json(); }) .then(function(data) { console.log('Unread count response:', data); if (data && data.success) { var count = parseInt(data.count, 10) || 0; console.log('Unread count:', count); // Update mobile navbar badge var mobileBadge = document.querySelector('.mobile-navbar .new-message'); console.log('Mobile badge element:', mobileBadge); if (mobileBadge) { if (count > 0) { mobileBadge.textContent = count > 99 ? '99+' : count; mobileBadge.style.display = 'block'; } else { mobileBadge.style.display = 'none'; } } // Update desktop navbar badge var desktopBadge = document.querySelector('.navbar-chat-badge'); console.log('Desktop badge element:', desktopBadge); if (desktopBadge) { if (count > 0) { desktopBadge.textContent = count > 99 ? '99+' : count; desktopBadge.style.display = 'inline-block'; console.log('Badge updated to:', count); } else { desktopBadge.style.display = 'none'; } } } }) .catch(function(err) { console.log('Unread fetch error:', err); }); } // Initial check updateUnreadBadge(); // Update every 30 seconds setInterval(updateUnreadBadge, 30000); })(); </script> <!-- FreightGPT Global Modal --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <div id="freightgpt-global-modal" class="freightgpt-modal-overlay" style="display: none;"> <div class="freightgpt-modal-container"> <div class="freightgpt-modal-topbar"> <div class="freightgpt-modal-topbar-left"> <span class="freightgpt-modal-topbar-title"></span> </div> <div class="freightgpt-modal-topbar-right"> <a href="https://fuvarborze.hu/el/?link=chat" class="freightgpt-modal-btn" title="Άνοιγμα σε ολόκληρη σελίδα"> <i class="fa-solid fa-up-right-and-down-left-from-center"></i> </a> <button type="button" class="freightgpt-modal-btn freightgpt-modal-close-btn" onclick="closeFreightGPTModal()" title="Κλείσιμο"> <i class="fa-solid fa-xmark"></i> </button> </div> </div> <div class="freightgpt-modal-body"> <iframe id="freightgpt-modal-iframe" src="about:blank" frameborder="0"></iframe> </div> </div> </div> <style> /* FreightGPT Global Modal Styles */ .freightgpt-modal-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.75); z-index: 999999; display: flex; align-items: center; justify-content: center; opacity: 0; visibility: hidden; transition: opacity 0.3s ease, visibility 0.3s ease; } .freightgpt-modal-overlay.show { opacity: 1; visibility: visible; } .freightgpt-modal-container { width: 95%; max-width: 1100px; height: 90vh; max-height: 800px; background: #fff; border-radius: 16px; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 25px 80px rgba(0, 0, 0, 0.5); transform: scale(0.95) translateY(20px); transition: transform 0.3s ease; } .freightgpt-modal-overlay.show .freightgpt-modal-container { transform: scale(1) translateY(0); } /* Kis topbar a bezárás és expand gombokkal */ .freightgpt-modal-topbar { background: #1e293b; color: white; padding: 8px 12px; display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; min-height: 40px; } .freightgpt-modal-topbar-left { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; } .freightgpt-modal-topbar-title { font-size: 13px; font-weight: 500; opacity: 0.9; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 500px; } .freightgpt-modal-topbar-right { display: flex; align-items: center; gap: 6px; } .freightgpt-modal-btn { width: 28px; height: 28px; border-radius: 6px; border: none; background: rgba(255, 255, 255, 0.1); color: white; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 14px; text-decoration: none; transition: background 0.2s ease; } .freightgpt-modal-btn:hover { background: rgba(255, 255, 255, 0.2); } .freightgpt-modal-close-btn:hover { background: #ef4444; } .freightgpt-modal-body { flex: 1; overflow: hidden; background: #f8fafc; } .freightgpt-modal-body iframe { width: 100%; height: 100%; border: none; } /* Mobile responsiveness */ @media (max-width: 768px) { .freightgpt-modal-container { width: 100%; height: 100%; max-height: 100%; max-width: 100%; border-radius: 0; } .freightgpt-modal-topbar-title { max-width: 200px; } } </style> <script> (function() { // FreightGPT Modal State var freightGPTModal = { isOpen: false, iframeLoaded: false, currentPrompt: '', currentTitle: '' }; // Base URL for the chat var chatBaseUrl = 'https://fuvarborze.hu/el/modules/pages/chatmodal.php'; /** * Open the FreightGPT Modal * @param {string} prompt - Optional prompt to send * @param {string} title - Optional title for the modal topbar */ window.openFreightGPTModal = function(prompt, title) { var modal = document.getElementById('freightgpt-global-modal'); var iframe = document.getElementById('freightgpt-modal-iframe'); var titleEl = modal.querySelector('.freightgpt-modal-topbar-title'); var expandLink = modal.querySelector('.freightgpt-modal-btn[href]'); if (!modal || !iframe) return; // Set title (opcionális - ha nincs title, üres marad) var displayTitle = title || ''; titleEl.textContent = displayTitle; freightGPTModal.currentTitle = displayTitle; freightGPTModal.currentPrompt = prompt || ''; // Build iframe URL var iframeUrl = chatBaseUrl; var params = []; if (prompt) { params.push('prompt=' + encodeURIComponent(prompt)); // Always force new conversation for prompts params.push('new=1'); } if (title) { params.push('title=' + encodeURIComponent(title)); } if (params.length > 0) { iframeUrl += '?' + params.join('&'); } // Update expand link var expandUrl = 'https://fuvarborze.hu/el/?link=chat'; if (prompt) { expandUrl += '&prompt=' + encodeURIComponent(prompt) + '&new=1'; } if (title) { expandUrl += '&title=' + encodeURIComponent(title); } if (expandLink) { expandLink.href = expandUrl; } // Load iframe iframe.src = iframeUrl; // Show modal with animation modal.style.display = 'flex'; // Force reflow for animation modal.offsetHeight; modal.classList.add('show'); // Prevent body scroll document.body.style.overflow = 'hidden'; freightGPTModal.isOpen = true; }; /** * Close the FreightGPT Modal */ window.closeFreightGPTModal = function() { var modal = document.getElementById('freightgpt-global-modal'); var iframe = document.getElementById('freightgpt-modal-iframe'); if (!modal) return; // Hide with animation modal.classList.remove('show'); setTimeout(function() { modal.style.display = 'none'; // Clear iframe to stop any ongoing processes iframe.src = 'about:blank'; }, 300); // Restore body scroll document.body.style.overflow = ''; freightGPTModal.isOpen = false; // Clean URL parameters var urlParams = new URLSearchParams(window.location.search); if (urlParams.get('link') === 'chat') { urlParams.delete('link'); urlParams.delete('prompt'); urlParams.delete('title'); var newUrl = window.location.pathname; var remaining = urlParams.toString(); if (remaining) { newUrl += '?' + remaining; } window.history.replaceState({}, '', newUrl); } }; /** * Toggle modal */ window.toggleFreightGPTModal = function() { if (freightGPTModal.isOpen) { closeFreightGPTModal(); } else { openFreightGPTModal(); } }; // Close on ESC key document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && freightGPTModal.isOpen) { closeFreightGPTModal(); } }); // Close on overlay click (not on container) document.addEventListener('click', function(e) { if (e.target.id === 'freightgpt-global-modal') { closeFreightGPTModal(); } }); // Auto-open if URL parameters present })(); </script> <!-- Segíthetünk? badge --> <style> .help-badge { position: fixed; bottom: 40px; right: 20px; z-index: 9999; } .help-badge-btn { background: linear-gradient(135deg, #3b82f6, #1d4ed8); color: #fff; border: none; padding: 12px 20px; border-radius: 50px; font-size: 14px; font-weight: 600; cursor: pointer; box-shadow: 0 4px 15px rgba(59, 130, 246, 0.4); display: flex; align-items: center; gap: 8px; transition: transform 0.2s, box-shadow 0.2s; } .help-badge-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(59, 130, 246, 0.5); } .help-badge-btn .icon { font-size: 18px; } .help-popup { display: none; position: absolute; bottom: 60px; right: 0; width: 320px; background: #fff; border-radius: 16px; box-shadow: 0 10px 40px rgba(0,0,0,0.2); overflow: hidden; animation: helpPopupIn 0.25s ease; } @keyframes helpPopupIn { from { opacity: 0; transform: translateY(10px) scale(0.95); } to { opacity: 1; transform: translateY(0) scale(1); } } .help-popup.show { display: block; } .help-popup-header { background: linear-gradient(135deg, #3b82f6, #1d4ed8); color: #fff; padding: 16px 20px; display: flex; justify-content: space-between; align-items: center; } .help-popup-header h3 { margin: 0; font-size: 16px; font-weight: 600; } .help-popup-close { background: rgba(255,255,255,0.2); border: none; color: #fff; width: 28px; height: 28px; border-radius: 50%; cursor: pointer; font-size: 16px; display: flex; align-items: center; justify-content: center; } .help-popup-close:hover { background: rgba(255,255,255,0.3); } .help-popup-body { padding: 20px; } .help-popup-body p { margin: 0 0 16px; font-size: 14px; color: #64748b; line-height: 1.5; } .help-popup-body input, .help-popup-body textarea { width: 100%; padding: 12px; border: 1px solid #e2e8f0; border-radius: 8px; font-size: 14px; margin-bottom: 12px; box-sizing: border-box; font-family: inherit; } .help-popup-body textarea { min-height: 100px; resize: vertical; } .help-popup-body input:focus, .help-popup-body textarea:focus { outline: none; border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); } .help-popup-submit { width: 100%; background: linear-gradient(135deg, #3b82f6, #1d4ed8); color: #fff; border: none; padding: 12px; border-radius: 8px; font-size: 14px; font-weight: 600; cursor: pointer; transition: opacity 0.2s; } .help-popup-submit:hover { opacity: 0.9; } .help-popup-submit:disabled { opacity: 0.7; cursor: not-allowed; } .help-loader { display: inline-block; width: 14px; height: 14px; border: 2px solid rgba(255,255,255,0.3); border-top-color: #fff; border-radius: 50%; animation: helpSpin 0.8s linear infinite; vertical-align: middle; margin-right: 6px; } @keyframes helpSpin { to { transform: rotate(360deg); } } @media (max-width: 728px) { .help-badge { right: 10px; bottom: 40px; } .help-popup { position: fixed; width: calc(100vw - 20px); right: 10px; left: 10px; bottom: auto; top: 50%; transform: translateY(-50%); max-height: calc(100vh - 100px); overflow-y: auto; } .help-popup-body textarea { min-height: 80px; } } </style> <div class="help-badge" id="helpBadge"> <div class="help-popup" id="helpPopup"> <div class="help-popup-header"> <h3>Βοηθάμε;</h3> <button type="button" class="help-popup-close" onclick="toggleHelpPopup()">×</button> </div> <div class="help-popup-body"> <p>Εάν έχετε ερωτήσεις ή παρατηρήσετε σφάλματα, παρακαλούμε επικοινωνήστε μαζί μας και θα σας απαντήσουμε σύντομα!</p> <textarea id="helpMessage" placeholder="Γράψτε την ερώτησή σας ή το εμπειρικό σφάλμα..."></textarea> <div style="display:flex;gap:8px;align-items:stretch;"> <button type="button" class="help-popup-submit" id="helpSubmitBtn" onclick="submitHelpForm()" style="flex:1;">⌲ Αποστολή μηνύματος</button> <style> /* Floating Voice Button - Global Styles */ .fgpt-global-voice-btn { transition: all 0.3s ease; user-select: none; -webkit-user-select: none; touch-action: none; height: auto; border: none; background: transparent; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0; } .fgpt-global-voice-btn:active { cursor: grabbing; } .fgpt-voice-circle { width: 64px; height: 64px; border-radius: 50%; background: linear-gradient(135deg, #10b981 0%, #059669 100%); color: #fff; box-shadow: 0 8px 24px rgba(16, 185, 129, 0.4); display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; } .fgpt-global-voice-btn:hover .fgpt-voice-circle { box-shadow: 0 12px 36px rgba(16, 185, 129, 0.5); transform: scale(1.08); } .fgpt-global-voice-btn.voice-active .fgpt-voice-circle { background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); box-shadow: 0 8px 24px rgba(239, 68, 68, 0.4); animation: voice-pulse 1.5s ease-in-out infinite; } .fgpt-global-voice-btn.voice-active .fgpt-voice-label { background: #fee2e2; color: #dc2626; } .fgpt-voice-circle svg { width: 30px; height: 30px; } /* Small indicator with bars and counter for active state */ .fgpt-voice-indicator-small { position: absolute; top: -20px; right: -20px; min-width: 50px; height: auto; border-radius: 12px; background: #fff; box-shadow: 0 2px 12px rgba(0,0,0,0.15); display: none; flex-direction: column; align-items: center; justify-content: center; padding: 6px 8px; gap: 4px; z-index: 2; } .fgpt-global-voice-btn.voice-active .fgpt-voice-indicator-small { display: flex; } /* Voice bars animation */ .fgpt-voice-bars { display: flex; align-items: center; justify-content: center; gap: 3px; height: 16px; } .fgpt-voice-bar { width: 3px; background: #ef4444; border-radius: 2px; animation: voice-bar-pulse 0.8s ease-in-out infinite; } .fgpt-voice-bar:nth-child(1) { height: 8px; animation-delay: 0s; } .fgpt-voice-bar:nth-child(2) { height: 12px; animation-delay: 0.1s; } .fgpt-voice-bar:nth-child(3) { height: 16px; animation-delay: 0.2s; } .fgpt-voice-bar:nth-child(4) { height: 12px; animation-delay: 0.3s; } .fgpt-voice-bar:nth-child(5) { height: 8px; animation-delay: 0.4s; } @keyframes voice-bar-pulse { 0%, 100% { transform: scaleY(0.5); opacity: 0.5; } 50% { transform: scaleY(1); opacity: 1; } } /* Timer counter */ .fgpt-voice-timer { font-size: 9px; font-weight: 600; color: #ef4444; font-family: monospace; line-height: 1; } @keyframes indicator-pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } 50% { transform: scale(1.1); } } .fgpt-voice-label { position: relative; margin-top: -8px; padding: 6px 12px; background: #fff; color: #059669; font-size: 11px; font-weight: 700; text-align: center; line-height: 1.2; border-radius: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); white-space: nowrap; z-index: 1; } @keyframes voice-pulse { 0%, 100% { box-shadow: 0 8px 24px rgba(239, 68, 68, 0.4); transform: scale(1); } 50% { box-shadow: 0 12px 36px rgba(239, 68, 68, 0.8); transform: scale(1.08); } } /* Voice Tooltip Bubble */ .fgpt-voice-tooltip { position: fixed; z-index: 99999; background: linear-gradient(135deg, #02beb5 0%, #01a79f 100%); color: #fff; padding: 16px 20px; border-radius: 16px; max-width: 280px; font-size: 14px; line-height: 1.5; box-shadow: 0 8px 24px rgba(2, 190, 181, 0.3), 0 2px 8px rgba(0, 0, 0, 0.1); opacity: 0; pointer-events: none; transition: opacity 0.3s ease, transform 0.3s ease; transform: translateY(10px); } .fgpt-voice-tooltip.show { opacity: 1; pointer-events: all; transform: translateY(0); } .fgpt-voice-tooltip::after { content: ''; position: absolute; bottom: -8px; left: 40px; width: 0; height: 0; border-left: 10px solid transparent; border-right: 10px solid transparent; border-top: 10px solid #01a79f; } .fgpt-tooltip-close { position: absolute; top: 8px; right: 8px; background: rgba(255, 255, 255, 0.2); border: none; color: #fff; width: 24px; height: 24px; border-radius: 50%; font-size: 18px; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background 0.2s ease; } .fgpt-tooltip-close:hover { background: rgba(255, 255, 255, 0.3); } @media screen and (max-width: 768px) { .fgpt-voice-tooltip { max-width: 240px; font-size: 13px; padding: 14px 18px; } .fgpt-voice-tooltip::after { left: 30px; } } /* Email input field for voice dictation */ .fgpt-voice-email-input { position: fixed; z-index: 99998; background: #fff; border-radius: 16px; padding: 20px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2); display: none; flex-direction: column; gap: 12px; min-width: 320px; max-width: 400px; animation: emailInputSlideIn 0.3s ease-out; } .fgpt-voice-email-input.show { display: flex; } @keyframes emailInputSlideIn { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: scale(1); } } .fgpt-voice-email-input h4 { margin: 0 0 8px 0; font-size: 16px; font-weight: 700; color: #1f2937; } .fgpt-voice-email-input p { margin: 0 0 12px 0; font-size: 13px; color: #6b7280; line-height: 1.4; } .fgpt-voice-email-input input[type="email"] { width: 100%; padding: 12px 14px; border: 2px solid #e5e7eb; border-radius: 8px; font-size: 15px; font-family: monospace; transition: border-color 0.2s ease; } .fgpt-voice-email-input input[type="email"]:focus { outline: none; border-color: #10b981; } .fgpt-voice-email-input .btn-group { display: flex; gap: 8px; } .fgpt-voice-email-input button { flex: 1; padding: 10px 16px; border: none; border-radius: 8px; font-size: 14px; font-weight: 600; cursor: pointer; transition: all 0.2s ease; } .fgpt-voice-email-input .btn-confirm { background: linear-gradient(135deg, #10b981 0%, #059669 100%); color: #fff; } .fgpt-voice-email-input .btn-confirm:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3); } .fgpt-voice-email-input .btn-cancel { background: #f3f4f6; color: #6b7280; } .fgpt-voice-email-input .btn-cancel:hover { background: #e5e7eb; } /* Dynamic action buttons during voice call */ .fgpt-voice-action-buttons { position: fixed; z-index: 99997; display: none; flex-direction: column; gap: 8px; animation: slideInButtons 0.3s ease-out; } .fgpt-voice-action-buttons.show { display: flex; } @keyframes slideInButtons { from { opacity: 0; transform: translateX(-20px); } to { opacity: 1; transform: translateX(0); } } .fgpt-action-btn { background: #fff; border: 2px solid #10b981; color: #059669; padding: 10px 16px; border-radius: 10px; font-size: 13px; font-weight: 600; cursor: pointer; transition: all 0.2s ease; box-shadow: 0 4px 12px rgba(16, 185, 129, 0.2); white-space: nowrap; display: flex; align-items: center; gap: 6px; } .fgpt-action-btn:hover { background: linear-gradient(135deg, #10b981 0%, #059669 100%); color: #fff; transform: translateX(4px); box-shadow: 0 6px 16px rgba(16, 185, 129, 0.4); } .fgpt-action-btn svg { width: 16px; height: 16px; } /* Mobile responsive */ @media (max-width: 768px) { .fgpt-global-voice-btn { width: 64px; } .fgpt-voice-circle { width: 56px; height: 56px; } .fgpt-voice-circle svg { width: 26px; height: 26px; } .fgpt-voice-label { font-size: 10px; padding: 5px 10px; } .fgpt-welcome-content { margin: 20px; padding: 24px; } .fgpt-voice-email-input { min-width: 280px; max-width: calc(100vw - 40px); left: 20px !important; right: 20px !important; } } </style> <!-- Voice Tooltip Bubble (csak első látogatáskor) --> <div id="fgpt-voice-tooltip" class="fgpt-voice-tooltip"> <button class="fgpt-tooltip-close" id="fgpt-tooltip-close" aria-label="Bezárás">×</button> <div>Μπορείτε να καλέσετε δωρεάν το Φόρμα Μορφωσύνη. Μπορείτε να μετακινήσετε το κουμπί κλήσης στη πιο άνετη θέση στην οθόνη.</div> </div> <!-- Floating Voice Button --> <button id="fgpt-global-voice-btn" class="fgpt-global-voice-btn" aria-label="Κλήση FreightGPT" title="Κλήση FreightGPT - μεταφοράςzogenικη"> <div class="fgpt-voice-circle"> <svg width="30" height="30" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> <path d="M20.01 15.38c-1.23 0-2.42-.2-3.53-.56a.977.977 0 0 0-1.01.24l-1.57 1.97c-2.83-1.35-5.48-3.9-6.89-6.83l1.95-1.66c.27-.28.35-.67.24-1.02-.37-1.11-.56-2.3-.56-3.53 0-.54-.45-.99-.99-.99H4.19C3.65 3 3 3.24 3 3.99 3 13.28 10.73 21 20.01 21c.71 0 .99-.63.99-1.18v-3.45c0-.54-.45-.99-.99-.99z"/> </svg> <div class="fgpt-voice-indicator-small"> <div class="fgpt-voice-bars"> <div class="fgpt-voice-bar"></div> <div class="fgpt-voice-bar"></div> <div class="fgpt-voice-bar"></div> <div class="fgpt-voice-bar"></div> <div class="fgpt-voice-bar"></div> </div> <div class="fgpt-voice-timer">00:00</div> </div> </div> <span class="fgpt-voice-label" data-inactive-text="Αίτηση FreightGPT" data-active-text="Τέλος κλήσης">Αίτηση FreightGPT</span> </button> <!-- Email Input Panel (megjelenik amikor AI kéri az email címet) --> <div id="fgpt-voice-email-input" class="fgpt-voice-email-input"> <h4>Επαλήθευση διεύθυνσης email</h4> <p>Παρακαλώ ελέγξτε και διορθώστε το email εάν χρειάζεται:</p> <input type="email" id="fgpt-voice-email-field" placeholder="pelda@email.com" /> <div class="btn-group"> <button class="btn-confirm" id="fgpt-email-confirm">Ορθό, μπορούμε να προχωρήσουμε</button> <button class="btn-cancel" id="fgpt-email-cancel">Ακυρώθηκε</button> </div> </div> <!-- Dynamic Action Buttons (megjelennek aktív hívás alatt) --> <div id="fgpt-voice-action-buttons" class="fgpt-voice-action-buttons"> <!-- Buttons will be dynamically inserted here --> </div> <script> (function() { 'use strict'; // Cookie helpers function fgptSetCookie(name, value, days) { const d = new Date(); d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000)); document.cookie = name + "=" + value + ";expires=" + d.toUTCString() + ";path=/"; } function fgptGetCookie(name) { const nameEQ = name + "="; const ca = document.cookie.split(';'); for (let i = 0; i < ca.length; i++) { let c = ca[i]; while (c.charAt(0) === ' ') c = c.substring(1, c.length); if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length); } return null; } // Voice tooltip logic const voiceTooltip = document.getElementById('fgpt-voice-tooltip'); const tooltipClose = document.getElementById('fgpt-tooltip-close'); const voiceBtn = document.getElementById('fgpt-global-voice-btn'); const emailInput = document.getElementById('fgpt-voice-email-input'); const emailField = document.getElementById('fgpt-voice-email-field'); const emailConfirm = document.getElementById('fgpt-email-confirm'); const emailCancel = document.getElementById('fgpt-email-cancel'); const actionButtonsContainer = document.getElementById('fgpt-voice-action-buttons'); // Dynamic action buttons management var currentActionButtons = []; function showActionButtons(buttons) { // Clear existing buttons actionButtonsContainer.innerHTML = ''; currentActionButtons = []; if (!buttons || buttons.length === 0) { actionButtonsContainer.classList.remove('show'); return; } // Position buttons near voice button var btnRect = voiceBtn.getBoundingClientRect(); var left = btnRect.right + 20; var top = btnRect.top; // If too far right, position to the left if (left + 200 > window.innerWidth - 20) { left = btnRect.left - 220; } actionButtonsContainer.style.left = left + 'px'; actionButtonsContainer.style.top = top + 'px'; // Create buttons buttons.forEach(function(btn) { var button = document.createElement('button'); button.className = 'fgpt-action-btn'; button.innerHTML = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/></svg>' + btn.label; button.onclick = function() { window.open(btn.url, '_blank'); }; actionButtonsContainer.appendChild(button); currentActionButtons.push(button); }); actionButtonsContainer.classList.add('show'); } function hideActionButtons() { actionButtonsContainer.classList.remove('show'); currentActionButtons = []; } // Position tooltip near voice button function positionTooltip() { var btnRect = voiceBtn.getBoundingClientRect(); var tooltipWidth = 280; // max-width from CSS var left = btnRect.left + (btnRect.width / 2) - (tooltipWidth / 2); var top = btnRect.top - 100; // Position above button // Ensure tooltip stays within viewport if (left < 20) left = 20; if (left + tooltipWidth > window.innerWidth - 20) { left = window.innerWidth - tooltipWidth - 20; } voiceTooltip.style.left = left + 'px'; voiceTooltip.style.top = top + 'px'; } // Check if user has seen tooltip const hasSeenTooltip = fgptGetCookie('fgpt_voice_welcome'); if (!hasSeenTooltip) { setTimeout(function() { positionTooltip(); voiceTooltip.classList.add('show'); }, 1500); } // Close tooltip function closeTooltip() { voiceTooltip.classList.remove('show'); fgptSetCookie('fgpt_voice_welcome', '1', 30); // 30 days } tooltipClose.addEventListener('click', closeTooltip); // Reposition tooltip on window resize window.addEventListener('resize', function() { if (voiceTooltip.classList.contains('show')) { positionTooltip(); } }); // Inactivity timer management (60 seconds - a max_response_output_tokens limitálja a válasz hosszát) var inactivityTimer = null; var INACTIVITY_TIMEOUT = 60000; // 60 seconds in milliseconds var aiSpeaking = false; // Track if AI is currently speaking window.resetInactivityTimer = function() { // Clear existing timer if (inactivityTimer) { clearTimeout(inactivityTimer); inactivityTimer = null; } // Only start timer if call is active AND AI is not speaking if (window.fgptVoiceGlobal && window.fgptVoiceGlobal.running && !aiSpeaking) { // console.log('[Voice] Inactivity timer reset (30s)'); inactivityTimer = setTimeout(function() { // console.log('[Voice] 30 seconds of inactivity detected, closing call...'); if (window.fgptVoiceGlobal && window.fgptVoiceGlobal.running) { window.fgptVoiceGlobal.stop(); } }, INACTIVITY_TIMEOUT); } }; // Pause inactivity timer when AI starts speaking window.pauseInactivityTimer = function() { aiSpeaking = true; if (inactivityTimer) { clearTimeout(inactivityTimer); inactivityTimer = null; } }; // Resume inactivity timer when AI stops speaking window.resumeInactivityTimer = function() { aiSpeaking = false; window.resetInactivityTimer(); }; // Clear inactivity timer when call ends window.addEventListener('fgpt-voice-stopped', function() { aiSpeaking = false; if (inactivityTimer) { clearTimeout(inactivityTimer); inactivityTimer = null; // console.log('[Voice] Inactivity timer cleared (call ended)'); } }); // Start inactivity timer when call begins window.addEventListener('fgpt-voice-started', function() { aiSpeaking = false; // console.log('[Voice] Call started, initializing inactivity timer'); window.resetInactivityTimer(); }); // Email input positioning near voice button function positionEmailInput() { var btnRect = voiceBtn.getBoundingClientRect(); var inputWidth = 320; var inputHeight = 200; // approximate // Try to position to the left of button var left = btnRect.left - inputWidth - 20; var top = btnRect.top; // If too far left, position to the right if (left < 20) { left = btnRect.right + 20; } // If too far right, center it if (left + inputWidth > window.innerWidth - 20) { left = (window.innerWidth - inputWidth) / 2; } // Keep vertical position in bounds if (top + inputHeight > window.innerHeight - 20) { top = window.innerHeight - inputHeight - 20; } if (top < 20) { top = 20; } emailInput.style.left = left + 'px'; emailInput.style.top = top + 'px'; } // Email input handlers var emailConfirmCallback = null; function showEmailInput(detectedEmail) { emailField.value = detectedEmail || ''; positionEmailInput(); emailInput.classList.add('show'); emailField.focus(); emailField.select(); } function hideEmailInput() { emailInput.classList.remove('show'); emailField.value = ''; emailConfirmCallback = null; } emailConfirm.addEventListener('click', function() { var email = emailField.value.trim(); if (email && emailConfirmCallback) { emailConfirmCallback(email); } hideEmailInput(); }); emailCancel.addEventListener('click', function() { hideEmailInput(); // Send cancellation message to AI if (window.fgptVoiceGlobal && window.fgptVoiceGlobal.dataChannel && window.fgptVoiceGlobal.dataChannel.readyState === 'open') { var cancelMsg = { type: 'conversation.item.create', item: { type: 'message', role: 'user', content: [{ type: 'input_text', text: 'Mégsem adom meg az email címemet most.' }] } }; window.fgptVoiceGlobal.dataChannel.send(JSON.stringify(cancelMsg)); window.fgptVoiceGlobal.dataChannel.send(JSON.stringify({ type: 'response.create' })); } }); emailField.addEventListener('keypress', function(e) { if (e.key === 'Enter') { emailConfirm.click(); } }); // --- Audio Context Management for Mobile --- // Create a single, reusable AudioContext for the entire page. // Mobile browsers require the AudioContext to be resumed by a user gesture. window.fgptAudioContext = new (window.AudioContext || window.webkitAudioContext)(); function ensureAudioContext() { return new Promise(function(resolve) { if (window.fgptAudioContext.state === 'suspended') { // console.log('AudioContext is suspended, attempting to resume...'); window.fgptAudioContext.resume().then(function() { // console.log('AudioContext resumed successfully.'); resolve(); }).catch(function(e) { // console.error('Failed to resume AudioContext:', e); // Even if it fails, resolve to not block the flow. // The browser might show its own permission prompt. resolve(); }); } else { // console.log('AudioContext is already running.'); resolve(); } }); } // Position management function getDefaultPosition() { const viewportWidth = window.innerWidth; const viewportHeight = window.innerHeight; const buttonHeight = voiceBtn.offsetHeight || 70; // Use actual height or fallback // Default: bottom-left (50px from left, 50px from bottom) const left = 50; let top = viewportHeight - buttonHeight - 50; // Ensure it stays within the viewport's bounds if (top < 20) { top = 20; // Minimum top margin } const maxLeft = Math.max(20, viewportWidth - (voiceBtn.offsetWidth || 70) - 20); const safeLeft = Math.min(Math.max(left, 20), maxLeft); return { left: safeLeft, top: top }; } function getSavedPosition() { const saved = fgptGetCookie('fgpt_voice_position'); if (saved) { try { return JSON.parse(saved); } catch(e) { return null; } } return null; } function savePosition(left, top) { const pos = JSON.stringify({ left: left, top: top }); fgptSetCookie('fgpt_voice_position', pos, 365); } function setPosition(pos) { voiceBtn.style.left = pos.left + 'px'; voiceBtn.style.top = pos.top + 'px'; } // Initialize position const savedPos = getSavedPosition(); if (savedPos) { setPosition(savedPos); } else { setPosition(getDefaultPosition()); } // Draggable functionality with click detection let isDragging = false; let hasMoved = false; let startX = 0, startY = 0; let initialX = 0, initialY = 0; let dragThreshold = 5; // pixel threshold to distinguish drag from click function handleStart(clientX, clientY) { isDragging = true; hasMoved = false; startX = clientX; startY = clientY; const rect = voiceBtn.getBoundingClientRect(); initialX = rect.left; initialY = rect.top; voiceBtn.style.transition = 'none'; } function handleMove(clientX, clientY) { if (!isDragging) return; const dx = clientX - startX; const dy = clientY - startY; // Check if moved beyond threshold if (!hasMoved && (Math.abs(dx) > dragThreshold || Math.abs(dy) > dragThreshold)) { hasMoved = true; } const newLeft = initialX + dx; const newTop = initialY + dy; // Keep within viewport const maxLeft = window.innerWidth - voiceBtn.offsetWidth; const maxTop = window.innerHeight - voiceBtn.offsetHeight; voiceBtn.style.left = Math.max(0, Math.min(newLeft, maxLeft)) + 'px'; voiceBtn.style.top = Math.max(0, Math.min(newTop, maxTop)) + 'px'; } function handleEnd() { if (!isDragging) return; voiceBtn.style.transition = 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)'; // Save position if moved if (hasMoved) { const rect = voiceBtn.getBoundingClientRect(); savePosition(rect.left, rect.top); } isDragging = false; // Small delay to prevent click event if dragged if (hasMoved) { setTimeout(function() { hasMoved = false; }, 100); } } // Mouse events voiceBtn.addEventListener('mousedown', function(e) { if (e.button !== 0) return; e.preventDefault(); handleStart(e.clientX, e.clientY); }); document.addEventListener('mousemove', function(e) { handleMove(e.clientX, e.clientY); }); document.addEventListener('mouseup', handleEnd); // Touch events voiceBtn.addEventListener('touchstart', function(e) { // Don't prevent default - let the click handler work handleStart(e.touches[0].clientX, e.touches[0].clientY); }, { passive: true }); document.addEventListener('touchmove', function(e) { if (isDragging) { e.preventDefault(); // Only prevent during actual drag handleMove(e.touches[0].clientX, e.touches[0].clientY); } }, { passive: false }); document.addEventListener('touchend', handleEnd); // Handle window resize to keep button visible window.addEventListener('resize', function() { const currentLeft = parseInt(voiceBtn.style.left) || 0; const currentTop = parseInt(voiceBtn.style.top) || 0; const maxLeft = window.innerWidth - voiceBtn.offsetWidth; const maxTop = window.innerHeight - voiceBtn.offsetHeight; const newLeft = Math.max(0, Math.min(currentLeft, maxLeft)); const newTop = Math.max(0, Math.min(currentTop, maxTop)); if (newLeft !== currentLeft || newTop !== currentTop) { voiceBtn.style.left = newLeft + 'px'; voiceBtn.style.top = newTop + 'px'; savePosition(newLeft, newTop); } }); // Click handler - csak akkor initál, ha NEM volt drag voiceBtn.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); if (hasMoved) { return; } // First, ensure the audio context is active (crucial for mobile) ensureAudioContext().then(function() { // Voice chat toggle logic if (voiceBtn.classList.contains('voice-active')) { // Stop voice if (typeof window.fgptVoiceGlobal !== 'undefined' && window.fgptVoiceGlobal.running) { window.fgptVoiceGlobal.stop(); } } else { // Start voice on current page initGlobalVoice(); } }); }); // Listen for voice state changes if (typeof window.addEventListener !== 'undefined') { window.addEventListener('fgpt-voice-started', function() { voiceBtn.classList.add('voice-active'); var label = voiceBtn.querySelector('.fgpt-voice-label'); if (label) { label.textContent = label.getAttribute('data-active-text') || 'Τέλος κλήσης'; } }); window.addEventListener('fgpt-voice-stopped', function() { voiceBtn.classList.remove('voice-active'); var label = voiceBtn.querySelector('.fgpt-voice-label'); if (label) { label.textContent = label.getAttribute('data-inactive-text') || 'Αίτηση FreightGPT'; } // Hide action buttons when call ends hideActionButtons(); }); } // Global voice initialization for non-chat pages function initGlobalVoice() { // Security check: Microphone access requires HTTPS if (window.location.protocol !== 'https:') { alert('Ασφαλής σύνδεση (HTTPS) απαιτείται για την κλήση φωνής.'); return; } // Create global voice object if it doesn't exist if (typeof window.fgptVoiceGlobal === 'undefined') { window.fgptVoiceGlobal = { running: false, peerConnection: null, dataChannel: null, audioElement: null, timerInterval: null, startTime: null, ringingAudio: null, confirmedEmail: null, // Track the last confirmed email greeted: false // Prevent double greeting }; } // Reset greeted flag for new call window.fgptVoiceGlobal.greeted = false; // Use the global AudioContext var audioContext = window.fgptAudioContext; var ringingInterval; function playRingingTone() { // Ensure context is running before playing sound if (audioContext.state === 'suspended') { audioContext.resume().then(function() { actuallyPlayRingingTone(); }); } else { actuallyPlayRingingTone(); } } function actuallyPlayRingingTone() { var oscillator = audioContext.createOscillator(); var gainNode = audioContext.createGain(); oscillator.connect(gainNode); gainNode.connect(audioContext.destination); oscillator.frequency.value = 440; // A4 note gainNode.gain.setValueAtTime(0.3, audioContext.currentTime); oscillator.start(audioContext.currentTime); oscillator.stop(audioContext.currentTime + 0.5); } // Play ringing every 2 seconds playRingingTone(); ringingInterval = setInterval(playRingingTone, 2000); // Get ephemeral token from server fetch('https://fuvarborze.hu/modules/dataimport/ajax.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: 'action=voice_session' }) .then(function(response) { return response.json(); }) .then(function(data) { if (!data.ok || !data.token) { clearInterval(ringingInterval); alert('Αδυναμία έναρξης ηχητικής συνομιλίας'); console.error('Session error:', data); return; } var ephemeralKey = data.token; // Request microphone access first navigator.mediaDevices.getUserMedia({ audio: true }) .then(function(stream) { var pc = new RTCPeerConnection(); window.fgptVoiceGlobal.peerConnection = pc; // Set up audio element var audioEl = document.createElement('audio'); audioEl.autoplay = true; audioEl.playbackRate = 1.1; // 110% speed window.fgptVoiceGlobal.audioElement = audioEl; // PAUSE inactivity timer when AI starts speaking audioEl.addEventListener('play', function() { if (typeof window.pauseInactivityTimer === 'function') { window.pauseInactivityTimer(); } }); // RESUME inactivity timer when AI stops speaking audioEl.addEventListener('pause', function() { if (typeof window.resumeInactivityTimer === 'function') { window.resumeInactivityTimer(); } }); audioEl.addEventListener('ended', function() { if (typeof window.resumeInactivityTimer === 'function') { window.resumeInactivityTimer(); } }); pc.ontrack = function(e) { audioEl.srcObject = e.streams[0]; // Ensure playback rate is applied after stream is set audioEl.playbackRate = 1.1; }; // Add local audio track from microphone stream.getTracks().forEach(function(track) { pc.addTrack(track, stream); }); // Create data channel var dc = pc.createDataChannel('oai-events'); window.fgptVoiceGlobal.dataChannel = dc; dc.onopen = function() { // Stop ringing and play connection beep clearInterval(ringingInterval); var beepOsc = audioContext.createOscillator(); var beepGain = audioContext.createGain(); beepOsc.connect(beepGain); beepGain.connect(audioContext.destination); beepOsc.frequency.value = 800; beepGain.gain.setValueAtTime(0.2, audioContext.currentTime); beepOsc.start(audioContext.currentTime); beepOsc.stop(audioContext.currentTime + 0.25); window.fgptVoiceGlobal.running = true; window.fgptVoiceGlobal.startTime = Date.now(); window.dispatchEvent(new Event('fgpt-voice-started')); // Start timer var timerEl = document.querySelector('.fgpt-voice-timer'); window.fgptVoiceGlobal.timerInterval = setInterval(function() { var elapsed = Math.floor((Date.now() - window.fgptVoiceGlobal.startTime) / 1000); var minutes = Math.floor(elapsed / 60); var seconds = elapsed % 60; if (timerEl) { timerEl.textContent = (minutes < 10 ? '0' : '') + minutes + ':' + (seconds < 10 ? '0' : '') + seconds; } }, 1000); // Get page context for dynamic instructions var pageTitle = document.title || ''; var pageDesc = ''; var metaDesc = document.querySelector('meta[name="description"]'); if (metaDesc) pageDesc = metaDesc.getAttribute('content') || ''; var pageContext = ''; if (pageTitle) pageContext += 'Az oldal címe: ' + pageTitle + '. '; if (pageDesc) pageContext += 'Az oldal leírása: ' + pageDesc + '. '; // Build comprehensive system instructions var instructions = `Te vagy a Fuvarbörze freightGPT hangalapú asszisztense. ALAPSZABÁLYOK: - MAGYAR nyelv! Whisper néha rosszul fordít - értelmezd magyarként! - RÖVID válaszok! Max 2-3 mondat! - NE ismételd vissza amit mondtak! - NE magyarázd a számítást! Csak az eredményt mondd! - MAGÁZZ! (Ön, Önnek) - "Ft" helyett mondd: "forint" (mert "font"-nak hangzik) - Számokat mondd ki: "százhúszezer forint nettó" Felhasználó NINCS bejelentkezve - email kell ajánlatkéréshez! ═══════════════════════════════════════════════════════════════ KRITIKUS: KALKULÁCIÓ ≠ AJÁNLATKÉRÉS! KÜLÖNBÖZŐ DOLGOK! ═══════════════════════════════════════════════════════════════ KALKULÁCIÓ = csak árat mondasz, NEM kérdezel ÁSZF-et, NEM kérsz email-t! AJÁNLATKÉRÉS = fuvarozókat értesítünk, EHHEZ kell ÁSZF + email! Ha "kalkuláció", "mennyi lenne", "mi az ára" → CSAK számolj és mondd az árat! Ha "ajánlatkérés", "fuvarozót keresek", "fel akarom adni" → AKKOR kérdezz ÁSZF-et! KALKULÁCIÓ FOLYAMATA (NEM kell ÁSZF!): 1. Kérdezd: Honnan-hová? 2. Kérdezd: Mit szállít, mennyi kg? 3. Számold ki az árat → Mondd az eredményt! 4. Utána kérdezd: "Szeretne ajánlatkérést is? Díjmentes!" - Ha NEM → kész, köszönj el! - Ha IGEN → AKKOR jön az ÁSZF kérdés! ═══ JÁRMŰ KAPACITÁS - KÖTELEZŐ SZABÁLY! ═══ NAGYON FONTOS MAGYARÁZAT: A járművek neve (3,5t, 7,5t, 12t, stb.) az ÖSSZTÖMEGET jelenti, NEM a szállítható rakományt! A 3,5 tonnás furgon NEM 3500 kg-ot tud szállítani! A 3,5 tonna az a jármű + a sofőr + az üzemanyag + a rakomány EGYÜTTES súlya! Ebből következik, hogy egy 3,5 tonnás furgon valós szállítási kapacitása csak kb. 1000-1200 kg. Ha valaki 1500 kg-ot akar szállítani, az NEM fér be egy 3,5 tonnás furgonba! Ahhoz 7,5 tonnás teherautó kell! KAPACITÁSOK: - 3,5t furgon: max 1000 kg, max 6 raklap (a jármű maga ~2500 kg) - 7,5t teherautó: max 2500 kg, max 14 raklap - 12t teherautó: max 5500 kg, max 18 raklap - 18t teherautó: max 9500 kg, max 22 raklap - 24t kamion: max 23000 kg, max 33 raklap DÖNTÉSI SZABÁLY: Mindig a NAGYOBB szempont számít! Ha a súly VAGY a raklapszám meghaladja a limitet, nagyobb jármű kell! PÉLDÁK: - 800 kg, 4 raklap → 3,5t OK - 1200 kg, 4 raklap → 7,5t KELL (mert 1200 > 1000!) - 600 kg, 8 raklap → 7,5t KELL (mert 8 > 6 raklap!) - 1500 kg, 8 raklap → 7,5t KELL (mindkettő meghaladja a 3,5t limitet!) SÚLY ALAPJÁN: - 0-1000 kg → 3,5t - 1001-2500 kg → 7,5t (3,5t NEM JÓ!) - 2501-5500 kg → 12t - 5501-9500 kg → 18t - 9501+ kg → 24t RAKLAP ALAPJÁN: - 1-6 raklap → 3,5t - 7-14 raklap → 7,5t (3,5t NEM JÓ!) - 15-18 raklap → 12t - 19-22 raklap → 18t - 23+ raklap → 24t ═══ ÁRAK ═══ 0-150 km = ÁTALÁNY: 3,5t: 55-70 ezer | 7,5t: 75-95 ezer | 12t: 95-120 ezer | 18t: 120-150 ezer | 24t: 145-180 ezer 150-300 km = km × díj: 3,5t: 360 Ft/km | 7,5t: 520 Ft/km | 12t: 600 Ft/km | 18t: 650 Ft/km | 24t: 800 Ft/km 300+ km = km × díj: 3,5t: 310 Ft/km | 7,5t: 460 Ft/km | 12t: 520 Ft/km | 18t: 570 Ft/km | 24t: 670 Ft/km PÉLDA: Hatvan-Sopron (280 km), 7,5t: → "Körülbelül százötven-százhatvanezer forint nettó. De ajánlatkéréssel olcsóbb lehet!" ═══ AJÁNLATKÉRÉS MOTIVÁCIÓ - NAGYON FONTOS! ═══ Kalkuláció után MINDIG erőteljesen ajánld az ajánlatkérést! Így mondd: "Ez a piaci átlagár. DE! Ha létrehoz egy díjmentes ajánlatkérést a Fuvarbörze-n, akár 20-30%-kal olcsóbb ajánlatot is kaphat! Miért? Mert olyan fuvarozókat találunk, akiknek PONT AZON AZ ÚTVONALON van visszfuvarjuk - nekik megéri olcsóbban vinni, mint üresen menni haza. Létrehozzam? Teljesen díjmentes és nem kötelez semmire!" RÖVID VERZIÓ (ha nincs idő): "Ajánlatkéréssel akár 30%-kal olcsóbb is lehet, mert találunk visszfuvarost! Díjmentes, létrehozzam?" ELŐNYÖK amiket hangsúlyozz: - DÍJMENTES az ajánlatkérés - NEM kötelez semmire - Akár 20-30%-kal OLCSÓBB lehet visszfuvarban - Több fuvarozó versenyez az Ön fuvarjáért - 24 órán belül kaphat ajánlatokat ═══ AJÁNLATKÉRÉS FOLYAMATA ═══ 1. "Elfogadja az ÁSZF-et?" - VÁRJ válaszra! 2. "Mondja be az email címét!" - "kukac"=@ "pont"=. 3. "Létrehozzam?" - csak IGEN után hívd a create_freight_request-et! Mai dátum: 2026-07-21`; // Send session configuration var sessionConfig = { type: 'session.update', session: { modalities: ['text', 'audio'], instructions: instructions, voice: 'alloy', input_audio_format: 'pcm16', output_audio_format: 'pcm16', input_audio_transcription: { model: 'whisper-1' }, turn_detection: { type: 'server_vad', threshold: 0.5, prefix_padding_ms: 300, silence_duration_ms: 500 }, tools: [{ type: 'function', name: 'create_freight_request', description: 'Létrehoz egy fuvar ajánlatkérést. Az irányítószámokat, koordinátákat és távolságot TE állapítsd meg a város neve alapján - NE kérdezd a felhasználót!', parameters: { type: 'object', properties: { email: { type: 'string', description: 'Felhasználó email címe - KÖTELEZŐ!' }, user_id: { type: 'number', description: 'Felhasználó ID ha be van jelentkezve' }, pickup_location: { type: 'string', description: 'Felrakodás helye (város) - KÖTELEZŐ!' }, pickup_location_zip: { type: 'string', description: 'Felrakodás irányítószáma - TE állapítsd meg a város alapján! (pl. Hatvan=3000, Gödöllő=2100, Budapest=1xxx)' }, unload_location: { type: 'string', description: 'Lerakodás helye (város) - KÖTELEZŐ!' }, unload_location_zip: { type: 'string', description: 'Lerakodás irányítószáma - TE állapítsd meg a város alapján!' }, pickup_country_code: { type: 'string', description: 'Felrakodás országkódja', default: 'HU' }, unload_country_code: { type: 'string', description: 'Lerakodás országkódja', default: 'HU' }, pickup_lat: { type: 'number', description: 'Felrakodás GPS lat - TE számítsd ki a város alapján!' }, pickup_lng: { type: 'number', description: 'Felrakodás GPS lng - TE számítsd ki a város alapján!' }, unload_lat: { type: 'number', description: 'Lerakodás GPS lat - TE számítsd ki a város alapján!' }, unload_lng: { type: 'number', description: 'Lerakodás GPS lng - TE számítsd ki a város alapján!' }, utvonal_hossza_km: { type: 'number', description: 'Útvonal hossza km-ben - TE számítsd ki a városok alapján!' }, weight: { type: 'number', description: 'Súly kg-ban - KÖTELEZŐ!' }, quantity: { type: 'number', description: 'Mennyiség - KÖTELEZŐ!' }, quantity_unit: { type: 'string', description: 'Mennyiség egysége', default: 'db' }, cargo_type_name: { type: 'string', description: 'Rakomány típusa', default: 'általános áruszállítás' }, cargo_type_rkat: { type: 'number', description: 'Rakomány kategória ID', default: 1 }, pickup_date_from: { type: 'string', description: 'Felrakodás dátuma YYYY-MM-DD - KÖTELEZŐ!' }, pickup_date_to: { type: 'string', description: 'Felrakodás dátuma vége YYYY-MM-DD' }, unload_date_from: { type: 'string', description: 'Lerakodás dátuma YYYY-MM-DD' }, unload_date_to: { type: 'string', description: 'Lerakodás dátuma vége YYYY-MM-DD' }, additional_info: { type: 'string', description: 'További információk' }, turns: { type: 'number', description: 'Fordulók száma', default: 1 } }, required: ['email', 'pickup_location', 'unload_location', 'weight', 'quantity', 'pickup_date_from'] } }], tool_choice: 'auto', max_response_output_tokens: 1000, // ~50-60 mp beszéd temperature: 0.7 } }; dc.send(JSON.stringify(sessionConfig)); // AZONNAL küldjük a köszöntést - ne várjunk a felhasználóra! // De csak egyszer - flag-gel védjük a dupla futást if (!window.fgptVoiceGlobal.greeted) { window.fgptVoiceGlobal.greeted = true; setTimeout(function() { // Köszöntő üzenet küldése - pontos szöveggel var greetingMsg = { type: 'conversation.item.create', item: { type: 'message', role: 'user', content: [{ type: 'input_text', text: 'Mondd: "Üdvözlöm! Ha fuvardíj kalkulációt szeretne készíteni, állok rendelkezésére, de más kérdésekre is szívesen válaszolok." - csak ezt az egy mondatot mondd, semmi mást!' }] } }; dc.send(JSON.stringify(greetingMsg)); dc.send(JSON.stringify({ type: 'response.create' })); }, 300); } }; // Helper function to save voice messages to database // KIKAPCSOLVA - a Whisper rossz nyelven írja át a magyar beszédet function saveVoiceMessage(message, sender) { // Mentés kikapcsolva mert rossz nyelvű átiratokat generál return; /* if (!message || message.trim() === '') return; fetch('https://fuvarborze.hu/modules/voicegpt/save_voice_message.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: 'message=' + encodeURIComponent(message) + '&sender=' + encodeURIComponent(sender) }).catch(function(err) { // Silent fail - don't interrupt voice chat }); */ } // Listen for AI messages to detect email request and JSON responses dc.onmessage = function(event) { try { var msg = JSON.parse(event.data); // console.log('[Voice] Received message type:', msg.type); // Reset inactivity timer on any activity if (typeof window.resetInactivityTimer === 'function') { window.resetInactivityTimer(); } // Save user input transcription to database if (msg.type === 'conversation.item.input_audio_transcription.completed') { var userTranscript = msg.transcript || ''; if (userTranscript.trim() !== '') { console.log('[Voice] USER said:', userTranscript); saveVoiceMessage(userTranscript, 'user'); } } // Handle function calls if (msg.type === 'response.function_call_arguments.done') { // console.log('[Voice] Function call received:', msg.name); // console.log('[Voice] Raw arguments string:', msg.arguments); if (msg.name === 'create_freight_request') { try { var args = JSON.parse(msg.arguments); // console.log('[Voice] Parsed function arguments:', args); // Extract email from nested structure if AI sent it that way var emailFromArgs = args.email || (args.fuvar_ajanlatkeres && args.fuvar_ajanlatkeres.userdata && args.fuvar_ajanlatkeres.userdata[0] && args.fuvar_ajanlatkeres.userdata[0].email) || ''; // Use the last confirmed email if available (this ensures we use the corrected email) var finalEmail = window.fgptVoiceGlobal.confirmedEmail || emailFromArgs; // console.log('[Voice] Email from args:', emailFromArgs); // console.log('[Voice] Confirmed email from global:', window.fgptVoiceGlobal.confirmedEmail); // console.log('[Voice] Final email to use:', finalEmail); // console.log('[Voice] All args keys:', Object.keys(args)); // Update email in the structure if AI already structured it if (args.fuvar_ajanlatkeres) { // Update the email with the confirmed one if (!args.fuvar_ajanlatkeres.userdata) { args.fuvar_ajanlatkeres.userdata = [{}]; } if (!args.fuvar_ajanlatkeres.userdata[0]) { args.fuvar_ajanlatkeres.userdata[0] = {}; } args.fuvar_ajanlatkeres.userdata[0].email = finalEmail; // console.log('[Voice] Processing freight request from function call with updated email:', args); // console.log('[Voice] JSON to send:', JSON.stringify(args)); // Send directly to backend fetch('https://fuvarborze.hu/modules/dataimport/ajax.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: 'action=process_freight_request&json_data=' + encodeURIComponent(JSON.stringify(args)) }) .then(function(response) { // console.log('[Voice] Backend response status:', response.status); if (!response.ok) { return response.text().then(function(text) { console.error('[Voice] Backend error response:', text); throw new Error('Backend returned ' + response.status + ': ' + text); }); } return response.json(); }) .then(function(data) { // console.log('[Voice] Backend response:', data); var dc = window.fgptVoiceGlobal.dataChannel; if (data.success) { // console.log('✅ Ajánlatkérés sikeresen létrehozva:', data); // Hide email input on success hideEmailInput(); // Send success response back to AI dc.send(JSON.stringify({ type: 'conversation.item.create', item: { type: 'function_call_output', call_id: msg.call_id, output: JSON.stringify({ success: true, message: 'Az ajánlatkérés sikeresen létrehozva! Azonosító: ' + (data.request_id || 'N/A') }) } })); // Trigger response generation dc.send(JSON.stringify({ type: 'response.create' })); } else { console.error('❌ Ajánlatkérés hiba:', data.error); // Send error back to AI for re-prompting var errorMsg = 'HIBA: ' + (data.message || data.error) + ' Kérem javítsa és próbálja újra!'; dc.send(JSON.stringify({ type: 'conversation.item.create', item: { type: 'function_call_output', call_id: msg.call_id, output: JSON.stringify({ success: false, error: data.error, message: errorMsg }) } })); // Trigger response generation dc.send(JSON.stringify({ type: 'response.create' })); } }) .catch(function(err) { console.error('[Voice] Backend error:', err); var dc = window.fgptVoiceGlobal.dataChannel; dc.send(JSON.stringify({ type: 'conversation.item.create', item: { type: 'function_call_output', call_id: msg.call_id, output: JSON.stringify({ success: false, error: 'Technikai hiba történt a mentés során: ' + err.message }) } })); dc.send(JSON.stringify({ type: 'response.create' })); }); return; // Exit early } // Build the freight request JSON (fallback if not structured) var freightRequest = { fuvar_ajanlatkeres: { userdata: [{ email: finalEmail // Use the confirmed email }], pickup_location: args.pickup_location, pickup_location_zip: args.pickup_location_zip || '', unload_location: args.unload_location, unload_location_zip: args.unload_location_zip || '', pickup_country_code: args.pickup_country_code || 'HU', unload_country_code: args.unload_country_code || 'HU', pickup_coordinates: { lat: args.pickup_lat || 0, lng: args.pickup_lng || 0 }, unload_coordinates: { lat: args.unload_lat || 0, lng: args.unload_lng || 0 }, utvonal_hossza_km: args.utvonal_hossza_km || 0, weight: args.weight, quantity: args.quantity, quantity_unit: args.quantity_unit || 'raklap', cargo_type: {}, pickup_date_from: args.pickup_date_from, pickup_date_to: args.pickup_date_to || args.pickup_date_from, unload_date_from: args.unload_date_from || args.pickup_date_from, unload_date_to: args.unload_date_to || args.pickup_date_from, additional_info: args.additional_info || '', turns: args.turns || 1 } }; // Add user_id if provided if (args.user_id) { freightRequest.fuvar_ajanlatkeres.userdata[0].user_id = args.user_id; freightRequest.fuvar_ajanlatkeres.user_id = args.user_id; } // Add cargo type if (args.cargo_type_name && args.cargo_type_rkat) { freightRequest.fuvar_ajanlatkeres.cargo_type[args.cargo_type_name] = { rkat: args.cargo_type_rkat }; } // console.log('[Voice] Processing freight request from function call:', freightRequest); // Send to backend fetch('https://fuvarborze.hu/modules/dataimport/ajax.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: 'action=process_freight_request&json_data=' + encodeURIComponent(JSON.stringify(freightRequest)) }) .then(function(response) { return response.json(); }) .then(function(data) { // console.log('[Voice] Backend response:', data); if (data.success) { // console.log('✅ Ajánlatkérés sikeresen létrehozva'); // Hide email input on success hideEmailInput(); // Send function response back to AI var funcResponse = { type: 'conversation.item.create', item: { type: 'function_call_output', call_id: msg.call_id, output: JSON.stringify({success: true}) } }; dc.send(JSON.stringify(funcResponse)); dc.send(JSON.stringify({ type: 'response.create' })); } else { console.error('❌ Ajánlatkérés hiba:', data.error); // Handle validation errors - send error back to AI if (data.validation_error) { var errorMsg = { type: 'conversation.item.create', item: { type: 'message', role: 'user', content: [{ type: 'input_text', text: 'HIBA: ' + data.message + ' Kérem javítsa és próbálja újra!' }] } }; dc.send(JSON.stringify(errorMsg)); dc.send(JSON.stringify({ type: 'response.create' })); } } }) .catch(function(err) { console.error('Backend error:', err); }); } catch(e) { console.error('Function call parse error:', e); } } } // Check for transcript or text output if (msg.type === 'response.audio_transcript.done' || msg.type === 'response.text.done' || msg.type === 'conversation.item.created') { var text = ''; var originalText = ''; if (msg.transcript) { text = msg.transcript; originalText = msg.transcript; } else if (msg.text) { text = msg.text; originalText = msg.text; } else if (msg.item && msg.item.content) { msg.item.content.forEach(function(c) { if (c.transcript) { text += c.transcript; originalText += c.transcript; } if (c.text) { text += c.text; originalText += c.text; } }); } // console.log('[Voice] Original text:', originalText.substring(0, 200)); // Save AI response to database (only for completed transcripts) if (msg.type === 'response.audio_transcript.done' && originalText.trim() !== '') { console.log('[Voice] AI said:', originalText); saveVoiceMessage(originalText, 'assistant'); } // Get lowercase version for all detections var textLower = originalText.toLowerCase(); // Detect goodbye phrases and auto-close var goodbyePhrases = ['viszlát', 'viszontlátásra', 'búcsúzom', 'kellemes napot', 'szép napot', 'legyen szép napja', 'további szép napot', 'sikeres fuvar', 'bármiben segíthetek', 'ha bármi kérdése', 'bye', 'goodbye', 'take care', 'see you']; // Check if the message contains farewell phrase // Allow longer messages (up to 200 chars) as AI sometimes adds extra text var hasGoodbye = false; if (textLower.length < 200) { hasGoodbye = goodbyePhrases.some(function(phrase) { return textLower.includes(phrase); }); } if (hasGoodbye && window.fgptVoiceGlobal && window.fgptVoiceGlobal.running) { console.log('[Voice] Goodbye detected, closing call in 5 seconds...'); setTimeout(function() { if (window.fgptVoiceGlobal && window.fgptVoiceGlobal.running) { window.fgptVoiceGlobal.stop(); } }, 5000); // Give 5 seconds for goodbye message to finish } // Reset inactivity timer on any message if (window.fgptVoiceGlobal && window.fgptVoiceGlobal.running) { if (typeof window.resetInactivityTimer === 'function') { window.resetInactivityTimer(); } } // Detect keywords and show relevant action buttons var buttonsToShow = []; if (textLower.includes('onmap') || textLower.includes('térképes') || textLower.includes('körfuvar')) { buttonsToShow.push({ label: 'OnMap', url: 'https://fuvarborze.hu/?link=onmap' }); } if (textLower.includes('dataimport') || textLower.includes('tömeges') || textLower.includes('fájl')) { buttonsToShow.push({ label: 'DataImport', url: 'https://fuvarborze.hu/modules/dataimport/' }); } if (textLower.includes('fuvarajánlat') || textLower.includes('tender') || textLower.includes('ajánlatot tehet')) { buttonsToShow.push({ label: 'Fuvarajánlatok', url: 'https://fuvarborze.hu/?link=tender_list' }); } if (textLower.includes('állandó útvonal') || textLower.includes('visszfuvar') || textLower.includes('raktérbörze')) { buttonsToShow.push({ label: 'Állandó útvonalak', url: 'https://fuvarborze.hu/?link=rakterborze' }); } if (textLower.includes('kalkuláció') || textLower.includes('fuvardíj') || textLower.includes('árajánlat')) { buttonsToShow.push({ label: 'Fuvardíj kalkuláció', url: 'https://fuvarborze.hu/?link=calc' }); } // Show buttons if any detected if (buttonsToShow.length > 0) { showActionButtons(buttonsToShow); } else if (currentActionButtons.length > 0) { // Hide buttons after 10 seconds if new topic setTimeout(function() { if (!textLower.includes('onmap') && !textLower.includes('dataimport') && !textLower.includes('fuvarajánlat') && !textLower.includes('állandó') && !textLower.includes('kalkuláció')) { hideActionButtons(); } }, 10000); } // Check for JSON in response (ajánlatkérés or unsubscribe) // Try to find complete JSON object (handle nested structures) var jsonMatch = null; var jsonData = null; // Look for JSON patterns starting with { and containing expected keys if (originalText.includes('fuvar_ajanlatkeres') || originalText.includes('unsubscribe')) { // console.log('[Voice] Found JSON keyword, attempting to parse...'); // Find the start of JSON var startIdx = originalText.indexOf('{'); if (startIdx !== -1) { // Try to parse from each { position for (var i = startIdx; i < originalText.length; i++) { if (originalText[i] === '{') { // Try to parse from this position to the end var substring = originalText.substring(i); // Find matching closing brace by counting var depth = 0; var endIdx = -1; for (var j = 0; j < substring.length; j++) { if (substring[j] === '{') depth++; else if (substring[j] === '}') { depth--; if (depth === 0) { endIdx = j; break; } } } if (endIdx !== -1) { var candidate = substring.substring(0, endIdx + 1); try { var parsed = JSON.parse(candidate); if (parsed.fuvar_ajanlatkeres || parsed.unsubscribe) { jsonMatch = candidate; jsonData = parsed; // console.log('Found valid JSON:', jsonMatch); break; } } catch(e) { // Not valid JSON, continue } } } } } } if (jsonData) { // Check if it's a freight request if (jsonData.fuvar_ajanlatkeres) { // console.log('Processing freight request:', jsonData); // Send JSON to backend for processing fetch('https://fuvarborze.hu/modules/dataimport/ajax.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: 'action=process_freight_request&json_data=' + encodeURIComponent(jsonMatch) }) .then(function(response) { return response.json(); }) .then(function(data) { if (data.success) { // console.log('Ajánlatkérés sikeresen létrehozva:', data); // Hide email input if shown hideEmailInput(); } else { // console.error('Ajánlatkérés hiba:', data.error); } }) .catch(function(err) { // console.error('Backend error:', err); }); } // Check if it's an unsubscribe request if (jsonData.unsubscribe) { fetch('https://fuvarborze.hu/modules/dataimport/ajax.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: 'action=process_unsubscribe&json_data=' + encodeURIComponent(jsonMatch) }) .then(function(response) { return response.json(); }) .then(function(data) { // console.log('Unsubscribe processed:', data); }); } } text = text.toLowerCase(); // Detect email request in AI response if (text.includes('email') || text.includes('e-mail') || text.includes('@')) { // Try to extract email from text var emailMatch = text.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/); var detectedEmail = emailMatch ? emailMatch[0] : ''; // Show email input panel showEmailInput(detectedEmail); // Set callback for when user confirms email emailConfirmCallback = function(confirmedEmail) { // Store confirmed email globally window.fgptVoiceGlobal.confirmedEmail = confirmedEmail; // console.log('[Voice] Email confirmed and stored:', confirmedEmail); // Send confirmed email back to AI var emailMsg = { type: 'conversation.item.create', item: { type: 'message', role: 'user', content: [{ type: 'input_text', text: 'Az email címem: ' + confirmedEmail }] } }; dc.send(JSON.stringify(emailMsg)); dc.send(JSON.stringify({ type: 'response.create' })); }; } } } catch(e) { // Ignore parse errors } }; dc.onclose = function() { window.fgptVoiceGlobal.running = false; window.dispatchEvent(new Event('fgpt-voice-stopped')); // Stop microphone tracks stream.getTracks().forEach(function(track) { track.stop(); }); }; dc.onerror = function(err) { console.error('DataChannel error:', err); window.fgptVoiceGlobal.running = false; window.dispatchEvent(new Event('fgpt-voice-stopped')); }; // Create and set offer pc.createOffer().then(function(offer) { return pc.setLocalDescription(offer); }).then(function() { return fetch('https://api.openai.com/v1/realtime?model=gpt-4o-realtime-preview-2024-12-17', { method: 'POST', headers: { 'Authorization': 'Bearer ' + ephemeralKey, 'Content-Type': 'application/sdp' }, body: pc.localDescription.sdp }); }).then(function(response) { return response.text(); }).then(function(answerSdp) { return pc.setRemoteDescription({ type: 'answer', sdp: answerSdp }); }).catch(function(err) { console.error('Voice init error:', err); alert('Σφάλμα κατά την έναρξη της λειτουργίας της φωνητικής συνομιλίας'); window.fgptVoiceGlobal.running = false; window.dispatchEvent(new Event('fgpt-voice-stopped')); }); }) .catch(function(err) { console.error('Microphone access denied:', err); alert('Παρακαλούμε ενεργοποιήστε τη χρήση μικροφώνου για ομιλία με ήχο!'); }); }) .catch(function(err) { console.error('Session error:', err); alert('Αδυναμία έναρξης ηχητικής συνομιλίας'); }); } // Global voice stop function window.fgptVoiceGlobal = window.fgptVoiceGlobal || {}; window.fgptVoiceGlobal.stop = function() { // Stop timer if (window.fgptVoiceGlobal.timerInterval) { clearInterval(window.fgptVoiceGlobal.timerInterval); window.fgptVoiceGlobal.timerInterval = null; } // Reset timer display var timerEl = document.querySelector('.fgpt-voice-timer'); if (timerEl) timerEl.textContent = '00:00'; if (window.fgptVoiceGlobal.dataChannel) { window.fgptVoiceGlobal.dataChannel.close(); } if (window.fgptVoiceGlobal.peerConnection) { // Stop all tracks before closing connection window.fgptVoiceGlobal.peerConnection.getSenders().forEach(function(sender) { if (sender.track) { sender.track.stop(); } }); window.fgptVoiceGlobal.peerConnection.close(); } if (window.fgptVoiceGlobal.audioElement) { window.fgptVoiceGlobal.audioElement.srcObject = null; } window.fgptVoiceGlobal.running = false; window.dispatchEvent(new Event('fgpt-voice-stopped')); }; // Publikus API – külső gombok számára window.fgptStartVoiceCall = function() { ensureAudioContext().then(function() { if (window.fgptVoiceGlobal && window.fgptVoiceGlobal.running) { window.fgptVoiceGlobal.stop(); } else { initGlobalVoice(); } }); }; })(); </script> </div> </div> </div> <button type="button" class="help-badge-btn" onclick="toggleHelpPopup()"> <span class="icon">💬</span> <span>Βοηθάμε;</span> </button> </div> <script> function toggleHelpPopup() { document.getElementById('helpPopup').classList.toggle('show'); } function submitHelpForm() { var message = document.getElementById('helpMessage').value.trim(); var btn = document.getElementById('helpSubmitBtn'); if (!message) { alert('Παρακαλώ γράψτε το μήνυμά σας!'); return; } // Disable gomb és loader megjelenítése btn.disabled = true; btn.innerHTML = '<span class="help-loader"></span> Άνοιγμα...'; // FreightGPT modal megnyitása az üzenettel if (typeof openFreightGPTModal === 'function') { document.getElementById('helpPopup').classList.remove('show'); document.getElementById('helpMessage').value = ''; btn.disabled = false; btn.innerHTML = '⌲ Αποστολή μηνύματος'; openFreightGPTModal(message, 'Βοηθάμε;'); } else { // Fallback: átirányítás a chat oldalra window.location.href = 'https://fuvarborze.hu/el/chat/?new=1&prompt=' + encodeURIComponent(message); } } // Bezárás kívülre kattintáskor document.addEventListener('click', function(e) { var badge = document.getElementById('helpBadge'); if (badge && !badge.contains(e.target)) { document.getElementById('helpPopup').classList.remove('show'); } }); </script> <style> /* ── Ticker sáv ── */ #site-ticker { position: fixed; bottom: 0; left: 0; width: 100%; height: 28px; z-index: 99999; background: rgba(8, 12, 26, 0.92); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); border-top: 1px solid rgba(255,255,255,0.08); display: flex; align-items: center; overflow: hidden; font-size: 12px; color: #e8e8e8; user-select: none; } #site-ticker .ticker-label { flex-shrink: 0; padding: 0 10px; font-weight: 700; font-size: 11px; letter-spacing: 0.08em; color: #fff; background: rgba(23, 159, 220, 0.85); height: 100%; display: flex; align-items: center; white-space: nowrap; border-right: 1px solid rgba(255,255,255,0.15); } #site-ticker .ticker-track-wrap { flex: 1; overflow: hidden; height: 100%; position: relative; } #site-ticker .ticker-track { display: inline-flex; align-items: center; height: 100%; white-space: nowrap; animation: tickerScroll 38s linear infinite; gap: 0; } #site-ticker .ticker-track:hover { animation-play-state: paused; } @keyframes tickerScroll { 0% { transform: translateX(0); } 100% { transform: translateX(-50%); } } #site-ticker .ti { display: inline-flex; align-items: center; gap: 4px; padding: 0 14px; border-right: 1px solid rgba(255,255,255,0.1); height: 100%; } #site-ticker .ti strong { color: #fff; font-weight: 700; } #site-ticker .ti-eur strong { color: #4fc3f7; } #site-ticker .ti-usd strong { color: #81d4fa; } #site-ticker .ti-diesel strong { color: #ffb74d; } #site-ticker .ti-live strong { color: #69f0ae; } #site-ticker .ti-sep { color: rgba(255,255,255,0.25); font-size: 0.9em; } #site-ticker .ticker-dot { display: inline-block; width: 6px; height: 6px; background: #69f0ae; border-radius: 50%; animation: tickerPulse 2s infinite; flex-shrink: 0; } @keyframes tickerPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.2; } } /* Padding so content is not hidden behind ticker */ body { padding-bottom: calc(28px + env(safe-area-inset-bottom, 0px)) !important; } /* Mobile bottom navbar already above ticker because its z-index < 99999 */ </style> <div id="site-ticker" role="marquee" aria-label="Élő adatok"> <div class="ticker-label">📡 LIVE</div> <div class="ticker-track-wrap"> <div class="ticker-track" id="ticker-track"> <a href="https://fuvarborze.hu/el/?link=statistics" class="ti ti-live" style="text-decoration:none;color:inherit;"> <span class="ticker-dot"></span> <span style="font-size:0.8em;opacity:0.7;margin-right:2px;">Επισκέπτες</span> 👥 <strong id="ticker-online">6</strong> online <span class="ti-sep">·</span> σήμερα: <strong id="ticker-today">2</strong> </a> <a href="https://fuvarborze.hu/el/?link=uzemanyag_arak" class="ti ti-diesel" style="text-decoration:none;color:inherit;"> <span style="font-size:0.8em;opacity:0.7;margin-right:2px;">Ντίζελ</span> ⛽ 🇩🇪 <strong class="ticker-diesel-val" data-country="DE">2,015</strong> 🇦🇹 <strong class="ticker-diesel-val" data-country="AT">1,840</strong> 🇮🇹 <strong class="ticker-diesel-val" data-country="IT">1,957</strong> 🇵🇱 <strong class="ticker-diesel-val" data-country="PL">1,612</strong> 🇭🇺 <strong class="ticker-diesel-val" data-country="HU">1,685</strong> <span style="font-size:0.82em;color:#aaa">€/L</span> </a> <span class="ti" style="padding-right:20px;"> 🚛 <a href="https://fuvarborze.hu/el/freightlist/" style="color:#ffd54f;text-decoration:none;">Προσφορές μεταφορικών</a> </span> <span class="ti"> 💼 <a href="https://fuvarborze.hu/el/job-seeking-drivers/" style="color:#ce93d8;text-decoration:none;">Θέσεις οδηγών</a> </span> <a href="https://fuvarborze.hu/el/?link=statistics" class="ti ti-live" style="text-decoration:none;color:inherit;"> <span class="ticker-dot"></span> <span style="font-size:0.8em;opacity:0.7;margin-right:2px;">Επισκέπτες</span> 👥 <strong id="ticker-online">6</strong> online <span class="ti-sep">·</span> σήμερα: <strong id="ticker-today">2</strong> </a> <a href="https://fuvarborze.hu/el/?link=uzemanyag_arak" class="ti ti-diesel" style="text-decoration:none;color:inherit;"> <span style="font-size:0.8em;opacity:0.7;margin-right:2px;">Ντίζελ</span> ⛽ 🇩🇪 <strong class="ticker-diesel-val" data-country="DE">2,015</strong> 🇦🇹 <strong class="ticker-diesel-val" data-country="AT">1,840</strong> 🇮🇹 <strong class="ticker-diesel-val" data-country="IT">1,957</strong> 🇵🇱 <strong class="ticker-diesel-val" data-country="PL">1,612</strong> 🇭🇺 <strong class="ticker-diesel-val" data-country="HU">1,685</strong> <span style="font-size:0.82em;color:#aaa">€/L</span> </a> <span class="ti" style="padding-right:20px;"> 🚛 <a href="https://fuvarborze.hu/el/freightlist/" style="color:#ffd54f;text-decoration:none;">Προσφορές μεταφορικών</a> </span> <span class="ti"> 💼 <a href="https://fuvarborze.hu/el/job-seeking-drivers/" style="color:#ce93d8;text-decoration:none;">Θέσεις οδηγών</a> </span> <!-- duplicate for seamless loop --> </div> </div> </div> <script> (function() { function refreshTicker() { // GA4 live fetch('/ajaxjobs/analytics.php?action=live') .then(r => r.json()) .then(function(d) { var o = document.querySelectorAll('#ticker-online'); var t = document.querySelectorAll('#ticker-today'); o.forEach(function(el) { if (d.online !== undefined) el.textContent = d.online; }); t.forEach(function(el) { if (d.today !== undefined) el.textContent = d.today; }); }).catch(function(){}); // Árfolyam fetch('/ajaxjobs/exchange_rates.php') .then(r => r.json()) .then(function(d) { document.querySelectorAll('#ticker-eur').forEach(function(el) { if (d.eur) el.textContent = Math.round(d.eur).toLocaleString('hu-HU'); }); document.querySelectorAll('#ticker-usd').forEach(function(el) { if (d.usd) el.textContent = Math.round(d.usd).toLocaleString('hu-HU'); }); }).catch(function(){}); // Diesel fetch('/ajaxjobs/diesel_prices.php') .then(r => r.json()) .then(function(d) { if (!d.prices) return; document.querySelectorAll('.ticker-diesel-val[data-country]').forEach(function(el) { var code = el.dataset.country; if (d.prices[code]) el.textContent = d.prices[code].toFixed(3).replace('.', ','); }); }).catch(function(){}); } // Frissítés minden 2 percben setInterval(refreshTicker, 120000); })(); </script> <style> .fb-site-footer{background:linear-gradient(135deg,#0f172a 0%,#1e293b 50%,#0f172a 100%);padding:60px 20px 0;margin-top:60px;} .fb-site-footer .fb-footer-content{max-width:1200px;margin:0 auto;padding-bottom:40px;} .fb-site-footer .fb-footer-main{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:40px;padding-bottom:40px;border-bottom:1px solid rgba(255,255,255,0.1);} .fb-site-footer .fb-footer-brand h3{color:#fff;font-size:24px;font-weight:800;margin-bottom:16px;display:flex;align-items:center;gap:10px;} .fb-site-footer .fb-footer-brand h3 span{background:linear-gradient(135deg,#3b82f6,#8b5cf6);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;} .fb-site-footer .fb-footer-brand p{color:#cbd5e1;font-size:14px;line-height:1.7;margin-bottom:20px;} .fb-site-footer .fb-footer-contact-box{background:rgba(16,185,129,0.15);border:1px solid rgba(16,185,129,0.3);border-radius:12px;padding:16px;} .fb-site-footer .fb-footer-contact-box .contact-title{display:flex;align-items:center;gap:8px;color:#10b981;font-size:14px;font-weight:600;margin-bottom:8px;} .fb-site-footer .fb-footer-contact-box .contact-title .live-dot{width:8px;height:8px;background:#10b981;border-radius:50%;animation:pulse 1.5s infinite;} .fb-site-footer .fb-footer-contact-box a{display:block;color:#fff;font-size:16px;font-weight:700;text-decoration:none;margin-bottom:4px;} .fb-site-footer .fb-footer-contact-box a:hover{color:#3b82f6;} .fb-site-footer .fb-footer-contact-box .response-time{color:#cbd5e1;font-size:12px;} .fb-site-footer .fb-footer-col h4{color:#fff;font-size:16px;font-weight:700;margin-bottom:20px;} .fb-site-footer .fb-footer-col ul{list-style:none;padding:0;margin:0;} .fb-site-footer .fb-footer-col ul li{margin-bottom:12px;} .fb-site-footer .fb-footer-col ul li a{color:#cbd5e1;text-decoration:none;font-size:14px;transition:color 0.2s;display:inline-flex;align-items:center;gap:6px;} .fb-site-footer .fb-footer-col ul li a:hover{color:#3b82f6;} .fb-site-footer .fb-footer-bottom{padding:24px 0;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:16px;} .fb-site-footer .fb-footer-copyright{color:#64748b;font-size:13px;} .fb-site-footer .fb-footer-legal{display:flex;gap:24px;flex-wrap:wrap;} .fb-site-footer .fb-footer-legal a{color:#cbd5e1;text-decoration:none;font-size:13px;transition:color 0.2s;} .fb-site-footer .fb-footer-legal a:hover{color:#3b82f6;} @media(max-width:992px){.fb-site-footer .fb-footer-main{grid-template-columns:1fr 1fr;gap:32px;}.fb-site-footer .fb-footer-brand{grid-column:span 2;}} @media(max-width:600px){.fb-site-footer .fb-footer-main{grid-template-columns:1fr;}.fb-site-footer .fb-footer-brand{grid-column:span 1;}.fb-site-footer .fb-footer-legal{gap:12px;}} </style> <footer class="fb-site-footer"> <div class="fb-footer-content"> <div class="fb-footer-main"> <div class="fb-footer-brand"> <h3>🚚 Fuvar<span>Börze</span></h3> <p>Ηγέτης στην αγορά μεταφορών στην Ουγγαρία από το 2007. <br> <br> Συνδέουμε τους αναθέτες με αξιόπιστους μεταφορείς, ώστε τα αγαθά να φτάνουν έγκαιρα και με ασφάλεια στον προορισμό τους.</p> <div class="fb-footer-contact-box"> <div class="contact-title"><span class="live-dot"></span>Άμεση απάντηση εγγυημένη</div> <a href="mailto:hello@fuvarborze.hu">hello@fuvarborze.hu</a> <div class="response-time">Μέσος χρόνος απάντησης: 5 λεπτά</div> </div> </div> <div class="fb-footer-col"> <h4>Υπηρεσίες</h4> <ul> <li><a href="https://fuvarborze.hu/el/submit-freight/">📦 Μεταφορά αγαθών</a></li> <li><a href="https://fuvarborze.hu/el/moving-calculator/">🏠 Μετακόμιση</a></li> <li><a href="https://fuvarborze.hu/el/car-transport/">🚗 Μεταφορά οχημάτων</a></li> <li><a href="https://fuvarborze.hu/el/freightlist/">📋 Εντολές Μεταφοράς</a></li> <li><a href="https://fuvarborze.hu/el/freight-cost-calculator/">🧮 Υπολογιστής</a></li> </ul> </div> <div class="fb-footer-col"> <h4>Για τους μεταφορείς</h4> <ul> <li><a href="https://fuvarborze.hu/el/signin/">✨ Εγγραφή</a></li> <li><a href="https://fuvarborze.hu/el/find-freight-offers/">🔍 Προσφορές μεταφορικών</a></li> <li><a href="https://fuvarborze.hu/el/submit-free-capacity/">🚛 Δήλωση διαθεσιμότητας φορτίων</a></li> <li><a href="https://fuvarborze.hu/el/job-offers-for-drivers/">👨‍✈️ Προτάσεις εργασίας</a></li> <li><a href="https://fuvarborze.hu/el/chat/">💬 Böbe</a></li> </ul> </div> <div class="fb-footer-col"> <h4>Εταιρεία μας</h4> <ul> <li><a href="https://fuvarborze.hu/el/helpdesk/">❓ Βοηθητικό Τμήμα</a></li> <li><a href="https://fuvarborze.hu/el/?link=terms">Γενικοί Όροι και Προϋποθέσεις</a></li> <li><a href="https://fuvarborze.hu/el/?link=adatvedelem">Προστασία δεδομένων</a></li> <li><a href="https://fuvarborze.hu/el/?link=impresszum">Εκτύπωση</a></li> <li><a href="https://fuvarborze.hu/el/affiliate-program/">Πρόγραμμα συνεργατών</a></li> </ul> </div> </div> <div class="fb-footer-bottom"> <div class="fb-footer-copyright">© 2026 Fuvarbörze. Όλα τα δικαιώματα κατοχυρώνονται.</div> <div class="fb-footer-legal"> <a href="https://fuvarborze.hu/el/?link=terms">Γενικοί Όροι Συμβάσεων</a> <a href="https://fuvarborze.hu/el/?link=adatvedelem">Πολιτική Απορρήτου</a> <a href="https://fuvarborze.hu/el/?link=cookie">Πολιτική για τα cookies</a> <a href="https://fuvarborze.hu/el/?link=impresszum">Εκτύπωση</a> </div> </div> <div style="text-align:center;margin-top:18px;padding-top:16px;border-top:1px solid rgba(255,255,255,0.1);"> <a href="https://www.barion.com" target="_blank" rel="noopener noreferrer"> <img src="https://fuvarborze.hu/images/barion.png" alt="Barion biztonságos fizetés" style="max-height:36px;opacity:0.85;transition:opacity .2s;" onmouseover="this.style.opacity='1'" onmouseout="this.style.opacity='0.85'"> </a> </div> </div> </footer> <!-- Barion Pixel – Full event helpers --> <script> (function() { function makeArrayPrototypeSafeForBarion() { if (!Object.keys || !Object.defineProperty || !Object.getOwnPropertyDescriptor) return; Object.keys(Array.prototype).forEach(function(key) { var descriptor = Object.getOwnPropertyDescriptor(Array.prototype, key); if (!descriptor || !descriptor.enumerable || !descriptor.configurable) return; descriptor.enumerable = false; try { Object.defineProperty(Array.prototype, key, descriptor); } catch (error) {} }); } window._barionMakeArrayPrototypeSafe = makeArrayPrototypeSafeForBarion; function bpReady(cb) { if (typeof bp === 'function') { cb(); return; } var attempts = 0; var t = setInterval(function() { attempts++; if (typeof bp === 'function') { clearInterval(t); cb(); } else if (attempts > 50) { clearInterval(t); } }, 100); } window._pendingBarionEvents = window._pendingBarionEvents || []; window.trackBarionEvent = function(eventName, payload) { bpReady(function() { makeArrayPrototypeSafeForBarion(); bp('track', eventName, payload || {}); }); }; while (window._pendingBarionEvents.length) { var pendingBarionEvent = window._pendingBarionEvents.shift(); window.trackBarionEvent(pendingBarionEvent.eventName, pendingBarionEvent.payload); } window._barionGrantConsent = function() { bpReady(function() { bp('consent', 'grantConsent', {}); }); }; if (window._pendingBarionConsent) { window._pendingBarionConsent = false; window._barionGrantConsent(); } window.addEventListener('load', function() { if (typeof getCookie === 'function' && getCookie('cookies_accepted') === 'true') { window._barionGrantConsent(); } }); })(); </script> </body> </html>