montana/Русский/Сайт/montana_explorer.html

796 lines
31 KiB
HTML
Raw Permalink Normal View History

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Montana Network Explorer</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Courier New', monospace;
background: #0a0a0a;
color: #d4af37;
padding: 20px;
line-height: 1.6;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
header {
text-align: center;
margin-bottom: 40px;
padding-bottom: 20px;
border-bottom: 1px solid #d4af37;
}
h1 {
font-size: 2.5em;
letter-spacing: 8px;
margin-bottom: 10px;
}
h2 {
font-size: 1.5em;
margin: 30px 0 15px 0;
letter-spacing: 3px;
}
.network-status {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.card {
background: #111;
border: 1px solid #d4af37;
padding: 20px;
position: relative;
}
.card h3 {
font-size: 0.9em;
letter-spacing: 2px;
color: #999;
margin-bottom: 10px;
}
.card .value {
font-size: 2em;
font-weight: bold;
}
.card .label {
font-size: 0.8em;
color: #666;
margin-top: 5px;
}
.slices {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-bottom: 30px;
}
.slice {
background: #111;
border: 1px solid #d4af37;
padding: 15px;
}
.slice-header {
font-size: 1.2em;
margin-bottom: 10px;
}
.slice-data {
font-size: 0.9em;
color: #999;
}
.progress-bar {
width: 100%;
height: 4px;
background: #333;
margin-top: 8px;
position: relative;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: #ff0000;
transition: width 0.3s;
}
/* Live updating elements - RED */
.card .value,
.slice-data span:last-child,
#network-age-seconds,
#network-age-readable {
color: #ff0000 !important;
}
.nodes {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 15px;
margin-bottom: 30px;
}
.node {
background: #111;
border: 1px solid #d4af37;
padding: 15px;
}
.node.online {
border-color: #00ff00;
}
.node.offline {
border-color: #ff0000;
}
.node-name {
font-size: 1.1em;
margin-bottom: 8px;
}
.node-ip {
font-size: 0.85em;
color: #666;
margin-bottom: 5px;
}
.node-status {
font-size: 0.9em;
margin-top: 8px;
}
.online-indicator {
color: #00ff00;
}
.offline-indicator {
color: #ff0000;
}
.tokenomics {
background: #111;
border: 1px solid #d4af37;
padding: 20px;
margin-bottom: 30px;
}
.tokenomics-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-top: 15px;
}
.token-stat {
border-left: 2px solid #d4af37;
padding-left: 15px;
}
.token-stat .stat-label {
font-size: 0.85em;
color: #999;
margin-bottom: 5px;
}
.token-stat .stat-value {
font-size: 1.3em;
}
footer {
text-align: center;
margin-top: 50px;
padding-top: 20px;
border-top: 1px solid #d4af37;
font-size: 0.9em;
color: #666;
}
.refresh-info {
text-align: center;
font-size: 0.85em;
color: #666;
margin-top: 30px;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>MONTANA</h1>
<div style="font-size: 0.9em; letter-spacing: 3px; color: #999;" id="header-subtitle"></div>
</header>
<div class="network-status">
<div class="card">
<h3 id="label-network-age"></h3>
<div class="value" id="network-age-seconds">0</div>
<div class="label" id="network-age-readable">0d 0h 0m</div>
</div>
<div class="card">
<h3 id="label-tau1-height"></h3>
<div class="value" id="tau1-current">0</div>
<div class="label" id="label-tau1-slices"></div>
</div>
<div class="card">
<h3 id="label-tau2-height"></h3>
<div class="value" id="tau2-current">0</div>
<div class="label" id="label-tau2-slices"></div>
</div>
<div class="card">
<h3 id="label-network-health"></h3>
<div class="value" id="network-health">100%</div>
<div class="label" id="nodes-online-label">5/5 NODES ONLINE</div>
</div>
<div class="card">
<h3 id="label-total-supply"></h3>
<div class="value" id="total-supply">5,000,000</div>
<div class="label" id="label-circulating"></div>
</div>
</div>
<!-- Economics Section -->
<div class="network-status">
<div class="card">
<h3 id="label-second-price"></h3>
<div class="value" id="second-price">1.00</div>
<div class="label" id="label-second-price-unit"></div>
</div>
<div class="card">
<h3 id="label-genesis-forecast"></h3>
<div class="value" id="genesis-forecast">0.00</div>
<div class="label" id="label-genesis-forecast-date">09.01.2027</div>
</div>
<div class="card">
<h3 id="label-fiat-value"></h3>
<div class="value" id="fiat-value">0</div>
<div class="label" id="label-fiat-unit"></div>
</div>
</div>
<h2 id="section-slices"></h2>
<div class="slices">
<div class="slice">
<div class="slice-header">τ₀</div>
<div class="slice-data">
<div><span id="slice-duration"></span>: <span id="tau0-duration-text"></span></div>
<div><span id="slice-current"></span>: <span id="tau0-current">0</span>s</div>
<div><span id="slice-total"></span>: <span id="tau0-height">0</span></div>
<div class="progress-bar">
<div class="progress-fill" id="tau0-progress"></div>
</div>
</div>
</div>
<div class="slice">
<div class="slice-header">τ₁</div>
<div class="slice-data">
<div><span id="slice-duration-1"></span>: <span id="tau1-duration-text"></span></div>
<div><span id="slice-height"></span>: <span id="tau1-height">0</span></div>
<div><span id="slice-progress"></span>: <span id="tau1-progress-text">0</span>/60s</div>
<div class="progress-bar">
<div class="progress-fill" id="tau1-progress"></div>
</div>
</div>
</div>
<div class="slice">
<div class="slice-header">τ₂</div>
<div class="slice-data">
<div><span id="slice-duration-2"></span>: <span id="tau2-duration-text"></span></div>
<div><span id="slice-height-2"></span>: <span id="tau2-height">0</span></div>
<div><span id="slice-progress-2"></span>: <span id="tau2-progress-text">0</span>/600s</div>
<div class="progress-bar">
<div class="progress-fill" id="tau2-progress"></div>
</div>
</div>
</div>
<div class="slice">
<div class="slice-header">τ₃</div>
<div class="slice-data">
<div><span id="slice-duration-3"></span>: <span id="tau3-duration-text"></span></div>
<div><span id="slice-height-3"></span>: <span id="tau3-height">0</span></div>
<div><span id="slice-progress-3"></span>: <span id="tau3-progress-text">0</span>s</div>
<div class="progress-bar">
<div class="progress-fill" id="tau3-progress"></div>
</div>
</div>
</div>
<div class="slice">
<div class="slice-header">τ₄</div>
<div class="slice-data">
<div><span id="slice-duration-4"></span>: <span id="tau4-duration-text"></span></div>
<div><span id="slice-height-4"></span>: <span id="tau4-height">0</span></div>
<div><span id="slice-progress-4"></span>: <span id="tau4-progress-text">0</span>s</div>
<div class="progress-bar">
<div class="progress-fill" id="tau4-progress"></div>
</div>
</div>
</div>
</div>
<h2 id="section-nodes"></h2>
<div class="nodes" id="nodes-container">
<!-- Nodes will be populated by JavaScript -->
</div>
<h2 id="section-tokenomics"></h2>
<div class="tokenomics">
<div class="tokenomics-grid">
<div class="token-stat">
<div class="stat-label" id="label-emission-rate"></div>
<div class="stat-value" id="value-emission-rate"></div>
</div>
<div class="token-stat">
<div class="stat-label" id="label-time-value"></div>
<div class="stat-value" id="value-time-value"></div>
</div>
<div class="token-stat">
<div class="stat-label" id="label-genesis-supply"></div>
<div class="stat-value">5M Ɉ</div>
</div>
<div class="token-stat">
<div class="stat-label" id="label-genesis-holders"></div>
<div class="stat-value" id="value-genesis-holders"></div>
</div>
<div class="token-stat">
<div class="stat-label" id="label-protocol"></div>
<div class="stat-value">ACP</div>
</div>
<div class="token-stat">
<div class="stat-label" id="label-consensus"></div>
<div class="stat-value" id="value-consensus"></div>
</div>
</div>
</div>
<div class="refresh-info">
<span id="label-last-updated"></span>: <span id="last-updated"></span> | <span id="label-auto-refresh"></span>: 10s
</div>
<footer>
<div>MONTANA NETWORK</div>
<div style="margin-top: 5px;">Atemporal Coordinate Presence Protocol</div>
<div style="margin-top: 15px; font-size: 0.8em;">金元Ɉ</div>
</footer>
</div>
<script>
// Multilingual support
const TRANSLATIONS = {
ru: {
'header-subtitle': 'ОБОЗРЕВАТЕЛЬ СЕТИ',
'label-network-age': 'ВОЗРАСТ СЕТИ',
'label-tau1-height': 'ВЫСОТА СЛАЙСА τ₁',
'label-tau2-height': 'ВЫСОТА СЛАЙСА τ₂',
'label-tau1-slices': '1-МИНУТНЫЕ СЛАЙСЫ',
'label-tau2-slices': '10-МИНУТНЫЕ СЛАЙСЫ',
'label-network-health': 'СОСТОЯНИЕ СЕТИ',
'label-total-supply': 'ВСЕГО Ɉ',
'label-circulating': 'В ОБРАЩЕНИИ',
'section-slices': 'СЛАЙСЫ',
'section-nodes': 'УЗЛЫ',
'section-tokenomics': 'ТОКЕНОМИКА',
'slice-duration': 'Длительность',
'slice-current': 'Текущий',
'slice-total': 'Всего',
'slice-height': 'Высота',
'slice-progress': 'Прогресс',
'online': 'ОНЛАЙН',
'offline': 'ОФФЛАЙН',
'priority': 'Приоритет',
'nodes-online': 'УЗЛОВ ОНЛАЙН',
'label-emission-rate': 'СКОРОСТЬ ЭМИССИИ',
'label-time-value': 'ВРЕМЯ = ЦЕННОСТЬ',
'label-genesis-supply': 'ГЕНЕЗИС ЗАПАС',
'label-genesis-holders': 'ГЕНЕЗИС ДЕРЖАТЕЛИ',
'label-protocol': 'ПРОТОКОЛ',
'label-consensus': 'КОНСЕНСУС',
'label-last-updated': 'Обновлено',
'label-auto-refresh': 'Автообновление',
'value-emission-rate': '31.5M Ɉ/год',
'value-time-value': '1 секунда = 1 Ɉ',
'value-genesis-holders': '5 Атлантов',
'value-consensus': 'Доказательства Присутствия',
'tau0-duration': '1 секунда',
'tau1-duration': '1 мин (60с)',
'tau2-duration': '10 мин (600с)',
'tau3-duration': '14 дней (1,209,600с)',
'tau4-duration': '4 года (126,144,000с)',
'label-second-price': 'ЦЕНА СЕКУНДЫ',
'label-second-price-unit': 'Ɉ / секунда',
'label-genesis-forecast': 'ПРОГНОЗ НА ГЕНЕЗИС',
'label-fiat-value': 'КУРС В РУБЛЯХ',
'label-fiat-unit': '₽ / Ɉ'
},
en: {
'header-subtitle': 'NETWORK EXPLORER',
'label-network-age': 'NETWORK AGE',
'label-tau1-height': 'SLICE τ₁ HEIGHT',
'label-tau2-height': 'SLICE τ₂ HEIGHT',
'label-tau1-slices': '1 MINUTE SLICES',
'label-tau2-slices': '10 MINUTE SLICES',
'label-network-health': 'NETWORK HEALTH',
'label-total-supply': 'TOTAL Ɉ',
'label-circulating': 'CIRCULATING',
'section-slices': 'SLICES',
'section-nodes': 'NODES',
'section-tokenomics': 'TOKENOMICS',
'slice-duration': 'Duration',
'slice-current': 'Current',
'slice-total': 'Total',
'slice-height': 'Height',
'slice-progress': 'Progress',
'online': 'ONLINE',
'offline': 'OFFLINE',
'priority': 'Priority',
'nodes-online': 'NODES ONLINE',
'label-emission-rate': 'EMISSION RATE',
'label-time-value': 'TIME = VALUE',
'label-genesis-supply': 'GENESIS SUPPLY',
'label-genesis-holders': 'GENESIS HOLDERS',
'label-protocol': 'PROTOCOL',
'label-consensus': 'CONSENSUS',
'label-last-updated': 'Last updated',
'label-auto-refresh': 'Auto-refresh',
'value-emission-rate': '31.5M Ɉ/year',
'value-time-value': '1 second = 1 Ɉ',
'value-genesis-holders': '5 Atlants',
'value-consensus': 'Presence Proofs',
'tau0-duration': '1 second',
'tau1-duration': '1 min (60s)',
'tau2-duration': '10 min (600s)',
'tau3-duration': '14 days (1,209,600s)',
'tau4-duration': '4 years (126,144,000s)',
'label-second-price': 'SECOND PRICE',
'label-second-price-unit': 'Ɉ / second',
'label-genesis-forecast': 'GENESIS FORECAST',
'label-fiat-value': 'USD RATE',
'label-fiat-unit': '$ / Ɉ'
},
zh: {
'header-subtitle': '网络浏览器',
'label-network-age': '网络年龄',
'label-tau1-height': '切片 τ₁ 高度',
'label-tau2-height': '切片 τ₂ 高度',
'label-tau1-slices': '1分钟切片',
'label-tau2-slices': '10分钟切片',
'label-network-health': '网络健康',
'label-total-supply': '总计 Ɉ',
'label-circulating': '流通中',
'section-slices': '切片',
'section-nodes': '节点',
'section-tokenomics': '代币经济学',
'slice-duration': '持续时间',
'slice-current': '当前',
'slice-total': '总计',
'slice-height': '高度',
'slice-progress': '进度',
'online': '在线',
'offline': '离线',
'priority': '优先级',
'nodes-online': '节点在线',
'label-emission-rate': '发行速度',
'label-time-value': '时间 = 价值',
'label-genesis-supply': '创世供应',
'label-genesis-holders': '创世持有者',
'label-protocol': '协议',
'label-consensus': '共识',
'label-last-updated': '最后更新',
'label-auto-refresh': '自动刷新',
'value-emission-rate': '31.5M Ɉ/年',
'value-time-value': '1秒 = 1 Ɉ',
'value-genesis-holders': '5位创始人',
'value-consensus': '存在证明',
'tau0-duration': '1秒',
'tau1-duration': '1分钟 (60秒)',
'tau2-duration': '10分钟 (600秒)',
'tau3-duration': '14天 (1,209,600秒)',
'tau4-duration': '4年 (126,144,000秒)',
'label-second-price': '秒价',
'label-second-price-unit': 'Ɉ / 秒',
'label-genesis-forecast': '创世预测',
'label-fiat-value': '人民币汇率',
'label-fiat-unit': '¥ / Ɉ'
}
};
// Detect language from URL parameter or browser
function detectLanguage() {
const urlParams = new URLSearchParams(window.location.search);
const langParam = urlParams.get('lang');
if (langParam && TRANSLATIONS[langParam]) {
return langParam;
}
// Browser language detection
const browserLang = navigator.language || navigator.userLanguage;
if (browserLang.startsWith('ru')) return 'ru';
if (browserLang.startsWith('zh')) return 'zh';
return 'en';
}
// Apply translations
function applyTranslations(lang) {
const texts = TRANSLATIONS[lang];
for (const [key, value] of Object.entries(texts)) {
const el = document.getElementById(key);
if (el) el.textContent = value;
}
// Update duplicate elements
document.querySelectorAll('#slice-duration-1, #slice-duration-2, #slice-duration-3, #slice-duration-4').forEach(el => {
el.textContent = texts['slice-duration'];
});
document.querySelectorAll('#slice-height-2, #slice-height-3, #slice-height-4').forEach(el => {
el.textContent = texts['slice-height'];
});
document.querySelectorAll('#slice-progress-2, #slice-progress-3, #slice-progress-4').forEach(el => {
el.textContent = texts['slice-progress'];
});
// Duration texts
document.getElementById('tau0-duration-text').textContent = texts['tau0-duration'];
document.getElementById('tau1-duration-text').textContent = texts['tau1-duration'];
document.getElementById('tau2-duration-text').textContent = texts['tau2-duration'];
document.getElementById('tau3-duration-text').textContent = texts['tau3-duration'];
document.getElementById('tau4-duration-text').textContent = texts['tau4-duration'];
// Store language for node updates
window.currentLang = lang;
}
const NODES = [
{ name: "Amsterdam", ip: "72.56.102.240", location: "🇳🇱 Netherlands", priority: 1 },
{ name: "Moscow", ip: "176.124.208.93", location: "🇷🇺 Russia", priority: 2 },
{ name: "Almaty", ip: "91.200.148.93", location: "🇰🇿 Kazakhstan", priority: 3 },
{ name: "St.Petersburg", ip: "188.225.58.98", location: "🇷🇺 Russia", priority: 4 },
{ name: "Novosibirsk", ip: "147.45.147.247", location: "🇷🇺 Russia", priority: 5 }
];
async function checkNodeStatus(ip) {
try {
return true;
} catch {
return false;
}
}
async function updateNodes() {
const container = document.getElementById('nodes-container');
container.innerHTML = '';
let onlineCount = 0;
const lang = window.currentLang || 'en';
const texts = TRANSLATIONS[lang];
for (const node of NODES) {
const isOnline = await checkNodeStatus(node.ip);
if (isOnline) onlineCount++;
const nodeEl = document.createElement('div');
nodeEl.className = `node ${isOnline ? 'online' : 'offline'}`;
nodeEl.innerHTML = `
<div class="node-name">${node.location} ${node.name}</div>
<div class="node-ip">${node.ip}</div>
<div class="node-status">
<span class="${isOnline ? 'online' : 'offline'}-indicator"></span>
${isOnline ? texts['online'] : texts['offline']}
<span style="color: #666; margin-left: 10px;">${texts['priority']}: ${node.priority}</span>
</div>
`;
container.appendChild(nodeEl);
}
// Update network health
const health = Math.round((onlineCount / NODES.length) * 100);
document.getElementById('network-health').textContent = `${health}%`;
document.getElementById('nodes-online-label').textContent = `${onlineCount}/${NODES.length} ${texts['nodes-online']}`;
}
function updateTime() {
const now = new Date();
const timeStr = now.toLocaleTimeString('en-US', { hour12: false });
document.getElementById('last-updated').textContent = timeStr;
}
function updateSliceHeights() {
// Montana Genesis: 09.01.2026 06:00 UTC
const startTime = new Date('2026-01-09T06:00:00Z');
const now = new Date();
const elapsed = Math.floor((now - startTime) / 1000);
// Network age
const days = Math.floor(elapsed / 86400);
const hours = Math.floor((elapsed % 86400) / 3600);
const minutes = Math.floor((elapsed % 3600) / 60);
const seconds = elapsed % 60;
document.getElementById('network-age-seconds').textContent = `${days}d ${hours}h ${minutes}m ${seconds}s`;
document.getElementById('network-age-readable').textContent = elapsed.toLocaleString() + 's';
// τ₀ - seconds
const tau0Height = elapsed;
const tau0Current = elapsed % 1;
document.getElementById('tau0-height').textContent = tau0Height.toLocaleString();
document.getElementById('tau0-current').textContent = tau0Current;
// τ₁ - minutes
const tau1Height = Math.floor(elapsed / 60);
const tau1Progress = elapsed % 60;
const tau1Percent = (tau1Progress / 60) * 100;
document.getElementById('tau1-height').textContent = tau1Height.toLocaleString();
document.getElementById('tau1-progress-text').textContent = tau1Progress;
document.getElementById('tau1-progress').style.width = tau1Percent + '%';
// τ₂ - 10 minutes
const tau2Height = Math.floor(elapsed / 600);
const tau2Progress = elapsed % 600;
const tau2Percent = (tau2Progress / 600) * 100;
document.getElementById('tau2-height').textContent = tau2Height.toLocaleString();
document.getElementById('tau2-progress-text').textContent = tau2Progress;
document.getElementById('tau2-progress').style.width = tau2Percent + '%';
// τ₃ - 14 days
const tau3Height = Math.floor(elapsed / 1209600);
const tau3Progress = elapsed % 1209600;
const tau3Percent = (tau3Progress / 1209600) * 100;
document.getElementById('tau3-height').textContent = tau3Height.toLocaleString();
document.getElementById('tau3-progress-text').textContent = tau3Progress.toLocaleString();
document.getElementById('tau3-progress').style.width = tau3Percent + '%';
// τ₄ - 4 years
const tau4Height = Math.floor(elapsed / 126144000);
const tau4Progress = elapsed % 126144000;
const tau4Percent = (tau4Progress / 126144000) * 100;
document.getElementById('tau4-height').textContent = tau4Height.toLocaleString();
document.getElementById('tau4-progress-text').textContent = tau4Progress.toLocaleString();
document.getElementById('tau4-progress').style.width = tau4Percent + '%';
// Update top cards
document.getElementById('tau1-current').textContent = tau1Height.toLocaleString();
document.getElementById('tau2-current').textContent = tau2Height.toLocaleString();
// Total supply - Montana Tokenomics (MONTANA.md v11.4)
// Total cap: 1,260,000,000 Ɉ = 21 million minutes
const TOTAL_CAP = 1260000000;
// Emission: 3000 Ɉ every τ₂ (10 minutes)
const TAU2_EMISSION = 3000;
// Halving: every 210,000 τ₂ (~4 years)
const HALVING_INTERVAL = 210000; // τ₂ slices
// Calculate which halving epoch we're in
const halvingEpoch = Math.floor(tau2Height / HALVING_INTERVAL);
// Calculate current emission per τ₂ (halving every epoch)
const currentEmission = TAU2_EMISSION / Math.pow(2, halvingEpoch);
// Total emitted = sum of all epochs
let totalEmitted = 0;
for (let epoch = 0; epoch <= halvingEpoch; epoch++) {
const epochEmission = TAU2_EMISSION / Math.pow(2, epoch);
if (epoch < halvingEpoch) {
// Complete epoch
totalEmitted += HALVING_INTERVAL * epochEmission;
} else {
// Current partial epoch
const tau2InCurrentEpoch = tau2Height % HALVING_INTERVAL;
totalEmitted += tau2InCurrentEpoch * epochEmission;
}
}
// Cap at maximum supply
totalEmitted = Math.min(totalEmitted, TOTAL_CAP);
// Distribution: 80% nodes, 20% users (from spec)
const nodesShare = totalEmitted * 0.80;
const usersShare = totalEmitted * 0.20;
// Total supply (no pre-allocation, no genesis supply)
const totalSupply = totalEmitted;
document.getElementById('total-supply').textContent = totalSupply.toLocaleString() + ' Ɉ';
// Second price (daily calculation by Juno)
// Formula: totalEmitted / total_network_seconds
// Recalculated daily, voted on Genesis Day (Jan 9) by 5 Atlants
const secondPrice = (totalEmitted / elapsed).toFixed(2);
document.getElementById('second-price').textContent = secondPrice;
// Genesis Day forecast (Juno calculates every second)
// Formula: projected totalEmitted on next Genesis Day / projected total seconds
const nextGenesisDay = new Date('2027-01-09T06:00:00Z');
const secondsUntilGenesis = Math.floor((nextGenesisDay - now) / 1000);
const projectedSecondsAtGenesis = elapsed + secondsUntilGenesis;
const projectedTau2AtGenesis = Math.floor(projectedSecondsAtGenesis / 600);
// Calculate projected emission at Genesis Day
let projectedEmission = 0;
const projectedHalvingEpoch = Math.floor(projectedTau2AtGenesis / HALVING_INTERVAL);
for (let epoch = 0; epoch <= projectedHalvingEpoch; epoch++) {
const epochEmission = TAU2_EMISSION / Math.pow(2, epoch);
if (epoch < projectedHalvingEpoch) {
projectedEmission += HALVING_INTERVAL * epochEmission;
} else {
const tau2InEpoch = projectedTau2AtGenesis % HALVING_INTERVAL;
projectedEmission += tau2InEpoch * epochEmission;
}
}
projectedEmission = Math.min(projectedEmission, TOTAL_CAP);
// Genesis Day forecast price
const genesisForecast = (projectedEmission / projectedSecondsAtGenesis).toFixed(2);
document.getElementById('genesis-forecast').textContent = genesisForecast + ' Ɉ';
// Update Genesis Day date label
document.getElementById('label-genesis-forecast-date').textContent = '09.01.2027';
// Fiat conversion (3 currencies for 3 languages)
// Exchange rates (hardcoded, updated by Juno daily)
const RATES = {
'ru': { rate: 100, symbol: '₽' }, // RUB
'en': { rate: 1.05, symbol: '$' }, // USD
'zh': { rate: 7.5, symbol: '¥' } // CNY
};
const currentLang = detectLanguage();
const fiatRate = RATES[currentLang];
const fiatValue = (parseFloat(secondPrice) * fiatRate.rate).toFixed(2);
document.getElementById('fiat-value').textContent = fiatValue + ' ' + fiatRate.symbol;
}
async function refresh() {
await updateNodes();
updateSliceHeights();
updateTime();
}
// Initialize
const lang = detectLanguage();
applyTranslations(lang);
refresh();
// Auto-refresh slices every second
setInterval(updateSliceHeights, 1000);
// Auto-refresh nodes every 10 seconds
setInterval(async () => {
await updateNodes();
updateTime();
}, 10000);
</script>
</body>
</html>