@genesislcap/ai-assistant 15.19.0 → 15.19.1
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/package.json +17 -18
- package/api-extractor.json +0 -11
- package/dist/dts/components/chat-driver/chat-driver.compact.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.compact.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.invocation-scope.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.invocation-scope.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.thinking-policy.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.thinking-policy.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.trace-capture.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.trace-capture.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.turn-usage.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.turn-usage.test.d.ts.map +0 -1
- package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.test.d.ts +0 -2
- package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.test.d.ts.map +0 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.budget.test.d.ts +0 -2
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.budget.test.d.ts.map +0 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts +0 -2
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts.map +0 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.pin.test.d.ts +0 -2
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.pin.test.d.ts.map +0 -1
- package/dist/dts/components/settings-modal/settings-modal.styles.test.d.ts +0 -2
- package/dist/dts/components/settings-modal/settings-modal.styles.test.d.ts.map +0 -1
- package/dist/dts/components/settings-modal/settings-modal.template.test.d.ts +0 -2
- package/dist/dts/components/settings-modal/settings-modal.template.test.d.ts.map +0 -1
- package/dist/dts/config/define-stateful-agent.test.d.ts +0 -2
- package/dist/dts/config/define-stateful-agent.test.d.ts.map +0 -1
- package/dist/dts/config/validate-providers.test.d.ts +0 -2
- package/dist/dts/config/validate-providers.test.d.ts.map +0 -1
- package/dist/dts/main/blocked-state.test.d.ts +0 -2
- package/dist/dts/main/blocked-state.test.d.ts.map +0 -1
- package/dist/dts/main/budget-meter.test.d.ts +0 -2
- package/dist/dts/main/budget-meter.test.d.ts.map +0 -1
- package/dist/dts/main/cost-session-banking.test.d.ts +0 -2
- package/dist/dts/main/cost-session-banking.test.d.ts.map +0 -1
- package/dist/dts/main/file-attachments.test.d.ts +0 -2
- package/dist/dts/main/file-attachments.test.d.ts.map +0 -1
- package/dist/dts/main/interaction-cost.test.d.ts +0 -2
- package/dist/dts/main/interaction-cost.test.d.ts.map +0 -1
- package/dist/dts/main/main.styles.test.d.ts +0 -2
- package/dist/dts/main/main.styles.test.d.ts.map +0 -1
- package/dist/dts/main/persistence-broken-sources.test.d.ts +0 -2
- package/dist/dts/main/persistence-broken-sources.test.d.ts.map +0 -1
- package/dist/dts/main/popout-interaction-gate.test.d.ts +0 -2
- package/dist/dts/main/popout-interaction-gate.test.d.ts.map +0 -1
- package/dist/dts/state/ai-assistant-slice.test.d.ts +0 -2
- package/dist/dts/state/ai-assistant-slice.test.d.ts.map +0 -1
- package/dist/dts/state/debug-event-log.test.d.ts +0 -2
- package/dist/dts/state/debug-event-log.test.d.ts.map +0 -1
- package/dist/dts/state/driver-registry.test.d.ts +0 -2
- package/dist/dts/state/driver-registry.test.d.ts.map +0 -1
- package/dist/dts/state/interaction-context.test.d.ts +0 -2
- package/dist/dts/state/interaction-context.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/diagnostics-cursors.test.d.ts +0 -2
- package/dist/dts/state/persistence/diagnostics-cursors.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/diagnostics.test.d.ts +0 -2
- package/dist/dts/state/persistence/diagnostics.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-persistence-provider.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-persistence-provider.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-persistence.integration.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-persistence.integration.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-persister.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-persister.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-snapshot.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-snapshot.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/stateful-restore.e2e.test.d.ts +0 -2
- package/dist/dts/state/persistence/stateful-restore.e2e.test.d.ts.map +0 -1
- package/dist/dts/utils/animation-exclusivity.test.d.ts +0 -2
- package/dist/dts/utils/animation-exclusivity.test.d.ts.map +0 -1
- package/dist/dts/utils/collect-session-models.test.d.ts +0 -2
- package/dist/dts/utils/collect-session-models.test.d.ts.map +0 -1
- package/dist/dts/utils/condense-history.test.d.ts +0 -2
- package/dist/dts/utils/condense-history.test.d.ts.map +0 -1
- package/dist/dts/utils/cost-session-history.test.d.ts +0 -2
- package/dist/dts/utils/cost-session-history.test.d.ts.map +0 -1
- package/dist/dts/utils/derive-cost-session-title.test.d.ts +0 -2
- package/dist/dts/utils/derive-cost-session-title.test.d.ts.map +0 -1
- package/dist/dts/utils/flatten-sub-agent-messages.test.d.ts +0 -2
- package/dist/dts/utils/flatten-sub-agent-messages.test.d.ts.map +0 -1
- package/dist/dts/utils/history-transform.test.d.ts +0 -2
- package/dist/dts/utils/history-transform.test.d.ts.map +0 -1
- package/dist/dts/utils/message-partition.test.d.ts +0 -2
- package/dist/dts/utils/message-partition.test.d.ts.map +0 -1
- package/dist/dts/utils/resolve-cost-history-config.test.d.ts +0 -2
- package/dist/dts/utils/resolve-cost-history-config.test.d.ts.map +0 -1
- package/dist/dts/utils/resolve-preference-baseline.test.d.ts +0 -2
- package/dist/dts/utils/resolve-preference-baseline.test.d.ts.map +0 -1
- package/dist/dts/utils/strip-agent-handlers.test.d.ts +0 -2
- package/dist/dts/utils/strip-agent-handlers.test.d.ts.map +0 -1
- package/dist/dts/utils/sum-costs.test.d.ts +0 -2
- package/dist/dts/utils/sum-costs.test.d.ts.map +0 -1
- package/dist/dts/utils/sum-tokens.test.d.ts +0 -2
- package/dist/dts/utils/sum-tokens.test.d.ts.map +0 -1
- package/dist/dts/utils/sum-usage.test.d.ts +0 -2
- package/dist/dts/utils/sum-usage.test.d.ts.map +0 -1
- package/dist/dts/utils/usage-rows.test.d.ts +0 -2
- package/dist/dts/utils/usage-rows.test.d.ts.map +0 -1
- package/dist/esm/components/chat-driver/chat-driver.compact.test.js +0 -93
- package/dist/esm/components/chat-driver/chat-driver.invocation-scope.test.js +0 -238
- package/dist/esm/components/chat-driver/chat-driver.test.js +0 -2770
- package/dist/esm/components/chat-driver/chat-driver.thinking-policy.test.js +0 -137
- package/dist/esm/components/chat-driver/chat-driver.trace-capture.test.js +0 -200
- package/dist/esm/components/chat-driver/chat-driver.turn-usage.test.js +0 -268
- package/dist/esm/components/chat-interaction-wrapper/chat-interaction-wrapper.test.js +0 -104
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.budget.test.js +0 -312
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.cost.test.js +0 -76
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.pin.test.js +0 -61
- package/dist/esm/components/settings-modal/settings-modal.styles.test.js +0 -80
- package/dist/esm/components/settings-modal/settings-modal.template.test.js +0 -91
- package/dist/esm/config/define-stateful-agent.test.js +0 -53
- package/dist/esm/config/validate-providers.test.js +0 -100
- package/dist/esm/main/blocked-state.test.js +0 -1065
- package/dist/esm/main/budget-meter.test.js +0 -359
- package/dist/esm/main/cost-session-banking.test.js +0 -538
- package/dist/esm/main/file-attachments.test.js +0 -164
- package/dist/esm/main/interaction-cost.test.js +0 -107
- package/dist/esm/main/main.styles.test.js +0 -161
- package/dist/esm/main/persistence-broken-sources.test.js +0 -180
- package/dist/esm/main/popout-interaction-gate.test.js +0 -54
- package/dist/esm/state/ai-assistant-slice.test.js +0 -229
- package/dist/esm/state/debug-event-log.test.js +0 -117
- package/dist/esm/state/driver-registry.test.js +0 -55
- package/dist/esm/state/interaction-context.test.js +0 -78
- package/dist/esm/state/persistence/diagnostics-cursors.test.js +0 -30
- package/dist/esm/state/persistence/diagnostics.test.js +0 -280
- package/dist/esm/state/persistence/session-persistence-provider.test.js +0 -110
- package/dist/esm/state/persistence/session-persistence.integration.test.js +0 -113
- package/dist/esm/state/persistence/session-persister.test.js +0 -613
- package/dist/esm/state/persistence/session-snapshot.test.js +0 -256
- package/dist/esm/state/persistence/stateful-restore.e2e.test.js +0 -158
- package/dist/esm/utils/animation-exclusivity.test.js +0 -52
- package/dist/esm/utils/collect-session-models.test.js +0 -53
- package/dist/esm/utils/condense-history.test.js +0 -547
- package/dist/esm/utils/cost-session-history.test.js +0 -174
- package/dist/esm/utils/derive-cost-session-title.test.js +0 -37
- package/dist/esm/utils/flatten-sub-agent-messages.test.js +0 -139
- package/dist/esm/utils/history-transform.test.js +0 -158
- package/dist/esm/utils/message-partition.test.js +0 -90
- package/dist/esm/utils/resolve-cost-history-config.test.js +0 -32
- package/dist/esm/utils/resolve-preference-baseline.test.js +0 -69
- package/dist/esm/utils/strip-agent-handlers.test.js +0 -81
- package/dist/esm/utils/sum-costs.test.js +0 -114
- package/dist/esm/utils/sum-tokens.test.js +0 -51
- package/dist/esm/utils/sum-usage.test.js +0 -164
- package/dist/esm/utils/usage-rows.test.js +0 -189
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/license.txt +0 -46
- package/sandbox/tsconfig.json +0 -8
- package/src/channel/ai-activity-bus.ts +0 -209
- package/src/channel/ai-activity-channel.ts +0 -146
- package/src/chat-driver-node.ts +0 -159
- package/src/components/activity-halo/activity-halo.ts +0 -106
- package/src/components/agent-picker/agent-picker.constants.ts +0 -2
- package/src/components/agent-picker/agent-picker.styles.ts +0 -24
- package/src/components/agent-picker/agent-picker.template.ts +0 -54
- package/src/components/agent-picker/agent-picker.ts +0 -99
- package/src/components/agent-picker/index.ts +0 -1
- package/src/components/ai-driver/ai-driver.ts +0 -166
- package/src/components/ai-driver/index.ts +0 -1
- package/src/components/chat-bubble/chat-bubble.styles.ts +0 -194
- package/src/components/chat-bubble/chat-bubble.template.ts +0 -67
- package/src/components/chat-bubble/chat-bubble.ts +0 -436
- package/src/components/chat-bubble/index.ts +0 -1
- package/src/components/chat-driver/align-event-globals.ts +0 -23
- package/src/components/chat-driver/chat-driver.compact.test.ts +0 -131
- package/src/components/chat-driver/chat-driver.invocation-scope.test.ts +0 -285
- package/src/components/chat-driver/chat-driver.test.ts +0 -3679
- package/src/components/chat-driver/chat-driver.thinking-policy.test.ts +0 -185
- package/src/components/chat-driver/chat-driver.trace-capture.test.ts +0 -251
- package/src/components/chat-driver/chat-driver.ts +0 -3925
- package/src/components/chat-driver/chat-driver.turn-usage.test.ts +0 -362
- package/src/components/chat-driver/index.ts +0 -1
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.ts +0 -7
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.template.ts +0 -6
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.test.ts +0 -144
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts +0 -243
- package/src/components/chat-interaction-wrapper/index.ts +0 -3
- package/src/components/chat-markdown/chat-markdown.ts +0 -89
- package/src/components/chat-markdown/index.ts +0 -1
- package/src/components/flowing-waves-indicator.ts +0 -286
- package/src/components/halo-overlay.ts +0 -184
- package/src/components/orchestrating-driver/index.ts +0 -1
- package/src/components/orchestrating-driver/orchestrating-driver.budget.test.ts +0 -438
- package/src/components/orchestrating-driver/orchestrating-driver.cost.test.ts +0 -107
- package/src/components/orchestrating-driver/orchestrating-driver.pin.test.ts +0 -96
- package/src/components/orchestrating-driver/orchestrating-driver.ts +0 -813
- package/src/components/plasma-orb-indicator.ts +0 -281
- package/src/components/popout-manager/index.ts +0 -1
- package/src/components/popout-manager/popout-manager.ts +0 -212
- package/src/components/settings-modal/index.ts +0 -2
- package/src/components/settings-modal/settings-modal.styles.test.ts +0 -94
- package/src/components/settings-modal/settings-modal.styles.ts +0 -853
- package/src/components/settings-modal/settings-modal.template.test.ts +0 -124
- package/src/components/settings-modal/settings-modal.template.ts +0 -943
- package/src/components/waves-indicator.ts +0 -241
- package/src/config/config.ts +0 -608
- package/src/config/define-stateful-agent.test.ts +0 -64
- package/src/config/define-stateful-agent.ts +0 -642
- package/src/config/fallback-agents.ts +0 -29
- package/src/config/index.ts +0 -2
- package/src/config/validate-providers.test.ts +0 -148
- package/src/config/validate-providers.ts +0 -58
- package/src/index.ts +0 -29
- package/src/main/blocked-state.test.ts +0 -1444
- package/src/main/budget-meter.test.ts +0 -477
- package/src/main/cost-session-banking.test.ts +0 -679
- package/src/main/file-attachments.test.ts +0 -215
- package/src/main/index.ts +0 -3
- package/src/main/interaction-cost.test.ts +0 -140
- package/src/main/main.styles.test.ts +0 -216
- package/src/main/main.styles.ts +0 -995
- package/src/main/main.template.ts +0 -1119
- package/src/main/main.ts +0 -5432
- package/src/main/main.types.ts +0 -225
- package/src/main/persistence-broken-sources.test.ts +0 -219
- package/src/main/popout-interaction-gate.test.ts +0 -87
- package/src/provider/ai-provider-switcher.ts +0 -40
- package/src/provider/assistant-app-settings.ts +0 -84
- package/src/state/ai-assistant-slice.test.ts +0 -336
- package/src/state/ai-assistant-slice.ts +0 -604
- package/src/state/debug-event-log.test.ts +0 -154
- package/src/state/debug-event-log.ts +0 -358
- package/src/state/driver-registry.test.ts +0 -70
- package/src/state/driver-registry.ts +0 -79
- package/src/state/interaction-context.test.ts +0 -90
- package/src/state/interaction-context.ts +0 -101
- package/src/state/persistence/build-timeline-entries.ts +0 -66
- package/src/state/persistence/diagnostics-cursors.test.ts +0 -53
- package/src/state/persistence/diagnostics-cursors.ts +0 -80
- package/src/state/persistence/diagnostics.test.ts +0 -346
- package/src/state/persistence/diagnostics.ts +0 -220
- package/src/state/persistence/index.ts +0 -10
- package/src/state/persistence/persister-registry.ts +0 -55
- package/src/state/persistence/session-persistence-provider.test.ts +0 -136
- package/src/state/persistence/session-persistence-provider.ts +0 -226
- package/src/state/persistence/session-persistence.integration.test.ts +0 -141
- package/src/state/persistence/session-persister.test.ts +0 -787
- package/src/state/persistence/session-persister.ts +0 -917
- package/src/state/persistence/session-snapshot.test.ts +0 -352
- package/src/state/persistence/session-snapshot.ts +0 -344
- package/src/state/persistence/stateful-restore.e2e.test.ts +0 -229
- package/src/state/session-store.ts +0 -56
- package/src/styles/ai-colours.ts +0 -30
- package/src/styles/menu.ts +0 -187
- package/src/styles/settings-section.ts +0 -40
- package/src/suggestions/chat-suggestions.ts +0 -186
- package/src/tags/index.ts +0 -1
- package/src/types/ai-chat-widget.ts +0 -67
- package/src/types/interaction-context.ts +0 -82
- package/src/utils/animated-panel-toggle.ts +0 -62
- package/src/utils/animation-exclusivity.test.ts +0 -72
- package/src/utils/animation-exclusivity.ts +0 -40
- package/src/utils/banked-usage-baselines.ts +0 -90
- package/src/utils/collect-session-models.test.ts +0 -82
- package/src/utils/collect-session-models.ts +0 -65
- package/src/utils/condense-history.test.ts +0 -746
- package/src/utils/condense-history.ts +0 -448
- package/src/utils/cost-session-history.test.ts +0 -226
- package/src/utils/cost-session-history.ts +0 -218
- package/src/utils/derive-cost-session-title.test.ts +0 -63
- package/src/utils/derive-cost-session-title.ts +0 -76
- package/src/utils/flatten-sub-agent-messages.test.ts +0 -163
- package/src/utils/flatten-sub-agent-messages.ts +0 -88
- package/src/utils/format-usd.ts +0 -26
- package/src/utils/history-transform.test.ts +0 -228
- package/src/utils/history-transform.ts +0 -163
- package/src/utils/index.ts +0 -3
- package/src/utils/logger.ts +0 -3
- package/src/utils/message-partition.test.ts +0 -129
- package/src/utils/message-partition.ts +0 -115
- package/src/utils/resolve-cost-history-config.test.ts +0 -38
- package/src/utils/resolve-cost-history-config.ts +0 -38
- package/src/utils/resolve-preference-baseline.test.ts +0 -84
- package/src/utils/resolve-preference-baseline.ts +0 -80
- package/src/utils/strip-agent-handlers.test.ts +0 -99
- package/src/utils/strip-agent-handlers.ts +0 -53
- package/src/utils/sum-costs.test.ts +0 -136
- package/src/utils/sum-costs.ts +0 -18
- package/src/utils/sum-tokens.test.ts +0 -93
- package/src/utils/sum-tokens.ts +0 -68
- package/src/utils/sum-usage.test.ts +0 -191
- package/src/utils/sum-usage.ts +0 -208
- package/src/utils/tool-fold.ts +0 -181
- package/src/utils/usage-rows.test.ts +0 -237
- package/src/utils/usage-rows.ts +0 -187
- package/src/utils/with-timeout.ts +0 -24
- package/tsconfig.json +0 -9
package/src/main/main.styles.ts
DELETED
|
@@ -1,995 +0,0 @@
|
|
|
1
|
-
import { css } from '@genesislcap/web-core';
|
|
2
|
-
import { settingsModalStyles } from '../components/settings-modal/settings-modal.styles';
|
|
3
|
-
import {
|
|
4
|
-
AI_COLOUR_AMBER,
|
|
5
|
-
AI_COLOUR_CYAN,
|
|
6
|
-
AI_COLOUR_PINK,
|
|
7
|
-
AI_COLOUR_VIOLET,
|
|
8
|
-
} from '../styles/ai-colours';
|
|
9
|
-
import { menuItemStyles } from '../styles/menu';
|
|
10
|
-
|
|
11
|
-
const baseStyles = css`
|
|
12
|
-
:host {
|
|
13
|
-
/* Shared max width for the conversation column and the composer, so they stay
|
|
14
|
-
aligned. Override on the host to change both at once. NOTE: the @container
|
|
15
|
-
threshold that floats the composer can't read this (container queries can't
|
|
16
|
-
use custom properties), so if you override this below the 1500px default the
|
|
17
|
-
float still triggers at 1500px. */
|
|
18
|
-
--ai-conversation-max-width: 1500px;
|
|
19
|
-
|
|
20
|
-
/* INTERNAL — not a supported override point, despite sitting beside one.
|
|
21
|
-
Deliberately NOT --ai-*-namespaced and absent from docs/styling.md: the
|
|
22
|
-
documented banner surface is ::part(blocked-banner), and this token is
|
|
23
|
-
plumbing, not a knob. It is the banner's block margin AND the exact
|
|
24
|
-
amount the resize handle pulls itself up by when it follows the banner —
|
|
25
|
-
one name, on the host only because a sibling cannot read a custom
|
|
26
|
-
property declared on the banner (they inherit downward), so the
|
|
27
|
-
cancellation is structural: change the gap here and both rules move
|
|
28
|
-
together, instead of two magnitudes ~80 lines apart that only prose kept
|
|
29
|
-
in sync. A host that overrides it anyway gets a consistent gap, but that
|
|
30
|
-
is a side effect, not a promise. */
|
|
31
|
-
--blocked-banner-gap: calc(var(--design-unit) * 1px);
|
|
32
|
-
|
|
33
|
-
display: flex;
|
|
34
|
-
flex-direction: column;
|
|
35
|
-
height: 100%;
|
|
36
|
-
width: 100%;
|
|
37
|
-
font-family: var(--body-font);
|
|
38
|
-
color: var(--neutral-foreground-rest);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.chat-wrapper {
|
|
42
|
-
container-type: inline-size;
|
|
43
|
-
position: relative;
|
|
44
|
-
display: flex;
|
|
45
|
-
flex-direction: column;
|
|
46
|
-
height: 100%;
|
|
47
|
-
overflow: hidden;
|
|
48
|
-
background-color: var(--neutral-layer-1);
|
|
49
|
-
border: 1px solid var(--neutral-stroke-rest);
|
|
50
|
-
border-radius: var(--control-corner-radius) * 1px;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
.chat-header {
|
|
54
|
-
display: flex;
|
|
55
|
-
justify-content: space-between;
|
|
56
|
-
align-items: center;
|
|
57
|
-
padding: calc(var(--design-unit) * 2px) calc(var(--design-unit) * 3px);
|
|
58
|
-
border-bottom: 1px solid var(--neutral-stroke-rest);
|
|
59
|
-
background-color: var(--neutral-layer-2);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.chat-header.draggable {
|
|
63
|
-
cursor: move;
|
|
64
|
-
user-select: none;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.chat-title {
|
|
68
|
-
font-weight: bold;
|
|
69
|
-
font-size: 1.2em;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.header-actions {
|
|
73
|
-
display: flex;
|
|
74
|
-
align-items: center;
|
|
75
|
-
gap: 2px;
|
|
76
|
-
margin-left: auto;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
.settings-button,
|
|
80
|
-
.popout-button {
|
|
81
|
-
font-size: 1.2em;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
::slotted([slot='header-actions-extra']) {
|
|
85
|
-
font-size: 1.2em;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
.splash-wrapper {
|
|
89
|
-
position: absolute;
|
|
90
|
-
inset: 0;
|
|
91
|
-
z-index: 10;
|
|
92
|
-
overflow: hidden;
|
|
93
|
-
pointer-events: none;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
::slotted([slot='splash']) {
|
|
97
|
-
display: block;
|
|
98
|
-
width: 100%;
|
|
99
|
-
height: 100%;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
.messages {
|
|
103
|
-
flex: 1;
|
|
104
|
-
|
|
105
|
-
/* Allow the scroll area to shrink below its content height so a grown
|
|
106
|
-
composer (drag-to-resize) takes space from here instead of overflowing
|
|
107
|
-
the column and clipping the input row's buttons. */
|
|
108
|
-
min-height: 0;
|
|
109
|
-
overflow-y: auto;
|
|
110
|
-
padding: 10px;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/* Caps and centres the conversation column inside the (full-width) scroll
|
|
114
|
-
container, so the scrollbar stays at the panel edge while the messages sit
|
|
115
|
-
in a readable-width column. Exposed as part="messages-content" so a host
|
|
116
|
-
can widen it (::part(messages-content) { max-width: none }) or neutralise
|
|
117
|
-
the wrapper entirely (::part(messages-content) { display: contents }). */
|
|
118
|
-
.messages-content {
|
|
119
|
-
display: flex;
|
|
120
|
-
flex-direction: column;
|
|
121
|
-
gap: calc(var(--design-unit) * 2.5px);
|
|
122
|
-
width: 100%;
|
|
123
|
-
max-width: var(--ai-conversation-max-width);
|
|
124
|
-
margin-inline: auto;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
@keyframes slide-in-right {
|
|
128
|
-
from {
|
|
129
|
-
opacity: 0%;
|
|
130
|
-
transform: translateX(16px);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
to {
|
|
134
|
-
opacity: 100%;
|
|
135
|
-
transform: translateX(0);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
@keyframes slide-in-left {
|
|
140
|
-
from {
|
|
141
|
-
opacity: 0%;
|
|
142
|
-
transform: translateX(-16px);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
to {
|
|
146
|
-
opacity: 100%;
|
|
147
|
-
transform: translateX(0);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
@keyframes thinking-ring {
|
|
152
|
-
0% {
|
|
153
|
-
transform: scale(1);
|
|
154
|
-
opacity: 60%;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
100% {
|
|
158
|
-
transform: scale(1.8);
|
|
159
|
-
opacity: 0%;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
.agent-switch-indicator {
|
|
164
|
-
display: flex;
|
|
165
|
-
align-items: center;
|
|
166
|
-
gap: 8px;
|
|
167
|
-
margin: 8px 0;
|
|
168
|
-
color: var(--neutral-foreground-hint, var(--neutral-foreground-rest));
|
|
169
|
-
opacity: 60%;
|
|
170
|
-
font-size: 0.75em;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
.agent-switch-indicator::before,
|
|
174
|
-
.agent-switch-indicator::after {
|
|
175
|
-
content: '';
|
|
176
|
-
flex: 1;
|
|
177
|
-
height: 1px;
|
|
178
|
-
background: currentColor;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
.agent-switch-label {
|
|
182
|
-
white-space: nowrap;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
.message-row {
|
|
186
|
-
display: flex;
|
|
187
|
-
align-items: flex-start;
|
|
188
|
-
gap: 8px;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
.message-row.user {
|
|
192
|
-
flex-direction: row-reverse;
|
|
193
|
-
animation: slide-in-right 0.25s ease-out;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
.message-row.ai,
|
|
197
|
-
.message-row.ai-thinking,
|
|
198
|
-
.message-row.ai-function {
|
|
199
|
-
animation: slide-in-left 0.25s ease-out;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
.message-row.interaction {
|
|
203
|
-
flex-direction: column;
|
|
204
|
-
animation: slide-in-left 0.25s ease-out;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/* A 'bubble' interaction reads like a normal assistant message: avatar to the
|
|
208
|
-
left, bubble to the right — not the full-width column the other interaction
|
|
209
|
-
presentations use. */
|
|
210
|
-
.message-row.interaction.present-bubble {
|
|
211
|
-
flex-direction: row;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
.avatar {
|
|
215
|
-
position: relative;
|
|
216
|
-
width: 32px;
|
|
217
|
-
height: 32px;
|
|
218
|
-
border-radius: 50%;
|
|
219
|
-
background-color: var(--neutral-layer-3);
|
|
220
|
-
border: 1px solid var(--neutral-stroke-rest);
|
|
221
|
-
display: flex;
|
|
222
|
-
align-items: center;
|
|
223
|
-
justify-content: center;
|
|
224
|
-
flex-shrink: 0;
|
|
225
|
-
font-size: 1em;
|
|
226
|
-
overflow: hidden;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
.avatar.ai-thinking {
|
|
230
|
-
border-color: var(--ai-thinking-color, #7c3aed);
|
|
231
|
-
overflow: visible;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
.avatar.ai-thinking::before,
|
|
235
|
-
.avatar.ai-thinking::after {
|
|
236
|
-
content: '';
|
|
237
|
-
position: absolute;
|
|
238
|
-
inset: 0;
|
|
239
|
-
border-radius: 50%;
|
|
240
|
-
border: 2px solid var(--ai-thinking-color, #7c3aed);
|
|
241
|
-
animation: thinking-ring 1.5s ease-out infinite;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
.avatar.ai-thinking::after {
|
|
245
|
-
animation-delay: 0.75s;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
.avatar-img {
|
|
249
|
-
width: 100%;
|
|
250
|
-
height: 100%;
|
|
251
|
-
object-fit: cover;
|
|
252
|
-
border-radius: 50%;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
.avatar-icon {
|
|
256
|
-
display: flex;
|
|
257
|
-
align-items: center;
|
|
258
|
-
justify-content: center;
|
|
259
|
-
width: 100%;
|
|
260
|
-
height: 100%;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
.avatar-icon svg {
|
|
264
|
-
/* !important so a consumer-supplied SVG's own inline width/height/style
|
|
265
|
-
cannot break out of the avatar bounds. */
|
|
266
|
-
width: 84% !important;
|
|
267
|
-
height: 84% !important;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
.message {
|
|
271
|
-
padding: calc(var(--design-unit) * 2.5px) calc(var(--design-unit) * 3.5px);
|
|
272
|
-
max-width: 80%;
|
|
273
|
-
min-width: 70px;
|
|
274
|
-
font-family: var(--body-font);
|
|
275
|
-
font-size: 1.1em;
|
|
276
|
-
|
|
277
|
-
/* Long unbroken strings (URLs, file paths, tokens, base64) wrap instead of
|
|
278
|
-
overflowing the bubble. overflow-wrap: anywhere also lets the bubble shrink
|
|
279
|
-
below such a string's width in the flex row, preventing horizontal overflow. */
|
|
280
|
-
overflow-wrap: anywhere;
|
|
281
|
-
word-break: break-word;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
.message.user {
|
|
285
|
-
background: linear-gradient(
|
|
286
|
-
135deg,
|
|
287
|
-
var(--accent-fill-rest) 0%,
|
|
288
|
-
color-mix(in srgb, var(--accent-fill-rest) 70%, black) 100%
|
|
289
|
-
);
|
|
290
|
-
|
|
291
|
-
/* The on-accent foreground token that pairs with the --accent-fill-rest background
|
|
292
|
-
above. It must be the design system's real token name: color is inherited, so an
|
|
293
|
-
undefined custom property with no fallback is invalid at computed-value time and
|
|
294
|
-
silently leaves the text at the inherited neutral foreground — which reads as
|
|
295
|
-
white-ish (fine) on a dark app and near-black (unreadable) on a light one. */
|
|
296
|
-
color: var(--foreground-on-accent-rest);
|
|
297
|
-
|
|
298
|
-
/* Squared "tail" at top-right — the corner nearest the user avatar. */
|
|
299
|
-
border-radius: 18px 4px 18px 18px;
|
|
300
|
-
box-shadow: 0 2px 8px color-mix(in srgb, var(--accent-fill-rest) 35%, transparent);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
.message.ai {
|
|
304
|
-
background: linear-gradient(135deg, var(--neutral-layer-3) 0%, var(--neutral-layer-4) 100%);
|
|
305
|
-
color: var(--neutral-foreground-rest);
|
|
306
|
-
|
|
307
|
-
/* Squared "tail" at top-left — the corner nearest the assistant avatar. */
|
|
308
|
-
border-radius: 4px 18px 18px;
|
|
309
|
-
border: calc(var(--stroke-width) * 1px) solid var(--neutral-stroke-rest);
|
|
310
|
-
box-shadow: var(--ai-message-shadow, 0 2px 8px rgb(0 0 0 / 15%));
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
.message.ai-thinking {
|
|
314
|
-
background: linear-gradient(
|
|
315
|
-
135deg,
|
|
316
|
-
color-mix(in srgb, var(--ai-thinking-color, #7c3aed) 12%, transparent) 0%,
|
|
317
|
-
color-mix(in srgb, var(--ai-thinking-color, #7c3aed) 18%, transparent) 100%
|
|
318
|
-
);
|
|
319
|
-
color: var(--neutral-foreground-rest);
|
|
320
|
-
border-radius: 4px 18px 18px;
|
|
321
|
-
border-left: 2px solid var(--ai-thinking-color, #7c3aed);
|
|
322
|
-
font-style: italic;
|
|
323
|
-
font-size: 0.95em;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/* Narration shares the Thinking bubble but is the assistant's commentary (labelled "Working"),
|
|
327
|
-
not its inner monologue — keep it upright so it reads as action, distinct from italic reasoning. */
|
|
328
|
-
.message.ai-thinking.narration {
|
|
329
|
-
font-style: normal;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
.message.ai-function {
|
|
333
|
-
background: linear-gradient(135deg, rgb(15 32 39 / 90%) 0%, rgb(30 58 58 / 80%) 100%);
|
|
334
|
-
color: var(--ai-function-color, #86efac);
|
|
335
|
-
border-radius: 4px 18px 18px;
|
|
336
|
-
font-size: 1em;
|
|
337
|
-
border: 1px solid color-mix(in srgb, var(--ai-function-color, #86efac) 20%, transparent);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
/* 'label' (default) and 'bare' interactions render the widget chrome-free and
|
|
341
|
-
full-width — the widget owns its body. */
|
|
342
|
-
.message-row.interaction.present-label .message,
|
|
343
|
-
.message-row.interaction.present-bare .message {
|
|
344
|
-
background: none;
|
|
345
|
-
border: none;
|
|
346
|
-
padding: 0;
|
|
347
|
-
max-width: 100%;
|
|
348
|
-
width: 100%;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/* 'bubble' interactions reuse the standard assistant-message skin so the
|
|
352
|
-
widget sits inside a normal chat bubble. Padding, max-width and min-width
|
|
353
|
-
come from the base .message rule. */
|
|
354
|
-
.message-row.interaction.present-bubble .message {
|
|
355
|
-
background: linear-gradient(135deg, var(--neutral-layer-3) 0%, var(--neutral-layer-4) 100%);
|
|
356
|
-
color: var(--neutral-foreground-rest);
|
|
357
|
-
border-radius: 4px 18px 18px;
|
|
358
|
-
border: calc(var(--stroke-width) * 1px) solid var(--neutral-stroke-rest);
|
|
359
|
-
box-shadow: var(--ai-message-shadow, 0 2px 8px rgb(0 0 0 / 15%));
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
.sender {
|
|
363
|
-
font-weight: bold;
|
|
364
|
-
font-size: 0.9em;
|
|
365
|
-
margin-bottom: 4px;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
.payload {
|
|
369
|
-
font-family: monospace;
|
|
370
|
-
white-space: pre-wrap;
|
|
371
|
-
margin: 0;
|
|
372
|
-
font-size: 0.95em;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
.payload.unknown-tool {
|
|
376
|
-
color: var(--error-color, #f87171);
|
|
377
|
-
border-left: 2px solid color-mix(in srgb, var(--error-color, #f87171) 40%, transparent);
|
|
378
|
-
padding-left: 8px;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
.live-sub-agent-trace {
|
|
382
|
-
animation: slide-in-left 0.25s ease-out;
|
|
383
|
-
border-left: 2px solid var(--neutral-stroke-rest);
|
|
384
|
-
padding: 4px 8px;
|
|
385
|
-
margin: 4px 0;
|
|
386
|
-
opacity: 80%;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
.live-sub-agent-name {
|
|
390
|
-
font-family: monospace;
|
|
391
|
-
font-size: 0.8em;
|
|
392
|
-
opacity: 70%;
|
|
393
|
-
font-style: italic;
|
|
394
|
-
display: block;
|
|
395
|
-
margin-bottom: 2px;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
.sub-agent-trace {
|
|
399
|
-
margin-top: 6px;
|
|
400
|
-
border-left: 2px solid var(--neutral-stroke-rest);
|
|
401
|
-
padding-left: 8px;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
.sub-agent-trace-summary {
|
|
405
|
-
font-family: monospace;
|
|
406
|
-
font-size: 0.85em;
|
|
407
|
-
opacity: 70%;
|
|
408
|
-
cursor: pointer;
|
|
409
|
-
user-select: none;
|
|
410
|
-
padding: 2px 0;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
.sub-agent-trace-summary:hover {
|
|
414
|
-
opacity: 100%;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
.sub-agent-message {
|
|
418
|
-
font-family: monospace;
|
|
419
|
-
font-size: 0.85em;
|
|
420
|
-
margin-top: 4px;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
.sub-agent-assistant {
|
|
424
|
-
opacity: 85%;
|
|
425
|
-
white-space: pre-wrap;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
.sub-agent-tool-call {
|
|
429
|
-
opacity: 60%;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
.sub-agent-tool-name::before {
|
|
433
|
-
content: '⚙ ';
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
.sub-agent-tool-result {
|
|
437
|
-
opacity: 50%;
|
|
438
|
-
border-left: 1px solid var(--neutral-stroke-rest);
|
|
439
|
-
padding-left: 6px;
|
|
440
|
-
white-space: pre-wrap;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
/* The composer is one bordered box: textarea on top, controls on a bar beneath
|
|
444
|
-
it, both inside the same surface. It is position:relative so it is the
|
|
445
|
-
containing block for the two menus, which anchor to its top edge. */
|
|
446
|
-
.composer {
|
|
447
|
-
position: relative;
|
|
448
|
-
display: flex;
|
|
449
|
-
flex-direction: column;
|
|
450
|
-
|
|
451
|
-
/* Matched by the bar's own padding-top below, so the divider between the two
|
|
452
|
-
sits with equal air above and below it. */
|
|
453
|
-
gap: calc(var(--design-unit) * 1.5px);
|
|
454
|
-
padding: calc(var(--design-unit) * 1.5px);
|
|
455
|
-
|
|
456
|
-
/* Flush with the panel edges by default, so only the top edge is drawn — side
|
|
457
|
-
and bottom borders on a full-bleed strip are either invisible or noise, and
|
|
458
|
-
a radius on square-cut corners reads as a mistake. The transparent border
|
|
459
|
-
is still declared on all four sides so the box metrics are identical in
|
|
460
|
-
both modes and crossing the floating threshold cannot reflow the composer.
|
|
461
|
-
The container query below promotes it to a full, rounded card. */
|
|
462
|
-
border: 1px solid transparent;
|
|
463
|
-
border-top-color: var(--neutral-stroke-rest);
|
|
464
|
-
background-color: var(--neutral-layer-2);
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
.composer-bar {
|
|
468
|
-
display: flex;
|
|
469
|
-
align-items: center;
|
|
470
|
-
gap: calc(var(--design-unit) * 2px);
|
|
471
|
-
|
|
472
|
-
/* Pulled out to the composer's padding edges so the divider below spans the
|
|
473
|
-
full box rather than floating inset from it, with the same amount added
|
|
474
|
-
back as padding so nothing on the bar actually moves. The inline padding is
|
|
475
|
-
therefore the composer's own padding PLUS the 8px the textarea's control
|
|
476
|
-
insets its text by — which is what keeps the leading pill aligned with the
|
|
477
|
-
placeholder and gives Send the same inset on the right. The block-start
|
|
478
|
-
padding is the divider's breathing room and pairs with the composer's gap. */
|
|
479
|
-
margin-inline: calc(var(--design-unit) * -1.5px);
|
|
480
|
-
padding: calc(var(--design-unit) * 1.5px)
|
|
481
|
-
calc(var(--design-unit) * 1.5px + var(--design-unit) * 2px) 0;
|
|
482
|
-
|
|
483
|
-
/* Off by default, but always PRESENT: painted in the composer's own surface
|
|
484
|
-
colour so it is invisible while still occupying its 1px, which means an app
|
|
485
|
-
switching it on gets a line and not a one-pixel reflow of the whole bar.
|
|
486
|
-
Hosts that want it set --ai-composer-divider to a colour — see
|
|
487
|
-
docs/styling.md. */
|
|
488
|
-
border-top: 1px solid var(--ai-composer-divider, var(--neutral-layer-2));
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
.composer-bar-start,
|
|
492
|
-
.composer-bar-end {
|
|
493
|
-
display: flex;
|
|
494
|
-
align-items: center;
|
|
495
|
-
gap: calc(var(--design-unit) * 1.5px);
|
|
496
|
-
min-width: 0;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
.composer-bar-start {
|
|
500
|
-
flex: 1 1 auto;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
.composer-bar-end {
|
|
504
|
-
flex: 0 0 auto;
|
|
505
|
-
margin-inline-start: auto;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
/* Mirror the messages column: cap the composer (input row + its buttons, resize
|
|
509
|
-
handle, attachment chips, agent picker panel, suggestions) at the same max width
|
|
510
|
-
and centre it, so it does not span full width while the messages sit in a
|
|
511
|
-
narrower column. These are flex items in the column layout, so margin-inline:auto
|
|
512
|
-
would disable their default stretch — width:100% keeps them filling up to the
|
|
513
|
-
cap, and border-box keeps padding/border from overflowing when full-width.
|
|
514
|
-
Overridable via ::part(input-row) etc. */
|
|
515
|
-
.composer,
|
|
516
|
-
.composer-resize-handle,
|
|
517
|
-
.attachment-chips,
|
|
518
|
-
.blocked-banner,
|
|
519
|
-
chat-suggestions {
|
|
520
|
-
box-sizing: border-box;
|
|
521
|
-
width: 100%;
|
|
522
|
-
max-width: var(--ai-conversation-max-width);
|
|
523
|
-
margin-inline: auto;
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
/* When the assistant is wider than that cap the composer is genuinely constrained,
|
|
527
|
-
so lift the input row — and the panels that sit above it — into matching
|
|
528
|
-
floating, rounded, outlined cards with a gap to the bottom. Below the cap they
|
|
529
|
-
stay full-width and flush (the default border-top). The query resolves against
|
|
530
|
-
the assistant's own inline-size container (.chat-wrapper). The threshold is a
|
|
531
|
-
literal because a container query can't read a custom property — keep it equal
|
|
532
|
-
to the --ai-conversation-max-width default. */
|
|
533
|
-
@container (width > 1500px) {
|
|
534
|
-
.composer,
|
|
535
|
-
chat-suggestions {
|
|
536
|
-
border: 1px solid var(--neutral-stroke-rest);
|
|
537
|
-
border-radius: 12px;
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
/* The banner joins the same floating-card family, but keeps its own
|
|
541
|
-
warning-toned border — overriding it with the neutral stroke would erase
|
|
542
|
-
the one colour signal it carries. Only the radius needs to match. */
|
|
543
|
-
.blocked-banner.is-visible {
|
|
544
|
-
border-radius: 12px;
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
.composer {
|
|
548
|
-
margin-bottom: 12px;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
/* Genuinely floating now, so the whole ring is drawn and the focus tint
|
|
552
|
-
follows it round rather than lighting only the top edge. */
|
|
553
|
-
.composer:focus-within {
|
|
554
|
-
border-color: var(--focus-stroke-outer);
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
/* chat-suggestions paints its background on an inner element, so clip it to the
|
|
558
|
-
rounded corners — otherwise that square inner background bleeds past the radius
|
|
559
|
-
and the corners read as square with the border hidden behind them. The smaller
|
|
560
|
-
end margin keeps it a distinct card above the composer without a large void. */
|
|
561
|
-
chat-suggestions {
|
|
562
|
-
overflow: hidden;
|
|
563
|
-
margin-bottom: 8px;
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
/* Focus lives on the textarea inside, which is visually flush with the box —
|
|
568
|
-
so lift the ring to the box itself and let the inner control stay quiet.
|
|
569
|
-
Driven by :focus-within rather than a class: no state to keep in sync.
|
|
570
|
-
Declared here, below the container query, because that block also styles a
|
|
571
|
-
bare .composer and a lower-specificity rule may not follow a higher one. */
|
|
572
|
-
.composer:focus-within {
|
|
573
|
-
border-top-color: var(--focus-stroke-outer);
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
/* ── Composer control pills ───────────────────────────────────────────────
|
|
577
|
-
One shape for every icon control on the bar: a round, quiet button that
|
|
578
|
-
tints on hover. The design-system button paints its surface on :host and
|
|
579
|
-
pads an inner 'control' part, so the circle is set here and the padding
|
|
580
|
-
cleared there — otherwise the control's default 16px inline padding forces
|
|
581
|
-
the host wider than it is tall and the circle becomes a lozenge. */
|
|
582
|
-
.composer-pill {
|
|
583
|
-
--pill-size: calc(var(--design-unit) * 7px);
|
|
584
|
-
|
|
585
|
-
height: var(--pill-size);
|
|
586
|
-
min-width: var(--pill-size);
|
|
587
|
-
border-radius: 999px;
|
|
588
|
-
color: var(--neutral-foreground-hint);
|
|
589
|
-
background: var(--neutral-fill-stealth-rest);
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
.composer-pill:hover {
|
|
593
|
-
color: var(--neutral-foreground-rest);
|
|
594
|
-
background: var(--neutral-fill-stealth-hover);
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
.composer-pill[disabled] {
|
|
598
|
-
opacity: 45%;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
.composer-pill::part(control) {
|
|
602
|
-
min-width: 0;
|
|
603
|
-
padding: 0;
|
|
604
|
-
justify-content: center;
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
/* The agent pill is the one that carries a label, so it is the one that grows.
|
|
608
|
-
A pill-height radius rather than a circle, and room for the text. */
|
|
609
|
-
.composer-pill-labelled {
|
|
610
|
-
max-width: 45%;
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
.composer-pill-labelled::part(control) {
|
|
614
|
-
gap: calc(var(--design-unit) * 1px);
|
|
615
|
-
padding: 0 calc(var(--design-unit) * 2px) 0 calc(var(--design-unit) * 1px);
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
/* The glyph keeps the circular footprint the unlabelled pills have, so the
|
|
619
|
-
three read as one family with the agent one simply extended by its label. */
|
|
620
|
-
.pill-glyph {
|
|
621
|
-
display: inline-flex;
|
|
622
|
-
align-items: center;
|
|
623
|
-
justify-content: center;
|
|
624
|
-
flex: 0 0 auto;
|
|
625
|
-
width: calc(var(--design-unit) * 5px);
|
|
626
|
-
height: calc(var(--design-unit) * 5px);
|
|
627
|
-
border-radius: 50%;
|
|
628
|
-
font-size: 0.8em;
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
.pill-label {
|
|
632
|
-
overflow: hidden;
|
|
633
|
-
font-size: 0.75em;
|
|
634
|
-
font-weight: 600;
|
|
635
|
-
letter-spacing: 0.02em;
|
|
636
|
-
text-overflow: ellipsis;
|
|
637
|
-
white-space: nowrap;
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
/* Send keeps the design system's own accent button. The shell around it is
|
|
641
|
-
inert by default and exists only as a styling hook — see the note in
|
|
642
|
-
main.template.ts and ::part(send-shell) in docs/styling.md. */
|
|
643
|
-
.send-shell {
|
|
644
|
-
display: inline-flex;
|
|
645
|
-
border-radius: calc(var(--control-corner-radius) * 1px);
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
.send-button {
|
|
649
|
-
height: calc(var(--design-unit) * 7px);
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
/* The "stopping" state shows a spinner — rotate it (the icon set's glyph is
|
|
653
|
-
static). Transform-only, so it never affects layout/width. */
|
|
654
|
-
@keyframes ai-stop-spin {
|
|
655
|
-
to {
|
|
656
|
-
transform: rotate(360deg);
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
.stop-icon-spinning {
|
|
661
|
-
/* inline-block so the icon host is transformable — an inline element
|
|
662
|
-
ignores the transform, which is why the spinner appeared frozen. */
|
|
663
|
-
display: inline-block;
|
|
664
|
-
animation: ai-stop-spin 0.8s linear infinite;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
/* ── Composer menus ───────────────────────────────────────────────────────
|
|
668
|
-
The agent picker and the session menu are the same panel with different
|
|
669
|
-
contents. Absolutely positioned against .composer, so opening one neither
|
|
670
|
-
pushes the transcript up nor covers a half-typed message, and edge-aligned
|
|
671
|
-
to the button that opened it. */
|
|
672
|
-
.composer-menu {
|
|
673
|
-
position: absolute;
|
|
674
|
-
z-index: 2;
|
|
675
|
-
box-sizing: border-box;
|
|
676
|
-
min-width: calc(var(--design-unit) * 55px);
|
|
677
|
-
|
|
678
|
-
/* Never wider than the composer, so a long agent name cannot push the menu
|
|
679
|
-
past the panel edge at narrow widths. */
|
|
680
|
-
max-width: 100%;
|
|
681
|
-
|
|
682
|
-
/* Both the ceiling and the measured headroom apply: whichever is smaller
|
|
683
|
-
wins, so a tall assistant gets a comfortable menu and a short one gets a
|
|
684
|
-
scrolling menu rather than one clipped by the wrapper's overflow. */
|
|
685
|
-
max-height: min(320px, var(--composer-menu-max-height, 320px));
|
|
686
|
-
overflow-y: auto;
|
|
687
|
-
padding: calc(var(--design-unit) * 1px);
|
|
688
|
-
border: 1px solid var(--neutral-stroke-rest);
|
|
689
|
-
border-radius: calc(var(--control-corner-radius) * 2px);
|
|
690
|
-
background-color: var(--neutral-layer-3);
|
|
691
|
-
box-shadow: 0 8px 24px rgb(0 0 0 / 28%);
|
|
692
|
-
|
|
693
|
-
/* All three offsets are measured and written by positionComposerMenu() when
|
|
694
|
-
the menu opens — CSS cannot read the trigger's offset from here. The menu
|
|
695
|
-
sits directly on top of the button that opened it, in both axes, and grows
|
|
696
|
-
out of that button's centre. Anchoring to the button rather than to the
|
|
697
|
-
composer's top edge means it can overlap the last line or two of the
|
|
698
|
-
textarea; that is the deliberate trade for a menu that reads as belonging
|
|
699
|
-
to the control, and it is transient. The fallbacks only apply for the one
|
|
700
|
-
frame before the measurement lands. */
|
|
701
|
-
left: var(--composer-menu-left, 0);
|
|
702
|
-
bottom: calc(var(--composer-menu-bottom, 100%) + var(--design-unit) * 2px);
|
|
703
|
-
transform-origin: var(--composer-menu-origin, 0) bottom;
|
|
704
|
-
animation: composer-menu-in 0.14s ease-out;
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
.composer-menu.closing {
|
|
708
|
-
animation: composer-menu-out 0.14s ease-in forwards;
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
@keyframes composer-menu-in {
|
|
712
|
-
from {
|
|
713
|
-
opacity: 0%;
|
|
714
|
-
transform: scale(0.96) translateY(4px);
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
to {
|
|
718
|
-
opacity: 100%;
|
|
719
|
-
transform: scale(1) translateY(0);
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
@keyframes composer-menu-out {
|
|
724
|
-
from {
|
|
725
|
-
opacity: 100%;
|
|
726
|
-
transform: scale(1) translateY(0);
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
to {
|
|
730
|
-
opacity: 0%;
|
|
731
|
-
transform: scale(0.96) translateY(4px);
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
/* The session menu renders its rows directly (the picker is a child element
|
|
736
|
-
that brings its own copy of the shared row styles). */
|
|
737
|
-
.session-menu-panel {
|
|
738
|
-
display: flex;
|
|
739
|
-
flex-direction: column;
|
|
740
|
-
gap: 1px;
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
/* Shown in place of the transcript while a manual compaction runs (GENC-1351). */
|
|
744
|
-
.compacting-indicator {
|
|
745
|
-
display: flex;
|
|
746
|
-
flex-direction: column;
|
|
747
|
-
align-items: center;
|
|
748
|
-
justify-content: center;
|
|
749
|
-
gap: calc(var(--design-unit) * 2px);
|
|
750
|
-
padding: calc(var(--design-unit) * 6px) 0;
|
|
751
|
-
color: var(--neutral-foreground-hint, var(--neutral-foreground-rest));
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
.compacting-caption {
|
|
755
|
-
font-size: 0.9em;
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
/* Backend-blocked banner (GENC-1464) — sits between the transcript and the
|
|
759
|
-
disabled composer. Flat and quiet rather than an error toast: the condition
|
|
760
|
-
is standing, not a momentary failure, so it should read as part of the
|
|
761
|
-
chrome the user is now working within. */
|
|
762
|
-
|
|
763
|
-
/* The container is ALWAYS in the DOM so the live region is registered before the
|
|
764
|
-
text arrives (see main.template.ts) — so the bare selector carries only layout,
|
|
765
|
-
and an unblocked banner is an empty, zero-height, invisible box. Everything
|
|
766
|
-
that would make it visible hangs off .is-visible. */
|
|
767
|
-
.blocked-banner {
|
|
768
|
-
display: flex;
|
|
769
|
-
align-items: center;
|
|
770
|
-
gap: calc(var(--design-unit) * 2px);
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
.blocked-banner.is-visible {
|
|
774
|
-
/* Block axis only. The inline-axis margin is owned by the composer width group
|
|
775
|
-
above (margin-inline: auto), which centres the banner on the same column as
|
|
776
|
-
the input row — an inline margin here would fight it. */
|
|
777
|
-
margin-block: var(--blocked-banner-gap);
|
|
778
|
-
padding: calc(var(--design-unit) * 2px) calc(var(--design-unit) * 3px);
|
|
779
|
-
border: calc(var(--stroke-width) * 1px) solid var(--warning-color);
|
|
780
|
-
border-radius: calc(var(--control-corner-radius) * 1px);
|
|
781
|
-
background: var(--neutral-layer-2);
|
|
782
|
-
color: var(--neutral-foreground-rest);
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
/* Partial exhaustion: at least one vendor is walled but the composer is still
|
|
786
|
-
live, so the banner is advice rather than a wall. Softened to match — same
|
|
787
|
-
layout, same part, lower alarm. */
|
|
788
|
-
.blocked-banner.is-partial {
|
|
789
|
-
border-color: var(--neutral-stroke-rest);
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
.blocked-banner-text {
|
|
793
|
-
font-size: 0.9em;
|
|
794
|
-
line-height: 1.4;
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
.chat-input {
|
|
798
|
-
flex: 1;
|
|
799
|
-
resize: none;
|
|
800
|
-
align-self: stretch;
|
|
801
|
-
|
|
802
|
-
/* Drag-to-resize. --composer-height (set inline by the handle) pins an
|
|
803
|
-
explicit height once dragged; unset, height is auto and capped at 150px
|
|
804
|
-
(the original auto-grow behaviour). The host is sized — not the inner
|
|
805
|
-
control — because the design system already stretches its control to the
|
|
806
|
-
host height, and that rule out-specifies anything we could set via
|
|
807
|
-
::part(control). Sizing the host (not just its max-height) is what stops
|
|
808
|
-
a downward drag from squishing the textarea below its natural height. */
|
|
809
|
-
height: var(--composer-height);
|
|
810
|
-
max-height: var(--composer-height, 150px);
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
/* The box around the textarea is .composer's job now, so strip the control's
|
|
814
|
-
own frame — two nested borders is what made the old row look like a field
|
|
815
|
-
inside a field. */
|
|
816
|
-
.chat-input::part(control) {
|
|
817
|
-
border: none;
|
|
818
|
-
background: transparent;
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
.chat-input:focus-within::part(control) {
|
|
822
|
-
outline: none;
|
|
823
|
-
box-shadow: none;
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
/* Full-width grab bar above the input row; drag up/down to resize the composer.
|
|
827
|
-
Sits above the row so it never overlaps the send/stop controls. */
|
|
828
|
-
.composer-resize-handle {
|
|
829
|
-
height: 7px;
|
|
830
|
-
flex-shrink: 0;
|
|
831
|
-
cursor: ns-resize;
|
|
832
|
-
touch-action: none;
|
|
833
|
-
user-select: none;
|
|
834
|
-
display: flex;
|
|
835
|
-
align-items: center;
|
|
836
|
-
justify-content: center;
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
.composer-resize-handle::after {
|
|
840
|
-
content: '';
|
|
841
|
-
width: 32px;
|
|
842
|
-
height: 3px;
|
|
843
|
-
border-radius: 999px;
|
|
844
|
-
background-color: var(--neutral-stroke-rest);
|
|
845
|
-
opacity: 0%;
|
|
846
|
-
transition: opacity 0.15s ease;
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
.composer-resize-handle:hover::after {
|
|
850
|
-
opacity: 70%;
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
/* With the banner visible, its block-end margin and the handle's height used
|
|
854
|
-
to STACK into an ~11px void between the exhausted message and the composer
|
|
855
|
-
— and the hover pill centres in the handle's own 7px slice, i.e. below the
|
|
856
|
-
middle of the gap the user actually sees. Pull the handle up over the
|
|
857
|
-
banner's end margin instead: the handle's height becomes the whole gap and
|
|
858
|
-
the pill lands dead-centre of it. FAST's when-anchors are comment nodes,
|
|
859
|
-
so the adjacency holds whenever the handle renders; without a handle
|
|
860
|
-
(resize disabled) the banner keeps its normal margin before the input row. */
|
|
861
|
-
.blocked-banner.is-visible + .composer-resize-handle {
|
|
862
|
-
margin-block-start: calc(var(--blocked-banner-gap) * -1);
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
.file-input {
|
|
866
|
-
display: none;
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
.thinking-dots {
|
|
870
|
-
display: flex;
|
|
871
|
-
align-items: center;
|
|
872
|
-
align-self: center;
|
|
873
|
-
gap: 5px;
|
|
874
|
-
padding: calc(var(--design-unit) * 2px) calc(var(--design-unit) * 3px);
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
.dot {
|
|
878
|
-
width: 9px;
|
|
879
|
-
height: 9px;
|
|
880
|
-
border-radius: 50%;
|
|
881
|
-
background-image: linear-gradient(145deg, rgb(255 255 255 / 40%) 0%, rgb(0 0 0 / 0%) 100%);
|
|
882
|
-
animation: dot-bounce 1.5s linear infinite;
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
.dot-1 {
|
|
886
|
-
background-color: ${AI_COLOUR_AMBER};
|
|
887
|
-
animation-delay: 0s;
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
.dot-2 {
|
|
891
|
-
background-color: ${AI_COLOUR_PINK};
|
|
892
|
-
animation-delay: 0.1s;
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
.dot-3 {
|
|
896
|
-
background-color: ${AI_COLOUR_CYAN};
|
|
897
|
-
animation-delay: 0.2s;
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
.dot-4 {
|
|
901
|
-
background-color: ${AI_COLOUR_VIOLET};
|
|
902
|
-
animation-delay: 0.3s;
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
@keyframes dot-bounce {
|
|
906
|
-
0%,
|
|
907
|
-
50%,
|
|
908
|
-
100% {
|
|
909
|
-
transform: scale(1);
|
|
910
|
-
filter: blur(0);
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
25% {
|
|
914
|
-
transform: scale(0.6);
|
|
915
|
-
filter: blur(2px);
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
75% {
|
|
919
|
-
transform: scale(1.4);
|
|
920
|
-
filter: blur(2px);
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
.thinking-waves,
|
|
925
|
-
.thinking-flowing-waves,
|
|
926
|
-
.thinking-plasma {
|
|
927
|
-
display: flex;
|
|
928
|
-
flex-direction: column;
|
|
929
|
-
align-items: center;
|
|
930
|
-
align-self: center;
|
|
931
|
-
gap: 6px;
|
|
932
|
-
padding: calc(var(--design-unit) * 2px) calc(var(--design-unit) * 3px);
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
/* The flowing-waves host is the avatar's height (32px), so drop the top padding
|
|
936
|
-
the shared rule adds — that keeps the wave line level with the avatar instead
|
|
937
|
-
of dropping it toward the row's vertical centre. */
|
|
938
|
-
.thinking-flowing-waves {
|
|
939
|
-
padding-top: 0;
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
.thinking-caption {
|
|
943
|
-
font-size: var(--type-ramp-minus-1-font-size, 12px);
|
|
944
|
-
line-height: var(--type-ramp-minus-1-line-height, 16px);
|
|
945
|
-
color: var(--neutral-foreground-rest);
|
|
946
|
-
opacity: 70%;
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
.attachment-chips {
|
|
950
|
-
display: flex;
|
|
951
|
-
flex-wrap: wrap;
|
|
952
|
-
gap: 8px;
|
|
953
|
-
padding: 0 calc(var(--design-unit) * 3px) calc(var(--design-unit) * 2px);
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
.attachment-chip {
|
|
957
|
-
display: flex;
|
|
958
|
-
align-items: center;
|
|
959
|
-
gap: 6px;
|
|
960
|
-
padding: 4px 8px;
|
|
961
|
-
background-color: var(--neutral-layer-4);
|
|
962
|
-
border-radius: calc(var(--control-corner-radius) * 1px);
|
|
963
|
-
font-size: 0.9em;
|
|
964
|
-
border: 1px solid var(--neutral-stroke-rest);
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
.attachment-chip-error {
|
|
968
|
-
background-color: var(--error-fill-rest);
|
|
969
|
-
border-color: var(--error-stroke-rest);
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
.chip-remove {
|
|
973
|
-
background: none;
|
|
974
|
-
border: none;
|
|
975
|
-
color: var(--neutral-foreground-rest);
|
|
976
|
-
cursor: pointer;
|
|
977
|
-
font-size: 1.2em;
|
|
978
|
-
padding: 0 0 0 4px;
|
|
979
|
-
opacity: 70%;
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
.chip-remove:hover {
|
|
983
|
-
opacity: 100%;
|
|
984
|
-
}
|
|
985
|
-
`;
|
|
986
|
-
|
|
987
|
-
export const styles = css`
|
|
988
|
-
${baseStyles}
|
|
989
|
-
${
|
|
990
|
-
/* The session menu's rows. Same partial the agent picker imports into its own
|
|
991
|
-
shadow root — the one thing that keeps the two menus looking alike. */ ''
|
|
992
|
-
}
|
|
993
|
-
${menuItemStyles}
|
|
994
|
-
${settingsModalStyles}
|
|
995
|
-
`;
|