Files
felhom.eu/website/kapcsolat.html
T
admin 43b67283c3
gates / gates (push) Failing after 14m58s
website: the footer dash swept site-wide, and the primary CTA meets WCAG AA
Two operator decisions from STOP 3, both independent of the home-page switch,
which was NOT approved and has NOT happened. index.html still serves the old
design; only the footer line and the button change on it.

1. The footer em dash, on all 21 page files (12 HU + 8 EN + the preview).
   "(c) 2026 felhom.eu - Sajat felhod..." now uses the spaced en dash, which is
   the correct Hungarian gondolatjel. Done as one sweep because site_gates.py
   gate 3 requires every page in a language set to carry an IDENTICAL footer, so
   this could never have been a one-page edit. Gate green: all 14 still match.

   Scope, stated honestly: this clears the footer only. 300 em dashes remain in
   the BODIES of the other 19 pages (gyik 53, en/faq 53, adatkezeles 33,
   szolgaltatasok-nonpublic 27, testing 24, teszteles 23, index 17/19, ...). The
   preview page is the only page at zero. The rest is NEXT.md work, page by page.

2. R-930, the operator's choice of the three offered: white on --blue measures
   4.01:1, under WCAG AA's 4.5:1 for body text. .cta-button goes to 1.2rem/700,
   which is >=18.66px at >=700 weight, so WCAG counts it as LARGE text and the
   floor becomes 3:1 - which 4.01 clears without touching --blue. Darkening the
   token was rejected because --blue is shared with the hub and controller UIs.
   Horizontal padding trimmed 32->26px to protect the one-line rule for the
   longest label; verified in the browser at 390px, not assumed.
   .cta-button-secondary is unchanged: it already measures 7.17:1.

   This reaches the primary button on 16 pages, which is the point - the defect
   was never the home page's.

site.css?v= bumped to 12 on all 21 files. The pages sat at v=10 and the preview
at v=11; leaving them split would have served a returning visitor the old
stylesheet and the change would have looked like it did not deploy.

site_gates.py green.
2026-10-11 00:25:43 +02:00

603 lines
30 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="hu">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kapcsolat — Kérj személyre szabott ajánlatot otthoni szerveredhez | Felhom.eu</title>
<meta name="description" content="Írj nekünk és személyre szabott ajánlatot készítünk otthoni szerveredhez. Kérdésed van? Segítünk! Email: info@felhom.eu">
<meta name="keywords" content="kapcsolat, ajánlatkérés, otthoni szerver ajánlat, Felhom elérhetőség">
<meta name="robots" content="index, follow">
<link rel="canonical" href="https://felhom.eu/kapcsolat">
<link rel="alternate" hreflang="hu" href="https://felhom.eu/kapcsolat">
<link rel="alternate" hreflang="en" href="https://felhom.eu/en/contact">
<link rel="alternate" hreflang="x-default" href="https://felhom.eu/kapcsolat">
<meta property="og:type" content="website">
<meta property="og:url" content="https://felhom.eu/kapcsolat">
<meta property="og:title" content="Kapcsolat — Felhom.eu">
<meta property="og:description" content="Írj nekünk és személyre szabott ajánlatot készítünk otthoni szerveredhez.">
<meta property="og:image" content="https://felhom.eu/assets/og-image.png">
<meta property="og:locale" content="hu_HU">
<meta property="og:site_name" content="Felhom.eu">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Kapcsolat — Felhom.eu">
<meta name="twitter:description" content="Kérdésed van? Írj nekünk: info@felhom.eu">
<meta name="twitter:image" content="https://felhom.eu/assets/og-image.png">
<!-- shared assets: bump ?v= together on any site.css/icons.svg change -->
<link rel="stylesheet" href="/assets/site.css?v=12">
<link rel="icon" type="image/png" href="/assets/logo_favicon_2.svg">
<script defer src="https://stats.felhom.eu/script.js" data-website-id="d419db57-5e1c-48df-bdb3-c29f25fb1661"></script>
</head>
<body class="page-kapcsolat">
<nav>
<div class="container">
<a href="/" class="logo">
<img class="logo-mark" src="/assets/logo-mark.svg" alt="" aria-hidden="true">
<img class="logo-word" src="/assets/logo-wordmark.png" alt="felhom.eu">
</a>
<ul class="nav-links">
<li><a href="/#szolgaltatasok">Szolgáltatások</a></li>
<li><a href="/alkalmazasok">Alkalmazások</a></li>
<li><a href="/technologiak">Technológiák</a></li>
<li><a href="/biztonsagimentes">Mentések</a></li>
<li><a href="/gyik">GYIK</a></li>
<li><a href="/kapcsolat" class="active">Kapcsolat</a></li>
<li class="lang-globe-li"><details class="lang-globe"><summary class="lang-globe-btn" aria-label="Nyelv" title="Nyelv"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-globe"/></svg></summary><ul class="lang-globe-menu"><li><a href="/kapcsolat" lang="hu" hreflang="hu" class="lang-globe-item current" aria-current="true">Magyar</a></li><li><a href="/en/contact" lang="en" hreflang="en" class="lang-globe-item">English</a></li></ul></details></li>
</ul>
<button class="hamburger" id="hamburger" aria-label="Menü megnyitása" aria-expanded="false">
<span class="hamburger-box">
<span class="hamburger-line"></span>
<span class="hamburger-line"></span>
<span class="hamburger-line"></span>
</span>
</button>
</div>
</nav>
<div class="mobile-overlay" id="mobileOverlay"></div>
<section class="page-header">
<div class="container">
<h1>Írj nekünk <span>bátran!</span></h1>
<p>Kérdésed van, vagy szeretnéd megbeszélni az igényeidet? Töltsd ki az űrlapot, és hamarosan válaszolunk.</p>
</div>
</section>
<main>
<section class="content-section" style="padding-top: 0;">
<div class="container">
<div class="contact-layout">
<!-- Form -->
<div class="contact-form-card">
<div id="formStatus" class="form-status"></div>
<form id="contactForm" novalidate>
<div style="position:absolute;left:-9999px;" aria-hidden="true">
<input type="text" name="website" tabindex="-1" autocomplete="off">
</div>
<div class="form-row">
<div class="form-group">
<label for="name">Név <span class="required">*</span></label>
<input type="text" id="name" name="name" placeholder="Teljes neved" required>
<div class="error-message" id="nameError">Kérlek, add meg a neved.</div>
</div>
<div class="form-group">
<label for="email">Email <span class="required">*</span></label>
<input type="email" id="email" name="email" placeholder="pelda@email.hu" required>
<div class="error-message" id="emailError">Kérlek, adj meg egy érvényes email címet.</div>
</div>
</div>
<div class="form-group">
<label for="subject">Tárgy <span class="required">*</span></label>
<select id="subject" name="subject" required>
<option value="" disabled selected>Válassz témát...</option>
<option value="zart-teszt">Zárt teszt — jelentkezem tesztelőnek</option>
<option value="erdeklodes">Érdeklődés — szeretném megismerni a szolgáltatást</option>
<option value="arajanlat">Árajánlat kérés — konkrét igényeim vannak</option>
<option value="tamogatas">Támogatás — meglévő szerveremet érintő kérdés</option>
<option value="egyeb">Egyéb</option>
</select>
<div class="error-message" id="subjectError">Kérlek, válassz egy témát.</div>
</div>
<div class="form-group">
<label for="message">Üzenet <span class="required">*</span></label>
<textarea id="message" name="message" placeholder="Írd le, miben segíthetünk..." required></textarea>
<div class="error-message" id="messageError">Kérlek, írd le az üzeneted.</div>
</div>
<div class="form-group">
<label>Fájl csatolás <span style="color: var(--text-3); font-weight: 400;">(opcionális)</span></label>
<div class="file-upload-zone" id="dropZone">
<input type="file" id="fileInput" multiple accept=".pdf,.doc,.docx,.xls,.xlsx,.png,.jpg,.jpeg,.gif,.webp,.txt,.csv,.zip,.7z">
<div class="upload-icon"><svg class="ico-tile" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-paperclip"/></svg></div>
<div class="upload-text">
<strong>Kattints ide</strong> vagy húzd ide a fájlokat
</div>
<div class="upload-hint">PDF, képek, dokumentumok · Max. 20 MB összesen</div>
</div>
<div class="file-list" id="fileList"></div>
<div class="file-total-size" id="fileTotalSize"></div>
</div>
<div class="checkbox-group">
<input type="checkbox" id="privacy" name="privacy" required>
<label for="privacy">
Elolvastam az <a href="/adatkezeles" target="_blank" rel="noopener">Adatkezelési tájékoztatót</a>, és hozzájárulok, hogy a megadott nevemet, e-mail-címemet, üzenetemet és csatolt fájljaimat a megkeresésem megválaszolására kezeljék. Az üzenetet levélküldő és levelezési szolgáltatók továbbítják. A hozzájárulásomat bármikor visszavonhatom az info@felhom.eu címen.
</label>
</div>
<div class="error-message" id="privacyError" style="margin-top: -16px; margin-bottom: 16px;">Az adatkezelési hozzájárulás szükséges.</div>
<button type="submit" class="submit-button" id="submitBtn">
<span class="btn-text">Üzenet küldése →</span>
<span class="spinner"></span>
</button>
</form>
</div>
<!-- Sidebar -->
<div class="contact-sidebar">
<div class="sidebar-card">
<h3><span class="icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-mail"/></svg></span> Közvetlen email</h3>
<p>Ha inkább emailben írnál:</p>
<a href="mailto:info@felhom.eu" class="direct-email">
<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-mail"/></svg> info@felhom.eu
</a>
</div>
<div class="sidebar-card">
<h3><span class="icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-clock"/></svg></span> Válaszidő</h3>
<p>Általában <strong style="color: var(--blue-bright);">24 órán belül</strong> válaszolunk munkanapokon.</p>
<p>Sürgős támogatási kérdés esetén jelezd a tárgyban.</p>
</div>
<div class="sidebar-card">
<h3><span class="icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-lightbulb"/></svg></span> Miben segíthetünk?</h3>
<ul class="sidebar-list">
<li><span class="li-icon"><svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-monitor"/></svg></span> Szerver konfiguráció tanácsadás</li>
<li><span class="li-icon"><svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-package"/></svg></span> Alkalmazás telepítés és beállítás</li>
<li><span class="li-icon"><svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-lock"/></svg></span> Biztonsági mentés kialakítás</li>
<li><span class="li-icon"><svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-globe"/></svg></span> Távoli elérés beállítása</li>
<li><span class="li-icon"><svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-wrench"/></svg></span> Meglévő szerver karbantartás</li>
</ul>
</div>
</div>
</div>
</div>
</section>
</main>
<footer>
<div class="container">
<p>© 2026 felhom.eu – Saját felhőd, saját szabályaid</p>
<p class="footer-legal">Üzemeltető: Nagyfenyvesi Viktor · <a href="mailto:info@felhom.eu">info@felhom.eu</a> · <a href="/adatkezeles">Adatkezelési tájékoztató</a> · <a href="/feltetelek">Feltételek</a></p>
</div>
</footer>
<script>
(() => {
'use strict';
// ==============================================
// CONFIGURATION
// ==============================================
const CONFIG = {
// TODO: Replace with your actual form backend endpoint.
// Options:
// 1. Self-hosted: Deploy a small container (e.g. Go/Python) that receives POST and sends via SMTP
// 2. Formspree: 'https://formspree.io/f/YOUR_FORM_ID'
// 3. Cloudflare Workers: Deploy a worker that forwards to email
//
// For now, falls back to mailto: if no endpoint is configured.
formEndpoint: '/api/contact',
maxTotalFileSize: 20 * 1024 * 1024, // 20 MB
maxSingleFileSize: 10 * 1024 * 1024, // 10 MB per file
maxFiles: 5,
allowedExtensions: ['pdf','doc','docx','xls','xlsx','png','jpg','jpeg','gif','webp','txt','csv','zip','7z'],
};
// ==============================================
// DOM REFS
// ==============================================
const form = document.getElementById('contactForm');
const submitBtn = document.getElementById('submitBtn');
const formStatus = document.getElementById('formStatus');
const dropZone = document.getElementById('dropZone');
const fileInput = document.getElementById('fileInput');
const fileListEl = document.getElementById('fileList');
const fileTotalSizeEl = document.getElementById('fileTotalSize');
let attachedFiles = [];
// Preselect the subject from ?tema= (the „Zárt teszt" CTA on the landing page
// links here as /kapcsolat?tema=zart-teszt). Unknown values are ignored.
(function preselectSubject() {
const wanted = new URLSearchParams(window.location.search).get('tema');
if (!wanted) return;
const select = document.getElementById('subject');
if (!select) return;
const match = Array.from(select.options).some(o => o.value === wanted);
if (match) {
select.value = wanted;
} else {
console.warn('[kapcsolat] unknown ?tema= value, ignoring:', wanted);
}
})();
// ==============================================
// VALIDATION
// ==============================================
function validateField(field) {
const errorEl = document.getElementById(field.id + 'Error');
let valid = true;
if (field.type === 'checkbox') {
valid = field.checked;
} else if (field.required && !field.value.trim()) {
valid = false;
} else if (field.type === 'email' && field.value.trim()) {
valid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(field.value.trim());
}
if (valid) {
field.classList.remove('error');
if (errorEl) errorEl.classList.remove('visible');
} else {
field.classList.add('error');
if (errorEl) errorEl.classList.add('visible');
}
return valid;
}
function validateForm() {
const fields = ['name', 'email', 'subject', 'message', 'privacy'];
let allValid = true;
fields.forEach(id => {
const field = document.getElementById(id);
if (!validateField(field)) allValid = false;
});
return allValid;
}
// Live validation on blur
['name', 'email', 'subject', 'message', 'privacy'].forEach(id => {
const el = document.getElementById(id);
const event = el.type === 'checkbox' ? 'change' : 'blur';
el.addEventListener(event, () => validateField(el));
// Clear error on input
el.addEventListener('input', () => {
if (el.classList.contains('error')) validateField(el);
});
});
// ==============================================
// FILE HANDLING
// ==============================================
function formatFileSize(bytes) {
if (bytes < 1024) return bytes + ' B';
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
}
function getFileIcon(name) {
const ext = name.split('.').pop().toLowerCase();
const icons = {
pdf: '<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-file-text"/></svg>', doc: '<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-file-text"/></svg>', docx: '<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-file-text"/></svg>', xls: '<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-chart-column"/></svg>', xlsx: '<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-chart-column"/></svg>',
png: '<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-image"/></svg>', jpg: '<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-image"/></svg>', jpeg: '<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-image"/></svg>', gif: '<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-image"/></svg>', webp: '<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-image"/></svg>',
txt: '<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-file-text"/></svg>', csv: '<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-chart-column"/></svg>', zip: '<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-package"/></svg>', '7z': '<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-package"/></svg>',
};
return icons[ext] || '<svg class="ico" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-paperclip"/></svg>';
}
function getTotalFileSize() {
return attachedFiles.reduce((sum, f) => sum + f.size, 0);
}
function addFiles(fileArray) {
for (const file of fileArray) {
// Check extension
const ext = file.name.split('.').pop().toLowerCase();
if (!CONFIG.allowedExtensions.includes(ext)) {
showStatus(`A "${file.name}" fájltípus nem engedélyezett.`, 'error-state');
continue;
}
// Check single file size
if (file.size > CONFIG.maxSingleFileSize) {
showStatus(`A "${file.name}" túl nagy (max. ${formatFileSize(CONFIG.maxSingleFileSize)} / fájl).`, 'error-state');
continue;
}
// Check max file count
if (attachedFiles.length >= CONFIG.maxFiles) {
showStatus(`Maximum ${CONFIG.maxFiles} fájl csatolható.`, 'error-state');
break;
}
// Check total size
if (getTotalFileSize() + file.size > CONFIG.maxTotalFileSize) {
showStatus(`Összesített fájlméret meghaladja a ${formatFileSize(CONFIG.maxTotalFileSize)} limitet.`, 'error-state');
break;
}
// Check duplicate
if (attachedFiles.some(f => f.name === file.name && f.size === file.size)) {
continue;
}
attachedFiles.push(file);
}
renderFileList();
}
function removeFile(index) {
attachedFiles.splice(index, 1);
renderFileList();
// Reset file input so same file can be re-added
fileInput.value = '';
}
function renderFileList() {
if (attachedFiles.length === 0) {
fileListEl.innerHTML = '';
fileTotalSizeEl.textContent = '';
return;
}
fileListEl.innerHTML = attachedFiles.map((file, i) => `
<div class="file-item">
<span class="file-icon">${getFileIcon(file.name)}</span>
<div class="file-info">
<div class="file-name" title="${file.name}">${file.name}</div>
<div class="file-size">${formatFileSize(file.size)}</div>
</div>
<button type="button" class="file-remove" data-index="${i}" title="Eltávolítás">&#215;</button>
</div>
`).join('');
// Bind remove buttons
fileListEl.querySelectorAll('.file-remove').forEach(btn => {
btn.addEventListener('click', () => removeFile(parseInt(btn.dataset.index)));
});
// Total size indicator
const total = getTotalFileSize();
const pct = (total / CONFIG.maxTotalFileSize) * 100;
fileTotalSizeEl.textContent = `${formatFileSize(total)} / ${formatFileSize(CONFIG.maxTotalFileSize)}`;
fileTotalSizeEl.className = 'file-total-size';
if (pct > 90) fileTotalSizeEl.classList.add('error-text');
else if (pct > 70) fileTotalSizeEl.classList.add('warning');
}
// File input change
fileInput.addEventListener('change', () => {
if (fileInput.files.length) {
addFiles(Array.from(fileInput.files));
fileInput.value = '';
}
});
// Drag & drop
['dragenter', 'dragover'].forEach(evt => {
dropZone.addEventListener(evt, e => {
e.preventDefault();
dropZone.classList.add('dragover');
});
});
['dragleave', 'drop'].forEach(evt => {
dropZone.addEventListener(evt, e => {
e.preventDefault();
dropZone.classList.remove('dragover');
});
});
dropZone.addEventListener('drop', e => {
if (e.dataTransfer.files.length) {
addFiles(Array.from(e.dataTransfer.files));
}
});
// ==============================================
// STATUS MESSAGES
// ==============================================
function showStatus(message, type) {
formStatus.textContent = message;
formStatus.className = 'form-status ' + type;
formStatus.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
if (type === 'error-state') {
setTimeout(() => {
formStatus.className = 'form-status';
}, 6000);
}
}
// ==============================================
// FORM SUBMISSION
// ==============================================
form.addEventListener('submit', async (e) => {
e.preventDefault();
formStatus.className = 'form-status';
if (!validateForm()) {
// Build specific error message
const missing = [];
if (!document.getElementById('name').value.trim()) missing.push('név');
const emailVal = document.getElementById('email').value.trim();
if (!emailVal || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailVal)) missing.push('email');
if (!document.getElementById('subject').value) missing.push('tárgy');
if (!document.getElementById('message').value.trim()) missing.push('üzenet');
if (!document.getElementById('privacy').checked) missing.push('adatkezelési hozzájárulás');
if (missing.length === 1 && missing[0] === 'adatkezelési hozzájárulás') {
showStatus('Kérlek, fogadd el az adatkezelési hozzájárulást a küldéshez.', 'error-state');
} else {
showStatus('Kérlek, töltsd ki az összes kötelező mezőt.', 'error-state');
}
return;
}
submitBtn.classList.add('loading');
submitBtn.disabled = true;
const formData = {
name: document.getElementById('name').value.trim(),
email: document.getElementById('email').value.trim(),
subject: document.getElementById('subject').value,
message: document.getElementById('message').value.trim(),
};
// Subject label mapping
const subjectLabels = {
'zart-teszt': 'Jelentkezés — zárt teszt',
erdeklodes: 'Érdeklődés',
arajanlat: 'Árajánlat kérés',
tamogatas: 'Támogatás',
egyeb: 'Egyéb',
};
try {
if (CONFIG.formEndpoint) {
// --- Backend submission ---
const data = new FormData();
data.append('name', formData.name);
data.append('email', formData.email);
data.append('subject', subjectLabels[formData.subject] || formData.subject);
data.append('message', formData.message);
attachedFiles.forEach(file => {
data.append('attachments', file);
});
const response = await fetch(CONFIG.formEndpoint, {
method: 'POST',
body: data,
});
if (!response.ok) {
throw new Error(`Szerver hiba: ${response.status}`);
}
showStatus('Üzeneted sikeresen elküldtük! Hamarosan válaszolunk.', 'success');
form.reset();
attachedFiles = [];
renderFileList();
} else {
// --- Fallback: mailto ---
const subjectLine = `[Felhom.eu] ${subjectLabels[formData.subject] || formData.subject}`;
const body = [
`Név: ${formData.name}`,
`Email: ${formData.email}`,
``,
formData.message,
].join('\n');
const mailtoUrl = `mailto:info@felhom.eu?subject=${encodeURIComponent(subjectLine)}&body=${encodeURIComponent(body)}`;
window.location.href = mailtoUrl;
if (attachedFiles.length > 0) {
showStatus('Az email kliens megnyílt. A csatolt fájlokat kézzel kell hozzáadnod az emailhez, mert a mailto: link nem támogatja a mellékleteket.', 'error-state');
} else {
showStatus('Az email kliens megnyílt az üzeneteddel. Küld el az emailt a kapcsolatfelvételhez!', 'success');
}
}
} catch (err) {
console.error('Form submission error:', err);
showStatus(`Hiba történt a küldés során. Kérlek, próbáld újra vagy írj közvetlenül az info@felhom.eu címre.`, 'error-state');
} finally {
submitBtn.classList.remove('loading');
submitBtn.disabled = false;
}
});
// ==============================================
// DEBUG HELPER
// ==============================================
// Uncomment to test form states:
// window.debugForm = {
// showSuccess: () => showStatus('Üzeneted sikeresen elküldtük!', 'success'),
// showError: () => showStatus('Hiba történt.', 'error-state'),
// getFiles: () => console.log(attachedFiles),
// getFormData: () => {
// const fd = new FormData(form);
// for (const [k,v] of fd.entries()) console.log(k, v);
// },
// };
})();
</script>
<script>
(function() {
var hamburger = document.getElementById('hamburger');
var navLinks = document.querySelector('.nav-links');
var overlay = document.getElementById('mobileOverlay');
var body = document.body;
if (!hamburger || !navLinks || !overlay) {
console.warn('[mobile-menu] Missing elements:', {
hamburger: !!hamburger,
navLinks: !!navLinks,
overlay: !!overlay
});
return;
}
function openMenu() {
hamburger.classList.add('is-active');
navLinks.classList.add('is-open');
overlay.classList.add('is-visible');
body.classList.add('menu-open');
hamburger.setAttribute('aria-expanded', 'true');
hamburger.setAttribute('aria-label', 'Menü bezárása');
}
function closeMenu() {
hamburger.classList.remove('is-active');
navLinks.classList.remove('is-open');
overlay.classList.remove('is-visible');
body.classList.remove('menu-open');
hamburger.setAttribute('aria-expanded', 'false');
hamburger.setAttribute('aria-label', 'Menü megnyitása');
}
hamburger.addEventListener('click', function() {
if (navLinks.classList.contains('is-open')) {
closeMenu();
} else {
openMenu();
}
});
overlay.addEventListener('click', closeMenu);
navLinks.querySelectorAll('a').forEach(function(link) {
link.addEventListener('click', closeMenu);
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && navLinks.classList.contains('is-open')) {
closeMenu();
}
});
window.addEventListener('resize', function() {
if (window.innerWidth > 900 && navLinks.classList.contains('is-open')) {
closeMenu();
}
});
})();
</script>
</body>
</html>