* { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; background: #0f172a; color: #e2e8f0; min-height: 100vh; } header { background: #1e293b; border-bottom: 1px solid #334155; padding: 20px 32px; display: flex; align-items: baseline; gap: 16px; } header h1 { font-size: 1.5rem; font-weight: 600; color: #f1f5f9; } .subtitle { font-size: 0.8rem; color: #64748b; } .refresh-btn { margin-left: auto; background: #334155; color: #94a3b8; border: 1px solid #475569; border-radius: 6px; padding: 4px 12px; font-size: 0.8rem; cursor: pointer; transition: all 0.2s; } .refresh-btn:hover { background: #3b82f6; color: #fff; border-color: #3b82f6; } .refresh-btn:disabled { opacity: 0.5; cursor: not-allowed; } .refresh-btn-sm { margin-left: auto; background: none; color: #475569; border: none; font-size: 0.85rem; cursor: pointer; padding: 0 4px; transition: color 0.2s; flex-shrink: 0; } .refresh-btn-sm:hover { color: #3b82f6; } .refresh-btn-sm:disabled { opacity: 0.4; cursor: not-allowed; } main { max-width: 1400px; margin: 0 auto; padding: 24px; } /* --- Group --- */ .group { margin-bottom: 32px; } .group-header { font-size: 1.1rem; font-weight: 600; color: #3b82f6; padding: 8px 0 12px 0; border-bottom: 2px solid #1e3a5f; margin-bottom: 16px; text-transform: uppercase; letter-spacing: 0.05em; } .server-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; } /* --- Server Card --- */ .server-card { background: #1e293b; border: 1px solid #334155; border-radius: 10px; padding: 16px; cursor: pointer; transition: all 0.2s ease; position: relative; } .server-card:hover { border-color: #475569; transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); } .server-card.expanded { grid-column: 1 / -1; border-color: #3b82f6; box-shadow: 0 0 20px rgba(59, 130, 246, 0.15); } .server-card.expanded .ct-summary-list { display: none; } .server-card.offline .card-summary { opacity: 0.6; } .card-header { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; } .status-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; } .status-dot.online { background: #22c55e; box-shadow: 0 0 6px rgba(34, 197, 94, 0.5); } .status-dot.offline { background: #ef4444; box-shadow: 0 0 6px rgba(239, 68, 68, 0.5); } .server-name { font-weight: 600; font-size: 0.95rem; color: #f1f5f9; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .server-link { color: #3b82f6; text-decoration: none; font-size: 0.9rem; flex-shrink: 0; opacity: 0.7; transition: opacity 0.2s; } .server-link:hover { opacity: 1; } .server-ip { font-size: 0.8rem; color: #94a3b8; margin-bottom: 2px; font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; } .server-os { font-size: 0.75rem; color: #64748b; margin-bottom: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* --- Service Links (summary card) --- */ .service-links { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; } .service-link { font-size: 0.65rem; color: #3b82f6; background: #1e3a5f; padding: 1px 6px; border-radius: 3px; text-decoration: none; transition: background 0.2s; } .service-link:hover { background: #2563eb; color: #fff; } .server-hw { font-size: 0.7rem; color: #475569; margin-bottom: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .offline-label { font-size: 0.8rem; color: #ef4444; font-style: italic; margin-top: 8px; } /* --- Usage Bars --- */ .usage-bars { display: flex; flex-direction: column; gap: 5px; } .usage-row { display: flex; align-items: center; gap: 6px; } .usage-label { font-size: 0.65rem; font-weight: 600; color: #64748b; width: 30px; text-transform: uppercase; letter-spacing: 0.05em; } .usage-bar-bg { flex: 1; height: 6px; background: #334155; border-radius: 3px; overflow: hidden; } .usage-bar-fill { height: 100%; border-radius: 3px; transition: width 0.5s ease; min-width: 2px; } .usage-pct { font-size: 0.7rem; color: #94a3b8; width: 30px; text-align: right; font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; } /* --- Card Details --- */ .card-details { margin-top: 16px; padding-top: 16px; border-top: 1px solid #334155; } .details-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; } .detail-section { background: #0f172a; border-radius: 8px; padding: 12px; border: 1px solid #1e3a5f; } .detail-section.wide { grid-column: 1 / -1; } .detail-section h4 { font-size: 0.75rem; font-weight: 600; color: #3b82f6; text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 8px; } .detail-section table { width: 100%; border-collapse: collapse; font-size: 0.8rem; } .detail-section td { padding: 3px 8px 3px 0; vertical-align: top; } .detail-section td:first-child { color: #64748b; white-space: nowrap; width: 1%; } .detail-section td:last-child { color: #cbd5e1; word-break: break-all; } .table-header td { font-weight: 600; color: #94a3b8 !important; border-bottom: 1px solid #334155; padding-bottom: 4px; margin-bottom: 4px; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; } .disk-pct { font-weight: 600; font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; } .error-text { color: #ef4444; font-size: 0.8rem; font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; } .last-updated { margin-top: 12px; font-size: 0.7rem; color: #475569; text-align: right; } /* --- Notes --- */ .notes-section { margin-bottom: 12px; } .notes-input { width: 100%; min-height: 32px; background: #0f172a; border: 1px solid #1e3a5f; border-radius: 6px; color: #cbd5e1; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; font-size: 0.8rem; padding: 8px 10px; resize: none; overflow: hidden; line-height: 1.4; } .notes-input:focus { outline: none; border-color: #3b82f6; } .notes-input::placeholder { color: #475569; } /* --- Links Editor (details) --- */ .links-section { margin-bottom: 12px; } .links-section h4 { font-size: 0.75rem; font-weight: 600; color: #3b82f6; text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 6px; } .links-list { display: flex; flex-direction: column; gap: 4px; } .link-row { display: flex; gap: 6px; align-items: center; } .link-label { width: 120px; background: #0f172a; border: 1px solid #1e3a5f; border-radius: 4px; color: #cbd5e1; font-size: 0.8rem; padding: 4px 8px; } .link-url { flex: 1; background: #0f172a; border: 1px solid #1e3a5f; border-radius: 4px; color: #cbd5e1; font-size: 0.8rem; padding: 4px 8px; } .link-label:focus, .link-url:focus { outline: none; border-color: #3b82f6; } .link-remove { background: none; border: none; color: #64748b; font-size: 1rem; cursor: pointer; padding: 2px 6px; } .link-remove:hover { color: #ef4444; } .link-add-btn { margin-top: 6px; background: none; border: 1px dashed #334155; border-radius: 4px; color: #64748b; font-size: 0.75rem; padding: 4px 10px; cursor: pointer; transition: all 0.2s; } .link-add-btn:hover { border-color: #3b82f6; color: #3b82f6; } /* --- Container Summary (on card face) --- */ .ct-summary-list { margin-top: 10px; padding-top: 8px; border-top: 1px solid #334155; display: flex; flex-direction: column; gap: 3px; } .ct-summary-item { display: flex; align-items: center; gap: 6px; font-size: 0.7rem; color: #94a3b8; overflow: hidden; } .status-dot-sm { width: 5px; height: 5px; border-radius: 50%; flex-shrink: 0; } .status-dot-sm.online { background: #22c55e; } .status-dot-sm.offline { background: #ef4444; } .ct-summary-name { font-weight: 600; color: #cbd5e1; white-space: nowrap; } .ct-summary-os { color: #64748b; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .ct-summary-type { font-size: 0.55rem; font-weight: 600; color: #64748b; background: #334155; padding: 0 4px; border-radius: 2px; letter-spacing: 0.05em; flex-shrink: 0; } .ct-summary-ip { color: #64748b; font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; font-size: 0.65rem; white-space: nowrap; margin-left: auto; flex-shrink: 0; } .ct-summary-item.nested { padding-left: 14px; opacity: 0.8; } .vm-containers { margin-top: 6px; padding-top: 4px; border-top: 1px dashed #334155; display: flex; flex-direction: column; gap: 2px; } /* --- Container / VM Sub-cards --- */ .container-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 8px; } .container-card { background: #1e293b; border: 1px solid #334155; border-radius: 8px; padding: 10px; } .container-card.offline { opacity: 0.6; } .ct-header { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; } .ct-name { font-weight: 600; font-size: 0.85rem; color: #f1f5f9; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; } .ct-type { font-size: 0.6rem; font-weight: 600; color: #64748b; background: #334155; padding: 1px 5px; border-radius: 3px; letter-spacing: 0.05em; flex-shrink: 0; } .ct-details { display: flex; gap: 10px; font-size: 0.75rem; color: #94a3b8; margin-bottom: 6px; } .ct-ip { font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; } .ct-image { font-size: 0.7rem; color: #475569; margin-bottom: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .ct-status-label { color: #64748b; font-style: italic; } /* --- Log Modal --- */ .log-modal { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.6); display: flex; align-items: center; justify-content: center; z-index: 1000; backdrop-filter: blur(2px); } .log-modal-content { background: #1e293b; border: 1px solid #334155; border-radius: 12px; width: 500px; max-width: 90vw; max-height: 60vh; display: flex; flex-direction: column; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5); } .log-modal-header { display: flex; align-items: center; gap: 10px; padding: 14px 18px; border-bottom: 1px solid #334155; font-weight: 600; font-size: 0.9rem; color: #f1f5f9; } .log-modal-body { padding: 12px 18px; overflow-y: auto; flex: 1; font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; font-size: 0.75rem; line-height: 1.6; } .log-line { color: #94a3b8; } .log-line.log-ok { color: #22c55e; } .log-line.log-err { color: #ef4444; } .spinner { width: 14px; height: 14px; border: 2px solid #334155; border-top-color: #3b82f6; border-radius: 50%; animation: spin 0.8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* --- Empty State --- */ .empty-state { text-align: center; padding: 80px 24px; color: #64748b; } .empty-state h2 { font-size: 1.2rem; margin-bottom: 8px; color: #94a3b8; } .empty-state code { background: #1e293b; padding: 2px 8px; border-radius: 4px; font-size: 0.85rem; color: #3b82f6; } /* --- Responsive --- */ @media (max-width: 600px) { header { padding: 16px; } main { padding: 12px; } .server-grid { grid-template-columns: 1fr; } .details-grid { grid-template-columns: 1fr; } }