Extract shared Lucid HTML components from Overview.hs and Invest.hs into Omni/Fund/Web/Components.hs, following the Omni/Task/Web/Components.hs pattern.
1. renderKpi — single KPI card with label, value, note, optional tooltip
2. renderKpiGrid — wraps children in .fund-kpi-grid div
3. renderSection — .fund-section-block with h2 title and description paragraph
4. renderSliderRow — labeled range input with value display span
5. renderDeltaRow — table row with asset, fund, target, actual, delta, action badge
Each component is a typed Lucid function. The types enforce correct usage (e.g., renderKpi takes a label Text, a value Html, an optional note Html).
Add Omni/Fund/Web/Components/Test.hs that renders each component with dummy data and asserts required CSS classes and HTML structure are present (using Lucid's renderText and Text.isInfixOf checks).
Ava verified: last comment from human author documents shipping/deployment with concrete evidence. Moving to Verified.
Created Omni/Fund/Web/Components.hs with shared Lucid components: fundSection, fundSectionWithDesc, kpiGrid, kpiCard, kpiCardWithId, kpiCardWithTip, kpiCardWithIdTip, kpiAlpine, kpiAlpineWithNote, sliderField/sliderFieldWith, kelSliderField/kelSliderFieldWith. Refactored Invest.hs to use all shared components. Removed local kpiAlpine and sliderField. All 5 sections now use FC.fundSection/FC.fundSectionWithDesc. Deployed.