feat(concept): live 3D massing → financial recompute in «7. Концепция» (#1965 Stage 2b)
Wire the interactive 3D massing to a LIVE financial recompute inside the
Section «7. Концепция» of the light analysis report (epic #1953).
- concept-api.ts: add MassingProgram / MassingRecomputeOutput contracts +
useRecomputeMassing() (POST /api/v1/concepts/recompute via shared apiFetch),
and polygonCentroidWkt() helper for the DB-price fallback hint.
- MassingScene.tsx: export MassingModel + add optional onModelChange prop fired
on the initial build and every floors/sections change (NOT on the sun/hour
slider). No-op when absent — /ptica cockpit + preview/drawer unchanged.
- MassingEconomics.tsx (new): light-token KPI strip rendering recomputed ТЭП
(GFA, продаваемая, квартиры, КСИТ факт/цель) + финмодель (выручка,
себестоимость, прибыль, ROI, NPV, IRR, цена). Debounced ~250ms, latest-wins
via monotonic request id, last-good values + subtle note on error, grey-fade
skeleton on first load, КСИТ over-cap flag.
- Section7Concept.tsx: mount lazy MassingViewer (dynamic ssr:false) + the
economics strip; map computeModel → MassingProgram (footprint/floors/sections
← model; site area ← polygon; class/type ← financial_estimate inferred,
fallback comfort/mid_rise; land ← egrn cadastral; price/source ←
financial_estimate; КСИТ-цель ← coerced nspd_zoning.max_far, fallback 3.5).