@lemoncat7/dsh-ssh 0.1.0-alpha.15 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +17 -0
  2. package/lib/activity-events.d.ts +26 -0
  3. package/lib/activity-events.d.ts.map +1 -0
  4. package/lib/activity-events.js +81 -0
  5. package/lib/activity-events.js.map +1 -0
  6. package/lib/api.d.ts +2 -0
  7. package/lib/api.d.ts.map +1 -1
  8. package/lib/api.js +105 -4
  9. package/lib/api.js.map +1 -1
  10. package/lib/client-api.d.ts +38 -1
  11. package/lib/client-api.d.ts.map +1 -1
  12. package/lib/client-api.js +18 -2
  13. package/lib/client-api.js.map +1 -1
  14. package/lib/client.d.ts.map +1 -1
  15. package/lib/client.js +351 -70
  16. package/lib/client.js.map +3 -3
  17. package/lib/connector.d.ts +1 -0
  18. package/lib/connector.d.ts.map +1 -1
  19. package/lib/connector.js +21 -8
  20. package/lib/connector.js.map +1 -1
  21. package/lib/credentials.d.ts +14 -0
  22. package/lib/credentials.d.ts.map +1 -1
  23. package/lib/credentials.js +48 -32
  24. package/lib/credentials.js.map +1 -1
  25. package/lib/domain.d.ts +23 -1
  26. package/lib/domain.d.ts.map +1 -1
  27. package/lib/domain.js +15 -1
  28. package/lib/domain.js.map +1 -1
  29. package/lib/index.d.ts.map +1 -1
  30. package/lib/index.js +7 -4
  31. package/lib/index.js.map +1 -1
  32. package/lib/store.d.ts +3 -1
  33. package/lib/store.d.ts.map +1 -1
  34. package/lib/store.js +11 -3
  35. package/lib/store.js.map +1 -1
  36. package/lib/terminal-io.d.ts +38 -0
  37. package/lib/terminal-io.d.ts.map +1 -0
  38. package/lib/terminal-io.js +83 -0
  39. package/lib/terminal-io.js.map +1 -0
  40. package/lib/terminal-stream.d.ts +9 -0
  41. package/lib/terminal-stream.d.ts.map +1 -0
  42. package/lib/terminal-stream.js +50 -0
  43. package/lib/terminal-stream.js.map +1 -0
  44. package/lib/terminal-transport.d.ts +29 -0
  45. package/lib/terminal-transport.d.ts.map +1 -0
  46. package/lib/terminal-transport.js +147 -0
  47. package/lib/terminal-transport.js.map +1 -0
  48. package/lib/terminal.d.ts +20 -4
  49. package/lib/terminal.d.ts.map +1 -1
  50. package/lib/terminal.js +45 -17
  51. package/lib/terminal.js.map +1 -1
  52. package/lib/tools.d.ts +1 -1
  53. package/lib/tools.d.ts.map +1 -1
  54. package/lib/tools.js +60 -11
  55. package/lib/tools.js.map +1 -1
  56. package/package.json +3 -1
package/lib/client.js CHANGED
@@ -6390,7 +6390,7 @@ var xterm_default = `/**
6390
6390
  `;
6391
6391
 
6392
6392
  // src/client.css
6393
- var client_default = '.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n.dsh-ssh-sidebar {\n box-sizing: border-box;\n flex: none;\n margin: 0 8px 8px 2px;\n padding: 4px 0 6px;\n border-bottom: 1px solid\n color-mix(in srgb, var(--dsw-alias-border-l2) 62%, transparent);\n color: var(--dsw-alias-label-primary);\n}\n.dsh-ssh-sidebar.is-rail {\n width: 36px;\n margin: 0 0 8px;\n padding: 0;\n border: 0;\n}\n.dsh-ssh-sidebar-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 32px;\n padding: 0 4px 0 5px;\n}\n.dsh-ssh-sidebar-title {\n display: flex;\n min-width: 0;\n align-items: center;\n gap: 5px;\n height: 28px;\n padding: 0 5px;\n color: var(--dsw-alias-label-secondary);\n border: 0;\n background: transparent;\n border-radius: 7px;\n font: 600 12px/1 var(--ds-font-family);\n cursor: pointer;\n}\n.dsh-ssh-sidebar-title:hover,\n.dsh-ssh-icon-button:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-disclosure {\n display: grid;\n place-items: center;\n transition: transform 0.16s ease;\n}\n.dsh-ssh-disclosure[data-open="false"] {\n transform: rotate(-90deg);\n}\n.dsh-ssh-icon-button {\n display: inline-grid;\n place-items: center;\n flex: none;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 0;\n border-radius: 8px;\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n cursor: pointer;\n}\n.dsh-ssh-icon-button.is-danger {\n color: #a65d58;\n}\n.dsh-ssh-sidebar-list {\n display: grid;\n gap: 2px;\n padding: 2px 1px 0;\n}\n.dsh-ssh-sidebar-row,\n.dsh-ssh-sidebar-empty,\n.dsh-ssh-sidebar-more {\n box-sizing: border-box;\n width: 100%;\n border: 1px solid transparent;\n background: transparent;\n color: inherit;\n cursor: pointer;\n}\n.dsh-ssh-sidebar-row {\n display: grid;\n grid-template-columns: 12px minmax(0, 1fr) 18px;\n align-items: center;\n gap: 7px;\n min-height: 40px;\n padding: 4px 7px;\n border-radius: 9px;\n text-align: left;\n}\n.dsh-ssh-sidebar-row:hover {\n background: color-mix(\n in srgb,\n var(--dsw-alias-interactive-bg-hover) 70%,\n transparent\n );\n}\n.dsh-ssh-sidebar-row.is-active {\n background: color-mix(\n in srgb,\n var(--dsw-alias-interactive-bg-hover) 92%,\n transparent\n );\n border-color: color-mix(in srgb, var(--dsw-alias-border-l2) 50%, transparent);\n}\n.dsh-ssh-status-dot {\n display: block;\n width: 7px;\n height: 7px;\n margin: auto;\n border: 1px solid\n color-mix(in srgb, var(--dsw-alias-label-secondary) 62%, transparent);\n border-radius: 50%;\n}\n.dsh-ssh-status-dot.is-injected {\n border-color: #5b8f82;\n background: #5b8f82;\n box-shadow: 0 0 0 2px color-mix(in srgb, #5b8f82 14%, transparent);\n}\n.dsh-ssh-sidebar-copy {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n.dsh-ssh-sidebar-copy strong,\n.dsh-ssh-sidebar-copy small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-sidebar-copy strong {\n font-size: 13px;\n font-weight: 500;\n}\n.dsh-ssh-sidebar-copy small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n.dsh-ssh-injected-mark {\n display: grid;\n place-items: center;\n color: #5b8f82;\n}\n.dsh-ssh-sidebar-empty,\n.dsh-ssh-sidebar-more {\n min-height: 34px;\n padding: 6px 10px;\n border-radius: 8px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n text-align: left;\n}\n.dsh-ssh-sidebar-empty:hover,\n.dsh-ssh-sidebar-more:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-rail-button {\n display: grid;\n place-items: center;\n width: 36px;\n height: 36px;\n padding: 0;\n border: 0;\n border-radius: 10px;\n color: var(--dsw-alias-label-primary);\n background: transparent;\n cursor: pointer;\n}\n.dsh-ssh-rail-button:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-server-glyph {\n display: inline-grid;\n place-items: center;\n color: currentColor;\n}\n.dsh-ssh-workspace {\n --ssh-accent: #547d78;\n --ssh-accent-strong: #406e67;\n --ssh-danger: #9c504c;\n --ssh-warning: #927443;\n --ssh-surface: color-mix(\n in srgb,\n var(--dsw-alias-bg-base, #f7f8f7) 94%,\n transparent\n );\n --ssh-surface-raised: color-mix(\n in srgb,\n var(--dsw-alias-bg-base, #fff) 98%,\n var(--dsw-alias-label-primary) 2%\n );\n --ssh-border: color-mix(\n in srgb,\n var(--dsw-alias-label-primary) 10%,\n transparent\n );\n --dpu-navigation-width: 248px;\n --dpu-inspector-width: 292px;\n --dpu-border: var(--ssh-border);\n --dpu-accent: var(--ssh-accent);\n --dpu-accent-strong: var(--ssh-accent-strong);\n --dpu-raised-surface: var(--ssh-surface-raised);\n --dpu-toolbar-surface: color-mix(\n in srgb,\n var(--ssh-surface-raised) 88%,\n transparent\n );\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n color: var(--dsw-alias-label-primary);\n background: var(--ssh-surface);\n font-family:\n var(--ds-font-family),\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n}\n.dsh-ssh-toolbar {\n display: grid;\n grid-template-columns: minmax(180px, 1fr) auto minmax(180px, 1fr);\n align-items: center;\n gap: 16px;\n min-height: 64px;\n padding: 0 20px;\n border-bottom: 1px solid var(--ssh-border);\n background: color-mix(in srgb, var(--ssh-surface-raised) 88%, transparent);\n}\n.dsh-ssh-brand {\n display: flex;\n align-items: center;\n gap: 10px;\n min-width: 0;\n}\n.dsh-ssh-brand-glyph {\n display: grid;\n place-items: center;\n width: 30px;\n height: 30px;\n border: 1px solid color-mix(in srgb, var(--ssh-accent) 28%, transparent);\n border-radius: 9px;\n color: var(--ssh-accent-strong);\n background: color-mix(in srgb, var(--ssh-accent) 8%, transparent);\n}\n.dsh-ssh-brand > span:last-child {\n display: grid;\n gap: 1px;\n}\n.dsh-ssh-brand strong {\n font-size: 14px;\n font-weight: 650;\n}\n.dsh-ssh-brand small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n.dsh-ssh-segments {\n display: flex;\n gap: 2px;\n padding: 3px;\n border: 1px solid color-mix(in srgb, var(--ssh-border) 80%, transparent);\n border-radius: 10px;\n background: color-mix(\n in srgb,\n var(--dsw-alias-label-primary) 3%,\n transparent\n );\n}\n.dsh-ssh-segments button {\n min-width: 74px;\n height: 28px;\n padding: 0 12px;\n border: 0;\n border-radius: 7px;\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n font-size: 12px;\n cursor: pointer;\n}\n.dsh-ssh-segments button:hover {\n color: var(--dsw-alias-label-primary);\n}\n.dsh-ssh-segments button.is-active {\n color: var(--dsw-alias-label-primary);\n background: var(--ssh-surface-raised);\n box-shadow: 0 1px 2px\n color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);\n}\n.dsh-ssh-toolbar > .dsh-ssh-primary-button {\n justify-self: end;\n}\n.dsh-ssh-primary-button,\n.dsh-ssh-secondary-button,\n.dsh-ssh-danger-button,\n.dsh-ssh-small-primary {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n min-height: 30px;\n padding: 0 12px;\n border-radius: 8px;\n font: 500 12px/1 var(--ds-font-family);\n cursor: pointer;\n}\n.dsh-ssh-primary-button,\n.dsh-ssh-small-primary {\n border: 1px solid\n color-mix(in srgb, var(--ssh-accent-strong) 64%, transparent);\n color: #f6fbf9;\n background: var(--ssh-accent-strong);\n}\n.dsh-ssh-primary-button:hover,\n.dsh-ssh-small-primary:hover {\n background: color-mix(in srgb, var(--ssh-accent-strong) 88%, #000);\n}\n.dsh-ssh-primary-button:disabled {\n opacity: 0.55;\n cursor: default;\n}\n.dsh-ssh-secondary-button {\n border: 1px solid var(--ssh-border);\n color: var(--dsw-alias-label-primary);\n background: var(--ssh-surface-raised);\n}\n.dsh-ssh-secondary-button:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-danger-button {\n border: 1px solid color-mix(in srgb, var(--ssh-danger) 28%, transparent);\n color: var(--ssh-danger);\n background: color-mix(in srgb, var(--ssh-danger) 7%, transparent);\n}\n.dsh-ssh-small-primary {\n min-height: 26px;\n padding: 0 9px;\n}\n.dsh-ssh-profile-panel,\n.dsh-ssh-inspector {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex-direction: column;\n background: color-mix(in srgb, var(--ssh-surface-raised) 72%, transparent);\n}\n.dsh-ssh-profile-panel {\n border-right: 1px solid var(--ssh-border);\n}\n.dsh-ssh-inspector {\n border-left: 1px solid var(--ssh-border);\n}\n.dsh-ssh-main-panel {\n min-width: 0;\n min-height: 0;\n overflow: auto;\n background: color-mix(in srgb, var(--ssh-surface) 88%, transparent);\n}\n.dsh-ssh-panel-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 58px;\n padding: 0 14px;\n border-bottom: 1px solid\n color-mix(in srgb, var(--ssh-border) 74%, transparent);\n}\n.dsh-ssh-panel-heading > span {\n display: grid;\n gap: 2px;\n}\n.dsh-ssh-panel-heading strong {\n font-size: 12px;\n font-weight: 650;\n}\n.dsh-ssh-panel-heading small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n.dsh-ssh-search {\n padding: 10px 10px 6px;\n}\n.dsh-ssh-search input,\n.dsh-ssh-field input,\n.dsh-ssh-field select,\n.dsh-ssh-field textarea,\n.dsh-ssh-number-row input {\n box-sizing: border-box;\n width: 100%;\n border: 1px solid var(--ssh-border);\n border-radius: 8px;\n outline: 0;\n color: var(--dsw-alias-label-primary);\n background: color-mix(in srgb, var(--ssh-surface-raised) 92%, transparent);\n font: 400 12px/1.35 var(--ds-font-family);\n}\n.dsh-ssh-search input {\n height: 30px;\n padding: 0 10px;\n}\n.dsh-ssh-search input:focus,\n.dsh-ssh-field input:focus,\n.dsh-ssh-field select:focus,\n.dsh-ssh-field textarea:focus,\n.dsh-ssh-number-row input:focus {\n border-color: color-mix(in srgb, var(--ssh-accent) 65%, transparent);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--ssh-accent) 12%, transparent);\n}\n.dsh-ssh-profile-list {\n display: grid;\n align-content: start;\n gap: 3px;\n min-height: 0;\n overflow: auto;\n padding: 4px 7px 12px;\n}\n.dsh-ssh-profile-group {\n min-width: 0;\n}\n.dsh-ssh-profile-group-heading {\n display: grid;\n grid-template-columns: 14px 18px minmax(0, 1fr);\n align-items: center;\n gap: 5px;\n width: 100%;\n min-height: 34px;\n padding: 0 6px;\n border: 0;\n border-radius: 8px;\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n text-align: left;\n cursor: pointer;\n}\n.dsh-ssh-profile-group-heading:hover {\n color: var(--dsw-alias-label-primary);\n background: color-mix(\n in srgb,\n var(--dsw-alias-interactive-bg-hover) 58%,\n transparent\n );\n}\n.dsh-ssh-profile-group-heading:focus-visible {\n outline: 2px solid color-mix(in srgb, var(--ssh-accent) 54%, transparent);\n outline-offset: -2px;\n}\n.dsh-ssh-profile-group-chevron {\n display: grid;\n place-items: center;\n transition: transform 160ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n.dsh-ssh-profile-group-chevron[data-open="false"] {\n transform: rotate(-90deg);\n}\n.dsh-ssh-profile-group-folder {\n display: grid;\n place-items: center;\n color: color-mix(\n in srgb,\n var(--ssh-accent-strong) 72%,\n var(--dsw-alias-label-secondary)\n );\n}\n.dsh-ssh-profile-group-copy {\n display: flex;\n min-width: 0;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n.dsh-ssh-profile-group-copy strong {\n overflow: hidden;\n font-size: 11px;\n font-weight: 600;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-profile-group-copy small {\n display: grid;\n place-items: center;\n min-width: 16px;\n height: 16px;\n color: var(--dsw-alias-label-tertiary);\n font:\n 9px/1 var(--ds-font-family-code),\n monospace;\n}\n.dsh-ssh-profile-group-children {\n display: grid;\n gap: 1px;\n margin-left: 13px;\n padding-left: 6px;\n border-left: 1px solid color-mix(in srgb, var(--ssh-border) 66%, transparent);\n animation: dsh-ssh-group-open 140ms ease-out both;\n}\n.dsh-ssh-profile-empty {\n margin: 18px 8px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n text-align: center;\n}\n.dsh-ssh-profile-row {\n display: grid;\n grid-template-columns: 30px minmax(0, 1fr) 10px;\n align-items: center;\n gap: 9px;\n width: 100%;\n min-height: 48px;\n padding: 5px 7px;\n border: 1px solid transparent;\n border-radius: 9px;\n color: inherit;\n background: transparent;\n text-align: left;\n cursor: pointer;\n}\n.dsh-ssh-profile-row:hover {\n background: color-mix(\n in srgb,\n var(--dsw-alias-interactive-bg-hover) 74%,\n transparent\n );\n}\n.dsh-ssh-profile-row.is-active {\n border-color: color-mix(in srgb, var(--ssh-accent) 16%, transparent);\n background: color-mix(in srgb, var(--ssh-accent) 9%, transparent);\n}\n.dsh-ssh-host-monogram {\n display: grid;\n place-items: center;\n width: 28px;\n height: 28px;\n border: 1px solid var(--ssh-border);\n border-radius: 8px;\n color: var(--dsw-alias-label-secondary);\n background: var(--ssh-surface-raised);\n font-size: 11px;\n font-weight: 650;\n}\n.dsh-ssh-profile-row > span:nth-child(2) {\n display: grid;\n min-width: 0;\n gap: 3px;\n}\n.dsh-ssh-profile-row strong,\n.dsh-ssh-profile-row small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-profile-row strong {\n font-size: 12px;\n font-weight: 550;\n}\n.dsh-ssh-profile-row small {\n color: var(--dsw-alias-label-tertiary);\n font:\n 10px/1.2 var(--ds-font-family-code),\n monospace;\n}\n.dsh-ssh-credential-state {\n width: 6px;\n height: 6px;\n border: 1px solid var(--dsw-alias-label-tertiary);\n border-radius: 50%;\n}\n.dsh-ssh-credential-state.is-ready {\n border-color: #5c8a76;\n background: #5c8a76;\n}\n.dsh-ssh-terminal-pane,\n.dsh-ssh-forward-pane,\n.dsh-ssh-settings-pane {\n box-sizing: border-box;\n display: flex;\n min-width: 0;\n min-height: 100%;\n flex-direction: column;\n padding: 0 18px 18px;\n}\n.dsh-ssh-content-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 20px;\n min-height: 76px;\n}\n.dsh-ssh-content-heading h1 {\n margin: 0;\n font-size: 16px;\n font-weight: 650;\n letter-spacing: -0.01em;\n}\n.dsh-ssh-content-heading p {\n margin: 4px 0 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n.dsh-ssh-heading-actions {\n display: flex;\n align-items: center;\n gap: 7px;\n}\n.dsh-ssh-title-line {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-ssh-live-dot {\n width: 7px;\n height: 7px;\n border: 1px solid var(--dsw-alias-label-tertiary);\n border-radius: 50%;\n}\n.dsh-ssh-live-dot.is-connected {\n border-color: #4d8d77;\n background: #4d8d77;\n box-shadow: 0 0 0 3px color-mix(in srgb, #4d8d77 12%, transparent);\n}\n.dsh-ssh-live-dot.is-connecting {\n border-color: #a27e45;\n background: #a27e45;\n}\n.dsh-ssh-live-dot.is-error {\n border-color: #a85a55;\n background: #a85a55;\n}\n.dsh-ssh-terminal-frame {\n display: flex;\n min-height: 360px;\n flex: 1;\n flex-direction: column;\n overflow: hidden;\n border: 1px solid color-mix(in srgb, #8ba49e 22%, #101817);\n border-radius: 12px;\n background: #111817;\n box-shadow: 0 10px 34px color-mix(in srgb, #0d1513 14%, transparent);\n}\n.dsh-ssh-xterm {\n min-height: 0;\n flex: 1;\n padding: 11px 11px 0;\n}\n.dsh-ssh-xterm .xterm {\n height: 100%;\n}\n.dsh-ssh-terminal-status {\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 28px;\n padding: 0 11px;\n border-top: 1px solid #ffffff12;\n color: #879691;\n background: #0d1413;\n font:\n 10px/1 var(--ds-font-family-code),\n monospace;\n}\n.dsh-ssh-banner {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 8px 18px;\n border-bottom: 1px solid transparent;\n font-size: 11px;\n}\n.dsh-ssh-banner > span {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n.dsh-ssh-banner code {\n font-family: var(--ds-font-family-code), monospace;\n}\n.dsh-ssh-banner button:not(.dsh-ssh-small-primary) {\n display: grid;\n place-items: center;\n border: 0;\n color: inherit;\n background: transparent;\n}\n.dsh-ssh-banner.is-error {\n border-color: color-mix(in srgb, var(--ssh-danger) 22%, transparent);\n color: var(--ssh-danger);\n background: color-mix(in srgb, var(--ssh-danger) 7%, var(--ssh-surface));\n}\n.dsh-ssh-banner.is-warning {\n border-color: color-mix(in srgb, var(--ssh-warning) 22%, transparent);\n color: color-mix(\n in srgb,\n var(--ssh-warning) 85%,\n var(--dsw-alias-label-primary)\n );\n background: color-mix(in srgb, var(--ssh-warning) 8%, var(--ssh-surface));\n}\n.dsh-ssh-inline-error {\n margin: 0 0 10px;\n padding: 7px 9px;\n border-radius: 7px;\n color: var(--ssh-danger);\n background: color-mix(in srgb, var(--ssh-danger) 7%, transparent);\n font-size: 11px;\n}\n.dsh-ssh-empty-state {\n display: grid;\n place-items: center;\n align-content: center;\n min-height: 100%;\n padding: 40px;\n text-align: center;\n}\n.dsh-ssh-empty-state > span {\n display: grid;\n place-items: center;\n width: 48px;\n height: 48px;\n margin-bottom: 14px;\n border: 1px solid var(--ssh-border);\n border-radius: 14px;\n color: var(--ssh-accent);\n background: var(--ssh-surface-raised);\n}\n.dsh-ssh-empty-state h1 {\n margin: 0;\n font-size: 17px;\n}\n.dsh-ssh-empty-state p {\n max-width: 420px;\n margin: 8px 0 18px;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 1.6;\n}\n.dsh-ssh-inspector {\n overflow: auto;\n}\n.dsh-ssh-session-chip {\n display: flex;\n align-items: center;\n gap: 9px;\n margin: 12px 12px 4px;\n padding: 9px 10px;\n border: 1px solid var(--ssh-border);\n border-radius: 9px;\n background: color-mix(in srgb, var(--ssh-surface-raised) 86%, transparent);\n}\n.dsh-ssh-session-chip > span:nth-child(2) {\n display: grid;\n gap: 2px;\n}\n.dsh-ssh-session-chip strong {\n font-size: 11px;\n}\n.dsh-ssh-session-chip small {\n color: var(--dsw-alias-label-tertiary);\n font:\n 9px/1 var(--ds-font-family-code),\n monospace;\n}\n.dsh-ssh-session-pulse {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--ssh-accent);\n}\n.dsh-ssh-fieldset {\n display: grid;\n gap: 3px;\n margin: 13px 12px 0;\n padding: 0;\n border: 0;\n}\n.dsh-ssh-fieldset legend {\n margin-bottom: 5px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n font-weight: 600;\n}\n.dsh-ssh-check-row,\n.dsh-ssh-radio-row {\n display: flex;\n align-items: center;\n gap: 9px;\n min-height: 38px;\n padding: 3px 5px;\n border-radius: 8px;\n}\n.dsh-ssh-check-row:hover,\n.dsh-ssh-radio-row:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-check-row input,\n.dsh-ssh-radio-row input {\n accent-color: var(--ssh-accent);\n}\n.dsh-ssh-check-row > span,\n.dsh-ssh-radio-row > span {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n.dsh-ssh-check-row strong,\n.dsh-ssh-radio-row strong {\n font-size: 11px;\n font-weight: 550;\n}\n.dsh-ssh-check-row small,\n.dsh-ssh-radio-row small {\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-switch-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 20px;\n min-height: 48px;\n margin: 13px 12px 0;\n padding: 7px 9px;\n border: 1px solid var(--ssh-border);\n border-radius: 9px;\n}\n.dsh-ssh-switch-row > span {\n display: grid;\n gap: 3px;\n}\n.dsh-ssh-switch-row strong {\n font-size: 11px;\n font-weight: 550;\n}\n.dsh-ssh-switch-row small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n line-height: 1.35;\n}\n.dsh-ssh-switch-row input {\n width: 28px;\n height: 16px;\n accent-color: var(--ssh-accent);\n}\n.dsh-ssh-inspector-hint,\n.dsh-ssh-save-state {\n margin: 10px 12px 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n.dsh-ssh-inspector-empty {\n margin: 14px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n line-height: 1.55;\n}\n.dsh-ssh-forward-list {\n display: grid;\n align-content: start;\n gap: 5px;\n}\n.dsh-ssh-forward-row {\n display: grid;\n grid-template-columns: 32px minmax(0, 1fr) auto 28px auto 28px;\n align-items: center;\n gap: 8px;\n min-height: 54px;\n padding: 6px 9px;\n border: 1px solid var(--ssh-border);\n border-radius: 10px;\n background: color-mix(in srgb, var(--ssh-surface-raised) 88%, transparent);\n}\n.dsh-ssh-forward-kind {\n display: grid;\n place-items: center;\n width: 28px;\n height: 28px;\n border: 1px solid var(--ssh-border);\n border-radius: 8px;\n color: var(--ssh-accent-strong);\n font:\n 600 11px/1 var(--ds-font-family-code),\n monospace;\n}\n.dsh-ssh-forward-copy {\n display: grid;\n min-width: 0;\n gap: 4px;\n}\n.dsh-ssh-forward-copy strong {\n font-size: 12px;\n}\n.dsh-ssh-forward-copy small {\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary);\n font:\n 10px/1 var(--ds-font-family-code),\n monospace;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-state-label {\n padding: 3px 7px;\n border-radius: 999px;\n color: var(--dsw-alias-label-tertiary);\n background: color-mix(\n in srgb,\n var(--dsw-alias-label-primary) 5%,\n transparent\n );\n font-size: 9px;\n}\n.dsh-ssh-state-label.is-running {\n color: #497967;\n background: color-mix(in srgb, #5d957f 10%, transparent);\n}\n.dsh-ssh-state-label.is-error {\n color: var(--ssh-danger);\n background: color-mix(in srgb, var(--ssh-danger) 8%, transparent);\n}\n.dsh-ssh-table-empty {\n display: grid;\n place-items: center;\n min-height: 180px;\n border: 1px dashed var(--ssh-border);\n border-radius: 12px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n}\n.dsh-ssh-settings-group {\n display: grid;\n max-width: 680px;\n gap: 8px;\n}\n.dsh-ssh-settings-group .dsh-ssh-switch-row {\n margin: 0;\n}\n.dsh-ssh-number-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 120px 32px;\n align-items: center;\n gap: 8px;\n min-height: 60px;\n padding: 6px 10px;\n border: 1px solid var(--ssh-border);\n border-radius: 10px;\n background: color-mix(in srgb, var(--ssh-surface-raised) 80%, transparent);\n}\n.dsh-ssh-number-row > span {\n display: grid;\n gap: 3px;\n}\n.dsh-ssh-number-row strong {\n font-size: 11px;\n}\n.dsh-ssh-number-row small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n}\n.dsh-ssh-number-row input {\n height: 30px;\n padding: 0 8px;\n}\n.dsh-ssh-number-row em {\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n font-style: normal;\n}\n.dsh-ssh-dialog-layer {\n position: fixed;\n z-index: 1000;\n inset: 0;\n display: grid;\n place-items: center;\n padding: 28px;\n background: color-mix(in srgb, #111817 28%, transparent);\n backdrop-filter: blur(3px);\n}\n.dsh-ssh-dialog {\n box-sizing: border-box;\n width: min(620px, calc(100vw - 40px));\n max-height: min(760px, calc(100vh - 40px));\n overflow: auto;\n border: 1px solid\n color-mix(in srgb, var(--dsw-alias-label-primary) 15%, transparent);\n border-radius: 14px;\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-bg-base, #f7f8f7);\n box-shadow: 0 24px 70px #07100d2e;\n}\n.dsh-ssh-dialog > header {\n position: sticky;\n z-index: 1;\n top: 0;\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 64px;\n padding: 0 18px;\n border-bottom: 1px solid\n var(\n --ssh-border,\n color-mix(in srgb, var(--dsw-alias-label-primary) 10%, transparent)\n );\n background: color-mix(\n in srgb,\n var(--dsw-alias-bg-base, #f7f8f7) 94%,\n transparent\n );\n backdrop-filter: blur(12px);\n}\n.dsh-ssh-dialog h2 {\n margin: 0;\n font-size: 15px;\n}\n.dsh-ssh-dialog header p {\n margin: 3px 0 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n.dsh-ssh-form {\n --ssh-border: color-mix(\n in srgb,\n var(--dsw-alias-label-primary) 11%,\n transparent\n );\n --ssh-accent: #547d78;\n --ssh-accent-strong: #406e67;\n --ssh-danger: #9c504c;\n display: grid;\n gap: 13px;\n padding: 18px;\n}\n.dsh-ssh-form-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n}\n.dsh-ssh-form-grid.is-host {\n grid-template-columns: minmax(0, 1fr) 110px;\n}\n.dsh-ssh-field {\n display: grid;\n gap: 5px;\n min-width: 0;\n color: var(--dsw-alias-label-secondary);\n font-size: 10px;\n font-weight: 550;\n}\n.dsh-ssh-field input,\n.dsh-ssh-field select {\n height: 34px;\n padding: 0 9px;\n}\n.dsh-ssh-field textarea {\n padding: 8px 9px;\n resize: vertical;\n font-family: var(--ds-font-family-code), monospace;\n}\n.dsh-ssh-field small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n font-weight: 400;\n}\n.dsh-ssh-form-divider {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-top: 2px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n.dsh-ssh-form-divider:after {\n height: 1px;\n flex: 1;\n background: var(--ssh-border);\n content: "";\n}\n.dsh-ssh-dialog-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding-top: 5px;\n}\n.dsh-ssh-form .dsh-ssh-switch-row {\n margin: 0;\n}\n.dsh-ssh-form .dsh-ssh-inline-error {\n margin: 0;\n}\n@container dpu-workspace (max-width: 1120px) {\n .dsh-ssh-toolbar {\n grid-template-columns: 1fr auto auto;\n }\n .dsh-ssh-brand small {\n display: none;\n }\n}\n@container dpu-workspace (max-width: 820px) {\n .dsh-ssh-toolbar {\n grid-template-columns: 1fr auto;\n gap: 8px;\n padding: 0 12px;\n }\n .dsh-ssh-segments {\n grid-row: 2;\n grid-column: 1/-1;\n margin-bottom: 8px;\n overflow-x: auto;\n scrollbar-width: none;\n }\n .dsh-ssh-segments::-webkit-scrollbar {\n display: none;\n }\n .dsh-ssh-segments button {\n min-width: 72px;\n height: 36px;\n flex: none;\n }\n .dsh-ssh-toolbar {\n padding-top: 8px;\n }\n .dsh-ssh-content-heading {\n align-items: flex-start;\n flex-direction: column;\n padding: 14px 0;\n }\n .dsh-ssh-heading-actions {\n flex-wrap: wrap;\n }\n .dsh-ssh-forward-row {\n grid-template-columns: 32px minmax(0, 1fr) auto;\n }\n .dsh-ssh-forward-row > .dsh-ssh-icon-button,\n .dsh-ssh-forward-row > .dsh-ssh-small-primary {\n display: none;\n }\n}\n@container dpu-workspace (max-width: 520px) {\n .dsh-ssh-toolbar {\n padding-right: max(10px, env(safe-area-inset-right));\n padding-left: max(10px, env(safe-area-inset-left));\n }\n .dsh-ssh-toolbar > .dsh-ssh-primary-button {\n width: 40px;\n min-height: 40px;\n padding: 0;\n }\n .dsh-ssh-toolbar > .dsh-ssh-primary-button span {\n display: none;\n }\n .dsh-ssh-terminal-pane,\n .dsh-ssh-forward-pane,\n .dsh-ssh-settings-pane,\n .dsh-ssh-vault-pane,\n .dsh-ssh-profile-sftp-pane {\n padding-right: 10px;\n padding-left: 10px;\n }\n .dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-columns,\n .dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row {\n grid-template-columns: minmax(120px, 1fr) 64px;\n }\n .dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-columns > :nth-child(3),\n .dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row > :nth-child(3) {\n display: none;\n }\n .dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row {\n min-height: 44px;\n }\n .dsh-ssh-number-row {\n grid-template-columns: minmax(0, 1fr) 86px 28px;\n }\n}\n@media (max-width: 600px) {\n .dsh-ssh-dialog-layer {\n align-items: stretch;\n padding: 0;\n }\n .dsh-ssh-dialog {\n width: 100%;\n max-height: 100dvh;\n border: 0;\n border-radius: 0;\n }\n .dsh-ssh-form-grid,\n .dsh-ssh-form-grid.is-host {\n grid-template-columns: 1fr;\n }\n .dsh-ssh-dialog-actions {\n position: sticky;\n bottom: 0;\n flex-wrap: wrap;\n padding: 10px 0 max(10px, env(safe-area-inset-bottom));\n background: var(--dsw-alias-bg-base, #f7f8f7);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .dsh-ssh-disclosure {\n transition: none;\n }\n}\n@media (prefers-reduced-transparency: reduce) {\n .dsh-ssh-dialog-layer {\n backdrop-filter: none;\n }\n .dsh-ssh-dialog > header {\n backdrop-filter: none;\n }\n}\n\n.dsh-ssh-activity-trigger {\n box-sizing: border-box;\n display: inline-grid;\n place-items: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 1px solid transparent;\n border-radius: 8px;\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n cursor: pointer;\n}\n.dsh-ssh-activity-trigger:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-activity-trigger.is-active {\n border-color: color-mix(in srgb, var(--ssh-accent, #547d78) 16%, transparent);\n color: var(--ssh-accent-strong, #406e67);\n background: color-mix(in srgb, var(--ssh-accent, #547d78) 8%, transparent);\n}\n.dsh-ssh-panel-right-icon {\n transform: rotate(180deg);\n}\n.dsh-ssh-activity-trigger:focus-visible,\n.dsh-ssh-activity-tabs button:focus-visible,\n.dsh-ssh-sftp button:focus-visible,\n.dsh-ssh-sftp input:focus-visible,\n.dsh-ssh-sftp select:focus-visible {\n outline: 2px solid\n color-mix(in srgb, var(--ssh-accent, #547d78) 62%, transparent);\n outline-offset: 2px;\n}\n.dsh-ssh-activity-panel {\n --ssh-activity-border: color-mix(\n in srgb,\n var(--dsw-alias-label-primary) 10%,\n transparent\n );\n box-sizing: border-box;\n display: flex;\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n flex-direction: column;\n color: var(--dsw-alias-label-primary);\n background: color-mix(\n in srgb,\n var(--dsw-alias-bg-base, #f7f8f7) 96%,\n transparent\n );\n font-family:\n var(--ds-font-family),\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n}\n.dsh-ssh-activity-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 58px;\n padding: 0 12px 0 14px;\n border-bottom: 1px solid var(--ssh-activity-border);\n background: color-mix(\n in srgb,\n var(--dsw-alias-bg-base, #f7f8f7) 88%,\n transparent\n );\n backdrop-filter: blur(10px);\n}\n.dsh-ssh-activity-header > span {\n display: grid;\n min-width: 0;\n gap: 3px;\n}\n.dsh-ssh-activity-header strong {\n font-size: 13px;\n font-weight: 650;\n}\n.dsh-ssh-activity-header small {\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary);\n font:\n 10px/1.2 var(--ds-font-family-code),\n monospace;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-activity-tabs {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 3px;\n margin: 10px 12px 0;\n padding: 3px;\n border: 1px solid var(--ssh-activity-border);\n border-radius: 10px;\n background: color-mix(\n in srgb,\n var(--dsw-alias-label-primary) 3%,\n transparent\n );\n}\n.dsh-ssh-activity-tabs button {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n min-height: 30px;\n padding: 0 9px;\n border: 0;\n border-radius: 7px;\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n font: 550 11px/1 var(--ds-font-family);\n cursor: pointer;\n}\n.dsh-ssh-activity-tabs button:hover {\n color: var(--dsw-alias-label-primary);\n}\n.dsh-ssh-activity-tabs button.is-active {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-bg-base, #f7f8f7);\n box-shadow: 0 1px 3px\n color-mix(in srgb, var(--dsw-alias-label-primary) 9%, transparent);\n}\n.dsh-ssh-activity-tabs button:only-child {\n grid-column: 1/-1;\n}\n.dsh-ssh-activity-body {\n display: flex;\n min-height: 0;\n flex: 1;\n overflow: hidden;\n padding: 14px 12px 18px;\n}\n.dsh-ssh-activity-body > * {\n width: 100%;\n}\n.dsh-ssh-activity-state {\n margin: 20px 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n.dsh-ssh-sftp {\n display: flex;\n min-height: 100%;\n flex-direction: column;\n}\n.dsh-ssh-sftp-hostbar {\n display: grid;\n grid-template-columns: 28px minmax(0, 1fr);\n align-items: center;\n gap: 8px;\n padding: 0 2px 10px;\n}\n.dsh-ssh-sftp-hostbar label {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n.dsh-ssh-sftp-hostbar select {\n min-width: 0;\n padding: 0;\n border: 0;\n outline: 0;\n color: var(--dsw-alias-label-primary);\n background: transparent;\n font: 600 11px/1.25 var(--ds-font-family);\n cursor: pointer;\n}\n.dsh-ssh-sftp-hostbar small {\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary);\n font:\n 9px/1.2 var(--ds-font-family-code),\n monospace;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-sftp-pathbar {\n display: grid;\n grid-template-columns: 30px minmax(0, 1fr) 30px;\n gap: 5px;\n margin-bottom: 9px;\n}\n.dsh-ssh-sftp-pathbar.has-upload {\n grid-template-columns: 30px minmax(0, 1fr) 30px auto;\n}\n.dsh-ssh-sftp-pathbar button,\n.dsh-ssh-sftp-pathbar input {\n box-sizing: border-box;\n height: 30px;\n border: 1px solid var(--ssh-activity-border);\n border-radius: 8px;\n color: var(--dsw-alias-label-primary);\n background: color-mix(\n in srgb,\n var(--dsw-alias-bg-base, #fff) 86%,\n transparent\n );\n}\n.dsh-ssh-sftp-pathbar button {\n display: grid;\n place-items: center;\n padding: 0;\n cursor: pointer;\n}\n.dsh-ssh-sftp-pathbar button:disabled {\n opacity: 0.35;\n cursor: default;\n}\n.dsh-ssh-sftp-pathbar input {\n min-width: 0;\n padding: 0 9px;\n outline: 0;\n font:\n 9px/1 var(--ds-font-family-code),\n monospace;\n}\n.dsh-ssh-sftp-pathbar .dsh-ssh-sftp-upload-button {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 0 10px;\n color: #f6fbf9;\n background: var(--ssh-accent-strong, #406e67);\n font: 550 10px/1 var(--ds-font-family);\n}\n.dsh-ssh-directory-error {\n margin: 0 0 8px;\n padding: 7px 8px;\n border-radius: 7px;\n color: var(--ssh-danger, #9c504c);\n background: color-mix(in srgb, var(--ssh-danger, #9c504c) 7%, transparent);\n font-size: 10px;\n line-height: 1.4;\n}\n.dsh-ssh-sftp-table {\n min-height: 0;\n flex: 1;\n overflow: auto;\n border: 1px solid var(--ssh-activity-border);\n border-radius: 10px;\n background: color-mix(\n in srgb,\n var(--dsw-alias-bg-base, #fff) 70%,\n transparent\n );\n}\n.dsh-ssh-sftp-columns,\n.dsh-ssh-sftp-row {\n display: grid;\n grid-template-columns: minmax(120px, 1fr) 58px 72px;\n align-items: center;\n gap: 7px;\n}\n.dsh-ssh-sftp-columns {\n position: sticky;\n z-index: 1;\n top: 0;\n min-height: 28px;\n padding: 0 9px;\n border-bottom: 1px solid var(--ssh-activity-border);\n color: var(--dsw-alias-label-tertiary);\n background: color-mix(\n in srgb,\n var(--dsw-alias-bg-base, #f7f8f7) 94%,\n transparent\n );\n font-size: 8px;\n}\n.dsh-ssh-sftp-row {\n box-sizing: border-box;\n width: 100%;\n min-height: 34px;\n padding: 0 9px;\n border: 0;\n border-bottom: 1px solid\n color-mix(in srgb, var(--ssh-activity-border) 55%, transparent);\n color: var(--dsw-alias-label-primary);\n background: transparent;\n text-align: left;\n}\n.dsh-ssh-sftp-row:last-child {\n border-bottom: 0;\n}\n.dsh-ssh-sftp-row.is-directory {\n cursor: pointer;\n}\n.dsh-ssh-sftp-row.is-directory:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-sftp-row:disabled {\n opacity: 1;\n}\n.dsh-ssh-sftp-row > span {\n display: flex;\n min-width: 0;\n align-items: center;\n gap: 7px;\n}\n.dsh-ssh-sftp-row svg {\n flex: none;\n color: var(--dsw-alias-label-secondary);\n}\n.dsh-ssh-sftp-row.is-directory svg {\n color: var(--ssh-accent-strong, #406e67);\n}\n.dsh-ssh-sftp-row strong {\n overflow: hidden;\n font-size: 10px;\n font-weight: 500;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-sftp-row small {\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary);\n font:\n 8px/1.2 var(--ds-font-family-code),\n monospace;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-sftp-state {\n display: grid;\n place-items: center;\n min-height: 160px;\n margin: 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n.dsh-ssh-activity-empty {\n display: grid;\n place-items: center;\n align-content: center;\n min-height: 240px;\n padding: 24px;\n text-align: center;\n}\n.dsh-ssh-activity-empty > svg {\n margin-bottom: 10px;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-ssh-activity-empty strong {\n font-size: 12px;\n}\n.dsh-ssh-activity-empty p {\n max-width: 260px;\n margin: 7px 0 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n line-height: 1.5;\n}\n.dsh-ssh-terminal-observer {\n display: flex;\n height: 100%;\n min-height: 280px;\n overflow: hidden;\n flex-direction: column;\n border: 1px solid color-mix(in srgb, #8ba49e 22%, #101817);\n border-radius: 11px;\n background: #111817;\n}\n.dsh-ssh-terminal-observer-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 42px;\n padding: 0 10px;\n border-bottom: 1px solid #ffffff12;\n color: #dce5e1;\n background: #0d1413;\n}\n.dsh-ssh-terminal-observer-heading > span:first-child {\n display: grid;\n min-width: 0;\n gap: 3px;\n}\n.dsh-ssh-terminal-observer-heading strong,\n.dsh-ssh-terminal-observer-heading small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-terminal-observer-heading strong {\n font-size: 10px;\n}\n.dsh-ssh-terminal-observer-heading small {\n color: #879691;\n font:\n 8px/1 var(--ds-font-family-code),\n monospace;\n}\n.dsh-ssh-terminal-state {\n flex: none;\n color: #879691;\n font-size: 9px;\n}\n.dsh-ssh-terminal-state.is-running {\n color: #8fc0af;\n}\n.dsh-ssh-terminal-screen {\n box-sizing: border-box;\n min-height: 0;\n flex: 1;\n padding: 9px 8px 0;\n}\n.dsh-ssh-terminal-screen .xterm {\n height: 100%;\n}\n@media (prefers-reduced-transparency: reduce) {\n .dsh-ssh-activity-header {\n backdrop-filter: none;\n }\n}\n\n.dsh-ssh-sftp-row:not(.is-directory) {\n cursor: pointer;\n}\n.dsh-ssh-file-preview {\n display: flex;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n overflow: hidden;\n border: 1px solid var(--ssh-activity-border);\n border-radius: 10px;\n background: color-mix(\n in srgb,\n var(--dsw-alias-bg-base, #fff) 70%,\n transparent\n );\n}\n.dsh-ssh-file-preview > header {\n display: grid;\n grid-template-columns: 28px minmax(0, 1fr) 28px;\n align-items: center;\n gap: 7px;\n min-height: 42px;\n padding: 0 7px;\n border-bottom: 1px solid var(--ssh-activity-border);\n}\n.dsh-ssh-file-preview > header > span {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n.dsh-ssh-file-preview > header strong,\n.dsh-ssh-file-preview > header small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-file-preview > header strong {\n font-size: 10px;\n}\n.dsh-ssh-file-preview > header small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 8px;\n}\n.dsh-ssh-file-preview > header > a {\n display: grid;\n place-items: center;\n width: 28px;\n height: 28px;\n border-radius: 8px;\n color: var(--dsw-alias-label-secondary);\n text-decoration: none;\n}\n.dsh-ssh-file-preview > header > a:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-file-preview-body {\n display: flex;\n min-height: 0;\n flex: 1;\n overflow: auto;\n flex-direction: column;\n}\n.dsh-ssh-file-preview-body > pre {\n box-sizing: border-box;\n min-width: 100%;\n min-height: 100%;\n margin: 0;\n padding: 12px;\n color: var(--dsw-alias-label-primary);\n background: transparent;\n font:\n 10px/1.55 var(--ds-font-family-code),\n monospace;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n.dsh-ssh-file-preview-body > small {\n padding: 8px 12px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n}\n.dsh-ssh-file-preview-body > img {\n display: block;\n max-width: 100%;\n max-height: 100%;\n margin: auto;\n object-fit: contain;\n}\n.dsh-ssh-file-preview-body > iframe {\n width: 100%;\n height: 100%;\n min-height: 420px;\n border: 0;\n background: #fff;\n}\n.dsh-ssh-file-binary {\n display: grid;\n place-items: center;\n align-content: center;\n min-height: 240px;\n padding: 20px;\n text-align: center;\n}\n.dsh-ssh-file-binary > svg {\n margin-bottom: 9px;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-ssh-file-binary strong {\n font-size: 11px;\n}\n.dsh-ssh-file-binary p {\n margin: 5px 0 12px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n}\n.dsh-ssh-file-binary a {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-height: 30px;\n padding: 0 10px;\n border: 1px solid var(--ssh-activity-border);\n border-radius: 8px;\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-button-elevated-fill);\n font-size: 10px;\n text-decoration: none;\n}\n.dsh-ssh-terminal-workbench {\n display: flex;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n gap: 7px;\n}\n.dsh-ssh-terminal-switcher {\n display: flex;\n flex: none;\n gap: 3px;\n overflow: auto;\n padding: 1px;\n}\n.dsh-ssh-terminal-switcher button {\n display: flex;\n min-width: 0;\n max-width: 150px;\n align-items: center;\n gap: 6px;\n height: 28px;\n padding: 0 8px;\n border: 1px solid transparent;\n border-radius: 7px;\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n font: 500 9px/1 var(--ds-font-family);\n white-space: nowrap;\n cursor: pointer;\n}\n.dsh-ssh-terminal-switcher button:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-terminal-switcher button.is-active {\n border-color: var(--ssh-activity-border);\n color: var(--dsw-alias-label-primary);\n background: color-mix(in srgb, var(--ssh-accent, #547d78) 8%, transparent);\n}\n.dsh-ssh-terminal-state-dot {\n width: 5px;\n height: 5px;\n flex: none;\n border: 1px solid #75827e;\n border-radius: 50%;\n}\n.dsh-ssh-terminal-state-dot.is-running {\n border-color: #6ca08d;\n background: #6ca08d;\n}\n.dsh-ssh-terminal-workbench .dsh-ssh-terminal-observer {\n height: auto;\n min-height: 0;\n flex: 1;\n}\n.dsh-ssh-terminal-input-error {\n margin: 0;\n padding: 6px 8px;\n border-radius: 6px;\n color: #d98e88;\n background: #351c1a;\n font-size: 9px;\n}\n\n.dsh-ssh-workspace::before {\n position: absolute;\n z-index: 0;\n inset: 0;\n pointer-events: none;\n background:\n radial-gradient(\n circle at 18% 12%,\n color-mix(in srgb, var(--ssh-accent) 7%, transparent),\n transparent 28%\n ),\n linear-gradient(\n 115deg,\n transparent 0 56%,\n color-mix(in srgb, var(--ssh-accent) 3%, transparent) 56.1% 56.35%,\n transparent 56.45% 100%\n );\n content: "";\n}\n.dsh-ssh-workspace > * {\n position: relative;\n z-index: 1;\n}\n.dsh-ssh-toolbar {\n box-shadow:\n inset 0 1px 0\n color-mix(in srgb, var(--dsw-alias-bg-base, #fff) 70%, transparent),\n 0 8px 28px\n color-mix(in srgb, var(--dsw-alias-label-primary) 3%, transparent);\n}\n.dsh-ssh-brand-glyph {\n position: relative;\n overflow: hidden;\n}\n.dsh-ssh-brand-glyph::after {\n position: absolute;\n width: 12px;\n height: 1px;\n left: 9px;\n bottom: 5px;\n border-radius: 1px;\n background: color-mix(in srgb, var(--ssh-accent) 66%, transparent);\n content: "";\n}\n.dsh-ssh-profile-row {\n position: relative;\n transition:\n background 140ms ease,\n border-color 140ms ease,\n transform 160ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n.dsh-ssh-profile-row::before {\n position: absolute;\n width: 2px;\n left: 0;\n top: 11px;\n bottom: 11px;\n border-radius: 2px;\n background: var(--ssh-accent);\n opacity: 0;\n transform: scaleY(0.45);\n transition:\n opacity 140ms ease,\n transform 170ms cubic-bezier(0.2, 0.8, 0.2, 1);\n content: "";\n}\n.dsh-ssh-profile-row.is-active {\n transform: translateX(2px);\n}\n.dsh-ssh-profile-row.is-active::before {\n opacity: 0.8;\n transform: scaleY(1);\n}\n.dsh-ssh-profile-row:active,\n.dsh-ssh-sftp-row:active,\n.dsh-ssh-terminal-switcher button:active {\n transform: scale(0.985);\n}\n.dsh-ssh-activity-panel {\n animation: dsh-ssh-panel-enter 180ms cubic-bezier(0.2, 0.8, 0.2, 1) both;\n}\n.dsh-ssh-sftp-table,\n.dsh-ssh-file-preview,\n.dsh-ssh-terminal-observer {\n box-shadow:\n inset 0 1px 0\n color-mix(in srgb, var(--dsw-alias-bg-base, #fff) 8%, transparent),\n 0 10px 30px\n color-mix(in srgb, var(--dsw-alias-label-primary) 4%, transparent);\n}\n.dsh-ssh-sftp-row {\n transition:\n background 120ms ease,\n transform 120ms ease;\n}\n.dsh-ssh-file-preview-body {\n animation: dsh-ssh-content-enter 160ms ease-out both;\n}\n.dsh-ssh-terminal-switcher button {\n transition:\n color 120ms ease,\n background 120ms ease,\n border-color 120ms ease,\n transform 120ms ease;\n}\n.dsh-ssh-terminal-switcher button.is-active {\n box-shadow: inset 0 1px 0\n color-mix(in srgb, var(--dsw-alias-bg-base, #fff) 55%, transparent);\n}\n.dsh-ssh-vault-pane {\n box-sizing: border-box;\n display: flex;\n min-height: 100%;\n flex-direction: column;\n padding: 0 18px 18px;\n}\n.dsh-ssh-vault-list {\n display: grid;\n align-content: start;\n gap: 5px;\n}\n.dsh-ssh-vault-row {\n display: grid;\n grid-template-columns: 34px minmax(160px, 1fr) auto 70px 28px 28px;\n align-items: center;\n gap: 9px;\n min-height: 56px;\n padding: 5px 8px;\n border: 1px solid var(--ssh-border);\n border-radius: 10px;\n background: color-mix(in srgb, var(--ssh-surface-raised) 82%, transparent);\n transition:\n background 140ms ease,\n border-color 140ms ease,\n transform 150ms ease;\n}\n.dsh-ssh-vault-row:hover {\n border-color: color-mix(in srgb, var(--ssh-accent) 18%, var(--ssh-border));\n background: color-mix(in srgb, var(--ssh-surface-raised) 94%, transparent);\n transform: translateY(-1px);\n}\n.dsh-ssh-vault-glyph {\n display: grid;\n place-items: center;\n width: 30px;\n height: 30px;\n border: 1px solid color-mix(in srgb, var(--ssh-accent) 18%, var(--ssh-border));\n border-radius: 9px;\n color: var(--ssh-accent-strong);\n background: color-mix(in srgb, var(--ssh-accent) 7%, transparent);\n}\n.dsh-ssh-vault-row > span:nth-child(2) {\n display: grid;\n min-width: 0;\n gap: 3px;\n}\n.dsh-ssh-vault-row strong,\n.dsh-ssh-vault-row small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-vault-row strong {\n font-size: 12px;\n font-weight: 600;\n}\n.dsh-ssh-vault-row small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n.dsh-ssh-vault-state {\n padding: 3px 7px;\n border-radius: 6px;\n color: var(--ssh-danger);\n background: color-mix(in srgb, var(--ssh-danger) 7%, transparent);\n font-size: 9px;\n}\n.dsh-ssh-vault-state.is-ready {\n color: var(--ssh-accent-strong);\n background: color-mix(in srgb, var(--ssh-accent) 9%, transparent);\n}\n.dsh-ssh-vault-empty {\n display: grid;\n place-items: center;\n align-content: center;\n min-height: 320px;\n text-align: center;\n}\n.dsh-ssh-vault-empty > span {\n display: grid;\n place-items: center;\n width: 46px;\n height: 46px;\n margin-bottom: 12px;\n border: 1px solid var(--ssh-border);\n border-radius: 14px;\n color: var(--ssh-accent-strong);\n background: color-mix(in srgb, var(--ssh-surface-raised) 88%, transparent);\n box-shadow: 0 12px 30px\n color-mix(in srgb, var(--dsw-alias-label-primary) 5%, transparent);\n}\n.dsh-ssh-vault-empty strong {\n font-size: 13px;\n}\n.dsh-ssh-vault-empty p {\n max-width: 360px;\n margin: 7px 0 16px;\n color: var(--dsw-alias-label-secondary);\n font-size: 11px;\n line-height: 1.55;\n}\n.dsh-ssh-credential-reference {\n display: grid;\n grid-template-columns: 34px minmax(0, 1fr) auto;\n align-items: center;\n gap: 9px;\n min-height: 52px;\n padding: 5px 9px;\n border: 1px solid color-mix(in srgb, var(--ssh-accent) 18%, var(--ssh-border));\n border-radius: 10px;\n background: color-mix(\n in srgb,\n var(--ssh-accent) 6%,\n var(--ssh-surface-raised)\n );\n}\n.dsh-ssh-credential-reference > span:first-child {\n display: grid;\n place-items: center;\n width: 30px;\n height: 30px;\n border-radius: 8px;\n color: var(--ssh-accent-strong);\n background: color-mix(in srgb, var(--ssh-accent) 9%, transparent);\n}\n.dsh-ssh-credential-reference > span:nth-child(2) {\n display: grid;\n gap: 3px;\n}\n.dsh-ssh-credential-reference strong {\n font-size: 11px;\n}\n.dsh-ssh-credential-reference small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n}\n.dsh-ssh-credential-reference em {\n color: var(--ssh-accent-strong);\n font-size: 9px;\n font-style: normal;\n}\n.dsh-ssh-jump-chain {\n display: grid;\n gap: 8px;\n margin: 0;\n padding: 10px;\n border: 1px solid var(--ssh-border);\n border-radius: 10px;\n background: color-mix(in srgb, var(--ssh-surface-raised) 72%, transparent);\n}\n.dsh-ssh-jump-chain legend {\n padding: 0 5px;\n color: var(--dsw-alias-label-secondary);\n font-size: 10px;\n font-weight: 600;\n}\n.dsh-ssh-jump-chain > p {\n margin: 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n}\n.dsh-ssh-jump-chain > div {\n display: grid;\n gap: 5px;\n}\n.dsh-ssh-jump-row {\n display: grid;\n grid-template-columns: 22px minmax(0, 1fr) 28px 28px 28px;\n align-items: center;\n gap: 4px;\n}\n.dsh-ssh-jump-row > em {\n display: grid;\n place-items: center;\n width: 20px;\n height: 20px;\n border-radius: 6px;\n color: var(--ssh-accent-strong);\n background: color-mix(in srgb, var(--ssh-accent) 9%, transparent);\n font:\n 600 9px/1 var(--ds-font-family-code),\n monospace;\n font-style: normal;\n}\n.dsh-ssh-jump-row select {\n box-sizing: border-box;\n min-width: 0;\n height: 30px;\n padding: 0 8px;\n border: 1px solid var(--ssh-border);\n border-radius: 8px;\n color: var(--dsw-alias-label-primary);\n background: var(--ssh-surface-raised);\n font-size: 10px;\n}\n.dsh-ssh-jump-row .dsh-ssh-icon-button:disabled {\n opacity: 0.3;\n cursor: default;\n}\n.dsh-ssh-jump-empty {\n padding: 7px !important;\n border-radius: 7px;\n background: color-mix(in srgb, var(--ssh-warning) 7%, transparent);\n}\n.dsh-ssh-jump-chain > .dsh-ssh-secondary-button {\n justify-self: start;\n}\n@keyframes dsh-ssh-panel-enter {\n from {\n opacity: 0;\n transform: translateX(6px);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n}\n@keyframes dsh-ssh-content-enter {\n from {\n opacity: 0;\n transform: translateY(3px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n@keyframes dsh-ssh-group-open {\n from {\n opacity: 0;\n transform: translateY(-2px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n@media (max-width: 820px) {\n .dsh-ssh-vault-row {\n grid-template-columns: 34px minmax(120px, 1fr) auto 28px;\n }\n .dsh-ssh-vault-row > small,\n .dsh-ssh-vault-row > .dsh-ssh-icon-button:last-child {\n display: none;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .dsh-ssh-activity-panel,\n .dsh-ssh-file-preview-body,\n .dsh-ssh-profile-group-children {\n animation: none;\n }\n .dsh-ssh-profile-row,\n .dsh-ssh-profile-row::before,\n .dsh-ssh-profile-group-chevron,\n .dsh-ssh-vault-row,\n .dsh-ssh-sftp-row,\n .dsh-ssh-terminal-switcher button {\n transition: none;\n }\n}\n.dsh-ssh-sidebar-panel {\n display: flex;\n align-items: center;\n gap: 7px;\n min-height: 34px;\n padding: 0 9px;\n border: 1px solid transparent;\n border-radius: 8px;\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n font: 550 11px/1 var(--ds-font-family);\n text-align: left;\n cursor: pointer;\n}\n.dsh-ssh-sidebar-panel svg {\n color: #547d78;\n}\n.dsh-ssh-sidebar-panel:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-sidebar-panel:active {\n transform: scale(0.985);\n}\n.dsh-ssh-icon-button.is-active,\n.dsh-ssh-rail-button.is-active {\n color: #406e67;\n background: color-mix(in srgb, #547d78 9%, transparent);\n}\n.dsh-ssh-icon-button:disabled,\n.dsh-ssh-rail-button:disabled {\n opacity: 0.36;\n cursor: default;\n}\n.dsh-ssh-icon-button:disabled:hover,\n.dsh-ssh-rail-button:disabled:hover {\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n}\n.dsh-ssh-test-button {\n margin-right: auto;\n}\n.dsh-ssh-test-result {\n box-sizing: border-box;\n margin: 0;\n border-radius: 9px;\n font-size: 10px;\n}\n.dsh-ssh-test-result.is-warning {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 14px;\n padding: 9px 10px;\n border: 1px solid color-mix(in srgb, var(--ssh-warning) 22%, transparent);\n color: color-mix(\n in srgb,\n var(--ssh-warning) 82%,\n var(--dsw-alias-label-primary)\n );\n background: color-mix(in srgb, var(--ssh-warning) 7%, transparent);\n}\n.dsh-ssh-test-result.is-warning > span {\n display: grid;\n min-width: 0;\n gap: 4px;\n}\n.dsh-ssh-test-result.is-warning code {\n overflow: hidden;\n font:\n 9px/1.3 var(--ds-font-family-code),\n monospace;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-test-result.is-success {\n display: flex;\n align-items: center;\n gap: 7px;\n padding: 8px 10px;\n color: #477565;\n background: color-mix(in srgb, #5c8a76 9%, transparent);\n}\n.dsh-ssh-sidebar-note {\n box-sizing: border-box;\n min-height: 32px;\n margin: 0;\n padding: 8px 9px;\n color: var(--dsw-alias-label-tertiary);\n font: 10px/1.4 var(--ds-font-family);\n}\n.dsh-ssh-profile-sftp-pane {\n box-sizing: border-box;\n display: flex;\n min-height: 100%;\n height: 100%;\n flex-direction: column;\n padding: 0 18px 18px;\n}\n.dsh-ssh-profile-sftp-pane > .dsh-ssh-content-heading {\n flex: none;\n}\n.dsh-ssh-sftp.is-workspace {\n --ssh-activity-border: var(--ssh-border);\n min-height: 0;\n flex: 1;\n}\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-pathbar {\n margin-bottom: 10px;\n}\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-columns,\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row {\n grid-template-columns: minmax(180px, 1fr) 90px 120px;\n}\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-columns {\n min-height: 34px;\n padding: 0 12px;\n font-size: 9px;\n}\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row {\n min-height: 40px;\n padding: 0 12px;\n cursor: pointer;\n}\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row strong {\n font-size: 11px;\n}\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row small {\n font-size: 9px;\n}\n.dsh-ssh-upload-conflict {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 9px;\n padding: 8px 10px;\n border: 1px solid\n color-mix(in srgb, var(--ssh-warning, #927443) 20%, transparent);\n border-radius: 8px;\n color: var(--dsw-alias-label-secondary);\n background: color-mix(in srgb, var(--ssh-warning, #927443) 7%, transparent);\n}\n.dsh-ssh-upload-conflict > span {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-ssh-upload-conflict > span:first-child {\n min-width: 0;\n}\n.dsh-ssh-upload-conflict strong {\n font-size: 10px;\n}\n.dsh-ssh-upload-conflict small {\n overflow: hidden;\n max-width: 240px;\n color: var(--dsw-alias-label-tertiary);\n font:\n 9px/1 var(--ds-font-family-code),\n monospace;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-upload-conflict button {\n min-height: 26px;\n padding: 0 9px;\n border: 1px solid var(--ssh-border);\n border-radius: 7px;\n color: var(--dsw-alias-label-secondary);\n background: var(--ssh-surface-raised);\n font-size: 9px;\n cursor: pointer;\n}\n.dsh-ssh-upload-conflict button.is-primary {\n border-color: color-mix(in srgb, var(--ssh-accent-strong) 56%, transparent);\n color: #f6fbf9;\n background: var(--ssh-accent-strong);\n}\n';
6393
+ var client_default = '.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n.dsh-ssh-sidebar {\n box-sizing: border-box;\n flex: none;\n margin: 0 8px 8px 2px;\n padding: 4px 0 6px;\n border-bottom: 1px solid\n color-mix(in srgb, var(--dsw-alias-border-l2) 62%, transparent);\n color: var(--dsw-alias-label-primary);\n}\n.dsh-ssh-sidebar.is-rail {\n width: 36px;\n margin: 0 0 8px;\n padding: 0;\n border: 0;\n}\n.dsh-ssh-sidebar-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 32px;\n padding: 0 4px 0 5px;\n}\n.dsh-ssh-sidebar-title {\n display: flex;\n min-width: 0;\n align-items: center;\n gap: 5px;\n height: 28px;\n padding: 0 5px;\n color: var(--dsw-alias-label-secondary);\n border: 0;\n background: transparent;\n border-radius: 7px;\n font: 600 12px/1 var(--ds-font-family);\n cursor: pointer;\n}\n.dsh-ssh-sidebar-title:hover,\n.dsh-ssh-icon-button:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-disclosure {\n display: grid;\n place-items: center;\n transition: transform 0.16s ease;\n}\n.dsh-ssh-disclosure[data-open="false"] {\n transform: rotate(-90deg);\n}\n.dsh-ssh-icon-button {\n display: inline-grid;\n place-items: center;\n flex: none;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 0;\n border-radius: 8px;\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n cursor: pointer;\n}\n.dsh-ssh-icon-button.is-danger {\n color: #a65d58;\n}\n.dsh-ssh-sidebar-list {\n display: grid;\n gap: 2px;\n padding: 2px 1px 0;\n}\n.dsh-ssh-sidebar-row,\n.dsh-ssh-sidebar-empty,\n.dsh-ssh-sidebar-more {\n box-sizing: border-box;\n width: 100%;\n border: 1px solid transparent;\n background: transparent;\n color: inherit;\n cursor: pointer;\n}\n.dsh-ssh-sidebar-row {\n display: grid;\n grid-template-columns: 12px minmax(0, 1fr) 18px;\n align-items: center;\n gap: 7px;\n min-height: 40px;\n padding: 4px 7px;\n border-radius: 9px;\n text-align: left;\n}\n.dsh-ssh-sidebar-row:hover {\n background: color-mix(\n in srgb,\n var(--dsw-alias-interactive-bg-hover) 70%,\n transparent\n );\n}\n.dsh-ssh-sidebar-row.is-active {\n background: color-mix(\n in srgb,\n var(--dsw-alias-interactive-bg-hover) 92%,\n transparent\n );\n border-color: color-mix(in srgb, var(--dsw-alias-border-l2) 50%, transparent);\n}\n.dsh-ssh-status-dot {\n display: block;\n width: 7px;\n height: 7px;\n margin: auto;\n border: 1px solid\n color-mix(in srgb, var(--dsw-alias-label-secondary) 62%, transparent);\n border-radius: 50%;\n}\n.dsh-ssh-status-dot.is-injected {\n border-color: #5b8f82;\n background: #5b8f82;\n box-shadow: 0 0 0 2px color-mix(in srgb, #5b8f82 14%, transparent);\n}\n.dsh-ssh-sidebar-copy {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n.dsh-ssh-sidebar-copy strong,\n.dsh-ssh-sidebar-copy small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-sidebar-copy strong {\n font-size: 13px;\n font-weight: 500;\n}\n.dsh-ssh-sidebar-copy small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n.dsh-ssh-injected-mark {\n display: grid;\n place-items: center;\n color: #5b8f82;\n}\n.dsh-ssh-sidebar-empty,\n.dsh-ssh-sidebar-more {\n min-height: 34px;\n padding: 6px 10px;\n border-radius: 8px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n text-align: left;\n}\n.dsh-ssh-sidebar-empty:hover,\n.dsh-ssh-sidebar-more:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-rail-button {\n display: grid;\n place-items: center;\n width: 36px;\n height: 36px;\n padding: 0;\n border: 0;\n border-radius: 10px;\n color: var(--dsw-alias-label-primary);\n background: transparent;\n cursor: pointer;\n}\n.dsh-ssh-rail-button:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-server-glyph {\n display: inline-grid;\n place-items: center;\n color: currentColor;\n}\n.dsh-ssh-workspace {\n --ssh-accent: #547d78;\n --ssh-accent-strong: #406e67;\n --ssh-danger: #9c504c;\n --ssh-warning: #927443;\n --ssh-surface: color-mix(\n in srgb,\n var(--dsw-alias-bg-base, #f7f8f7) 94%,\n transparent\n );\n --ssh-surface-raised: color-mix(\n in srgb,\n var(--dsw-alias-bg-base, #fff) 98%,\n var(--dsw-alias-label-primary) 2%\n );\n --ssh-activity-surface: var(--ssh-surface);\n --ssh-activity-surface-raised: var(--ssh-surface-raised);\n --ssh-border: color-mix(\n in srgb,\n var(--dsw-alias-label-primary) 10%,\n transparent\n );\n --dpu-navigation-width: 248px;\n --dpu-inspector-width: 292px;\n --dpu-border: var(--ssh-border);\n --dpu-accent: var(--ssh-accent);\n --dpu-accent-strong: var(--ssh-accent-strong);\n --dpu-raised-surface: var(--ssh-surface-raised);\n --dpu-toolbar-surface: color-mix(\n in srgb,\n var(--ssh-surface-raised) 88%,\n transparent\n );\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n color: var(--dsw-alias-label-primary);\n background: var(--ssh-surface);\n font-family:\n var(--ds-font-family),\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n}\n.dsh-ssh-toolbar {\n display: grid;\n grid-template-columns: minmax(180px, 1fr) auto minmax(180px, 1fr);\n align-items: center;\n gap: 16px;\n min-height: 64px;\n padding: 0 20px;\n border-bottom: 1px solid var(--ssh-border);\n background: color-mix(in srgb, var(--ssh-surface-raised) 88%, transparent);\n}\n.dsh-ssh-brand {\n display: flex;\n align-items: center;\n gap: 10px;\n min-width: 0;\n}\n.dsh-ssh-brand-glyph {\n display: grid;\n place-items: center;\n width: 30px;\n height: 30px;\n border: 1px solid color-mix(in srgb, var(--ssh-accent) 28%, transparent);\n border-radius: 9px;\n color: var(--ssh-accent-strong);\n background: color-mix(in srgb, var(--ssh-accent) 8%, transparent);\n}\n.dsh-ssh-brand > span:last-child {\n display: grid;\n gap: 1px;\n}\n.dsh-ssh-brand strong {\n font-size: 14px;\n font-weight: 650;\n}\n.dsh-ssh-brand small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n.dsh-ssh-segments {\n display: flex;\n gap: 2px;\n padding: 3px;\n border: 1px solid color-mix(in srgb, var(--ssh-border) 80%, transparent);\n border-radius: 10px;\n background: color-mix(\n in srgb,\n var(--dsw-alias-label-primary) 3%,\n transparent\n );\n}\n.dsh-ssh-segments button {\n min-width: 74px;\n height: 28px;\n padding: 0 12px;\n border: 0;\n border-radius: 7px;\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n font-size: 12px;\n cursor: pointer;\n}\n.dsh-ssh-segments button:hover {\n color: var(--dsw-alias-label-primary);\n}\n.dsh-ssh-segments button.is-active {\n color: var(--dsw-alias-label-primary);\n background: var(--ssh-surface-raised);\n box-shadow: 0 1px 2px\n color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);\n}\n.dsh-ssh-toolbar > .dsh-ssh-primary-button {\n justify-self: end;\n}\n.dsh-ssh-primary-button,\n.dsh-ssh-secondary-button,\n.dsh-ssh-danger-button,\n.dsh-ssh-small-primary {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n min-height: 30px;\n padding: 0 12px;\n border-radius: 8px;\n font: 500 12px/1 var(--ds-font-family);\n cursor: pointer;\n}\n.dsh-ssh-primary-button,\n.dsh-ssh-small-primary {\n border: 1px solid\n color-mix(in srgb, var(--ssh-accent-strong) 64%, transparent);\n color: #f6fbf9;\n background: var(--ssh-accent-strong);\n}\n.dsh-ssh-primary-button:hover,\n.dsh-ssh-small-primary:hover {\n background: color-mix(in srgb, var(--ssh-accent-strong) 88%, #000);\n}\n.dsh-ssh-primary-button:disabled {\n opacity: 0.55;\n cursor: default;\n}\n.dsh-ssh-secondary-button {\n border: 1px solid var(--ssh-border);\n color: var(--dsw-alias-label-primary);\n background: var(--ssh-surface-raised);\n}\n.dsh-ssh-secondary-button:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-danger-button {\n border: 1px solid color-mix(in srgb, var(--ssh-danger) 28%, transparent);\n color: var(--ssh-danger);\n background: color-mix(in srgb, var(--ssh-danger) 7%, transparent);\n}\n.dsh-ssh-small-primary {\n min-height: 26px;\n padding: 0 9px;\n}\n.dsh-ssh-profile-panel,\n.dsh-ssh-inspector {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex-direction: column;\n background: color-mix(in srgb, var(--ssh-surface-raised) 72%, transparent);\n}\n.dsh-ssh-profile-panel {\n border-right: 1px solid var(--ssh-border);\n}\n.dsh-ssh-inspector {\n border-left: 1px solid var(--ssh-border);\n}\n.dsh-ssh-main-panel {\n min-width: 0;\n min-height: 0;\n overflow: auto;\n background: color-mix(in srgb, var(--ssh-surface) 88%, transparent);\n}\n.dsh-ssh-panel-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 58px;\n padding: 0 14px;\n border-bottom: 1px solid\n color-mix(in srgb, var(--ssh-border) 74%, transparent);\n}\n.dsh-ssh-panel-heading > span {\n display: grid;\n gap: 2px;\n}\n.dsh-ssh-panel-heading strong {\n font-size: 12px;\n font-weight: 650;\n}\n.dsh-ssh-panel-heading small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n.dsh-ssh-search {\n padding: 10px 10px 6px;\n}\n.dsh-ssh-search input,\n.dsh-ssh-field input,\n.dsh-ssh-field select,\n.dsh-ssh-field textarea,\n.dsh-ssh-number-row input {\n box-sizing: border-box;\n width: 100%;\n border: 1px solid var(--ssh-border);\n border-radius: 8px;\n outline: 0;\n color: var(--dsw-alias-label-primary);\n background: color-mix(in srgb, var(--ssh-surface-raised) 92%, transparent);\n font: 400 12px/1.35 var(--ds-font-family);\n}\n.dsh-ssh-search input {\n height: 30px;\n padding: 0 10px;\n}\n.dsh-ssh-search input:focus,\n.dsh-ssh-field input:focus,\n.dsh-ssh-field select:focus,\n.dsh-ssh-field textarea:focus,\n.dsh-ssh-number-row input:focus {\n border-color: color-mix(in srgb, var(--ssh-accent) 65%, transparent);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--ssh-accent) 12%, transparent);\n}\n.dsh-ssh-profile-list {\n display: grid;\n align-content: start;\n gap: 3px;\n min-height: 0;\n overflow: auto;\n padding: 4px 7px 12px;\n}\n.dsh-ssh-profile-group {\n min-width: 0;\n}\n.dsh-ssh-profile-group-heading {\n display: grid;\n grid-template-columns: 14px 18px minmax(0, 1fr);\n align-items: center;\n gap: 5px;\n width: 100%;\n min-height: 34px;\n padding: 0 6px;\n border: 0;\n border-radius: 8px;\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n text-align: left;\n cursor: pointer;\n}\n.dsh-ssh-profile-group-heading:hover {\n color: var(--dsw-alias-label-primary);\n background: color-mix(\n in srgb,\n var(--dsw-alias-interactive-bg-hover) 58%,\n transparent\n );\n}\n.dsh-ssh-profile-group-heading:focus-visible {\n outline: 2px solid color-mix(in srgb, var(--ssh-accent) 54%, transparent);\n outline-offset: -2px;\n}\n.dsh-ssh-profile-group-chevron {\n display: grid;\n place-items: center;\n transition: transform 160ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n.dsh-ssh-profile-group-chevron[data-open="false"] {\n transform: rotate(-90deg);\n}\n.dsh-ssh-profile-group-folder {\n display: grid;\n place-items: center;\n color: color-mix(\n in srgb,\n var(--ssh-accent-strong) 72%,\n var(--dsw-alias-label-secondary)\n );\n}\n.dsh-ssh-profile-group-copy {\n display: flex;\n min-width: 0;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n.dsh-ssh-profile-group-copy strong {\n overflow: hidden;\n font-size: 11px;\n font-weight: 600;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-profile-group-copy small {\n display: grid;\n place-items: center;\n min-width: 16px;\n height: 16px;\n color: var(--dsw-alias-label-tertiary);\n font:\n 9px/1 var(--ds-font-family-code),\n monospace;\n}\n.dsh-ssh-profile-group-children {\n display: grid;\n gap: 1px;\n margin-left: 13px;\n padding-left: 6px;\n border-left: 1px solid color-mix(in srgb, var(--ssh-border) 66%, transparent);\n animation: dsh-ssh-group-open 140ms ease-out both;\n}\n.dsh-ssh-profile-empty {\n margin: 18px 8px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n text-align: center;\n}\n.dsh-ssh-profile-row {\n display: grid;\n grid-template-columns: 30px minmax(0, 1fr) 10px;\n align-items: center;\n gap: 9px;\n width: 100%;\n min-height: 48px;\n padding: 5px 7px;\n border: 1px solid transparent;\n border-radius: 9px;\n color: inherit;\n background: transparent;\n text-align: left;\n cursor: pointer;\n}\n.dsh-ssh-profile-row:hover {\n background: color-mix(\n in srgb,\n var(--dsw-alias-interactive-bg-hover) 74%,\n transparent\n );\n}\n.dsh-ssh-profile-row.is-active {\n border-color: color-mix(in srgb, var(--ssh-accent) 16%, transparent);\n background: color-mix(in srgb, var(--ssh-accent) 9%, transparent);\n}\n.dsh-ssh-host-monogram {\n display: grid;\n place-items: center;\n width: 28px;\n height: 28px;\n border: 1px solid var(--ssh-border);\n border-radius: 8px;\n color: var(--dsw-alias-label-secondary);\n background: var(--ssh-surface-raised);\n font-size: 11px;\n font-weight: 650;\n}\n.dsh-ssh-profile-row > span:nth-child(2) {\n display: grid;\n min-width: 0;\n gap: 3px;\n}\n.dsh-ssh-profile-row strong,\n.dsh-ssh-profile-row small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-profile-row strong {\n font-size: 12px;\n font-weight: 550;\n}\n.dsh-ssh-profile-row small {\n color: var(--dsw-alias-label-tertiary);\n font:\n 10px/1.2 var(--ds-font-family-code),\n monospace;\n}\n.dsh-ssh-credential-state {\n width: 6px;\n height: 6px;\n border: 1px solid var(--dsw-alias-label-tertiary);\n border-radius: 50%;\n}\n.dsh-ssh-credential-state.is-ready {\n border-color: #5c8a76;\n background: #5c8a76;\n}\n.dsh-ssh-terminal-pane,\n.dsh-ssh-forward-pane,\n.dsh-ssh-settings-pane {\n box-sizing: border-box;\n display: flex;\n min-width: 0;\n min-height: 100%;\n flex-direction: column;\n padding: 0 18px 18px;\n}\n.dsh-ssh-content-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 20px;\n min-height: 76px;\n}\n.dsh-ssh-content-heading h1 {\n margin: 0;\n font-size: 16px;\n font-weight: 650;\n letter-spacing: -0.01em;\n}\n.dsh-ssh-content-heading p {\n margin: 4px 0 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n.dsh-ssh-heading-actions {\n display: flex;\n align-items: center;\n gap: 7px;\n}\n.dsh-ssh-title-line {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-ssh-live-dot {\n width: 7px;\n height: 7px;\n border: 1px solid var(--dsw-alias-label-tertiary);\n border-radius: 50%;\n}\n.dsh-ssh-live-dot.is-connected {\n border-color: #4d8d77;\n background: #4d8d77;\n box-shadow: 0 0 0 3px color-mix(in srgb, #4d8d77 12%, transparent);\n}\n.dsh-ssh-live-dot.is-connecting {\n border-color: #a27e45;\n background: #a27e45;\n}\n.dsh-ssh-live-dot.is-error {\n border-color: #a85a55;\n background: #a85a55;\n}\n.dsh-ssh-terminal-frame {\n display: flex;\n min-height: 360px;\n flex: 1;\n flex-direction: column;\n overflow: hidden;\n border: 1px solid color-mix(in srgb, #8ba49e 22%, #101817);\n border-radius: 12px;\n background: #111817;\n box-shadow: 0 10px 34px color-mix(in srgb, #0d1513 14%, transparent);\n}\n.dsh-ssh-xterm {\n min-height: 0;\n flex: 1;\n padding: 11px 11px 0;\n}\n.dsh-ssh-xterm .xterm {\n height: 100%;\n}\n.dsh-ssh-terminal-status {\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 28px;\n padding: 0 11px;\n border-top: 1px solid #ffffff12;\n color: #879691;\n background: #0d1413;\n font:\n 10px/1 var(--ds-font-family-code),\n monospace;\n}\n.dsh-ssh-banner {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 8px 18px;\n border-bottom: 1px solid transparent;\n font-size: 11px;\n}\n.dsh-ssh-banner > span {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n.dsh-ssh-banner code {\n font-family: var(--ds-font-family-code), monospace;\n}\n.dsh-ssh-banner button:not(.dsh-ssh-small-primary) {\n display: grid;\n place-items: center;\n border: 0;\n color: inherit;\n background: transparent;\n}\n.dsh-ssh-banner.is-error {\n border-color: color-mix(in srgb, var(--ssh-danger) 22%, transparent);\n color: var(--ssh-danger);\n background: color-mix(in srgb, var(--ssh-danger) 7%, var(--ssh-surface));\n}\n.dsh-ssh-banner.is-warning {\n border-color: color-mix(in srgb, var(--ssh-warning) 22%, transparent);\n color: color-mix(\n in srgb,\n var(--ssh-warning) 85%,\n var(--dsw-alias-label-primary)\n );\n background: color-mix(in srgb, var(--ssh-warning) 8%, var(--ssh-surface));\n}\n.dsh-ssh-inline-error {\n margin: 0 0 10px;\n padding: 7px 9px;\n border-radius: 7px;\n color: var(--ssh-danger);\n background: color-mix(in srgb, var(--ssh-danger) 7%, transparent);\n font-size: 11px;\n}\n.dsh-ssh-empty-state {\n display: grid;\n place-items: center;\n align-content: center;\n min-height: 100%;\n padding: 40px;\n text-align: center;\n}\n.dsh-ssh-empty-state > span {\n display: grid;\n place-items: center;\n width: 48px;\n height: 48px;\n margin-bottom: 14px;\n border: 1px solid var(--ssh-border);\n border-radius: 14px;\n color: var(--ssh-accent);\n background: var(--ssh-surface-raised);\n}\n.dsh-ssh-empty-state h1 {\n margin: 0;\n font-size: 17px;\n}\n.dsh-ssh-empty-state p {\n max-width: 420px;\n margin: 8px 0 18px;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 1.6;\n}\n.dsh-ssh-inspector {\n overflow: auto;\n}\n.dsh-ssh-session-chip {\n display: flex;\n align-items: center;\n gap: 9px;\n margin: 12px 12px 4px;\n padding: 9px 10px;\n border: 1px solid var(--ssh-border);\n border-radius: 9px;\n background: color-mix(in srgb, var(--ssh-surface-raised) 86%, transparent);\n}\n.dsh-ssh-session-chip > span:nth-child(2) {\n display: grid;\n gap: 2px;\n}\n.dsh-ssh-session-chip strong {\n font-size: 11px;\n}\n.dsh-ssh-session-chip small {\n color: var(--dsw-alias-label-tertiary);\n font:\n 9px/1 var(--ds-font-family-code),\n monospace;\n}\n.dsh-ssh-session-pulse {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--ssh-accent);\n}\n.dsh-ssh-fieldset {\n display: grid;\n gap: 3px;\n margin: 13px 12px 0;\n padding: 0;\n border: 0;\n}\n.dsh-ssh-fieldset legend {\n margin-bottom: 5px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n font-weight: 600;\n}\n.dsh-ssh-check-row,\n.dsh-ssh-radio-row {\n display: flex;\n align-items: center;\n gap: 9px;\n min-height: 38px;\n padding: 3px 5px;\n border-radius: 8px;\n}\n.dsh-ssh-check-row:hover,\n.dsh-ssh-radio-row:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-check-row input,\n.dsh-ssh-radio-row input {\n accent-color: var(--ssh-accent);\n}\n.dsh-ssh-check-row > span,\n.dsh-ssh-radio-row > span {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n.dsh-ssh-check-row strong,\n.dsh-ssh-radio-row strong {\n font-size: 11px;\n font-weight: 550;\n}\n.dsh-ssh-check-row small,\n.dsh-ssh-radio-row small {\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-switch-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 20px;\n min-height: 48px;\n margin: 13px 12px 0;\n padding: 7px 9px;\n border: 1px solid var(--ssh-border);\n border-radius: 9px;\n}\n.dsh-ssh-switch-row > span {\n display: grid;\n gap: 3px;\n}\n.dsh-ssh-switch-row strong {\n font-size: 11px;\n font-weight: 550;\n}\n.dsh-ssh-switch-row small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n line-height: 1.35;\n}\n.dsh-ssh-switch-row input {\n width: 28px;\n height: 16px;\n accent-color: var(--ssh-accent);\n}\n.dsh-ssh-inspector-hint,\n.dsh-ssh-save-state {\n margin: 10px 12px 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n.dsh-ssh-inspector-empty {\n margin: 14px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n line-height: 1.55;\n}\n.dsh-ssh-forward-list {\n display: grid;\n align-content: start;\n gap: 5px;\n}\n.dsh-ssh-forward-row {\n display: grid;\n grid-template-columns: 32px minmax(0, 1fr) auto 28px auto 28px;\n align-items: center;\n gap: 8px;\n min-height: 54px;\n padding: 6px 9px;\n border: 1px solid var(--ssh-border);\n border-radius: 10px;\n background: color-mix(in srgb, var(--ssh-surface-raised) 88%, transparent);\n}\n.dsh-ssh-forward-kind {\n display: grid;\n place-items: center;\n width: 28px;\n height: 28px;\n border: 1px solid var(--ssh-border);\n border-radius: 8px;\n color: var(--ssh-accent-strong);\n font:\n 600 11px/1 var(--ds-font-family-code),\n monospace;\n}\n.dsh-ssh-forward-copy {\n display: grid;\n min-width: 0;\n gap: 4px;\n}\n.dsh-ssh-forward-copy strong {\n font-size: 12px;\n}\n.dsh-ssh-forward-copy small {\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary);\n font:\n 10px/1 var(--ds-font-family-code),\n monospace;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-state-label {\n padding: 3px 7px;\n border-radius: 999px;\n color: var(--dsw-alias-label-tertiary);\n background: color-mix(\n in srgb,\n var(--dsw-alias-label-primary) 5%,\n transparent\n );\n font-size: 9px;\n}\n.dsh-ssh-state-label.is-running {\n color: #497967;\n background: color-mix(in srgb, #5d957f 10%, transparent);\n}\n.dsh-ssh-state-label.is-error {\n color: var(--ssh-danger);\n background: color-mix(in srgb, var(--ssh-danger) 8%, transparent);\n}\n.dsh-ssh-table-empty {\n display: grid;\n place-items: center;\n min-height: 180px;\n border: 1px dashed var(--ssh-border);\n border-radius: 12px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n}\n.dsh-ssh-settings-group {\n display: grid;\n max-width: 680px;\n gap: 8px;\n}\n.dsh-ssh-settings-group .dsh-ssh-switch-row {\n margin: 0;\n}\n.dsh-ssh-number-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 120px 32px;\n align-items: center;\n gap: 8px;\n min-height: 60px;\n padding: 6px 10px;\n border: 1px solid var(--ssh-border);\n border-radius: 10px;\n background: color-mix(in srgb, var(--ssh-surface-raised) 80%, transparent);\n}\n.dsh-ssh-number-row > span {\n display: grid;\n gap: 3px;\n}\n.dsh-ssh-number-row strong {\n font-size: 11px;\n}\n.dsh-ssh-number-row small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n}\n.dsh-ssh-number-row input {\n height: 30px;\n padding: 0 8px;\n}\n.dsh-ssh-number-row em {\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n font-style: normal;\n}\n.dsh-ssh-dialog-layer {\n position: fixed;\n z-index: 1000;\n inset: 0;\n display: grid;\n place-items: center;\n padding: 28px;\n background: color-mix(in srgb, #111817 28%, transparent);\n backdrop-filter: blur(3px);\n}\n.dsh-ssh-dialog {\n box-sizing: border-box;\n width: min(620px, calc(100vw - 40px));\n max-height: min(760px, calc(100vh - 40px));\n overflow: auto;\n border: 1px solid\n color-mix(in srgb, var(--dsw-alias-label-primary) 15%, transparent);\n border-radius: 14px;\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-bg-base, #f7f8f7);\n box-shadow: 0 24px 70px #07100d2e;\n}\n.dsh-ssh-dialog > header {\n position: sticky;\n z-index: 1;\n top: 0;\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 64px;\n padding: 0 18px;\n border-bottom: 1px solid\n var(\n --ssh-border,\n color-mix(in srgb, var(--dsw-alias-label-primary) 10%, transparent)\n );\n background: color-mix(\n in srgb,\n var(--dsw-alias-bg-base, #f7f8f7) 94%,\n transparent\n );\n backdrop-filter: blur(12px);\n}\n.dsh-ssh-dialog h2 {\n margin: 0;\n font-size: 17px;\n font-weight: 650;\n letter-spacing: -0.01em;\n}\n.dsh-ssh-dialog header p {\n margin: 3px 0 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n.dsh-ssh-form {\n --ssh-border: color-mix(\n in srgb,\n var(--dsw-alias-label-primary) 11%,\n transparent\n );\n --ssh-accent: #547d78;\n --ssh-accent-strong: #406e67;\n --ssh-danger: #9c504c;\n display: grid;\n gap: 15px;\n padding: 20px 18px 18px;\n}\n.dsh-ssh-form-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n}\n.dsh-ssh-form-grid.is-host {\n grid-template-columns: minmax(0, 1fr) 110px;\n}\n.dsh-ssh-field {\n display: grid;\n gap: 5px;\n min-width: 0;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n font-weight: 600;\n}\n.dsh-ssh-field input,\n.dsh-ssh-field select {\n height: 38px;\n padding: 0 10px;\n font-size: 13px;\n}\n.dsh-ssh-field textarea {\n padding: 9px 10px;\n font-size: 13px;\n line-height: 1.5;\n resize: vertical;\n font-family: var(--ds-font-family-code), monospace;\n}\n.dsh-ssh-field small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n line-height: 1.4;\n font-weight: 400;\n}\n.dsh-ssh-form-divider {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-top: 2px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n font-weight: 600;\n}\n.dsh-ssh-form-divider:after {\n height: 1px;\n flex: 1;\n background: var(--ssh-border);\n content: "";\n}\n.dsh-ssh-dialog-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding-top: 5px;\n}\n.dsh-ssh-dialog-actions .dsh-ssh-primary-button,\n.dsh-ssh-dialog-actions .dsh-ssh-secondary-button {\n min-height: 34px;\n font-size: 13px;\n}\n.dsh-ssh-form .dsh-ssh-switch-row {\n margin: 0;\n}\n.dsh-ssh-form .dsh-ssh-inline-error {\n margin: 0;\n}\n@container dpu-workspace (max-width: 1120px) {\n .dsh-ssh-toolbar {\n grid-template-columns: 1fr auto auto;\n }\n .dsh-ssh-brand small {\n display: none;\n }\n}\n@container dpu-workspace (max-width: 820px) {\n .dsh-ssh-toolbar {\n grid-template-columns: 1fr auto;\n gap: 8px;\n padding: 0 12px;\n }\n .dsh-ssh-segments {\n grid-row: 2;\n grid-column: 1/-1;\n margin-bottom: 8px;\n overflow-x: auto;\n scrollbar-width: none;\n }\n .dsh-ssh-segments::-webkit-scrollbar {\n display: none;\n }\n .dsh-ssh-segments button {\n min-width: 72px;\n height: 36px;\n flex: none;\n }\n .dsh-ssh-toolbar {\n padding-top: 8px;\n }\n .dsh-ssh-content-heading {\n align-items: flex-start;\n flex-direction: column;\n padding: 14px 0;\n }\n .dsh-ssh-heading-actions {\n flex-wrap: wrap;\n }\n .dsh-ssh-forward-row {\n grid-template-columns: 32px minmax(0, 1fr) auto;\n }\n .dsh-ssh-forward-row > .dsh-ssh-icon-button,\n .dsh-ssh-forward-row > .dsh-ssh-small-primary {\n display: none;\n }\n}\n@container dpu-workspace (max-width: 520px) {\n .dsh-ssh-toolbar {\n padding-right: max(10px, env(safe-area-inset-right));\n padding-left: max(10px, env(safe-area-inset-left));\n }\n .dsh-ssh-toolbar > .dsh-ssh-primary-button {\n width: 40px;\n min-height: 40px;\n padding: 0;\n }\n .dsh-ssh-toolbar > .dsh-ssh-primary-button span {\n display: none;\n }\n .dsh-ssh-terminal-pane,\n .dsh-ssh-forward-pane,\n .dsh-ssh-settings-pane,\n .dsh-ssh-vault-pane,\n .dsh-ssh-proxy-pane,\n .dsh-ssh-profile-sftp-pane {\n padding-right: 10px;\n padding-left: 10px;\n }\n .dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-columns,\n .dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row {\n grid-template-columns: minmax(120px, 1fr) 64px;\n }\n .dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-columns > :nth-child(3),\n .dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row > :nth-child(3) {\n display: none;\n }\n .dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row {\n min-height: 44px;\n }\n .dsh-ssh-number-row {\n grid-template-columns: minmax(0, 1fr) 86px 28px;\n }\n}\n@media (max-width: 600px) {\n .dsh-ssh-dialog-layer {\n align-items: stretch;\n padding: 0;\n }\n .dsh-ssh-dialog {\n width: 100%;\n max-height: 100dvh;\n border: 0;\n border-radius: 0;\n }\n .dsh-ssh-form-grid,\n .dsh-ssh-form-grid.is-host {\n grid-template-columns: 1fr;\n }\n .dsh-ssh-dialog-actions {\n position: sticky;\n bottom: 0;\n flex-wrap: wrap;\n padding: 10px 0 max(10px, env(safe-area-inset-bottom));\n background: var(--dsw-alias-bg-base, #f7f8f7);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .dsh-ssh-disclosure {\n transition: none;\n }\n}\n@media (prefers-reduced-transparency: reduce) {\n .dsh-ssh-dialog-layer {\n backdrop-filter: none;\n }\n .dsh-ssh-dialog > header {\n backdrop-filter: none;\n }\n}\n\n.dsh-ssh-activity-trigger {\n box-sizing: border-box;\n display: inline-grid;\n place-items: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 1px solid transparent;\n border-radius: 8px;\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n cursor: pointer;\n}\n.dsh-ssh-activity-trigger:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-activity-trigger.is-active {\n border-color: color-mix(in srgb, var(--ssh-accent, #547d78) 16%, transparent);\n color: var(--ssh-accent-strong, #406e67);\n background: color-mix(in srgb, var(--ssh-accent, #547d78) 8%, transparent);\n}\n.dsh-ssh-panel-right-icon {\n transform: rotate(180deg);\n}\n.dsh-ssh-activity-trigger:focus-visible,\n.dsh-ssh-activity-tabs button:focus-visible,\n.dsh-ssh-sftp button:focus-visible,\n.dsh-ssh-sftp input:focus-visible,\n.dsh-ssh-sftp select:focus-visible {\n outline: 2px solid\n color-mix(in srgb, var(--ssh-accent, #547d78) 62%, transparent);\n outline-offset: 2px;\n}\n.dsh-ssh-activity-panel {\n --ssh-activity-border: color-mix(\n in srgb,\n var(--dsw-alias-label-primary) 10%,\n transparent\n );\n --ssh-activity-surface: color-mix(\n in srgb,\n var(--dsw-alias-bg-overlay, #f1f5f5) 97%,\n var(--dsw-alias-label-primary) 3%\n );\n --ssh-activity-surface-raised: color-mix(\n in srgb,\n var(--dsw-alias-bg-overlay, #f1f5f5) 99%,\n var(--dsw-alias-label-primary) 1%\n );\n box-sizing: border-box;\n display: flex;\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n flex-direction: column;\n color: var(--dsw-alias-label-primary);\n background: var(--ssh-activity-surface);\n font-family:\n var(--ds-font-family),\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n}\n.dsh-ssh-activity-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 58px;\n padding: 0 12px 0 14px;\n border-bottom: 1px solid var(--ssh-activity-border);\n background: var(--ssh-activity-surface-raised);\n}\n.dsh-ssh-activity-header > span {\n display: grid;\n min-width: 0;\n gap: 3px;\n}\n.dsh-ssh-activity-header strong {\n font-size: 13px;\n font-weight: 650;\n}\n.dsh-ssh-activity-header small {\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary);\n font:\n 10px/1.2 var(--ds-font-family-code),\n monospace;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-activity-tabs {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 3px;\n margin: 10px 12px 0;\n padding: 3px;\n border: 1px solid var(--ssh-activity-border);\n border-radius: 10px;\n background: color-mix(\n in srgb,\n var(--dsw-alias-label-primary) 3%,\n transparent\n );\n}\n.dsh-ssh-activity-tabs button {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n min-height: 30px;\n padding: 0 9px;\n border: 0;\n border-radius: 7px;\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n font: 550 11px/1 var(--ds-font-family);\n cursor: pointer;\n}\n.dsh-ssh-activity-tabs button:hover {\n color: var(--dsw-alias-label-primary);\n}\n.dsh-ssh-activity-tabs button.is-active {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-bg-base, #f7f8f7);\n box-shadow: 0 1px 3px\n color-mix(in srgb, var(--dsw-alias-label-primary) 9%, transparent);\n}\n.dsh-ssh-activity-tabs button:only-child {\n grid-column: 1/-1;\n}\n.dsh-ssh-activity-body {\n display: flex;\n min-height: 0;\n flex: 1;\n overflow: hidden;\n padding: 14px 12px 18px;\n}\n.dsh-ssh-activity-body > * {\n width: 100%;\n}\n.dsh-ssh-activity-state {\n margin: 20px 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n.dsh-ssh-sftp {\n display: flex;\n min-height: 100%;\n flex-direction: column;\n}\n.dsh-ssh-sftp-hostbar {\n display: grid;\n grid-template-columns: 28px minmax(0, 1fr);\n align-items: center;\n gap: 8px;\n padding: 0 2px 10px;\n}\n.dsh-ssh-sftp-hostbar label {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n.dsh-ssh-sftp-hostbar select {\n min-width: 0;\n padding: 0;\n border: 0;\n outline: 0;\n color: var(--dsw-alias-label-primary);\n background: transparent;\n font: 600 11px/1.25 var(--ds-font-family);\n cursor: pointer;\n}\n.dsh-ssh-sftp-hostbar small {\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary);\n font:\n 9px/1.2 var(--ds-font-family-code),\n monospace;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-sftp-pathbar {\n display: grid;\n grid-template-columns: 30px minmax(0, 1fr) 30px;\n gap: 5px;\n margin-bottom: 9px;\n}\n.dsh-ssh-sftp-pathbar.has-upload {\n grid-template-columns: 30px minmax(0, 1fr) 30px auto;\n}\n.dsh-ssh-sftp-pathbar button,\n.dsh-ssh-sftp-pathbar input {\n box-sizing: border-box;\n height: 30px;\n border: 1px solid var(--ssh-activity-border);\n border-radius: 8px;\n color: var(--dsw-alias-label-primary);\n background: var(--ssh-activity-surface-raised);\n}\n.dsh-ssh-sftp-pathbar button {\n display: grid;\n place-items: center;\n padding: 0;\n cursor: pointer;\n}\n.dsh-ssh-sftp-pathbar button:disabled {\n opacity: 0.35;\n cursor: default;\n}\n.dsh-ssh-sftp-pathbar input {\n min-width: 0;\n padding: 0 9px;\n outline: 0;\n font:\n 9px/1 var(--ds-font-family-code),\n monospace;\n}\n.dsh-ssh-sftp-pathbar .dsh-ssh-sftp-upload-button {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 0 10px;\n color: #f6fbf9;\n background: var(--ssh-accent-strong, #406e67);\n font: 550 10px/1 var(--ds-font-family);\n}\n.dsh-ssh-directory-error {\n margin: 0 0 8px;\n padding: 7px 8px;\n border-radius: 7px;\n color: var(--ssh-danger, #9c504c);\n background: color-mix(in srgb, var(--ssh-danger, #9c504c) 7%, transparent);\n font-size: 10px;\n line-height: 1.4;\n}\n.dsh-ssh-sftp-table {\n min-height: 0;\n flex: 1;\n overflow: auto;\n border: 1px solid var(--ssh-activity-border);\n border-radius: 10px;\n background: var(--ssh-activity-surface-raised);\n}\n.dsh-ssh-sftp-columns,\n.dsh-ssh-sftp-row {\n display: grid;\n grid-template-columns: minmax(120px, 1fr) 58px 72px;\n align-items: center;\n gap: 7px;\n}\n.dsh-ssh-sftp-columns {\n position: sticky;\n z-index: 1;\n top: 0;\n min-height: 28px;\n padding: 0 9px;\n border-bottom: 1px solid var(--ssh-activity-border);\n color: var(--dsw-alias-label-tertiary);\n background: var(--ssh-activity-surface);\n font-size: 8px;\n}\n.dsh-ssh-sftp-row {\n box-sizing: border-box;\n width: 100%;\n min-height: 34px;\n padding: 0 9px;\n border: 0;\n border-bottom: 1px solid\n color-mix(in srgb, var(--ssh-activity-border) 55%, transparent);\n color: var(--dsw-alias-label-primary);\n background: transparent;\n text-align: left;\n}\n.dsh-ssh-sftp-row:last-child {\n border-bottom: 0;\n}\n.dsh-ssh-sftp-row.is-directory {\n cursor: pointer;\n}\n.dsh-ssh-sftp-row.is-directory:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-sftp-row:disabled {\n opacity: 1;\n}\n.dsh-ssh-sftp-row > span {\n display: flex;\n min-width: 0;\n align-items: center;\n gap: 7px;\n}\n.dsh-ssh-sftp-row svg {\n flex: none;\n color: var(--dsw-alias-label-secondary);\n}\n.dsh-ssh-sftp-row.is-directory svg {\n color: var(--ssh-accent-strong, #406e67);\n}\n.dsh-ssh-sftp-row strong {\n overflow: hidden;\n font-size: 11px;\n font-weight: 500;\n line-height: 1.3;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-sftp-row small {\n overflow: hidden;\n color: var(--dsw-alias-label-tertiary);\n font:\n 8px/1.2 var(--ds-font-family-code),\n monospace;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-sftp-state {\n display: grid;\n place-items: center;\n min-height: 160px;\n margin: 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n.dsh-ssh-activity-empty {\n display: grid;\n place-items: center;\n align-content: center;\n min-height: 240px;\n padding: 24px;\n text-align: center;\n}\n.dsh-ssh-activity-empty > svg {\n margin-bottom: 10px;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-ssh-activity-empty strong {\n font-size: 12px;\n}\n.dsh-ssh-activity-empty p {\n max-width: 260px;\n margin: 7px 0 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n line-height: 1.5;\n}\n.dsh-ssh-terminal-observer {\n display: flex;\n height: 100%;\n min-height: 280px;\n overflow: hidden;\n flex-direction: column;\n border: 1px solid color-mix(in srgb, #8ba49e 22%, #101817);\n border-radius: 11px;\n background: #111817;\n}\n.dsh-ssh-terminal-observer-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 42px;\n padding: 0 10px;\n border-bottom: 1px solid #ffffff12;\n color: #dce5e1;\n background: #0d1413;\n}\n.dsh-ssh-terminal-observer-heading > span:first-child {\n display: grid;\n min-width: 0;\n gap: 3px;\n}\n.dsh-ssh-terminal-observer-heading strong,\n.dsh-ssh-terminal-observer-heading small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-terminal-observer-heading strong {\n font-size: 10px;\n}\n.dsh-ssh-terminal-observer-heading small {\n color: #879691;\n font:\n 8px/1 var(--ds-font-family-code),\n monospace;\n}\n.dsh-ssh-terminal-state {\n flex: none;\n color: #879691;\n font-size: 9px;\n}\n.dsh-ssh-terminal-state.is-running {\n color: #8fc0af;\n}\n.dsh-ssh-terminal-screen {\n box-sizing: border-box;\n min-height: 0;\n flex: 1;\n padding: 9px 8px 0;\n}\n.dsh-ssh-terminal-screen .xterm {\n height: 100%;\n}\n.dsh-ssh-sftp-row:not(.is-directory) {\n cursor: pointer;\n}\n.dsh-ssh-file-preview {\n display: flex;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n overflow: hidden;\n border: 1px solid var(--ssh-activity-border);\n border-radius: 10px;\n background: var(--ssh-activity-surface-raised);\n}\n.dsh-ssh-file-preview > header {\n display: grid;\n grid-template-columns: 28px minmax(0, 1fr) 28px;\n align-items: center;\n gap: 7px;\n min-height: 42px;\n padding: 0 7px;\n border-bottom: 1px solid var(--ssh-activity-border);\n}\n.dsh-ssh-file-preview > header > span {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n.dsh-ssh-file-preview > header strong,\n.dsh-ssh-file-preview > header small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-file-preview > header strong {\n font-size: 10px;\n}\n.dsh-ssh-file-preview > header small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 8px;\n}\n.dsh-ssh-file-preview > header > a {\n display: grid;\n place-items: center;\n width: 28px;\n height: 28px;\n border-radius: 8px;\n color: var(--dsw-alias-label-secondary);\n text-decoration: none;\n}\n.dsh-ssh-file-preview > header > a:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-file-preview-body {\n display: flex;\n min-height: 0;\n flex: 1;\n overflow: auto;\n flex-direction: column;\n}\n.dsh-ssh-file-preview-body > pre {\n box-sizing: border-box;\n min-width: 100%;\n min-height: 100%;\n margin: 0;\n padding: 12px;\n color: var(--dsw-alias-label-primary);\n background: transparent;\n font:\n 10px/1.55 var(--ds-font-family-code),\n monospace;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n.dsh-ssh-file-preview-body > small {\n padding: 8px 12px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n}\n.dsh-ssh-file-preview-body > img {\n display: block;\n max-width: 100%;\n max-height: 100%;\n margin: auto;\n object-fit: contain;\n}\n.dsh-ssh-file-preview-body > iframe {\n width: 100%;\n height: 100%;\n min-height: 420px;\n border: 0;\n background: #fff;\n}\n.dsh-ssh-file-binary {\n display: grid;\n place-items: center;\n align-content: center;\n min-height: 240px;\n padding: 20px;\n text-align: center;\n}\n.dsh-ssh-file-binary > svg {\n margin-bottom: 9px;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-ssh-file-binary strong {\n font-size: 11px;\n}\n.dsh-ssh-file-binary p {\n margin: 5px 0 12px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n}\n.dsh-ssh-file-binary a {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-height: 30px;\n padding: 0 10px;\n border: 1px solid var(--ssh-activity-border);\n border-radius: 8px;\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-button-elevated-fill);\n font-size: 10px;\n text-decoration: none;\n}\n.dsh-ssh-terminal-workbench {\n display: flex;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n gap: 7px;\n}\n.dsh-ssh-terminal-switcher {\n display: flex;\n flex: none;\n gap: 3px;\n overflow: auto;\n padding: 1px;\n}\n.dsh-ssh-terminal-switcher button {\n display: flex;\n min-width: 0;\n max-width: 150px;\n align-items: center;\n gap: 6px;\n height: 28px;\n padding: 0 8px;\n border: 1px solid transparent;\n border-radius: 7px;\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n font: 500 9px/1 var(--ds-font-family);\n white-space: nowrap;\n cursor: pointer;\n}\n.dsh-ssh-terminal-switcher button:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-terminal-switcher button.is-active {\n border-color: var(--ssh-activity-border);\n color: var(--dsw-alias-label-primary);\n background: color-mix(in srgb, var(--ssh-accent, #547d78) 8%, transparent);\n}\n.dsh-ssh-terminal-state-dot {\n width: 5px;\n height: 5px;\n flex: none;\n border: 1px solid #75827e;\n border-radius: 50%;\n}\n.dsh-ssh-terminal-state-dot.is-running {\n border-color: #6ca08d;\n background: #6ca08d;\n}\n.dsh-ssh-terminal-workbench .dsh-ssh-terminal-observer {\n height: auto;\n min-height: 0;\n flex: 1;\n}\n.dsh-ssh-terminal-input-error {\n margin: 0;\n padding: 6px 8px;\n border-radius: 6px;\n color: #d98e88;\n background: #351c1a;\n font-size: 9px;\n}\n\n.dsh-ssh-workspace::before {\n position: absolute;\n z-index: 0;\n inset: 0;\n pointer-events: none;\n background:\n radial-gradient(\n circle at 18% 12%,\n color-mix(in srgb, var(--ssh-accent) 7%, transparent),\n transparent 28%\n ),\n linear-gradient(\n 115deg,\n transparent 0 56%,\n color-mix(in srgb, var(--ssh-accent) 3%, transparent) 56.1% 56.35%,\n transparent 56.45% 100%\n );\n content: "";\n}\n.dsh-ssh-workspace > * {\n position: relative;\n z-index: 1;\n}\n.dsh-ssh-toolbar {\n box-shadow:\n inset 0 1px 0\n color-mix(in srgb, var(--dsw-alias-bg-base, #fff) 70%, transparent),\n 0 8px 28px\n color-mix(in srgb, var(--dsw-alias-label-primary) 3%, transparent);\n}\n.dsh-ssh-brand-glyph {\n position: relative;\n overflow: hidden;\n}\n.dsh-ssh-brand-glyph::after {\n position: absolute;\n width: 12px;\n height: 1px;\n left: 9px;\n bottom: 5px;\n border-radius: 1px;\n background: color-mix(in srgb, var(--ssh-accent) 66%, transparent);\n content: "";\n}\n.dsh-ssh-profile-row {\n position: relative;\n transition:\n background 140ms ease,\n border-color 140ms ease,\n transform 160ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n.dsh-ssh-profile-row::before {\n position: absolute;\n width: 2px;\n left: 0;\n top: 11px;\n bottom: 11px;\n border-radius: 2px;\n background: var(--ssh-accent);\n opacity: 0;\n transform: scaleY(0.45);\n transition:\n opacity 140ms ease,\n transform 170ms cubic-bezier(0.2, 0.8, 0.2, 1);\n content: "";\n}\n.dsh-ssh-profile-row.is-active {\n transform: translateX(2px);\n}\n.dsh-ssh-profile-row.is-active::before {\n opacity: 0.8;\n transform: scaleY(1);\n}\n.dsh-ssh-profile-row:active,\n.dsh-ssh-sftp-row:active,\n.dsh-ssh-terminal-switcher button:active {\n transform: scale(0.985);\n}\n.dsh-ssh-activity-panel {\n animation: dsh-ssh-panel-enter 180ms cubic-bezier(0.2, 0.8, 0.2, 1) both;\n}\n.dsh-ssh-sftp-table,\n.dsh-ssh-file-preview,\n.dsh-ssh-terminal-observer {\n box-shadow:\n inset 0 1px 0\n color-mix(in srgb, var(--dsw-alias-bg-base, #fff) 8%, transparent),\n 0 10px 30px\n color-mix(in srgb, var(--dsw-alias-label-primary) 4%, transparent);\n}\n.dsh-ssh-sftp-row {\n transition:\n background 120ms ease,\n transform 120ms ease;\n}\n.dsh-ssh-file-preview-body {\n animation: dsh-ssh-content-enter 160ms ease-out both;\n}\n.dsh-ssh-terminal-switcher button {\n transition:\n color 120ms ease,\n background 120ms ease,\n border-color 120ms ease,\n transform 120ms ease;\n}\n.dsh-ssh-terminal-switcher button.is-active {\n box-shadow: inset 0 1px 0\n color-mix(in srgb, var(--dsw-alias-bg-base, #fff) 55%, transparent);\n}\n.dsh-ssh-vault-pane,\n.dsh-ssh-proxy-pane {\n box-sizing: border-box;\n display: flex;\n min-height: 100%;\n flex-direction: column;\n padding: 0 18px 18px;\n}\n.dsh-ssh-vault-list,\n.dsh-ssh-proxy-list {\n display: grid;\n align-content: start;\n gap: 5px;\n}\n.dsh-ssh-vault-row,\n.dsh-ssh-proxy-row {\n display: grid;\n grid-template-columns: 34px minmax(160px, 1fr) auto 70px 28px 28px;\n align-items: center;\n gap: 9px;\n min-height: 56px;\n padding: 5px 8px;\n border: 1px solid var(--ssh-border);\n border-radius: 10px;\n background: color-mix(in srgb, var(--ssh-surface-raised) 82%, transparent);\n transition:\n background 140ms ease,\n border-color 140ms ease,\n transform 150ms ease;\n}\n.dsh-ssh-vault-row:hover,\n.dsh-ssh-proxy-row:hover {\n border-color: color-mix(in srgb, var(--ssh-accent) 18%, var(--ssh-border));\n background: color-mix(in srgb, var(--ssh-surface-raised) 94%, transparent);\n transform: translateY(-1px);\n}\n.dsh-ssh-vault-glyph {\n display: grid;\n place-items: center;\n width: 30px;\n height: 30px;\n border: 1px solid color-mix(in srgb, var(--ssh-accent) 18%, var(--ssh-border));\n border-radius: 9px;\n color: var(--ssh-accent-strong);\n background: color-mix(in srgb, var(--ssh-accent) 7%, transparent);\n}\n.dsh-ssh-vault-row > span:nth-child(2),\n.dsh-ssh-proxy-row > span:nth-child(2) {\n display: grid;\n min-width: 0;\n gap: 3px;\n}\n.dsh-ssh-vault-row strong,\n.dsh-ssh-vault-row small,\n.dsh-ssh-proxy-row strong,\n.dsh-ssh-proxy-row small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-vault-row strong,\n.dsh-ssh-proxy-row strong {\n font-size: 12px;\n font-weight: 600;\n}\n.dsh-ssh-vault-row small,\n.dsh-ssh-proxy-row small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n.dsh-ssh-proxy-kind {\n padding: 3px 7px;\n border-radius: 6px;\n color: var(--ssh-accent-strong);\n background: color-mix(in srgb, var(--ssh-accent) 9%, transparent);\n font: 600 9px/1 var(--ds-font-family-code), monospace;\n}\n.dsh-ssh-vault-state {\n padding: 3px 7px;\n border-radius: 6px;\n color: var(--ssh-danger);\n background: color-mix(in srgb, var(--ssh-danger) 7%, transparent);\n font-size: 9px;\n}\n.dsh-ssh-vault-state.is-ready {\n color: var(--ssh-accent-strong);\n background: color-mix(in srgb, var(--ssh-accent) 9%, transparent);\n}\n.dsh-ssh-vault-empty {\n display: grid;\n place-items: center;\n align-content: center;\n min-height: 320px;\n text-align: center;\n}\n.dsh-ssh-vault-empty > span {\n display: grid;\n place-items: center;\n width: 46px;\n height: 46px;\n margin-bottom: 12px;\n border: 1px solid var(--ssh-border);\n border-radius: 14px;\n color: var(--ssh-accent-strong);\n background: color-mix(in srgb, var(--ssh-surface-raised) 88%, transparent);\n box-shadow: 0 12px 30px\n color-mix(in srgb, var(--dsw-alias-label-primary) 5%, transparent);\n}\n.dsh-ssh-vault-empty strong {\n font-size: 13px;\n}\n.dsh-ssh-vault-empty p {\n max-width: 360px;\n margin: 7px 0 16px;\n color: var(--dsw-alias-label-secondary);\n font-size: 11px;\n line-height: 1.55;\n}\n.dsh-ssh-credential-reference {\n display: grid;\n grid-template-columns: 34px minmax(0, 1fr) auto;\n align-items: center;\n gap: 9px;\n min-height: 52px;\n padding: 5px 9px;\n border: 1px solid color-mix(in srgb, var(--ssh-accent) 18%, var(--ssh-border));\n border-radius: 10px;\n background: color-mix(\n in srgb,\n var(--ssh-accent) 6%,\n var(--ssh-surface-raised)\n );\n}\n.dsh-ssh-credential-reference > span:first-child {\n display: grid;\n place-items: center;\n width: 30px;\n height: 30px;\n border-radius: 8px;\n color: var(--ssh-accent-strong);\n background: color-mix(in srgb, var(--ssh-accent) 9%, transparent);\n}\n.dsh-ssh-credential-reference > span:nth-child(2) {\n display: grid;\n gap: 3px;\n}\n.dsh-ssh-credential-reference strong {\n font-size: 11px;\n}\n.dsh-ssh-credential-reference small {\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n}\n.dsh-ssh-credential-reference em {\n color: var(--ssh-accent-strong);\n font-size: 9px;\n font-style: normal;\n}\n.dsh-ssh-jump-chain {\n display: grid;\n gap: 8px;\n margin: 0;\n padding: 10px;\n border: 1px solid var(--ssh-border);\n border-radius: 10px;\n background: color-mix(in srgb, var(--ssh-surface-raised) 72%, transparent);\n}\n.dsh-ssh-jump-chain legend {\n padding: 0 5px;\n color: var(--dsw-alias-label-secondary);\n font-size: 10px;\n font-weight: 600;\n}\n.dsh-ssh-jump-chain > p {\n margin: 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 9px;\n}\n.dsh-ssh-jump-chain > div {\n display: grid;\n gap: 5px;\n}\n.dsh-ssh-jump-row {\n display: grid;\n grid-template-columns: 22px minmax(0, 1fr) 28px 28px 28px;\n align-items: center;\n gap: 4px;\n}\n.dsh-ssh-jump-row > em {\n display: grid;\n place-items: center;\n width: 20px;\n height: 20px;\n border-radius: 6px;\n color: var(--ssh-accent-strong);\n background: color-mix(in srgb, var(--ssh-accent) 9%, transparent);\n font:\n 600 9px/1 var(--ds-font-family-code),\n monospace;\n font-style: normal;\n}\n.dsh-ssh-jump-row select {\n box-sizing: border-box;\n min-width: 0;\n height: 30px;\n padding: 0 8px;\n border: 1px solid var(--ssh-border);\n border-radius: 8px;\n color: var(--dsw-alias-label-primary);\n background: var(--ssh-surface-raised);\n font-size: 10px;\n}\n.dsh-ssh-jump-row .dsh-ssh-icon-button:disabled {\n opacity: 0.3;\n cursor: default;\n}\n.dsh-ssh-jump-empty {\n padding: 7px !important;\n border-radius: 7px;\n background: color-mix(in srgb, var(--ssh-warning) 7%, transparent);\n}\n.dsh-ssh-jump-chain > .dsh-ssh-secondary-button {\n justify-self: start;\n}\n@keyframes dsh-ssh-panel-enter {\n from {\n opacity: 0;\n transform: translateX(6px);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n}\n@keyframes dsh-ssh-content-enter {\n from {\n opacity: 0;\n transform: translateY(3px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n@keyframes dsh-ssh-group-open {\n from {\n opacity: 0;\n transform: translateY(-2px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n@media (max-width: 820px) {\n .dsh-ssh-vault-row,\n .dsh-ssh-proxy-row {\n grid-template-columns: 34px minmax(120px, 1fr) auto 28px;\n }\n .dsh-ssh-vault-row > small,\n .dsh-ssh-vault-row > .dsh-ssh-icon-button:last-child,\n .dsh-ssh-proxy-row > small,\n .dsh-ssh-proxy-row > .dsh-ssh-icon-button:last-child {\n display: none;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .dsh-ssh-activity-panel,\n .dsh-ssh-file-preview-body,\n .dsh-ssh-profile-group-children {\n animation: none;\n }\n .dsh-ssh-profile-row,\n .dsh-ssh-profile-row::before,\n .dsh-ssh-profile-group-chevron,\n .dsh-ssh-vault-row,\n .dsh-ssh-proxy-row,\n .dsh-ssh-sftp-row,\n .dsh-ssh-terminal-switcher button {\n transition: none;\n }\n}\n.dsh-ssh-sidebar-panel {\n display: flex;\n align-items: center;\n gap: 7px;\n min-height: 34px;\n padding: 0 9px;\n border: 1px solid transparent;\n border-radius: 8px;\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n font: 550 11px/1 var(--ds-font-family);\n text-align: left;\n cursor: pointer;\n}\n.dsh-ssh-sidebar-panel svg {\n color: #547d78;\n}\n.dsh-ssh-sidebar-panel:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-sidebar-panel:active {\n transform: scale(0.985);\n}\n.dsh-ssh-icon-button.is-active,\n.dsh-ssh-rail-button.is-active {\n color: #406e67;\n background: color-mix(in srgb, #547d78 9%, transparent);\n}\n.dsh-ssh-icon-button:disabled,\n.dsh-ssh-rail-button:disabled {\n opacity: 0.36;\n cursor: default;\n}\n.dsh-ssh-icon-button:disabled:hover,\n.dsh-ssh-rail-button:disabled:hover {\n color: var(--dsw-alias-label-secondary);\n background: transparent;\n}\n.dsh-ssh-test-button {\n margin-right: auto;\n}\n.dsh-ssh-test-result {\n box-sizing: border-box;\n margin: 0;\n border-radius: 9px;\n font-size: 10px;\n}\n.dsh-ssh-test-result.is-warning {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 14px;\n padding: 9px 10px;\n border: 1px solid color-mix(in srgb, var(--ssh-warning) 22%, transparent);\n color: color-mix(\n in srgb,\n var(--ssh-warning) 82%,\n var(--dsw-alias-label-primary)\n );\n background: color-mix(in srgb, var(--ssh-warning) 7%, transparent);\n}\n.dsh-ssh-test-result.is-warning > span {\n display: grid;\n min-width: 0;\n gap: 4px;\n}\n.dsh-ssh-test-result.is-warning code {\n overflow: hidden;\n font:\n 9px/1.3 var(--ds-font-family-code),\n monospace;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-test-result.is-success {\n display: flex;\n align-items: center;\n gap: 7px;\n padding: 8px 10px;\n color: #477565;\n background: color-mix(in srgb, #5c8a76 9%, transparent);\n}\n.dsh-ssh-sidebar-note {\n box-sizing: border-box;\n min-height: 32px;\n margin: 0;\n padding: 8px 9px;\n color: var(--dsw-alias-label-tertiary);\n font: 10px/1.4 var(--ds-font-family);\n}\n.dsh-ssh-profile-sftp-pane {\n box-sizing: border-box;\n display: flex;\n min-height: 100%;\n height: 100%;\n flex-direction: column;\n padding: 0 18px 18px;\n}\n.dsh-ssh-profile-sftp-pane > .dsh-ssh-content-heading {\n flex: none;\n}\n.dsh-ssh-sftp.is-workspace {\n --ssh-activity-border: var(--ssh-border);\n min-height: 0;\n flex: 1;\n}\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-pathbar {\n margin-bottom: 10px;\n}\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-columns,\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row {\n grid-template-columns: minmax(180px, 1fr) 90px 120px;\n}\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-columns {\n min-height: 34px;\n padding: 0 12px;\n font-size: 9px;\n}\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row {\n min-height: 40px;\n padding: 0 12px;\n cursor: pointer;\n}\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row strong {\n font-size: 11px;\n}\n.dsh-ssh-sftp.is-workspace .dsh-ssh-sftp-row small {\n font-size: 9px;\n}\n.dsh-ssh-upload-conflict {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 9px;\n padding: 8px 10px;\n border: 1px solid\n color-mix(in srgb, var(--ssh-warning, #927443) 20%, transparent);\n border-radius: 8px;\n color: var(--dsw-alias-label-secondary);\n background: color-mix(in srgb, var(--ssh-warning, #927443) 7%, transparent);\n}\n.dsh-ssh-upload-conflict > span {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-ssh-upload-conflict > span:first-child {\n min-width: 0;\n}\n.dsh-ssh-upload-conflict strong {\n font-size: 10px;\n}\n.dsh-ssh-upload-conflict small {\n overflow: hidden;\n max-width: 240px;\n color: var(--dsw-alias-label-tertiary);\n font:\n 9px/1 var(--ds-font-family-code),\n monospace;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-ssh-upload-conflict button {\n min-height: 26px;\n padding: 0 9px;\n border: 1px solid var(--ssh-border);\n border-radius: 7px;\n color: var(--dsw-alias-label-secondary);\n background: var(--ssh-surface-raised);\n font-size: 9px;\n cursor: pointer;\n}\n.dsh-ssh-upload-conflict button.is-primary {\n border-color: color-mix(in srgb, var(--ssh-accent-strong) 56%, transparent);\n color: #f6fbf9;\n background: var(--ssh-accent-strong);\n}\n';
6394
6394
 
6395
6395
  // src/client-api.ts
6396
6396
  var SSH_API = "/ssh-local/v1";
@@ -6423,6 +6423,9 @@ function loadProfiles() {
6423
6423
  function loadVaultEntries() {
6424
6424
  return api("/vault");
6425
6425
  }
6426
+ function loadProxyEntries() {
6427
+ return api("/proxies");
6428
+ }
6426
6429
  function loadForwards() {
6427
6430
  return api("/forwards");
6428
6431
  }
@@ -6432,6 +6435,9 @@ function loadInjection(sessionId) {
6432
6435
  function loadActivity(sessionId) {
6433
6436
  return api(`/activity?sessionId=${encodeURIComponent(sessionId)}`);
6434
6437
  }
6438
+ function activityEventStreamUrl(sessionId) {
6439
+ return `${SSH_API}/activity/events?sessionId=${encodeURIComponent(sessionId)}`;
6440
+ }
6435
6441
  function loadSftpDirectory(sessionId, profileId, path) {
6436
6442
  const query = new URLSearchParams({ sessionId, profileId });
6437
6443
  if (path !== void 0) query.set("path", path);
@@ -6471,8 +6477,20 @@ async function uploadProfileSftpFile(profileId, directory, file, overwrite = fal
6471
6477
  if (!response.ok) throw new ApiError(response.status, typeof body.error === "string" ? body.error : `HTTP ${response.status}`, body);
6472
6478
  return body;
6473
6479
  }
6474
- function sendActivityTerminalInput(sessionId, terminalId, text) {
6475
- return api(`/activity/terminals/${encodeURIComponent(terminalId)}/input`, { method: "POST", body: JSON.stringify({ sessionId, text }) });
6480
+ function sendActivityTerminalInput(sessionId, terminalId, text, sequence) {
6481
+ return api(`/activity/terminals/${encodeURIComponent(terminalId)}/input`, { method: "POST", body: JSON.stringify({ sessionId, text, sequence }) });
6482
+ }
6483
+ function readActivityTerminalOutput(sessionId, terminalId, cursor) {
6484
+ const query = new URLSearchParams({ sessionId, cursor: String(cursor) });
6485
+ return api(`/activity/terminals/${encodeURIComponent(terminalId)}/output?${query.toString()}`);
6486
+ }
6487
+ function activityTerminalStreamUrl(sessionId, terminalId, cursor = 0) {
6488
+ const query = new URLSearchParams({ sessionId, cursor: String(cursor) });
6489
+ return `${SSH_API}/activity/terminals/${encodeURIComponent(terminalId)}/stream?${query.toString()}`;
6490
+ }
6491
+ function browserTerminalStreamUrl(terminalId, cursor = 0) {
6492
+ const query = new URLSearchParams({ cursor: String(cursor) });
6493
+ return `${SSH_API}/terminals/${encodeURIComponent(terminalId)}/stream?${query.toString()}`;
6476
6494
  }
6477
6495
  function resizeActivityTerminal(sessionId, terminalId, cols, rows) {
6478
6496
  return api(`/activity/terminals/${encodeURIComponent(terminalId)}/resize`, { method: "POST", body: JSON.stringify({ sessionId, cols, rows }) });
@@ -6740,6 +6758,125 @@ function errorMessage(error) {
6740
6758
  return error instanceof Error ? error.message : String(error);
6741
6759
  }
6742
6760
 
6761
+ // src/terminal-transport.ts
6762
+ var TerminalTransport = class {
6763
+ constructor(endpoints) {
6764
+ this.endpoints = endpoints;
6765
+ }
6766
+ input = "";
6767
+ inputSequence = 0;
6768
+ inputScheduled = false;
6769
+ disposed = false;
6770
+ sendInput(text, onError) {
6771
+ if (this.disposed || !text) return;
6772
+ this.input += text;
6773
+ if (this.inputScheduled) return;
6774
+ this.inputScheduled = true;
6775
+ queueMicrotask(() => {
6776
+ this.inputScheduled = false;
6777
+ if (this.disposed) return;
6778
+ const pending = this.input;
6779
+ this.input = "";
6780
+ if (!pending) return;
6781
+ const sequence = this.inputSequence++;
6782
+ this.deliverInput(pending, sequence, onError);
6783
+ });
6784
+ }
6785
+ observe(observer) {
6786
+ let stopped = false;
6787
+ let cursor = 0;
6788
+ let source;
6789
+ let streamWatchdog;
6790
+ let pollTimer;
6791
+ let streamConfirmed = false;
6792
+ const stop = () => {
6793
+ if (stopped) return;
6794
+ stopped = true;
6795
+ source?.close();
6796
+ if (streamWatchdog !== void 0) clearTimeout(streamWatchdog);
6797
+ if (pollTimer !== void 0) clearTimeout(pollTimer);
6798
+ };
6799
+ const accept = (value) => {
6800
+ if (stopped) return;
6801
+ cursor = value.cursor;
6802
+ observer.output(value);
6803
+ if (value.closed) stop();
6804
+ };
6805
+ const poll = async () => {
6806
+ if (stopped) return;
6807
+ try {
6808
+ const value = await this.endpoints.read(cursor);
6809
+ accept(value);
6810
+ if (!stopped) pollTimer = window.setTimeout(() => {
6811
+ void poll();
6812
+ }, document.hidden ? 500 : value.data ? 16 : 64);
6813
+ } catch (reason) {
6814
+ if (stopped) return;
6815
+ observer.error(reason);
6816
+ pollTimer = window.setTimeout(() => {
6817
+ void poll();
6818
+ }, 500);
6819
+ }
6820
+ };
6821
+ const startPolling = () => {
6822
+ if (stopped || pollTimer !== void 0) return;
6823
+ source?.close();
6824
+ source = void 0;
6825
+ void poll();
6826
+ };
6827
+ if (typeof EventSource === "undefined") {
6828
+ startPolling();
6829
+ return stop;
6830
+ }
6831
+ source = new EventSource(this.endpoints.streamUrl);
6832
+ source.onmessage = (event) => {
6833
+ try {
6834
+ const value = parseOutput(event.data);
6835
+ streamConfirmed = true;
6836
+ if (streamWatchdog !== void 0) {
6837
+ clearTimeout(streamWatchdog);
6838
+ streamWatchdog = void 0;
6839
+ }
6840
+ accept(value);
6841
+ } catch (reason) {
6842
+ observer.error(reason);
6843
+ startPolling();
6844
+ }
6845
+ };
6846
+ source.onerror = () => {
6847
+ if (!streamConfirmed && source?.readyState === EventSource.CLOSED) startPolling();
6848
+ };
6849
+ streamWatchdog = window.setTimeout(() => {
6850
+ if (!streamConfirmed) startPolling();
6851
+ }, 1500);
6852
+ return stop;
6853
+ }
6854
+ dispose() {
6855
+ this.disposed = true;
6856
+ this.input = "";
6857
+ }
6858
+ deliverInput(text, sequence, onError, attempt = 0) {
6859
+ void this.endpoints.send(text, sequence).catch((reason) => {
6860
+ if (this.disposed) return;
6861
+ if (attempt < 2 && isRetryable(reason)) {
6862
+ window.setTimeout(() => this.deliverInput(text, sequence, onError, attempt + 1), 60 * (attempt + 1));
6863
+ return;
6864
+ }
6865
+ onError(reason);
6866
+ });
6867
+ }
6868
+ };
6869
+ function parseOutput(value) {
6870
+ const parsed = JSON.parse(value);
6871
+ if (typeof parsed.data !== "string" || typeof parsed.cursor !== "number" || !Number.isSafeInteger(parsed.cursor) || parsed.cursor < 0 || typeof parsed.truncated !== "boolean" || typeof parsed.closed !== "boolean") throw new Error("SSH terminal stream returned an invalid event");
6872
+ return parsed;
6873
+ }
6874
+ function isRetryable(reason) {
6875
+ if (typeof reason !== "object" || reason === null || !("status" in reason)) return true;
6876
+ const status = Number(reason.status);
6877
+ return !Number.isFinite(status) || status >= 500;
6878
+ }
6879
+
6743
6880
  // src/client.tsx
6744
6881
  var import_jsx_runtime3 = require("react/jsx-runtime");
6745
6882
  var PLUGIN_ID = "@lemoncat7/dsh-ssh";
@@ -6807,14 +6944,16 @@ function createActivityController(ctx) {
6807
6944
  const listeners = /* @__PURE__ */ new Set();
6808
6945
  let openSessionId;
6809
6946
  let selectedProfileId;
6947
+ let requestedView;
6810
6948
  let dispose;
6811
6949
  const notify = () => {
6812
6950
  for (const listener of listeners) listener();
6813
6951
  };
6814
6952
  const controller = {
6815
- open(sessionId, profileId) {
6953
+ open(sessionId, profileId, view) {
6816
6954
  if (dispose !== void 0 && openSessionId === sessionId) {
6817
6955
  if (profileId !== void 0) selectedProfileId = profileId;
6956
+ if (view !== void 0) requestedView = view;
6818
6957
  ctx.layout.openDetails();
6819
6958
  notify();
6820
6959
  return;
@@ -6822,6 +6961,7 @@ function createActivityController(ctx) {
6822
6961
  controller.close();
6823
6962
  openSessionId = sessionId;
6824
6963
  selectedProfileId = profileId;
6964
+ requestedView = view;
6825
6965
  dispose = ctx.slots.register({ name: "details", priority: -2 }, (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SshActivityPanel, { ...props, controller }));
6826
6966
  ctx.layout.openDetails();
6827
6967
  notify();
@@ -6836,12 +6976,14 @@ function createActivityController(ctx) {
6836
6976
  dispose = void 0;
6837
6977
  openSessionId = void 0;
6838
6978
  selectedProfileId = void 0;
6979
+ requestedView = void 0;
6839
6980
  current?.();
6840
6981
  if (current !== void 0) ctx.layout.closeDetails();
6841
6982
  notify();
6842
6983
  },
6843
6984
  isOpen: (sessionId) => dispose !== void 0 && openSessionId === sessionId,
6844
6985
  selected: (sessionId) => openSessionId === sessionId ? selectedProfileId : void 0,
6986
+ requestedView: (sessionId) => openSessionId === sessionId ? requestedView : void 0,
6845
6987
  subscribe(listener) {
6846
6988
  listeners.add(listener);
6847
6989
  return () => listeners.delete(listener);
@@ -6852,10 +6994,14 @@ function createActivityController(ctx) {
6852
6994
  function SshActivityPanel(props) {
6853
6995
  const sessionId = String(props.sessionId);
6854
6996
  const [activity, setActivity] = (0, import_react4.useState)();
6855
- const [view, setView] = (0, import_react4.useState)("directory");
6997
+ const [view, setView] = (0, import_react4.useState)(() => props.controller.requestedView(sessionId) ?? "directory");
6856
6998
  const [error, setError] = (0, import_react4.useState)();
6857
6999
  const [, setRevision] = (0, import_react4.useState)(0);
6858
- (0, import_react4.useEffect)(() => props.controller.subscribe(() => setRevision((value) => value + 1)), [props.controller]);
7000
+ (0, import_react4.useEffect)(() => props.controller.subscribe(() => {
7001
+ const requested = props.controller.requestedView(sessionId);
7002
+ if (requested !== void 0) setView(requested);
7003
+ setRevision((value) => value + 1);
7004
+ }), [props.controller, sessionId]);
6859
7005
  const refresh = (0, import_react4.useCallback)(async () => {
6860
7006
  try {
6861
7007
  const next = await loadActivity(sessionId);
@@ -6870,7 +7016,7 @@ function SshActivityPanel(props) {
6870
7016
  void refresh();
6871
7017
  const timer = window.setInterval(() => {
6872
7018
  void refresh();
6873
- }, view === "terminals" ? 800 : 2500);
7019
+ }, view === "terminals" ? 1800 : 2500);
6874
7020
  return () => clearInterval(timer);
6875
7021
  }, [refresh, view]);
6876
7022
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "dsh-ssh-activity-panel", "aria-label": "SSH \u6D3B\u52A8", children: [
@@ -6948,8 +7094,6 @@ function TerminalActivity({ sessionId, terminals }) {
6948
7094
  function InteractiveTerminal({ sessionId, terminal: activity, onError }) {
6949
7095
  const hostRef = (0, import_react4.useRef)(null);
6950
7096
  const terminalRef = (0, import_react4.useRef)();
6951
- const previousRef = (0, import_react4.useRef)("");
6952
- const inputQueueRef = (0, import_react4.useRef)(Promise.resolve());
6953
7097
  (0, import_react4.useEffect)(() => {
6954
7098
  const host = hostRef.current;
6955
7099
  if (host === null) return;
@@ -6970,20 +7114,22 @@ function InteractiveTerminal({ sessionId, terminal: activity, onError }) {
6970
7114
  fit.fit();
6971
7115
  terminalRef.current = terminal;
6972
7116
  terminal.focus();
6973
- let inputBuffer = "";
6974
- let inputTimer;
7117
+ const transport = new TerminalTransport({
7118
+ streamUrl: activityTerminalStreamUrl(sessionId, activity.terminalId),
7119
+ read: (cursor) => readActivityTerminalOutput(sessionId, activity.terminalId, cursor),
7120
+ send: (text, sequence) => sendActivityTerminalInput(sessionId, activity.terminalId, text, sequence)
7121
+ });
6975
7122
  let resizeTimer;
6976
7123
  let lastSize = "";
6977
- const flushInput = () => {
6978
- inputTimer = void 0;
6979
- const text = inputBuffer;
6980
- inputBuffer = "";
6981
- if (!text) return;
6982
- inputQueueRef.current = inputQueueRef.current.catch(() => void 0).then(() => sendActivityTerminalInput(sessionId, activity.terminalId, text)).then(() => onError(void 0), (reason) => onError(message(reason)));
6983
- };
6984
- const input = terminal.onData((data) => {
6985
- inputBuffer += data;
6986
- if (inputTimer === void 0) inputTimer = window.setTimeout(flushInput, 12);
7124
+ const input = terminal.onData((data) => transport.sendInput(data, (reason) => onError(message(reason))));
7125
+ const stopOutput = transport.observe({
7126
+ output: (value) => {
7127
+ if (value.truncated) terminal.reset();
7128
+ if (value.data) terminal.write(value.data);
7129
+ terminal.scrollToBottom();
7130
+ onError(void 0);
7131
+ },
7132
+ error: (reason) => onError(message(reason))
6987
7133
  });
6988
7134
  const syncSize = () => {
6989
7135
  fit.fit();
@@ -6998,30 +7144,19 @@ function InteractiveTerminal({ sessionId, terminal: activity, onError }) {
6998
7144
  });
6999
7145
  resize.observe(host);
7000
7146
  return () => {
7001
- if (inputTimer !== void 0) {
7002
- clearTimeout(inputTimer);
7003
- flushInput();
7004
- }
7005
7147
  if (resizeTimer !== void 0) clearTimeout(resizeTimer);
7148
+ stopOutput();
7149
+ transport.dispose();
7006
7150
  input.dispose();
7007
7151
  resize.disconnect();
7008
7152
  terminal.dispose();
7009
7153
  terminalRef.current = void 0;
7010
- previousRef.current = "";
7011
7154
  };
7012
- }, [activity.status.kind, activity.terminalId, onError, sessionId]);
7155
+ }, [activity.terminalId, onError, sessionId]);
7013
7156
  (0, import_react4.useEffect)(() => {
7014
7157
  const terminal = terminalRef.current;
7015
- if (terminal === void 0) return;
7016
- const previous = previousRef.current;
7017
- if (activity.scrollback.startsWith(previous)) terminal.write(activity.scrollback.slice(previous.length));
7018
- else {
7019
- terminal.reset();
7020
- terminal.write(activity.scrollback);
7021
- }
7022
- previousRef.current = activity.scrollback;
7023
- terminal.scrollToBottom();
7024
- }, [activity.scrollback]);
7158
+ if (terminal !== void 0) terminal.options.disableStdin = activity.status.kind !== "running";
7159
+ }, [activity.status.kind]);
7025
7160
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: hostRef, className: "dsh-ssh-terminal-screen", "aria-label": "\u4EA4\u4E92\u5F0F SSH \u7EC8\u7AEF" });
7026
7161
  }
7027
7162
  function RemoteSidebar(props) {
@@ -7044,10 +7179,25 @@ function RemoteSidebar(props) {
7044
7179
  const currentSessionId = sessionId === void 0 ? void 0 : String(sessionId);
7045
7180
  const activityOpen = currentSessionId !== void 0 && props.activityController.isOpen(currentSessionId);
7046
7181
  const availableProfiles = injection === null ? [] : injection.profileIds.map((profileId) => profiles.find((profile) => profile.id === profileId)).filter((profile) => profile !== void 0);
7182
+ (0, import_react4.useEffect)(() => {
7183
+ if (currentSessionId === void 0 || injection?.permission !== "terminal") return;
7184
+ const source = new EventSource(activityEventStreamUrl(currentSessionId));
7185
+ const opened = (raw) => {
7186
+ const event = parseTerminalOpenedEvent(raw);
7187
+ if (event === void 0 || event.sessionId !== currentSessionId) return;
7188
+ props.controller.close();
7189
+ props.activityController.open(currentSessionId, event.profileId, "terminals");
7190
+ };
7191
+ source.addEventListener("terminal-opened", opened);
7192
+ return () => {
7193
+ source.removeEventListener("terminal-opened", opened);
7194
+ source.close();
7195
+ };
7196
+ }, [currentSessionId, injection?.permission, props.activityController, props.controller]);
7047
7197
  const openActivity = (profileId) => {
7048
7198
  if (currentSessionId === void 0) return;
7049
7199
  props.controller.close();
7050
- props.activityController.open(currentSessionId, profileId);
7200
+ props.activityController.open(currentSessionId, profileId, "directory");
7051
7201
  };
7052
7202
  const toggleActivity = () => {
7053
7203
  if (currentSessionId === void 0) return;
@@ -7094,6 +7244,7 @@ function RemoteWorkspace(props) {
7094
7244
  const sessionId = props.useSessions((state) => state.current);
7095
7245
  const [profiles, setProfiles] = (0, import_react4.useState)([]);
7096
7246
  const [vaultEntries, setVaultEntries] = (0, import_react4.useState)([]);
7247
+ const [proxyEntries, setProxyEntries] = (0, import_react4.useState)([]);
7097
7248
  const [selectedId, setSelectedId] = (0, import_react4.useState)(props.controller.selected());
7098
7249
  const [view, setView] = (0, import_react4.useState)("terminal");
7099
7250
  const [editing, setEditing] = (0, import_react4.useState)();
@@ -7102,9 +7253,10 @@ function RemoteWorkspace(props) {
7102
7253
  const openedSessionRef = (0, import_react4.useRef)(sessionId);
7103
7254
  const refresh = (0, import_react4.useCallback)(async () => {
7104
7255
  try {
7105
- const [next, credentials] = await Promise.all([loadProfiles(), loadVaultEntries()]);
7256
+ const [next, credentials, proxies] = await Promise.all([loadProfiles(), loadVaultEntries(), loadProxyEntries()]);
7106
7257
  setProfiles(next);
7107
7258
  setVaultEntries(credentials);
7259
+ setProxyEntries(proxies);
7108
7260
  setSelectedId((current) => current !== void 0 && next.some((item) => item.id === current) ? current : next[0]?.id);
7109
7261
  setError(void 0);
7110
7262
  } catch (reason) {
@@ -7140,6 +7292,7 @@ function RemoteWorkspace(props) {
7140
7292
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Segment, { active: view === "sftp", onClick: () => setView("sftp"), children: "SFTP" }),
7141
7293
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Segment, { active: view === "forwards", onClick: () => setView("forwards"), children: "\u7AEF\u53E3\u8F6C\u53D1" }),
7142
7294
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Segment, { active: view === "vault", onClick: () => setView("vault"), children: "\u5BC6\u94A5\u5E93" }),
7295
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Segment, { active: view === "proxies", onClick: () => setView("proxies"), children: "\u4EE3\u7406\u5E93" }),
7143
7296
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Segment, { active: view === "settings", onClick: () => setView("settings"), children: "\u8BBE\u7F6E" })
7144
7297
  ] }),
7145
7298
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { type: "button", className: "dsh-ssh-primary-button", "aria-label": "\u65B0\u5EFA\u8FDE\u63A5", onClick: () => setEditing("new"), children: [
@@ -7170,10 +7323,10 @@ function RemoteWorkspace(props) {
7170
7323
  inspectorLabel: "\u4F1A\u8BDD\u6388\u6743",
7171
7324
  inspectorIcon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives2.IconUserOutline16, { size: 15 }),
7172
7325
  inspector: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(InjectionInspector, { sessionId: sessionId === void 0 ? void 0 : String(sessionId), profiles, selected }),
7173
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("section", { className: "dsh-ssh-main-panel", children: view === "vault" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(VaultPane, { entries: vaultEntries, onChanged: () => setRefreshKey((value) => value + 1) }) : selected === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(EmptyState, { onNew: () => setEditing("new") }) : view === "terminal" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TerminalPane, { profile: selected, onEdit: () => setEditing(selected) }) : view === "sftp" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ProfileSftpPane, { profile: selected }, selected.id) : view === "forwards" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ForwardPane, { profiles, selected }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SettingsPane, {}) })
7326
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("section", { className: "dsh-ssh-main-panel", children: view === "vault" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(VaultPane, { entries: vaultEntries, onChanged: () => setRefreshKey((value) => value + 1) }) : view === "proxies" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ProxyPane, { entries: proxyEntries, onChanged: () => setRefreshKey((value) => value + 1) }) : selected === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(EmptyState, { onNew: () => setEditing("new") }) : view === "terminal" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TerminalPane, { profile: selected, onEdit: () => setEditing(selected) }) : view === "sftp" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ProfileSftpPane, { profile: selected }, selected.id) : view === "forwards" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ForwardPane, { profiles, selected }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SettingsPane, {}) })
7174
7327
  }
7175
7328
  ),
7176
- editing !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ProfileEditor, { profile: editing === "new" ? void 0 : editing, profiles, vaultEntries, onClose: () => setEditing(void 0), onSaved: () => {
7329
+ editing !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ProfileEditor, { profile: editing === "new" ? void 0 : editing, profiles, vaultEntries, proxyEntries, onClose: () => setEditing(void 0), onSaved: () => {
7177
7330
  setEditing(void 0);
7178
7331
  setRefreshKey((value) => value + 1);
7179
7332
  } })
@@ -7305,36 +7458,29 @@ function TerminalPane({ profile, onEdit }) {
7305
7458
  if (terminalId === void 0) return;
7306
7459
  const terminal = terminalRef.current;
7307
7460
  if (terminal === void 0) return;
7308
- const input = terminal.onData((data) => {
7309
- void api(`/terminals/${terminalId}/input`, { method: "POST", body: JSON.stringify({ text: data }) }).catch((reason) => setError(message(reason)));
7461
+ const transport = new TerminalTransport({
7462
+ streamUrl: browserTerminalStreamUrl(terminalId),
7463
+ read: (cursor) => api(`/terminals/${terminalId}/output?cursor=${cursor}`),
7464
+ send: (text, sequence) => api(`/terminals/${terminalId}/input`, { method: "POST", body: JSON.stringify({ text, sequence }) })
7310
7465
  });
7311
- let cursor = 0;
7312
- let stopped = false;
7313
- const poll = async () => {
7314
- if (stopped) return;
7315
- try {
7316
- const output = await api(`/terminals/${terminalId}/output?cursor=${cursor}`);
7317
- if (output.truncated) terminal.write("\r\n\x1B[33m[\u8F83\u65E9\u8F93\u51FA\u5DF2\u622A\u65AD]\x1B[0m\r\n");
7318
- if (output.data) terminal.write(output.data);
7319
- cursor = output.cursor;
7320
- if (output.closed) {
7466
+ const input = terminal.onData((data) => transport.sendInput(data, (reason) => setError(message(reason))));
7467
+ const stopOutput = transport.observe({
7468
+ output: (value) => {
7469
+ if (value.truncated) terminal.write("\r\n\x1B[33m[\u8F83\u65E9\u8F93\u51FA\u5DF2\u622A\u65AD]\x1B[0m\r\n");
7470
+ if (value.data) terminal.write(value.data);
7471
+ if (value.closed) {
7321
7472
  setPhase("idle");
7322
7473
  setTerminalId(void 0);
7323
- return;
7324
- }
7325
- } catch (reason) {
7326
- if (!stopped) {
7327
- setError(message(reason));
7328
- setPhase("error");
7329
7474
  }
7475
+ },
7476
+ error: (reason) => {
7477
+ setError(message(reason));
7478
+ setPhase("error");
7330
7479
  }
7331
- if (!stopped) window.setTimeout(() => {
7332
- void poll();
7333
- }, document.hidden ? 800 : 180);
7334
- };
7335
- void poll();
7480
+ });
7336
7481
  return () => {
7337
- stopped = true;
7482
+ stopOutput();
7483
+ transport.dispose();
7338
7484
  input.dispose();
7339
7485
  };
7340
7486
  }, [terminalId]);
@@ -7709,6 +7855,117 @@ function VaultEditor({ value, onClose, onSaved }) {
7709
7855
  ] })
7710
7856
  ] }) });
7711
7857
  }
7858
+ function ProxyPane({ entries, onChanged }) {
7859
+ const [editing, setEditing] = (0, import_react4.useState)();
7860
+ const [error, setError] = (0, import_react4.useState)();
7861
+ const remove = async (entry) => {
7862
+ if (!window.confirm(`\u5220\u9664\u4EE3\u7406\u201C${entry.name}\u201D\uFF1F\u6B64\u64CD\u4F5C\u65E0\u6CD5\u64A4\u9500\u3002`)) return;
7863
+ try {
7864
+ await api(`/proxies/${entry.id}`, { method: "DELETE" });
7865
+ onChanged();
7866
+ } catch (reason) {
7867
+ setError(message(reason));
7868
+ }
7869
+ };
7870
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-ssh-proxy-pane", children: [
7871
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-ssh-content-heading", children: [
7872
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
7873
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h1", { children: "\u4EE3\u7406\u5E93" }),
7874
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: "\u96C6\u4E2D\u4FDD\u5B58\u5E38\u7528 HTTP \u4E0E SOCKS5 \u4EE3\u7406\uFF0C\u4E3B\u673A\u914D\u7F6E\u53EA\u4FDD\u7559\u5F15\u7528\u3002" })
7875
+ ] }),
7876
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { type: "button", className: "dsh-ssh-primary-button", onClick: () => setEditing("new"), children: [
7877
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives2.IconPlusOutline16, { size: 16 }),
7878
+ "\u65B0\u5EFA\u4EE3\u7406"
7879
+ ] })
7880
+ ] }),
7881
+ error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "dsh-ssh-inline-error", role: "alert", children: error }),
7882
+ entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-ssh-vault-empty", children: [
7883
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives2.IconDataOutline16, { size: 20 }) }),
7884
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: "\u8FD8\u6CA1\u6709\u5E38\u7528\u4EE3\u7406" }),
7885
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: "\u4FDD\u5B58\u4E00\u6B21\u540E\uFF0C\u591A\u53F0 SSH \u4E3B\u673A\u53EF\u4EE5\u5171\u7528\u540C\u4E00\u6761\u8FDE\u63A5\u8DEF\u5F84\u3002" }),
7886
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { type: "button", className: "dsh-ssh-secondary-button", onClick: () => setEditing("new"), children: [
7887
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives2.IconPlusOutline16, { size: 15 }),
7888
+ "\u6DFB\u52A0\u4EE3\u7406"
7889
+ ] })
7890
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-ssh-proxy-list", children: entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "dsh-ssh-proxy-row", children: [
7891
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-ssh-vault-glyph", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives2.IconDataOutline16, { size: 16 }) }),
7892
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
7893
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: entry.name }),
7894
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("small", { children: [
7895
+ entry.host,
7896
+ ":",
7897
+ entry.port,
7898
+ entry.username ? ` \xB7 ${entry.username}` : ""
7899
+ ] })
7900
+ ] }),
7901
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-ssh-proxy-kind", children: entry.proxyType === "http" ? "HTTP" : "SOCKS5" }),
7902
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("small", { children: [
7903
+ entry.references,
7904
+ " \u4E2A\u8FDE\u63A5"
7905
+ ] }),
7906
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dsh-ssh-icon-button", "aria-label": `\u7F16\u8F91 ${entry.name}`, onClick: () => setEditing(entry), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives2.IconEditOutline16, { size: 16 }) }),
7907
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dsh-ssh-icon-button is-danger", disabled: entry.references > 0, "aria-label": `\u5220\u9664 ${entry.name}`, title: entry.references > 0 ? "\u4ECD\u6709\u8FDE\u63A5\u6B63\u5728\u4F7F\u7528" : "\u5220\u9664\u4EE3\u7406", onClick: () => {
7908
+ void remove(entry);
7909
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives2.IconTrashOutline16, { size: 16 }) })
7910
+ ] }, entry.id)) }),
7911
+ editing !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ProxyEditor, { value: editing === "new" ? void 0 : editing, onClose: () => setEditing(void 0), onSaved: () => {
7912
+ setEditing(void 0);
7913
+ onChanged();
7914
+ } })
7915
+ ] });
7916
+ }
7917
+ function ProxyEditor({ value, onClose, onSaved }) {
7918
+ const [form, setForm] = (0, import_react4.useState)({
7919
+ name: value?.name ?? "",
7920
+ proxyType: value?.proxyType ?? "socks5",
7921
+ host: value?.host ?? "",
7922
+ port: String(value?.port ?? 1080),
7923
+ username: value?.username ?? "",
7924
+ password: ""
7925
+ });
7926
+ const [saving, setSaving] = (0, import_react4.useState)(false);
7927
+ const [error, setError] = (0, import_react4.useState)();
7928
+ const submit = async (event) => {
7929
+ event.preventDefault();
7930
+ setSaving(true);
7931
+ setError(void 0);
7932
+ try {
7933
+ await api(value === void 0 ? "/proxies" : `/proxies/${value.id}`, {
7934
+ method: value === void 0 ? "POST" : "PUT",
7935
+ body: JSON.stringify({ entry: { name: form.name, proxyType: form.proxyType, host: form.host, port: Number(form.port), ...form.username.trim() ? { username: form.username.trim() } : {} }, secrets: { proxyPassword: form.password } })
7936
+ });
7937
+ onSaved();
7938
+ } catch (reason) {
7939
+ setError(message(reason));
7940
+ } finally {
7941
+ setSaving(false);
7942
+ }
7943
+ };
7944
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Dialog, { title: value === void 0 ? "\u65B0\u5EFA\u5E38\u7528\u4EE3\u7406" : `\u7F16\u8F91 ${value.name}`, subtitle: "\u4EE3\u7406\u5BC6\u7801\u4FDD\u5B58\u540E\u4E0D\u4F1A\u56DE\u663E", onClose, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("form", { className: "dsh-ssh-form", onSubmit: (event) => {
7945
+ void submit(event);
7946
+ }, children: [
7947
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-ssh-form-grid", children: [
7948
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Field, { label: "\u540D\u79F0", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { required: true, maxLength: 80, value: form.name, onChange: (event) => setForm({ ...form, name: event.target.value }), placeholder: "\u529E\u516C\u5BA4 SOCKS5" }) }),
7949
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Field, { label: "\u4EE3\u7406\u7C7B\u578B", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("select", { value: form.proxyType, onChange: (event) => setForm({ ...form, proxyType: event.target.value }), children: [
7950
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "socks5", children: "SOCKS5" }),
7951
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "http", children: "HTTP CONNECT" })
7952
+ ] }) })
7953
+ ] }),
7954
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-ssh-form-grid is-host", children: [
7955
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Field, { label: "\u4EE3\u7406\u4E3B\u673A", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { required: true, maxLength: 253, value: form.host, onChange: (event) => setForm({ ...form, host: event.target.value }), placeholder: "127.0.0.1" }) }),
7956
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Field, { label: "\u4EE3\u7406\u7AEF\u53E3", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { required: true, type: "number", min: "1", max: "65535", value: form.port, onChange: (event) => setForm({ ...form, port: event.target.value }) }) })
7957
+ ] }),
7958
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-ssh-form-grid", children: [
7959
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Field, { label: "\u4EE3\u7406\u7528\u6237\u540D", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { maxLength: 128, value: form.username, onChange: (event) => setForm({ ...form, username: event.target.value }), autoComplete: "username" }) }),
7960
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Field, { label: "\u4EE3\u7406\u5BC6\u7801", hint: value?.credential.fields.includes("proxyPassword") ? "\u5DF2\u4FDD\u5B58\uFF1B\u7559\u7A7A\u4FDD\u6301\u4E0D\u53D8" : "\u53EF\u9009\uFF0C\u4FDD\u5B58\u540E\u4E0D\u53EF\u8BFB\u56DE", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "password", autoComplete: "new-password", value: form.password, onChange: (event) => setForm({ ...form, password: event.target.value }) }) })
7961
+ ] }),
7962
+ error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "dsh-ssh-inline-error", role: "alert", children: error }),
7963
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-ssh-dialog-actions", children: [
7964
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dsh-ssh-secondary-button", onClick: onClose, children: "\u53D6\u6D88" }),
7965
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "dsh-ssh-primary-button", disabled: saving, children: saving ? "\u6B63\u5728\u4FDD\u5B58\u2026" : "\u4FDD\u5B58\u4EE3\u7406" })
7966
+ ] })
7967
+ ] }) });
7968
+ }
7712
7969
  function SettingsPane() {
7713
7970
  const [settings, setSettings] = (0, import_react4.useState)();
7714
7971
  const [error, setError] = (0, import_react4.useState)();
@@ -7761,7 +8018,7 @@ function SettingsPane() {
7761
8018
  error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "dsh-ssh-inline-error", children: error })
7762
8019
  ] });
7763
8020
  }
7764
- function ProfileEditor({ profile, profiles, vaultEntries, onClose, onSaved }) {
8021
+ function ProfileEditor({ profile, profiles, vaultEntries, proxyEntries, onClose, onSaved }) {
7765
8022
  const [form, setForm] = (0, import_react4.useState)(() => ({
7766
8023
  name: profile?.name ?? "",
7767
8024
  group: profile?.group ?? "",
@@ -7771,6 +8028,7 @@ function ProfileEditor({ profile, profiles, vaultEntries, onClose, onSaved }) {
7771
8028
  authType: profile?.authType ?? "password",
7772
8029
  credentialId: profile?.credentialId ?? "",
7773
8030
  proxyType: profile?.proxy.type ?? "none",
8031
+ proxyEntryId: profile?.proxy.type === "saved" ? profile.proxy.proxyId : "",
7774
8032
  proxyHost: profile?.proxy.type === "http" || profile?.proxy.type === "socks5" ? profile.proxy.host : "",
7775
8033
  proxyPort: profile?.proxy.type === "http" || profile?.proxy.type === "socks5" ? String(profile.proxy.port) : "1080",
7776
8034
  proxyUsername: profile?.proxy.type === "http" || profile?.proxy.type === "socks5" ? profile.proxy.username ?? "" : "",
@@ -7794,7 +8052,7 @@ function ProfileEditor({ profile, profiles, vaultEntries, onClose, onSaved }) {
7794
8052
  } });
7795
8053
  const selectedCredential = vaultEntries.find((entry) => entry.id === form.credentialId);
7796
8054
  const buildPayload = (hostFingerprint = form.hostFingerprint) => {
7797
- const proxy = form.proxyType === "none" ? { type: "none" } : form.proxyType === "jump" ? { type: "jump", profileIds: form.jumpProfileIds } : { type: form.proxyType, host: form.proxyHost, port: Number(form.proxyPort), ...form.proxyUsername.trim() ? { username: form.proxyUsername.trim() } : {} };
8055
+ const proxy = form.proxyType === "none" ? { type: "none" } : form.proxyType === "saved" ? { type: "saved", proxyId: form.proxyEntryId } : form.proxyType === "jump" ? { type: "jump", profileIds: form.jumpProfileIds } : { type: form.proxyType, host: form.proxyHost, port: Number(form.proxyPort), ...form.proxyUsername.trim() ? { username: form.proxyUsername.trim() } : {} };
7798
8056
  return {
7799
8057
  profile: { name: form.name, ...form.group.trim() ? { group: form.group.trim() } : {}, host: form.host, port: Number(form.port), username: selectedCredential?.username ?? form.username, authType: selectedCredential?.authType ?? form.authType, ...form.credentialId ? { credentialId: form.credentialId } : {}, ...hostFingerprint ? { hostFingerprint } : {}, proxy, keepAliveIntervalMs: profile?.keepAliveIntervalMs ?? 15e3, connectTimeoutMs: profile?.connectTimeoutMs ?? 15e3, terminalType: profile?.terminalType ?? "xterm-256color", tags: form.tags.split(",").map((item) => item.trim()).filter(Boolean) },
7800
8058
  secrets: { password: form.password, privateKey: form.privateKey, passphrase: form.passphrase, proxyPassword: form.proxyPassword }
@@ -7879,10 +8137,23 @@ function ProfileEditor({ profile, profiles, vaultEntries, onClose, onSaved }) {
7879
8137
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-ssh-form-divider", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u4EE3\u7406" }) }),
7880
8138
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Field, { label: "\u8FDE\u63A5\u8DEF\u5F84", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("select", { ...field("proxyType"), children: [
7881
8139
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "none", children: "\u76F4\u8FDE" }),
7882
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "http", children: "HTTP CONNECT" }),
7883
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "socks5", children: "SOCKS5" }),
8140
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "saved", children: "\u5E38\u7528\u4EE3\u7406" }),
8141
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "http", children: "\u81EA\u5B9A\u4E49 HTTP CONNECT" }),
8142
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "socks5", children: "\u81EA\u5B9A\u4E49 SOCKS5" }),
7884
8143
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "jump", children: "SSH \u8DF3\u677F" })
7885
8144
  ] }) }),
8145
+ form.proxyType === "saved" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Field, { label: "\u5E38\u7528\u4EE3\u7406", hint: proxyEntries.length === 0 ? "\u8BF7\u5148\u5728\u4EE3\u7406\u5E93\u4E2D\u6DFB\u52A0 HTTP \u6216 SOCKS5 \u4EE3\u7406\u3002" : "\u591A\u53F0\u4E3B\u673A\u53EF\u5F15\u7528\u540C\u4E00\u6761\u4EE3\u7406\u914D\u7F6E\u3002", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("select", { required: true, ...field("proxyEntryId"), children: [
8146
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "", children: "\u9009\u62E9\u4EE3\u7406" }),
8147
+ proxyEntries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("option", { value: entry.id, children: [
8148
+ entry.name,
8149
+ " \xB7 ",
8150
+ entry.proxyType === "http" ? "HTTP" : "SOCKS5",
8151
+ " \xB7 ",
8152
+ entry.host,
8153
+ ":",
8154
+ entry.port
8155
+ ] }, entry.id))
8156
+ ] }) }),
7886
8157
  (form.proxyType === "http" || form.proxyType === "socks5") && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
7887
8158
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-ssh-form-grid is-host", children: [
7888
8159
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Field, { label: "\u4EE3\u7406\u4E3B\u673A", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { required: true, ...field("proxyHost") }) }),
@@ -8036,7 +8307,7 @@ function ServerGlyph() {
8036
8307
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-ssh-server-glyph", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives2.IconDataOutline16, { size: 17 }) });
8037
8308
  }
8038
8309
  function proxyLabel(profile) {
8039
- return profile.proxy.type === "none" ? "\u76F4\u8FDE" : profile.proxy.type === "jump" ? "SSH \u8DF3\u677F" : profile.proxy.type === "http" ? "HTTP \u4EE3\u7406" : "SOCKS5 \u4EE3\u7406";
8310
+ return profile.proxy.type === "none" ? "\u76F4\u8FDE" : profile.proxy.type === "saved" ? "\u5E38\u7528\u4EE3\u7406" : profile.proxy.type === "jump" ? "SSH \u8DF3\u677F" : profile.proxy.type === "http" ? "HTTP \u4EE3\u7406" : "SOCKS5 \u4EE3\u7406";
8040
8311
  }
8041
8312
  function shortId(id) {
8042
8313
  return id.length <= 16 ? id : `${id.slice(0, 8)}\u2026${id.slice(-5)}`;
@@ -8044,6 +8315,16 @@ function shortId(id) {
8044
8315
  function message(error) {
8045
8316
  return error instanceof Error ? error.message : String(error);
8046
8317
  }
8318
+ function parseTerminalOpenedEvent(raw) {
8319
+ if (!(raw instanceof MessageEvent) || typeof raw.data !== "string") return void 0;
8320
+ try {
8321
+ const value = JSON.parse(raw.data);
8322
+ if (value.type !== "terminal-opened" || typeof value.sessionId !== "string" || typeof value.terminalId !== "string" || typeof value.profileId !== "string" || typeof value.createdAt !== "number") return void 0;
8323
+ return value;
8324
+ } catch {
8325
+ return void 0;
8326
+ }
8327
+ }
8047
8328
  function forwardSummary(rule, status) {
8048
8329
  const bind = `${rule.bindHost}:${status?.bindPort ?? rule.bindPort}`;
8049
8330
  return rule.kind === "dynamic" ? `${bind} \u2192 SOCKS5` : `${bind} \u2192 ${rule.targetHost}:${rule.targetPort}`;