.sb-act {
display: grid; grid-template-columns: 240px 1fr;
min-height: 480px;
font-family: 'Georgia', 'Times New Roman', serif;
background: #f4ecdb;
color: #2a1a10;
border-radius: 0; overflow: hidden;
border: 1px solid #2a1a10;
}
.sb-act-side {
background: #ede0c4;
border-right: 1px solid #2a1a10;
padding: 22px 18px;
display: flex; flex-direction: column; gap: 14px;
}
.sb-act-side header { padding-bottom: 14px; border-bottom: 2px solid #2a1a10; }
.sb-act-issue { font-family: 'Inter', sans-serif; font-size: 10.5px; font-weight: 700; letter-spacing: 0.22em; color: #8a4a2c; text-transform: uppercase; }
.sb-act-side h3 { margin: 4px 0 0; font-size: 30px; font-weight: 500; font-style: italic; color: #2a1a10; letter-spacing: -0.02em; line-height: 1; }
.sb-act-side ol { list-style: none; margin: 0; padding: 0; counter-reset: act; display: flex; flex-direction: column; gap: 0; }
.sb-act-side li { counter-increment: act; }
.sb-act-side a {
position: relative;
display: grid; grid-template-columns: 26px 1fr auto;
align-items: baseline; gap: 12px;
padding: 10px 4px;
font-size: 16px; color: #2a1a10; text-decoration: none;
border-bottom: 1px dotted #b89668;
transition: padding-left 0.16s, color 0.16s;
}
.sb-act-side a::before {
content: counter(act, decimal-leading-zero);
font-family: 'Inter', sans-serif;
font-size: 10px;
font-weight: 700;
letter-spacing: 0.16em;
color: #8a4a2c;
align-self: center;
}
.sb-act-side a span { font-style: italic; }
.sb-act-side a em { font-family: 'Inter', sans-serif; font-style: normal; font-size: 10.5px; font-weight: 600; letter-spacing: 0.04em; color: #8a4a2c; }
.sb-act-side a:hover { padding-left: 4px; color: #8a1f2c; }
.sb-act-side footer { margin-top: auto; padding-top: 14px; border-top: 1px solid #2a1a10; font-family: 'Inter', sans-serif; font-size: 10.5px; letter-spacing: 0.18em; color: #8a4a2c; text-align: center; text-transform: uppercase; }
.sb-act-main { padding: 28px 32px; overflow-y: auto; max-height: 480px; background: #fbf5e6; }
.sb-act-sec { padding: 18px 0; border-bottom: 1px solid #d8c598; }
.sb-act-sec:last-child { border-bottom: 0; }
.sb-act-page { font-family: 'Inter', sans-serif; font-size: 10.5px; font-weight: 700; letter-spacing: 0.2em; color: #8a1f2c; text-transform: uppercase; }
.sb-act-sec h2 { margin: 4px 0 8px; font-family: 'Playfair Display', 'Georgia', serif; font-size: clamp(28px, 4vw, 44px); font-weight: 900; color: #2a1a10; line-height: 0.96; letter-spacing: -0.02em; }
.sb-act-sec p { margin: 0; font-size: 14.5px; color: #3c2818; line-height: 1.7; max-width: 540px; }
.sb-act-sec code { font-family: 'JetBrains Mono', monospace; font-size: 12.5px; color: #8a1f2c; background: rgba(138,31,44,0.08); padding: 1px 5px; border-radius: 0; font-weight: 600; }
/* Default first-link active when no :target yet */
.sb-act-side a[href="#sb-act-overview"] { padding-left: 4px; color: #8a1f2c; font-weight: 700; }
.sb-act-side a[href="#sb-act-overview"]::after { content: '·'; font-family: serif; font-size: 22px; line-height: 0; color: #8a1f2c; margin-left: 4px; }
/* Override default when any section is targeted */
.sb-act:has(:target) .sb-act-side a[href="#sb-act-overview"] { padding-left: 0; color: #2a1a10; font-weight: 400; }
.sb-act:has(:target) .sb-act-side a[href="#sb-act-overview"]::after { content: ''; }
/* Highlight the link matching the targeted section */
.sb-act:has(#sb-act-overview:target) .sb-act-side a[href="#sb-act-overview"],
.sb-act:has(#sb-act-features:target) .sb-act-side a[href="#sb-act-features"],
.sb-act:has(#sb-act-pricing:target) .sb-act-side a[href="#sb-act-pricing"],
.sb-act:has(#sb-act-changelog:target) .sb-act-side a[href="#sb-act-changelog"] { padding-left: 4px; color: #8a1f2c; font-weight: 700; }
.sb-act:has(#sb-act-overview:target) .sb-act-side a[href="#sb-act-overview"]::after,
.sb-act:has(#sb-act-features:target) .sb-act-side a[href="#sb-act-features"]::after,
.sb-act:has(#sb-act-pricing:target) .sb-act-side a[href="#sb-act-pricing"]::after,
.sb-act:has(#sb-act-changelog:target) .sb-act-side a[href="#sb-act-changelog"]::after { content: '·'; font-family: serif; font-size: 22px; line-height: 0; color: #8a1f2c; margin-left: 4px; } <div class="sb-act" id="sb-act-root">
<aside class="sb-act-side" aria-label="Primary">
<header>
<span class="sb-act-issue">Issue No. 47</span>
<h3>Contents</h3>
</header>
<nav aria-label="Primary">
<ol>
<li><a href="#sb-act-overview" data-tgt="overview"><span>Overview</span><em>p. 04</em></a></li>
<li><a href="#sb-act-features" data-tgt="features"><span>Features</span><em>p. 12</em></a></li>
<li><a href="#sb-act-pricing" data-tgt="pricing"><span>Pricing</span><em>p. 28</em></a></li>
<li><a href="#sb-act-changelog" data-tgt="changelog"><span>Changelog</span><em>p. 36</em></a></li>
</ol>
</nav>
<footer>
Spring · MMXXVI
</footer>
</aside>
<main class="sb-act-main">
<section id="sb-act-overview" class="sb-act-sec">
<span class="sb-act-page">— Page 04</span>
<h2>Overview.</h2>
<p>Click a link to the left — the <code>:target</code> pseudo-class highlights it automatically. Sibling selectors do the work; <code>history.pushState</code> keeps the host page from jumping.</p>
</section>
<section id="sb-act-features" class="sb-act-sec">
<span class="sb-act-page">— Page 12</span>
<h2>Features.</h2>
<p>The CSS pattern is <code>:has(#section:target) a[href="#section"]</code>. No JavaScript needed for the highlighting itself.</p>
</section>
<section id="sb-act-pricing" class="sb-act-sec">
<span class="sb-act-page">— Page 28</span>
<h2>Pricing.</h2>
<p>Hash-based routing works in any browser. No router library, no framework dependency, no virtual DOM.</p>
</section>
<section id="sb-act-changelog" class="sb-act-sec">
<span class="sb-act-page">— Page 36</span>
<h2>Changelog.</h2>
<p>Each section is a real <code><section></code> with an id — semantic, bookmarkable, and shareable.</p>
</section>
</main>
</div> /* :target stays the engine — JS only updates the hash without scrolling. */
document.querySelectorAll('.sb-act-side a').forEach(function (a) {
a.addEventListener('click', function (e) {
e.preventDefault();
var hash = a.getAttribute('href');
if (hash && hash.charAt(0) === '#') history.pushState(null, '', hash);
});
}); Live preview Edit any tab — preview updates live Ready