445 lines
26 KiB
HTML
445 lines
26 KiB
HTML
<!DOCTYPE html>
|
||
<!-- no-design-system -->
|
||
<!-- Дизайн: Стандартный дизайн. Финансовый рабочий экран КФУ. Палитра задана пользователем. -->
|
||
<html lang="ru" data-theme="light">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>КФУ — финансовая устойчивость</title>
|
||
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
|
||
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
|
||
<link rel="stylesheet" href="design-system/kt-ai-components.css">
|
||
<link rel="stylesheet" href="design-system/kt-ai-page.css">
|
||
<link rel="stylesheet" href="design-system/vibe-theme.css">
|
||
<script src="design-system/icons/kt-ai-icons.js"></script>
|
||
<script src="vendor/xlsx.full.min.js"></script>
|
||
<style>
|
||
/* Финансовые токены — пользовательские, поверх ДС */
|
||
:root {
|
||
--kfu-bg: #F4F6F8;
|
||
--kfu-surface: #FFFFFF;
|
||
--kfu-ink: #1E2430;
|
||
--kfu-ink-2: #5A6472;
|
||
--kfu-ink-3: #8A93A3;
|
||
--kfu-accent: #0D9AAA;
|
||
--kfu-accent-hover: #0A7E8C;
|
||
--kfu-accent-soft: #E4F4F5;
|
||
--kfu-border: #E1E5EA;
|
||
--kfu-border-2: #CBD2DB;
|
||
--kfu-risk: #C03D32;
|
||
--kfu-risk-bg: #FBEAE8;
|
||
--kfu-warn: #A5701A;
|
||
--kfu-warn-bg: #FDF4E3;
|
||
--kfu-ok: #247A4B;
|
||
--kfu-ok-bg: #E7F4EE;
|
||
--kfu-neutral: #5A6472;
|
||
--kfu-neutral-bg: #F0F2F5;
|
||
--kfu-radius: 10px;
|
||
--kfu-radius-sm: 6px;
|
||
--kfu-shadow: 0 1px 3px rgba(30,36,48,.06), 0 1px 2px rgba(30,36,48,.04);
|
||
--kfu-shadow-md: 0 4px 16px rgba(30,36,48,.08);
|
||
--kfu-max: 1180px;
|
||
}
|
||
|
||
@layer product {
|
||
[hidden] { display: none !important; }
|
||
.kfu-*, .kfu-::before, .kfu-::after, .kfu-topbar *, .kfu-topbar *::before, .kfu-topbar *::after, .kfu-wrap *, .kfu-wrap *::before, .kfu-wrap *::after, .kfu-drawer *, .kfu-drawer *::before, .kfu-drawer *::after { box-sizing: border-box; }
|
||
a.kt-ai-btn { text-decoration: none; }
|
||
body { background: var(--kfu-bg); }
|
||
.kt-ai-sidebar { display: none !important; }
|
||
|
||
/* ---------- верхняя полоса ---------- */
|
||
.kfu-topbar { position: sticky; top: 0; z-index: var(--kt-ai-z-sticky);
|
||
background: var(--kfu-surface); border-bottom: 1px solid var(--kfu-border);
|
||
height: 56px; display: flex; align-items: center; padding: 0 24px; gap: 16px; }
|
||
.kfu-brand { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
|
||
.kfu-brand-mark { width: 32px; height: 32px; border-radius: 8px; background: var(--kfu-ink);
|
||
color: #fff; display: flex; align-items: center; justify-content: center;
|
||
font-size: 14px; font-weight: 700; letter-spacing: .3px; }
|
||
.kfu-brand-text { line-height: 1.2; }
|
||
.kfu-brand-text b { display: block; font-size: 14px; font-weight: 600; color: var(--kfu-ink); letter-spacing: -.01em; }
|
||
.kfu-brand-text span { display: block; font-size: 11px; color: var(--kfu-ink-3); }
|
||
.kfu-topbar-right { margin-left: auto; display: flex; align-items: center; gap: 12px; }
|
||
.kfu-file-badge { font-size: 12px; color: var(--kfu-ink-2); display: flex; align-items: center; gap: 8px;
|
||
background: var(--kfu-neutral-bg); padding: 5px 12px; border-radius: var(--kfu-radius-sm);
|
||
max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.kfu-file-badge .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--kfu-accent); flex-shrink: 0; }
|
||
.kfu-btn { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 14px;
|
||
border-radius: var(--kfu-radius-sm); font-size: 13px; font-weight: 500; cursor: pointer;
|
||
border: 1px solid var(--kfu-border-2); background: var(--kfu-surface); color: var(--kfu-ink);
|
||
transition: background .12s, border-color .12s, box-shadow .12s; white-space: nowrap; }
|
||
.kfu-btn:hover { background: var(--kfu-bg); border-color: var(--kfu-accent); }
|
||
.kfu-btn:focus-visible { outline: 2px solid var(--kfu-accent); outline-offset: 1px; }
|
||
.kfu-btn.primary { background: var(--kfu-accent); color: #fff; border-color: var(--kfu-accent); }
|
||
.kfu-btn.primary:hover { background: var(--kfu-accent-hover); }
|
||
.kfu-btn svg { width: 15px; height: 15px; flex-shrink: 0; }
|
||
|
||
/* ---------- контент ---------- */
|
||
.kfu-wrap { max-width: var(--kfu-max); margin: 0 auto; padding: 24px 24px 64px; }
|
||
|
||
/* ---------- заголовок ---------- */
|
||
.kfu-header { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px;
|
||
margin-bottom: 20px; flex-wrap: wrap; }
|
||
.kfu-header-left { min-width: 0; }
|
||
.kfu-header h1 { font-size: 32px; font-weight: 600; color: var(--kfu-ink); letter-spacing: -.025em;
|
||
line-height: 1.15; margin: 0 0 6px; }
|
||
.kfu-header-sub { font-size: 15px; color: var(--kfu-ink-2); line-height: 1.4; margin: 0; }
|
||
.kfu-header-sub b { color: var(--kfu-ink); font-weight: 600; }
|
||
.kfu-recon-chip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px;
|
||
border-radius: var(--kfu-radius-sm); background: var(--kfu-ok-bg); color: var(--kfu-ok);
|
||
font-size: 12px; font-weight: 500; white-space: nowrap; flex-shrink: 0; }
|
||
.kfu-recon-chip svg { width: 14px; height: 14px; }
|
||
|
||
/* ---------- сводка (горизонтальная полоса) ---------- */
|
||
.kfu-brief { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
|
||
background: var(--kfu-border); border: 1px solid var(--kfu-border); border-radius: var(--kfu-radius);
|
||
overflow: hidden; margin-bottom: 20px; box-shadow: var(--kfu-shadow); }
|
||
.kfu-brief-item { background: var(--kfu-surface); padding: 16px 20px; display: flex; align-items: center; gap: 14px; }
|
||
.kfu-brief-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
|
||
.kfu-brief-dot.risk { background: var(--kfu-risk); }
|
||
.kfu-brief-dot.warn { background: var(--kfu-warn); }
|
||
.kfu-brief-dot.ok { background: var(--kfu-ok); }
|
||
.kfu-brief-dot.neutral { background: var(--kfu-neutral); }
|
||
.kfu-brief-num { font-size: 28px; font-weight: 600; letter-spacing: -.02em; font-variant-numeric: tabular-nums;
|
||
line-height: 1; color: var(--kfu-ink); }
|
||
.kfu-brief-num-b { font-size: 13px; font-weight: 500; color: var(--kfu-ink-3); margin-left: 6px; line-height: 1; }
|
||
.kfu-brief-lbl { font-size: 12px; color: var(--kfu-ink-3); margin-top: 2px; }
|
||
|
||
/* ---------- поиск + фильтры ---------- */
|
||
.kfu-toolbar { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }
|
||
.kfu-search { position: relative; flex: 0 1 300px; min-width: 200px; }
|
||
.kfu-search svg { position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
|
||
width: 15px; height: 15px; color: var(--kfu-ink-3); pointer-events: none; }
|
||
.kfu-search input { width: 100%; height: 34px; padding: 0 12px 0 32px; border-radius: var(--kfu-radius-sm);
|
||
border: 1px solid var(--kfu-border-2); background: var(--kfu-surface); font-size: 13px; color: var(--kfu-ink);
|
||
transition: border-color .12s, box-shadow .12s; }
|
||
.kfu-search input:focus { outline: none; border-color: var(--kfu-accent); box-shadow: 0 0 0 3px var(--kfu-accent-soft); }
|
||
.kfu-search input::placeholder { color: var(--kfu-ink-3); }
|
||
.kfu-chip-filter { display: inline-flex; align-items: center; height: 32px; padding: 0 14px;
|
||
border-radius: var(--kfu-radius-sm); border: 1px solid var(--kfu-border-2); background: var(--kfu-surface);
|
||
font-size: 13px; font-weight: 500; color: var(--kfu-ink-2); cursor: pointer;
|
||
transition: all .12s; white-space: nowrap; }
|
||
.kfu-chip-filter:hover { border-color: var(--kfu-accent); color: var(--kfu-ink); }
|
||
.kfu-chip-filter.active { background: var(--kfu-accent); color: #fff; border-color: var(--kfu-accent); }
|
||
.kfu-table-count { font-size: 13px; color: var(--kfu-ink-3); margin-left: auto; white-space: nowrap; }
|
||
|
||
/* ---------- таблица ---------- */
|
||
.kfu-table-card { background: var(--kfu-surface); border: 1px solid var(--kfu-border);
|
||
border-radius: var(--kfu-radius); box-shadow: var(--kfu-shadow); overflow-x: auto; }
|
||
.kfu-table { width: 100%; border-collapse: collapse; table-layout: fixed; }
|
||
.kfu-table colgroup col:nth-child(1) { width: 26%; }
|
||
.kfu-table colgroup col:nth-child(2) { width: 12%; }
|
||
.kfu-table colgroup col:nth-child(3) { width: 10%; }
|
||
.kfu-table colgroup col:nth-child(4) { width: 10%; }
|
||
.kfu-table colgroup col:nth-child(5) { width: 10%; }
|
||
.kfu-table colgroup col:nth-child(6) { width: 32%; }
|
||
.kfu-table thead th { padding: 10px 14px; font-size: 11px; font-weight: 600; color: var(--kfu-ink-3);
|
||
text-transform: uppercase; letter-spacing: .5px; border-bottom: 1px solid var(--kfu-border);
|
||
background: var(--kfu-bg); text-align: right; white-space: nowrap; cursor: pointer; user-select: none;
|
||
position: sticky; top: 0; z-index: 1; }
|
||
.kfu-table thead th:last-child { text-align: left; white-space: nowrap; text-transform: none; font-weight: 500; }
|
||
.kfu-table thead th:first-child { text-align: left; }
|
||
.kfu-table thead th .th-sub { display: block; font-weight: 400; text-transform: none; letter-spacing: 0;
|
||
font-size: 10px; color: var(--kfu-ink-3); opacity: .7; margin-top: 1px; }
|
||
.kfu-table thead th.sorted-asc::after { content: " ↑"; color: var(--kfu-accent); }
|
||
.kfu-table thead th.sorted-desc::after { content: " ↓"; color: var(--kfu-accent); }
|
||
.kfu-table tbody tr { cursor: pointer; transition: background .1s; }
|
||
.kfu-table tbody tr:hover { background: var(--kfu-bg); }
|
||
.kfu-table tbody tr.is-group { background: var(--kfu-neutral-bg); }
|
||
.kfu-table tbody tr.is-group:hover { background: #E8EBEF; }
|
||
.kfu-table td { padding: 12px 14px; border-bottom: 1px solid var(--kfu-border); font-size: 14px;
|
||
text-align: right; font-variant-numeric: tabular-nums; vertical-align: middle; }
|
||
.kfu-table td:first-child { text-align: left; }
|
||
.kfu-table td:first-child .co-name { font-weight: 500; color: var(--kfu-ink); line-height: 1.3;
|
||
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; word-break: break-word; }
|
||
.kfu-table td:first-child .co-sub { font-size: 11px; color: var(--kfu-ink-3); margin-top: 1px; }
|
||
|
||
/* метка учебного режима */
|
||
.kfu-mock-chip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px;
|
||
border-radius: var(--kfu-radius-sm); background: var(--kfu-warn-bg); color: var(--kfu-warn);
|
||
font-size: 12px; font-weight: 600; letter-spacing: .3px; text-transform: uppercase; white-space: nowrap; flex-shrink: 0; }
|
||
|
||
/* статус-метка */
|
||
.kfu-status { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 500;
|
||
padding: 3px 10px; border-radius: 5px; white-space: nowrap; }
|
||
.kfu-status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
|
||
.kfu-status.s-red { background: var(--kfu-risk-bg); color: var(--kfu-risk); }
|
||
.kfu-status.s-yellow { background: var(--kfu-warn-bg); color: var(--kfu-warn); }
|
||
.kfu-status.s-green { background: var(--kfu-ok-bg); color: var(--kfu-ok); }
|
||
.kfu-status.s-nodefault { background: var(--kfu-neutral-bg); color: var(--kfu-neutral); }
|
||
.kfu-status.s-nodata { background: var(--kfu-neutral-bg); color: var(--kfu-neutral); }
|
||
|
||
/* ячейка коэффициента: число + точка */
|
||
.kfu-coef { display: inline-flex; align-items: baseline; gap: 6px; }
|
||
.kfu-coef .cv { font-weight: 500; font-variant-numeric: tabular-nums; }
|
||
.kfu-coef .cd { width: 6px; height: 6px; border-radius: 50%; align-self: center; flex-shrink: 0; }
|
||
.kfu-coef .cd.c-green { background: var(--kfu-ok); }
|
||
.kfu-coef .cd.c-yellow { background: var(--kfu-warn); }
|
||
.kfu-coef .cd.c-red { background: var(--kfu-risk); }
|
||
.kfu-coef .cd.c-nodefault { background: var(--kfu-neutral); }
|
||
.kfu-coef .cd.c-nodata { background: var(--kfu-neutral); opacity: .4; }
|
||
.kfu-coef .cv.cv-red { color: var(--kfu-risk); }
|
||
.kfu-coef .cv.cv-yellow { color: var(--kfu-warn); }
|
||
.kfu-coef .cv-none { color: var(--kfu-ink-3); font-size: 13px; }
|
||
.kfu-cause { font-size: 13px; color: var(--kfu-ink-2); line-height: 1.45; }
|
||
.kfu-table td:last-child { text-align: left; }
|
||
.kfu-cause.caution { color: var(--kfu-warn); font-weight: 500; }
|
||
.kfu-cause.danger { color: var(--kfu-risk); font-weight: 500; }
|
||
.kfu-dash { color: var(--kfu-ink-3); }
|
||
|
||
/* ---------- блок группы ---------- */
|
||
.kfu-group-block { margin-top: 16px; background: var(--kfu-surface); border: 1px solid var(--kfu-border);
|
||
border-radius: var(--kfu-radius); box-shadow: var(--kfu-shadow); overflow: hidden; }
|
||
.kfu-group-header { padding: 12px 16px; background: var(--kfu-neutral-bg); border-bottom: 1px solid var(--kfu-border);
|
||
font-size: 12px; font-weight: 600; color: var(--kfu-ink-2); text-transform: uppercase; letter-spacing: .4px; }
|
||
.kfu-group-block .kfu-table thead { display: none; }
|
||
.kfu-group-block .kfu-table td:first-child { font-weight: 600; }
|
||
|
||
/* ---------- диагностика ---------- */
|
||
.kfu-diag { margin-top: 20px; background: var(--kfu-surface); border: 1px solid var(--kfu-border);
|
||
border-radius: var(--kfu-radius); box-shadow: var(--kfu-shadow); }
|
||
.kfu-diag summary { padding: 12px 16px; font-size: 13px; font-weight: 500; color: var(--kfu-ink-2);
|
||
cursor: pointer; list-style: none; display: flex; align-items: center; gap: 8px;
|
||
font-variant-numeric: tabular-nums; }
|
||
.kfu-diag summary::-webkit-details-marker { display: none; }
|
||
.kfu-diag summary::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--kfu-warn); }
|
||
.kfu-diag[open] summary::before { background: var(--kfu-accent); }
|
||
.kfu-diag-list { padding: 0 16px 12px; max-height: 200px; overflow-y: auto; list-style: none; margin: 0; }
|
||
.kfu-diag-list li { padding: 6px 0; border-top: 1px solid var(--kfu-border); font-size: 12px;
|
||
color: var(--kfu-ink-2); font-family: var(--kt-ai-font-mono); font-variant-numeric: tabular-nums; }
|
||
.kfu-diag-list li:first-child { border-top: none; }
|
||
|
||
/* ---------- первая загрузка ---------- */
|
||
.kfu-upload { display: flex; flex-direction: column; align-items: center; justify-content: center;
|
||
text-align: center; padding: 72px 32px; background: var(--kfu-surface); border: 1px solid var(--kfu-border);
|
||
border-radius: var(--kfu-radius); box-shadow: var(--kfu-shadow); }
|
||
.kfu-upload-icon { width: 56px; height: 56px; border-radius: 14px; background: var(--kfu-accent-soft);
|
||
color: var(--kfu-accent); display: flex; align-items: center; justify-content: center; margin-bottom: 20px; }
|
||
.kfu-upload-icon svg { width: 28px; height: 28px; }
|
||
.kfu-upload h2 { font-size: 22px; font-weight: 600; color: var(--kfu-ink); letter-spacing: -.015em; margin: 0 0 8px; }
|
||
.kfu-upload p { font-size: 15px; color: var(--kfu-ink-2); max-width: 400px; line-height: 1.5; margin: 0 0 24px; }
|
||
.kfu-upload-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
|
||
.kfu-upload-note { margin-top: 16px; font-size: 12px; color: var(--kfu-ink-3); }
|
||
|
||
/* ---------- drawer (карточка компании) ---------- */
|
||
.kfu-drawer { position: fixed; top: 0; right: 0; bottom: 0; width: 520px; max-width: 94vw;
|
||
background: var(--kfu-surface); border-left: 1px solid var(--kfu-border); box-shadow: var(--kfu-shadow-md);
|
||
z-index: 100; padding: 24px; overflow-y: auto; display: none; }
|
||
.kfu-drawer.open { display: block; animation: kfuSlide .18s ease-out; }
|
||
@keyframes kfuSlide { from { transform: translateX(24px); opacity: .4; } to { transform: none; opacity: 1; } }
|
||
.kfu-drawer-head { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 20px; }
|
||
.kfu-drawer-head h2 { font-size: 22px; font-weight: 600; color: var(--kfu-ink); letter-spacing: -.02em;
|
||
line-height: 1.2; margin: 0 0 4px; flex: 1; }
|
||
.kfu-drawer-head .close-btn { margin-left: auto; flex-shrink: 0; width: 32px; height: 32px;
|
||
border-radius: var(--kfu-radius-sm); border: 1px solid var(--kfu-border); background: var(--kfu-surface);
|
||
cursor: pointer; display: flex; align-items: center; justify-content: center; color: var(--kfu-ink-2); }
|
||
.kfu-drawer-head .close-btn:hover { background: var(--kfu-bg); }
|
||
.kfu-drawer-head .close-btn svg { width: 16px; height: 16px; }
|
||
.kfu-drawer-section { margin-bottom: 20px; }
|
||
.kfu-drawer-section h3 { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .6px;
|
||
color: var(--kfu-ink-3); margin: 0 0 10px; }
|
||
|
||
/* коэффициент в drawer */
|
||
.kfu-metrics { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
|
||
.kfu-metric { border: 1px solid var(--kfu-border); border-radius: var(--kfu-radius-sm); padding: 12px;
|
||
background: var(--kfu-bg); }
|
||
.kfu-metric .mlabel { font-size: 11px; font-weight: 600; color: var(--kfu-ink-3);
|
||
text-transform: uppercase; letter-spacing: .3px; margin-bottom: 6px; display: flex; align-items: center; gap: 5px; }
|
||
.kfu-metric .mlabel .sdot { width: 6px; height: 6px; border-radius: 50%; }
|
||
.kfu-metric .mval { font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -.01em;
|
||
color: var(--kfu-ink); }
|
||
.kfu-metric .mval.mval-red { color: var(--kfu-risk); }
|
||
.kfu-metric .mval.mval-yellow { color: var(--kfu-warn); }
|
||
.kfu-metric .mval.mval-none { color: var(--kfu-ink-3); font-size: 14px; font-weight: 500; }
|
||
.kfu-metric .mhint { font-size: 11px; color: var(--kfu-ink-3); margin-top: 4px; font-variant-numeric: tabular-nums; }
|
||
.kfu-metric .mwhy { font-size: 11px; color: var(--kfu-warn); margin-top: 3px; font-weight: 500; }
|
||
.kfu-metric .mformula { font-size: 10px; color: var(--kfu-ink-3); margin-top: 6px;
|
||
padding-top: 6px; border-top: 1px solid var(--kfu-border); font-family: var(--kt-ai-font-mono); }
|
||
|
||
/* исходные данные */
|
||
.kfu-sources { width: 100%; border-collapse: collapse; font-size: 13px; }
|
||
.kfu-sources td { padding: 7px 0; border-bottom: 1px solid var(--kfu-border); vertical-align: top; }
|
||
.kfu-sources td:last-child { text-align: right; font-family: var(--kt-ai-font-mono); font-size: 12px;
|
||
color: var(--kfu-ink-2); white-space: nowrap; padding-left: 12px; font-variant-numeric: tabular-nums; }
|
||
.kfu-sources .src-addr { font-size: 11px; color: var(--kfu-ink-3); font-family: var(--kt-ai-font-mono); }
|
||
|
||
/* сценарий */
|
||
.kfu-scenario-lbl { font-size: 13px; color: var(--kfu-ink-2); margin-bottom: 8px; line-height: 1.4; }
|
||
.kfu-scenario-lbl b { color: var(--kfu-ink); font-weight: 600; font-variant-numeric: tabular-nums; }
|
||
.kfu-scenario-row { display: flex; gap: 8px; align-items: stretch; }
|
||
.kfu-scenario-row .kfu-input { flex: 1; font-variant-numeric: tabular-nums; font-size: 14px;
|
||
height: 38px; border-radius: var(--kfu-radius-sm); padding: 0 12px; border: 1px solid var(--kfu-border-2);
|
||
background: var(--kfu-surface); color: var(--kfu-ink); }
|
||
.kfu-scenario-row .kfu-input:focus { outline: none; border-color: var(--kfu-accent); box-shadow: 0 0 0 3px var(--kfu-accent-soft); }
|
||
.kfu-scenario-hint { font-size: 12px; color: var(--kfu-ink-3); margin-top: 8px; line-height: 1.4; }
|
||
|
||
/* раскрываемый раздел источников */
|
||
.kfu-sources-block summary { font-size: 12px; font-weight: 500; color: var(--kfu-ink-2); cursor: pointer;
|
||
padding: 8px 0; list-style: none; display: flex; align-items: center; gap: 6px; }
|
||
.kfu-sources-block summary::-webkit-details-marker { display: none; }
|
||
.kfu-sources-block summary::after { content: " →"; font-size: 12px; transition: transform .15s; }
|
||
.kfu-sources-block[open] summary::after { transform: rotate(90deg); }
|
||
|
||
/* ---------- toast ---------- */
|
||
.kfu-toast-stack { position: fixed; bottom: 20px; right: 20px; z-index: 200; display: flex; flex-direction: column; gap: 8px; }
|
||
.kfu-toast { padding: 10px 16px; border-radius: 8px; background: var(--kfu-ink); color: #fff;
|
||
font-size: 13px; box-shadow: var(--kfu-shadow-md); display: flex; align-items: center; gap: 8px;
|
||
animation: kfuToastIn .15s ease-out; max-width: 400px; }
|
||
.kfu-toast.err { background: var(--kfu-risk); }
|
||
@keyframes kfuToastIn { from { transform: translateY(8px); opacity: 0; } to { transform: none; opacity: 1; } }
|
||
|
||
/* ---------- empty state ---------- */
|
||
.kfu-empty { padding: 40px 24px; text-align: center; color: var(--kfu-ink-3); font-size: 14px; }
|
||
.kfu-empty svg { width: 28px; height: 28px; margin-bottom: 8px; opacity: .4; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body class="kt-ai-app">
|
||
|
||
<!-- верхняя полоса -->
|
||
<header class="kfu-topbar">
|
||
<div class="kfu-brand">
|
||
<div class="kfu-brand-mark">КФУ</div>
|
||
<div class="kfu-brand-text">
|
||
<b>Финансовый мониторинг</b>
|
||
<span>Факт 2025</span>
|
||
</div>
|
||
</div>
|
||
<div class="kfu-topbar-right">
|
||
<span class="kfu-file-badge" id="fileBadge" hidden>
|
||
<span class="dot"></span>
|
||
<span id="fileBadgeText"></span>
|
||
</span>
|
||
<button class="kfu-btn" id="btnReplace" hidden>
|
||
<svg class="kt-icon" aria-hidden="true"><use href="#upload"></use></svg>
|
||
Заменить файл
|
||
</button>
|
||
<button class="kfu-btn primary" id="btnExport" hidden>
|
||
<svg class="kt-icon" aria-hidden="true"><use href="#download"></use></svg>
|
||
Выгрузить отчёт
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="kfu-wrap">
|
||
|
||
<!-- заголовок -->
|
||
<div class="kfu-header" id="headerBlock">
|
||
<div class="kfu-header-left">
|
||
<h1>Финансовая устойчивость</h1>
|
||
<p class="kfu-header-sub" id="headerSub"></p>
|
||
</div>
|
||
<div style="display:flex;gap:8px;align-items:center">
|
||
<span class="kfu-mock-chip" id="mockChip" hidden>Учебный пример · синтетические данные</span>
|
||
<span class="kfu-recon-chip" id="reconChip" hidden>
|
||
<svg class="kt-icon" aria-hidden="true"><use href="#check"></use></svg>
|
||
<span id="reconChipText"></span>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- сводка -->
|
||
<div class="kfu-brief" id="brief" hidden>
|
||
<div class="kfu-brief-item">
|
||
<span class="kfu-brief-dot risk"></span>
|
||
<div><span class="kfu-brief-num" id="briefRed">0</span><div class="kfu-brief-lbl">Нарушения</div></div>
|
||
</div>
|
||
<div class="kfu-brief-item">
|
||
<span class="kfu-brief-dot warn"></span>
|
||
<div><span class="kfu-brief-num" id="briefYellow">0</span><div class="kfu-brief-lbl">Под наблюдением</div></div>
|
||
</div>
|
||
<div class="kfu-brief-item">
|
||
<span class="kfu-brief-dot ok"></span>
|
||
<div><span class="kfu-brief-num" id="briefGreen">0</span><span class="kfu-brief-num-b" id="briefGreenSub"></span><div class="kfu-brief-lbl">В норме</div></div>
|
||
</div>
|
||
<div class="kfu-brief-item">
|
||
<span class="kfu-brief-dot neutral"></span>
|
||
<div><span class="kfu-brief-num" id="briefNoNorm">0</span><div class="kfu-brief-lbl">Без нормативов</div></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- поиск + фильтры -->
|
||
<div class="kfu-toolbar" id="toolbar" hidden>
|
||
<div class="kfu-search">
|
||
<svg class="kt-icon" aria-hidden="true"><use href="#search"></use></svg>
|
||
<input type="text" id="q" placeholder="Поиск по названию…">
|
||
</div>
|
||
<button class="kfu-chip-filter active" data-zone="" id="zoneAll">Все</button>
|
||
<button class="kfu-chip-filter" data-zone="red" id="zoneRed">Нарушения</button>
|
||
<button class="kfu-chip-filter" data-zone="yellow" id="zoneYellow">Под наблюдением</button>
|
||
<button class="kfu-chip-filter" data-zone="nodefault" id="zoneNoNorm">Без нормативов</button>
|
||
<span class="kfu-table-count" id="tableCount"></span>
|
||
</div>
|
||
|
||
<!-- таблица компаний -->
|
||
<div class="kfu-table-card" id="tableWrap" hidden>
|
||
<table class="kfu-table">
|
||
<colgroup><col><col><col><col><col><col></colgroup>
|
||
<thead>
|
||
<tr>
|
||
<th data-k="name">Компания</th>
|
||
<th>Статус</th>
|
||
<th data-k="k1">К1<span class="th-sub">Debt/EBITDA</span></th>
|
||
<th data-k="k2">К2<span class="th-sub">EBITDA/Int</span></th>
|
||
<th data-k="k3">К3<span class="th-sub">Debt/Equity</span></th>
|
||
<th>Причина</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="tbody"></tbody>
|
||
</table>
|
||
<div class="kfu-empty" id="emptyState" hidden>
|
||
<svg class="kt-icon" aria-hidden="true"><use href="#search"></use></svg>
|
||
<div>Ничего не найдено. Измените фильтры.</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- блок группы -->
|
||
<div class="kfu-group-block" id="groupBlock" hidden>
|
||
<div class="kfu-group-header">Консолидированная группа</div>
|
||
<table class="kfu-table" style="border-radius:0">
|
||
<colgroup><col><col><col><col><col><col></colgroup>
|
||
<tbody id="groupTbody"></tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- первая загрузка -->
|
||
<div class="kfu-upload" id="uploadPanel">
|
||
<div class="kfu-upload-icon">
|
||
<svg class="kt-icon" aria-hidden="true"><use href="#upload"></use></svg>
|
||
</div>
|
||
<h2>Загрузите сводную книгу</h2>
|
||
<p>Получите коэффициенты, зоны риска и отчёт в .xlsx</p>
|
||
<div class="kfu-upload-actions">
|
||
<button class="kfu-btn primary" id="btnUpload" style="height:40px;padding:0 24px;font-size:14px">
|
||
<svg class="kt-icon" aria-hidden="true"><use href="#upload"></use></svg>
|
||
Загрузить .xlsx
|
||
</button>
|
||
<button class="kfu-btn" id="btnSample" style="height:40px;padding:0 20px;font-size:14px">
|
||
<svg class="kt-icon" aria-hidden="true"><use href="#spreadsheet"></use></svg>
|
||
Учебный пример
|
||
</button>
|
||
</div>
|
||
<p style="font-size:12px;color:var(--kfu-ink-3);margin:16px 0 0">Файл обрабатывается в браузере и не отправляется на сервер</p>
|
||
</div>
|
||
|
||
<!-- диагностика -->
|
||
<details class="kfu-diag" id="diagBlock" hidden>
|
||
<summary id="diagSummary"></summary>
|
||
<ul class="kfu-diag-list" id="diagList"></ul>
|
||
</details>
|
||
|
||
</div>
|
||
|
||
<!-- drawer -->
|
||
<aside class="kfu-drawer" id="drawer" role="dialog" aria-modal="false" aria-labelledby="drawerTitle">
|
||
<div id="drawerBody"></div>
|
||
</aside>
|
||
|
||
<div class="kfu-toast-stack" id="toasts"></div>
|
||
|
||
<input type="file" id="fileInput" accept=".xlsx,.xls" style="display:none">
|
||
|
||
<script src="kfu-client.js"></script>
|
||
</body>
|
||
</html>
|