Layout: - Add panel-container and session-panel CSS so workspace content doesn't overlap sidebar - Session panels use position: absolute to fill workspace area - Workspace is now flex column for proper empty-state/panel stacking Terminal: - xterm.js overrides now target .session-panel in addition to .terminal-container so terminal fills available space - Added debounced window resize handler for terminal re-fit Notifications: - Rewrote Notifications class to emit .notification-* classes matching the existing polished CSS (was emitting .toast-* with no CSS) - Icon is now a small coloured circle badge instead of oversized SVG Sidebar: - Fixed class mismatches: sidebar-dot → protocol-indicator, sidebar-item-sub → sidebar-item-host, sidebar-star → sidebar-item-star - protocolColour() now returns proto-ssh etc. matching CSS selectors Other: - Replaced prompt() in tab rename with custom _inputPrompt modal
898 lines
20 KiB
CSS
898 lines
20 KiB
CSS
/* ==========================================================================
|
|
Nexus Terminal — Reusable Components
|
|
Buttons, form controls, badges, dropdowns, modals, notifications, etc.
|
|
========================================================================== */
|
|
|
|
/* =======================================================================
|
|
BUTTONS
|
|
======================================================================= */
|
|
|
|
.btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: var(--space-2);
|
|
height: 30px;
|
|
padding: 0 var(--space-3);
|
|
font-size: var(--text-sm);
|
|
font-weight: var(--weight-medium);
|
|
line-height: 1;
|
|
border-radius: var(--radius-md);
|
|
border: 1px solid transparent;
|
|
cursor: pointer;
|
|
white-space: nowrap;
|
|
transition:
|
|
background var(--transition-fast),
|
|
border-color var(--transition-fast),
|
|
color var(--transition-fast),
|
|
box-shadow var(--transition-fast);
|
|
user-select: none;
|
|
}
|
|
|
|
.btn:disabled {
|
|
opacity: 0.45;
|
|
cursor: not-allowed;
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* Primary — accent filled */
|
|
.btn-primary {
|
|
background: var(--accent);
|
|
color: var(--text-inverse);
|
|
border-color: var(--accent);
|
|
}
|
|
.btn-primary:hover {
|
|
background: var(--accent-hover);
|
|
border-color: var(--accent-hover);
|
|
}
|
|
.btn-primary:active {
|
|
background: #3da69f;
|
|
border-color: #3da69f;
|
|
}
|
|
|
|
/* Accent — success-tinted action, e.g. "Save & Connect" */
|
|
.btn-accent {
|
|
background: var(--success);
|
|
color: var(--text-inverse);
|
|
border-color: var(--success);
|
|
}
|
|
.btn-accent:hover {
|
|
background: #57a85c;
|
|
border-color: #57a85c;
|
|
}
|
|
.btn-accent:active {
|
|
background: #4a9a4e;
|
|
border-color: #4a9a4e;
|
|
}
|
|
|
|
/* Secondary — subtle border */
|
|
.btn-secondary {
|
|
background: transparent;
|
|
color: var(--text-secondary);
|
|
border-color: var(--border-default);
|
|
}
|
|
.btn-secondary:hover {
|
|
background: var(--bg-hover);
|
|
color: var(--text-primary);
|
|
border-color: var(--border-strong);
|
|
}
|
|
.btn-secondary:active {
|
|
background: var(--bg-active);
|
|
}
|
|
|
|
/* Ghost — transparent, hover only */
|
|
.btn-ghost {
|
|
background: transparent;
|
|
color: var(--text-secondary);
|
|
}
|
|
.btn-ghost:hover {
|
|
background: var(--bg-hover);
|
|
color: var(--text-primary);
|
|
}
|
|
.btn-ghost:active {
|
|
background: var(--bg-active);
|
|
}
|
|
|
|
/* Danger */
|
|
.btn-danger {
|
|
background: transparent;
|
|
color: var(--error);
|
|
border-color: var(--error);
|
|
}
|
|
.btn-danger:hover {
|
|
background: rgba(239, 83, 80, 0.12);
|
|
}
|
|
.btn-danger:active {
|
|
background: rgba(239, 83, 80, 0.20);
|
|
}
|
|
|
|
.btn-danger-filled {
|
|
background: var(--error);
|
|
color: #fff;
|
|
border-color: var(--error);
|
|
}
|
|
.btn-danger-filled:hover {
|
|
background: #e53935;
|
|
border-color: #e53935;
|
|
}
|
|
|
|
/* Size variants */
|
|
.btn-sm {
|
|
height: 26px;
|
|
padding: 0 var(--space-2);
|
|
font-size: var(--text-xs);
|
|
}
|
|
|
|
.btn-xs {
|
|
height: 22px;
|
|
padding: 0 var(--space-2);
|
|
font-size: var(--text-xs);
|
|
border-radius: var(--radius-sm);
|
|
}
|
|
|
|
/* Icon-only button (square) */
|
|
.btn-icon {
|
|
width: 30px;
|
|
padding: 0;
|
|
flex-shrink: 0;
|
|
}
|
|
.btn-icon.btn-sm {
|
|
width: 26px;
|
|
}
|
|
.btn-icon.btn-xs {
|
|
width: 22px;
|
|
}
|
|
|
|
/* Button group */
|
|
.btn-group {
|
|
display: inline-flex;
|
|
}
|
|
|
|
/* Outline button — transparent background, subtle border */
|
|
.btn-outline {
|
|
background: transparent;
|
|
border: 1px solid var(--border);
|
|
color: var(--text-secondary);
|
|
}
|
|
.btn-outline:hover {
|
|
background: var(--surface-2);
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.btn-group .btn {
|
|
border-radius: 0;
|
|
}
|
|
.btn-group .btn:first-child {
|
|
border-radius: var(--radius-md) 0 0 var(--radius-md);
|
|
}
|
|
.btn-group .btn:last-child {
|
|
border-radius: 0 var(--radius-md) var(--radius-md) 0;
|
|
}
|
|
.btn-group .btn + .btn {
|
|
margin-left: -1px;
|
|
}
|
|
|
|
|
|
/* =======================================================================
|
|
FORM CONTROLS
|
|
======================================================================= */
|
|
|
|
.form-group {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-1);
|
|
}
|
|
|
|
.form-label {
|
|
font-size: var(--text-sm);
|
|
font-weight: var(--weight-medium);
|
|
color: var(--text-secondary);
|
|
user-select: none;
|
|
}
|
|
|
|
.form-label-required::after {
|
|
content: ' *';
|
|
color: var(--error);
|
|
}
|
|
|
|
/* Text input, select, textarea share a common treatment */
|
|
.form-input,
|
|
.form-select,
|
|
.form-textarea {
|
|
height: 30px;
|
|
padding: 0 var(--space-3);
|
|
font-size: var(--text-sm);
|
|
color: var(--text-primary);
|
|
background: var(--bg-input);
|
|
border: 1px solid var(--border-default);
|
|
border-radius: var(--radius-md);
|
|
transition:
|
|
border-color var(--transition-fast),
|
|
box-shadow var(--transition-fast);
|
|
}
|
|
|
|
.form-input::placeholder,
|
|
.form-textarea::placeholder {
|
|
color: var(--text-disabled);
|
|
}
|
|
|
|
.form-input:hover,
|
|
.form-select:hover,
|
|
.form-textarea:hover {
|
|
border-color: var(--border-strong);
|
|
}
|
|
|
|
.form-input:focus,
|
|
.form-select:focus,
|
|
.form-textarea:focus {
|
|
border-color: var(--accent);
|
|
box-shadow: 0 0 0 2px var(--accent-muted);
|
|
outline: none;
|
|
}
|
|
|
|
.form-input:disabled,
|
|
.form-select:disabled,
|
|
.form-textarea:disabled {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
/* Select arrow */
|
|
.form-select {
|
|
appearance: none;
|
|
padding-right: var(--space-8);
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%236e6e88'/%3E%3C/svg%3E");
|
|
background-repeat: no-repeat;
|
|
background-position: right 10px center;
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* Textarea */
|
|
.form-textarea {
|
|
height: auto;
|
|
min-height: 64px;
|
|
padding: var(--space-2) var(--space-3);
|
|
resize: vertical;
|
|
line-height: var(--leading-normal);
|
|
}
|
|
|
|
/* Help text */
|
|
.form-help {
|
|
font-size: var(--text-xs);
|
|
color: var(--text-tertiary);
|
|
line-height: var(--leading-normal);
|
|
}
|
|
|
|
/* Error message */
|
|
.form-error {
|
|
font-size: var(--text-xs);
|
|
color: var(--error);
|
|
line-height: var(--leading-normal);
|
|
}
|
|
|
|
/* Error state on inputs */
|
|
.form-input.is-error,
|
|
.form-select.is-error,
|
|
.form-textarea.is-error {
|
|
border-color: var(--error);
|
|
}
|
|
.form-input.is-error:focus,
|
|
.form-select.is-error:focus,
|
|
.form-textarea.is-error:focus {
|
|
box-shadow: 0 0 0 2px rgba(239, 83, 80, 0.20);
|
|
}
|
|
|
|
/* Inline layout (label beside control) */
|
|
.form-inline {
|
|
flex-direction: row;
|
|
align-items: center;
|
|
gap: var(--space-3);
|
|
}
|
|
.form-inline .form-label {
|
|
min-width: 100px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* Checkbox */
|
|
.form-checkbox {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
cursor: pointer;
|
|
font-size: var(--text-sm);
|
|
color: var(--text-secondary);
|
|
user-select: none;
|
|
}
|
|
|
|
.form-checkbox input[type="checkbox"] {
|
|
appearance: none;
|
|
width: 16px;
|
|
height: 16px;
|
|
border: 1px solid var(--border-strong);
|
|
border-radius: var(--radius-sm);
|
|
background: var(--bg-input);
|
|
flex-shrink: 0;
|
|
cursor: pointer;
|
|
transition:
|
|
background var(--transition-fast),
|
|
border-color var(--transition-fast);
|
|
position: relative;
|
|
}
|
|
|
|
.form-checkbox input[type="checkbox"]:checked {
|
|
background: var(--accent);
|
|
border-color: var(--accent);
|
|
}
|
|
|
|
.form-checkbox input[type="checkbox"]:checked::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: 2px;
|
|
left: 5px;
|
|
width: 4px;
|
|
height: 8px;
|
|
border: solid var(--text-inverse);
|
|
border-width: 0 2px 2px 0;
|
|
transform: rotate(45deg);
|
|
}
|
|
|
|
.form-checkbox input[type="checkbox"]:focus-visible {
|
|
outline: 2px solid var(--accent);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
/* Toggle switch */
|
|
.form-toggle {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
cursor: pointer;
|
|
font-size: var(--text-sm);
|
|
color: var(--text-secondary);
|
|
user-select: none;
|
|
}
|
|
|
|
.form-toggle input[type="checkbox"] {
|
|
appearance: none;
|
|
width: 32px;
|
|
height: 18px;
|
|
border-radius: var(--radius-full);
|
|
background: var(--border-strong);
|
|
position: relative;
|
|
cursor: pointer;
|
|
flex-shrink: 0;
|
|
transition: background var(--transition-normal);
|
|
}
|
|
|
|
.form-toggle input[type="checkbox"]::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: 2px;
|
|
left: 2px;
|
|
width: 14px;
|
|
height: 14px;
|
|
border-radius: 50%;
|
|
background: var(--text-secondary);
|
|
transition: transform var(--transition-normal), background var(--transition-normal);
|
|
}
|
|
|
|
.form-toggle input[type="checkbox"]:checked {
|
|
background: var(--accent);
|
|
}
|
|
|
|
.form-toggle input[type="checkbox"]:checked::after {
|
|
transform: translateX(14px);
|
|
background: var(--text-inverse);
|
|
}
|
|
|
|
|
|
/* =======================================================================
|
|
BADGES
|
|
======================================================================= */
|
|
|
|
.badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
height: 18px;
|
|
padding: 0 var(--space-2);
|
|
font-size: 10px;
|
|
font-weight: var(--weight-semibold);
|
|
line-height: 1;
|
|
border-radius: var(--radius-sm);
|
|
white-space: nowrap;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.04em;
|
|
background: var(--bg-overlay);
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
/* Protocol badges */
|
|
.badge-ssh {
|
|
background: rgba(78, 205, 196, 0.15);
|
|
color: var(--protocol-ssh);
|
|
}
|
|
.badge-telnet {
|
|
background: rgba(255, 167, 38, 0.15);
|
|
color: var(--protocol-telnet);
|
|
}
|
|
.badge-raw {
|
|
background: rgba(171, 71, 188, 0.15);
|
|
color: var(--protocol-raw);
|
|
}
|
|
|
|
/* Status badges */
|
|
.badge-status {
|
|
gap: var(--space-1);
|
|
}
|
|
.badge-status::before {
|
|
content: '';
|
|
width: 6px;
|
|
height: 6px;
|
|
border-radius: 50%;
|
|
background: var(--text-tertiary);
|
|
flex-shrink: 0;
|
|
}
|
|
.badge-status.is-connected::before { background: var(--success); }
|
|
.badge-status.is-connecting::before { background: var(--warning); animation: pulse-dot 1.2s ease infinite; }
|
|
.badge-status.is-error::before { background: var(--error); }
|
|
.badge-status.is-disconnected::before { background: var(--text-tertiary); }
|
|
|
|
@keyframes pulse-dot {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0.4; }
|
|
}
|
|
|
|
|
|
/* =======================================================================
|
|
CARDS & SURFACES
|
|
======================================================================= */
|
|
|
|
.surface {
|
|
background: var(--bg-elevated);
|
|
border: 1px solid var(--border-subtle);
|
|
border-radius: var(--radius-lg);
|
|
box-shadow: var(--shadow-sm);
|
|
}
|
|
|
|
.card {
|
|
background: var(--bg-elevated);
|
|
border: 1px solid var(--border-subtle);
|
|
border-radius: var(--radius-lg);
|
|
padding: var(--space-4);
|
|
cursor: pointer;
|
|
transition:
|
|
background var(--transition-fast),
|
|
border-color var(--transition-fast),
|
|
box-shadow var(--transition-fast);
|
|
}
|
|
.card:hover {
|
|
background: var(--bg-hover);
|
|
border-color: var(--border-default);
|
|
box-shadow: var(--shadow-md);
|
|
}
|
|
.card:active {
|
|
background: var(--bg-active);
|
|
}
|
|
|
|
|
|
/* =======================================================================
|
|
DROPDOWN / CONTEXT MENU
|
|
======================================================================= */
|
|
|
|
.dropdown {
|
|
position: relative;
|
|
display: inline-flex;
|
|
}
|
|
|
|
.dropdown-menu {
|
|
position: absolute;
|
|
top: 100%;
|
|
left: 0;
|
|
z-index: var(--z-dropdown);
|
|
min-width: 160px;
|
|
padding: var(--space-1) 0;
|
|
background: var(--bg-overlay);
|
|
border: 1px solid var(--border-default);
|
|
border-radius: var(--radius-md);
|
|
box-shadow: var(--shadow-lg);
|
|
opacity: 0;
|
|
visibility: hidden;
|
|
transform: translateY(-4px);
|
|
transition:
|
|
opacity var(--transition-fast),
|
|
visibility var(--transition-fast),
|
|
transform var(--transition-fast);
|
|
}
|
|
|
|
.dropdown.is-open .dropdown-menu,
|
|
.dropdown-menu.is-visible {
|
|
opacity: 1;
|
|
visibility: visible;
|
|
transform: translateY(2px);
|
|
}
|
|
|
|
/* Right-aligned variant */
|
|
.dropdown-menu.is-right {
|
|
left: auto;
|
|
right: 0;
|
|
}
|
|
|
|
.dropdown-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
width: 100%;
|
|
padding: var(--space-1) var(--space-3);
|
|
font-size: var(--text-sm);
|
|
color: var(--text-secondary);
|
|
cursor: pointer;
|
|
transition: background var(--transition-fast), color var(--transition-fast);
|
|
border: none;
|
|
background: none;
|
|
text-align: left;
|
|
}
|
|
|
|
.dropdown-item:hover {
|
|
background: var(--bg-hover);
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.dropdown-item.is-danger {
|
|
color: var(--error);
|
|
}
|
|
.dropdown-item.is-danger:hover {
|
|
background: rgba(239, 83, 80, 0.10);
|
|
}
|
|
|
|
.dropdown-item.is-disabled {
|
|
opacity: 0.4;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.dropdown-item-icon {
|
|
width: 16px;
|
|
text-align: center;
|
|
flex-shrink: 0;
|
|
font-size: var(--text-md);
|
|
}
|
|
|
|
.dropdown-item-shortcut {
|
|
margin-left: auto;
|
|
font-size: var(--text-xs);
|
|
color: var(--text-tertiary);
|
|
}
|
|
|
|
.dropdown-separator {
|
|
height: 1px;
|
|
margin: var(--space-1) 0;
|
|
background: var(--border-subtle);
|
|
}
|
|
|
|
.dropdown-header {
|
|
padding: var(--space-1) var(--space-3);
|
|
font-size: var(--text-xs);
|
|
font-weight: var(--weight-semibold);
|
|
color: var(--text-tertiary);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
}
|
|
|
|
|
|
/* =======================================================================
|
|
NOTIFICATIONS (toast)
|
|
======================================================================= */
|
|
|
|
.notifications-container {
|
|
position: fixed;
|
|
top: var(--space-4);
|
|
right: var(--space-4);
|
|
z-index: var(--z-notification);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-2);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.notification {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: var(--space-3);
|
|
min-width: 280px;
|
|
max-width: 400px;
|
|
padding: var(--space-3) var(--space-4);
|
|
background: var(--bg-overlay);
|
|
border: 1px solid var(--border-default);
|
|
border-radius: var(--radius-lg);
|
|
box-shadow: var(--shadow-xl);
|
|
pointer-events: auto;
|
|
animation: notification-in var(--transition-slow) ease forwards;
|
|
}
|
|
|
|
.notification.is-leaving {
|
|
animation: notification-out var(--transition-normal) ease forwards;
|
|
}
|
|
|
|
@keyframes notification-in {
|
|
from { opacity: 0; transform: translateX(20px); }
|
|
to { opacity: 1; transform: translateX(0); }
|
|
}
|
|
@keyframes notification-out {
|
|
from { opacity: 1; transform: translateX(0); }
|
|
to { opacity: 0; transform: translateX(20px); }
|
|
}
|
|
|
|
.notification-icon {
|
|
flex-shrink: 0;
|
|
width: 20px;
|
|
height: 20px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 50%;
|
|
font-size: 11px;
|
|
font-weight: var(--weight-bold);
|
|
line-height: 1;
|
|
color: var(--text-inverse);
|
|
background: var(--text-tertiary);
|
|
}
|
|
|
|
.notification-success .notification-icon { background: var(--success); }
|
|
.notification-error .notification-icon { background: var(--error); }
|
|
.notification-warning .notification-icon { background: var(--warning); }
|
|
.notification-info .notification-icon { background: var(--info); }
|
|
|
|
.notification-body {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.notification-title {
|
|
font-size: var(--text-sm);
|
|
font-weight: var(--weight-semibold);
|
|
color: var(--text-primary);
|
|
margin-bottom: 2px;
|
|
}
|
|
|
|
.notification-message {
|
|
font-size: var(--text-xs);
|
|
color: var(--text-secondary);
|
|
line-height: var(--leading-normal);
|
|
}
|
|
|
|
.notification-close {
|
|
flex-shrink: 0;
|
|
width: 20px;
|
|
height: 20px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: var(--radius-sm);
|
|
color: var(--text-tertiary);
|
|
cursor: pointer;
|
|
transition: background var(--transition-fast), color var(--transition-fast);
|
|
}
|
|
.notification-close:hover {
|
|
background: var(--bg-hover);
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
/* Colour variants (left border accent) */
|
|
.notification-success { border-left: 3px solid var(--success); }
|
|
.notification-error { border-left: 3px solid var(--error); }
|
|
.notification-warning { border-left: 3px solid var(--warning); }
|
|
.notification-info { border-left: 3px solid var(--info); }
|
|
|
|
|
|
/* =======================================================================
|
|
DISCLOSURE / ACCORDION
|
|
======================================================================= */
|
|
|
|
.disclosure {
|
|
border-bottom: 1px solid var(--border-subtle);
|
|
}
|
|
|
|
.disclosure-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
width: 100%;
|
|
padding: var(--space-3) var(--space-4);
|
|
font-size: var(--text-sm);
|
|
font-weight: var(--weight-medium);
|
|
color: var(--text-secondary);
|
|
cursor: pointer;
|
|
transition: background var(--transition-fast), color var(--transition-fast);
|
|
user-select: none;
|
|
text-align: left;
|
|
background: none;
|
|
border: none;
|
|
}
|
|
|
|
.disclosure-header:hover {
|
|
background: var(--bg-hover);
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.disclosure-chevron {
|
|
width: 16px;
|
|
height: 16px;
|
|
flex-shrink: 0;
|
|
transition: transform var(--transition-normal);
|
|
color: var(--text-tertiary);
|
|
}
|
|
|
|
.disclosure.is-open .disclosure-chevron {
|
|
transform: rotate(90deg);
|
|
}
|
|
|
|
.disclosure-content {
|
|
overflow: hidden;
|
|
max-height: 0;
|
|
transition: max-height var(--transition-slow);
|
|
}
|
|
|
|
.disclosure.is-open .disclosure-content {
|
|
max-height: 2000px;
|
|
}
|
|
|
|
.disclosure-content-inner {
|
|
padding: 0 var(--space-4) var(--space-4);
|
|
}
|
|
|
|
|
|
/* =======================================================================
|
|
SEARCH INPUT
|
|
======================================================================= */
|
|
|
|
.search-input {
|
|
width: 100%;
|
|
height: 30px;
|
|
padding: 0 var(--space-3) 0 var(--space-8);
|
|
font-size: var(--text-sm);
|
|
color: var(--text-primary);
|
|
background: var(--bg-input);
|
|
border: 1px solid var(--border-subtle);
|
|
border-radius: var(--radius-md);
|
|
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
|
|
}
|
|
|
|
.search-input::placeholder {
|
|
color: var(--text-disabled);
|
|
}
|
|
|
|
.search-input:hover {
|
|
border-color: var(--border-default);
|
|
}
|
|
|
|
.search-input:focus {
|
|
border-color: var(--accent);
|
|
box-shadow: 0 0 0 2px var(--accent-muted);
|
|
outline: none;
|
|
}
|
|
|
|
/* Wrapper with icon */
|
|
.search-wrapper {
|
|
position: relative;
|
|
}
|
|
|
|
.search-wrapper::before {
|
|
content: '⌕';
|
|
position: absolute;
|
|
left: var(--space-3);
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
font-size: var(--text-sm);
|
|
color: var(--text-tertiary);
|
|
pointer-events: none;
|
|
}
|
|
|
|
|
|
/* =======================================================================
|
|
EMPTY STATE
|
|
======================================================================= */
|
|
|
|
.empty-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex: 1;
|
|
padding: var(--space-8);
|
|
text-align: center;
|
|
}
|
|
|
|
.empty-state-icon {
|
|
font-size: 48px;
|
|
color: var(--text-tertiary);
|
|
margin-bottom: var(--space-4);
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.empty-state h2 {
|
|
font-size: var(--text-lg);
|
|
font-weight: var(--weight-semibold);
|
|
color: var(--text-secondary);
|
|
margin-bottom: var(--space-2);
|
|
}
|
|
|
|
.empty-state p {
|
|
font-size: var(--text-sm);
|
|
color: var(--text-tertiary);
|
|
max-width: 320px;
|
|
line-height: var(--leading-relaxed);
|
|
margin-bottom: var(--space-6);
|
|
}
|
|
|
|
.empty-state-actions {
|
|
display: flex;
|
|
gap: var(--space-3);
|
|
}
|
|
|
|
|
|
/* =======================================================================
|
|
TOOLTIP
|
|
======================================================================= */
|
|
|
|
.tooltip {
|
|
position: absolute;
|
|
z-index: var(--z-tooltip);
|
|
padding: var(--space-1) var(--space-2);
|
|
font-size: var(--text-xs);
|
|
font-weight: var(--weight-medium);
|
|
color: var(--text-primary);
|
|
background: var(--bg-overlay);
|
|
border: 1px solid var(--border-default);
|
|
border-radius: var(--radius-sm);
|
|
box-shadow: var(--shadow-md);
|
|
white-space: nowrap;
|
|
pointer-events: none;
|
|
opacity: 0;
|
|
transition: opacity var(--transition-fast);
|
|
}
|
|
|
|
.tooltip.is-visible {
|
|
opacity: 1;
|
|
}
|
|
|
|
|
|
/* =======================================================================
|
|
DIVIDER
|
|
======================================================================= */
|
|
|
|
.divider {
|
|
height: 1px;
|
|
background: var(--border-subtle);
|
|
margin: var(--space-2) 0;
|
|
}
|
|
|
|
.divider-vertical {
|
|
width: 1px;
|
|
align-self: stretch;
|
|
background: var(--border-subtle);
|
|
margin: 0 var(--space-2);
|
|
}
|
|
|
|
|
|
/* =======================================================================
|
|
LOADING / SPINNER
|
|
======================================================================= */
|
|
|
|
.spinner {
|
|
width: 16px;
|
|
height: 16px;
|
|
border: 2px solid var(--border-strong);
|
|
border-top-color: var(--accent);
|
|
border-radius: 50%;
|
|
animation: spin 0.6s linear infinite;
|
|
}
|
|
|
|
.spinner-sm {
|
|
width: 12px;
|
|
height: 12px;
|
|
border-width: 1.5px;
|
|
}
|
|
|
|
@keyframes spin {
|
|
to { transform: rotate(360deg); }
|
|
}
|