---
estimated_steps: 15
estimated_files: 2
skills_used: []
---

# T02: Add IntersectionObserver active section tracking

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.

## Inputs

- ``frontend/src/components/TableOfContents.tsx` — restyled component from T01 with ul lists and 'On this page' heading`
- ``frontend/src/App.css` — restyled ToC CSS from T01 with accent bar and hover states`

## Expected Output

- ``frontend/src/components/TableOfContents.tsx` — IntersectionObserver tracking active section, applying active classes`
- ``frontend/src/App.css` — active link styles (.technique-toc__link--active, .technique-toc__sublink--active)`

## Verification

cd frontend && npm run build 2>&1 | tail -5 && echo 'Build OK'
