@chatcode/cco-better-sidebar 0.18.0-alpha.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/LICENSE +21 -0
- package/README.md +554 -0
- package/README_EN.md +563 -0
- package/assets/logo.svg +1 -0
- package/cordis.patch.yml +79 -0
- package/lib/client-editor.js +55744 -0
- package/lib/client-mermaid.js +208256 -0
- package/lib/client-registry.js +30378 -0
- package/lib/client-terminal.js +16894 -0
- package/lib/client.js +30378 -0
- package/lib/index.js +6897 -0
- package/lib/invariant.js +22 -0
- package/lib/types/agent-opens.d.ts +65 -0
- package/lib/types/agent-pty.d.ts +226 -0
- package/lib/types/browser-probe.d.ts +15 -0
- package/lib/types/bundle-route.d.ts +12 -0
- package/lib/types/chatcode-update.d.ts +47 -0
- package/lib/types/client/AccountMenu.d.ts +1 -0
- package/lib/types/client/AiRatioSection.d.ts +3 -0
- package/lib/types/client/BrowserView.d.ts +39 -0
- package/lib/types/client/ChatcodeGate.d.ts +6 -0
- package/lib/types/client/CodingPlanModelsSettings.d.ts +9 -0
- package/lib/types/client/DiffTab.d.ts +6 -0
- package/lib/types/client/DiffView.d.ts +51 -0
- package/lib/types/client/EditorHost.d.ts +13 -0
- package/lib/types/client/FenceErrorNotice.d.ts +5 -0
- package/lib/types/client/FileTree.d.ts +41 -0
- package/lib/types/client/FreeWindow.d.ts +29 -0
- package/lib/types/client/GitView.d.ts +12 -0
- package/lib/types/client/MarkdownHtml.d.ts +32 -0
- package/lib/types/client/OrphanedTab.d.ts +11 -0
- package/lib/types/client/PdfView.d.ts +6 -0
- package/lib/types/client/ReleaseNotesDialog.d.ts +11 -0
- package/lib/types/client/RenderBoundary.d.ts +32 -0
- package/lib/types/client/SandboxStatusBar.d.ts +10 -0
- package/lib/types/client/SideCardSection.d.ts +74 -0
- package/lib/types/client/Sidebar.d.ts +8 -0
- package/lib/types/client/TabBar.d.ts +54 -0
- package/lib/types/client/TerminalView.d.ts +24 -0
- package/lib/types/client/TextEditor.d.ts +10 -0
- package/lib/types/client/TreePanel.d.ts +27 -0
- package/lib/types/client/UpdateDialog.d.ts +10 -0
- package/lib/types/client/UpdateSettingsPanel.d.ts +1 -0
- package/lib/types/client/UpdateSettingsSection.d.ts +10 -0
- package/lib/types/client/UploadOverlay.d.ts +20 -0
- package/lib/types/client/UsageHeatmapSection.d.ts +4 -0
- package/lib/types/client/add-plugin-modal.d.ts +15 -0
- package/lib/types/client/api.d.ts +345 -0
- package/lib/types/client/binary-download.d.ts +12 -0
- package/lib/types/client/breakpoints.d.ts +17 -0
- package/lib/types/client/browser.d.ts +60 -0
- package/lib/types/client/builtins/index.d.ts +18 -0
- package/lib/types/client/builtins/tabs.d.ts +11 -0
- package/lib/types/client/builtins/viewers.d.ts +3 -0
- package/lib/types/client/chat-presentation.d.ts +13 -0
- package/lib/types/client/chunk-loader.d.ts +124 -0
- package/lib/types/client/chunks/editor.d.ts +9 -0
- package/lib/types/client/chunks/mermaid.d.ts +10 -0
- package/lib/types/client/chunks/terminal.d.ts +9 -0
- package/lib/types/client/cm-themes.d.ts +24 -0
- package/lib/types/client/conversation-draft.d.ts +14 -0
- package/lib/types/client/desktop-env.d.ts +35 -0
- package/lib/types/client/editor-load.d.ts +66 -0
- package/lib/types/client/frame-batcher.d.ts +24 -0
- package/lib/types/client/icons.d.ts +66 -0
- package/lib/types/client/image-types.d.ts +3 -0
- package/lib/types/client/ime-guard.d.ts +36 -0
- package/lib/types/client/index.d.ts +19 -0
- package/lib/types/client/intercept.d.ts +44 -0
- package/lib/types/client/lang.d.ts +14 -0
- package/lib/types/client/layout-push.d.ts +15 -0
- package/lib/types/client/lazy-chunk.d.ts +25 -0
- package/lib/types/client/link-intercept.d.ts +42 -0
- package/lib/types/client/locales-ar.d.ts +18 -0
- package/lib/types/client/locales-de.d.ts +4 -0
- package/lib/types/client/locales-fr.d.ts +10 -0
- package/lib/types/client/locales-hi.d.ts +17 -0
- package/lib/types/client/locales-id.d.ts +15 -0
- package/lib/types/client/locales-it.d.ts +8 -0
- package/lib/types/client/locales-ja.d.ts +17 -0
- package/lib/types/client/locales-ko.d.ts +9 -0
- package/lib/types/client/locales-nl.d.ts +16 -0
- package/lib/types/client/locales-pl.d.ts +19 -0
- package/lib/types/client/locales-pt.d.ts +1 -0
- package/lib/types/client/locales-ru.d.ts +13 -0
- package/lib/types/client/locales-sv.d.ts +1 -0
- package/lib/types/client/locales-th.d.ts +17 -0
- package/lib/types/client/locales-tr.d.ts +17 -0
- package/lib/types/client/locales-vi.d.ts +17 -0
- package/lib/types/client/locales-zh-HK.d.ts +32 -0
- package/lib/types/client/locales-zh-MO.d.ts +32 -0
- package/lib/types/client/locales-zh-TW.d.ts +32 -0
- package/lib/types/client/locales.d.ts +571 -0
- package/lib/types/client/markdown-html.d.ts +96 -0
- package/lib/types/client/markdown-images.d.ts +45 -0
- package/lib/types/client/markdown-labels.d.ts +21 -0
- package/lib/types/client/md-toc.d.ts +4 -0
- package/lib/types/client/mermaid-blocks.d.ts +47 -0
- package/lib/types/client/mermaid-sanitize.d.ts +2 -0
- package/lib/types/client/mermaid.d.ts +12 -0
- package/lib/types/client/open-when-sized.d.ts +20 -0
- package/lib/types/client/open-with-settings.d.ts +4 -0
- package/lib/types/client/open-with.d.ts +87 -0
- package/lib/types/client/openpath-intercept.d.ts +52 -0
- package/lib/types/client/paths.d.ts +43 -0
- package/lib/types/client/pdf-types.d.ts +2 -0
- package/lib/types/client/pinned.d.ts +86 -0
- package/lib/types/client/plugin-settings.d.ts +8 -0
- package/lib/types/client/plugins-shared.d.ts +27 -0
- package/lib/types/client/plugins-tabs.d.ts +3 -0
- package/lib/types/client/plugins-viewers.d.ts +3 -0
- package/lib/types/client/prefs.d.ts +41 -0
- package/lib/types/client/produced-files.d.ts +29 -0
- package/lib/types/client/selection-payload.d.ts +27 -0
- package/lib/types/client/service.d.ts +445 -0
- package/lib/types/client/session-pins.d.ts +14 -0
- package/lib/types/client/settings-nav-icon.d.ts +27 -0
- package/lib/types/client/shell-presets.d.ts +48 -0
- package/lib/types/client/split-pane.d.ts +38 -0
- package/lib/types/client/state.d.ts +480 -0
- package/lib/types/client/tab-content-memo.d.ts +40 -0
- package/lib/types/client/terminal-font.d.ts +78 -0
- package/lib/types/client/terminal-links.d.ts +119 -0
- package/lib/types/client/theme.d.ts +45 -0
- package/lib/types/client/titlebar-strip.d.ts +23 -0
- package/lib/types/client/ui-tweaks/appicons.d.ts +16 -0
- package/lib/types/client/ui-tweaks/archive.d.ts +42 -0
- package/lib/types/client/ui-tweaks/branding.d.ts +45 -0
- package/lib/types/client/ui-tweaks/cachehit.d.ts +41 -0
- package/lib/types/client/ui-tweaks/gitbar.d.ts +103 -0
- package/lib/types/client/ui-tweaks/index.d.ts +279 -0
- package/lib/types/client/ui-tweaks/mcp.d.ts +28 -0
- package/lib/types/client/ui-tweaks/notifier.d.ts +125 -0
- package/lib/types/client/ui-tweaks/whale.d.ts +55 -0
- package/lib/types/client/upload.d.ts +69 -0
- package/lib/types/client/useChatcodeAccount.d.ts +10 -0
- package/lib/types/client/wco.d.ts +47 -0
- package/lib/types/codingplan.d.ts +37 -0
- package/lib/types/config.d.ts +95 -0
- package/lib/types/context-types.d.ts +540 -0
- package/lib/types/fs-operations.d.ts +30 -0
- package/lib/types/fs-search.d.ts +24 -0
- package/lib/types/fs-tree.d.ts +51 -0
- package/lib/types/git.d.ts +124 -0
- package/lib/types/html-route.d.ts +59 -0
- package/lib/types/index.d.ts +47 -0
- package/lib/types/invariant.d.ts +15 -0
- package/lib/types/login-route.d.ts +2 -0
- package/lib/types/open-external.d.ts +24 -0
- package/lib/types/path-security.d.ts +26 -0
- package/lib/types/prefs-shared.d.ts +257 -0
- package/lib/types/pty-deps.d.ts +79 -0
- package/lib/types/pty-manager.d.ts +168 -0
- package/lib/types/tools.d.ts +34 -0
- package/lib/types/trust-fence.d.ts +24 -0
- package/lib/types/ui-tweaks/archive.d.ts +71 -0
- package/lib/types/ui-tweaks/config.d.ts +186 -0
- package/lib/types/ui-tweaks/git-web.d.ts +43 -0
- package/lib/types/ui-tweaks/git.d.ts +311 -0
- package/lib/types/ui-tweaks/index.d.ts +17 -0
- package/lib/types/ui-tweaks/mcp.d.ts +103 -0
- package/lib/types/ui-tweaks/turn-outcome.d.ts +57 -0
- package/lib/types/ui-tweaks/web.d.ts +55 -0
- package/lib/types/wire.d.ts +38 -0
- package/package.json +213 -0
- package/scripts/install.ps1 +310 -0
- package/scripts/install.sh +287 -0
- package/src/agent-opens.ts +265 -0
- package/src/agent-pty.ts +527 -0
- package/src/browser-probe.ts +26 -0
- package/src/bundle-route.ts +129 -0
- package/src/chatcode-update.ts +193 -0
- package/src/client/AccountMenu.tsx +177 -0
- package/src/client/AiRatioSection.module.css +329 -0
- package/src/client/AiRatioSection.tsx +292 -0
- package/src/client/BrowserView.tsx +289 -0
- package/src/client/ChatcodeGate.tsx +35 -0
- package/src/client/CodingPlanModelsSettings.module.css +118 -0
- package/src/client/CodingPlanModelsSettings.tsx +101 -0
- package/src/client/DiffTab.tsx +114 -0
- package/src/client/DiffView.tsx +305 -0
- package/src/client/EditorHost.tsx +563 -0
- package/src/client/FenceErrorNotice.tsx +40 -0
- package/src/client/FileTree.tsx +701 -0
- package/src/client/FreeWindow.tsx +337 -0
- package/src/client/GitView.tsx +722 -0
- package/src/client/MarkdownHtml.tsx +296 -0
- package/src/client/OrphanedTab.tsx +27 -0
- package/src/client/PdfView.tsx +110 -0
- package/src/client/ReleaseNotesDialog.tsx +91 -0
- package/src/client/RenderBoundary.tsx +49 -0
- package/src/client/SandboxStatusBar.tsx +60 -0
- package/src/client/SideCardSection.module.css +932 -0
- package/src/client/SideCardSection.tsx +1169 -0
- package/src/client/Sidebar.tsx +1857 -0
- package/src/client/TabBar.tsx +365 -0
- package/src/client/TerminalView.tsx +424 -0
- package/src/client/TextEditor.tsx +468 -0
- package/src/client/TreePanel.tsx +279 -0
- package/src/client/UpdateDialog.tsx +186 -0
- package/src/client/UpdateSettingsPanel.tsx +29 -0
- package/src/client/UpdateSettingsSection.tsx +22 -0
- package/src/client/UploadOverlay.tsx +62 -0
- package/src/client/UsageHeatmapSection.module.css +440 -0
- package/src/client/UsageHeatmapSection.tsx +301 -0
- package/src/client/add-plugin-modal.tsx +199 -0
- package/src/client/api.ts +433 -0
- package/src/client/binary-download.tsx +23 -0
- package/src/client/breakpoints.ts +61 -0
- package/src/client/browser.ts +167 -0
- package/src/client/builtins/index.ts +37 -0
- package/src/client/builtins/tabs.tsx +275 -0
- package/src/client/builtins/viewers.tsx +125 -0
- package/src/client/chat-presentation.ts +95 -0
- package/src/client/chunk-loader.ts +350 -0
- package/src/client/chunks/editor.tsx +9 -0
- package/src/client/chunks/mermaid.tsx +10 -0
- package/src/client/chunks/terminal.tsx +9 -0
- package/src/client/cm-themes.ts +129 -0
- package/src/client/conversation-draft.ts +29 -0
- package/src/client/css-modules.d.ts +5 -0
- package/src/client/desktop-env.ts +72 -0
- package/src/client/editor-load.ts +92 -0
- package/src/client/frame-batcher.ts +56 -0
- package/src/client/icons.tsx +170 -0
- package/src/client/image-types.ts +8 -0
- package/src/client/ime-guard.ts +47 -0
- package/src/client/index.tsx +501 -0
- package/src/client/intercept.tsx +172 -0
- package/src/client/lang.ts +225 -0
- package/src/client/layout-push.ts +37 -0
- package/src/client/layout.css +156 -0
- package/src/client/lazy-chunk.tsx +89 -0
- package/src/client/link-intercept.ts +73 -0
- package/src/client/locales-ar.ts +387 -0
- package/src/client/locales-de.ts +372 -0
- package/src/client/locales-fr.ts +379 -0
- package/src/client/locales-hi.ts +386 -0
- package/src/client/locales-id.ts +384 -0
- package/src/client/locales-it.ts +377 -0
- package/src/client/locales-ja.ts +486 -0
- package/src/client/locales-ko.ts +378 -0
- package/src/client/locales-nl.ts +384 -0
- package/src/client/locales-pl.ts +388 -0
- package/src/client/locales-pt.ts +369 -0
- package/src/client/locales-ru.ts +384 -0
- package/src/client/locales-sv.ts +369 -0
- package/src/client/locales-th.ts +386 -0
- package/src/client/locales-tr.ts +386 -0
- package/src/client/locales-vi.ts +386 -0
- package/src/client/locales-zh-HK.ts +401 -0
- package/src/client/locales-zh-MO.ts +401 -0
- package/src/client/locales-zh-TW.ts +401 -0
- package/src/client/locales.ts +1229 -0
- package/src/client/markdown-html.ts +331 -0
- package/src/client/markdown-images.ts +137 -0
- package/src/client/markdown-labels.tsx +31 -0
- package/src/client/md-toc.tsx +127 -0
- package/src/client/mermaid-blocks.ts +110 -0
- package/src/client/mermaid-sanitize.ts +93 -0
- package/src/client/mermaid.tsx +406 -0
- package/src/client/open-when-sized.ts +43 -0
- package/src/client/open-with-settings.tsx +135 -0
- package/src/client/open-with.ts +221 -0
- package/src/client/openpath-intercept.ts +79 -0
- package/src/client/paths.ts +63 -0
- package/src/client/pdf-types.ts +4 -0
- package/src/client/pinned.ts +184 -0
- package/src/client/plugin-settings.ts +43 -0
- package/src/client/plugins-shared.ts +29 -0
- package/src/client/plugins-tabs.ts +153 -0
- package/src/client/plugins-viewers.ts +44 -0
- package/src/client/prefs.ts +216 -0
- package/src/client/produced-files.ts +120 -0
- package/src/client/selection-payload.ts +86 -0
- package/src/client/service.ts +873 -0
- package/src/client/session-pins.tsx +334 -0
- package/src/client/settings-nav-icon.ts +55 -0
- package/src/client/shell-presets.ts +83 -0
- package/src/client/sidebar.module.css +3607 -0
- package/src/client/split-pane.tsx +333 -0
- package/src/client/state.ts +1646 -0
- package/src/client/tab-content-memo.ts +55 -0
- package/src/client/terminal-font.ts +224 -0
- package/src/client/terminal-links.ts +194 -0
- package/src/client/theme.ts +110 -0
- package/src/client/titlebar-strip.ts +37 -0
- package/src/client/ui-tweaks/appicons.ts +24 -0
- package/src/client/ui-tweaks/archive.tsx +281 -0
- package/src/client/ui-tweaks/branding.tsx +232 -0
- package/src/client/ui-tweaks/cachehit.tsx +122 -0
- package/src/client/ui-tweaks/gitbar.tsx +2559 -0
- package/src/client/ui-tweaks/index.tsx +1696 -0
- package/src/client/ui-tweaks/mcp.tsx +582 -0
- package/src/client/ui-tweaks/notifier.ts +514 -0
- package/src/client/ui-tweaks/whale.tsx +171 -0
- package/src/client/upload.ts +187 -0
- package/src/client/useChatcodeAccount.ts +103 -0
- package/src/client/wco.ts +120 -0
- package/src/codingplan.ts +146 -0
- package/src/config.ts +207 -0
- package/src/context-types.ts +559 -0
- package/src/fs-operations.ts +97 -0
- package/src/fs-search.ts +113 -0
- package/src/fs-tree.ts +158 -0
- package/src/git.ts +446 -0
- package/src/html-route.ts +106 -0
- package/src/index.ts +1524 -0
- package/src/invariant.ts +32 -0
- package/src/login-route.ts +26 -0
- package/src/open-external.ts +90 -0
- package/src/path-security.ts +81 -0
- package/src/prefs-shared.ts +303 -0
- package/src/pty-deps.ts +241 -0
- package/src/pty-manager.ts +376 -0
- package/src/tools.ts +482 -0
- package/src/trust-fence.ts +84 -0
- package/src/ui-tweaks/archive.ts +293 -0
- package/src/ui-tweaks/config.ts +257 -0
- package/src/ui-tweaks/git-web.ts +421 -0
- package/src/ui-tweaks/git.ts +1524 -0
- package/src/ui-tweaks/index.ts +61 -0
- package/src/ui-tweaks/mcp.ts +535 -0
- package/src/ui-tweaks/turn-outcome.ts +105 -0
- package/src/ui-tweaks/web.ts +225 -0
- package/src/wire.ts +110 -0
- package/vendor/addon-fit.js +2 -0
- package/vendor/xterm.css +218 -0
- package/vendor/xterm.js +5 -0
|
@@ -0,0 +1,3607 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sidebar styles. Per the DSH web-styling rules every visual value rides the
|
|
3
|
+
* theme: --dsw-alias-* semantic tokens for colors, --dsw-font-* typography
|
|
4
|
+
* roles (size paired with line-height), and --ds-* for motion. The chrome
|
|
5
|
+
* mirrors the native DSH sidebar: flat (NO box-shadows anywhere), the
|
|
6
|
+
* sidebar fill surface, hairline borders, and the 28/36px circular icon
|
|
7
|
+
* controls with hover fills. No static palette values, no color literals, no
|
|
8
|
+
* theme selectors — light/dark adaptation is the theme package's job.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/* ── Shell ─────────────────────────────────────────────────────────────── */
|
|
12
|
+
|
|
13
|
+
/* One-time post-upgrade release notes. This lives above the native overlay
|
|
14
|
+
stack and uses only semantic theme tokens so every DSH skin remains valid. */
|
|
15
|
+
.releaseNotesOverlay {
|
|
16
|
+
position: fixed;
|
|
17
|
+
inset: 0;
|
|
18
|
+
z-index: 120;
|
|
19
|
+
display: grid;
|
|
20
|
+
place-items: center;
|
|
21
|
+
padding: 24px;
|
|
22
|
+
pointer-events: auto;
|
|
23
|
+
background: color-mix(in srgb, var(--dsw-alias-bg-base) 72%, transparent);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.releaseNotesDialog {
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-direction: column;
|
|
29
|
+
width: min(720px, 100%);
|
|
30
|
+
max-height: min(760px, calc(100vh - 48px));
|
|
31
|
+
overflow: hidden;
|
|
32
|
+
color: var(--dsw-alias-label-primary);
|
|
33
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
34
|
+
border: 1px solid var(--dsw-alias-border-l1);
|
|
35
|
+
border-radius: 12px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.releaseNotesHeader,
|
|
39
|
+
.releaseNotesFooter {
|
|
40
|
+
display: flex;
|
|
41
|
+
align-items: center;
|
|
42
|
+
padding: 16px 20px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.releaseNotesHeader {
|
|
46
|
+
justify-content: space-between;
|
|
47
|
+
gap: 16px;
|
|
48
|
+
border-bottom: 1px solid var(--dsw-alias-border-l1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.releaseNotesHeader h2 {
|
|
52
|
+
margin: 0;
|
|
53
|
+
font: var(--dsw-font-s-18);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.releaseNotesContent {
|
|
57
|
+
min-height: 120px;
|
|
58
|
+
padding: 20px;
|
|
59
|
+
overflow: auto;
|
|
60
|
+
font: var(--dsw-font-s-14);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.releaseNotesFooter {
|
|
64
|
+
justify-content: flex-end;
|
|
65
|
+
border-top: 1px solid var(--dsw-alias-border-l1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.releaseNotesIconButton,
|
|
69
|
+
.releaseNotesButton {
|
|
70
|
+
border: 1px solid var(--dsw-alias-border-l1);
|
|
71
|
+
color: var(--dsw-alias-label-primary);
|
|
72
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
73
|
+
cursor: pointer;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.releaseNotesIconButton:hover,
|
|
77
|
+
.releaseNotesButton:hover {
|
|
78
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.releaseNotesIconButton {
|
|
82
|
+
width: 32px;
|
|
83
|
+
height: 32px;
|
|
84
|
+
padding: 0;
|
|
85
|
+
border-radius: 50%;
|
|
86
|
+
font: var(--dsw-font-s-18);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.releaseNotesButton {
|
|
90
|
+
min-width: 84px;
|
|
91
|
+
min-height: 36px;
|
|
92
|
+
padding: 6px 16px;
|
|
93
|
+
border-radius: 8px;
|
|
94
|
+
font: var(--dsw-font-s-14);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* ── ChatCode update (account menu) ───────────────────────────────────── */
|
|
98
|
+
|
|
99
|
+
/* Upgrade list inside the update dialog: package name + version transition. */
|
|
100
|
+
.updateList {
|
|
101
|
+
margin: 0;
|
|
102
|
+
padding: 0;
|
|
103
|
+
list-style: none;
|
|
104
|
+
display: flex;
|
|
105
|
+
flex-direction: column;
|
|
106
|
+
gap: 10px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.updateList li {
|
|
110
|
+
display: flex;
|
|
111
|
+
align-items: center;
|
|
112
|
+
justify-content: space-between;
|
|
113
|
+
gap: 16px;
|
|
114
|
+
font: var(--dsw-font-s-14);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.updateVersions {
|
|
118
|
+
font-variant-numeric: tabular-nums;
|
|
119
|
+
color: var(--dsw-alias-label-secondary);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.updateOk {
|
|
123
|
+
color: var(--dsw-alias-state-success-primary);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.updateError,
|
|
127
|
+
.updateErrorText {
|
|
128
|
+
color: var(--dsw-alias-state-error-primary);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.updateErrorText {
|
|
132
|
+
margin: 12px 0 0;
|
|
133
|
+
white-space: pre-wrap;
|
|
134
|
+
font: var(--dsw-font-s-14);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Pasteable manual npm command shown when a global install fails. */
|
|
138
|
+
.updateCommand {
|
|
139
|
+
margin: 8px 0 0;
|
|
140
|
+
padding: 8px 10px;
|
|
141
|
+
border-radius: 6px;
|
|
142
|
+
overflow-x: auto;
|
|
143
|
+
background: var(--dsw-alias-bg-layer-3);
|
|
144
|
+
font-family: var(--dsw-font-code, var(--ds-font-family-code, monospace));
|
|
145
|
+
font-size: 12px;
|
|
146
|
+
white-space: pre-wrap;
|
|
147
|
+
word-break: break-all;
|
|
148
|
+
user-select: all;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* Update entry row inside the host Settings custom panel. It is the sole
|
|
152
|
+
content of the settings card (the `.group` already supplies its padding +
|
|
153
|
+
border), so no top divider or extra top spacing is needed — otherwise the
|
|
154
|
+
row sits too far from the card's top edge and loses vertical balance. */
|
|
155
|
+
.updateSettingsRow {
|
|
156
|
+
display: flex;
|
|
157
|
+
align-items: center;
|
|
158
|
+
justify-content: space-between;
|
|
159
|
+
gap: 16px;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.updateSettingsText {
|
|
163
|
+
display: flex;
|
|
164
|
+
flex-direction: column;
|
|
165
|
+
gap: 2px;
|
|
166
|
+
min-width: 0;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.updateSettingsTitle {
|
|
170
|
+
font: var(--dsw-font-s-14);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.updateSettingsDesc {
|
|
174
|
+
font: var(--dsw-font-s-13);
|
|
175
|
+
color: var(--dsw-alias-label-secondary);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* The in-Settings update body (inline variant of the old full-screen modal):
|
|
179
|
+
moves the action buttons to the right edge, matching the Settings row
|
|
180
|
+
layout, with the state text wrapping to the next line instead of a
|
|
181
|
+
vertical footer bar. */
|
|
182
|
+
.updateSettingsBlock {
|
|
183
|
+
display: flex;
|
|
184
|
+
flex-direction: column;
|
|
185
|
+
gap: 12px;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/* States + footer shared by the UpdateDialog variants; kept layout-neutral so
|
|
189
|
+
the same content reads identically as a modal or embedded in Settings. */
|
|
190
|
+
.updateBody {
|
|
191
|
+
margin: 20px 0 0;
|
|
192
|
+
font: var(--dsw-font-s-14);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.updateFooter {
|
|
196
|
+
display: flex;
|
|
197
|
+
justify-content: flex-end;
|
|
198
|
+
gap: 8px;
|
|
199
|
+
margin-top: 4px;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* Inline variant: the dimmed overlay and modal frame are omitted; the update
|
|
203
|
+
states unfold right under the entry row, on the Settings pane's own
|
|
204
|
+
surface (a soft inset card so the block reads as one unit). */
|
|
205
|
+
.updateInline {
|
|
206
|
+
padding: 16px;
|
|
207
|
+
border-radius: 8px;
|
|
208
|
+
border: 1px solid var(--dsw-alias-border-l1);
|
|
209
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/* Skinning contract (token-driven): every surface here consumes DSH's
|
|
213
|
+
generic tokens (`--dsw-alias-*`), NEVER `--dsw-specific-sidebar-fill` —
|
|
214
|
+
skin systems override that token to restyle the APP's own left-nav column
|
|
215
|
+
(dsh-web-ui skins make it translucent glass or theme colors, Aqua makes it
|
|
216
|
+
transparent), and a panel consuming it would lose its fill or clash with
|
|
217
|
+
the label tokens. The panels use the generic card surface
|
|
218
|
+
`--dsw-alias-bg-layer-1`, which every dsh-web-ui skin overrides — so
|
|
219
|
+
switching skins in the dsh-web-ui skin center re-skins the sidebar panels
|
|
220
|
+
automatically (see AGENTS.md §8). */
|
|
221
|
+
|
|
222
|
+
/* The unified panel host: a fixed, viewport-sized, click-transparent
|
|
223
|
+
containing block for every panel element. Panels are ABSOLUTE within it
|
|
224
|
+
(not fixed), so a desktop shell's intermediate wrapper transform can
|
|
225
|
+
never hijack their containing block — the host itself is the only fixed
|
|
226
|
+
element, appended directly to document.body. The layer sits at z-index 25:
|
|
227
|
+
above the app's shell overlay (AppFrame overlayLayer, 20) and in-flow
|
|
228
|
+
content, below DSH's ui-cordis dynamic-plugin panel (fixed, 30 — the
|
|
229
|
+
inventory/surfacing surface must never be hidden behind the workbench),
|
|
230
|
+
and below the app's overlay stack at 100+; each panel re-enables pointer
|
|
231
|
+
events on itself. Degraded mode ([data-dsh-panel-host-degraded]) covers
|
|
232
|
+
the rare shell that transforms <html>/<body> itself: the host becomes
|
|
233
|
+
absolute and the mount self-check pins it to the viewport every frame. */
|
|
234
|
+
:global([data-dsh-panel-host]) {
|
|
235
|
+
position: fixed;
|
|
236
|
+
inset: 0;
|
|
237
|
+
z-index: 25;
|
|
238
|
+
pointer-events: none;
|
|
239
|
+
/* Clip at the viewport edge: collapsed panels slide off-screen with
|
|
240
|
+
`transform: translate(102%)`, and a transformed element still
|
|
241
|
+
contributes to its ancestors' scrollable overflow — without this the
|
|
242
|
+
hidden panels extended the document's scrollable area, making the whole
|
|
243
|
+
page draggable left-right and up-down while any panel was collapsed.
|
|
244
|
+
The host is exactly viewport-sized (inset: 0), so the clip is invisible
|
|
245
|
+
until a panel slides in from the edge; internal scroll containers and
|
|
246
|
+
the app's fixed overlay stack are unaffected. `clip`, not `hidden`: a
|
|
247
|
+
hidden box stays a PROGRAMMATICALLY scrollable container, and a
|
|
248
|
+
scrollIntoView fired from panel content (the file tree's "Show in
|
|
249
|
+
folder" reveal) scrolled the host itself — shifting the whole panel,
|
|
250
|
+
tab bar included, out of the viewport with no way to scroll back. */
|
|
251
|
+
overflow: clip;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
:global([data-dsh-panel-host][data-dsh-panel-host-degraded]) {
|
|
255
|
+
position: absolute;
|
|
256
|
+
top: 0;
|
|
257
|
+
left: 0;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/* Pinned conversations are a small React island alongside the host-owned
|
|
261
|
+
Workspace browser. The native browser still owns its workspace tree and
|
|
262
|
+
all existing operations; this island merely supplies the peer-level
|
|
263
|
+
pinned group. */
|
|
264
|
+
:global([data-dsh-pinned-sessions]) {
|
|
265
|
+
flex: none;
|
|
266
|
+
min-width: 0;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.pinnedSessions {
|
|
270
|
+
/* Match the host Workspace section's edge-to-edge section geometry. */
|
|
271
|
+
margin: 0 0 6px;
|
|
272
|
+
padding: 4px 0 6px;
|
|
273
|
+
border-bottom: 1px solid var(--dsw-alias-border-l1);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.pinnedSessionsHeading {
|
|
277
|
+
display: flex;
|
|
278
|
+
align-items: center;
|
|
279
|
+
height: 36px;
|
|
280
|
+
/* Same left inset and ink as DSH's Workspace section label. */
|
|
281
|
+
padding: 0 4px;
|
|
282
|
+
color: var(--dsw-alias-label-primary);
|
|
283
|
+
font: var(--dsw-font-s-14);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.pinnedSessionsList {
|
|
287
|
+
display: grid;
|
|
288
|
+
gap: 1px;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/* A pinned session leaves its original Workspace row while it is in the
|
|
292
|
+
top-level pin group. Removing the marker (unpin) restores the native row
|
|
293
|
+
without remounting or changing that browser's own ordering state. */
|
|
294
|
+
:global([data-slot="sidebar.workspaces"] [class*="_sessionRow"][data-dsh-session-pinned]) {
|
|
295
|
+
display: none;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.pinnedSessionRow {
|
|
299
|
+
position: relative;
|
|
300
|
+
display: flex;
|
|
301
|
+
align-items: center;
|
|
302
|
+
min-width: 0;
|
|
303
|
+
height: 32px;
|
|
304
|
+
border-radius: 8px;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.pinnedSessionRow:hover,
|
|
308
|
+
.pinnedSessionRow:focus-within {
|
|
309
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.pinnedSessionOpen,
|
|
313
|
+
.pinnedSessionMore,
|
|
314
|
+
.pinnedSessionMenu button {
|
|
315
|
+
border: 0;
|
|
316
|
+
font: inherit;
|
|
317
|
+
cursor: pointer;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.pinnedSessionOpen {
|
|
321
|
+
display: flex;
|
|
322
|
+
align-items: center;
|
|
323
|
+
gap: 8px;
|
|
324
|
+
min-width: 0;
|
|
325
|
+
height: 100%;
|
|
326
|
+
flex: 1;
|
|
327
|
+
padding: 0 6px 0 8px;
|
|
328
|
+
background: transparent;
|
|
329
|
+
color: var(--dsw-alias-label-primary);
|
|
330
|
+
text-align: left;
|
|
331
|
+
font: var(--dsw-font-s-14);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.pinnedSessionOpen[aria-current="page"] {
|
|
335
|
+
color: var(--dsw-alias-brand-primary);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.pinnedSessionDot {
|
|
339
|
+
width: 6px;
|
|
340
|
+
height: 6px;
|
|
341
|
+
flex: none;
|
|
342
|
+
border-radius: 50%;
|
|
343
|
+
background: var(--dsw-alias-label-tertiary);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.pinnedSessionDot[data-running] {
|
|
347
|
+
background: var(--dsw-alias-state-success-primary);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.pinnedSessionTitle {
|
|
351
|
+
min-width: 0;
|
|
352
|
+
overflow: hidden;
|
|
353
|
+
text-overflow: ellipsis;
|
|
354
|
+
white-space: nowrap;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.pinnedSessionMore {
|
|
358
|
+
display: inline-flex;
|
|
359
|
+
align-items: center;
|
|
360
|
+
justify-content: center;
|
|
361
|
+
width: 28px;
|
|
362
|
+
height: 28px;
|
|
363
|
+
margin-right: 2px;
|
|
364
|
+
padding: 0;
|
|
365
|
+
border-radius: 50%;
|
|
366
|
+
background: transparent;
|
|
367
|
+
color: var(--dsw-alias-label-secondary);
|
|
368
|
+
letter-spacing: 1px;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.pinnedSessionMore:hover,
|
|
372
|
+
.pinnedSessionMore[aria-expanded="true"] {
|
|
373
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
374
|
+
color: var(--dsw-alias-label-primary);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.pinnedSessionMenu {
|
|
378
|
+
position: absolute;
|
|
379
|
+
top: calc(100% + 2px);
|
|
380
|
+
right: 0;
|
|
381
|
+
z-index: 1101;
|
|
382
|
+
box-sizing: border-box;
|
|
383
|
+
min-width: 150px;
|
|
384
|
+
padding: 4px;
|
|
385
|
+
border: 1px solid var(--dsw-alias-border-inverted);
|
|
386
|
+
border-radius: 10px;
|
|
387
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.pinnedSessionMenu button {
|
|
391
|
+
display: flex;
|
|
392
|
+
align-items: center;
|
|
393
|
+
gap: 8px;
|
|
394
|
+
width: 100%;
|
|
395
|
+
min-height: 32px;
|
|
396
|
+
padding: 5px 8px;
|
|
397
|
+
border-radius: 7px;
|
|
398
|
+
background: transparent;
|
|
399
|
+
color: var(--dsw-alias-label-primary);
|
|
400
|
+
text-align: left;
|
|
401
|
+
font: var(--dsw-font-xxs-12);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.pinnedSessionMenu button:hover {
|
|
405
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.pinnedSessionMenuDivider {
|
|
409
|
+
height: 1px;
|
|
410
|
+
margin: 4px;
|
|
411
|
+
background: var(--dsw-alias-border-l1);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/* Bottom-left account menu: it replaces the host's gear launcher while this
|
|
415
|
+
plugin is mounted, but opens that native launcher for Settings. */
|
|
416
|
+
.accountMenu {
|
|
417
|
+
position: absolute;
|
|
418
|
+
left: 0;
|
|
419
|
+
bottom: 0;
|
|
420
|
+
z-index: 3;
|
|
421
|
+
box-sizing: border-box;
|
|
422
|
+
width: var(--dsh-account-menu-width, 280px);
|
|
423
|
+
border-top: 1px solid var(--dsw-alias-border-l2);
|
|
424
|
+
/* Continue the left navigation rail's right-hand divider through the
|
|
425
|
+
account area, so the vertical boundary reaches the viewport bottom. */
|
|
426
|
+
border-right: 1px solid var(--dsw-alias-border-l2);
|
|
427
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
428
|
+
pointer-events: auto;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.accountTrigger,
|
|
432
|
+
.accountItem {
|
|
433
|
+
border: 0;
|
|
434
|
+
color: var(--dsw-alias-fg-base);
|
|
435
|
+
font: inherit;
|
|
436
|
+
cursor: pointer;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
.accountTrigger {
|
|
440
|
+
display: flex;
|
|
441
|
+
align-items: center;
|
|
442
|
+
box-sizing: border-box;
|
|
443
|
+
gap: 8px;
|
|
444
|
+
width: 100%;
|
|
445
|
+
min-height: 52px;
|
|
446
|
+
padding: 10px 14px max(10px, env(safe-area-inset-bottom));
|
|
447
|
+
border-radius: 0;
|
|
448
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
449
|
+
font-family: var(--dsw-font-family-body);
|
|
450
|
+
font-size: var(--dsw-font-size-body-sm);
|
|
451
|
+
line-height: var(--dsw-font-line-height-body-sm);
|
|
452
|
+
transition: background var(--ds-transition-duration-slow) var(--ds-ease-in-out);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
.accountTrigger:hover,
|
|
456
|
+
.accountTrigger[aria-expanded="true"] {
|
|
457
|
+
background: var(--dsw-alias-bg-hover);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
.accountTrigger:focus-visible,
|
|
461
|
+
.accountItem:focus-visible {
|
|
462
|
+
outline: 2px solid var(--dsw-alias-border-accent);
|
|
463
|
+
outline-offset: 2px;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
.accountAvatar {
|
|
467
|
+
position: relative;
|
|
468
|
+
display: grid;
|
|
469
|
+
width: 28px;
|
|
470
|
+
height: 28px;
|
|
471
|
+
flex: none;
|
|
472
|
+
place-items: center;
|
|
473
|
+
border-radius: 50%;
|
|
474
|
+
background: var(--dsw-alias-bg-layer-3);
|
|
475
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
476
|
+
color: var(--dsw-alias-fg-accent);
|
|
477
|
+
font-weight: 600;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
.accountName {
|
|
481
|
+
overflow: hidden;
|
|
482
|
+
text-overflow: ellipsis;
|
|
483
|
+
white-space: nowrap;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
.accountDropdown {
|
|
487
|
+
position: absolute;
|
|
488
|
+
/* A separate popover card, deliberately narrower than the sidebar button. */
|
|
489
|
+
bottom: calc(100% + 8px);
|
|
490
|
+
left: 8px;
|
|
491
|
+
display: grid;
|
|
492
|
+
box-sizing: border-box;
|
|
493
|
+
width: min(252px, calc(100% - 16px));
|
|
494
|
+
padding: 10px 8px 8px;
|
|
495
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
496
|
+
border-radius: 12px;
|
|
497
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
498
|
+
z-index: 1;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
.accountDropdownHeader {
|
|
502
|
+
display: flex;
|
|
503
|
+
align-items: center;
|
|
504
|
+
gap: 8px;
|
|
505
|
+
min-height: 36px;
|
|
506
|
+
padding: 0 8px 8px;
|
|
507
|
+
font-family: var(--dsw-font-family-body);
|
|
508
|
+
font-size: var(--dsw-font-size-body-sm);
|
|
509
|
+
line-height: var(--dsw-font-line-height-body-sm);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
.accountMenuDivider {
|
|
513
|
+
height: 1px;
|
|
514
|
+
margin: 0 4px 6px;
|
|
515
|
+
background: var(--dsw-alias-border-l2);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
.accountItem {
|
|
519
|
+
display: flex;
|
|
520
|
+
align-items: center;
|
|
521
|
+
gap: 8px;
|
|
522
|
+
min-height: 32px;
|
|
523
|
+
padding: 0 10px;
|
|
524
|
+
border-radius: 7px;
|
|
525
|
+
background: transparent;
|
|
526
|
+
text-align: left;
|
|
527
|
+
font: var(--dsw-font-s-14);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
.accountItem:hover {
|
|
531
|
+
background: var(--dsw-alias-bg-hover);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
.accountPresence {
|
|
535
|
+
box-sizing: content-box;
|
|
536
|
+
width: 6px;
|
|
537
|
+
height: 6px;
|
|
538
|
+
margin-left: auto;
|
|
539
|
+
flex: none;
|
|
540
|
+
border-radius: 50%;
|
|
541
|
+
border: 2px solid var(--dsw-alias-bg-layer-2);
|
|
542
|
+
background: var(--dsw-alias-fg-accent);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
.accountTrigger .accountPresence {
|
|
546
|
+
border-color: var(--dsw-alias-bg-layer-1);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/* The compatibility action cluster used when the host exposes no native
|
|
550
|
+
right-sidebar affordance. It stays pinned to the viewport corner, sitting
|
|
551
|
+
flush in the 34px tab strip (28px buttons at top: 3) whose right end it
|
|
552
|
+
really squeezes. Host-internal z-index 45
|
|
553
|
+
(above the panels' 40); the host's global layer is z-index 25, so the
|
|
554
|
+
whole cluster stays below DSH's ui-cordis dynamic-plugin panel (30) and
|
|
555
|
+
the app's overlay stack (menus/tooltips/modals sit at 100+), so a cordis
|
|
556
|
+
approval popup is never hidden behind the workbench (issue #52). Absolute
|
|
557
|
+
within the panel host (the host's inset: 0 makes viewport coordinates
|
|
558
|
+
identical). */
|
|
559
|
+
.toggleCluster {
|
|
560
|
+
position: absolute;
|
|
561
|
+
/* env() resolves to 0 on devices without a top inset (desktops). */
|
|
562
|
+
top: var(--dsh-native-sidebar-toggle-top, calc(3px + env(safe-area-inset-top)));
|
|
563
|
+
right: 10px;
|
|
564
|
+
z-index: 45;
|
|
565
|
+
display: flex;
|
|
566
|
+
flex-direction: row;
|
|
567
|
+
gap: 4px;
|
|
568
|
+
pointer-events: auto;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/* Current DSH hosts expose a persistent Session utilities row immediately
|
|
572
|
+
before the native right-sidebar corner seat. The Sidebar portals all three
|
|
573
|
+
actions into that row, so they stay clear when either right panel opens.
|
|
574
|
+
Reset all viewport-fallback positioning. */
|
|
575
|
+
.toggleClusterNative {
|
|
576
|
+
position: static;
|
|
577
|
+
inset: auto;
|
|
578
|
+
z-index: auto;
|
|
579
|
+
flex: none;
|
|
580
|
+
align-items: center;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/* The plugin supplies the integrated sidebar control in the utilities row.
|
|
584
|
+
Keep DSH's intercepted corner glyph mounted for React ownership and event
|
|
585
|
+
compatibility, but remove its duplicate visual footprint. */
|
|
586
|
+
:global(button[data-dsh-better-sidebar-toggle]) {
|
|
587
|
+
display: none;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/* On an older host, the tab strip of the OPEN right panel reserves the
|
|
591
|
+
viewport cluster's width at its right end. Current hosts need no reserve:
|
|
592
|
+
their actions live in the Session utilities row outside the panel. */
|
|
593
|
+
:global(body:not([data-dsh-native-sidebar-toggle])) .panel:not(.panelHidden) .tabBar {
|
|
594
|
+
padding-right: var(--dsh-sidebar-toggle-reserve, 188px);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/* The panel affordance is the native rail icon control (or the plugin's
|
|
598
|
+
compatibility fallback on older hosts): a plain
|
|
599
|
+
28px circle (the app's icon-button size — the cluster must stay inside
|
|
600
|
+
the 34px tab-strip band so it never covers the pane headers below),
|
|
601
|
+
transparent fill, secondary ink; hover raises the fill. No border, no
|
|
602
|
+
shadow — the icon alone is the affordance. */
|
|
603
|
+
.toggleButton {
|
|
604
|
+
display: flex;
|
|
605
|
+
align-items: center;
|
|
606
|
+
justify-content: center;
|
|
607
|
+
width: 28px;
|
|
608
|
+
height: 28px;
|
|
609
|
+
border: none;
|
|
610
|
+
border-radius: 50%;
|
|
611
|
+
background: transparent;
|
|
612
|
+
color: var(--dsw-alias-label-secondary);
|
|
613
|
+
cursor: pointer;
|
|
614
|
+
transition:
|
|
615
|
+
background var(--ds-transition-duration-slow) var(--ds-ease-in-out),
|
|
616
|
+
color var(--ds-transition-duration-slow) var(--ds-ease-in-out);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/* The manual is deliberately a labeled action rather than a third anonymous
|
|
620
|
+
rail glyph. Its fixed CJK-friendly minimum width preserves the icon +
|
|
621
|
+
"使用手册" label as one compact, easily discoverable control; the extra
|
|
622
|
+
right-tab-strip reservation above keeps every tab clear of it. */
|
|
623
|
+
.manualButton {
|
|
624
|
+
display: inline-flex;
|
|
625
|
+
align-items: center;
|
|
626
|
+
justify-content: center;
|
|
627
|
+
flex: none;
|
|
628
|
+
gap: 6px;
|
|
629
|
+
min-width: 94px;
|
|
630
|
+
height: 28px;
|
|
631
|
+
margin-right: 4px;
|
|
632
|
+
padding: 0 10px;
|
|
633
|
+
border: none;
|
|
634
|
+
border-radius: 6px;
|
|
635
|
+
background: transparent;
|
|
636
|
+
color: var(--dsw-alias-label-secondary);
|
|
637
|
+
font: var(--dsw-font-xxs-12);
|
|
638
|
+
white-space: nowrap;
|
|
639
|
+
cursor: pointer;
|
|
640
|
+
transition:
|
|
641
|
+
background var(--ds-transition-duration-slow) var(--ds-ease-in-out),
|
|
642
|
+
color var(--ds-transition-duration-slow) var(--ds-ease-in-out);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
.manualButton:hover {
|
|
646
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
647
|
+
color: var(--dsw-alias-label-primary);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
.toggleButton:hover:not(:disabled):not([aria-disabled='true']) {
|
|
651
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
652
|
+
color: var(--dsw-alias-label-primary);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
.toggleButton:disabled,
|
|
656
|
+
.toggleButton[aria-disabled='true'] {
|
|
657
|
+
opacity: 0.4;
|
|
658
|
+
cursor: default;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
.panel {
|
|
662
|
+
box-sizing: border-box;
|
|
663
|
+
position: absolute;
|
|
664
|
+
top: 0;
|
|
665
|
+
right: 0;
|
|
666
|
+
/* Full height: the bottom panel squeezes only the center column, so the
|
|
667
|
+
right panel never gives up any vertical position. */
|
|
668
|
+
bottom: 0;
|
|
669
|
+
/* Host-internal z-index 40 (sibling of the bottom panel's 40; the two
|
|
670
|
+
never overlap — the bottom panel's right edge is this panel's left
|
|
671
|
+
edge — and both sit below the toggle cluster's 45). The absolute
|
|
672
|
+
global layer comes from the host ([data-dsh-panel-host], 25) — the
|
|
673
|
+
whole stack stays above the app's in-flow content and below DSH's
|
|
674
|
+
ui-cordis dynamic-plugin panel (30) and the app's overlay stack (100+),
|
|
675
|
+
so menus/tooltips/modals always win over the panels (issue #52). The
|
|
676
|
+
corner handle is a child and stacks within the panel. */
|
|
677
|
+
z-index: 40;
|
|
678
|
+
display: flex;
|
|
679
|
+
flex-direction: column;
|
|
680
|
+
/* Re-enable interaction inside the click-transparent panel host. */
|
|
681
|
+
pointer-events: auto;
|
|
682
|
+
/* The generic card surface (see the root contract above). Never
|
|
683
|
+
`--dsw-specific-sidebar-fill` — skin plugins restyle that token for the
|
|
684
|
+
app's own left nav and a panel consuming it loses its fill or clashes
|
|
685
|
+
with labels (#60/#105/#106). */
|
|
686
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
687
|
+
border-left: 1px solid var(--dsw-alias-border-l2);
|
|
688
|
+
/* Bottom safe-area (notched phones): the drawer's bottom content clears
|
|
689
|
+
the home indicator; 0 on desktops. */
|
|
690
|
+
padding-bottom: env(safe-area-inset-bottom);
|
|
691
|
+
/* Expand/collapse slides the panel; fullscreen animates the width. */
|
|
692
|
+
transition:
|
|
693
|
+
transform var(--ds-transition-duration-slow) var(--ds-ease-in-out),
|
|
694
|
+
width var(--ds-transition-duration-slow) var(--ds-ease-in-out);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/* Collapsed: slid off-screen, interactive nothing, hidden after the slide. */
|
|
698
|
+
.panelHidden {
|
|
699
|
+
transform: translateX(102%);
|
|
700
|
+
pointer-events: none;
|
|
701
|
+
visibility: hidden;
|
|
702
|
+
transition:
|
|
703
|
+
transform var(--ds-transition-duration-slow) var(--ds-ease-in-out),
|
|
704
|
+
width var(--ds-transition-duration-slow) var(--ds-ease-in-out),
|
|
705
|
+
visibility 0s linear var(--ds-transition-duration-slow);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/* Width drags write at pointer cadence; easing would detach the edge. */
|
|
709
|
+
.panel[data-dragging] {
|
|
710
|
+
transition: none;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
.panelResize {
|
|
714
|
+
position: absolute;
|
|
715
|
+
/* Centered on the panel edge (an 8px hit strip straddling the border, the
|
|
716
|
+
same pattern as the host's own frame handles). */
|
|
717
|
+
left: -4px;
|
|
718
|
+
top: 0;
|
|
719
|
+
bottom: 0;
|
|
720
|
+
width: 8px;
|
|
721
|
+
cursor: col-resize;
|
|
722
|
+
z-index: 2;
|
|
723
|
+
touch-action: none;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
.panelResizeActive {
|
|
727
|
+
background: var(--dsw-alias-interactive-bg-hover-accent);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
.panelBody {
|
|
731
|
+
flex: 1;
|
|
732
|
+
min-height: 0;
|
|
733
|
+
min-width: 0;
|
|
734
|
+
display: flex;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/* ── Bottom panel ──────────────────────────────────────────────────────── */
|
|
738
|
+
|
|
739
|
+
/* The bottom panel: an independent workbench at the bottom of the CENTER
|
|
740
|
+
column only (the Sidebar shell writes left/right inline: from the app's
|
|
741
|
+
own left sidebar to the right panel's left edge) — the sidebars never
|
|
742
|
+
give up any position. Same surface as the right panel, with a top
|
|
743
|
+
hairline instead of the left one. Host-internal z-index 40 mirrors the
|
|
744
|
+
right panel; the absolute global layer comes from the host (25), below
|
|
745
|
+
DSH's ui-cordis dynamic-plugin panel (30) so the cordis inventory
|
|
746
|
+
surface floats above the workbench, and below the app's overlay stack
|
|
747
|
+
(100+) so popups win over the workbench (issue #52). */
|
|
748
|
+
.bottomPanel {
|
|
749
|
+
position: absolute;
|
|
750
|
+
bottom: 0;
|
|
751
|
+
z-index: 40;
|
|
752
|
+
display: flex;
|
|
753
|
+
flex-direction: column;
|
|
754
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
755
|
+
border-top: 1px solid var(--dsw-alias-border-l2);
|
|
756
|
+
/* Re-enable interaction inside the click-transparent panel host. */
|
|
757
|
+
pointer-events: auto;
|
|
758
|
+
/* Bottom safe-area (notched phones); 0 on desktops. */
|
|
759
|
+
padding-bottom: env(safe-area-inset-bottom);
|
|
760
|
+
/* Expand/collapse slides the panel; height drags animate the height. */
|
|
761
|
+
transition:
|
|
762
|
+
transform var(--ds-transition-duration-slow) var(--ds-ease-in-out),
|
|
763
|
+
height var(--ds-transition-duration-slow) var(--ds-ease-in-out);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/* Collapsed: slid off-screen, interactive nothing, hidden after the slide. */
|
|
767
|
+
.bottomPanelHidden {
|
|
768
|
+
transform: translateY(102%);
|
|
769
|
+
pointer-events: none;
|
|
770
|
+
visibility: hidden;
|
|
771
|
+
transition:
|
|
772
|
+
transform var(--ds-transition-duration-slow) var(--ds-ease-in-out),
|
|
773
|
+
height var(--ds-transition-duration-slow) var(--ds-ease-in-out),
|
|
774
|
+
visibility 0s linear var(--ds-transition-duration-slow);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/* Height drags write at pointer cadence; easing would detach the edge. */
|
|
778
|
+
.bottomPanel[data-dragging] {
|
|
779
|
+
transition: none;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/* Layout isolation: panel-internal reflows (tabs, editors, terminals) never
|
|
783
|
+
leak into the app shell's layout, and the app shell's layout changes
|
|
784
|
+
never cascade through the panel subtree — the drag stays confined.
|
|
785
|
+
will-change: transform is only live while a drag is (the body attribute
|
|
786
|
+
toggles with the drag state), promoting the panels to their own layer
|
|
787
|
+
without paying the compositing cost at rest. */
|
|
788
|
+
.panel,
|
|
789
|
+
.bottomPanel {
|
|
790
|
+
contain: layout style;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
body[data-dsh-sidebar-dragging] .panel,
|
|
794
|
+
body[data-dsh-sidebar-dragging] .bottomPanel {
|
|
795
|
+
will-change: transform;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
/* The bottom panel's height drag: the top edge strip (mirror of the right
|
|
799
|
+
panel's width strip), centered on the border like the width strip. */
|
|
800
|
+
.bottomResize {
|
|
801
|
+
position: absolute;
|
|
802
|
+
left: 0;
|
|
803
|
+
right: 0;
|
|
804
|
+
top: -4px;
|
|
805
|
+
height: 8px;
|
|
806
|
+
cursor: row-resize;
|
|
807
|
+
z-index: 2;
|
|
808
|
+
touch-action: none;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
.bottomResizeActive {
|
|
812
|
+
background: var(--dsw-alias-interactive-bg-hover-accent);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/* The bottom panel's close control: the app's icon-button pattern (28px
|
|
816
|
+
circle), pinned to the tab strip's right end — one tap collapses the
|
|
817
|
+
panel. The tab strips below reserve its width so the + menu never hides
|
|
818
|
+
under it. */
|
|
819
|
+
.bottomClose {
|
|
820
|
+
position: absolute;
|
|
821
|
+
top: 3px;
|
|
822
|
+
right: 6px;
|
|
823
|
+
z-index: 4;
|
|
824
|
+
display: inline-flex;
|
|
825
|
+
align-items: center;
|
|
826
|
+
justify-content: center;
|
|
827
|
+
width: 28px;
|
|
828
|
+
height: 28px;
|
|
829
|
+
padding: 0;
|
|
830
|
+
border: none;
|
|
831
|
+
border-radius: 50%;
|
|
832
|
+
background: transparent;
|
|
833
|
+
color: var(--dsw-alias-label-secondary);
|
|
834
|
+
cursor: pointer;
|
|
835
|
+
flex: none;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
.bottomClose:hover:not(:disabled) {
|
|
839
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
840
|
+
color: var(--dsw-alias-label-primary);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
/* The bottom panel's tab strips reserve the close control's width at their
|
|
844
|
+
right end, so the + menu never hides under it. */
|
|
845
|
+
.bottomPanel .tabBar {
|
|
846
|
+
padding-right: 40px;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/* ── Free windows ──────────────────────────────────────────────────────── */
|
|
850
|
+
|
|
851
|
+
/* One floating tab: the same card surface as the panels, at viewport
|
|
852
|
+
coordinates inside the panel host (immune to shell transforms). z-index
|
|
853
|
+
42: above the panels (40) so a window drags across them, below the
|
|
854
|
+
toggle cluster (45) and the app's overlay stack (100+, issue #52).
|
|
855
|
+
Stacking among windows is the floats array order (siblings share the
|
|
856
|
+
z-index; DOM order wins). Deliberately NO box transition — the header/
|
|
857
|
+
resize drags write left/top/width/height per frame. Elevated surface,
|
|
858
|
+
so unlike the flat panels it earns a shadow token. */
|
|
859
|
+
.floatWindow {
|
|
860
|
+
position: absolute;
|
|
861
|
+
z-index: 42;
|
|
862
|
+
display: flex;
|
|
863
|
+
flex-direction: column;
|
|
864
|
+
/* Re-enable interaction inside the click-transparent panel host. */
|
|
865
|
+
pointer-events: auto;
|
|
866
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
867
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
868
|
+
border-radius: 8px;
|
|
869
|
+
box-shadow: var(--dsw-shadow-lv3);
|
|
870
|
+
overflow: hidden;
|
|
871
|
+
contain: layout style;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
.floatWindowDragging {
|
|
875
|
+
will-change: left, top, width, height;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/* The header: the move/dock-back drag handle, mirroring the tab strip's
|
|
879
|
+
chrome (34px, hairline bottom, secondary label). */
|
|
880
|
+
.floatHeader {
|
|
881
|
+
flex: none;
|
|
882
|
+
display: flex;
|
|
883
|
+
align-items: center;
|
|
884
|
+
gap: 4px;
|
|
885
|
+
height: 34px;
|
|
886
|
+
padding: 0 4px 0 10px;
|
|
887
|
+
font: var(--dsw-font-xxs-12);
|
|
888
|
+
color: var(--dsw-alias-label-secondary);
|
|
889
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
890
|
+
border-bottom: 1px solid var(--dsw-alias-border-l1);
|
|
891
|
+
cursor: grab;
|
|
892
|
+
user-select: none;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
.floatWindowDragging .floatHeader {
|
|
896
|
+
cursor: grabbing;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
.floatTitle {
|
|
900
|
+
flex: 1;
|
|
901
|
+
min-width: 0;
|
|
902
|
+
overflow: hidden;
|
|
903
|
+
text-overflow: ellipsis;
|
|
904
|
+
white-space: nowrap;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
/* Mirrors .tabClose. */
|
|
908
|
+
.floatClose {
|
|
909
|
+
display: inline-flex;
|
|
910
|
+
align-items: center;
|
|
911
|
+
justify-content: center;
|
|
912
|
+
width: 18px;
|
|
913
|
+
height: 18px;
|
|
914
|
+
padding: 0;
|
|
915
|
+
border: none;
|
|
916
|
+
border-radius: 4px;
|
|
917
|
+
background: transparent;
|
|
918
|
+
color: var(--dsw-alias-label-tertiary);
|
|
919
|
+
cursor: pointer;
|
|
920
|
+
flex: none;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
.floatClose:hover {
|
|
924
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
925
|
+
color: var(--dsw-alias-label-primary);
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/* Mirrors .paneContent's column-flex contract: the tab cell must hand its
|
|
929
|
+
child a definite WIDTH via align-stretch. A row flex (the default) sizes
|
|
930
|
+
the main axis (width) from content — intrinsic-zero hosts (e.g. a plugin
|
|
931
|
+
tab UI) collapse to a 0px-wide sliver and paint nothing (the blank
|
|
932
|
+
whale-report window). */
|
|
933
|
+
.floatContent {
|
|
934
|
+
flex: 1;
|
|
935
|
+
min-height: 0;
|
|
936
|
+
min-width: 0;
|
|
937
|
+
display: flex;
|
|
938
|
+
flex-direction: column;
|
|
939
|
+
overflow: hidden;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
/* The SE resize corner (mirror of .cornerHandle). */
|
|
943
|
+
.floatResize {
|
|
944
|
+
position: absolute;
|
|
945
|
+
right: 0;
|
|
946
|
+
bottom: 0;
|
|
947
|
+
width: 14px;
|
|
948
|
+
height: 14px;
|
|
949
|
+
z-index: 2;
|
|
950
|
+
cursor: nwse-resize;
|
|
951
|
+
touch-action: none;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
.floatResize:hover {
|
|
955
|
+
background: var(--dsw-alias-interactive-bg-hover-accent);
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
/* A pane highlighted as the dock target while a float header drag hovers it
|
|
959
|
+
(the attribute is written directly by the drag at pointer cadence;
|
|
960
|
+
skin-addressable via [data-dsh-pane][data-dsh-float-dock-over]). */
|
|
961
|
+
.pane[data-dsh-float-dock-over] {
|
|
962
|
+
outline: 2px dashed var(--dsw-alias-interactive-bg-hover-accent);
|
|
963
|
+
outline-offset: -2px;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/* The drag-out hint over the conversation column: a dashed frame marking
|
|
967
|
+
the drop zone, pointer-transparent so it never disturbs the drag it
|
|
968
|
+
describes. z-index 46: above the windows (42) for unambiguous feedback,
|
|
969
|
+
still below the app's overlay stack. */
|
|
970
|
+
.floatDropHint {
|
|
971
|
+
position: absolute;
|
|
972
|
+
z-index: 46;
|
|
973
|
+
pointer-events: none;
|
|
974
|
+
border: 2px dashed var(--dsw-alias-interactive-bg-hover-accent);
|
|
975
|
+
border-radius: 8px;
|
|
976
|
+
background: color-mix(in srgb, var(--dsw-alias-interactive-bg-hover-accent) 12%, transparent);
|
|
977
|
+
display: flex;
|
|
978
|
+
align-items: center;
|
|
979
|
+
justify-content: center;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
.floatDropHintLabel {
|
|
983
|
+
padding: 4px 12px;
|
|
984
|
+
border-radius: 999px;
|
|
985
|
+
font: var(--dsw-font-xxs-12);
|
|
986
|
+
color: var(--dsw-alias-label-primary);
|
|
987
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
988
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
/* ── Desktop drag-region opt-out ──────────────────────────────────────── */
|
|
992
|
+
|
|
993
|
+
/* Frameless desktop shells make the top strip of the web content draggable
|
|
994
|
+
(Electron `-webkit-app-region: drag`); pointer events over that strip are
|
|
995
|
+
swallowed as window drags unless the interactive element opts out
|
|
996
|
+
(issues #103/#111). The plugin's viewport-corner chrome must declare
|
|
997
|
+
`no-drag` itself — some shells (Tauri, older desktop builds, third-party
|
|
998
|
+
wrappers) have no blanket button rule. The property is a no-op in plain
|
|
999
|
+
browsers and in shells without drag regions — safe everywhere. */
|
|
1000
|
+
.toggleCluster,
|
|
1001
|
+
.toggleButton,
|
|
1002
|
+
.manualButton,
|
|
1003
|
+
.tabBar,
|
|
1004
|
+
.floatHeader {
|
|
1005
|
+
-webkit-app-region: no-drag;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
/* ── Position compatibility mode (Windows native title bar) ────────────── */
|
|
1009
|
+
|
|
1010
|
+
/* Windows frameless / hidden-title-bar windows draw the native caption
|
|
1011
|
+
strip (minimize / maximize / close) at the window's top-right corner,
|
|
1012
|
+
OVER the web content. When the user enables the "position compatibility"
|
|
1013
|
+
pref, the sidebar yields the strip: the toggle cluster drops below it and
|
|
1014
|
+
the right panel's content starts below it — the panel's surface still
|
|
1015
|
+
spans the full height, so the caption buttons float over empty sidebar
|
|
1016
|
+
fill (the VSCode hidden-title-bar look). The strip height is user-tunable
|
|
1017
|
+
(`--dsh-title-bar-strip`, written by the Sidebar shell from
|
|
1018
|
+
`titleBarStripPx`; 40px fallback). The bottom panel is unaffected: it
|
|
1019
|
+
sits at the window's bottom, never under the top strip. */
|
|
1020
|
+
:global(body[data-dsh-title-bar-compat]) .toggleCluster {
|
|
1021
|
+
top: var(--dsh-native-sidebar-toggle-top, calc(var(--dsh-title-bar-strip, 40px) + 3px));
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
:global(body[data-dsh-title-bar-compat]) .panel {
|
|
1025
|
+
/* The caption strip is drawn over the panel's own top edge: keep the
|
|
1026
|
+
surface full-height and push the content (the tab strip) below the
|
|
1027
|
+
strip instead. .panelResize is absolutely positioned and unaffected. */
|
|
1028
|
+
padding-top: var(--dsh-title-bar-strip, 40px);
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
/* The shared corner (both panels open): the intersection of the right
|
|
1032
|
+
panel's left edge and the bottom panel's top edge. Horizontal drags
|
|
1033
|
+
resize the width, vertical drags the height — the two panels drag
|
|
1034
|
+
against each other. Rendered INSIDE the right panel and positioned
|
|
1035
|
+
relative to it (left edge + the bottom panel's height from the layout
|
|
1036
|
+
variable), so no JS-written viewport coordinates are involved. The
|
|
1037
|
+
z-index is panel-local (above the panel's content; the panel itself sits
|
|
1038
|
+
at 40, below the app's overlay stack). */
|
|
1039
|
+
.cornerHandle {
|
|
1040
|
+
position: absolute;
|
|
1041
|
+
left: -6px;
|
|
1042
|
+
bottom: calc(var(--dsh-sidebar-height, 0px) + 6px);
|
|
1043
|
+
width: 12px;
|
|
1044
|
+
height: 12px;
|
|
1045
|
+
z-index: 2;
|
|
1046
|
+
cursor: nwse-resize;
|
|
1047
|
+
touch-action: none;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
.cornerHandle:hover,
|
|
1051
|
+
.cornerHandle[data-dragging] {
|
|
1052
|
+
background: var(--dsw-alias-interactive-bg-hover-accent);
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
/* Icon button: the app's own icon-button pattern (ui-workspace) — a 28px
|
|
1056
|
+
circle, secondary label, hover fill; no border so the icon alone is the
|
|
1057
|
+
affordance. */
|
|
1058
|
+
.iconButton {
|
|
1059
|
+
display: inline-flex;
|
|
1060
|
+
align-items: center;
|
|
1061
|
+
justify-content: center;
|
|
1062
|
+
width: 28px;
|
|
1063
|
+
height: 28px;
|
|
1064
|
+
padding: 0;
|
|
1065
|
+
border: none;
|
|
1066
|
+
border-radius: 50%;
|
|
1067
|
+
background: transparent;
|
|
1068
|
+
color: var(--dsw-alias-label-secondary);
|
|
1069
|
+
cursor: pointer;
|
|
1070
|
+
flex: none;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
.iconButton:hover:not(:disabled) {
|
|
1074
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
1075
|
+
color: var(--dsw-alias-label-primary);
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
.iconButton:disabled {
|
|
1079
|
+
opacity: 0.4;
|
|
1080
|
+
cursor: default;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
/* ── Workbench / split panes ───────────────────────────────────────────── */
|
|
1084
|
+
|
|
1085
|
+
.workbench {
|
|
1086
|
+
flex: 1;
|
|
1087
|
+
min-width: 0;
|
|
1088
|
+
min-height: 0;
|
|
1089
|
+
display: flex;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
.split {
|
|
1093
|
+
flex: 1;
|
|
1094
|
+
min-width: 0;
|
|
1095
|
+
min-height: 0;
|
|
1096
|
+
display: flex;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
.splitRow {
|
|
1100
|
+
flex-direction: row;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
.splitCol {
|
|
1104
|
+
flex-direction: column;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
.splitChild {
|
|
1108
|
+
position: relative;
|
|
1109
|
+
display: flex;
|
|
1110
|
+
overflow: hidden;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
.divider {
|
|
1114
|
+
position: relative;
|
|
1115
|
+
flex: none;
|
|
1116
|
+
z-index: 3;
|
|
1117
|
+
touch-action: none;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
/* The hit area stays 7px wide enough to grab, but the visual is a 1px
|
|
1121
|
+
hairline centered in it — a divider line, not a thick band. */
|
|
1122
|
+
.dividerRow::after,
|
|
1123
|
+
.dividerCol::after {
|
|
1124
|
+
content: '';
|
|
1125
|
+
position: absolute;
|
|
1126
|
+
background: var(--dsw-alias-border-l2);
|
|
1127
|
+
transition: background var(--ds-transition-duration-slow) var(--ds-ease-in-out);
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
.dividerRow {
|
|
1131
|
+
width: 7px;
|
|
1132
|
+
margin: 0 -2px;
|
|
1133
|
+
cursor: col-resize;
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
.dividerRow::after {
|
|
1137
|
+
top: 0;
|
|
1138
|
+
bottom: 0;
|
|
1139
|
+
left: 50%;
|
|
1140
|
+
width: 1px;
|
|
1141
|
+
transform: translateX(-50%);
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
.dividerCol {
|
|
1145
|
+
height: 7px;
|
|
1146
|
+
margin: -2px 0;
|
|
1147
|
+
cursor: row-resize;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
.dividerCol::after {
|
|
1151
|
+
left: 0;
|
|
1152
|
+
right: 0;
|
|
1153
|
+
top: 50%;
|
|
1154
|
+
height: 1px;
|
|
1155
|
+
transform: translateY(-50%);
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
.divider:hover::after,
|
|
1159
|
+
.dividerActive::after {
|
|
1160
|
+
background: var(--dsw-alias-interactive-bg-hover-accent);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
.pane {
|
|
1164
|
+
position: relative;
|
|
1165
|
+
flex: 1;
|
|
1166
|
+
min-width: 0;
|
|
1167
|
+
min-height: 0;
|
|
1168
|
+
display: flex;
|
|
1169
|
+
flex-direction: column;
|
|
1170
|
+
background: var(--dsw-alias-bg-base);
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
.paneDrop {
|
|
1174
|
+
outline: 1px solid var(--dsw-alias-interactive-bg-hover-accent);
|
|
1175
|
+
outline-offset: -1px;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
/* VSCode-style drag-to-edge drop zones (25% edges, 50% center). */
|
|
1179
|
+
.dropOverlay {
|
|
1180
|
+
position: absolute;
|
|
1181
|
+
z-index: 6;
|
|
1182
|
+
pointer-events: none;
|
|
1183
|
+
background: var(--dsw-alias-interactive-bg-hover-accent);
|
|
1184
|
+
opacity: 0.5;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
.dropLeft {
|
|
1188
|
+
left: 0;
|
|
1189
|
+
top: 0;
|
|
1190
|
+
bottom: 0;
|
|
1191
|
+
width: 25%;
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
.dropRight {
|
|
1195
|
+
right: 0;
|
|
1196
|
+
top: 0;
|
|
1197
|
+
bottom: 0;
|
|
1198
|
+
width: 25%;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
.dropUp {
|
|
1202
|
+
top: 0;
|
|
1203
|
+
left: 0;
|
|
1204
|
+
right: 0;
|
|
1205
|
+
height: 25%;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
.dropDown {
|
|
1209
|
+
bottom: 0;
|
|
1210
|
+
left: 0;
|
|
1211
|
+
right: 0;
|
|
1212
|
+
height: 25%;
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
.dropCenter {
|
|
1216
|
+
left: 25%;
|
|
1217
|
+
right: 25%;
|
|
1218
|
+
top: 25%;
|
|
1219
|
+
bottom: 25%;
|
|
1220
|
+
background: transparent;
|
|
1221
|
+
outline: 2px dashed var(--dsw-alias-interactive-bg-hover-accent);
|
|
1222
|
+
outline-offset: -2px;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
.paneContent {
|
|
1226
|
+
flex: 1;
|
|
1227
|
+
min-height: 0;
|
|
1228
|
+
display: flex;
|
|
1229
|
+
flex-direction: column;
|
|
1230
|
+
overflow: hidden;
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
/* One tab's mounted content; inactive tabs stay mounted but hidden so
|
|
1234
|
+
switching never tears down terminals/editors (state survives). */
|
|
1235
|
+
.paneTab {
|
|
1236
|
+
flex: 1;
|
|
1237
|
+
min-height: 0;
|
|
1238
|
+
display: flex;
|
|
1239
|
+
flex-direction: column;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
.paneTabHidden {
|
|
1243
|
+
display: none;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
/* An empty pane's welcome cards: a responsive grid of compact cards — as
|
|
1247
|
+
many per row as the pane width allows; rows that cannot fit the pane
|
|
1248
|
+
height are clipped (never scrolled or squeezed smaller). */
|
|
1249
|
+
.paneEmptyCards {
|
|
1250
|
+
flex: 1;
|
|
1251
|
+
min-height: 0;
|
|
1252
|
+
display: grid;
|
|
1253
|
+
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
|
1254
|
+
align-content: start;
|
|
1255
|
+
gap: 8px;
|
|
1256
|
+
padding: 12px;
|
|
1257
|
+
overflow: hidden;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
.paneCard {
|
|
1261
|
+
display: flex;
|
|
1262
|
+
flex-direction: column;
|
|
1263
|
+
align-items: center;
|
|
1264
|
+
justify-content: center;
|
|
1265
|
+
gap: 6px;
|
|
1266
|
+
min-width: 0;
|
|
1267
|
+
padding: 12px 8px;
|
|
1268
|
+
border: 1px solid var(--dsw-alias-border-l1);
|
|
1269
|
+
border-radius: 8px;
|
|
1270
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
1271
|
+
color: var(--dsw-alias-label-secondary);
|
|
1272
|
+
font: var(--dsw-font-xxs-strong-12);
|
|
1273
|
+
cursor: pointer;
|
|
1274
|
+
text-align: center;
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
.paneCard:hover:not(:disabled) {
|
|
1278
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
1279
|
+
color: var(--dsw-alias-label-primary);
|
|
1280
|
+
border-color: var(--dsw-alias-border-l2);
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
.paneCard:disabled {
|
|
1284
|
+
opacity: 0.45;
|
|
1285
|
+
cursor: default;
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
/* ── Tab strip ─────────────────────────────────────────────────────────── */
|
|
1289
|
+
|
|
1290
|
+
.tabBar {
|
|
1291
|
+
flex: none;
|
|
1292
|
+
display: flex;
|
|
1293
|
+
align-items: stretch;
|
|
1294
|
+
height: 34px;
|
|
1295
|
+
border-bottom: 1px solid var(--dsw-alias-border-l1);
|
|
1296
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
.tabBarDrop {
|
|
1300
|
+
outline: 1px dashed var(--dsw-alias-interactive-bg-hover-accent);
|
|
1301
|
+
outline-offset: -1px;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
.tabList {
|
|
1305
|
+
flex: 1;
|
|
1306
|
+
min-width: 0;
|
|
1307
|
+
display: flex;
|
|
1308
|
+
overflow-x: auto;
|
|
1309
|
+
scrollbar-width: none;
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
.tabList::-webkit-scrollbar {
|
|
1313
|
+
display: none;
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
.tab {
|
|
1317
|
+
flex: none;
|
|
1318
|
+
max-width: 160px;
|
|
1319
|
+
min-width: 64px;
|
|
1320
|
+
display: flex;
|
|
1321
|
+
align-items: center;
|
|
1322
|
+
gap: 4px;
|
|
1323
|
+
padding: 0 4px 0 10px;
|
|
1324
|
+
font: var(--dsw-font-xxs-12);
|
|
1325
|
+
color: var(--dsw-alias-label-secondary);
|
|
1326
|
+
border-right: 1px solid var(--dsw-alias-border-l1);
|
|
1327
|
+
background: transparent;
|
|
1328
|
+
cursor: pointer;
|
|
1329
|
+
user-select: none;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
.tab:hover {
|
|
1333
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
.tabActive {
|
|
1337
|
+
color: var(--dsw-alias-label-primary);
|
|
1338
|
+
/* Native selected fill (Rows .sessionRow.selected) — no underline, no shadow. */
|
|
1339
|
+
background: var(--dsw-alias-interactive-bg-active);
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
.tabTitle {
|
|
1343
|
+
flex: 1;
|
|
1344
|
+
min-width: 0;
|
|
1345
|
+
overflow: hidden;
|
|
1346
|
+
text-overflow: ellipsis;
|
|
1347
|
+
white-space: nowrap;
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
/* One tab's descriptor badge (a count capped at 99+, or a short text). */
|
|
1351
|
+
.tabBadge {
|
|
1352
|
+
flex: none;
|
|
1353
|
+
min-width: 16px;
|
|
1354
|
+
height: 15px;
|
|
1355
|
+
padding: 0 4px;
|
|
1356
|
+
display: inline-flex;
|
|
1357
|
+
align-items: center;
|
|
1358
|
+
justify-content: center;
|
|
1359
|
+
border-radius: 8px;
|
|
1360
|
+
font: var(--dsw-font-xxxs-strong-11);
|
|
1361
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
1362
|
+
color: var(--dsw-alias-brand-primary);
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
.tabClose {
|
|
1366
|
+
display: inline-flex;
|
|
1367
|
+
align-items: center;
|
|
1368
|
+
justify-content: center;
|
|
1369
|
+
width: 18px;
|
|
1370
|
+
height: 18px;
|
|
1371
|
+
padding: 0;
|
|
1372
|
+
border: none;
|
|
1373
|
+
border-radius: 4px;
|
|
1374
|
+
background: transparent;
|
|
1375
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1376
|
+
cursor: pointer;
|
|
1377
|
+
flex: none;
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
.tabClose:hover {
|
|
1381
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
1382
|
+
color: var(--dsw-alias-label-primary);
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
.tabBarPlus {
|
|
1386
|
+
flex: none;
|
|
1387
|
+
align-self: center;
|
|
1388
|
+
/* Adjacent to the rightmost tab; sticky so overflowing tab rows keep it
|
|
1389
|
+
visible at the right edge of the scrollport. */
|
|
1390
|
+
position: sticky;
|
|
1391
|
+
right: 0;
|
|
1392
|
+
display: inline-flex;
|
|
1393
|
+
align-items: center;
|
|
1394
|
+
justify-content: center;
|
|
1395
|
+
width: 22px;
|
|
1396
|
+
height: 22px;
|
|
1397
|
+
margin: 0 6px;
|
|
1398
|
+
padding: 0;
|
|
1399
|
+
border: none;
|
|
1400
|
+
border-radius: 5px;
|
|
1401
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
1402
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1403
|
+
cursor: pointer;
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
.tabBarPlus:hover {
|
|
1407
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
1408
|
+
color: var(--dsw-alias-label-primary);
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
/* ── Pinned-terminal tab (v0.17.0+) ───────────────────────────────────── */
|
|
1412
|
+
|
|
1413
|
+
/* Pinned virtual tabs (injected from other sessions) render inline in the
|
|
1414
|
+
tab bar with a pin icon and a subtle tint to distinguish them from the
|
|
1415
|
+
session's own tabs. Token-driven so skins follow. */
|
|
1416
|
+
.pinnedTab {
|
|
1417
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1418
|
+
font-style: italic;
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
.pinnedTab:hover {
|
|
1422
|
+
color: var(--dsw-alias-label-secondary);
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
/* ── Explorer ──────────────────────────────────────────────────────────── */
|
|
1426
|
+
|
|
1427
|
+
.explorer {
|
|
1428
|
+
flex: 1;
|
|
1429
|
+
min-height: 0;
|
|
1430
|
+
display: flex;
|
|
1431
|
+
flex-direction: column;
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
.explorerHeader {
|
|
1435
|
+
flex: none;
|
|
1436
|
+
display: flex;
|
|
1437
|
+
align-items: center;
|
|
1438
|
+
justify-content: space-between;
|
|
1439
|
+
gap: 8px;
|
|
1440
|
+
height: 36px;
|
|
1441
|
+
padding: 0 8px 0 12px;
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
.explorerRoot {
|
|
1445
|
+
font: var(--dsw-font-s-14);
|
|
1446
|
+
color: var(--dsw-alias-label-secondary);
|
|
1447
|
+
overflow: hidden;
|
|
1448
|
+
text-overflow: ellipsis;
|
|
1449
|
+
white-space: nowrap;
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
.explorerBody {
|
|
1453
|
+
flex: 1;
|
|
1454
|
+
min-height: 0;
|
|
1455
|
+
overflow-y: auto;
|
|
1456
|
+
/* Deep trees truncate their labels instead of scrolling horizontally. */
|
|
1457
|
+
overflow-x: hidden;
|
|
1458
|
+
padding: 4px 8px 8px;
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
/* One tree row: the app's session-row cell (34px, radius 8, inset, hover
|
|
1462
|
+
fill, 22px indent step, 14px ink) with a mount fade so expanding a
|
|
1463
|
+
directory reveals its children gently (stable keys keep existing rows from
|
|
1464
|
+
replaying it). */
|
|
1465
|
+
.explorerRow {
|
|
1466
|
+
display: flex;
|
|
1467
|
+
align-items: center;
|
|
1468
|
+
gap: 6px;
|
|
1469
|
+
/* border-box keeps the inline indent padding (depth * 22 + 6) INSIDE the
|
|
1470
|
+
row's 100% width — without it deep rows overflow and force a horizontal
|
|
1471
|
+
scrollbar on the tree body. */
|
|
1472
|
+
box-sizing: border-box;
|
|
1473
|
+
width: 100%;
|
|
1474
|
+
max-width: 100%;
|
|
1475
|
+
height: 34px;
|
|
1476
|
+
padding: 0 8px;
|
|
1477
|
+
border: none;
|
|
1478
|
+
background: transparent;
|
|
1479
|
+
font: var(--dsw-font-s-14);
|
|
1480
|
+
color: var(--dsw-alias-label-primary);
|
|
1481
|
+
text-align: left;
|
|
1482
|
+
cursor: pointer;
|
|
1483
|
+
white-space: nowrap;
|
|
1484
|
+
border-radius: 8px;
|
|
1485
|
+
animation: dsh-row-in 150ms var(--ds-ease-in-out);
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
.explorerRow:hover {
|
|
1489
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
/* A "Show in folder" reveal highlight: the target row stays tinted until
|
|
1493
|
+
the transient reveal set is cleared (a reload starts unhighlighted).
|
|
1494
|
+
The DSH business-blue surface (the same source the host's nav items use
|
|
1495
|
+
for their active accent) — a flat tint, deliberately no left bar. */
|
|
1496
|
+
.explorerRowRevealed {
|
|
1497
|
+
background: var(--dsw-alias-state-business-tertiary);
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
/* Reveal sets usually list sibling files — consecutive tinted rows merge
|
|
1501
|
+
into ONE rounded block: the touching edges square off, so a multi-file
|
|
1502
|
+
highlight has no per-row radius notches. A solo revealed row (or the
|
|
1503
|
+
first/last of a run) keeps its full radius. Rows are flat siblings in
|
|
1504
|
+
the tree body (depth is inline padding), so the sibling combinator sees
|
|
1505
|
+
every adjacency. */
|
|
1506
|
+
.explorerRowRevealed + .explorerRowRevealed {
|
|
1507
|
+
border-top-left-radius: 0;
|
|
1508
|
+
border-top-right-radius: 0;
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
.explorerRowRevealed:has(+ .explorerRowRevealed) {
|
|
1512
|
+
border-bottom-left-radius: 0;
|
|
1513
|
+
border-bottom-right-radius: 0;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
.explorerDir {
|
|
1517
|
+
font: var(--dsw-font-s-strong-14);
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
.explorerHidden {
|
|
1521
|
+
opacity: 0.45;
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
/* The link badge on symlink rows (folder and file rows alike). */
|
|
1525
|
+
.explorerSymlink {
|
|
1526
|
+
flex: none;
|
|
1527
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
/* A symlink whose target is missing: error ink on the name (the row stays
|
|
1531
|
+
clickable — the editor surfaces the read failure). */
|
|
1532
|
+
.explorerBroken .explorerName {
|
|
1533
|
+
color: var(--dsw-alias-state-error-primary);
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
.explorerName {
|
|
1537
|
+
/* min-width: 0 lets the flex item shrink below its content so the label
|
|
1538
|
+
truncates with an ellipsis instead of widening the row. */
|
|
1539
|
+
min-width: 0;
|
|
1540
|
+
overflow: hidden;
|
|
1541
|
+
text-overflow: ellipsis;
|
|
1542
|
+
white-space: nowrap;
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
/* The hover-revealed @-reference button at the row's far right (and the
|
|
1546
|
+
transient "copied" label that replaces it after a copy). Hidden rows
|
|
1547
|
+
keep the name at full width; hovering or focusing the row reveals it. */
|
|
1548
|
+
.explorerRef {
|
|
1549
|
+
flex: none;
|
|
1550
|
+
display: none;
|
|
1551
|
+
align-items: center;
|
|
1552
|
+
height: 20px;
|
|
1553
|
+
padding: 0 8px;
|
|
1554
|
+
border: 1px solid var(--dsw-alias-border-l1);
|
|
1555
|
+
border-radius: 999px;
|
|
1556
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
1557
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1558
|
+
font: var(--dsw-font-xxxs-strong-11);
|
|
1559
|
+
cursor: pointer;
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
.explorerRef:hover {
|
|
1563
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
1564
|
+
color: var(--dsw-alias-label-primary);
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
.explorerRow:hover .explorerRef,
|
|
1568
|
+
.explorerRow:focus-within .explorerRef {
|
|
1569
|
+
display: inline-flex;
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
.explorerCopied {
|
|
1573
|
+
flex: none;
|
|
1574
|
+
font: var(--dsw-font-xxxs-11);
|
|
1575
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
.explorerError {
|
|
1579
|
+
font: var(--dsw-font-xxs-12);
|
|
1580
|
+
color: var(--dsw-alias-state-error-primary);
|
|
1581
|
+
cursor: default;
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
/* Mount fade for tree rows (the app's session-row reveal). */
|
|
1585
|
+
@keyframes dsh-row-in {
|
|
1586
|
+
from { opacity: 0; }
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
.explorerEmpty {
|
|
1590
|
+
padding: 16px;
|
|
1591
|
+
font: var(--dsw-font-xxs-12);
|
|
1592
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1593
|
+
text-align: center;
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
/* Drag a file/folder over a tree row: the target directory row gets a filled
|
|
1597
|
+
highlight (drops land inside it; file rows target their parent directory).
|
|
1598
|
+
The zone frame around the whole tree is the portaled .uploadDropZone. */
|
|
1599
|
+
.explorerRowDropTarget {
|
|
1600
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
1601
|
+
outline: 1px dashed var(--dsw-alias-interactive-bg-hover-accent);
|
|
1602
|
+
outline-offset: -1px;
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
/* The sidebar's drop surface: a pointer-inert frame portaled to
|
|
1606
|
+
document.body, fixed over the explorer body's viewport rect at z-1001 —
|
|
1607
|
+
above DSH's own whole-page drop mask (z-1000, see InputBar's
|
|
1608
|
+
document-level intake). The giant box-shadow spread IS the full-viewport
|
|
1609
|
+
mask (same token DSH uses for its drop mask): everything dims except the
|
|
1610
|
+
zone rect, teaching the zone split — the dimmed conversation column still
|
|
1611
|
+
takes drops into the chat natively, the clear frame marks the tree as the
|
|
1612
|
+
workspace-upload zone. Deliberate exception to the "panel stays below the
|
|
1613
|
+
DSH float stack" rule: transient and pointer-events none, so the drop
|
|
1614
|
+
always lands on the row beneath. The hint pill docks at the TOP edge of
|
|
1615
|
+
the zone (right under the search row, the first thing the eye meets),
|
|
1616
|
+
leaving the rows — the actual drop targets — aimable. */
|
|
1617
|
+
.uploadDropZone {
|
|
1618
|
+
position: fixed;
|
|
1619
|
+
z-index: 1001;
|
|
1620
|
+
pointer-events: none;
|
|
1621
|
+
display: flex;
|
|
1622
|
+
align-items: flex-start;
|
|
1623
|
+
justify-content: center;
|
|
1624
|
+
padding: 12px;
|
|
1625
|
+
border: 2px dashed var(--dsw-alias-interactive-bg-hover-accent);
|
|
1626
|
+
border-radius: 10px;
|
|
1627
|
+
box-shadow: 0 0 0 200vmax var(--dsw-alias-bg-mask-drop);
|
|
1628
|
+
animation: dsh-row-in 150ms var(--ds-ease-in-out);
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
/* The zone's drop hero, docked at the TOP edge (right under the search
|
|
1632
|
+
row, the first thing the eye meets): the colorful tray illustration over
|
|
1633
|
+
the hint pill — stacked so the rows below stay aimable. */
|
|
1634
|
+
.uploadDropHero {
|
|
1635
|
+
display: flex;
|
|
1636
|
+
flex-direction: column;
|
|
1637
|
+
align-items: center;
|
|
1638
|
+
gap: 10px;
|
|
1639
|
+
max-width: 100%;
|
|
1640
|
+
padding-top: 8px;
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
.uploadDropZonePill {
|
|
1644
|
+
display: flex;
|
|
1645
|
+
align-items: center;
|
|
1646
|
+
gap: 6px;
|
|
1647
|
+
max-width: 100%;
|
|
1648
|
+
padding: 6px 12px;
|
|
1649
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
1650
|
+
border-radius: 999px;
|
|
1651
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
1652
|
+
box-shadow: var(--dsw-shadow-lv2);
|
|
1653
|
+
color: var(--dsw-alias-label-primary);
|
|
1654
|
+
font: var(--dsw-font-xxs-strong-12);
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
.uploadDropZoneText {
|
|
1658
|
+
white-space: nowrap;
|
|
1659
|
+
overflow: hidden;
|
|
1660
|
+
text-overflow: ellipsis;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
/* The left zone's invitation: centered in the viewport space beside the
|
|
1664
|
+
tree (inline width = the zone's left edge), telling the user the dimmed
|
|
1665
|
+
conversation column still accepts drops — into the chat, natively. */
|
|
1666
|
+
.uploadDropChatHint {
|
|
1667
|
+
position: fixed;
|
|
1668
|
+
top: 0;
|
|
1669
|
+
left: 0;
|
|
1670
|
+
bottom: 0;
|
|
1671
|
+
z-index: 1002;
|
|
1672
|
+
pointer-events: none;
|
|
1673
|
+
display: flex;
|
|
1674
|
+
align-items: center;
|
|
1675
|
+
justify-content: center;
|
|
1676
|
+
padding: 24px;
|
|
1677
|
+
animation: dsh-row-in 150ms var(--ds-ease-in-out);
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
/* The invitation's content: the colorful photo-cards illustration over the
|
|
1681
|
+
label — the drop overlay is this flow's one brand moment, so it gets the
|
|
1682
|
+
color the rest of the UI never does (palette borrowed from DSH's native
|
|
1683
|
+
drop illustration so the two zones read as one family). */
|
|
1684
|
+
.uploadDropChatCard {
|
|
1685
|
+
display: flex;
|
|
1686
|
+
flex-direction: column;
|
|
1687
|
+
align-items: center;
|
|
1688
|
+
gap: 12px;
|
|
1689
|
+
max-width: 100%;
|
|
1690
|
+
text-align: center;
|
|
1691
|
+
color: var(--dsw-alias-label-primary);
|
|
1692
|
+
font: var(--dsw-font-s-strong-14);
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
/* Full-window upload progress: blurred scrim + card (same mask/backdrop
|
|
1696
|
+
tokens as the repo's Modal primitive; absolute within the tree panel so it
|
|
1697
|
+
never covers the conversation column). */
|
|
1698
|
+
.uploadOverlay {
|
|
1699
|
+
position: absolute;
|
|
1700
|
+
inset: 0;
|
|
1701
|
+
z-index: 30;
|
|
1702
|
+
display: flex;
|
|
1703
|
+
align-items: center;
|
|
1704
|
+
justify-content: center;
|
|
1705
|
+
background: var(--dsw-alias-bg-mask-1);
|
|
1706
|
+
backdrop-filter: var(--dsw-mask-blur);
|
|
1707
|
+
animation: dsh-row-in 150ms var(--ds-ease-in-out);
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
.uploadOverlayCard {
|
|
1711
|
+
display: flex;
|
|
1712
|
+
flex-direction: column;
|
|
1713
|
+
gap: 12px;
|
|
1714
|
+
min-width: 280px;
|
|
1715
|
+
max-width: min(420px, calc(100% - 48px));
|
|
1716
|
+
padding: 20px 24px;
|
|
1717
|
+
border: 1px solid var(--dsw-alias-border-inverted);
|
|
1718
|
+
border-radius: 24px;
|
|
1719
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
1720
|
+
box-shadow: var(--dsw-shadow-lv3);
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
.uploadOverlayTitle {
|
|
1724
|
+
display: flex;
|
|
1725
|
+
align-items: center;
|
|
1726
|
+
gap: 8px;
|
|
1727
|
+
font: var(--dsw-font-s-strong-14);
|
|
1728
|
+
color: var(--dsw-alias-label-primary);
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1731
|
+
.uploadOverlayTitle > svg {
|
|
1732
|
+
flex: none;
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
.uploadOverlayTitle > span {
|
|
1736
|
+
min-width: 0;
|
|
1737
|
+
white-space: nowrap;
|
|
1738
|
+
overflow: hidden;
|
|
1739
|
+
text-overflow: ellipsis;
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
.uploadOverlayProgress {
|
|
1743
|
+
height: 6px;
|
|
1744
|
+
border-radius: 3px;
|
|
1745
|
+
background: var(--dsw-alias-border-l2);
|
|
1746
|
+
overflow: hidden;
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
.uploadOverlayProgressFill {
|
|
1750
|
+
height: 100%;
|
|
1751
|
+
border-radius: 3px;
|
|
1752
|
+
background: var(--dsw-alias-interactive-bg-hover-accent);
|
|
1753
|
+
transition: width 150ms var(--ds-ease-in-out);
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
.uploadOverlayStatus {
|
|
1757
|
+
min-height: 1em;
|
|
1758
|
+
font: var(--dsw-font-xxs-12);
|
|
1759
|
+
font-variant-numeric: tabular-nums;
|
|
1760
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1761
|
+
white-space: nowrap;
|
|
1762
|
+
overflow: hidden;
|
|
1763
|
+
text-overflow: ellipsis;
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
.uploadOverlayCancel {
|
|
1767
|
+
align-self: flex-end;
|
|
1768
|
+
height: 28px;
|
|
1769
|
+
padding: 0 14px;
|
|
1770
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
1771
|
+
border-radius: 8px;
|
|
1772
|
+
background: transparent;
|
|
1773
|
+
color: var(--dsw-alias-label-primary);
|
|
1774
|
+
font: var(--dsw-font-xxs-strong-12);
|
|
1775
|
+
cursor: pointer;
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
.uploadOverlayCancel:hover:not(:disabled) {
|
|
1779
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
1780
|
+
border-color: var(--dsw-alias-border-l2);
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
.uploadOverlayCancel:disabled {
|
|
1784
|
+
opacity: 0.4;
|
|
1785
|
+
cursor: default;
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
/* ── Editor ────────────────────────────────────────────────────────────── */
|
|
1789
|
+
|
|
1790
|
+
.editor {
|
|
1791
|
+
flex: 1;
|
|
1792
|
+
min-height: 0;
|
|
1793
|
+
display: flex;
|
|
1794
|
+
flex-direction: column;
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
.editorHeader {
|
|
1798
|
+
flex: none;
|
|
1799
|
+
display: flex;
|
|
1800
|
+
align-items: center;
|
|
1801
|
+
gap: 6px;
|
|
1802
|
+
padding: 6px 8px;
|
|
1803
|
+
border-bottom: 1px solid var(--dsw-alias-border-l1);
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
.editorTitle {
|
|
1807
|
+
flex: 1;
|
|
1808
|
+
min-width: 0;
|
|
1809
|
+
font: var(--dsw-font-xxs-strong-12);
|
|
1810
|
+
color: var(--dsw-alias-label-secondary);
|
|
1811
|
+
overflow: hidden;
|
|
1812
|
+
text-overflow: ellipsis;
|
|
1813
|
+
white-space: nowrap;
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
/* Merged mode (the editorExplorer pref): the header's path input replaces
|
|
1817
|
+
the plain title, and a toggleable file tree docks at the tab's right edge. */
|
|
1818
|
+
.editorPathInput {
|
|
1819
|
+
flex: 1;
|
|
1820
|
+
min-width: 0;
|
|
1821
|
+
box-sizing: border-box;
|
|
1822
|
+
height: 28px;
|
|
1823
|
+
padding: 0 10px;
|
|
1824
|
+
border: 1px solid var(--dsw-alias-border-l1);
|
|
1825
|
+
border-radius: 6px;
|
|
1826
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
1827
|
+
color: var(--dsw-alias-label-primary);
|
|
1828
|
+
font: var(--dsw-font-xxs-12);
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
.editorPathInput:focus {
|
|
1832
|
+
outline: none;
|
|
1833
|
+
border-color: var(--dsw-alias-border-l2);
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
/* The tree-panel toggle in the header: active = panel open (the selected
|
|
1837
|
+
fill of the tab strip). */
|
|
1838
|
+
.editorTreeToggleActive {
|
|
1839
|
+
color: var(--dsw-alias-label-primary);
|
|
1840
|
+
background: var(--dsw-alias-interactive-bg-active);
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
.editorBody {
|
|
1844
|
+
flex: 1;
|
|
1845
|
+
min-height: 0;
|
|
1846
|
+
display: flex;
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
.editorMain {
|
|
1850
|
+
flex: 1;
|
|
1851
|
+
min-width: 0;
|
|
1852
|
+
min-height: 0;
|
|
1853
|
+
display: flex;
|
|
1854
|
+
flex-direction: column;
|
|
1855
|
+
}
|
|
1856
|
+
|
|
1857
|
+
/* The docked file tree: the wrapper owns the (drag-adjustable) width and
|
|
1858
|
+
the hairline separation; the resize handle is a wider invisible strip on
|
|
1859
|
+
its left edge with a hover affordance. */
|
|
1860
|
+
.editorTreeDock {
|
|
1861
|
+
position: relative;
|
|
1862
|
+
flex: none;
|
|
1863
|
+
min-height: 0;
|
|
1864
|
+
display: flex;
|
|
1865
|
+
border-left: 1px solid var(--dsw-alias-border-l1);
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
.editorTreeResize {
|
|
1869
|
+
position: absolute;
|
|
1870
|
+
top: 0;
|
|
1871
|
+
bottom: 0;
|
|
1872
|
+
/* Inside the dock (left edge): pointer capture on the handle keeps the
|
|
1873
|
+
drag alive even when the pointer leaves the strip. */
|
|
1874
|
+
left: 0;
|
|
1875
|
+
width: 6px;
|
|
1876
|
+
cursor: col-resize;
|
|
1877
|
+
touch-action: none;
|
|
1878
|
+
z-index: 3;
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
.editorTreeResize:hover {
|
|
1882
|
+
background: var(--dsw-alias-border-l2);
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
.editorTreePanel {
|
|
1886
|
+
/* Relative so the upload overlay and drop pill can cover the tree exactly. */
|
|
1887
|
+
position: relative;
|
|
1888
|
+
flex: 1;
|
|
1889
|
+
min-width: 0;
|
|
1890
|
+
min-height: 0;
|
|
1891
|
+
display: flex;
|
|
1892
|
+
flex-direction: column;
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
/* The tree panel's full-window form (the `full` prop): fill the tab body. */
|
|
1896
|
+
.editorTreePanelFull {
|
|
1897
|
+
flex: 1;
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
.editorTreeSearch {
|
|
1901
|
+
flex: none;
|
|
1902
|
+
display: flex;
|
|
1903
|
+
align-items: center;
|
|
1904
|
+
gap: 6px;
|
|
1905
|
+
padding: 6px 8px;
|
|
1906
|
+
border-bottom: 1px solid var(--dsw-alias-border-l1);
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
.editorSearchInput {
|
|
1910
|
+
flex: 1;
|
|
1911
|
+
min-width: 0;
|
|
1912
|
+
height: 26px;
|
|
1913
|
+
padding: 0 10px;
|
|
1914
|
+
border: 1px solid var(--dsw-alias-border-l1);
|
|
1915
|
+
border-radius: 6px;
|
|
1916
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
1917
|
+
color: var(--dsw-alias-label-primary);
|
|
1918
|
+
font: var(--dsw-font-xxs-12);
|
|
1919
|
+
}
|
|
1920
|
+
|
|
1921
|
+
.editorSearchInput:focus {
|
|
1922
|
+
outline: none;
|
|
1923
|
+
border-color: var(--dsw-alias-border-l2);
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
.editorSearchHint {
|
|
1927
|
+
padding: 8px 12px;
|
|
1928
|
+
font: var(--dsw-font-xxs-12);
|
|
1929
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
.editorSearchResult {
|
|
1933
|
+
display: block;
|
|
1934
|
+
width: 100%;
|
|
1935
|
+
padding: 4px 8px;
|
|
1936
|
+
border: none;
|
|
1937
|
+
border-radius: 6px;
|
|
1938
|
+
background: transparent;
|
|
1939
|
+
color: var(--dsw-alias-label-primary);
|
|
1940
|
+
font: var(--dsw-font-xxs-12);
|
|
1941
|
+
text-align: left;
|
|
1942
|
+
cursor: pointer;
|
|
1943
|
+
overflow: hidden;
|
|
1944
|
+
text-overflow: ellipsis;
|
|
1945
|
+
white-space: nowrap;
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
.editorSearchResult:hover {
|
|
1949
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1952
|
+
.editorStatus {
|
|
1953
|
+
font: var(--dsw-font-xxxs-11);
|
|
1954
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
.editorStatusError {
|
|
1958
|
+
color: var(--dsw-alias-state-error-primary);
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
.dirtyDot {
|
|
1962
|
+
width: 7px;
|
|
1963
|
+
height: 7px;
|
|
1964
|
+
border-radius: 50%;
|
|
1965
|
+
background: var(--dsw-alias-state-warn-primary);
|
|
1966
|
+
flex: none;
|
|
1967
|
+
}
|
|
1968
|
+
|
|
1969
|
+
.editorPlaceholder {
|
|
1970
|
+
flex: 1;
|
|
1971
|
+
display: flex;
|
|
1972
|
+
align-items: center;
|
|
1973
|
+
justify-content: center;
|
|
1974
|
+
font: var(--dsw-font-xxs-12);
|
|
1975
|
+
color: var(--dsw-alias-label-tertiary);
|
|
1976
|
+
padding: 16px;
|
|
1977
|
+
text-align: center;
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
/* The unregistered tab type shown by the orphaned-tab placeholder. */
|
|
1981
|
+
.orphanedType {
|
|
1982
|
+
display: block;
|
|
1983
|
+
margin-top: 8px;
|
|
1984
|
+
font-size: 12px;
|
|
1985
|
+
opacity: 0.7;
|
|
1986
|
+
overflow-wrap: anywhere;
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
/* Binary / download-only files (legacy OLE .doc/.xls/.ppt, unknown binaries):
|
|
1990
|
+
a centered notice plus a download link — the user always gets the file. */
|
|
1991
|
+
.editorBinary {
|
|
1992
|
+
flex: 1;
|
|
1993
|
+
display: flex;
|
|
1994
|
+
flex-direction: column;
|
|
1995
|
+
align-items: center;
|
|
1996
|
+
justify-content: center;
|
|
1997
|
+
gap: 12px;
|
|
1998
|
+
padding: 24px 16px;
|
|
1999
|
+
text-align: center;
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
.editorBinaryNotice {
|
|
2003
|
+
font: var(--dsw-font-xxs-12);
|
|
2004
|
+
color: var(--dsw-alias-label-tertiary);
|
|
2005
|
+
}
|
|
2006
|
+
|
|
2007
|
+
.editorDownloadLink {
|
|
2008
|
+
display: inline-flex;
|
|
2009
|
+
align-items: center;
|
|
2010
|
+
gap: 6px;
|
|
2011
|
+
padding: 6px 14px;
|
|
2012
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
2013
|
+
border-radius: 6px;
|
|
2014
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
2015
|
+
color: var(--dsw-alias-label-primary);
|
|
2016
|
+
font: var(--dsw-font-xxs-strong-12);
|
|
2017
|
+
text-decoration: none;
|
|
2018
|
+
cursor: pointer;
|
|
2019
|
+
transition:
|
|
2020
|
+
background var(--ds-transition-duration-slow) var(--ds-ease-in-out),
|
|
2021
|
+
border-color var(--ds-transition-duration-slow) var(--ds-ease-in-out);
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
.editorDownloadLink:hover {
|
|
2025
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
2026
|
+
border-color: var(--dsw-alias-border-l2);
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
.editorError {
|
|
2030
|
+
padding: 12px 16px;
|
|
2031
|
+
font: var(--dsw-font-xxs-12);
|
|
2032
|
+
color: var(--dsw-alias-state-error-primary);
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
/* The workspace-fence refusal row (FenceErrorNotice): reason text plus the
|
|
2036
|
+
* one-click global-off button share one baseline, wrapping when narrow. */
|
|
2037
|
+
.fenceError {
|
|
2038
|
+
display: flex;
|
|
2039
|
+
align-items: center;
|
|
2040
|
+
flex-wrap: wrap;
|
|
2041
|
+
gap: 8px;
|
|
2042
|
+
padding: 8px 16px;
|
|
2043
|
+
font: var(--dsw-font-xxs-12);
|
|
2044
|
+
color: var(--dsw-alias-state-error-primary);
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
.editorBanner {
|
|
2048
|
+
flex: none;
|
|
2049
|
+
padding: 4px 8px;
|
|
2050
|
+
font: var(--dsw-font-xxxs-11);
|
|
2051
|
+
color: var(--dsw-alias-state-warn-label);
|
|
2052
|
+
background: var(--dsw-alias-state-warn-tertiary);
|
|
2053
|
+
}
|
|
2054
|
+
|
|
2055
|
+
/* Live sandbox status row (HTML preview / browser tab): GREEN while the
|
|
2056
|
+
sandbox is on (with the one-tap temporary unlock), RED while it is off
|
|
2057
|
+
(global setting or temporary unlock) — the red state is the persistent
|
|
2058
|
+
warning that the page runs on the GUI's own origin. */
|
|
2059
|
+
.sandboxStatus {
|
|
2060
|
+
flex: none;
|
|
2061
|
+
display: flex;
|
|
2062
|
+
align-items: center;
|
|
2063
|
+
gap: 8px;
|
|
2064
|
+
padding: 4px 10px;
|
|
2065
|
+
font: var(--dsw-font-xxxs-11);
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
.sandboxStatusOn {
|
|
2069
|
+
color: var(--dsw-alias-label-secondary);
|
|
2070
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
2071
|
+
border-bottom: 1px solid var(--dsw-alias-border-l1);
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
.sandboxStatusOff {
|
|
2075
|
+
color: var(--dsw-alias-state-error-primary);
|
|
2076
|
+
background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);
|
|
2077
|
+
border-bottom: 1px solid color-mix(in srgb, var(--dsw-alias-state-error-primary) 45%, transparent);
|
|
2078
|
+
}
|
|
2079
|
+
|
|
2080
|
+
.sandboxDot {
|
|
2081
|
+
flex: none;
|
|
2082
|
+
width: 6px;
|
|
2083
|
+
height: 6px;
|
|
2084
|
+
border-radius: 50%;
|
|
2085
|
+
background: var(--dsw-alias-state-success-primary);
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2088
|
+
.sandboxStatusOff .sandboxDot {
|
|
2089
|
+
background: var(--dsw-alias-state-error-primary);
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
.sandboxStatusText {
|
|
2093
|
+
flex: 1;
|
|
2094
|
+
min-width: 0;
|
|
2095
|
+
overflow: hidden;
|
|
2096
|
+
text-overflow: ellipsis;
|
|
2097
|
+
white-space: nowrap;
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
.sandboxAction {
|
|
2101
|
+
flex: none;
|
|
2102
|
+
padding: 2px 8px;
|
|
2103
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
2104
|
+
border-radius: 6px;
|
|
2105
|
+
background: transparent;
|
|
2106
|
+
font: inherit;
|
|
2107
|
+
color: inherit;
|
|
2108
|
+
cursor: pointer;
|
|
2109
|
+
}
|
|
2110
|
+
|
|
2111
|
+
.sandboxAction:hover {
|
|
2112
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
/* The HTML preview iframe: fills the editor body. Route-src (never srcdoc)
|
|
2116
|
+
so the frame is cross-origin by construction even if the sandbox
|
|
2117
|
+
attribute is ever dropped; sandboxed by default (see TextEditor). */
|
|
2118
|
+
.editorHtml {
|
|
2119
|
+
flex: 1;
|
|
2120
|
+
min-height: 0;
|
|
2121
|
+
width: 100%;
|
|
2122
|
+
border: none;
|
|
2123
|
+
background: var(--dsw-alias-bg-base);
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2126
|
+
/* ── Browser tab ──────────────────────────────────────────────────────── */
|
|
2127
|
+
|
|
2128
|
+
.browser {
|
|
2129
|
+
flex: 1;
|
|
2130
|
+
min-height: 0;
|
|
2131
|
+
display: flex;
|
|
2132
|
+
flex-direction: column;
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2135
|
+
.browserBar {
|
|
2136
|
+
flex: none;
|
|
2137
|
+
display: flex;
|
|
2138
|
+
align-items: center;
|
|
2139
|
+
gap: 4px;
|
|
2140
|
+
padding: 6px 8px;
|
|
2141
|
+
border-bottom: 1px solid var(--dsw-alias-border-l1);
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2144
|
+
.browserInput {
|
|
2145
|
+
flex: 1;
|
|
2146
|
+
min-width: 0;
|
|
2147
|
+
height: 28px;
|
|
2148
|
+
padding: 0 10px;
|
|
2149
|
+
border: 1px solid var(--dsw-alias-border-l1);
|
|
2150
|
+
border-radius: 6px;
|
|
2151
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
2152
|
+
color: var(--dsw-alias-label-primary);
|
|
2153
|
+
font: var(--dsw-font-xxs-12);
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
.browserInput:focus {
|
|
2157
|
+
outline: none;
|
|
2158
|
+
border-color: var(--dsw-alias-border-l2);
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
.browserMessage {
|
|
2162
|
+
flex: none;
|
|
2163
|
+
padding: 4px 12px;
|
|
2164
|
+
font: var(--dsw-font-xxxs-11);
|
|
2165
|
+
color: var(--dsw-alias-state-warn-label);
|
|
2166
|
+
background: var(--dsw-alias-state-warn-tertiary);
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
.browserFrame {
|
|
2170
|
+
flex: 1;
|
|
2171
|
+
min-height: 0;
|
|
2172
|
+
width: 100%;
|
|
2173
|
+
border: none;
|
|
2174
|
+
background: var(--dsw-alias-bg-base);
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
.browserStart {
|
|
2178
|
+
flex: 1;
|
|
2179
|
+
min-height: 0;
|
|
2180
|
+
display: flex;
|
|
2181
|
+
align-items: center;
|
|
2182
|
+
justify-content: center;
|
|
2183
|
+
padding: 20px;
|
|
2184
|
+
text-align: center;
|
|
2185
|
+
font: var(--dsw-font-xs-13);
|
|
2186
|
+
color: var(--dsw-alias-label-tertiary);
|
|
2187
|
+
}
|
|
2188
|
+
|
|
2189
|
+
/* Embed-refusal panel (X-Frame-Options / frame-ancestors): replaces the
|
|
2190
|
+
blank refused iframe with the reason + open-in-browser actions. */
|
|
2191
|
+
.browserBlocked {
|
|
2192
|
+
flex: 1;
|
|
2193
|
+
min-height: 0;
|
|
2194
|
+
display: flex;
|
|
2195
|
+
flex-direction: column;
|
|
2196
|
+
align-items: center;
|
|
2197
|
+
justify-content: center;
|
|
2198
|
+
gap: 6px;
|
|
2199
|
+
padding: 24px;
|
|
2200
|
+
text-align: center;
|
|
2201
|
+
color: var(--dsw-alias-state-warn-primary);
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2204
|
+
.browserBlockedTitle {
|
|
2205
|
+
font: var(--dsw-font-xxs-strong-12);
|
|
2206
|
+
color: var(--dsw-alias-label-primary);
|
|
2207
|
+
}
|
|
2208
|
+
|
|
2209
|
+
.browserBlockedDesc {
|
|
2210
|
+
max-width: 280px;
|
|
2211
|
+
font: var(--dsw-font-xxxs-11);
|
|
2212
|
+
color: var(--dsw-alias-label-secondary);
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2215
|
+
.browserBlockedActions {
|
|
2216
|
+
display: flex;
|
|
2217
|
+
gap: 8px;
|
|
2218
|
+
margin-top: 6px;
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
.browserBlockedButton {
|
|
2222
|
+
padding: 4px 12px;
|
|
2223
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
2224
|
+
border-radius: 6px;
|
|
2225
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
2226
|
+
color: var(--dsw-alias-label-primary);
|
|
2227
|
+
font: var(--dsw-font-xxxs-11);
|
|
2228
|
+
cursor: pointer;
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2231
|
+
.browserBlockedButton:hover {
|
|
2232
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
.editorCm {
|
|
2236
|
+
flex: 1;
|
|
2237
|
+
min-height: 0;
|
|
2238
|
+
overflow: hidden;
|
|
2239
|
+
background: transparent;
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
.editorCmHidden {
|
|
2243
|
+
display: none;
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
/* CodeMirror fills the pane; the theme supplies its own token palette
|
|
2247
|
+
(a designed dark theme, same policy as the xterm palette). */
|
|
2248
|
+
.editorCm :global(.cm-editor) {
|
|
2249
|
+
height: 100%;
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
/* Code lines get the same 12/16 inset as the markdown preview, so toggling
|
|
2253
|
+
preview/edit never jumps the text's resting position. */
|
|
2254
|
+
.editorCm :global(.cm-scroller) {
|
|
2255
|
+
padding: 12px 16px;
|
|
2256
|
+
}
|
|
2257
|
+
|
|
2258
|
+
.editorCm :global(.cm-editor.cm-focused) {
|
|
2259
|
+
outline: none;
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
/* Preview / edit segmented toggle (markdown and other previewable files). */
|
|
2263
|
+
.editorModeToggle {
|
|
2264
|
+
flex: none;
|
|
2265
|
+
display: inline-flex;
|
|
2266
|
+
align-items: center;
|
|
2267
|
+
gap: 2px;
|
|
2268
|
+
padding: 2px;
|
|
2269
|
+
border: 1px solid var(--dsw-alias-border-l1);
|
|
2270
|
+
border-radius: 6px;
|
|
2271
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2274
|
+
.editorModeButton {
|
|
2275
|
+
padding: 2px 8px;
|
|
2276
|
+
border: none;
|
|
2277
|
+
border-radius: 4px;
|
|
2278
|
+
background: transparent;
|
|
2279
|
+
color: var(--dsw-alias-label-tertiary);
|
|
2280
|
+
font: var(--dsw-font-xxxs-11);
|
|
2281
|
+
cursor: pointer;
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
.editorModeButton:hover {
|
|
2285
|
+
color: var(--dsw-alias-label-primary);
|
|
2286
|
+
}
|
|
2287
|
+
|
|
2288
|
+
.editorModeActive {
|
|
2289
|
+
background: var(--dsw-alias-bg-base);
|
|
2290
|
+
color: var(--dsw-alias-label-primary);
|
|
2291
|
+
}
|
|
2292
|
+
|
|
2293
|
+
.editorImageWrap {
|
|
2294
|
+
flex: 1;
|
|
2295
|
+
min-height: 0;
|
|
2296
|
+
display: flex;
|
|
2297
|
+
align-items: center;
|
|
2298
|
+
justify-content: center;
|
|
2299
|
+
overflow: auto;
|
|
2300
|
+
padding: 12px;
|
|
2301
|
+
}
|
|
2302
|
+
|
|
2303
|
+
.editorImage {
|
|
2304
|
+
max-width: 100%;
|
|
2305
|
+
max-height: 100%;
|
|
2306
|
+
object-fit: contain;
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2309
|
+
.editorMd {
|
|
2310
|
+
flex: 1;
|
|
2311
|
+
min-height: 0;
|
|
2312
|
+
overflow-y: auto;
|
|
2313
|
+
padding: 12px 16px;
|
|
2314
|
+
font: var(--dsw-font-xs-13);
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2317
|
+
/* ── Mermaid diagram block (markdown preview, mermaid lazy chunk) ────────
|
|
2318
|
+
Mirrors the md-code-block chrome the DSH CodeBlock renders, so a diagram
|
|
2319
|
+
reads as a peer of the surrounding fences: hairline border, layer-2
|
|
2320
|
+
header with the info string + copy action, layer-1 body. The SVG body is
|
|
2321
|
+
static (no bindFunctions) and sanitized (no foreignObject/script/@attrs/
|
|
2322
|
+
hrefs), so it carries no event surface beyond the copy button; the body
|
|
2323
|
+
click opens the zoom modal on a sanitized clone. */
|
|
2324
|
+
|
|
2325
|
+
.mermaidWrap {
|
|
2326
|
+
margin: 6px 0;
|
|
2327
|
+
border: 1px solid var(--dsw-alias-border-l1);
|
|
2328
|
+
border-radius: 6px;
|
|
2329
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
2330
|
+
overflow: hidden;
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
.mermaidHeader {
|
|
2334
|
+
display: flex;
|
|
2335
|
+
align-items: center;
|
|
2336
|
+
justify-content: space-between;
|
|
2337
|
+
gap: 6px;
|
|
2338
|
+
padding: 4px 8px;
|
|
2339
|
+
border-bottom: 1px solid var(--dsw-alias-border-l1);
|
|
2340
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
2341
|
+
}
|
|
2342
|
+
|
|
2343
|
+
.mermaidInfo {
|
|
2344
|
+
font: var(--dsw-font-xxxs-strong-11);
|
|
2345
|
+
color: var(--dsw-alias-label-tertiary);
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
.mermaidCopy {
|
|
2349
|
+
display: inline-flex;
|
|
2350
|
+
align-items: center;
|
|
2351
|
+
gap: 4px;
|
|
2352
|
+
padding: 0 6px;
|
|
2353
|
+
height: 20px;
|
|
2354
|
+
border: none;
|
|
2355
|
+
border-radius: 4px;
|
|
2356
|
+
background: transparent;
|
|
2357
|
+
color: var(--dsw-alias-label-secondary);
|
|
2358
|
+
font: var(--dsw-font-xxxs-11);
|
|
2359
|
+
cursor: pointer;
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
.mermaidCopy:hover {
|
|
2363
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
2364
|
+
color: var(--dsw-alias-label-primary);
|
|
2365
|
+
}
|
|
2366
|
+
|
|
2367
|
+
.mermaidBody {
|
|
2368
|
+
display: flex;
|
|
2369
|
+
justify-content: center;
|
|
2370
|
+
padding: 10px;
|
|
2371
|
+
overflow: auto;
|
|
2372
|
+
cursor: zoom-in;
|
|
2373
|
+
}
|
|
2374
|
+
|
|
2375
|
+
.mermaidBody :global(svg) {
|
|
2376
|
+
max-width: 100%;
|
|
2377
|
+
height: auto;
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2380
|
+
.mermaidError {
|
|
2381
|
+
padding: 6px 10px;
|
|
2382
|
+
border-bottom: 1px solid var(--dsw-alias-border-l1);
|
|
2383
|
+
color: var(--dsw-alias-state-error-primary);
|
|
2384
|
+
font: var(--dsw-font-xxxs-11);
|
|
2385
|
+
}
|
|
2386
|
+
|
|
2387
|
+
/* The diagram source shown under a render error (helps fixing the fence). */
|
|
2388
|
+
.mermaidCode {
|
|
2389
|
+
margin: 0;
|
|
2390
|
+
padding: 8px 10px;
|
|
2391
|
+
overflow: auto;
|
|
2392
|
+
font: var(--dsw-font-xxxs-11);
|
|
2393
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2396
|
+
/* The mermaid markdown container (single MarkdownText pass): a swapped
|
|
2397
|
+
code block keeps its React-managed .md-code-block wrapper in the tree
|
|
2398
|
+
(reconciliation safety), but the wrapper's own box is suppressed so only
|
|
2399
|
+
the diagram chrome renders; the swapped-in host div flows as a block. */
|
|
2400
|
+
.mermaidMarkdown :global(.md-code-block[data-mermaid-processed]) {
|
|
2401
|
+
display: contents;
|
|
2402
|
+
}
|
|
2403
|
+
|
|
2404
|
+
/* ── Mermaid zoom modal (click-to-enlarge; portalled to document.body) ──
|
|
2405
|
+
Fixed overlay above the DSH overlay stack (1000+), token-driven surface.
|
|
2406
|
+
The stage centers the (sanitized, cloned) svg and the modal owns the
|
|
2407
|
+
transform; the drag/zoom listeners live in the component, nothing here
|
|
2408
|
+
targets global class names. */
|
|
2409
|
+
|
|
2410
|
+
.mermaidModal {
|
|
2411
|
+
position: fixed;
|
|
2412
|
+
inset: 0;
|
|
2413
|
+
z-index: 1000;
|
|
2414
|
+
display: flex;
|
|
2415
|
+
flex-direction: column;
|
|
2416
|
+
align-items: center;
|
|
2417
|
+
justify-content: center;
|
|
2418
|
+
background: var(--dsw-alias-bg-mask-1);
|
|
2419
|
+
backdrop-filter: blur(2px);
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
.mermaidModalToolbar {
|
|
2423
|
+
position: absolute;
|
|
2424
|
+
top: 16px;
|
|
2425
|
+
right: 16px;
|
|
2426
|
+
display: flex;
|
|
2427
|
+
gap: 8px;
|
|
2428
|
+
z-index: 10;
|
|
2429
|
+
}
|
|
2430
|
+
|
|
2431
|
+
.mermaidModalButton {
|
|
2432
|
+
width: 36px;
|
|
2433
|
+
height: 36px;
|
|
2434
|
+
border-radius: 8px;
|
|
2435
|
+
border: 1px solid var(--dsw-alias-border-l1);
|
|
2436
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
2437
|
+
color: var(--dsw-alias-label-primary);
|
|
2438
|
+
font: var(--dsw-font-xs-strong-13);
|
|
2439
|
+
cursor: pointer;
|
|
2440
|
+
display: inline-flex;
|
|
2441
|
+
align-items: center;
|
|
2442
|
+
justify-content: center;
|
|
2443
|
+
}
|
|
2444
|
+
|
|
2445
|
+
.mermaidModalButton:hover {
|
|
2446
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
2447
|
+
}
|
|
2448
|
+
|
|
2449
|
+
.mermaidModalStage {
|
|
2450
|
+
width: 90vw;
|
|
2451
|
+
height: 80vh;
|
|
2452
|
+
overflow: hidden;
|
|
2453
|
+
position: relative;
|
|
2454
|
+
display: flex;
|
|
2455
|
+
align-items: center;
|
|
2456
|
+
justify-content: center;
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
.mermaidModalStage :global(svg) {
|
|
2460
|
+
max-width: none;
|
|
2461
|
+
max-height: none;
|
|
2462
|
+
cursor: grab;
|
|
2463
|
+
transform-origin: center center;
|
|
2464
|
+
user-select: none;
|
|
2465
|
+
-webkit-user-drag: none;
|
|
2466
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
2467
|
+
padding: 16px;
|
|
2468
|
+
border-radius: 12px;
|
|
2469
|
+
}
|
|
2470
|
+
|
|
2471
|
+
.mermaidModalStage :global(svg):active {
|
|
2472
|
+
cursor: grabbing;
|
|
2473
|
+
}
|
|
2474
|
+
|
|
2475
|
+
.mermaidModalHint {
|
|
2476
|
+
position: absolute;
|
|
2477
|
+
bottom: 16px;
|
|
2478
|
+
left: 50%;
|
|
2479
|
+
transform: translateX(-50%);
|
|
2480
|
+
color: var(--dsw-alias-label-tertiary);
|
|
2481
|
+
font: var(--dsw-font-xxxs-11);
|
|
2482
|
+
pointer-events: none;
|
|
2483
|
+
}
|
|
2484
|
+
|
|
2485
|
+
/* The floating "add to conversation" button anchored above a text
|
|
2486
|
+
selection in the preview/code viewers. Portalled to document.body and
|
|
2487
|
+
position:fixed, so the editor's overflow clips cannot crop it; flat
|
|
2488
|
+
chrome like the rest of the sidebar (hairline border, layer-2 fill,
|
|
2489
|
+
hover fill — no shadow). */
|
|
2490
|
+
.selectionPopup {
|
|
2491
|
+
position: fixed;
|
|
2492
|
+
z-index: 60;
|
|
2493
|
+
transform: translate(-50%, calc(-100% - 8px));
|
|
2494
|
+
display: inline-flex;
|
|
2495
|
+
align-items: center;
|
|
2496
|
+
height: 28px;
|
|
2497
|
+
padding: 0 10px;
|
|
2498
|
+
border: 1px solid var(--dsw-alias-border-l1);
|
|
2499
|
+
border-radius: 6px;
|
|
2500
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
2501
|
+
color: var(--dsw-alias-label-primary);
|
|
2502
|
+
font: var(--dsw-font-xxxs-strong-11);
|
|
2503
|
+
white-space: nowrap;
|
|
2504
|
+
cursor: pointer;
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2507
|
+
.selectionPopup:hover {
|
|
2508
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2511
|
+
.editorPdf {
|
|
2512
|
+
flex: 1;
|
|
2513
|
+
min-height: 0;
|
|
2514
|
+
display: flex;
|
|
2515
|
+
flex-direction: column;
|
|
2516
|
+
background: var(--dsw-alias-bg-base);
|
|
2517
|
+
}
|
|
2518
|
+
|
|
2519
|
+
.editorPdfToolbar {
|
|
2520
|
+
flex: none;
|
|
2521
|
+
display: flex;
|
|
2522
|
+
justify-content: flex-end;
|
|
2523
|
+
padding: 6px 8px;
|
|
2524
|
+
border-bottom: 1px solid var(--dsw-alias-border-l1);
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2527
|
+
.editorPdfStage {
|
|
2528
|
+
position: relative;
|
|
2529
|
+
flex: 1;
|
|
2530
|
+
min-height: 0;
|
|
2531
|
+
display: flex;
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
.editorPdfFrame {
|
|
2535
|
+
flex: 1;
|
|
2536
|
+
min-height: 0;
|
|
2537
|
+
width: 100%;
|
|
2538
|
+
border: none;
|
|
2539
|
+
background: var(--dsw-alias-bg-base);
|
|
2540
|
+
}
|
|
2541
|
+
|
|
2542
|
+
.editorPdfFrameBlocked {
|
|
2543
|
+
pointer-events: none;
|
|
2544
|
+
}
|
|
2545
|
+
|
|
2546
|
+
.editorPdfDragShield {
|
|
2547
|
+
position: absolute;
|
|
2548
|
+
inset: 0;
|
|
2549
|
+
z-index: 4;
|
|
2550
|
+
pointer-events: none;
|
|
2551
|
+
background: transparent;
|
|
2552
|
+
}
|
|
2553
|
+
|
|
2554
|
+
.editorPdfDragShieldActive {
|
|
2555
|
+
pointer-events: auto;
|
|
2556
|
+
}
|
|
2557
|
+
|
|
2558
|
+
/* Tab drag must switch iframe hit-testing before the pointer can enter the
|
|
2559
|
+
Chromium PDF browsing context. The body flag is set synchronously by the
|
|
2560
|
+
drag source, avoiding React render timing entirely. */
|
|
2561
|
+
:global(body[data-dsh-tab-dragging]) .editorPdfFrame {
|
|
2562
|
+
pointer-events: none !important;
|
|
2563
|
+
}
|
|
2564
|
+
|
|
2565
|
+
:global(body[data-dsh-tab-dragging]) .editorPdfDragShield {
|
|
2566
|
+
pointer-events: auto !important;
|
|
2567
|
+
}
|
|
2568
|
+
|
|
2569
|
+
/* ── Terminal ──────────────────────────────────────────────────────────── */
|
|
2570
|
+
|
|
2571
|
+
.terminalWrap {
|
|
2572
|
+
flex: 1;
|
|
2573
|
+
min-height: 0;
|
|
2574
|
+
position: relative;
|
|
2575
|
+
display: flex;
|
|
2576
|
+
flex-direction: column;
|
|
2577
|
+
background: var(--dsw-alias-bg-base);
|
|
2578
|
+
}
|
|
2579
|
+
|
|
2580
|
+
.terminal {
|
|
2581
|
+
flex: 1;
|
|
2582
|
+
min-height: 0;
|
|
2583
|
+
padding: 6px 4px 6px 8px;
|
|
2584
|
+
}
|
|
2585
|
+
|
|
2586
|
+
.terminal :global(.xterm) {
|
|
2587
|
+
height: 100%;
|
|
2588
|
+
}
|
|
2589
|
+
|
|
2590
|
+
.terminalBanner {
|
|
2591
|
+
flex: none;
|
|
2592
|
+
display: flex;
|
|
2593
|
+
align-items: center;
|
|
2594
|
+
flex-wrap: wrap;
|
|
2595
|
+
gap: 8px;
|
|
2596
|
+
padding: 3px 10px;
|
|
2597
|
+
font: var(--dsw-font-xxxs-11);
|
|
2598
|
+
color: var(--dsw-alias-state-warn-label);
|
|
2599
|
+
background: var(--dsw-alias-state-warn-tertiary);
|
|
2600
|
+
}
|
|
2601
|
+
|
|
2602
|
+
/* The attempted ws URL, shown when the connection failed (diagnosis). */
|
|
2603
|
+
.terminalBannerUrl {
|
|
2604
|
+
flex-basis: 100%;
|
|
2605
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
2606
|
+
word-break: break-all;
|
|
2607
|
+
opacity: 0.85;
|
|
2608
|
+
}
|
|
2609
|
+
|
|
2610
|
+
.boundaryError {
|
|
2611
|
+
position: fixed;
|
|
2612
|
+
right: 0;
|
|
2613
|
+
top: 0;
|
|
2614
|
+
bottom: 0;
|
|
2615
|
+
z-index: 50;
|
|
2616
|
+
display: flex;
|
|
2617
|
+
flex-direction: column;
|
|
2618
|
+
gap: 8px;
|
|
2619
|
+
align-items: flex-start;
|
|
2620
|
+
padding: 16px;
|
|
2621
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
2622
|
+
border-left: 1px solid var(--dsw-alias-border-l2);
|
|
2623
|
+
font: var(--dsw-font-xxs-12);
|
|
2624
|
+
color: var(--dsw-alias-state-error-primary);
|
|
2625
|
+
overflow: auto;
|
|
2626
|
+
}
|
|
2627
|
+
|
|
2628
|
+
.terminalRetry {
|
|
2629
|
+
flex: none;
|
|
2630
|
+
padding: 1px 8px;
|
|
2631
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
2632
|
+
border-radius: 999px;
|
|
2633
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
2634
|
+
color: var(--dsw-alias-label-secondary);
|
|
2635
|
+
font: var(--dsw-font-xxxs-strong-11);
|
|
2636
|
+
cursor: pointer;
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
.terminalRetry:hover {
|
|
2640
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
2641
|
+
color: var(--dsw-alias-label-primary);
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
/* The node-pty dependency failure banner (issue #140): a taller warn block
|
|
2645
|
+
carrying the pasteable repair command (bash / cmd / PowerShell). */
|
|
2646
|
+
.terminalDepsBanner {
|
|
2647
|
+
flex: none;
|
|
2648
|
+
display: flex;
|
|
2649
|
+
flex-direction: column;
|
|
2650
|
+
gap: 6px;
|
|
2651
|
+
padding: 10px;
|
|
2652
|
+
font: var(--dsw-font-xxs-12);
|
|
2653
|
+
color: var(--dsw-alias-state-warn-label);
|
|
2654
|
+
background: var(--dsw-alias-state-warn-tertiary);
|
|
2655
|
+
}
|
|
2656
|
+
|
|
2657
|
+
.terminalDepsTitle {
|
|
2658
|
+
font: var(--dsw-font-xxs-strong-12);
|
|
2659
|
+
color: var(--dsw-alias-state-warn-primary);
|
|
2660
|
+
}
|
|
2661
|
+
|
|
2662
|
+
.terminalDepsHint {
|
|
2663
|
+
opacity: 0.9;
|
|
2664
|
+
}
|
|
2665
|
+
|
|
2666
|
+
.terminalDepsCommandRow {
|
|
2667
|
+
display: flex;
|
|
2668
|
+
align-items: flex-start;
|
|
2669
|
+
gap: 8px;
|
|
2670
|
+
}
|
|
2671
|
+
|
|
2672
|
+
/* The command the user pastes into a terminal / cmd. Selectable, wrapping,
|
|
2673
|
+
and scrollable when long (Windows paths can get very long). */
|
|
2674
|
+
.terminalRepairCommand {
|
|
2675
|
+
flex: 1;
|
|
2676
|
+
min-width: 0;
|
|
2677
|
+
margin: 0;
|
|
2678
|
+
padding: 6px 8px;
|
|
2679
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
2680
|
+
font-size: 11px;
|
|
2681
|
+
line-height: 1.5;
|
|
2682
|
+
white-space: pre-wrap;
|
|
2683
|
+
word-break: break-all;
|
|
2684
|
+
user-select: text;
|
|
2685
|
+
color: var(--dsw-alias-label-primary);
|
|
2686
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
2687
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
2688
|
+
border-radius: 4px;
|
|
2689
|
+
max-height: 160px;
|
|
2690
|
+
overflow: auto;
|
|
2691
|
+
}
|
|
2692
|
+
|
|
2693
|
+
.terminalDepsNote {
|
|
2694
|
+
opacity: 0.85;
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2697
|
+
.terminalDepsActions {
|
|
2698
|
+
display: flex;
|
|
2699
|
+
align-items: center;
|
|
2700
|
+
gap: 8px;
|
|
2701
|
+
}
|
|
2702
|
+
|
|
2703
|
+
/* The PER-TAB error strip: fills one tab's content area (unlike
|
|
2704
|
+
.boundaryError, the full-height fixed rail for shell-level crashes), so a
|
|
2705
|
+
crashing viewer/editor never hides the toggle cluster or the other tabs. */
|
|
2706
|
+
.tabBoundaryError {
|
|
2707
|
+
flex: 1;
|
|
2708
|
+
min-height: 0;
|
|
2709
|
+
display: flex;
|
|
2710
|
+
flex-direction: column;
|
|
2711
|
+
gap: 8px;
|
|
2712
|
+
align-items: flex-start;
|
|
2713
|
+
padding: 12px 16px;
|
|
2714
|
+
overflow: auto;
|
|
2715
|
+
font: var(--dsw-font-xxs-12);
|
|
2716
|
+
color: var(--dsw-alias-state-error-primary);
|
|
2717
|
+
}
|
|
2718
|
+
|
|
2719
|
+
/* ── Git ───────────────────────────────────────────────────────────────── */
|
|
2720
|
+
|
|
2721
|
+
.git {
|
|
2722
|
+
flex: 1;
|
|
2723
|
+
min-height: 0;
|
|
2724
|
+
min-width: 0;
|
|
2725
|
+
display: flex;
|
|
2726
|
+
flex-direction: column;
|
|
2727
|
+
overflow-y: auto;
|
|
2728
|
+
/* Tab pages never scroll horizontally: content wraps or truncates to the
|
|
2729
|
+
panel width instead of panning sideways. */
|
|
2730
|
+
overflow-x: hidden;
|
|
2731
|
+
}
|
|
2732
|
+
|
|
2733
|
+
.gitHeader {
|
|
2734
|
+
flex: none;
|
|
2735
|
+
display: flex;
|
|
2736
|
+
align-items: center;
|
|
2737
|
+
gap: 8px;
|
|
2738
|
+
height: 36px;
|
|
2739
|
+
padding: 0 8px 0 12px;
|
|
2740
|
+
}
|
|
2741
|
+
|
|
2742
|
+
.gitWorktreeRow {
|
|
2743
|
+
flex: none;
|
|
2744
|
+
display: flex;
|
|
2745
|
+
align-items: center;
|
|
2746
|
+
gap: 8px;
|
|
2747
|
+
padding: 6px 8px 0 12px;
|
|
2748
|
+
}
|
|
2749
|
+
|
|
2750
|
+
.gitWorktreeLabel {
|
|
2751
|
+
flex: none;
|
|
2752
|
+
color: var(--dsw-alias-label-tertiary);
|
|
2753
|
+
font: var(--dsw-font-xxxs-11);
|
|
2754
|
+
}
|
|
2755
|
+
|
|
2756
|
+
.gitBranchSelect {
|
|
2757
|
+
flex: 1;
|
|
2758
|
+
min-width: 0;
|
|
2759
|
+
height: 26px;
|
|
2760
|
+
padding: 0 6px;
|
|
2761
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
2762
|
+
border-radius: 6px;
|
|
2763
|
+
background: var(--dsw-alias-bg-base);
|
|
2764
|
+
color: var(--dsw-alias-label-primary);
|
|
2765
|
+
font: var(--dsw-font-xxs-12);
|
|
2766
|
+
}
|
|
2767
|
+
|
|
2768
|
+
.gitSection {
|
|
2769
|
+
border-top: 1px solid var(--dsw-alias-border-l1);
|
|
2770
|
+
}
|
|
2771
|
+
|
|
2772
|
+
.gitSectionHeader {
|
|
2773
|
+
display: flex;
|
|
2774
|
+
align-items: center;
|
|
2775
|
+
justify-content: space-between;
|
|
2776
|
+
padding: 6px 12px 4px;
|
|
2777
|
+
font: var(--dsw-font-xxxs-strong-11);
|
|
2778
|
+
color: var(--dsw-alias-label-tertiary);
|
|
2779
|
+
text-transform: uppercase;
|
|
2780
|
+
}
|
|
2781
|
+
|
|
2782
|
+
.gitLink {
|
|
2783
|
+
border: none;
|
|
2784
|
+
background: transparent;
|
|
2785
|
+
font: var(--dsw-font-xxxs-11);
|
|
2786
|
+
color: var(--dsw-alias-brand-primary);
|
|
2787
|
+
cursor: pointer;
|
|
2788
|
+
padding: 0;
|
|
2789
|
+
}
|
|
2790
|
+
|
|
2791
|
+
.gitLink:hover:not(:disabled) {
|
|
2792
|
+
text-decoration: underline;
|
|
2793
|
+
}
|
|
2794
|
+
|
|
2795
|
+
.gitLink:disabled {
|
|
2796
|
+
opacity: 0.4;
|
|
2797
|
+
cursor: default;
|
|
2798
|
+
}
|
|
2799
|
+
|
|
2800
|
+
.gitRow {
|
|
2801
|
+
display: flex;
|
|
2802
|
+
align-items: center;
|
|
2803
|
+
gap: 6px;
|
|
2804
|
+
min-height: 34px;
|
|
2805
|
+
margin: 0 6px;
|
|
2806
|
+
padding: 0 8px;
|
|
2807
|
+
border-radius: 8px;
|
|
2808
|
+
animation: dsh-row-in 150ms var(--ds-ease-in-out);
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
.gitRow:hover {
|
|
2812
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
2813
|
+
}
|
|
2814
|
+
|
|
2815
|
+
.gitRowSelected {
|
|
2816
|
+
background: var(--dsw-alias-interactive-bg-active);
|
|
2817
|
+
}
|
|
2818
|
+
|
|
2819
|
+
.gitRowMain {
|
|
2820
|
+
flex: 1;
|
|
2821
|
+
min-width: 0;
|
|
2822
|
+
display: flex;
|
|
2823
|
+
align-items: center;
|
|
2824
|
+
gap: 8px;
|
|
2825
|
+
border: none;
|
|
2826
|
+
background: transparent;
|
|
2827
|
+
padding: 3px 0;
|
|
2828
|
+
cursor: pointer;
|
|
2829
|
+
text-align: left;
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2832
|
+
.gitBadge {
|
|
2833
|
+
flex: none;
|
|
2834
|
+
width: 20px;
|
|
2835
|
+
height: 16px;
|
|
2836
|
+
display: inline-flex;
|
|
2837
|
+
align-items: center;
|
|
2838
|
+
justify-content: center;
|
|
2839
|
+
border-radius: 4px;
|
|
2840
|
+
font: var(--dsw-font-xxxs-strong-11);
|
|
2841
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
2842
|
+
color: var(--dsw-alias-label-secondary);
|
|
2843
|
+
}
|
|
2844
|
+
|
|
2845
|
+
.gitName {
|
|
2846
|
+
flex: 1;
|
|
2847
|
+
min-width: 0;
|
|
2848
|
+
overflow: hidden;
|
|
2849
|
+
text-overflow: ellipsis;
|
|
2850
|
+
white-space: nowrap;
|
|
2851
|
+
font: var(--dsw-font-s-14);
|
|
2852
|
+
color: var(--dsw-alias-label-primary);
|
|
2853
|
+
}
|
|
2854
|
+
|
|
2855
|
+
.gitEmpty {
|
|
2856
|
+
padding: 4px 12px 8px;
|
|
2857
|
+
font: var(--dsw-font-xxs-12);
|
|
2858
|
+
color: var(--dsw-alias-label-tertiary);
|
|
2859
|
+
}
|
|
2860
|
+
|
|
2861
|
+
.gitPlaceholder {
|
|
2862
|
+
padding: 16px;
|
|
2863
|
+
font: var(--dsw-font-xxs-12);
|
|
2864
|
+
color: var(--dsw-alias-label-tertiary);
|
|
2865
|
+
text-align: center;
|
|
2866
|
+
}
|
|
2867
|
+
|
|
2868
|
+
.gitError {
|
|
2869
|
+
padding: 8px 12px;
|
|
2870
|
+
font: var(--dsw-font-xxs-12);
|
|
2871
|
+
color: var(--dsw-alias-state-error-primary);
|
|
2872
|
+
white-space: pre-wrap;
|
|
2873
|
+
}
|
|
2874
|
+
|
|
2875
|
+
.gitDiff {
|
|
2876
|
+
border-top: 1px solid var(--dsw-alias-border-l1);
|
|
2877
|
+
padding: 8px;
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
/* The diff tab (a change opened from the git panel, like VSCode's diff
|
|
2881
|
+
editor): header + scrollable diff body, no horizontal panning. */
|
|
2882
|
+
.gitDiffTab {
|
|
2883
|
+
flex: 1;
|
|
2884
|
+
min-height: 0;
|
|
2885
|
+
min-width: 0;
|
|
2886
|
+
display: flex;
|
|
2887
|
+
flex-direction: column;
|
|
2888
|
+
overflow-y: auto;
|
|
2889
|
+
overflow-x: hidden;
|
|
2890
|
+
}
|
|
2891
|
+
|
|
2892
|
+
.gitDiffTabHeader {
|
|
2893
|
+
flex: none;
|
|
2894
|
+
display: flex;
|
|
2895
|
+
align-items: center;
|
|
2896
|
+
gap: 8px;
|
|
2897
|
+
height: 36px;
|
|
2898
|
+
padding: 0 8px 0 12px;
|
|
2899
|
+
border-bottom: 1px solid var(--dsw-alias-border-l1);
|
|
2900
|
+
}
|
|
2901
|
+
|
|
2902
|
+
.gitDiffTabTitle {
|
|
2903
|
+
flex: 1;
|
|
2904
|
+
min-width: 0;
|
|
2905
|
+
overflow: hidden;
|
|
2906
|
+
text-overflow: ellipsis;
|
|
2907
|
+
white-space: nowrap;
|
|
2908
|
+
font: var(--dsw-font-xxs-strong-12);
|
|
2909
|
+
color: var(--dsw-alias-label-primary);
|
|
2910
|
+
}
|
|
2911
|
+
|
|
2912
|
+
/* One changed file's section: path header, hunk headers, aligned lines. */
|
|
2913
|
+
.gitDiffFile {
|
|
2914
|
+
width: 100%;
|
|
2915
|
+
display: flex;
|
|
2916
|
+
align-items: baseline;
|
|
2917
|
+
gap: 6px;
|
|
2918
|
+
padding: 8px 2px 2px;
|
|
2919
|
+
border: 0;
|
|
2920
|
+
background: transparent;
|
|
2921
|
+
color: inherit;
|
|
2922
|
+
text-align: left;
|
|
2923
|
+
cursor: pointer;
|
|
2924
|
+
}
|
|
2925
|
+
|
|
2926
|
+
.gitDiffFile:disabled {
|
|
2927
|
+
cursor: default;
|
|
2928
|
+
}
|
|
2929
|
+
|
|
2930
|
+
.gitDiffFile:hover:not(:disabled) {
|
|
2931
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
2932
|
+
}
|
|
2933
|
+
|
|
2934
|
+
.gitDiffFileChevron {
|
|
2935
|
+
flex: none;
|
|
2936
|
+
color: var(--dsw-alias-label-tertiary);
|
|
2937
|
+
transform: rotate(0deg);
|
|
2938
|
+
}
|
|
2939
|
+
|
|
2940
|
+
.gitDiffFileChevronExpanded {
|
|
2941
|
+
transform: rotate(90deg);
|
|
2942
|
+
}
|
|
2943
|
+
|
|
2944
|
+
.gitDiffFilePath {
|
|
2945
|
+
font: var(--dsw-font-xxs-strong-12);
|
|
2946
|
+
color: var(--dsw-alias-label-primary);
|
|
2947
|
+
overflow: hidden;
|
|
2948
|
+
text-overflow: ellipsis;
|
|
2949
|
+
white-space: nowrap;
|
|
2950
|
+
}
|
|
2951
|
+
|
|
2952
|
+
.gitDiffFileOld {
|
|
2953
|
+
flex: none;
|
|
2954
|
+
font: var(--dsw-font-xxxs-11);
|
|
2955
|
+
color: var(--dsw-alias-label-tertiary);
|
|
2956
|
+
overflow: hidden;
|
|
2957
|
+
text-overflow: ellipsis;
|
|
2958
|
+
white-space: nowrap;
|
|
2959
|
+
max-width: 40%;
|
|
2960
|
+
}
|
|
2961
|
+
|
|
2962
|
+
.gitDiffFileTag {
|
|
2963
|
+
flex: none;
|
|
2964
|
+
padding: 0 6px;
|
|
2965
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
2966
|
+
border-radius: 999px;
|
|
2967
|
+
font: var(--dsw-font-xxxs-strong-11);
|
|
2968
|
+
color: var(--dsw-alias-label-secondary);
|
|
2969
|
+
}
|
|
2970
|
+
|
|
2971
|
+
.gitDiffHunk {
|
|
2972
|
+
display: flex;
|
|
2973
|
+
gap: 8px;
|
|
2974
|
+
padding: 3px 2px;
|
|
2975
|
+
font: var(--dsw-font-markdown-code-block-small);
|
|
2976
|
+
color: var(--dsw-alias-label-tertiary);
|
|
2977
|
+
}
|
|
2978
|
+
|
|
2979
|
+
.gitDiffHunkHeader {
|
|
2980
|
+
flex: none;
|
|
2981
|
+
color: var(--dsw-alias-label-secondary);
|
|
2982
|
+
}
|
|
2983
|
+
|
|
2984
|
+
.gitDiffHunkSection {
|
|
2985
|
+
overflow: hidden;
|
|
2986
|
+
text-overflow: ellipsis;
|
|
2987
|
+
white-space: nowrap;
|
|
2988
|
+
}
|
|
2989
|
+
|
|
2990
|
+
/* One aligned diff line: old gutter / new gutter / code. Lines WRAP instead
|
|
2991
|
+
of scrolling horizontally (the tab-page rule: fill the width adaptively),
|
|
2992
|
+
with the long-token fallback breaking anywhere a space never comes. */
|
|
2993
|
+
.gitDiffLine {
|
|
2994
|
+
display: flex;
|
|
2995
|
+
align-items: stretch;
|
|
2996
|
+
font: var(--dsw-font-markdown-code-block-small);
|
|
2997
|
+
line-height: 20px;
|
|
2998
|
+
white-space: pre-wrap;
|
|
2999
|
+
overflow-wrap: anywhere;
|
|
3000
|
+
min-width: 0;
|
|
3001
|
+
}
|
|
3002
|
+
|
|
3003
|
+
.gitDiffNum {
|
|
3004
|
+
flex: none;
|
|
3005
|
+
width: 36px;
|
|
3006
|
+
padding-right: 8px;
|
|
3007
|
+
text-align: right;
|
|
3008
|
+
color: var(--dsw-alias-label-tertiary);
|
|
3009
|
+
user-select: none;
|
|
3010
|
+
}
|
|
3011
|
+
|
|
3012
|
+
.gitDiffCode {
|
|
3013
|
+
flex: 1;
|
|
3014
|
+
min-width: 0;
|
|
3015
|
+
overflow: visible;
|
|
3016
|
+
}
|
|
3017
|
+
|
|
3018
|
+
.gitDiffCtx {
|
|
3019
|
+
color: var(--dsw-alias-label-primary);
|
|
3020
|
+
}
|
|
3021
|
+
|
|
3022
|
+
.gitDiffDel {
|
|
3023
|
+
color: var(--dsw-alias-state-error-primary);
|
|
3024
|
+
background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent);
|
|
3025
|
+
}
|
|
3026
|
+
|
|
3027
|
+
.gitDiffAdd {
|
|
3028
|
+
color: var(--dsw-alias-state-success-primary);
|
|
3029
|
+
background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 12%, transparent);
|
|
3030
|
+
}
|
|
3031
|
+
|
|
3032
|
+
.gitDiffMeta {
|
|
3033
|
+
padding-left: 2px;
|
|
3034
|
+
}
|
|
3035
|
+
|
|
3036
|
+
.gitDiffMetaText {
|
|
3037
|
+
font: var(--dsw-font-xxxs-11);
|
|
3038
|
+
font-style: italic;
|
|
3039
|
+
color: var(--dsw-alias-label-tertiary);
|
|
3040
|
+
}
|
|
3041
|
+
|
|
3042
|
+
.gitDiffExpand {
|
|
3043
|
+
display: block;
|
|
3044
|
+
width: 100%;
|
|
3045
|
+
margin: 4px 0;
|
|
3046
|
+
border: none;
|
|
3047
|
+
background: transparent;
|
|
3048
|
+
font: var(--dsw-font-xxs-12);
|
|
3049
|
+
color: var(--dsw-alias-brand-primary);
|
|
3050
|
+
cursor: pointer;
|
|
3051
|
+
text-align: center;
|
|
3052
|
+
}
|
|
3053
|
+
|
|
3054
|
+
.gitDiffExpand:hover {
|
|
3055
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
3056
|
+
}
|
|
3057
|
+
|
|
3058
|
+
.gitConfirmDesc {
|
|
3059
|
+
margin: 0;
|
|
3060
|
+
font: var(--dsw-font-s-14);
|
|
3061
|
+
color: var(--dsw-alias-label-primary);
|
|
3062
|
+
white-space: pre-wrap;
|
|
3063
|
+
}
|
|
3064
|
+
|
|
3065
|
+
.gitCommit {
|
|
3066
|
+
display: flex;
|
|
3067
|
+
gap: 6px;
|
|
3068
|
+
padding: 8px 12px;
|
|
3069
|
+
border-top: 1px solid var(--dsw-alias-border-l1);
|
|
3070
|
+
align-items: center;
|
|
3071
|
+
}
|
|
3072
|
+
|
|
3073
|
+
.gitCommitInput {
|
|
3074
|
+
flex: 1;
|
|
3075
|
+
min-width: 0;
|
|
3076
|
+
}
|
|
3077
|
+
|
|
3078
|
+
.gitCommitButton {
|
|
3079
|
+
flex: none;
|
|
3080
|
+
height: 26px;
|
|
3081
|
+
padding: 0 12px;
|
|
3082
|
+
border: none;
|
|
3083
|
+
border-radius: 6px;
|
|
3084
|
+
background: var(--dsw-alias-button-primary-fill);
|
|
3085
|
+
color: var(--dsw-alias-label-primary-inverted);
|
|
3086
|
+
font: var(--dsw-font-xxs-strong-12);
|
|
3087
|
+
cursor: pointer;
|
|
3088
|
+
}
|
|
3089
|
+
|
|
3090
|
+
.gitCommitButton:hover:not(:disabled) {
|
|
3091
|
+
background: var(--dsw-alias-button-primary-hover);
|
|
3092
|
+
}
|
|
3093
|
+
|
|
3094
|
+
.gitCommitButton:disabled {
|
|
3095
|
+
opacity: 0.45;
|
|
3096
|
+
cursor: default;
|
|
3097
|
+
}
|
|
3098
|
+
|
|
3099
|
+
/* A history row: line 1 = hash + subject, line 2 = ref badges + author/date
|
|
3100
|
+
(badges live on the second line so they never crowd the subject). */
|
|
3101
|
+
.gitLogRow {
|
|
3102
|
+
display: flex;
|
|
3103
|
+
flex-direction: column;
|
|
3104
|
+
gap: 2px;
|
|
3105
|
+
padding: 5px 12px;
|
|
3106
|
+
cursor: pointer;
|
|
3107
|
+
border-radius: 8px;
|
|
3108
|
+
}
|
|
3109
|
+
|
|
3110
|
+
.gitLogRow:hover {
|
|
3111
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
3112
|
+
}
|
|
3113
|
+
|
|
3114
|
+
.gitLogLine1 {
|
|
3115
|
+
display: flex;
|
|
3116
|
+
align-items: baseline;
|
|
3117
|
+
gap: 8px;
|
|
3118
|
+
min-width: 0;
|
|
3119
|
+
}
|
|
3120
|
+
|
|
3121
|
+
.gitLogHash {
|
|
3122
|
+
flex: none;
|
|
3123
|
+
font: var(--dsw-font-markdown-code-block-small);
|
|
3124
|
+
color: var(--dsw-alias-label-tertiary);
|
|
3125
|
+
}
|
|
3126
|
+
|
|
3127
|
+
.gitLogLine2 {
|
|
3128
|
+
display: flex;
|
|
3129
|
+
align-items: center;
|
|
3130
|
+
gap: 6px;
|
|
3131
|
+
min-width: 0;
|
|
3132
|
+
flex-wrap: wrap;
|
|
3133
|
+
}
|
|
3134
|
+
|
|
3135
|
+
.gitLogRef {
|
|
3136
|
+
flex: none;
|
|
3137
|
+
padding: 0 5px;
|
|
3138
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
3139
|
+
border-radius: 999px;
|
|
3140
|
+
font: var(--dsw-font-xxxs-strong-11);
|
|
3141
|
+
color: var(--dsw-alias-brand-primary);
|
|
3142
|
+
white-space: nowrap;
|
|
3143
|
+
}
|
|
3144
|
+
|
|
3145
|
+
.gitLogSubject {
|
|
3146
|
+
flex: 1;
|
|
3147
|
+
min-width: 0;
|
|
3148
|
+
overflow: hidden;
|
|
3149
|
+
text-overflow: ellipsis;
|
|
3150
|
+
white-space: nowrap;
|
|
3151
|
+
font: var(--dsw-font-s-14);
|
|
3152
|
+
color: var(--dsw-alias-label-primary);
|
|
3153
|
+
}
|
|
3154
|
+
|
|
3155
|
+
.gitLogMeta {
|
|
3156
|
+
font: var(--dsw-font-xxxs-11);
|
|
3157
|
+
color: var(--dsw-alias-label-tertiary);
|
|
3158
|
+
}
|
|
3159
|
+
|
|
3160
|
+
.gitLogMore {
|
|
3161
|
+
display: block;
|
|
3162
|
+
width: calc(100% - 24px);
|
|
3163
|
+
margin: 4px 12px 8px;
|
|
3164
|
+
padding: 6px 0;
|
|
3165
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
3166
|
+
border-radius: 6px;
|
|
3167
|
+
background: transparent;
|
|
3168
|
+
font: var(--dsw-font-xxs-12);
|
|
3169
|
+
color: var(--dsw-alias-label-secondary);
|
|
3170
|
+
cursor: pointer;
|
|
3171
|
+
}
|
|
3172
|
+
|
|
3173
|
+
.gitLogMore:hover:not(:disabled) {
|
|
3174
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
3175
|
+
color: var(--dsw-alias-label-primary);
|
|
3176
|
+
}
|
|
3177
|
+
|
|
3178
|
+
.gitLogMore:disabled {
|
|
3179
|
+
opacity: 0.5;
|
|
3180
|
+
cursor: default;
|
|
3181
|
+
}
|
|
3182
|
+
|
|
3183
|
+
/* ── Intercepted produced-files row ────────────────────────────────────── */
|
|
3184
|
+
|
|
3185
|
+
.producedRow {
|
|
3186
|
+
display: flex;
|
|
3187
|
+
align-items: center;
|
|
3188
|
+
gap: 8px;
|
|
3189
|
+
flex-wrap: wrap;
|
|
3190
|
+
padding: 4px 0;
|
|
3191
|
+
}
|
|
3192
|
+
|
|
3193
|
+
.producedLabel {
|
|
3194
|
+
font: var(--dsw-font-xxs-12);
|
|
3195
|
+
color: var(--dsw-alias-label-tertiary);
|
|
3196
|
+
}
|
|
3197
|
+
|
|
3198
|
+
.producedChip {
|
|
3199
|
+
display: inline-flex;
|
|
3200
|
+
align-items: center;
|
|
3201
|
+
gap: 4px;
|
|
3202
|
+
max-width: 200px;
|
|
3203
|
+
padding: 2px 8px;
|
|
3204
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
3205
|
+
border-radius: 999px;
|
|
3206
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
3207
|
+
color: var(--dsw-alias-label-secondary);
|
|
3208
|
+
font: var(--dsw-font-xxs-12);
|
|
3209
|
+
cursor: pointer;
|
|
3210
|
+
overflow: hidden;
|
|
3211
|
+
}
|
|
3212
|
+
|
|
3213
|
+
.producedChip:hover {
|
|
3214
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
3215
|
+
color: var(--dsw-alias-label-primary);
|
|
3216
|
+
}
|
|
3217
|
+
|
|
3218
|
+
.producedChip span {
|
|
3219
|
+
overflow: hidden;
|
|
3220
|
+
text-overflow: ellipsis;
|
|
3221
|
+
white-space: nowrap;
|
|
3222
|
+
}
|
|
3223
|
+
|
|
3224
|
+
.producedMore {
|
|
3225
|
+
font: var(--dsw-font-xxs-12);
|
|
3226
|
+
color: var(--dsw-alias-label-tertiary);
|
|
3227
|
+
}
|
|
3228
|
+
|
|
3229
|
+
/* ── Shared interaction rules ──────────────────────────────────────────── */
|
|
3230
|
+
|
|
3231
|
+
/* Keyboard focus stays visible on every interactive control (the styling
|
|
3232
|
+
policy requires focus visibility; the accent token doubles as the ring). */
|
|
3233
|
+
.toggleButton:focus-visible,
|
|
3234
|
+
.manualButton:focus-visible,
|
|
3235
|
+
.bottomClose:focus-visible,
|
|
3236
|
+
.iconButton:focus-visible,
|
|
3237
|
+
.tab:focus-visible,
|
|
3238
|
+
.tabClose:focus-visible,
|
|
3239
|
+
.tabBarPlus:focus-visible,
|
|
3240
|
+
.paneCard:focus-visible,
|
|
3241
|
+
.explorerRow:focus-visible,
|
|
3242
|
+
.explorerRef:focus-visible,
|
|
3243
|
+
.gitRowMain:focus-visible,
|
|
3244
|
+
.gitLink:focus-visible,
|
|
3245
|
+
.gitCommitButton:focus-visible,
|
|
3246
|
+
.gitLogRow:focus-visible,
|
|
3247
|
+
.gitLogMore:focus-visible,
|
|
3248
|
+
.gitDiffFile:focus-visible,
|
|
3249
|
+
.gitDiffExpand:focus-visible,
|
|
3250
|
+
.terminalRetry:focus-visible,
|
|
3251
|
+
.editorModeButton:focus-visible,
|
|
3252
|
+
.editorDownloadLink:focus-visible,
|
|
3253
|
+
.editorPptxButton:focus-visible,
|
|
3254
|
+
.editorDocxZoomRange:focus-visible {
|
|
3255
|
+
outline: 2px solid var(--dsw-alias-interactive-bg-hover-accent);
|
|
3256
|
+
outline-offset: -1px;
|
|
3257
|
+
}
|
|
3258
|
+
|
|
3259
|
+
/* Reduced motion: no slides, fades or color transitions. */
|
|
3260
|
+
@media (prefers-reduced-motion: reduce) {
|
|
3261
|
+
.panel,
|
|
3262
|
+
.panelHidden,
|
|
3263
|
+
.bottomPanel,
|
|
3264
|
+
.bottomPanelHidden,
|
|
3265
|
+
.toggleCluster,
|
|
3266
|
+
.toggleButton,
|
|
3267
|
+
.tab,
|
|
3268
|
+
.tabBarPlus,
|
|
3269
|
+
.paneCard,
|
|
3270
|
+
.explorerRow,
|
|
3271
|
+
.gitRow,
|
|
3272
|
+
.divider,
|
|
3273
|
+
.dividerRow::after,
|
|
3274
|
+
.dividerCol::after {
|
|
3275
|
+
transition: none;
|
|
3276
|
+
animation: none;
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3279
|
+
|
|
3280
|
+
/* ── Narrow (mobile) viewport ──────────────────────────────────────────── */
|
|
3281
|
+
|
|
3282
|
+
/* Pairs with NARROW_MAX_WIDTH = 768 in src/client/breakpoints.ts: widths
|
|
3283
|
+
strictly below 768px (i.e. max-width: 767px) switch the sidebar to the
|
|
3284
|
+
mobile layout — one full-screen drawer (the bottom panel's tabs were
|
|
3285
|
+
migrated into the right tree), one toggle button. The structural
|
|
3286
|
+
switches (which panels render, the migration) are JS-driven via
|
|
3287
|
+
useNarrowViewport; this block only adapts the pure style details. */
|
|
3288
|
+
@media (max-width: 767px) {
|
|
3289
|
+
/* The action cluster holds the labeled manual and right-panel control on
|
|
3290
|
+
narrow viewports (the bottom-panel button is not rendered), so the open
|
|
3291
|
+
panel's tab strip still yields enough room for the full manual label. */
|
|
3292
|
+
.panel:not(.panelHidden) .tabBar {
|
|
3293
|
+
padding-right: 148px;
|
|
3294
|
+
}
|
|
3295
|
+
|
|
3296
|
+
/* Narrower tabs: a phone-width drawer fits more open tabs before the
|
|
3297
|
+
strip scrolls. */
|
|
3298
|
+
.tab {
|
|
3299
|
+
min-width: 48px;
|
|
3300
|
+
max-width: 128px;
|
|
3301
|
+
}
|
|
3302
|
+
}
|
|
3303
|
+
|
|
3304
|
+
/* The file tree "open with" menu rows: the label area is a BLOCK-level flex
|
|
3305
|
+
row that fills the primitives `.itemLabel` span (which is itself `flex: 1`
|
|
3306
|
+
inside the row), so the trailing control — the pushpin on submenu rows,
|
|
3307
|
+
the chevron on the submenu parent — docks at the row's far right, exactly
|
|
3308
|
+
like the trailing check on selected rows of every other menu. */
|
|
3309
|
+
.openWithLabel {
|
|
3310
|
+
display: flex;
|
|
3311
|
+
align-items: center;
|
|
3312
|
+
gap: 8px;
|
|
3313
|
+
width: 100%;
|
|
3314
|
+
min-width: 0;
|
|
3315
|
+
}
|
|
3316
|
+
|
|
3317
|
+
.openWithName {
|
|
3318
|
+
flex: 1 1 auto;
|
|
3319
|
+
min-width: 0;
|
|
3320
|
+
overflow: hidden;
|
|
3321
|
+
text-overflow: ellipsis;
|
|
3322
|
+
white-space: nowrap;
|
|
3323
|
+
}
|
|
3324
|
+
|
|
3325
|
+
/* The trailing "expands into a submenu" chevron on the open-with parent row
|
|
3326
|
+
(the primitives Menu renders no arrow for submenu parents). */
|
|
3327
|
+
.openWithChevron {
|
|
3328
|
+
flex: none;
|
|
3329
|
+
color: var(--dsw-alias-label-tertiary);
|
|
3330
|
+
}
|
|
3331
|
+
|
|
3332
|
+
/* The pushpin toggle on an "open with" submenu row: brand ink once the
|
|
3333
|
+
target is pinned to the menu's top level. */
|
|
3334
|
+
.openWithPin {
|
|
3335
|
+
flex: none;
|
|
3336
|
+
display: inline-flex;
|
|
3337
|
+
align-items: center;
|
|
3338
|
+
justify-content: center;
|
|
3339
|
+
width: 20px;
|
|
3340
|
+
height: 20px;
|
|
3341
|
+
border-radius: 6px;
|
|
3342
|
+
color: var(--dsw-alias-label-tertiary);
|
|
3343
|
+
cursor: pointer;
|
|
3344
|
+
}
|
|
3345
|
+
|
|
3346
|
+
.openWithPin:hover {
|
|
3347
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
3348
|
+
color: var(--dsw-alias-label-primary);
|
|
3349
|
+
}
|
|
3350
|
+
|
|
3351
|
+
.openWithPinActive {
|
|
3352
|
+
color: var(--dsw-alias-state-business-primary);
|
|
3353
|
+
}
|
|
3354
|
+
|
|
3355
|
+
/* ── Markdown preview: raw-HTML runs + table of contents ─────────────────
|
|
3356
|
+
The HTML runs lifted out of the markdown source (MarkdownHtml.tsx) render
|
|
3357
|
+
as sanitized block leaves; the TOC is a zero-height sticky bar keeping the
|
|
3358
|
+
outline button pinned at the preview's top-right without consuming layout.
|
|
3359
|
+
All visuals ride the alias tokens (skin system follows automatically). */
|
|
3360
|
+
|
|
3361
|
+
/* A sanitized HTML run leaf (block-level box; content is DOMPurify output). */
|
|
3362
|
+
.editorHtmlBlock {
|
|
3363
|
+
margin: 8px 0;
|
|
3364
|
+
}
|
|
3365
|
+
|
|
3366
|
+
.editorHtmlBlock img,
|
|
3367
|
+
.editorHtmlBlock video {
|
|
3368
|
+
max-width: 100%;
|
|
3369
|
+
}
|
|
3370
|
+
|
|
3371
|
+
.editorHtmlBlock details {
|
|
3372
|
+
margin: 4px 0;
|
|
3373
|
+
padding: 4px 0;
|
|
3374
|
+
}
|
|
3375
|
+
|
|
3376
|
+
.editorHtmlBlock summary {
|
|
3377
|
+
cursor: pointer;
|
|
3378
|
+
}
|
|
3379
|
+
|
|
3380
|
+
/* The zero-height sticky bar: occupies no layout, keeps the button visible
|
|
3381
|
+
while the preview scrolls, and lets pointer events pass through the bar
|
|
3382
|
+
itself (only the interactive children re-enable them). */
|
|
3383
|
+
.tocBar {
|
|
3384
|
+
position: sticky;
|
|
3385
|
+
top: 0;
|
|
3386
|
+
z-index: 3;
|
|
3387
|
+
display: flex;
|
|
3388
|
+
justify-content: flex-end;
|
|
3389
|
+
height: 0;
|
|
3390
|
+
pointer-events: none;
|
|
3391
|
+
}
|
|
3392
|
+
|
|
3393
|
+
.tocButton {
|
|
3394
|
+
pointer-events: auto;
|
|
3395
|
+
display: inline-flex;
|
|
3396
|
+
align-items: center;
|
|
3397
|
+
justify-content: center;
|
|
3398
|
+
width: 26px;
|
|
3399
|
+
height: 26px;
|
|
3400
|
+
margin: 4px 2px 0 0;
|
|
3401
|
+
padding: 0;
|
|
3402
|
+
border: 1px solid var(--dsw-alias-border-l1);
|
|
3403
|
+
border-radius: 6px;
|
|
3404
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
3405
|
+
color: var(--dsw-alias-label-secondary);
|
|
3406
|
+
cursor: pointer;
|
|
3407
|
+
}
|
|
3408
|
+
|
|
3409
|
+
.tocButton:hover {
|
|
3410
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
3411
|
+
color: var(--dsw-alias-label-primary);
|
|
3412
|
+
}
|
|
3413
|
+
|
|
3414
|
+
/* The outline popover, anchored under the button (the bar is the containing
|
|
3415
|
+
block; its height is 0, so the panel drops below the pinned button row). */
|
|
3416
|
+
.tocPanel {
|
|
3417
|
+
position: absolute;
|
|
3418
|
+
top: 32px;
|
|
3419
|
+
right: 2px;
|
|
3420
|
+
display: flex;
|
|
3421
|
+
flex-direction: column;
|
|
3422
|
+
width: min(300px, 82%);
|
|
3423
|
+
max-height: 60vh;
|
|
3424
|
+
overflow-y: auto;
|
|
3425
|
+
padding: 4px;
|
|
3426
|
+
border: 1px solid var(--dsw-alias-border-l1);
|
|
3427
|
+
border-radius: 8px;
|
|
3428
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
3429
|
+
box-shadow: var(--dsw-shadow-lv2);
|
|
3430
|
+
pointer-events: auto;
|
|
3431
|
+
}
|
|
3432
|
+
|
|
3433
|
+
.tocItem {
|
|
3434
|
+
display: flex;
|
|
3435
|
+
align-items: baseline;
|
|
3436
|
+
gap: 8px;
|
|
3437
|
+
min-width: 0;
|
|
3438
|
+
padding: 4px 8px;
|
|
3439
|
+
border: none;
|
|
3440
|
+
border-radius: 6px;
|
|
3441
|
+
background: transparent;
|
|
3442
|
+
color: var(--dsw-alias-label-secondary);
|
|
3443
|
+
font: var(--dsw-font-xxs-12);
|
|
3444
|
+
text-align: left;
|
|
3445
|
+
cursor: pointer;
|
|
3446
|
+
}
|
|
3447
|
+
|
|
3448
|
+
.tocItem:hover {
|
|
3449
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
3450
|
+
color: var(--dsw-alias-label-primary);
|
|
3451
|
+
}
|
|
3452
|
+
|
|
3453
|
+
/* Indent by heading level (h2 = one step, h3 = two steps…). */
|
|
3454
|
+
.tocItem[data-level='2'] { padding-left: 18px; }
|
|
3455
|
+
.tocItem[data-level='3'] { padding-left: 28px; }
|
|
3456
|
+
.tocItem[data-level='4'] { padding-left: 38px; }
|
|
3457
|
+
.tocItem[data-level='5'] { padding-left: 48px; }
|
|
3458
|
+
.tocItem[data-level='6'] { padding-left: 58px; }
|
|
3459
|
+
|
|
3460
|
+
/* The tiny level number keeps deep outlines scannable. */
|
|
3461
|
+
.tocItemLevel {
|
|
3462
|
+
flex: none;
|
|
3463
|
+
font: var(--dsw-font-xxxs-11);
|
|
3464
|
+
color: var(--dsw-alias-label-tertiary);
|
|
3465
|
+
}
|
|
3466
|
+
|
|
3467
|
+
.tocItemText {
|
|
3468
|
+
flex: 1 1 auto;
|
|
3469
|
+
min-width: 0;
|
|
3470
|
+
overflow: hidden;
|
|
3471
|
+
text-overflow: ellipsis;
|
|
3472
|
+
white-space: nowrap;
|
|
3473
|
+
}
|
|
3474
|
+
|
|
3475
|
+
/* The jumped-to heading flashes once (the class is added to the host-rendered
|
|
3476
|
+
heading element by md-toc.tsx; @keyframes rides the CSS module). */
|
|
3477
|
+
@keyframes dsh-toc-flash {
|
|
3478
|
+
0%, 60% { background: var(--dsw-alias-interactive-bg-hover); }
|
|
3479
|
+
100% { background: transparent; }
|
|
3480
|
+
}
|
|
3481
|
+
|
|
3482
|
+
.tocFlash {
|
|
3483
|
+
animation: dsh-toc-flash 1.2s ease-out;
|
|
3484
|
+
border-radius: 4px;
|
|
3485
|
+
}
|
|
3486
|
+
|
|
3487
|
+
/* Mandatory account gate advertised by the auth service. */
|
|
3488
|
+
.chatcodeGate {
|
|
3489
|
+
position: fixed;
|
|
3490
|
+
inset: 0;
|
|
3491
|
+
z-index: 2147483000;
|
|
3492
|
+
display: grid;
|
|
3493
|
+
place-items: center;
|
|
3494
|
+
padding: 24px;
|
|
3495
|
+
isolation: isolate;
|
|
3496
|
+
overflow: hidden;
|
|
3497
|
+
/* `bg-mask-*` is deliberately translucent, so it cannot serve as this
|
|
3498
|
+
mandatory gate's base. Tooltip fill is the host's opaque dark surface;
|
|
3499
|
+
paired with the brand token it produces a dependable blue-black field. */
|
|
3500
|
+
background-color: var(--dsw-alias-tooltip-bg);
|
|
3501
|
+
background-image: linear-gradient(135deg, var(--dsw-alias-tooltip-bg) 0%, var(--dsw-alias-brand-primary) 48%, var(--dsw-alias-tooltip-bg) 100%);
|
|
3502
|
+
color: var(--dsw-alias-fg-base);
|
|
3503
|
+
pointer-events: auto;
|
|
3504
|
+
}
|
|
3505
|
+
|
|
3506
|
+
.chatcodeGateCard {
|
|
3507
|
+
position: relative;
|
|
3508
|
+
box-sizing: border-box;
|
|
3509
|
+
width: min(460px, 100%);
|
|
3510
|
+
padding: 40px 36px;
|
|
3511
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
3512
|
+
border-radius: 20px;
|
|
3513
|
+
background: linear-gradient(145deg, var(--dsw-alias-bg-layer-2), var(--dsw-alias-bg-layer-1));
|
|
3514
|
+
box-shadow: var(--dsw-shadow-lv3);
|
|
3515
|
+
text-align: center;
|
|
3516
|
+
}
|
|
3517
|
+
|
|
3518
|
+
.chatcodeGateContent {
|
|
3519
|
+
position: relative;
|
|
3520
|
+
}
|
|
3521
|
+
|
|
3522
|
+
.chatcodeGateCard h1 {
|
|
3523
|
+
margin: 0 0 12px;
|
|
3524
|
+
font: var(--dsw-font-heading-lg);
|
|
3525
|
+
font-size: clamp(32px, 5vw, 46px);
|
|
3526
|
+
line-height: 1.1;
|
|
3527
|
+
letter-spacing: -.02em;
|
|
3528
|
+
}
|
|
3529
|
+
|
|
3530
|
+
.chatcodeGateCard p {
|
|
3531
|
+
max-width: 29em;
|
|
3532
|
+
margin: 0 auto;
|
|
3533
|
+
color: var(--dsw-alias-label-secondary);
|
|
3534
|
+
font: var(--dsw-font-s-14);
|
|
3535
|
+
line-height: 1.7;
|
|
3536
|
+
}
|
|
3537
|
+
|
|
3538
|
+
.chatcodeGateError {
|
|
3539
|
+
position: relative;
|
|
3540
|
+
margin-top: 16px !important;
|
|
3541
|
+
padding: 9px 11px;
|
|
3542
|
+
border: 1px solid color-mix(in srgb, var(--dsw-alias-fg-error) 36%, var(--dsw-alias-border-l2));
|
|
3543
|
+
border-radius: 10px;
|
|
3544
|
+
background: color-mix(in srgb, var(--dsw-alias-fg-error) 8%, transparent);
|
|
3545
|
+
color: var(--dsw-alias-fg-error) !important;
|
|
3546
|
+
font: var(--dsw-font-xxs-12) !important;
|
|
3547
|
+
line-height: 1.5 !important;
|
|
3548
|
+
}
|
|
3549
|
+
|
|
3550
|
+
.chatcodeGateActions {
|
|
3551
|
+
position: relative;
|
|
3552
|
+
display: flex;
|
|
3553
|
+
justify-content: center;
|
|
3554
|
+
gap: 10px;
|
|
3555
|
+
margin: 28px 0 14px;
|
|
3556
|
+
}
|
|
3557
|
+
.chatcodeGateActions button,
|
|
3558
|
+
.chatcodeGateCard a {
|
|
3559
|
+
min-height: 42px;
|
|
3560
|
+
padding: 9px 17px;
|
|
3561
|
+
border: 1px solid var(--dsw-alias-border-l2);
|
|
3562
|
+
border-radius: 10px;
|
|
3563
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
3564
|
+
color: var(--dsw-alias-fg-base);
|
|
3565
|
+
font: var(--dsw-font-xxs-strong-12);
|
|
3566
|
+
cursor: pointer;
|
|
3567
|
+
transition: transform var(--ds-transition-duration-slow) var(--ds-ease-in-out), background var(--ds-transition-duration-slow) var(--ds-ease-in-out), border-color var(--ds-transition-duration-slow) var(--ds-ease-in-out);
|
|
3568
|
+
}
|
|
3569
|
+
|
|
3570
|
+
.chatcodeGateActions button:first-child {
|
|
3571
|
+
min-width: 152px;
|
|
3572
|
+
min-height: 46px;
|
|
3573
|
+
border-color: var(--dsw-alias-state-error-primary);
|
|
3574
|
+
background: var(--dsw-alias-state-error-primary);
|
|
3575
|
+
color: var(--dsw-alias-label-primary-inverted);
|
|
3576
|
+
}
|
|
3577
|
+
|
|
3578
|
+
.chatcodeGateActions button:first-child:hover:not(:disabled) {
|
|
3579
|
+
transform: translateY(-2px);
|
|
3580
|
+
border-color: var(--dsw-alias-state-error-primary) !important;
|
|
3581
|
+
background: var(--dsw-alias-state-error-primary) !important;
|
|
3582
|
+
color: var(--dsw-alias-label-primary-inverted) !important;
|
|
3583
|
+
box-shadow: var(--dsw-shadow-lv2);
|
|
3584
|
+
}
|
|
3585
|
+
|
|
3586
|
+
.chatcodeGateActions button:not(:first-child):hover:not(:disabled),
|
|
3587
|
+
.chatcodeGateCard a:hover {
|
|
3588
|
+
transform: translateY(-1px);
|
|
3589
|
+
border-color: var(--dsw-alias-button-primary-hover);
|
|
3590
|
+
background: var(--dsw-alias-button-primary-hover);
|
|
3591
|
+
color: var(--dsw-alias-label-primary-inverted);
|
|
3592
|
+
}
|
|
3593
|
+
|
|
3594
|
+
.chatcodeGateActions button:disabled { cursor: default; opacity: .55; }
|
|
3595
|
+
.chatcodeGateCard a { position: relative; display: inline-flex; align-items: center; text-decoration: none; }
|
|
3596
|
+
.chatcodeGateActions button:focus-visible,
|
|
3597
|
+
.chatcodeGateCard a:focus-visible {
|
|
3598
|
+
outline: 2px solid var(--dsw-alias-border-accent);
|
|
3599
|
+
outline-offset: 3px;
|
|
3600
|
+
}
|
|
3601
|
+
|
|
3602
|
+
@media (max-width: 480px) {
|
|
3603
|
+
.chatcodeGate { padding: 16px; }
|
|
3604
|
+
.chatcodeGateCard { padding: 32px 24px; }
|
|
3605
|
+
.chatcodeGateActions { align-items: stretch; flex-direction: column; }
|
|
3606
|
+
.chatcodeGateActions button, .chatcodeGateCard a { justify-content: center; }
|
|
3607
|
+
}
|