ptn 0.1.4__py3-none-any.whl → 0.2.5__py3-none-any.whl
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.
- porterminal/__init__.py +19 -3
- porterminal/_version.py +34 -0
- porterminal/app.py +8 -4
- porterminal/application/services/terminal_service.py +116 -28
- porterminal/asgi.py +8 -3
- porterminal/cli/args.py +50 -0
- porterminal/composition.py +13 -5
- porterminal/config.py +54 -70
- porterminal/container.py +0 -11
- porterminal/domain/__init__.py +0 -2
- porterminal/domain/entities/output_buffer.py +0 -4
- porterminal/domain/ports/__init__.py +1 -2
- porterminal/domain/ports/pty_port.py +0 -29
- porterminal/domain/ports/tab_repository.py +0 -5
- porterminal/infrastructure/config/__init__.py +0 -2
- porterminal/infrastructure/config/shell_detector.py +1 -0
- porterminal/infrastructure/repositories/in_memory_tab.py +0 -4
- porterminal/infrastructure/server.py +10 -3
- porterminal/static/assets/app-By4EXMHC.js +72 -0
- porterminal/static/assets/app-DQePboVd.css +32 -0
- porterminal/static/index.html +16 -25
- porterminal/updater.py +115 -168
- ptn-0.2.5.dist-info/METADATA +148 -0
- {ptn-0.1.4.dist-info → ptn-0.2.5.dist-info}/RECORD +27 -29
- porterminal/infrastructure/config/yaml_loader.py +0 -34
- porterminal/static/assets/app-BQiuUo6Q.css +0 -32
- porterminal/static/assets/app-YNN_jEhv.js +0 -71
- porterminal/static/manifest.json +0 -31
- porterminal/static/sw.js +0 -66
- ptn-0.1.4.dist-info/METADATA +0 -191
- {ptn-0.1.4.dist-info → ptn-0.2.5.dist-info}/WHEEL +0 -0
- {ptn-0.1.4.dist-info → ptn-0.2.5.dist-info}/entry_points.txt +0 -0
- {ptn-0.1.4.dist-info → ptn-0.2.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
porterminal/__init__.py,sha256=
|
|
1
|
+
porterminal/__init__.py,sha256=fqY1ac5vc_zXQBWBMgziJbRJFEnpfFOezf-feWGCvEQ,10677
|
|
2
2
|
porterminal/__main__.py,sha256=XLo21rqmISrIZFiaHC58Trgq8E0gxH4Wb3driD4JA7c,137
|
|
3
|
-
porterminal/
|
|
4
|
-
porterminal/
|
|
5
|
-
porterminal/
|
|
6
|
-
porterminal/
|
|
7
|
-
porterminal/
|
|
3
|
+
porterminal/_version.py,sha256=9wrJ_4Dlc0arUzKiaIqvTY85rMJma3eb1nNlF3uHAxU,704
|
|
4
|
+
porterminal/app.py,sha256=kuZfiV23wsMLi6382R2mhGjzGibFgutxms8PXAesAoE,14101
|
|
5
|
+
porterminal/asgi.py,sha256=P76H7k03T3GYBAmjWqLaCZXV-YIou6NMhfRySO8He1A,1276
|
|
6
|
+
porterminal/composition.py,sha256=UfcULLg6_HzKubmAU93jUI7ABwawhMd-XzcgVjBV2ag,6698
|
|
7
|
+
porterminal/config.py,sha256=rABTms9AammCSbRFjYvGGdybWx5WZ7Z8PQAi1Zb8v30,5253
|
|
8
|
+
porterminal/container.py,sha256=upetU-eK-fo-lKStO_DCY9odD_f-SoBkdgjZlFG4gWA,1450
|
|
8
9
|
porterminal/logging_setup.py,sha256=DhoN_FdJFbRawcsYy8mLRU32TCT1ZfZ2G4Q_AOKwZuA,1513
|
|
9
|
-
porterminal/updater.py,sha256=
|
|
10
|
+
porterminal/updater.py,sha256=iIUQzo4AW8DWoQdJnCQ9DRiSgTZRiN6XXbTYn4puPaw,6222
|
|
10
11
|
porterminal/application/__init__.py,sha256=Q5gQia_11ubfMcDbzjvI6RoUU2jFJkuQrsbSuIfQCRA,55
|
|
11
12
|
porterminal/application/ports/__init__.py,sha256=zKcSDFmPPOIP0Oxuf8O5AEMmURV7AaSVA2D8iahwU6c,149
|
|
12
13
|
porterminal/application/ports/connection_port.py,sha256=kXIl-fzx3SbpU8kV1rpmgNeI22XSJMbzXGt1YcwZO8Y,926
|
|
@@ -14,19 +15,19 @@ porterminal/application/services/__init__.py,sha256=YO-iPdE_-EEV9tVnu0NcB5bwSCCS
|
|
|
14
15
|
porterminal/application/services/management_service.py,sha256=WllcHDCQuPzAKkEEyhV8afDWJ2aUw8rsBsFhbZ3DWPU,8661
|
|
15
16
|
porterminal/application/services/session_service.py,sha256=f1Mk-a9ug895jSsskOKY1uW3N5IcMTEutpM_d0RAmaM,8234
|
|
16
17
|
porterminal/application/services/tab_service.py,sha256=0_S978dYhBW2-eaZN2wOlcZOY4V4iPt2MMNOyoZQxPs,8307
|
|
17
|
-
porterminal/application/services/terminal_service.py,sha256=
|
|
18
|
+
porterminal/application/services/terminal_service.py,sha256=za8Rr-Hb7C2xzCF0HmSG7VpCk1_gvTsnChyyPyOzVPs,19818
|
|
18
19
|
porterminal/cli/__init__.py,sha256=A3y-QgKrT-vdAYV-xsZjeyMkiPymZaZzYUGQ-_3cXmQ,305
|
|
19
|
-
porterminal/cli/args.py,sha256=
|
|
20
|
+
porterminal/cli/args.py,sha256=VEkN-nUHgPipFIzK95hmHblRdgin7FLl1spre3Cvf5o,3672
|
|
20
21
|
porterminal/cli/display.py,sha256=wErWVPz3PmCvX5vxxaCdPb4YSeByrEj1dj0BSSmrZE0,5530
|
|
21
|
-
porterminal/domain/__init__.py,sha256=
|
|
22
|
+
porterminal/domain/__init__.py,sha256=OIkaxSb2BThs1COAvsuyOWC-l7lWd7Dfvl1kwNVlgPg,1646
|
|
22
23
|
porterminal/domain/entities/__init__.py,sha256=dIQp6T0M-Bl_DJpSOGQGBD29Rl_FDR0XfVrDL08ck50,463
|
|
23
|
-
porterminal/domain/entities/output_buffer.py,sha256=
|
|
24
|
+
porterminal/domain/entities/output_buffer.py,sha256=d5ILcaxBsTLtZQEaGAgXFByQVacdsXRO9ioEAIgWqlA,2133
|
|
24
25
|
porterminal/domain/entities/session.py,sha256=SzAEqbqr49QhcSW_2BqYVJst1_6yo8qs21Efh_uBJDA,2680
|
|
25
26
|
porterminal/domain/entities/tab.py,sha256=OQPS_CtTx5MD8bjH23NQw0Z4RbXh8Mqew3P0_KYHYl4,2124
|
|
26
|
-
porterminal/domain/ports/__init__.py,sha256=
|
|
27
|
-
porterminal/domain/ports/pty_port.py,sha256=
|
|
27
|
+
porterminal/domain/ports/__init__.py,sha256=ryAYtrvSanQecroEz7tPHzWN_U9icx51Fn_snDBNDiQ,264
|
|
28
|
+
porterminal/domain/ports/pty_port.py,sha256=HGk7kyE1j5vG5aebB2XFfrhjNX6a2g37eUUPpgPJxu0,1179
|
|
28
29
|
porterminal/domain/ports/session_repository.py,sha256=Gh5c2cneboXYEuNw8Gxw06IZwpMqhN0HA7KINFFi2LQ,1611
|
|
29
|
-
porterminal/domain/ports/tab_repository.py,sha256=
|
|
30
|
+
porterminal/domain/ports/tab_repository.py,sha256=_QMuTqjc9A095sDInD4fk7sjCu_v-aXXM4HzCQsOyO0,1826
|
|
30
31
|
porterminal/domain/services/__init__.py,sha256=YiEokgIXvSbfieNlBfdWSPJlbBYDFrzIYc5aVpkjSeI,561
|
|
31
32
|
porterminal/domain/services/environment_sanitizer.py,sha256=RslZDn8jso8bX1hG9p9NQyv1ey19u1F5xATPlq6pKVw,2014
|
|
32
33
|
porterminal/domain/services/rate_limiter.py,sha256=I0cybe1PX7uYWlr7l92N3jM89yFQDRKqD5p9-lT8Mas,1724
|
|
@@ -43,15 +44,14 @@ porterminal/domain/values/user_id.py,sha256=eskGRVL-qj4czXljF0e5imDh19pAq16faXJY
|
|
|
43
44
|
porterminal/infrastructure/__init__.py,sha256=rIaiEG4gyvfSixSEry0kA2uMhStQQIWv9PRlfs17qts,649
|
|
44
45
|
porterminal/infrastructure/cloudflared.py,sha256=6vGUdFmGrxLTbopGgEdYRKJ5n0M3Ov00cuM-hEYAjSk,11506
|
|
45
46
|
porterminal/infrastructure/network.py,sha256=XnYbEXKQA8BnrLFl9b4OTTixFG1pVFxfeVuhN-XPkfU,1275
|
|
46
|
-
porterminal/infrastructure/server.py,sha256=
|
|
47
|
-
porterminal/infrastructure/config/__init__.py,sha256=
|
|
48
|
-
porterminal/infrastructure/config/shell_detector.py,sha256=
|
|
49
|
-
porterminal/infrastructure/config/yaml_loader.py,sha256=7EQhJLQymHRGwHLIsEXvIDTnfcRmMgl-ASuQaOaycnY,877
|
|
47
|
+
porterminal/infrastructure/server.py,sha256=r0tr4I28ocL1JskGmZcTTmBd6gDW446QjV2paZWvLqY,4850
|
|
48
|
+
porterminal/infrastructure/config/__init__.py,sha256=kcoM8mQYa83rkxn8TUfh0nETKynrsLmVwD9ySIfvdPQ,139
|
|
49
|
+
porterminal/infrastructure/config/shell_detector.py,sha256=pCbtD1HHmH99Ih1i8PypRhoS3ZxKKLvr7jmhD3SB15k,2702
|
|
50
50
|
porterminal/infrastructure/registry/__init__.py,sha256=reNbIYRr1alNps7zm_oENuS6QWNKiiO-WG09LT5MLmM,157
|
|
51
51
|
porterminal/infrastructure/registry/user_connection_registry.py,sha256=u9KOSijHiRITnwnOBKwXuYOKbFguh2NbxmNMxIoo8vc,3398
|
|
52
52
|
porterminal/infrastructure/repositories/__init__.py,sha256=UyF9lpobXgKb9Ti6ucC6fDcC9CkMAGDThggEG-Rf-Aw,250
|
|
53
53
|
porterminal/infrastructure/repositories/in_memory_session.py,sha256=yNkCuxrR8S5yTC_I_OFOYg1DlgEkxcI2DEW6aPq9ByQ,2490
|
|
54
|
-
porterminal/infrastructure/repositories/in_memory_tab.py,sha256=
|
|
54
|
+
porterminal/infrastructure/repositories/in_memory_tab.py,sha256=txHwO3xdRZjBzmdxCQy02conzjkq8lRWGQoKUd4J__E,4230
|
|
55
55
|
porterminal/infrastructure/web/__init__.py,sha256=QZqOtxOqhuxh4AD5xzPl9CBfOscdXOoGQv4zT4rpy7Q,147
|
|
56
56
|
porterminal/infrastructure/web/websocket_adapter.py,sha256=vVjIhcfWikPw-PKfSyqm3Y7PbTxNj1mstfrHIpcg6ng,2424
|
|
57
57
|
porterminal/pty/__init__.py,sha256=WNniN5uYKthLMOT7nzH63pkfFCJltToika50NZGR2cA,1054
|
|
@@ -61,13 +61,11 @@ porterminal/pty/protocol.py,sha256=-OPHIfLxL6R_JTrOQNB2t-sRH7LqtFgJE3QkBcHBqNA,1
|
|
|
61
61
|
porterminal/pty/unix.py,sha256=hDwHuD2XD4RN6t_Hk_q-XvgQ4dNF9zUSwJhe0-Y9JBU,5094
|
|
62
62
|
porterminal/pty/windows.py,sha256=7WrtxgUbqDKSPMK9_pN9vNPzMalV1p-UyyZlBZJn8EY,3933
|
|
63
63
|
porterminal/static/icon.svg,sha256=y7-MIl7F_wVQMLHWmmC7MrZHZK5ikLg1BR_0jbqnTkc,1949
|
|
64
|
-
porterminal/static/index.html,sha256=
|
|
65
|
-
porterminal/static/
|
|
66
|
-
porterminal/static/
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
ptn-0.
|
|
70
|
-
ptn-0.
|
|
71
|
-
ptn-0.
|
|
72
|
-
ptn-0.1.4.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
|
73
|
-
ptn-0.1.4.dist-info/RECORD,,
|
|
64
|
+
porterminal/static/index.html,sha256=JzhGkRmuEZsCPU-kvJcCWj5yUXrjFxqRpBwxME3MSNU,5920
|
|
65
|
+
porterminal/static/assets/app-By4EXMHC.js,sha256=OrKBI-ysghknqzSOLRXb1oeggDdaq4SyYjUwu_nuagU,433902
|
|
66
|
+
porterminal/static/assets/app-DQePboVd.css,sha256=um-bPz_s6bxB6ZofHC6DHbApYpy5Ds8OEgvmireZfHg,18043
|
|
67
|
+
ptn-0.2.5.dist-info/METADATA,sha256=tGG6euOUP8PWeewJJutBN0_Y-sZrVrmmZGx9PRC8m2w,5676
|
|
68
|
+
ptn-0.2.5.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
69
|
+
ptn-0.2.5.dist-info/entry_points.txt,sha256=Ftj1zSu_7G0yD5mAtGN3RoewyIuoBOfP_noSISe73tU,41
|
|
70
|
+
ptn-0.2.5.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
|
71
|
+
ptn-0.2.5.dist-info/RECORD,,
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"""YAML configuration loader."""
|
|
2
|
-
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from typing import Any
|
|
5
|
-
|
|
6
|
-
import yaml
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class YAMLConfigLoader:
|
|
10
|
-
"""Load configuration from YAML files."""
|
|
11
|
-
|
|
12
|
-
def __init__(self, config_path: Path | str = "config.yaml") -> None:
|
|
13
|
-
self._config_path = Path(config_path)
|
|
14
|
-
|
|
15
|
-
def load(self) -> dict[str, Any]:
|
|
16
|
-
"""Load raw configuration data from YAML.
|
|
17
|
-
|
|
18
|
-
Returns:
|
|
19
|
-
Configuration dictionary, empty dict if file not found.
|
|
20
|
-
"""
|
|
21
|
-
if not self._config_path.exists():
|
|
22
|
-
return {}
|
|
23
|
-
|
|
24
|
-
with open(self._config_path, encoding="utf-8") as f:
|
|
25
|
-
return yaml.safe_load(f) or {}
|
|
26
|
-
|
|
27
|
-
def reload(self) -> dict[str, Any]:
|
|
28
|
-
"""Reload configuration from file."""
|
|
29
|
-
return self.load()
|
|
30
|
-
|
|
31
|
-
@property
|
|
32
|
-
def path(self) -> Path:
|
|
33
|
-
"""Get configuration file path."""
|
|
34
|
-
return self._config_path
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
|
3
|
-
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
|
4
|
-
* https://github.com/chjj/term.js
|
|
5
|
-
* @license MIT
|
|
6
|
-
*
|
|
7
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
-
* of this software and associated documentation files (the "Software"), to deal
|
|
9
|
-
* in the Software without restriction, including without limitation the rights
|
|
10
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
-
* copies of the Software, and to permit persons to whom the Software is
|
|
12
|
-
* furnished to do so, subject to the following conditions:
|
|
13
|
-
*
|
|
14
|
-
* The above copyright notice and this permission notice shall be included in
|
|
15
|
-
* all copies or substantial portions of the Software.
|
|
16
|
-
*
|
|
17
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
|
-
* THE SOFTWARE.
|
|
24
|
-
*
|
|
25
|
-
* Originally forked from (with the author's permission):
|
|
26
|
-
* Fabrice Bellard's javascript vt100 for jslinux:
|
|
27
|
-
* http://bellard.org/jslinux/
|
|
28
|
-
* Copyright (c) 2011 Fabrice Bellard
|
|
29
|
-
* The original design remains. The terminal itself
|
|
30
|
-
* has been extended to include xterm CSI codes, among
|
|
31
|
-
* other features.
|
|
32
|
-
*/.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}:root{--bg-primary: #1e1e1e;--bg-elevated: #252525;--bg-surface: #2d2d2d;--bg-gradient-top: #232323;--bg-gradient-bottom: #1a1a1a;--text-primary: #cccccc;--text-high: rgba(255, 255, 255, .9);--text-secondary: rgba(255, 255, 255, .7);--text-muted: rgba(255, 255, 255, .5);--text-disabled: rgba(255, 255, 255, .4);--border-subtle: rgba(255, 255, 255, .05);--border-light: rgba(255, 255, 255, .1);--border-medium: rgba(255, 255, 255, .15);--color-success: rgba(100, 220, 100, .8);--color-success-text: rgba(130, 230, 150, 1);--color-success-bg: rgba(100, 200, 120, .15);--color-danger: rgba(255, 100, 100, .8);--color-danger-muted: rgba(255, 120, 120, .7);--color-danger-text: rgba(255, 150, 150, 1);--color-danger-bg: rgba(255, 80, 80, .15);--color-accent: rgba(80, 160, 255, .8);--color-accent-text: rgba(150, 200, 255, 1);--color-accent-bg: rgba(80, 160, 255, .3);--color-accent-strong: rgba(80, 160, 255, .5);--hover-overlay: rgba(255, 255, 255, .05);--active-overlay: rgba(255, 255, 255, .08);--scrollbar-thumb: rgba(255, 255, 255, .15);--scrollbar-hover: rgba(255, 255, 255, .25);--cursor-color: #aeafad;--selection-bg: rgba(38, 79, 120, .5);--shadow-elevated: 0 4px 16px rgba(0, 0, 0, .5);--glow-success: 0 0 6px rgba(100, 220, 100, .4);--glow-danger: 0 0 6px rgba(255, 100, 100, .4);--glow-accent: 0 0 8px rgba(80, 160, 255, .4);--overlay-bg: rgba(0, 0, 0, .9)}.tool-btn,.tab-btn{-webkit-touch-callout:none}html,body{margin:0;padding:0;height:100%;overflow:hidden;background:var(--bg-primary);color:var(--text-primary);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:13px;position:fixed;width:100%;touch-action:none;overscroll-behavior:none}#app{display:flex;flex-direction:column;height:100%;height:100dvh;height:100svh;padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px);overflow:hidden;overscroll-behavior:none}#tab-bar{display:flex;align-items:center;height:30px;min-height:30px;background:linear-gradient(to bottom,var(--bg-gradient-top),var(--bg-gradient-bottom));border-bottom:1px solid var(--border-subtle);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}#tab-bar::-webkit-scrollbar{display:none}.tab-btn{display:flex;align-items:center;gap:2px;height:30px;padding:0 2px 0 8px;background:transparent;border:none;border-right:1px solid var(--border-subtle);color:var(--text-muted);font-size:12px;cursor:pointer;white-space:nowrap;flex-shrink:0;transition:all .15s ease}.tab-btn:active{background:var(--hover-overlay)}.tab-btn.active{background:var(--active-overlay);color:var(--text-high)}.tab-btn.tab-add{color:var(--text-disabled);font-size:18px;padding:0 10px;border-right:none}.tab-btn.tab-add:active{color:#fffc}.tab-label{max-width:100px;overflow:hidden;text-overflow:ellipsis}.tab-close{display:flex;align-items:center;justify-content:center;width:16px;height:16px;margin-left:2px;border-radius:4px;font-size:14px;color:var(--text-disabled);transition:all .15s ease;position:relative;overflow:hidden}.tab-close:before{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background:var(--color-danger-bg);transform:scaleX(0);transform-origin:left;transition:transform .4s ease-out;z-index:-1}.tab-close.holding:before{transform:scaleX(1)}.tab-close.holding{color:var(--color-danger-text)}.tab-close.ready{background:var(--color-danger-bg);color:var(--color-danger-text);animation:pulseReady .3s ease}@keyframes pulseReady{0%,to{transform:scale(1)}50%{transform:scale(1.1)}}#shell-selector{margin-left:auto;display:flex;align-items:center;padding:0 12px;height:30px;border-left:1px solid var(--border-subtle)}#shell-select{background:transparent;border:none;color:#fff9;font-size:11px;padding:4px 8px;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none}#connection-dot{width:6px;height:6px;border-radius:50%;background:var(--color-danger);margin-left:12px;margin-right:8px;box-shadow:var(--glow-danger);flex-shrink:0}#connection-dot.connected{background:var(--color-success);box-shadow:var(--glow-success)}#btn-info,#btn-textview,#btn-shutdown{background:transparent;border:none;color:var(--text-disabled);font-size:14px;padding:4px;margin-left:4px;cursor:pointer;transition:color .15s ease}#btn-info:active,#btn-textview:active{color:var(--color-accent)}#btn-shutdown{color:var(--color-danger-muted)}#btn-shutdown:active{color:var(--color-danger-text)}#terminal-container{flex:1;overflow:hidden;background:var(--bg-primary);-webkit-user-select:none;user-select:none;-webkit-touch-callout:none;touch-action:none;overscroll-behavior:contain;contain:strict;isolation:isolate}#terminal{height:100%!important;width:100%!important;contain:layout paint}.terminal-instance{height:100%;width:100%;contain:layout paint}.xterm-screen canvas,.xterm canvas{transform:translateZ(0);backface-visibility:hidden}#terminal .xterm-viewport{background:var(--bg-primary)!important;touch-action:none;overscroll-behavior:contain;contain:paint}#terminal .xterm-viewport::-webkit-scrollbar{width:8px}#terminal .xterm-viewport::-webkit-scrollbar-track{background:transparent}#terminal .xterm-viewport::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);border-radius:4px}#terminal .xterm-viewport::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-hover)}#terminal .xterm-screen{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}#terminal .xterm-helper-textarea,.xterm-helper-textarea{-webkit-text-security:none!important;font-size:16px!important;-webkit-user-select:text;user-select:text}.xterm-helper-textarea::-webkit-contacts-auto-fill-button,.xterm-helper-textarea::-webkit-credentials-auto-fill-button{visibility:hidden;display:none!important;pointer-events:none;position:absolute;right:0;width:0;height:0}#toolbar{display:flex;flex-direction:column;background:linear-gradient(to bottom,var(--bg-gradient-top),var(--bg-gradient-bottom));border-top:1px solid var(--border-subtle);padding-bottom:env(safe-area-inset-bottom,0px)}.toolbar-row{display:flex;align-items:center;justify-content:center;height:30px;min-height:30px;gap:0;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.toolbar-row:first-child{border-bottom:1px solid var(--border-subtle)}.toolbar-row::-webkit-scrollbar{display:none}.tool-btn{display:flex;align-items:center;justify-content:center;height:30px;padding:0 10px;background:transparent;border:none;border-right:1px solid var(--border-subtle);border-radius:0;color:var(--text-muted);font-size:12px;cursor:pointer;transition:all .15s ease;-webkit-touch-callout:none;flex-shrink:0}.tool-btn:active{background:var(--hover-overlay);color:var(--text-high)}.tool-btn.arrow{padding:0 10px}.tool-btn.danger{color:var(--color-danger-muted)}.tool-btn.danger:active{background:var(--color-danger-bg);color:var(--color-danger-text)}.tool-btn.modifier{padding:0 10px}.tool-btn.icon{font-size:18px}.tool-btn.enter{color:#64c878cc}.tool-btn.enter:active{background:var(--color-success-bg);color:var(--color-success-text)}.tool-btn.sticky{background:var(--color-accent-bg);color:var(--color-accent-text)}.tool-btn.locked{background:var(--color-accent-strong);color:#fff;box-shadow:var(--glow-accent)}#disconnect-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:var(--overlay-bg);z-index:1000;display:flex;align-items:center;justify-content:center}#disconnect-content{text-align:center}#disconnect-icon{font-size:48px;color:var(--color-danger);margin-bottom:16px}#disconnect-text{color:var(--text-secondary);font-size:18px;margin-bottom:24px}#disconnect-retry{padding:12px 32px;background:var(--border-light);border:1px solid var(--border-medium);border-radius:8px;color:#fffc;font-size:14px;cursor:pointer;transition:all .15s ease}#disconnect-retry:active{background:#fff3;color:#fff}#copy-button{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);padding:8px 20px;background:linear-gradient(to bottom,var(--bg-surface),var(--bg-elevated));border:1px solid var(--border-light);border-radius:6px;color:var(--text-high);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:13px;font-weight:500;cursor:pointer;z-index:10000;box-shadow:var(--shadow-elevated);display:none;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none;touch-action:manipulation;transition:all .15s ease}#copy-button:active{background:linear-gradient(to bottom,#3a3a3a,var(--bg-surface));transform:translate(-50%,-50%) scale(.97)}#copy-button.visible{display:block;animation:copyButtonAppear .1s ease-out}#copy-button.success{background:linear-gradient(to bottom,#2a3a2a,#1f2f1f);border-color:#64c8784d;color:var(--color-success-text)}#copy-button.error{background:linear-gradient(to bottom,#3a2a2a,#2f1f1f);border-color:#ff78784d;color:var(--color-danger-text)}@keyframes copyButtonAppear{0%{opacity:0;transform:translate(-50%,-50%) scale(.9)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}#help-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:var(--overlay-bg);z-index:1000;display:flex;align-items:center;justify-content:center;padding:20px}#help-content{background:var(--bg-elevated);border:1px solid var(--border-light);border-radius:12px;max-width:320px;width:100%;box-shadow:var(--shadow-elevated);animation:helpAppear .15s ease-out}@keyframes helpAppear{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}#help-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border-subtle);color:var(--text-high);font-size:14px;font-weight:500}#help-close{background:transparent;border:none;color:var(--text-muted);font-size:20px;cursor:pointer;padding:4px 8px;line-height:1}#help-close:active{color:var(--text-high)}#help-body{padding:12px 16px}.help-section{margin-bottom:12px}.help-section:last-child{margin-bottom:0}.help-title{color:var(--text-muted);font-size:10px;text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px}.help-item{display:flex;align-items:center;gap:10px;padding:4px 0;color:var(--text-secondary);font-size:12px}.help-key{display:inline-block;min-width:80px;padding:2px 6px;background:var(--bg-surface);border:1px solid var(--border-subtle);border-radius:4px;color:var(--text-high);font-size:11px;text-align:center}#textview-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:var(--bg-primary);z-index:1000;display:flex;flex-direction:column;padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px)}#textview-content{display:flex;flex-direction:column;width:100%;height:100%;background:var(--bg-primary)}#textview-header{display:flex;align-items:center;height:30px;min-height:30px;background:linear-gradient(to bottom,var(--bg-gradient-top),var(--bg-gradient-bottom));border-bottom:1px solid var(--border-subtle);flex-shrink:0}#textview-title{padding:0 12px;color:var(--text-muted);font-size:12px;border-right:1px solid var(--border-subtle)}.textview-zoom-btn{display:flex;align-items:center;justify-content:center;height:30px;padding:0 12px;background:transparent;border:none;border-right:1px solid var(--border-subtle);color:var(--text-muted);font-size:14px;cursor:pointer;transition:all .15s ease}.textview-zoom-btn:active{background:var(--hover-overlay);color:var(--text-high)}#textview-close{margin-left:auto;display:flex;align-items:center;justify-content:center;height:30px;padding:0 12px;background:transparent;border:none;border-left:1px solid var(--border-subtle);color:var(--text-muted);font-size:16px;cursor:pointer;transition:all .15s ease}#textview-close:active{background:var(--hover-overlay);color:var(--text-high)}#textview-body{flex:1;min-height:0;margin:0;padding:8px 12px;background:var(--bg-primary);border:none;color:var(--text-primary);font-family:Menlo,Monaco,Consolas,monospace;font-size:10px;line-height:1.3;overflow-y:auto;white-space:pre-wrap;word-wrap:break-word;user-select:text;-webkit-user-select:text}.hidden{display:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;transition-duration:.01ms!important}}
|