Files
BetterDesk/web-nodejs/public/css/dashboard.css
T
UNITRONIX 9896799d4b fix(ui): warn on unreachable config QR hosts (#368)
Keys QR now uses the same Dashboard client-host override, and both modals warn when the payload embeds localhost/loopback/.local so phones are not misled after the encoding fix.

Refs #368

Thanks: INSOLVE (Honorary); Marco Jakobs (@jacotec); MyNameisStitch (@MyNameisStitch); Redspin (@playerumpknow)
2026-08-17 06:55:04 +02:00

1148 lines
24 KiB
CSS

/**
* BetterDesk Console - Dashboard Styles
*/
.dashboard-header {
margin-bottom: var(--space-lg);
}
.dashboard-header h1 {
font-size: var(--font-size-2xl);
font-weight: var(--font-weight-bold);
margin-bottom: var(--space-xs);
}
.dashboard-header p {
color: var(--text-secondary);
}
/* Stats cards grid */
.dashboard-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: var(--space-md);
margin-bottom: var(--space-xl);
}
.dashboard-layout {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(320px, 360px);
gap: var(--space-lg);
align-items: start;
}
.dashboard-primary {
min-width: 0;
}
.dashboard-side-panel {
position: sticky;
top: 0;
max-height: calc(100dvh - var(--navbar-height) - (var(--space-lg) * 2));
min-height: 0;
overflow-x: hidden;
overflow-y: auto;
overscroll-behavior: contain;
padding-right: 2px;
}
.dashboard-stat-card {
background: var(--bg-secondary);
border: 1px solid var(--border-primary);
border-radius: var(--radius-lg);
padding: var(--space-lg);
display: flex;
align-items: flex-start;
gap: var(--space-md);
transition: border-color var(--transition-fast), transform var(--transition-fast), box-shadow var(--transition-fast);
transform: translateY(0);
}
.dashboard-stat-card:hover {
border-color: var(--border-hover);
transform: translateY(-2px);
}
.dashboard-stat-icon {
width: 52px;
height: 52px;
border-radius: var(--radius-md);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.dashboard-stat-icon .material-icons {
font-size: 28px;
}
.dashboard-stat-icon.devices {
background: var(--accent-blue-muted);
color: var(--accent-blue);
}
.dashboard-stat-icon.online {
background: var(--accent-green-muted);
color: var(--accent-green);
}
.dashboard-stat-icon.banned {
background: var(--accent-red-muted);
color: var(--accent-red);
}
.dashboard-stat-icon.connections {
background: var(--accent-purple-muted);
color: var(--accent-purple);
}
.dashboard-stat-icon.offline {
background: var(--accent-orange-muted, rgba(255, 152, 0, 0.1));
color: var(--accent-orange, #ff9800);
}
.dashboard-stat-content {
flex: 1;
}
.dashboard-stat-value {
font-size: var(--font-size-3xl);
font-weight: var(--font-weight-bold);
line-height: 1;
margin-bottom: var(--space-xs);
}
.dashboard-stat-label {
font-size: var(--font-size-sm);
color: var(--text-secondary);
}
.dashboard-stat-change {
font-size: var(--font-size-xs);
margin-top: var(--space-xs);
display: flex;
align-items: center;
gap: var(--space-xs);
}
.dashboard-stat-change.positive {
color: var(--accent-green);
}
.dashboard-stat-change.negative {
color: var(--accent-red);
}
/* Server status */
.server-status-section {
margin-bottom: var(--space-xl);
}
.server-status-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: var(--space-md);
}
.server-status-card {
background: var(--bg-secondary);
border: 1px solid var(--border-primary);
border-radius: var(--radius-lg);
padding: var(--space-lg);
}
.server-status-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: var(--space-md);
}
.server-status-title {
display: flex;
align-items: center;
gap: var(--space-sm);
font-weight: var(--font-weight-semibold);
}
.server-status-title .material-icons {
font-size: 20px;
color: var(--accent-blue);
}
.server-status-indicator {
display: flex;
align-items: center;
gap: var(--space-xs);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-medium);
}
.server-status-indicator .status-dot {
width: 10px;
height: 10px;
border-radius: 50%;
}
.server-status-indicator.running {
color: var(--accent-green);
}
.server-status-indicator.running .status-dot {
background: var(--accent-green);
animation: pulse 2s infinite;
}
.server-status-indicator.stopped {
color: var(--accent-red);
}
.server-status-indicator.stopped .status-dot {
background: var(--accent-red);
}
.server-status-indicators.unknown {
color: var(--text-tertiary);
}
.server-status-details {
display: grid;
gap: var(--space-sm);
}
.server-detail-row {
display: flex;
justify-content: space-between;
font-size: var(--font-size-sm);
}
.server-detail-label {
color: var(--text-secondary);
}
.server-detail-value {
color: var(--text-primary);
font-family: var(--font-mono);
}
/* Recent activity */
.recent-activity-section {
margin-bottom: var(--space-xl);
}
.section-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: var(--space-md);
}
.section-title {
font-size: var(--font-size-lg);
font-weight: var(--font-weight-semibold);
display: flex;
align-items: center;
gap: var(--space-sm);
}
.section-title .material-icons {
color: var(--accent-blue);
}
.activity-list {
background: var(--bg-secondary);
border: 1px solid var(--border-primary);
border-radius: var(--radius-lg);
overflow: hidden;
}
.activity-item {
display: flex;
align-items: flex-start;
gap: var(--space-md);
padding: var(--space-md);
border-bottom: 1px solid var(--border-primary);
transition: background var(--transition-fast);
}
.activity-item:last-child {
border-bottom: none;
}
.activity-item:hover {
background: var(--bg-tertiary);
}
.activity-icon {
width: 36px;
height: 36px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.activity-icon.connect {
background: var(--accent-green-muted);
color: var(--accent-green);
}
.activity-icon.disconnect {
background: var(--bg-elevated);
color: var(--text-secondary);
}
.activity-icon.ban {
background: var(--accent-red-muted);
color: var(--accent-red);
}
.activity-icon.unban {
background: var(--accent-yellow-muted);
color: var(--accent-yellow);
}
.activity-icon .material-icons {
font-size: 18px;
}
.activity-content {
flex: 1;
min-width: 0;
}
.activity-text {
font-size: var(--font-size-sm);
}
.activity-text strong {
font-family: var(--font-mono);
color: var(--accent-blue);
}
.activity-time {
font-size: var(--font-size-xs);
color: var(--text-tertiary);
margin-top: var(--space-xs);
}
.activity-empty {
text-align: center;
padding: var(--space-xl);
color: var(--text-secondary);
}
/* Quick actions */
.quick-actions {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: var(--space-md);
}
.quick-action-card {
background: var(--bg-secondary);
border: 1px solid var(--border-primary);
border-radius: var(--radius-lg);
padding: var(--space-lg);
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
cursor: pointer;
transition: all var(--transition-fast);
}
.quick-action-card:hover {
border-color: var(--accent-blue);
background: var(--accent-blue-muted);
}
.quick-action-icon {
width: 48px;
height: 48px;
border-radius: 50%;
background: var(--bg-tertiary);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: var(--space-md);
transition: all var(--transition-fast);
}
.quick-action-card:hover .quick-action-icon {
background: var(--accent-blue);
color: white;
}
.quick-action-icon .material-icons {
font-size: 24px;
}
.quick-action-title {
font-weight: var(--font-weight-medium);
margin-bottom: var(--space-xs);
}
.quick-action-desc {
font-size: var(--font-size-xs);
color: var(--text-secondary);
}
/* Responsive */
@media (max-width: 768px) {
.dashboard-stats {
grid-template-columns: 1fr;
}
.server-status-grid {
grid-template-columns: 1fr;
}
.quick-actions {
grid-template-columns: repeat(2, 1fr);
}
.dashboard-bottom-grid {
grid-template-columns: 1fr;
}
.health-cards {
grid-template-columns: repeat(2, 1fr);
}
.welcome-greeting h1 {
font-size: var(--font-size-xl);
}
}
/* Welcome Section */
.dashboard-welcome {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: var(--space-lg);
margin-bottom: var(--space-lg);
}
.welcome-greeting h1 {
font-size: var(--font-size-2xl);
font-weight: var(--font-weight-bold);
margin-bottom: var(--space-xs);
}
.welcome-subtitle {
color: var(--text-secondary);
}
.welcome-tip {
display: flex;
align-items: center;
gap: var(--space-sm);
background: var(--accent-blue-muted);
border: 1px solid var(--accent-blue);
border-radius: var(--radius-md);
padding: var(--space-sm) var(--space-md);
font-size: var(--font-size-sm);
max-width: 380px;
flex-shrink: 0;
animation: tipSlideIn 0.4s ease;
}
@keyframes tipSlideIn {
from { opacity: 0; transform: translateX(12px); }
to { opacity: 1; transform: translateX(0); }
}
.tip-icon {
color: var(--accent-blue);
font-size: 20px;
flex-shrink: 0;
}
.tip-text {
flex: 1;
color: var(--text-primary);
line-height: 1.4;
}
.tip-dismiss {
background: none;
border: none;
cursor: pointer;
color: var(--text-secondary);
padding: 2px;
border-radius: var(--radius-sm);
display: flex;
align-items: center;
flex-shrink: 0;
transition: color var(--transition-fast);
}
.tip-dismiss:hover {
color: var(--text-primary);
}
.tip-dismiss .material-icons {
font-size: 16px;
}
/* Health Overview */
.dashboard-bottom-grid {
display: flex;
flex-direction: column;
gap: var(--space-lg);
margin-bottom: 0;
}
.health-cards {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-sm);
}
.health-card {
background: var(--bg-secondary);
border: 1px solid var(--border-primary);
border-radius: var(--radius-md);
padding: var(--space-md);
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
gap: var(--space-xs);
transition: border-color var(--transition-fast);
}
.health-card:hover {
border-color: var(--border-hover);
}
.health-card .material-icons {
font-size: 24px;
}
.health-card-value {
font-size: var(--font-size-xl);
font-weight: var(--font-weight-bold);
line-height: 1;
}
.health-card-label {
font-size: var(--font-size-xs);
color: var(--text-secondary);
}
.health-online .material-icons { color: var(--accent-green); }
.health-alerts .material-icons { color: var(--accent-yellow, #d29922); }
.health-connections .material-icons { color: var(--accent-blue); }
.health-uptime .material-icons { color: var(--accent-purple, #a371f7); }
/* Activity Feed */
.activity-feed-section .activity-list {
max-height: 360px;
overflow-y: auto;
}
@media (max-width: 1180px) {
.dashboard-layout {
grid-template-columns: 1fr;
}
.dashboard-side-panel {
position: static;
max-height: none;
overflow: visible;
padding-right: 0;
}
.dashboard-bottom-grid {
display: grid;
grid-template-columns: 340px 1fr;
}
}
@media (max-width: 768px) {
.dashboard-bottom-grid {
grid-template-columns: 1fr;
}
}
.activity-item .activity-icon {
width: 32px;
height: 32px;
}
.activity-item .activity-icon .material-icons {
font-size: 16px;
}
.activity-icon.login {
background: var(--accent-blue-muted);
color: var(--accent-blue);
}
.activity-icon.alert {
background: var(--accent-yellow-muted, rgba(210, 153, 34, 0.1));
color: var(--accent-yellow, #d29922);
}
.activity-icon.file {
background: var(--accent-purple-muted, rgba(163, 113, 247, 0.1));
color: var(--accent-purple, #a371f7);
}
/* Dashboard redesign */
.dashboard-shell {
display: flex;
flex-direction: column;
gap: var(--space-lg);
}
.dashboard-hero {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-lg);
padding: var(--space-lg);
background:
radial-gradient(circle at top left, rgba(88, 166, 255, 0.16), transparent 34rem),
var(--surface-glass-bg-secondary, var(--bg-secondary));
border: 1px solid var(--surface-glass-border, var(--border-primary));
border-radius: var(--radius-xl);
}
.dashboard-hero-copy h1 {
font-size: clamp(1.5rem, 2vw, 2.25rem);
line-height: var(--line-height-tight);
margin-bottom: var(--space-xs);
}
.dashboard-eyebrow {
display: inline-flex;
align-items: center;
gap: var(--space-xs);
margin-bottom: var(--space-xs);
color: var(--accent-blue);
font-size: var(--font-size-xs);
font-weight: var(--font-weight-bold);
letter-spacing: 0.08em;
text-transform: uppercase;
}
.dashboard-hero-actions {
display: flex;
align-items: center;
gap: var(--space-sm);
flex-wrap: wrap;
justify-content: flex-end;
}
.system-pill {
display: inline-flex;
align-items: center;
gap: var(--space-sm);
min-height: 40px;
padding: var(--space-sm) var(--space-md);
border-radius: var(--radius-full);
border: 1px solid var(--border-primary);
background: var(--bg-tertiary);
color: var(--text-secondary);
font-size: var(--font-size-sm);
font-weight: var(--font-weight-semibold);
}
.system-pill .status-dot {
width: 10px;
height: 10px;
border-radius: 50%;
background: var(--text-tertiary);
}
.system-pill.running {
border-color: rgba(46, 164, 79, 0.45);
color: var(--accent-green);
background: var(--accent-green-muted);
}
.system-pill.running .status-dot {
background: var(--accent-green);
}
.system-pill.stopped {
border-color: rgba(248, 81, 73, 0.45);
color: var(--accent-red);
background: var(--accent-red-muted);
}
.system-pill.stopped .status-dot {
background: var(--accent-red);
}
.system-pill.unknown {
border-color: rgba(210, 153, 34, 0.45);
color: var(--accent-yellow);
background: var(--accent-yellow-muted);
}
.system-pill.unknown .status-dot {
background: var(--accent-yellow);
}
.dashboard-tip {
display: flex;
align-items: center;
gap: var(--space-sm);
padding: var(--space-sm) var(--space-md);
background: var(--accent-blue-muted);
border: 1px solid rgba(88, 166, 255, 0.35);
border-radius: var(--radius-lg);
color: var(--text-primary);
}
.dashboard-tip .tip-icon {
color: var(--accent-blue);
}
.dashboard-tip .tip-text {
flex: 1;
color: var(--text-secondary);
font-size: var(--font-size-sm);
}
.dashboard-tip .tip-dismiss {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border: 1px solid transparent;
border-radius: var(--radius-md);
background: transparent;
color: var(--text-secondary);
cursor: pointer;
}
.dashboard-tip .tip-dismiss:hover,
.dashboard-tip .tip-dismiss:focus-visible {
color: var(--text-primary);
background: var(--bg-hover);
border-color: var(--border-primary);
}
.dashboard-layout {
grid-template-columns: minmax(0, 1fr) minmax(300px, 340px);
}
.dashboard-primary {
display: flex;
flex-direction: column;
gap: var(--space-lg);
}
.dashboard-stats {
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: var(--space-md);
margin-bottom: 0;
}
.dashboard-stat-card,
.server-status-card,
.quick-action-card,
.client-config-card,
.attention-section,
.activity-feed-section {
background: var(--surface-glass-bg-secondary, var(--bg-secondary));
border: 1px solid var(--surface-glass-border, var(--border-primary));
border-radius: var(--radius-xl);
box-shadow: var(--shadow-sm);
}
.dashboard-stat-card {
padding: var(--space-md);
align-items: center;
}
.dashboard-stat-icon {
width: 44px;
height: 44px;
}
.dashboard-stat-icon .material-icons {
font-size: 24px;
}
.dashboard-stat-value {
font-size: clamp(1.6rem, 2.6vw, 2.35rem);
}
.client-config-card {
padding: var(--space-lg);
border-color: rgba(88, 166, 255, 0.32);
background:
linear-gradient(135deg, rgba(88, 166, 255, 0.12), transparent 42%),
var(--surface-glass-bg-secondary, var(--bg-secondary));
}
.client-config-header,
.client-config-footer {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: var(--space-md);
}
.client-config-subtitle,
.client-config-footer p {
color: var(--text-secondary);
font-size: var(--font-size-sm);
}
.client-config-actions,
.client-config-links {
display: flex;
flex-wrap: wrap;
gap: var(--space-sm);
justify-content: flex-end;
}
.client-config-host-row {
margin-top: var(--space-md);
padding: var(--space-md);
border: 1px solid var(--border-primary);
border-radius: var(--radius-lg);
background: var(--bg-secondary);
}
.client-config-host-label {
display: block;
font-size: var(--font-size-sm);
font-weight: 600;
margin-bottom: var(--space-xs);
}
.client-config-host-controls {
display: flex;
flex-wrap: wrap;
gap: var(--space-sm);
align-items: center;
}
.client-config-host-input {
flex: 1 1 220px;
min-width: 0;
}
.client-config-host-hint {
margin: var(--space-sm) 0 0;
color: var(--text-secondary);
font-size: var(--font-size-sm);
}
.client-config-script-modal p {
color: var(--text-secondary);
font-size: var(--font-size-sm);
margin-bottom: var(--space-md);
}
.client-config-script-block {
max-height: 360px;
overflow: auto;
padding: var(--space-md);
border-radius: var(--radius-md);
background: var(--bg-tertiary);
border: 1px solid var(--border-primary);
font-size: 12px;
line-height: 1.45;
white-space: pre-wrap;
word-break: break-word;
}
.client-config-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: var(--space-md);
margin: var(--space-lg) 0;
}
.client-config-field {
position: relative;
min-width: 0;
padding: var(--space-md) calc(var(--space-lg) + 28px) var(--space-md) var(--space-md);
background: var(--bg-tertiary);
border: 1px solid var(--border-primary);
border-radius: var(--radius-lg);
}
.client-config-field-wide {
grid-column: 1 / -1;
padding-right: calc(var(--space-lg) + 68px);
}
.client-config-label {
display: block;
margin-bottom: var(--space-xs);
color: var(--text-secondary);
font-size: var(--font-size-xs);
font-weight: var(--font-weight-semibold);
text-transform: uppercase;
letter-spacing: 0.04em;
}
.client-config-value {
display: block;
min-height: 1.4rem;
color: var(--text-primary);
font-family: var(--font-mono);
font-size: var(--font-size-sm);
line-height: 1.45;
overflow-wrap: anywhere;
}
.client-config-value.is-masked {
letter-spacing: 0.2em;
color: var(--text-secondary);
}
.client-config-reveal,
.client-config-copy {
position: absolute;
top: var(--space-md);
right: var(--space-md);
display: inline-flex;
align-items: center;
justify-content: center;
width: 34px;
height: 34px;
border: 1px solid var(--border-primary);
border-radius: var(--radius-md);
background: var(--bg-elevated, var(--bg-secondary));
color: var(--text-secondary);
cursor: pointer;
transition: color var(--transition-fast), border-color var(--transition-fast), background var(--transition-fast);
}
.client-config-reveal {
right: calc(var(--space-md) + 40px);
}
.client-config-reveal .material-icons,
.client-config-copy .material-icons {
font-size: 18px;
}
.client-config-reveal:hover,
.client-config-reveal:focus-visible {
color: var(--accent-blue);
border-color: var(--accent-blue);
background: var(--accent-blue-muted);
}
.client-config-copy:hover,
.client-config-copy:focus-visible,
.client-config-copy.copied,
#copy-client-config-btn.copied {
color: var(--accent-green);
border-color: var(--accent-green);
background: var(--accent-green-muted);
}
.server-status-section,
.quick-actions-section {
margin-bottom: 0;
}
.server-status-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.server-status-card {
padding: var(--space-md);
}
.server-status-header {
gap: var(--space-sm);
}
.server-status-details {
padding-top: var(--space-xs);
}
.server-detail-row {
gap: var(--space-sm);
}
.quick-actions {
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: var(--space-md);
}
.quick-action-card {
min-height: 128px;
padding: var(--space-md);
}
.quick-action-card:focus-visible,
.btn:focus-visible,
.client-config-reveal:focus-visible,
.client-config-copy:focus-visible {
outline: 3px solid var(--sidebar-focus-ring, rgba(121, 192, 255, 0.55));
outline-offset: 2px;
}
.dashboard-side-panel {
display: flex;
flex-direction: column;
gap: var(--space-lg);
}
.attention-section,
.activity-feed-section {
padding: var(--space-md);
}
.attention-list {
display: grid;
gap: var(--space-sm);
}
.attention-item {
display: flex;
align-items: center;
gap: var(--space-sm);
padding: var(--space-sm);
border: 1px solid var(--border-primary);
border-radius: var(--radius-lg);
background: var(--bg-tertiary);
}
.attention-item .material-icons {
font-size: 22px;
}
.attention-item strong {
display: block;
font-size: var(--font-size-xl);
line-height: 1.1;
}
.attention-item span:last-child {
color: var(--text-secondary);
font-size: var(--font-size-xs);
}
.attention-online .material-icons { color: var(--accent-green); }
.attention-alerts .material-icons { color: var(--accent-yellow); }
.attention-connections .material-icons { color: var(--accent-blue); }
.attention-uptime .material-icons { color: var(--accent-purple); }
.client-config-qr-modal {
text-align: center;
}
.client-config-qr-frame {
display: inline-block;
padding: var(--space-md);
margin-bottom: var(--space-md);
background: #fff;
border-radius: var(--radius-lg);
}
.client-config-qr-frame img {
width: 300px;
height: 300px;
}
.client-config-qr-modal p {
color: var(--text-secondary);
}
.client-config-qr-modal p.client-config-qr-warn {
margin-top: var(--space-sm);
color: var(--accent-yellow, #b45309);
font-weight: 500;
}
@media (max-width: 1280px) {
.dashboard-stats,
.quick-actions {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.server-status-grid {
grid-template-columns: 1fr;
}
.client-config-grid {
grid-template-columns: 1fr;
}
}
@media (max-width: 1180px) {
.dashboard-layout {
grid-template-columns: 1fr;
}
.dashboard-side-panel {
position: static;
max-height: none;
overflow: visible;
padding-right: 0;
}
.attention-list {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
}
@media (max-width: 820px) {
.dashboard-hero,
.client-config-header,
.client-config-footer {
align-items: stretch;
flex-direction: column;
}
.dashboard-hero-actions,
.client-config-actions,
.client-config-links {
justify-content: flex-start;
}
.dashboard-stats,
.quick-actions,
.attention-list {
grid-template-columns: 1fr;
}
}
@media (max-width: 560px) {
.dashboard-hero,
.client-config-card,
.attention-section,
.activity-feed-section {
padding: var(--space-md);
}
.client-config-field {
padding-right: var(--space-md);
}
.client-config-field-wide {
padding-right: var(--space-md);
}
.client-config-reveal,
.client-config-copy {
position: static;
margin-top: var(--space-sm);
}
.client-config-field-wide .client-config-reveal,
.client-config-field-wide .client-config-copy {
display: inline-flex;
margin-right: var(--space-xs);
}
}