gendesign/preview/site-finder.html
lekss361 f1bc821c2b feat(preview): add static mockups behind basic auth at /preview/*
4 HTML mockups (landing/site-finder/analytics/monitoring) — alternative
designs для audit-review без замены существующих React-страниц.

- Caddy file_server на handle_path /preview/* (внутри gendsgn.ru block)
- Bind mount ./preview:/srv/preview:ro в caddy container
- basic auth: user=preview / pwd shared via private channel
- Static, isolated — не влияет на /, /site-finder, /analytics (Next.js routes)
2026-05-17 11:15:13 +03:00

597 lines
38 KiB
HTML
Raw 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/recommend — Рекомендатор площадки · 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 { 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; }
/* ============ LAYOUT — form left, result right ============ */
.rec-grid { display:grid; grid-template-columns:340px 1fr; gap:24px; align-items:start; }
.form-card { position:sticky; top:88px; background:var(--bg-card); border:1px solid var(--border-card); border-radius:12px; padding:20px; }
.form-card h2 { font-size:16px; font-weight:600; margin-bottom:4px; }
.form-card .sub { font-size:12.5px; color:var(--fg-secondary); margin-bottom:16px; }
.field { margin-bottom:16px; }
.field label { display:block; font-size:11px; letter-spacing:0.04em; text-transform:uppercase; color:var(--fg-secondary); font-weight:500; margin-bottom:6px; }
.field input, .field select { width:100%; height:36px; padding:0 12px; border:1px solid var(--border-strong); border-radius:6px; background:var(--bg-card); font:inherit; color:var(--fg-primary); font-variant-numeric:tabular-nums; }
.field input:focus, .field select:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-soft); }
.field .row2 { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
.field .with-suffix { position:relative; }
.field .with-suffix .suf { position:absolute; right:12px; top:50%; transform:translateY(-50%); font-size:12px; color:var(--fg-tertiary); pointer-events:none; }
.chip-group { display:flex; flex-wrap:wrap; gap:4px; }
.chip-group .chip { display:inline-flex; align-items:center; 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); cursor:pointer; transition:all .12s; }
.chip-group .chip[aria-pressed="true"] { color:var(--accent); background:var(--accent-soft); border-color:var(--accent-soft); }
.form-cta { margin-top:16px; padding-top:16px; border-top:1px solid var(--border-soft); }
.form-cta .btn-primary { width:100%; justify-content:center; }
.form-meta { margin-top:12px; font-size:11.5px; color:var(--fg-tertiary); line-height:1.5; }
/* ============ RESULT ============ */
.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-3 { display:grid; grid-template-columns:repeat(3,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); height:44px; padding:0 20px; font-size:14px; }
.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; }
/* ============ VELOCITY PANEL (slider + live KPI) ============ */
.velocity { display:grid; grid-template-columns:1fr 280px; gap:24px; align-items:start; }
.velocity-slider { padding-top:16px; }
.velocity-slider .lbl-row { display:flex; justify-content:space-between; align-items:baseline; margin-bottom:12px; }
.velocity-slider .lbl-row .name { font-size:13px; font-weight:500; color:var(--fg-primary); }
.velocity-slider .lbl-row .val { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:13px; font-weight:600; color:var(--accent); font-variant-numeric:tabular-nums; }
.slider-track { position:relative; height:8px; background:var(--bg-card-alt); border-radius:4px; }
.slider-track .fill { position:absolute; top:0; left:0; height:100%; background:var(--accent); border-radius:4px; width:62%; }
.slider-track .handle { position:absolute; top:50%; left:62%; transform:translate(-50%,-50%); width:20px; height:20px; background:#fff; border:2px solid var(--accent); border-radius:50%; cursor:grab; box-shadow:0 1px 4px rgba(0,0,0,0.1); }
.slider-ticks { display:flex; justify-content:space-between; margin-top:8px; font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:10px; color:var(--fg-tertiary); }
.velocity-side { background:var(--bg-card-alt); border:1px solid var(--border-soft); border-radius:8px; padding:16px; }
.velocity-side h3 { font-size:11px; letter-spacing:0.04em; text-transform:uppercase; color:var(--fg-secondary); font-weight:500; margin-bottom:12px; }
.velocity-side .row { display:flex; justify-content:space-between; align-items:baseline; padding:8px 0; border-top:1px solid var(--border-soft); }
.velocity-side .row:first-of-type { border-top:0; padding-top:0; }
.velocity-side .row .lbl { font-size:12.5px; color:var(--fg-secondary); }
.velocity-side .row .val { font-size:14px; font-weight:600; color:var(--fg-primary); font-variant-numeric:tabular-nums; }
.velocity-side .row .val.pos { color:var(--success); }
.velocity-side .row .val.neg { color:var(--danger); }
/* ============ MIX SLIDERS ============ */
.mix-list { display:flex; flex-direction:column; gap:12px; }
.mix-row { display:grid; grid-template-columns:130px 1fr 60px 80px; gap:12px; align-items:center; }
.mix-row .name { font-size:13px; color:var(--fg-primary); font-weight:500; }
.mix-row .bar-wrap { height:8px; background:var(--bg-card-alt); border-radius:4px; position:relative; }
.mix-row .bar-wrap .fill { height:100%; border-radius:4px; background:var(--accent); }
.mix-row .pct { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:13px; font-weight:600; color:var(--fg-primary); text-align:right; font-variant-numeric:tabular-nums; }
.mix-row .pop { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:11.5px; color:var(--fg-secondary); text-align:right; font-variant-numeric:tabular-nums; }
.mix-foot { margin-top:16px; padding-top:12px; border-top:1px solid var(--border-soft); display:flex; justify-content:space-between; font-size:12.5px; color:var(--fg-secondary); }
.mix-foot b { color:var(--fg-primary); font-weight:600; }
/* ============ DISTRICT KPI GRID (5 cards) ============ */
.dist-grid { display:grid; grid-template-columns:repeat(5,1fr); gap:8px; }
.dist-cell { background:var(--bg-card-alt); border:1px solid var(--border-soft); border-radius:8px; padding:12px 14px; }
.dist-cell .lbl { font-size:10.5px; letter-spacing:0.04em; text-transform:uppercase; color:var(--fg-secondary); font-weight:500; }
.dist-cell .val { font-size:20px; font-weight:600; color:var(--fg-primary); letter-spacing:-0.01em; margin-top:4px; font-variant-numeric:tabular-nums; }
.dist-cell .meta { font-size:11.5px; color:var(--fg-tertiary); margin-top:4px; }
.dist-cell.warn .val { color:var(--warn); }
.dist-cell.ok .val { color:var(--success); }
/* ============ LIQUIDITY CHART ============ */
.liq-chart { position:relative; height:240px; border-left:1px solid var(--border-soft); border-bottom:1px solid var(--border-soft); }
.liq-chart svg { width:100%; height:100%; display:block; }
/* ============ BUCKETS CHART + TABLE ============ */
.buckets-row { display:grid; grid-template-columns:1fr 1fr; gap:24px; }
.bucket-chart { padding:8px 0; }
.bucket-chart svg { width:100%; height:200px; display:block; }
.buckets-table { width:100%; border-collapse:collapse; }
.buckets-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); }
.buckets-table th:not(:first-child), .buckets-table td:not(:first-child) { text-align:right; }
.buckets-table td { font-size:13px; padding:10px 8px 10px 0; border-bottom:1px solid var(--border-soft); color:var(--fg-primary); font-variant-numeric:tabular-nums; }
.buckets-table tr:last-child td { border-bottom:0; }
.buckets-table tr.total td { font-weight:600; background:var(--bg-card-alt); border-top:2px solid var(--border-card); }
/* ============ COMPARABLES ============ */
.comparables { display:flex; flex-direction:column; gap:8px; }
.comp-row { display:grid; grid-template-columns:1fr 100px 80px 70px 80px; gap:12px; align-items:center; padding:10px 0; border-top:1px solid var(--border-soft); }
.comp-row:first-child { border-top:0; }
.comp-row .name a { color:var(--accent); font-weight:500; font-size:13px; }
.comp-row .name a:hover { text-decoration:underline; }
.comp-row .name .meta { font-size:11.5px; color:var(--fg-secondary); margin-top:2px; }
.comp-row .num { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:13px; font-weight:500; text-align:right; font-variant-numeric:tabular-nums; }
/* ============ ACCORDIONS ============ */
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; }
details.acc[open] summary::after { content:''; }
details.acc .acc-body { padding:0 20px 20px; font-size:13px; color:var(--fg-primary); line-height:1.55; }
/* ============ CAVEAT ============ */
.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) {
.rec-grid { grid-template-columns:1fr; }
.form-card { position:relative; top:auto; }
.kpi-row-3 { grid-template-columns:1fr; }
.velocity { grid-template-columns:1fr; }
.dist-grid { grid-template-columns:repeat(2,1fr); }
.buckets-row { grid-template-columns:1fr; }
}
</style>
</head>
<body>
<aside class="dev-nav" aria-label="Dev navigation">
<span class="dev-label">DEV · ТОЛЬКО ДЛЯ РАЗРАБОТКИ</span>
<nav class="dev-tabs" aria-label="WIP страницы">
<a href="landing.html">лендинг</a>
<a href="analytics.html">/analytics</a>
<a href="site-finder.html" aria-current="page">/recommend</a>
<a href="monitoring.html">/developers</a>
<span class="dev-sep"></span>
<a href="audit.html">audit&nbsp;(live)</a>
<a href="gendsgn-audit.html">audit&nbsp;(отчёт)</a>
</nav>
<span class="dev-hint">временная панель · скроется в print</span>
</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>
</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>
<a href="analytics.html">analytics</a>
<span class="sep">/</span>
<span class="last">recommend — рекомендатор площадки</span>
</nav>
<div class="page-head">
<div>
<h1>Рекомендатор площадки</h1>
<div class="sub">Mix квартир по комнатности, прогноз срока 80 % продаж, расчёт выручки на основе sold % сегмента и района</div>
</div>
</div>
<nav class="a-tabs" aria-label="Разделы аналитики">
<a href="analytics.html">Свердл рынок</a>
<a href="site-finder.html" aria-current="page">Рекомендатор</a>
<a href="monitoring.html">Девелоперы</a>
<a href="#">PRINZIP · профиль</a>
<a href="#">Объекты</a>
</nav>
<div class="rec-grid">
<!-- LEFT: form -->
<aside class="form-card" aria-label="Параметры площадки">
<h2>Параметры площадки</h2>
<div class="sub">Заполните, рекомендатор пересчитает за &lt; 1 сек</div>
<div class="field">
<label for="f-district">Район</label>
<select id="f-district">
<option>Академический</option>
<option>Центр</option>
<option>ВИЗ</option>
<option>Пионерский</option>
<option>Юго-Запад</option>
<option>Уралмаш</option>
<option>Уктус</option>
</select>
</div>
<div class="field">
<label>Класс жилья</label>
<div class="chip-group" role="group">
<button class="chip" aria-pressed="false">эконом</button>
<button class="chip" aria-pressed="true">комфорт</button>
<button class="chip" aria-pressed="false">бизнес</button>
<button class="chip" aria-pressed="false">премиум</button>
</div>
</div>
<div class="field">
<label for="f-area">Площадь застройки</label>
<div class="with-suffix">
<input id="f-area" type="text" value="12 000" />
<span class="suf">м²</span>
</div>
</div>
<div class="field">
<label>Окно ввода</label>
<div class="row2">
<div class="with-suffix"><input type="text" value="Q3 2026" /></div>
<div class="with-suffix"><input type="text" value="Q1 2028" /></div>
</div>
</div>
<div class="field">
<label for="f-target">Целевой срок 80 % продаж</label>
<div class="with-suffix">
<input id="f-target" type="text" value="24" />
<span class="suf">мес</span>
</div>
</div>
<div class="field">
<label for="f-price">Price factor</label>
<div class="with-suffix">
<input id="f-price" type="text" value="1,00" />
<span class="suf">× медианы района</span>
</div>
</div>
<div class="form-cta">
<button class="btn btn-primary">Рассчитать</button>
<div class="form-meta">Расчёт по 6 832 411 ДДУ Росреестра и портфелю ДОМ.РФ. Доверительный интервал ±p25/p75.</div>
</div>
</aside>
<!-- RIGHT: result -->
<div>
<div class="headline-bar" role="status">
<span class="tag">рекомендация</span>
<p class="verdict"><b>Академический</b> · комфорт · <b>12 000 м²</b>: mix <b>32/26/22/15/5</b> · срок 80 % продаж <b>22 мес</b> · выручка <b>2,4 млрд ₽</b></p>
<span class="caveat">пересчитано: 12 сек назад</span>
</div>
<!-- 3 KPI -->
<div class="kpi-row-3">
<div class="kpi">
<div class="label">Выручка</div>
<div class="value">2,4<small>млрд ₽</small></div>
<div class="hint">по медианной цене района ×1,00</div>
<span class="delta pos">↑ +180 млн vs дефолтный mix</span>
</div>
<div class="kpi">
<div class="label">Срок 80 % продаж</div>
<div class="value">22<small>мес</small></div>
<div class="hint">target 24 мес — внутри окна</div>
<span class="delta pos">опережает target на 2 мес</span>
</div>
<div class="kpi">
<div class="label">Liquidity score</div>
<div class="value">7,8<small>/ 10</small></div>
<div class="hint">взвешенно по sold % сегментов</div>
<span class="delta pos">в топ-30 % площадок района</span>
</div>
</div>
<!-- Velocity Panel -->
<section class="section">
<div class="section-head">
<div>
<h2>Velocity Panel — влияние цены</h2>
<div class="sub">Сдвиньте price factor, чтобы увидеть, как меняется срок 80 % продаж и выручка</div>
</div>
</div>
<div class="velocity">
<div class="velocity-slider">
<div class="lbl-row"><span class="name">Price factor (× медианы района)</span><span class="val">1,00</span></div>
<div class="slider-track"><div class="fill"></div><div class="handle"></div></div>
<div class="slider-ticks"><span>0,75</span><span>0,85</span><span>0,95</span><span>1,00</span><span>1,10</span><span>1,20</span><span>1,30</span></div>
<div style="margin-top:16px;font-size:12.5px;color:var(--fg-secondary);line-height:1.55;">
При factor <b style="color:var(--fg-primary);">0,90</b> срок падает до <b style="color:var(--success);">18 мес</b>, выручка снижается до <b>2,16 млрд ₽</b> (240 млн). При <b style="color:var(--fg-primary);">1,15</b> срок растёт до <b style="color:var(--danger);">31 мес</b> — выходим из окна. Сладкое пятно — 0,951,05.
</div>
</div>
<aside class="velocity-side">
<h3>На текущем factor 1,00</h3>
<div class="row"><span class="lbl">Срок 80 %</span><span class="val">22 мес</span></div>
<div class="row"><span class="lbl">Выручка</span><span class="val">2,4 млрд</span></div>
<div class="row"><span class="lbl">Маржа vs target</span><span class="val pos">+ 2 мес</span></div>
<div class="row"><span class="lbl">Liquidity</span><span class="val pos">7,8 / 10</span></div>
<div class="row"><span class="lbl">Δ sold % мес</span><span class="val">3,8 пп</span></div>
</aside>
</div>
</section>
<!-- CAVEAT -->
<div class="caveat-bar">
<span class="icon">!</span>
<div>
<b>Caveat по прогнозу.</b> Срок продаж предсказывается по выборке из 38 ЖК комфорт-класса в Академическом за последние 14 мес. Доверительный интервал p25/p75: 1926 мес. Прогноз чувствителен к курсу ипотеки — при ставке &gt; 18 % сместите окно на +6 мес.
</div>
</div>
<!-- ACCORDIONS -->
<details class="acc" open>
<summary>5 KPI района — Академический · комфорт</summary>
<div class="acc-body">
<div class="dist-grid">
<div class="dist-cell"><div class="lbl">Конкуренты</div><div class="val">11</div><div class="meta">ЖК в открытой продаже</div></div>
<div class="dist-cell"><div class="lbl">Velocity покрытие</div><div class="val">94 %</div><div class="meta">38 / 40 объектов в выборке</div></div>
<div class="dist-cell ok"><div class="lbl">Sold % медиана</div><div class="val">71 %</div><div class="meta">по комфорт-классу района</div></div>
<div class="dist-cell ok"><div class="lbl">Тренд 6 мес</div><div class="val">+4,2 пп</div><div class="meta">sold % растёт</div></div>
<div class="dist-cell"><div class="lbl">Class × District</div><div class="val">A</div><div class="meta">приоритет mix-инвестиций</div></div>
</div>
</div>
</details>
<details class="acc" open>
<summary>Mix квартир — рекомендованное распределение</summary>
<div class="acc-body">
<div class="mix-list">
<div class="mix-row">
<span class="name">Студии до 30 м²</span>
<div class="bar-wrap"><div class="fill" style="width:5%"></div></div>
<span class="pct">5 %</span>
<span class="pop">≈ 38 кв</span>
</div>
<div class="mix-row">
<span class="name">1-комн. 3045 м²</span>
<div class="bar-wrap"><div class="fill" style="width:15%"></div></div>
<span class="pct">15 %</span>
<span class="pop">≈ 115 кв</span>
</div>
<div class="mix-row">
<span class="name">2-комн. 4565 м²</span>
<div class="bar-wrap"><div class="fill" style="width:22%"></div></div>
<span class="pct">22 %</span>
<span class="pop">≈ 168 кв</span>
</div>
<div class="mix-row">
<span class="name">3-комн. 6585 м²</span>
<div class="bar-wrap"><div class="fill" style="width:26%"></div></div>
<span class="pct">26 %</span>
<span class="pop">≈ 198 кв</span>
</div>
<div class="mix-row">
<span class="name">4+ комн. / 85+ м²</span>
<div class="bar-wrap"><div class="fill" style="width:32%"></div></div>
<span class="pct">32 %</span>
<span class="pop">≈ 244 кв</span>
</div>
</div>
<div class="mix-foot">
<span>Итого <b>763 кв</b> · <b>59 800 м²</b> жилой площади</span>
<span>Sold % взвешенный по mix: <b style="color:var(--success);">74,1 %</b></span>
</div>
</div>
</details>
<details class="acc">
<summary>Liquidity по месяцам — 36 мес прогноз</summary>
<div class="acc-body">
<div class="liq-chart">
<svg viewBox="0 0 800 240" preserveAspectRatio="none">
<g stroke="#EEF0F3" stroke-width="1">
<line x1="0" y1="48" x2="800" y2="48"/>
<line x1="0" y1="96" x2="800" y2="96"/>
<line x1="0" y1="144" x2="800" y2="144"/>
<line x1="0" y1="192" x2="800" y2="192"/>
</g>
<!-- prediction band -->
<path d="M 0,200 L 50,180 L 100,150 L 150,120 L 200,98 L 250,82 L 300,70 L 350,62 L 400,52 L 450,46 L 500,42 L 550,38 L 600,36 L 650,34 L 700,32 L 750,30 L 800,28 L 800,80 L 750,82 L 700,84 L 650,88 L 600,90 L 550,94 L 500,98 L 450,102 L 400,108 L 350,118 L 300,128 L 250,140 L 200,156 L 150,178 L 100,206 L 50,224 L 0,240 Z" fill="rgba(14,165,233,0.18)"/>
<!-- main line -->
<polyline fill="none" stroke="#1D4ED8" stroke-width="2.5" points="0,220 50,200 100,178 150,156 200,134 250,116 300,98 350,84 400,72 450,62 500,54 550,48 600,42 650,38 700,34 750,32 800,30"/>
<!-- 80% target line -->
<line x1="0" y1="48" x2="800" y2="48" stroke="#0A7A3A" stroke-width="1.5" stroke-dasharray="6,4"/>
<text x="6" y="42" font-family="ui-monospace,Menlo" font-size="10" fill="#0A7A3A">target 80 %</text>
<!-- 22 mo marker -->
<line x1="490" y1="0" x2="490" y2="240" stroke="#F2994A" stroke-width="1.5" stroke-dasharray="4,3"/>
<text x="496" y="14" font-family="ui-monospace,Menlo" font-size="10" fill="#F2994A">22 мес — выход на target</text>
<!-- month axis -->
<g font-family="ui-monospace,Menlo" font-size="9" fill="#73767E">
<text x="0" y="236">0</text><text x="130" y="236">6</text><text x="262" y="236">12</text><text x="394" y="236">18</text><text x="526" y="236">24</text><text x="658" y="236">30</text><text x="780" y="236">36</text>
</g>
</svg>
</div>
<div style="margin-top:12px;font-size:12px;color:var(--fg-secondary);">Прогноз кумулятивного sold % по месяцам с учётом mix. Полоса — доверительный интервал p25/p75 на основе выборки 38 ЖК комфорт-класса района.</div>
</div>
</details>
<details class="acc">
<summary>Buckets — графика + таблица + Export Excel</summary>
<div class="acc-body">
<div class="buckets-row">
<div class="bucket-chart">
<svg viewBox="0 0 400 200" preserveAspectRatio="none">
<g stroke="#EEF0F3" stroke-width="1">
<line x1="0" y1="40" x2="400" y2="40"/>
<line x1="0" y1="80" x2="400" y2="80"/>
<line x1="0" y1="120" x2="400" y2="120"/>
<line x1="0" y1="160" x2="400" y2="160"/>
</g>
<g>
<rect x="20" y="160" width="50" height="30" fill="#93C5FD"/>
<text x="45" y="155" font-family="Inter" font-size="11" fill="#5B6066" text-anchor="middle">5 %</text>
<rect x="90" y="130" width="50" height="60" fill="#60A5FA"/>
<text x="115" y="125" font-family="Inter" font-size="11" fill="#5B6066" text-anchor="middle">15 %</text>
<rect x="160" y="102" width="50" height="88" fill="#3B82F6"/>
<text x="185" y="97" font-family="Inter" font-size="11" fill="#5B6066" text-anchor="middle">22 %</text>
<rect x="230" y="86" width="50" height="104" fill="#1D4ED8"/>
<text x="255" y="81" font-family="Inter" font-size="11" fill="#5B6066" text-anchor="middle">26 %</text>
<rect x="300" y="62" width="50" height="128" fill="#1E3A8A"/>
<text x="325" y="57" font-family="Inter" font-size="11" fill="#5B6066" text-anchor="middle">32 %</text>
</g>
<g font-family="ui-monospace,Menlo" font-size="9" fill="#73767E">
<text x="45" y="200" text-anchor="middle">студ</text>
<text x="115" y="200" text-anchor="middle"></text>
<text x="185" y="200" text-anchor="middle"></text>
<text x="255" y="200" text-anchor="middle"></text>
<text x="325" y="200" text-anchor="middle">4+</text>
</g>
</svg>
</div>
<table class="buckets-table">
<thead>
<tr><th>Сегмент</th><th>Кв</th><th>м²</th><th>Выручка</th></tr>
</thead>
<tbody>
<tr><td>студии</td><td>38</td><td>1 140</td><td>180 М</td></tr>
<tr><td>1-к</td><td>115</td><td>4 600</td><td>740 М</td></tr>
<tr><td>2-к</td><td>168</td><td>9 240</td><td>1,49 Б</td></tr>
<tr><td>3-к</td><td>198</td><td>14 850</td><td>2,39 Б</td></tr>
<tr><td>4+</td><td>244</td><td>29 970</td><td>4,82 Б</td></tr>
<tr class="total"><td>Итого</td><td>763</td><td>59 800</td><td>9,62 Б</td></tr>
</tbody>
</table>
</div>
<div style="margin-top:16px;display:flex;justify-content:space-between;align-items:center;padding-top:12px;border-top:1px solid var(--border-soft);">
<span style="font-size:12.5px;color:var(--fg-secondary);">Цифры в подсказке headline-bar — это выручка по сценарию price factor 1,00. Полная выгрузка — Export Excel.</span>
<button class="btn btn-secondary btn-compact">Export Excel ⤓</button>
</div>
</div>
</details>
<details class="acc">
<summary>Comparables — топ-5 похожих ЖК в районе</summary>
<div class="acc-body">
<div class="comparables">
<div class="comp-row">
<div class="name"><a href="#">Каменные палатки</a><div class="meta">PRINZIP · комфорт · 1 824 кв</div></div>
<div class="num">78 %</div>
<div class="num">22 мес</div>
<div class="num">173 ₽</div>
<div class="num">1,4 Б</div>
</div>
<div class="comp-row">
<div class="name"><a href="#">Северная корона</a><div class="meta">Брусника · комфорт · 1 408 кв</div></div>
<div class="num">71 %</div>
<div class="num">24 мес</div>
<div class="num">198 ₽</div>
<div class="num">1,8 Б</div>
</div>
<div class="comp-row">
<div class="name"><a href="#">Светлый</a><div class="meta">Атомстройком. · комфорт · 962 кв</div></div>
<div class="num">68 %</div>
<div class="num">26 мес</div>
<div class="num">156 ₽</div>
<div class="num">0,9 Б</div>
</div>
<div class="comp-row">
<div class="name"><a href="#">Радуга-Парк</a><div class="meta">Форум-групп · комфорт · 720 кв</div></div>
<div class="num">62 %</div>
<div class="num">28 мес</div>
<div class="num">162 ₽</div>
<div class="num">0,7 Б</div>
</div>
<div class="comp-row">
<div class="name"><a href="#">Уют</a><div class="meta">Атлас Девел. · комфорт · 612 кв</div></div>
<div class="num">52 %</div>
<div class="num">31 мес</div>
<div class="num">141 ₽</div>
<div class="num">0,5 Б</div>
</div>
</div>
<div style="margin-top:12px;font-size:11.5px;color:var(--fg-secondary);">Колонки: sold %, срок 80 %, ср. цена ₽/м², оценочная выручка. Клик по названию → /analytics/objects/[id].</div>
</div>
</details>
<details class="acc">
<summary>Caveats — что важно учесть</summary>
<div class="acc-body">
<ul style="list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:8px;">
<li>• Выборка для прогноза — только ЖК с лотностью &gt; 200 кв; малоквартирные клубные дома (&lt; 100 кв) дают другой режим спроса.</li>
<li>• Расчёт не учитывает паркинг и кладовые — добавьте 47 % к выручке при наличии паркинга 1:1.</li>
<li>• Прогноз 36 мес — экстраполяция; при горизонте &gt; 24 мес доверительный интервал расширяется до p10/p90.</li>
<li>• Mix чувствителен к политике ипотеки: при ставке &gt; 18 % спрос смещается в студии и 1-к — пересмотрите mix.</li>
</ul>
</div>
</details>
</div>
</div>
</main>
</body>
</html>