tabby-ai-assistant 1.0.5 → 1.0.6
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/dist/components/chat/ai-sidebar.component.d.ts +147 -0
- package/dist/components/chat/chat-interface.component.d.ts +38 -6
- package/dist/components/settings/general-settings.component.d.ts +6 -3
- package/dist/components/settings/provider-config.component.d.ts +25 -12
- package/dist/components/terminal/command-preview.component.d.ts +38 -0
- package/dist/index-full.d.ts +8 -0
- package/dist/index-minimal.d.ts +3 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.js +1 -2
- package/dist/providers/tabby/ai-config.provider.d.ts +57 -5
- package/dist/providers/tabby/ai-hotkey.provider.d.ts +8 -14
- package/dist/providers/tabby/ai-toolbar-button.provider.d.ts +8 -9
- package/dist/services/chat/ai-sidebar.service.d.ts +89 -0
- package/dist/services/chat/chat-history.service.d.ts +78 -0
- package/dist/services/chat/chat-session.service.d.ts +57 -2
- package/dist/services/context/compaction.d.ts +90 -0
- package/dist/services/context/manager.d.ts +69 -0
- package/dist/services/context/memory.d.ts +116 -0
- package/dist/services/context/token-budget.d.ts +105 -0
- package/dist/services/core/ai-assistant.service.d.ts +40 -1
- package/dist/services/core/checkpoint.service.d.ts +130 -0
- package/dist/services/platform/escape-sequence.service.d.ts +132 -0
- package/dist/services/platform/platform-detection.service.d.ts +146 -0
- package/dist/services/providers/anthropic-provider.service.d.ts +5 -0
- package/dist/services/providers/base-provider.service.d.ts +6 -1
- package/dist/services/providers/glm-provider.service.d.ts +5 -0
- package/dist/services/providers/minimax-provider.service.d.ts +10 -1
- package/dist/services/providers/ollama-provider.service.d.ts +76 -0
- package/dist/services/providers/openai-compatible.service.d.ts +5 -0
- package/dist/services/providers/openai-provider.service.d.ts +5 -0
- package/dist/services/providers/vllm-provider.service.d.ts +82 -0
- package/dist/services/terminal/buffer-analyzer.service.d.ts +128 -0
- package/dist/services/terminal/terminal-manager.service.d.ts +185 -0
- package/dist/services/terminal/terminal-tools.service.d.ts +79 -0
- package/dist/types/ai.types.d.ts +92 -0
- package/dist/types/provider.types.d.ts +1 -1
- package/package.json +7 -10
- package/src/components/chat/ai-sidebar.component.ts +945 -0
- package/src/components/chat/chat-input.component.html +9 -24
- package/src/components/chat/chat-input.component.scss +3 -2
- package/src/components/chat/chat-interface.component.html +77 -69
- package/src/components/chat/chat-interface.component.scss +54 -4
- package/src/components/chat/chat-interface.component.ts +250 -34
- package/src/components/chat/chat-settings.component.scss +4 -4
- package/src/components/chat/chat-settings.component.ts +22 -11
- package/src/components/common/error-message.component.html +15 -0
- package/src/components/common/error-message.component.scss +77 -0
- package/src/components/common/error-message.component.ts +2 -96
- package/src/components/common/loading-spinner.component.html +4 -0
- package/src/components/common/loading-spinner.component.scss +57 -0
- package/src/components/common/loading-spinner.component.ts +2 -63
- package/src/components/security/consent-dialog.component.html +22 -0
- package/src/components/security/consent-dialog.component.scss +34 -0
- package/src/components/security/consent-dialog.component.ts +2 -55
- package/src/components/security/password-prompt.component.html +19 -0
- package/src/components/security/password-prompt.component.scss +30 -0
- package/src/components/security/password-prompt.component.ts +2 -54
- package/src/components/security/risk-confirm-dialog.component.html +8 -12
- package/src/components/security/risk-confirm-dialog.component.scss +8 -5
- package/src/components/security/risk-confirm-dialog.component.ts +6 -6
- package/src/components/settings/ai-settings-tab.component.html +16 -20
- package/src/components/settings/ai-settings-tab.component.scss +8 -5
- package/src/components/settings/ai-settings-tab.component.ts +12 -12
- package/src/components/settings/general-settings.component.html +8 -17
- package/src/components/settings/general-settings.component.scss +6 -3
- package/src/components/settings/general-settings.component.ts +62 -22
- package/src/components/settings/provider-config.component.html +19 -39
- package/src/components/settings/provider-config.component.scss +182 -39
- package/src/components/settings/provider-config.component.ts +119 -7
- package/src/components/settings/security-settings.component.scss +1 -1
- package/src/components/terminal/ai-toolbar-button.component.html +8 -0
- package/src/components/terminal/ai-toolbar-button.component.scss +20 -0
- package/src/components/terminal/ai-toolbar-button.component.ts +2 -30
- package/src/components/terminal/command-preview.component.html +61 -0
- package/src/components/terminal/command-preview.component.scss +72 -0
- package/src/components/terminal/command-preview.component.ts +127 -140
- package/src/components/terminal/command-suggestion.component.html +23 -0
- package/src/components/terminal/command-suggestion.component.scss +55 -0
- package/src/components/terminal/command-suggestion.component.ts +2 -77
- package/src/index-minimal.ts +32 -0
- package/src/index.ts +94 -11
- package/src/index.ts.backup +165 -0
- package/src/providers/tabby/ai-config.provider.ts +60 -51
- package/src/providers/tabby/ai-hotkey.provider.ts +23 -39
- package/src/providers/tabby/ai-settings-tab.provider.ts +2 -2
- package/src/providers/tabby/ai-toolbar-button.provider.ts +29 -24
- package/src/services/chat/ai-sidebar.service.ts +258 -0
- package/src/services/chat/chat-history.service.ts +308 -0
- package/src/services/chat/chat-history.service.ts.backup +239 -0
- package/src/services/chat/chat-session.service.ts +276 -3
- package/src/services/context/compaction.ts +483 -0
- package/src/services/context/manager.ts +442 -0
- package/src/services/context/memory.ts +519 -0
- package/src/services/context/token-budget.ts +422 -0
- package/src/services/core/ai-assistant.service.ts +280 -5
- package/src/services/core/ai-provider-manager.service.ts +2 -2
- package/src/services/core/checkpoint.service.ts +619 -0
- package/src/services/platform/escape-sequence.service.ts +499 -0
- package/src/services/platform/platform-detection.service.ts +494 -0
- package/src/services/providers/anthropic-provider.service.ts +28 -1
- package/src/services/providers/base-provider.service.ts +7 -1
- package/src/services/providers/glm-provider.service.ts +28 -1
- package/src/services/providers/minimax-provider.service.ts +209 -11
- package/src/services/providers/ollama-provider.service.ts +445 -0
- package/src/services/providers/openai-compatible.service.ts +9 -0
- package/src/services/providers/openai-provider.service.ts +9 -0
- package/src/services/providers/vllm-provider.service.ts +463 -0
- package/src/services/security/risk-assessment.service.ts +6 -2
- package/src/services/terminal/buffer-analyzer.service.ts +594 -0
- package/src/services/terminal/terminal-manager.service.ts +748 -0
- package/src/services/terminal/terminal-tools.service.ts +441 -0
- package/src/styles/ai-assistant.scss +78 -6
- package/src/types/ai.types.ts +144 -0
- package/src/types/provider.types.ts +1 -1
- package/tsconfig.json +9 -9
- package/webpack.config.js +28 -6
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
<div class="chat-input-container">
|
|
2
2
|
<!-- 输入区域 -->
|
|
3
3
|
<div class="input-wrapper">
|
|
4
|
-
<textarea
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
[value]="inputValue"
|
|
8
|
-
[placeholder]="placeholder"
|
|
9
|
-
[disabled]="disabled"
|
|
10
|
-
(keydown)="onKeydown($event)"
|
|
11
|
-
(input)="onInput($event)"
|
|
12
|
-
(compositionstart)="onCompositionStart()"
|
|
13
|
-
(compositionend)="onCompositionEnd()"
|
|
14
|
-
rows="1">
|
|
4
|
+
<textarea #textInput class="chat-textarea" [(ngModel)]="inputValue" [placeholder]="placeholder"
|
|
5
|
+
[disabled]="disabled" (keydown)="onKeydown($event)" (input)="onInput($event)"
|
|
6
|
+
(compositionstart)="onCompositionStart()" (compositionend)="onCompositionEnd()" rows="1">
|
|
15
7
|
</textarea>
|
|
16
8
|
|
|
17
9
|
<!-- 字符计数 -->
|
|
@@ -26,21 +18,14 @@
|
|
|
26
18
|
<!-- 操作按钮 -->
|
|
27
19
|
<div class="input-actions">
|
|
28
20
|
<!-- 清空按钮 -->
|
|
29
|
-
<button
|
|
30
|
-
|
|
31
|
-
class="btn-icon"
|
|
32
|
-
(click)="clear()"
|
|
33
|
-
title="清空">
|
|
34
|
-
<i class="icon-clear"></i>
|
|
21
|
+
<button *ngIf="inputValue && !disabled" class="btn-icon" (click)="clear()" title="清空">
|
|
22
|
+
<i class="fa fa-times"></i>
|
|
35
23
|
</button>
|
|
36
24
|
|
|
37
25
|
<!-- 发送按钮 -->
|
|
38
|
-
<button
|
|
39
|
-
class="btn-send"
|
|
40
|
-
[disabled]="!inputValue.trim() || disabled || isOverLimit()"
|
|
41
|
-
(click)="submit()"
|
|
26
|
+
<button class="btn-send" [disabled]="!inputValue.trim() || disabled || isOverLimit()" (click)="submit()"
|
|
42
27
|
title="发送 (Enter)">
|
|
43
|
-
<i class="
|
|
28
|
+
<i class="fa fa-paper-plane"></i>
|
|
44
29
|
<span class="btn-text">发送</span>
|
|
45
30
|
</button>
|
|
46
31
|
</div>
|
|
@@ -54,8 +39,8 @@
|
|
|
54
39
|
<kbd>Shift + Enter</kbd> 换行
|
|
55
40
|
</span>
|
|
56
41
|
<span class="hint-item" *ngIf="isNearLimit()">
|
|
57
|
-
<i class="
|
|
42
|
+
<i class="fa fa-exclamation-triangle"></i>
|
|
58
43
|
接近字符限制
|
|
59
44
|
</span>
|
|
60
45
|
</div>
|
|
61
|
-
</div>
|
|
46
|
+
</div>
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
gap: 0.5rem;
|
|
111
111
|
|
|
112
112
|
&:hover:not(:disabled) {
|
|
113
|
-
background-color:
|
|
113
|
+
background-color: #0069d9;
|
|
114
114
|
transform: translateY(-1px);
|
|
115
115
|
}
|
|
116
116
|
|
|
@@ -169,6 +169,7 @@
|
|
|
169
169
|
.input-actions {
|
|
170
170
|
.btn-send {
|
|
171
171
|
min-width: 80px;
|
|
172
|
+
|
|
172
173
|
.btn-text {
|
|
173
174
|
display: none;
|
|
174
175
|
}
|
|
@@ -180,4 +181,4 @@
|
|
|
180
181
|
font-size: 0.7rem;
|
|
181
182
|
}
|
|
182
183
|
}
|
|
183
|
-
}
|
|
184
|
+
}
|
|
@@ -3,117 +3,125 @@
|
|
|
3
3
|
<div class="ai-chat-header">
|
|
4
4
|
<div class="header-left">
|
|
5
5
|
<h2 class="ai-title">
|
|
6
|
-
<i class="
|
|
6
|
+
<i class="fa fa-comments"></i>
|
|
7
7
|
AI助手
|
|
8
8
|
</h2>
|
|
9
9
|
<span class="provider-badge">
|
|
10
|
-
<i class="
|
|
10
|
+
<i class="fa fa-cloud"></i>
|
|
11
11
|
{{ currentProvider }}
|
|
12
12
|
</span>
|
|
13
13
|
</div>
|
|
14
14
|
<div class="header-actions">
|
|
15
15
|
<button class="btn-icon" (click)="switchProvider()" title="切换AI提供商">
|
|
16
|
-
<i class="
|
|
16
|
+
<i class="fa fa-exchange"></i>
|
|
17
17
|
</button>
|
|
18
18
|
<button class="btn-icon" (click)="exportChat()" title="导出聊天记录">
|
|
19
|
-
<i class="
|
|
19
|
+
<i class="fa fa-download"></i>
|
|
20
20
|
</button>
|
|
21
21
|
<button class="btn-icon danger" (click)="clearChat()" title="清空聊天记录">
|
|
22
|
-
<i class="
|
|
22
|
+
<i class="fa fa-trash"></i>
|
|
23
23
|
</button>
|
|
24
24
|
</div>
|
|
25
25
|
</div>
|
|
26
26
|
|
|
27
|
-
<!--
|
|
28
|
-
<div class="
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
<
|
|
32
|
-
<!--
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
<!-- 消息项 -->
|
|
41
|
-
<div class="message-item"
|
|
42
|
-
[ngClass]="{
|
|
43
|
-
'user-message': message.role === 'user',
|
|
44
|
-
'assistant-message': message.role === 'assistant',
|
|
45
|
-
'system-message': message.role === 'system'
|
|
46
|
-
}">
|
|
47
|
-
<!-- 头像 -->
|
|
48
|
-
<div class="message-avatar">
|
|
49
|
-
<div *ngIf="message.role === 'user'" class="avatar user">
|
|
50
|
-
<i class="icon-user"></i>
|
|
51
|
-
</div>
|
|
52
|
-
<div *ngIf="message.role === 'assistant'" class="avatar assistant">
|
|
53
|
-
<i class="icon-bot"></i>
|
|
54
|
-
</div>
|
|
55
|
-
<div *ngIf="message.role === 'system'" class="avatar system">
|
|
56
|
-
<i class="icon-info"></i>
|
|
57
|
-
</div>
|
|
27
|
+
<!-- 消息列表包装器 (用于滚动按钮定位) -->
|
|
28
|
+
<div class="chat-content-wrapper">
|
|
29
|
+
<!-- 消息列表 -->
|
|
30
|
+
<div class="ai-chat-container" #chatContainer (scroll)="onScroll($event)">
|
|
31
|
+
<div class="messages-wrapper">
|
|
32
|
+
<!-- 消息分组 -->
|
|
33
|
+
<ng-container *ngFor="let message of messages; let i = index">
|
|
34
|
+
<!-- 检查是否需要显示日期分隔线 -->
|
|
35
|
+
<div *ngIf="i === 0 || !isSameDay(message.timestamp, messages[i-1].timestamp)"
|
|
36
|
+
class="date-separator">
|
|
37
|
+
<span class="date-text">
|
|
38
|
+
{{ isToday(message.timestamp) ? '今天' : message.timestamp.toLocaleDateString('zh-CN') }}
|
|
39
|
+
</span>
|
|
58
40
|
</div>
|
|
59
41
|
|
|
60
|
-
<!--
|
|
61
|
-
<div class="message-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
42
|
+
<!-- 消息项 -->
|
|
43
|
+
<div class="message-item" [ngClass]="{
|
|
44
|
+
'user-message': message.role === 'user',
|
|
45
|
+
'assistant-message': message.role === 'assistant',
|
|
46
|
+
'system-message': message.role === 'system'
|
|
47
|
+
}">
|
|
48
|
+
<!-- 头像 -->
|
|
49
|
+
<div class="message-avatar">
|
|
50
|
+
<div *ngIf="message.role === 'user'" class="avatar user">
|
|
51
|
+
<i class="fa fa-user"></i>
|
|
66
52
|
</div>
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<div *ngIf="message.role === 'assistant'" class="message-text ai-response">
|
|
70
|
-
<pre>{{ message.content }}</pre>
|
|
53
|
+
<div *ngIf="message.role === 'assistant'" class="avatar assistant">
|
|
54
|
+
<i class="fa fa-robot"></i>
|
|
71
55
|
</div>
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
<div *ngIf="message.role === 'system'" class="message-text system">
|
|
75
|
-
<i class="icon-warning"></i>
|
|
76
|
-
{{ message.content }}
|
|
56
|
+
<div *ngIf="message.role === 'system'" class="avatar system">
|
|
57
|
+
<i class="fa fa-info-circle"></i>
|
|
77
58
|
</div>
|
|
78
59
|
</div>
|
|
79
60
|
|
|
80
|
-
<!--
|
|
81
|
-
<div class="message-
|
|
82
|
-
|
|
61
|
+
<!-- 消息内容 -->
|
|
62
|
+
<div class="message-content">
|
|
63
|
+
<div class="message-bubble">
|
|
64
|
+
<!-- 用户消息 -->
|
|
65
|
+
<div *ngIf="message.role === 'user'" class="message-text">
|
|
66
|
+
{{ message.content }}
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<!-- AI消息 -->
|
|
70
|
+
<div *ngIf="message.role === 'assistant'" class="message-text ai-response">
|
|
71
|
+
<pre>{{ message.content }}</pre>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<!-- 系统消息 -->
|
|
75
|
+
<div *ngIf="message.role === 'system'" class="message-text system">
|
|
76
|
+
<i class="fa fa-exclamation-triangle"></i>
|
|
77
|
+
{{ message.content }}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<!-- 消息时间 -->
|
|
82
|
+
<div class="message-time">
|
|
83
|
+
{{ formatTimestamp(message.timestamp) }}
|
|
84
|
+
</div>
|
|
83
85
|
</div>
|
|
84
86
|
</div>
|
|
85
|
-
</
|
|
86
|
-
</ng-container>
|
|
87
|
+
</ng-container>
|
|
87
88
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
<!-- 加载指示器 -->
|
|
90
|
+
<div *ngIf="isLoading" class="loading-indicator">
|
|
91
|
+
<div class="typing-indicator">
|
|
92
|
+
<span></span>
|
|
93
|
+
<span></span>
|
|
94
|
+
<span></span>
|
|
95
|
+
</div>
|
|
96
|
+
<span class="loading-text">AI正在思考...</span>
|
|
94
97
|
</div>
|
|
95
|
-
<span class="loading-text">AI正在思考...</span>
|
|
96
98
|
</div>
|
|
97
99
|
</div>
|
|
100
|
+
|
|
101
|
+
<!-- 滚动按钮 (在容器外部以便固定定位) -->
|
|
102
|
+
<button *ngIf="showScrollTop" class="scroll-btn scroll-top" (click)="scrollToTop()" title="滚动到顶部">
|
|
103
|
+
<i class="fa fa-chevron-up"></i>
|
|
104
|
+
</button>
|
|
105
|
+
<button *ngIf="showScrollBottom" class="scroll-btn scroll-bottom" (click)="scrollToBottom()" title="滚动到底部">
|
|
106
|
+
<i class="fa fa-chevron-down"></i>
|
|
107
|
+
</button>
|
|
98
108
|
</div>
|
|
99
109
|
|
|
100
110
|
<!-- 输入区域 -->
|
|
101
111
|
<div class="ai-chat-input">
|
|
102
|
-
<app-chat-input
|
|
103
|
-
(send)="onSendMessage($event)"
|
|
104
|
-
[disabled]="isLoading">
|
|
112
|
+
<app-chat-input (send)="onSendMessage($event)" [disabled]="isLoading">
|
|
105
113
|
</app-chat-input>
|
|
106
114
|
</div>
|
|
107
115
|
|
|
108
116
|
<!-- 提示信息 -->
|
|
109
117
|
<div class="chat-tips" *ngIf="messages.length === 1">
|
|
110
118
|
<div class="tip-item">
|
|
111
|
-
<i class="
|
|
119
|
+
<i class="fa fa-lightbulb-o"></i>
|
|
112
120
|
<span>提示:您可以描述想执行的命令,例如"查看当前目录的所有文件"</span>
|
|
113
121
|
</div>
|
|
114
122
|
<div class="tip-item">
|
|
115
|
-
<i class="
|
|
123
|
+
<i class="fa fa-keyboard-o"></i>
|
|
116
124
|
<span>快捷键:Ctrl+Shift+G 生成命令,Ctrl+Shift+E 解释命令</span>
|
|
117
125
|
</div>
|
|
118
126
|
</div>
|
|
119
|
-
</div>
|
|
127
|
+
</div>
|
|
@@ -84,6 +84,15 @@
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
/* 内容包装器 (用于滚动按钮定位) */
|
|
88
|
+
.chat-content-wrapper {
|
|
89
|
+
flex: 1;
|
|
90
|
+
display: flex;
|
|
91
|
+
flex-direction: column;
|
|
92
|
+
position: relative;
|
|
93
|
+
overflow: hidden;
|
|
94
|
+
}
|
|
95
|
+
|
|
87
96
|
/* 消息容器 */
|
|
88
97
|
.ai-chat-container {
|
|
89
98
|
flex: 1;
|
|
@@ -122,6 +131,43 @@
|
|
|
122
131
|
}
|
|
123
132
|
}
|
|
124
133
|
|
|
134
|
+
/* 滚动按钮 */
|
|
135
|
+
.scroll-btn {
|
|
136
|
+
position: absolute;
|
|
137
|
+
z-index: 100;
|
|
138
|
+
width: 36px;
|
|
139
|
+
height: 36px;
|
|
140
|
+
border: none;
|
|
141
|
+
border-radius: 50%;
|
|
142
|
+
background-color: var(--ai-primary);
|
|
143
|
+
color: white;
|
|
144
|
+
cursor: pointer;
|
|
145
|
+
display: flex;
|
|
146
|
+
align-items: center;
|
|
147
|
+
justify-content: center;
|
|
148
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
149
|
+
transition: all 0.2s ease;
|
|
150
|
+
opacity: 0.9;
|
|
151
|
+
right: 15px;
|
|
152
|
+
|
|
153
|
+
&:hover {
|
|
154
|
+
opacity: 1;
|
|
155
|
+
transform: scale(1.1);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
&.scroll-top {
|
|
159
|
+
top: 10px;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
&.scroll-bottom {
|
|
163
|
+
bottom: 10px;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
i {
|
|
167
|
+
font-size: 0.875rem;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
125
171
|
/* 消息项 */
|
|
126
172
|
.message-item {
|
|
127
173
|
display: flex;
|
|
@@ -258,8 +304,8 @@
|
|
|
258
304
|
gap: 0.25rem;
|
|
259
305
|
|
|
260
306
|
span {
|
|
261
|
-
width:
|
|
262
|
-
height;
|
|
307
|
+
width: 6px;
|
|
308
|
+
height: 6px;
|
|
263
309
|
border-radius: 50%;
|
|
264
310
|
background-color: var(--ai-secondary);
|
|
265
311
|
animation: typing 1.4s infinite ease-in-out;
|
|
@@ -281,10 +327,14 @@
|
|
|
281
327
|
}
|
|
282
328
|
|
|
283
329
|
@keyframes typing {
|
|
284
|
-
|
|
330
|
+
|
|
331
|
+
0%,
|
|
332
|
+
80%,
|
|
333
|
+
100% {
|
|
285
334
|
transform: scale(0.8);
|
|
286
335
|
opacity: 0.5;
|
|
287
336
|
}
|
|
337
|
+
|
|
288
338
|
40% {
|
|
289
339
|
transform: scale(1);
|
|
290
340
|
opacity: 1;
|
|
@@ -351,4 +401,4 @@
|
|
|
351
401
|
font-size: 0.8rem;
|
|
352
402
|
}
|
|
353
403
|
}
|
|
354
|
-
}
|
|
404
|
+
}
|