Files
portal/web/v8/v8_reports.html
T
Дмитрий 887abf444e rebrand(v8.5→Лидерра): дизайн-handoff Платона v8 Forest + Лидпоток→Лидерра
Получен 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>
2026-05-08 07:11:58 +03:00

322 lines
25 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">
<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; }
:root {
--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;
--side-bg:#012019; --side-text:#B1C2BD; --side-text-2:#7A8C87;
--side-active:#13382F; --side-icon:#5C7A72; --side-icon-act:#32C8A9;
--side-hover:#0A2A22; --side-border:#1A3A30;
--st-paid:#007EB8; --st-quote:#008A4D; --st-call:#9A6700; --st-new:#B94837; --st-fail:#6C60C4;
--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'; -webkit-font-smoothing:antialiased; font-variation-settings:'opsz' 14; min-height:100vh; }
button { font-family:inherit; }
a { color:inherit; text-decoration:none; }
a:focus-visible, button:focus-visible, input:focus-visible, select: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; font-weight:600; border-radius:var(--r-sm); }
.skip-link:focus { top:12px; }
.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:#FFF; }
.brand-mark { width:22px; height:22px; border-radius:var(--r-xs); background:#FFF; 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); }
.nav-item:hover { background:var(--side-hover); color:#FFF; }
.nav-item.active { background:var(--side-active); color:#FFF; font-weight:500; }
.nav-item.active .nav-icon { color:var(--side-icon-act); }
.nav-icon { width:15px; height:15px; flex-shrink:0; color:var(--side-icon); stroke-width:1.6; }
.nav-item:hover .nav-icon { color:#FFF; }
.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; }
.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; }
.user-chip .uname { font-size:12px; color:var(--ink); font-weight:500; }
.content { display:grid; grid-template-columns:380px 1fr; gap:18px; padding:24px 28px 80px; max-width:1500px; margin:0 auto; }
.page-h { grid-column:1 / -1; display:flex; align-items:flex-end; justify-content:space-between; margin-bottom:6px; gap:16px; }
.page-title { font-size:28px; font-weight:600; font-variation-settings:'opsz' 28; letter-spacing:-0.02em; line-height:1.1; margin:0 0 6px; }
.page-meta { font-size:12.5px; color:var(--ink-3); }
.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); }
.section { background:var(--surface); border:1px solid var(--hairline); border-radius:var(--r-md); padding:20px 22px; }
.section-h { display:flex; align-items:flex-start; justify-content:space-between; gap:12px; margin-bottom:16px; }
.section-h h2 { font-size:16px; font-weight:600; font-variation-settings:'opsz' 18; letter-spacing:-0.012em; margin:0 0 4px; }
.section-h .desc { font-size:12px; color:var(--ink-3); line-height:1.5; }
.section-h .h-action { font-size:11.5px; color:var(--accent); font-weight:500; cursor:pointer; background:none; border:none; padding:0; font-family:inherit; display:inline-flex; align-items:center; gap:4px; }
.field { display:flex; flex-direction:column; gap:6px; margin-bottom:14px; }
.field label { font-size:11.5px; font-weight:500; color:var(--ink-2); letter-spacing:-0.005em; }
.input, .select { height:36px; padding:0 12px; border:1px solid var(--hairline); border-radius:var(--r-sm); background:var(--surface); font-family:inherit; font-size:13px; color:var(--ink); outline:none; letter-spacing:-0.005em; }
.input.mono { font-family:var(--font-mono); font-feature-settings:'tnum'; letter-spacing:0; }
.input:focus, .select:focus { border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-tint); }
.select { appearance:none; -webkit-appearance:none; padding-right:30px; background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%2366635C' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); background-repeat:no-repeat; background-position:right 10px center; cursor:pointer; }
.field-row { display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-bottom:14px; }
.field-row .field { margin-bottom:0; }
/* radio chips for type */
.type-chips { display:grid; grid-template-columns:1fr 1fr; gap:6px; margin-top:6px; }
.tc-card { display:flex; flex-direction:column; gap:3px; padding:10px 12px; border:1px solid var(--hairline); background:var(--surface); border-radius:var(--r-sm); cursor:pointer; font-size:12.5px; font-family:inherit; text-align:left; }
.tc-card:hover { border-color:var(--ink-disabled); }
.tc-card.active { border-color:var(--accent); background:var(--accent-tint); }
.tc-card .tc-name { font-weight:600; color:var(--ink); letter-spacing:-0.005em; }
.tc-card .tc-desc { font-size:11px; color:var(--ink-3); line-height:1.4; }
.tc-card.active .tc-desc { color:var(--accent-deep); }
/* format radios */
.fmt-row { display:flex; gap:6px; margin-top:6px; }
.fmt-card { flex:1; padding:8px 10px; border:1px solid var(--hairline); background:var(--surface); border-radius:var(--r-sm); cursor:pointer; font-family:inherit; text-align:center; font-size:12px; font-weight:500; color:var(--ink-2); letter-spacing:-0.005em; }
.fmt-card:hover { border-color:var(--ink-disabled); color:var(--ink); }
.fmt-card.active { border-color:var(--accent); background:var(--accent-tint); color:var(--accent-deep); font-weight:600; }
.btn { display:inline-flex; align-items:center; gap:7px; height:38px; padding:0 16px; border-radius:var(--r-sm); border:1px solid var(--hairline); background:var(--surface); font-size:13px; font-weight:500; color:var(--ink); cursor:pointer; font-family:inherit; letter-spacing:-0.005em; }
.btn:hover { border-color:var(--ink-disabled); background:var(--sunken); }
.btn-primary { background:var(--accent); color:#fff; border-color:var(--accent); }
.btn-primary:hover { background:var(--accent-deep); border-color:var(--accent-deep); }
.btn svg { width:13px; height:13px; stroke-width:1.7; }
.quota-banner { padding:11px 14px; border-radius:var(--r-sm); background:var(--accent-tint); color:var(--accent-deep); font-size:12px; line-height:1.5; display:flex; gap:10px; align-items:flex-start; margin-bottom:14px; letter-spacing:-0.005em; }
.quota-banner svg { width:14px; height:14px; flex-shrink:0; margin-top:1px; }
.quota-banner strong { color:var(--accent-deep); font-weight:600; }
.quota-banner .quota-bar { display:inline-flex; align-items:center; gap:4px; }
.quota-banner .qd { width:8px; height:8px; border-radius:2px; background:var(--accent); }
.quota-banner .qd.empty { background:rgba(15,110,86,0.20); }
/* Jobs list */
.jobs { display:flex; flex-direction:column; }
.job { display:grid; grid-template-columns:auto 1fr auto auto; gap:14px; padding:12px 18px; border-bottom:1px solid var(--hairline-soft); align-items:center; }
.job:last-child { border-bottom:none; }
.job-icon { width:34px; height:34px; border-radius:var(--r-sm); background:var(--bg); border:1px solid var(--hairline-soft); display:inline-flex; align-items:center; justify-content:center; color:var(--ink-2); flex-shrink:0; }
.job-icon svg { width:15px; height:15px; stroke-width:1.7; }
.job-icon.done { background:var(--accent-tint); color:var(--accent); border-color:transparent; }
.job-icon.running { background:#FFF8E5; color:#B35100; border-color:transparent; }
.job-icon.failed { background:#FFE7E2; color:var(--st-new); border-color:transparent; }
.job-info { min-width:0; }
.job-title { font-size:13px; font-weight:500; color:var(--ink); letter-spacing:-0.005em; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.job-meta { font-size:11.5px; color:var(--ink-3); margin-top:2px; font-family:var(--font-mono); font-feature-settings:'tnum'; letter-spacing:-0.005em; }
.job-status { display:inline-flex; align-items:center; gap:6px; font-size:11.5px; font-weight:500; }
.job-status .dot { width:7px; height:7px; border-radius:50%; position:relative; }
.job-status .dot::after { content:''; position:absolute; inset:-1px; border-radius:50%; border:1px solid rgba(10,19,25,0.10); }
.job-status.s-done .dot { background:var(--st-quote); }
.job-status.s-done { color:#006A3B; font-weight:600; }
.job-status.s-run .dot { background:var(--st-call); }
.job-status.s-run { color:var(--st-call); }
.job-status.s-fail .dot { background:var(--st-new); }
.job-status.s-fail { color:var(--st-new); }
.job-status.s-queued .dot { background:var(--ink-disabled); }
.job-status.s-queued { color:var(--ink-3); }
.job-action { display:inline-flex; gap:4px; }
.job-action button { width:26px; height:26px; border:1px solid var(--hairline); background:var(--surface); border-radius:var(--r-xs); color:var(--ink-2); cursor:pointer; display:inline-flex; align-items:center; justify-content:center; }
.job-action button:hover { border-color:var(--ink-disabled); color:var(--ink); }
.job-action button svg { width:12px; height:12px; stroke-width:1.7; }
.job-progress { width:140px; height:4px; background:var(--hairline-soft); border-radius:2px; overflow:hidden; margin-top:5px; position:relative; }
.job-progress .bar { height:100%; background:var(--accent); border-radius:2px; }
@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 60px; grid-template-columns:1fr; }
}
@media (max-width:768px) {
.app { grid-template-columns:1fr; }
.side { display:none; }
.topbar .crumb span:first-child { display:none; }
.field-row { grid-template-columns:1fr; }
.job { grid-template-columns:auto 1fr auto; }
.job-action { grid-column:1 / -1; justify-self:flex-end; }
}
</style>
</head>
<body>
<a href="#main" class="skip-link">К контенту</a>
<div class="app">
<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" href="#"><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"/></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"/></svg><span class="nav-text">Биллинг</span></a>
<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"><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"><circle cx="9" cy="7" r="4"/></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"/></svg><span class="nav-text">Настройки</span></a>
</nav>
</aside>
<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="user-chip" aria-label="Профиль · Иван Петров"><span class="ava" aria-hidden="true">ИП</span><span class="uname">Иван П.</span></button>
</div>
<main id="main" class="content">
<header class="page-h">
<div>
<h1 class="page-title">Отчёты</h1>
<div class="page-meta">очередь <span class="accent-num num">2</span>/3 · обработано за месяц <span class="num">38</span> · средний размер <span class="num">2.4 MB</span></div>
</div>
</header>
<!-- Form -->
<form class="section" aria-labelledby="form-h">
<div class="section-h">
<div>
<h2 id="form-h">Запросить отчёт</h2>
<div class="desc">Готовится асинхронно. При &gt; 5 000 строк — на email.</div>
</div>
</div>
<div class="field">
<label>Тип отчёта</label>
<div class="type-chips" role="radiogroup" aria-label="Тип отчёта">
<button type="button" class="tc-card active" role="radio" aria-checked="true">
<span class="tc-name">Сделки · детально</span>
<span class="tc-desc">все колонки, фильтры применены</span>
</button>
<button type="button" class="tc-card" role="radio" aria-checked="false">
<span class="tc-name">Менеджеры</span>
<span class="tc-desc">конверсия, средний чек, время в воронке</span>
</button>
<button type="button" class="tc-card" role="radio" aria-checked="false">
<span class="tc-name">Источники</span>
<span class="tc-desc">Я.Директ / VK / Avito / прямые</span>
</button>
<button type="button" class="tc-card" role="radio" aria-checked="false">
<span class="tc-name">Биллинг</span>
<span class="tc-desc">пополнения, списания, возвраты</span>
</button>
</div>
</div>
<div class="field-row">
<div class="field"><label for="r-from">Период с</label><input class="input mono" id="r-from" type="date" value="2026-04-01"></div>
<div class="field"><label for="r-to">по</label><input class="input mono" id="r-to" type="date" value="2026-05-07"></div>
</div>
<div class="field-row">
<div class="field"><label for="r-proj">Проект</label><select class="select" id="r-proj"><option>Все проекты</option><option>Окна Москва</option><option>Натяжные потолки</option><option>Кухни на заказ</option></select></div>
<div class="field"><label for="r-mng">Менеджер</label><select class="select" id="r-mng"><option>Все</option><option>Иван Петров</option><option>Мария Соколова</option></select></div>
</div>
<div class="field">
<label>Формат файла</label>
<div class="fmt-row" role="radiogroup" aria-label="Формат">
<button type="button" class="fmt-card active" role="radio" aria-checked="true">CSV</button>
<button type="button" class="fmt-card" role="radio" aria-checked="false">XLSX</button>
<button type="button" class="fmt-card" role="radio" aria-checked="false">JSON</button>
<button type="button" class="fmt-card" role="radio" aria-checked="false">PDF</button>
</div>
</div>
<div class="quota-banner" role="status">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.7" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 8v4M12 16h.01"/></svg>
<span>Квота: <strong>2 из 3</strong> одновременных отчётов · <span class="quota-bar"><span class="qd"></span><span class="qd"></span><span class="qd empty"></span></span> · до <strong>3 попыток retry</strong> в окне 7 дней.</span>
</div>
<div style="display:flex;gap:8px;margin-top:6px">
<button type="submit" class="btn btn-primary"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><polygon points="5 3 19 12 5 21 5 3"/></svg>Запустить</button>
<button type="reset" class="btn">Сброс</button>
</div>
</form>
<!-- Jobs list -->
<section class="section" style="padding:0">
<div class="section-h" style="padding:18px 22px 14px;margin-bottom:0">
<div>
<h2>Сгенерированные отчёты</h2>
<div class="desc">retry-failed для owner отчёта, до 3 попыток · 7 дней</div>
</div>
<button type="button" class="h-action">все 38 →</button>
</div>
<div class="jobs">
<div class="job">
<span class="job-icon done"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><polyline points="20 6 9 17 4 12"/></svg></span>
<div class="job-info">
<div class="job-title">Сделки · детально · апрель 2026</div>
<div class="job-meta">CSV · 1.8 MB · 412 строк · 14:21 → 14:23</div>
</div>
<span class="job-status s-done"><span class="dot" aria-hidden="true"></span>Готов</span>
<div class="job-action"><button type="button" aria-label="Скачать"><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></button><button type="button" aria-label="Удалить"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/></svg></button></div>
</div>
<div class="job">
<span class="job-icon running"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg></span>
<div class="job-info">
<div class="job-title">Менеджеры · апрель 2026</div>
<div class="job-meta">XLSX · в работе · ~30 секунд</div>
<div class="job-progress" role="progressbar" aria-label="Прогресс отчёта" aria-valuenow="62" aria-valuemin="0" aria-valuemax="100"><div class="bar" style="width:62%"></div></div>
</div>
<span class="job-status s-run"><span class="dot" aria-hidden="true"></span>В работе · 62%</span>
<div class="job-action"><button type="button" aria-label="Отменить" disabled style="opacity:0.4"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M18 6 6 18M6 6l12 12"/></svg></button></div>
</div>
<div class="job">
<span class="job-icon running"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg></span>
<div class="job-info">
<div class="job-title">Источники · последние 30 дней</div>
<div class="job-meta">JSON · в очереди · позиция 1</div>
</div>
<span class="job-status s-queued"><span class="dot" aria-hidden="true"></span>В очереди</span>
<div class="job-action"><button type="button" aria-label="Отменить"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M18 6 6 18M6 6l12 12"/></svg></button></div>
</div>
<div class="job">
<span class="job-icon failed"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><line x1="12" y1="8" x2="12" y2="13"/><circle cx="12" cy="16" r=".5"/></svg></span>
<div class="job-info">
<div class="job-title">Биллинг · март 2026</div>
<div class="job-meta">XLSX · 2/3 попытки · ошибка S3 timeout · 12:14</div>
</div>
<span class="job-status s-fail"><span class="dot" aria-hidden="true"></span>Ошибка</span>
<div class="job-action"><button type="button" aria-label="Повторить"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><polyline points="23 4 23 10 17 10"/><path d="M3.51 15a9 9 0 0 0 14.85 3.36"/></svg></button><button type="button" aria-label="Удалить"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14"/></svg></button></div>
</div>
<div class="job">
<span class="job-icon done"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><polyline points="20 6 9 17 4 12"/></svg></span>
<div class="job-info">
<div class="job-title">Менеджеры · март 2026</div>
<div class="job-meta">XLSX · 2.1 MB · 38 строк · 6 дней назад</div>
</div>
<span class="job-status s-done"><span class="dot" aria-hidden="true"></span>Готов</span>
<div class="job-action"><button type="button" aria-label="Скачать"><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></button><button type="button" aria-label="Удалить"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14"/></svg></button></div>
</div>
</div>
</section>
</main>
</div>
</div>
</body>
</html>