— V2MapLegend overlay над cockpit-картой (электр/вода/канал/тепло/газ) с nearest_m + статус-точка, источник utilities.summary (subtype-buckets зеркалят backend _nearest() aliases; electric расширен power_line, gas включает legacy generic pipeline). — Per-theme заголовок карты: dark «СПУТНИК · СВЕЖИЙ СНИМОК», light «СПУТНИК · СХЕМА ПОДКЛЮЧЕНИЙ» (toggle через CSS [data-theme], без JS). — Точечный light-theme contrast в v2.module.css: kv/eng значения, drawer eyebrow, .more / .ver / активная вкладка с cyan→accent-blue, status-dot halo off на белом. Dark не тронут. Scope: только ptica-v2/* и v2.module.css. PticaMapInner (шарится со старым ptica) не тронут.
2057 lines
41 KiB
CSS
2057 lines
41 KiB
CSS
/*
|
|
* Site Finder v2 — «ПТИЦА» cockpit, ported 1:1 from the approved static
|
|
* prototype (ptica-v2/index.html). EVERY token and rule is scoped under
|
|
* `.v2Root[data-theme="dark"]` / `[data-theme="light"]` so the cockpit theme
|
|
* NEVER leaks into the rest of the (light) application — the wrapper carries the
|
|
* class AND the data-theme attribute.
|
|
*
|
|
* Fonts come from the globally-wired next/font CSS vars (--font-inter /
|
|
* --font-plex-mono — see app/layout.tsx); no new font deps.
|
|
*/
|
|
|
|
/* ===================== SCOPED TOKENS ===================== */
|
|
.v2Root {
|
|
--font-ui:
|
|
var(--font-inter), "Inter", "Manrope", -apple-system, "Segoe UI", system-ui,
|
|
sans-serif;
|
|
--font-mono:
|
|
var(--font-plex-mono), "IBM Plex Mono", "Roboto Mono", ui-monospace,
|
|
monospace;
|
|
|
|
--radius-xs: 4px;
|
|
--radius-sm: 8px;
|
|
--radius-md: 12px;
|
|
--radius-lg: 16px;
|
|
--line: 1px;
|
|
--line-strong: 1.5px;
|
|
|
|
--accent-blue: #2f6f9f;
|
|
--accent-cyan: #7fd0ee;
|
|
--accent-cyan-strong: #8ed3ff;
|
|
--accent-green: #38c172;
|
|
--accent-green-soft: #2faa63;
|
|
--accent-yellow: #e0a93b;
|
|
--accent-red: #d2655b;
|
|
--accent-purple: #9b80d6;
|
|
--accent-orange: #e46c35;
|
|
|
|
--res-electric: #e6b23c;
|
|
--res-water: #4d9bd7;
|
|
--res-sewer: #9b80d6;
|
|
--res-heat: #e46c35;
|
|
--res-gas: #d2655b;
|
|
--res-poi: #3fa77d;
|
|
|
|
--gauge-track: 9px;
|
|
}
|
|
|
|
.v2Root[data-theme="dark"] {
|
|
--bg: #060f16;
|
|
--bg-2: #08131c;
|
|
--grid-line: rgba(120, 165, 190, 0.06);
|
|
--surface: rgba(11, 26, 36, 0.72);
|
|
--surface-2: rgba(9, 22, 31, 0.62);
|
|
--surface-strong: rgba(12, 30, 42, 0.94);
|
|
--surface-muted: rgba(26, 52, 67, 0.55);
|
|
--surface-inset: rgba(4, 12, 18, 0.6);
|
|
--text: #dcebf2;
|
|
--text-strong: #f2fafe;
|
|
--text-muted: #8ba6b3;
|
|
--text-soft: #5f7886;
|
|
--border: rgba(150, 192, 214, 0.18);
|
|
--border-strong: rgba(150, 192, 214, 0.4);
|
|
--border-faint: rgba(150, 192, 214, 0.1);
|
|
--map-bg: #0a1820;
|
|
--glow: rgba(110, 200, 240, 0.28);
|
|
--glow-strong: rgba(110, 200, 240, 0.55);
|
|
--shadow: 0 18px 70px rgba(0, 0, 0, 0.5);
|
|
--verdict: var(--accent-green);
|
|
--gauge-good: var(--accent-green);
|
|
--chip-bg: rgba(20, 42, 56, 0.6);
|
|
--topbar-bg: rgba(7, 16, 23, 0.9);
|
|
}
|
|
|
|
.v2Root[data-theme="light"] {
|
|
--bg: #eaeef2;
|
|
--bg-2: #e4e9ee;
|
|
--grid-line: rgba(70, 110, 135, 0.07);
|
|
--surface: #ffffff;
|
|
--surface-2: rgba(255, 255, 255, 0.85);
|
|
--surface-strong: #ffffff;
|
|
--surface-muted: rgba(222, 231, 238, 0.7);
|
|
--surface-inset: rgba(232, 238, 243, 0.8);
|
|
--text: #102132;
|
|
--text-strong: #06141f;
|
|
--text-muted: #51616f;
|
|
--text-soft: #768493;
|
|
--border: rgba(40, 70, 95, 0.2);
|
|
--border-strong: rgba(40, 70, 95, 0.36);
|
|
--border-faint: rgba(40, 70, 95, 0.1);
|
|
--map-bg: #d9e4ea;
|
|
--glow: rgba(70, 140, 180, 0.2);
|
|
--glow-strong: rgba(70, 140, 180, 0.4);
|
|
--shadow:
|
|
0 1px 2px rgba(16, 24, 40, 0.06), 0 10px 28px rgba(40, 68, 92, 0.09);
|
|
--verdict: #1f9d57;
|
|
--gauge-good: #1f9d57;
|
|
--chip-bg: rgba(225, 234, 241, 0.85);
|
|
--topbar-bg: rgba(255, 255, 255, 0.92);
|
|
}
|
|
|
|
/* ===================== ROOT / BASE ===================== */
|
|
.v2Root {
|
|
position: relative;
|
|
width: 100%;
|
|
min-height: 100vh;
|
|
font-family: var(--font-ui);
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
-webkit-font-smoothing: antialiased;
|
|
font-size: 12px;
|
|
line-height: 1.3;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.v2Root :where(button) {
|
|
font: inherit;
|
|
cursor: pointer;
|
|
color: inherit;
|
|
border: none;
|
|
background: none;
|
|
}
|
|
.v2Root svg {
|
|
display: block;
|
|
}
|
|
.mono {
|
|
font-family: var(--font-mono);
|
|
}
|
|
.muted {
|
|
color: var(--text-muted);
|
|
}
|
|
.soft {
|
|
color: var(--text-soft);
|
|
}
|
|
.dash {
|
|
color: var(--text-soft);
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
.app {
|
|
width: 100%;
|
|
height: 100vh;
|
|
display: grid;
|
|
grid-template-rows: 56px 1fr 26px;
|
|
background:
|
|
linear-gradient(var(--grid-line) 1px, transparent 1px) 0 0 / 34px 34px,
|
|
linear-gradient(90deg, var(--grid-line) 1px, transparent 1px) 0 0 / 34px 34px,
|
|
radial-gradient(1200px 700px at 30% -10%, var(--bg-2), var(--bg));
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.lbl {
|
|
font-family: var(--font-mono);
|
|
font-size: 9px;
|
|
letter-spacing: 0.13em;
|
|
text-transform: uppercase;
|
|
color: var(--text-muted);
|
|
font-weight: 500;
|
|
}
|
|
.sectionTitle {
|
|
font-family: var(--font-mono);
|
|
font-size: 10px;
|
|
letter-spacing: 0.16em;
|
|
text-transform: uppercase;
|
|
color: var(--text-strong);
|
|
font-weight: 600;
|
|
}
|
|
.sectionSub {
|
|
font-family: var(--font-mono);
|
|
font-size: 9px;
|
|
letter-spacing: 0.13em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* ===================== TOPBAR ===================== */
|
|
.topbar {
|
|
grid-row: 1;
|
|
display: grid;
|
|
grid-template-columns: 300px 1fr 300px;
|
|
align-items: center;
|
|
border-bottom: 1px solid var(--border);
|
|
background: var(--topbar-bg);
|
|
padding: 0 18px;
|
|
backdrop-filter: blur(6px);
|
|
z-index: 10;
|
|
}
|
|
.brand {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 11px;
|
|
text-decoration: none;
|
|
color: inherit;
|
|
}
|
|
.brandLogo {
|
|
width: 30px;
|
|
height: 30px;
|
|
color: var(--accent-cyan);
|
|
flex: 0 0 auto;
|
|
}
|
|
.brandLogo svg {
|
|
width: 100%;
|
|
height: 100%;
|
|
filter: drop-shadow(0 0 6px var(--glow));
|
|
}
|
|
.brandName {
|
|
font-family: var(--font-mono);
|
|
font-weight: 600;
|
|
font-size: 18px;
|
|
letter-spacing: 0.34em;
|
|
color: var(--text-strong);
|
|
}
|
|
.brandSub {
|
|
font-size: 7.5px;
|
|
letter-spacing: 0.05em;
|
|
color: var(--text-soft);
|
|
text-transform: uppercase;
|
|
margin-top: 2px;
|
|
line-height: 1.25;
|
|
max-width: 200px;
|
|
}
|
|
.tabs {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
gap: 30px;
|
|
height: 100%;
|
|
}
|
|
.tab {
|
|
font-family: var(--font-mono);
|
|
font-size: 11px;
|
|
letter-spacing: 0.14em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
font-weight: 500;
|
|
position: relative;
|
|
height: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
.tabActive {
|
|
color: var(--text-strong);
|
|
}
|
|
.tabActive::after {
|
|
content: "";
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
height: 2px;
|
|
background: var(--accent-cyan);
|
|
box-shadow: 0 0 8px var(--glow-strong);
|
|
}
|
|
.topbarRight {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-end;
|
|
gap: 14px;
|
|
}
|
|
.clock {
|
|
text-align: right;
|
|
}
|
|
.clock .time {
|
|
font-family: var(--font-mono);
|
|
font-size: 15px;
|
|
font-weight: 500;
|
|
color: var(--text-strong);
|
|
letter-spacing: 0.04em;
|
|
}
|
|
.clock .date {
|
|
font-family: var(--font-mono);
|
|
font-size: 8.5px;
|
|
color: var(--text-soft);
|
|
letter-spacing: 0.06em;
|
|
margin-top: 1px;
|
|
}
|
|
.ver {
|
|
font-family: var(--font-mono);
|
|
font-size: 8.5px;
|
|
letter-spacing: 0.08em;
|
|
color: var(--accent-cyan);
|
|
padding: 3px 7px;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-xs);
|
|
background: var(--surface-2);
|
|
}
|
|
.tbIcons {
|
|
display: flex;
|
|
gap: 6px;
|
|
}
|
|
.tbIc {
|
|
width: 24px;
|
|
height: 24px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-xs);
|
|
color: var(--text-muted);
|
|
background: var(--surface-2);
|
|
}
|
|
.tbIc svg {
|
|
width: 13px;
|
|
height: 13px;
|
|
}
|
|
|
|
/* ===================== BODY GRID ===================== */
|
|
.body {
|
|
grid-row: 2;
|
|
display: grid;
|
|
grid-template-columns: 76px 1fr;
|
|
min-height: 0;
|
|
}
|
|
|
|
/* rail */
|
|
.rail {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
border-right: 1px solid var(--border);
|
|
background: var(--surface-2);
|
|
padding: 10px 0;
|
|
gap: 2px;
|
|
}
|
|
.railItem {
|
|
width: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 4px;
|
|
padding: 9px 0;
|
|
color: var(--text-soft);
|
|
position: relative;
|
|
}
|
|
.railItem svg {
|
|
width: 19px;
|
|
height: 19px;
|
|
}
|
|
.railItem .rlbl {
|
|
font-family: var(--font-mono);
|
|
font-size: 7px;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
}
|
|
.railItemActive {
|
|
color: var(--accent-cyan);
|
|
}
|
|
.railItemActive::before {
|
|
content: "";
|
|
position: absolute;
|
|
left: 0;
|
|
top: 6px;
|
|
bottom: 6px;
|
|
width: 2px;
|
|
background: var(--accent-cyan);
|
|
box-shadow: 0 0 8px var(--glow-strong);
|
|
}
|
|
.railSpacer {
|
|
flex: 1;
|
|
}
|
|
|
|
/* content area */
|
|
.content {
|
|
display: grid;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
gap: 8px;
|
|
padding: 8px;
|
|
grid-template-rows:
|
|
minmax(0, 2.18fr) minmax(0, 1.18fr) minmax(0, 1.3fr)
|
|
minmax(0, 1fr);
|
|
overflow-y: auto;
|
|
}
|
|
|
|
/* card primitive */
|
|
.card {
|
|
background: var(--surface);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-sm);
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
.cardH {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 8px 11px 7px;
|
|
border-bottom: 1px solid var(--border-faint);
|
|
flex: 0 0 auto;
|
|
}
|
|
.cardH .ttl {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 8px;
|
|
min-width: 0;
|
|
}
|
|
.cardB {
|
|
padding: 9px 11px;
|
|
flex: 1;
|
|
min-height: 0;
|
|
}
|
|
.more {
|
|
font-family: var(--font-mono);
|
|
font-size: 8.5px;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
color: var(--accent-cyan);
|
|
white-space: nowrap;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 3px;
|
|
}
|
|
.moreRow {
|
|
text-align: right;
|
|
margin-top: 6px;
|
|
}
|
|
.moreRowAuto {
|
|
text-align: right;
|
|
margin-top: auto;
|
|
}
|
|
|
|
/* bracket corners (light only). bc1 = bottom-left, bc2 = bottom-right; the two
|
|
top corners are the ::before / ::after of the card itself. */
|
|
.brk::before,
|
|
.brk::after,
|
|
.bc1,
|
|
.bc2 {
|
|
content: "";
|
|
position: absolute;
|
|
width: 15px;
|
|
height: 15px;
|
|
pointer-events: none;
|
|
z-index: 3;
|
|
}
|
|
.v2Root[data-theme="light"] .brk::before {
|
|
top: -1px;
|
|
left: -1px;
|
|
border-top: 2px solid var(--border-strong);
|
|
border-left: 2px solid var(--border-strong);
|
|
}
|
|
.v2Root[data-theme="light"] .brk::after {
|
|
top: -1px;
|
|
right: -1px;
|
|
border-top: 2px solid var(--border-strong);
|
|
border-right: 2px solid var(--border-strong);
|
|
}
|
|
.v2Root[data-theme="light"] .brk .bc1 {
|
|
bottom: -1px;
|
|
left: -1px;
|
|
border-bottom: 2px solid var(--border-strong);
|
|
border-left: 2px solid var(--border-strong);
|
|
}
|
|
.v2Root[data-theme="light"] .brk .bc2 {
|
|
bottom: -1px;
|
|
right: -1px;
|
|
border-bottom: 2px solid var(--border-strong);
|
|
border-right: 2px solid var(--border-strong);
|
|
}
|
|
|
|
/* rows */
|
|
.row1 {
|
|
display: grid;
|
|
grid-template-columns: 1.74fr 1.06fr 0.86fr;
|
|
gap: 8px;
|
|
min-height: 0;
|
|
}
|
|
.row2 {
|
|
display: grid;
|
|
grid-template-columns: repeat(6, 1fr);
|
|
gap: 8px;
|
|
min-height: 0;
|
|
}
|
|
.row3 {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr 1.25fr 1fr;
|
|
gap: 8px;
|
|
min-height: 0;
|
|
}
|
|
.row4 {
|
|
display: grid;
|
|
grid-template-columns: 1.55fr 1.05fr 1.1fr;
|
|
gap: 8px;
|
|
min-height: 0;
|
|
}
|
|
|
|
/* ===================== MAP ===================== */
|
|
.mapCard {
|
|
padding: 0;
|
|
}
|
|
/* The Leaflet map fills the card; PticaMapInner brings its own internal
|
|
overlay/controls (reused plumbing). */
|
|
.mapMount {
|
|
position: absolute;
|
|
inset: 0;
|
|
border-radius: var(--radius-sm);
|
|
overflow: hidden;
|
|
}
|
|
.mapLoading {
|
|
position: absolute;
|
|
inset: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: var(--map-bg);
|
|
color: var(--text-soft);
|
|
font-family: var(--font-mono);
|
|
font-size: 10px;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
}
|
|
.mapHead {
|
|
position: absolute;
|
|
top: 9px;
|
|
left: 11px;
|
|
z-index: 5;
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 8px;
|
|
pointer-events: none;
|
|
}
|
|
.mapHead .ttl {
|
|
font-family: var(--font-mono);
|
|
font-size: 10px;
|
|
letter-spacing: 0.14em;
|
|
text-transform: uppercase;
|
|
color: var(--text-strong);
|
|
font-weight: 600;
|
|
text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
|
|
}
|
|
|
|
/* ===================== PASSPORT ===================== */
|
|
.passport .cardB {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0;
|
|
padding: 0;
|
|
}
|
|
.ppId {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 9px 11px;
|
|
border-bottom: 1px solid var(--border-faint);
|
|
}
|
|
.ppId .v {
|
|
font-family: var(--font-mono);
|
|
font-size: 14px;
|
|
color: var(--text-strong);
|
|
letter-spacing: 0.02em;
|
|
}
|
|
.ppId .cp {
|
|
width: 14px;
|
|
height: 14px;
|
|
color: var(--text-soft);
|
|
margin-left: auto;
|
|
}
|
|
.ppGrid {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
}
|
|
.ppCell {
|
|
padding: 9px 11px;
|
|
border-bottom: 1px solid var(--border-faint);
|
|
}
|
|
.ppCell:nth-child(odd) {
|
|
border-right: 1px solid var(--border-faint);
|
|
}
|
|
.ppCell .k {
|
|
font-family: var(--font-mono);
|
|
font-size: 8px;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
margin-bottom: 4px;
|
|
}
|
|
.ppCell .vv {
|
|
font-size: 12px;
|
|
color: var(--text);
|
|
font-weight: 500;
|
|
line-height: 1.3;
|
|
}
|
|
.ppCell .vv.big {
|
|
font-family: var(--font-mono);
|
|
font-size: 13px;
|
|
}
|
|
.ppCellWide {
|
|
grid-column: span 2;
|
|
border-right: none;
|
|
}
|
|
.statusOn {
|
|
color: var(--accent-green);
|
|
font-family: var(--font-mono);
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
font-size: 12px;
|
|
}
|
|
|
|
/* ===================== RIGHT COLUMN row1 ===================== */
|
|
.colStack {
|
|
display: grid;
|
|
grid-template-rows: 1.35fr 1fr;
|
|
gap: 8px;
|
|
min-height: 0;
|
|
}
|
|
.gaugeCard .cardB {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 6px;
|
|
}
|
|
.gaugeWrap {
|
|
position: relative;
|
|
width: 118px;
|
|
height: 118px;
|
|
}
|
|
.gaugeWrap svg {
|
|
width: 100%;
|
|
height: 100%;
|
|
transform: rotate(-90deg);
|
|
}
|
|
.gaugeCenter {
|
|
position: absolute;
|
|
inset: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
.gaugeCenter .pct {
|
|
font-family: var(--font-mono);
|
|
font-size: 30px;
|
|
font-weight: 600;
|
|
line-height: 1;
|
|
}
|
|
.gaugeCenter .pct.mutedG {
|
|
color: var(--text-soft);
|
|
}
|
|
.gaugeCenter .cap {
|
|
font-family: var(--font-mono);
|
|
font-size: 9px;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
margin-top: 3px;
|
|
text-align: center;
|
|
}
|
|
.gaugeFoot {
|
|
font-family: var(--font-mono);
|
|
font-size: 8px;
|
|
color: var(--text-soft);
|
|
letter-spacing: 0.06em;
|
|
}
|
|
|
|
.invest .cardB {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
.invest .scoreRow {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
.invest .score {
|
|
font-family: var(--font-mono);
|
|
font-size: 26px;
|
|
font-weight: 600;
|
|
color: var(--text-strong);
|
|
}
|
|
.invest .score .u {
|
|
font-size: 13px;
|
|
color: var(--text-soft);
|
|
}
|
|
.invest .score.dashed {
|
|
color: var(--text-soft);
|
|
}
|
|
.invest .spark {
|
|
height: 26px;
|
|
color: var(--accent-cyan);
|
|
opacity: 0.8;
|
|
}
|
|
.invest .spark svg {
|
|
height: 100%;
|
|
width: auto;
|
|
}
|
|
.invest .prRow {
|
|
display: flex;
|
|
gap: 10px;
|
|
}
|
|
.invest .pr {
|
|
flex: 1;
|
|
}
|
|
.invest .pr .k {
|
|
font-family: var(--font-mono);
|
|
font-size: 8px;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
margin-bottom: 3px;
|
|
}
|
|
.invest .pr .vv {
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
color: var(--accent-green);
|
|
}
|
|
.invest .pr .vv.amb {
|
|
color: var(--accent-yellow);
|
|
}
|
|
.invest .pr .vv.none {
|
|
color: var(--text-soft);
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
/* ===================== ROW2 dev scan ===================== */
|
|
.kv {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
gap: 8px;
|
|
padding: 3.5px 0;
|
|
}
|
|
.kv .k {
|
|
font-family: var(--font-mono);
|
|
font-size: 8.5px;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
white-space: nowrap;
|
|
}
|
|
.kv .v {
|
|
font-size: 11px;
|
|
color: var(--text);
|
|
font-weight: 500;
|
|
text-align: right;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.kv .v.mono {
|
|
font-family: var(--font-mono);
|
|
}
|
|
.kv .v.dash {
|
|
color: var(--text-soft);
|
|
font-family: var(--font-mono);
|
|
}
|
|
.engRow {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 6px;
|
|
padding: 3px 0;
|
|
font-size: 9.5px;
|
|
}
|
|
.engRow .nm {
|
|
font-family: var(--font-mono);
|
|
font-size: 8.5px;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
color: var(--text);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
.engRow .nm .sd {
|
|
width: 7px;
|
|
height: 7px;
|
|
border-radius: 50%;
|
|
flex: 0 0 auto;
|
|
box-shadow: 0 0 5px currentColor;
|
|
}
|
|
.engRow .st {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
.engRow .st .stt {
|
|
font-size: 9.5px;
|
|
font-weight: 500;
|
|
}
|
|
.engRow .st .dm {
|
|
font-family: var(--font-mono);
|
|
font-size: 9px;
|
|
color: var(--text-soft);
|
|
min-width: 46px;
|
|
text-align: right;
|
|
}
|
|
.ok {
|
|
color: var(--accent-green);
|
|
}
|
|
.warnc {
|
|
color: var(--accent-orange);
|
|
}
|
|
.badge {
|
|
font-family: var(--font-mono);
|
|
font-size: 7.5px;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
color: var(--accent-yellow);
|
|
border: 1px solid var(--accent-yellow);
|
|
border-radius: 3px;
|
|
padding: 1px 5px;
|
|
opacity: 0.85;
|
|
}
|
|
.badge.soon {
|
|
color: var(--accent-cyan);
|
|
border-color: var(--accent-cyan);
|
|
}
|
|
.note {
|
|
font-family: var(--font-mono);
|
|
font-size: 8px;
|
|
letter-spacing: 0.04em;
|
|
color: var(--text-soft);
|
|
margin-top: 3px;
|
|
}
|
|
.emptyState {
|
|
font-family: var(--font-mono);
|
|
font-size: 9px;
|
|
letter-spacing: 0.04em;
|
|
color: var(--text-soft);
|
|
text-align: center;
|
|
padding: 10px 0;
|
|
}
|
|
|
|
/* small risk gauge in row2 */
|
|
.minigauge {
|
|
position: relative;
|
|
width: 74px;
|
|
height: 74px;
|
|
margin: 0 auto;
|
|
}
|
|
.minigauge svg {
|
|
width: 100%;
|
|
height: 100%;
|
|
transform: rotate(-90deg);
|
|
}
|
|
.minigauge .c {
|
|
position: absolute;
|
|
inset: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
.minigauge .c .p {
|
|
font-family: var(--font-mono);
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
color: var(--accent-cyan);
|
|
}
|
|
.riskCard .cardB {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 4px;
|
|
}
|
|
.riskCard .rk {
|
|
font-family: var(--font-mono);
|
|
font-size: 8px;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
}
|
|
|
|
/* ===================== ROW3 ===================== */
|
|
.oksPlan {
|
|
flex: 1;
|
|
display: flex;
|
|
gap: 9px;
|
|
min-height: 0;
|
|
}
|
|
.oksMini {
|
|
flex: 0 0 96px;
|
|
background: var(--surface-inset);
|
|
border: 1px solid var(--border-faint);
|
|
border-radius: var(--radius-xs);
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
.oksMini svg {
|
|
position: absolute;
|
|
inset: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
.oksKv {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
}
|
|
.dpGrid {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr 1fr;
|
|
gap: 7px 10px;
|
|
flex: 1;
|
|
align-content: center;
|
|
}
|
|
.dpCell .k {
|
|
font-family: var(--font-mono);
|
|
font-size: 8px;
|
|
letter-spacing: 0.07em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
margin-bottom: 3px;
|
|
}
|
|
.dpCell .v {
|
|
font-family: var(--font-mono);
|
|
font-size: 15px;
|
|
font-weight: 600;
|
|
color: var(--text-strong);
|
|
white-space: nowrap;
|
|
}
|
|
.dpCell .v .u {
|
|
font-size: 10px;
|
|
color: var(--text-soft);
|
|
}
|
|
.dpCell .v.dash {
|
|
color: var(--text-soft);
|
|
}
|
|
.dpCellWide {
|
|
grid-column: span 3;
|
|
border-top: 1px solid var(--border-faint);
|
|
padding-top: 6px;
|
|
margin-top: 2px;
|
|
}
|
|
|
|
/* product card */
|
|
.chips {
|
|
display: flex;
|
|
gap: 5px;
|
|
margin-bottom: 9px;
|
|
flex-wrap: wrap;
|
|
}
|
|
.chip {
|
|
font-family: var(--font-mono);
|
|
font-size: 8.5px;
|
|
letter-spacing: 0.04em;
|
|
padding: 3px 8px;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-xs);
|
|
color: var(--text-soft);
|
|
background: var(--surface-2);
|
|
}
|
|
.chipActive {
|
|
color: var(--accent-cyan);
|
|
border-color: var(--accent-cyan);
|
|
background: var(--chip-bg);
|
|
box-shadow: 0 0 8px var(--glow);
|
|
}
|
|
.chipDim {
|
|
opacity: 0.45;
|
|
}
|
|
.aptrow {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 2.5px 0;
|
|
}
|
|
.aptrow .nm {
|
|
font-family: var(--font-mono);
|
|
font-size: 8.5px;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
width: 34px;
|
|
flex: 0 0 auto;
|
|
}
|
|
.aptrow .track {
|
|
flex: 1;
|
|
height: 6px;
|
|
background: var(--surface-inset);
|
|
border-radius: 3px;
|
|
overflow: hidden;
|
|
}
|
|
.aptrow .track i {
|
|
display: block;
|
|
height: 100%;
|
|
background: var(--accent-cyan);
|
|
opacity: 0.85;
|
|
border-radius: 3px;
|
|
}
|
|
.aptrow .pc {
|
|
font-family: var(--font-mono);
|
|
font-size: 9px;
|
|
color: var(--text-soft);
|
|
width: 30px;
|
|
text-align: right;
|
|
}
|
|
.qgTitle {
|
|
font-family: var(--font-mono);
|
|
font-size: 7.5px;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
margin-bottom: 5px;
|
|
}
|
|
.dimBars .track i {
|
|
background: var(--text-soft);
|
|
opacity: 0.3;
|
|
}
|
|
|
|
/* insolation */
|
|
.insoCard .cardB {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
.insoIso {
|
|
flex: 0 0 110px;
|
|
height: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: var(--text-soft);
|
|
}
|
|
.insoIso svg {
|
|
width: 108px;
|
|
height: 96px;
|
|
}
|
|
.insoTxt {
|
|
flex: 1;
|
|
}
|
|
.insoTxt .d {
|
|
font-size: 10px;
|
|
color: var(--text-soft);
|
|
margin-top: 6px;
|
|
line-height: 1.4;
|
|
max-width: 150px;
|
|
}
|
|
|
|
/* ===================== ROW4 ===================== */
|
|
.finCard .cardB {
|
|
display: flex;
|
|
align-items: stretch;
|
|
gap: 14px;
|
|
}
|
|
.finMain {
|
|
display: flex;
|
|
gap: 18px;
|
|
flex: 1;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
}
|
|
.finBig .k {
|
|
font-family: var(--font-mono);
|
|
font-size: 8px;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
margin-bottom: 4px;
|
|
}
|
|
.finBig .v {
|
|
font-family: var(--font-mono);
|
|
font-size: 25px;
|
|
font-weight: 600;
|
|
color: var(--text-strong);
|
|
line-height: 1;
|
|
}
|
|
.finBig .v.dashed {
|
|
color: var(--text-soft);
|
|
}
|
|
.finBig .u {
|
|
font-family: var(--font-mono);
|
|
font-size: 9px;
|
|
color: var(--text-soft);
|
|
margin-top: 3px;
|
|
letter-spacing: 0.06em;
|
|
}
|
|
.finSep {
|
|
width: 1px;
|
|
background: var(--border-faint);
|
|
align-self: stretch;
|
|
}
|
|
.finRatios {
|
|
display: flex;
|
|
gap: 16px;
|
|
align-items: center;
|
|
}
|
|
.finRatios .r .k {
|
|
font-family: var(--font-mono);
|
|
font-size: 8px;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
margin-bottom: 4px;
|
|
}
|
|
.finRatios .r .v {
|
|
font-family: var(--font-mono);
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
color: var(--text-strong);
|
|
}
|
|
.finRatios .r .v.dashed {
|
|
color: var(--text-soft);
|
|
}
|
|
.buyGauge {
|
|
flex: 0 0 auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 3px;
|
|
border-left: 1px solid var(--border-faint);
|
|
padding-left: 14px;
|
|
}
|
|
|
|
/* legal */
|
|
.legalGrid {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 0 14px;
|
|
flex: 1;
|
|
align-content: start;
|
|
}
|
|
.legalRow {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
padding: 4px 0;
|
|
border-bottom: 1px solid var(--border-faint);
|
|
}
|
|
.legalRow .k {
|
|
font-family: var(--font-mono);
|
|
font-size: 9px;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
}
|
|
.legalRow .v {
|
|
font-size: 11px;
|
|
color: var(--text);
|
|
font-weight: 500;
|
|
}
|
|
.legalRow .v.no {
|
|
color: var(--accent-green);
|
|
}
|
|
.legalRow .v.dash {
|
|
color: var(--text-soft);
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
/* verdict */
|
|
.verdictCard .cardB {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 16px;
|
|
}
|
|
.verdictBig {
|
|
flex: 0 0 auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
}
|
|
.verdictBig .v {
|
|
font-family: var(--font-mono);
|
|
font-size: 34px;
|
|
font-weight: 700;
|
|
letter-spacing: 0.04em;
|
|
color: var(--verdict);
|
|
line-height: 1;
|
|
text-shadow: 0 0 14px var(--glow);
|
|
}
|
|
.verdictBig .v.warn {
|
|
color: var(--accent-yellow);
|
|
}
|
|
.verdictBig .v.bad {
|
|
color: var(--accent-red);
|
|
}
|
|
.verdictBig .note {
|
|
margin-top: 8px;
|
|
}
|
|
.verdictCheck {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0;
|
|
min-width: 0;
|
|
}
|
|
.vchk {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 4px 0;
|
|
border-bottom: 1px solid var(--border-faint);
|
|
font-size: 10.5px;
|
|
}
|
|
.vchk svg {
|
|
width: 14px;
|
|
height: 14px;
|
|
flex: 0 0 auto;
|
|
}
|
|
.vchk.okRow {
|
|
color: var(--text);
|
|
}
|
|
.vchk.okRow svg {
|
|
color: var(--accent-green);
|
|
}
|
|
.vchk.warnRow svg {
|
|
color: var(--accent-orange);
|
|
}
|
|
.vchk.warnRow {
|
|
color: var(--text);
|
|
}
|
|
.vchk.badRow svg {
|
|
color: var(--accent-red);
|
|
}
|
|
.vchk.badRow {
|
|
color: var(--text);
|
|
}
|
|
|
|
/* ===================== FOOTER ===================== */
|
|
.footer {
|
|
grid-row: 3;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
border-top: 1px solid var(--border);
|
|
background: var(--topbar-bg);
|
|
padding: 0 18px;
|
|
font-family: var(--font-mono);
|
|
font-size: 8.5px;
|
|
letter-spacing: 0.06em;
|
|
color: var(--text-soft);
|
|
text-transform: uppercase;
|
|
}
|
|
.footer .left {
|
|
display: flex;
|
|
gap: 10px;
|
|
align-items: center;
|
|
}
|
|
.footer .left b {
|
|
color: var(--text-muted);
|
|
font-weight: 600;
|
|
}
|
|
.footDot {
|
|
color: var(--text-soft);
|
|
opacity: 0.6;
|
|
}
|
|
.footer .right {
|
|
color: var(--text-soft);
|
|
}
|
|
|
|
/* ===================== TOAST ===================== */
|
|
.toast {
|
|
position: fixed;
|
|
left: 50%;
|
|
bottom: 64px;
|
|
z-index: 90;
|
|
transform: translateX(-50%) translateY(14px);
|
|
background: var(--surface-strong);
|
|
border: 1px solid var(--border-strong);
|
|
border-radius: var(--radius-sm);
|
|
padding: 11px 18px;
|
|
font-family: var(--font-mono);
|
|
font-size: 11px;
|
|
letter-spacing: 0.04em;
|
|
color: var(--text-strong);
|
|
box-shadow: var(--shadow);
|
|
opacity: 0;
|
|
visibility: hidden;
|
|
transition:
|
|
opacity 0.2s,
|
|
transform 0.2s,
|
|
visibility 0.2s;
|
|
}
|
|
.toastShow {
|
|
opacity: 1;
|
|
visibility: visible;
|
|
transform: translateX(-50%) translateY(0);
|
|
}
|
|
|
|
/* theme toggle */
|
|
.themeToggle {
|
|
position: fixed;
|
|
right: 14px;
|
|
bottom: 38px;
|
|
z-index: 50;
|
|
width: 38px;
|
|
height: 38px;
|
|
border-radius: 50%;
|
|
background: var(--surface-strong);
|
|
border: 1px solid var(--border-strong);
|
|
color: var(--accent-cyan);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: var(--shadow);
|
|
font-size: 16px;
|
|
}
|
|
|
|
/* ===================== STATE SCREENS ===================== */
|
|
.stateScreen {
|
|
grid-row: 2;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 40px;
|
|
}
|
|
.stateBox {
|
|
font-family: var(--font-mono);
|
|
font-size: 11px;
|
|
letter-spacing: 0.08em;
|
|
color: var(--text-muted);
|
|
text-transform: uppercase;
|
|
}
|
|
.stateError {
|
|
font-family: var(--font-mono);
|
|
font-size: 12px;
|
|
color: var(--accent-red);
|
|
margin-bottom: 12px;
|
|
}
|
|
.stateLink {
|
|
font-family: var(--font-mono);
|
|
font-size: 10px;
|
|
letter-spacing: 0.06em;
|
|
color: var(--accent-cyan);
|
|
text-transform: uppercase;
|
|
text-decoration: none;
|
|
}
|
|
|
|
/* ===================== OVERLAY (shared scrim) ===================== */
|
|
.scrim {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 60;
|
|
background: rgba(2, 8, 12, 0.55);
|
|
opacity: 0;
|
|
visibility: hidden;
|
|
transition:
|
|
opacity 0.22s ease,
|
|
visibility 0.22s ease;
|
|
backdrop-filter: blur(1.5px);
|
|
}
|
|
.v2Root[data-theme="light"] .scrim {
|
|
background: rgba(30, 50, 70, 0.32);
|
|
}
|
|
.scrimOpen {
|
|
opacity: 1;
|
|
visibility: visible;
|
|
}
|
|
|
|
/* ===================== DRAWER ===================== */
|
|
.drawer {
|
|
position: fixed;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
z-index: 70;
|
|
width: 480px;
|
|
max-width: 92vw;
|
|
background: var(--surface-strong);
|
|
border-left: 1px solid var(--border-strong);
|
|
box-shadow: -24px 0 70px rgba(0, 0, 0, 0.42);
|
|
transform: translateX(100%);
|
|
transition: transform 0.26s cubic-bezier(0.4, 0, 0.2, 1);
|
|
display: flex;
|
|
flex-direction: column;
|
|
background-image:
|
|
linear-gradient(var(--grid-line) 1px, transparent 1px),
|
|
linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
|
|
background-size:
|
|
34px 34px,
|
|
34px 34px;
|
|
}
|
|
.v2Root[data-theme="light"] .drawer {
|
|
box-shadow: -18px 0 50px rgba(40, 68, 92, 0.18);
|
|
}
|
|
.drawerOpen {
|
|
transform: translateX(0);
|
|
}
|
|
.drawerH {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: 10px;
|
|
padding: 16px 18px 13px;
|
|
border-bottom: 1px solid var(--border);
|
|
flex: 0 0 auto;
|
|
background: var(--topbar-bg);
|
|
}
|
|
.drawerH .dhLeft {
|
|
min-width: 0;
|
|
}
|
|
.drawerH .dhEyebrow {
|
|
font-family: var(--font-mono);
|
|
font-size: 8.5px;
|
|
letter-spacing: 0.16em;
|
|
text-transform: uppercase;
|
|
color: var(--accent-cyan);
|
|
margin-bottom: 5px;
|
|
}
|
|
.drawerH .dhTitle {
|
|
font-family: var(--font-mono);
|
|
font-size: 15px;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
color: var(--text-strong);
|
|
font-weight: 600;
|
|
line-height: 1.15;
|
|
}
|
|
.drawerH .dhSum {
|
|
font-size: 11px;
|
|
color: var(--text-muted);
|
|
margin-top: 7px;
|
|
line-height: 1.45;
|
|
max-width: 380px;
|
|
}
|
|
.drawerClose {
|
|
flex: 0 0 auto;
|
|
width: 28px;
|
|
height: 28px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-xs);
|
|
background: var(--surface-2);
|
|
color: var(--text-muted);
|
|
font-size: 15px;
|
|
line-height: 1;
|
|
}
|
|
.drawerClose:hover {
|
|
color: var(--text-strong);
|
|
border-color: var(--border-strong);
|
|
}
|
|
.drawerB {
|
|
flex: 1;
|
|
min-height: 0;
|
|
overflow-y: auto;
|
|
padding: 16px 18px 22px;
|
|
}
|
|
.drawerB::-webkit-scrollbar {
|
|
width: 7px;
|
|
}
|
|
.drawerB::-webkit-scrollbar-thumb {
|
|
background: var(--border-strong);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
/* drawer content primitives */
|
|
.dsec {
|
|
margin-bottom: 18px;
|
|
}
|
|
.dsec:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
.dsecT {
|
|
font-family: var(--font-mono);
|
|
font-size: 9px;
|
|
letter-spacing: 0.14em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
margin-bottom: 9px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
.dsecT::after {
|
|
content: "";
|
|
flex: 1;
|
|
height: 1px;
|
|
background: var(--border-faint);
|
|
}
|
|
.drow {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
gap: 14px;
|
|
padding: 7px 0;
|
|
border-bottom: 1px solid var(--border-faint);
|
|
}
|
|
.drow:last-child {
|
|
border-bottom: none;
|
|
}
|
|
.drow .k {
|
|
font-family: var(--font-mono);
|
|
font-size: 9.5px;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
flex: 0 0 auto;
|
|
max-width: 48%;
|
|
}
|
|
.drow .v {
|
|
font-size: 12px;
|
|
color: var(--text);
|
|
font-weight: 500;
|
|
text-align: right;
|
|
font-variant-numeric: tabular-nums;
|
|
line-height: 1.35;
|
|
}
|
|
.drow .v.mono {
|
|
font-family: var(--font-mono);
|
|
}
|
|
.drow .v.dash {
|
|
color: var(--text-soft);
|
|
font-family: var(--font-mono);
|
|
}
|
|
.drow .v.ok {
|
|
color: var(--verdict);
|
|
}
|
|
.drow .v.warnc {
|
|
color: var(--accent-orange);
|
|
}
|
|
.dnote {
|
|
font-family: var(--font-mono);
|
|
font-size: 8.5px;
|
|
letter-spacing: 0.04em;
|
|
color: var(--text-soft);
|
|
margin-top: 10px;
|
|
line-height: 1.5;
|
|
}
|
|
.dsource {
|
|
font-family: var(--font-mono);
|
|
font-size: 8.5px;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
margin-top: 16px;
|
|
padding-top: 12px;
|
|
border-top: 1px solid var(--border-faint);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 7px;
|
|
}
|
|
.dsource svg {
|
|
width: 12px;
|
|
height: 12px;
|
|
flex: 0 0 auto;
|
|
opacity: 0.8;
|
|
}
|
|
.dbadge {
|
|
display: inline-block;
|
|
font-family: var(--font-mono);
|
|
font-size: 8px;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
padding: 2px 7px;
|
|
border-radius: 3px;
|
|
border: 1px solid var(--accent-yellow);
|
|
color: var(--accent-yellow);
|
|
}
|
|
.dbadge.cyan {
|
|
border-color: var(--accent-cyan);
|
|
color: var(--accent-cyan);
|
|
}
|
|
.dbadge.green {
|
|
border-color: var(--verdict);
|
|
color: var(--verdict);
|
|
}
|
|
.dbadgeRight {
|
|
margin-left: auto;
|
|
}
|
|
|
|
/* drawer data table */
|
|
.dtable {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.dtable th,
|
|
.dtable td {
|
|
text-align: right;
|
|
padding: 6px 6px;
|
|
border-bottom: 1px solid var(--border-faint);
|
|
white-space: nowrap;
|
|
}
|
|
.dtable th {
|
|
font-family: var(--font-mono);
|
|
font-size: 7.5px;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
font-weight: 500;
|
|
}
|
|
.dtable td {
|
|
font-size: 10px;
|
|
color: var(--text);
|
|
}
|
|
.dtable th:first-child,
|
|
.dtable td:first-child {
|
|
text-align: left;
|
|
}
|
|
.dtable td.mono {
|
|
font-family: var(--font-mono);
|
|
}
|
|
.dtable tr.me td {
|
|
color: var(--accent-cyan);
|
|
}
|
|
.dtable td.dash {
|
|
color: var(--text-soft);
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
/* factor bars */
|
|
.dfac {
|
|
margin: 9px 0;
|
|
}
|
|
.dfacH {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
font-family: var(--font-mono);
|
|
font-size: 9px;
|
|
color: var(--text-soft);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.04em;
|
|
margin-bottom: 4px;
|
|
}
|
|
.dfacH b {
|
|
color: var(--text);
|
|
font-weight: 500;
|
|
}
|
|
.dfacTrack {
|
|
height: 7px;
|
|
background: var(--surface-inset);
|
|
border-radius: 4px;
|
|
overflow: hidden;
|
|
}
|
|
.dfacTrack i {
|
|
display: block;
|
|
height: 100%;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
/* drawer export buttons */
|
|
.dexport {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 9px;
|
|
}
|
|
.dbtn {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 9px;
|
|
padding: 11px 12px;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-xs);
|
|
background: var(--surface-2);
|
|
color: var(--text);
|
|
font-family: var(--font-mono);
|
|
font-size: 10px;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
text-align: left;
|
|
}
|
|
.dbtn:hover {
|
|
border-color: var(--accent-cyan);
|
|
color: var(--accent-cyan);
|
|
box-shadow: 0 0 10px var(--glow);
|
|
}
|
|
.dbtn svg {
|
|
width: 15px;
|
|
height: 15px;
|
|
flex: 0 0 auto;
|
|
opacity: 0.85;
|
|
}
|
|
.dbtn .ds {
|
|
font-size: 7.5px;
|
|
color: var(--text-soft);
|
|
text-transform: none;
|
|
letter-spacing: 0;
|
|
}
|
|
.dbtn b {
|
|
font-weight: 600;
|
|
display: block;
|
|
}
|
|
|
|
/* ===================== CHAT ===================== */
|
|
.chatFab {
|
|
position: fixed;
|
|
right: 14px;
|
|
bottom: 84px;
|
|
z-index: 55;
|
|
width: 46px;
|
|
height: 46px;
|
|
border-radius: 50%;
|
|
background: var(--accent-blue);
|
|
border: 1px solid var(--accent-cyan);
|
|
color: #fff;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow:
|
|
0 8px 28px rgba(0, 0, 0, 0.4),
|
|
0 0 14px var(--glow-strong);
|
|
}
|
|
.chatFab svg {
|
|
width: 21px;
|
|
height: 21px;
|
|
}
|
|
.chatPanel {
|
|
position: fixed;
|
|
right: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
z-index: 75;
|
|
width: 380px;
|
|
max-width: 90vw;
|
|
background: var(--surface-strong);
|
|
border-left: 1px solid var(--border-strong);
|
|
box-shadow: -24px 0 70px rgba(0, 0, 0, 0.42);
|
|
transform: translateX(110%);
|
|
transition: transform 0.26s cubic-bezier(0.4, 0, 0.2, 1);
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
.v2Root[data-theme="light"] .chatPanel {
|
|
box-shadow: -18px 0 50px rgba(40, 68, 92, 0.18);
|
|
}
|
|
.chatPanelOpen {
|
|
transform: translateX(0);
|
|
}
|
|
.chatH {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 10px;
|
|
padding: 14px 16px 12px;
|
|
border-bottom: 1px solid var(--border);
|
|
background: var(--topbar-bg);
|
|
flex: 0 0 auto;
|
|
}
|
|
.chatH .chL {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 9px;
|
|
min-width: 0;
|
|
}
|
|
.chatH .chIc {
|
|
width: 26px;
|
|
height: 26px;
|
|
border-radius: 50%;
|
|
background: var(--accent-blue);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: #fff;
|
|
flex: 0 0 auto;
|
|
}
|
|
.chatH .chIc svg {
|
|
width: 14px;
|
|
height: 14px;
|
|
}
|
|
.chatH .chT {
|
|
font-family: var(--font-mono);
|
|
font-size: 11px;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
color: var(--text-strong);
|
|
font-weight: 600;
|
|
}
|
|
.chatH .chS {
|
|
font-family: var(--font-mono);
|
|
font-size: 8px;
|
|
letter-spacing: 0.06em;
|
|
color: var(--text-soft);
|
|
margin-top: 2px;
|
|
}
|
|
.chatMsgs {
|
|
flex: 1;
|
|
min-height: 0;
|
|
overflow-y: auto;
|
|
padding: 16px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
}
|
|
.chatMsgs::-webkit-scrollbar {
|
|
width: 7px;
|
|
}
|
|
.chatMsgs::-webkit-scrollbar-thumb {
|
|
background: var(--border-strong);
|
|
border-radius: 4px;
|
|
}
|
|
.msg {
|
|
max-width: 84%;
|
|
font-size: 12px;
|
|
line-height: 1.5;
|
|
padding: 10px 12px;
|
|
border-radius: 12px;
|
|
white-space: pre-wrap;
|
|
}
|
|
.msgBot {
|
|
align-self: flex-start;
|
|
background: var(--surface-muted);
|
|
border: 1px solid var(--border-faint);
|
|
color: var(--text);
|
|
border-top-left-radius: 3px;
|
|
}
|
|
.msgUser {
|
|
align-self: flex-end;
|
|
background: var(--accent-blue);
|
|
color: #fff;
|
|
border-top-right-radius: 3px;
|
|
}
|
|
.chatChips {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 7px;
|
|
padding: 0 16px 12px;
|
|
flex: 0 0 auto;
|
|
}
|
|
.chatChip {
|
|
font-family: var(--font-mono);
|
|
font-size: 9.5px;
|
|
letter-spacing: 0.02em;
|
|
padding: 6px 11px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 14px;
|
|
color: var(--text-muted);
|
|
background: var(--surface-2);
|
|
}
|
|
.chatChip:hover {
|
|
border-color: var(--accent-cyan);
|
|
color: var(--accent-cyan);
|
|
}
|
|
.chatInput {
|
|
display: flex;
|
|
gap: 8px;
|
|
padding: 12px 14px;
|
|
border-top: 1px solid var(--border);
|
|
background: var(--topbar-bg);
|
|
flex: 0 0 auto;
|
|
}
|
|
.chatInput input {
|
|
flex: 1;
|
|
background: var(--surface-inset);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-xs);
|
|
color: var(--text);
|
|
font-family: var(--font-ui);
|
|
font-size: 12px;
|
|
padding: 9px 11px;
|
|
outline: none;
|
|
}
|
|
.chatInput input:focus {
|
|
border-color: var(--accent-cyan);
|
|
}
|
|
.chatInput input::placeholder {
|
|
color: var(--text-soft);
|
|
}
|
|
.chatSend {
|
|
flex: 0 0 auto;
|
|
width: 38px;
|
|
border: 1px solid var(--accent-cyan);
|
|
border-radius: var(--radius-xs);
|
|
background: var(--accent-blue);
|
|
color: #fff;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
.chatSend svg {
|
|
width: 16px;
|
|
height: 16px;
|
|
}
|
|
.chatTyping {
|
|
align-self: flex-start;
|
|
display: flex;
|
|
gap: 4px;
|
|
padding: 11px 13px;
|
|
background: var(--surface-muted);
|
|
border: 1px solid var(--border-faint);
|
|
border-radius: 12px;
|
|
border-top-left-radius: 3px;
|
|
}
|
|
.chatTyping i {
|
|
width: 5px;
|
|
height: 5px;
|
|
border-radius: 50%;
|
|
background: var(--text-soft);
|
|
animation: tdot 1s infinite;
|
|
}
|
|
.chatTyping i:nth-child(2) {
|
|
animation-delay: 0.2s;
|
|
}
|
|
.chatTyping i:nth-child(3) {
|
|
animation-delay: 0.4s;
|
|
}
|
|
@keyframes tdot {
|
|
0%,
|
|
60%,
|
|
100% {
|
|
opacity: 0.3;
|
|
transform: translateY(0);
|
|
}
|
|
30% {
|
|
opacity: 1;
|
|
transform: translateY(-3px);
|
|
}
|
|
}
|
|
|
|
/* =====================================================================
|
|
* MAP — per-theme title + resource legend overlay
|
|
* (matches prototype `ptica-v2/index.html` `.map-head` + `.legend .lg-res`)
|
|
* ===================================================================== */
|
|
|
|
/* Per-theme map title — both spans rendered, CSS shows one. Mirrors the
|
|
prototype `.tnum-d` / `.tnum-l` toggle. */
|
|
.mapTitleDark,
|
|
.mapTitleLight {
|
|
display: none;
|
|
}
|
|
.v2Root[data-theme="dark"] .mapTitleDark {
|
|
display: inline;
|
|
}
|
|
.v2Root[data-theme="light"] .mapTitleLight {
|
|
display: inline;
|
|
}
|
|
|
|
/* Resource legend (top-left, under the map title) — compact 5-row panel. */
|
|
.mapLegend {
|
|
position: absolute;
|
|
left: 11px;
|
|
top: 34px;
|
|
z-index: 6;
|
|
min-width: 168px;
|
|
max-width: 200px;
|
|
background: var(--surface-strong);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-xs);
|
|
padding: 8px 9px;
|
|
backdrop-filter: blur(3px);
|
|
pointer-events: none;
|
|
}
|
|
.mapLegendTitle {
|
|
font-family: var(--font-mono);
|
|
font-size: 7.5px;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
color: var(--text-soft);
|
|
margin: 0 0 5px;
|
|
}
|
|
.mapLegendRow {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
height: 15px;
|
|
font-size: 9px;
|
|
}
|
|
.mapLegendDot {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
flex: 0 0 auto;
|
|
box-shadow: 0 0 5px currentColor;
|
|
}
|
|
.mapLegendLabel {
|
|
font-family: var(--font-mono);
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
color: var(--text);
|
|
font-size: 8.5px;
|
|
}
|
|
.mapLegendDist {
|
|
margin-left: auto;
|
|
font-family: var(--font-mono);
|
|
font-size: 8.5px;
|
|
color: var(--text-muted);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.mapLegendDistEmpty {
|
|
color: var(--text-soft);
|
|
opacity: 0.7;
|
|
}
|
|
|
|
/* =====================================================================
|
|
* LIGHT THEME — targeted contrast polish
|
|
* Tokens stay; just bump the value-side text and the cyan accents that
|
|
* appear washed-out on white. Dark theme is untouched.
|
|
* ===================================================================== */
|
|
|
|
/* kv-row: value text on white needs darker ink. */
|
|
.v2Root[data-theme="light"] .kv .v {
|
|
color: var(--text-strong);
|
|
}
|
|
|
|
/* Инженерия status-row: distance was --text-soft (#768493 ≈ AA-borderline
|
|
at 12px on white); push to --text-muted (#51616f) for solid AA. */
|
|
.v2Root[data-theme="light"] .engRow .st .dm {
|
|
color: var(--text-muted);
|
|
}
|
|
/* Status-dot glow on white reads as a halo — soften it. */
|
|
.v2Root[data-theme="light"] .engRow .nm .sd {
|
|
box-shadow: none;
|
|
}
|
|
|
|
/* Map-legend value column — same readability bump on white. */
|
|
.v2Root[data-theme="light"] .mapLegendDist {
|
|
color: var(--text-strong);
|
|
}
|
|
.v2Root[data-theme="light"] .mapLegendLabel {
|
|
color: var(--text-strong);
|
|
}
|
|
.v2Root[data-theme="light"] .mapLegendDot {
|
|
box-shadow: none;
|
|
}
|
|
/* Map title (light): drop the dark text-shadow that makes thin uppercase
|
|
look smudgy on a satellite-light map base. */
|
|
.v2Root[data-theme="light"] .mapHead .ttl {
|
|
text-shadow: 0 1px 2px rgba(255, 255, 255, 0.6);
|
|
color: var(--text-strong);
|
|
}
|
|
|
|
/* Cards `Подробнее →` — cyan on white is faint. Swap to the deeper blue. */
|
|
.v2Root[data-theme="light"] .more {
|
|
color: var(--accent-blue);
|
|
}
|
|
|
|
/* Drawer eyebrow (cyan in dark) — use blue on white for AA. */
|
|
.v2Root[data-theme="light"] .drawerH .dhEyebrow {
|
|
color: var(--accent-blue);
|
|
}
|
|
|
|
/* Topbar version-chip: cyan text on a white pill is illegible. */
|
|
.v2Root[data-theme="light"] .ver {
|
|
color: var(--accent-blue);
|
|
border-color: var(--border-strong);
|
|
background: var(--surface);
|
|
}
|
|
/* Topbar clock — separator-like vertical line between time + date is faint;
|
|
strengthen the date line and the chip border for visible structure. */
|
|
.v2Root[data-theme="light"] .clock .date {
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
/* Active tab underline — cyan + glow on white reads as a pale smudge.
|
|
Swap to brand blue + drop the glow halo. */
|
|
.v2Root[data-theme="light"] .tabActive::after {
|
|
background: var(--accent-blue);
|
|
box-shadow: none;
|
|
}
|
|
/* Rail active marker — same treatment. */
|
|
.v2Root[data-theme="light"] .railItemActive {
|
|
color: var(--accent-blue);
|
|
}
|
|
.v2Root[data-theme="light"] .railItemActive::before {
|
|
background: var(--accent-blue);
|
|
box-shadow: none;
|
|
}
|
|
|
|
/* Generic note / drawer note / source — bump from --text-soft to --text-muted
|
|
on white so the caveat copy stays readable but still secondary. */
|
|
.v2Root[data-theme="light"] .note,
|
|
.v2Root[data-theme="light"] .dnote,
|
|
.v2Root[data-theme="light"] .dsource {
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
/* Section separator line inside drawer (`::after` on .dsecT) — barely visible
|
|
on white at 10% alpha; strengthen the border-faint reach within drawer. */
|
|
.v2Root[data-theme="light"] .dsecT::after,
|
|
.v2Root[data-theme="light"] .drow {
|
|
border-color: rgba(40, 70, 95, 0.16);
|
|
}
|