Files
dc-observatio/services/pcp-tgu-ops-ui/src/features/constellation/dashboard.css
T
Дмитрий Соловьев 821de2b0c0 pcp-tgu-ops-ui: вкладка «Группировка» (состояние группировки) на реальных данных
Встраивание дизайн-хэндоффа constellation dashboard отдельной вкладкой рядом с
Планы/Карта/Комплексный план/Редактор/Заявки.

- модуль src/features/constellation/ (прототип на JSX + realData.ts/ConstellationTab.tsx)
- реальные данные вместо симуляции: платформы (OPERATIONAL), станции, заявки→ROI (WKT),
  трасса flight-line как эфемерида (сэмплер позиции через env.subSat), ЗРВ→сброс,
  съёмка по пролёту над ROI; оптика/локация — по имени КА из НСИ
- d3-geo + topojson-client; карта world-atlas локально (без CDN)
- изоляция стилей на .cdash (конфликт --line с theme.css), высота .app=100%
- локальное время в часах и оси таймлайна (конвенция проекта)
- allowJs:true в tsconfig.app.json под JSX-модуль
2026-06-05 23:37:47 +03:00

185 lines
13 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.
/* Fonts — remove this @import if your app already loads IBM Plex */
@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans:wght@400;500;600;700&display=swap");
/* Переменные и резеты дашборда оскоплены на .cdash, чтобы не течь в остальное
приложение (см. INTEGRATION.md §6). В частности, --line здесь свой и не должен
переопределять --line из styles/theme.css на уровне всего приложения. */
.cdash {
--bg0:#0a0c0b; --bg1:#0e1211; --panel:#111514; --ins:#0a0e0d;
--line:rgba(255,255,255,0.06); --line2:rgba(255,255,255,0.11);
--hi:#e7ece9; --mid:#95a19d; --dim:#5b6662; --faint:#3c4644;
--teal:#5fb3a3; --teal-bg:rgba(95,179,163,0.13); --teal-br:rgba(95,179,163,0.35);
--amber:#d99a4e; --blue:#5b9bd5; --red:#d9685f; --green:#5cae7e; --violet:#a78bdb;
color:var(--hi); font-family:'IBM Plex Sans',system-ui,sans-serif; font-size:13px;
-webkit-font-smoothing:antialiased;
}
.cdash *{box-sizing:border-box;}
.mono,.clock-time,.sr-norad,.map-cursor,.tl-tick,.fc-meta{font-family:'IBM Plex Mono',monospace;}
.cdash button{font-family:inherit; cursor:pointer; color:inherit;}
.cdash ::-webkit-scrollbar{width:8px;height:8px;}
.cdash ::-webkit-scrollbar-thumb{background:rgba(255,255,255,0.07);border-radius:4px;}
.cdash ::-webkit-scrollbar-track{background:transparent;}
/* Встроено вкладкой в shell с собственной шапкой: высота от родителя, не 100vh
(см. INTEGRATION.md §4). display:contents у обёртки вкладки делает .app прямым
элементом grid-строки shell (minmax(0,1fr)). */
.app{height:100%; display:flex; flex-direction:column; overflow:hidden;}
/* ---------- header ---------- */
.hdr{
height:54px; flex:none; display:flex; align-items:center;
border-bottom:1px solid var(--line); background:linear-gradient(var(--bg1),var(--bg0));
padding:0 16px; gap:18px; position:relative; z-index:5;
}
.hdr-brand{display:flex; align-items:center; gap:11px; min-width:248px;}
.brand-mark{width:20px;height:20px;border-radius:50%;border:1.5px solid var(--teal);
box-shadow:0 0 10px rgba(95,179,163,0.4) inset, 0 0 6px rgba(95,179,163,0.3);}
.brand-1{font-weight:600; font-size:13px; letter-spacing:.04em; white-space:nowrap;}
.brand-2{font-family:'IBM Plex Mono',monospace; font-size:9px; color:var(--dim); letter-spacing:.12em; margin-top:1px;}
.hdr-transport{flex:1; display:flex; align-items:center; justify-content:center; gap:7px;}
.t-btn{background:var(--bg1); border:1px solid var(--line2); color:var(--mid);
height:30px; min-width:34px; padding:0 11px; border-radius:6px; font-size:11.5px; letter-spacing:.04em;
transition:.12s;}
.t-btn:hover{border-color:var(--teal-br); color:var(--hi);}
.t-play{font-size:12px; color:var(--teal); border-color:var(--teal-br); background:var(--teal-bg); width:42px;}
.t-play.on{background:rgba(95,179,163,0.2);}
.t-now{font-size:10.5px; letter-spacing:.1em;}
.t-now.live{background:rgba(92,174,126,0.16); border-color:rgba(92,174,126,0.5); color:var(--green);}
.t-sep{width:1px; height:20px; background:var(--line2); margin:0 4px;}
.speed-seg{display:flex; border:1px solid var(--line2); border-radius:6px; overflow:hidden; background:var(--bg1);}
.speed-seg .sp{background:transparent; border:0; color:var(--dim); height:28px; padding:0 11px; font-size:11px;
font-family:'IBM Plex Mono',monospace; border-right:1px solid var(--line); transition:.12s;}
.speed-seg .sp:last-child{border-right:0;}
.speed-seg .sp:hover{color:var(--mid);}
.speed-seg .sp.on{background:var(--teal-bg); color:var(--teal);}
.hdr-clock{display:flex; flex-direction:column; align-items:flex-end; min-width:240px; gap:1px;}
.live-badge{display:flex; align-items:center; gap:5px; font-size:9.5px; letter-spacing:.16em; color:var(--amber);
font-family:'IBM Plex Mono',monospace;}
.live-badge .live-dot{width:6px;height:6px;border-radius:50%;background:var(--amber);}
.live-badge.on{color:var(--green);}
.live-badge.on .live-dot{background:var(--green); box-shadow:0 0 6px var(--green); animation:pulse 1.4s infinite;}
@keyframes pulse{0%,100%{opacity:1;}50%{opacity:.35;}}
.clock-main{display:flex; align-items:baseline; gap:6px;}
.clock-time{font-size:22px; font-weight:500; letter-spacing:.02em; line-height:1;}
.clock-utc{font-size:9px; color:var(--dim); letter-spacing:.1em;}
.clock-date{font-size:10px; color:var(--mid); font-family:'IBM Plex Mono',monospace; letter-spacing:.06em;}
/* ---------- body ---------- */
.body{flex:1; display:flex; min-height:0;}
.side{width:328px; flex:none; border-right:1px solid var(--line); background:var(--bg1);
display:flex; flex-direction:column; overflow:hidden;}
.main{flex:1; display:flex; flex-direction:column; min-width:0;}
.sec-label{font-family:'IBM Plex Mono',monospace; font-size:9.5px; letter-spacing:.16em; color:var(--dim);
padding:13px 16px 8px; display:flex; align-items:center; gap:8px;}
.sec-label.tight{padding-top:6px;}
.sec-label .count{background:var(--bg0); border:1px solid var(--line2); border-radius:8px; padding:0 6px;
font-size:9px; color:var(--mid);}
/* summary */
.summary{padding:0 14px 6px;}
.summary-tiles{display:grid; grid-template-columns:repeat(4,1fr); gap:6px;}
.s-tile{background:var(--ins); border:1px solid var(--line); border-radius:7px; padding:9px 4px 7px; text-align:center;}
.s-num{font-family:'IBM Plex Mono',monospace; font-size:21px; font-weight:600; line-height:1;}
.s-lbl{font-size:8px; color:var(--dim); letter-spacing:.1em; margin-top:5px;}
.summary-foot{display:flex; align-items:center; gap:13px; padding:9px 2px 2px; font-size:10px;
color:var(--mid); font-family:'IBM Plex Mono',monospace;}
.summary-foot .dot,.r-domain .dot{width:7px;height:7px;border-radius:2px;display:inline-block;margin-right:5px;vertical-align:middle;}
.summary-foot .muted{margin-left:auto; color:var(--dim);}
/* search */
.side-search{padding:4px 14px 2px;}
.side-search input{width:100%; background:var(--ins); border:1px solid var(--line); border-radius:6px;
color:var(--hi); padding:7px 10px; font-size:11.5px; outline:none; font-family:'IBM Plex Mono',monospace;}
.side-search input::placeholder{color:var(--faint);}
.side-search input:focus{border-color:var(--teal-br);}
/* roster */
.roster{flex:1; min-height:0; overflow-y:auto; padding:0 8px 8px;}
.r-domain{font-family:'IBM Plex Mono',monospace; font-size:10px; letter-spacing:.14em; color:var(--mid);
padding:11px 8px 5px; display:flex; align-items:center;}
.r-group{font-size:9.5px; color:var(--faint); letter-spacing:.08em; padding:3px 8px 3px 20px; text-transform:uppercase;}
.sat-row{display:flex; gap:9px; padding:7px 8px 7px 10px; border-radius:7px; cursor:pointer;
align-items:center; transition:.1s; border:1px solid transparent;}
.sat-row:hover{background:rgba(255,255,255,0.025);}
.sat-row.focus{background:var(--teal-bg); border-color:var(--teal-br);}
.sr-payload{width:3px; align-self:stretch; border-radius:2px; flex:none;}
.sr-main{flex:1; min-width:0;}
.sr-top{display:flex; justify-content:space-between; align-items:baseline; gap:8px;}
.sr-name{font-size:12.5px; font-weight:500; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
.sr-status{font-size:9px; letter-spacing:.08em; font-family:'IBM Plex Mono',monospace; flex:none; display:flex; align-items:center; gap:3px;}
.sr-status .ecl{opacity:.85;}
.sr-bot{display:flex; align-items:center; gap:8px; margin-top:4px;}
.sr-norad{font-size:9px; color:var(--dim); flex:none;}
.mem-bar{flex:1; height:4px; background:rgba(255,255,255,0.07); border-radius:2px; overflow:hidden;}
.mem-bar span{display:block; height:100%; border-radius:2px; transition:width .2s;}
.sr-mem{font-size:9.5px; font-family:'IBM Plex Mono',monospace; flex:none; width:30px; text-align:right;}
/* activity */
.activity{flex:none; max-height:34%; display:flex; flex-direction:column; border-top:1px solid var(--line); overflow:hidden;}
.act-list{overflow-y:auto; padding:0 8px 8px;}
.act-empty{color:var(--faint); font-size:11px; padding:6px 10px; font-family:'IBM Plex Mono',monospace;}
.act-row{display:flex; gap:8px; padding:6px 8px; border-radius:6px; cursor:pointer; align-items:center;}
.act-row:hover{background:rgba(255,255,255,0.025);}
.act-row.focus{background:var(--teal-bg);}
.act-bar{width:3px; align-self:stretch; border-radius:2px; flex:none;}
.act-body{flex:1; min-width:0;}
.act-top{display:flex; gap:7px; align-items:baseline;}
.act-type{font-size:9.5px; letter-spacing:.1em; font-family:'IBM Plex Mono',monospace;}
.act-tgt{font-size:11px; color:var(--hi); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
.act-sub{display:flex; justify-content:space-between; font-size:9.5px; color:var(--dim); margin-top:2px; font-family:'IBM Plex Mono',monospace;}
.act-rem{color:var(--mid);}
/* ---------- map ---------- */
.map-area{flex:1; position:relative; min-height:0; overflow:hidden; background:var(--ins);}
.map-wrap{position:absolute; inset:0;}
.map-wrap canvas{display:block;}
.map-caption{position:absolute; top:12px; left:12px; z-index:3;}
.cap-hint{font-family:'IBM Plex Mono',monospace; font-size:9.5px; letter-spacing:.12em; color:var(--faint);
background:rgba(10,14,13,0.6); border:1px solid var(--line); padding:6px 10px; border-radius:6px; white-space:nowrap;}
.focus-card{display:flex; align-items:stretch; gap:11px; background:rgba(11,16,15,0.92); backdrop-filter:blur(6px);
border:1px solid var(--teal-br); border-radius:8px; padding:10px 13px; min-width:330px;}
.fc-pay{width:3px; border-radius:2px; flex:none;}
.fc-info{flex:1;}
.fc-name{font-size:14px; font-weight:600; display:flex; justify-content:space-between; align-items:center;}
.fc-x{background:none; border:0; color:var(--dim); font-size:12px; padding:0 2px;}
.fc-x:hover{color:var(--hi);}
.fc-meta{font-size:9.5px; color:var(--mid); margin-top:4px; display:flex; gap:6px; align-items:center; letter-spacing:.04em;}
.fc-dot{color:var(--faint);}
.fc-pos{text-align:right; font-family:'IBM Plex Mono',monospace; font-size:10px; color:var(--mid); display:flex; flex-direction:column; justify-content:center; gap:4px;}
.fc-mem b{color:var(--hi);}
.map-legend{position:absolute; bottom:12px; left:12px; z-index:3; background:rgba(10,14,13,0.55);
border:1px solid var(--line); border-radius:7px; padding:8px 11px; display:flex; flex-direction:column; gap:5px;}
.ml-row{display:flex; align-items:center; gap:8px; font-family:'IBM Plex Mono',monospace; font-size:9px;
letter-spacing:.08em; color:var(--mid); white-space:nowrap;}
.ml-tri{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-bottom:7px solid #cdd6d3;}
.ml-sw{width:14px; height:3px; border-radius:2px; background:var(--teal);}
.ml-sw.amber{background:var(--amber);}
.ml-sw.blue{background:var(--blue);}
.ml-sw.blue.dash{background:repeating-linear-gradient(90deg,var(--blue) 0 4px,transparent 4px 7px);}
.ml-sw.night{background:rgba(90,120,170,0.5); height:9px; width:14px; border-radius:2px;}
.map-cursor{position:absolute; bottom:10px; right:14px; z-index:3; font-family:'IBM Plex Mono',monospace;
font-size:10px; color:var(--mid); background:rgba(10,14,13,0.6); padding:3px 8px; border-radius:5px; border:1px solid var(--line);}
.map-tip{position:absolute; z-index:4; pointer-events:none; font-family:'IBM Plex Mono',monospace; font-size:10px;
background:rgba(11,16,15,0.95); border:1px solid var(--line2); padding:3px 7px; border-radius:5px; color:var(--hi); white-space:nowrap;}
/* ---------- timeline ---------- */
.tl-area{height:248px; flex:none; border-top:1px solid var(--line); background:var(--bg1); display:flex; flex-direction:column;}
.tl-head{height:34px; flex:none; display:flex; align-items:center; gap:18px; padding:0 16px; border-bottom:1px solid var(--line);}
.tl-title{font-family:'IBM Plex Mono',monospace; font-size:10px; letter-spacing:.16em; color:var(--mid);}
.tl-legend{display:flex; gap:15px; flex:1;}
.leg-item{display:flex; align-items:center; gap:6px; font-family:'IBM Plex Mono',monospace; font-size:9px;
letter-spacing:.08em; color:var(--dim);}
.leg-sw{width:13px; height:8px; border-radius:2px; display:inline-block;}
.leg-sw.hatch{background:repeating-linear-gradient(45deg,rgba(217,104,95,0.7) 0 2px,rgba(217,104,95,0.12) 2px 5px); border:1px solid rgba(217,104,95,0.5);}
.tl-hint{font-family:'IBM Plex Mono',monospace; font-size:9.5px; color:var(--faint); letter-spacing:.06em;}
.tl-wrap{flex:1; overflow-y:auto; overflow-x:hidden; user-select:none; cursor:crosshair;}
.tl-tick{fill:var(--dim); font-size:9px; font-family:'IBM Plex Mono',monospace;}
.tl-group{fill:var(--faint); font-size:9px; letter-spacing:.14em; font-family:'IBM Plex Mono',monospace;}
.tl-name{fill:var(--mid); font-size:10.5px;}
.tl-nowlbl{fill:rgba(95,179,163,0.6); font-size:8px; letter-spacing:.12em; font-family:'IBM Plex Mono',monospace;}