Files
headquarter/apps/web/src/styles/utilities.css
T
Developer 415aecc0dd fix: constrain dialog content to the viewport
- Add dynamic viewport bounds and scrollable body regions to dialogs and modals\n- Make tool-launch popups use the shared scrollable body pattern\n- Keep mobile sheets, action sheets, and notification popups scroll-contained\n- Restore the ProjectsPage test setup required for the frontend suite\n\nOpenSpec: fix-dialog-scroll-containment\nQuality gates: npm run typecheck, npm run lint, npm test (88 passed), npm run build
2026-07-15 10:20:20 +00:00

4449 lines
77 KiB
CSS

/* ============================================
Responsive Design System
============================================ */
/* Layout Utilities */
.container {
width: 100%;
max-width: min(1200px, 100vw - 2rem);
margin-inline: auto;
padding-inline: var(--space-4);
}
.stack {
display: flex;
flex-direction: column;
gap: var(--space-3);
}
.stack-sm {
gap: var(--space-2);
}
.stack-md {
gap: var(--space-3);
}
.stack-lg {
gap: var(--space-4);
}
.stack-xl {
gap: var(--space-5);
}
.row {
display: flex;
flex-wrap: wrap;
gap: var(--space-3);
align-items: center;
}
.row-sm {
gap: var(--space-2);
}
.row-md {
gap: var(--space-3);
}
.row-lg {
gap: var(--space-4);
}
.row.items-start,
.items-start {
align-items: flex-start;
}
.row.items-center,
.items-center {
align-items: center;
}
.row.items-end,
.items-end {
align-items: flex-end;
}
.justify-between {
justify-content: space-between;
}
.justify-center {
justify-content: center;
}
.justify-end {
justify-content: flex-end;
}
.flex-1 {
flex: 1;
}
.flex-2 {
flex: 2;
}
.flex-none {
flex: none;
}
.flex-wrap {
flex-wrap: wrap;
}
.min-h-0 {
min-height: 0;
}
.w-full {
width: 100%;
}
.w-fit {
width: fit-content;
}
.min-w-0 {
min-width: 0;
}
.max-w-prose {
max-width: 65ch;
}
.max-w-form {
max-width: 800px;
}
.grid {
display: grid;
gap: var(--space-4);
grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
}
/* Text Utilities */
.truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.text-xs {
font-size: var(--font-size-xs);
}
.text-sm {
font-size: var(--font-size-sm);
}
.text-base {
font-size: var(--font-size-base);
}
.text-lg {
font-size: var(--font-size-lg);
}
.text-xl {
font-size: var(--font-size-xl);
}
.font-mono {
font-family:
"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
monospace;
}
.font-medium {
font-weight: 500;
}
.font-semibold {
font-weight: 600;
}
.text-center {
text-align: center;
}
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
/* Visual Utilities */
.cursor-pointer {
cursor: pointer;
}
.overflow-auto {
overflow: auto;
}
.overflow-hidden {
overflow: hidden;
}
.rounded-sm {
border-radius: var(--radius-sm);
}
.rounded-md {
border-radius: var(--radius-md);
}
.rounded-lg {
border-radius: var(--radius-lg);
}
.rounded-xl {
border-radius: var(--radius-xl);
}
.rounded-full {
border-radius: var(--radius-full);
}
/* Spacing Utilities */
.m-0 {
margin: 0;
}
.mt-1 {
margin-top: var(--space-1);
}
.mt-2 {
margin-top: var(--space-2);
}
.mt-3 {
margin-top: var(--space-3);
}
.mt-4 {
margin-top: var(--space-4);
}
.mt-5 {
margin-top: var(--space-5);
}
.mt-6 {
margin-top: var(--space-6);
}
.mb-0 {
margin-bottom: 0;
}
.mb-1 {
margin-bottom: var(--space-1);
}
.mb-2 {
margin-bottom: var(--space-2);
}
.mb-3 {
margin-bottom: var(--space-3);
}
.mb-4 {
margin-bottom: var(--space-4);
}
.mb-5 {
margin-bottom: var(--space-5);
}
.mb-6 {
margin-bottom: var(--space-6);
}
.ml-auto {
margin-left: auto;
}
.mr-auto {
margin-right: auto;
}
.ml-1 {
margin-left: var(--space-1);
}
.ml-2 {
margin-left: var(--space-2);
}
.ml-3 {
margin-left: var(--space-3);
}
.mr-1 {
margin-right: var(--space-1);
}
.mr-2 {
margin-right: var(--space-2);
}
.mr-3 {
margin-right: var(--space-3);
}
.p-1 {
padding: var(--space-1);
}
.p-2 {
padding: var(--space-2);
}
.p-3 {
padding: var(--space-3);
}
.p-4 {
padding: var(--space-4);
}
.p-5 {
padding: var(--space-5);
}
.px-2 {
padding-left: var(--space-2);
padding-right: var(--space-2);
}
.px-3 {
padding-left: var(--space-3);
padding-right: var(--space-3);
}
.px-4 {
padding-left: var(--space-4);
padding-right: var(--space-4);
}
.py-1 {
padding-top: var(--space-1);
padding-bottom: var(--space-1);
}
.py-2 {
padding-top: var(--space-2);
padding-bottom: var(--space-2);
}
.py-3 {
padding-top: var(--space-3);
padding-bottom: var(--space-3);
}
.py-4 {
padding-top: var(--space-4);
padding-bottom: var(--space-4);
}
.pl-2 {
padding-left: var(--space-2);
}
.pl-3 {
padding-left: var(--space-3);
}
.pl-4 {
padding-left: var(--space-4);
}
.pr-2 {
padding-right: var(--space-2);
}
.pr-3 {
padding-right: var(--space-3);
}
.pr-4 {
padding-right: var(--space-4);
}
/* Border Utilities */
.border {
border: 1px solid var(--border);
}
.border-l {
border-left: 1px solid var(--border);
}
.border-l-2 {
border-left: 2px solid var(--border);
}
/* Card Utilities */
.card-sm {
padding: var(--space-3);
background: var(--panel);
border: 1px solid var(--border);
border-radius: var(--radius-md);
}
.card-md {
padding: var(--space-4);
background: var(--panel);
border: 1px solid var(--border);
border-radius: var(--radius-md);
}
.card-lg {
padding: var(--space-5);
background: var(--panel);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
}
.truncate-multiline {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.break-word {
overflow-wrap: break-word;
word-wrap: break-word;
hyphens: auto;
}
/* Touch Targets */
.button,
.nav-link,
.icon-button,
button,
[role="button"] {
min-height: var(--touch-target);
min-width: var(--touch-target);
}
/* Table Responsive */
.table-responsive {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.table-responsive table {
min-width: 100%;
}
/* Mobile-first Media Queries */
@media (max-width: 767px) {
/* Card layout for tables on mobile */
.table-responsive thead {
display: none;
}
.table-responsive tbody tr {
display: block;
margin-bottom: var(--space-4);
border: 1px solid var(--border);
border-radius: 8px;
padding: var(--space-4);
}
.table-responsive td {
display: flex;
justify-content: space-between;
padding: var(--space-2) 0;
border-bottom: 1px solid var(--border);
}
.table-responsive td:last-child {
border-bottom: none;
}
.table-responsive td::before {
content: attr(data-label);
font-weight: 600;
margin-right: var(--space-2);
}
/* Larger touch targets on mobile */
.button,
button {
padding: var(--space-3) var(--space-4);
}
/* Full-width inputs on mobile */
input,
select,
textarea {
width: 100%;
min-height: var(--touch-target);
}
}
/* Small devices */
@media (min-width: 480px) {
.container {
padding-inline: var(--space-5);
}
}
/* Medium devices */
@media (min-width: 768px) {
.container {
padding-inline: var(--space-6);
}
}
/* Large devices */
@media (min-width: 1024px) {
.container {
padding-inline: var(--space-8);
}
}
/* Extra large devices */
@media (min-width: 1280px) {
.container {
max-width: 1200px;
}
}
/* ============================================
Page-Specific Responsive Styles
============================================ */
/* Forms - Full width on mobile */
@media (max-width: 767px) {
.form-field input,
.form-field textarea,
.form-field select {
width: 100%;
min-height: var(--touch-target);
}
/* Settings page stack */
.settings-layout {
flex-direction: column;
}
.settings-nav {
flex-direction: row;
overflow-x: auto;
padding-bottom: var(--space-2);
}
/* Project cards full width */
.project-card {
flex-direction: column;
gap: var(--space-3);
}
.project-actions {
width: 100%;
justify-content: flex-start;
}
/* Repository cards */
.repository-card {
flex-direction: column;
gap: var(--space-3);
align-items: flex-start;
}
.repository-actions {
width: 100%;
justify-content: flex-start;
}
/* Git toolbar wrap */
.git-toolbar {
flex-wrap: wrap;
gap: var(--space-2);
}
/* Dashboard cards */
.dashboard-grid {
grid-template-columns: 1fr;
}
/* Stack form actions */
.form-actions {
flex-direction: column;
width: 100%;
}
.form-actions button {
width: 100%;
justify-content: center;
}
}
/* Ensure all pages have proper padding */
.stack > h1,
.stack > h2 {
margin-top: 0;
}
/* Touch target verification override */
button,
[role="button"],
a.nav-item,
.tree-entry {
min-height: var(--touch-target);
}
/* Table horizontal scroll wrapper */
.table-wrapper {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
width: 100%;
}
/* Prevent text overflow in cards */
.card h3,
.card p {
overflow: hidden;
text-overflow: ellipsis;
}
/* Session Navigation */
.session-item {
display: flex;
align-items: flex-start;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
text-align: left;
width: 100%;
}
.session-icon-wrap {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 1.25rem;
height: 1.25rem;
flex-shrink: 0;
margin-top: 2px;
}
.session-icon-wrap .icon {
margin-right: 0;
}
.session-status {
position: absolute;
top: -2px;
right: -3px;
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--muted);
border: 2px solid var(--panel);
}
.session-status.running {
background: var(--success);
}
.session-meta {
display: flex;
flex-direction: column;
min-width: 0;
flex: 1;
line-height: 1.25;
}
.session-workspace,
.session-context {
font-size: var(--font-size-xs);
color: var(--muted);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.session-display-name {
font-weight: 500;
color: var(--ink);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.nav-divider {
height: 1px;
background: var(--border);
margin: var(--space-2) var(--space-3);
}
.nav-section-title {
padding: var(--space-2) var(--space-4);
font-size: var(--text-xs);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--muted);
}
/* Instance List */
.instance-list {
margin-top: var(--space-4);
}
.instance-list-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-4);
}
.instance-list-header h3 {
margin: 0;
}
.instance-grid {
display: grid;
gap: var(--space-3);
}
.instance-card {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--space-4);
background: var(--bg);
border: 1px solid var(--border);
border-radius: 10px;
position: relative;
}
.instance-info {
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.instance-name {
font-weight: 600;
}
.instance-meta {
display: flex;
align-items: center;
gap: var(--space-2);
font-size: var(--text-sm);
color: var(--muted);
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.instance-actions {
display: flex;
gap: var(--space-2);
align-items: center;
}
/* ============================================
Loading Overlay
============================================ */
.loading-overlay {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.12);
backdrop-filter: blur(1px);
border-radius: inherit;
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
}
.loading-overlay-content {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-2);
color: var(--text, currentColor);
}
.loading-overlay-label {
font-size: var(--text-sm);
font-weight: 500;
}
.icon-spin {
animation: icon-spin 1s linear infinite;
}
@keyframes icon-spin {
to {
transform: rotate(360deg);
}
}
.session-card,
.tool-starter,
.create-session-form-wrapper {
position: relative;
}
/* ============================================
Terminal Styles
============================================ */
.terminal-page {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
padding: var(--space-4);
gap: var(--space-4);
overflow: hidden;
}
.terminal-page-header {
display: flex;
align-items: center;
gap: var(--space-4);
flex-shrink: 0;
}
.terminal-page-header h1 {
margin: 0;
}
.terminal-wrapper {
display: grid;
grid-template-rows: auto 1fr;
flex: 1;
min-height: 0;
max-height: 100%;
border: 1px solid var(--border);
border-radius: 10px;
overflow: hidden;
background: #1e1e1e;
}
/* When controls are hidden (fullscreen), only the container is in flow;
force it into the 1fr track so it fills the wrapper instead of landing
in the auto track and shrinking on each fit(). */
.terminal-wrapper.no-controls {
grid-template-rows: 1fr;
}
.terminal-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--space-3) var(--space-4);
background: #2d2d2d;
border-bottom: 1px solid #3e3e3e;
flex-shrink: 0;
}
.terminal-status {
display: flex;
align-items: center;
gap: var(--space-2);
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #666;
}
.status-dot.connecting {
background: #f5f543;
animation: pulse 1.5s infinite;
}
.status-dot.connected {
background: #0dbc79;
}
.status-dot.disconnected,
.status-dot.error {
background: #cd3131;
}
@keyframes pulse {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
.status-text {
font-size: 0.875rem;
color: #d4d4d4;
text-transform: capitalize;
}
.terminal-close {
padding: var(--space-1) var(--space-3);
background: transparent;
border: 1px solid #666;
border-radius: 6px;
color: #d4d4d4;
cursor: pointer;
font-size: 0.875rem;
}
.terminal-close:hover {
background: #3e3e3e;
}
.terminal-error {
padding: var(--space-3) var(--space-4);
background: #cd3131;
color: white;
font-size: 0.875rem;
flex-shrink: 0;
}
.terminal-container {
position: relative;
width: 100%;
height: 100%;
min-height: 0;
padding: 0;
overflow: hidden;
}
/* Let xterm.js's own viewport handle touch; we only lock the outer page */
.terminal-container .xterm-viewport {
touch-action: auto;
overscroll-behavior: auto;
max-height: 100% !important;
width: 100% !important;
/* Full-screen TUI tools repaint in place; scrollback is 0 (see terminal.tsx).
Hide the viewport scrollbar so it never appears or captures input. */
scrollbar-width: none;
-ms-overflow-style: none;
}
.terminal-container .xterm-viewport::-webkit-scrollbar {
display: none;
}
/* On mobile the custom touch handler scrolls the buffer; disable native
panning/overscroll so swipe gestures are not forwarded to a scrollbar. */
.terminal-wrapper.mobile .terminal-container,
.terminal-wrapper.mobile .terminal-container .xterm-viewport {
touch-action: none;
overscroll-behavior: none;
}
/* xterm.js manages its own positioning and sizing */
.terminal-container canvas {
display: block;
}
/* xterm.js manages its own viewport dimensions - do not override */
/* Mobile terminal container - no padding to maximize space */
.terminal-wrapper.mobile .terminal-container {
padding: 0;
}
.terminal-wrapper.mobile {
touch-action: none;
overscroll-behavior: none;
}
/* Ensure xterm viewport fills container properly */
/* Responsive terminal */
@media (max-width: 767px) {
.terminal-page {
padding: var(--space-2);
gap: var(--space-2);
}
.terminal-page-header h1 {
font-size: 1.25rem;
}
}
/* ============================================
Terminal Session Tabs
============================================ */
.terminal-session-tabs {
display: flex;
flex-shrink: 0;
background: #2d2d2d;
border-bottom: 1px solid #3e3e3e;
overflow: hidden;
}
.terminal-session-tabs.mobile {
background: #1e1e1e;
}
.terminal-session-tabs-scroll {
display: flex;
gap: 2px;
padding: var(--space-1) var(--space-2);
overflow-x: auto;
scrollbar-width: thin;
scrollbar-color: #555 transparent;
flex: 1;
min-width: 0;
}
.terminal-session-tabs-scroll::-webkit-scrollbar {
height: 4px;
}
.terminal-session-tabs-scroll::-webkit-scrollbar-thumb {
background: #555;
border-radius: 2px;
}
.terminal-session-tab {
display: flex;
align-items: center;
gap: var(--space-1);
padding: var(--space-1) var(--space-2);
border: 1px solid transparent;
border-radius: 6px;
background: transparent;
color: #888;
cursor: pointer;
font-size: 0.8125rem;
white-space: nowrap;
transition:
background 0.15s,
color 0.15s,
border-color 0.15s;
user-select: none;
min-width: 0;
}
.terminal-session-tab:hover {
background: #3e3e3e;
color: #ccc;
}
.terminal-session-tab.active {
background: #1e1e1e;
color: #d4d4d4;
border-color: #3e3e3e;
}
.terminal-session-tab-status {
width: 6px;
height: 6px;
border-radius: 50%;
flex-shrink: 0;
}
.terminal-session-tab-status.connecting {
background: #f5f543;
animation: pulse 1.5s infinite;
}
.terminal-session-tab-status.connected {
background: #0dbc79;
}
.terminal-session-tab-status.disconnected,
.terminal-session-tab-status.error {
background: #cd3131;
}
.terminal-session-tab-name {
max-width: 120px;
overflow: hidden;
text-overflow: ellipsis;
}
.terminal-session-tab-input {
background: #1e1e1e;
border: 1px solid var(--brand);
border-radius: 4px;
color: #d4d4d4;
font-size: 0.8125rem;
padding: 1px 4px;
width: 100px;
outline: none;
}
.terminal-session-tab-close {
display: flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
padding: 0;
margin: 0;
background: transparent;
border: none;
color: #888;
cursor: pointer;
font-size: 0.875rem;
line-height: 1;
border-radius: 3px;
opacity: 0;
transition:
opacity 0.15s,
background 0.15s;
}
.terminal-session-tab:hover .terminal-session-tab-close {
opacity: 1;
}
.terminal-session-tab-close:hover {
background: #cd3131;
color: white;
}
.terminal-session-tab-confirm {
font-size: 0.6875rem;
color: #cd3131;
padding: 1px 4px;
border-radius: 3px;
background: rgba(205, 49, 49, 0.15);
white-space: nowrap;
}
.terminal-session-tab.new-session {
font-weight: 600;
font-size: 1rem;
line-height: 1;
padding: var(--space-1) var(--space-2);
color: #888;
}
.terminal-session-tab.new-session:hover {
background: #3e3e3e;
color: #d4d4d4;
}
.terminal-session-tab.new-session:disabled {
opacity: 0.4;
cursor: not-allowed;
}
/* Terminal page with multi-session */
.terminal-page-content {
display: flex;
flex-direction: column;
flex: 1;
min-height: 0;
border: 1px solid var(--border);
border-radius: 10px;
overflow: hidden;
background: #1e1e1e;
}
.terminal-instance {
flex: 1;
min-height: 0;
max-height: 100%;
display: none;
overflow: hidden;
}
.terminal-instance.active {
display: flex;
}
.terminal-empty-state {
display: flex;
align-items: center;
justify-content: center;
flex: 1;
color: #888;
font-size: 0.875rem;
}
.terminal-error-banner {
padding: var(--space-2) var(--space-4);
background: var(--danger-light);
color: var(--danger);
font-size: 0.875rem;
border-bottom: 1px solid var(--danger-light);
}
/* Fullscreen mode */
.terminal-page.fullscreen {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
padding: 8px;
gap: 8px;
background: #1e1e1e;
}
.terminal-page.fullscreen .terminal-page-content {
border: none;
border-radius: 0;
}
/* Unified fullscreen header: session tabs + terminal controls */
.terminal-fullscreen-header {
display: flex;
align-items: center;
justify-content: space-between;
background: #2d2d2d;
border-bottom: 1px solid #3e3e3e;
flex-shrink: 0;
min-height: 0;
}
.terminal-fullscreen-header-tabs {
flex: 1;
min-width: 0;
overflow: hidden;
}
.terminal-fullscreen-header-tabs .terminal-session-tabs {
background: transparent;
border-bottom: none;
}
.terminal-fullscreen-header-controls {
display: flex;
align-items: center;
gap: var(--space-2);
padding: 0 var(--space-3);
flex-shrink: 0;
border-left: 1px solid #3e3e3e;
}
.terminal-fullscreen-status {
width: 8px;
height: 8px;
border-radius: 50%;
background: #666;
flex-shrink: 0;
}
.terminal-fullscreen-status.connecting {
background: #f5f543;
animation: pulse 1.5s infinite;
}
.terminal-fullscreen-status.connected {
background: #0dbc79;
}
.terminal-fullscreen-status.disconnected,
.terminal-fullscreen-status.error {
background: #cd3131;
}
/* ============================================
Mobile Terminal Overlay
============================================ */
/* Mobile terminal page — no padding, terminal fills viewport, locked in place */
.terminal-page.mobile {
padding: 0;
gap: 0;
height: 100vh;
height: 100dvh;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
touch-action: none;
overscroll-behavior: none;
}
/* Overlay status bar — floats over terminal; only its buttons consume pointer events */
.mobile-terminal-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 100;
background: #2d2d2d;
border-bottom: 1px solid #3e3e3e;
pointer-events: none;
transition:
transform 0.3s ease,
opacity 0.3s ease;
}
.mobile-terminal-overlay.visible {
pointer-events: auto;
}
.mobile-terminal-overlay > *,
.mobile-terminal-overlay-tabs {
pointer-events: auto;
}
.mobile-terminal-overlay.hidden {
transform: translateY(-100%);
opacity: 0;
pointer-events: none;
}
.mobile-terminal-overlay.visible {
transform: translateY(0);
opacity: 1;
}
/* Toolbar row */
.mobile-terminal-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--space-2) var(--space-3);
gap: var(--space-2);
}
.mobile-terminal-toolbar-left,
.mobile-terminal-toolbar-right {
display: flex;
align-items: center;
gap: var(--space-1);
flex: 0 0 auto;
}
.mobile-terminal-toolbar-center {
display: flex;
align-items: center;
gap: var(--space-2);
flex: 1;
justify-content: center;
min-width: 0;
}
.mobile-terminal-title {
font-size: 0.875rem;
font-weight: 500;
color: #d4d4d4;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mobile-terminal-status {
width: 8px;
height: 8px;
border-radius: 50%;
background: #666;
flex-shrink: 0;
}
.mobile-terminal-status.connecting {
background: #f5f543;
animation: pulse 1.5s infinite;
}
.mobile-terminal-status.connected {
background: #0dbc79;
}
.mobile-terminal-status.disconnected,
.mobile-terminal-status.error {
background: #cd3131;
}
.mobile-terminal-toolbtn {
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
padding: 0;
background: transparent;
border: 1px solid #3e3e3e;
border-radius: 6px;
color: #d4d4d4;
cursor: pointer;
font-size: 0.875rem;
transition: background 0.2s ease;
}
.mobile-terminal-toolbtn:hover {
background: #3e3e3e;
}
/* Session tabs inside overlay */
.mobile-terminal-overlay-tabs {
background: #1e1e1e;
border-top: 1px solid #3e3e3e;
}
.mobile-terminal-overlay-tabs .terminal-session-tabs {
background: #1e1e1e;
border-bottom: none;
}
/* Terminal content — always fills full viewport on mobile, locked against page scroll */
.terminal-page-content.mobile-full {
flex: 1;
min-height: 0;
border: none;
border-radius: 0;
overflow: hidden;
touch-action: none;
overscroll-behavior: none;
}
/* Mobile fullscreen */
@media (max-width: 767px) {
.terminal-page.fullscreen {
padding: 0;
}
.terminal-session-tab-name {
max-width: 80px;
}
}
/* ============================================
Sessions Page Styles
============================================ */
.nav-badge {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 18px;
height: 18px;
padding: 0 5px;
background: var(--primary);
color: var(--primary-fg);
border-radius: 9px;
font-size: 11px;
font-weight: 600;
margin-left: auto;
}
.sessions-page {
max-width: 1200px;
}
.last-session-section {
margin-bottom: var(--space-6);
}
.last-session-card {
display: flex;
justify-content: space-between;
align-items: center;
gap: var(--space-4);
padding: var(--space-5);
border: 2px solid var(--primary);
}
.last-session-info h3 {
margin: 0 0 var(--space-1) 0;
font-size: 1.25rem;
}
.active-sessions-section {
position: relative;
margin-bottom: var(--space-6);
}
.active-sessions-section.dimmed {
opacity: 0.5;
pointer-events: none;
}
.active-sessions-section h2 {
display: flex;
align-items: center;
gap: var(--space-2);
}
.active-sessions-section .badge {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 24px;
height: 24px;
padding: 0 6px;
background: var(--success);
color: white;
border-radius: 12px;
font-size: 12px;
font-weight: 600;
}
.sessions-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: var(--space-4);
}
.session-card {
display: flex;
flex-direction: column;
gap: var(--space-3);
padding: var(--space-4);
}
.session-info h4 {
margin: 0 0 var(--space-1) 0;
font-size: 1rem;
}
.session-url {
margin: var(--space-1) 0;
font-size: 0.8rem;
word-break: break-all;
}
.session-url a {
color: var(--color-primary);
text-decoration: none;
}
.session-url a:hover {
text-decoration: underline;
}
.session-actions {
display: flex;
gap: var(--space-2);
}
/* Session Card - Unified Component */
.session-card-content {
flex: 1;
}
.session-card-header {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.session-card-title {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: var(--space-2);
}
.session-card-title h4 {
margin: 0;
font-size: 1rem;
font-weight: 600;
}
.session-card-status-badges {
display: flex;
gap: var(--space-1);
flex-wrap: wrap;
}
.session-card-meta {
font-size: 0.85rem;
margin: 0;
}
.session-card-meta .icon {
margin-right: var(--space-1);
vertical-align: text-bottom;
}
.session-card-url {
margin: var(--space-1) 0;
font-size: 0.8rem;
word-break: break-all;
}
.session-card-url a {
color: var(--color-primary);
text-decoration: none;
}
.session-card-url a:hover {
text-decoration: underline;
}
.session-card-actions {
display: flex;
gap: var(--space-2);
flex-wrap: wrap;
margin-top: var(--space-2);
padding-top: var(--space-3);
border-top: 1px solid var(--color-border);
}
/* Session List - Unified Component */
.session-list {
display: flex;
flex-direction: column;
gap: var(--space-6);
}
.session-group {
display: flex;
flex-direction: column;
gap: var(--space-3);
}
.session-group-header {
display: flex;
align-items: center;
gap: var(--space-2);
}
.session-group-header h3 {
margin: 0;
font-size: 1.1rem;
font-weight: 600;
}
/* Action labels - hidden on mobile */
.action-label {
margin-left: var(--space-1);
}
@media (max-width: 640px) {
.action-label {
display: none;
}
.session-card-actions {
gap: var(--space-1);
}
.session-card-actions button,
.session-card-actions a {
padding: var(--space-1);
}
}
.recent-sessions-section {
margin-bottom: var(--space-6);
}
/* Loading overlay for sessions */
.sessions-grid {
position: relative;
}
.sessions-grid.dimmed {
opacity: 0.5;
pointer-events: none;
}
.recent-sessions-list {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.recent-session-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--space-3) var(--space-4);
background: var(--bg);
border: 1px solid var(--border);
border-radius: 8px;
}
.recent-session-info {
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.recent-session-name {
font-weight: 500;
}
.recent-session-actions {
display: flex;
gap: var(--space-2);
align-items: center;
}
.delete-confirm-inline,
.stop-confirm-inline {
display: flex;
gap: var(--space-2);
align-items: center;
}
.confirm-text {
font-size: 13px;
color: var(--muted);
font-weight: 500;
}
.create-session-section {
position: relative;
margin-bottom: var(--space-6);
}
.create-session-section.dimmed {
opacity: 0.5;
pointer-events: none;
}
.create-session-form {
max-width: 600px;
}
.create-session-form .form-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: var(--space-4);
}
.status-badge {
display: inline-flex;
align-items: center;
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
text-transform: capitalize;
}
.status-badge.running {
background: var(--success-light, #dcfce7);
color: var(--success, #16a34a);
}
.status-badge.stopped {
background: var(--muted-bg, #f3f4f6);
color: var(--muted, #6b7280);
}
.status-badge.pending {
background: var(--warning-light, #fef3c7);
color: var(--warning, #d97706);
}
.status-badge.error {
background: var(--danger-light, #fee2e2);
color: var(--danger, #dc2626);
}
.status-badge.starting,
.status-badge.probing {
background: var(--info-light, #dbeafe);
color: var(--info, #2563eb);
}
.status-badge.unhealthy {
background: var(--warning-light, #fef3c7);
color: var(--warning, #d97706);
}
/* ============================================
Mobile Terminal Styles
============================================ */
/* Mobile terminal shell - fills viewport */
.shell.mobile-terminal-shell {
height: 100vh;
height: 100dvh;
overflow: hidden;
display: flex;
flex-direction: column;
}
.mobile-terminal-wrapper {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
background: #1e1e1e;
position: relative;
overflow: hidden;
}
/* Mobile Terminal Header */
.mobile-terminal-header {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--space-2) var(--space-3);
background: #2d2d2d;
border-bottom: 1px solid #3e3e3e;
transition:
transform 0.3s ease,
opacity 0.3s ease,
height 0.3s ease,
padding 0.3s ease,
margin 0.3s ease;
z-index: 100;
overflow: hidden;
}
.mobile-terminal-header.hidden {
transform: translateY(-100%);
opacity: 0;
pointer-events: none;
height: 0;
padding-top: 0;
padding-bottom: 0;
margin-top: 0;
margin-bottom: 0;
border-width: 0;
flex-shrink: 1;
}
.mobile-terminal-header.visible {
transform: translateY(0);
opacity: 1;
height: auto;
}
.mobile-terminal-header-left,
.mobile-terminal-header-right {
display: flex;
align-items: center;
gap: var(--space-2);
flex: 0 0 auto;
}
.mobile-terminal-header-center {
display: flex;
align-items: center;
gap: var(--space-2);
flex: 1;
justify-content: center;
min-width: 0;
}
.mobile-terminal-header-title {
font-size: 0.875rem;
font-weight: 500;
color: #d4d4d4;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mobile-terminal-header-button {
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
padding: 0;
background: transparent;
border: 1px solid #3e3e3e;
border-radius: 6px;
color: #d4d4d4;
cursor: pointer;
font-size: 0.875rem;
transition: background 0.2s ease;
}
.mobile-terminal-header-button:hover {
background: #3e3e3e;
}
.mobile-terminal-header-status {
width: 8px;
height: 8px;
border-radius: 50%;
background: #666;
flex-shrink: 0;
}
.mobile-terminal-header-status.connecting {
background: #f5f543;
animation: pulse 1.5s infinite;
}
.mobile-terminal-header-status.connected {
background: #0dbc79;
}
.mobile-terminal-header-status.disconnected,
.mobile-terminal-header-status.error {
background: #cd3131;
}
/* Mobile Terminal Content */
.mobile-terminal-content {
flex: 1;
min-height: 0;
overflow: hidden;
position: relative;
background: #1e1e1e;
display: flex;
flex-direction: column;
}
/* Terminal wrapper - fills content area */
.terminal-wrapper.mobile {
border: none;
border-radius: 0;
flex: 1;
min-height: 0;
width: 100%;
overflow: hidden;
display: flex;
flex-direction: column;
}
.terminal-wrapper.mobile .terminal-container {
width: 100%;
flex: 1;
min-height: 0;
padding: 0;
overflow: hidden;
position: relative;
touch-action: none;
}
/* xterm.js manages its own sizing */
/* xterm.js manages its own scrolling and viewport dimensions */
/* Special Keys Strip */
.special-keys-strip {
flex-shrink: 0;
display: flex;
align-items: center;
gap: 2px;
padding: var(--space-1) var(--space-2);
background: #2d2d2d;
border-top: 1px solid #3e3e3e;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
transition:
transform 0.3s ease,
opacity 0.3s ease;
z-index: 100;
}
.special-keys-strip.hidden {
transform: translateY(100%);
opacity: 0;
pointer-events: none;
}
.special-keys-strip.visible {
transform: translateY(0);
opacity: 1;
}
.special-keys-strip::-webkit-scrollbar {
display: none;
}
.special-key-button {
display: flex;
align-items: center;
justify-content: center;
min-width: var(--touch-target);
height: 44px;
padding: 0 var(--space-2);
background: #3e3e3e;
border: 1px solid #4e4e4e;
border-radius: 6px;
color: #d4d4d4;
font-size: 0.75rem;
font-weight: 500;
cursor: pointer;
white-space: nowrap;
flex-shrink: 0;
transition:
background 0.15s ease,
transform 0.1s ease;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
}
.special-key-button:active {
background: #4e4e4e;
transform: scale(0.95);
}
.special-key-more {
background: #2472c8;
border-color: #2472c8;
color: white;
}
.special-key-more:active {
background: #1e5fa8;
}
.special-key-button.active-modifier {
background: #f5f543;
color: #1e1e1e;
border-color: #f5f543;
font-weight: 700;
box-shadow: 0 0 8px rgba(245, 245, 67, 0.5);
}
/* Special Keys Panel */
.special-keys-panel-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 200;
display: flex;
align-items: flex-end;
justify-content: center;
}
.special-keys-panel {
background: #2d2d2d;
border-top: 1px solid #3e3e3e;
border-radius: 12px 12px 0 0;
padding: var(--space-4);
width: 100%;
max-height: 70vh;
overflow-y: auto;
animation: slideUp 0.2s ease;
}
.special-keys-panel-section {
display: flex;
flex-wrap: wrap;
gap: var(--space-2);
margin-bottom: var(--space-3);
}
.special-keys-panel-section:last-child {
margin-bottom: 0;
}
.special-keys-panel-divider {
height: 1px;
background: #3e3e3e;
margin: var(--space-3) 0;
}
/* Terminal Component Updates */
/* Note: .terminal-wrapper.mobile is defined above with position: absolute to fill grid cell */
.terminal-wrapper.mobile .terminal-header {
display: none;
}
.terminal-header-left {
display: flex;
align-items: center;
gap: var(--space-2);
}
.terminal-header-right {
display: flex;
align-items: center;
gap: var(--space-2);
}
.terminal-header-button {
padding: var(--space-1) var(--space-2);
background: transparent;
border: 1px solid #666;
border-radius: 4px;
color: #d4d4d4;
cursor: pointer;
font-size: 0.75rem;
transition: background 0.2s ease;
}
.terminal-header-button:hover {
background: #3e3e3e;
}
.terminal-reconnect {
margin-left: var(--space-2);
padding: var(--space-1) var(--space-2);
background: #2472c8;
border: none;
border-radius: 4px;
color: white;
cursor: pointer;
font-size: 0.75rem;
}
.terminal-reset-confirm {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.8);
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
}
.terminal-reset-confirm-content {
background: var(--bg-surface);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: var(--space-4);
max-width: 400px;
text-align: center;
}
.terminal-reset-confirm-content p {
margin: 0 0 var(--space-4) 0;
color: var(--text-primary);
}
.terminal-reset-confirm-buttons {
display: flex;
gap: var(--space-2);
justify-content: center;
}
.terminal-reset-confirm-button {
padding: var(--space-2) var(--space-4);
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 0.875rem;
}
.terminal-reset-confirm-button.cancel {
background: var(--bg-elevated);
color: var(--text-primary);
}
.terminal-reset-confirm-button.confirm {
background: #cd3131;
color: white;
}
.terminal-hidden-input {
position: fixed;
left: -9999px;
top: -9999px;
width: 1px;
height: 1px;
opacity: 0;
pointer-events: none;
user-select: none;
-webkit-user-select: none;
}
/* Disable zoom on mobile terminal */
@media (max-width: 767px) {
.mobile-terminal-wrapper {
touch-action: none;
-webkit-text-size-adjust: none;
}
.mobile-terminal-wrapper button,
.mobile-terminal-wrapper .special-key-button {
touch-action: manipulation;
}
.terminal-container {
touch-action: none;
padding: 0;
}
.terminal-wrapper.mobile .terminal-container .xterm-viewport {
touch-action: none;
overscroll-behavior: none;
}
}
/* Animations */
@keyframes slideUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
@keyframes pulse {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
/* Mobile Menu Overlay */
.mobile-menu-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 50;
}
.mobile-menu-close {
position: absolute;
top: var(--space-2);
right: var(--space-2);
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
background: transparent;
border: none;
color: var(--text);
cursor: pointer;
}
/* AppShell mobile menu */
@media (max-width: 767px) {
.shell-nav {
position: fixed;
top: 0;
left: 0;
bottom: 0;
width: 260px;
background: var(--bg);
z-index: 100;
transform: translateX(-100%);
transition: transform 0.3s ease;
padding-top: var(--space-8);
}
.shell-nav.mobile-open {
transform: translateX(0);
}
}
/* Mobile Navigation */
.mobile-nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-around;
align-items: center;
background: var(--panel);
border-top: 1px solid var(--border);
padding-bottom: env(safe-area-inset-bottom, 0);
z-index: 100;
height: var(--mobile-nav-height);
}
.mobile-nav-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 2px;
padding: 8px 12px;
color: var(--muted);
text-decoration: none;
font-size: 11px;
min-width: 64px;
min-height: var(--touch-target);
border-radius: 8px;
transition: color 0.15s ease;
}
.mobile-nav-item.active {
color: var(--brand);
}
.mobile-nav-icon-wrapper {
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.mobile-nav-badge {
position: absolute;
top: -6px;
right: -8px;
background: var(--danger);
color: white;
font-size: 10px;
font-weight: 600;
min-width: 16px;
height: 16px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
padding: 0 4px;
}
/* Mobile Bottom Sheet */
.mobile-bottom-sheet-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 200;
display: flex;
align-items: flex-end;
justify-content: center;
}
.mobile-bottom-sheet {
background: var(--panel);
border-radius: 16px 16px 0 0;
width: 100%;
max-width: 600px;
max-height: 70vh;
max-height: 70dvh;
display: flex;
flex-direction: column;
min-height: 0;
animation: slide-up 0.2s ease-out;
}
@keyframes slide-up {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
.mobile-bottom-sheet-header {
display: flex;
flex-direction: column;
align-items: center;
padding: 12px 16px 8px;
border-bottom: 1px solid var(--border);
}
.mobile-bottom-sheet-handle {
width: 36px;
height: 4px;
background: var(--border);
border-radius: 2px;
margin-bottom: 8px;
}
.mobile-bottom-sheet-title {
font-size: 16px;
font-weight: 600;
margin: 0;
}
.mobile-bottom-sheet-content {
flex: 1;
min-height: 0;
padding: 8px 0;
overflow-y: auto;
overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
}
.mobile-bottom-sheet-item {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 16px;
background: none;
border: none;
color: var(--text);
font-size: 16px;
text-align: left;
cursor: pointer;
min-height: var(--touch-target);
}
.mobile-bottom-sheet-item:active {
background: var(--hover);
}
.mobile-bottom-sheet-item.active {
color: var(--brand);
}
/* Mobile List View */
.mobile-list-view {
display: flex;
flex-direction: column;
gap: var(--space-3);
}
.mobile-list-items {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.mobile-list-item {
display: flex;
align-items: center;
gap: var(--space-3);
width: 100%;
padding: var(--space-3);
background: var(--panel);
border: 1px solid var(--border);
border-radius: 10px;
color: var(--text);
text-align: left;
cursor: pointer;
min-height: 56px;
}
.mobile-list-item:active {
background: var(--bg);
}
.mobile-list-item-icon {
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
color: var(--muted);
}
.mobile-list-item-content {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.mobile-list-item-title {
font-weight: 600;
font-size: var(--font-size-base);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mobile-list-item-subtitle {
font-size: var(--font-size-sm);
color: var(--muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mobile-list-item-actions {
display: flex;
align-items: center;
gap: var(--space-1);
flex-shrink: 0;
color: var(--muted);
}
.mobile-list-item-action {
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
padding: 0;
background: transparent;
border: 1px solid var(--border);
border-radius: 8px;
color: var(--muted);
cursor: pointer;
}
.mobile-list-item-action:active {
background: var(--bg);
}
.mobile-list-item-action-delete {
color: var(--danger);
border-color: var(--danger);
}
.mobile-list-item-action-delete:active {
background: var(--danger-light);
}
.mobile-list-empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: var(--space-3);
padding: var(--space-10) var(--space-4);
color: var(--muted);
text-align: center;
}
.mobile-list-empty p {
margin: 0;
}
/* Rich project rows */
.mobile-list-item-content-rich {
gap: var(--space-2);
}
.mobile-list-item-description {
margin: 0;
font-size: var(--font-size-sm);
color: var(--muted);
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.mobile-list-item-chips {
display: flex;
flex-wrap: wrap;
gap: var(--space-1);
margin-top: var(--space-1);
}
.mobile-list-item-chip {
font-size: var(--font-size-xs);
padding: var(--space-1) var(--space-2);
background: var(--bg);
border: 1px solid var(--border);
border-radius: 999px;
color: var(--ink);
}
.mobile-list-item-chip.muted {
color: var(--muted);
font-style: italic;
background: transparent;
}
/* Mobile Page */
.mobile-page {
padding: var(--space-2);
padding-bottom: calc(var(--space-4) + 64px);
min-height: 100%;
}
/* Mobile Edit View */
.mobile-edit-view {
display: flex;
flex-direction: column;
min-height: 100%;
background: var(--bg);
}
.mobile-edit-header {
position: sticky;
top: 0;
z-index: 10;
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
background: var(--panel);
border-bottom: 1px solid var(--border);
}
.mobile-edit-cancel,
.mobile-edit-save,
.mobile-edit-delete {
min-height: var(--touch-target);
padding: var(--space-2) var(--space-3);
border-radius: 10px;
font: inherit;
font-size: 0.9375rem;
cursor: pointer;
}
.mobile-edit-cancel {
background: transparent;
border: 1px solid var(--border);
color: var(--text);
}
.mobile-edit-save {
background: var(--brand);
border: 1px solid var(--brand);
color: white;
}
.mobile-edit-delete {
background: var(--danger-light);
border: 1px solid var(--danger);
color: var(--danger);
}
.mobile-edit-save:disabled,
.mobile-edit-cancel:disabled,
.mobile-edit-delete:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.mobile-edit-title {
font-size: 1rem;
font-weight: 600;
margin: 0;
flex: 1;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mobile-edit-form {
flex: 1;
overflow-y: auto;
padding: var(--space-3);
padding-bottom: calc(var(--space-3) + 148px);
}
/* Mobile Edit Actions (sticky bottom bar) */
.mobile-edit-actions {
position: fixed;
left: 0;
right: 0;
bottom: var(--mobile-nav-height);
z-index: 110;
display: flex;
flex-direction: column;
gap: var(--space-2);
padding: var(--space-3);
padding-bottom: calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
background: var(--panel);
border-top: 1px solid var(--border);
box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.08);
}
.mobile-edit-actions .mobile-edit-save,
.mobile-edit-actions .mobile-edit-delete {
width: 100%;
justify-content: center;
min-height: 48px;
}
.mobile-edit-field {
margin-bottom: var(--space-3);
}
.mobile-edit-field-label {
display: block;
font-size: 0.875rem;
font-weight: 500;
margin-bottom: var(--space-2);
}
.mobile-edit-input,
.mobile-edit-textarea,
.mobile-edit-select {
width: 100%;
padding: var(--space-3);
border: 1px solid var(--border);
border-radius: 10px;
background: var(--panel);
color: var(--text);
font: inherit;
min-height: var(--touch-target);
}
.mobile-edit-textarea {
resize: vertical;
min-height: 96px;
}
.mobile-edit-code {
font-family:
"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
monospace;
font-size: 0.8125rem;
}
.mobile-edit-checkbox {
display: flex;
align-items: center;
gap: var(--space-2);
cursor: pointer;
}
.mobile-edit-checkbox input {
width: 22px;
height: 22px;
accent-color: var(--brand);
}
/* Mobile Profile */
.profile-mobile-avatar-section {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-3);
padding: var(--space-6) var(--space-3);
margin-bottom: var(--space-2);
}
.profile-mobile-avatar {
width: 96px;
height: 96px;
border-radius: 50%;
overflow: hidden;
background: var(--bg);
border: 2px solid var(--border);
flex-shrink: 0;
}
.profile-mobile-avatar-image {
width: 100%;
height: 100%;
object-fit: cover;
}
.profile-mobile-avatar-placeholder {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 2.5rem;
font-weight: 600;
color: var(--muted);
background: var(--bg);
}
/* Mobile Page Header */
.mobile-page-header {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-2) 0;
margin-bottom: var(--space-3);
border-bottom: 1px solid var(--border);
}
.mobile-page-header-back {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
background: transparent;
border: none;
color: var(--text);
cursor: pointer;
border-radius: 8px;
padding: 0;
}
.mobile-page-header-back:active {
background: var(--color-border);
}
.mobile-page-header h1 {
margin: 0;
font-size: 1.1rem;
font-weight: 600;
flex: 1;
}
.mobile-page-header-actions {
display: flex;
gap: var(--space-2);
}
.mobile-nav-label {
font-size: 11px;
font-weight: 500;
}
/* Mobile shell content padding adjustment */
.shell-content.mobile {
padding-bottom: calc(var(--mobile-nav-height) + var(--space-3));
}
/* Mobile form actions (bottom button row) */
.mobile-form-actions {
display: flex;
flex-direction: column;
gap: var(--space-2);
padding: var(--space-3) var(--space-2);
margin-top: auto;
}
.mobile-form-actions .primary-button,
.mobile-form-actions .secondary-button,
.mobile-form-actions .ghost-button,
.mobile-form-actions .danger-button {
width: 100%;
justify-content: center;
min-height: 48px;
}
/* Mobile form group (inline fields) */
.mobile-form-group {
padding: var(--space-3);
background: var(--panel);
border-radius: 8px;
border: 1px solid var(--border);
margin-bottom: var(--space-2);
}
.mobile-form-label {
display: block;
font-size: 0.875rem;
font-weight: 500;
margin-bottom: var(--space-2);
color: var(--text);
}
.mobile-form-input,
.mobile-form-select,
.mobile-form-textarea {
width: 100%;
padding: var(--space-3);
border: 1px solid var(--border);
border-radius: 10px;
background: var(--bg);
color: var(--text);
font: inherit;
min-height: var(--touch-target);
}
.mobile-form-textarea {
resize: vertical;
min-height: 96px;
}
.mobile-form-code {
font-family:
"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
monospace;
font-size: 0.8125rem;
}
.mobile-form-select {
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 0.75rem center;
padding-right: 2.5rem;
}
.mobile-form-checkbox-label {
display: flex;
align-items: center;
gap: var(--space-2);
font-weight: 500;
cursor: pointer;
}
.mobile-form-checkbox {
width: 22px;
height: 22px;
min-width: 22px;
min-height: 22px;
accent-color: var(--brand);
cursor: pointer;
}
.mobile-form-help {
display: block;
font-size: 0.8125rem;
color: var(--muted);
margin-top: var(--space-1);
}
.mobile-form-error {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-3);
background: var(--danger-light);
color: var(--danger);
border-radius: 10px;
font-size: 0.875rem;
margin: var(--space-2) 0;
}
.mobile-discard-button {
width: 100%;
justify-content: center;
margin-top: var(--space-2);
}
/* Manifest editor responsive overrides inside mobile forms */
.mobile-manifest-editor-wrapper .card {
padding: var(--space-3);
margin-bottom: var(--space-3);
}
.mobile-manifest-editor-wrapper .row {
flex-direction: column;
align-items: stretch;
gap: var(--space-2);
}
.mobile-manifest-editor-wrapper .form-group,
.mobile-manifest-editor-wrapper input,
.mobile-manifest-editor-wrapper select,
.mobile-manifest-editor-wrapper textarea {
width: 100%;
min-width: 0;
}
.mobile-manifest-editor-wrapper input[style*="width:"] {
width: 100% !important;
}
/* Mobile config profile form extras */
.mobile-form-group p {
margin: 0;
}
.mobile-form-row {
display: flex;
align-items: center;
}
.mobile-form-section {
padding: var(--space-3);
background: var(--panel);
border-radius: 8px;
border: 1px solid var(--border);
margin-bottom: var(--space-2);
}
.mobile-form-section-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: var(--space-3);
}
.mobile-form-section-header h4 {
margin: 0;
font-size: 1rem;
}
.mobile-add-button {
width: 100%;
justify-content: center;
margin-top: var(--space-2);
}
.mobile-form-success {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-3);
background: var(--success-light);
color: var(--success);
border-radius: 10px;
font-size: 0.875rem;
margin: var(--space-2) 0;
}
.mobile-list-plain {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.mobile-list-plain li {
padding: var(--space-2);
background: var(--bg);
border-radius: 6px;
font-size: 0.875rem;
}
/* Mobile detail extra actions */
.mobile-detail-actions-extra {
padding: var(--space-3);
padding-top: 0;
margin-top: calc(var(--space-2) * -1);
}
.mobile-detail-actions-extra .secondary-button {
width: 100%;
justify-content: center;
}
/* Mobile includes */
.mobile-includes-list {
display: flex;
flex-direction: column;
gap: var(--space-2);
margin-bottom: var(--space-3);
}
.mobile-include-item {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
background: var(--bg);
border: 1px solid var(--border);
border-radius: 8px;
}
.mobile-include-name {
flex: 1;
font-weight: 500;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.mobile-include-scope {
font-size: 0.75rem;
padding: 0.125rem 0.5rem;
background: var(--bg);
color: var(--muted);
border-radius: 999px;
text-transform: uppercase;
letter-spacing: 0.025em;
}
/* Mobile key/value rows */
.mobile-key-value-row {
display: flex;
gap: var(--space-2);
align-items: center;
margin-bottom: var(--space-2);
}
.mobile-key-value-row .mobile-form-input {
flex: 1;
}
/* Mobile file and mount cards */
.mobile-file-card,
.mobile-mount-card {
padding: var(--space-3);
background: var(--bg);
border: 1px solid var(--border);
border-radius: 8px;
margin-bottom: var(--space-2);
}
.mobile-file-header,
.mobile-mount-header {
display: flex;
gap: var(--space-2);
align-items: center;
margin-bottom: var(--space-2);
}
.mobile-file-header .mobile-form-input,
.mobile-mount-header .mobile-form-input {
flex: 1;
}
.mobile-mount-files {
padding-left: var(--space-3);
border-left: 2px solid var(--border);
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.mobile-mount-file-row {
display: flex;
gap: var(--space-2);
align-items: flex-start;
}
.mobile-mount-file-row .mobile-form-input,
.mobile-mount-file-row .mobile-form-textarea {
flex: 1;
}
/* Mobile preview */
.mobile-preview-code {
background: var(--code-bg, #1e1e1e);
color: var(--code-fg, #d4d4d4);
padding: var(--space-3);
border-radius: 8px;
overflow-x: auto;
font-size: 0.8125rem;
font-family:
"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
monospace;
margin: var(--space-2) 0 0 0;
}
.mobile-preview-item {
padding: var(--space-3);
background: var(--bg);
border: 1px solid var(--border);
border-radius: 8px;
margin-bottom: var(--space-2);
font-size: 0.875rem;
}
.mobile-preview-item strong {
display: block;
margin-bottom: var(--space-2);
word-break: break-all;
}
.mobile-preview-mapping {
font-family:
"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
monospace;
font-size: 0.8125rem;
color: var(--muted);
margin-top: var(--space-1);
}
/* Mobile git mount editor overrides */
.mobile-form-section .git-mount-editor .card {
padding: var(--space-3);
margin-bottom: var(--space-2);
}
.mobile-form-section .git-mount-editor .form-row {
flex-direction: column;
align-items: stretch;
gap: var(--space-2);
}
.mobile-form-section .git-mount-editor input,
.mobile-form-section .git-mount-editor select,
.mobile-form-section .git-mount-editor textarea {
width: 100%;
}
.mobile-form-section .git-mount-editor .form-actions {
flex-direction: row;
}
.mobile-form-section .git-mount-editor button {
min-height: var(--touch-target);
}
/* Ensure minimum touch targets on mobile */
button,
a,
input,
select,
textarea,
[role="button"] {
min-height: var(--touch-target);
min-width: var(--touch-target);
}
/* Active states for touch feedback */
button:active,
a:active,
[role="button"]:active {
opacity: 0.8;
transform: scale(0.98);
}
/* Remove transform on buttons that shouldn't scale */
.mobile-nav-item:active,
.mobile-action-sheet-button:active,
.mobile-action-sheet-cancel:active {
transform: none;
}
@media (max-width: 767px) {
.dialog-actions {
flex-direction: column-reverse;
gap: 0.5rem;
}
.dialog-actions button {
width: 100%;
min-height: var(--touch-target);
}
}
.workspace-main {
padding: var(--space-2);
}
.tree-entry {
padding: 0.5rem;
min-height: var(--touch-target);
display: flex;
align-items: center;
}
@media (max-width: 767px) {
.modal-content {
min-width: auto;
width: calc(100% - 2rem);
max-width: 100%;
margin: 1rem;
padding: 1rem;
max-height: calc(100vh - 2rem);
}
.modal-actions {
flex-direction: column-reverse;
gap: 0.5rem;
}
.modal-actions button {
width: 100%;
min-height: var(--touch-target);
}
}
/* Mobile Action Sheet */
.mobile-action-sheet-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 200;
display: flex;
align-items: flex-end;
justify-content: center;
animation: fadeIn 0.2s ease;
}
.mobile-action-sheet {
background: var(--bg);
border-radius: 16px 16px 0 0;
width: 100%;
max-width: 500px;
max-height: 80vh;
max-height: 80dvh;
overflow-y: auto;
overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
animation: slideUp 0.3s ease;
padding-bottom: env(safe-area-inset-bottom, 0);
}
.mobile-action-sheet-header {
padding: var(--space-3) var(--space-4) var(--space-2);
text-align: center;
}
.mobile-action-sheet-handle {
width: 36px;
height: 4px;
background: var(--color-border);
border-radius: 2px;
margin: 0 auto var(--space-3);
}
.mobile-action-sheet-header h3 {
margin: 0;
font-size: 1rem;
font-weight: 600;
}
.mobile-action-sheet-actions {
display: flex;
flex-direction: column;
gap: 1px;
background: var(--color-border);
margin: 0 var(--space-2);
border-radius: 12px;
overflow: hidden;
}
.mobile-action-sheet-button {
display: flex;
align-items: center;
gap: var(--space-3);
width: 100%;
padding: var(--space-3) var(--space-4);
background: var(--bg);
border: none;
color: var(--text);
font-size: 1rem;
cursor: pointer;
min-height: 56px;
text-align: left;
}
.mobile-action-sheet-button.danger {
color: #cd3131;
}
.mobile-action-sheet-button:active {
background: var(--color-border);
}
.mobile-action-sheet-cancel {
display: block;
width: calc(100% - var(--space-4));
margin: var(--space-3) var(--space-2);
padding: var(--space-3);
background: var(--bg);
border: 1px solid var(--color-border);
border-radius: 12px;
color: var(--text);
font-size: 1rem;
font-weight: 600;
cursor: pointer;
min-height: 56px;
}
.mobile-action-sheet-cancel:active {
background: var(--color-border);
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slideUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
/* Notification Center */
.notification-center {
position: relative;
display: inline-flex;
z-index: 9999;
}
.notification-bell {
position: relative;
display: flex;
align-items: center;
justify-content: center;
padding: 0.4rem;
background: transparent;
border: none;
border-radius: 8px;
color: var(--muted);
cursor: pointer;
transition:
background-color 0.15s ease,
color 0.15s ease;
min-height: 36px;
min-width: 36px;
}
.notification-bell:hover {
background: var(--bg);
color: var(--ink);
}
.notification-badge {
position: absolute;
top: -2px;
right: -4px;
min-width: 18px;
height: 18px;
padding: 0 5px;
background: var(--danger);
color: white;
border-radius: 9px;
font-size: 11px;
font-weight: 600;
display: inline-flex;
align-items: center;
justify-content: center;
}
.notification-dropdown {
position: fixed;
width: 360px;
max-width: calc(100vw - 2rem);
max-height: 480px;
background: var(--panel);
border: 1px solid var(--border);
border-radius: 12px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
z-index: 9999;
display: flex;
flex-direction: column;
overflow: hidden;
}
.notification-dropdown-header {
padding: 0.75rem 1rem;
font-weight: 600;
font-size: 0.95rem;
border-bottom: 1px solid var(--border);
color: var(--ink);
flex-shrink: 0;
}
.notification-list {
list-style: none;
margin: 0;
padding: 0;
overflow-y: auto;
flex: 1;
min-height: 0;
}
.notification-empty {
padding: 2rem 1rem;
text-align: center;
color: var(--muted);
font-size: 0.9rem;
}
.notification-dropdown-footer {
padding: 0.75rem 1rem;
border-top: 1px solid var(--border);
flex-shrink: 0;
display: flex;
gap: 0.5rem;
}
.notification-mark-all {
flex: 1;
padding: 0.5rem 0.75rem;
background: transparent;
border: 1px solid var(--border);
border-radius: 8px;
color: var(--muted);
font: inherit;
font-size: 0.85rem;
cursor: pointer;
transition: all 0.15s ease;
}
.notification-mark-all:hover {
background: var(--bg);
color: var(--ink);
border-color: var(--brand);
}
.notification-clear-all {
flex: 1;
padding: 0.5rem 0.75rem;
background: transparent;
border: 1px solid var(--border);
border-radius: 8px;
color: var(--muted);
font: inherit;
font-size: 0.85rem;
cursor: pointer;
transition: all 0.15s ease;
}
.notification-clear-all:hover {
background: var(--bg);
color: var(--danger);
border-color: var(--danger);
}
/* Notification Item */
.notification-item {
display: flex;
align-items: flex-start;
gap: 0.75rem;
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--border);
transition: background-color 0.15s ease;
}
.notification-item:last-child {
border-bottom: none;
}
.notification-item:hover {
background: var(--bg);
}
.notification-item--unread {
font-weight: 500;
border-left: 3px solid var(--brand);
padding-left: calc(1rem - 3px);
background: color-mix(in srgb, var(--brand) 4%, var(--panel));
}
.notification-item--read {
opacity: 0.75;
}
.notification-item-icon {
flex-shrink: 0;
margin-top: 0.1rem;
color: var(--muted);
}
.notification-item-content {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 0.2rem;
}
.notification-item-title {
font-size: 0.9rem;
line-height: 1.3;
color: var(--ink);
}
.notification-item--read .notification-item-title {
font-weight: 400;
}
.notification-item-time {
font-size: 0.8rem;
color: var(--muted);
}
.notification-item-message {
font-size: 0.85rem;
color: var(--muted);
line-height: 1.35;
margin-top: 0.15rem;
word-break: break-word;
}
.notification-item-metadata {
margin-top: 0.5rem;
padding: 0.5rem 0.75rem;
background: var(--bg);
border-radius: 6px;
border: 1px solid var(--border);
font-size: 0.8rem;
}
.notification-metadata-row {
display: flex;
gap: 0.5rem;
padding: 0.15rem 0;
}
.notification-metadata-row dt {
font-weight: 500;
color: var(--ink);
min-width: 6rem;
text-transform: capitalize;
flex-shrink: 0;
}
.notification-metadata-row dd {
margin: 0;
color: var(--muted);
font-family: monospace;
word-break: break-word;
}
.notification-item-actions {
display: flex;
gap: 0.35rem;
flex-shrink: 0;
}
.notification-item-action {
padding: 0.25rem 0.5rem;
background: transparent;
border: none;
border-radius: 6px;
color: var(--muted);
font: inherit;
font-size: 0.75rem;
cursor: pointer;
transition: all 0.15s ease;
white-space: nowrap;
}
.notification-item-action:hover {
background: var(--bg);
color: var(--ink);
}
@media (max-width: 767px) {
.notification-dropdown-backdrop {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.35);
z-index: 9998;
}
.notification-dropdown {
width: auto;
left: 0.75rem;
right: 0.75rem;
max-width: none;
border-radius: 12px;
max-height: 70vh;
max-height: 70dvh;
}
}
/* Toast animations */
@keyframes toastSlideIn {
from {
opacity: 0;
transform: translateX(100%);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes toastFadeOut {
from {
opacity: 1;
transform: translateX(0);
}
to {
opacity: 0;
transform: translateX(100%);
}
}
/* ─── Mobile Detail View ─── */
.mobile-detail-view {
display: flex;
flex-direction: column;
min-height: 100%;
background: var(--bg);
}
.mobile-detail-header {
position: sticky;
top: 0;
z-index: 10;
display: flex;
align-items: center;
gap: var(--space-3);
padding: var(--space-3);
background: var(--panel);
border-bottom: 1px solid var(--border);
}
.mobile-detail-header-content {
flex: 1;
min-width: 0;
}
.mobile-detail-title {
margin: 0;
font-size: var(--font-size-lg);
line-height: var(--line-height-tight);
}
.mobile-detail-subtitle {
margin: var(--space-1) 0 0;
color: var(--muted);
font-size: var(--font-size-sm);
line-height: var(--line-height-normal);
}
.mobile-detail-actions {
display: flex;
gap: var(--space-2);
}
.mobile-detail-action {
display: flex;
align-items: center;
justify-content: center;
width: var(--touch-target);
height: var(--touch-target);
padding: 0;
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius-md);
color: var(--ink);
cursor: pointer;
transition: background 0.12s ease;
}
.mobile-detail-action:hover {
background: var(--panel);
}
.mobile-detail-action-danger {
color: var(--danger);
border-color: color-mix(in srgb, var(--danger) 30%, transparent);
background: var(--danger-light);
}
.mobile-detail-fields {
display: flex;
flex-direction: column;
gap: var(--space-3);
padding: var(--space-3);
}
.mobile-detail-field {
display: flex;
flex-direction: column;
gap: var(--space-1);
padding: var(--space-3);
background: var(--panel);
border: 1px solid var(--border);
border-radius: var(--radius-md);
}
.mobile-detail-field-label {
font-size: var(--font-size-xs);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--muted);
}
.mobile-detail-field-value {
font-size: var(--font-size-base);
color: var(--ink);
line-height: var(--line-height-normal);
word-break: break-word;
}
.mobile-detail-code {
overflow: auto;
max-width: 100%;
font-size: var(--font-size-sm);
line-height: var(--line-height-normal);
}
/* ─── Mobile List Search ─── */
.mobile-list-search {
padding: var(--space-3);
border-bottom: 1px solid var(--border);
background: var(--panel);
}
.mobile-list-search-input {
width: 100%;
min-height: var(--touch-target);
padding: var(--space-2) var(--space-3);
border: 1px solid var(--border);
border-radius: var(--radius-md);
background: var(--bg);
color: var(--ink);
font-size: var(--font-size-base);
}
.mobile-list-search-input:focus {
outline: none;
border-color: var(--brand);
}
/* ─── SSH Key Signing / Verification ─── */
.key-signing,
.key-verification {
display: flex;
flex-direction: column;
gap: var(--space-3);
padding: var(--space-3);
background: var(--panel);
border: 1px solid var(--border);
border-radius: var(--radius-md);
margin-top: var(--space-3);
}
.signature-result,
.verify-result {
display: flex;
flex-direction: column;
gap: var(--space-2);
padding: var(--space-3);
border-radius: var(--radius-md);
background: var(--bg);
border: 1px solid var(--border);
font-family: "IBM Plex Mono", monospace;
font-size: var(--font-size-sm);
word-break: break-all;
}
.verify-result.valid {
background: var(--success-light);
border-color: color-mix(in srgb, var(--success) 30%, transparent);
color: var(--success);
}
.verify-result.invalid {
background: var(--danger-light);
border-color: color-mix(in srgb, var(--danger) 30%, transparent);
color: var(--danger);
}
.signature-result code,
.verify-result code {
font-family: "IBM Plex Mono", monospace;
}
.signature-result button,
.verify-result button {
align-self: flex-start;
}
/* Delete button in sidebar list items (icon-only, shown on hover) */
.delete-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: var(--touch-target);
height: var(--touch-target);
padding: 0;
background: transparent;
border: none;
color: var(--muted);
cursor: pointer;
border-radius: var(--radius-md);
transition:
background 0.12s ease,
color 0.12s ease;
}
.delete-btn:hover {
background: var(--danger-light);
color: var(--danger);
}
.delete-btn:focus-visible {
outline: 2px solid var(--brand);
outline-offset: 2px;
}
/* Workspace header action buttons */
.workspace-header-action-btn {
display: inline-flex;
align-items: center;
gap: var(--space-2);
min-height: var(--touch-target);
padding: var(--space-2) var(--space-3);
background: var(--panel);
border: 1px solid var(--border);
border-radius: var(--radius-md);
color: var(--ink);
font-size: var(--font-size-sm);
font-weight: 500;
text-decoration: none;
transition:
background 0.12s ease,
border-color 0.12s ease;
}
.workspace-header-action-btn:hover {
background: var(--bg);
}
.workspace-header-action-btn:focus-visible {
outline: 2px solid var(--brand);
outline-offset: 2px;
}
/* ─── Code Editor ─── */
.code-editor {
position: relative;
border: 1px solid var(--border);
border-radius: var(--radius-md);
background: var(--panel);
overflow: hidden;
}
.editor-textarea {
width: 100%;
min-height: 12rem;
padding: var(--space-3);
border: none;
background: transparent;
color: var(--ink);
font-family: "IBM Plex Mono", monospace;
font-size: var(--font-size-sm);
line-height: var(--line-height-normal);
resize: vertical;
}
.editor-textarea:focus {
outline: none;
}
/* ─── Syntax Highlighter ─── */
.syntax-highlighter {
position: relative;
border: 1px solid var(--border);
border-radius: var(--radius-md);
background: var(--panel);
overflow: hidden;
}
.highlighter-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
background: var(--bg);
border-bottom: 1px solid var(--border);
}
.language-badge {
font-size: var(--font-size-xs);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--muted);
}
.copy-button {
display: inline-flex;
align-items: center;
gap: var(--space-1);
padding: var(--space-1) var(--space-2);
background: var(--panel);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
color: var(--muted);
font-size: var(--font-size-xs);
cursor: pointer;
transition:
background 0.12s ease,
color 0.12s ease;
}
.copy-button:hover {
background: var(--bg);
color: var(--ink);
}
.copy-button:focus-visible {
outline: 2px solid var(--brand);
outline-offset: 2px;
}
.code-container {
display: flex;
overflow: auto;
max-height: 24rem;
}
.line-numbers {
flex-shrink: 0;
padding: var(--space-3) var(--space-2);
background: var(--bg);
border-right: 1px solid var(--border);
text-align: right;
user-select: none;
}
.line-number {
font-family: "IBM Plex Mono", monospace;
font-size: var(--font-size-sm);
line-height: var(--line-height-normal);
color: var(--muted);
}
.code-block {
flex: 1;
margin: 0;
padding: var(--space-3);
overflow: visible;
font-family: "IBM Plex Mono", monospace;
font-size: var(--font-size-sm);
line-height: var(--line-height-normal);
}
/* ─── Danger Zone ─── */
.danger-zone {
margin-top: var(--space-6);
padding: var(--space-4);
border: 1px solid var(--danger);
border-radius: var(--radius-md);
background: var(--danger-light);
}
.danger-zone h3 {
margin: 0 0 var(--space-3);
color: var(--danger);
}
/* ─── Form Helpers ─── */
.form-help {
display: block;
font-size: var(--font-size-sm);
color: var(--muted);
margin-top: var(--space-1);
}
.form-section {
padding: var(--space-4);
background: var(--panel);
border: 1px solid var(--border);
border-radius: var(--radius-md);
}
.form-section > h4 {
margin: 0 0 var(--space-3);
font-size: var(--font-size-base);
}
.required {
color: var(--danger);
}
/* ─── Repository List ─── */
.repository-list {
display: flex;
flex-direction: column;
gap: var(--space-3);
}
/* ─── Sessions List Wrapper ─── */
.sessions-list-wrapper {
margin-top: var(--space-4);
}
/* ─── SSH Key Selection in Tool Starter ─── */
.ssh-key-selection {
/* The component uses .form-group.ssh-key-selection for scoping only. */
}
/* ─── Inline Confirm / Profile Select ─── */
.inline-confirm,
.inline-profile-select {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--space-2);
padding: var(--space-2);
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius-md);
}
.inline-profile-select {
flex-direction: column;
align-items: stretch;
}
.inline-profile-select select,
.inline-profile-select input {
width: 100%;
}
/* ─── Instance Profile Badge Container ─── */
.instance-profile {
margin-top: var(--space-1);
}
/* ─── Changed Files List in Dirty Delete Modal ─── */
.changed-files-list {
margin: var(--space-3) 0;
padding: var(--space-3);
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius-md);
}
.changed-files-list h4 {
margin: 0 0 var(--space-2);
font-size: var(--font-size-sm);
color: var(--muted);
}
.changed-files-list ul {
margin: 0;
padding-left: var(--space-4);
}
.changed-files-list li {
font-size: var(--font-size-sm);
word-break: break-all;
}
/* ─── Project Description ─── */
.project-description {
margin: var(--space-1) 0 0;
color: var(--muted);
}
/* ─── Home Summary Card ─── */
.home-summary-card {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
/* ─── Workspace Header Sub-elements ─── */
.workspace-header-left {
display: flex;
align-items: center;
gap: var(--space-3);
}
.workspace-header-icon {
display: flex;
align-items: center;
justify-content: center;
width: 3rem;
height: 3rem;
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius-md);
color: var(--brand);
}
.workspace-header-info {
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.workspace-header-title {
margin: 0;
font-size: var(--font-size-xl);
line-height: var(--line-height-tight);
}
.workspace-header-subtitle {
color: var(--muted);
font-size: var(--font-size-sm);
}
/* ─── Tree Up Entry ─── */
.tree-up {
font-weight: 500;
color: var(--brand);
}
/* ─── Git Mount List ─── */
.git-mount-list {
display: flex;
flex-direction: column;
gap: var(--space-3);
}
/* ─── Sticky Footer ─── */
.sticky-footer {
position: sticky;
bottom: var(--space-4);
z-index: 10;
background: var(--panel);
padding: var(--space-4);
border: 1px solid var(--border);
border-radius: var(--radius-md);
box-shadow: var(--shadow-md);
}
/* ─── Drag Items ─── */
.drag-item {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
background: var(--panel);
border: 1px solid var(--border);
border-radius: var(--radius-md);
margin-bottom: var(--space-1);
cursor: grab;
transition: background 0.15s;
}
.drag-item:hover {
background: var(--bg);
}
.drag-item-active {
background: var(
--brand-light,
color-mix(in srgb, var(--brand) 10%, transparent)
);
border-color: var(--brand);
}
.drag-handle {
cursor: grab;
color: var(--muted);
}
/* ─── Code Block ─── */
.code-block {
background: var(--code-bg, #1e1e1e);
color: var(--code-fg, #d4d4d4);
padding: var(--space-4);
border-radius: var(--radius-md);
overflow: auto;
font-family:
"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
monospace;
font-size: var(--font-size-sm);
line-height: var(--line-height-normal);
}
/* ─── Empty State ─── */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding-top: var(--space-10);
color: var(--muted);
text-align: center;
}
.empty-state-icon {
opacity: 0.3;
margin-bottom: var(--space-4);
}
.empty-state h3 {
margin: 0 0 var(--space-2);
font-weight: 500;
}
.empty-state p {
margin: 0;
}
/* ─── Sidebar ─── */
.sidebar {
width: var(--sidebar-width);
min-width: var(--sidebar-width);
display: flex;
flex-direction: column;
border-right: 1px solid var(--border);
background: var(--panel);
}
.sidebar-header {
padding: var(--space-4);
border-bottom: 1px solid var(--border);
}
.sidebar-header h2 {
margin: 0;
font-size: var(--font-size-lg);
}
.sidebar-header p {
margin: var(--space-1) 0 0;
font-size: var(--font-size-sm);
}
.sidebar-list {
flex: 1;
overflow-y: auto;
padding: var(--space-2);
}
.sidebar-footer {
padding: var(--space-4);
border-top: 1px solid var(--border);
}
.sidebar-item {
width: 100%;
text-align: left;
padding: var(--space-3) var(--space-4);
margin-bottom: var(--space-1);
border-radius: var(--radius-md);
border: none;
background: transparent;
color: var(--ink);
cursor: pointer;
display: flex;
align-items: center;
gap: var(--space-3);
transition: background 0.15s;
}
.sidebar-item:hover {
background: var(--bg);
}
.sidebar-item-active,
.sidebar-item-active:hover {
background: var(--brand);
color: white;
}
.sidebar-item-active .delete-btn {
color: rgba(255, 255, 255, 0.8);
}
.sidebar-item-active .delete-btn:hover {
background: rgba(255, 255, 255, 0.15);
color: white;
}
.sidebar-item-active .badge {
background: rgba(255, 255, 255, 0.2);
border-color: rgba(255, 255, 255, 0.3);
color: white;
}
.sidebar-item-content {
flex: 1;
min-width: 0;
}
.sidebar-item-title {
font-weight: 600;
font-size: var(--font-size-base);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.sidebar-item-subtitle {
font-size: var(--font-size-sm);
opacity: 0.8;
margin-top: var(--space-1);
}
.sidebar-item .delete-btn {
opacity: 0;
}
.sidebar-item:hover .delete-btn,
.sidebar-item:focus-within .delete-btn {
opacity: 1;
}
.sidebar-create-button {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
gap: var(--space-2);
padding: var(--space-3);
border-radius: var(--radius-md);
border: 2px dashed var(--border);
background: transparent;
color: var(--muted);
cursor: pointer;
font-weight: 600;
transition:
border-color 0.15s,
color 0.15s;
}
.sidebar-create-button:hover {
border-color: var(--brand);
color: var(--brand);
}
/* ─── Mobile FAB ─── */
.mobile-fab {
position: fixed;
bottom: calc(var(--mobile-nav-height) + var(--space-3));
right: var(--space-4);
z-index: 50;
width: 3.5rem;
height: 3.5rem;
border-radius: 50%;
background: var(--primary);
color: var(--primary-fg);
border: none;
box-shadow: var(--shadow-md);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition:
transform 0.15s ease,
box-shadow 0.15s ease;
}
.mobile-fab:hover {
transform: scale(1.08);
box-shadow: var(--shadow-lg);
}
.mobile-fab:active {
transform: scale(0.95);
}
.mobile-fab:focus-visible {
outline: 2px solid var(--brand);
outline-offset: 2px;
}
/* ─── Mobile Bottom Sheet Item Label ─── */
.mobile-bottom-sheet-item-label {
font-size: var(--font-size-sm);
font-weight: 500;
color: var(--ink);
}
/* ─── Mobile List Item Duplicate Action ─── */
.mobile-list-item-action-duplicate {
color: var(--info);
}
.mobile-list-item-action-duplicate:hover {
background: var(--info-light);
}
/* ─── Diff Line Content ─── */
.diff-line-content {
flex: 1;
font-family: "IBM Plex Mono", monospace;
font-size: var(--font-size-sm);
word-break: break-all;
}
/* ─── Button Icon (legacy alias) ─── */
.button-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: var(--touch-target);
height: var(--touch-target);
padding: 0;
background: transparent;
border: none;
color: var(--muted);
cursor: pointer;
border-radius: var(--radius-md);
}
.button-icon:hover {
background: var(--bg);
color: var(--ink);
}
.button-icon:focus-visible {
outline: 2px solid var(--brand);
outline-offset: 2px;
}