Files
gotermix/internals/web/app.css
T

313 lines
12 KiB
CSS
Raw Normal View History

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; background: #0d0f14; color: #e2e8f0;
font-family: 'JetBrains Mono','Fira Mono',monospace; overflow: hidden; }
/* ── Tab bar ── */
#tabBar {
position: fixed; top: 0; left: 0; right: 0; height: 36px;
background: #0a0c11; border-bottom: 1px solid rgba(255,255,255,0.06);
display: flex; align-items: center;
padding: 0 4px; z-index: 50; overflow: hidden;
}
/* tabList fills bar, scrolls horizontally when many tabs.
The "+" button lives at the end of this list. */
#tabList {
display: flex; align-items: center; gap: 2px;
flex: 1; overflow-x: auto; overflow-y: hidden; height: 100%;
scrollbar-width: none;
}
#tabList::-webkit-scrollbar { display: none; }
.tab-item {
display: flex; align-items: center; gap: 4px;
padding: 0 8px 0 12px; height: 28px; border-radius: 5px;
background: transparent; color: #4b5563;
font-size: 11px; font-family: inherit; cursor: default;
white-space: nowrap; flex-shrink: 0;
border: 1px solid transparent;
transition: background 0.15s, color 0.15s;
user-select: none;
}
.tab-item:hover { background: rgba(255,255,255,0.05); color: #9ca3af; }
.tab-item.active {
background: #13161e; color: #e2e8f0;
border-color: rgba(255,255,255,0.08);
}
.tab-label { cursor: pointer; }
2026-05-24 06:37:59 +00:00
.tab-rename-input {
background: #0d0f14; border: 1px solid rgba(110,231,183,0.45);
border-radius: 3px; color: #e2e8f0; font-size: 11px;
font-family: inherit; padding: 1px 5px; outline: none;
width: 90px; min-width: 40px;
}
.tab-x {
width: 16px; height: 16px; border: none; border-radius: 3px;
background: transparent; color: inherit; cursor: pointer;
font-size: 14px; line-height: 1; padding: 0;
display: flex; align-items: center; justify-content: center;
opacity: 0.4; transition: opacity 0.15s, background 0.15s;
}
.tab-x:hover { opacity: 1; background: rgba(255,255,255,0.12); }
.tab-new {
height: 28px; width: 28px; border: none; border-radius: 5px;
background: transparent; color: #4b5563;
font-size: 20px; line-height: 1; cursor: pointer; flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
transition: background 0.15s, color 0.15s;
}
.tab-new:hover { background: rgba(255,255,255,0.07); color: #6ee7b7; }
/* ── Terminal container + panes ── */
#termContainer {
position: fixed; top: 36px; left: 0; right: 0; bottom: 48px;
}
2026-05-24 06:37:59 +00:00
/* One per tab — holds the entire pane tree for that tab */
.tab-pane { width: 100%; height: 100%; }
/* Leaf node — wraps an xterm canvas */
.term-pane { width: 100%; height: 100%; overflow: hidden; }
/* Active pane highlight (shown only when 2+ panes exist in a tab) */
.pane-active { box-shadow: inset 0 0 0 1px rgba(110,231,183,0.45); }
/* ── Split containers ── */
/* dir 'h': side-by-side with a vertical divider */
.split-h {
display: flex; flex-direction: row;
width: 100%; height: 100%; overflow: hidden;
}
/* dir 'v': stacked with a horizontal divider */
.split-v {
display: flex; flex-direction: column;
width: 100%; height: 100%; overflow: hidden;
}
/* ── Draggable dividers ── */
.split-div-h {
flex: 0 0 4px; height: 100%;
background: rgba(255,255,255,0.07);
cursor: col-resize;
transition: background 0.15s;
position: relative;
}
.split-div-h::after {
content: ''; position: absolute; inset: 0 -2px;
/* wider hit target without affecting layout */
}
.split-div-h:hover { background: rgba(110,231,183,0.35); }
.split-div-v {
flex: 0 0 4px; width: 100%;
background: rgba(255,255,255,0.07);
cursor: row-resize;
transition: background 0.15s;
position: relative;
}
.split-div-v::after {
content: ''; position: absolute; inset: -2px 0;
}
.split-div-v:hover { background: rgba(110,231,183,0.35); }
/* ── Compact toolbar ── */
.toolbar {
position: fixed; bottom: 0; left: 0; right: 0; height: 48px;
background: #13161e; border-top: 1px solid rgba(255,255,255,0.07);
display: flex; align-items: center;
justify-content: space-between;
padding: 0 10px; gap: 6px; z-index: 50;
}
.tb-left { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1; }
.tb-right { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
/* connection dot */
.dot {
width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
background: #f59e0b; box-shadow: 0 0 5px #f59e0b; transition: all 0.3s;
}
.dot.ok { background: #6ee7b7; box-shadow: 0 0 5px #6ee7b7; }
.dot.err { background: #ef4444; box-shadow: 0 0 5px #ef4444; }
/* status label — truncates on narrow screens */
.status-label {
font-size: 11px; color: #4b5563; white-space: nowrap;
overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
/* toolbar icon buttons */
.tb-btn {
height: 32px; padding: 0 10px; border: none; border-radius: 6px;
background: rgba(255,255,255,0.05); color: #9ca3af;
font-size: 11px; font-family: inherit; font-weight: 600;
cursor: pointer; display: flex; align-items: center; gap: 5px;
transition: background 0.15s, color 0.15s; white-space: nowrap; flex-shrink: 0;
}
.tb-btn:hover { background: rgba(255,255,255,0.1); color: #e2e8f0; }
.tb-btn svg { flex-shrink: 0; }
2026-05-24 06:37:59 +00:00
.tb-btn.accent { background: rgba(110,231,183,0.1); color: #6ee7b7;
border: 1px solid rgba(110,231,183,0.15); }
.tb-btn.accent:hover { background: rgba(110,231,183,0.18); }
.tb-btn.tb-danger { background: rgba(239,68,68,0.08); color: #f87171;
border: 1px solid rgba(239,68,68,0.15); }
.tb-btn.tb-danger:hover { background: rgba(239,68,68,0.16); color: #fca5a5; }
2026-05-24 07:44:54 +00:00
.tb-btn.tb-info { background: rgba(59,130,246,0.1); color: #93c5fd;
border: 1px solid rgba(59,130,246,0.2); }
.tb-btn.tb-info:hover { background: rgba(59,130,246,0.18); color: #bfdbfe; }
2026-05-24 06:37:59 +00:00
.tb-sep { width: 1px; height: 20px; background: rgba(255,255,255,0.07); flex-shrink: 0; margin: 0 2px; }
/* ── Toast ── */
.toast {
position: fixed; bottom: 56px; left: 50%;
transform: translateX(-50%) translateY(6px);
opacity: 0; pointer-events: none; z-index: 400;
background: #1e2330; border: 1px solid rgba(255,255,255,0.1);
padding: 7px 16px; border-radius: 20px; font-size: 12px;
white-space: nowrap; transition: opacity 0.2s, transform 0.2s;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast.ok { border-color: rgba(110,231,183,0.35); color: #6ee7b7; }
.toast.err { border-color: rgba(239,68,68,0.35); color: #f87171; }
/* ── Shared modal base ── */
.m-overlay {
position: fixed; inset: 0; z-index: 200;
background: rgba(5,7,11,0.88); backdrop-filter: blur(6px);
display: flex; align-items: center; justify-content: center;
padding: 16px;
}
.m-overlay.hidden { display: none; }
.m-card {
width: 100%; max-width: 380px;
background: #13161e; border-radius: 14px;
border: 1px solid rgba(255,255,255,0.08);
box-shadow: 0 32px 80px rgba(0,0,0,0.7);
overflow: hidden;
}
.m-head {
display: flex; align-items: center; justify-content: space-between;
padding: 14px 20px; border-bottom: 1px solid rgba(255,255,255,0.06);
}
.m-title {
font-size: 13px; font-weight: 600; color: #e2e8f0;
display: flex; align-items: center; gap: 8px;
}
.m-title svg { color: #6ee7b7; }
.m-x {
width: 28px; height: 28px; border: none; border-radius: 6px;
background: transparent; color: #6b7280; cursor: pointer; font-size: 16px;
display: flex; align-items: center; justify-content: center;
transition: background 0.15s, color 0.15s;
}
.m-x:hover { background: rgba(255,255,255,0.07); color: #e2e8f0; }
.m-body { padding: 20px; }
.m-label {
display: block; font-size: 11px; color: #6b7280;
text-transform: uppercase; letter-spacing: 0.07em; margin-bottom: 6px;
}
.m-input {
width: 100%; padding: 10px 12px;
background: #0d0f14; border: 1px solid rgba(255,255,255,0.08);
border-radius: 7px; color: #e2e8f0; font-size: 13px;
font-family: inherit; outline: none; margin-bottom: 14px;
transition: border-color 0.15s, box-shadow 0.15s;
}
.m-input:focus {
border-color: rgba(110,231,183,0.45);
box-shadow: 0 0 0 3px rgba(110,231,183,0.07);
}
.m-input::placeholder { color: #374151; }
/* file drop zone */
.file-zone {
border: 1px dashed rgba(255,255,255,0.12); border-radius: 7px;
padding: 18px 16px; text-align: center; cursor: pointer;
margin-bottom: 14px; transition: border-color 0.15s, background 0.15s;
}
.file-zone:hover { border-color: rgba(110,231,183,0.35); background: rgba(110,231,183,0.03); }
.file-zone.has-file { border-color: rgba(110,231,183,0.4); background: rgba(110,231,183,0.04); }
.file-zone-icon { color: #4b5563; margin-bottom: 6px; }
.file-zone.has-file .file-zone-icon { color: #6ee7b7; }
.file-zone-name { font-size: 12px; color: #6b7280; }
.file-zone.has-file .file-zone-name { color: #9ca3af; }
.m-btn {
width: 100%; padding: 11px; border: none; border-radius: 7px;
background: #6ee7b7; color: #0d0f14; font-size: 13px; font-weight: 700;
font-family: inherit; cursor: pointer; display: flex;
align-items: center; justify-content: center; gap: 8px;
transition: background 0.15s, transform 0.1s;
}
.m-btn:hover { background: #34d399; }
.m-btn:active { transform: scale(0.98); }
.m-btn:disabled { background: #1f2937; color: #374151; cursor: not-allowed; transform: none; }
.m-btn.ghost {
background: rgba(255,255,255,0.06); color: #9ca3af;
border: 1px solid rgba(255,255,255,0.1);
}
.m-btn.ghost:hover { background: rgba(255,255,255,0.1); color: #e2e8f0; }
.m-fb { font-size: 11px; margin-top: 10px; text-align: center; min-height: 16px; }
.m-fb.ok { color: #6ee7b7; }
.m-fb.err { color: #f87171; }
/* spinner */
.spin {
width: 14px; height: 14px; border: 2px solid rgba(13,15,20,0.3);
border-top-color: #0d0f14; border-radius: 50%;
animation: spin 0.65s linear infinite; display: none;
}
.m-btn.busy .spin { display: block; }
.m-btn.busy .btn-text { display: none; }
@keyframes spin { to { transform: rotate(360deg); } }
2026-05-24 07:44:54 +00:00
/* ── Info modal ── */
.info-section-label {
font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em;
color: #6ee7b7; font-weight: 700; margin: 14px 0 6px;
}
.info-section-label:first-child { margin-top: 0; }
.info-table {
width: 100%; border-collapse: collapse; font-size: 12px;
}
.info-table tr { border-bottom: 1px solid rgba(255,255,255,0.04); }
.info-table tr:last-child { border-bottom: none; }
.info-table td { padding: 5px 4px; color: #9ca3af; vertical-align: top; }
.info-table td:first-child { white-space: nowrap; padding-right: 16px; color: #e2e8f0; }
kbd {
display: inline-block; padding: 1px 6px;
background: rgba(255,255,255,0.07); border: 1px solid rgba(255,255,255,0.12);
border-radius: 4px; font-size: 11px; font-family: inherit; color: #e2e8f0;
}
/* ── Auth modal specifics ── */
.auth-card { padding: 40px 36px; }
.auth-logo { font-size: 22px; font-weight: 700; color: #6ee7b7;
letter-spacing: -0.5px; margin-bottom: 4px; }
.auth-logo em { color: rgba(110,231,183,0.4); font-style: normal; }
.auth-sub { font-size: 11px; color: #374151; margin-bottom: 32px;
text-transform: uppercase; letter-spacing: 0.06em; }
.auth-err {
font-size: 12px; color: #f87171; display: none;
padding: 9px 13px; margin-bottom: 16px;
background: rgba(239,68,68,0.08);
border: 1px solid rgba(239,68,68,0.2); border-radius: 7px;
}
.auth-err.show { display: block; }
.auth-btn {
width: 100%; padding: 13px; border: none; border-radius: 7px;
background: #6ee7b7; color: #0d0f14; font-size: 14px; font-weight: 700;
font-family: inherit; cursor: pointer;
display: flex; align-items: center; justify-content: center; gap: 10px;
transition: background 0.15s, transform 0.1s;
}
.auth-btn:hover { background: #34d399; }
.auth-btn:active { transform: scale(0.98); }
.auth-btn:disabled { background: #1f2937; color: #374151; cursor: not-allowed; transform: none; }
.auth-spin {
width: 15px; height: 15px; border: 2px solid rgba(13,15,20,0.25);
border-top-color: #0d0f14; border-radius: 50%;
animation: spin 0.65s linear infinite; display: none;
}
.auth-btn.busy .auth-spin { display: block; }
.auth-btn.busy .btn-text { display: none; }