@oddessentials/agent-guild 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +182 -135
  2. package/package.json +1 -1
  3. package/src/manager/changelog.mjs +195 -0
  4. package/src/manager/config.mjs +1 -0
  5. package/src/manager/github.mjs +842 -0
  6. package/src/manager/main.mjs +10 -3
  7. package/src/manager/news.mjs +5 -5
  8. package/src/manager/server.mjs +70 -8
  9. package/src/manager/session-manager.mjs +32 -3
  10. package/src/manager/session.mjs +4 -1
  11. package/web/app.js +1005 -11
  12. package/web/art/art.css +374 -159
  13. package/web/art/characters/anthropic/idle.avif +0 -0
  14. package/web/art/characters/anthropic/idle.webp +0 -0
  15. package/web/art/characters/anthropic/locked.avif +0 -0
  16. package/web/art/characters/anthropic/locked.webp +0 -0
  17. package/web/art/characters/anthropic/working.avif +0 -0
  18. package/web/art/characters/anthropic/working.webp +0 -0
  19. package/web/art/characters/google/idle.avif +0 -0
  20. package/web/art/characters/google/idle.webp +0 -0
  21. package/web/art/characters/google/locked.avif +0 -0
  22. package/web/art/characters/google/locked.webp +0 -0
  23. package/web/art/characters/google/working.avif +0 -0
  24. package/web/art/characters/google/working.webp +0 -0
  25. package/web/art/characters/openai/idle.avif +0 -0
  26. package/web/art/characters/openai/idle.webp +0 -0
  27. package/web/art/characters/openai/locked.avif +0 -0
  28. package/web/art/characters/openai/locked.webp +0 -0
  29. package/web/art/characters/openai/working.avif +0 -0
  30. package/web/art/characters/openai/working.webp +0 -0
  31. package/web/art/characters/shell/idle.avif +0 -0
  32. package/web/art/characters/shell/idle.webp +0 -0
  33. package/web/art/characters/shell/locked.avif +0 -0
  34. package/web/art/characters/shell/locked.webp +0 -0
  35. package/web/art/characters/shell/working.avif +0 -0
  36. package/web/art/characters/shell/working.webp +0 -0
  37. package/web/art/characters/xai/idle.avif +0 -0
  38. package/web/art/characters/xai/idle.webp +0 -0
  39. package/web/art/characters/xai/locked.avif +0 -0
  40. package/web/art/characters/xai/locked.webp +0 -0
  41. package/web/art/characters/xai/working.avif +0 -0
  42. package/web/art/characters/xai/working.webp +0 -0
  43. package/web/art/icons/anthropic.avif +0 -0
  44. package/web/art/icons/anthropic.webp +0 -0
  45. package/web/art/icons/google.avif +0 -0
  46. package/web/art/icons/google.webp +0 -0
  47. package/web/art/icons/openai.avif +0 -0
  48. package/web/art/icons/openai.webp +0 -0
  49. package/web/art/icons/shell.avif +0 -0
  50. package/web/art/icons/shell.webp +0 -0
  51. package/web/art/icons/xai.avif +0 -0
  52. package/web/art/icons/xai.webp +0 -0
  53. package/web/art/page-light.avif +0 -0
  54. package/web/art/page-light.webp +0 -0
  55. package/web/art/page.avif +0 -0
  56. package/web/art/page.webp +0 -0
  57. package/web/art/ui/empty-state.avif +0 -0
  58. package/web/art/ui/empty-state.webp +0 -0
  59. package/web/art/ui/favicon.png +0 -0
  60. package/web/art/ui/frame-ornate.png +0 -0
  61. package/web/art/ui/guild-crest.png +0 -0
  62. package/web/fonts/OFL.txt +93 -0
  63. package/web/fonts/cinzel.woff2 +0 -0
  64. package/web/index.html +101 -15
  65. package/web/styles.css +240 -71
  66. package/web/art/characters/anthropic/idle.png +0 -0
  67. package/web/art/characters/anthropic/locked.png +0 -0
  68. package/web/art/characters/anthropic/working.png +0 -0
  69. package/web/art/characters/google/idle.png +0 -0
  70. package/web/art/characters/google/locked.png +0 -0
  71. package/web/art/characters/google/working.png +0 -0
  72. package/web/art/characters/openai/idle.png +0 -0
  73. package/web/art/characters/openai/locked.png +0 -0
  74. package/web/art/characters/openai/working.png +0 -0
  75. package/web/art/characters/shell/idle.png +0 -0
  76. package/web/art/characters/shell/locked.png +0 -0
  77. package/web/art/characters/shell/working.png +0 -0
  78. package/web/art/characters/xai/idle.png +0 -0
  79. package/web/art/characters/xai/locked.png +0 -0
  80. package/web/art/characters/xai/working.png +0 -0
  81. package/web/art/icons/anthropic.png +0 -0
  82. package/web/art/icons/google.png +0 -0
  83. package/web/art/icons/openai.png +0 -0
  84. package/web/art/icons/shell.png +0 -0
  85. package/web/art/icons/xai.png +0 -0
  86. package/web/art/page.png +0 -0
package/web/art/art.css CHANGED
@@ -1,153 +1,281 @@
1
- .level-badge { display: none; }
1
+ .brand::before {
2
+ content: ""; width: 34px; height: 34px; flex: none;
3
+ background: url("/art/ui/guild-crest.png") center / contain no-repeat;
4
+ }
5
+ .topbar { border-bottom: 1px solid; border-image: linear-gradient(90deg, transparent, color-mix(in srgb, var(--gold) 55%, transparent) 25%, color-mix(in srgb, var(--gold) 55%, transparent) 75%, transparent) 1; }
6
+ .version { background: transparent; color: var(--gold-ink); border-color: color-mix(in srgb, var(--gold) 45%, transparent); }
7
+ .version:hover { color: var(--gold-ink); border-color: var(--gold); }
8
+ .version.unread::after {
9
+ background: radial-gradient(circle at 35% 30%, #fff 0 14%, var(--accent) 48%, color-mix(in srgb, var(--accent) 55%, #000) 100%);
10
+ box-shadow: 0 0 6px color-mix(in srgb, var(--accent) 70%, transparent);
11
+ }
12
+ .connection .dot {
13
+ width: 9px; height: 9px;
14
+ background: radial-gradient(circle at 35% 30%, #fff 0 14%, var(--dot) 48%, color-mix(in srgb, var(--dot) 55%, #000) 100%);
15
+ box-shadow: 0 0 6px color-mix(in srgb, var(--dot) 70%, transparent);
16
+ }
17
+ .section-head {
18
+ padding-bottom: 9px; border-bottom: 1px solid;
19
+ border-image: linear-gradient(90deg, var(--gold), color-mix(in srgb, var(--gold) 35%, transparent) 45%, transparent 90%) 1;
20
+ }
21
+
22
+ .provider, .session-card {
23
+ --pc: #a67cf6;
24
+ --idle: image-set(url("/art/characters/shell/idle.avif") type("image/avif"), url("/art/characters/shell/idle.webp") type("image/webp"));
25
+ --working: image-set(url("/art/characters/shell/working.avif") type("image/avif"), url("/art/characters/shell/working.webp") type("image/webp"));
26
+ --locked: image-set(url("/art/characters/shell/locked.avif") type("image/avif"), url("/art/characters/shell/locked.webp") type("image/webp"));
27
+ }
28
+ .provider[data-id="anthropic"], .session-card[data-provider="anthropic"] {
29
+ --pc: #d97757;
30
+ --idle: image-set(url("/art/characters/anthropic/idle.avif") type("image/avif"), url("/art/characters/anthropic/idle.webp") type("image/webp"));
31
+ --working: image-set(url("/art/characters/anthropic/working.avif") type("image/avif"), url("/art/characters/anthropic/working.webp") type("image/webp"));
32
+ --locked: image-set(url("/art/characters/anthropic/locked.avif") type("image/avif"), url("/art/characters/anthropic/locked.webp") type("image/webp"));
33
+ }
34
+ .provider[data-id="openai"], .session-card[data-provider="openai"] {
35
+ --pc: #1fd08f;
36
+ --idle: image-set(url("/art/characters/openai/idle.avif") type("image/avif"), url("/art/characters/openai/idle.webp") type("image/webp"));
37
+ --working: image-set(url("/art/characters/openai/working.avif") type("image/avif"), url("/art/characters/openai/working.webp") type("image/webp"));
38
+ --locked: image-set(url("/art/characters/openai/locked.avif") type("image/avif"), url("/art/characters/openai/locked.webp") type("image/webp"));
39
+ }
40
+ .provider[data-id="google"], .session-card[data-provider="google"] {
41
+ --pc: #5b9cff;
42
+ --idle: image-set(url("/art/characters/google/idle.avif") type("image/avif"), url("/art/characters/google/idle.webp") type("image/webp"));
43
+ --working: image-set(url("/art/characters/google/working.avif") type("image/avif"), url("/art/characters/google/working.webp") type("image/webp"));
44
+ --locked: image-set(url("/art/characters/google/locked.avif") type("image/avif"), url("/art/characters/google/locked.webp") type("image/webp"));
45
+ }
46
+ .provider[data-id="xai"], .session-card[data-provider="xai"] {
47
+ --pc: #38d6e8;
48
+ --idle: image-set(url("/art/characters/xai/idle.avif") type("image/avif"), url("/art/characters/xai/idle.webp") type("image/webp"));
49
+ --working: image-set(url("/art/characters/xai/working.avif") type("image/avif"), url("/art/characters/xai/working.webp") type("image/webp"));
50
+ --locked: image-set(url("/art/characters/xai/locked.avif") type("image/avif"), url("/art/characters/xai/locked.webp") type("image/webp"));
51
+ }
52
+
53
+ .provider-icon[data-provider="anthropic"] { --icon: image-set(url("/art/icons/anthropic.avif") type("image/avif"), url("/art/icons/anthropic.webp") type("image/webp")); }
54
+ .provider-icon[data-provider="openai"] { --icon: image-set(url("/art/icons/openai.avif") type("image/avif"), url("/art/icons/openai.webp") type("image/webp")); }
55
+ .provider-icon[data-provider="google"] { --icon: image-set(url("/art/icons/google.avif") type("image/avif"), url("/art/icons/google.webp") type("image/webp")); }
56
+ .provider-icon[data-provider="xai"] { --icon: image-set(url("/art/icons/xai.avif") type("image/avif"), url("/art/icons/xai.webp") type("image/webp")); }
57
+ .provider-icon[data-provider="shell"] { --icon: image-set(url("/art/icons/shell.avif") type("image/avif"), url("/art/icons/shell.webp") type("image/webp")); }
58
+ .provider-icon:not(.has-image)[data-provider="anthropic"],
59
+ .provider-icon:not(.has-image)[data-provider="openai"],
60
+ .provider-icon:not(.has-image)[data-provider="google"],
61
+ .provider-icon:not(.has-image)[data-provider="xai"],
62
+ .provider-icon:not(.has-image)[data-provider="shell"] {
63
+ background: var(--icon) center / cover no-repeat; color: transparent;
64
+ }
65
+
66
+ body::before {
67
+ content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
68
+ background: var(--page-art) center bottom / cover no-repeat;
69
+ }
70
+
71
+ .provider, .session-card {
72
+ position: relative; isolation: isolate; overflow: hidden;
73
+ border-radius: 6px; padding: 18px;
74
+ transition: border-color 0.2s, box-shadow 0.2s, transform 0.3s var(--ease);
75
+ }
76
+ .provider:hover { transform: translateY(-3px); }
77
+ .session-card:hover { transform: translateY(-2px); }
78
+ .provider::before {
79
+ content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
80
+ background: linear-gradient(105deg, transparent 38%, var(--glint) 50%, transparent 62%);
81
+ transform: translateX(-110%);
82
+ }
83
+ .provider:hover::before { transform: translateX(110%); transition: transform 1s var(--ease); }
84
+ .provider .card-art::before { transition: transform 0.5s var(--ease); }
85
+ .provider:hover .card-art::before { transform: translate(calc(var(--px, 0) * -7px), calc(var(--py, 0) * -5px)) scale(1.045); }
86
+ .providers.deal > .provider { animation: deal 0.55s var(--ease) both; }
87
+ .providers.deal > .provider:nth-child(2) { animation-delay: 0.06s; }
88
+ .providers.deal > .provider:nth-child(3) { animation-delay: 0.12s; }
89
+ .providers.deal > .provider:nth-child(4) { animation-delay: 0.18s; }
90
+ .providers.deal > .provider:nth-child(5) { animation-delay: 0.24s; }
91
+ .providers.deal > .provider:nth-child(6) { animation-delay: 0.3s; }
92
+ .providers.deal > .provider:nth-child(n + 7) { animation-delay: 0.36s; }
93
+ .session-card.enter { animation: card-enter 0.5s var(--ease) both; }
94
+ .provider::after, .session-card::after {
95
+ content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
96
+ border: 44px solid transparent; border-image: url("/art/ui/frame.png") 168;
97
+ }
98
+ .card-art { position: absolute; z-index: -1; overflow: hidden; pointer-events: none; }
99
+ .card-art::before { content: ""; position: absolute; inset: 0; background: var(--idle) no-repeat; }
100
+ .provider.unavailable .card-art::before { background-image: var(--locked); }
101
+ .provider.unavailable::after {
102
+ background: url("/art/ui/padlock.png") right 16px top 14px / 30px 40px no-repeat border-box;
103
+ }
104
+ .session-card { min-height: 196px; }
105
+ .session-card .card-art::after {
106
+ content: ""; position: absolute; inset: 0; background: var(--working) no-repeat;
107
+ opacity: 0; transition: opacity 0.6s var(--ease);
108
+ }
109
+ .session-card:has(.status-pill.active) .card-art::after { opacity: 1; }
110
+ .card-aura {
111
+ position: absolute; z-index: -1; overflow: hidden; pointer-events: none;
112
+ opacity: 0; transition: opacity 0.6s var(--ease);
113
+ }
114
+ .card-aura::before {
115
+ content: ""; position: absolute; inset: -12%;
116
+ background: radial-gradient(closest-side, transparent 52%, color-mix(in srgb, var(--pc) 55%, transparent) 84%, transparent);
117
+ }
118
+ .card-aura::after {
119
+ content: ""; position: absolute; inset: 0 0 auto; height: calc(100% + 96px);
120
+ background-image:
121
+ radial-gradient(circle, color-mix(in srgb, var(--pc) 80%, #fff) 0 1.4px, transparent 2.2px),
122
+ radial-gradient(circle, color-mix(in srgb, var(--pc) 65%, #fff) 0 1px, transparent 1.8px),
123
+ radial-gradient(circle, #fff3d0 0 0.9px, transparent 1.6px);
124
+ background-size: 44px 96px, 61px 48px, 37px 96px;
125
+ background-position: 6px 10px, 30px 30px, 18px 62px;
126
+ }
127
+ .session-card:has(.status-pill.active) .card-aura { opacity: 1; }
128
+ .session-card:has(.status-pill.active) .card-aura::before { animation: aura 3.6s ease-in-out infinite alternate; }
129
+ .session-card:has(.status-pill.active) .card-aura::after { animation: sparks 3.2s linear infinite; }
130
+ body:has(#terminal-panel:not([hidden])) main :is(.card-aura, .status-pill, .agent)::before,
131
+ body:has(#terminal-panel:not([hidden])) main :is(.card-aura, .agent)::after { animation-play-state: paused; }
132
+ .session-card .card-top > .provider-icon { display: none; }
133
+ .session-card .card-top { flex-wrap: wrap; gap: 6px 8px; }
134
+ .session-card .card-title { flex-basis: 100%; }
135
+
136
+ .level-badge {
137
+ display: grid; place-items: center; position: absolute; left: 12px; bottom: 12px; z-index: 1;
138
+ width: 46px; height: 46px; padding-top: 1px;
139
+ background: url("/art/ui/level-medallion.png") center / contain no-repeat;
140
+ font: 700 1.05rem var(--font-display); color: #f6dea6;
141
+ text-shadow: 0 1px 2px #000, 0 0 6px rgba(0, 0, 0, 0.8);
142
+ }
143
+ .level-badge.level-up { animation: level-up 1.2s var(--ease); }
144
+ .agent.summon { animation: summon 0.6s var(--ease) both; }
145
+
146
+ #empty { padding: 4px 16px 8px; text-align: center; }
147
+ #empty::before {
148
+ content: ""; display: block; width: 190px; height: 206px; margin: 0 auto 12px;
149
+ background: image-set(url("/art/ui/empty-state.avif") type("image/avif"), url("/art/ui/empty-state.webp") type("image/webp")) center / contain no-repeat;
150
+ filter: drop-shadow(0 12px 14px var(--empty-shadow));
151
+ }
152
+
153
+ body:has(#app[hidden]):has(#auth[hidden]):has(#stopped[hidden])::after {
154
+ content: ""; position: fixed; left: 50%; top: 50%; width: 72px; height: 72px; margin: -36px 0 0 -36px;
155
+ background: url("/art/ui/guild-crest.png") center / contain no-repeat;
156
+ animation: splash 1.4s ease-in-out infinite alternate;
157
+ }
158
+
159
+ .agent {
160
+ border-width: 1px; border-color: var(--fc); place-items: end end; padding: 0 3px 1px 0;
161
+ background: #0e1016 center / 118% auto no-repeat;
162
+ color: #fff; font-size: 0.62rem; text-shadow: 0 0 3px #000, 0 1px 2px #000;
163
+ box-shadow: 0 0 10px color-mix(in srgb, var(--fc) 45%, transparent);
164
+ }
165
+ .session-card .agent { width: 34px; height: 34px; }
166
+ .agent.working::after { border-color: var(--fc); }
167
+ .agent[data-familiar="flame"] { --fc: #f08a3c; background-image: url("/art/familiars/flame.png"); }
168
+ .agent[data-familiar="leaf"] { --fc: #5fd068; background-image: url("/art/familiars/leaf.png"); }
169
+ .agent[data-familiar="night"] { --fc: #a66cf0; background-image: url("/art/familiars/night.png"); }
170
+ .agent[data-familiar="aether"] { --fc: #7cc8ff; background-image: url("/art/familiars/aether.png"); }
171
+
172
+ .meter-label { padding-left: 18px; background: url("/art/ui/gem-vitality.png") left center / 14px auto no-repeat; }
173
+ .meter + .meter .meter-label { background-image: url("/art/ui/gem-mana.png"); }
174
+ .meter-bar, .stat-bar { height: 7px; }
175
+ .model-stats-head { color: var(--gold-ink); }
176
+ .stat-tier { border-radius: 3px; font-family: var(--font-display); }
177
+ .tier-s .stat-tier { color: #2b1b06; background: linear-gradient(180deg, #fbe9bd 0%, #e2b867 55%, #a97b35 100%); }
178
+
179
+ .tip {
180
+ background: #14120f; color: #ece4d1; border: 1px solid #4a3d25;
181
+ box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.06), 0 10px 28px rgba(0, 0, 0, 0.45);
182
+ }
183
+ .tip strong { color: #f0cf8a; font-family: var(--font-display); }
184
+
185
+ .models::after, .auth::after {
186
+ content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
187
+ border: 54px solid transparent; border-image: url("/art/ui/frame-ornate.png") 232;
188
+ }
189
+ .models-bar { padding: 30px 36px 12px; }
190
+ .models-body { margin: 0 24px; padding: 0 12px 14px; }
191
+ .models-source { padding: 10px 36px 30px; }
192
+ .history-tools { padding: 10px 36px 0; }
193
+ .history-form { padding: 10px 36px 30px; }
194
+ .github-accounts { padding: 10px 36px; }
195
+ .model-group h4, .news-day, .changelog-type { font-family: var(--font-display); letter-spacing: 0.08em; color: var(--gold-ink); }
196
+ .news-bar { padding: 16px 18px 12px; }
197
+ .news-filters, .news-status { padding-left: 18px; padding-right: 18px; }
198
+ .news-body { padding: 0 18px 14px; }
199
+ .news-row { transition: background-color 0.15s; }
200
+ .news-row:hover { background: color-mix(in srgb, var(--gold) 7%, transparent); }
201
+ .news-row:first-child { border-radius: 6px 6px 0 0; }
202
+ .news-row:last-child { border-radius: 0 0 6px 6px; }
203
+
204
+ .terminal-panel { border-radius: 6px; }
205
+ .panel-bar { padding: 10px 14px; border-bottom: 1px solid; border-image: linear-gradient(90deg, transparent, var(--gold) 20%, var(--gold) 80%, transparent) 1; }
206
+
207
+ .auth { position: relative; border-radius: 6px; padding: 40px 44px; }
208
+ .auth pre { color: var(--gold-ink); }
2
209
 
3
- /* The guild look is the dark theme. The rules below nest under the theme
4
- attribute that theme.js sets on <html>, so they apply whether the user
5
- chose dark or the system did. :where() keeps their specificity as it was
6
- inside the media query, so styles.css still loses to them only on order. */
7
210
  :where(:root[data-theme="dark"]) {
8
- --gold: #e8c47c;
9
211
  --gold-dim: #8a6d3b;
10
212
  --card-bg: rgba(18, 20, 26, 0.9);
213
+ --glint: rgba(255, 238, 200, 0.1);
214
+ --empty-shadow: rgba(0, 0, 0, 0.55);
215
+ --page-art: image-set(url("/art/page.avif") type("image/avif"), url("/art/page.webp") type("image/webp"));
11
216
 
12
- .provider, .session-card {
13
- --pc: #a67cf6;
14
- --idle: url("/art/characters/shell/idle.png");
15
- --working: url("/art/characters/shell/working.png");
16
- --locked: url("/art/characters/shell/locked.png");
17
- }
18
- .provider[data-id="anthropic"], .session-card[data-provider="anthropic"] {
19
- --pc: #d97757;
20
- --idle: url("/art/characters/anthropic/idle.png");
21
- --working: url("/art/characters/anthropic/working.png");
22
- --locked: url("/art/characters/anthropic/locked.png");
23
- }
24
- .provider[data-id="openai"], .session-card[data-provider="openai"] {
25
- --pc: #1fd08f;
26
- --idle: url("/art/characters/openai/idle.png");
27
- --working: url("/art/characters/openai/working.png");
28
- --locked: url("/art/characters/openai/locked.png");
29
- }
30
- .provider[data-id="google"], .session-card[data-provider="google"] {
31
- --pc: #5b9cff;
32
- --idle: url("/art/characters/google/idle.png");
33
- --working: url("/art/characters/google/working.png");
34
- --locked: url("/art/characters/google/locked.png");
35
- }
36
- .provider[data-id="xai"], .session-card[data-provider="xai"] {
37
- --pc: #38d6e8;
38
- --idle: url("/art/characters/xai/idle.png");
39
- --working: url("/art/characters/xai/working.png");
40
- --locked: url("/art/characters/xai/locked.png");
41
- }
42
-
43
- .provider-icon[data-provider="anthropic"] { --icon: url("/art/icons/anthropic.png"); }
44
- .provider-icon[data-provider="openai"] { --icon: url("/art/icons/openai.png"); }
45
- .provider-icon[data-provider="google"] { --icon: url("/art/icons/google.png"); }
46
- .provider-icon[data-provider="xai"] { --icon: url("/art/icons/xai.png"); }
47
- .provider-icon[data-provider="shell"] { --icon: url("/art/icons/shell.png"); }
48
- .provider-icon:not(.has-image)[data-provider="anthropic"],
49
- .provider-icon:not(.has-image)[data-provider="openai"],
50
- .provider-icon:not(.has-image)[data-provider="google"],
51
- .provider-icon:not(.has-image)[data-provider="xai"],
52
- .provider-icon:not(.has-image)[data-provider="shell"] {
53
- background: var(--icon) center / cover no-repeat; color: transparent;
54
- }
55
-
56
- body { background: #0b0c10 url("/art/page.png") center bottom / cover fixed; }
57
- .topbar { background: rgba(12, 13, 17, 0.88); backdrop-filter: blur(6px); border-bottom-color: #2a2418; }
58
- .brand-mark { display: none; }
59
- .brand::before {
60
- content: ""; width: 34px; height: 34px; flex: none;
61
- background: url("/art/ui/guild-crest.png") center / contain no-repeat;
62
- }
63
- h1, h2 { font-family: "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif; letter-spacing: 0.01em; }
64
- h1 {
65
- font-size: 1.3rem; font-weight: 600; color: var(--gold);
66
- background: linear-gradient(180deg, #fbe9bd 0%, #e2b867 55%, #a97b35 100%);
67
- -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
68
- }
69
- h2 { color: #f1e2c2; font-size: 1.15rem; font-weight: 600; }
217
+ body { background: #0b0c10; }
218
+ .topbar { background: rgba(12, 13, 17, 0.88); backdrop-filter: blur(6px); }
70
219
 
71
220
  .provider, .session-card {
72
- position: relative; isolation: isolate; overflow: hidden;
73
- border-radius: 6px; padding: 18px;
74
221
  background: var(--card-bg);
75
222
  border: 1px solid color-mix(in srgb, var(--pc) 35%, #2a303b);
76
223
  box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.06), 0 8px 24px rgba(0, 0, 0, 0.35);
77
- transition: border-color 0.2s, box-shadow 0.2s;
78
224
  }
79
225
  .provider:hover, .session-card:hover {
80
226
  border-color: color-mix(in srgb, var(--pc) 70%, #2a303b);
81
227
  box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.1), 0 0 22px color-mix(in srgb, var(--pc) 22%, transparent);
82
228
  }
83
- .provider::before, .session-card::before {
84
- content: ""; position: absolute; z-index: -1; pointer-events: none;
85
- background-repeat: no-repeat; background-size: cover; background-position: center top;
86
- }
87
- .provider::after, .session-card::after {
88
- content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
89
- border: 44px solid transparent; border-image: url("/art/ui/frame.png") 168;
90
- }
91
229
 
92
- .provider { padding-top: 188px; align-content: start; }
93
- .provider::before {
230
+ .provider { padding-top: 188px; }
231
+ .provider .card-art {
94
232
  inset: 0 0 auto 0; height: 250px;
95
- background-image: var(--idle);
96
- -webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
97
- mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
233
+ mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
98
234
  }
99
- .provider.unavailable::before { background-image: var(--locked); }
235
+ .provider .card-art::before { background-size: cover; background-position: center top; }
100
236
  .provider.unavailable { border-color: #2a2d33; }
101
- .provider.unavailable::after {
102
- background: url("/art/ui/padlock.png") right 16px top 14px / 30px 40px no-repeat border-box;
103
- }
104
237
  .provider .vendor { color: #f3ead8; }
105
238
 
106
- .meter-label { padding-left: 18px; background: url("/art/ui/gem-vitality.png") left center / 14px auto no-repeat; }
107
- .meter + .meter .meter-label { background-image: url("/art/ui/gem-mana.png"); }
108
- .meter-bar { height: 7px; background: #0c0e12; box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.18); }
239
+ .session-card { padding-left: 152px; }
240
+ .session-card .card-art, .session-card .card-aura {
241
+ inset: 0 auto 0 0; width: 168px;
242
+ mask-image: linear-gradient(to right, #000 62%, transparent 100%);
243
+ }
244
+ .session-card .card-aura {
245
+ mask-image: linear-gradient(to right, #000 62%, transparent 100%), linear-gradient(transparent, #000 22%, #000 78%, transparent);
246
+ mask-composite: intersect;
247
+ }
248
+ .session-card .card-art::before, .session-card .card-art::after { background-size: 168px auto; background-position: center top; }
249
+ .session-card:has(.status-pill.active) {
250
+ border-color: color-mix(in srgb, var(--pc) 75%, #2a303b);
251
+ box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.1), 0 0 26px color-mix(in srgb, var(--pc) 28%, transparent);
252
+ }
253
+ .session-card.exited .card-art { filter: grayscale(1) brightness(0.7); }
254
+
255
+ .meter-bar, .stat-bar { background: #0c0e12; box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.18); }
109
256
  .meter-fill { background: linear-gradient(90deg, #1f9d5c, #52e08f); box-shadow: 0 0 8px rgba(82, 224, 143, 0.55); }
110
257
  .meter + .meter .meter-fill { background: linear-gradient(90deg, #2a62c9, #5ba6ff); box-shadow: 0 0 8px rgba(91, 166, 255, 0.55); }
111
258
  .meter.low .meter-fill { background: var(--warn); box-shadow: 0 0 8px rgba(224, 168, 74, 0.5); }
112
259
  .meter.empty .meter-fill { background: var(--danger); box-shadow: 0 0 8px rgba(239, 107, 102, 0.5); }
113
260
 
114
- .model-stats-head { color: var(--gold); }
115
261
  .info { color: #b89a5e; }
116
262
  .info:hover, .info:focus-visible { color: var(--gold); }
117
- .tip {
118
- background: #12141a; color: #e9e2cf; border: 1px solid #4a3d25;
119
- box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.06), 0 10px 28px rgba(0, 0, 0, 0.6);
120
- }
121
- .tip strong { color: var(--gold); font-family: "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif; }
122
- .stat-bar { height: 7px; background: #0c0e12; box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.18); }
123
263
  .stat-fill {
124
264
  background: linear-gradient(90deg, color-mix(in srgb, var(--tier) 55%, #000), var(--tier));
125
265
  box-shadow: 0 0 8px color-mix(in srgb, var(--tier) 50%, transparent);
126
266
  }
127
267
  .stat-tier {
128
- border-radius: 3px; font-family: "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
129
268
  background: linear-gradient(color-mix(in srgb, var(--tier) 34%, #1a1d26), #0d0f15);
130
269
  border-color: color-mix(in srgb, var(--tier) 70%, #000);
131
270
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 0 6px color-mix(in srgb, var(--tier) 30%, transparent);
132
271
  }
133
- .tier-s .stat-tier {
134
- color: #2b1b06; border-color: #f6dea6;
135
- background: linear-gradient(180deg, #fbe9bd 0%, #e2b867 55%, #a97b35 100%);
136
- box-shadow: 0 0 10px rgba(232, 196, 124, 0.6);
137
- }
272
+ .tier-s .stat-tier { border-color: #f6dea6; box-shadow: 0 0 10px rgba(232, 196, 124, 0.6); }
138
273
 
139
274
  .models {
140
275
  border-radius: 6px; border-color: #4a3d25; background: #12141a;
141
276
  box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.06), 0 24px 60px rgba(0, 0, 0, 0.6);
142
277
  }
143
- .models::after {
144
- content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
145
- border: 44px solid transparent; border-image: url("/art/ui/frame.png") 168;
146
- }
147
278
  .models::backdrop { background: rgba(5, 6, 9, 0.72); }
148
- .models-bar { padding: 20px 24px 12px; }
149
- .models-body { padding: 0 24px 14px; }
150
- .models-source { padding: 10px 24px 20px; }
151
279
  .models-bar, .models-source, .model-columns, .model { border-color: #2a2418; }
152
280
  .model-columns { background: #12141a; }
153
281
  .model-toggle:hover { background: rgba(232, 196, 124, 0.06); }
@@ -159,7 +287,7 @@
159
287
  border-radius: 6px; border-color: #4a3d25; background: var(--card-bg);
160
288
  box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.06), 0 8px 24px rgba(0, 0, 0, 0.35);
161
289
  }
162
- .news-row + .news-row, .news-bar, .news-filters, .news-item, .news-status { border-color: #2a2418; }
290
+ .news-row + .news-row, .news-bar, .news-filters, .news-item, .news-status, .changelog-release + .changelog-release { border-color: #2a2418; }
163
291
  .news-link { color: #f3ead8; }
164
292
  a.news-link:visited { color: var(--muted); }
165
293
  .news-panel {
@@ -167,86 +295,173 @@
167
295
  box-shadow: inset 1px 0 0 rgba(232, 196, 124, 0.08), -24px 0 60px rgba(0, 0, 0, 0.6);
168
296
  }
169
297
  .news-panel::backdrop { background: rgba(5, 6, 9, 0.72); }
170
- .news-bar { padding: 16px 18px 12px; }
171
- .news-filters, .news-status { padding-left: 18px; padding-right: 18px; }
172
- .news-body { padding: 0 18px 14px; }
173
298
  .news-day { background: #12141a; color: #c9ab72; }
299
+ .changelog-type { color: #c9ab72; }
174
300
  .news-filter { border-color: #4a3d25; background: rgba(0, 0, 0, 0.35); }
175
301
  .news-filter:hover { border-color: var(--gold-dim); }
176
- .news-filter[aria-pressed="true"] { border-color: #b8955a; color: #fff; background: linear-gradient(#8e8ef6, #6262d6); }
177
-
178
- .session-card { padding-left: 152px; min-height: 196px; }
179
- .session-card::before {
180
- inset: 0 auto 0 0; width: 168px; background-size: 168px auto;
181
- background-image: var(--idle);
182
- -webkit-mask-image: linear-gradient(to right, #000 62%, transparent 100%);
183
- mask-image: linear-gradient(to right, #000 62%, transparent 100%);
184
- }
185
- .session-card:has(.status-pill.active)::before { background-image: var(--working); }
186
- .session-card:has(.status-pill.active) {
187
- border-color: color-mix(in srgb, var(--pc) 75%, #2a303b);
188
- box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.1), 0 0 26px color-mix(in srgb, var(--pc) 28%, transparent);
189
- }
190
- .session-card.exited::before { filter: grayscale(1) brightness(0.7); }
191
- .session-card .card-top > .provider-icon { display: none; }
192
- .session-card .card-top { flex-wrap: wrap; gap: 6px 8px; }
193
- .session-card .card-title { flex-basis: 100%; }
194
-
195
- .level-badge {
196
- display: grid; place-items: center; position: absolute; left: 12px; bottom: 12px; z-index: 1;
197
- width: 46px; height: 46px; padding-top: 1px;
198
- background: url("/art/ui/level-medallion.png") center / contain no-repeat;
199
- font: 700 1.05rem "Palatino Linotype", Palatino, Georgia, serif; color: #f6dea6;
200
- text-shadow: 0 1px 2px #000, 0 0 6px rgba(0, 0, 0, 0.8);
201
- }
202
-
203
- .session-card .agent {
204
- width: 34px; height: 34px; border-width: 1px; border-color: var(--fc);
205
- place-items: end end; padding: 0 3px 1px 0;
206
- background: #0e1016 center / 118% auto no-repeat;
207
- color: #fff; font-size: 0.62rem; text-shadow: 0 0 3px #000, 0 1px 2px #000;
208
- box-shadow: 0 0 10px color-mix(in srgb, var(--fc) 45%, transparent);
209
- }
210
- .session-card .agent.working::after { border-color: var(--fc); }
211
- .session-card .agent[data-familiar="flame"] { --fc: #f08a3c; background-image: url("/art/familiars/flame.png"); }
212
- .session-card .agent[data-familiar="leaf"] { --fc: #5fd068; background-image: url("/art/familiars/leaf.png"); }
213
- .session-card .agent[data-familiar="night"] { --fc: #a66cf0; background-image: url("/art/familiars/night.png"); }
214
- .session-card .agent[data-familiar="aether"] { --fc: #7cc8ff; background-image: url("/art/familiars/aether.png"); }
302
+ .news-filter[aria-pressed="true"] { border-color: #b8955a; color: #fff; background: #5b40d0 linear-gradient(#7a5fe6, #4f34bf); }
215
303
 
216
304
  .status-pill { background: rgba(0, 0, 0, 0.45); border: 1px solid #4a3d25; }
305
+ .status-pill.active { border-color: color-mix(in srgb, var(--ok) 55%, transparent); box-shadow: 0 0 10px rgba(76, 195, 138, 0.25); }
217
306
  .model-pill { border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent); }
218
307
  .provider .tier { background: rgba(0, 0, 0, 0.45); border-color: #4a3d25; color: var(--gold); }
219
308
 
220
309
  .btn {
221
- border-radius: 6px; border-color: #4a3d25;
310
+ border-color: #4a3d25;
222
311
  background: linear-gradient(#242834, #171a22);
223
312
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 1px 2px rgba(0, 0, 0, 0.5);
224
313
  }
225
314
  .btn:hover { border-color: var(--gold-dim); }
226
315
  .btn.primary {
227
316
  border-color: #b8955a; color: #fff; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.35);
228
- background: linear-gradient(#8e8ef6, #6262d6);
229
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 2px 8px rgba(124, 124, 240, 0.25);
317
+ background: #5b40d0 linear-gradient(#7a5fe6, #4f34bf);
318
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), 0 2px 10px rgba(91, 64, 208, 0.35);
230
319
  }
231
320
  .btn.primary:hover { border-color: var(--gold); filter: brightness(1.08); }
232
321
  .btn.danger { color: #ff9a94; }
233
322
  .btn.danger:hover { border-color: #b8524d; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 0 12px rgba(239, 107, 102, 0.3); }
234
323
  .cwd input, .auth input { border-color: #4a3d25; background: rgba(12, 13, 17, 0.8); }
235
324
  .auth {
236
- border-radius: 6px; padding: 28px; background: var(--card-bg);
325
+ background: var(--card-bg);
237
326
  border: 1px solid #4a3d25; box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.06), 0 8px 24px rgba(0, 0, 0, 0.35);
238
327
  }
239
- .auth pre { background: rgba(12, 13, 17, 0.8); border: 1px solid #2a2418; color: var(--gold); }
328
+ .auth pre { background: rgba(12, 13, 17, 0.8); border: 1px solid #2a2418; }
240
329
  .notice h2 { color: #ff9a94; }
241
330
  .notice.stopping h2 { color: var(--gold); }
242
- .status-pill.active { border-color: color-mix(in srgb, var(--ok) 55%, transparent); box-shadow: 0 0 10px rgba(76, 195, 138, 0.25); }
331
+ .terminal-panel { border-color: #4a3d25; box-shadow: inset 0 0 0 1px rgba(232, 196, 124, 0.06), 0 24px 60px rgba(0, 0, 0, 0.6); }
332
+ .panel-bar { background: linear-gradient(#1a1d25, #121419); }
243
333
 
244
334
  @media (max-width: 640px) {
245
335
  .session-card { padding-left: 118px; }
246
- .session-card::before { width: 132px; background-size: 132px auto; }
336
+ .session-card .card-art, .session-card .card-aura { width: 132px; }
337
+ .session-card .card-art::before, .session-card .card-art::after { background-size: 132px auto; }
338
+ }
339
+ }
340
+
341
+ :where(:root[data-theme="light"]) {
342
+ --page-art: image-set(url("/art/page-light.avif") type("image/avif"), url("/art/page-light.webp") type("image/webp"));
343
+ --glint: rgba(255, 244, 214, 0.26);
344
+ --empty-shadow: rgba(70, 48, 12, 0.28);
345
+ --card-shadow: inset 0 1px 0 #fff, 0 1px 2px rgba(70, 48, 12, 0.08), 0 10px 26px rgba(70, 48, 12, 0.1);
346
+
347
+ body { background: #eee5d4; }
348
+ .topbar { background: rgba(255, 252, 246, 0.9); backdrop-filter: blur(6px); }
349
+
350
+ .provider, .session-card {
351
+ background: var(--surface);
352
+ border: 1px solid #e4d6b6;
353
+ box-shadow: var(--card-shadow);
354
+ }
355
+ .provider:hover, .session-card:hover {
356
+ border-color: color-mix(in srgb, var(--pc) 40%, #d7c49b);
357
+ box-shadow: inset 0 1px 0 #fff, 0 2px 4px rgba(70, 48, 12, 0.08), 0 14px 34px rgba(70, 48, 12, 0.15);
247
358
  }
359
+ .card-art {
360
+ border-radius: 3px;
361
+ background: radial-gradient(85% 70% at 50% 34%, color-mix(in srgb, var(--pc) 46%, #1d1726) 0%, #120f17 74%);
362
+ box-shadow: inset 0 0 0 1px rgba(255, 233, 186, 0.3), 0 0 0 1px #c9a45e, 0 1px 3px rgba(70, 48, 12, 0.3);
363
+ }
364
+ .provider .card-art::after {
365
+ content: ""; position: absolute; inset: 0;
366
+ background: linear-gradient(transparent 58%, rgba(10, 8, 14, 0.45));
367
+ box-shadow: inset 0 0 18px rgba(0, 0, 0, 0.55);
368
+ }
369
+
370
+ .provider { padding-top: 242px; }
371
+ .provider .card-art { inset: 14px 14px auto; height: 214px; }
372
+ .provider .card-art::before { background-size: 112% auto; background-position: 50% 4%; }
373
+ .provider.unavailable .card-art { background: radial-gradient(85% 70% at 50% 34%, #45434a 0%, #17161a 74%); }
374
+ .provider-icon:not(.has-image)[data-provider] { box-shadow: 0 0 0 1px #c9a45e, 0 1px 3px rgba(70, 48, 12, 0.3); }
375
+
376
+ .session-card { padding-left: 160px; }
377
+ .session-card .card-art, .session-card .card-aura { inset: 14px auto 14px 14px; width: 132px; border-radius: 3px; }
378
+ .session-card .card-aura { mask-image: linear-gradient(transparent, #000 22%, #000 78%, transparent); }
379
+ .session-card .card-art::before, .session-card .card-art::after { background-size: 160% auto; background-position: 50% 8%; }
380
+ .session-card:has(.status-pill.active) {
381
+ border-color: color-mix(in srgb, var(--pc) 55%, #d7c49b);
382
+ box-shadow: inset 0 1px 0 #fff, 0 2px 4px rgba(70, 48, 12, 0.08), 0 12px 30px color-mix(in srgb, var(--pc) 22%, rgba(70, 48, 12, 0.12));
383
+ }
384
+ .session-card.exited .card-art { filter: grayscale(1) brightness(0.9); }
385
+
386
+ .meter-bar, .stat-bar { background: #ebe2cd; box-shadow: inset 0 1px 2px rgba(70, 48, 12, 0.2); }
387
+ .meter-fill { background: linear-gradient(90deg, #1b7a45, #31a868); }
388
+ .meter + .meter .meter-fill { background: linear-gradient(90deg, #2a57b0, #4382e2); }
389
+ .meter.low .meter-fill { background: linear-gradient(90deg, #9a5f00, #d08a14); }
390
+ .meter.empty .meter-fill { background: linear-gradient(90deg, #a8302b, #d24a43); }
391
+ .stat-fill { background: linear-gradient(90deg, color-mix(in srgb, var(--tier) 72%, #3a2a10), var(--tier)); }
392
+ .stat-tier {
393
+ background: linear-gradient(color-mix(in srgb, var(--tier) 10%, #fffdf8), color-mix(in srgb, var(--tier) 24%, #fffdf8));
394
+ border-color: color-mix(in srgb, var(--tier) 55%, #fff);
395
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
396
+ }
397
+ .tier-s .stat-tier { color: #3a2604; border-color: #b8892f; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), 0 1px 3px rgba(150, 100, 20, 0.35); }
398
+
399
+ .models { border-color: #d8c597; box-shadow: 0 24px 60px rgba(40, 28, 8, 0.28); }
400
+ .models::backdrop { background: rgba(40, 30, 14, 0.38); }
401
+ .model-toggle:hover { background: #f6eedd; }
402
+
403
+ .news-latest { border-color: #e4d6b6; box-shadow: 0 1px 2px rgba(70, 48, 12, 0.08), 0 10px 26px rgba(70, 48, 12, 0.08); }
404
+ .news-panel { border-left-color: #e2d3b2; box-shadow: -24px 0 60px rgba(40, 28, 8, 0.22); }
405
+ .news-panel::backdrop { background: rgba(40, 30, 14, 0.3); }
406
+
407
+ .status-pill { background: #f6efe0; border: 1px solid #e2d3b2; }
408
+ .status-pill.active { border-color: color-mix(in srgb, var(--ok) 40%, transparent); background: color-mix(in srgb, var(--ok) 8%, #fffcf6); }
409
+ .status-pill.exited { border-color: color-mix(in srgb, var(--danger) 35%, transparent); background: color-mix(in srgb, var(--danger) 6%, #fffcf6); }
410
+ .model-pill { border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); background: color-mix(in srgb, var(--accent) 9%, #fffcf6); }
411
+ .provider .tier { color: #5c3f08; border-color: #d4b06a; background: linear-gradient(#fbf0d2, #f1dfb2); }
248
412
 
249
- @media (prefers-reduced-motion: reduce) {
250
- .provider, .session-card { transition: none; }
413
+ .btn {
414
+ border-color: #d8c597;
415
+ background: linear-gradient(#fffefa, #f2e9d6);
416
+ box-shadow: inset 0 1px 0 #fff, 0 1px 2px rgba(70, 48, 12, 0.12);
417
+ }
418
+ .btn:hover { border-color: #b8892f; }
419
+ .btn.primary {
420
+ border-color: #8f6d2a; color: #fff; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);
421
+ background: #5a3fc0 linear-gradient(#6c51d6, #4a30ad);
422
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 2px 6px rgba(74, 48, 173, 0.28);
423
+ }
424
+ .btn.primary:hover { border-color: #b8892f; filter: brightness(1.08); }
425
+ .btn.danger:hover { border-color: #c4625d; }
426
+ .cwd input, .auth input, .history-tools input[type="search"], .history-form input {
427
+ border-color: #dccba5; background: #fffdf8; box-shadow: inset 0 1px 2px rgba(70, 48, 12, 0.06);
428
+ }
429
+ .auth { border-color: #e4d6b6; box-shadow: var(--card-shadow); }
430
+ .auth pre { background: #f6efe0; border: 1px solid #e4d6b6; }
431
+ .terminal-panel { border-color: #c9b07a; box-shadow: 0 24px 60px rgba(40, 28, 8, 0.35); }
432
+ .panel-bar { background: linear-gradient(#fffdf8, #f3ead7); }
433
+
434
+ @media (max-width: 640px) {
435
+ .session-card { padding-left: 140px; }
436
+ .session-card .card-art, .session-card .card-aura { width: 112px; }
437
+ .session-card .card-art::before, .session-card .card-art::after { background-size: 165% auto; }
251
438
  }
252
439
  }
440
+
441
+ @media (max-width: 640px) {
442
+ .models::after, .auth::after { border-width: 40px; }
443
+ .models-bar { padding: 24px 26px 10px; }
444
+ .models-body { margin: 0 16px; padding: 0 10px 12px; }
445
+ .models-source { padding: 10px 26px 24px; }
446
+ .history-tools { padding: 10px 26px 0; }
447
+ .history-form { padding: 10px 26px 24px; }
448
+ .github-accounts { padding: 10px 26px; }
449
+ .auth { padding: 32px 30px; }
450
+ }
451
+
452
+ @keyframes deal { from { opacity: 0; transform: translateY(16px) rotate(-1.2deg) scale(0.97); } }
453
+ @keyframes card-enter { from { opacity: 0; transform: translateY(10px) scale(0.98); } }
454
+ @keyframes aura { from { opacity: 0.5; transform: scale(0.97); } to { opacity: 1; transform: scale(1.03); } }
455
+ @keyframes sparks { to { transform: translateY(-96px); } }
456
+ @keyframes level-up { 30% { transform: scale(1.28); filter: brightness(1.5) drop-shadow(0 0 8px #f6dea6); } }
457
+ @keyframes summon { from { opacity: 0; transform: scale(0.3); } 60% { opacity: 1; transform: scale(1.15); } }
458
+ @keyframes splash { from { opacity: 0.3; transform: scale(0.95); } to { opacity: 0.85; transform: scale(1.03); } }
459
+
460
+ @media (prefers-reduced-motion: reduce) {
461
+ .provider, .session-card, .card-aura, .session-card .card-art::after, .provider .card-art::before { transition: none; }
462
+ .provider:hover, .session-card:hover, .provider:hover .card-art::before { transform: none; }
463
+ .provider::before { display: none; }
464
+ .providers.deal > .provider, .session-card.enter, .level-badge.level-up, .agent.summon,
465
+ .session-card:has(.status-pill.active) .card-aura::before, .session-card:has(.status-pill.active) .card-aura::after,
466
+ body:has(#app[hidden]):has(#auth[hidden]):has(#stopped[hidden])::after { animation: none; }
467
+ }