/* ============================================================ rustguac — shared operator-console stylesheet - 8px baseline grid for chrome controls (px units). - Body copy 18px, control heights 38/44/54px. - CSS variable theming is driven by the theme picker; only the palette tokens here are intended to be overridden. ============================================================ */ :root { /* theme palette */ --primary: #e94560; --primary-hover: #c73652; --accent: #5bc0be; --accent-hover: #4aa3a1; --bg: #1a1a2e; --surface: #16213e; --input: #0f3460; --text: #e0e0e0; --text-muted: #aaa; --border: #333; --text-dim: #666; --text-on-primary: #fff; --btn-disabled: #555; --status-pending: #f0c040; --status-active: #5bc0be; --status-completed: #888; --status-error: #e94560; --status-expired: #666; --type-ssh-bg: #1b4332; --type-ssh-fg: #52b788; --type-rdp-bg: #3d1f00; --type-rdp-fg: #f0a050; --type-vnc-bg: #2d1b4e; --type-vnc-fg: #b07ff0; --type-web-bg: #1a1a4e; --type-web-fg: #7b8ff0; --type-vdi-bg: #0e2a2a; --type-vdi-fg: #2dd4bf; --hop-bg: #1b4332; --hop-fg: #52b788; --bg-pattern: none; /* spacing (4px unit) */ --s-1: 4px; --s-2: 8px; --s-3: 14px; --s-4: 20px; --s-5: 28px; --s-6: 40px; /* geometry */ --radius: 2px; /* control heights */ --ctl-sm: 38px; --ctl-md: 44px; --ctl-lg: 54px; /* type scale — fz-md == body */ --fz-xs: 14px; --fz-sm: 16px; --fz-md: 18px; --fz-lg: 20px; --fz-xl: 24px; } /* ── Reset / base ─────────────────────────────── */ body { font-family: monospace; background-color: var(--bg); background-image: var(--bg-pattern); background-attachment: fixed; min-height: 100vh; color: var(--text); padding: var(--s-5) var(--s-6); font-size: 18px; line-height: 1.55; margin: 0; } h1 { color: var(--primary); margin: 0; font-size: 30px; letter-spacing: 0.02em; font-weight: bold; } h2 { color: var(--primary); font-size: var(--fz-lg); margin-top: var(--s-5); letter-spacing: 0.02em; } h3 { color: var(--text); font-size: var(--fz-md); margin-top: var(--s-4); letter-spacing: 0.02em; } a { color: var(--accent); } code { background: var(--surface); padding: 2px var(--s-1); border-radius: var(--radius); font-size: 0.9em; } .brand-row { display: flex; align-items: center; gap: var(--s-3); } .brand-row #site-logo { height: 36px; width: auto; display: block; } /* ── Navigation ─────────────────────────────── */ nav { margin-top: var(--s-4); margin-bottom: var(--s-5); padding-bottom: var(--s-3); border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: var(--s-5); font-size: var(--fz-md); } nav a { text-decoration: none; color: var(--text-muted); padding: var(--s-1) 0; margin: 0; position: relative; line-height: 1.4; } nav a:hover { color: var(--text); text-decoration: none; } nav a.active { color: var(--primary); font-weight: bold; } nav a.active::after { content: ''; position: absolute; left: 0; right: 0; bottom: calc(var(--s-3) * -1 - 1px); height: 2px; background: var(--primary); } #user-menu-wrapper { margin-left: auto; display: inline-flex; align-items: center; gap: var(--s-3); position: relative; float: none; } #logout-item { color: var(--text-muted); font-size: var(--fz-md); text-decoration: none; padding: var(--s-1) 0; line-height: 1.4; margin: 0; } #logout-item:hover { color: var(--primary); } #user-menu-btn { cursor: pointer; color: var(--text-muted); font-size: var(--fz-md); display: inline-flex; align-items: center; gap: var(--s-1); padding: 0 var(--s-2); height: var(--ctl-sm); border: 1px solid var(--border); border-radius: var(--radius); line-height: 1; box-sizing: border-box; transition: color .12s, border-color .12s; } #user-menu-btn:hover { color: var(--text); border-color: var(--text-muted); } #user-menu { display: none; position: absolute; right: 0; top: calc(var(--ctl-sm) + var(--s-2)); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); min-width: 260px; z-index: 50; padding: var(--s-1) 0; box-shadow: 0 8px 24px rgba(0,0,0,0.4); } .um-section-label { padding: var(--s-2) var(--s-3) var(--s-1); font-size: var(--fz-xs); color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.1em; } .um-item { padding: var(--s-2) var(--s-3); cursor: pointer; display: flex; align-items: center; gap: var(--s-2); font-size: var(--fz-sm); color: var(--text); } .um-item:hover { background: var(--input); } .um-item.active { color: var(--accent); } .um-theme-info { display: flex; flex-direction: column; } .um-theme-name { font-weight: bold; } .um-theme-desc { font-size: var(--fz-xs); color: var(--text-dim); } .um-swatch { display: inline-block; width: 14px; height: 14px; border-radius: 50%; border: 1px solid var(--border); flex-shrink: 0; } .um-divider { height: 1px; background: var(--border); margin: var(--s-1) 0; } .um-logout { color: var(--text-muted); } .um-logout:hover { color: var(--primary); background: var(--input); } /* ── Buttons (unified ladder) ─────────────────────────────── */ button { display: inline-flex; align-items: center; justify-content: center; gap: var(--s-1); height: var(--ctl-md); padding: 0 var(--s-3); background: var(--primary); color: var(--text-on-primary); border: 1px solid var(--primary); border-radius: var(--radius); font-family: monospace; font-size: var(--fz-md); font-weight: bold; line-height: 1; cursor: pointer; white-space: nowrap; transition: background .12s, border-color .12s, color .12s; box-sizing: border-box; } button:hover { background: var(--primary-hover); border-color: var(--primary-hover); } button:disabled { background: var(--btn-disabled); border-color: var(--btn-disabled); color: var(--text-dim); cursor: default; } button.btn-primary { background: var(--primary); border-color: var(--primary); color: var(--text-on-primary); } .btn-connect { background: var(--accent); border-color: var(--accent); color: var(--bg); height: var(--ctl-sm); padding: 0 var(--s-4); font-size: var(--fz-sm); min-width: 130px; } .btn-connect:hover { background: var(--accent-hover); border-color: var(--accent-hover); } .btn-add { background: transparent; color: var(--text); border: 1px solid var(--border); font-weight: normal; height: var(--ctl-sm); padding: 0 var(--s-3); font-size: var(--fz-sm); } .btn-add:hover { background: var(--surface); border-color: var(--accent); color: var(--accent); } .btn-small { background: transparent; border: 1px solid transparent; color: var(--text-muted); font-weight: normal; height: var(--ctl-sm); padding: 0 var(--s-2); font-size: var(--fz-sm); font-family: monospace; cursor: pointer; border-radius: var(--radius); } .btn-small:hover { color: var(--primary); background: transparent; border-color: var(--border); text-decoration: none; } .btn-action { color: var(--accent); } .btn-action:hover { color: var(--accent-hover); } /* ── Form controls (base) ─────────────────────────────── */ input[type="text"], input[type="password"], input[type="email"], input[type="number"], input[type="date"], input[type="search"], select, textarea { background: var(--input); border: 1px solid var(--border); color: var(--text); font-family: monospace; font-size: var(--fz-md); padding: 0 var(--s-2); height: var(--ctl-md); border-radius: var(--radius); box-sizing: border-box; line-height: 1; } textarea { height: auto; padding: var(--s-2); line-height: 1.5; } input:focus, select:focus, textarea:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 2px rgba(233, 69, 96, 0.18); } label { display: block; margin-top: var(--s-3); color: var(--text-muted); font-size: var(--fz-xs); text-transform: uppercase; letter-spacing: 0.08em; } /* ── Generic tables ─────────────────────────────── */ table { border-collapse: collapse; width: 100%; margin-top: var(--s-3); border: 1px solid var(--border); } th, td { text-align: left; padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--border); font-size: var(--fz-md); vertical-align: middle; } th { color: var(--text-muted); font-size: var(--fz-sm); font-weight: normal; text-transform: uppercase; letter-spacing: 0.12em; background: var(--surface); line-height: 1.6; } tbody tr:nth-child(even) { background: rgba(255,255,255,0.02); } tbody tr:hover { background: var(--surface); } tbody tr:last-child td { border-bottom: none; } /* ── Status colors (session/token lifecycle) ─────────────── */ .status-pending { color: var(--status-pending); } .status-active { color: var(--status-active); } .status-completed { color: var(--status-completed); } .status-error { color: var(--status-error); } .status-expired { color: var(--status-expired); } .status-disabled { color: var(--primary); } /* ── Session type badges ─────────────────────────────── */ .type-badge { display: inline-block; padding: 3px var(--s-2); border-radius: var(--radius); font-size: var(--fz-sm); font-weight: bold; letter-spacing: 0.12em; text-transform: uppercase; min-width: 52px; text-align: center; line-height: 1.5; } .type-ssh { background: var(--type-ssh-bg); color: var(--type-ssh-fg); } .type-rdp { background: var(--type-rdp-bg); color: var(--type-rdp-fg); } .type-vnc { background: var(--type-vnc-bg); color: var(--type-vnc-fg); } .type-web { background: var(--type-web-bg); color: var(--type-web-fg); } .type-vdi { background: var(--type-vdi-bg); color: var(--type-vdi-fg); } /* ── Section heading strip (used above grids/lists) ──────── */ .section-head { display: flex; align-items: baseline; gap: var(--s-2); margin-bottom: var(--s-3); padding-bottom: var(--s-2); border-bottom: 1px solid var(--border); } .section-head strong { color: var(--accent); font-size: var(--fz-sm); text-transform: uppercase; letter-spacing: 0.14em; font-weight: bold; } .section-count { color: var(--text-muted); font-size: var(--fz-sm); font-weight: normal; letter-spacing: 0.04em; } /* ── Empty / error messages ─────────────────────────────── */ .empty { color: var(--text-dim); margin: var(--s-5) 0; font-size: var(--fz-md); } #global-error, #error { color: var(--primary); margin-top: var(--s-2); white-space: pre-wrap; font-size: var(--fz-md); } .no-vault { color: var(--text-muted); margin: var(--s-5) 0; } .empty-state { border: 1px dashed var(--border); border-radius: var(--radius); padding: var(--s-6) var(--s-5); text-align: center; margin: var(--s-5) 0; } .empty-state h3 { color: var(--accent); margin: 0 0 var(--s-2); text-transform: uppercase; letter-spacing: 0.08em; font-size: var(--fz-lg); } .empty-state p { color: var(--text-muted); margin: 0 0 var(--s-4); } .empty-state button { height: var(--ctl-lg); padding: 0 var(--s-4); font-size: var(--fz-md); } /* ── Modal ─────────────────────────────── */ .modal-overlay { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.75); z-index: 100; justify-content: center; align-items: center; backdrop-filter: blur(2px); } .modal-overlay.active { display: flex; } .modal { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--s-5); min-width: 440px; max-width: 600px; max-height: 85vh; overflow-y: auto; box-shadow: 0 16px 48px rgba(0,0,0,0.55); } .modal h3 { color: var(--primary); margin: 0 0 var(--s-3); padding-bottom: var(--s-2); border-bottom: 1px solid var(--border); font-size: var(--fz-lg); text-transform: uppercase; letter-spacing: 0.08em; } .modal label { display: block; margin-top: var(--s-3); color: var(--text-muted); font-size: var(--fz-xs); text-transform: uppercase; letter-spacing: 0.08em; } .modal input, .modal select, .modal textarea { display: block; width: 100%; margin-top: var(--s-1); background: var(--input); border: 1px solid var(--border); color: var(--text); font-family: monospace; font-size: var(--fz-md); padding: 0 var(--s-2); height: var(--ctl-md); border-radius: var(--radius); box-sizing: border-box; text-transform: none; letter-spacing: 0; } .modal textarea { height: auto; padding: var(--s-2); } /* Checkboxes / radios live inside labels and shouldn't take the full 44px input height — keep native size, inline, next to the label text. */ .modal input[type="checkbox"], .modal input[type="radio"] { display: inline-block; width: auto; height: auto; padding: 0; margin: 0 var(--s-1) 0 0; vertical-align: middle; box-shadow: none; } .modal label:has(> input[type="checkbox"]), .modal label:has(> input[type="radio"]) { text-transform: none; letter-spacing: 0; font-size: var(--fz-sm); color: var(--text); cursor: pointer; display: flex; align-items: center; gap: var(--s-2); } .modal input:focus, .modal select:focus, .modal textarea:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 2px rgba(233, 69, 96, 0.18); } .modal-actions { margin-top: var(--s-4); padding-top: var(--s-3); border-top: 1px solid var(--border); display: flex; gap: var(--s-2); justify-content: flex-end; } .modal-actions .btn-cancel { background: transparent; color: var(--text-muted); border-color: var(--border); font-weight: normal; } .modal-actions .btn-cancel:hover { background: var(--surface); border-color: var(--text-muted); color: var(--text); } .field-hint { font-size: var(--fz-xs); color: var(--text-dim); margin-top: var(--s-1); text-transform: none; letter-spacing: 0; } .pw-wrap { position: relative; } .pw-wrap input { padding-right: 2.4em; } .pw-toggle { position: absolute; right: var(--s-1); top: 50%; transform: translateY(-50%); background: none; border: none; color: var(--text-muted); cursor: pointer; font-size: var(--fz-sm); padding: var(--s-1); line-height: 1; width: auto; height: auto; font-weight: normal; } .pw-toggle:hover { color: var(--text); background: none; border-color: transparent; } /* ── Card (generic surface block used for status panels, cards) ── */ .card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--s-4); } /* ── Status-card grid (used on admin dashboard) ──────────────── */ .status-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--s-3); margin: var(--s-3) 0 var(--s-5); } .status-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--s-3) var(--s-4); } .status-card .label { color: var(--text-muted); font-size: var(--fz-xs); text-transform: uppercase; letter-spacing: 0.1em; } .status-card .value { color: var(--accent); font-size: var(--fz-xl); font-weight: bold; margin-top: var(--s-1); line-height: 1.2; } .status-card .detail { color: var(--text-dim); font-size: var(--fz-xs); margin-top: var(--s-1); } /* ── Small chips for feature flags, tags ──────────────────────── */ .feat-tag { display: inline-block; padding: 2px var(--s-2); border-radius: var(--radius); font-size: var(--fz-xs); margin-right: var(--s-1); margin-bottom: var(--s-1); letter-spacing: 0.06em; } .feat-on { background: var(--type-ssh-bg); color: var(--type-ssh-fg); } .feat-off { background: var(--border); color: var(--text-dim); } /* ── Form card (used by sessions form, onboarding) ──────────── */ form.card, .add-form { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--s-4) var(--s-5); margin-top: var(--s-3); } /* ── Hop cards (SSH jump host editor — used by addressbook + sessions) ── */ .hop-card { background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: var(--s-2); } .hop-card-header { display: flex; align-items: center; gap: var(--s-2); padding: var(--s-2) var(--s-3); cursor: pointer; font-size: var(--fz-md); } .hop-card-header:hover { background: var(--surface); } .hop-card-header .hop-num { color: var(--accent); font-weight: bold; min-width: 2em; } .hop-card-header .hop-hostname { flex: 1; color: var(--text); } .hop-card-header .hop-hostname input { display: inline; width: 100%; height: var(--ctl-sm); padding: 0 var(--s-2); font-size: var(--fz-md); background: var(--input); border: 1px solid var(--border); color: var(--text); font-family: monospace; border-radius: var(--radius); box-sizing: border-box; } .hop-card-header .hop-remove { color: var(--primary); cursor: pointer; font-size: var(--fz-sm); background: none; border: 1px solid transparent; padding: 0 var(--s-2); font-family: monospace; font-weight: normal; height: var(--ctl-sm); } .hop-card-header .hop-remove:hover { text-decoration: underline; background: none; border-color: transparent; } .hop-card-body { padding: var(--s-1) var(--s-3) var(--s-3) 44px; display: none; } .hop-card-body.expanded { display: block; } .hop-card-body label { margin-top: var(--s-2); } .hop-card-body input, .hop-card-body textarea { display: block; width: 100%; padding: 0 var(--s-2); height: var(--ctl-md); margin-top: var(--s-1); background: var(--input); border: 1px solid var(--border); color: var(--text); font-family: monospace; font-size: var(--fz-md); border-radius: var(--radius); box-sizing: border-box; } .hop-card-body textarea { height: auto; padding: var(--s-2); } /* ── Token reveal (one-time token display, admin/tokens pages) ── */ .token-reveal { background: var(--surface); padding: var(--s-4); border-radius: var(--radius); margin-top: var(--s-3); border: 1px solid var(--accent); } .token-reveal code { background: var(--input); padding: var(--s-2) var(--s-3); border-radius: var(--radius); font-size: var(--fz-sm); word-break: break-all; display: block; margin: var(--s-2) 0; user-select: all; } .token-reveal .warning { color: var(--primary); font-size: var(--fz-sm); margin-top: var(--s-2); } /* ── Row states ─────────────────────────────── */ .disabled-row { opacity: 0.5; } /* ── Status pill (used in reports / sessions grids) ──────────── */ .status-badge { display: inline-block; padding: 2px var(--s-2); border-radius: var(--radius); font-size: var(--fz-sm); letter-spacing: 0.06em; } /* ── Pagination ─────────────────────────────── */ .pagination { display: flex; align-items: center; gap: var(--s-3); margin: var(--s-3) 0; font-size: var(--fz-sm); } .pagination button { background: transparent; color: var(--text); border: 1px solid var(--border); font-family: monospace; font-size: var(--fz-sm); height: var(--ctl-sm); padding: 0 var(--s-3); border-radius: var(--radius); font-weight: normal; } .pagination button:hover { background: var(--surface); border-color: var(--accent); color: var(--accent); } .pagination button:disabled { color: var(--text-dim); border-color: var(--border); background: transparent; } .pagination .page-info { color: var(--text-muted); } /* ── Summary cards (reports top-of-page KPI strip) ─────────── */ .summary-cards { display: flex; gap: var(--s-3); margin: var(--s-4) 0; flex-wrap: wrap; } .summary-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--s-3) var(--s-4); flex: 1; min-width: 180px; } .summary-card .card-label { color: var(--text-muted); font-size: var(--fz-xs); text-transform: uppercase; letter-spacing: 0.1em; } .summary-card .card-value { color: var(--accent); font-size: var(--fz-xl); font-weight: bold; margin-top: var(--s-1); line-height: 1.2; } /* ── Flow diagram (you → hop → target path) ─────────────────── */ .flow-diagram { display: flex; align-items: center; gap: 0; flex-wrap: wrap; margin-bottom: var(--s-3); font-size: var(--fz-sm); } .flow-node { display: inline-flex; align-items: center; height: var(--ctl-sm); padding: 0 var(--s-2); border-radius: var(--radius); white-space: nowrap; } .flow-node-you { background: var(--input); color: var(--text-muted); } .flow-node-hop { background: var(--hop-bg); color: var(--hop-fg); } .flow-node-target { background: var(--input); color: var(--accent); font-weight: bold; } .flow-arrow { color: var(--text-muted); margin: 0 var(--s-1); }