<!doctype html><html lang=”en”>
<head>
<meta charset=”utf-8″ />
<meta name=”viewport” content=”width=device-width,initial-scale=1″ />
<title>Federation — Informational Site</title>
<meta name=”description” content=”Federation — official website. Learn about our mission, events, gallery and how to contact us. Available in English and Georgian.” />
<!– Open Graph & Twitter –>
<meta property=”og:title” content=”Federation — Informational Site” />
<meta property=”og:description” content=”Federation — official website. Learn about our mission, events, gallery and how to contact us.” />
<meta property=”og:type” content=”website” />
<meta name=”twitter:card” content=”summary_large_image” />
<!– Fonts: Inter (EN) + Noto Sans Georgian (KA) –>
<link rel=”preconnect” href=”https://fonts.gstatic.com” crossorigin>
<link href=”https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&family=Noto+Sans+Georgian:wght@300;400;600;700&display=swap” rel=”stylesheet”>
<style>
:root{
–primary:#D32F2F; /* red */
–primary-dark:#b82727; /* hover */
–text:#222222;
–muted:#F5F5F5;
–border:#E0E0E0;
–radius:10px;
–base-font-size:16px;
}
html{font-family:Inter, system-ui, -apple-system, ‘Segoe UI’, Roboto, ‘Noto Sans Georgian’, sans-serif; font-size:var(–base-font-size); color:var(–text); background:white;}
/* If Georgian language active, switch font */
:root[lang=”ka”] html, html[lang=”ka”]{font-family:’Noto Sans Georgian’, ‘Inter’, sans-serif}
*{box-sizing:border-box}
body{margin:0;line-height:1.45;-webkit-font-smoothing:antialiased}
a{color:var(–primary); text-decoration:none}
a:focus{outline:3px solid rgba(211,47,47,0.2)}
/* Header */
header{position:sticky;top:0;z-index:60;background:linear-gradient(0deg,rgba(255,255,255,0.96),rgba(255,255,255,0.96));backdrop-filter:blur(4px);border-bottom:1px solid var(–border)}
.container{max-width:1100px;margin:0 auto;padding:1rem}
.header-grid{display:flex;align-items:center;justify-content:space-between;gap:1rem}
.logo{display:flex;align-items:center;gap:.75rem}
.logo svg{width:42px;height:42px;background:var(–primary);border-radius:8px;padding:6px}
nav ul{display:flex;gap:1rem;list-style:none;padding:0;margin:0}
.lang-switch{display:flex;gap:.5rem;align-items:center}
.lang-btn{border:1px solid var(–border);background:transparent;padding:.35rem .6rem;border-radius:6px;cursor:pointer}
.lang-btn[aria-pressed=”true”]{background:var(–primary);color:#fff;border-color:transparent}
/* Hero */
.hero{padding:3rem 0;display:grid;grid-template-columns:1fr;gap:1.25rem;align-items:center}
.hero-inner{display:flex;flex-direction:column;gap:1rem}
.hero h1{font-size:2rem;margin:0}
.hero p{margin:0;color:#333}
.cta-row{display:flex;gap:.75rem;flex-wrap:wrap}
.btn{background:var(–primary);color:#fff;padding:.6rem 1rem;border-radius:8px;border:none;cursor:pointer}
.btn.secondary{background:transparent;border:1px solid var(–primary);color:var(–primary)}
.btn:hover{background:var(–primary-dark)}
/* Sections */
section{padding:2rem 0;border-bottom:1px solid var(–border)}
.grid-3{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:1rem}
/* Events */
.events-list{display:grid;gap:1rem}
.event-card{border:1px solid var(–border);padding:1rem;border-radius:8px;background:linear-gradient(180deg,#fff,#fff);}
/* Gallery */
.gallery{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:6px}
.gallery img{width:100%;height:120px;object-fit:cover;border-radius:6px;display:block}
/* Footer */
footer{background:var(–muted);padding:1.25rem 0}
.footer-grid{display:grid;grid-template-columns:1fr 1fr;gap:1rem;align-items:start}
/* Forms */
input,textarea,select{width:100%;padding:.6rem;border:1px solid var(–border);border-radius:8px;font-size:1rem}
button[type=”submit”]{background:var(–primary);color:white;padding:.6rem 1rem;border-radius:8px;border:none}
/* Focus states */
:focus{outline:3px solid rgba(211,47,47,0.18)}
/* Responsive tweaks */
@media(min-width:768px){
.hero{grid-template-columns:1fr 380px}
.hero h1{font-size:2.6rem}
}
/* Utility */
.muted{color:#666}
.chip{display:inline-block;padding:.25rem .6rem;border-radius:999px;border:1px solid var(–border)}
/* Simple masonry-ish */
.masonry{column-count:3;column-gap:8px}
.masonry-item{display:inline-block;width:100%;margin-bottom:8px}
@media(max-width:900px){.masonry{column-count:2}}
@media(max-width:520px){.masonry{column-count:1}}
</style>
</head>
<body>
<!– Light-weight white SVG logo (keeps logo white on red backgrounds) –>
<header role=”banner”>
<div class=”container header-grid”>
<div class=”logo”>
<svg viewBox=”0 0 100 100″ aria-hidden=”true” focusable=”false”>
<rect width=”100″ height=”100″ rx=”18″ fill=”#fff”/>
<g transform=”translate(12,12)”>
<path d=”M10 40 L70 10 L70 70 Z” fill=”#D32F2F”></path>
</g>
</svg>
<div>
<strong id=”site-title”>Federation</strong>
<div class=”muted” style=”font-size:.85rem”>Federation — KA | EN</div>
</div>
</div>
<nav aria-label=”Main navigation”>
<ul id=”main-nav”>
<li><a href=”/en/” data-slug=”home”>Home</a></li>
<li><a href=”/en/about” data-slug=”about”>About</a></li>
<li><a href=”/en/events” data-slug=”events”>Events</a></li>
<li><a href=”/en/gallery” data-slug=”gallery”>Gallery</a></li>
<li><a href=”/en/contact” data-slug=”contact”>Contact</a></li>
</ul>
</nav>
<div class=”lang-switch” aria-hidden=”false”>
<button class=”lang-btn” id=”ka-btn” data-lang=”ka” aria-pressed=”false”>KA</button>
<button class=”lang-btn” id=”en-btn” data-lang=”en” aria-pressed=”true”>EN</button>
</div>
</div>
</header>
<main id=”app” role=”main”>
<!– Marketing / Front content is rendered dynamically by JS based on language + route –>
</main>
<footer role=”contentinfo”>
<div class=”container footer-grid”>
<div>
<strong>Federation</strong>
<p class=”muted”>Small blurb about the federation — fostering community, sport and culture.</p>
<p><span class=”chip”>Address:</span> 123 Federation St, City</p>
<p><span class=”chip”>Email:</span> info@federation.example</p>
<p><span class=”chip”>Phone:</span> +995 32 2 345 678</p>
</div>
<div>
<nav aria-label=”Footer navigation”>
<ul style=”list-style:none;padding:0;display:grid;grid-template-columns:repeat(2,1fr);gap:.5rem;margin:0″>
<li><a href=”/en/”>Home</a></li>
<li><a href=”/en/about”>About</a></li>
<li><a href=”/en/events”>Events</a></li>
<li><a href=”/en/gallery”>Gallery</a></li>
<li><a href=”/en/contact”>Contact</a></li>
</ul>
</nav>
<div style=”margin-top:1rem;font-size:.9rem;color:#666″>© <span id=”year”></span> Federation. All rights reserved.</div>
</div>
</div>
</footer>
<!– Lightbox (simple) –>
<div id=”lightbox” style=”display:none;position:fixed;inset:0;background:rgba(0,0,0,0.85);align-items:center;justify-content:center;padding:20px;z-index:200″>
<button id=”lb-close” style=”position:absolute;right:16px;top:16px;background:transparent;border:none;color:white;font-size:1.4rem”>✕</button>
<img id=”lb-img” src=”” alt=”” style=”max-width:calc(100% – 40px);max-height:calc(100% – 40px);border-radius:8px” />
</div>
<script type=”application/ld+json” id=”org-schema”>
{
“@context”:”https://schema.org”,
“@type”:”Organization”,
“name”:”Federation”,
“url”:”https://example.org/”,
“logo”:”https://example.org/logo.png”,
“sameAs”:[]
}
</script>
<script>
// — Basic client-side router + bilingual content —
const DEFAULT_LANG = ‘en’;
const supported = [‘en’,’ka’];
const langFromPath = () => {
const p = location.pathname.split(‘/’).filter(Boolean);
if(p[0] && supported.includes(p[0])) return p[0];
return DEFAULT_LANG;
}
let state = {lang: langFromPath(), page: ‘home’};
// Content placeholders: English + Georgian. Replace copy as you like.
const CONTENT = {
en: {
siteTitle: ‘Federation’,
nav: {home:’Home’, about:’About Us’, events:’Events’, gallery:’Gallery’, contact:’Contact’},
home:{
h1:’Welcome to the Federation’,
sub:’We bring communities together through sports, culture and education. Join our events and be part of the movement.’,
bullets:[‘National reach’,’Community programs’,’Transparent governance’],
cta1:’Learn More’, cta2:’Join an Event’
},
about:{mission:’Our mission is to …’, vision:’Our vision is to …’, history:’Founded in 19XX…’},
events:[
{id:1,title:’Spring Championship’,date:’2025-05-20′,location:’Sports Hall’,desc:’Top competitors from across the country.’},
{id:2,title:’Coaching Workshop’,date:’2025-06-10′,location:’Conference Center’,desc:’Improve coaching skills.’},
{id:3,title:’Community Day’,date:’2025-07-15′,location:’Central Park’,desc:’Family-friendly activities.’}
],
gallery:{items:[
{src:’https://via.placeholder.com/800×600.webp?text=Event+1′,alt:’Event 1′,cat:’Competitions’},
{src:’https://via.placeholder.com/800×1200.webp?text=Workshop’,alt:’Workshop’,cat:’Workshops’},
{src:’https://via.placeholder.com/800×800.webp?text=Community’,alt:’Community’,cat:’Community’},
{src:’https://via.placeholder.com/800×500.webp?text=Competition+2′,alt:’Competition 2′,cat:’Competitions’},
{src:’https://via.placeholder.com/800×600.webp?text=Community+2′,alt:’Community 2′,cat:’Community’},
{src:’https://via.placeholder.com/800×900.webp?text=Workshop+2′,alt:’Workshop 2′,cat:’Workshops’}
]},
contact:{address:’123 Federation St, City’,email:’info@federation.example’,phone:’+995 32 2 345 678′}
},
ka: {
siteTitle: ‘ფედერაცია’,
nav: {home:’მთავარი’, about:’ჩვენ შესახებ’, events:’ღონისძიებები’, gallery:’გალერეა’, contact:’კონტაქტი’},
home:{
h1:’კეთილი იყოს თქვენი მობრძანება ფედერაციაში’,
sub:’ვაერთიანებთ საზოგადოებას სპორტის, კულტურისა და განათლების საშუალებით. შეუერთდით ჩვენს ღონისძიებებს.’,
bullets:[‘ეროვნული დაფარვა’,’საზოგადოებრივი პროგრამები’,’ტრანსპარანტული მმართველობა’],
cta1:’მითითებები’, cta2:’შემოგვიერთდი ღონისძიებაზე’
},
about:{mission:’ჩვენი მისიაა …’, vision:’ჩვენი ხედვაა …’, history:’დაარსდა 19XX წელს…’},
events:[
{id:1,title:’გაზაფხულის ჩემპიონატი’,date:’2025-05-20′,location:’სპორტის დარბაზი’,desc:’ქვეყნის საუკეთესო მონაწილეები.’},
{id:2,title:’მასწავლებლების ტრენინგი’,date:’2025-06-10′,location:’კონგრეს ჰოლ’,desc:’კომპეტენციების გაუმჯობესება.’},
{id:3,title:’საზოგადოებრივი დღე’,date:’2025-07-15′,location:’ცენტრალური პარკი’,desc:’ოჯახური ივენთი.’}
],
gallery:{items:[
{src:’https://via.placeholder.com/800×600.webp?text=ღონისძიება+1′,alt:’ღონისძიება 1′,cat:’Competitions’},
{src:’https://via.placeholder.com/800×1200.webp?text=სამუშაოშოპი’,alt:’სამუშაოშოპი’,cat:’Workshops’},
{src:’https://via.placeholder.com/800×800.webp?text=საზოგადოება’,alt:’საზოგადოება’,cat:’Community’},
{src:’https://via.placeholder.com/800×500.webp?text=ჩემპიონატი+2′,alt:’ჩემპიონატი 2′,cat:’Competitions’},
{src:’https://via.placeholder.com/800×600.webp?text=საზოგადოება+2′,alt:’საზოგადოება 2′,cat:’Community’},
{src:’https://via.placeholder.com/800×900.webp?text=სამუშაოშოპი+2′,alt:’სამუშაოშოპი 2′,cat:’Workshops’}
]},
contact:{address:’123 ფედერაციის ვ.’,email:’info@federation.example’,phone:’+995 32 2 345 678′}
}
};
// — Helper: update document language attribute & fonts —
function setLangAttr(lang){
document.documentElement.lang = lang === ‘ka’ ? ‘ka’ : ‘en’;
// Toggle header nav links to proper slugs
document.querySelectorAll(‘#main-nav a’).forEach(a=>{
const slug = a.dataset.slug;
a.href = `/${lang}/${slug === ‘home’ ? ” : slug}`;
});
document.getElementById(‘ka-btn’).setAttribute(‘aria-pressed’, lang===’ka’);
document.getElementById(‘en-btn’).setAttribute(‘aria-pressed’, lang===’en’);
}
// — Router render functions —
function render(){
state.lang = langFromPath();
setLangAttr(state.lang);
// derive page from pathname
const p = location.pathname.split(‘/’).filter(Boolean);
const page = p[1] || ‘home’;
state.page = page;
const content = CONTENT[state.lang];
document.getElementById(‘site-title’).textContent = content.siteTitle;
document.title = content.siteTitle + ‘ — ‘ + (content.nav[page] || content.nav.home);
const main = document.getElementById(‘app’);
main.innerHTML = ”;
if(page===’home’) return main.appendChild(renderHome(content));
if(page===’about’) return main.appendChild(renderAbout(content));
if(page===’events’) return main.appendChild(renderEvents(content));
if(page===’event’) return main.appendChild(renderSingleEvent(content, parseInt(p[2]||p[1]||’1′)));
if(page===’gallery’) return main.appendChild(renderGallery(content));
if(page===’contact’) return main.appendChild(renderContact(content));
// fallback
const el = document.createElement(‘div’); el.innerHTML=`<section class=”container”><h2>404</h2><p>Page not found.</p></section>`; main.appendChild(el);
}
function elFromHTML(html){ const tmp = document.createElement(‘div’); tmp.innerHTML = html.trim(); return tmp.firstElementChild; }
function renderHome(content){
const sec = document.createElement(‘div’);
sec.innerHTML = `
<section class=”hero container” aria-labelledby=”hero-title”>
<div class=”hero-inner”>
<h1 id=”hero-title”>${escapeHtml(content.home.h1)}</h1>
<p>${escapeHtml(content.home.sub)}</p>
<div class=”cta-row”>
<button class=”btn” id=”learn-more”>${escapeHtml(content.home.cta1)}</button>
<button class=”btn secondary” id=”join-event”>${escapeHtml(content.home.cta2)}</button>
</div>
<div style=”margin-top:1rem”>
<h3>${state.lang===’ka’ ? ‘ჩვენ შესახებ (ხილადი)’ : ‘About Federation (teaser)’}</h3>
<ul>
${content.home.bullets.map(b=>`<li>${escapeHtml(b)}</li>`).join(”)}
</ul>
</div>
</div>
<div aria-hidden=”true” style=”background:var(–primary);color:white;border-radius:12px;padding:1rem;display:flex;align-items:center;justify-content:center”>
<div style=”max-width:320px;text-align:center”>
<img src=”https://via.placeholder.com/600×360.webp?text=Federation+Hero” alt=”Federation hero image” style=”width:100%;height:auto;border-radius:8px” loading=”lazy”>
</div>
</div>
</section>
<section class=”container”>
<h2>${state.lang===’ka’ ? ‘მოსალოდნელი ღონისძიებები’ : ‘Upcoming Events’}</h2>
<div class=”events-list” id=”home-events”>
</div>
</section>
<section class=”container”>
<h2>${state.lang===’ka’ ? ‘გალერეა’ : ‘Gallery’}</h2>
<div class=”gallery” id=”home-gallery”></div>
</section>
<section class=”container” style=”text-align:center;padding:2rem;background:var(–muted);border-radius:8px;margin:1rem”>
<h3>${state.lang===’ka’ ? ‘გვსურს თქვენი ჩართვა’ : ‘Get in touch’}</h3>
<p class=”muted”>${state.lang===’ka’ ? ‘დაგვიკავშირდით დეტალებზე’ : ‘Contact us for more information’}</p>
<div style=”margin-top:1rem”><a class=”btn” href=”/${state.lang}/contact”>${state.lang===’ka’ ? ‘კონტაქტი’ : ‘Contact’}</a></div>
</section>
`;
// populate events and gallery with JS for structured layout
setTimeout(()=>{
const eventsEl = sec.querySelector(‘#home-events’);
content.events.slice(0,3).forEach(ev=>{
const d = document.createElement(‘div’); d.className=’event-card’; d.innerHTML = `<strong>${escapeHtml(ev.title)}</strong><div class=”muted”>${escapeHtml(ev.date)} · ${escapeHtml(ev.location)}</div><p>${escapeHtml(ev.desc)}</p><div><a href=”/${state.lang}/events/${ev.id}”>Details</a></div>`; eventsEl.appendChild(d);
});
const gal = sec.querySelector(‘#home-gallery’);
content.gallery.items.slice(0,4).forEach(it=>{ const img = document.createElement(‘img’); img.dataset.src=it.src; img.alt=it.alt; img.loading=’lazy’; img.tabIndex=0; img.addEventListener(‘click’,()=>openLightbox(it.src,it.alt)); img.addEventListener(‘keypress’,(e)=>{ if(e.key===’Enter’) openLightbox(it.src,it.alt); }); /* lazy load: set src */ img.src = it.src; gal.appendChild(img); });
},10);
// CTA buttons actions
sec.querySelector(‘#learn-more’).addEventListener(‘click’,()=>navigate(`/${state.lang}/about`));
sec.querySelector(‘#join-event’).addEventListener(‘click’,()=>navigate(`/${state.lang}/events`));
return sec;
}
function renderAbout(content){
const sec = document.createElement(‘section’); sec.className=’container’;
sec.innerHTML = `
<h1>${escapeHtml(content.nav.about)}</h1>
<div class=”grid-3″>
<div><h3>${state.lang===’ka’ ? ‘მისია’ : ‘Mission’}</h3><p>${escapeHtml(content.about.mission)}</p></div>
<div><h3>${state.lang===’ka’ ? ‘ხედვა’ : ‘Vision’}</h3><p>${escapeHtml(content.about.vision)}</p></div>
<div><h3>${state.lang===’ka’ ? ‘ისტორია’ : ‘History’}</h3><p>${escapeHtml(content.about.history)}</p></div>
</div>
<h2 style=”margin-top:1rem”>${state.lang===’ka’ ? ‘გამგეობა’ : ‘Leadership’}</h2>
<div class=”grid-3″ id=”leadership”>
<!– leadership grid: photo, name, role, bio –>
</div>
<h2 style=”margin-top:1rem”>${state.lang===’ka’ ? ‘დოკუმენტების ჩამოტვირთვა’ : ‘Downloadable Documents’}</h2>
<ul>
<li><a href=”/assets/statute.pdf” download>Statute (PDF)</a></li>
<li><a href=”/assets/annual-report.pdf” download>Annual Report (PDF)</a></li>
</ul>
`;
const leaders = sec.querySelector(‘#leadership’);
const sample = [
{name: state.lang===’ka’? ‘ნინო წულუკიძე’ : ‘Nino T.’, role: state.lang===’ka’? ‘პრეზიდენტი’ : ‘President’, bio: state.lang===’ka’? ‘მოკლე ბიო…’ : ‘Short bio…’},
{name: state.lang===’ka’? ‘ლევან მიქაძე’ : ‘Levan M.’, role: state.lang===’ka’? ‘ტექა დირექტორი’ : ‘Technical Director’, bio: state.lang===’ka’? ‘მოკლე ბიო…’ : ‘Short bio…’}
];
sample.forEach(ld=>{ const d = document.createElement(‘div’); d.innerHTML = `<img src=”https://via.placeholder.com/320×240.webp?text=${encodeURIComponent(ld.name)}” alt=”${escapeHtml(ld.name)}” style=”width:100%;border-radius:8px;margin-bottom:.5rem”><strong>${escapeHtml(ld.name)}</strong><div class=”muted”>${escapeHtml(ld.role)}</div><p>${escapeHtml(ld.bio)}</p>`; leaders.appendChild(d); });
return sec;
}
function renderEvents(content){
const sec = document.createElement(‘section’); sec.className=’container’;
sec.innerHTML = `
<h1>${escapeHtml(content.nav.events)}</h1>
<div style=”margin-bottom:1rem”><button class=”chip” data-filter=”all”>All</button> <button class=”chip” data-filter=”upcoming”>Upcoming</button> <button class=”chip” data-filter=”past”>Past</button></div>
<div id=”events-list”></div>
`;
const list = sec.querySelector(‘#events-list’);
function populate(filter){ list.innerHTML=”;
const now = new Date();
content.events.forEach(ev=>{
const ed = new Date(ev.date);
const isPast = ed < now;
if(filter===’upcoming’ && isPast) return; if(filter===’past’ && !isPast) return;
const card = document.createElement(‘div’); card.className=’event-card’;
card.innerHTML = `<strong>${escapeHtml(ev.title)}</strong><div class=”muted”>${escapeHtml(ev.date)} · ${escapeHtml(ev.location)}</div><p>${escapeHtml(ev.desc)}</p><div><a href=”/${state.lang}/events/${ev.id}”>Details</a></div>`;
list.appendChild(card);
});
}
sec.querySelectorAll(‘.chip’).forEach(b=>b.addEventListener(‘click’,()=>populate(b.dataset.filter)));
populate(‘all’);
return sec;
}
function renderSingleEvent(content,eventId){
const ev = content.events.find(e=>e.id===eventId) || content.events[0];
const sec = document.createElement(‘section’); sec.className=’container’;
sec.innerHTML = `
<h1>${escapeHtml(ev.title)}</h1>
<div class=”muted”>${escapeHtml(ev.date)} · ${escapeHtml(ev.location)}</div>
<p>${escapeHtml(ev.desc)}</p>
<h3>${state.lang===’ka’ ? ‘გრაფიკი’ : ‘Schedule’}</h3>
<ul><li>10:00 — Opening</li><li>12:00 — Session</li><li>15:00 — Finals</li></ul>
<div style=”margin-top:1rem”><button class=”btn” id=”register”>${state.lang===’ka’ ? ‘რეგისტრაცია’ : ‘Register’}</button></div>
<div style=”margin-top:1rem”>Share: <a href=”#” onclick=”return false;”>Twitter</a> · <a href=”#” onclick=”return false;”>Facebook</a></div>
<div id=”map” style=”height:220px;background:#eee;border-radius:8px;margin-top:1rem;display:flex;align-items:center;justify-content:center”>[Map placeholder]</div>
`;
// Event structured data (simple)
const schema = {
‘@context’:’https://schema.org’,
‘@type’:’Event’,
‘name’: ev.title,
‘startDate’: ev.date,
‘location’: { ‘@type’:’Place’, ‘name’: ev.location },
‘description’: ev.desc
};
let script = document.getElementById(‘event-schema’); if(script) script.remove();
script = document.createElement(‘script’); script.type=’application/ld+json’; script.id=’event-schema’; script.textContent = JSON.stringify(schema);
document.head.appendChild(script);
sec.querySelector(‘#register’).addEventListener(‘click’,()=>{ alert(state.lang===’ka’ ? ‘თქვენ წარმატებით დარეგისტრირდით (იმიტაცია)’ : ‘Registered (demo)’); });
return sec;
}
function renderGallery(content){
const sec = document.createElement(‘section’); sec.className=’container’;
sec.innerHTML = `<h1>${escapeHtml(content.nav.gallery)}</h1><div class=”masonry” id=”masonry”></div>`;
const m = sec.querySelector(‘#masonry’);
content.gallery.items.forEach(it=>{
const d = document.createElement(‘div’); d.className=’masonry-item’; d.innerHTML = `<img src=”${it.src}” alt=”${escapeHtml(it.alt)}” loading=”lazy” tabindex=”0″>`; d.querySelector(‘img’).addEventListener(‘click’,()=>openLightbox(it.src,it.alt)); m.appendChild(d);
});
return sec;
}
function renderContact(content){
const sec = document.createElement(‘section’); sec.className=’container’;
sec.innerHTML = `
<h1>${escapeHtml(content.nav.contact)}</h1>
<div style=”display:grid;grid-template-columns:1fr;gap:1rem”>
<form id=”contact-form” aria-label=”Contact form”>
<label>${state.lang===’ka’ ? ‘სახელი’ : ‘Name’}<input name=”name” required></label>
<label>${state.lang===’ka’ ? ‘ელ-ფოსტა’ : ‘Email’}<input name=”email” type=”email” required></label>
<label>${state.lang===’ka’ ? ‘ტელეფონი’ : ‘Phone’}<input name=”phone”></label>
<label>${state.lang===’ka’ ? ‘შეტყობინება’ : ‘Message’}<textarea name=”message” rows=”4″></textarea></label>
<label style=”display:flex;gap:.5rem;align-items:center”><input type=”checkbox” name=”gdpr”> <span class=”muted”>${state.lang===’ka’ ? ‘ვეთანხმები მონაცემთა დამუშავებას’ : ‘I consent to data processing’}</span></label>
<!– reCAPTCHA integration placeholder: insert server-side/actual reCAPTCHA widget here –>
<div style=”margin-top:.5rem”><button type=”submit”>${state.lang===’ka’ ? ‘გაგზავნა’ : ‘Send’}</button></div>
</form>
<div>
<h3>${state.lang===’ka’ ? ‘მისამართი’ : ‘Address’}</h3>
<p>${escapeHtml(content.contact.address)}</p>
<p><strong>${escapeHtml(content.contact.phone)}</strong></p>
<p><a href=”mailto:${content.contact.email}”>${escapeHtml(content.contact.email)}</a></p>
<div style=”margin-top:1rem;background:#fff;border:1px solid var(–border);padding:8px;border-radius:8px”>[Map embed placeholder]</div>
</div>
</div>
`;
sec.querySelector(‘#contact-form’).addEventListener(‘submit’,e=>{
e.preventDefault();
// Normally: validate + send to server + reCAPTCHA. Here: simulate success and accessible message.
alert(state.lang===’ka’ ? ‘გაუგზავნა — წარმატებით’ : ‘Message sent — success (demo)’);
});
return sec;
}
// navigation helper uses history API and keeps language persist
function navigate(path){ history.pushState({},”,path); render(); }
window.addEventListener(‘popstate’,render);
// header language buttons
document.getElementById(‘ka-btn’).addEventListener(‘click’,()=>{ const p = location.pathname.split(‘/’).filter(Boolean); p[0]=’ka’; if(!p[1]) p[1]=”; const newp = ‘/’+p.join(‘/’); navigate(‘/ka/’+(p[1]||”)); });
document.getElementById(‘en-btn’).addEventListener(‘click’,()=>{ const p = location.pathname.split(‘/’).filter(Boolean); p[0]=’en’; navigate(‘/en/’+(p[1]||”)); });
// make nav links use client router
document.addEventListener(‘click’,e=>{
const a = e.target.closest(‘a’); if(!a) return; const href = a.getAttribute(‘href’)||”; if(href.startsWith(‘http’)||href.startsWith(‘mailto:’)||href.startsWith(‘/assets’)) return; // allow external and asset links
e.preventDefault(); navigate(href);
});
// lightbox
function openLightbox(src,alt){ const lb = document.getElementById(‘lightbox’); document.getElementById(‘lb-img’).src = src; document.getElementById(‘lb-img’).alt = alt; lb.style.display=’flex’; lb.focus(); }
document.getElementById(‘lb-close’).addEventListener(‘click’,()=>{ document.getElementById(‘lightbox’).style.display=’none’; });
// small helpers
function escapeHtml(s){ if(!s) return ”; return String(s).replaceAll(‘&’,’&’).replaceAll(‘<‘,’<’).replaceAll(‘>’,’>’); }
// initial year
document.getElementById(‘year’).textContent = new Date().getFullYear();
// SEO: sitemap (simple representation) – provide as string for server admin to write as /sitemap.xml
const sitemap = `<?xml version=”1.0″ encoding=”UTF-8″?>\n<urlset xmlns=\”http://www.sitemaps.org/schemas/sitemap/0.9\”>\n <url><loc>https://example.org/en/</loc></url>\n <url><loc>https://example.org/ka/</loc></url>\n <url><loc>https://example.org/en/about</loc></url>\n <url><loc>https://example.org/en/events</loc></url>\n <url><loc>https://example.org/en/gallery</loc></url>\n <url><loc>https://example.org/en/contact</loc></url>\n</urlset>`;
// console.log(‘Sitemap (paste to /sitemap.xml):’,sitemap);
// initial render
render();
</script>
</body>
</html>