🔍 ESC
↑ ↑ ↓ ↓ ← → ← → B A
AETHERION CHEAT CODE ACTIVATED
click anywhere to close
Press ⌘K or Ctrl+K to open command palette
ΔΙΑΘΕΣΙΜΟΣ
↑
💬
A
Aetherion Assistant
Online
Γεια! 👋 Είμαι ο AI assistant της Aetherion Projects. Μπορώ να απαντήσω για υπηρεσίες, τιμές, timelines και projects. Τι θέλεις να μάθεις;

Λογαριασμός

Γεια σου!

'; if(ch) ch.textContent=ed.value.length+' chars'; } window.pgUpdate=upd; window.pgReset=function(){ed.value=DEF;upd();}; window.pgSnippet=function(k){ed.value=SN[k]||DEF;upd();}; ed.addEventListener('keydown',function(e){ if((e.ctrlKey||e.metaKey)&&e.key==='Enter'){e.preventDefault();upd();} if(e.key==='Tab'){e.preventDefault();var s=ed.selectionStart;ed.value=ed.value.slice(0,s)+' '+ed.value.slice(ed.selectionEnd);ed.selectionStart=ed.selectionEnd=s+2;} }); ed.value=DEF; upd(); })(); /* ══ SERVER LOGS ════════════════════════════════════════════════════ */ (function(){ var out=document.getElementById('log-output'); if(!out) return; var C={'GET':'#4ade80','POST':'#818cf8','PUT':'#fbbf24','DELETE':'#f87171','200':'#4ade80','201':'#34d399','204':'#60a5fa','[WS]':'#c084fc','[DB]':'#60a5fa','[CRON]':'#fb923c'}; var R=[ ['GET','/api/v2/devices','200','18ms'],['POST','/api/v2/location','201','12ms'], ['GET','/api/v2/fleet','200','24ms'],['GET','/api/v2/alerts','200','8ms'], ['POST','/api/v2/auth/token','200','31ms'],['PUT','/api/v2/devices/3421','200','14ms'], ['[WS]','device:3421 connected','',''],['[WS]','device:1189 location update','',''], ['[DB]','SELECT devices WHERE active=true','','4ms'],['[CRON]','heartbeat 2.147 devices','',''], ['GET','/api/v2/map/tiles','200','6ms'],['DELETE','/api/v2/sessions/old','204','9ms'], ['POST','/api/v2/webhooks','200','22ms'],['[WS]','fleet:DE-Munich 14 vehicles','',''], ]; function addLog(){ var e=R[Math.floor(Math.random()*R.length)]; var t=new Date().toLocaleTimeString('en',{hour12:false}); var d=document.createElement('div'); d.style='border-bottom:1px solid rgba(255,255,255,.03);padding:.1rem 0;display:flex;gap:.6rem;overflow:hidden'; d.innerHTML=''+t+'' +''+e[0]+'' +''+e[1]+'' +(e[2]?''+e[2]+'':'') +(e[3]?''+e[3]+'':''); out.appendChild(d); if(out.children.length>40) out.removeChild(out.firstChild); out.scrollTop=out.scrollHeight; } setTimeout(function(){for(var i=0;i<5;i++)addLog();setInterval(addLog,1000+Math.random()*600);},800); function jitter(){ var api=20+Math.floor(Math.random()*20),db=8+Math.floor(Math.random()*12); var dev=2140+Math.floor(Math.random()*20),ws=840+Math.floor(Math.random()*20); function s(id,v){var e=document.getElementById(id);if(e)e.textContent=v;} function w(id,pct){var e=document.getElementById(id);if(e)e.style.width=pct+'%';} s('pm-api',api+'ms');s('pm-db',db+'ms'); s('pm-dev',dev.toLocaleString('el-GR'));s('pm-ws',ws); w('pm-api-bar',Math.max(40,100-api*2));w('pm-db-bar',Math.max(60,100-db*3)); w('pm-dev-bar',dev/3000*100);w('pm-ws-bar',ws/2000*100); } setInterval(jitter,2000);setTimeout(jitter,1500); })(); /* ══ CUSTOM CURSOR ═══════════════════════════════════════════════════ */ (function(){ var dot = document.getElementById('cursor-dot'); var ring = document.getElementById('cursor-ring'); if(!dot||!ring||window.matchMedia('(hover:none)').matches) return; var dx=0,dy=0,rx=0,ry=0; window.addEventListener('mousemove',function(e){ dx=e.clientX; dy=e.clientY; dot.style.transform='translate(calc('+dx+'px - 50%), calc('+dy+'px - 50%))'; },{passive:true}); // ring removed // expand effects removed })(); /* ══ SOCIAL PROOF TOASTS (disabled) ════════════════════════════════ */ /* DISABLED (function(){ var container = document.getElementById('toast-container'); if(!container) return; var visitors = [ {name:'Μ. Παπαδόπουλος', city:'Αθήνα 🇬🇷', action:'είδε το Portfolio', color:'#818cf8'}, {name:'Klaus M.', city:'München 🇩🇪', action:'ζήτησε προσφορά', color:'#fbbf24'}, {name:'Γ. Κωνσταντίνου', city:'Θεσσαλονίκη 🇬🇷', action:'διάβασε για FahrTrack', color:'#E03030'}, {name:'Nikos A.', city:'Λευκωσία 🇨🇾', action:'άνοιξε το Contact', color:'#4ade80'}, {name:'Thomas B.', city:'Wien 🇦🇹', action:'χρησιμοποίησε το Terminal', color:'#c084fc'}, {name:'Σ. Αλεξάνδρου', city:'Πάτρα 🇬🇷', action:'είδε τις τιμές', color:'#fb923c'}, ]; var i=0; function showToast(){ var v=visitors[i%visitors.length]; i++; var t=document.createElement('div'); t.className='toast'; t.innerHTML= '
👤
'+ '
'+ '
'+v.name+'
'+ '
'+v.city+' · '+v.action+'
'+ '
'; container.appendChild(t); requestAnimationFrame(function(){ requestAnimationFrame(function(){ t.classList.add('show'); }); }); setTimeout(function(){ t.classList.remove('show'); setTimeout(function(){ if(t.parentNode) t.parentNode.removeChild(t); },400); }, 4500); } // Start after 3s, then every 8s setTimeout(showToast, 3000); setInterval(showToast, 8000); })(); /* ══ LIVE TYPING DEMO (simplified) ══════════════════════════════ */ (function(){ var code = document.getElementById('live-demo-code'); if(!code) return; var lines = [ 'const site = await buildSite({', ' stack: ["React", "Node", "Stripe"],', ' lighthouse: 98,', ' deploy: "netlify"', '});', 'await site.deploy(); // ✓ live!', ]; var li=0; var obs=new IntersectionObserver(function(entries){ if(!entries[0].isIntersecting) return; obs.disconnect(); (function next(){ if(li>=lines.length) return; var d=document.createElement('div'); d.innerHTML=lines[li++]; code.appendChild(d); if(li'+cmd.icon+''+ ''+cmd.label+''+ ''+cmd.sub+''; div.addEventListener('click', function(){ execute(cmd); }); div.addEventListener('mouseenter', function(){ selected=idx; updateSelected(); }); return div; } function updateSelected(){ results.querySelectorAll('.cmd-item').forEach(function(el,i){ el.classList.toggle('selected', i===selected); }); } function execute(cmd){ close(); setTimeout(function(){ if(cmd.r){ if(window.showPage) window.showPage(cmd.r); window.scrollTo(0,0); } else if(cmd.action==='whatsapp'){ window.open('https://wa.me/30398371244','_blank'); } else if(cmd.action==='email'){ window.location.href='mailto:info@aetherionprojects.cloud'; } else if(cmd.action==='dark'){ if(window.toggleDark) window.toggleDark(); } else if(cmd.action==='terminal'){ if(window.showPage) window.showPage('home'); setTimeout(function(){ var t=document.getElementById('term-input'); if(t){ t.scrollIntoView({behavior:'smooth',block:'center'}); t.focus(); } },500); } }, 100); } // Keyboard shortcuts document.addEventListener('keydown', function(e){ if((e.metaKey||e.ctrlKey) && e.key==='k'){ e.preventDefault(); open(); return; } if(!backdrop.classList.contains('open')) return; if(e.key==='Escape'){ close(); return; } if(e.key==='ArrowDown'){ e.preventDefault(); selected=Math.min(selected+1,filtered.length-1); updateSelected(); } if(e.key==='ArrowUp'){ e.preventDefault(); selected=Math.max(selected-1,0); updateSelected(); } if(e.key==='Enter'){ if(filtered[selected]) execute(filtered[selected]); } }); input.addEventListener('input', function(){ var q=input.value.toLowerCase(); if(!q){ render(commands); return; } render(commands.filter(function(c){ return c.label.toLowerCase().includes(q) || c.sub.toLowerCase().includes(q); })); }); backdrop.addEventListener('click', function(e){ if(e.target===backdrop) close(); }); })(); /* ══ CONFETTI 🎉 ═════════════════════════════════════════════════════ */ window.launchConfetti = function(x, y){ var colors=['#818cf8','#c084fc','#4ade80','#fb923c','#f472b6','#fbbf24','#60a5fa']; for(var i=0;i<60;i++){ (function(i){ var el=document.createElement('div'); el.className='confetti-piece'; var color=colors[Math.floor(Math.random()*colors.length)]; el.style.cssText='left:'+(x||50)+'%;top:'+(y||0)+'px;background:'+color+ ';border-radius:'+(Math.random()>.5?'50%':'2px')+ ';animation-duration:'+(Math.random()*1.5+1)+'s'+ ';animation-delay:'+(Math.random()*.5)+'s'; document.body.appendChild(el); setTimeout(function(){ el.remove(); }, 2500); })(i); } }; /* ══ MOUSE TRAIL 🌟 ══════════════════════════════════════════════════ */ (function(){ var colors=['#6366f1','#818cf8','#c084fc','#4ade80','#f472b6']; var ci=0; var lastX=0,lastY=0; window.addEventListener('mousemove',function(e){ if(Math.abs(e.clientX-lastX)<25 && Math.abs(e.clientY-lastY)<25) return; lastX=e.clientX; lastY=e.clientY; // Only on dark sections var el=document.elementFromPoint(e.clientX,e.clientY); var dark=false; for(var k=el,d=0;k&&d<5;k=k.parentElement,d++){ var bg=window.getComputedStyle(k).backgroundColor; if(bg&&(bg.includes('17, 17')||bg.includes('10, 10')||bg.includes('12, 12')||bg.includes('13, 13'))){ dark=true;break; } } if(!dark) return; var dot=document.createElement('div'); dot.className='trail-dot'; dot.style.cssText='left:'+e.clientX+'px;top:'+e.clientY+'px;background:'+colors[ci%colors.length]+';opacity:.7;animation-duration:'+(Math.random()*.3+.4)+'s'; ci++; document.body.appendChild(dot); setTimeout(function(){dot.remove();},700); },{passive:true}); })(); /* ══ KONAMI CODE ↑↑↓↓←→←→BA ══════════════════════════════════════ */ (function(){ var seq=[38,38,40,40,37,39,37,39,66,65]; var pos=0; document.addEventListener('keydown',function(e){ if(e.keyCode===seq[pos]){ pos++; if(pos===seq.length){ pos=0; var ov=document.getElementById('konami-overlay'); if(!ov) return; ov.classList.add('show'); window.launchConfetti && window.launchConfetti(50,0); // Matrix rain on the konami canvas var wrap=document.getElementById('konami-canvas-wrap'); if(wrap){ var c=document.createElement('canvas'); c.width=300;c.height=120; c.style.cssText='display:block;margin:0 auto;opacity:.6'; wrap.innerHTML=''; wrap.appendChild(c); var ctx=c.getContext('2d'); var chars='アイウエオΑΒΓΔ0101'; var cols=Math.floor(c.width/14); var drops=Array(cols).fill(1); var iv=setInterval(function(){ ctx.fillStyle='rgba(10,0,20,.15)'; ctx.fillRect(0,0,c.width,c.height); ctx.fillStyle='#c084fc'; ctx.font='13px monospace'; drops.forEach(function(y,i){ ctx.fillText(chars[Math.floor(Math.random()*chars.length)],i*14,y*14); if(y*14>c.height && Math.random()>.95) drops[i]=0; drops[i]++; }); },60); setTimeout(function(){ clearInterval(iv); },6000); } } } else { pos=0; } }); })(); /* ══ CONTACT FORM CONFETTI ═══════════════════════════════════════════ */ (function(){ var form=document.getElementById('contact-form'); if(!form) return; form.addEventListener('submit',function(e){ setTimeout(function(){ window.launchConfetti && window.launchConfetti(50,0); },400); }); // Also on chat send var chatSend=document.getElementById('chat-send'); if(chatSend){ chatSend.addEventListener('click',function(){ window.launchConfetti && window.launchConfetti(Math.random()*80+10,200); }); } })(); /* ══ TIME-BASED GREETING IN HERO ════════════════════════════════════ */ (function(){ var el=document.getElementById('hero-greeting'); if(!el) return; var h=new Date(new Date().toLocaleString('en',{timeZone:'Europe/Athens'})).getHours(); var greet= h<5?'🌙 Καλά ξημερώματα' : h<12?'☀️ Καλημέρα' : h<17?'🌤 Καλό απόγευμα' : h<21?'🌆 Καλό βράδυ' : '🌙 Καλό βράδυ'; el.textContent=greet; })(); var API_BASE = (function(){ var h = window.location.hostname; return (h==='localhost'||h==='127.0.0.1') ? 'http://localhost:3001/api/v1' : 'https://api.aetherionprojects.cloud/api/v1'; })(); async function apiFetch(method, path, body){ var res = await fetch(API_BASE+path,{ method: method, credentials: 'include', headers: {'Content-Type':'application/json'}, body: body ? JSON.stringify(body) : undefined }); var json = await res.json(); if(!json.success) throw new Error(json.error?.message||'Σφάλμα'); return json.data; } function showErr(id, msg){ var el=document.getElementById(id); el.textContent=msg; el.style.display='block'; } function hideErr(id){ document.getElementById(id).style.display='none'; } function showOk(id, msg){ var el=document.getElementById(id); el.textContent=msg; el.style.display='block'; } function pwStrength(pw){ var score = 0; if(pw.length>=8) score++; if(pw.length>=12) score++; if(/[A-Z]/.test(pw)) score++; if(/[0-9]/.test(pw)) score++; if(/[^a-zA-Z0-9]/.test(pw)) score++; var bar = document.getElementById('pw-bar'); if(!bar)return; var cols=['#ef4444','#f97316','#eab308','#22c55e','#16a34a']; var widths=['20%','40%','60%','80%','100%']; bar.style.background = cols[Math.min(score,4)]; bar.style.width = widths[Math.min(score,4)]; } var _user=JSON.parse(localStorage.getItem('ae_user')||'null'); if(!_user){location.href='/login.html';} function doLogout(){localStorage.removeItem('ae_user');localStorage.removeItem('ae_access');localStorage.removeItem('ae_domain_cart');location.href='/login.html';} (function(){if(!_user)return;var av=document.getElementById('sb-av'),nm=document.getElementById('sb-name'),em=document.getElementById('sb-email');if(av)av.textContent=(_user.name||_user.firstName||_user.email||'?').charAt(0).toUpperCase();if(nm)nm.textContent=_user.name||(_user.firstName?_user.firstName+' '+(_user.lastName||''):_user.email)||'—';if(em)em.textContent=_user.email||'—';})(); async function apiFetch(m,p,b){var h={'Content-Type':'application/json'};var t=localStorage.getItem('ae_access');if(t)h.Authorization='Bearer '+t;var r=await fetch((location.hostname==='localhost'?'http://localhost:3001':'https://api.aetherionprojects.cloud')+'/api/v1'+p,{method:m,credentials:'include',headers:h,body:b?JSON.stringify(b):undefined});var j=await r.json();if(!j.success)throw new Error(j.error?.message||'Σφάλμα');return j.data;} /* ─── Mock data ──────────────────────────────────────────── */ var MOCK = { domains: [ {fqdn:'aetherionprojects.cloud', expiresAt:'2027-09-15', autoRenew:true, status:'ACTIVE'}, {fqdn:'fahrtrack.de', expiresAt:'2025-11-01', autoRenew:true, status:'ACTIVE'}, {fqdn:'gokok.gr', expiresAt:'2025-10-20', autoRenew:false, status:'ACTIVE'}, {fqdn:'avconsulting.gr', expiresAt:'2025-12-31', autoRenew:true, status:'ACTIVE'}, ], orders: [ {id:'ord_1', items:[{fqdn:'aetherionprojects.cloud'}], totalAmount:'18.99', status:'COMPLETED', createdAt:'2024-09-15T10:02:00Z'}, {id:'ord_4', items:[{fqdn:'avconsulting.gr'}], totalAmount:'5.99', status:'PENDING', createdAt:'2025-04-10T11:00:00Z'}, {id:'ord_6', items:[{fqdn:'fahrtrack.de'}], totalAmount:'8.99', status:'COMPLETED', createdAt:'2024-11-01T12:01:00Z'}, {id:'ord_7', items:[{fqdn:'gokok.gr'}], totalAmount:'5.99', status:'COMPLETED', createdAt:'2025-02-14T10:00:00Z'}, ], invoices: [ {number:'ΑΠΥ-2024-001', domain:'aetherionprojects.cloud', amount:'18.99', date:'2024-09-15'}, {number:'ΑΠΥ-2024-002', domain:'fahrtrack.de', amount:'8.99', date:'2024-11-01'}, {number:'ΑΠΥ-2025-001', domain:'gokok.gr', amount:'5.99', date:'2025-02-14'}, ], }; /* ─── Init ───────────────────────────────────────────────── */ document.addEventListener('DOMContentLoaded', function() { setGreeting(); setTime(); setInterval(setTime, 60000); loadDashboard(); }); function setGreeting() { var h = new Date().getHours(); var g = h < 5 ? 'Καλό βράδυ' : h < 12 ? 'Καλημέρα' : h < 17 ? 'Καλό απόγευμα' : h < 21 ? 'Καλησπέρα' : 'Καλό βράδυ'; var u = JSON.parse(localStorage.getItem('ae_user')||'{}'); var name = u.firstName || u.name || ''; document.getElementById('greeting').textContent = g + (name ? ', ' + name + '!' : '!'); } function setTime() { document.getElementById('dash-time').textContent = new Date().toLocaleString('el-GR',{weekday:'long',day:'2-digit',month:'long',hour:'2-digit',minute:'2-digit'}); } async function loadDashboard() { var data = MOCK; try { var [doms, ords, invs] = await Promise.all([ apiFetch('GET','/account/domains'), apiFetch('GET','/account/orders'), apiFetch('GET','/account/invoices'), ]); data = {domains:doms, orders:ords, invoices:invs}; } catch(e) {} renderKPIs(data); renderAlerts(data); renderDomains(data.domains); renderActivity(data.orders); renderInvoices(data.invoices); renderBilling(data.orders); } /* ─── KPIs ───────────────────────────────────────────────── */ function renderKPIs(data) { var spent = data.orders.filter(function(o){return o.status!=='PENDING';}).reduce(function(s,o){return s+(+o.totalAmount);},0); sv('kp-domains', data.domains.length); sv('kp-orders', data.orders.filter(function(o){return o.status==='COMPLETED';}).length); sv('kp-invoices', data.invoices.length); sv('kp-spent', '€'+spent.toFixed(0)); } /* ─── Alerts ─────────────────────────────────────────────── */ function renderAlerts(data) { // Expiring soon (≤30 days) var expiring = data.domains.filter(function(d){ return daysLeft(d.expiresAt) <= 30 && daysLeft(d.expiresAt) >= 0; }).sort(function(a,b){ return daysLeft(a.expiresAt)-daysLeft(b.expiresAt); }); if (expiring.length) { var al = document.getElementById('exp-alert'); al.style.display = 'flex'; document.getElementById('exp-alert-t').textContent = expiring.length === 1 ? '⚠ ' + expiring[0].fqdn + ' λήγει σε ' + daysLeft(expiring[0].expiresAt) + ' μέρες' : '⚠ ' + expiring.length + ' domains λήγουν σύντομα'; document.getElementById('exp-alert-d').textContent = expiring.map(function(d){ return d.fqdn + ' (' + daysLeft(d.expiresAt) + 'μ.)'; }).join(' · '); } // Pending payments var pending = data.orders.filter(function(o){ return o.status==='PENDING'; }); if (pending.length) { var pa = document.getElementById('pay-alert'); pa.style.display = 'flex'; document.getElementById('pay-alert-d').textContent = pending.map(function(o){ return (o.items||[])[0]?.fqdn || o.id; }).join(', ') + ' · €' + pending.reduce(function(s,o){return s+(+o.totalAmount);},0).toFixed(2); } } /* ─── Domains list ───────────────────────────────────────── */ function renderDomains(domains) { var el = document.getElementById('dom-list'); if (!domains.length) { el.innerHTML = '
Δεν υπάρχουν domains
'; return; } var sorted = domains.slice().sort(function(a,b){ return daysLeft(a.expiresAt)-daysLeft(b.expiresAt); }); el.innerHTML = sorted.slice(0,5).map(function(d) { var days = daysLeft(d.expiresAt); var cls = days < 0 ? 'days-crit' : days <= 14 ? 'days-crit' : days <= 30 ? 'days-warn' : 'days-ok'; var pct = Math.min(100, Math.max(2, Math.round((days/365)*100))); var barC = days <= 14 ? '#ef4444' : days <= 30 ? '#f59e0b' : '#22c55e'; return '' +'
' +'
' +''+d.fqdn+'' +(d.autoRenew?'AR':'') +'
' +'
' +'
' +''+( days < 0 ? 'Έληξε' : days+'μ.')+'' +'
'; }).join(''); } /* ─── Activity feed ──────────────────────────────────────── */ function renderActivity(orders) { var el = document.getElementById('act-list'); var events = orders.slice().sort(function(a,b){ return new Date(b.createdAt)-new Date(a.createdAt); }); if (!events.length) { el.innerHTML = '
Δεν υπάρχει δραστηριότητα
'; return; } el.innerHTML = events.slice(0,5).map(function(o) { var icon = {COMPLETED:'✅',PAID:'💳',PENDING:'⏳',FAILED:'❌'}[o.status]||'📦'; var bg = {COMPLETED:'#f0fdf4',PAID:'#eff6ff',PENDING:'#fffbeb',FAILED:'#fff0f0'}[o.status]||'#f7f7f7'; var fqdn = (o.items||[])[0]?.fqdn || o.id; return '
' +'
'+icon+'
' +'
' +'
'+({COMPLETED:'Καταχώρηση ολοκληρώθηκε',PAID:'Πληρωμή ελήφθη',PENDING:'Αναμένει πληρωμή',FAILED:'Απέτυχε'}[o.status]||'Παραγγελία')+'
' +'
'+fqdn+' · €'+parseFloat(o.totalAmount).toFixed(2)+' · '+relTime(o.createdAt)+'
' +'
' +(o.status==='PENDING'?'Πλήρωσε →':'') +'
'; }).join(''); } /* ─── Invoices ───────────────────────────────────────────── */ function renderInvoices(invoices) { var el = document.getElementById('inv-list'); if (!invoices.length) { el.innerHTML = '
Δεν υπάρχουν τιμολόγια
'; return; } el.innerHTML = invoices.slice(0,3).map(function(inv) { return '
' +'
🧾
' +'
' +'
'+inv.number+'
' +'
'+inv.domain+' · '+new Date(inv.date).toLocaleDateString('el-GR')+'
' +'
' +'€'+parseFloat(inv.amount).toFixed(2)+'' +'
'; }).join(''); } /* ─── Billing summary ────────────────────────────────────── */ function renderBilling(orders) { var el = document.getElementById('billing-summary'); var done = orders.filter(function(o){return o.status!=='PENDING';}); var pend = orders.filter(function(o){return o.status==='PENDING';}); var total = done.reduce(function(s,o){return s+(+o.totalAmount);},0); var pendAmt = pend.reduce(function(s,o){return s+(+o.totalAmount);},0); var yr = new Date().getFullYear(); var yrAmt = done.filter(function(o){return o.createdAt.startsWith(yr);}).reduce(function(s,o){return s+(+o.totalAmount);},0); el.innerHTML = [ ['Σύνολο δαπανών', '€'+total.toFixed(2), '#111'], ['Φέτος ('+yr+')', '€'+yrAmt.toFixed(2), '#6366f1'], ['Εκκρεμείς', pend.length ? '€'+pendAmt.toFixed(2) : '—', pend.length?'#d97706':'var(--dim)'], ['ΦΠΑ (24%) ~ σύνολο','€'+(total*.24/(1.24)).toFixed(2),'var(--dim)'], ].map(function(r){ return '
' +''+r[0]+'' +''+r[1]+'' +'
'; }).join('') +'Δες πλήρες ιστορικό →'; } /* ─── Helpers ────────────────────────────────────────────── */ function sv(id,v){var e=document.getElementById(id);if(e)e.textContent=v;} function daysLeft(d){return Math.ceil((new Date(d)-new Date())/86400000);} function relTime(d){ var diff=Math.floor((Date.now()-new Date(d))/1000); if(diff<60)return 'μόλις τώρα'; if(diff<3600)return Math.floor(diff/60)+'λ. πριν'; if(diff<86400)return Math.floor(diff/3600)+'ω. πριν'; if(diff<2592000)return Math.floor(diff/86400)+'μ. πριν'; return Math.floor(diff/2592000)+'μήνες πριν'; }