(function bindHelpModal() {
var wikiA = document.getElementById('sidebar-help-wiki-link');
if (wikiA) wikiA.setAttribute('href', HELP_WIKI_URL);
function openHelpModal() {
var ov = document.getElementById('sidebar-help-overlay');
var cb = document.getElementById('modal-hints-toggle');
if (cb) cb.checked = hintsEnabled();
if (ov) {
ov.style.display = 'flex';
ov.setAttribute('aria-hidden', 'false');
}
var closeBtn = document.getElementById('sidebar-help-close');
if (closeBtn) closeBtn.focus();
}
function closeHelpModal() {
var ov = document.getElementById('sidebar-help-overlay');
if (ov) {
ov.style.display = 'none';
ov.setAttribute('aria-hidden', 'true');
}
}
var sbOpen = document.getElementById('sidebar-help-open');
var hdOpen = document.getElementById('header-help-open');
if (sbOpen) sbOpen.addEventListener('click', openHelpModal);
if (hdOpen) hdOpen.addEventListener('click', openHelpModal);
var closeEl = document.getElementById('sidebar-help-close');
if (closeEl) closeEl.addEventListener('click', closeHelpModal);
var helpOv = document.getElementById('sidebar-help-overlay');
if (helpOv) {
helpOv.addEventListener('click', function(ev) {
if (ev.target === helpOv) closeHelpModal();
});
}
var helpDlg = document.getElementById('sidebar-help-dialog');
if (helpDlg) {
helpDlg.addEventListener('click', function(ev) { ev.stopPropagation(); });
}
document.addEventListener('keydown', function(ev) {
if (ev.key !== 'Escape') return;
var ov = document.getElementById('sidebar-help-overlay');
if (ov && ov.style.display === 'flex') {
ev.preventDefault();
closeHelpModal();
}
});
var modalHints = document.getElementById('modal-hints-toggle');
if (modalHints) {
modalHints.addEventListener('change', function() {
var enabled = !!modalHints.checked;
if (enabled) { setHintsEnabled(true); } else { disableAndClearHints(); }
try { window.localStorage.setItem(HINTS_PROMPTED_KEY, '1'); } catch (_) {}
toast(enabled ? 'Hints enabled' : 'Hints disabled');
if (App && App.page) App.navigate(App.page);
});
}
})();
function highlightJson(text) {
var h = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
h = h.replace(/"([^"\\]|\\.)*"\s*:/g, function(m) {
return '<span class="jh-key">' + m + '</span>';
});
h = h.replace(/"([^"\\]|\\.)*"/g, function(m) {
return '<span class="jh-str">' + m + '</span>';
});
h = h.replace(/\b(-?\d+\.?\d*([eE][+-]?\d+)?)\b/g, '<span class="jh-num">$1</span>');
h = h.replace(/\b(true|false)\b/g, '<span class="jh-bool">$1</span>');
h = h.replace(/\bnull\b/g, '<span class="jh-null">null</span>');
h = h.replace(/([{}[\]])/g, '<span class="jh-brace">$1</span>');
return h;
}
function highlightToml(text) {
function highlightTomlValue(rawValue) {
var placeholders = [];
var escaped = String(rawValue || '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
escaped = escaped.replace(/"([^"\\]|\\.)*"/g, function(m) {
var idx = placeholders.length;
placeholders.push('<span class="jh-str">' + m + '</span>');
return '___TOML_STR_' + idx + '___';
});
escaped = escaped.replace(/\b(true|false)\b/g, '<span class="jh-bool">$1</span>');
escaped = escaped.replace(/\b(-?\d+\.?\d*([eE][+-]?\d+)?)\b/g, '<span class="jh-num">$1</span>');
escaped = escaped.replace(/([\[\]\{\}])/g, '<span class="jh-brace">$1</span>');
return escaped.replace(/___TOML_STR_(\d+)___/g, function(_, idx) {
return placeholders[Number(idx)] || '';
});
}
var lines = String(text || '').split('\n');
return lines.map(function(line) {
if (/^\s*#/.test(line)) {
return '<span class="jh-comment">' + line.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>') + '</span>';
}
if (/^\s*\[\[?[^\]]+\]\]?\s*$/.test(line)) {
return '<span class="jh-section">' + line.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>') + '</span>';
}
var match = line.match(/^(\s*)([A-Za-z0-9_.-]+)(\s*=\s*)(.*)$/);
if (!match) {
return highlightTomlValue(line);
}
var leading = match[1].replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
var key = match[2].replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
var sep = match[3].replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
var value = highlightTomlValue(match[4]);
return leading + '<span class="jh-key">' + key + '</span>' + sep + value;
}).join('\n');
}
function syncJsonHighlight() {
var ta = document.getElementById('settings-json-editor');
var pre = document.getElementById('json-highlight');
if (!ta || !pre) return;
pre.innerHTML = highlightJson(ta.value) + '\n';
pre.scrollTop = ta.scrollTop;
pre.scrollLeft = ta.scrollLeft;
}
function syncRawHighlight() {
var ta = document.getElementById('settings-raw-editor');
var pre = document.getElementById('settings-raw-highlight');
if (!ta || !pre) return;
pre.innerHTML = highlightToml(ta.value) + '\n'; ta.style.height = pre.scrollHeight + 'px';
}
function syncSettingsHighlight() {
if (document.getElementById('settings-raw-editor')) {
syncRawHighlight();
return;
}
syncJsonHighlight();
}
if (content) content.addEventListener('scroll', function(e) {
if (e.target.id === 'settings-json-editor') {
var pre = document.getElementById('json-highlight');
if (pre) { pre.scrollTop = e.target.scrollTop; pre.scrollLeft = e.target.scrollLeft; }
}
}, true);
function onHash() {
var hash = (window.location.hash || '#overview').slice(1) || 'overview';
if (hash === 'roster') { hash = 'agents'; App._agentsTab = 'roster'; window.location.hash = 'agents'; return; }
if (hash === 'observability') { hash = 'metrics'; window.location.hash = 'metrics'; return; }
if (pages.indexOf(hash) === -1) hash = 'overview';
ensureAuth().then(function() {
refreshSidebarIdentity();
App.navigate(hash);
});
}
document.querySelectorAll('.sidebar-nav a, .mobile-nav a').forEach(function(a) {
a.addEventListener('click', function(ev) {
ev.preventDefault();
var p = a.getAttribute('data-page');
if (p === 'efficiency') App._effTab = 'performance';
if (p) window.location.hash = p;
var sb = document.getElementById('sidebar');
if (sb && window.innerWidth <= 768) sb.classList.remove('open');
});
});