887abf444e
Получен handoff-пакет liderra_v8_handoff/ от дизайнера Платона (kpd9363@gmail.com) от 07.05.2026 — v8 Forest. Заказчик 08.05 решил применить только в части дизайна, имени, логотипа. Функционал, состав страниц и правила (CTO-11, click-wrap, SSO break-glass, 14 статусов воронки) — без изменений (источник — ТЗ v8.5/schema v8.5). Что сделано: - Массовая замена Лидпоток→Лидерра (с учётом падежей: Лидерры/Лидерре) в 33 файлах (449 вхождений) — все .md/.sql/.json/.toml/.yml/.txt/.html, кроме исторических упоминаний внутри liderra_v8_handoff/ - Удалён docs/brandbook.md v1.1 — заменён на BRANDBOOK_v2.md из handoff - Скопированы 13 концептов liderra_v8_handoff/concepts/v8_*.html в web/v8/. Удалены старые web/01-login.html, 02-dashboard.html, 03-deals.html, index.html (палитра v1.1 deprecated) - CLAUDE.md v1.0→v1.1: §0 (BRANDBOOK_v2 + DEVELOPER_HANDOFF в источниках), §2 (палитра Forest, Inter+JBM, Lucide), §5 п.6 (anti-pattern Inter снят — в Forest Inter наш основной шрифт), §6 (13 концептов в web/v8/) - Реестр Открытые_вопросы_v8_3.md v1.12→v1.13: добавлена запись о ребрендинге + 4 точечных расхождений handoff vs ТЗ (статусы воронки, click-wrap чекбоксы, SSO fallback, axe violations) - package.json/package-lock.json: name lidpotok→liderra 4 расхождения handoff vs ТЗ (НЕ применены, источник истины — ТЗ/schema): 1. 14 «обобщённых» статусов в BRANDBOOK_v2 §3.6 ≠ 14 slug'ов в schema.sql:2076 (совпадает 2 из 14: «Переговоры», «Оплачено»). Источник — schema/ТЗ §6.4 (реселлерская модель из аудита crm.bp-gr.ru, 6 системных + 8 настраиваемых статусов). 2. 3-й click-wrap в v8_login.html («маркетинг-опционально») ≠ ТЗ §1.5/§4.1 («согласие на ПДн», обязательное, OPEN-Ж-3). 3. SSO в v8_admin.html («локальный 2FA fallback») ≠ ТЗ OPEN-И-13 (break-glass super_admin, локальный 2FA выключен). 4. Заявление «axe-core 4.10.2 — 0 violations» в README handoff — локально Pa11y 9.1.1 + axe нашёл 81 violation на 10/13 HTML (преимущественно color-contrast на декоративных separator'ах с --ink-disabled). Чисто: settings/errors/palette_options. Что НЕ включено в коммит: - лендинг/TZ_landing_v1_0.md — untracked, не моя работа в этой сессии - .tmp/ — gitignored Что осталось (для следующих сессий): - Возможное переименование GitHub-репо CoralMinister/lidpotok → liderra (отдельное решение заказчика) - Опционально: обратная связь Платону по 4 расхождениям handoff vs ТЗ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1153 lines
48 KiB
HTML
1153 lines
48 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>v8 · Дашборд — Лидерра (Forest)</title>
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<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:opsz,wght@14..32,400;14..32,500;14..32,600;14..32,700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
||
<style>
|
||
*, *::before, *::after { box-sizing: border-box; }
|
||
html, body { margin: 0; padding: 0; }
|
||
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.has-motion { animation: none !important; transition: none !important; }
|
||
}
|
||
|
||
:root {
|
||
/* v8 Forest — warm ivory main + deep teal-noir sidebar */
|
||
--bg: #F6F3EC;
|
||
--surface: #FFFDFA;
|
||
--sunken: #F0EDE4;
|
||
--hairline: #D9D5CD;
|
||
--hairline-soft:#E8E3D6;
|
||
|
||
--ink: #081319;
|
||
--ink-2: #343C41;
|
||
--ink-3: #66635C;
|
||
--ink-disabled: #92907B;
|
||
|
||
--accent: #0F6E56;
|
||
--accent-tint: #E1EEEA;
|
||
--accent-deep: #084635;
|
||
|
||
/* Forest sidebar tokens — dark teal-noir */
|
||
--side-bg: #012019;
|
||
--side-text: #B1C2BD; /* nav-item text on side-bg */
|
||
--side-text-2: #7A8C87; /* nav-eyebrow / muted */
|
||
--side-active: #13382F; /* active fill */
|
||
--side-icon: #5C7A72; /* nav-icon idle */
|
||
--side-icon-act: #32C8A9; /* bright Teal — accent on dark */
|
||
--side-hover: #0A2A22;
|
||
--side-border: #1A3A30;
|
||
|
||
/* funnel 14 — same OKLCH palette as v7_deals */
|
||
--st-new-solid: #B94837;
|
||
--st-work-solid: #B35100;
|
||
--st-call-solid: #9A6700;
|
||
--st-nocall-solid: #7E7500;
|
||
--st-neg-solid: #538200;
|
||
--st-quote-solid: #008A4D;
|
||
--st-think-solid: #008C7E;
|
||
--st-wait-solid: #00889B;
|
||
--st-paid-solid: #007EB8;
|
||
--st-refund-solid: #406DC8;
|
||
--st-fail-solid: #6C60C4;
|
||
--st-dup-solid: #9052AE;
|
||
--st-spam-solid: #AA4788;
|
||
--st-arch-solid: #B7445F;
|
||
|
||
--r-xs: 4px;
|
||
--r-sm: 6px;
|
||
--r-md: 10px;
|
||
--r-lg: 14px;
|
||
|
||
--font-ui: 'Inter', system-ui, sans-serif;
|
||
--font-mono:'JetBrains Mono', ui-monospace, monospace;
|
||
}
|
||
|
||
body {
|
||
background: var(--bg);
|
||
color: var(--ink);
|
||
font-family: var(--font-ui);
|
||
font-feature-settings: 'cv11', 'ss01', 'ss03';
|
||
-webkit-font-smoothing: antialiased;
|
||
-moz-osx-font-smoothing: grayscale;
|
||
font-variation-settings: 'opsz' 14;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
a { color: inherit; text-decoration: none; }
|
||
button { font-family: inherit; }
|
||
|
||
a:focus-visible, button:focus-visible, input:focus-visible,
|
||
[tabindex]:focus-visible {
|
||
outline: 2px solid var(--accent);
|
||
outline-offset: 2px;
|
||
border-radius: var(--r-sm);
|
||
}
|
||
|
||
.skip-link {
|
||
position: absolute; top: -40px; left: 12px;
|
||
background: var(--ink); color: #fff;
|
||
padding: 9px 16px; z-index: 200;
|
||
text-decoration: none; font-weight: 600;
|
||
border-radius: var(--r-sm);
|
||
}
|
||
.skip-link:focus { top: 12px; }
|
||
|
||
/* ============================================================
|
||
APP — same shell as v7_deals.html
|
||
============================================================ */
|
||
.app {
|
||
display: grid;
|
||
grid-template-columns: 232px 1fr;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
.side {
|
||
background: var(--side-bg);
|
||
border-right: 1px solid var(--side-border);
|
||
padding: 18px 12px 24px;
|
||
position: sticky; top: 0; height: 100vh;
|
||
overflow-y: auto;
|
||
color: var(--side-text);
|
||
}
|
||
.brand {
|
||
display: flex; align-items: center; gap: 10px;
|
||
padding: 6px 8px 18px;
|
||
font-weight: 600;
|
||
font-size: 14.5px;
|
||
letter-spacing: -0.01em;
|
||
font-variation-settings: 'opsz' 18;
|
||
color: #FFFFFF;
|
||
}
|
||
.brand-mark {
|
||
width: 22px; height: 22px;
|
||
border-radius: var(--r-xs);
|
||
background: #FFFFFF;
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
flex-shrink: 0;
|
||
overflow: hidden;
|
||
}
|
||
.brand-mark svg { width: 100%; height: 100%; display: block; }
|
||
.brand-dot { color: var(--side-icon-act); }
|
||
.nav { display: flex; flex-direction: column; gap: 1px; }
|
||
.nav-eyebrow {
|
||
font-size: 11px; font-weight: 500;
|
||
letter-spacing: 0.01em;
|
||
color: var(--side-text-2);
|
||
padding: 14px 10px 6px;
|
||
}
|
||
.nav-item {
|
||
display: flex; align-items: center; gap: 10px;
|
||
height: 32px; padding: 0 10px;
|
||
border-radius: var(--r-sm);
|
||
font-size: 13px;
|
||
color: var(--side-text);
|
||
transition: background 100ms ease, color 100ms ease;
|
||
}
|
||
.nav-item:hover { background: var(--side-hover); color: #FFFFFF; }
|
||
.nav-item.active { background: var(--side-active); color: #FFFFFF; font-weight: 500; }
|
||
.nav-item.active .nav-icon { color: var(--side-icon-act); }
|
||
.nav-item.active .nav-count { background: rgba(255,255,255,0.14); color: #fff; }
|
||
.nav-icon { width: 15px; height: 15px; flex-shrink: 0; color: var(--side-icon); stroke-width: 1.6; }
|
||
.nav-item:hover .nav-icon { color: #FFFFFF; }
|
||
.nav-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.nav-count {
|
||
font-family: var(--font-mono);
|
||
font-size: 10.5px; font-weight: 500;
|
||
font-feature-settings: 'tnum';
|
||
background: rgba(255,255,255,0.10);
|
||
color: var(--side-text);
|
||
padding: 2px 6px;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.main { display: flex; flex-direction: column; min-width: 0; }
|
||
|
||
.topbar {
|
||
height: 48px;
|
||
border-bottom: 1px solid var(--hairline);
|
||
background: var(--surface);
|
||
padding: 0 24px;
|
||
display: flex; align-items: center; gap: 12px;
|
||
position: sticky; top: 0; z-index: 50;
|
||
}
|
||
.crumb { font-size: 12.5px; color: var(--ink-3); display: flex; align-items: center; gap: 8px; }
|
||
.crumb strong { color: var(--ink); font-weight: 500; }
|
||
.crumb svg { width: 11px; height: 11px; color: var(--ink-3); opacity: 0.5; }
|
||
.topbar-spacer { flex: 1; }
|
||
|
||
.searchbar {
|
||
display: inline-flex; align-items: center; gap: 8px;
|
||
height: 30px; padding: 0 10px 0 12px;
|
||
border: 1px solid var(--hairline);
|
||
border-radius: var(--r-sm);
|
||
background: var(--surface);
|
||
font-size: 12.5px; color: var(--ink-3);
|
||
cursor: pointer;
|
||
min-width: 280px;
|
||
}
|
||
.searchbar:hover { border-color: #BFC4C8; }
|
||
.searchbar svg { width: 13px; height: 13px; flex-shrink: 0; }
|
||
.searchbar kbd {
|
||
margin-left: auto;
|
||
font-family: var(--font-mono);
|
||
font-size: 10px;
|
||
color: var(--ink-3);
|
||
background: var(--sunken);
|
||
padding: 2px 5px;
|
||
border-radius: 3px;
|
||
border: 1px solid var(--hairline);
|
||
}
|
||
|
||
.icon-btn {
|
||
width: 30px; height: 30px;
|
||
border-radius: var(--r-sm);
|
||
border: 1px solid transparent;
|
||
background: transparent;
|
||
color: var(--ink-2);
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
cursor: pointer; position: relative;
|
||
}
|
||
.icon-btn:hover { background: var(--sunken); color: var(--ink); }
|
||
.icon-btn .pip {
|
||
position: absolute; top: 5px; right: 5px;
|
||
width: 6px; height: 6px;
|
||
border-radius: 50%;
|
||
background: var(--accent);
|
||
box-shadow: 0 0 0 2px var(--surface);
|
||
}
|
||
|
||
.user-chip {
|
||
display: inline-flex; align-items: center; gap: 8px;
|
||
height: 30px; padding: 0 10px 0 4px;
|
||
border-radius: 100px;
|
||
border: 1px solid var(--hairline);
|
||
background: var(--surface);
|
||
}
|
||
.user-chip .ava {
|
||
width: 22px; height: 22px;
|
||
border-radius: 50%;
|
||
background: var(--ink); color: #fff;
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
font-size: 9.5px; font-weight: 600;
|
||
letter-spacing: 0.02em;
|
||
}
|
||
.user-chip .uname { font-size: 12px; color: var(--ink); font-weight: 500; }
|
||
|
||
/* ============================================================
|
||
DASHBOARD CONTENT
|
||
============================================================ */
|
||
.content { padding: 24px 28px 56px; flex: 1; }
|
||
|
||
.page-head {
|
||
display: flex; align-items: flex-end; justify-content: space-between;
|
||
margin-bottom: 22px; gap: 16px;
|
||
}
|
||
.page-greet {
|
||
font-size: 28px;
|
||
font-weight: 600;
|
||
font-variation-settings: 'opsz' 28;
|
||
letter-spacing: -0.02em;
|
||
line-height: 1.1;
|
||
margin: 0 0 6px;
|
||
}
|
||
.page-greet em { color: var(--accent); font-style: normal; }
|
||
.page-meta {
|
||
font-size: 12.5px; color: var(--ink-3);
|
||
display: flex; gap: 12px; align-items: center;
|
||
}
|
||
.page-meta .num { font-family: var(--font-mono); font-feature-settings: 'tnum'; color: var(--ink-2); font-weight: 500; }
|
||
.page-meta .accent-num { color: var(--accent); font-weight: 600; }
|
||
.page-meta .sep { color: var(--ink-disabled); }
|
||
|
||
.range-toggle {
|
||
display: inline-flex; gap: 1px;
|
||
border: 1px solid var(--hairline);
|
||
border-radius: var(--r-sm);
|
||
padding: 2px;
|
||
background: var(--surface);
|
||
}
|
||
.range-toggle button {
|
||
height: 26px; padding: 0 11px;
|
||
border: none; background: transparent;
|
||
font-family: inherit; font-size: 11.5px; font-weight: 500;
|
||
color: var(--ink-3);
|
||
cursor: pointer; border-radius: 4px;
|
||
letter-spacing: -0.005em;
|
||
}
|
||
.range-toggle button.active { background: var(--ink); color: #fff; }
|
||
|
||
/* ============================================================
|
||
KPI ROW — 4 monochrome tiles, 1 hero (balance + runway)
|
||
============================================================ */
|
||
.kpi-row {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr 1fr 1.45fr;
|
||
gap: 12px;
|
||
margin-bottom: 14px;
|
||
}
|
||
|
||
.kpi {
|
||
background: var(--surface);
|
||
border: 1px solid var(--hairline);
|
||
border-radius: var(--r-md);
|
||
padding: 16px 18px;
|
||
display: flex; flex-direction: column;
|
||
justify-content: space-between;
|
||
min-height: 132px;
|
||
position: relative;
|
||
}
|
||
.kpi-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
|
||
.kpi-label {
|
||
font-size: 11.5px; color: var(--ink-3); font-weight: 500;
|
||
letter-spacing: 0.005em;
|
||
}
|
||
.kpi-info {
|
||
width: 18px; height: 18px;
|
||
border: none; background: none;
|
||
color: var(--ink-disabled); cursor: pointer;
|
||
border-radius: 50%;
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
}
|
||
.kpi-info:hover { background: var(--sunken); color: var(--ink-2); }
|
||
.kpi-info svg { width: 12px; height: 12px; stroke-width: 1.7; }
|
||
|
||
.kpi-value {
|
||
font-family: var(--font-mono);
|
||
font-feature-settings: 'tnum', 'ss01';
|
||
font-size: 32px;
|
||
font-weight: 500;
|
||
letter-spacing: -0.025em;
|
||
line-height: 1;
|
||
color: var(--ink);
|
||
}
|
||
.kpi-value .unit {
|
||
font-size: 14px;
|
||
color: var(--ink-3);
|
||
margin-left: 3px;
|
||
font-weight: 400;
|
||
letter-spacing: -0.005em;
|
||
}
|
||
.kpi-foot {
|
||
display: flex; align-items: center; gap: 6px;
|
||
font-family: var(--font-mono);
|
||
font-feature-settings: 'tnum';
|
||
font-size: 11px;
|
||
color: var(--ink-3);
|
||
letter-spacing: -0.005em;
|
||
}
|
||
.delta-up { color: var(--accent); font-weight: 600; display: inline-flex; align-items: center; gap: 3px; }
|
||
.delta-up svg { width: 9px; height: 9px; stroke-width: 2.5; }
|
||
.delta-down { color: var(--st-new-solid); font-weight: 600; display: inline-flex; align-items: center; gap: 3px; }
|
||
.delta-down svg { width: 9px; height: 9px; stroke-width: 2.5; }
|
||
.delta-neutral { color: var(--ink-2); font-weight: 500; }
|
||
|
||
/* hero balance — same surface, no dark island, accent ring + runway scale */
|
||
.balance {
|
||
background: var(--surface);
|
||
border: 1px solid var(--hairline);
|
||
border-radius: var(--r-md);
|
||
padding: 16px 18px 18px;
|
||
display: flex; flex-direction: column; gap: 10px;
|
||
min-height: 132px;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
.balance::before {
|
||
content: ''; position: absolute;
|
||
inset: -1px;
|
||
border-radius: var(--r-md);
|
||
border: 1px solid var(--accent);
|
||
pointer-events: none;
|
||
opacity: 0.55;
|
||
}
|
||
.balance-row1 {
|
||
display: flex; align-items: center; justify-content: space-between;
|
||
}
|
||
.balance-label { font-size: 11.5px; color: var(--ink-3); font-weight: 500; }
|
||
.balance-tag {
|
||
font-family: var(--font-mono);
|
||
font-size: 9.5px; font-weight: 600;
|
||
letter-spacing: 0.06em;
|
||
padding: 2px 6px;
|
||
border-radius: 3px;
|
||
background: var(--accent-tint);
|
||
color: var(--accent-deep);
|
||
}
|
||
.balance-amount {
|
||
display: flex; align-items: baseline; gap: 4px;
|
||
}
|
||
.balance-amount .num {
|
||
font-family: var(--font-mono);
|
||
font-feature-settings: 'tnum';
|
||
font-weight: 600;
|
||
font-size: 36px;
|
||
letter-spacing: -0.03em;
|
||
line-height: 1;
|
||
color: var(--ink);
|
||
}
|
||
.balance-amount .ru {
|
||
font-family: var(--font-mono);
|
||
font-size: 14px;
|
||
color: var(--ink-3);
|
||
font-weight: 400;
|
||
}
|
||
/* runway scale — hairline ticks visualising days of runway */
|
||
.runway {
|
||
display: flex; flex-direction: column; gap: 6px;
|
||
}
|
||
.runway-bar {
|
||
display: grid; grid-template-columns: repeat(7, 1fr);
|
||
gap: 3px;
|
||
height: 6px;
|
||
}
|
||
.runway-bar span {
|
||
background: var(--sunken);
|
||
border-radius: 1px;
|
||
position: relative;
|
||
}
|
||
.runway-bar span.fill { background: var(--accent); }
|
||
.runway-bar span.partial::after {
|
||
content: ''; position: absolute;
|
||
left: 0; top: 0; bottom: 0;
|
||
width: 35%;
|
||
background: var(--accent);
|
||
border-radius: 1px 0 0 1px;
|
||
}
|
||
.runway-foot {
|
||
display: flex; justify-content: space-between; align-items: center;
|
||
font-family: var(--font-mono);
|
||
font-feature-settings: 'tnum';
|
||
font-size: 10.5px;
|
||
color: var(--ink-3);
|
||
letter-spacing: -0.005em;
|
||
}
|
||
.runway-foot strong { color: var(--accent); font-weight: 600; }
|
||
|
||
/* ============================================================
|
||
CHART PANEL + FUNNEL
|
||
============================================================ */
|
||
.charts-row {
|
||
display: grid;
|
||
grid-template-columns: 1.6fr 1fr;
|
||
gap: 12px;
|
||
margin-bottom: 14px;
|
||
}
|
||
|
||
.panel {
|
||
background: var(--surface);
|
||
border: 1px solid var(--hairline);
|
||
border-radius: var(--r-md);
|
||
padding: 18px 20px;
|
||
}
|
||
.panel-head {
|
||
display: flex; align-items: flex-start; justify-content: space-between;
|
||
margin-bottom: 14px;
|
||
}
|
||
.panel-title {
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
font-variation-settings: 'opsz' 18;
|
||
letter-spacing: -0.012em;
|
||
margin: 0 0 2px;
|
||
}
|
||
.panel-sub { font-size: 11.5px; color: var(--ink-3); }
|
||
.panel-tabs { display: inline-flex; gap: 2px; padding: 2px; background: var(--sunken); border-radius: var(--r-sm); }
|
||
.panel-tabs button {
|
||
height: 24px; padding: 0 9px;
|
||
border: none; background: transparent;
|
||
font-family: inherit; font-size: 11px; font-weight: 500;
|
||
color: var(--ink-3);
|
||
cursor: pointer; border-radius: 4px;
|
||
letter-spacing: -0.005em;
|
||
}
|
||
.panel-tabs button.active { background: var(--surface); color: var(--ink); box-shadow: inset 0 0 0 1px var(--hairline); }
|
||
|
||
.chart-wrap { height: 220px; position: relative; }
|
||
.chart-wrap svg { display: block; width: 100%; height: 100%; }
|
||
.chart-axis-y, .chart-axis-x {
|
||
font-family: var(--font-mono);
|
||
font-feature-settings: 'tnum';
|
||
font-size: 10px;
|
||
fill: var(--ink-3);
|
||
letter-spacing: -0.01em;
|
||
}
|
||
.chart-axis-x.today { fill: var(--ink); font-weight: 600; }
|
||
|
||
/* legend dots */
|
||
.chart-legend {
|
||
display: flex; gap: 14px; margin-top: 10px;
|
||
font-size: 11.5px; color: var(--ink-2);
|
||
}
|
||
.chart-legend span { display: inline-flex; align-items: center; gap: 6px; }
|
||
.chart-legend .ldot {
|
||
width: 8px; height: 8px;
|
||
border-radius: 50%;
|
||
position: relative;
|
||
}
|
||
.chart-legend .ldot::after {
|
||
content: ''; position: absolute; inset: -1px;
|
||
border-radius: 50%;
|
||
border: 1px solid rgba(10,19,25,0.10);
|
||
}
|
||
.chart-legend .ldot.received { background: var(--ink); }
|
||
.chart-legend .ldot.paid { background: var(--accent); }
|
||
.chart-legend .ldot.refused { background: var(--st-new-solid); }
|
||
|
||
/* ============================================================
|
||
FUNNEL — horizontal stacked bar, 14 statuses
|
||
============================================================ */
|
||
.funnel-bar {
|
||
display: flex;
|
||
height: 28px;
|
||
border-radius: 4px;
|
||
overflow: hidden;
|
||
border: 1px solid var(--hairline);
|
||
background: var(--sunken);
|
||
}
|
||
.funnel-seg {
|
||
position: relative;
|
||
cursor: default;
|
||
}
|
||
.funnel-seg + .funnel-seg { box-shadow: inset 1px 0 0 rgba(255,255,255,0.18); }
|
||
|
||
.funnel-list {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
column-gap: 14px; row-gap: 6px;
|
||
margin-top: 14px;
|
||
font-size: 12px;
|
||
color: var(--ink-2);
|
||
}
|
||
.funnel-list-item {
|
||
display: flex; align-items: center; gap: 8px;
|
||
letter-spacing: -0.005em;
|
||
}
|
||
.funnel-list-item .dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; position: relative; }
|
||
.funnel-list-item .dot::after {
|
||
content: ''; position: absolute; inset: -1px;
|
||
border-radius: 50%;
|
||
border: 1px solid rgba(10,19,25,0.10);
|
||
}
|
||
.funnel-list-item .name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.funnel-list-item .qty {
|
||
font-family: var(--font-mono); font-feature-settings: 'tnum';
|
||
font-size: 11px; color: var(--ink-3); font-weight: 500;
|
||
}
|
||
|
||
/* ============================================================
|
||
ACTIVITY LIST — recent leads, compact
|
||
============================================================ */
|
||
.activity-row {
|
||
display: grid;
|
||
grid-template-columns: 1.5fr 1fr;
|
||
gap: 12px;
|
||
margin-bottom: 14px;
|
||
}
|
||
|
||
.list-row {
|
||
display: flex; align-items: center; gap: 10px;
|
||
padding: 10px 18px;
|
||
border-bottom: 1px solid var(--hairline-soft);
|
||
font-size: 12.5px;
|
||
}
|
||
.list-row:last-child { border-bottom: none; }
|
||
.list-row:hover { background: var(--sunken); cursor: pointer; }
|
||
.l-time {
|
||
font-family: var(--font-mono); font-feature-settings: 'tnum';
|
||
font-size: 10.5px; color: var(--ink-3);
|
||
width: 48px; flex-shrink: 0;
|
||
letter-spacing: -0.005em;
|
||
}
|
||
.l-deal { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; }
|
||
.l-ava {
|
||
width: 22px; height: 22px;
|
||
border-radius: 50%;
|
||
background: var(--sunken);
|
||
color: var(--ink-2);
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
font-size: 8.5px; font-weight: 600;
|
||
position: relative;
|
||
flex-shrink: 0;
|
||
}
|
||
.l-ava::after {
|
||
content: ''; position: absolute; inset: 0;
|
||
border-radius: 50%;
|
||
border: 1px solid rgba(10,19,25,0.08);
|
||
}
|
||
.l-name { font-weight: 500; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||
.l-product { color: var(--ink-3); font-size: 11.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||
.l-chip {
|
||
display: inline-flex; align-items: center; gap: 6px;
|
||
font-size: 11.5px; font-weight: 500;
|
||
color: var(--ink);
|
||
white-space: nowrap;
|
||
flex-shrink: 0;
|
||
}
|
||
.l-chip .dot {
|
||
width: 7px; height: 7px; border-radius: 50%;
|
||
position: relative;
|
||
}
|
||
.l-chip .dot::after {
|
||
content: ''; position: absolute; inset: -1px;
|
||
border-radius: 50%;
|
||
border: 1px solid rgba(10,19,25,0.10);
|
||
}
|
||
.l-price {
|
||
font-family: var(--font-mono); font-feature-settings: 'tnum';
|
||
font-size: 11.5px; color: var(--ink); font-weight: 500;
|
||
letter-spacing: -0.005em;
|
||
min-width: 58px; text-align: right;
|
||
}
|
||
|
||
.list-foot {
|
||
padding: 10px 18px;
|
||
border-top: 1px solid var(--hairline);
|
||
text-align: center;
|
||
font-size: 12px;
|
||
color: var(--ink-3);
|
||
}
|
||
.list-foot a { color: var(--accent); font-weight: 500; }
|
||
.list-foot a:hover { text-decoration: underline; }
|
||
|
||
/* ============================================================
|
||
SYSTEM HEALTH PANEL
|
||
============================================================ */
|
||
.health-list { display: flex; flex-direction: column; gap: 1px; }
|
||
.health-row {
|
||
display: grid;
|
||
grid-template-columns: 1fr auto auto;
|
||
gap: 12px;
|
||
padding: 9px 0;
|
||
align-items: center;
|
||
border-bottom: 1px solid var(--hairline-soft);
|
||
font-size: 12.5px;
|
||
}
|
||
.health-row:last-child { border-bottom: none; }
|
||
.h-name { color: var(--ink); font-weight: 500; }
|
||
.h-name .h-sub { display: block; font-size: 11px; color: var(--ink-3); font-weight: 400; margin-top: 2px; }
|
||
.h-metric {
|
||
font-family: var(--font-mono); font-feature-settings: 'tnum';
|
||
font-size: 11px; color: var(--ink-2);
|
||
letter-spacing: -0.005em;
|
||
}
|
||
.h-status {
|
||
display: inline-flex; align-items: center; gap: 6px;
|
||
font-size: 11px; color: var(--ink-2);
|
||
font-weight: 500;
|
||
}
|
||
.h-status .dot {
|
||
width: 7px; height: 7px; border-radius: 50%;
|
||
position: relative;
|
||
background: var(--accent);
|
||
}
|
||
.h-status .dot::after {
|
||
content: ''; position: absolute; inset: -1px;
|
||
border-radius: 50%;
|
||
border: 1px solid rgba(10,19,25,0.10);
|
||
}
|
||
.h-status.warn .dot { background: var(--st-call-solid); }
|
||
.h-status.fail .dot { background: var(--st-new-solid); }
|
||
|
||
/* ============================================================
|
||
QUICK ACTIONS
|
||
============================================================ */
|
||
.qa-row {
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
gap: 12px;
|
||
}
|
||
.qa-card {
|
||
background: var(--surface);
|
||
border: 1px solid var(--hairline);
|
||
border-radius: var(--r-md);
|
||
padding: 14px 16px;
|
||
display: flex; align-items: center; gap: 12px;
|
||
cursor: pointer;
|
||
transition: border-color 120ms ease, background 120ms ease;
|
||
}
|
||
.qa-card:hover { border-color: var(--ink-disabled); background: var(--surface); }
|
||
.qa-icon {
|
||
width: 30px; height: 30px;
|
||
border-radius: var(--r-sm);
|
||
background: var(--sunken);
|
||
color: var(--ink-2);
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
flex-shrink: 0;
|
||
}
|
||
.qa-icon svg { width: 14px; height: 14px; stroke-width: 1.7; }
|
||
.qa-text { display: flex; flex-direction: column; min-width: 0; }
|
||
.qa-title {
|
||
font-size: 12.5px; color: var(--ink); font-weight: 500;
|
||
letter-spacing: -0.005em;
|
||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
||
}
|
||
.qa-sub {
|
||
font-family: var(--font-mono); font-feature-settings: 'tnum';
|
||
font-size: 10.5px; color: var(--ink-3);
|
||
letter-spacing: -0.005em;
|
||
}
|
||
|
||
/* ============================================================
|
||
RESPONSIVE
|
||
============================================================ */
|
||
@media (max-width: 1280px) {
|
||
.kpi-row { grid-template-columns: 1fr 1fr; }
|
||
.charts-row { grid-template-columns: 1fr; }
|
||
.activity-row { grid-template-columns: 1fr; }
|
||
.qa-row { grid-template-columns: repeat(2, 1fr); }
|
||
}
|
||
@media (max-width: 1100px) {
|
||
.app { grid-template-columns: 56px 1fr; }
|
||
.side { padding: 14px 6px; }
|
||
.brand .brand-text,
|
||
.nav-eyebrow,
|
||
.nav-text,
|
||
.nav-item:not(.active) .nav-count { display: none; }
|
||
.nav-item { justify-content: center; padding: 0; }
|
||
.topbar { padding: 0 16px; }
|
||
.content { padding: 18px 18px 56px; }
|
||
.searchbar { min-width: 200px; }
|
||
}
|
||
@media (max-width: 768px) {
|
||
.app { grid-template-columns: 1fr; }
|
||
.side { display: none; }
|
||
.topbar .crumb span:first-child { display: none; }
|
||
.page-head { flex-direction: column; align-items: flex-start; gap: 12px; }
|
||
.page-greet { font-size: 24px; }
|
||
.kpi-row { grid-template-columns: 1fr; }
|
||
.qa-row { grid-template-columns: 1fr; }
|
||
.funnel-list { grid-template-columns: 1fr; }
|
||
.chart-wrap { height: 180px; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<a href="#main" class="skip-link">К контенту</a>
|
||
|
||
<div class="app">
|
||
|
||
<!-- ===== SIDEBAR ===== -->
|
||
<aside class="side" aria-label="Главное меню">
|
||
<div class="brand">
|
||
<span class="brand-mark" aria-hidden="true">
|
||
<svg viewBox="0 0 48 48"><path d="M16 14 L16 34 L32 34" stroke="#012019" stroke-width="4.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="32" cy="34" r="3.5" fill="#0F6E56"/></svg>
|
||
</span>
|
||
<span class="brand-text">Лидерра<span class="brand-dot">.</span></span>
|
||
</div>
|
||
<nav class="nav">
|
||
<div class="nav-eyebrow">Работа</div>
|
||
<a class="nav-item active" href="#" aria-current="page">
|
||
<svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>
|
||
<span class="nav-text">Дашборд</span>
|
||
</a>
|
||
<a class="nav-item" href="#">
|
||
<svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 6h18M6 12h12M9 18h6"/></svg>
|
||
<span class="nav-text">Сделки</span>
|
||
<span class="nav-count">247</span>
|
||
</a>
|
||
<a class="nav-item" href="#">
|
||
<svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="3" width="6" height="18"/><rect x="11" y="3" width="6" height="12"/><rect x="19" y="3" width="2" height="8"/></svg>
|
||
<span class="nav-text">Канбан</span>
|
||
</a>
|
||
<a class="nav-item" href="#">
|
||
<svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 6v6l4 2"/><circle cx="12" cy="12" r="9"/></svg>
|
||
<span class="nav-text">Напоминания</span>
|
||
<span class="nav-count">12</span>
|
||
</a>
|
||
<div class="nav-eyebrow">Финансы</div>
|
||
<a class="nav-item" href="#">
|
||
<svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="6" width="18" height="13" rx="1"/><path d="M3 10h18M7 15h3"/></svg>
|
||
<span class="nav-text">Биллинг</span>
|
||
</a>
|
||
<a class="nav-item" href="#">
|
||
<svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 12h18M3 6h18M3 18h18"/></svg>
|
||
<span class="nav-text">Отчёты</span>
|
||
</a>
|
||
<div class="nav-eyebrow">Команда</div>
|
||
<a class="nav-item" href="#">
|
||
<svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
|
||
<span class="nav-text">Менеджеры</span>
|
||
<span class="nav-count">4</span>
|
||
</a>
|
||
<a class="nav-item" href="#">
|
||
<svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
|
||
<span class="nav-text">Настройки</span>
|
||
</a>
|
||
</nav>
|
||
</aside>
|
||
|
||
<!-- ===== MAIN ===== -->
|
||
<div class="main">
|
||
|
||
<div class="topbar">
|
||
<div class="crumb">
|
||
<span>Рабочая область</span>
|
||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M9 18l6-6-6-6"/></svg>
|
||
<strong>Дашборд</strong>
|
||
</div>
|
||
<div class="topbar-spacer"></div>
|
||
<button type="button" class="searchbar" aria-label="Поиск, ⌘K">
|
||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
|
||
<span>Поиск</span>
|
||
<kbd>⌘K</kbd>
|
||
</button>
|
||
<button type="button" class="icon-btn" aria-label="Уведомления, есть новые">
|
||
<svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.7" aria-hidden="true"><path d="M18 8a6 6 0 1 0-12 0c0 7-3 9-3 9h18s-3-2-3-9M13.73 21a2 2 0 0 1-3.46 0"/></svg>
|
||
<span class="pip" aria-hidden="true"></span>
|
||
</button>
|
||
<button type="button" class="user-chip" aria-label="Профиль · Иван Петров">
|
||
<span class="ava" aria-hidden="true">ИП</span>
|
||
<span class="uname">Иван П.</span>
|
||
</button>
|
||
</div>
|
||
|
||
<main id="main" class="content">
|
||
|
||
<!-- page head -->
|
||
<header class="page-head">
|
||
<div>
|
||
<h1 class="page-greet">Доброе утро, <em>Иван</em></h1>
|
||
<div class="page-meta">
|
||
<span><span class="num accent-num">+3</span> новых лида с утра</span>
|
||
<span class="sep">·</span>
|
||
<span>сегодня <span class="num">11</span> · вчера <span class="num">38</span></span>
|
||
<span class="sep">·</span>
|
||
<span>средняя стоимость <span class="num">2 248 ₽</span></span>
|
||
</div>
|
||
</div>
|
||
<div class="range-toggle" role="group" aria-label="Период">
|
||
<button type="button" aria-pressed="false">Сегодня</button>
|
||
<button type="button" class="active" aria-pressed="true">7 дней</button>
|
||
<button type="button" aria-pressed="false">30 дней</button>
|
||
<button type="button" aria-pressed="false">Период…</button>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- KPI strip + balance hero -->
|
||
<div class="kpi-row">
|
||
|
||
<article class="kpi" tabindex="0" aria-label="KPI: получено лидов">
|
||
<div class="kpi-head">
|
||
<span class="kpi-label">Получено лидов</span>
|
||
<button type="button" class="kpi-info" aria-label="Подробнее"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 8v4M12 16h.01"/></svg></button>
|
||
</div>
|
||
<div>
|
||
<div class="kpi-value">247</div>
|
||
<div class="kpi-foot">
|
||
<span class="delta-up"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M7 14l5-5 5 5"/></svg>12.3%</span>
|
||
<span>vs предыдущие 7 дней</span>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
|
||
<article class="kpi" tabindex="0" aria-label="KPI: конверсия в оплату">
|
||
<div class="kpi-head">
|
||
<span class="kpi-label">Конверсия в оплату</span>
|
||
<button type="button" class="kpi-info" aria-label="Подробнее"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 8v4M12 16h.01"/></svg></button>
|
||
</div>
|
||
<div>
|
||
<div class="kpi-value">18.4<span class="unit">%</span></div>
|
||
<div class="kpi-foot">
|
||
<span class="delta-up"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M7 14l5-5 5 5"/></svg>2.1pp</span>
|
||
<span>vs предыдущие 7 дней</span>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
|
||
<article class="kpi" tabindex="0" aria-label="KPI: активные проекты">
|
||
<div class="kpi-head">
|
||
<span class="kpi-label">Активные проекты</span>
|
||
<button type="button" class="kpi-info" aria-label="Подробнее"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 8v4M12 16h.01"/></svg></button>
|
||
</div>
|
||
<div>
|
||
<div class="kpi-value">8<span class="unit">/ 10</span></div>
|
||
<div class="kpi-foot">
|
||
<span class="delta-neutral">2 свободно</span>
|
||
<span class="sep" style="color:var(--ink-disabled)">·</span>
|
||
<span>тариф «Команда»</span>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
|
||
<!-- Hero balance + runway scale -->
|
||
<article class="balance" tabindex="0" aria-labelledby="bal-label">
|
||
<div class="balance-row1">
|
||
<span id="bal-label" class="balance-label">Баланс</span>
|
||
<span class="balance-tag">LIVE</span>
|
||
</div>
|
||
<div class="balance-amount">
|
||
<span class="num">14 250</span><span class="ru">₽</span>
|
||
</div>
|
||
<div class="runway">
|
||
<div class="runway-bar" aria-label="Хватит на 4 дня из 7" role="img">
|
||
<span class="fill"></span>
|
||
<span class="fill"></span>
|
||
<span class="fill"></span>
|
||
<span class="fill"></span>
|
||
<span class="partial"></span>
|
||
<span></span>
|
||
<span></span>
|
||
</div>
|
||
<div class="runway-foot">
|
||
<span>≈ 285 лидов · хватит на <strong>4 дня</strong></span>
|
||
<span>пополнить →</span>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
|
||
</div>
|
||
|
||
<!-- Activity chart + Funnel -->
|
||
<div class="charts-row">
|
||
|
||
<section class="panel" aria-labelledby="chart-title">
|
||
<div class="panel-head">
|
||
<div>
|
||
<h2 class="panel-title" id="chart-title">Активность по дням</h2>
|
||
<div class="panel-sub">принято · оплачено · отказ — последние 7 дней</div>
|
||
</div>
|
||
<div class="panel-tabs" role="tablist" aria-label="Метрика графика">
|
||
<button type="button" role="tab" aria-selected="true" class="active">Принято</button>
|
||
<button type="button" role="tab" aria-selected="false">Оплачено</button>
|
||
<button type="button" role="tab" aria-selected="false">Отказ</button>
|
||
</div>
|
||
</div>
|
||
<div class="chart-wrap">
|
||
<svg viewBox="0 0 800 220" preserveAspectRatio="none" aria-label="Активность по дням, последние 7 дней">
|
||
<line x1="36" y1="20" x2="790" y2="20" stroke="#E8EBED"/>
|
||
<line x1="36" y1="68" x2="790" y2="68" stroke="#E8EBED"/>
|
||
<line x1="36" y1="116" x2="790" y2="116" stroke="#E8EBED"/>
|
||
<line x1="36" y1="164" x2="790" y2="164" stroke="#E8EBED"/>
|
||
<text x="28" y="24" text-anchor="end" class="chart-axis-y">60</text>
|
||
<text x="28" y="72" text-anchor="end" class="chart-axis-y">45</text>
|
||
<text x="28" y="120" text-anchor="end" class="chart-axis-y">30</text>
|
||
<text x="28" y="168" text-anchor="end" class="chart-axis-y">15</text>
|
||
<text x="28" y="200" text-anchor="end" class="chart-axis-y">0</text>
|
||
|
||
<defs>
|
||
<linearGradient id="grad-area" x1="0" y1="0" x2="0" y2="1">
|
||
<stop offset="0%" stop-color="#0A1319" stop-opacity="0.10"/>
|
||
<stop offset="100%" stop-color="#0A1319" stop-opacity="0"/>
|
||
</linearGradient>
|
||
</defs>
|
||
<path d="M50,148 L170,108 L290,124 L410,72 L530,90 L650,52 L770,60 L770,200 L50,200 Z"
|
||
fill="url(#grad-area)"/>
|
||
<path d="M50,148 L170,108 L290,124 L410,72 L530,90 L650,52 L770,60"
|
||
fill="none" stroke="#0A1319" stroke-width="1.7" stroke-linejoin="round" stroke-linecap="round"/>
|
||
|
||
<circle cx="50" cy="148" r="2.6" fill="#FFFFFF" stroke="#0A1319" stroke-width="1.6"/>
|
||
<circle cx="170" cy="108" r="2.6" fill="#FFFFFF" stroke="#0A1319" stroke-width="1.6"/>
|
||
<circle cx="290" cy="124" r="2.6" fill="#FFFFFF" stroke="#0A1319" stroke-width="1.6"/>
|
||
<circle cx="410" cy="72" r="2.6" fill="#FFFFFF" stroke="#0A1319" stroke-width="1.6"/>
|
||
<circle cx="530" cy="90" r="2.6" fill="#FFFFFF" stroke="#0A1319" stroke-width="1.6"/>
|
||
<circle cx="650" cy="52" r="4.2" fill="#0F6E56" stroke="#FFFFFF" stroke-width="2"/>
|
||
<circle cx="770" cy="60" r="2.6" fill="#FFFFFF" stroke="#0A1319" stroke-width="1.6"/>
|
||
|
||
<text x="50" y="216" text-anchor="middle" class="chart-axis-x">пн</text>
|
||
<text x="170" y="216" text-anchor="middle" class="chart-axis-x">вт</text>
|
||
<text x="290" y="216" text-anchor="middle" class="chart-axis-x">ср</text>
|
||
<text x="410" y="216" text-anchor="middle" class="chart-axis-x">чт</text>
|
||
<text x="530" y="216" text-anchor="middle" class="chart-axis-x">пт</text>
|
||
<text x="650" y="216" text-anchor="middle" class="chart-axis-x today">сб</text>
|
||
<text x="770" y="216" text-anchor="middle" class="chart-axis-x">сегодня</text>
|
||
</svg>
|
||
</div>
|
||
<div class="chart-legend" aria-hidden="true">
|
||
<span><span class="ldot received"></span>принято</span>
|
||
<span><span class="ldot paid"></span>оплачено</span>
|
||
<span><span class="ldot refused"></span>отказ</span>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel" aria-labelledby="funnel-title">
|
||
<div class="panel-head">
|
||
<div>
|
||
<h2 class="panel-title" id="funnel-title">Воронка</h2>
|
||
<div class="panel-sub">14 статусов · 247 лидов · сейчас</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="funnel-bar" role="img" aria-label="Распределение 247 лидов по 14 статусам — детали ниже">
|
||
<div class="funnel-seg" style="flex: 18; background: var(--st-new-solid);" title="Новая · 18"></div>
|
||
<div class="funnel-seg" style="flex: 14; background: var(--st-work-solid);" title="В работе · 14"></div>
|
||
<div class="funnel-seg" style="flex: 22; background: var(--st-call-solid);" title="Дозвон · 22"></div>
|
||
<div class="funnel-seg" style="flex: 9; background: var(--st-nocall-solid);" title="Не дозвон. · 9"></div>
|
||
<div class="funnel-seg" style="flex: 16; background: var(--st-neg-solid);" title="Переговоры · 16"></div>
|
||
<div class="funnel-seg" style="flex: 11; background: var(--st-quote-solid);" title="КП · 11"></div>
|
||
<div class="funnel-seg" style="flex: 7; background: var(--st-think-solid);" title="Думает · 7"></div>
|
||
<div class="funnel-seg" style="flex: 4; background: var(--st-wait-solid);" title="Ждёт оплату · 4"></div>
|
||
<div class="funnel-seg" style="flex: 45; background: var(--st-paid-solid);" title="Оплачено · 45"></div>
|
||
<div class="funnel-seg" style="flex: 3; background: var(--st-refund-solid);" title="Возврат · 3"></div>
|
||
<div class="funnel-seg" style="flex: 38; background: var(--st-fail-solid);" title="Отказ · 38"></div>
|
||
<div class="funnel-seg" style="flex: 5; background: var(--st-dup-solid);" title="Дубликат · 5"></div>
|
||
<div class="funnel-seg" style="flex: 5; background: var(--st-spam-solid);" title="Спам · 5"></div>
|
||
<div class="funnel-seg" style="flex: 39; background: var(--st-arch-solid);" title="Архив · 39"></div>
|
||
</div>
|
||
|
||
<div class="funnel-list">
|
||
<span class="funnel-list-item"><span class="dot" style="background: var(--st-new-solid)"></span><span class="name">Новая</span><span class="qty">18</span></span>
|
||
<span class="funnel-list-item"><span class="dot" style="background: var(--st-paid-solid)"></span><span class="name">Оплачено</span><span class="qty">45</span></span>
|
||
<span class="funnel-list-item"><span class="dot" style="background: var(--st-work-solid)"></span><span class="name">В работе</span><span class="qty">14</span></span>
|
||
<span class="funnel-list-item"><span class="dot" style="background: var(--st-arch-solid)"></span><span class="name">Архив</span><span class="qty">39</span></span>
|
||
<span class="funnel-list-item"><span class="dot" style="background: var(--st-call-solid)"></span><span class="name">Дозвон</span><span class="qty">22</span></span>
|
||
<span class="funnel-list-item"><span class="dot" style="background: var(--st-fail-solid)"></span><span class="name">Отказ</span><span class="qty">38</span></span>
|
||
<span class="funnel-list-item"><span class="dot" style="background: var(--st-neg-solid)"></span><span class="name">Переговоры</span><span class="qty">16</span></span>
|
||
<span class="funnel-list-item"><span class="dot" style="background: var(--st-quote-solid)"></span><span class="name">КП отправлено</span><span class="qty">11</span></span>
|
||
<span class="funnel-list-item"><span class="dot" style="background: var(--st-nocall-solid)"></span><span class="name">Не дозвон.</span><span class="qty">9</span></span>
|
||
<span class="funnel-list-item"><span class="dot" style="background: var(--st-wait-solid)"></span><span class="name">Ждёт оплату</span><span class="qty">4</span></span>
|
||
<span class="funnel-list-item"><span class="dot" style="background: var(--st-think-solid)"></span><span class="name">Думает</span><span class="qty">7</span></span>
|
||
<span class="funnel-list-item"><span class="dot" style="background: var(--st-spam-solid)"></span><span class="name">Спам</span><span class="qty">5</span></span>
|
||
<span class="funnel-list-item"><span class="dot" style="background: var(--st-dup-solid)"></span><span class="name">Дубликат</span><span class="qty">5</span></span>
|
||
<span class="funnel-list-item"><span class="dot" style="background: var(--st-refund-solid)"></span><span class="name">Возврат</span><span class="qty">3</span></span>
|
||
</div>
|
||
</section>
|
||
|
||
</div>
|
||
|
||
<!-- Recent activity + system health -->
|
||
<div class="activity-row">
|
||
|
||
<section class="panel" style="padding:0" aria-labelledby="recent-title">
|
||
<div class="panel-head" style="padding:18px 20px 14px">
|
||
<div>
|
||
<h2 class="panel-title" id="recent-title">Последние сделки</h2>
|
||
<div class="panel-sub">обновляются автоматически</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="list-row">
|
||
<span class="l-time">28м</span>
|
||
<span class="l-deal"><span class="l-ava" aria-hidden="true">АС</span><span class="l-name">Анна Соколова</span><span class="l-product">· Натяжные потолки</span></span>
|
||
<span class="l-chip"><span class="dot" style="background: var(--st-new-solid)"></span>Новая</span>
|
||
<span class="l-price">1 850 ₽</span>
|
||
</div>
|
||
<div class="list-row">
|
||
<span class="l-time">1ч</span>
|
||
<span class="l-deal"><span class="l-ava" aria-hidden="true">ИП</span><span class="l-name">Иван Петров</span><span class="l-product">· Окна Москва</span></span>
|
||
<span class="l-chip"><span class="dot" style="background: var(--st-neg-solid)"></span>Переговоры</span>
|
||
<span class="l-price">2 200 ₽</span>
|
||
</div>
|
||
<div class="list-row">
|
||
<span class="l-time">2ч</span>
|
||
<span class="l-deal"><span class="l-ava" aria-hidden="true">ДК</span><span class="l-name">Дмитрий Котов</span><span class="l-product">· Окна Москва</span></span>
|
||
<span class="l-chip"><span class="dot" style="background: var(--st-paid-solid)"></span>Оплачено</span>
|
||
<span class="l-price">2 200 ₽</span>
|
||
</div>
|
||
<div class="list-row">
|
||
<span class="l-time">3ч</span>
|
||
<span class="l-deal"><span class="l-ava" aria-hidden="true">МО</span><span class="l-name">Михаил Орлов</span><span class="l-product">· Натяжные потолки</span></span>
|
||
<span class="l-chip"><span class="dot" style="background: var(--st-wait-solid)"></span>Ждёт оплату</span>
|
||
<span class="l-price">1 850 ₽</span>
|
||
</div>
|
||
<div class="list-row">
|
||
<span class="l-time">4ч</span>
|
||
<span class="l-deal"><span class="l-ava" aria-hidden="true">ЕВ</span><span class="l-name">Елена Васильева</span><span class="l-product">· Кухни на заказ</span></span>
|
||
<span class="l-chip"><span class="dot" style="background: var(--st-call-solid)"></span>Дозвон</span>
|
||
<span class="l-price">3 100 ₽</span>
|
||
</div>
|
||
<div class="list-row">
|
||
<span class="l-time">5ч</span>
|
||
<span class="l-deal"><span class="l-ava" aria-hidden="true">СН</span><span class="l-name">Сергей Новиков</span><span class="l-product">· Окна Москва</span></span>
|
||
<span class="l-chip"><span class="dot" style="background: var(--st-fail-solid)"></span>Отказ</span>
|
||
<span class="l-price">2 200 ₽</span>
|
||
</div>
|
||
<div class="list-foot">
|
||
<a href="#">Все сделки →</a>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel" aria-labelledby="health-title">
|
||
<div class="panel-head">
|
||
<div>
|
||
<h2 class="panel-title" id="health-title">Состояние системы</h2>
|
||
<div class="panel-sub">за последние 24 часа</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="health-list">
|
||
<div class="health-row">
|
||
<span class="h-name">Приём лидов <span class="h-sub">webhook → API</span></span>
|
||
<span class="h-metric">142 ms · 99.97%</span>
|
||
<span class="h-status"><span class="dot" aria-hidden="true"></span>OK</span>
|
||
</div>
|
||
<div class="health-row">
|
||
<span class="h-name">Платёжный шлюз <span class="h-sub">YooKassa</span></span>
|
||
<span class="h-metric">208 ms · 100%</span>
|
||
<span class="h-status"><span class="dot" aria-hidden="true"></span>OK</span>
|
||
</div>
|
||
<div class="health-row">
|
||
<span class="h-name">Telegram-бот <span class="h-sub">уведомления команды</span></span>
|
||
<span class="h-metric">89 ms · 99.20%</span>
|
||
<span class="h-status warn"><span class="dot" aria-hidden="true"></span>деградация</span>
|
||
</div>
|
||
<div class="health-row">
|
||
<span class="h-name">Я.Директ интеграция <span class="h-sub">utm + лиды</span></span>
|
||
<span class="h-metric">синхр. 3 мин назад</span>
|
||
<span class="h-status"><span class="dot" aria-hidden="true"></span>OK</span>
|
||
</div>
|
||
<div class="health-row">
|
||
<span class="h-name">SMS-шлюз <span class="h-sub">SMSC.RU</span></span>
|
||
<span class="h-metric">412 ms · 96.40%</span>
|
||
<span class="h-status warn"><span class="dot" aria-hidden="true"></span>задержка</span>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
</div>
|
||
|
||
<!-- Quick actions -->
|
||
<section aria-labelledby="qa-title">
|
||
<h2 class="panel-title" id="qa-title" style="margin-bottom:10px;font-size:13px;color:var(--ink-3);font-weight:500;letter-spacing:0.005em">Быстрые действия</h2>
|
||
<div class="qa-row">
|
||
<button type="button" class="qa-card">
|
||
<span class="qa-icon" aria-hidden="true">
|
||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
|
||
</span>
|
||
<span class="qa-text">
|
||
<span class="qa-title">Новая сделка</span>
|
||
<span class="qa-sub">⌘ + N</span>
|
||
</span>
|
||
</button>
|
||
<button type="button" class="qa-card">
|
||
<span class="qa-icon" aria-hidden="true">
|
||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><rect x="3" y="6" width="18" height="13" rx="1"/><path d="M3 10h18M7 15h3"/></svg>
|
||
</span>
|
||
<span class="qa-text">
|
||
<span class="qa-title">Пополнить баланс</span>
|
||
<span class="qa-sub">от 5 000 ₽</span>
|
||
</span>
|
||
</button>
|
||
<button type="button" class="qa-card">
|
||
<span class="qa-icon" aria-hidden="true">
|
||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7,10 12,15 17,10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
||
</span>
|
||
<span class="qa-text">
|
||
<span class="qa-title">Экспорт отчёта</span>
|
||
<span class="qa-sub">CSV · Excel</span>
|
||
</span>
|
||
</button>
|
||
<button type="button" class="qa-card">
|
||
<span class="qa-icon" aria-hidden="true">
|
||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
|
||
</span>
|
||
<span class="qa-text">
|
||
<span class="qa-title">Настроить дашборд</span>
|
||
<span class="qa-sub">видимые виджеты</span>
|
||
</span>
|
||
</button>
|
||
</div>
|
||
</section>
|
||
|
||
</main>
|
||
</div>
|
||
</div>
|
||
|
||
</body>
|
||
</html>
|