diff --git a/apps/web/src/styles/utilities.css b/apps/web/src/styles/utilities.css index 56f6abb..0e3713e 100644 --- a/apps/web/src/styles/utilities.css +++ b/apps/web/src/styles/utilities.css @@ -67,8 +67,8 @@ .icon-button, button, [role="button"] { - min-height: 44px; - min-width: 44px; + min-height: var(--touch-target); + min-width: var(--touch-target); } /* Dialog Responsive */ @@ -135,7 +135,7 @@ button, select, textarea { width: 100%; - min-height: 44px; + min-height: var(--touch-target); } } @@ -177,7 +177,7 @@ button, .form-field textarea, .form-field select { width: 100%; - min-height: 44px; + min-height: var(--touch-target); } /* Settings page stack */ @@ -248,7 +248,7 @@ button, [role="button"], a.nav-item, .tree-entry { - min-height: 44px; + min-height: var(--touch-target); } /* Table horizontal scroll wrapper */ @@ -1610,7 +1610,7 @@ a.nav-item, display: flex; align-items: center; justify-content: center; - min-width: 44px; + min-width: var(--touch-target); height: 44px; padding: 0 var(--space-2); background: #3e3e3e; @@ -1905,7 +1905,7 @@ a.nav-item, border-top: 1px solid var(--border); padding-bottom: env(safe-area-inset-bottom, 0); z-index: 100; - height: 64px; + height: var(--mobile-nav-height); } .mobile-nav-item { @@ -1919,7 +1919,7 @@ a.nav-item, text-decoration: none; font-size: 11px; min-width: 64px; - min-height: 44px; + min-height: var(--touch-target); border-radius: 8px; transition: color 0.15s ease; } @@ -2022,7 +2022,7 @@ a.nav-item, font-size: 16px; text-align: left; cursor: pointer; - min-height: 44px; + min-height: var(--touch-target); } .mobile-bottom-sheet-item:active { @@ -2215,7 +2215,7 @@ a.nav-item, .mobile-edit-cancel, .mobile-edit-save, .mobile-edit-delete { - min-height: 44px; + min-height: var(--touch-target); padding: var(--space-2) var(--space-3); border-radius: 10px; font: inherit; @@ -2271,7 +2271,7 @@ a.nav-item, position: fixed; left: 0; right: 0; - bottom: 64px; + bottom: var(--mobile-nav-height); z-index: 110; display: flex; flex-direction: column; @@ -2311,7 +2311,7 @@ a.nav-item, background: var(--panel); color: var(--text); font: inherit; - min-height: 44px; + min-height: var(--touch-target); } .mobile-edit-textarea { @@ -2424,7 +2424,7 @@ a.nav-item, /* Mobile shell content padding adjustment */ .shell-content.mobile { - padding-bottom: calc(1.25rem + 64px); + padding-bottom: calc(var(--mobile-nav-height) + var(--space-3)); } /* Mobile form actions (bottom button row) */ @@ -2472,7 +2472,7 @@ a.nav-item, background: var(--bg); color: var(--text); font: inherit; - min-height: 44px; + min-height: var(--touch-target); } .mobile-form-textarea { @@ -2789,7 +2789,7 @@ a.nav-item, } .mobile-form-section .git-mount-editor button { - min-height: 44px; + min-height: var(--touch-target); } /* Ensure minimum touch targets on mobile */ @@ -2799,8 +2799,8 @@ input, select, textarea, [role="button"] { - min-height: 44px; - min-width: 44px; + min-height: var(--touch-target); + min-width: var(--touch-target); } /* Active states for touch feedback */ @@ -2825,7 +2825,7 @@ a:active, .dialog-actions button { width: 100%; - min-height: 44px; + min-height: var(--touch-target); } } @@ -2835,7 +2835,7 @@ a:active, .tree-entry { padding: 0.5rem; - min-height: 44px; + min-height: var(--touch-target); display: flex; align-items: center; } @@ -2856,7 +2856,7 @@ a:active, .modal-actions button { width: 100%; - min-height: 44px; + min-height: var(--touch-target); } } @@ -3268,3 +3268,594 @@ a:active, 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); +} + +/* ─── 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; +}