*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } :root { --bg: #09090b; --surface: #111113; --card: #18181b; --elevated: #1f1f23; --border: #27272a; --border2: #3f3f46; --text: #fafafa; --text2: #a1a1aa; --text3: #71717a; --text4: #52525b; --cyan: #22d3ee; --cyan-dim: rgba(34,211,238,.12); --cyan-mid: rgba(34,211,238,.25); --green: #4ade80; --green-dim: rgba(74,222,128,.12); --amber: #fbbf24; --amber-dim: rgba(251,191,36,.12); --red: #f43f5e; --red-dim: rgba(244,63,94,.12); --red-mid: rgba(244,63,94,.25); --radius-sm: 6px; --radius: 10px; --radius-lg: 14px; --sidebar-w: 224px; --transition: 0.15s ease; --terminal-bg: #0d0d0f; } [data-theme="light"] { --bg: #f4f4f5; --surface: #ffffff; --card: #ffffff; --elevated: #f9f9fb; --border: #e4e4e7; --border2: #d4d4d8; --text: #18181b; --text2: #3f3f46; --text3: #71717a; --text4: #a1a1aa; --cyan: #0891b2; --cyan-dim: rgba(8,145,178,.10); --cyan-mid: rgba(8,145,178,.20); --green: #16a34a; --green-dim: rgba(22,163,74,.10); --amber: #d97706; --amber-dim: rgba(217,119,6,.10); --red: #e11d48; --red-dim: rgba(225,29,72,.10); --red-mid: rgba(225,29,72,.20); --terminal-bg: #1a1a1e; } /* Light theme: white checkmark on the darker cyan */ [data-theme="light"] input[type="checkbox"].vhost-row-cb:checked::after, [data-theme="light"] input[type="checkbox"].server-row-cb:checked::after, [data-theme="light"] input[type="checkbox"].svc-row-cb:checked::after, [data-theme="light"] input[type="checkbox"]#vhostSelectAll:checked::after, [data-theme="light"] input[type="checkbox"]#serverSelectAll:checked::after, [data-theme="light"] input[type="checkbox"]#svcSelectAll:checked::after, [data-theme="light"] input[type="checkbox"]#addVhostUseTls:checked::after, [data-theme="light"] input[type="checkbox"]#startServerSecure:checked::after, [data-theme="light"] input[type="checkbox"]#sshConnAutoReconnect:checked::after { border-color: #ffffff; } html, body { height: 100%; background: var(--bg); color: var(--text); font-family: 'Inter', system-ui, sans-serif; font-size: 14px; line-height: 1.5; -webkit-font-smoothing: antialiased; } /* ── Scrollbar ─────────────────────────────────── */ ::-webkit-scrollbar { width: 6px; height: 6px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 99px; } ::-webkit-scrollbar-thumb:hover { background: var(--text4); } /* ── Layout ────────────────────────────────────── */ .layout { display: flex; height: 100vh; overflow: hidden; } /* ── Sidebar ───────────────────────────────────── */ .sidebar { width: var(--sidebar-w); flex-shrink: 0; background: var(--surface); border-right: 1px solid var(--border); display: flex; flex-direction: column; overflow: hidden; } .sidebar-logo { padding: 20px 18px 16px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 10px; } .sidebar-logo-icon { width: 32px; height: 32px; border-radius: var(--radius-sm); overflow: hidden; flex-shrink: 0; display: flex; align-items: center; justify-content: center; } .sidebar-logo-icon img { width: 32px; height: 32px; display: block; } .sidebar-logo-text { line-height: 1.2; } .sidebar-logo-name { font-size: 15px; font-weight: 700; color: var(--text); letter-spacing: -0.02em; } .sidebar-logo-version { font-size: 11px; color: var(--text4); margin-top: 1px; } .sidebar-nav { flex: 1; padding: 8px 0; overflow-y: auto; } .nav-item { display: flex; align-items: center; gap: 10px; padding: 9px 14px; margin: 1px 8px; border-radius: var(--radius-sm); color: var(--text3); font-size: 13.5px; font-weight: 500; cursor: pointer; transition: background var(--transition), color var(--transition); user-select: none; } .nav-item:hover { background: var(--border); color: var(--text2); } .nav-item.active { background: var(--cyan-dim); color: var(--cyan); } .nav-item svg { width: 16px; height: 16px; flex-shrink: 0; } .nav-badge { margin-left: auto; font-size: 11px; font-weight: 600; padding: 1px 7px; border-radius: 99px; background: var(--elevated); color: var(--text3); min-width: 20px; text-align: center; } .nav-item.active .nav-badge { background: var(--cyan-mid); color: var(--cyan); } .sidebar-footer { padding: 12px 16px; border-top: 1px solid var(--border); } .status-pill { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--text3); } .status-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text4); flex-shrink: 0; } .status-dot.connected { background: var(--green); box-shadow: 0 0 6px var(--green); animation: pulse 2.5s infinite; } .status-dot.disconnected { background: var(--red); } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } /* ── Main ──────────────────────────────────────── */ .main { flex: 1; overflow-y: auto; display: flex; flex-direction: column; } /* Top bar */ .topbar { position: sticky; top: 0; z-index: 10; background: var(--bg); border-bottom: 1px solid var(--border); padding: 0 28px; height: 52px; display: flex; align-items: center; justify-content: space-between; gap: 12px; } .topbar-title { font-size: 15px; font-weight: 600; color: var(--text); } .topbar-actions { display: flex; align-items: center; gap: 8px; } .content { padding: 24px 28px; flex: 1; min-height: 0; display: flex; flex-direction: column; } /* ── Page visibility ───────────────────────────── */ .page { display: none; } .page.active { display: block; } /* Overview page fills the content area as a flex column so Quick Actions sticks to the bottom and the list cards share all remaining space. */ #page-dashboard.active { display: flex; flex-direction: column; flex: 1; min-height: 0; overflow: hidden; } /* ── Cards ─────────────────────────────────────── */ .card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 16px; } .card-header { padding: 14px 18px; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; gap: 12px; } .card-title { font-size: 13.5px; font-weight: 600; color: var(--text); } .card-subtitle { font-size: 12px; color: var(--text3); margin-top: 2px; } .card-body { padding: 16px 18px; } .card-body.flush { padding: 0; } /* ── Stats grid ────────────────────────────────── */ .stats-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 16px; } @media (max-width: 1100px) { .stats-grid { grid-template-columns: repeat(3, 1fr) !important; } } @media (max-width: 700px) { .stats-grid { grid-template-columns: repeat(2, 1fr) !important; } } .stat-card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 16px 18px; display: flex; flex-direction: column; gap: 8px; } .stat-icon { width: 32px; height: 32px; border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center; } .stat-icon svg { width: 16px; height: 16px; } .stat-icon.cyan { background: var(--cyan-dim); color: var(--cyan); } .stat-icon.green { background: var(--green-dim); color: var(--green); } .stat-icon.amber { background: var(--amber-dim); color: var(--amber); } .stat-icon.red { background: var(--red-dim); color: var(--red); } .stat-value { font-size: 26px; font-weight: 700; color: var(--text); letter-spacing: -0.03em; line-height: 1; } .stat-label { font-size: 11.5px; font-weight: 500; color: var(--text3); text-transform: uppercase; letter-spacing: 0.06em; } /* ── Buttons ───────────────────────────────────── */ .btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 7px 14px; border-radius: var(--radius-sm); font-size: 13px; font-weight: 500; font-family: inherit; cursor: pointer; border: none; transition: all var(--transition); white-space: nowrap; text-decoration: none; } .btn svg { width: 14px; height: 14px; flex-shrink: 0; } .btn:disabled { opacity: 0.45; cursor: not-allowed; pointer-events: none; } .btn-primary { background: var(--cyan); color: var(--bg); } .btn-primary:hover { background: color-mix(in srgb, var(--cyan) 85%, black); } .btn-secondary { background: var(--elevated); color: var(--text2); border: 1px solid var(--border); } .btn-secondary:hover { background: var(--border); color: var(--text); } .btn-ghost { background: transparent; color: var(--text3); } .btn-ghost:hover { background: var(--border); color: var(--text2); } .btn-danger { background: var(--red-dim); color: var(--red); border: 1px solid var(--red-mid); } .btn-danger:hover { background: var(--red-mid); } .btn-icon { padding: 6px; border-radius: var(--radius-sm); background: transparent; color: var(--text3); border: none; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; transition: all var(--transition); } .btn-icon:hover { background: var(--border); color: var(--text2); } .btn-icon svg { width: 14px; height: 14px; } .btn-sm { padding: 4px 10px; font-size: 12px; } .btn-sm svg { width: 12px; height: 12px; } .btn-xs { padding: 3px 8px; font-size: 11px; } /* ── Badges / Tags ─────────────────────────────── */ .badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 99px; font-size: 11.5px; font-weight: 500; } .badge-cyan { background: var(--cyan-dim); color: var(--cyan); } .badge-green { background: var(--green-dim); color: var(--green); } .badge-amber { background: var(--amber-dim); color: var(--amber); } .badge-red { background: var(--red-dim); color: var(--red); } .badge-neutral { background: var(--elevated); color: var(--text3); } /* ── Latency badges ─────────────────────────────── */ .latency-badge { transition: color 0.4s ease, opacity 0.3s ease; display: inline-block; min-width: 32px; text-align: right; } .latency-badge.pinging { opacity: 0.45; } /* ── Overview list cards ────────────────────────── */ .ov-list-card { display: flex; flex-direction: column; min-height: 0; /* Cards fill the grid cell height set by the flex grid rows */ height: 100%; } /* The scroll area grows to fill whatever height the card has after the header and search input. No max-height — the grid rows control height. */ .ov-scroll-area { flex: 1; overflow-y: auto; overflow-x: hidden; min-height: 0; } /* When the list is empty, disable scrolling and center the message */ .ov-scroll-area.ov-empty { overflow: hidden; display: flex; align-items: center; justify-content: center; } .ov-scroll-area.ov-empty table { width: 100%; height: 100%; } .ov-scroll-area.ov-empty .table .empty { padding: 0; } .ov-table thead th { position: sticky; top: 0; background: var(--card); z-index: 1; } .ov-sentinel { height: 1px; } /* ── Tables ────────────────────────────────────── */ .table { width: 100%; border-collapse: collapse; } .table th { padding: 10px 16px; text-align: left; font-size: 11px; font-weight: 600; color: var(--text4); text-transform: uppercase; letter-spacing: 0.07em; background: var(--elevated); border-bottom: 1px solid var(--border); } .table td { padding: 11px 16px; font-size: 13px; color: var(--text2); border-bottom: 1px solid var(--border); vertical-align: middle; } .table tbody tr:last-child td { border-bottom: none; } .table tbody tr:hover td { background: rgba(255,255,255,.025); } .table .mono { font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--cyan); } .table .empty { text-align: center; color: var(--text4); padding: 36px 16px; font-size: 13px; } /* ── Mono chip ─────────────────────────────────── */ .mono-chip { display: inline-flex; align-items: center; gap: 6px; font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--cyan); background: var(--cyan-dim); border: 1px solid rgba(34,211,238,.15); padding: 3px 8px; border-radius: var(--radius-sm); } /* ── Form inputs ───────────────────────────────── */ .input { background: var(--elevated); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text); font-family: inherit; font-size: 13px; padding: 8px 11px; outline: none; transition: border-color var(--transition); width: 100%; } .input:focus { border-color: var(--cyan); } .input::placeholder { color: var(--text4); } .input.mono { font-family: 'JetBrains Mono', monospace; font-size: 12px; } .form-group { display: flex; flex-direction: column; gap: 5px; } .form-label { font-size: 12px; font-weight: 500; color: var(--text3); } .form-error { font-size: 12px; color: var(--red); margin-top: 4px; display: none; } /* ── Toggle ────────────────────────────────────── */ .toggle { position: relative; width: 40px; height: 22px; background: var(--border2); border-radius: 99px; cursor: pointer; transition: background var(--transition); flex-shrink: 0; } .toggle.active { background: var(--cyan); } .toggle::after { content: ''; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; background: #fff; border-radius: 50%; transition: transform var(--transition); box-shadow: 0 1px 3px rgba(0,0,0,.3); } .toggle.active::after { transform: translateX(18px); } /* ── Settings rows ─────────────────────────────── */ .setting-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 13px 0; border-bottom: 1px solid var(--border); } .setting-row:last-child { border-bottom: none; } .setting-info { flex: 1; min-width: 0; } .setting-label { font-size: 13.5px; color: var(--text); font-weight: 500; } .setting-desc { font-size: 12px; color: var(--text3); margin-top: 2px; } .setting-control { flex-shrink: 0; } /* ── Section heading ───────────────────────────── */ .section-heading { font-size: 11px; font-weight: 600; color: var(--text4); text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 10px; margin-top: 20px; } .section-heading:first-child { margin-top: 0; } /* ── Logs ──────────────────────────────────────── */ .logs-toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; } .logs-filter { flex: 1; min-width: 180px; max-width: 280px; } .logs-container { background: #0a0a0c; border: 1px solid var(--border); border-radius: var(--radius); height: calc(100vh - 220px); overflow-y: auto; font-family: 'JetBrains Mono', monospace; font-size: 12px; } .log-entry { display: flex; gap: 12px; padding: 5px 14px; border-bottom: 1px solid rgba(255,255,255,.03); } .log-entry:hover { background: rgba(255,255,255,.025); } .log-time { color: var(--text4); flex-shrink: 0; font-size: 11px; padding-top: 1px; } .log-msg { color: var(--text2); word-break: break-all; line-height: 1.5; } .log-msg.is-error { color: var(--red); } .log-msg.is-warn { color: var(--amber); } .log-msg.is-info { color: var(--cyan); } /* ── Proxy/CA page ─────────────────────────────── */ .info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; } .info-item { background: var(--elevated); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px 16px; } .info-item-label { font-size: 11px; font-weight: 600; color: var(--text4); text-transform: uppercase; letter-spacing: 0.07em; margin-bottom: 6px; } .info-item-value { font-size: 20px; font-weight: 700; color: var(--text); font-family: 'JetBrains Mono', monospace; } /* ── Empty state ───────────────────────────────── */ .empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 48px 24px; color: var(--text4); text-align: center; } .empty-state svg { width: 36px; height: 36px; opacity: 0.4; } .empty-state-title { font-size: 14px; font-weight: 600; color: var(--text3); } .empty-state-desc { font-size: 13px; } .empty-state-btn { margin-top: 12px; } /* ── Modals ────────────────────────────────────── */ .modal-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.7); backdrop-filter: blur(4px); z-index: 100; display: flex; align-items: center; justify-content: center; opacity: 0; pointer-events: none; transition: opacity 0.2s ease; } .modal-backdrop.open { opacity: 1; pointer-events: all; } .modal { background: var(--card); border: 1px solid var(--border2); border-radius: var(--radius-lg); width: 100%; max-width: 440px; margin: 16px; box-shadow: 0 24px 64px rgba(0,0,0,.6); transform: translateY(12px) scale(0.98); transition: transform 0.2s ease; } .modal-backdrop.open .modal { transform: translateY(0) scale(1); } .modal-header { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; border-bottom: 1px solid var(--border); } .modal-title { font-size: 15px; font-weight: 600; color: var(--text); } .modal-body { padding: 20px; display: flex; flex-direction: column; gap: 14px; } .modal-desc { font-size: 13px; color: var(--text2); line-height: 1.6; } .modal-footer { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 14px 20px; border-top: 1px solid var(--border); } .modal-error { font-size: 12px; color: var(--red); display: none; } /* ── Confirm inline ────────────────────────────── */ .confirm-inline { display: none; align-items: center; gap: 6px; font-size: 12px; color: var(--text2); } .confirm-inline.show { display: inline-flex; } /* ── Toast ─────────────────────────────────────── */ .toast { position: fixed; bottom: 24px; right: 24px; background: var(--elevated); border: 1px solid var(--border2); border-radius: var(--radius); padding: 10px 16px; font-size: 13px; color: var(--text); box-shadow: 0 8px 24px rgba(0,0,0,.4); z-index: 200; transform: translateY(8px); opacity: 0; pointer-events: none; transition: all 0.2s ease; max-width: 320px; } .toast.show { opacity: 1; transform: translateY(0); } .toast.success { border-color: rgba(74,222,128,.3); color: var(--green); } .toast.error { border-color: var(--red-mid); color: var(--red); } /* ── Divider ───────────────────────────────────── */ .divider { height: 1px; background: var(--border); margin: 16px 0; } /* ── Copy feedback ─────────────────────────────── */ .copy-btn { position: relative; } .copy-tooltip { position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%); background: var(--elevated); border: 1px solid var(--border2); border-radius: 4px; padding: 3px 8px; font-size: 11px; color: var(--green); white-space: nowrap; pointer-events: none; opacity: 0; transition: opacity 0.15s; } .copy-btn.copied .copy-tooltip { opacity: 1; } /* ── Page headers ──────────────────────────────── */ /* ── Inline row layout ─────────────────────────── */ .row { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; } .row .form-group { flex: 1; min-width: 120px; } /* ── Checkbox ──────────────────────────────────── */ .checkbox-row { display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; } .checkbox-row label { font-size: 13px; color: var(--text2); cursor: pointer; } /* ── Table row checkboxes (bulk selection) and form checkboxes (same style) ──────── */ input[type="checkbox"].vhost-row-cb, input[type="checkbox"].server-row-cb, input[type="checkbox"].svc-row-cb, input[type="checkbox"]#vhostSelectAll, input[type="checkbox"]#serverSelectAll, input[type="checkbox"]#svcSelectAll, input[type="checkbox"]#addVhostUseTls, input[type="checkbox"]#startServerSecure, input[type="checkbox"]#sshConnAutoReconnect { appearance: none; -webkit-appearance: none; width: 15px; height: 15px; min-width: 15px; border: 1.5px solid var(--border2); border-radius: 4px; background: var(--elevated); cursor: pointer; position: relative; transition: border-color var(--transition), background var(--transition); vertical-align: middle; } input[type="checkbox"].vhost-row-cb:hover, input[type="checkbox"].server-row-cb:hover, input[type="checkbox"].svc-row-cb:hover, input[type="checkbox"]#vhostSelectAll:hover, input[type="checkbox"]#serverSelectAll:hover, input[type="checkbox"]#svcSelectAll:hover, input[type="checkbox"]#addVhostUseTls:hover, input[type="checkbox"]#startServerSecure:hover, input[type="checkbox"]#sshConnAutoReconnect:hover { border-color: var(--cyan); } input[type="checkbox"].vhost-row-cb:checked, input[type="checkbox"].server-row-cb:checked, input[type="checkbox"].svc-row-cb:checked, input[type="checkbox"]#vhostSelectAll:checked, input[type="checkbox"]#serverSelectAll:checked, input[type="checkbox"]#svcSelectAll:checked, input[type="checkbox"]#addVhostUseTls:checked, input[type="checkbox"]#startServerSecure:checked, input[type="checkbox"]#sshConnAutoReconnect:checked { background: var(--cyan); border-color: var(--cyan); } input[type="checkbox"].vhost-row-cb:checked::after, input[type="checkbox"].server-row-cb:checked::after, input[type="checkbox"].svc-row-cb:checked::after, input[type="checkbox"]#vhostSelectAll:checked::after, input[type="checkbox"]#serverSelectAll:checked::after, input[type="checkbox"]#svcSelectAll:checked::after, input[type="checkbox"]#addVhostUseTls:checked::after, input[type="checkbox"]#startServerSecure:checked::after, input[type="checkbox"]#sshConnAutoReconnect:checked::after { content: ''; position: absolute; left: 3px; top: 1px; width: 5px; height: 9px; border: 2px solid #09090b; border-top: none; border-left: none; transform: rotate(45deg); } /* ── Radio ──────────────────────────────────────── */ .radio-row { display: flex; align-items: center; gap: 6px; cursor: pointer; user-select: none; padding: 6px 12px; border: 1px solid var(--border); border-radius: 6px; font-size: 13px; color: var(--text2); transition: border-color 0.15s, background 0.15s; } .radio-row:has(input:checked) { border-color: var(--cyan); background: color-mix(in srgb, var(--cyan) 10%, transparent); color: var(--cyan); } .radio-row input[type="radio"] { accent-color: var(--cyan); cursor: pointer; } /* ── Remote Desktop page ────────────────────────── */ .rdp-conn-card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px 16px; display: flex; flex-direction: column; gap: 10px; transition: border-color var(--transition), background var(--transition); cursor: default; } .rdp-conn-card:hover { border-color: var(--border2); background: var(--elevated); } .rdp-conn-card-top { display: flex; align-items: center; gap: 12px; min-width: 0; } .rdp-conn-icon { width: 38px; height: 38px; border-radius: var(--radius-sm); background: var(--cyan-dim); display: flex; align-items: center; justify-content: center; flex-shrink: 0; color: var(--cyan); } .rdp-conn-icon svg { width: 18px; height: 18px; } .rdp-conn-info { flex: 1; min-width: 0; } .rdp-conn-label { font-size: 14px; font-weight: 600; color: var(--text); word-break: break-word; } .rdp-conn-actions { display: flex; gap: 6px; flex-shrink: 0; margin-left: auto; } .rdp-conn-meta { font-size: 11px; color: var(--text3); font-family: 'JetBrains Mono', monospace; word-break: break-all; line-height: 1.5; padding: 6px 8px; background: var(--base); border-radius: var(--radius-sm); border: 1px solid var(--border); } .rdp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 12px; } /* ── RDP Viewer modal ───────────────────────────── */ .modal-rdp-viewer { max-width: 95vw; width: 95vw; height: 90vh; padding: 0; display: flex; flex-direction: column; overflow: hidden; } .rdp-viewer-toolbar { display: flex; align-items: center; gap: 10px; padding: 10px 14px; background: var(--elevated); border-bottom: 1px solid var(--border); flex-shrink: 0; } .rdp-viewer-statusbar { display: flex; align-items: center; gap: 12px; padding: 6px 14px; background: var(--elevated); border-top: 1px solid var(--border); flex-shrink: 0; font-size: 11px; color: var(--text4); } .rdp-viewer-statusbar span { color: var(--text3); } #rdpViewerContainer { flex: 1; background: #000; overflow: hidden; position: relative; display: flex; align-items: center; justify-content: center; } #rdpViewerContainer canvas { max-width: 100%; max-height: 100%; display: block; } /* noVNC injects its own canvas — make it fill the container */ #rdpViewerContainer > :first-child { width: 100% !important; height: 100% !important; } /* ── SSH page ───────────────────────────────────── */ .ssh-conn-card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px 18px; display: flex; flex-direction: column; gap: 10px; transition: border-color var(--transition), background var(--transition); cursor: default; } .ssh-conn-card:hover { border-color: var(--border2); background: var(--elevated); } .ssh-conn-card-top { display: flex; align-items: center; gap: 14px; min-width: 0; } .ssh-conn-icon { width: 38px; height: 38px; border-radius: var(--radius-sm); background: var(--cyan-dim); border: 1px solid var(--cyan-mid); display: flex; align-items: center; justify-content: center; flex-shrink: 0; color: var(--cyan); } .ssh-conn-icon svg { width: 18px; height: 18px; } .ssh-conn-info { flex: 1; min-width: 0; } .ssh-conn-label { font-size: 14px; font-weight: 600; color: var(--text); word-break: break-word; } .ssh-conn-actions { display: flex; gap: 6px; flex-shrink: 0; margin-left: auto; } .ssh-conn-meta { font-size: 11px; color: var(--text3); font-family: 'JetBrains Mono', monospace; word-break: break-all; line-height: 1.5; padding: 6px 8px; background: var(--base); border-radius: var(--radius-sm); border: 1px solid var(--border); } .ssh-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 12px; } /* ── SSH Terminal modal ──────────────────────────── */ .modal-terminal { max-width: 95vw; width: 95vw; height: 90vh; margin: 0; display: flex; flex-direction: column; } .terminal-toolbar { display: flex; align-items: center; gap: 10px; padding: 10px 16px; border-bottom: 1px solid var(--border); flex-shrink: 0; background: var(--surface); border-radius: var(--radius-lg) var(--radius-lg) 0 0; } .terminal-conn-label { font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--cyan); background: var(--cyan-dim); border: 1px solid var(--cyan-mid); border-radius: var(--radius-sm); padding: 3px 10px; flex-shrink: 0; max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .terminal-status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--green); box-shadow: 0 0 6px var(--green); flex-shrink: 0; animation: pulse 2.5s infinite; } .terminal-status-dot.disconnected { background: var(--red); box-shadow: 0 0 6px var(--red); animation: none; } .terminal-spacer { flex: 1; } .terminal-statusbar { display: flex; align-items: center; gap: 12px; padding: 6px 16px; border-top: 1px solid var(--border); background: var(--surface); border-radius: 0 0 var(--radius-lg) var(--radius-lg); flex-shrink: 0; font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--text4); } .terminal-statusbar span { color: var(--text3); } #terminalContainer { flex: 1; background: var(--terminal-bg); overflow: hidden; padding: 8px; } /* Override xterm defaults to match our palette */ #terminalContainer .xterm { height: 100%; } #terminalContainer .xterm-viewport { background: transparent !important; } #terminalContainer .xterm-screen { background: transparent !important; } /* Respect user preference for reduced motion */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } }