hephaestus.x: overlay side nav on home and docs

Home page: How it works, Source and Pantheon were in the topnav next
to cross-site tabs. Moved them plus Sign in and Verify into an overlay
sidebar on the left edge — same shape as Sirius.X and Theseus.X —
pointer-events:none, opacity 0.35 by default, hover brightens with a
blurred backdrop, active section painted acid green,
IntersectionObserver replaced with scroll-position tracking so the
final section still activates when the reader hits the page end.
Topnav collapses to the site tabs the header still owns: Hephaestus.X ·
Docs · Explore repos · Sign in.

Docs page: the two-column grid with an inline .toc left column has
been swapped for the same overlay rail. The 13 chapter titles now sit
at the left edge, keep their numbered mono prefix via CSS counter,
and stay legible under the semi-transparent hover backdrop. Content
column is centred at 820px so the reading axis is on the middle of
the viewport rather than shifted right by a sidebar. Icon rail at
64px on medium; sidebar hidden altogether on mobile because there is
no room for a 13-item rail.
This commit is contained in:
Local Dev 2026-09-20 20:40:39 +02:00
parent 0296e8fede
commit c5353e3e47
2 changed files with 143 additions and 35 deletions

View file

@ -56,16 +56,36 @@
.topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)} .topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)}
.topnav .spacer{margin-left:auto} .topnav .spacer{margin-left:auto}
/* Docs layout: TOC left, content right */ /* Docs layout: single-column centred; the section rail is an overlay. */
.doc{display:grid;grid-template-columns:220px 1fr;gap:32px;max-width:1080px;margin:0 auto;padding:2.4rem 1.2rem 4rem} .doc{max-width:820px;margin:0 auto;padding:2.4rem 1.2rem 4rem}
.toc{position:sticky;top:60px;align-self:start;font-size:13.5px;max-height:calc(100vh - 80px);overflow:auto;padding-right:6px}
.toc h4{font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);margin:0 0 8px;font-weight:500}
.toc ol{list-style:none;padding:0;margin:0 0 1.4rem;display:grid;gap:2px;counter-reset:t}
.toc ol li{counter-increment:t}
.toc ol li a{display:block;padding:5px 8px;border-radius:6px;color:var(--mut);text-decoration:none;line-height:1.35}
.toc ol li a::before{content:counter(t) ". ";color:var(--dim);font-family:var(--mono);font-size:11px}
.toc ol li a:hover{color:var(--ink);background:var(--panel)}
.content{min-width:0} .content{min-width:0}
/* Adaptive side nav — overlay pattern shared with the rest of Silent Mode. */
:root{--sn-w:220px}
.sidenav{position:fixed;top:56px;left:0;bottom:0;width:var(--sn-w);z-index:15;
background:transparent;padding:32px 12px 22px 18px;
overflow-y:auto;pointer-events:none;transition:width .15s ease}
.sidenav a{display:flex;align-items:center;gap:10px;color:var(--mut);text-decoration:none;
padding:6px 10px;border-radius:8px;
font-size:13.5px;font-weight:500;opacity:.35;pointer-events:auto;line-height:1.35;
transition:opacity .12s,color .12s,background .12s,backdrop-filter .12s;counter-increment:t}
.sidenav a::before{content:counter(t) ". ";color:currentColor;font-family:var(--mono);font-size:11px;opacity:.7;flex:none}
.sidenav a .lb{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sidenav a:hover{opacity:1;color:var(--ink);background:rgba(5,8,16,.72);backdrop-filter:blur(8px)}
.sidenav a.active{opacity:.9;color:var(--acid)}
.sidenav a.active:hover{opacity:1}
.sidenav > .list{counter-reset:t;display:contents}
h2{scroll-margin-top:70px}
@media (max-width:1180px){
:root{--sn-w:52px}
.sidenav{padding:22px 4px}
.sidenav a{justify-content:center;padding:8px 2px;gap:0}
.sidenav a .lb{display:none}
}
@media (max-width:720px){
:root{--sn-w:0}
.sidenav{display:none}
}
h1{font-size:clamp(2rem,4vw,2.5rem);margin:.4rem 0 .3rem;line-height:1.05} h1{font-size:clamp(2rem,4vw,2.5rem);margin:.4rem 0 .3rem;line-height:1.05}
h1 .g{color:var(--forge)} h1 .g{color:var(--forge)}
h2{font-size:1.35rem;margin:2.4rem 0 .6rem;padding-top:1rem;border-top:1px solid var(--line)} h2{font-size:1.35rem;margin:2.4rem 0 .6rem;padding-top:1rem;border-top:1px solid var(--line)}
@ -125,8 +145,6 @@
footer.deep .bar .mono{font-family:var(--mono);letter-spacing:.03em} footer.deep .bar .mono{font-family:var(--mono);letter-spacing:.03em}
@media (max-width:820px){ @media (max-width:820px){
.doc{grid-template-columns:1fr;gap:0}
.toc{position:relative;top:0;max-height:none;margin-bottom:1.2rem}
footer.deep .fwrap{grid-template-columns:1fr 1fr;gap:24px} footer.deep .fwrap{grid-template-columns:1fr 1fr;gap:24px}
} }
@media (max-width:520px){ @media (max-width:520px){
@ -138,35 +156,32 @@
<nav class="topnav"> <nav class="topnav">
<a class="brand" href="../"><span>⚒️</span><span><span class="g">Hephaestus</span>.X</span></a> <a class="brand" href="../"><span>⚒️</span><span><span class="g">Hephaestus</span>.X</span></a>
<a href="../#how">How it works</a>
<a href="./" class="here">Docs</a> <a href="./" class="here">Docs</a>
<a href="../#source">Source</a>
<a href="https://code.silentmode.st/explore/repos" rel="noopener">Explore repos</a> <a href="https://code.silentmode.st/explore/repos" rel="noopener">Explore repos</a>
<span class="spacer"></span> <span class="spacer"></span>
<a href="https://code.silentmode.st/user/oauth2/hephaestus-wallet" style="color:var(--acid)">🔑 Sign in</a> <a href="https://code.silentmode.st/user/oauth2/hephaestus-wallet" style="color:var(--acid)">🔑 Sign in</a>
</nav> </nav>
<div class="doc"> <aside class="sidenav" aria-label="On this page">
<div class="list">
<aside class="toc"> <a href="#what" ><span class="lb">What Hephaestus is</span></a>
<h4>On this page</h4> <a href="#hosts" ><span class="lb">Two hostnames</span></a>
<ol> <a href="#signin" ><span class="lb">Sign in with a wallet</span></a>
<li><a href="#what">What Hephaestus is</a></li> <a href="#rename" ><span class="lb">Rename your username</span></a>
<li><a href="#hosts">Two hostnames</a></li> <a href="#repos" ><span class="lb">Create + push a repo</span></a>
<li><a href="#signin">Sign in with a wallet</a></li> <a href="#tokens" ><span class="lb">Personal access tokens</span></a>
<li><a href="#rename">Rename your username</a></li> <a href="#registry"><span class="lb">Container registry</span></a>
<li><a href="#repos">Create + push a repo</a></li> <a href="#api" ><span class="lb">API basics</span></a>
<li><a href="#tokens">Personal access tokens</a></li> <a href="#storage" ><span class="lb">Where files live</span></a>
<li><a href="#registry">Container registry (OCI)</a></li> <a href="#selfhost"><span class="lb">Self-hosting</span></a>
<li><a href="#api">API basics</a></li> <a href="#gotchas" ><span class="lb">Known gotchas</span></a>
<li><a href="#storage">Where files live</a></li> <a href="#sessions"><span class="lb">CLI + GUI access</span></a>
<li><a href="#selfhost">Self-hosting</a></li> <a href="#help" ><span class="lb">Help + source</span></a>
<li><a href="#gotchas">Known gotchas</a></li> </div>
<li><a href="#sessions">CLI + GUI access</a></li>
<li><a href="#help">Help + source</a></li>
</ol>
</aside> </aside>
<div class="doc">
<main class="content"> <main class="content">
<h1>Hephaestus <span class="g">docs</span></h1> <h1>Hephaestus <span class="g">docs</span></h1>
@ -509,6 +524,32 @@ const { redirect } = await (await fetch(
</footer> </footer>
<script defer src="../js/theme.js"></script> <script defer src="../js/theme.js"></script>
<script>
// Sidenav scroll-spy: highlight the section currently in view.
(() => {
const links = document.querySelectorAll(".sidenav a[href^='#']");
if (!links.length) return;
const entries = [];
links.forEach((a) => { const el = document.querySelector(a.getAttribute("href")); if (el) entries.push({ el, link: a }); });
if (!entries.length) return;
const setActive = (link) => { links.forEach((l) => l.classList.remove("active")); link.classList.add("active"); };
const update = () => {
const doc = document.documentElement;
const scrollBottom = window.scrollY + window.innerHeight;
if (scrollBottom >= (doc.scrollHeight - 4)) { setActive(entries[entries.length - 1].link); return; }
const line = window.scrollY + window.innerHeight * 0.35;
let active = entries[0].link;
for (const e of entries) {
if (e.el.getBoundingClientRect().top + window.scrollY <= line) active = e.link;
else break;
}
setActive(active);
};
window.addEventListener("scroll", update, { passive: true });
window.addEventListener("resize", update);
update();
})();
</script>
</body> </body>
</html> </html>

View file

@ -80,6 +80,42 @@
.topnav a:hover{color:var(--ink);background:var(--panel)} .topnav a:hover{color:var(--ink);background:var(--panel)}
.topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)} .topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)}
.topnav .spacer{margin-left:auto} .topnav .spacer{margin-left:auto}
/* Adaptive side nav — matches Sirius.X and Theseus.X. Overlay on top of
centred content, semi-transparent, hover brightens. */
:root{--sn-w:200px}
.sidenav{position:fixed;top:56px;left:0;bottom:0;width:var(--sn-w);z-index:15;
background:transparent;padding:32px 12px 22px 18px;
overflow-y:auto;pointer-events:none;transition:width .15s ease}
.sidenav a{display:flex;align-items:center;gap:14px;color:var(--mut);text-decoration:none;
padding:9px 12px;border-radius:10px;
font-size:14.5px;font-weight:500;opacity:.35;pointer-events:auto;
transition:opacity .12s,color .12s,background .12s,backdrop-filter .12s}
.sidenav a .ic{flex:none;width:22px;font-size:18px;line-height:1;text-align:center;
display:none;justify-content:center;align-items:center}
.sidenav a .lb{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sidenav a:hover{opacity:1;color:var(--ink);background:rgba(5,8,16,.72);backdrop-filter:blur(8px)}
.sidenav a.active{opacity:.85;color:var(--acid)}
.sidenav a.active:hover{opacity:1}
section{scroll-margin-top:70px}
@media (max-width:1180px){
:root{--sn-w:64px}
.sidenav{padding:22px 6px}
.sidenav a{justify-content:center;padding:12px 4px;gap:0}
.sidenav a .ic{display:inline-flex}
.sidenav a .lb{display:none}
}
@media (max-width:720px){
:root{--sn-w:0}
body{padding-bottom:64px}
.sidenav{top:auto;bottom:0;left:0;right:0;width:100%;height:auto;
padding:4px;flex-direction:row;background:rgba(5,8,16,.52);
display:flex;justify-content:space-around;overflow-x:auto}
.sidenav a{flex:1;min-width:56px;padding:10px 6px;justify-content:center;gap:0;opacity:.5}
.sidenav a .ic{display:inline-flex}
.sidenav a .lb{display:none}
}
header.hero{text-align:center;padding:5rem 1.2rem 1rem} header.hero{text-align:center;padding:5rem 1.2rem 1rem}
.mark{font-size:56px;line-height:1} .mark{font-size:56px;line-height:1}
h1{font-size:clamp(2rem,5.5vw,3rem);margin:.4rem 0 .3rem} h1{font-size:clamp(2rem,5.5vw,3rem);margin:.4rem 0 .3rem}
@ -193,10 +229,7 @@
<nav class="topnav"> <nav class="topnav">
<a class="brand" href="./"><span>⚒️</span><span><span class="g">Hephaestus</span>.X</span></a> <a class="brand" href="./"><span>⚒️</span><span><span class="g">Hephaestus</span>.X</span></a>
<a href="#how">How it works</a>
<a href="./docs/">Docs</a> <a href="./docs/">Docs</a>
<a href="#source">Source</a>
<a href="#pantheon">Pantheon</a>
<a href="https://code.silentmode.st/explore/repos" rel="noopener">Explore repos</a> <a href="https://code.silentmode.st/explore/repos" rel="noopener">Explore repos</a>
<span class="spacer"></span> <span class="spacer"></span>
<details class="wallet-dd"> <details class="wallet-dd">
@ -227,6 +260,14 @@
</details> </details>
</nav> </nav>
<aside class="sidenav" aria-label="On this page">
<a href="#how" title="How it works" ><span class="ic" aria-hidden="true">⚙️</span><span class="lb">How it works</span></a>
<a href="#signin" title="Sign in with a wallet"><span class="ic" aria-hidden="true">🔑</span><span class="lb">Sign in</span></a>
<a href="#source" title="Source" ><span class="ic" aria-hidden="true">📦</span><span class="lb">Source</span></a>
<a href="#pantheon" title="The Silent Mode pantheon"><span class="ic" aria-hidden="true">🏛</span><span class="lb">Pantheon</span></a>
<a href="#verify" title="Verify this page" ><span class="ic" aria-hidden="true">🔐</span><span class="lb">Verify</span></a>
</aside>
<div class="wrap"> <div class="wrap">
<header class="hero"> <header class="hero">
@ -490,6 +531,32 @@ open https://your-domain.example/user/oauth2/hephaestus-wallet</pre>
</footer> </footer>
<script defer src="./js/theme.js"></script> <script defer src="./js/theme.js"></script>
<script>
// Sidenav scroll-spy: highlight the section currently in view.
(() => {
const links = document.querySelectorAll(".sidenav a[href^='#']");
if (!links.length) return;
const entries = [];
links.forEach((a) => { const el = document.querySelector(a.getAttribute("href")); if (el) entries.push({ el, link: a }); });
if (!entries.length) return;
const setActive = (link) => { links.forEach((l) => l.classList.remove("active")); link.classList.add("active"); };
const update = () => {
const doc = document.documentElement;
const scrollBottom = window.scrollY + window.innerHeight;
if (scrollBottom >= (doc.scrollHeight - 4)) { setActive(entries[entries.length - 1].link); return; }
const line = window.scrollY + window.innerHeight * 0.35;
let active = entries[0].link;
for (const e of entries) {
if (e.el.getBoundingClientRect().top + window.scrollY <= line) active = e.link;
else break;
}
setActive(active);
};
window.addEventListener("scroll", update, { passive: true });
window.addEventListener("resize", update);
update();
})();
</script>
</body> </body>
</html> </html>