@crievo/omni 0.1.7 → 0.1.8

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.
Files changed (68) hide show
  1. package/omnivideo.config.example.json +1 -0
  2. package/package.json +1 -1
  3. package/reference/cloud.md +15 -1
  4. package/reference/learnings.md +7 -0
  5. package/reference/studio.md +1 -0
  6. package/studio/api/app.ts +4 -0
  7. package/studio/api/routes/cost.ts +13 -0
  8. package/studio/api/routes/me.ts +8 -0
  9. package/studio/api/services/agent-tools.ts +2 -2
  10. package/studio/api/services/cost.ts +22 -0
  11. package/studio/api/services/me.ts +67 -0
  12. package/studio/api/services/sessions.ts +8 -2
  13. package/studio/runner/runner.ts +57 -10
  14. package/studio/shared/omni-screens.ts +1 -1
  15. package/studio/shared/schemas/cost.ts +10 -0
  16. package/studio/shared/types/api.ts +74 -0
  17. package/studio/studio.ts +27 -2
  18. package/studio/web/components/AppShell.tsx +11 -3
  19. package/studio/web/components/FirstConnection.tsx +222 -0
  20. package/studio/web/components/OfflineNotice.tsx +59 -0
  21. package/studio/web/components/SetupSteps.tsx +63 -0
  22. package/studio/web/components/Sidebar.tsx +10 -25
  23. package/studio/web/components/StudioOffline.tsx +48 -50
  24. package/studio/web/components/UserCard.tsx +79 -0
  25. package/studio/web/components/icons.tsx +2 -0
  26. package/studio/web/hooks/useComputers.ts +55 -0
  27. package/studio/web/hooks/useCost.ts +11 -0
  28. package/studio/web/hooks/useMe.ts +32 -0
  29. package/studio/web/hooks/useSetupProgress.ts +54 -0
  30. package/studio/web/lib/me.ts +17 -0
  31. package/studio/web/lib/query-client.ts +6 -0
  32. package/studio/web/lib/settings-categories.ts +2 -2
  33. package/studio/web/lib/setup-retry.ts +29 -0
  34. package/studio/web/lib/studio-offline.ts +105 -59
  35. package/studio/web/pages/ConnectPreviewPage/index.tsx +215 -0
  36. package/studio/web/pages/SettingsPage/components/AgentCategory.tsx +18 -9
  37. package/studio/web/pages/SettingsPage/components/AgentCostPanel.tsx +253 -0
  38. package/studio/web/pages/SettingsPage/components/ComputersPanel.tsx +145 -0
  39. package/studio/web/pages/SettingsPage/components/PublishingCategory/OmnichatSettingsPanel.tsx +2 -2
  40. package/studio/web/pages/SettingsPage/components/PublishingCategory/SchedulePanel.tsx +3 -3
  41. package/studio/web/pages/SettingsPage/components/UsageCategory.tsx +7 -2
  42. package/studio/web/pages/SettingsPage/index.tsx +15 -1
  43. package/studio/web/pages/VideoPage/components/PublishForm.tsx +5 -2
  44. package/studio/web/router.tsx +8 -0
  45. package/studio/web/styles/components/setup-steps.css +163 -0
  46. package/studio/web/styles/components/user-card.css +121 -0
  47. package/studio/web/styles/index.css +2 -0
  48. package/studio/web/styles/pages/settings/shell.css +79 -0
  49. package/studio/web/styles/pages/settings/usage.css +47 -0
  50. package/studio/web/styles/pages/studio-offline.css +224 -38
  51. package/tools/cost.mjs +114 -0
  52. package/tools/lib/agents.mjs +3 -2
  53. package/tools/lib/channel.mjs +1 -1
  54. package/tools/lib/cloud-user.mjs +58 -0
  55. package/tools/lib/cost.mjs +357 -0
  56. package/tools/lib/deps.mjs +27 -12
  57. package/tools/lib/oauth-client.mjs +28 -14
  58. package/tools/lib/pages-style.mjs +67 -0
  59. package/tools/lib/pairing.mjs +1 -1
  60. package/tools/lib/schedule/schedule.mjs +1 -1
  61. package/tools/lib/self-update.mjs +122 -0
  62. package/tools/lib/setup-progress.mjs +315 -0
  63. package/tools/lib/up.mjs +176 -61
  64. package/tools/metrics.mjs +6 -1
  65. package/tools/omni.mjs +41 -16
  66. package/tools/omnichat.mjs +45 -9
  67. package/tools/platforms.mjs +75 -14
  68. package/tools/runner.mjs +6 -6
@@ -0,0 +1,163 @@
1
+ /* SetupSteps.tsx: the first-time setup as a vertical stepper. A circle on the left of each step (the line
2
+ between them runs down the circles' column), loading while it runs and an emerald check when it is done. */
3
+ .setup-steps {
4
+ list-style: none;
5
+ margin: 0;
6
+ padding: 0;
7
+ display: flex;
8
+ flex-direction: column;
9
+ }
10
+ .setup-step {
11
+ position: relative;
12
+ display: grid;
13
+ grid-template-columns: 28px minmax(0, 1fr) auto;
14
+ align-items: start;
15
+ gap: 0 14px;
16
+ padding-bottom: 20px;
17
+ }
18
+ .setup-step:last-child {
19
+ padding-bottom: 0;
20
+ }
21
+ /* the line down to the next circle: emerald once this step is done */
22
+ .setup-step:not(:last-child)::before {
23
+ content: "";
24
+ position: absolute;
25
+ left: 13px;
26
+ top: 30px;
27
+ bottom: 2px;
28
+ width: 2px;
29
+ border-radius: 1px;
30
+ background: var(--border-strong);
31
+ transition: background 0.3s;
32
+ }
33
+ .setup-step.done:not(:last-child)::before {
34
+ background: color-mix(in srgb, var(--emerald) 70%, transparent);
35
+ }
36
+ .setup-mark {
37
+ position: relative;
38
+ z-index: 1;
39
+ display: grid;
40
+ place-items: center;
41
+ width: 28px;
42
+ height: 28px;
43
+ border-radius: 50%;
44
+ border: 2px solid var(--border-strong);
45
+ background: var(--bg);
46
+ color: var(--text-3);
47
+ font-size: 14px;
48
+ transition:
49
+ background 0.25s,
50
+ border-color 0.25s,
51
+ color 0.25s;
52
+ }
53
+ .setup-step.running .setup-mark {
54
+ border-color: var(--border-strong);
55
+ }
56
+ /* a white check on the dark emerald in both themes: the dark theme's --emerald is a light one, kept for text and lines */
57
+ .setup-step.done .setup-mark {
58
+ background: #059669;
59
+ border-color: #059669;
60
+ color: #fff;
61
+ animation: setup-pop 0.3s ease-out;
62
+ }
63
+ .setup-step.error .setup-mark {
64
+ background: var(--error-bg);
65
+ border-color: var(--error);
66
+ color: var(--error);
67
+ }
68
+ /* the loading ring inside the circle */
69
+ .setup-spin {
70
+ display: inline-block;
71
+ width: 14px;
72
+ height: 14px;
73
+ border-radius: 50%;
74
+ border: 2px solid var(--running);
75
+ border-top-color: transparent;
76
+ animation: spin 0.9s linear infinite;
77
+ }
78
+ .setup-text {
79
+ display: flex;
80
+ flex-direction: column;
81
+ gap: 2px;
82
+ min-width: 0;
83
+ padding-top: 3px;
84
+ }
85
+ .setup-text b {
86
+ font-size: var(--el-text-ui);
87
+ font-weight: 500;
88
+ line-height: 20px;
89
+ color: var(--text);
90
+ }
91
+ .setup-step.pending .setup-text b {
92
+ color: var(--text-2);
93
+ }
94
+ .setup-detail {
95
+ font-size: var(--el-text-small);
96
+ line-height: 18px;
97
+ color: var(--text-3);
98
+ }
99
+ .setup-step.error .setup-detail {
100
+ color: var(--error);
101
+ }
102
+ .setup-error {
103
+ align-self: flex-start;
104
+ max-width: 100%;
105
+ margin-top: 4px;
106
+ padding: 2px 6px;
107
+ border-radius: 6px;
108
+ background: var(--muted);
109
+ font: 400 12px / 18px var(--mono);
110
+ color: var(--text-2);
111
+ overflow-wrap: anywhere;
112
+ }
113
+ .setup-said {
114
+ padding-top: 5px;
115
+ font-size: 12px;
116
+ line-height: 16px;
117
+ color: var(--text-3);
118
+ white-space: nowrap;
119
+ }
120
+ .setup-step.done .setup-said {
121
+ color: var(--emerald);
122
+ }
123
+ .setup-step.error .setup-said {
124
+ color: var(--error);
125
+ }
126
+ @keyframes setup-pop {
127
+ 0% {
128
+ transform: scale(0.7);
129
+ }
130
+ 60% {
131
+ transform: scale(1.12);
132
+ }
133
+ 100% {
134
+ transform: scale(1);
135
+ }
136
+ }
137
+ @media (prefers-reduced-motion: reduce) {
138
+ .setup-step.done .setup-mark {
139
+ animation: none;
140
+ }
141
+ .setup-spin {
142
+ animation-duration: 2.4s;
143
+ }
144
+ }
145
+ @media (max-width: 560px) {
146
+ .setup-said {
147
+ display: none;
148
+ }
149
+ }
150
+
151
+ /* "Tentar de novo" on a failed step, in the place of its state */
152
+ .setup-step .setup-retry {
153
+ display: inline-flex;
154
+ align-items: center;
155
+ gap: 6px;
156
+ height: 30px;
157
+ padding: 0 10px;
158
+ white-space: nowrap;
159
+ }
160
+ .setup-step .setup-retry .ic {
161
+ width: 14px;
162
+ height: 14px;
163
+ }
@@ -0,0 +1,121 @@
1
+ /* UserCard.tsx: under Omni's card in the menu, who is using the studio (avatar, name, email). Quieter than Omni's
2
+ card: the same shape, no border or light around it, and no click (hosted, only its sign-out button clicks). */
3
+ .menu .menu-user {
4
+ position: relative;
5
+ display: flex;
6
+ align-items: center;
7
+ gap: 8px;
8
+ width: 100%;
9
+ min-width: 0;
10
+ padding: 8px 8px 8px 10px;
11
+ border-radius: 16px;
12
+ background: var(--bg);
13
+ }
14
+ .menu .menu-user-initials,
15
+ .menu .menu-user-photo {
16
+ flex: none;
17
+ border-radius: 50%;
18
+ }
19
+ .menu .menu-user-photo {
20
+ display: block;
21
+ width: 36px;
22
+ height: 36px;
23
+ object-fit: cover;
24
+ }
25
+ /* no picture: two initials on a soft disc */
26
+ .menu .menu-user-initials {
27
+ display: grid;
28
+ place-items: center;
29
+ width: 36px;
30
+ height: 36px;
31
+ background: var(--surface-3);
32
+ font-size: 13px;
33
+ font-weight: 600;
34
+ letter-spacing: 0.02em;
35
+ color: var(--text-2);
36
+ }
37
+ .menu .menu-user-text {
38
+ display: flex;
39
+ flex: 1;
40
+ flex-direction: column;
41
+ min-width: 0;
42
+ line-height: 18px;
43
+ }
44
+ .menu .menu-user-text b {
45
+ font-size: 14px;
46
+ font-weight: 600;
47
+ color: var(--text);
48
+ overflow: hidden;
49
+ text-overflow: ellipsis;
50
+ white-space: nowrap;
51
+ }
52
+ .menu .menu-user-text span {
53
+ font-size: 12px;
54
+ color: var(--text-3);
55
+ overflow: hidden;
56
+ text-overflow: ellipsis;
57
+ white-space: nowrap;
58
+ }
59
+ /* collapsed menu: just the avatar */
60
+ .menu-collapsed .menu .menu-user {
61
+ justify-content: center;
62
+ padding: 6px 0;
63
+ background: none;
64
+ }
65
+
66
+ /* Sair (hosted): an icon button on the right of the card, the look of the menu's collapse button */
67
+ .menu .menu-user-exit {
68
+ display: contents;
69
+ }
70
+ .menu .menu-user-signout {
71
+ display: inline-grid;
72
+ place-items: center;
73
+ width: 32px;
74
+ height: 32px;
75
+ flex: none;
76
+ margin-left: auto;
77
+ padding: 0;
78
+ border: 0;
79
+ border-radius: var(--el-radius-nav);
80
+ background: transparent;
81
+ color: var(--text-3);
82
+ cursor: pointer;
83
+ }
84
+ .menu .menu-user-signout svg {
85
+ width: 20px;
86
+ height: 20px;
87
+ }
88
+ .menu .menu-user-signout:hover,
89
+ .menu .menu-user-signout:focus-visible {
90
+ background: var(--el-muted);
91
+ color: var(--text);
92
+ }
93
+ /* collapsed (the menu only collapses on a wide screen), the button sits over the avatar and appears, with a
94
+ fade, when the pointer is on it; the avatar fades out under it, as the logo does for the collapse button */
95
+ @media (min-width: 901px) {
96
+ .menu-collapsed .menu .menu-user-signout {
97
+ position: absolute;
98
+ top: 50%;
99
+ left: 50%;
100
+ margin: -16px 0 0 -16px;
101
+ opacity: 0;
102
+ transition:
103
+ opacity 0.18s ease,
104
+ background 0.12s ease,
105
+ color 0.12s ease;
106
+ }
107
+ .menu-collapsed .menu .menu-user:hover .menu-user-signout,
108
+ .menu-collapsed .menu .menu-user-signout:focus-visible {
109
+ opacity: 1;
110
+ }
111
+ .menu-collapsed .menu .menu-user-photo,
112
+ .menu-collapsed .menu .menu-user-initials {
113
+ transition: opacity 0.18s ease;
114
+ }
115
+ .menu-collapsed .menu .menu-user:hover .menu-user-photo,
116
+ .menu-collapsed .menu .menu-user:hover .menu-user-initials,
117
+ .menu-collapsed .menu .menu-user:has(.menu-user-signout:focus-visible) .menu-user-photo,
118
+ .menu-collapsed .menu .menu-user:has(.menu-user-signout:focus-visible) .menu-user-initials {
119
+ opacity: 0;
120
+ }
121
+ }
@@ -24,6 +24,8 @@
24
24
  @import "./pages/video-list/list.css";
25
25
  @import "./components/badge.css";
26
26
  @import "./components/stepper.css";
27
+ @import "./components/setup-steps.css";
28
+ @import "./components/user-card.css";
27
29
  @import "./components/panel.css";
28
30
  @import "./components/queue.css";
29
31
  @import "./pages/video/layout.css";
@@ -363,3 +363,82 @@
363
363
  .agent-missing small {
364
364
  flex-basis: 100%;
365
365
  }
366
+
367
+ /* Configurações → Agente de IA (hosted): the computers signed in and the actions that went through */
368
+ .computers-intro {
369
+ margin: 0 0 12px;
370
+ max-width: 70ch;
371
+ font-size: var(--el-text-small);
372
+ line-height: 18px;
373
+ }
374
+ .computers {
375
+ list-style: none;
376
+ margin: 0;
377
+ padding: 0;
378
+ display: flex;
379
+ flex-direction: column;
380
+ }
381
+ .computer {
382
+ display: grid;
383
+ grid-template-columns: 36px minmax(0, 1fr) auto auto;
384
+ align-items: center;
385
+ gap: 12px;
386
+ padding: 12px 0;
387
+ border-top: 1px solid var(--border);
388
+ }
389
+ .computer:first-child {
390
+ border-top: 0;
391
+ padding-top: 0;
392
+ }
393
+ .computer-icon {
394
+ display: grid;
395
+ place-items: center;
396
+ width: 36px;
397
+ height: 36px;
398
+ border-radius: var(--el-radius-control);
399
+ background: var(--muted);
400
+ color: var(--text-2);
401
+ font-size: 18px;
402
+ }
403
+ .computer-text {
404
+ display: flex;
405
+ flex-direction: column;
406
+ min-width: 0;
407
+ gap: 1px;
408
+ }
409
+ .computer-text b {
410
+ font-weight: 500;
411
+ font-size: var(--el-text-ui);
412
+ }
413
+ .computer-text .subtle {
414
+ font-size: var(--el-text-small);
415
+ }
416
+ .computer-ask {
417
+ display: inline-flex;
418
+ gap: 6px;
419
+ }
420
+ .audit-scroll {
421
+ max-height: 420px;
422
+ overflow: auto;
423
+ }
424
+ .audit-table code {
425
+ font: 400 12px / 18px var(--mono);
426
+ overflow-wrap: anywhere;
427
+ }
428
+ .audit-table .audit-ok {
429
+ color: var(--ok);
430
+ }
431
+ .audit-table .audit-bad {
432
+ color: var(--error);
433
+ }
434
+ @media (max-width: 720px) {
435
+ .computer {
436
+ grid-template-columns: 36px minmax(0, 1fr);
437
+ }
438
+ .computer > .badge,
439
+ .computer > .button,
440
+ .computer > .computer-ask {
441
+ grid-column: 2;
442
+ justify-self: start;
443
+ }
444
+ }
@@ -61,3 +61,50 @@
61
61
  position: relative;
62
62
  top: -1px;
63
63
  }
64
+
65
+ /* --- agent cost (AgentCostPanel) ---------------------------------------------------------- */
66
+ .usage-section {
67
+ margin: 8px 0 0;
68
+ font: 600 15px var(--sans);
69
+ color: var(--text-2);
70
+ }
71
+ .cost-rows {
72
+ list-style: none;
73
+ margin: 0;
74
+ padding: 0;
75
+ display: flex;
76
+ flex-direction: column;
77
+ gap: 8px;
78
+ }
79
+ .cost-rows li {
80
+ display: grid;
81
+ grid-template-columns: minmax(0, 1fr) auto auto;
82
+ column-gap: 10px;
83
+ align-items: baseline;
84
+ font-size: 13px;
85
+ }
86
+ .cost-rows .cost-name {
87
+ min-width: 0;
88
+ overflow: hidden;
89
+ text-overflow: ellipsis;
90
+ white-space: nowrap;
91
+ }
92
+ .cost-rows .bar {
93
+ grid-column: 1 / -1;
94
+ grid-row: 2;
95
+ margin-top: 3px;
96
+ }
97
+ .cost-rows .cost-value {
98
+ font-variant-numeric: tabular-nums;
99
+ font-weight: 600;
100
+ }
101
+ .cost-rows .cost-pct {
102
+ min-width: 34px;
103
+ text-align: right;
104
+ font-variant-numeric: tabular-nums;
105
+ }
106
+ .cost-sub {
107
+ margin: 14px 0 8px;
108
+ font: 600 12.5px var(--sans);
109
+ color: var(--text-3);
110
+ }
@@ -1,15 +1,13 @@
1
- /* StudioOffline.tsx: the screen over the whole app while the hosted studio isn't connected. The same
2
- look as the 404 (not-found.css): centered column, light heading, 40 px buttons. */
1
+ /* StudioOffline.tsx and FirstConnection.tsx: the screen inside the app (the menu stays) while the studio isn't
2
+ connected. A computer that was there and is away: the 404's look, a centered column (not-found.css). The first
3
+ time: the welcome, how it works, the plugin to install and the setup's steps. */
4
+
5
+ /* --- a computer that was there and is away ---------------------------------------------------- */
3
6
  .studio-offline {
4
- position: fixed;
5
- inset: 0;
6
- z-index: 100;
7
7
  display: flex;
8
8
  align-items: center;
9
9
  justify-content: center;
10
- padding: 24px 16px;
11
- overflow-y: auto;
12
- background: var(--bg);
10
+ min-height: calc(var(--content-height) - var(--top-offset) - 88px);
13
11
  }
14
12
  .studio-offline-body {
15
13
  display: flex;
@@ -44,28 +42,11 @@
44
42
  line-height: 20px;
45
43
  color: var(--text-2);
46
44
  }
47
- .studio-offline-steps {
48
- margin: 4px 0 0;
49
- padding: 14px 16px 14px 36px;
50
- max-width: 100%;
51
- border-radius: var(--el-radius-control);
52
- background: var(--muted);
45
+ /* the stepper under the line: a card, left aligned inside the centered column */
46
+ .studio-offline-card {
47
+ width: 100%;
48
+ margin-top: 8px;
53
49
  text-align: left;
54
- font-size: var(--el-text-ui);
55
- line-height: 22px;
56
- color: var(--text-2);
57
- }
58
- .studio-offline-steps li + li {
59
- margin-top: 6px;
60
- }
61
- .studio-offline-steps code {
62
- padding: 1px 6px;
63
- border: 1px solid var(--border-strong);
64
- border-radius: 6px;
65
- background: var(--bg);
66
- font: 400 var(--el-text-small) / 20px var(--mono);
67
- color: var(--text);
68
- overflow-wrap: anywhere;
69
50
  }
70
51
  .studio-offline-actions {
71
52
  justify-content: center;
@@ -80,26 +61,231 @@
80
61
  padding: 0 16px;
81
62
  border-radius: var(--el-radius-control);
82
63
  font: 500 var(--el-text-ui) / 20px var(--sans);
64
+ text-decoration: none;
83
65
  }
84
66
  .studio-offline-actions .button .ic {
85
67
  width: 16px;
86
68
  height: 16px;
87
69
  }
88
70
  .studio-offline-actions .ic.spin {
89
- animation: studio-offline-spin 0.9s linear infinite;
71
+ animation: spin 0.9s linear infinite;
90
72
  }
91
- .studio-offline-hint {
73
+
74
+ /* --- the first time ---------------------------------------------------------------------------- */
75
+ .connect {
76
+ max-width: 760px;
77
+ margin: 0 auto;
78
+ display: flex;
79
+ flex-direction: column;
80
+ gap: 16px;
81
+ }
82
+ .connect .header {
83
+ margin-bottom: 0;
84
+ }
85
+ /* the welcome: three short lines with an icon each */
86
+ .connect-welcome {
87
+ list-style: none;
92
88
  margin: 0;
89
+ padding: 0;
90
+ display: grid;
91
+ grid-template-columns: repeat(3, minmax(0, 1fr));
92
+ gap: 12px;
93
+ }
94
+ .connect-welcome li {
95
+ display: flex;
96
+ flex-direction: column;
97
+ gap: 2px;
98
+ padding: 14px;
99
+ border: 1px solid var(--border);
100
+ border-radius: var(--radius);
101
+ background: var(--surface);
93
102
  font-size: var(--el-text-small);
103
+ line-height: 18px;
94
104
  color: var(--text-3);
95
105
  }
96
- @keyframes studio-offline-spin {
97
- to {
98
- transform: rotate(360deg);
99
- }
106
+ .connect-welcome li b {
107
+ font-size: var(--el-text-ui);
108
+ font-weight: 500;
109
+ line-height: 20px;
110
+ color: var(--text);
111
+ }
112
+ .connect-welcome-icon {
113
+ display: grid;
114
+ place-items: center;
115
+ width: 32px;
116
+ height: 32px;
117
+ margin-bottom: 8px;
118
+ border-radius: var(--el-radius-nav);
119
+ background: var(--muted);
120
+ color: var(--text);
121
+ font-size: 18px;
122
+ }
123
+ /* the steps before the computer reports: numbered circles on the same line as the setup's */
124
+ .install-steps .setup-step.todo .setup-mark {
125
+ border-color: var(--text-2);
126
+ color: var(--text);
127
+ font-size: 13px;
128
+ font-weight: 600;
129
+ }
130
+ .install-steps .setup-text {
131
+ gap: 6px;
132
+ }
133
+ .install-steps .setup-step {
134
+ padding-bottom: 24px;
135
+ }
136
+ .install-steps .setup-step:last-child {
137
+ padding-bottom: 0;
138
+ }
139
+ .install-steps .setup-step:not(:last-child)::before {
140
+ background: var(--border-strong);
141
+ }
142
+ .connect-command {
143
+ display: flex;
144
+ align-items: center;
145
+ gap: 10px;
146
+ margin-top: 10px;
147
+ padding: 8px 8px 8px 14px;
148
+ border: 1px solid var(--border-strong);
149
+ border-radius: var(--el-radius-control);
150
+ background: var(--muted);
151
+ }
152
+ .connect-command code {
153
+ flex: 1 1 auto;
154
+ min-width: 0;
155
+ font: 400 var(--el-text-small) / 20px var(--mono);
156
+ color: var(--text);
157
+ overflow-wrap: anywhere;
158
+ }
159
+ .connect-command .button {
160
+ flex: none;
161
+ height: 32px;
162
+ padding: 0 12px;
163
+ }
164
+ .connect-does-title {
165
+ margin-top: 4px;
166
+ font-size: 12px;
167
+ font-weight: 500;
168
+ letter-spacing: 0.02em;
169
+ color: var(--text-3);
170
+ }
171
+ .connect-does {
172
+ list-style: none;
173
+ margin: 0;
174
+ padding: 0;
175
+ display: flex;
176
+ flex-direction: column;
177
+ gap: 4px;
178
+ }
179
+ .connect-does li {
180
+ display: flex;
181
+ align-items: center;
182
+ gap: 8px;
183
+ font-size: var(--el-text-small);
184
+ line-height: 18px;
185
+ color: var(--text-2);
186
+ }
187
+ .connect-does li svg {
188
+ flex: none;
189
+ color: var(--emerald);
190
+ }
191
+ /* the approval page, in miniature */
192
+ .connect-mock {
193
+ width: 100%;
194
+ max-width: 300px;
195
+ margin-top: 4px;
196
+ border: 1px solid var(--border-strong);
197
+ border-radius: var(--el-radius-control);
198
+ background: var(--bg);
199
+ overflow: hidden;
200
+ }
201
+ .connect-mock-bar {
202
+ display: flex;
203
+ gap: 5px;
204
+ padding: 8px 10px;
205
+ border-bottom: 1px solid var(--border);
206
+ background: var(--muted);
207
+ }
208
+ .connect-mock-bar i {
209
+ width: 8px;
210
+ height: 8px;
211
+ border-radius: 50%;
212
+ background: var(--border-strong);
213
+ }
214
+ .connect-mock-body {
215
+ display: flex;
216
+ flex-direction: column;
217
+ align-items: center;
218
+ gap: 8px;
219
+ padding: 14px 16px 16px;
220
+ text-align: center;
221
+ }
222
+ .connect-mock-body b {
223
+ font-size: 13px;
224
+ font-weight: 500;
225
+ color: var(--text);
226
+ }
227
+ .connect-mock-lines {
228
+ display: flex;
229
+ flex-direction: column;
230
+ gap: 4px;
231
+ width: 80%;
232
+ }
233
+ .connect-mock-lines i {
234
+ height: 5px;
235
+ border-radius: 3px;
236
+ background: var(--muted-hover);
237
+ }
238
+ .connect-mock-lines i:last-child {
239
+ width: 60%;
240
+ align-self: center;
241
+ }
242
+ .connect-mock-buttons {
243
+ display: flex;
244
+ gap: 6px;
245
+ width: 100%;
246
+ }
247
+ .connect-mock-buttons em {
248
+ flex: 1;
249
+ padding: 5px 0;
250
+ border: 1px solid transparent;
251
+ border-radius: 8px;
252
+ background: var(--action);
253
+ font-size: 11px;
254
+ font-style: normal;
255
+ font-weight: 500;
256
+ color: var(--action-text);
257
+ }
258
+ .connect-mock-buttons em.outline {
259
+ background: none;
260
+ border-color: var(--border-strong);
261
+ color: var(--text);
262
+ }
263
+ /* one line of status under a stepper */
264
+ .connect-status {
265
+ display: flex;
266
+ align-items: center;
267
+ gap: 10px;
268
+ margin: 20px 0 0;
269
+ padding: 10px 12px;
270
+ border-radius: var(--el-radius-control);
271
+ background: var(--muted);
272
+ font-size: var(--el-text-small);
273
+ line-height: 18px;
274
+ color: var(--text-2);
275
+ }
276
+ .connect-status.warning {
277
+ background: var(--warning-bg);
278
+ color: var(--warning);
279
+ }
280
+ .connect-status svg {
281
+ flex: none;
282
+ font-size: 16px;
283
+ }
284
+ .connect .panel-top {
285
+ margin-bottom: 16px;
100
286
  }
101
- @media (prefers-reduced-motion: reduce) {
102
- .studio-offline-actions .ic.spin {
103
- animation: none;
287
+ @media (max-width: 720px) {
288
+ .connect-welcome {
289
+ grid-template-columns: 1fr;
104
290
  }
105
291
  }