Files
SHiNE-server/shine-UI/styles/features/network.css
T
qandClaude Opus 5.5 f8900e531a UI: новый общий стиль, тёмная/светлая тема, настраиваемая палитра
- styles/main.css: роли цветов (по умолчанию «Индиго»), шкала отступов/скруглений/шрифтов,
  цвета отношений для обеих тем; жёсткие цвета в стилях заменены на роли.
- Палитра: пресеты и личные правки, «Оформление» Авто/День/Ночь, долгое нажатие —
  редактор цветов с экспортом/импортом.
- Каналы: пузыри постов автора, плашки дней, строка «Написать в канал…», «О канале»,
  создание канала с адресом из названия; лента открывается на свежих постах.
- Чаты: плоский список, чипы-фильтры, пузыри, плашки дней; нижняя панель скрыта в переписке.
- Корневые разделы — единая шапка; профиль и чужой профиль — общая карточка;
  настройки, кошелёк, сеансы — меню-списки.
- Нижняя панель: иконки без подписей, бейджи на иконках.
- confirmDialog вместо window.confirm/alert; на телефоне диалоги — шторки снизу.
- docs/UI-Design/ISSUES-for-dev.md — найденные ошибки сервера/UI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:05:26 +03:00

403 lines
9.3 KiB
CSS
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.
/* Connections/network feature styles layered before network-graph.css. */
.node-dot img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
border-radius: 50%;
display: block;
opacity: 0;
transition: opacity 120ms ease;
}
.network-board {
position: relative;
height: 290px;
border: 1px solid var(--border-subtle);
border-radius: var(--radius-lg);
background: radial-gradient(circle at center, color-mix(in srgb, var(--rel-shining) 8%, transparent), color-mix(in srgb, var(--text-primary) 1%, transparent));
overflow: hidden;
}
.network-screen {
position: relative;
margin: -14px -14px -24px;
min-height: calc(100dvh - 74px);
}
.app-shell--scroll-locked .screen-content .network-screen {
margin: 0 0 -24px;
}
.network-stage {
position: relative;
height: calc(100dvh - 74px);
overflow: hidden;
}
.network-board--full {
position: absolute;
inset: 0;
min-height: 0;
height: 100%;
border-radius: 0;
}
.network-legend {
display: flex;
flex-wrap: wrap;
gap: 10px;
font-size: 12px;
color: var(--text-primary);
}
.network-legend span {
display: inline-flex;
align-items: center;
gap: 6px;
}
.legend-line,
.legend-arrow {
width: 18px;
height: 2px;
display: inline-block;
border-radius: 2px;
background: color-mix(in srgb, var(--rel-shining) 95%, transparent);
position: relative;
}
.legend-line.relative {
background: color-mix(in srgb, var(--rel-family) 95%, transparent);
}
.legend-arrow::after {
content: "";
position: absolute;
right: -1px;
top: -3px;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
border-left: 6px solid color-mix(in srgb, var(--rel-shining) 95%, transparent);
}
.network-svg {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
.network-link {
stroke-width: 2;
}
.network-link.is-friend {
stroke: var(--rel-shining);
}
.network-link.is-relative {
stroke: var(--rel-family);
}
.node-dot {
position: relative;
width: 52px;
height: 52px;
margin: 0 auto 4px;
border-radius: 50%;
display: grid;
place-items: center;
font-weight: 700;
background: var(--surface);
border: 1px solid var(--border-subtle);
box-shadow: 0 8px 16px rgba(4, 8, 15, 0.35);
}
.node-badge-official {
position: absolute;
left: 50%;
top: -8px;
transform: translateX(-50%);
min-width: 26px;
height: 18px;
padding: 0 6px;
border-radius: 999px;
border: 1px solid transparent;
background: linear-gradient(180deg, var(--rel-family), var(--rel-family));
color: var(--rel-family);
font-size: 11px;
line-height: 16px;
font-weight: 800;
letter-spacing: 0.3px;
text-transform: uppercase;
box-shadow: 0 6px 14px rgba(0, 0, 0, 0.3);
z-index: 2;
}
.node.is-shine .node-dot::before {
content: "";
position: absolute;
inset: -14px;
border-radius: 50%;
background: radial-gradient(circle, color-mix(in srgb, var(--rel-shining) 62%, transparent) 0%, color-mix(in srgb, var(--rel-shining) 28%, transparent) 42%, color-mix(in srgb, var(--rel-shining) 0%, transparent) 76%);
filter: blur(2px);
z-index: -1;
}
.node.is-shine .node-dot {
box-shadow: 0 0 0 2px color-mix(in srgb, var(--rel-shining) 50%, transparent), 0 0 28px color-mix(in srgb, var(--rel-shining) 58%, transparent), 0 8px 16px rgba(4, 8, 15, 0.35);
}
.node.is-friend .node-dot {
background: linear-gradient(165deg, var(--rel-contact), var(--surface));
}
.node.is-relative .node-dot {
background: linear-gradient(165deg, var(--rel-family), var(--surface));
border-color: color-mix(in srgb, var(--rel-family) 55%, transparent);
}
.node.center .node-dot {
width: 60px;
height: 60px;
background: linear-gradient(130deg, var(--rel-shining), var(--rel-shining));
color: var(--on-accent);
}
.node-label {
display: grid;
gap: 1px;
margin-top: 1px;
font-size: 11px;
color: var(--text-primary);
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.28);
line-height: 1.12;
}
.node-label.is-login-only .node-name {
display: none;
}
.node-name {
display: grid;
gap: 1px;
color: var(--text-primary);
}
.node-name-line {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.node-login {
display: block;
color: var(--text-primary);
font-size: 11px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.node-relation {
display: block;
color: var(--text-primary);
font-size: 11px;
font-weight: 600;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.network-search-candidate {
width: 100%;
justify-content: flex-start;
}
.network-search-candidate.is-selected {
border-color: color-mix(in srgb, var(--rel-shining) 78%, transparent);
background: color-mix(in srgb, var(--rel-shining) 24%, transparent);
}
.node:focus-visible .node-dot,
.node:hover .node-dot {
border-color: color-mix(in srgb, var(--rel-shining) 92%, transparent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--rel-shining) 20%, transparent), 0 8px 16px rgba(4, 8, 15, 0.35);
}
.node-menu {
position: absolute;
z-index: 3;
min-width: 240px;
padding: 8px;
}
.node-menu-actions {
display: grid;
gap: 8px;
}
/* Граф занимает ровно доступную область между общей шапкой и нижним toolbar. */
.app-shell--scroll-locked .screen-content .network-screen {
width: 100%;
height: 100%;
min-height: 0;
margin: 0;
}
.app-shell--scroll-locked .screen-content .network-stage {
width: 100%;
height: 100%;
min-height: 0;
}
/* В «Связях» screen-content намеренно без padding, поэтому тот же отступ задаём явно. */
.network-stage > .fg-filter-bar.app-top-tabs {
position: absolute;
top: var(--app-primary-tabs-top-gap);
left: 14px;
right: 14px;
z-index: 11;
min-height: var(--app-primary-tab-min-height);
padding: 0;
}
/* Одинаковая фактическая высота и типографика самих верхних чипов. */
/* «Связи»: фильтры остаются ниже интерактивной части общего TopBar. */
.app-shell--scroll-locked .network-stage > .fg-filter-bar.app-top-tabs {
top: calc(var(--topbar-height, 64px) + var(--app-primary-tabs-top-gap, 14px));
}
/* ===== «Связи»: боковой fade, ослабленный в зоне центрального света =====
* Радиальная виньетка давала слишком общий эффект. Здесь края затухают независимо:
* по X — узкой мягкой полосой от левого/правого края, а по Y сила этой полосы
* уменьшается возле источника света графа (50% / 47%) и растёт к углам.
* Поэтому центральное свечение визуально доходит почти до боковой кромки, тогда как
* верхние/нижние участки графа растворяются по краям раньше. Blur не используется. */
.app-shell--scroll-locked .network-stage::after {
content: "";
position: absolute;
inset: 0;
z-index: 10;
pointer-events: none;
background:
linear-gradient(
to right,
var(--background) 0%,
var(--background) 4%,
var(--background) 8%,
color-mix(in srgb, var(--background) 18%, transparent) 12%,
color-mix(in srgb, var(--background) 6%, transparent) 15%,
color-mix(in srgb, var(--background) 0%, transparent) 18%
) left center / 50% 100% no-repeat,
linear-gradient(
to left,
var(--background) 0%,
var(--background) 4%,
var(--background) 8%,
color-mix(in srgb, var(--background) 18%, transparent) 12%,
color-mix(in srgb, var(--background) 6%, transparent) 15%,
color-mix(in srgb, var(--background) 0%, transparent) 18%
) right center / 50% 100% no-repeat;
-webkit-mask-image: linear-gradient(
to bottom,
var(--background) 0%,
var(--background) 18%,
var(--background) 34%,
color-mix(in srgb, var(--background) 18%, transparent) 47%,
color-mix(in srgb, var(--background) 28%, transparent) 58%,
var(--background) 72%,
var(--background) 88%,
var(--background) 100%
);
mask-image: linear-gradient(
to bottom,
var(--background) 0%,
var(--background) 18%,
var(--background) 34%,
color-mix(in srgb, var(--background) 18%, transparent) 47%,
color-mix(in srgb, var(--background) 28%, transparent) 58%,
var(--background) 72%,
var(--background) 88%,
var(--background) 100%
);
}
.network-screen { background: radial-gradient(ellipse at 50% 45%, color-mix(in srgb, var(--rel-shining) 7%, transparent), transparent 70%); }
.network-board--full { border: 0; background: transparent; }
.network-screen .fg-stage { background: transparent; }
.network-stage > .fg-filter-bar.app-top-tabs {
left: 0;
right: 0;
justify-content: flex-start;
flex-wrap: nowrap;
overflow-x: auto;
padding-inline: var(--page-gutter);
scrollbar-width: none;
pointer-events: auto;
-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
}
.network-stage > .fg-filter-bar.app-top-tabs::-webkit-scrollbar { display: none; }