/* 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; }