secubox-openwrt/package/secubox/luci-app-streamlit/htdocs/luci-static/resources/streamlit/dashboard.css
CyberMind-FR 906bf6f549 feat: Add HTTP health checks, portal speedtest, and fix cert detection
- metablogizer: Add HTTP health checks for backend (uhttpd) and frontend (HAProxy)
- metablogizer: Fix BusyBox-compatible certificate expiry detection using openssl checkend
- secubox-portal: Add speed test widget with ping/download/upload measurement
- tor-shield: Fix settings save ensuring UCI sections exist
- cdn-cache: UI improvements and restructure
- streamlit: Fix port conflict (sappix now uses 8503)
- secubox-core: Add proxy mode detection
- security-threats: Dashboard improvements
- haproxy: Init.d and Makefile updates

PKG_RELEASE bumps:
- luci-app-cdn-cache: 3
- luci-app-metablogizer: 2
- luci-app-secubox-portal: 2
- luci-app-secubox-security-threats: 2
- luci-app-secubox: 4
- luci-app-streamlit: 9
- luci-app-tor-shield: 2
- secubox-app-haproxy: 23
- secubox-core: 6

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 19:46:26 +01:00

635 lines
11 KiB
CSS

/**
* Streamlit Platform Dashboard - Cyberpunk Theme
* SecuBox OpenWrt - CyberMind Studio
*/
/* ============================================
Base Dashboard Styles
============================================ */
.streamlit-dashboard {
padding: 20px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
min-height: 100vh;
background: #0a0a0f;
}
/* ============================================
Header
============================================ */
.st-header {
background: linear-gradient(135deg, rgba(0, 255, 255, 0.1), rgba(139, 92, 246, 0.1));
border: 1px solid rgba(0, 255, 255, 0.3);
border-radius: 12px;
padding: 24px;
margin-bottom: 24px;
position: relative;
overflow: hidden;
}
.st-header::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: repeating-linear-gradient(
0deg,
rgba(0, 255, 255, 0.03) 0px,
rgba(0, 255, 255, 0.03) 1px,
transparent 1px,
transparent 2px
);
pointer-events: none;
}
.st-header-content {
display: flex;
align-items: center;
gap: 20px;
position: relative;
z-index: 1;
}
.st-logo {
font-size: 48px;
text-shadow: 0 0 20px #0ff;
}
.st-title {
margin: 0;
font-size: 28px;
color: #0ff;
text-shadow: 0 0 10px #0ff, 0 0 20px #0ff;
font-family: 'Courier New', monospace;
letter-spacing: 2px;
}
.st-subtitle {
margin: 4px 0 0 0;
color: #94a3b8;
font-size: 14px;
}
/* ============================================
Stats Grid
============================================ */
.st-stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
margin-bottom: 24px;
}
.st-stat-card {
background: rgba(15, 23, 42, 0.8);
border: 1px solid rgba(0, 255, 255, 0.2);
border-radius: 12px;
padding: 20px;
display: flex;
align-items: center;
gap: 16px;
transition: all 0.3s ease;
}
.st-stat-card:hover {
border-color: rgba(0, 255, 255, 0.5);
box-shadow: 0 0 20px rgba(0, 255, 255, 0.2);
}
.st-stat-card.success { border-color: rgba(16, 185, 129, 0.5); }
.st-stat-card.warning { border-color: rgba(245, 158, 11, 0.5); }
.st-stat-card.error { border-color: rgba(244, 63, 94, 0.5); }
.st-stat-icon {
font-size: 32px;
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 255, 255, 0.1);
border-radius: 10px;
}
.st-stat-content {
flex: 1;
}
.st-stat-value {
font-size: 24px;
font-weight: 600;
color: #f1f5f9;
text-shadow: 0 0 5px rgba(0, 255, 255, 0.5);
}
.st-stat-label {
font-size: 13px;
color: #94a3b8;
margin-top: 2px;
}
/* ============================================
Cards
============================================ */
.st-main-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
}
@media (max-width: 900px) {
.st-main-grid {
grid-template-columns: 1fr;
}
}
.st-card {
background: rgba(15, 23, 42, 0.8);
border: 1px solid rgba(0, 255, 255, 0.2);
border-radius: 12px;
overflow: hidden;
}
.st-card-header {
padding: 16px 20px;
border-bottom: 1px solid rgba(0, 255, 255, 0.2);
display: flex;
align-items: center;
justify-content: space-between;
background: rgba(0, 255, 255, 0.05);
}
.st-card-title {
font-size: 16px;
font-weight: 600;
color: #0ff;
display: flex;
align-items: center;
gap: 8px;
}
.st-card-body {
padding: 20px;
}
.st-card-full {
grid-column: span 2;
}
@media (max-width: 900px) {
.st-card-full {
grid-column: span 1;
}
}
/* ============================================
Buttons
============================================ */
.st-btn {
padding: 10px 20px;
border-radius: 8px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
border: none;
transition: all 0.2s;
display: inline-flex;
align-items: center;
gap: 8px;
text-transform: uppercase;
letter-spacing: 1px;
}
.st-btn-primary {
background: linear-gradient(135deg, #0ff, #00a0a0);
color: #000;
}
.st-btn-primary:hover {
transform: translateY(-1px);
box-shadow: 0 0 20px rgba(0, 255, 255, 0.6);
}
.st-btn-success {
background: linear-gradient(135deg, #10b981, #059669);
color: white;
}
.st-btn-danger {
background: linear-gradient(135deg, #f43f5e, #e11d48);
color: white;
}
.st-btn-warning {
background: linear-gradient(135deg, #f59e0b, #d97706);
color: white;
}
.st-btn-secondary {
background: rgba(51, 65, 85, 0.8);
color: #94a3b8;
border: 1px solid rgba(0, 255, 255, 0.3);
}
.st-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none !important;
}
.st-btn-group {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
/* ============================================
Status Badge
============================================ */
.st-status-badge {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
border-radius: 20px;
font-size: 13px;
font-weight: 500;
}
.st-status-badge.running {
background: rgba(0, 255, 255, 0.2);
color: #0ff;
box-shadow: 0 0 10px rgba(0, 255, 255, 0.3);
}
.st-status-badge.stopped {
background: rgba(244, 63, 94, 0.2);
color: #f43f5e;
}
.st-status-badge.not-installed {
background: rgba(245, 158, 11, 0.2);
color: #f59e0b;
}
/* ============================================
Info List
============================================ */
.st-info-list {
list-style: none;
padding: 0;
margin: 0;
}
.st-info-list li {
display: flex;
justify-content: space-between;
padding: 10px 0;
border-bottom: 1px solid rgba(0, 255, 255, 0.1);
}
.st-info-list li:last-child {
border-bottom: none;
}
.st-info-label {
color: #94a3b8;
}
.st-info-value {
color: #f1f5f9;
font-weight: 500;
}
.st-info-value a {
color: #0ff;
text-decoration: none;
}
.st-info-value a:hover {
text-decoration: underline;
text-shadow: 0 0 10px #0ff;
}
/* ============================================
Logs
============================================ */
.st-logs {
background: #0a0a0f;
border: 1px solid rgba(0, 255, 255, 0.2);
border-radius: 8px;
padding: 12px;
font-family: "Monaco", "Consolas", monospace;
font-size: 12px;
color: #0ff;
max-height: 300px;
overflow-y: auto;
}
.st-logs-line {
margin: 4px 0;
white-space: pre-wrap;
word-break: break-all;
opacity: 0.8;
}
.st-logs-line:hover {
opacity: 1;
background: rgba(0, 255, 255, 0.05);
}
/* ============================================
Progress
============================================ */
.st-progress {
background: rgba(51, 65, 85, 0.5);
border-radius: 8px;
height: 8px;
overflow: hidden;
margin: 16px 0;
}
.st-progress-bar {
height: 100%;
background: linear-gradient(90deg, #0ff, #8b5cf6);
border-radius: 8px;
transition: width 0.3s ease;
box-shadow: 0 0 10px #0ff;
}
.st-progress-text {
text-align: center;
color: #0ff;
font-size: 13px;
margin-top: 8px;
}
/* ============================================
Apps Table
============================================ */
.st-apps-table {
width: 100%;
border-collapse: collapse;
}
.st-apps-table th,
.st-apps-table td {
padding: 12px;
text-align: left;
border-bottom: 1px solid rgba(0, 255, 255, 0.1);
}
.st-apps-table th {
color: #0ff;
font-weight: 600;
text-transform: uppercase;
font-size: 12px;
letter-spacing: 1px;
}
.st-apps-table td {
color: #f1f5f9;
}
.st-apps-table tr:hover td {
background: rgba(0, 255, 255, 0.05);
}
.st-app-active {
color: #0ff;
font-weight: 600;
}
.st-app-badge {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
font-size: 11px;
text-transform: uppercase;
}
.st-app-badge.active {
background: rgba(0, 255, 255, 0.2);
color: #0ff;
}
/* ============================================
Instances Table
============================================ */
.st-instances-table {
width: 100%;
border-collapse: collapse;
}
.st-instances-table th,
.st-instances-table td {
padding: 12px 16px;
text-align: left;
border-bottom: 1px solid rgba(0, 255, 255, 0.1);
}
.st-instances-table th {
color: #0ff;
font-weight: 600;
text-transform: uppercase;
font-size: 11px;
letter-spacing: 1px;
background: rgba(0, 255, 255, 0.05);
}
.st-instances-table td {
color: #f1f5f9;
font-size: 13px;
}
.st-instances-table tr:hover td {
background: rgba(0, 255, 255, 0.05);
}
.st-instances-table tr.st-row-active td {
background: rgba(0, 255, 255, 0.1);
border-left: 3px solid #0ff;
}
.st-instances-table .st-mono {
font-family: "Monaco", "Consolas", monospace;
color: #8b5cf6;
}
.st-instances-table a {
color: #0ff;
text-decoration: none;
}
.st-instances-table a:hover {
text-decoration: underline;
}
.st-app-desc {
font-size: 11px;
color: #64748b;
margin-top: 2px;
}
.st-status-dot {
display: inline-block;
}
.st-status-dot.st-running {
text-shadow: 0 0 8px #10b981;
}
.st-status-dot.st-stopped {
opacity: 0.7;
}
.st-no-padding {
padding: 0 !important;
}
.st-link {
color: #0ff;
text-decoration: none;
font-size: 13px;
}
.st-link:hover {
text-decoration: underline;
}
.st-btn-sm {
padding: 8px 16px;
font-size: 12px;
margin-top: 12px;
}
/* ============================================
Empty State
============================================ */
.st-empty {
text-align: center;
padding: 40px 20px;
color: #64748b;
}
.st-empty-icon {
font-size: 48px;
margin-bottom: 12px;
opacity: 0.5;
}
/* ============================================
Form Elements
============================================ */
.st-form-group {
margin-bottom: 16px;
}
.st-form-label {
display: block;
color: #0ff;
font-size: 13px;
margin-bottom: 6px;
text-transform: uppercase;
letter-spacing: 1px;
}
.st-form-input {
width: 100%;
padding: 10px 14px;
background: rgba(15, 23, 42, 0.8);
border: 1px solid rgba(0, 255, 255, 0.3);
border-radius: 8px;
color: #f1f5f9;
font-size: 14px;
}
.st-form-input:focus {
outline: none;
border-color: #0ff;
box-shadow: 0 0 10px rgba(0, 255, 255, 0.3);
}
.st-form-select {
width: 100%;
padding: 10px 14px;
background: rgba(15, 23, 42, 0.8);
border: 1px solid rgba(0, 255, 255, 0.3);
border-radius: 8px;
color: #f1f5f9;
font-size: 14px;
}
/* ============================================
Upload Area
============================================ */
.st-upload-area {
border: 2px dashed rgba(0, 255, 255, 0.3);
border-radius: 12px;
padding: 40px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.st-upload-area:hover {
border-color: #0ff;
background: rgba(0, 255, 255, 0.05);
}
.st-upload-area.dragover {
border-color: #0ff;
background: rgba(0, 255, 255, 0.1);
box-shadow: 0 0 20px rgba(0, 255, 255, 0.3);
}
.st-upload-icon {
font-size: 48px;
margin-bottom: 12px;
}
.st-upload-text {
color: #94a3b8;
}
/* ============================================
Animations
============================================ */
@keyframes pulse-glow {
0%, 100% {
box-shadow: 0 0 5px rgba(0, 255, 255, 0.5);
}
50% {
box-shadow: 0 0 20px rgba(0, 255, 255, 0.8);
}
}
.st-status-badge.running {
animation: pulse-glow 2s infinite;
}
@keyframes scanline {
0% {
transform: translateY(-100%);
}
100% {
transform: translateY(100vh);
}
}