mirror of
https://github.com/smittix/intercept.git
synced 2026-06-08 14:11:54 -07:00
020126b6e0
The sidebar-hiding CSS lives only in meshtastic.css, which is lazily loaded and may not be present when switching directly to Meshcore mode. Duplicating the three rules into meshcore.css ensures the generic sidebar is correctly hidden and the output panel fills the screen regardless of load order. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
432 lines
9.1 KiB
CSS
432 lines
9.1 KiB
CSS
/* Meshcore mode — scoped styles */
|
|
|
|
/* ── Sidebar hiding (same rules as meshtastic.css — needed here since
|
|
meshtastic.css is only lazily loaded when that mode is visited) ── */
|
|
.main-content.mesh-sidebar-hidden {
|
|
display: flex !important;
|
|
flex-direction: column !important;
|
|
}
|
|
|
|
.main-content.mesh-sidebar-hidden > .sidebar {
|
|
display: none !important;
|
|
width: 0 !important;
|
|
height: 0 !important;
|
|
overflow: hidden !important;
|
|
}
|
|
|
|
.main-content.mesh-sidebar-hidden > .output-panel {
|
|
flex: 1 !important;
|
|
width: 100% !important;
|
|
max-width: 100% !important;
|
|
}
|
|
|
|
/* ── Container overrides ── */
|
|
#meshcoreVisuals {
|
|
flex-direction: column;
|
|
padding: 0;
|
|
gap: 0;
|
|
}
|
|
|
|
#meshcoreMode {
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 1;
|
|
min-height: 0;
|
|
overflow: hidden;
|
|
gap: 0;
|
|
}
|
|
|
|
/* ── Connection strip ── */
|
|
.meshcore-strip {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 6px 12px;
|
|
background: var(--bg-card);
|
|
border-bottom: 1px solid var(--border-color);
|
|
flex-shrink: 0;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.meshcore-strip-group {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
|
|
.meshcore-strip-divider {
|
|
width: 1px;
|
|
height: 20px;
|
|
background: var(--border-color);
|
|
margin: 0 4px;
|
|
}
|
|
|
|
.meshcore-strip-status-text {
|
|
font-size: 12px;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.meshcore-strip-select {
|
|
background: var(--bg-input);
|
|
border: 1px solid var(--border-color);
|
|
color: var(--text-primary);
|
|
padding: 4px 6px;
|
|
font-size: 12px;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.meshcore-strip-input {
|
|
background: var(--bg-input);
|
|
border: 1px solid var(--border-color);
|
|
color: var(--text-primary);
|
|
padding: 4px 6px;
|
|
font-size: 12px;
|
|
border-radius: 3px;
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
.meshcore-strip-btn {
|
|
padding: 4px 10px;
|
|
font-size: 12px;
|
|
border-radius: 3px;
|
|
cursor: pointer;
|
|
border: 1px solid var(--border-color);
|
|
background: var(--bg-input);
|
|
color: var(--text-primary);
|
|
transition: background 0.15s;
|
|
}
|
|
|
|
.meshcore-strip-btn:hover { opacity: 0.85; }
|
|
.meshcore-strip-btn.connect { background: var(--accent-cyan); color: #000; border-color: var(--accent-cyan); }
|
|
.meshcore-strip-btn.disconnect { border-color: #f44336; color: #f44336; }
|
|
.meshcore-strip-btn:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
|
|
/* Transport tabs in strip */
|
|
.meshcore-transport-tabs {
|
|
display: flex;
|
|
gap: 2px;
|
|
}
|
|
|
|
.meshcore-transport-tab {
|
|
padding: 3px 8px;
|
|
font-size: 11px;
|
|
background: var(--bg-input);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 3px;
|
|
cursor: pointer;
|
|
color: var(--text-muted);
|
|
transition: background 0.15s, color 0.15s;
|
|
}
|
|
|
|
.meshcore-transport-tab.active {
|
|
background: var(--accent-cyan);
|
|
color: #000;
|
|
border-color: var(--accent-cyan);
|
|
}
|
|
|
|
/* Strip stats */
|
|
.meshcore-strip-stat {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
min-width: 40px;
|
|
}
|
|
|
|
.meshcore-strip-value {
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: var(--accent-cyan);
|
|
font-family: var(--font-mono);
|
|
line-height: 1;
|
|
}
|
|
|
|
.meshcore-strip-label {
|
|
font-size: 9px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.08em;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
/* ── Status dot ── */
|
|
.meshcore-status-dot {
|
|
display: inline-block;
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
background: var(--text-muted);
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.meshcore-status-dot.connected { background: #4caf50; box-shadow: 0 0 5px #4caf50; }
|
|
.meshcore-status-dot.connecting { background: #ff9800; animation: meshcore-pulse 1s infinite; }
|
|
.meshcore-status-dot.error { background: #f44336; }
|
|
|
|
@keyframes meshcore-pulse {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0.3; }
|
|
}
|
|
|
|
/* ── Body (panel + content) ── */
|
|
.meshcore-body {
|
|
display: flex;
|
|
flex: 1;
|
|
min-height: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* ── Left contacts/nodes panel ── */
|
|
.meshcore-panel {
|
|
width: 200px;
|
|
min-width: 200px;
|
|
background: var(--bg-card);
|
|
border-right: 1px solid var(--border-color);
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.meshcore-panel-section {
|
|
padding: 10px;
|
|
border-bottom: 1px solid var(--border-color);
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.meshcore-panel-section--grow {
|
|
flex: 1;
|
|
}
|
|
|
|
.meshcore-panel-title {
|
|
font-size: 10px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.08em;
|
|
color: var(--text-muted);
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
/* ── Node / contact list items ── */
|
|
.meshcore-node-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 5px 0;
|
|
font-size: 12px;
|
|
border-bottom: 1px solid var(--border-color);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.meshcore-node-item:last-child { border-bottom: none; }
|
|
|
|
.meshcore-node-icon {
|
|
width: 10px;
|
|
height: 10px;
|
|
border-radius: 50%;
|
|
background: var(--accent-cyan);
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.meshcore-node-icon.repeater {
|
|
border-radius: 0;
|
|
clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
|
|
background: #ff9800;
|
|
}
|
|
|
|
.meshcore-node-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
.meshcore-node-meta { font-size: 10px; color: var(--text-muted); }
|
|
|
|
.meshcore-empty {
|
|
font-size: 11px;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.meshcore-label {
|
|
font-size: 12px;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
/* ── Right content ── */
|
|
.meshcore-content {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* ── Tab bar ── */
|
|
.meshcore-tabs {
|
|
display: flex;
|
|
border-bottom: 1px solid var(--border-color);
|
|
background: var(--bg-card);
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.meshcore-tab {
|
|
padding: 8px 16px;
|
|
font-size: 12px;
|
|
cursor: pointer;
|
|
color: var(--text-muted);
|
|
border-bottom: 2px solid transparent;
|
|
transition: color 0.15s, border-color 0.15s;
|
|
}
|
|
|
|
.meshcore-tab.active {
|
|
color: var(--accent-cyan);
|
|
border-bottom-color: var(--accent-cyan);
|
|
}
|
|
|
|
/* ── Tab panels ── */
|
|
.meshcore-tab-panel {
|
|
display: none;
|
|
flex: 1;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.meshcore-tab-panel.active { display: flex; }
|
|
|
|
/* ── Message feed ── */
|
|
.meshcore-messages {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: 12px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
.meshcore-message {
|
|
background: var(--bg-card);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 6px;
|
|
padding: 8px 10px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.meshcore-message.pending { opacity: 0.6; border-style: dashed; }
|
|
.meshcore-message.direct { border-left: 3px solid var(--accent-cyan); }
|
|
|
|
.meshcore-message-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-bottom: 4px;
|
|
font-size: 11px;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.meshcore-message-sender { color: var(--accent-cyan); font-weight: 600; }
|
|
.meshcore-message-text { color: var(--text-primary); }
|
|
|
|
/* ── Compose bar ── */
|
|
.meshcore-compose {
|
|
display: flex;
|
|
gap: 6px;
|
|
padding: 8px 12px;
|
|
border-top: 1px solid var(--border-color);
|
|
background: var(--bg-card);
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.meshcore-compose-select {
|
|
background: var(--bg-input);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 4px;
|
|
padding: 6px 8px;
|
|
color: var(--text-primary);
|
|
font-size: 12px;
|
|
width: 140px;
|
|
}
|
|
|
|
.meshcore-compose-input {
|
|
flex: 1;
|
|
background: var(--bg-input);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 4px;
|
|
padding: 6px 10px;
|
|
color: var(--text-primary);
|
|
font-size: 13px;
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
.meshcore-compose-input:focus {
|
|
outline: none;
|
|
border-color: var(--accent-cyan);
|
|
}
|
|
|
|
.meshcore-compose-btn {
|
|
padding: 6px 16px;
|
|
background: var(--accent-cyan);
|
|
color: #000;
|
|
border: none;
|
|
border-radius: 4px;
|
|
font-size: 12px;
|
|
cursor: pointer;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* ── Map tab ── */
|
|
#meshcoreTabMap { overflow: hidden; }
|
|
|
|
#meshcoreMap {
|
|
width: 100%;
|
|
height: 100%;
|
|
min-height: 300px;
|
|
}
|
|
|
|
/* ── Repeaters table ── */
|
|
.meshcore-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.meshcore-table th {
|
|
text-align: left;
|
|
padding: 6px 10px;
|
|
font-size: 10px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.06em;
|
|
color: var(--text-muted);
|
|
border-bottom: 1px solid var(--border-color);
|
|
}
|
|
|
|
.meshcore-table td {
|
|
padding: 6px 10px;
|
|
border-bottom: 1px solid var(--border-color);
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
/* ── Traceroute modal ── */
|
|
.meshcore-traceroute-hops {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
padding: 16px 0;
|
|
}
|
|
|
|
.meshcore-hop {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 4px;
|
|
}
|
|
|
|
.meshcore-hop-node {
|
|
background: var(--bg-input);
|
|
border: 1px solid var(--accent-cyan);
|
|
border-radius: 4px;
|
|
padding: 4px 8px;
|
|
font-size: 11px;
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
.meshcore-hop-arrow {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
padding: 0 6px;
|
|
font-size: 10px;
|
|
color: var(--text-muted);
|
|
}
|