Markup structure
Start with a semantic <nav> containing nested <ol> elements. Each heading in the article body gets a matching id so anchor links work without JavaScript.
Active state with Intersection Observer
Observe every section heading. When a heading crosses the viewport threshold, swap its corresponding TOC link to the active style — a violet left border and bold weight. Debounce with a single requestAnimationFrame.
Collapsible nesting
H3 children hide behind a disclosure toggle. Store the expanded state in a Map keyed by parent ID. Animate height with a CSS transition onmax-height — no layout thrashing.
Sticky positioning
Wrap the TOC in a container withposition: sticky; top: 6rem. Subtract the header height so the TOC never overlaps the navbar. On mobile, collapse the TOC into a horizontal scrollable strip below the hero.