# S04: ToC Modernization

**Goal:** Technique page ToC: no counters, left accent bar, "On this page" heading, active section highlighting on scroll, sticky in sidebar.
**Demo:** After this: Technique page ToC: no counters, left accent bar, On this page heading, active section highlighting on scroll, sticky in sidebar.

## Tasks
- [x] **T01: Moved Table of Contents from main prose column to sidebar top; replaced card/counter styling with left accent bar and hover backgrounds** — Move the TableOfContents render from inside technique-columns__main (inside technique-prose) to the top of technique-columns__sidebar. Restyle: remove CSS counters, remove card background, add left accent bar, rename heading to 'On this page', add hover background states on links.

This slice owns R040 (Table of Contents Modernization). The ToC currently renders at line 425 of TechniquePage.tsx inside the v2 prose section. It needs to move to the sidebar div (line 470). Only render ToC in sidebar for v2 format pages.

CSS changes in App.css (lines 2034–2108):
- Remove counter-reset, counter-increment, and ::before pseudo-elements
- Remove background/border card styling
- Add border-left: 2px solid var(--color-accent) accent bar
- Add hover background: var(--color-accent-subtle) on links
- Change .technique-toc__title text to be set by the component (not CSS)

Component changes in TableOfContents.tsx:
- Change heading from 'Contents' to 'On this page'
- Change <ol> to <ul> (no ordered list needed without counters)

Layout note: The sidebar is already position: sticky; top: 1.5rem. Placing ToC at the top of the sidebar makes it sticky automatically.
  - Estimate: 30m
  - Files: frontend/src/pages/TechniquePage.tsx, frontend/src/components/TableOfContents.tsx, frontend/src/App.css
  - Verify: cd frontend && npm run build 2>&1 | tail -5 && echo 'Build OK'
- [x] **T02: Added IntersectionObserver scroll-spy to ToC highlighting the active section as user scrolls through technique page content** — Add scroll-based active section highlighting to the ToC using IntersectionObserver.

In TableOfContents.tsx:
- Add state: const [activeId, setActiveId] = useState<string>('')
- useEffect: create IntersectionObserver watching all section/subsection IDs
  - rootMargin: '0px 0px -70% 0px' — triggers when section enters top 30% of viewport
  - On intersect: find the topmost intersecting entry, setActiveId to its target.id
  - Collect all IDs from sections prop: H2 = slugify(heading), H3 = sectionSlug--slugify(sub.heading)
  - Observe each element by document.getElementById(id)
  - Cleanup: disconnect observer on unmount
- Apply active class: technique-toc__link--active (or sublink variant) when href matches activeId

In App.css, add active state styles:
- .technique-toc__link--active: color: var(--color-accent), font-weight 500, border-left or background highlight
- .technique-toc__sublink--active: same treatment
- Ensure active state is visually distinct from hover state

Slug convention (from KNOWLEDGE.md): H2 = slugify(heading), H3 = sectionSlug--slugify(sub.heading) with double-hyphen separator. These IDs are already set on the div elements in TechniquePage.tsx prose rendering.
  - Estimate: 30m
  - Files: frontend/src/components/TableOfContents.tsx, frontend/src/App.css
  - Verify: cd frontend && npm run build 2>&1 | tail -5 && echo 'Build OK'
