5fe8f228c1
Add a read-only /ecosystem page that consumes the sibling services' JSON APIs (Nexus entities, Praxis attention, Hexis capabilities), fetched concurrently with honest per-panel error states. Siblings stay headless — mavweb is their human surface (arch §16). Wired via mavweb -nexus/-praxis/-hexis flags; mavweb joins the ecosystem compose network. Fix mobile horizontal overflow across all pages: .content is a flex child with default min-width:auto, so it refused to shrink below the tables' intrinsic width. min-width:0 lets wide tables pan inside .scroll instead of dragging the page sideways. Verified via CDP geometry check (scrollWidth === clientWidth at 430px). Also includes in-progress Ethos UI redesign, ecosystem deploy compose, and planning docs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
57 lines
2.2 KiB
HTML
57 lines
2.2 KiB
HTML
{{template "shellTop" "voice"}}
|
|
<div class=voice-page>
|
|
<div class=voice-status id=status>tap & hold to speak</div>
|
|
<button class=voice-btn id=btn type=button>
|
|
<svg width="36" height="36"><use href="/ethos-icons.svg#i-mic"/></svg>
|
|
</button>
|
|
<div class=voice-log id=log></div>
|
|
<details class=voice-cheat id=cheat>
|
|
<summary>Cheatsheet</summary>
|
|
<dl>
|
|
<dt>Act</dt>
|
|
<dd class=ru>включи свет · сделай громче</dd>
|
|
<dd class=en>restart nginx · turn on the light</dd>
|
|
<dt>Reminder</dt>
|
|
<dd class=ru>напомни через 4 часа размяться</dd>
|
|
<dd class=en>remind me tomorrow at 8am to call the doctor</dd>
|
|
<dt>Fact</dt>
|
|
<dd class=ru>выпил кофе · вес 73 кг</dd>
|
|
<dd class=en>ran 3 kilometers</dd>
|
|
<dt>Note</dt>
|
|
<dd class=ru>запиши рецепт блинов</dd>
|
|
<dd class=en>note: add a backup job for the db</dd>
|
|
<dt>Query</dt>
|
|
<dd class=ru>какой сегодня день · какой прогноз погоды</dd>
|
|
<dd class=en>what version are you · what's the weather</dd>
|
|
<dt>System</dt>
|
|
<dd class=ru>включи тихий режим · как загрузка системы</dd>
|
|
<dd class=en>quiet mode on · system load</dd>
|
|
</dl>
|
|
</details>
|
|
<div class=voice-lang>
|
|
<span class="active" data-lang=ru>RU</span>
|
|
<span data-lang=en>EN</span>
|
|
</div>
|
|
</div>
|
|
<script defer src="/app.js"></script>
|
|
<script>
|
|
(function() {
|
|
var lang = new URLSearchParams(window.location.search).get('lang') || 'ru';
|
|
if (lang !== 'en') lang = 'ru';
|
|
document.documentElement.setAttribute('data-lang', lang);
|
|
document.querySelectorAll('.voice-lang span').forEach(function(el) {
|
|
el.addEventListener('click', function() {
|
|
var l = el.dataset.lang;
|
|
document.documentElement.setAttribute('data-lang', l);
|
|
document.querySelectorAll('.voice-lang span').forEach(function(b) { b.classList.remove('active'); });
|
|
el.classList.add('active');
|
|
var url = new URL(window.location);
|
|
url.searchParams.set('lang', l);
|
|
history.replaceState(null, '', url);
|
|
});
|
|
});
|
|
})();
|
|
</script>
|
|
{{template "shellBottom"}}
|
|
</html>
|