_STATUS_BADGE_CLS_RE was too broad: `status|badge|tag|chip|label` matched
generic UI elements (e.g. <span class="label">, <span class="chip">) that
are unrelated to the sale-status badge, risking picking the wrong block.
Narrowed to `(?<![a-z])status(?![a-z])` — requires the literal token
"status" as a hyphen-delimited component of the CSS class (matches
`status-badge`, `flat-status-tag`, `object-status` but not bare `label`,
`tag`, `chip`, `badge`).
Adds regression test: page with generic label/tag/chip/badge elements
containing "В продаже" must NOT activate Level-1; only the real
`status-badge` block ("Продана") should be returned → status=sold.
Replace whole-HTML re.search for status with a 3-level block-scoped strategy:
1. CSS badge classes (status/badge/tag/chip/label) — highest precision.
2. Proximity to block labelled «Статус» via _find_text_near.
3. Full blocks scan where sold/reserved keywords always beat free —
preventing «в продаже» from nav/similar-flats sections from
misclassifying sold flats as free.
Add _STATUS_KW_RE and _classify_status_kw at module level with full
morphological coverage: продан/продана/продано, реализован[аоы]?,
забронирован[аоы]?, свободн[аоы]?.
Add 31 tests in test_domrf_catalog_parse.py covering all three
extraction levels plus regression for fem. word-form «Квартира продана».
begin_nested() лишь RELEASE'ит SAVEPOINT — без db.commit() все UPDATE
цен откатывались при db.close() в Celery task. Зеркалит правильный
паттерн scrape_catalog_objects (domrf_catalog_object.py:460): try-
commit/except-rollback в конце функции. 50 catalog тестов зелёные.
Closes#1227