gendesign/frontend/public/analytics.html
lekss361 6d9eddc8e9 chore: refresh preview pages + add tradein landing
Заменяем устаревшие preview-странички (старая landing.html из PR #279) на
новый набор из аудита gendsgn.ru:

- public/analytics.html (44KB)
- public/developers.html (37KB)
- public/index.html (30KB)
- public/landing.html (41KB, replaces PR #279 version)
- public/site-finder.html (31KB)
- public/site-finder-analysis.html (86KB)
- public/tradein.html (85KB) — новая страничка trade-in

Все 7 файлов self-contained HTML (inline assets) → доступны после deploy
по URL https://gendsgn.ru/<filename>.html. Не пересекаются с Next.js
routes (расширение .html — public/ wins).
2026-05-17 15:37:28 +03:00

586 lines
43 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>/analytics — Свердл рынок · gendsgn</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
--bg-app:#F6F7F9; --bg-card:#FFFFFF; --bg-card-alt:#FAFBFC; --bg-headline:#0F172A;
--border-soft:#EEF0F3; --border-card:#E6E8EC; --border-strong:#D1D5DB;
--fg-primary:#111111; --fg-secondary:#5B6066; --fg-tertiary:#73767E;
--fg-on-dark:#E2E8F0; --fg-on-dark-muted:#94A3B8;
--accent:#1D4ED8; --accent-hover:#1E40AF; --accent-soft:#DBEAFE; --accent-2:#F2994A;
--success:#0A7A3A; --success-soft:#DCFCE7;
--warn:#9A6700; --warn-soft:#FEF3C7;
--danger:#B3261E; --danger-soft:#FEE2E2;
--viz-1:#1D4ED8; --viz-2:#0EA5E9; --viz-3:#14B8A6; --viz-4:#F59E0B; --viz-5:#8B5CF6;
--prediction-band: rgba(14,165,233,0.18);
--font-body:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',system-ui,sans-serif;
}
* { box-sizing:border-box; margin:0; padding:0; }
html { background:var(--bg-app); }
body { font-family:var(--font-body); font-size:14px; line-height:1.5; color:var(--fg-primary); font-variant-numeric:tabular-nums; font-feature-settings:"tnum"; -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale; }
a { color:inherit; text-decoration:none; }
button { font:inherit; cursor:pointer; }
.mono { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; }
.wrap { max-width:1440px; margin:0 auto; padding:0 24px; }
/* ============ DEV NAV ============ */
.dev-nav { position:sticky; top:0; z-index:100; display:flex; align-items:center; gap:18px; height:38px; padding:0 18px; background:#0b0f1a; color:rgba(255,255,255,0.92); font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:11.5px; letter-spacing:0.04em; border-bottom:1px solid rgba(255,255,255,0.08); }
.dev-nav .dev-label { display:inline-flex; align-items:center; gap:8px; color:#fbbf24; font-weight:600; letter-spacing:0.18em; text-transform:uppercase; white-space:nowrap; }
.dev-nav .dev-label::before { content:''; width:6px; height:6px; border-radius:50%; background:#fbbf24; box-shadow:0 0 0 3px rgba(251,191,36,0.22); }
.dev-nav .dev-tabs { display:inline-flex; gap:2px; align-items:center; }
.dev-nav .dev-sep { width:1px; height:16px; background:rgba(255,255,255,0.16); margin:0 6px; }
.dev-nav .dev-tabs a { padding:5px 11px; border-radius:5px; color:rgba(255,255,255,0.62); transition:background .12s,color .12s; }
.dev-nav .dev-tabs a:hover { color:#fff; background:rgba(255,255,255,0.08); }
.dev-nav .dev-tabs a[aria-current="page"] { color:#0b0f1a; background:#fbbf24; font-weight:600; }
.dev-nav .dev-hint { margin-left:auto; color:rgba(255,255,255,0.36); white-space:nowrap; }
@media print { .dev-nav { display:none !important; } }
.topbar { background:var(--bg-card); border-bottom:1px solid var(--border-card); }
.topbar-inner { display:flex; align-items:center; justify-content:space-between; height:56px; }
.brand { display:inline-flex; align-items:center; gap:8px; font-weight:700; font-size:15px; color:var(--fg-primary); letter-spacing:-0.01em; }
.brand-mark { width:22px; height:22px; border-radius:6px; background:var(--accent); display:grid; place-items:center; color:#fff; font-size:11px; font-weight:700; }
.brand-mark::before { content:'gd'; }
.topbar-user { display:flex; align-items:center; gap:12px; font-size:13px; color:var(--fg-secondary); }
.topbar-user .who { display:flex; align-items:center; gap:8px; padding:6px 12px; border-radius:6px; background:var(--bg-card-alt); border:1px solid var(--border-card); }
.topbar-user .avatar { width:22px; height:22px; border-radius:50%; background:var(--accent-soft); color:var(--accent); display:grid; place-items:center; font-weight:600; font-size:10px; }
.crumbs { display:flex; gap:8px; align-items:center; padding-top:16px; font-size:12.5px; color:var(--fg-secondary); }
.crumbs a { color:var(--fg-secondary); }
.crumbs a:hover { color:var(--accent); text-decoration:underline; text-underline-offset:3px; }
.crumbs .sep { color:var(--fg-tertiary); }
.crumbs .last { color:var(--fg-primary); }
.page-head { padding:8px 0 16px; display:flex; justify-content:space-between; align-items:flex-end; gap:24px; }
.page-head h1 { font-size:22px; line-height:1.25; font-weight:600; letter-spacing:-0.01em; }
.page-head .sub { font-size:13px; color:var(--fg-secondary); margin-top:4px; }
.page-head .right { display:flex; gap:8px; align-items:center; }
.a-tabs { display:flex; gap:2px; border-bottom:1px solid var(--border-card); margin-bottom:16px; overflow-x:auto; }
.a-tabs a { padding:10px 14px; font-size:13px; font-weight:500; color:var(--fg-secondary); border-bottom:2px solid transparent; margin-bottom:-1px; white-space:nowrap; }
.a-tabs a:hover { color:var(--fg-primary); }
.a-tabs a[aria-current="page"] { color:var(--accent); border-bottom-color:var(--accent); font-weight:600; }
.headline-bar { background:var(--bg-headline); color:var(--fg-on-dark); border-radius:12px; padding:16px 20px; display:flex; align-items:center; gap:16px; margin-bottom:16px; }
.headline-bar .tag { font-size:10.5px; letter-spacing:0.08em; text-transform:uppercase; font-weight:600; color:var(--accent-2); white-space:nowrap; }
.headline-bar .verdict { font-size:15px; font-weight:500; line-height:1.4; color:var(--fg-on-dark); }
.headline-bar .verdict b { color:#fff; font-weight:600; }
.headline-bar .caveat { margin-left:auto; font-size:11.5px; color:var(--fg-on-dark-muted); white-space:nowrap; }
.kpi-row { display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin-bottom:24px; }
.kpi { background:var(--bg-card); border:1px solid var(--border-card); border-radius:12px; padding:16px 18px; }
.kpi .label { font-size:11px; letter-spacing:0.04em; text-transform:uppercase; color:var(--fg-secondary); font-weight:500; }
.kpi .value { font-size:28px; line-height:1.15; font-weight:600; color:var(--fg-primary); letter-spacing:-0.015em; margin-top:8px; }
.kpi .value small { font-size:14px; color:var(--fg-secondary); font-weight:500; margin-left:4px; }
.kpi .hint { font-size:12.5px; color:var(--fg-secondary); margin-top:6px; }
.kpi .delta { display:inline-flex; align-items:center; gap:4px; font-size:12px; font-weight:600; margin-top:8px; padding:2px 8px; border-radius:4px; font-variant-numeric:tabular-nums; }
.kpi .delta.pos { color:var(--success); background:var(--success-soft); }
.kpi .delta.neg { color:var(--danger); background:var(--danger-soft); }
.section { background:var(--bg-card); border:1px solid var(--border-card); border-radius:12px; padding:20px; margin-bottom:24px; }
.section-head { display:flex; align-items:flex-end; justify-content:space-between; gap:16px; margin-bottom:16px; }
.section-head h2 { font-size:18px; line-height:1.25; font-weight:600; letter-spacing:-0.01em; }
.section-head .sub { font-size:12.5px; color:var(--fg-secondary); margin-top:4px; }
.section-head .right { display:flex; gap:8px; align-items:center; }
.btn { display:inline-flex; align-items:center; gap:6px; height:36px; padding:0 16px; border-radius:8px; font-weight:500; font-size:13.5px; border:1px solid transparent; transition:all .12s; }
.btn-primary { background:var(--accent); color:#fff; border-color:var(--accent); }
.btn-primary:hover { background:var(--accent-hover); border-color:var(--accent-hover); }
.btn-secondary { background:var(--accent-2); color:#fff; border-color:var(--accent-2); }
.btn-secondary:hover { filter:brightness(0.94); }
.btn-tertiary { background:transparent; color:var(--fg-primary); border-color:var(--border-card); }
.btn-tertiary:hover { border-color:var(--fg-primary); }
.btn-compact { height:32px; padding:0 12px; font-size:12.5px; border-radius:6px; }
.chip { display:inline-flex; align-items:center; gap:6px; height:28px; padding:0 12px; border-radius:14px; font-size:12px; font-weight:500; color:var(--fg-secondary); background:transparent; border:1px solid var(--border-card); transition:all .12s; cursor:pointer; }
.chip:hover { color:var(--fg-primary); border-color:var(--fg-secondary); }
.chip[aria-pressed="true"] { color:var(--accent); background:var(--accent-soft); border-color:var(--accent-soft); }
.badge { display:inline-flex; align-items:center; gap:4px; font-size:11px; font-weight:600; padding:2px 8px; border-radius:4px; }
.badge.live { color:var(--success); background:var(--success-soft); }
.badge.live::before { content:''; width:6px; height:6px; border-radius:50%; background:var(--success); box-shadow:0 0 0 3px rgba(10,122,58,0.18); }
.map-wrap { position:relative; height:480px; border-radius:8px; overflow:hidden; border:1px solid var(--border-soft); background:#EEF2F7; }
.map-wrap svg { width:100%; height:100%; display:block; }
.map-legend { position:absolute; bottom:12px; left:12px; background:rgba(255,255,255,0.96); backdrop-filter:blur(8px); border:1px solid var(--border-card); border-radius:8px; padding:10px 12px; font-size:11.5px; display:flex; flex-direction:column; gap:6px; }
.map-legend h4 { font-size:10px; letter-spacing:0.04em; text-transform:uppercase; color:var(--fg-secondary); font-weight:500; }
.map-legend .row { display:flex; align-items:center; gap:8px; }
.map-legend .row .pip { width:10px; height:10px; border-radius:50%; border:1.5px solid #fff; box-shadow:0 0 0 1px rgba(0,0,0,0.06); }
.map-controls { position:absolute; top:12px; right:12px; display:flex; flex-direction:column; gap:4px; }
.map-controls button { width:32px; height:32px; border-radius:6px; background:rgba(255,255,255,0.96); border:1px solid var(--border-card); font-size:14px; color:var(--fg-primary); display:grid; place-items:center; }
.map-tooltip { position:absolute; top:14%; left:36%; background:#fff; border:1px solid var(--border-card); border-radius:8px; padding:10px 12px; font-size:11.5px; box-shadow:0 8px 24px -8px rgba(0,0,0,0.18); min-width:200px; }
.map-tooltip .name { font-weight:600; color:var(--fg-primary); font-size:12.5px; margin-bottom:2px; }
.map-tooltip .meta { color:var(--fg-secondary); font-size:11px; line-height:1.45; }
.map-tooltip .stat { display:flex; justify-content:space-between; padding-top:6px; margin-top:6px; border-top:1px solid var(--border-soft); }
.pulse-wrap { display:grid; grid-template-columns:1fr 240px; gap:24px; align-items:start; }
.pulse-chart { position:relative; height:280px; border-left:1px solid var(--border-soft); border-bottom:1px solid var(--border-soft); }
.pulse-chart svg { width:100%; height:100%; display:block; }
.pulse-legend { display:flex; flex-direction:column; gap:10px; padding-top:8px; }
.pulse-legend .leg-row { display:flex; align-items:center; gap:8px; font-size:12.5px; }
.pulse-legend .leg-row .sw { width:14px; height:8px; border-radius:2px; }
.pulse-legend .leg-row .name { color:var(--fg-primary); font-weight:500; }
.pulse-legend .leg-row .meta { margin-left:auto; color:var(--fg-secondary); font-size:11.5px; }
.pulse-axis { position:absolute; font-size:10px; color:var(--fg-tertiary); font-family:ui-monospace,SFMono-Regular,Menlo,monospace; }
.qg-table { display:grid; grid-template-columns:160px 1fr 70px; gap:12px; }
.qg-row { display:contents; }
.qg-cell { padding:8px 0; border-top:1px solid var(--border-soft); display:flex; align-items:center; }
.qg-row:first-child .qg-cell { border-top:0; }
.qg-name { color:var(--fg-primary); font-weight:500; font-size:13px; }
.qg-bars { display:flex; flex-direction:column; gap:4px; padding:6px 0; flex:1; }
.qg-bar { height:14px; border-radius:4px; position:relative; min-width:1%; transition:all .15s; }
.qg-bar .v { position:absolute; right:8px; top:50%; transform:translateY(-50%); font-size:10.5px; font-weight:600; color:#fff; font-variant-numeric:tabular-nums; }
.qg-bar.supply { background:var(--fg-tertiary); }
.qg-bar.demand { background:var(--accent); }
.qg-delta { font-size:12px; font-weight:600; padding:3px 8px; border-radius:4px; text-align:center; font-variant-numeric:tabular-nums; }
.qg-delta.pos { color:var(--success); background:var(--success-soft); }
.qg-delta.neg { color:var(--danger); background:var(--danger-soft); }
.qg-delta.flat { color:var(--fg-secondary); background:var(--bg-card-alt); }
.two-col { display:grid; grid-template-columns:1fr 1fr; gap:24px; margin-bottom:24px; }
.pipeline { display:flex; flex-direction:column; gap:10px; padding-top:8px; }
.pipe-row { display:grid; grid-template-columns:60px 1fr 80px; gap:12px; align-items:center; }
.pipe-row .year { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:12px; color:var(--fg-secondary); }
.pipe-row .stack { height:18px; border-radius:4px; overflow:hidden; display:flex; background:var(--bg-card-alt); }
.pipe-row .stack .seg { height:100%; }
.pipe-row .total { font-size:12.5px; font-weight:600; color:var(--fg-primary); text-align:right; font-variant-numeric:tabular-nums; }
.ann-table { width:100%; border-collapse:collapse; }
.ann-table th { font-size:10px; letter-spacing:0.04em; text-transform:uppercase; color:var(--fg-secondary); font-weight:500; text-align:left; padding:8px 8px 8px 0; border-bottom:1px solid var(--border-card); }
.ann-table th:last-child, .ann-table td:last-child { text-align:right; padding-right:0; }
.ann-table td { font-size:13px; padding:10px 8px 10px 0; border-bottom:1px solid var(--border-soft); color:var(--fg-primary); }
.ann-table tr:last-child td { border-bottom:0; }
.ann-table .num { font-variant-numeric:tabular-nums; font-weight:500; }
.ann-table a { color:var(--accent); }
.ann-table a:hover { text-decoration:underline; text-underline-offset:2px; }
.treemap { display:grid; grid-template-columns:repeat(12,1fr); grid-auto-rows:54px; gap:4px; }
.tile { background:var(--accent); color:#fff; padding:10px 12px; border-radius:6px; display:flex; flex-direction:column; justify-content:space-between; cursor:pointer; transition:transform .1s; overflow:hidden; }
.tile:hover { transform:translateY(-1px); }
.tile .t-name { font-size:13px; font-weight:600; line-height:1.2; }
.tile .t-meta { font-size:11px; opacity:0.85; font-variant-numeric:tabular-nums; }
.tile.lvl-5 { background:#1E3A8A; }
.tile.lvl-4 { background:#1D4ED8; }
.tile.lvl-3 { background:#3B82F6; }
.tile.lvl-2 { background:#60A5FA; }
.tile.lvl-1 { background:#93C5FD; color:#1E3A8A; }
.tile.lvl-1 .t-meta { opacity:0.75; }
details.acc { background:var(--bg-card); border:1px solid var(--border-card); border-radius:12px; margin-bottom:12px; }
details.acc summary { padding:14px 20px; font-size:14px; font-weight:600; color:var(--fg-primary); cursor:pointer; list-style:none; display:flex; justify-content:space-between; align-items:center; }
details.acc summary::-webkit-details-marker { display:none; }
details.acc summary::after { content:'+'; color:var(--fg-secondary); font-size:18px; font-weight:400; }
details.acc[open] summary::after { content:''; }
details.acc .acc-body { padding:0 20px 20px; font-size:13px; color:var(--fg-secondary); line-height:1.55; }
.caveat-bar { background:var(--warn-soft); border:1px solid var(--warn); border-radius:8px; padding:12px 16px; display:flex; gap:12px; align-items:flex-start; font-size:13px; color:var(--fg-primary); margin-bottom:24px; }
.caveat-bar .icon { width:18px; height:18px; flex-shrink:0; color:var(--warn); display:grid; place-items:center; font-weight:700; border:1.5px solid var(--warn); border-radius:50%; font-size:12px; }
.caveat-bar b { color:var(--warn); }
@media (max-width:1200px) {
.kpi-row { grid-template-columns:repeat(2,1fr); }
.two-col { grid-template-columns:1fr; }
.pulse-wrap { grid-template-columns:1fr; }
.treemap { grid-template-columns:repeat(6,1fr); }
}
</style>
</head>
<body>
<aside class="dev-nav" aria-label="Dev navigation">
<span class="dev-label">Превью · gendsgn</span>
<nav class="dev-tabs" aria-label="Превью страницы">
<a href="index.html">обзор</a>
<a href="landing.html">лендинг</a>
<a href="analytics.html" aria-current="page">/analytics</a>
<a href="site-finder.html">/site-finder</a>
<a href="site-finder-analysis.html">/site-finder/анализ</a>
<a href="developers.html">/developers</a>
</nav>
</aside>
<header class="topbar">
<div class="wrap topbar-inner">
<div style="display:flex;align-items:center;gap:24px;">
<a href="landing.html" class="brand"><span class="brand-mark"></span><span>gendsgn</span></a>
<span class="badge live">live · обновлено 4 ч назад</span>
</div>
<div class="topbar-user">
<span style="font-size:12px;color:var(--fg-tertiary);">Свердловская обл. · 2025-Q1</span>
<div class="who"><div class="avatar">AD</div>Алексей · PRINZIP (demo)</div>
</div>
</div>
</header>
<main class="wrap">
<nav class="crumbs" aria-label="Breadcrumb">
<a href="landing.html">gendsgn</a>
<span class="sep">/</span>
<span class="last">analytics — Свердл рынок</span>
</nav>
<div class="page-head">
<div>
<h1>Свердл рынок — обзор спроса и предложения</h1>
<div class="sub">6 832 411 ДДУ Росреестра · 1 482 объекта ДОМ.РФ в активной фазе · обновление еженедельно</div>
</div>
<div class="right">
<button class="btn btn-tertiary btn-compact">Снимок PDF</button>
<button class="btn btn-secondary btn-compact">Export CSV ⤓</button>
</div>
</div>
<nav class="a-tabs" aria-label="Разделы аналитики">
<a href="analytics.html" aria-current="page">Свердл рынок</a>
<a href="site-finder.html">Рекомендатор</a>
<a href="developers.html">Девелоперы</a>
<a href="#">PRINZIP · профиль</a>
<a href="#">Объекты</a>
</nav>
<div class="headline-bar" role="status">
<span class="tag">вердикт квартала</span>
<p class="verdict">Дефицит средне-большого жилья <b>80+ м²</b>: <b>37%</b> сделок Росреестра, но <b>11%</b> портфеля ДОМ.РФ. Окно сужается к <b>Q3 2026</b>.</p>
<span class="caveat">источник: ДОМ.РФ · Росреестр · март 2026</span>
</div>
<div class="kpi-row">
<div class="kpi">
<div class="label">Объём строительства</div>
<div class="value">5,82<small>млн м²</small></div>
<div class="hint">в активной фазе по области</div>
<span class="delta pos">↑ 4,1% YoY</span>
</div>
<div class="kpi">
<div class="label">Sold % (медиана)</div>
<div class="value">61,4 %</div>
<div class="hint">объекты в продаже &gt; 6 мес</div>
<span class="delta neg">↓ 3,2 пп QoQ</span>
</div>
<div class="kpi">
<div class="label">Средняя цена</div>
<div class="value">186<small>тыс ₽/м²</small></div>
<div class="hint">первичка, март 2026</div>
<span class="delta pos">↑ 1,8% MoM</span>
</div>
<div class="kpi">
<div class="label">Активных новостроек</div>
<div class="value">347</div>
<div class="hint">в открытой продаже Я.Недв</div>
<span class="delta pos">+12 за месяц</span>
</div>
</div>
<section class="section">
<div class="section-head">
<div>
<h2>Карта рынка — новостройки Свердловской области</h2>
<div class="sub">347 объектов в активной продаже · цвет точки — sold % за 6 месяцев · клик → drill-in</div>
</div>
<div class="right">
<button class="chip" aria-pressed="true">все классы</button>
<button class="chip">комфорт</button>
<button class="chip">бизнес</button>
<button class="chip">премиум</button>
<button class="btn btn-secondary btn-compact">Export GeoJSON ⤓</button>
</div>
</div>
<div class="map-wrap">
<svg viewBox="0 0 1200 480" preserveAspectRatio="xMidYMid slice" role="img" aria-label="Карта новостроек Екатеринбурга и окрестностей">
<defs>
<pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
<path d="M 40 0 L 0 0 0 40" fill="none" stroke="#DDE3EB" stroke-width="0.5"/>
</pattern>
</defs>
<rect width="1200" height="480" fill="url(#grid)"/>
<path d="M 100 80 Q 280 180 380 220 T 700 280 Q 880 320 1100 380" stroke="#0EA5E9" stroke-width="3.5" fill="none" opacity="0.45" stroke-linecap="round"/>
<path d="M 0 240 L 1200 240" stroke="#C5CCD6" stroke-width="2" opacity="0.6"/>
<path d="M 600 0 L 600 480" stroke="#C5CCD6" stroke-width="2" opacity="0.6"/>
<path d="M 180 0 Q 380 240 580 480" stroke="#C5CCD6" stroke-width="1.5" opacity="0.5"/>
<path d="M 850 0 Q 700 240 850 480" stroke="#C5CCD6" stroke-width="1.5" opacity="0.5"/>
<text x="280" y="110" font-family="Inter,sans-serif" font-size="11" fill="#5B6066" font-weight="500">Академический</text>
<text x="540" y="160" font-family="Inter,sans-serif" font-size="11" fill="#5B6066" font-weight="500">ВИЗ</text>
<text x="730" y="200" font-family="Inter,sans-serif" font-size="11" fill="#5B6066" font-weight="500">Центр</text>
<text x="920" y="270" font-family="Inter,sans-serif" font-size="11" fill="#5B6066" font-weight="500">Пионерский</text>
<text x="380" y="330" font-family="Inter,sans-serif" font-size="11" fill="#5B6066" font-weight="500">Юго-Запад</text>
<text x="680" y="380" font-family="Inter,sans-serif" font-size="11" fill="#5B6066" font-weight="500">Уралмаш</text>
<text x="980" y="420" font-family="Inter,sans-serif" font-size="11" fill="#5B6066" font-weight="500">Эльмаш</text>
<g id="markers">
<circle cx="220" cy="140" r="6" fill="#B3261E" stroke="#fff" stroke-width="2"/>
<circle cx="250" cy="160" r="6" fill="#B3261E" stroke="#fff" stroke-width="2"/>
<circle cx="310" cy="155" r="5" fill="#B3261E" stroke="#fff" stroke-width="2"/>
<circle cx="940" cy="290" r="5" fill="#B3261E" stroke="#fff" stroke-width="2"/>
<circle cx="290" cy="130" r="5" fill="#F59E0B" stroke="#fff" stroke-width="2"/>
<circle cx="340" cy="170" r="6" fill="#F59E0B" stroke="#fff" stroke-width="2"/>
<circle cx="520" cy="180" r="5" fill="#F59E0B" stroke="#fff" stroke-width="2"/>
<circle cx="570" cy="200" r="6" fill="#F59E0B" stroke="#fff" stroke-width="2"/>
<circle cx="650" cy="170" r="5" fill="#F59E0B" stroke="#fff" stroke-width="2"/>
<circle cx="720" cy="220" r="6" fill="#F59E0B" stroke="#fff" stroke-width="2"/>
<circle cx="790" cy="190" r="5" fill="#F59E0B" stroke="#fff" stroke-width="2"/>
<circle cx="900" cy="260" r="6" fill="#F59E0B" stroke="#fff" stroke-width="2"/>
<circle cx="380" cy="360" r="5" fill="#F59E0B" stroke="#fff" stroke-width="2"/>
<circle cx="420" cy="340" r="6" fill="#F59E0B" stroke="#fff" stroke-width="2"/>
<circle cx="700" cy="400" r="5" fill="#F59E0B" stroke="#fff" stroke-width="2"/>
<circle cx="240" cy="180" r="6" fill="#14B8A6" stroke="#fff" stroke-width="2"/>
<circle cx="610" cy="140" r="5" fill="#14B8A6" stroke="#fff" stroke-width="2"/>
<circle cx="670" cy="190" r="6" fill="#14B8A6" stroke="#fff" stroke-width="2"/>
<circle cx="800" cy="230" r="5" fill="#14B8A6" stroke="#fff" stroke-width="2"/>
<circle cx="450" cy="280" r="6" fill="#14B8A6" stroke="#fff" stroke-width="2"/>
<circle cx="500" cy="320" r="5" fill="#14B8A6" stroke="#fff" stroke-width="2"/>
<circle cx="970" cy="380" r="6" fill="#14B8A6" stroke="#fff" stroke-width="2"/>
<circle cx="1020" cy="410" r="5" fill="#14B8A6" stroke="#fff" stroke-width="2"/>
<circle cx="320" cy="220" r="7" fill="#0A7A3A" stroke="#fff" stroke-width="2"/>
<circle cx="560" cy="240" r="6" fill="#0A7A3A" stroke="#fff" stroke-width="2"/>
<circle cx="640" cy="280" r="7" fill="#0A7A3A" stroke="#fff" stroke-width="2"/>
<circle cx="730" cy="320" r="6" fill="#0A7A3A" stroke="#fff" stroke-width="2"/>
<circle cx="850" cy="350" r="7" fill="#0A7A3A" stroke="#fff" stroke-width="2"/>
</g>
</svg>
<div class="map-controls">
<button aria-label="Zoom in">+</button>
<button aria-label="Zoom out"></button>
<button aria-label="Сбросить вид"></button>
</div>
<div class="map-legend">
<h4>Sold % за 6 мес</h4>
<div class="row"><span class="pip" style="background:#B3261E"></span>&lt; 40 % · риск затоваривания</div>
<div class="row"><span class="pip" style="background:#F59E0B"></span>4065 % · средний темп</div>
<div class="row"><span class="pip" style="background:#14B8A6"></span>6580 % · хороший темп</div>
<div class="row"><span class="pip" style="background:#0A7A3A"></span>80+ % · близко к закрытию</div>
</div>
<div class="map-tooltip" role="tooltip">
<div class="name">ЖК «Каменные палатки» · PRINZIP</div>
<div class="meta">Академический · комфорт · 1 824 кв</div>
<div class="stat"><span>Sold %</span><b style="color:var(--success);">78 %</b></div>
<div class="stat"><span>Срок продаж</span><b>22 мес</b></div>
<div class="stat"><span>Ср. цена</span><b>173 тыс ₽/м²</b></div>
</div>
</div>
<div style="margin-top:12px;font-size:12px;color:var(--fg-tertiary);">Карта стилизована для превью. В продукте — Leaflet с базой 2GIS, клик → /analytics/objects/[id]</div>
</section>
<section class="section">
<div class="section-head">
<div>
<h2>Динамика рынка — 14 месяцев</h2>
<div class="sub">Объём ДДУ (Росреестр) и две линии: sold % портфеля и средняя цена м²</div>
</div>
<div class="right">
<button class="chip" aria-pressed="true">14 мес</button>
<button class="chip">12 мес</button>
<button class="chip">6 мес</button>
<button class="btn btn-secondary btn-compact">Export CSV ⤓</button>
</div>
</div>
<div class="pulse-wrap">
<div class="pulse-chart">
<svg viewBox="0 0 800 280" preserveAspectRatio="none">
<g stroke="#EEF0F3" stroke-width="1">
<line x1="0" y1="56" x2="800" y2="56"/>
<line x1="0" y1="112" x2="800" y2="112"/>
<line x1="0" y1="168" x2="800" y2="168"/>
<line x1="0" y1="224" x2="800" y2="224"/>
</g>
<g fill="#DBEAFE">
<rect x="20" y="180" width="36" height="100"/>
<rect x="76" y="190" width="36" height="90"/>
<rect x="132" y="170" width="36" height="110"/>
<rect x="188" y="160" width="36" height="120"/>
<rect x="244" y="150" width="36" height="130"/>
<rect x="300" y="140" width="36" height="140"/>
<rect x="356" y="155" width="36" height="125"/>
<rect x="412" y="130" width="36" height="150"/>
<rect x="468" y="120" width="36" height="160"/>
<rect x="524" y="135" width="36" height="145"/>
<rect x="580" y="115" width="36" height="165"/>
<rect x="636" y="105" width="36" height="175"/>
<rect x="692" y="125" width="36" height="155"/>
<rect x="748" y="110" width="36" height="170"/>
</g>
<polyline fill="none" stroke="#1D4ED8" stroke-width="2.5" points="38,90 94,82 150,98 206,76 262,68 318,72 374,84 430,60 486,52 542,66 598,48 654,42 710,58 766,46"/>
<g fill="#1D4ED8">
<circle cx="38" cy="90" r="3"/><circle cx="94" cy="82" r="3"/><circle cx="150" cy="98" r="3"/><circle cx="206" cy="76" r="3"/>
<circle cx="262" cy="68" r="3"/><circle cx="318" cy="72" r="3"/><circle cx="374" cy="84" r="3"/><circle cx="430" cy="60" r="3"/>
<circle cx="486" cy="52" r="3"/><circle cx="542" cy="66" r="3"/><circle cx="598" cy="48" r="3"/><circle cx="654" cy="42" r="3"/>
<circle cx="710" cy="58" r="3"/><circle cx="766" cy="46" r="3"/>
</g>
<polyline fill="none" stroke="#F59E0B" stroke-width="2" points="38,140 94,138 150,134 206,128 262,126 318,120 374,116 430,112 486,108 542,102 598,98 654,92 710,88 766,84"/>
<g font-family="ui-monospace,Menlo" font-size="9" fill="#73767E">
<text x="34" y="276">фев</text><text x="90" y="276">мар</text><text x="146" y="276">апр</text><text x="202" y="276">май</text>
<text x="258" y="276">июн</text><text x="316" y="276">июл</text><text x="372" y="276">авг</text><text x="428" y="276">сен</text>
<text x="484" y="276">окт</text><text x="540" y="276">ноя</text><text x="596" y="276">дек</text><text x="654" y="276">янв</text>
<text x="710" y="276">фев</text><text x="764" y="276">мар</text>
</g>
</svg>
</div>
<aside class="pulse-legend">
<div class="leg-row"><span class="sw" style="background:#DBEAFE"></span><span class="name">Объём ДДУ</span><span class="meta">62 415</span></div>
<div class="leg-row"><span class="sw" style="background:#1D4ED8"></span><span class="name">Sold %</span><span class="meta">61,4 % · ↓ 3,2 пп</span></div>
<div class="leg-row"><span class="sw" style="background:#F59E0B"></span><span class="name">Цена ₽/м²</span><span class="meta">186 тыс · ↑ 12 %</span></div>
<div style="margin-top:16px;padding-top:16px;border-top:1px solid var(--border-soft);font-size:11.5px;color:var(--fg-secondary);line-height:1.5;">
Левая ось — sold % (синяя), правая ось — цена ₽/м² (оранжевая). Бары — объём ДДУ помесячно. Hover на точку — раскладка по классу жилья.
</div>
</aside>
</div>
</section>
<section class="section">
<div class="section-head">
<div>
<h2>Парадокс портфеля по комнатности</h2>
<div class="sub">Доля сегмента в портфеле ДОМ.РФ против доли в сделках Росреестра за 14 мес</div>
</div>
<div class="right">
<button class="chip" aria-pressed="true">вся область</button>
<button class="chip">Екатеринбург</button>
<button class="chip">область без ЕКБ</button>
<button class="btn btn-secondary btn-compact">Export CSV ⤓</button>
</div>
</div>
<div class="qg-table" role="table">
<div class="qg-row">
<div class="qg-cell qg-name">Сегмент</div>
<div class="qg-cell"><span style="font-size:10.5px;letter-spacing:0.04em;text-transform:uppercase;color:var(--fg-secondary);font-weight:500;">портфель ДОМ.РФ vs сделки Росреестра</span></div>
<div class="qg-cell" style="justify-content:flex-end;"><span style="font-size:10.5px;letter-spacing:0.04em;text-transform:uppercase;color:var(--fg-secondary);font-weight:500;">Δ пп</span></div>
</div>
<div class="qg-row">
<div class="qg-cell qg-name">Студии до 30 м²</div>
<div class="qg-cell qg-bars"><div class="qg-bar supply" style="width:78%"><span class="v">24%</span></div><div class="qg-bar demand" style="width:30%"><span class="v">9%</span></div></div>
<div class="qg-cell" style="justify-content:flex-end;"><span class="qg-delta neg">15</span></div>
</div>
<div class="qg-row">
<div class="qg-cell qg-name">1-комн. 3045 м²</div>
<div class="qg-cell qg-bars"><div class="qg-bar supply" style="width:88%"><span class="v">31%</span></div><div class="qg-bar demand" style="width:72%"><span class="v">24%</span></div></div>
<div class="qg-cell" style="justify-content:flex-end;"><span class="qg-delta neg">7</span></div>
</div>
<div class="qg-row">
<div class="qg-cell qg-name">2-комн. 4565 м²</div>
<div class="qg-cell qg-bars"><div class="qg-bar supply" style="width:62%"><span class="v">22%</span></div><div class="qg-bar demand" style="width:66%"><span class="v">23%</span></div></div>
<div class="qg-cell" style="justify-content:flex-end;"><span class="qg-delta flat">+1</span></div>
</div>
<div class="qg-row">
<div class="qg-cell qg-name">3-комн. 6585 м²</div>
<div class="qg-cell qg-bars"><div class="qg-bar supply" style="width:38%"><span class="v">13%</span></div><div class="qg-bar demand" style="width:72%"><span class="v">24%</span></div></div>
<div class="qg-cell" style="justify-content:flex-end;"><span class="qg-delta pos">+11</span></div>
</div>
<div class="qg-row">
<div class="qg-cell qg-name">4+ комн. / 85+ м²</div>
<div class="qg-cell qg-bars"><div class="qg-bar supply" style="width:32%"><span class="v">11%</span></div><div class="qg-bar demand" style="width:58%"><span class="v">20%</span></div></div>
<div class="qg-cell" style="justify-content:flex-end;"><span class="qg-delta pos">+9</span></div>
</div>
</div>
</section>
<div class="two-col">
<section class="section" style="margin-bottom:0;">
<div class="section-head">
<div>
<h2>Pipeline по году ввода</h2>
<div class="sub">Объём (тыс. м²) в разрезе классов</div>
</div>
<div class="right">
<button class="btn btn-secondary btn-compact">Export CSV ⤓</button>
</div>
</div>
<div class="pipeline">
<div class="pipe-row"><span class="year">2024</span><div class="stack"><div class="seg" style="width:42%;background:#93C5FD"></div><div class="seg" style="width:34%;background:#3B82F6"></div><div class="seg" style="width:18%;background:#1D4ED8"></div><div class="seg" style="width:6%;background:#1E3A8A"></div></div><span class="total">1 240</span></div>
<div class="pipe-row"><span class="year">2025</span><div class="stack"><div class="seg" style="width:48%;background:#93C5FD"></div><div class="seg" style="width:30%;background:#3B82F6"></div><div class="seg" style="width:16%;background:#1D4ED8"></div><div class="seg" style="width:6%;background:#1E3A8A"></div></div><span class="total">1 820</span></div>
<div class="pipe-row"><span class="year">2026</span><div class="stack"><div class="seg" style="width:52%;background:#93C5FD"></div><div class="seg" style="width:28%;background:#3B82F6"></div><div class="seg" style="width:14%;background:#1D4ED8"></div><div class="seg" style="width:6%;background:#1E3A8A"></div></div><span class="total">2 110</span></div>
<div class="pipe-row"><span class="year">2027</span><div class="stack"><div class="seg" style="width:56%;background:#93C5FD"></div><div class="seg" style="width:26%;background:#3B82F6"></div><div class="seg" style="width:12%;background:#1D4ED8"></div><div class="seg" style="width:6%;background:#1E3A8A"></div></div><span class="total">2 580</span></div>
<div class="pipe-row"><span class="year">2028</span><div class="stack"><div class="seg" style="width:60%;background:#93C5FD"></div><div class="seg" style="width:24%;background:#3B82F6"></div><div class="seg" style="width:11%;background:#1D4ED8"></div><div class="seg" style="width:5%;background:#1E3A8A"></div></div><span class="total">1 970</span></div>
</div>
<div style="margin-top:16px;display:flex;gap:16px;font-size:11.5px;color:var(--fg-secondary);flex-wrap:wrap;">
<span style="display:inline-flex;align-items:center;gap:6px;"><span style="width:10px;height:10px;background:#93C5FD;border-radius:2px;"></span>комфорт</span>
<span style="display:inline-flex;align-items:center;gap:6px;"><span style="width:10px;height:10px;background:#3B82F6;border-radius:2px;"></span>бизнес</span>
<span style="display:inline-flex;align-items:center;gap:6px;"><span style="width:10px;height:10px;background:#1D4ED8;border-radius:2px;"></span>премиум</span>
<span style="display:inline-flex;align-items:center;gap:6px;"><span style="width:10px;height:10px;background:#1E3A8A;border-radius:2px;"></span>элит</span>
</div>
</section>
<section class="section" style="margin-bottom:0;">
<div class="section-head">
<div>
<h2>Активные новостройки</h2>
<div class="sub">Топ-7 по объёму · Я.Недвижимость · обновлено 4 ч назад</div>
</div>
<div class="right">
<button class="btn btn-secondary btn-compact">Export CSV ⤓</button>
</div>
</div>
<table class="ann-table">
<thead>
<tr><th>ЖК</th><th>Девелопер</th><th>Sold %</th><th>Ср. цена</th></tr>
</thead>
<tbody>
<tr><td><a href="#">Каменные палатки</a></td><td>PRINZIP</td><td class="num">78 %</td><td class="num">173 ₽</td></tr>
<tr><td><a href="#">Северная корона</a></td><td>Брусника</td><td class="num">71 %</td><td class="num">198 ₽</td></tr>
<tr><td><a href="#">Чкалов</a></td><td>Атомстройком.</td><td class="num">64 %</td><td class="num">156 ₽</td></tr>
<tr><td><a href="#">Малевич</a></td><td>Форум-групп</td><td class="num">58 %</td><td class="num">182 ₽</td></tr>
<tr><td><a href="#">Уют</a></td><td>Атлас Девел.</td><td class="num">52 %</td><td class="num">141 ₽</td></tr>
<tr><td><a href="#">Гольф-парк</a></td><td>КОРТРОС</td><td class="num">41 %</td><td class="num">224 ₽</td></tr>
<tr><td><a href="#">Эталон City</a></td><td>Эталон</td><td class="num">38 %</td><td class="num">167 ₽</td></tr>
</tbody>
</table>
</section>
</div>
<section class="section">
<div class="section-head">
<div>
<h2>Концентрация ЖК по районам</h2>
<div class="sub">Площадь плитки — объём строительства · цвет — sold % · клик → топ девелоперов района</div>
</div>
<div class="right">
<button class="chip" aria-pressed="true">по объёму</button>
<button class="chip">по числу ЖК</button>
<button class="chip">по выручке</button>
</div>
</div>
<div class="treemap">
<a href="developers.html" class="tile lvl-4" style="grid-column:span 4;grid-row:span 2;"><span class="t-name">Академический</span><span class="t-meta">42 ЖК · 824 тыс м² · sold 71 %</span></a>
<a href="developers.html" class="tile lvl-3" style="grid-column:span 3;grid-row:span 2;"><span class="t-name">Центр</span><span class="t-meta">28 ЖК · 612 тыс м² · sold 64 %</span></a>
<a href="developers.html" class="tile lvl-5" style="grid-column:span 3;grid-row:span 2;"><span class="t-name">ВИЗ</span><span class="t-meta">31 ЖК · 588 тыс м² · sold 48 %</span></a>
<a href="developers.html" class="tile lvl-2" style="grid-column:span 2;grid-row:span 2;"><span class="t-name">Пионерский</span><span class="t-meta">19 ЖК · 411 тыс м²</span></a>
<a href="developers.html" class="tile lvl-4" style="grid-column:span 3;"><span class="t-name">Юго-Запад</span><span class="t-meta">14 · 386 тыс м²</span></a>
<a href="developers.html" class="tile lvl-2" style="grid-column:span 3;"><span class="t-name">Уралмаш</span><span class="t-meta">11 · 254 тыс м²</span></a>
<a href="developers.html" class="tile lvl-3" style="grid-column:span 2;"><span class="t-name">Эльмаш</span><span class="t-meta">8 · 198</span></a>
<a href="developers.html" class="tile lvl-1" style="grid-column:span 2;"><span class="t-name">Сортировка</span><span class="t-meta">6 · 142</span></a>
<a href="developers.html" class="tile lvl-3" style="grid-column:span 2;"><span class="t-name">Уктус</span><span class="t-meta">7 · 168</span></a>
<a href="developers.html" class="tile lvl-1" style="grid-column:span 2;"><span class="t-name">Химмаш</span><span class="t-meta">4 · 96</span></a>
<a href="developers.html" class="tile lvl-2" style="grid-column:span 3;"><span class="t-name">Широкая речка</span><span class="t-meta">5 · 124 тыс м²</span></a>
<a href="developers.html" class="tile lvl-1" style="grid-column:span 3;"><span class="t-name">Верхняя Пышма</span><span class="t-meta">12 · 218 тыс м²</span></a>
</div>
</section>
<div class="caveat-bar">
<span class="icon">!</span>
<div>
<b>Caveat по данным.</b> Sold % считается по объектам в продаже более 6 месяцев; новые ЖК со стартом &lt; 6 мес не входят в медиану, но видны на карте. Росреестр может задерживать ДДУ до 14 дней — берём 7-дневный backfill при еженедельном пересчёте.
</div>
</div>
<details class="acc">
<summary>Развёрнутый разрез по 17 районам области</summary>
<div class="acc-body">Sold %, средний срок, цена м², объём в работе — по каждому из 17 районов с фильтром по классу. Открывается отдельной таблицей в /analytics/districts.</div>
</details>
<details class="acc">
<summary>Методология подсчёта sold %</summary>
<div class="acc-body">Sold % = (общее число проданных лотов по объекту) / (общее число лотов в продаже). Источник: ДДУ Росреестра матчатся с лотами портфеля ДОМ.РФ по cadastral_id + comm_name fuzzy match (порог 0.85, pg_trgm).</div>
</details>
<details class="acc">
<summary>Сравнение с январём 2025 (год к году)</summary>
<div class="acc-body">Sold % медиана: 64,6 % → 61,4 % (3,2 пп). Объём строительства: 5,59 → 5,82 млн м² (+4,1 %). Средняя цена: 166 → 186 тыс ₽/м² (+12 %). Разрыв спрос-предложение в 3к/4+ сегменте увеличился: с +14 пп до +20 пп суммарно.</div>
</details>
</main>
</body>
</html>