@ljwei-stak/dsh-model-route-bot 0.66.3 → 0.67.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/.dsh-plugin/bot-product.mjs +81 -5
- package/.dsh-plugin/client.js +17490 -1791
- package/README.i18n.yaml +4 -4
- package/README.md +409 -364
- package/README.zh.md +409 -364
- package/apps/integration-client/README.md +31 -7
- package/apps/integration-client/api.mjs +14 -3
- package/apps/integration-client/binding-editor.jsx +308 -109
- package/apps/integration-client/binding-model.mjs +262 -0
- package/apps/integration-client/binding.css +144 -0
- package/apps/integration-client/bot-model-status.mjs +18 -0
- package/apps/integration-client/bot-profile-identity.jsx +197 -0
- package/apps/integration-client/bot-profile.css +57 -0
- package/apps/integration-client/bot-profile.mjs +97 -0
- package/apps/integration-client/bot-settings-dialog.css +18 -0
- package/apps/integration-client/bot-settings-dialog.jsx +111 -0
- package/apps/integration-client/bot-thread-header-bridge.css +20 -0
- package/apps/integration-client/bot-thread-header.jsx +278 -0
- package/apps/integration-client/bot-threads-panel.jsx +378 -0
- package/apps/integration-client/bot-threads.css +169 -0
- package/apps/integration-client/chat-design.mjs +250 -0
- package/apps/integration-client/chat-ui.jsx +175 -0
- package/apps/integration-client/chat.css +477 -0
- package/apps/integration-client/composer-draft-binding.mjs +50 -0
- package/apps/integration-client/composer-draft-bound.jsx +14 -0
- package/apps/integration-client/composer-draft-host.jsx +142 -0
- package/apps/integration-client/composer-draft-session.jsx +287 -0
- package/apps/integration-client/composer-draft-witness.mjs +115 -0
- package/apps/integration-client/composer-draft.css +4 -0
- package/apps/integration-client/composer-draft.mjs +322 -0
- package/apps/integration-client/contact-attention.jsx +54 -0
- package/apps/integration-client/data-panel.jsx +439 -0
- package/apps/integration-client/data.css +69 -0
- package/apps/integration-client/desktop-bridge.mjs +1 -0
- package/apps/integration-client/desktop-http-socket.mjs +49 -0
- package/apps/integration-client/desktop-keyboard.mjs +32 -0
- package/apps/integration-client/desktop-pane.jsx +99 -30
- package/apps/integration-client/desktop-stream.mjs +13 -3
- package/apps/integration-client/desktop-tools.jsx +19 -0
- package/apps/integration-client/desktop-touch.mjs +27 -0
- package/apps/integration-client/desktop.css +41 -0
- package/apps/integration-client/independent-chat-controller.mjs +224 -0
- package/apps/integration-client/independent-chat-entry.jsx +61 -0
- package/apps/integration-client/independent-chat-navigation.mjs +21 -0
- package/apps/integration-client/independent-chat-page.jsx +148 -0
- package/apps/integration-client/independent-chat-rich.jsx +64 -0
- package/apps/integration-client/independent-chat-rich.mjs +30 -0
- package/apps/integration-client/independent-chat.css +73 -0
- package/apps/integration-client/index.jsx +24 -16
- package/apps/integration-client/library-panel.jsx +4 -1
- package/apps/integration-client/licenses/jsqr-1.4.0-LICENSE.txt +202 -0
- package/apps/integration-client/main-route-editor.jsx +94 -0
- package/apps/integration-client/main-route-model.mjs +100 -0
- package/apps/integration-client/model-picker.css +37 -0
- package/apps/integration-client/model-picker.jsx +83 -0
- package/apps/integration-client/native-activity.css +141 -0
- package/apps/integration-client/native-activity.jsx +276 -0
- package/apps/integration-client/native-activity.mjs +384 -0
- package/apps/integration-client/notifications-panel.jsx +186 -0
- package/apps/integration-client/notifications.css +126 -0
- package/apps/integration-client/pairing-qr.jsx +79 -0
- package/apps/integration-client/panels.jsx +126 -115
- package/apps/integration-client/product-slots.jsx +46 -0
- package/apps/integration-client/routine-recorder.mjs +23 -2
- package/apps/integration-client/secure-pairing.jsx +84 -0
- package/apps/integration-client/tasks-panel.jsx +32 -10
- package/apps/integration-client/ui-icons.jsx +17 -0
- package/apps/integration-client/usage-explorer.jsx +43 -0
- package/apps/integration-client/usage-report.mjs +71 -0
- package/apps/integration-client/usage.css +34 -0
- package/apps/integration-client/web-panel-model.mjs +140 -0
- package/apps/integration-client/web-panel-page.jsx +221 -0
- package/apps/integration-client/web-panel-pins-live.jsx +28 -0
- package/apps/integration-client/web-panel.css +139 -0
- package/apps/integration-client/workspace-model.mjs +67 -0
- package/apps/integration-client/workspace-navigation.mjs +56 -0
- package/apps/integration-client/workspace-ui.jsx +173 -0
- package/apps/integration-client/workspace.css +332 -0
- package/modules/bot-runtime/SOURCE.json +176 -50
- package/modules/bot-runtime/index.mjs +169 -13
- package/modules/bot-runtime/product-overlay/OVERLAY.json +128 -2
- package/modules/bot-runtime/product-overlay/base/src/client/header.js +244 -0
- package/modules/bot-runtime/product-overlay/base/src/client/learning-card.js +202 -0
- package/modules/bot-runtime/product-overlay/base/src/client/model-menu.js +371 -0
- package/modules/bot-runtime/product-overlay/base/src/client/secret-card.js +363 -0
- package/modules/bot-runtime/product-overlay/base/src/client/sources.js +68 -0
- package/modules/bot-runtime/product-overlay/base/src/client/turn-error.js +260 -0
- package/modules/bot-runtime/product-overlay/base/src/host/channel.js +647 -0
- package/modules/bot-runtime/product-overlay/base/src/host/memory.js +2050 -0
- package/modules/bot-runtime/product-overlay/base/src/host/models.js +314 -0
- package/modules/bot-runtime/product-overlay/base/src/host/parts.js +1473 -0
- package/modules/bot-runtime/product-overlay/base/src/host/privacy.js +368 -0
- package/modules/bot-runtime/product-overlay/base/src/host/roster.js +776 -0
- package/modules/bot-runtime/product-overlay/base/src/host/store.js +512 -0
- package/modules/bot-runtime/product-overlay/base/src/host/usage.js +653 -0
- package/modules/bot-runtime/product-overlay/patches/src/client/details-drawer.js.patch +48 -2
- package/modules/bot-runtime/product-overlay/patches/src/client/header.js.patch +41 -0
- package/modules/bot-runtime/product-overlay/patches/src/client/index.js.patch +33 -1
- package/modules/bot-runtime/product-overlay/patches/src/client/learning-card.js.patch +20 -0
- package/modules/bot-runtime/product-overlay/patches/src/client/model-menu.js.patch +24 -0
- package/modules/bot-runtime/product-overlay/patches/src/client/secret-card.js.patch +25 -0
- package/modules/bot-runtime/product-overlay/patches/src/client/sources.js.patch +52 -0
- package/modules/bot-runtime/product-overlay/patches/src/client/turn-error.js.patch +23 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/channel.js.patch +46 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/memory.js.patch +11 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/models.js.patch +16 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/parts.js.patch +95 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/privacy.js.patch +11 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/roster.js.patch +145 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/store.js.patch +68 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/usage.js.patch +11 -0
- package/modules/bot-runtime/read-model.mjs +19 -4
- package/modules/bot-runtime/vendor/ds-bot/src/client/details-drawer.js +15 -5
- package/modules/bot-runtime/vendor/ds-bot/src/client/header.js +9 -2
- package/modules/bot-runtime/vendor/ds-bot/src/client/index.js +9 -2
- package/modules/bot-runtime/vendor/ds-bot/src/client/learning-card.js +2 -2
- package/modules/bot-runtime/vendor/ds-bot/src/client/model-menu.js +5 -3
- package/modules/bot-runtime/vendor/ds-bot/src/client/secret-card.js +3 -3
- package/modules/bot-runtime/vendor/ds-bot/src/client/sources.js +25 -2
- package/modules/bot-runtime/vendor/ds-bot/src/client/turn-error.js +3 -2
- package/modules/bot-runtime/vendor/ds-bot/src/host/channel.js +14 -2
- package/modules/bot-runtime/vendor/ds-bot/src/host/memory.js +1 -1
- package/modules/bot-runtime/vendor/ds-bot/src/host/models.js +7 -0
- package/modules/bot-runtime/vendor/ds-bot/src/host/parts.js +26 -9
- package/modules/bot-runtime/vendor/ds-bot/src/host/privacy.js +1 -1
- package/modules/bot-runtime/vendor/ds-bot/src/host/roster.js +112 -3
- package/modules/bot-runtime/vendor/ds-bot/src/host/store.js +34 -1
- package/modules/bot-runtime/vendor/ds-bot/src/host/usage.js +1 -1
- package/modules/independent-runtime/index.mjs +152 -62
- package/modules/independent-runtime/remote-tools.mjs +8 -5
- package/modules/openmaus-protocol/NOTICE +10 -0
- package/modules/openmaus-protocol/README.md +15 -0
- package/modules/openmaus-protocol/SOURCE.json +68 -0
- package/modules/openmaus-protocol/dist/protocol.mjs +1203 -0
- package/modules/openmaus-protocol/index.mjs +1 -0
- package/modules/openmaus-protocol/transport.mjs +77 -0
- package/modules/openmaus-protocol/vendor/LICENSE +202 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/README.md +405 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/credentials.ts +128 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/descriptor.ts +84 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/noise.ts +456 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/phone.ts +104 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/session.ts +417 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/vectors/v1.json +2565 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/vectors/v1.sha256 +1 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/yamux.ts +335 -0
- package/package.json +20 -6
- package/packages/bot-acp/README.md +156 -0
- package/packages/bot-acp/licenses/LICENSE-OpenMausBot +202 -0
- package/packages/bot-acp/licenses/NOTICE.md +27 -0
- package/packages/bot-acp/src/acp-adapter.mjs +795 -0
- package/packages/bot-acp/src/acp-host.mjs +148 -0
- package/packages/bot-acp/src/native-launch.mjs +121 -0
- package/packages/bot-acp/src/permission-policy.mjs +283 -0
- package/packages/bot-acp/src/rpc-codec.mjs +265 -0
- package/packages/bot-acp/src/session-core.mjs +581 -0
- package/packages/bot-acp/src/stdio-rpc.mjs +329 -0
- package/packages/bot-engines/README.md +281 -0
- package/packages/bot-engines/licenses/LICENSE-OpenMausBot +202 -0
- package/packages/bot-engines/licenses/NOTICE.md +32 -0
- package/packages/bot-engines/src/claude-engine.mjs +772 -0
- package/packages/bot-engines/src/claude-llm-adapter.mjs +797 -0
- package/packages/bot-engines/src/claude-llm-turn.mjs +292 -0
- package/packages/bot-engines/src/claude-permission-broker.mjs +130 -0
- package/packages/bot-engines/src/claude-permission-proxy.mjs +87 -0
- package/packages/bot-engines/src/claude-protocol.mjs +177 -0
- package/packages/bot-engines/src/driver-catalog.mjs +334 -0
- package/packages/bot-engines/src/host-loop-request.mjs +95 -0
- package/packages/bot-engines/src/host-registrations.mjs +105 -0
- package/packages/capability-broker/src/cli-bootstrap.mjs +86 -16
- package/packages/capability-broker/src/cli-bridge-response.mjs +80 -0
- package/packages/capability-broker/src/cli-stdio-bridge.mjs +21 -8
- package/packages/cli-runtime/src/codex-session-core.mjs +4 -0
- package/packages/cli-runtime/src/native-cli-output.mjs +57 -0
- package/packages/cli-runtime/src/native-peer.ps1 +51 -3
- package/packages/cli-runtime/src/native-process.mjs +77 -14
- package/packages/model-router-plugin/README.md +3 -3
- package/packages/model-router-plugin/package.json +1 -1
- package/packages/orchestration/src/binding-product.mjs +19 -0
- package/packages/orchestration/src/bot-data-actions.mjs +45 -0
- package/packages/orchestration/src/bot-data-chart.mjs +109 -0
- package/packages/orchestration/src/bot-data-context.mjs +44 -0
- package/packages/orchestration/src/bot-data-engine.mjs +809 -0
- package/packages/orchestration/src/bot-data-io.mjs +186 -0
- package/packages/orchestration/src/bot-data-sql.mjs +195 -0
- package/packages/orchestration/src/bot-data-surface.mjs +144 -0
- package/packages/orchestration/src/bot-data-tools.mjs +68 -0
- package/packages/orchestration/src/bot-data-worker.mjs +228 -0
- package/packages/orchestration/src/bot-independent-execution.mjs +195 -0
- package/packages/orchestration/src/bot-independent-stream.mjs +74 -0
- package/packages/orchestration/src/bot-loop.mjs +152 -19
- package/packages/orchestration/src/bot-notifications.mjs +159 -0
- package/packages/orchestration/src/bot-policy.mjs +43 -4
- package/packages/orchestration/src/bot-profile.mjs +171 -0
- package/packages/orchestration/src/bot-routine.mjs +4 -4
- package/packages/orchestration/src/bot-runtime-assembly.mjs +255 -8
- package/packages/orchestration/src/bot-runtime-switch.mjs +13 -2
- package/packages/orchestration/src/bot-serving.mjs +164 -0
- package/packages/orchestration/src/bot-session-store.mjs +105 -9
- package/packages/orchestration/src/bot-settings.mjs +50 -11
- package/packages/orchestration/src/bot-thread-admission.mjs +84 -0
- package/packages/orchestration/src/bot-thread-host.mjs +187 -0
- package/packages/orchestration/src/bot-threads.mjs +790 -0
- package/packages/orchestration/src/data-product-access.mjs +37 -0
- package/packages/orchestration/src/data-tool-contract.mjs +291 -0
- package/packages/orchestration/src/desktop-http-carrier.mjs +120 -0
- package/packages/orchestration/src/desktop-proxy.mjs +311 -0
- package/packages/orchestration/src/desktop-sessions.mjs +43 -9
- package/packages/orchestration/src/ds-lifecycle.mjs +31 -4
- package/packages/orchestration/src/grant-refresh-queue.mjs +17 -0
- package/packages/orchestration/src/independent-chat-page.mjs +39 -0
- package/packages/orchestration/src/independent-chat-service.mjs +308 -0
- package/packages/orchestration/src/independent-context-state.mjs +44 -0
- package/packages/orchestration/src/independent-message-wire.mjs +84 -0
- package/packages/orchestration/src/independent-tool-catalog.mjs +175 -0
- package/packages/orchestration/src/independent-tool-families.mjs +73 -0
- package/packages/orchestration/src/independent-tool-host.mjs +344 -0
- package/packages/orchestration/src/main-bot-grant.mjs +15 -0
- package/packages/orchestration/src/main-model-routes.mjs +208 -0
- package/packages/orchestration/src/model-accounting.mjs +99 -35
- package/packages/orchestration/src/model-auxiliary-dispatch.mjs +187 -0
- package/packages/orchestration/src/model-loop-frame.mjs +179 -0
- package/packages/orchestration/src/model-prepared-generation.mjs +175 -0
- package/packages/orchestration/src/model-request-bounds.mjs +111 -0
- package/packages/orchestration/src/native-activity-contract.mjs +491 -0
- package/packages/orchestration/src/native-activity-service.mjs +102 -0
- package/packages/orchestration/src/native-activity-store.mjs +249 -0
- package/packages/orchestration/src/native-conversation-tools.mjs +78 -0
- package/packages/orchestration/src/native-data-tools.mjs +100 -0
- package/packages/orchestration/src/native-remote-actions.mjs +742 -0
- package/packages/orchestration/src/native-team-tools.mjs +73 -0
- package/packages/orchestration/src/pairing-invite.mjs +37 -0
- package/packages/orchestration/src/product-composition.mjs +1559 -1001
- package/packages/orchestration/src/remote-machines.mjs +82 -14
- package/packages/orchestration/src/routine-execution.mjs +5 -3
- package/packages/orchestration/src/routine-session.mjs +19 -13
- package/packages/orchestration/src/secure-pairing-host.mjs +112 -0
- package/packages/orchestration/src/task-journal.mjs +29 -0
- package/packages/orchestration/src/task-product.mjs +17 -0
- package/packages/orchestration/src/team-assignment-store.mjs +120 -0
- package/packages/orchestration/src/team-bridge.mjs +282 -0
- package/packages/orchestration/src/team-scheduler.mjs +83 -0
- package/packages/orchestration/src/team-sdk-tools.mjs +84 -0
- package/packages/orchestration/src/team-tool-contract.mjs +284 -0
- package/packages/orchestration/src/ui-host-namespace.mjs +23 -0
- package/packages/orchestration/src/web-panel-actions.mjs +103 -0
- package/packages/orchestration/src/web-panel-framing.mjs +227 -0
- package/packages/orchestration/src/web-panel-store.mjs +206 -0
- package/remote-computer-agent/README.md +39 -29
- package/remote-computer-agent/build.mjs +3 -0
- package/remote-computer-agent/dist/OPENMAUSBOT_LICENSE +202 -0
- package/remote-computer-agent/dist/OPENMAUSBOT_NOTICE +10 -0
- package/remote-computer-agent/dist/OPENMAUSBOT_SOURCE.json +68 -0
- package/remote-computer-agent/dist/cli-stdio-bridge.mjs +215 -25
- package/remote-computer-agent/dist/cli-stdio-bridge.mjs.map +4 -4
- package/remote-computer-agent/dist/cli.mjs +1688 -168
- package/remote-computer-agent/dist/cli.mjs.map +4 -4
- package/remote-computer-agent/dist/index.mjs +1579 -122
- package/remote-computer-agent/dist/index.mjs.map +4 -4
- package/remote-computer-agent/dist/native-peer.ps1 +51 -3
- package/remote-computer-agent/package-lock.json +308 -2
- package/remote-computer-agent/package.json +2 -1
- package/remote-computer-agent/pair-device.ps1 +20 -0
- package/remote-computer-agent/setup.ps1 +38 -16
- package/remote-computer-agent/src/cli.ts +24 -3
- package/remote-computer-agent/src/desktop-session.ts +11 -3
- package/remote-computer-agent/src/e2e-server.ts +81 -0
- package/remote-computer-agent/src/pairing-page.ts +35 -0
- package/remote-computer-agent/src/protocol.ts +25 -25
- package/remote-computer-agent/src/secure-pairing.ts +105 -0
- package/remote-computer-agent/src/store.ts +20 -5
- package/remote-computer-agent/src/transport.ts +39 -15
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import React, { useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'
|
|
2
|
+
import { modelName, TASK_STATES } from './api.mjs'
|
|
3
|
+
import { taskIdOf, taskKey, taskTitle } from './task-progress.mjs'
|
|
4
|
+
import { workspaceOverview, workspaceSearch } from './workspace-model.mjs'
|
|
5
|
+
import { UiIcon } from './ui-icons.jsx'
|
|
6
|
+
|
|
7
|
+
const APPEARANCE_KEY = 'dsh.bot.workspace.appearance.v1'
|
|
8
|
+
const appearanceStores = new WeakMap()
|
|
9
|
+
const defaults = Object.freeze({ appearance: 'host', density: 'comfortable', chatWidth: 'standard', colorUserBubbles: true, saved: true })
|
|
10
|
+
const normalizeAppearance = value => ({ appearance: ['host', 'light', 'dark'].includes(value?.appearance) ? value.appearance : 'host',
|
|
11
|
+
density: value?.density === 'compact' ? 'compact' : 'comfortable',
|
|
12
|
+
chatWidth: ['standard', 'wide', 'full'].includes(value?.chatWidth) ? value.chatWidth : 'standard',
|
|
13
|
+
colorUserBubbles: value?.colorUserBubbles !== false, saved: true })
|
|
14
|
+
|
|
15
|
+
export function workspaceAppearance(win = window) {
|
|
16
|
+
if (appearanceStores.has(win)) return appearanceStores.get(win)
|
|
17
|
+
let value = defaults
|
|
18
|
+
const read = () => { try { return normalizeAppearance(JSON.parse(win.localStorage.getItem(APPEARANCE_KEY))) } catch { return defaults } }
|
|
19
|
+
value = read()
|
|
20
|
+
const listeners = new Set()
|
|
21
|
+
const publish = () => { for (const listener of listeners) listener() }
|
|
22
|
+
const store = Object.freeze({
|
|
23
|
+
getSnapshot: () => value,
|
|
24
|
+
subscribe(listener) { listeners.add(listener); return () => listeners.delete(listener) },
|
|
25
|
+
set(patch) {
|
|
26
|
+
value = normalizeAppearance({ ...value, ...patch })
|
|
27
|
+
try { win.localStorage.setItem(APPEARANCE_KEY, JSON.stringify({ appearance: value.appearance, density: value.density,
|
|
28
|
+
chatWidth: value.chatWidth, colorUserBubbles: value.colorUserBubbles })) }
|
|
29
|
+
catch { value = { ...value, saved: false } }
|
|
30
|
+
publish()
|
|
31
|
+
},
|
|
32
|
+
reload() { value = read(); publish() },
|
|
33
|
+
})
|
|
34
|
+
appearanceStores.set(win, store)
|
|
35
|
+
return store
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function installWorkspaceAppearance(win = window) {
|
|
39
|
+
const body = win.document.body, store = workspaceAppearance(win)
|
|
40
|
+
const attributes = ['data-bp-appearance', 'data-bp-density', 'data-bp-chat-width', 'data-bp-user-bubbles']
|
|
41
|
+
const previous = attributes.map(name => body.getAttribute(name))
|
|
42
|
+
const paint = () => {
|
|
43
|
+
const value = store.getSnapshot()
|
|
44
|
+
body.setAttribute(attributes[0], value.appearance); body.setAttribute(attributes[1], value.density)
|
|
45
|
+
body.setAttribute(attributes[2], value.chatWidth); body.setAttribute(attributes[3], value.colorUserBubbles ? 'colored' : 'neutral')
|
|
46
|
+
}
|
|
47
|
+
const onStorage = event => { if (event.key === APPEARANCE_KEY || event.key === null) store.reload() }
|
|
48
|
+
const unsubscribe = store.subscribe(paint)
|
|
49
|
+
paint(); win.addEventListener('storage', onStorage)
|
|
50
|
+
return () => {
|
|
51
|
+
unsubscribe(); win.removeEventListener('storage', onStorage)
|
|
52
|
+
attributes.forEach((name, index) => previous[index] === null ? body.removeAttribute(name) : body.setAttribute(name, previous[index]))
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function AppearanceControls() {
|
|
57
|
+
const store = workspaceAppearance(), value = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot)
|
|
58
|
+
return <details className="bp-appearance"><summary aria-label="外观与显示" title="外观与显示"><UiIcon name="sun" size={17} /></summary>
|
|
59
|
+
<div className="bp-appearance-menu"><strong>外观与显示</strong>
|
|
60
|
+
<fieldset><legend>颜色</legend><div className="bp-segmented">{[['host', '跟随宿主'], ['light', '浅色'], ['dark', '深色']].map(([key, label]) => <button key={key} type="button" aria-pressed={value.appearance === key} onClick={() => store.set({ appearance: key })}>{label}</button>)}</div></fieldset>
|
|
61
|
+
<fieldset><legend>信息密度</legend><div className="bp-segmented">{[['comfortable', '舒适'], ['compact', '紧凑']].map(([key, label]) => <button key={key} type="button" aria-pressed={value.density === key} onClick={() => store.set({ density: key })}>{label}</button>)}</div></fieldset>
|
|
62
|
+
<fieldset><legend>聊天宽度</legend><div className="bp-segmented">{[['standard', '标准'], ['wide', '宽屏'], ['full', '铺满']].map(([key, label]) => <button key={key} type="button" aria-pressed={value.chatWidth === key} onClick={() => store.set({ chatWidth: key })}>{label}</button>)}</div></fieldset>
|
|
63
|
+
<fieldset><legend>我的消息气泡</legend><div className="bp-segmented">{[[true, '彩色'], [false, '素色']].map(([enabled, label]) => <button key={label} type="button" aria-pressed={value.colorUserBubbles === enabled} onClick={() => store.set({ colorUserBubbles: enabled })}>{label}</button>)}</div></fieldset>
|
|
64
|
+
{!value.saved && <p role="status">已应用到此窗口,浏览器暂不能保存偏好。</p>}
|
|
65
|
+
</div>
|
|
66
|
+
</details>
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function WorkspaceToolbar({ title, onHome, onSearch }) {
|
|
70
|
+
return <div className="bp-workspace-bar"><div className="bp-workspace-location"><button type="button" className="bp-workspace-brand" onClick={onHome} aria-label="返回工作空间总览"><UiIcon name="spark" size={18} /><span>DSH WORKSPACE</span></button><span className="bp-workspace-divider" aria-hidden="true">/</span><span className="bp-workspace-current">{title}</span></div>
|
|
71
|
+
<div className="bp-workspace-bar-actions"><button type="button" className="bp-workspace-search" onClick={onSearch} aria-label="搜索工作空间"><UiIcon name="search" size={16} /><span>查找任务、伙伴、电脑</span><kbd>Ctrl K</kbd></button><AppearanceControls /></div>
|
|
72
|
+
</div>
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function WorkspaceCommandPalette({ open, onClose, snapshot, onNavigate, openSession }) {
|
|
76
|
+
const [query, setQuery] = useState(''), [cursor, setCursor] = useState(0)
|
|
77
|
+
const input = useRef(null), close = useRef(null), selected = useRef(null)
|
|
78
|
+
const listId = useId(), titleId = useId()
|
|
79
|
+
const results = useMemo(() => workspaceSearch(snapshot, query), [snapshot, query])
|
|
80
|
+
const position = results.items.length ? Math.min(cursor, results.items.length - 1) : 0
|
|
81
|
+
useLayoutEffect(() => {
|
|
82
|
+
if (!open) return undefined
|
|
83
|
+
const previous = document.activeElement
|
|
84
|
+
setQuery(''); setCursor(0); input.current?.focus()
|
|
85
|
+
return () => { if (previous?.isConnected) previous.focus() }
|
|
86
|
+
}, [open])
|
|
87
|
+
useEffect(() => { selected.current?.scrollIntoView?.({ block: 'nearest' }) }, [position, query, open])
|
|
88
|
+
if (!open) return null
|
|
89
|
+
const activate = row => {
|
|
90
|
+
onClose()
|
|
91
|
+
if (row.kind === 'bot' && row.sessionId && typeof openSession === 'function') openSession(row.sessionId)
|
|
92
|
+
else onNavigate(row.target)
|
|
93
|
+
}
|
|
94
|
+
const onKeyDown = event => {
|
|
95
|
+
if (event.nativeEvent.isComposing || event.nativeEvent.keyCode === 229) { event.stopPropagation(); return }
|
|
96
|
+
if (event.key === 'Escape') { event.preventDefault(); event.stopPropagation(); onClose() }
|
|
97
|
+
else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
98
|
+
event.preventDefault()
|
|
99
|
+
const length = results.items.length
|
|
100
|
+
setCursor(length ? (position + (event.key === 'ArrowDown' ? 1 : -1) + length) % length : 0)
|
|
101
|
+
} else if (event.key === 'Enter' && event.target !== close.current) {
|
|
102
|
+
event.preventDefault(); if (results.items[position]) activate(results.items[position])
|
|
103
|
+
} else if (event.key === 'Tab') {
|
|
104
|
+
event.preventDefault(); if (document.activeElement === input.current) close.current?.focus(); else input.current?.focus()
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return <div className="bp-palette-backdrop" onMouseDown={event => { if (event.target === event.currentTarget) onClose() }} onKeyDown={onKeyDown}>
|
|
108
|
+
<section className="bp-palette" role="dialog" aria-modal="true" aria-labelledby={titleId}><h2 id={titleId} className="bp-sr-only">搜索工作空间</h2>
|
|
109
|
+
<div className="bp-palette-input"><UiIcon name="search" size={20} /><input ref={input} role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls={listId} aria-activedescendant={results.items.length ? `${listId}-${position}` : undefined} value={query} onChange={event => { setQuery(event.target.value); setCursor(0) }} placeholder="搜索任务、Bot、模型或操作编号…" aria-label="搜索任务、Bot 和电脑" autoComplete="off" /><button ref={close} type="button" aria-label="关闭搜索" onClick={onClose}><UiIcon name="close" size={18} /></button></div>
|
|
110
|
+
<p className="bp-palette-caption">当前工作空间 · 仅搜索已加载记录{snapshot?.tasks?.truncated ? `(任务已加载 ${snapshot.tasks.items?.length ?? 0} / ${snapshot.tasks.total ?? '未知'} 条)` : ''}</p>
|
|
111
|
+
<div className="bp-palette-results" id={listId} role="listbox" aria-label="搜索结果">{results.items.map((row, index) => <button key={row.id} id={`${listId}-${index}`} role="option" aria-selected={index === position} tabIndex={-1} type="button" ref={index === position ? selected : undefined} onMouseMove={() => setCursor(index)} onClick={() => activate(row)}>
|
|
112
|
+
<span className="bp-result-icon"><UiIcon name={row.icon} size={19} /></span><span className="bp-result-copy"><strong>{row.label}</strong><small>{row.detail}</small></span><span className="bp-result-kind">{{ page: '页面', bot: 'Bot', task: '任务', machine: '电脑' }[row.kind]}</span><UiIcon name="chevron" size={14} />
|
|
113
|
+
</button>)}{!results.items.length && <p className="bp-search-empty">没有匹配的记录。试试名称、模型或完整任务编号。</p>}</div>
|
|
114
|
+
<footer className="bp-palette-footer"><span><kbd>↑ ↓</kbd> 选择 <kbd>Enter</kbd> 打开 <kbd>Esc</kbd> 关闭</span><span role="status">{results.total} 项{results.truncated ? `,显示前 ${results.items.length} 项` : ''}</span></footer>
|
|
115
|
+
</section>
|
|
116
|
+
</div>
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const STAGES = { reconcile: ['收据待核对', 'clock'], approve: ['等待审批', 'lock'], 'remote-unknown': ['结果待确认', 'clock'], budget: ['等待预算', 'chart'], failed: ['执行失败', 'activity'], blocked: ['需要协助', 'inbox'] }
|
|
120
|
+
const when = value => value && Number.isFinite(new Date(value).getTime()) ? new Date(value).toLocaleString('zh-CN', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }) : '时间未提供'
|
|
121
|
+
const destinationFor = row => ({ section: 'tasks', botId: row.botId, taskId: taskIdOf(row) })
|
|
122
|
+
|
|
123
|
+
export function WorkspaceInbox({ snapshot, onNavigate, openSession, preview = false }) {
|
|
124
|
+
const { progress, tasksAvailable } = useMemo(() => workspaceOverview(snapshot), [snapshot])
|
|
125
|
+
const [stage, setStage] = useState('all')
|
|
126
|
+
const rows = progress.attention.filter(row => stage === 'all' || row.stage === stage)
|
|
127
|
+
const visible = preview ? rows.slice(0, 4) : rows
|
|
128
|
+
return <section className={`bp-inbox${preview ? ' bp-inbox-preview' : ''}`} aria-label="任务待办">
|
|
129
|
+
<div className="bp-section-heading"><div><p className="bp-section-kicker">NEEDS YOUR ATTENTION</p><h2>需要你处理 <span className="bp-count">{tasksAvailable ? progress.attention.length : '—'}</span></h2></div>{preview && progress.attention.length > 0 && <button className="bp-text-button" type="button" onClick={() => onNavigate({ section: 'inbox' })}>查看全部<UiIcon name="chevron" size={14} /></button>}</div>
|
|
130
|
+
{!tasksAvailable ? <div className="bp-empty-work"><UiIcon name="inbox" size={28} /><p>{snapshot.tasks?.reason ?? '任务状态暂不可用。'}</p>{snapshot.tasks?.nextAction && <small>{snapshot.tasks.nextAction}</small>}</div> : <>
|
|
131
|
+
{snapshot.tasks.truncated && <p className="bp-muted">待办来自已加载的 {progress.items.length} / {snapshot.tasks.total ?? '未知'} 条任务。</p>}
|
|
132
|
+
{!preview && progress.attention.length > 0 && <div className="bp-inbox-filters" aria-label="按待办类型筛选"><button type="button" aria-pressed={stage === 'all'} onClick={() => setStage('all')}>全部 {progress.attention.length}</button>{Object.entries(STAGES).filter(([key]) => progress.attention.some(row => row.stage === key)).map(([key, [label]]) => <button type="button" key={key} aria-pressed={stage === key} onClick={() => setStage(key)}>{label} {progress.attention.filter(row => row.stage === key).length}</button>)}</div>}
|
|
133
|
+
{!progress.attention.length ? <div className="bp-empty-work"><span className="bp-calm-mark"><UiIcon name="check" size={26} /></span><h3>暂时没有需要你介入的任务</h3><p>团队的任务进展会在这里汇集。</p><button type="button" onClick={() => onNavigate({ section: 'tasks' })}>查看团队任务<UiIcon name="arrow" size={14} /></button></div> : <div className="bp-inbox-rows">{visible.map(row => {
|
|
134
|
+
const task = progress.items.find(item => taskKey(item) === taskKey(row))
|
|
135
|
+
const bot = snapshot.bots?.find(item => item.id === row.botId)
|
|
136
|
+
const [label, icon] = STAGES[row.stage] ?? ['需要处理', 'inbox']
|
|
137
|
+
return <article key={taskKey(row)} className="bp-inbox-item" data-stage={row.stage}><span className="bp-inbox-icon"><UiIcon name={icon} size={18} /></span><div className="bp-inbox-copy"><span className="bp-state-label">{label}</span><h3><button type="button" className="bp-text-button" onClick={() => onNavigate(destinationFor(row))}>{task ? taskTitle(task) : row.title}</button></h3><p>{row.detail}</p><small>{bot?.name ?? row.botId ?? '归属未提供'}</small></div><div className="bp-inbox-actions"><button type="button" onClick={() => onNavigate(destinationFor(row))}>查看任务<UiIcon name="chevron" size={13} /></button>{row.stage === 'approve' && bot?.sessionId && openSession && <button type="button" onClick={() => openSession(bot.sessionId)}>打开审批会话</button>}</div></article>
|
|
138
|
+
})}{!visible.length && <p className="bp-muted">该类型暂无待办。</p>}</div>}
|
|
139
|
+
</>}
|
|
140
|
+
</section>
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function WorkspaceHome({ snapshot, onNavigate, openSession, disabled }) {
|
|
144
|
+
const overview = useMemo(() => workspaceOverview(snapshot), [snapshot])
|
|
145
|
+
const [goal, setGoal] = useState('')
|
|
146
|
+
const { progress, bots, machines, recent, tasksAvailable } = overview
|
|
147
|
+
const canCompose = snapshot.availableActions?.includes('botRoutingInspect')
|
|
148
|
+
const main = bots.find(bot => bot.main)
|
|
149
|
+
const submit = event => { event.preventDefault(); if (!goal.trim() || disabled) return; onNavigate({ section: 'tasks', compose: true, draft: goal.trim() }); setGoal('') }
|
|
150
|
+
return <div className="bp-home">
|
|
151
|
+
<section className="bp-home-intro"><div><p className="bp-section-kicker">YOUR TEAM, IN MOTION</p><h1>下一件事,<br /><span>和团队一起完成。</span></h1><p>{bots.length ? `${bots.length} 位 Bot 伙伴,与目标、资料和工具在一个工作空间里。` : '从第一位 Bot 开始,组建适合你的工作团队。'}</p></div><div className="bp-home-orbit" aria-hidden="true"><span><UiIcon name="bot" size={35} /></span><i className="bp-orbit-node bp-orbit-one"><UiIcon name="file" size={20} /></i><i className="bp-orbit-node bp-orbit-two"><UiIcon name="computer" size={20} /></i><i className="bp-orbit-node bp-orbit-three"><UiIcon name="check" size={20} /></i></div></section>
|
|
152
|
+
<div className="bp-home-stats" aria-label="已加载任务概览">{[['active', '进行中的任务', 'activity'], ['attention', '需要你处理', 'inbox'], ['finished', '已结束的任务', 'check']].map(([filter, label, icon]) => <button key={filter} type="button" onClick={() => onNavigate({ section: filter === 'attention' ? 'inbox' : 'tasks', filter })}><span className="bp-stat-icon"><UiIcon name={icon} size={18} /></span><span><strong>{tasksAvailable ? progress.counts[filter] : '—'}</strong><small>{label}</small></span><UiIcon name="arrow" size={15} /></button>)}<button type="button" onClick={() => onNavigate({ section: 'machines' })}><span className="bp-stat-icon"><UiIcon name="computer" size={18} /></span><span><strong>{snapshot.machines?.status === 'available' ? overview.onlineMachines : '—'}<em> / {snapshot.machines?.status === 'available' ? machines.length : '—'}</em></strong><small>在线电脑</small></span><UiIcon name="arrow" size={15} /></button></div>
|
|
153
|
+
{overview.tasksTruncated && <p className="bp-loaded-note">任务统计仅包含已加载的 {progress.items.length} / {snapshot.tasks.total ?? '未知'} 条记录。</p>}
|
|
154
|
+
<div className="bp-home-main"><div className="bp-home-primary"><section className="bp-goal-card"><div className="bp-section-heading"><div><p className="bp-section-kicker">START SOMETHING</p><h2>你想完成什么?</h2></div><span className="bp-goal-symbol"><UiIcon name="spark" size={21} /></span></div>
|
|
155
|
+
{canCompose ? <form onSubmit={submit}><label className="bp-sr-only" htmlFor="bp-workspace-goal">任务目标</label><textarea id="bp-workspace-goal" value={goal} onChange={event => setGoal(event.target.value)} maxLength={20_000} rows={3} placeholder="描述你的目标,例如:检查这个项目,整理需要改进的地方…" /><div className="bp-goal-footer"><span><UiIcon name="lock" size={13} />先预览方案,再确认执行</span><button className="bp-button-primary" type="submit" disabled={disabled || !goal.trim()}>准备任务<UiIcon name="arrow" size={15} /></button></div></form> : <div className="bp-start-chat"><p>把目标告诉团队协调 Bot,或者在任务页查看已有工作。</p>{main?.sessionId && openSession ? <button className="bp-button-primary" type="button" onClick={() => openSession(main.sessionId)}>和 {main.name} 聊聊<UiIcon name="arrow" size={15} /></button> : <button type="button" onClick={() => onNavigate({ section: 'bindings' })}>查看团队<UiIcon name="arrow" size={15} /></button>}</div>}
|
|
156
|
+
</section><WorkspaceInbox snapshot={snapshot} onNavigate={onNavigate} openSession={openSession} preview /></div>
|
|
157
|
+
<aside className="bp-home-secondary"><section className="bp-recent"><div className="bp-section-heading"><div><p className="bp-section-kicker">RECENT WORK</p><h2>最近的工作</h2></div><button className="bp-text-button" type="button" onClick={() => onNavigate({ section: 'tasks' })} aria-label="查看全部任务"><UiIcon name="arrow" size={16} /></button></div>
|
|
158
|
+
{!tasksAvailable ? <p className="bp-muted">任务记录暂不可用。</p> : recent.length ? <ol className="bp-recent-list">{recent.map(task => <li key={taskKey(task)}><span className="bp-recent-dot" data-state={progress.category(task)} aria-hidden="true" /><button type="button" className="bp-text-button" onClick={() => onNavigate(destinationFor(task))}><strong>{taskTitle(task)}</strong><small>{snapshot.bots?.find(bot => bot.id === task.botId)?.name ?? task.botId} · {TASK_STATES[task.state] ?? task.state}</small><time>{when(task.updatedAt ?? task.createdAt)}</time></button></li>)}</ol> : <div className="bp-empty-work"><UiIcon name="tasks" size={25} /><p>新的任务会出现在这里。</p></div>}
|
|
159
|
+
</section><section className="bp-resource-links"><p className="bp-section-kicker">MAKE IT YOURS</p>{[['library', 'folder', '准备好资料', '把背景文件交给你的 Bot'], ['routine', 'repeat', '少做一次重复工作', '保存演示过的操作步骤']].map(([section, icon, title, detail]) => <button type="button" key={section} onClick={() => onNavigate({ section })}><UiIcon name={icon} size={19} /><span><strong>{title}</strong><small>{detail}</small></span><UiIcon name="chevron" size={14} /></button>)}</section></aside></div>
|
|
160
|
+
<section className="bp-home-team"><div className="bp-section-heading"><div><p className="bp-section-kicker">PEOPLE TO WORK WITH</p><h2>你的 Bot 团队</h2></div><button type="button" className="bp-text-button" onClick={() => onNavigate({ section: 'bindings' })}>管理团队<UiIcon name="chevron" size={14} /></button></div>
|
|
161
|
+
{bots.length ? <div className="bp-home-team-grid">{bots.slice(0, 8).map(bot => <button type="button" className="bp-home-person" key={bot.id} onClick={() => onNavigate({ section: 'bindings', botId: bot.id })}><span className="bp-team-avatar"><UiIcon name={bot.main ? 'spark' : 'bot'} size={24} /></span><span className="bp-home-person-copy"><strong>{bot.name}{bot.main && <span className="bp-main-label">协调</span>}</strong><small>{bot.role || '尚未填写职责'}</small><span className="bp-person-state" data-state={bot.state}>{bot.state === 'attention' ? `${bot.work.attention} 项待处理` : bot.state === 'active' ? `${bot.work.active} 项进行中` : '暂无进行中任务'}</span></span><UiIcon name="chevron" size={14} /></button>)}</div> : <p className="bp-muted">在侧栏新建 Bot 后,可在这里管理团队与工作配置。</p>}
|
|
162
|
+
{bots.length > 8 && <button className="bp-text-button" type="button" onClick={() => onNavigate({ section: 'bindings' })}>查看全部 {bots.length} 位伙伴</button>}
|
|
163
|
+
</section>
|
|
164
|
+
</div>
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function TeamDirectory({ snapshot, selected, onSelect }) {
|
|
168
|
+
const [query, setQuery] = useState('')
|
|
169
|
+
const { bots } = useMemo(() => workspaceOverview(snapshot), [snapshot])
|
|
170
|
+
const terms = query.trim().toLocaleLowerCase().split(/\s+/u).filter(Boolean)
|
|
171
|
+
const rows = bots.filter(bot => terms.every(term => `${bot.name} ${bot.role ?? ''} ${modelName(bot.model)}`.toLocaleLowerCase().includes(term)))
|
|
172
|
+
return <section className="bp-team-directory" aria-label="Bot 列表"><label className="bp-team-search"><UiIcon name="search" size={16} /><input aria-label="搜索团队成员" value={query} onChange={event => setQuery(event.target.value)} placeholder="搜索伙伴、职责、模型" type="search" /></label><div className="bp-team-directory-count">{rows.length} 位伙伴</div><div className="bp-team-directory-list">{rows.map(bot => <button type="button" key={bot.id} className="bp-team-member" aria-current={selected === bot.id ? 'true' : undefined} onClick={() => onSelect(bot.id)}><span className="bp-team-avatar"><UiIcon name={bot.main ? 'spark' : 'bot'} size={22} /></span><span><strong>{bot.name}{bot.main && <span className="bp-main-label">协调</span>}</strong><small>{bot.role || '尚未填写职责'}</small><span className="bp-team-model">{modelName(bot.model)}</span><span className="bp-person-state" data-state={bot.state}>{bot.state === 'attention' ? `${bot.work.attention} 项待处理` : bot.state === 'active' ? `${bot.work.active} 项进行中` : '暂无进行中任务'}</span></span></button>)}</div>{!rows.length && <p className="bp-muted">没有匹配的团队成员。</p>}</section>
|
|
173
|
+
}
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
html body[data-bot-product-ui] {
|
|
2
|
+
--bp-bg: #f7f8f5;
|
|
3
|
+
--bp-sidebar: #eef1ec;
|
|
4
|
+
--bp-surface: #ffffff;
|
|
5
|
+
--bp-subtle: #f1f4ef;
|
|
6
|
+
--bp-hover: #e7ece5;
|
|
7
|
+
--bp-border: #dfe5dc;
|
|
8
|
+
--bp-ink: #24332a;
|
|
9
|
+
--bp-muted: #657269;
|
|
10
|
+
--bp-quiet: #8b978e;
|
|
11
|
+
--bp-solid: #285c45;
|
|
12
|
+
--bp-on-solid: #ffffff;
|
|
13
|
+
--bp-focus: #33765a;
|
|
14
|
+
--bp-accent-soft: #e4eee5;
|
|
15
|
+
--bp-warning: #8d6226;
|
|
16
|
+
--bp-warning-bg: #faf1df;
|
|
17
|
+
--bp-danger: #a8483f;
|
|
18
|
+
--bp-danger-bg: #f8eae6;
|
|
19
|
+
--bp-mono: "Cascadia Code", "SFMono-Regular", Consolas, monospace;
|
|
20
|
+
--bt-user: #285c45;
|
|
21
|
+
--bt-user-ink: #ffffff;
|
|
22
|
+
}
|
|
23
|
+
html body[data-bot-product-ui][data-ds-dark-theme]:not([data-bp-appearance=light]),
|
|
24
|
+
html body[data-bot-product-ui][data-bp-appearance=dark] {
|
|
25
|
+
--bp-bg: #111915;
|
|
26
|
+
--bp-sidebar: #152019;
|
|
27
|
+
--bp-surface: #1b261f;
|
|
28
|
+
--bp-subtle: #202e25;
|
|
29
|
+
--bp-hover: #2a3b2f;
|
|
30
|
+
--bp-border: #344339;
|
|
31
|
+
--bp-ink: #e5eee6;
|
|
32
|
+
--bp-muted: #a3b4a7;
|
|
33
|
+
--bp-quiet: #819588;
|
|
34
|
+
--bp-solid: #b4d4b8;
|
|
35
|
+
--bp-on-solid: #15251b;
|
|
36
|
+
--bp-focus: #a6d4ae;
|
|
37
|
+
--bp-accent-soft: #293e2e;
|
|
38
|
+
--bp-warning: #e1bd7e;
|
|
39
|
+
--bp-warning-bg: #392f20;
|
|
40
|
+
--bp-danger: #f2aaa0;
|
|
41
|
+
--bp-danger-bg: #3b2824;
|
|
42
|
+
--bt-user: #b4d4b8;
|
|
43
|
+
--bt-user-ink: #15251b;
|
|
44
|
+
}
|
|
45
|
+
html body[data-bot-product-ui][data-bp-appearance=light] {
|
|
46
|
+
--bp-bg: #f7f8f5; --bp-sidebar: #eef1ec; --bp-surface: #fff;
|
|
47
|
+
--bp-subtle: #f1f4ef; --bp-hover: #e7ece5; --bp-border: #dfe5dc;
|
|
48
|
+
--bp-ink: #24332a; --bp-muted: #657269; --bp-quiet: #8b978e;
|
|
49
|
+
--bp-solid: #285c45; --bp-on-solid: #fff; --bp-focus: #33765a;
|
|
50
|
+
--bp-accent-soft: #e4eee5; --bp-warning: #8d6226; --bp-warning-bg: #faf1df;
|
|
51
|
+
--bp-danger: #a8483f; --bp-danger-bg: #f8eae6;
|
|
52
|
+
--bt-user: #285c45; --bt-user-ink: #fff;
|
|
53
|
+
}
|
|
54
|
+
html body[data-bot-product-ui][data-bp-appearance] {
|
|
55
|
+
--bt-main: var(--bp-bg); --bt-sidebar: var(--bp-sidebar); --bt-card: var(--bp-surface);
|
|
56
|
+
--bt-bubble: var(--bp-surface); --bt-ink: var(--bp-ink); --bt-ink-2: var(--bp-muted); --bt-ink-3: var(--bp-muted);
|
|
57
|
+
--bt-line: var(--bp-border); --bt-line-2: var(--bp-border); --bt-hover: var(--bp-hover); --bt-active: var(--bp-accent-soft);
|
|
58
|
+
--bt-accent: var(--bp-solid); --bt-accent-ink: var(--bp-on-solid); --bt-tag-bg: var(--bp-subtle); --bt-tag-ink: var(--bp-muted);
|
|
59
|
+
}
|
|
60
|
+
.bp-workspace { display: flex; flex-direction: column; height: 100%; min-height: 0; min-width: 0; color: var(--bp-ink); background: var(--bp-bg); font: 13px/1.6 var(--bp-font, system-ui); }
|
|
61
|
+
.bp-workspace *, .bp-palette * { box-sizing: border-box; }
|
|
62
|
+
.bp-workspace button, .bp-workspace input, .bp-workspace textarea { font-family: inherit; }
|
|
63
|
+
.bp-workspace-bar { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-shrink: 0; height: 60px; padding: 0 30px; border-bottom: 1px solid var(--bp-border); background: var(--bp-surface); }
|
|
64
|
+
.bp-workspace-location, .bp-workspace-bar-actions { display: flex; align-items: center; gap: 15px; min-width: 0; }
|
|
65
|
+
.bp-workspace-bar button { display: inline-flex; align-items: center; gap: 9px; padding: 7px 10px; color: var(--bp-ink); background: none; border: 1px solid transparent; border-radius: 7px; cursor: pointer; }
|
|
66
|
+
.bp-workspace-bar button:hover { background: var(--bp-subtle); }
|
|
67
|
+
.bp-workspace-brand { flex-shrink: 0; font-size: 10px; font-weight: 650; letter-spacing: .12em; }
|
|
68
|
+
.bp-workspace-brand > svg { color: var(--bp-solid); }
|
|
69
|
+
.bp-workspace-divider { color: var(--bp-border); font-size: 20px; font-weight: 300; }
|
|
70
|
+
.bp-workspace-current { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--bp-muted); font-size: 12px; }
|
|
71
|
+
.bp-workspace-bar .bp-workspace-search { min-width: 260px; color: var(--bp-muted); background: var(--bp-bg); border-color: var(--bp-border); font-size: 11px; }
|
|
72
|
+
.bp-workspace-search kbd { margin-left: auto; font-size: 10px; color: var(--bp-muted); }
|
|
73
|
+
.bp-appearance { position: relative; flex-shrink: 0; }
|
|
74
|
+
.bp-appearance > summary { display: grid; place-items: center; width: 34px; height: 34px; cursor: pointer; list-style: none; border-radius: 7px; color: var(--bp-muted); }
|
|
75
|
+
.bp-appearance > summary::-webkit-details-marker { display: none; }
|
|
76
|
+
.bp-appearance > summary:hover { background: var(--bp-subtle); }
|
|
77
|
+
.bp-appearance-menu { position: absolute; top: 43px; right: 0; z-index: 50; width: min(265px, calc(100vw - 24px)); max-height: calc(100dvh - 80px); overflow: auto; padding: 20px; border: 1px solid var(--bp-border); border-radius: 12px; color: var(--bp-ink); background: var(--bp-surface); box-shadow: 0 12px 40px #1223181a; }
|
|
78
|
+
.bp-appearance-menu > strong { font-size: 13px; font-weight: 600; }
|
|
79
|
+
.bp-appearance-menu fieldset { border: 0; padding: 0; margin: 17px 0 0; }
|
|
80
|
+
.bp-appearance-menu legend { font-size: 11px; color: var(--bp-muted); padding: 0 0 7px; }
|
|
81
|
+
.bp-appearance-menu p { font-size: 11px; color: var(--bp-muted); }
|
|
82
|
+
.bp-workspace .bp-page { flex: 1; height: auto; min-height: 0; padding: 30px clamp(20px, 4vw, 58px); }
|
|
83
|
+
.bp-workspace .bp-page-inner { max-width: 1180px; }
|
|
84
|
+
.bp-workspace .bp-page-header { margin-bottom: 24px; padding-bottom: 24px; }
|
|
85
|
+
.bp-workspace .bp-page h1 { font-weight: 650; letter-spacing: -.04em; font-size: 27px; }
|
|
86
|
+
.bp-workspace .bp-page h2 { font-size: 15px; letter-spacing: -.015em; }
|
|
87
|
+
.bp-workspace .bp-page-description { color: var(--bp-muted); max-width: 680px; }
|
|
88
|
+
.bp-workspace .bp-card { padding: 24px; border-radius: 12px; box-shadow: none; }
|
|
89
|
+
.bp-workspace .bp-selected-resource { border-color: var(--bp-solid); }
|
|
90
|
+
.bp-workspace .bp-page button { font-weight: 500; }
|
|
91
|
+
.bp-workspace .bp-page .bp-text-button { padding: 0; background: none; border: 0; box-shadow: none; text-align: left; min-height: 0; color: inherit; }
|
|
92
|
+
.bp-workspace .bp-page .bp-text-button:hover { color: var(--bp-solid); background: none; text-decoration: none; }
|
|
93
|
+
.bp-workspace .bp-page .bp-text-button:focus-visible { outline-offset: 4px; }
|
|
94
|
+
.bp-workspace .bp-page .bp-home-header { margin-bottom: 22px; padding: 0; border: 0; align-items: center; }
|
|
95
|
+
.bp-live-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--bp-solid); }
|
|
96
|
+
.bp-page .bp-section-kicker { color: var(--bp-muted); font-size: 9px; line-height: 1.5; font-weight: 600; letter-spacing: .13em; margin: 0 0 7px; }
|
|
97
|
+
.bp-section-heading { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 20px; }
|
|
98
|
+
.bp-section-heading > div { min-width: 0; }
|
|
99
|
+
.bp-section-heading h2 { display: flex; align-items: center; gap: 9px; }
|
|
100
|
+
.bp-count { font-size: 11px; font-weight: 500; padding: 1px 6px; border: 1px solid var(--bp-border); border-radius: 5px; color: var(--bp-muted); }
|
|
101
|
+
.bp-home-intro { display: flex; justify-content: space-between; align-items: center; gap: 28px; padding: 2px 0 30px; }
|
|
102
|
+
.bp-home .bp-home-intro h1 { margin: 0 0 17px; font-size: clamp(28px, 3.2vw, 40px); line-height: 1.4; letter-spacing: -.045em; font-weight: 650; }
|
|
103
|
+
.bp-home-intro h1 > span { color: var(--bp-solid); }
|
|
104
|
+
.bp-home-intro > div > p:last-child { color: var(--bp-muted); font-size: 12px; margin: 0; }
|
|
105
|
+
.bp-home-orbit { position: relative; width: 190px; height: 135px; flex-shrink: 0; margin: 0 45px 0 10px; border: 1px solid var(--bp-border); border-radius: 50%; transform: rotate(-14deg); }
|
|
106
|
+
.bp-home-orbit > span { display: grid; place-items: center; position: absolute; inset: 24px 52px; border: 1px solid var(--bp-border); border-radius: 24px; background: var(--bp-accent-soft); color: var(--bp-solid); transform: rotate(14deg); }
|
|
107
|
+
.bp-orbit-node { position: absolute; display: grid; place-items: center; width: 40px; height: 40px; border: 1px solid var(--bp-border); border-radius: 12px; color: var(--bp-muted); background: var(--bp-surface); transform: rotate(14deg); }
|
|
108
|
+
.bp-orbit-one { top: 4px; left: -3px; }
|
|
109
|
+
.bp-orbit-two { bottom: 7px; right: -6px; }
|
|
110
|
+
.bp-orbit-three { top: -14px; right: 25px; color: var(--bp-solid); }
|
|
111
|
+
.bp-home-stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); border-top: 1px solid var(--bp-border); border-bottom: 1px solid var(--bp-border); margin-bottom: 30px; }
|
|
112
|
+
.bp-home-stats > button { justify-content: flex-start; gap: 13px; border: 0; border-radius: 0; background: none; padding: 21px 16px; min-width: 0; }
|
|
113
|
+
.bp-home-stats > button:first-child { padding-left: 0; }
|
|
114
|
+
.bp-home-stats > button:not(:first-child) { border-left: 1px solid var(--bp-border); }
|
|
115
|
+
.bp-home-stats > button:hover { background: var(--bp-subtle); border: 0; }
|
|
116
|
+
.bp-home-stats > button:hover:not(:first-child) { border-left: 1px solid var(--bp-border); }
|
|
117
|
+
.bp-home-stats > button > .bp-icon:last-child { margin-left: auto; color: var(--bp-muted); }
|
|
118
|
+
.bp-stat-icon { display: grid; place-items: center; width: 34px; height: 34px; border: 1px solid var(--bp-border); border-radius: 10px; color: var(--bp-muted); background: var(--bp-surface); }
|
|
119
|
+
.bp-home-stats > button > span { text-align: left; }
|
|
120
|
+
.bp-home-stats strong { display: block; font-size: 25px; line-height: 1.2; font-weight: 550; font-variant-numeric: tabular-nums; }
|
|
121
|
+
.bp-home-stats strong em { font-style: normal; color: var(--bp-muted); font-size: 13px; }
|
|
122
|
+
.bp-home-stats small { margin-top: 6px; font-size: 10px; }
|
|
123
|
+
.bp-loaded-note { margin-top: -21px; margin-bottom: 24px; font-size: 11px; color: var(--bp-muted); }
|
|
124
|
+
.bp-home-main { display: grid; grid-template-columns: minmax(0, 1.8fr) minmax(235px, 1fr); gap: 34px; }
|
|
125
|
+
.bp-home-primary, .bp-home-secondary { min-width: 0; }
|
|
126
|
+
.bp-goal-card { padding: 24px; border: 1px solid var(--bp-border); border-radius: 13px; background: var(--bp-surface); margin-bottom: 32px; }
|
|
127
|
+
.bp-goal-symbol { color: var(--bp-solid); }
|
|
128
|
+
.bp-goal-card .bp-section-heading { margin-bottom: 16px; }
|
|
129
|
+
.bp-goal-card textarea { display: block; width: 100%; min-height: 94px; max-height: 300px; resize: vertical; font-size: 13px; border: 0 !important; padding: 4px 0 !important; box-shadow: none !important; border-radius: 0 !important; background: transparent !important; line-height: 1.8; }
|
|
130
|
+
.bp-goal-card textarea:focus-visible { outline-offset: 3px; }
|
|
131
|
+
.bp-goal-footer { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding-top: 16px; border-top: 1px solid var(--bp-border); margin-top: 13px; }
|
|
132
|
+
.bp-goal-footer > span { display: flex; align-items: center; gap: 5px; font-size: 10px; color: var(--bp-muted); }
|
|
133
|
+
.bp-goal-footer button { flex-shrink: 0; }
|
|
134
|
+
.bp-start-chat > p { color: var(--bp-muted); margin: 10px 0 18px; }
|
|
135
|
+
.bp-home-secondary { border-left: 1px solid var(--bp-border); padding-left: 30px; }
|
|
136
|
+
.bp-recent { padding-top: 3px; }
|
|
137
|
+
.bp-recent-list { list-style: none; margin: 0; padding: 0; }
|
|
138
|
+
.bp-recent-list > li { display: flex; gap: 12px; position: relative; min-width: 0; padding-bottom: 24px; }
|
|
139
|
+
.bp-recent-list > li:not(:last-child)::after { content: ''; position: absolute; top: 13px; left: 3px; bottom: 0; width: 1px; background: var(--bp-border); }
|
|
140
|
+
.bp-recent-dot { width: 7px; height: 7px; border: 1px solid var(--bp-quiet); border-radius: 50%; flex-shrink: 0; margin-top: 6px; position: relative; z-index: 1; background: var(--bp-bg); }
|
|
141
|
+
.bp-recent-dot[data-state=active] { background: var(--bp-solid); border-color: var(--bp-solid); }
|
|
142
|
+
.bp-recent-dot[data-state=attention] { background: var(--bp-warning-bg); border-color: var(--bp-warning); }
|
|
143
|
+
.bp-recent-list .bp-text-button { display: block; width: 100%; overflow-wrap: anywhere; }
|
|
144
|
+
.bp-recent-list strong { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; font-size: 12px; font-weight: 500; line-height: 1.7; }
|
|
145
|
+
.bp-recent-list time { display: block; font-size: 10px; color: var(--bp-muted); margin-top: 5px; }
|
|
146
|
+
.bp-recent-list small { font-size: 10px; }
|
|
147
|
+
.bp-resource-links { border-top: 1px solid var(--bp-border); padding-top: 20px; margin-top: 4px; }
|
|
148
|
+
.bp-resource-links > button { display: flex; width: 100%; text-align: left; justify-content: flex-start; padding: 11px 0; border: 0; border-radius: 0; background: none; gap: 12px; }
|
|
149
|
+
.bp-resource-links > button > svg { color: var(--bp-muted); }
|
|
150
|
+
.bp-resource-links > button > svg:last-child { margin-left: auto; }
|
|
151
|
+
.bp-resource-links strong { font-size: 12px; font-weight: 500; }
|
|
152
|
+
.bp-resource-links small { font-size: 10px; }
|
|
153
|
+
.bp-inbox { min-width: 0; }
|
|
154
|
+
.bp-inbox-rows { border-top: 1px solid var(--bp-border); }
|
|
155
|
+
.bp-inbox-item { display: flex; align-items: flex-start; gap: 14px; padding: 21px 0; border-bottom: 1px solid var(--bp-border); }
|
|
156
|
+
.bp-inbox-icon { width: 32px; height: 32px; flex-shrink: 0; display: grid; place-items: center; border-radius: 9px; background: var(--bp-warning-bg); color: var(--bp-warning); margin-top: 2px; }
|
|
157
|
+
.bp-inbox-item[data-stage=approve] .bp-inbox-icon { color: var(--bp-solid); background: var(--bp-accent-soft); }
|
|
158
|
+
.bp-inbox-copy { flex: 1; min-width: 0; }
|
|
159
|
+
.bp-inbox-copy .bp-state-label { font-size: 10px; color: var(--bp-muted); }
|
|
160
|
+
.bp-inbox-copy h3 { font-size: 13px; margin: 4px 0 6px; }
|
|
161
|
+
.bp-inbox-copy h3 > button { font-weight: 550; line-height: 1.7; overflow-wrap: anywhere; }
|
|
162
|
+
.bp-inbox-copy > p { color: var(--bp-muted); font-size: 11px; line-height: 1.8; margin: 0; }
|
|
163
|
+
.bp-inbox-copy > small { font-size: 10px; margin-top: 8px; }
|
|
164
|
+
.bp-inbox-actions { display: flex; flex-direction: column; gap: 8px; margin-left: auto; flex-shrink: 0; padding-top: 5px; }
|
|
165
|
+
.bp-inbox-actions > button { min-height: 29px; font-size: 11px; padding: 5px 9px; }
|
|
166
|
+
.bp-inbox-preview .bp-inbox-item { gap: 11px; }
|
|
167
|
+
.bp-inbox-preview .bp-inbox-actions > button { font-size: 10px; }
|
|
168
|
+
.bp-inbox-filters { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 20px; }
|
|
169
|
+
.bp-inbox-filters button { font-size: 12px; }
|
|
170
|
+
.bp-inbox-filters button[aria-pressed=true] { color: var(--bp-solid); background: var(--bp-accent-soft); border-color: var(--bp-solid); }
|
|
171
|
+
.bp-empty-work { padding: 30px 16px; text-align: center; color: var(--bp-muted); }
|
|
172
|
+
.bp-empty-work > svg { margin-bottom: 8px; }
|
|
173
|
+
.bp-empty-work h3 { margin: 12px 0 6px; color: var(--bp-ink); }
|
|
174
|
+
.bp-empty-work p { font-size: 12px; margin: 8px 0; }
|
|
175
|
+
.bp-empty-work button { margin-top: 12px; }
|
|
176
|
+
.bp-calm-mark { display: inline-grid; place-items: center; width: 50px; height: 50px; border: 1px solid var(--bp-border); border-radius: 50%; color: var(--bp-solid); background: var(--bp-accent-soft); }
|
|
177
|
+
.bp-home-team { border-top: 1px solid var(--bp-border); padding-top: 28px; margin-top: 34px; }
|
|
178
|
+
.bp-home-team-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
|
|
179
|
+
.bp-home-team-grid > .bp-home-person { justify-content: flex-start; padding: 17px; gap: 13px; text-align: left; border: 1px solid var(--bp-border); border-radius: 10px; background: var(--bp-surface); min-width: 0; }
|
|
180
|
+
.bp-team-avatar { display: inline-grid; place-items: center; width: 42px; height: 42px; flex-shrink: 0; background: var(--bp-accent-soft); color: var(--bp-solid); border: 1px solid var(--bp-border); border-radius: 13px; }
|
|
181
|
+
.bp-home-person-copy { min-width: 0; }
|
|
182
|
+
.bp-home-person-copy > strong { display: flex; align-items: center; gap: 9px; font-size: 13px; font-weight: 550; }
|
|
183
|
+
.bp-home-person-copy > small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; }
|
|
184
|
+
.bp-home-person > .bp-icon:last-child { color: var(--bp-muted); margin-left: auto; }
|
|
185
|
+
.bp-main-label { display: inline-block; font-size: 9px; font-weight: 500; color: var(--bp-solid); background: var(--bp-accent-soft); border-radius: 4px; padding: 1px 5px; }
|
|
186
|
+
.bp-person-state { display: flex; align-items: center; gap: 5px; font-size: 10px; color: var(--bp-muted); margin-top: 8px; }
|
|
187
|
+
.bp-person-state::before { content: ''; width: 4px; height: 4px; border-radius: 50%; background: var(--bp-quiet); }
|
|
188
|
+
.bp-person-state[data-state=active]::before { background: var(--bp-solid); }
|
|
189
|
+
.bp-person-state[data-state=attention]::before { background: var(--bp-warning); }
|
|
190
|
+
.bp-workspace .bp-team-layout { grid-template-columns: minmax(210px, 270px) minmax(0, 1fr); gap: 24px; }
|
|
191
|
+
.bp-team-directory { min-width: 0; }
|
|
192
|
+
.bp-team-search { display: flex; align-items: center; gap: 9px; padding: 0 11px; border: 1px solid var(--bp-border); border-radius: 8px; color: var(--bp-muted); background: var(--bp-surface); }
|
|
193
|
+
.bp-team-search input { flex: 1; width: 100%; border: 0 !important; background: none !important; box-shadow: none !important; padding-left: 0 !important; font-size: 12px !important; }
|
|
194
|
+
.bp-team-directory-count { font-size: 10px; color: var(--bp-muted); margin: 14px 0 9px 4px; }
|
|
195
|
+
.bp-team-directory-list { display: flex; flex-direction: column; gap: 8px; }
|
|
196
|
+
.bp-team-directory .bp-team-member { display: flex; align-items: flex-start; justify-content: flex-start; text-align: left; width: 100%; padding: 15px 12px; gap: 11px; border: 1px solid transparent; background: none; border-radius: 10px; }
|
|
197
|
+
.bp-team-member[aria-current=true] { background: var(--bp-surface) !important; border-color: var(--bp-border) !important; }
|
|
198
|
+
.bp-team-member > span:last-child { min-width: 0; }
|
|
199
|
+
.bp-team-member strong { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; font-size: 13px; font-weight: 600; }
|
|
200
|
+
.bp-team-member small { font-size: 11px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
|
201
|
+
.bp-team-model { display: block; color: var(--bp-muted); font-size: 10px; font-family: var(--bp-mono); overflow-wrap: anywhere; margin-top: 8px; }
|
|
202
|
+
.bp-team-member .bp-team-avatar { width: 34px; height: 34px; border-radius: 10px; }
|
|
203
|
+
.bp-workspace .bp-task-overview { background: none; border: 0; padding: 0; }
|
|
204
|
+
.bp-workspace .bp-task-counts { gap: 0; border: 1px solid var(--bp-border); border-radius: 10px; background: var(--bp-surface); overflow: hidden; }
|
|
205
|
+
.bp-workspace .bp-task-counts button { border: 0; border-radius: 0; padding: 16px; }
|
|
206
|
+
.bp-workspace .bp-task-counts button + button { border-left: 1px solid var(--bp-border); }
|
|
207
|
+
.bp-workspace .bp-task-counts button[aria-pressed=true] { background: var(--bp-accent-soft); color: var(--bp-solid); }
|
|
208
|
+
.bp-segmented { display: flex; align-items: center; padding: 3px; border: 1px solid var(--bp-border); border-radius: 8px; background: var(--bp-subtle); gap: 2px; }
|
|
209
|
+
.bp-workspace .bp-segmented button { font-size: 11px; min-height: 27px; border: 1px solid transparent; background: none; padding: 4px 9px; border-radius: 5px; }
|
|
210
|
+
.bp-workspace .bp-segmented button[aria-pressed=true] { border-color: var(--bp-border); background: var(--bp-surface); color: var(--bp-ink); }
|
|
211
|
+
.bp-board { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(220px, 1fr); gap: 13px; overflow-x: auto; margin-top: 20px; padding-bottom: 12px; }
|
|
212
|
+
.bp-board-lane { min-width: 0; border-radius: 8px; background: var(--bp-subtle); padding: 11px; }
|
|
213
|
+
.bp-board-lane > h3 { display: flex; align-items: center; gap: 7px; margin: 0 0 14px; padding: 0 2px; font-size: 11px; font-weight: 550; }
|
|
214
|
+
.bp-board-lane > h3 > span { margin-left: auto; color: var(--bp-muted); font-size: 10px; }
|
|
215
|
+
.bp-board-lane[data-lane=attention] > h3 { color: var(--bp-warning); }
|
|
216
|
+
.bp-board-items { display: flex; flex-direction: column; gap: 10px; }
|
|
217
|
+
.bp-board-card { min-width: 0; border: 1px solid var(--bp-border); background: var(--bp-surface); border-radius: 8px; padding: 13px; }
|
|
218
|
+
.bp-board-state { display: block; font-size: 9px; color: var(--bp-muted); margin-bottom: 8px; }
|
|
219
|
+
.bp-board-card > button { font-size: 12px; font-weight: 550 !important; line-height: 1.8; overflow-wrap: anywhere; }
|
|
220
|
+
.bp-board-card > p { font-size: 10px; color: var(--bp-muted); margin: 10px 0 0; }
|
|
221
|
+
.bp-board-card > small { font-size: 10px; }
|
|
222
|
+
.bp-board-card > footer { border-top: 1px solid var(--bp-border); margin-top: 13px; padding-top: 9px; }
|
|
223
|
+
.bp-board-card time { font-size: 9px; color: var(--bp-muted); }
|
|
224
|
+
.bp-board-card .bp-actions { margin-top: 8px; }
|
|
225
|
+
.bp-board-card .bp-actions:empty { display: none; }
|
|
226
|
+
.bp-board-card .bp-actions button { font-size: 10px; min-height: 25px; padding: 3px 8px; }
|
|
227
|
+
.bp-board-empty { font-size: 11px; color: var(--bp-muted); padding: 20px 0; text-align: center; }
|
|
228
|
+
.bp-workspace .bp-task-records { padding: 21px; }
|
|
229
|
+
.bp-palette-backdrop { position: fixed; inset: 0; z-index: 10000; display: flex; align-items: flex-start; justify-content: center; padding: min(14vh, 120px) 20px 30px; background: #0c1a1459; backdrop-filter: blur(3px); font: 13px/1.6 var(--bp-font, system-ui); }
|
|
230
|
+
.bp-palette { width: min(620px, 100%); max-height: min(680px, 76vh); display: flex; flex-direction: column; overflow: hidden; color: var(--bp-ink); background: var(--bp-surface); border: 1px solid var(--bp-border); border-radius: 14px; box-shadow: 0 24px 90px #07150f40; }
|
|
231
|
+
.bp-palette button { font: inherit; color: inherit; cursor: pointer; }
|
|
232
|
+
.bp-palette-input { display: flex; align-items: center; gap: 13px; border-bottom: 1px solid var(--bp-border); padding: 17px 18px; color: var(--bp-muted); }
|
|
233
|
+
.bp-palette-input > input { flex: 1; min-width: 0; border: 0; background: none; font: 14px var(--bp-font, system-ui); color: var(--bp-ink); outline: none; }
|
|
234
|
+
.bp-palette-input > input::placeholder { color: var(--bp-muted); }
|
|
235
|
+
.bp-palette-input > button { display: grid; place-items: center; padding: 5px; border: 0; border-radius: 5px; background: none; }
|
|
236
|
+
.bp-palette-input > button:hover { background: var(--bp-subtle); }
|
|
237
|
+
.bp-palette-caption { margin: 11px 18px 5px; font-size: 10px; color: var(--bp-muted); }
|
|
238
|
+
.bp-palette-results { overflow: auto; min-height: 0; padding: 8px; }
|
|
239
|
+
.bp-palette-results > button { display: flex; width: 100%; align-items: center; gap: 12px; text-align: left; padding: 12px; border: 1px solid transparent; border-radius: 8px; background: none; }
|
|
240
|
+
.bp-palette-results > button[aria-selected=true] { background: var(--bp-accent-soft); }
|
|
241
|
+
.bp-result-icon { display: grid; place-items: center; flex-shrink: 0; width: 32px; height: 32px; background: var(--bp-surface); border: 1px solid var(--bp-border); border-radius: 8px; color: var(--bp-muted); }
|
|
242
|
+
.bp-result-copy { min-width: 0; flex: 1; }
|
|
243
|
+
.bp-result-copy > strong { display: block; font-size: 12px; font-weight: 550; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
|
244
|
+
.bp-result-copy > small { display: block; color: var(--bp-muted); font-size: 10px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; margin-top: 3px; }
|
|
245
|
+
.bp-result-kind { font-size: 10px; color: var(--bp-muted); }
|
|
246
|
+
.bp-palette-footer { display: flex; flex-shrink: 0; justify-content: space-between; gap: 12px; color: var(--bp-muted); border-top: 1px solid var(--bp-border); padding: 11px 17px; font-size: 9px; }
|
|
247
|
+
.bp-palette-footer kbd { font: inherit; padding: 1px 4px; border: 1px solid var(--bp-border); border-radius: 3px; margin: 0 3px; }
|
|
248
|
+
.bp-search-empty { padding: 30px 12px; color: var(--bp-muted); font-size: 12px; text-align: center; }
|
|
249
|
+
.bp-sr-only { position: absolute; width: 1px; height: 1px; margin: -1px !important; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; padding: 0; border: 0; }
|
|
250
|
+
.bp-workspace :is(button, summary):focus-visible, .bp-palette button:focus-visible { outline: 2px solid var(--bp-focus); outline-offset: 3px; }
|
|
251
|
+
body[data-bot-product-ui] .bt-side { display: flex; flex-direction: column; }
|
|
252
|
+
body[data-bot-product-ui] .bt-side-top, body[data-bot-product-ui] .bt-rail-top { order: 0; flex-shrink: 0; }
|
|
253
|
+
body[data-bot-product-ui] .bp-nav { order: 1; flex-shrink: 0; max-height: 54%; overflow-y: auto; border-top: 0; border-bottom: 1px solid var(--bp-border); padding: 8px 10px 13px; margin: 0 4px 7px; display: flex; flex-direction: column; gap: 0; }
|
|
254
|
+
body[data-bot-product-ui] .bt-list { order: 2; min-height: 60px; flex: 1; }
|
|
255
|
+
body[data-bot-product-ui] .bt-leftcol-foot { order: 3; flex-shrink: 0; }
|
|
256
|
+
.bp-nav-group { display: flex; flex-direction: column; gap: 2px; }
|
|
257
|
+
.bp-nav .bp-nav-label { padding: 0 10px; margin: 14px 0 7px; font-size: 10px; font-weight: 500; letter-spacing: .02em; }
|
|
258
|
+
.bp-nav button { min-height: 33px; padding: 7px 10px; gap: 11px; font-size: 12px; border-radius: 7px; }
|
|
259
|
+
.bp-nav button[aria-current=page] { color: var(--bp-solid); background: var(--bp-accent-soft); font-weight: 600; }
|
|
260
|
+
.bp-nav .bp-nav-search { border: 1px solid var(--bp-border); background: var(--bp-surface); color: var(--bp-muted); margin: 2px 0 3px; }
|
|
261
|
+
body[data-bot-product-ui] .bt-side .bt-list { padding-top: 8px; }
|
|
262
|
+
body[data-bot-product-ui] .bt-row-preview { font-size: 11px; }
|
|
263
|
+
body[data-bot-product-ui] .bt-side-top .bt-brand { color: var(--bp-solid); }
|
|
264
|
+
body[data-bp-density=compact] .bp-workspace .bp-page { padding-top: 20px; }
|
|
265
|
+
body[data-bp-density=compact] .bp-workspace .bp-card { padding: 17px; margin-bottom: 14px; }
|
|
266
|
+
body[data-bp-density=compact] .bp-workspace .bp-page :is(td, th) { padding-top: 8px; padding-bottom: 8px; }
|
|
267
|
+
body[data-bp-density=compact] .bp-inbox-item { padding-top: 14px; padding-bottom: 14px; }
|
|
268
|
+
body[data-bp-density=compact] .bp-team-directory .bp-team-member { padding-top: 10px; padding-bottom: 10px; }
|
|
269
|
+
@container (max-width: 850px) {
|
|
270
|
+
.bp-home-main { grid-template-columns: minmax(0, 1fr) minmax(210px, .7fr); gap: 22px; }
|
|
271
|
+
.bp-home-secondary { padding-left: 20px; }
|
|
272
|
+
.bp-home-stats > button { gap: 8px; padding: 17px 11px; }
|
|
273
|
+
.bp-home-stats .bp-stat-icon { display: none; }
|
|
274
|
+
.bp-home-orbit { margin-right: 10px; width: 165px; height: 120px; }
|
|
275
|
+
.bp-home-orbit > span { inset: 20px 42px; }
|
|
276
|
+
.bp-inbox-preview .bp-inbox-actions { display: none; }
|
|
277
|
+
}
|
|
278
|
+
@container (max-width: 650px) {
|
|
279
|
+
.bp-home-main { grid-template-columns: 1fr; }
|
|
280
|
+
.bp-home-secondary { border-left: 0; border-top: 1px solid var(--bp-border); padding: 24px 0 0; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 25px; }
|
|
281
|
+
.bp-resource-links { margin-top: 0; border-top: 0; padding-top: 0; }
|
|
282
|
+
.bp-home-orbit { display: none; }
|
|
283
|
+
.bp-workspace .bp-team-layout { grid-template-columns: 1fr; }
|
|
284
|
+
.bp-team-directory-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); max-height: 340px; overflow-y: auto; }
|
|
285
|
+
.bp-inbox-item { flex-wrap: wrap; }
|
|
286
|
+
.bp-inbox-actions { flex-direction: row; width: 100%; margin-left: 46px; }
|
|
287
|
+
.bp-home-stats > button { padding: 16px 12px; }
|
|
288
|
+
.bp-home-stats > button > .bp-icon:last-child { display: none; }
|
|
289
|
+
}
|
|
290
|
+
@container (max-width: 440px) {
|
|
291
|
+
.bp-home-team-grid, .bp-home-secondary, .bp-team-directory-list { grid-template-columns: 1fr; }
|
|
292
|
+
.bp-home-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
293
|
+
.bp-home-stats > button:first-child { padding-left: 12px; }
|
|
294
|
+
.bp-home-stats > button:nth-child(3) { border-left: 0 !important; border-top: 1px solid var(--bp-border); }
|
|
295
|
+
.bp-home-stats > button:nth-child(4) { border-top: 1px solid var(--bp-border); }
|
|
296
|
+
.bp-goal-card { padding: 18px; }
|
|
297
|
+
.bp-goal-footer > span { max-width: 110px; font-size: 9px; }
|
|
298
|
+
.bp-home-intro { padding-bottom: 22px; }
|
|
299
|
+
}
|
|
300
|
+
@container workspace-navigation (max-width: 130px) {
|
|
301
|
+
.bp-nav-group { gap: 1px; }
|
|
302
|
+
.bp-nav .bp-nav-label { display: none; }
|
|
303
|
+
.bp-nav-group + .bp-nav-group { border-top: 1px solid var(--bp-border); padding-top: 6px; margin-top: 6px; }
|
|
304
|
+
}
|
|
305
|
+
@media (max-width: 1000px) { .bp-workspace-search > span, .bp-workspace-search kbd { display: none; } .bp-workspace-bar .bp-workspace-search { min-width: 0; background: none; border-color: transparent; } }
|
|
306
|
+
@media (max-width: 600px) {
|
|
307
|
+
.bp-workspace-bar { padding: 0 13px; height: 49px; gap: 8px; }
|
|
308
|
+
.bp-workspace-location, .bp-workspace-bar-actions { gap: 7px; }
|
|
309
|
+
.bp-workspace-brand > span { display: none; }
|
|
310
|
+
.bp-workspace .bp-page { padding: 20px 17px; }
|
|
311
|
+
.bp-palette-backdrop { padding: 18px 10px; }
|
|
312
|
+
.bp-palette { max-height: calc(100dvh - 40px); }
|
|
313
|
+
.bp-palette-footer > span:first-child { display: none; }
|
|
314
|
+
.bp-appearance-menu { right: -4px; }
|
|
315
|
+
}
|
|
316
|
+
@media (pointer: coarse) {
|
|
317
|
+
.bp-workspace button, .bp-workspace .bp-page button, .bp-nav button { min-height: 40px; }
|
|
318
|
+
.bp-workspace .bp-page .bp-text-button { min-height: 28px; }
|
|
319
|
+
.bp-appearance > summary { width: 40px; height: 40px; }
|
|
320
|
+
.bp-workspace :is(input, textarea), .bp-palette-input > input { font-size: 16px !important; }
|
|
321
|
+
}
|
|
322
|
+
@media (prefers-reduced-motion: reduce) { .bp-workspace *, .bp-palette * { transition: none !important; animation: none !important; scroll-behavior: auto !important; } }
|
|
323
|
+
.bp-pairing-identity { display: grid; gap: 8px; min-width: 0; padding: 14px; border: 1px solid var(--bp-border); border-radius: 12px; background: var(--bp-subtle); }
|
|
324
|
+
.bp-pairing-identity code { display: block; white-space: normal; overflow-wrap: anywhere; font-size: 12px; }
|
|
325
|
+
.bp-pairing-identity p { margin: 0; }
|
|
326
|
+
.bp-secure-pairing > summary { display: flex; align-items: center; gap: 8px; cursor: pointer; }
|
|
327
|
+
.bp-pairing-file { position: absolute; width: 1px !important; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
|
|
328
|
+
.bp-pairing-camera-overlay { position: fixed; inset: 0; z-index: 10002; display: grid; place-items: center; padding: 16px; background: #101e18b3; }
|
|
329
|
+
.bp-pairing-camera { width: min(540px,100%); padding: 18px; border: 1px solid var(--bp-border); border-radius: 16px; background: var(--bp-surface); color: var(--bp-ink); }
|
|
330
|
+
.bp-pairing-camera header { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 12px; }
|
|
331
|
+
.bp-pairing-camera video { display: block; width: 100%; aspect-ratio: 4/3; background: #0d1411; border-radius: 12px; object-fit: cover; }
|
|
332
|
+
body[data-bot-product-ui] .bp-task-timeline li[data-focused-attempt] { background:var(--bp-hover);border-radius:8px; }
|