{data.cards.map((card, ci) => {
// Price hierarchy (audit H2 + M1). The three cards are NOT equal weight:
// ci 0 — РЕКОМЕНДОВАННАЯ ЦЕНА В ОБЪЯВЛЕНИИ (market asking, baseline)
// ci 1 — ОЖИДАЕМАЯ ЦЕНА СДЕЛКИ (the real answer → headline)
// ci 2 — ДКП · РОСРЕЕСТР (registry reference, ~−43% → demoted)
// The headline gets an accent border + tint + glow + a larger accent
// value so the user can't confuse it with the registry figure; the
// registry card is demoted to a softer, smaller, muted "СПРАВОЧНО"
// tile. Value scale reads expected(40) ≫ asking(30) > ДКП(28).
// #1991 — column width above is the third, independent axis: asking
// and expected visually dominate the row, ДКП is narrow/secondary.
//
// H1 — when the expected card has no prediction (emptyNote), it drops
// to an honest empty-state and the accent frame moves onto the asking
// card (ci 0) so the panel always has ONE clear headline, never a hole.
const expectedEmpty = Boolean(data.cards[1]?.emptyNote);
const isEmptyCard = Boolean(card.emptyNote);
const isRegistry = ci === 2;
const headlineIndex = expectedEmpty ? 0 : 1;
const isHeadline = !isEmptyCard && ci === headlineIndex;
const isAsking = ci === 0;
return (
{lines(card.title)}
{/* #1991 — explicit "this is the figure that goes into the offer"
mark on the headline card, so the two dominant prices are not
just visually bigger but literally labelled which one to quote. */}
{isHeadline && !isEmptyCard && (
В ОФФЕР
)}
{isRegistry && (
{/* §M8 — расшифровка «ДКП» один раз на секцию. */}
СПРАВОЧНО · ДОГОВОРЫ КУПЛИ-ПРОДАЖИ
)}
{/* H1 empty-state: no bare «—» / gauge / «· с учётом торга» — just an
honest note pointing at the recommended asking price. */}
{isEmptyCard ? (
{card.emptyNote}
) : (
<>
{card.value}
{card.unit}
{card.range && (
{card.range}
)}
{card.ppm && (
{card.ppm}
)}
{card.note && (
{card.note}
)}
>
)}
{isEmptyCard ? (
) : card.bars ? (
{card.bars.map((h, bi) => (
))}
) : (
// M2 — calm delta pill (was a 51px circular gauge that read like a
// tech "занижение" indicator). Full text «−18% к цене объявления»,
// neutral accentDeep on a soft-blue chip, tabular-nums.
{/* §1.2 честный разброс: диапазоны цен = рыночный спред, НЕ погрешность
оценки. Ставим сразу под ценовыми карточками, чтобы широкий диапазон
не читался как «неуверенность расчёта». */}
Диапазоны показывают разброс цен на рынке, а не погрешность оценки.
{/* Fix #1 (audit) — the tile counts below are summed from the top-10
persisted sample, which can be less than builtOn's full n_analogs
total (footer, below) for large result sets. */}
{data.meta.sourcesNote && (
{data.meta.sourcesNote}
)}
{data.sources.map((s, si) =>
s.active ? (
{sourceName(s.name)}
{s.count}
{s.label}
) : (
{s.name}
{s.count}
{s.label}
),
)}
При недоступности источника частичный результат не блокируется
{data.meta.builtOn ?? "—"}