1492 lines
37 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

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

<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>MoexVibe - брокерский счет</title>
<style>
:root {
--canvas: #f4f6f4;
--surface: #ffffff;
--surface-subtle: #f8faf8;
--surface-tint: #eef6f1;
--text: #17211c;
--muted: #647067;
--soft: #8a948e;
--line: #dfe6e1;
--line-strong: #cbd8d0;
--primary: #176747;
--primary-dark: #0f4e35;
--primary-soft: #e5f2ea;
--blue: #2563eb;
--blue-soft: #e8f0ff;
--amber: #b7791f;
--amber-soft: #fff5dc;
--negative: #b42318;
--positive: #176747;
--shadow: 0 12px 34px rgba(24, 38, 31, 0.08);
--radius: 8px;
color-scheme: light;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
background: var(--canvas);
color: var(--text);
font-family:
Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
line-height: 1.45;
}
button,
input {
font: inherit;
}
button:focus-visible,
a:focus-visible,
input:focus-visible {
outline: 2px solid #5f9ed8;
outline-offset: 2px;
}
a {
color: var(--primary);
text-decoration: none;
}
.app-shell {
min-height: 100vh;
}
.topbar {
height: 56px;
border-bottom: 1px solid var(--line);
background: rgba(255, 255, 255, 0.88);
backdrop-filter: blur(12px);
display: grid;
grid-template-columns: minmax(180px, 1fr) auto minmax(180px, 1fr);
align-items: center;
gap: 24px;
padding: 0 18px;
position: sticky;
top: 0;
z-index: 20;
}
.brand-row,
.user-row,
.main-nav {
display: flex;
align-items: center;
}
.brand-row {
gap: 16px;
}
.brand {
font-weight: 800;
letter-spacing: 0;
}
.search {
width: min(210px, 36vw);
height: 38px;
border: 1px solid var(--line-strong);
border-radius: var(--radius);
background: #fff;
color: var(--muted);
padding: 0 12px;
}
.main-nav {
gap: 8px;
justify-content: center;
}
.main-nav a {
color: #2f3a34;
font-size: 13px;
font-weight: 650;
padding: 8px 10px;
border-radius: var(--radius);
}
.main-nav a.active {
color: var(--primary);
background: var(--primary-soft);
}
.user-row {
justify-content: flex-end;
gap: 12px;
color: var(--muted);
font-size: 13px;
}
.ghost-button {
border: 1px solid var(--line);
background: #fff;
color: var(--muted);
border-radius: var(--radius);
padding: 7px 12px;
}
.page {
width: min(1040px, calc(100vw - 32px));
margin: 28px auto 56px;
display: grid;
gap: 18px;
}
.page-title-row {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 16px;
min-height: 72px;
}
.page-title-main {
display: flex;
align-items: center;
gap: 18px;
min-width: 0;
min-height: 72px;
flex: 1 1 auto;
}
.page-title-skeleton {
width: 100%;
justify-content: flex-start;
}
.page-title-skeleton-main {
display: grid;
gap: 10px;
flex: 1 1 auto;
min-width: 0;
}
.page-title-skeleton-main .skel.full {
width: min(100%, 320px);
height: 44px;
}
.page-title-skeleton-main .skel.medium {
width: min(100%, 96px);
height: 12px;
}
.page-title-skeleton-side {
display: grid;
gap: 8px;
flex: 0 0 108px;
min-width: 108px;
align-content: center;
}
.page-title-skeleton-side .skel.short:first-child {
width: 74px;
height: 12px;
}
.page-title-skeleton-side .skel.short:last-child {
width: 104px;
height: 32px;
}
h1 {
margin: 0;
font-size: clamp(30px, 4vw, 48px);
line-height: 1.02;
letter-spacing: 0;
font-weight: 760;
}
.page-yield {
display: grid;
gap: 2px;
min-width: 108px;
}
.page-yield .metric-label {
font-size: 11px;
}
.page-yield-value {
font-size: 24px;
font-weight: 760;
line-height: 1;
}
.screen-toggle {
display: inline-flex;
align-items: center;
border: 1px solid var(--line-strong);
background: #fff;
border-radius: var(--radius);
padding: 3px;
gap: 2px;
}
.screen-toggle button {
border: 0;
background: transparent;
color: var(--muted);
border-radius: 6px;
padding: 7px 11px;
cursor: pointer;
font-size: 13px;
font-weight: 650;
}
.screen-toggle button.active {
color: #fff;
background: var(--primary);
}
.account-tabs {
display: flex;
gap: 4px;
border-bottom: 1px solid var(--line);
overflow-x: auto;
padding-bottom: 5px;
}
.account-tabs a {
flex: 0 0 auto;
color: var(--muted);
font-size: 13px;
font-weight: 650;
padding: 9px 12px;
border-radius: var(--radius);
}
.account-tabs a.active {
background: var(--primary-soft);
color: var(--primary);
}
.hero {
border: 1px solid #91c7a8;
background:
linear-gradient(135deg, rgba(229, 242, 234, 0.9), rgba(255, 255, 255, 0.85)),
var(--surface);
border-radius: 18px;
padding: 20px;
display: grid;
grid-template-columns: 1fr;
gap: 14px;
align-items: stretch;
}
.hero-kicker,
.metric-label,
.section-kicker,
th {
color: var(--muted);
font-size: 12px;
font-weight: 700;
}
.hero-name {
margin-top: 3px;
font-size: 28px;
line-height: 1.12;
font-weight: 800;
}
.metric {
background: rgba(255, 255, 255, 0.58);
border: 1px solid rgba(145, 199, 168, 0.46);
border-radius: var(--radius);
padding: 12px;
min-height: 78px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.metric-value {
margin-top: 5px;
font-size: 18px;
font-weight: 760;
white-space: nowrap;
}
.metric-value.positive {
color: var(--positive);
}
.metric-value.negative {
color: var(--negative);
}
.metric-note {
color: var(--soft);
font-size: 12px;
}
.metric-note.positive {
color: #3f745a;
}
.metric-note.negative {
color: #a04e4e;
}
.portfolio-trend {
border-radius: 14px;
display: grid;
gap: 10px;
min-width: 0;
}
.portfolio-trend-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
}
.portfolio-trend-meta {
display: grid;
gap: 2px;
}
.portfolio-trend-title {
margin: 0;
font-size: 24px;
line-height: 1.08;
font-weight: 780;
}
.portfolio-trend svg {
width: 100%;
height: 120px;
display: block;
margin: 0 -20px;
width: calc(100% + 40px);
}
.trend-area {
fill: rgba(23, 103, 71, 0.08);
}
.trend-area-fill {
fill: rgba(23, 103, 71, 0.12);
}
.trend-line {
fill: none;
stroke: var(--primary);
stroke-width: 3;
stroke-linecap: round;
stroke-linejoin: round;
}
.trend-guide {
stroke: rgba(23, 103, 71, 0.14);
stroke-width: 1;
stroke-dasharray: 4 6;
}
.trend-point {
fill: #fff;
stroke: var(--primary);
stroke-width: 3;
}
.trend-axis {
position: relative;
margin: 0 -20px;
width: calc(100% + 40px);
height: 24px;
color: var(--soft);
font-size: 11px;
font-weight: 700;
}
.trend-axis span {
position: absolute;
bottom: 0;
transform: translateX(-50%);
}
.trend-axis span:first-child {
left: 12px;
transform: translateX(0);
}
.trend-axis span:nth-child(2) {
left: 20%;
}
.trend-axis span:nth-child(3) {
left: 40%;
}
.trend-axis span:nth-child(4) {
left: 60%;
}
.trend-axis span:nth-child(5) {
left: 80%;
}
.trend-axis span:last-child {
left: calc(100% - 12px);
transform: translateX(-100%);
}
.analytics-panel {
min-height: 254px;
position: relative;
overflow: hidden;
}
.card.portfolio-history-card {
border-color: #91c7a8;
background:
linear-gradient(135deg, rgba(229, 242, 234, 0.96), rgba(255, 255, 255, 0.86)),
var(--surface);
}
.portfolio-history-card .data-only,
.portfolio-history-card .loading-only {
min-height: 208px;
}
.card {
background: var(--surface);
border: 1px solid var(--line);
border-radius: 14px;
box-shadow: var(--shadow);
padding: 18px;
min-width: 0;
}
.card-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 14px;
margin-bottom: 14px;
}
.card-title {
display: flex;
align-items: baseline;
gap: 10px;
}
h2 {
margin: 0;
font-size: 22px;
line-height: 1.18;
letter-spacing: 0;
font-weight: 760;
}
.count-badge {
color: var(--muted);
background: var(--surface-subtle);
border: 1px solid var(--line);
border-radius: 999px;
padding: 3px 8px;
font-size: 12px;
font-weight: 700;
}
.card-link {
font-size: 13px;
font-weight: 700;
white-space: nowrap;
}
.table-toolbar {
display: grid;
grid-template-columns: minmax(240px, 1fr) auto auto;
gap: 10px;
align-items: center;
border: 1px solid var(--line);
background: var(--surface-subtle);
border-radius: 10px;
padding: 9px;
margin-bottom: 12px;
}
.control-group {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
}
.control-label {
color: var(--muted);
font-size: 12px;
font-weight: 750;
white-space: nowrap;
}
.chips {
display: flex;
gap: 6px;
flex-wrap: wrap;
}
.chip {
height: 30px;
display: inline-flex;
align-items: center;
gap: 6px;
border: 1px solid var(--line-strong);
border-radius: 999px;
background: #fff;
color: var(--muted);
padding: 0 10px;
font-size: 12px;
font-weight: 760;
cursor: pointer;
}
.chip.active {
border-color: transparent;
color: #fff;
background: var(--primary);
}
.chip.info.active {
background: var(--blue);
}
.chip.warning.active {
color: #473000;
background: #f4c447;
}
.period-wrap {
position: relative;
}
.period-button,
.apply-button,
.pager-button {
height: 32px;
border-radius: var(--radius);
cursor: pointer;
font-size: 12px;
font-weight: 760;
}
.period-button {
display: inline-flex;
align-items: center;
gap: 8px;
border: 1px solid var(--line-strong);
background: #fff;
color: var(--text);
padding: 0 10px;
white-space: nowrap;
}
.calendar-icon {
width: 14px;
height: 14px;
border: 1.8px solid currentColor;
border-radius: 3px;
position: relative;
}
.calendar-icon::before {
content: "";
position: absolute;
left: -1.8px;
right: -1.8px;
top: 3px;
border-top: 1.8px solid currentColor;
}
.chevron-icon {
width: 7px;
height: 7px;
border-right: 1.8px solid currentColor;
border-bottom: 1.8px solid currentColor;
color: var(--soft);
transform: rotate(45deg) translateY(-1px);
flex: 0 0 auto;
}
.period-popover {
position: absolute;
right: 0;
top: 40px;
width: 330px;
display: none;
background: #fff;
border: 1px solid var(--line);
border-radius: 12px;
box-shadow: 0 22px 55px rgba(24, 38, 31, 0.16);
padding: 12px;
z-index: 10;
}
.period-popover.open {
display: block;
}
.preset-row {
display: flex;
gap: 6px;
flex-wrap: wrap;
margin-bottom: 12px;
}
.preset {
border: 1px solid var(--line);
background: var(--surface-subtle);
color: var(--muted);
border-radius: 999px;
padding: 6px 10px;
font-size: 12px;
font-weight: 750;
}
.preset.active {
color: var(--primary);
background: var(--primary-soft);
border-color: #b6d7c3;
}
.calendar-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 4px;
color: var(--muted);
font-size: 12px;
text-align: center;
}
.calendar-grid span {
padding: 5px 0;
border-radius: 6px;
}
.calendar-grid .day {
color: var(--text);
background: var(--surface-subtle);
}
.calendar-grid .in-range {
background: var(--primary-soft);
color: var(--primary);
}
.calendar-grid .selected {
background: var(--primary);
color: #fff;
}
.popover-actions {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 12px;
}
.link-button {
border: 0;
background: transparent;
color: var(--muted);
font-size: 12px;
font-weight: 700;
cursor: pointer;
}
.apply-button {
border: 0;
background: var(--primary);
color: #fff;
padding: 0 12px;
white-space: nowrap;
}
.apply-button:hover,
.screen-toggle button.active:hover {
background: var(--primary-dark);
}
.table-wrap {
overflow-x: auto;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}
th {
text-align: left;
padding: 8px 10px;
background: var(--surface-subtle);
border-bottom: 1px solid var(--line);
white-space: nowrap;
}
td {
padding: 8px 10px;
border-bottom: 1px solid var(--line);
white-space: nowrap;
}
tbody tr:hover td {
background: #fbfcfb;
}
.ticker {
font-weight: 780;
letter-spacing: 0;
}
.ticker-wrap {
display: grid;
gap: 3px;
}
.instrument-name {
color: var(--muted);
font-size: 11px;
line-height: 1.25;
}
.amount,
.status,
.num {
text-align: right;
}
.amount {
font-weight: 780;
}
.positive {
color: var(--positive);
}
.negative {
color: var(--negative);
}
.planned {
color: var(--soft);
}
.type-badge {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 24px;
padding: 0 10px;
border-radius: 999px;
border: 1px solid var(--line-strong);
background: #fff;
color: var(--muted);
font-size: 12px;
font-weight: 760;
}
.type-badge.coupon {
background: var(--blue-soft);
border-color: #cddcff;
color: var(--blue);
}
.type-badge.dividend {
background: var(--primary-soft);
border-color: #bcdcc9;
color: var(--primary);
}
.type-badge.maturity {
background: var(--amber-soft);
border-color: #f0d898;
color: #8d6400;
}
.type-badge.tax {
background: #fef0ef;
border-color: #f6c6c2;
color: var(--negative);
}
.status-pill {
display: inline-flex;
justify-content: center;
min-width: 82px;
border-radius: 999px;
background: var(--primary-soft);
color: var(--primary);
padding: 4px 8px;
font-size: 12px;
font-weight: 760;
}
.status-pill.negative {
background: #fef0ef;
color: var(--negative);
}
.status-pill.planned {
background: #eef2ef;
color: var(--muted);
}
.muted {
color: var(--muted);
}
.table-footer {
min-height: 34px;
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
margin-top: 10px;
color: var(--muted);
font-size: 12px;
}
.table-footer.compact {
justify-content: flex-end;
}
.pager {
display: flex;
align-items: center;
gap: 8px;
}
.pager-button {
min-width: 34px;
border: 1px solid var(--line-strong);
background: #fff;
color: var(--primary);
}
.pager-button:disabled {
color: #b8c0bb;
border-color: var(--line);
cursor: default;
}
.analytics-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
.analytics-summary {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
margin-bottom: 12px;
}
.analytics-item {
border: 1px solid var(--line);
background: var(--surface-subtle);
border-radius: var(--radius);
padding: 12px;
min-height: 72px;
}
.analytics-item.positive {
background: linear-gradient(180deg, #f3faf5, #edf7f0);
border-color: #cae6d3;
}
.analytics-item.negative {
background: linear-gradient(180deg, #fff7f5, #fff1ef);
border-color: #f3d2cb;
}
.analytics-value {
margin-top: 4px;
font-size: 15px;
font-weight: 760;
}
.analytics-skeleton-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
.analytics-skeleton-card {
border: 1px solid var(--line);
background: var(--surface-subtle);
border-radius: var(--radius);
padding: 12px;
min-height: 72px;
display: grid;
gap: 10px;
}
.analytics-summary .analytics-skeleton-card {
min-height: 78px;
}
.allocation-skeleton {
display: grid;
gap: 14px;
}
.allocation-skeleton-row {
display: grid;
gap: 8px;
}
.chart-loading {
min-height: 208px;
display: grid;
gap: 14px;
}
.chart-loading-head {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 16px;
}
.chart-loading-meta {
display: grid;
gap: 8px;
}
.chart-loading-visual {
position: relative;
height: 144px;
margin: 0 -20px;
width: calc(100% + 40px);
border-radius: 12px;
background: rgba(23, 103, 71, 0.05);
overflow: hidden;
}
.chart-loading-visual::before {
content: "";
position: absolute;
left: 0;
right: 0;
bottom: 26px;
border-top: 1px dashed rgba(23, 103, 71, 0.16);
}
.chart-loading-visual::after {
content: "";
position: absolute;
inset: 18px 0 26px;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
animation: shimmer 1.8s ease-in-out infinite;
}
.chart-loading svg {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
display: block;
}
.chart-loading .trend-area-fill {
fill: rgba(23, 103, 71, 0.08);
}
.chart-loading .trend-line {
stroke: rgba(23, 103, 71, 0.55);
stroke-width: 2.5;
stroke-dasharray: 10 10;
animation: dashflow 10s linear infinite;
}
.allocation-head {
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 12px;
margin-bottom: 12px;
}
.allocation-total {
font-weight: 780;
}
.allocation-list {
display: grid;
gap: 12px;
}
.alloc-row {
display: grid;
gap: 6px;
}
.alloc-meta {
display: flex;
justify-content: space-between;
gap: 12px;
font-size: 13px;
}
.bar-track {
height: 9px;
background: #edf1ee;
border-radius: 999px;
overflow: hidden;
}
.bar {
height: 100%;
border-radius: 999px;
}
.bar.shares {
width: 28.6%;
background: #4f6bed;
}
.bar.bonds {
width: 70.6%;
background: #e7a328;
}
.bar.cash {
width: 0.8%;
background: #8f6ad8;
}
.loading-only {
display: none;
}
body.loading .data-only {
display: none;
}
body.loading .loading-only {
display: block;
}
body.loading .page-title-main.loading-only {
display: none;
}
.skeleton-table {
display: grid;
gap: 0;
border: 1px solid var(--line);
border-radius: var(--radius);
overflow: hidden;
}
.skeleton-row {
display: grid;
grid-template-columns: 120px 1.4fr 1fr 110px;
gap: 16px;
align-items: center;
min-height: 38px;
padding: 8px 10px;
border-bottom: 1px solid var(--line);
}
.skeleton-row:last-child {
border-bottom: 0;
}
.income-skeleton .skeleton-row {
grid-template-columns: 120px 1.4fr 1fr 120px;
}
.skel {
height: 13px;
border-radius: 999px;
background: linear-gradient(90deg, #edf1ee 0%, #f8faf8 48%, #edf1ee 100%);
background-size: 220% 100%;
animation: shimmer 1.35s ease-in-out infinite;
}
.skel.short {
width: 64px;
}
.skel.medium {
width: 92px;
}
.skel.long {
width: 74%;
}
.skel.full {
width: 100%;
}
@keyframes shimmer {
0% {
background-position: 120% 0;
}
100% {
background-position: -120% 0;
}
}
@keyframes dashflow {
from {
stroke-dashoffset: 120;
}
to {
stroke-dashoffset: 0;
}
}
@media (max-width: 860px) {
.topbar {
grid-template-columns: 1fr;
height: auto;
align-items: stretch;
padding: 12px 16px;
gap: 10px;
}
.main-nav,
.user-row {
justify-content: flex-start;
overflow-x: auto;
}
.page-title-row {
align-items: flex-start;
flex-direction: column;
}
.page-title-main {
align-items: flex-start;
flex-direction: column;
gap: 10px;
}
.hero,
.analytics-grid,
.analytics-summary,
.analytics-skeleton-grid {
grid-template-columns: 1fr;
}
.table-toolbar {
grid-template-columns: 1fr;
}
.control-group {
align-items: flex-start;
flex-direction: column;
}
.period-popover {
left: 0;
right: auto;
width: min(330px, calc(100vw - 64px));
}
.skeleton-row {
grid-template-columns: 80px 1fr 90px;
}
.skeleton-row span:nth-child(4),
.skeleton-row span:nth-child(5) {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.skel {
animation: none;
}
}
</style>
</head>
<body>
<div class="app-shell">
<header class="topbar">
<div class="brand-row">
<div class="brand">MoexVibe</div>
<input class="search" value="Поиск" aria-label="Поиск" readonly />
</div>
<nav class="main-nav" aria-label="Основная навигация">
<a href="#">Портфели</a>
<a href="#" class="active">Брокер</a>
<a href="#">Скринер</a>
</nav>
<div class="user-row">
<span>Sergey</span>
<button class="ghost-button" type="button">Выйти</button>
</div>
</header>
<main class="page">
<div class="page-title-row">
<div class="data-only page-title-main">
<h1>Брокерский счёт</h1>
<div class="page-yield" aria-label="Доходность счёта">
<div class="metric-label">Доходность</div>
<div class="page-yield-value negative">-6,84%</div>
<div class="metric-note positive">За день: +1 688,04 ₽</div>
</div>
</div>
<div class="loading-only page-title-main page-title-skeleton" aria-hidden="true">
<div class="page-title-skeleton-main">
<span class="skel full"></span>
<span class="skel medium"></span>
</div>
<div class="page-title-skeleton-side">
<span class="skel short"></span>
<span class="skel short"></span>
</div>
</div>
<div class="screen-toggle" aria-label="Состояние данных">
<button type="button" class="active" data-mode="data">Данные</button>
<button type="button" data-mode="loading">Загрузка</button>
</div>
</div>
<nav class="account-tabs" aria-label="Разделы брокерского счёта">
<a class="active" href="#">Обзор</a>
<a href="#">Акции</a>
<a href="#">Облигации</a>
<a href="#">Операции</a>
<a href="#">События</a>
<a href="#">Аналитика</a>
</nav>
<section class="card portfolio-history-card" aria-labelledby="income-title">
<div class="card-head">
<div class="card-title">
<h2 id="income-title">Стоимость портфеля за 6 месяцев</h2>
</div>
</div>
<div class="data-only">
<div class="portfolio-trend" aria-label="График стоимости портфеля за последние шесть месяцев">
<div class="portfolio-trend-head">
<div class="portfolio-trend-meta">
<div class="metric-label">Текущая стоимость</div>
<div class="metric-value">1 884 891,72 ₽</div>
</div>
</div>
<svg viewBox="0 0 1000 120" role="img" aria-label="Рост стоимости портфеля за шесть месяцев">
<title>Стоимость портфеля с января по июнь 2026</title>
<desc>График показывает изменение стоимости портфеля за последние шесть месяцев, от января до июня 2026.</desc>
<path class="trend-guide" d="M0 96H1000"></path>
<rect class="trend-area" x="0" y="24" width="1000" height="96"></rect>
<path class="trend-area-fill" d="M0 98 C70 98, 130 95, 200 93 S340 82, 400 79 S540 73, 600 72 S740 51, 800 44 S930 29, 1000 24 L1000 120 L0 120 Z"></path>
<path class="trend-line" d="M0 98 C70 98, 130 95, 200 93 S340 82, 400 79 S540 73, 600 72 S740 51, 800 44 S930 29, 1000 24"></path>
</svg>
<div class="trend-axis" aria-hidden="true">
<span>Янв</span>
<span>Фев</span>
<span>Мар</span>
<span>Апр</span>
<span>Май</span>
<span>Июн</span>
</div>
</div>
</div>
<div class="loading-only">
<div class="chart-loading" aria-hidden="true">
<div class="chart-loading-head">
<div class="chart-loading-meta">
<span class="skel long"></span>
<span class="skel medium"></span>
</div>
</div>
<div class="chart-loading-visual">
<svg viewBox="0 0 1000 144" preserveAspectRatio="none">
<path class="trend-area-fill" d="M0 120 C90 120, 160 116, 230 112 S390 100, 460 94 S620 90, 690 82 S850 56, 920 46 S970 38, 1000 34 L1000 144 L0 144 Z"></path>
<path class="trend-line" d="M0 120 C90 120, 160 116, 230 112 S390 100, 460 94 S620 90, 690 82 S850 56, 920 46 S970 38, 1000 34"></path>
</svg>
</div>
</div>
</div>
</section>
<section class="card" aria-labelledby="analytics-title">
<div class="card-head">
<div class="card-title">
<h2 id="analytics-title">Аналитика доходности</h2>
</div>
</div>
<div class="data-only analytics-panel">
<div class="analytics-summary">
<div class="metric">
<div>
<div class="metric-label">Стоимость портфеля</div>
<div class="metric-value">1 884 891,72 ₽</div>
</div>
</div>
<div class="metric">
<div>
<div class="metric-label">Всего доходов</div>
<div class="metric-value positive">186 087,53 ₽</div>
</div>
</div>
</div>
<div class="analytics-grid">
<div class="analytics-item positive"><div class="section-kicker">Пополнения</div><div class="analytics-value positive">113 773,03 ₽</div></div>
<div class="analytics-item negative"><div class="section-kicker">Выводы</div><div class="analytics-value negative">-684 753,92 ₽</div></div>
<div class="analytics-item positive"><div class="section-kicker">Дивиденды</div><div class="analytics-value positive">27 137,88 ₽</div></div>
<div class="analytics-item positive"><div class="section-kicker">Купоны</div><div class="analytics-value positive">158 949,65 ₽</div></div>
<div class="analytics-item negative"><div class="section-kicker">Комиссия</div><div class="analytics-value negative">-3 418,72 ₽</div></div>
<div class="analytics-item negative"><div class="section-kicker">Уплаченные налоги</div><div class="analytics-value negative">-24 906,14 ₽</div></div>
</div>
</div>
<div class="loading-only analytics-panel">
<div class="analytics-summary">
<div class="analytics-skeleton-card"><span class="skel medium"></span><span class="skel short"></span></div>
<div class="analytics-skeleton-card"><span class="skel medium"></span><span class="skel short"></span></div>
</div>
<div class="analytics-skeleton-grid">
<div class="analytics-skeleton-card"><span class="skel medium"></span><span class="skel short"></span></div>
<div class="analytics-skeleton-card"><span class="skel medium"></span><span class="skel short"></span></div>
<div class="analytics-skeleton-card"><span class="skel medium"></span><span class="skel short"></span></div>
<div class="analytics-skeleton-card"><span class="skel medium"></span><span class="skel short"></span></div>
<div class="analytics-skeleton-card"><span class="skel medium"></span><span class="skel short"></span></div>
<div class="analytics-skeleton-card"><span class="skel medium"></span><span class="skel short"></span></div>
</div>
</div>
</section>
<section class="card" aria-labelledby="allocation-title">
<div class="card-head">
<div class="card-title">
<h2 id="allocation-title">Структура</h2>
</div>
</div>
<div class="data-only">
<div class="allocation-head">
<span class="allocation-total">1 884 891,72 ₽</span>
</div>
<div class="allocation-list">
<div class="alloc-row">
<div class="alloc-meta"><strong>Акции</strong><span class="muted">539 344,64 ₽ · 28,6%</span></div>
<div class="bar-track"><div class="bar shares"></div></div>
</div>
<div class="alloc-row">
<div class="alloc-meta"><strong>Облигации</strong><span class="muted">1 330 791,92 ₽ · 70,6%</span></div>
<div class="bar-track"><div class="bar bonds"></div></div>
</div>
<div class="alloc-row">
<div class="alloc-meta"><strong>Деньги</strong><span class="muted">14 755,16 ₽ · 0,8%</span></div>
<div class="bar-track"><div class="bar cash"></div></div>
</div>
</div>
</div>
<div class="loading-only">
<div class="allocation-skeleton">
<span class="skel short"></span>
<div class="allocation-skeleton-row"><span class="skel medium"></span><span class="skel full"></span></div>
<div class="allocation-skeleton-row"><span class="skel medium"></span><span class="skel full"></span></div>
<div class="allocation-skeleton-row"><span class="skel medium"></span><span class="skel full"></span></div>
</div>
</div>
</section>
<section class="card" aria-labelledby="events-title">
<div class="card-head">
<div class="card-title">
<h2 id="events-title">Последние события</h2>
</div>
<a class="card-link" href="#">Все события</a>
</div>
<div class="data-only">
<div class="table-wrap">
<table>
<thead>
<tr>
<th>Дата</th>
<th>Инструмент</th>
<th>Тип</th>
<th class="num">Сумма</th>
</tr>
</thead>
<tbody>
<tr><td>15.05.2026</td><td><div class="ticker-wrap"><div class="ticker">HeadHunter Group</div><div class="instrument-name">HEAD</div></div></td><td><span class="type-badge dividend">Дивиденд</span></td><td class="amount positive">+1 631,00 ₽</td></tr>
<tr><td>15.05.2026</td><td><div class="ticker-wrap"><div class="ticker">ОФЗ 26241</div><div class="instrument-name">RU000A10A4C1</div></div></td><td><span class="type-badge maturity">Погашение</span></td><td class="amount positive">+150,00 ₽</td></tr>
<tr><td>14.05.2026</td><td><div class="ticker-wrap"><div class="ticker">Самолет БО-П14</div><div class="instrument-name">RU000A10B461</div></div></td><td><span class="type-badge tax">Налог</span></td><td class="amount negative">-87,00 ₽</td></tr>
<tr><td>14.05.2026</td><td><div class="ticker-wrap"><div class="ticker">Система 001Р-31</div><div class="instrument-name">RU000A10A3Z4</div></div></td><td><span class="type-badge coupon">Купон</span></td><td class="amount positive">+1 212,45 ₽</td></tr>
<tr><td>13.05.2026</td><td><div class="ticker-wrap"><div class="ticker">ЕвроТранс 001Р-06</div><div class="instrument-name">RU000A10B883</div></div></td><td><span class="type-badge coupon">Купон</span></td><td class="amount positive">+13,97 ₽</td></tr>
<tr><td>13.05.2026</td><td><div class="ticker-wrap"><div class="ticker">Газпром капитал 2Р-09</div><div class="instrument-name">RU000A10B024</div></div></td><td><span class="type-badge coupon">Купон</span></td><td class="amount positive">+326,92 ₽</td></tr>
<tr><td>13.05.2026</td><td><div class="ticker-wrap"><div class="ticker">РЖД 001Р-37R</div><div class="instrument-name">RU000A10AEF9</div></div></td><td><span class="type-badge coupon">Купон</span></td><td class="amount positive">+43,56 ₽</td></tr>
</tbody>
</table>
</div>
<div class="table-footer compact">
<div class="pager">
<button class="pager-button" type="button" disabled>&larr;</button>
<span>1</span>
<button class="pager-button" type="button">&rarr;</button>
</div>
</div>
</div>
<div class="loading-only">
<div class="skeleton-table">
<div class="skeleton-row"><span class="skel short"></span><span class="skel long"></span><span class="skel medium"></span><span class="skel short"></span></div>
<div class="skeleton-row"><span class="skel short"></span><span class="skel full"></span><span class="skel medium"></span><span class="skel short"></span></div>
<div class="skeleton-row"><span class="skel short"></span><span class="skel long"></span><span class="skel medium"></span><span class="skel short"></span></div>
<div class="skeleton-row"><span class="skel short"></span><span class="skel full"></span><span class="skel medium"></span><span class="skel short"></span></div>
<div class="skeleton-row"><span class="skel short"></span><span class="skel long"></span><span class="skel medium"></span><span class="skel short"></span></div>
</div>
</div>
</section>
</main>
</div>
<script>
const modeButtons = document.querySelectorAll('[data-mode]');
modeButtons.forEach((button) => {
button.addEventListener('click', () => {
modeButtons.forEach((item) => item.classList.remove('active'));
button.classList.add('active');
document.body.classList.toggle('loading', button.dataset.mode === 'loading');
});
});
document.querySelectorAll('[data-popover]').forEach((button) => {
button.addEventListener('click', (event) => {
event.stopPropagation();
const id = button.getAttribute('data-popover');
const popover = document.getElementById(id);
document.querySelectorAll('.period-popover').forEach((item) => {
if (item !== popover) item.classList.remove('open');
});
popover.classList.toggle('open');
});
});
document.addEventListener('click', () => {
document.querySelectorAll('.period-popover').forEach((item) => item.classList.remove('open'));
});
document.querySelectorAll('.period-popover').forEach((popover) => {
popover.addEventListener('click', (event) => event.stopPropagation());
});
</script>
</body>
</html>