dsh-zen-remote 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.
- package/AGENTS.md +51 -0
- package/LICENSE +38 -0
- package/README.md +237 -0
- package/assets/home.png +0 -0
- package/assets/info.png +0 -0
- package/assets/pairing.png +0 -0
- package/assets/session.png +0 -0
- package/assets/sheet.png +0 -0
- package/cordis.patch.yml +17 -0
- package/cordis.patch.yml.example +16 -0
- package/docs/interface.md +200 -0
- package/docs/remote-access.en.md +335 -0
- package/docs/remote-access.md +422 -0
- package/dsh-push.mjs +213 -0
- package/lan-gate.mjs +78 -0
- package/lib/client.js +6615 -0
- package/lib/index.js +310 -0
- package/lib/index.js.map +1 -0
- package/lib/lan-gate-server.cjs +626 -0
- package/lib/types/client/MobileAttachButton.d.ts +25 -0
- package/lib/types/client/MobileAttachButton.d.ts.map +1 -0
- package/lib/types/client/MobileAttachChips.d.ts +32 -0
- package/lib/types/client/MobileAttachChips.d.ts.map +1 -0
- package/lib/types/client/MobileDrawerFooter.d.ts +21 -0
- package/lib/types/client/MobileDrawerFooter.d.ts.map +1 -0
- package/lib/types/client/MobileHome.d.ts +24 -0
- package/lib/types/client/MobileHome.d.ts.map +1 -0
- package/lib/types/client/MobileHomeChips.d.ts +76 -0
- package/lib/types/client/MobileHomeChips.d.ts.map +1 -0
- package/lib/types/client/MobileNavOverlay.d.ts +15 -0
- package/lib/types/client/MobileNavOverlay.d.ts.map +1 -0
- package/lib/types/client/MobileNavToggle.d.ts +18 -0
- package/lib/types/client/MobileNavToggle.d.ts.map +1 -0
- package/lib/types/client/MobileSessionHeader.d.ts +58 -0
- package/lib/types/client/MobileSessionHeader.d.ts.map +1 -0
- package/lib/types/client/MobileSessionInfo.d.ts +41 -0
- package/lib/types/client/MobileSessionInfo.d.ts.map +1 -0
- package/lib/types/client/attach-upload.d.ts +78 -0
- package/lib/types/client/attach-upload.d.ts.map +1 -0
- package/lib/types/client/chips-store.d.ts +13 -0
- package/lib/types/client/chips-store.d.ts.map +1 -0
- package/lib/types/client/debug.d.ts +9 -0
- package/lib/types/client/debug.d.ts.map +1 -0
- package/lib/types/client/effects/aionui-compat.d.ts +4 -0
- package/lib/types/client/effects/aionui-compat.d.ts.map +1 -0
- package/lib/types/client/effects/gestures.d.ts +7 -0
- package/lib/types/client/effects/gestures.d.ts.map +1 -0
- package/lib/types/client/effects/header-status.d.ts +15 -0
- package/lib/types/client/effects/header-status.d.ts.map +1 -0
- package/lib/types/client/effects/phone-chrome.d.ts +106 -0
- package/lib/types/client/effects/phone-chrome.d.ts.map +1 -0
- package/lib/types/client/effects/turn-fold.d.ts +25 -0
- package/lib/types/client/effects/turn-fold.d.ts.map +1 -0
- package/lib/types/client/index.d.ts +18 -0
- package/lib/types/client/index.d.ts.map +1 -0
- package/lib/types/client/locales.d.ts +58 -0
- package/lib/types/client/locales.d.ts.map +1 -0
- package/lib/types/client/nav-store.d.ts +73 -0
- package/lib/types/client/nav-store.d.ts.map +1 -0
- package/lib/types/client/session-dot.d.ts +12 -0
- package/lib/types/client/session-dot.d.ts.map +1 -0
- package/lib/types/client/styles/base.css.d.ts +2 -0
- package/lib/types/client/styles/base.css.d.ts.map +1 -0
- package/lib/types/client/styles/chips.css.d.ts +2 -0
- package/lib/types/client/styles/chips.css.d.ts.map +1 -0
- package/lib/types/client/styles/compat.css.d.ts +2 -0
- package/lib/types/client/styles/compat.css.d.ts.map +1 -0
- package/lib/types/client/styles/composer.css.d.ts +2 -0
- package/lib/types/client/styles/composer.css.d.ts.map +1 -0
- package/lib/types/client/styles/header.css.d.ts +2 -0
- package/lib/types/client/styles/header.css.d.ts.map +1 -0
- package/lib/types/client/styles/home.css.d.ts +2 -0
- package/lib/types/client/styles/home.css.d.ts.map +1 -0
- package/lib/types/client/styles/index.d.ts +15 -0
- package/lib/types/client/styles/index.d.ts.map +1 -0
- package/lib/types/client/styles/info.css.d.ts +2 -0
- package/lib/types/client/styles/info.css.d.ts.map +1 -0
- package/lib/types/client/styles/layout.css.d.ts +2 -0
- package/lib/types/client/styles/layout.css.d.ts.map +1 -0
- package/lib/types/client/styles/misc.css.d.ts +2 -0
- package/lib/types/client/styles/misc.css.d.ts.map +1 -0
- package/lib/types/client/styles/turn-fold.css.d.ts +2 -0
- package/lib/types/client/styles/turn-fold.css.d.ts.map +1 -0
- package/lib/types/index.d.ts +83 -0
- package/lib/types/index.d.ts.map +1 -0
- package/llms.txt +20 -0
- package/package.json +128 -0
- package/pwa/app.css +95 -0
- package/pwa/icons/icon-192.png +0 -0
- package/pwa/icons/icon-512.png +0 -0
- package/pwa/icons/icon-maskable-512.png +0 -0
- package/pwa/icons/icon-maskable.svg +1 -0
- package/pwa/icons/icon.svg +1 -0
- package/pwa/inject.js +190 -0
- package/pwa/manifest.json +29 -0
- package/pwa/offline.html +38 -0
- package/pwa/sw.js +176 -0
- package/pwa/touch-gestures.js +94 -0
- package/scripts/build-client.mjs +101 -0
- package/scripts/cdp-probe.mjs +64 -0
- package/scripts/check-attach-upload.mjs +99 -0
- package/scripts/check-sunk-viewport.mjs +33 -0
- package/scripts/check-upload-endpoint.mjs +168 -0
- package/src/client/MobileAttachButton.tsx +125 -0
- package/src/client/MobileAttachChips.tsx +85 -0
- package/src/client/MobileDrawerFooter.tsx +56 -0
- package/src/client/MobileHome.tsx +348 -0
- package/src/client/MobileHomeChips.tsx +426 -0
- package/src/client/MobileNavOverlay.tsx +279 -0
- package/src/client/MobileNavToggle.tsx +52 -0
- package/src/client/MobileSessionHeader.tsx +242 -0
- package/src/client/MobileSessionInfo.tsx +303 -0
- package/src/client/attach-upload.ts +140 -0
- package/src/client/chips-store.ts +41 -0
- package/src/client/debug.ts +253 -0
- package/src/client/effects/aionui-compat.ts +183 -0
- package/src/client/effects/gestures.ts +265 -0
- package/src/client/effects/header-status.ts +30 -0
- package/src/client/effects/phone-chrome.ts +265 -0
- package/src/client/effects/turn-fold.ts +258 -0
- package/src/client/index.tsx +227 -0
- package/src/client/locales.ts +109 -0
- package/src/client/nav-store.ts +78 -0
- package/src/client/session-dot.ts +17 -0
- package/src/client/styles/base.css.ts +167 -0
- package/src/client/styles/chips.css.ts +224 -0
- package/src/client/styles/compat.css.ts +681 -0
- package/src/client/styles/composer.css.ts +504 -0
- package/src/client/styles/header.css.ts +368 -0
- package/src/client/styles/home.css.ts +477 -0
- package/src/client/styles/index.ts +25 -0
- package/src/client/styles/info.css.ts +238 -0
- package/src/client/styles/layout.css.ts +501 -0
- package/src/client/styles/misc.css.ts +128 -0
- package/src/client/styles/turn-fold.css.ts +106 -0
- package/src/index.ts +343 -0
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
// header — session-page header five-piece reflow (S2, 2026-08-17). Scoped
|
|
2
|
+
// entirely to (max-width: 767px) and appended LAST (after home.css.ts) so
|
|
3
|
+
// its rules win ties against the shared <=1023px block in layout.css.ts —
|
|
4
|
+
// same reasoning as home.css.ts: 768-1023px keeps the v1.0.0 drawer header
|
|
5
|
+
// untouched, >=1024px is a strict no-op.
|
|
6
|
+
//
|
|
7
|
+
// DOM this reflows (dsh-client-ui-conversation lib/client.js:6949-7009,
|
|
8
|
+
// verified live 2026-08-17 at 375px — class names below are the CURRENT
|
|
9
|
+
// hashed values, always targeted by suffix):
|
|
10
|
+
// header ConversationSessionHeader root
|
|
11
|
+
// div.titleRow
|
|
12
|
+
// div.titleCluster (official: a flex cluster; we flatten it)
|
|
13
|
+
// nav.crumbs breadcrumb chain, last segment = the title
|
|
14
|
+
// div.headerActions [data-slot="conversation.session.header.actions"]
|
|
15
|
+
// div.headerUtilities [data-slot="conversation.session.header.utilities"]
|
|
16
|
+
// div.tabs[role="tablist"] Chat/Trajectory, only when there is >1 view
|
|
17
|
+
|
|
18
|
+
export const HEADER_CSS = `/* ---------- session header five-piece reflow (< 768px) ---------- */
|
|
19
|
+
|
|
20
|
+
/* New elements render unconditionally (React does not know about media
|
|
21
|
+
queries); default them to hidden so 768px+ never sees them, then
|
|
22
|
+
re-enable inside the phone block below. Belt-and-braces alongside the
|
|
23
|
+
scoped rules — mirrors the existing [data-mobile-nav="*"] desktop no-op
|
|
24
|
+
list in misc.css.ts. */
|
|
25
|
+
[data-mobile-nav="header-back"],
|
|
26
|
+
[data-mobile-nav="header-viewrow"],
|
|
27
|
+
[data-mobile-nav="header-info"],
|
|
28
|
+
[data-mobile-nav="header-workbench"],
|
|
29
|
+
/* The workbench close pill's default-hidden used to live in compat.css.ts —
|
|
30
|
+
but EVERYTHING in layout/compat/misc sits inside one shared
|
|
31
|
+
(max-width: 1023px) block (opened at the top of layout, closed at the end
|
|
32
|
+
of misc), so that "top-level" rule silently never applied at >=1024 and
|
|
33
|
+
the pill rendered as an unstyled button on desktop (2026-08-17 report).
|
|
34
|
+
This file is appended after the shared block closes, so here it is truly
|
|
35
|
+
global; the <=767px :has() show rule in compat overrides it with
|
|
36
|
+
!important. */
|
|
37
|
+
[data-mobile-nav="better-sidebar-close"] {
|
|
38
|
+
display: none;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@media (max-width: 767px) {
|
|
42
|
+
/* The Files action targeted the dsh-web-ui-all (aionui) explorer sheet —
|
|
43
|
+
a different, unrelated suite from the workbench entry this slice adds
|
|
44
|
+
(dsh-better-sidebar). Hidden here only; 768-1023px keeps it exactly as
|
|
45
|
+
v1.0.0 shipped it. */
|
|
46
|
+
[data-mobile-nav="files"] {
|
|
47
|
+
display: none !important;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* --- three-column header: [back 92px] [title, truly centered] [utilities 92px] --- */
|
|
51
|
+
/* The bottom padding is the view-switch row's seat: that row is
|
|
52
|
+
position:absolute (see the bottom of this file — it renders two levels
|
|
53
|
+
deep inside headerActions and can never be a grid item of titleRow), so
|
|
54
|
+
without a reserve it would hang over the message list. 28px = its
|
|
55
|
+
height. Unconditional rather than header:has([data-mobile-nav=
|
|
56
|
+
"header-viewrow"]) on purpose: :has() is silently dropped by pre-105
|
|
57
|
+
WebViews (see AGENTS.md) and a 28px overlap on the first message is a
|
|
58
|
+
worse failure than 28px of empty band in the (never observed in
|
|
59
|
+
practice) single-view session. Total header chrome: 48 + 28 = 76px.
|
|
60
|
+
Left/right 8px (S2.1 report leftover, fixed in S4): the official header
|
|
61
|
+
had zero horizontal padding, so the utilities button cluster's right
|
|
62
|
+
edge sat flush against the screen edge (x=390 at 390px width, no
|
|
63
|
+
margin). The 92px grid columns absorb this fine — they're fixed track
|
|
64
|
+
widths, only the center 1fr column shrinks by 16px. */
|
|
65
|
+
[data-phase] header {
|
|
66
|
+
position: relative;
|
|
67
|
+
padding: 0 8px 28px !important;
|
|
68
|
+
}
|
|
69
|
+
/* No header bottom line — fade instead (real-device round 2, 2026-08-17).
|
|
70
|
+
The official header draws its border as a \`::after\` 1px bar (the
|
|
71
|
+
\`border-bottom\` on the header itself is transparent, just a layout
|
|
72
|
+
reserve — dsh-client-ui-conversation lib/client.js ".wSkVaW_header{
|
|
73
|
+
border-bottom:1px solid #0000}.wSkVaW_header:after{...height:1px;
|
|
74
|
+
position:absolute;bottom:1px...}", verified live 2026-08-17), so
|
|
75
|
+
hiding the pseudo-element is enough; the header's own border-bottom
|
|
76
|
+
never had a visible color to begin with. The message scroller now
|
|
77
|
+
fades in from under the header instead (styles/composer.css.ts, "no
|
|
78
|
+
divider above OR below the message list" — the two edges share one
|
|
79
|
+
mask-image on [class$="_scrollBody"]). */
|
|
80
|
+
[data-phase] header::after {
|
|
81
|
+
display: none !important;
|
|
82
|
+
}
|
|
83
|
+
/* grid-row: 1 on every item is load-bearing, not decoration (S2.1 fix for
|
|
84
|
+
the "标题被挤下去" report). The three items are placed with explicit
|
|
85
|
+
grid-column but arrive in DOM order crumbs(2) → headerActions(1) →
|
|
86
|
+
headerUtilities(3): sparse auto-placement never moves its cursor
|
|
87
|
+
backwards, so headerActions and headerUtilities were pushed onto an
|
|
88
|
+
implicit SECOND row. Measured at 390px: row1 = crumbs 28px, row2 =
|
|
89
|
+
back button 44px, titleRow = 72px with the title stuck at the top
|
|
90
|
+
instead of centered. Pinning the row makes it one 48px band again. */
|
|
91
|
+
[data-phase] header [class$="_titleRow"] {
|
|
92
|
+
position: relative;
|
|
93
|
+
display: grid;
|
|
94
|
+
grid-template-columns: 92px 1fr 92px;
|
|
95
|
+
grid-template-rows: minmax(48px, auto);
|
|
96
|
+
align-items: center;
|
|
97
|
+
min-height: 48px;
|
|
98
|
+
padding: 0 !important;
|
|
99
|
+
}
|
|
100
|
+
/* Flatten the official cluster so its two children (crumbs, headerActions)
|
|
101
|
+
become direct grid items of titleRow instead of a nested flex box. */
|
|
102
|
+
[data-phase] header [class$="_titleCluster"] {
|
|
103
|
+
display: contents;
|
|
104
|
+
}
|
|
105
|
+
/* margin-left: 0 cancels layout.css.ts's shared <=1023px
|
|
106
|
+
"margin-left: auto !important" on this exact selector (it pushed the
|
|
107
|
+
Files button to the row's right edge in the old non-grid header;
|
|
108
|
+
inside our grid column it instead shoves the back button 48px right of
|
|
109
|
+
the column's start — the auto margin absorbs the leftover space
|
|
110
|
+
between the button's content width and the 92px column). */
|
|
111
|
+
[data-phase] header [class$="_headerActions"] {
|
|
112
|
+
grid-column: 1;
|
|
113
|
+
grid-row: 1;
|
|
114
|
+
justify-self: start;
|
|
115
|
+
margin-left: 0 !important;
|
|
116
|
+
display: flex;
|
|
117
|
+
align-items: center;
|
|
118
|
+
min-width: 0;
|
|
119
|
+
}
|
|
120
|
+
/* layout.css.ts's shared <=1023px block hides this element outright
|
|
121
|
+
(header > :first-child > :last-child { display: none !important },
|
|
122
|
+
specificity (0,3,1) — v1.0.0 relocated the desktop Session-log capsule
|
|
123
|
+
to the drawer footer on every narrow width). That selector is repeated
|
|
124
|
+
here at equal specificity so the later source order wins the display
|
|
125
|
+
property; the class-suffix selector alone (0,2,1) would silently lose. */
|
|
126
|
+
[data-phase] header [class$="_headerUtilities"],
|
|
127
|
+
[data-phase] header > :first-child > :last-child {
|
|
128
|
+
grid-column: 3;
|
|
129
|
+
grid-row: 1;
|
|
130
|
+
justify-self: end;
|
|
131
|
+
display: flex !important;
|
|
132
|
+
align-items: center;
|
|
133
|
+
gap: 4px;
|
|
134
|
+
min-width: 0;
|
|
135
|
+
}
|
|
136
|
+
/* justify-self: stretch (the grid default) so this fills the whole 1fr
|
|
137
|
+
column as a definite-width box — center/center-content happens inside
|
|
138
|
+
it. justify-self: center (tried first) sizes the item to its content
|
|
139
|
+
with no automatic column cap, and the obvious fix — max-width: 100% —
|
|
140
|
+
resolves against the WRONG box here (measured 93.6px at 390px, where
|
|
141
|
+
the column is ~206px): the item's DOM parent (titleCluster) is
|
|
142
|
+
display:contents, and percentage max-width does not reliably resolve
|
|
143
|
+
through a boxless ancestor to the grid track. Stretching sidesteps the
|
|
144
|
+
percentage entirely — but layout.css.ts's shared <=1023px block ALSO
|
|
145
|
+
caps this exact selector at max-width: 24vw !important (93.6px at
|
|
146
|
+
390px — the value this rule used to silently inherit once its own
|
|
147
|
+
max-width was dropped in favor of stretch), so that must be reset to
|
|
148
|
+
none here too. */
|
|
149
|
+
[data-phase] header [class$="_crumbs"] {
|
|
150
|
+
grid-column: 2;
|
|
151
|
+
grid-row: 1;
|
|
152
|
+
justify-self: stretch;
|
|
153
|
+
max-width: none !important;
|
|
154
|
+
display: flex;
|
|
155
|
+
align-items: center;
|
|
156
|
+
justify-content: center;
|
|
157
|
+
min-width: 0;
|
|
158
|
+
overflow: hidden;
|
|
159
|
+
}
|
|
160
|
+
/* Only the current session's own name is the "title" — the parent chain
|
|
161
|
+
(subagent breadcrumbs) is the "多余项" the design calls out to hide,
|
|
162
|
+
while the current segment (and its running dot, see below) stays. */
|
|
163
|
+
[data-phase] header [class$="_crumbSeg"]:not(:last-child) {
|
|
164
|
+
display: none !important;
|
|
165
|
+
}
|
|
166
|
+
[data-phase] header [class$="_crumbSeg"]:last-child {
|
|
167
|
+
display: flex;
|
|
168
|
+
align-items: center;
|
|
169
|
+
min-width: 0;
|
|
170
|
+
max-width: 100%;
|
|
171
|
+
}
|
|
172
|
+
[data-phase] header [class$="_crumbSeg"]:last-child [class$="_crumbSep"] {
|
|
173
|
+
display: none !important;
|
|
174
|
+
}
|
|
175
|
+
/* BOTH selectors are required: [class$=] matches the whole class
|
|
176
|
+
ATTRIBUTE's suffix, and the current-session title button's attribute is
|
|
177
|
+
"wSkVaW_crumb wSkVaW_crumbCurrent" — it ends in _crumbCurrent, so the _crumb
|
|
178
|
+
suffix selector alone silently missed the one element that matters
|
|
179
|
+
(measured live: the title stayed 14px while the rule sat in the bundle,
|
|
180
|
+
2026-08-17). */
|
|
181
|
+
[data-phase] header [class$="_crumb"],
|
|
182
|
+
[data-phase] header [class$="_crumbCurrent"] {
|
|
183
|
+
overflow: hidden;
|
|
184
|
+
text-overflow: ellipsis;
|
|
185
|
+
white-space: nowrap;
|
|
186
|
+
min-width: 0;
|
|
187
|
+
max-width: 100%;
|
|
188
|
+
/* Real-device feedback (2026-08-17): the session title read too small
|
|
189
|
+
next to the enlarged header icons — 19px sits just under the home
|
|
190
|
+
screen's 22px workspace title, keeping the two-level hierarchy. */
|
|
191
|
+
font-size: 19px;
|
|
192
|
+
font-weight: 600;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/* Running-status dot: no official element to reposition (the header
|
|
196
|
+
renders only the crumb title, the two action slots, and the tablist —
|
|
197
|
+
no status indicator), so this is the plan's documented fallback —
|
|
198
|
+
read the data ourselves and draw it (effects/header-status.ts stamps
|
|
199
|
+
data-mobile-nav-dot on the frame). A ::after on the title crumb keeps
|
|
200
|
+
it truly inline with the (centered, truncated) text instead of a
|
|
201
|
+
separately positioned box that would fight the centering math. */
|
|
202
|
+
[data-phase] header [class$="_crumbCurrent"]::after {
|
|
203
|
+
content: '';
|
|
204
|
+
display: none;
|
|
205
|
+
width: 6px;
|
|
206
|
+
height: 6px;
|
|
207
|
+
margin-left: 6px;
|
|
208
|
+
border-radius: 50%;
|
|
209
|
+
vertical-align: middle;
|
|
210
|
+
}
|
|
211
|
+
[data-mobile-nav="frame"][data-mobile-nav-dot] header [class$="_crumbCurrent"]::after {
|
|
212
|
+
display: inline-block;
|
|
213
|
+
}
|
|
214
|
+
[data-mobile-nav="frame"][data-mobile-nav-dot="ongoing"] header [class$="_crumbCurrent"]::after {
|
|
215
|
+
background: var(--dsw-alias-state-business-primary, #4f6ef7);
|
|
216
|
+
}
|
|
217
|
+
[data-mobile-nav="frame"][data-mobile-nav-dot="warning"] header [class$="_crumbCurrent"]::after {
|
|
218
|
+
background: var(--dsw-alias-state-warn-primary, #d97706);
|
|
219
|
+
}
|
|
220
|
+
[data-mobile-nav="frame"][data-mobile-nav-dot="done"] header [class$="_crumbCurrent"]::after {
|
|
221
|
+
background: var(--dsw-alias-state-success-primary, #16a34a);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* Everything else the official header puts in these two list slots — the
|
|
225
|
+
agent-preset mode badge, the jobs/subagent trigger, the desktop
|
|
226
|
+
Session-log download capsule, and this plugin's own legacy directory
|
|
227
|
+
toggle — is the "不常驻" set the design defers to the S4 info card.
|
|
228
|
+
Scoped by the slots' own [data-slot] wrapper (a stable, non-hashed
|
|
229
|
+
contract marker) rather than enumerating each registrant, so a future
|
|
230
|
+
third-party header action is hidden by default too. */
|
|
231
|
+
[data-phase] header [data-slot="conversation.session.header.actions"] > *,
|
|
232
|
+
[data-phase] header [data-slot="conversation.session.header.utilities"] > * {
|
|
233
|
+
display: none !important;
|
|
234
|
+
}
|
|
235
|
+
/* The agent-preset mode badge specifically survives the blanket hide
|
|
236
|
+
above: layout.css.ts's shared <=1023px block targets it directly
|
|
237
|
+
(header [class$="_label"]:has(> svg) { display: block !important }),
|
|
238
|
+
specificity (0,3,1), higher than the [data-slot] wrapper rule (0,2,1) —
|
|
239
|
+
display wins on specificity before source order, so a same-selector
|
|
240
|
+
override is needed here too. */
|
|
241
|
+
[data-phase] header [class$="_label"]:has(> svg) {
|
|
242
|
+
display: none !important;
|
|
243
|
+
}
|
|
244
|
+
[data-phase] header [data-slot="conversation.session.header.actions"] > [data-mobile-nav="header-back"] {
|
|
245
|
+
display: inline-flex !important;
|
|
246
|
+
}
|
|
247
|
+
/* header-viewrow is position:absolute (see below), so its re-shown
|
|
248
|
+
display value must match the flex layout its own rule declares. */
|
|
249
|
+
[data-phase] header [data-slot="conversation.session.header.actions"] > [data-mobile-nav="header-viewrow"] {
|
|
250
|
+
display: flex !important;
|
|
251
|
+
}
|
|
252
|
+
[data-phase] header [data-slot="conversation.session.header.utilities"] > [data-mobile-nav="header-info"],
|
|
253
|
+
[data-phase] header [data-slot="conversation.session.header.utilities"] > [data-mobile-nav="header-workbench"] {
|
|
254
|
+
display: inline-flex !important;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/* Back button: 44pt touch target, leftmost column. */
|
|
258
|
+
[data-mobile-nav="header-back"] {
|
|
259
|
+
display: inline-flex;
|
|
260
|
+
align-items: center;
|
|
261
|
+
justify-content: center;
|
|
262
|
+
width: 44px;
|
|
263
|
+
height: 44px;
|
|
264
|
+
padding: 0;
|
|
265
|
+
border: none;
|
|
266
|
+
background: transparent;
|
|
267
|
+
color: var(--dsw-alias-label-primary, inherit);
|
|
268
|
+
cursor: pointer;
|
|
269
|
+
touch-action: manipulation;
|
|
270
|
+
-webkit-tap-highlight-color: transparent;
|
|
271
|
+
}
|
|
272
|
+
[data-mobile-nav="header-back"]:active {
|
|
273
|
+
opacity: .6;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/* Info + workbench utility buttons, rightmost column. */
|
|
277
|
+
[data-mobile-nav="header-info"],
|
|
278
|
+
[data-mobile-nav="header-workbench"] {
|
|
279
|
+
display: inline-flex;
|
|
280
|
+
align-items: center;
|
|
281
|
+
justify-content: center;
|
|
282
|
+
width: 34px;
|
|
283
|
+
height: 34px;
|
|
284
|
+
padding: 0;
|
|
285
|
+
border: none;
|
|
286
|
+
border-radius: 50%;
|
|
287
|
+
background: transparent;
|
|
288
|
+
color: var(--dsw-alias-label-secondary, inherit);
|
|
289
|
+
cursor: pointer;
|
|
290
|
+
touch-action: manipulation;
|
|
291
|
+
-webkit-tap-highlight-color: transparent;
|
|
292
|
+
}
|
|
293
|
+
[data-mobile-nav="header-info"]:active,
|
|
294
|
+
[data-mobile-nav="header-workbench"]:active {
|
|
295
|
+
background: var(--dsw-alias-interactive-bg-hover, rgba(0, 0, 0, .06));
|
|
296
|
+
}
|
|
297
|
+
/* Icon family unification (real-device round 2, 2026-08-17): the ⓘ text
|
|
298
|
+
glyph is gone (MobileSessionHeader.tsx now renders IconInfoOutline16,
|
|
299
|
+
a local 16px SVG built to match the primitives icon family) and the
|
|
300
|
+
workbench button's IconPanelLeftOutline16 is mirrored into a
|
|
301
|
+
panel-RIGHT glyph — there's no IconPanelRightOutline16 in primitives
|
|
302
|
+
(checked lib/types/icons/index.d.ts), and the plugin's own right-side
|
|
303
|
+
panel semantics are exactly the left icon flipped. Both buttons now
|
|
304
|
+
carry a same-size (16px), same-stroke-weight icon. */
|
|
305
|
+
[data-mobile-nav="header-workbench"] svg {
|
|
306
|
+
transform: scaleX(-1);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/* Official Chat/Trajectory tablist: removed from layout entirely (S2.1 —
|
|
310
|
+
visibility:hidden still held a 27px row, so the header carried the
|
|
311
|
+
view-switch row's band TWICE: 72 + 27 + gap = 104px measured at 390px,
|
|
312
|
+
and a real iPhone added ~54px of notch on top of that). The header's own
|
|
313
|
+
padding-bottom above is now the row's seat.
|
|
314
|
+
display:none does NOT break the view switch: HTMLElement.click()
|
|
315
|
+
dispatches synthetically and fires React's handler regardless of
|
|
316
|
+
rendering — only real pointer hit-testing needs a box, and this plugin
|
|
317
|
+
never relies on it (MobileSessionHeader always calls .click()). */
|
|
318
|
+
[data-phase] header [class$="_tabs"][role="tablist"] {
|
|
319
|
+
display: none;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/* View-switch row: "current view name + dots", replacing the (still
|
|
323
|
+
present, still clickable) official tablist visually. It renders inside
|
|
324
|
+
headerActions/headerUtilities, but titleRow's own position:relative
|
|
325
|
+
(set above) makes IT the containing block for absolute descendants —
|
|
326
|
+
display:contents on titleCluster does not break that search — so
|
|
327
|
+
top:100% sits directly under the title regardless of the title row's
|
|
328
|
+
actual height, with no hardcoded offset to keep in sync. */
|
|
329
|
+
[data-mobile-nav="header-viewrow"] {
|
|
330
|
+
position: absolute;
|
|
331
|
+
left: 0;
|
|
332
|
+
right: 0;
|
|
333
|
+
top: 100%;
|
|
334
|
+
display: flex;
|
|
335
|
+
align-items: center;
|
|
336
|
+
justify-content: center;
|
|
337
|
+
gap: 6px;
|
|
338
|
+
height: 28px;
|
|
339
|
+
padding: 0;
|
|
340
|
+
border: none;
|
|
341
|
+
background: transparent;
|
|
342
|
+
color: var(--dsw-alias-label-secondary, rgba(0, 0, 0, .5));
|
|
343
|
+
font-family: inherit;
|
|
344
|
+
font-size: 13px;
|
|
345
|
+
line-height: 18px;
|
|
346
|
+
cursor: pointer;
|
|
347
|
+
touch-action: manipulation;
|
|
348
|
+
-webkit-tap-highlight-color: transparent;
|
|
349
|
+
}
|
|
350
|
+
[data-mobile-nav="header-viewrow-dots"] {
|
|
351
|
+
display: inline-flex;
|
|
352
|
+
align-items: center;
|
|
353
|
+
gap: 3px;
|
|
354
|
+
}
|
|
355
|
+
[data-mobile-nav="header-viewrow-dots"] > i {
|
|
356
|
+
display: block;
|
|
357
|
+
width: 4px;
|
|
358
|
+
height: 4px;
|
|
359
|
+
border-radius: 50%;
|
|
360
|
+
background: currentColor;
|
|
361
|
+
opacity: .35;
|
|
362
|
+
font-style: normal;
|
|
363
|
+
}
|
|
364
|
+
[data-mobile-nav="header-viewrow-dots"] > i[data-active] {
|
|
365
|
+
opacity: 1;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
`
|