something-x-dev 1.8.0.dev23__tar.gz → 1.8.0.dev24__tar.gz

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 (46) hide show
  1. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/PKG-INFO +1 -1
  2. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/nothing_app/_version.py +2 -2
  3. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/nothing_app/data/style.css +213 -89
  4. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/nothing_app/pages/device.py +61 -21
  5. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/nothing_app/pages/home.py +2 -0
  6. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/something_x_dev.egg-info/PKG-INFO +1 -1
  7. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/.github/CODEOWNERS +0 -0
  8. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/.github/workflows/ci.yml +0 -0
  9. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/.github/workflows/release-dev.yml +0 -0
  10. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/.github/workflows/release.yml +0 -0
  11. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/.gitignore +0 -0
  12. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/DEVICES.md +0 -0
  13. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/LICENSE +0 -0
  14. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/PKGBUILD +0 -0
  15. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/README.md +0 -0
  16. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/ROADMAP.md +0 -0
  17. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/cliff.toml +0 -0
  18. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/docs/RELEASING.md +0 -0
  19. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/docs/docs.html +0 -0
  20. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/docs/index.html +0 -0
  21. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/flake.nix +0 -0
  22. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/nothing_app/__init__.py +0 -0
  23. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/nothing_app/application.py +0 -0
  24. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/nothing_app/bluetooth.py +0 -0
  25. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/nothing_app/data/__init__.py +0 -0
  26. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/nothing_app/data/com.something.x.omarchy.desktop +0 -0
  27. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/nothing_app/pages/__init__.py +0 -0
  28. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/nothing_app/profiles.py +0 -0
  29. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/nothing_app/protocol.py +0 -0
  30. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/nothing_app/splash.py +0 -0
  31. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/nothing_app/tray.py +0 -0
  32. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/nothing_app/window.py +0 -0
  33. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/pyproject.toml +0 -0
  34. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/setup.cfg +0 -0
  35. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/something_x_dev.egg-info/SOURCES.txt +0 -0
  36. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/something_x_dev.egg-info/dependency_links.txt +0 -0
  37. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/something_x_dev.egg-info/entry_points.txt +0 -0
  38. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/something_x_dev.egg-info/requires.txt +0 -0
  39. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/something_x_dev.egg-info/top_level.txt +0 -0
  40. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/somethingx +0 -0
  41. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/tests/__init__.py +0 -0
  42. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/tests/conftest.py +0 -0
  43. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/tests/test_bluetooth.py +0 -0
  44. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/tests/test_crc.py +0 -0
  45. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/tests/test_profiles.py +0 -0
  46. {something_x_dev-1.8.0.dev23 → something_x_dev-1.8.0.dev24}/tests/test_protocol.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: something-x-dev
3
- Version: 1.8.0.dev23
3
+ Version: 1.8.0.dev24
4
4
  Summary: Something X device manager for Omarchy / Linux
5
5
  Author: Raphael
6
6
  License: MIT
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '1.8.0.dev23'
22
- __version_tuple__ = version_tuple = (1, 8, 0, 'dev23')
21
+ __version__ = version = '1.8.0.dev24'
22
+ __version_tuple__ = version_tuple = (1, 8, 0, 'dev24')
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -1,12 +1,12 @@
1
1
  @define-color window_bg_color #000000;
2
2
  @define-color window_fg_color #ffffff;
3
- @define-color view_bg_color #000000;
3
+ @define-color view_bg_color #030308;
4
4
  @define-color view_fg_color #ffffff;
5
- @define-color headerbar_bg_color #000000;
5
+ @define-color headerbar_bg_color #080812;
6
6
  @define-color headerbar_fg_color #ffffff;
7
- @define-color headerbar_border_color rgba(255,255,255,0.07);
8
- @define-color headerbar_backdrop_color #000000;
9
- @define-color card_bg_color rgba(255,255,255,0.04);
7
+ @define-color headerbar_border_color rgba(255,255,255,0.09);
8
+ @define-color headerbar_backdrop_color #030308;
9
+ @define-color card_bg_color rgba(255,255,255,0.045);
10
10
  @define-color card_fg_color #ffffff;
11
11
  @define-color accent_bg_color #e83535;
12
12
  @define-color accent_fg_color #ffffff;
@@ -16,6 +16,47 @@
16
16
  @define-color success_bg_color #8fdf72;
17
17
  @define-color success_fg_color #0a0a0a;
18
18
 
19
+ /* ── Keyframe Animations ─────────────────────────────────────────────────── */
20
+
21
+ @keyframes dot-pulse {
22
+ 0%, 100% { box-shadow: 0 0 6px rgba(232, 53, 53, 0.62); }
23
+ 50% { box-shadow: 0 0 14px rgba(232, 53, 53, 0.92), 0 0 28px rgba(232, 53, 53, 0.20); }
24
+ }
25
+
26
+ @keyframes card-enter {
27
+ from { opacity: 0; }
28
+ to { opacity: 1; }
29
+ }
30
+
31
+ @keyframes fade-up {
32
+ from { opacity: 0; }
33
+ to { opacity: 1; }
34
+ }
35
+
36
+ @keyframes badge-breathe {
37
+ 0%, 100% { opacity: 1; }
38
+ 50% { opacity: 0.68; }
39
+ }
40
+
41
+ @keyframes scan-bloom {
42
+ 0%, 100% {
43
+ box-shadow:
44
+ 0 0 0 1px rgba(232, 53, 53, 0.12),
45
+ 0 4px 24px rgba(232, 53, 53, 0.38),
46
+ 0 12px 48px rgba(232, 53, 53, 0.15),
47
+ inset 0 1px 0 rgba(255, 148, 148, 0.24),
48
+ inset 0 -1px 0 rgba(0, 0, 0, 0.38);
49
+ }
50
+ 50% {
51
+ box-shadow:
52
+ 0 0 0 1px rgba(232, 53, 53, 0.22),
53
+ 0 4px 34px rgba(232, 53, 53, 0.54),
54
+ 0 12px 68px rgba(232, 53, 53, 0.24),
55
+ inset 0 1px 0 rgba(255, 148, 148, 0.30),
56
+ inset 0 -1px 0 rgba(0, 0, 0, 0.38);
57
+ }
58
+ }
59
+
19
60
  /* ── Splash ──────────────────────────────────────────────────────────────── */
20
61
 
21
62
  .splash-window,
@@ -33,7 +74,7 @@ window,
33
74
 
34
75
  scrolledwindow,
35
76
  viewport {
36
- background-color: #000000;
77
+ background-color: #030308;
37
78
  }
38
79
 
39
80
  scrollbar trough {
@@ -46,18 +87,24 @@ scrollbar slider {
46
87
  border-radius: 3px;
47
88
  min-width: 3px;
48
89
  min-height: 48px;
90
+ transition: background 160ms ease, box-shadow 160ms ease;
91
+ }
92
+ scrollbar slider:hover {
93
+ background-color: rgba(255, 255, 255, 0.17);
94
+ box-shadow: 0 0 6px rgba(255, 255, 255, 0.07);
49
95
  }
50
- scrollbar slider:hover { background-color: rgba(255, 255, 255, 0.18); }
51
96
 
52
97
  /* ── Header ──────────────────────────────────────────────────────────────── */
53
98
 
54
99
  headerbar,
55
100
  .nothing-header {
56
- background: linear-gradient(180deg, rgba(255, 255, 255, 0.025) 0%, #000000 100%);
57
- border-bottom: 1px solid rgba(255, 255, 255, 0.06);
101
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.068) 0%, rgba(255, 255, 255, 0.015) 100%);
102
+ border-bottom: 1px solid rgba(255, 255, 255, 0.09);
58
103
  color: #ffffff;
59
104
  min-height: 56px;
60
- box-shadow: none;
105
+ box-shadow:
106
+ inset 0 1px 0 rgba(255, 255, 255, 0.06),
107
+ 0 8px 36px rgba(0, 0, 0, 0.52);
61
108
  padding: 0 10px;
62
109
  }
63
110
 
@@ -75,7 +122,7 @@ headerbar button.flat:not(.close):not(.minimize):not(.maximize) {
75
122
  background: none;
76
123
  border: none;
77
124
  box-shadow: none;
78
- color: rgba(255, 255, 255, 0.4);
125
+ color: rgba(255, 255, 255, 0.40);
79
126
  border-radius: 10px;
80
127
  min-width: 36px;
81
128
  min-height: 36px;
@@ -94,7 +141,7 @@ headerbar button:not(.close):not(.minimize):not(.maximize):active {
94
141
  /* ── Page ────────────────────────────────────────────────────────────────── */
95
142
 
96
143
  .nothing-page {
97
- background-color: #000000;
144
+ background: linear-gradient(180deg, #090205 0%, #030308 18%);
98
145
  padding: 0 18px 40px;
99
146
  }
100
147
 
@@ -106,7 +153,7 @@ headerbar button:not(.close):not(.minimize):not(.maximize):active {
106
153
  font-weight: 700;
107
154
  letter-spacing: 4px;
108
155
  text-transform: uppercase;
109
- color: rgba(255, 255, 255, 0.25);
156
+ color: rgba(255, 255, 255, 0.30);
110
157
  padding: 0 2px;
111
158
  margin-top: 36px;
112
159
  margin-bottom: 14px;
@@ -127,20 +174,27 @@ headerbar button:not(.close):not(.minimize):not(.maximize):active {
127
174
  /* ── Device list cards ───────────────────────────────────────────────────── */
128
175
 
129
176
  .device-card {
130
- background: rgba(255, 255, 255, 0.04);
177
+ background: linear-gradient(155deg, rgba(255, 255, 255, 0.055) 0%, rgba(255, 255, 255, 0.022) 100%);
131
178
  border-radius: 24px;
132
- border: 1px solid rgba(255, 255, 255, 0.08);
179
+ border: 1px solid rgba(255, 255, 255, 0.10);
133
180
  padding: 22px;
134
181
  margin-bottom: 8px;
135
- box-shadow: 0 4px 32px rgba(0, 0, 0, 0.6),
136
- inset 0 1px 0 rgba(255, 255, 255, 0.06);
182
+ box-shadow:
183
+ 0 6px 32px rgba(0, 0, 0, 0.72),
184
+ 0 0 0 0.5px rgba(255, 255, 255, 0.04),
185
+ inset 0 1px 0 rgba(255, 255, 255, 0.11),
186
+ inset 0 -1px 0 rgba(0, 0, 0, 0.32);
137
187
  transition: background 200ms ease, border-color 200ms ease, box-shadow 200ms ease;
188
+ animation: card-enter 280ms cubic-bezier(0.16, 1, 0.3, 1) both;
138
189
  }
139
190
  .device-card:hover {
140
- background: rgba(255, 255, 255, 0.07);
141
- border-color: rgba(255, 255, 255, 0.13);
142
- box-shadow: 0 8px 40px rgba(0, 0, 0, 0.7),
143
- inset 0 1px 0 rgba(255, 255, 255, 0.09);
191
+ background: linear-gradient(155deg, rgba(255, 255, 255, 0.082) 0%, rgba(255, 255, 255, 0.036) 100%);
192
+ border-color: rgba(255, 255, 255, 0.16);
193
+ box-shadow:
194
+ 0 10px 44px rgba(0, 0, 0, 0.82),
195
+ 0 0 0 0.5px rgba(255, 255, 255, 0.06),
196
+ inset 0 1px 0 rgba(255, 255, 255, 0.14),
197
+ inset 0 -1px 0 rgba(0, 0, 0, 0.32);
144
198
  }
145
199
 
146
200
  .device-card-name {
@@ -153,9 +207,10 @@ headerbar button:not(.close):not(.minimize):not(.maximize):active {
153
207
  .device-card-address {
154
208
  font-family: "JetBrains Mono", monospace;
155
209
  font-size: 10px;
156
- color: rgba(255, 255, 255, 0.2);
210
+ color: rgba(255, 255, 255, 0.20);
157
211
  letter-spacing: 1.5px;
158
212
  margin-top: 4px;
213
+ font-variant-numeric: tabular-nums;
159
214
  }
160
215
 
161
216
  .status-connected {
@@ -179,29 +234,40 @@ headerbar button:not(.close):not(.minimize):not(.maximize):active {
179
234
  letter-spacing: 2.5px;
180
235
  text-transform: uppercase;
181
236
  color: #e83535;
182
- background: rgba(232, 53, 53, 0.1);
237
+ background: rgba(232, 53, 53, 0.10);
183
238
  border: 1px solid rgba(232, 53, 53, 0.22);
184
239
  border-radius: 6px;
185
240
  padding: 3px 9px;
241
+ animation: badge-breathe 3.6s ease-in-out infinite;
186
242
  }
187
243
 
188
244
  /* ── Battery progress ────────────────────────────────────────────────────── */
189
245
 
190
246
  progressbar,
191
247
  progressbar trough {
192
- background-color: rgba(255, 255, 255, 0.07);
193
- border-radius: 4px;
194
- min-height: 4px;
248
+ background: linear-gradient(90deg, rgba(255, 255, 255, 0.052) 0%, rgba(255, 255, 255, 0.030) 100%);
249
+ border-radius: 6px;
250
+ min-height: 5px;
195
251
  border: none;
252
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.55);
196
253
  }
197
254
  progressbar progress {
198
255
  background-color: #e83535;
199
- border-radius: 4px;
200
- min-height: 4px;
256
+ border-radius: 6px;
257
+ min-height: 5px;
258
+ }
259
+ progressbar.battery-high progress {
260
+ background: linear-gradient(90deg, #6bc454 0%, #8fdf72 100%);
261
+ box-shadow: 0 0 8px rgba(143, 223, 114, 0.32);
262
+ }
263
+ progressbar.battery-mid progress {
264
+ background: linear-gradient(90deg, #d4a820 0%, #f0c040 100%);
265
+ box-shadow: 0 0 8px rgba(240, 192, 64, 0.32);
266
+ }
267
+ progressbar.battery-low progress {
268
+ background: linear-gradient(90deg, #c83030 0%, #e85252 100%);
269
+ box-shadow: 0 0 8px rgba(232, 82, 82, 0.35);
201
270
  }
202
- progressbar.battery-high progress { background-color: #8fdf72; }
203
- progressbar.battery-mid progress { background-color: #f0c040; }
204
- progressbar.battery-low progress { background-color: #e85252; }
205
271
 
206
272
  .battery-pct {
207
273
  font-family: "JetBrains Mono", monospace;
@@ -209,6 +275,7 @@ progressbar.battery-low progress { background-color: #e85252; }
209
275
  font-weight: 700;
210
276
  color: #ffffff;
211
277
  min-width: 38px;
278
+ font-variant-numeric: tabular-nums;
212
279
  }
213
280
  .battery-label-small {
214
281
  font-family: "JetBrains Mono", monospace;
@@ -223,6 +290,7 @@ progressbar.battery-low progress { background-color: #e85252; }
223
290
  font-weight: 700;
224
291
  color: #ffffff;
225
292
  letter-spacing: -2px;
293
+ font-variant-numeric: tabular-nums;
226
294
  }
227
295
  .battery-unit {
228
296
  font-family: "JetBrains Mono", monospace;
@@ -234,12 +302,14 @@ progressbar.battery-low progress { background-color: #e85252; }
234
302
  /* ── Sound mode — segmented control ─────────────────────────────────────── */
235
303
 
236
304
  .anc-container {
237
- background: rgba(255, 255, 255, 0.035);
305
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.040) 0%, rgba(255, 255, 255, 0.014) 100%);
238
306
  border-radius: 20px;
239
- border: 1px solid rgba(255, 255, 255, 0.07);
307
+ border: 1px solid rgba(255, 255, 255, 0.08);
240
308
  padding: 4px;
241
- box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.6),
242
- inset 0 1px 0 rgba(255, 255, 255, 0.04);
309
+ box-shadow:
310
+ inset 0 2px 8px rgba(0, 0, 0, 0.62),
311
+ inset 0 1px 0 rgba(255, 255, 255, 0.04),
312
+ 0 4px 20px rgba(0, 0, 0, 0.42);
243
313
  }
244
314
 
245
315
  .anc-button {
@@ -247,12 +317,12 @@ progressbar.battery-low progress { background-color: #e85252; }
247
317
  border: none;
248
318
  box-shadow: none;
249
319
  border-radius: 16px;
250
- color: rgba(255, 255, 255, 0.3);
320
+ color: rgba(255, 255, 255, 0.30);
251
321
  font-family: "JetBrains Mono", monospace;
252
322
  font-size: 12px;
253
323
  font-weight: 600;
254
324
  padding: 11px 14px;
255
- transition: all 220ms ease;
325
+ transition: all 220ms cubic-bezier(0.16, 1, 0.3, 1);
256
326
  letter-spacing: 0.2px;
257
327
  }
258
328
  .anc-button:hover {
@@ -264,8 +334,9 @@ progressbar.battery-low progress { background-color: #e85252; }
264
334
  background: linear-gradient(160deg, #e83535 0%, #c02424 100%);
265
335
  color: #ffffff;
266
336
  font-weight: 700;
267
- box-shadow: 0 2px 20px rgba(232, 53, 53, 0.55),
268
- inset 0 1px 0 rgba(255, 255, 255, 0.22);
337
+ box-shadow:
338
+ 0 2px 16px rgba(232, 53, 53, 0.38),
339
+ inset 0 1px 0 rgba(255, 255, 255, 0.20);
269
340
  }
270
341
  .anc-button.active label,
271
342
  .anc-button:checked label { color: #ffffff; }
@@ -277,22 +348,29 @@ progressbar.battery-low progress { background-color: #e85252; }
277
348
  /* ── EQ preset pills ─────────────────────────────────────────────────────── */
278
349
 
279
350
  .eq-button {
280
- background: rgba(255, 255, 255, 0.04);
281
- border: 1px solid rgba(255, 255, 255, 0.08);
282
- box-shadow: none;
351
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.052) 0%, rgba(255, 255, 255, 0.022) 100%);
352
+ border: 1px solid rgba(255, 255, 255, 0.09);
353
+ box-shadow:
354
+ inset 0 1px 0 rgba(255, 255, 255, 0.08),
355
+ inset 0 -1px 0 rgba(0, 0, 0, 0.22),
356
+ 0 2px 8px rgba(0, 0, 0, 0.42);
283
357
  border-radius: 100px;
284
- color: rgba(255, 255, 255, 0.38);
358
+ color: rgba(255, 255, 255, 0.40);
285
359
  font-family: "JetBrains Mono", monospace;
286
360
  font-size: 12px;
287
361
  font-weight: 600;
288
362
  padding: 10px 20px;
289
- transition: all 220ms ease;
363
+ transition: all 200ms ease;
290
364
  letter-spacing: 0.2px;
291
365
  }
292
366
  .eq-button:hover {
293
- background: rgba(255, 255, 255, 0.08);
294
- border-color: rgba(255, 255, 255, 0.13);
367
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.085) 0%, rgba(255, 255, 255, 0.040) 100%);
368
+ border-color: rgba(255, 255, 255, 0.14);
295
369
  color: rgba(255, 255, 255, 0.72);
370
+ box-shadow:
371
+ inset 0 1px 0 rgba(255, 255, 255, 0.12),
372
+ inset 0 -1px 0 rgba(0, 0, 0, 0.22),
373
+ 0 4px 14px rgba(0, 0, 0, 0.52);
296
374
  }
297
375
  .eq-button.active,
298
376
  .eq-button:checked {
@@ -300,8 +378,9 @@ progressbar.battery-low progress { background-color: #e85252; }
300
378
  border-color: transparent;
301
379
  color: #ffffff;
302
380
  font-weight: 700;
303
- box-shadow: 0 2px 20px rgba(232, 53, 53, 0.5),
304
- inset 0 1px 0 rgba(255, 255, 255, 0.22);
381
+ box-shadow:
382
+ 0 2px 16px rgba(232, 53, 53, 0.36),
383
+ inset 0 1px 0 rgba(255, 255, 255, 0.20);
305
384
  }
306
385
  .eq-button.active label,
307
386
  .eq-button:checked label { color: #ffffff; }
@@ -313,27 +392,37 @@ progressbar.battery-low progress { background-color: #e85252; }
313
392
  /* ── Volume slider ───────────────────────────────────────────────────────── */
314
393
 
315
394
  scale trough {
316
- background-color: rgba(255, 255, 255, 0.08);
395
+ background: linear-gradient(90deg, rgba(255, 255, 255, 0.060) 0%, rgba(255, 255, 255, 0.038) 100%);
317
396
  border-radius: 8px;
318
- min-height: 5px;
397
+ min-height: 6px;
319
398
  border: none;
399
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.62);
320
400
  }
321
401
  scale trough highlight {
322
- background: linear-gradient(90deg, #c42424 0%, #e83535 100%);
402
+ background: linear-gradient(90deg, #a81e1e 0%, #e83535 65%, #f04040 100%);
323
403
  border-radius: 8px;
404
+ box-shadow: 0 0 10px rgba(232, 53, 53, 0.36);
324
405
  }
325
406
  scale slider {
326
- background-color: #ffffff;
407
+ background: radial-gradient(circle at 35% 30%, #ffffff 0%, #d2d2d2 100%);
327
408
  border-radius: 50%;
328
409
  min-width: 22px;
329
410
  min-height: 22px;
330
411
  border: none;
331
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.6);
412
+ box-shadow:
413
+ 0 2px 12px rgba(0, 0, 0, 0.65),
414
+ inset 0 1px 0 rgba(255, 255, 255, 0.50);
415
+ }
416
+ scale slider:hover {
417
+ background: radial-gradient(circle at 35% 30%, #ffffff 0%, #e0e0e0 100%);
332
418
  }
333
- scale slider:hover { background-color: #eeeeee; }
334
419
  scale slider:active {
335
- background-color: #dddddd;
336
- box-shadow: 0 0 0 6px rgba(232, 53, 53, 0.18), 0 2px 10px rgba(0, 0, 0, 0.6);
420
+ background: radial-gradient(circle at 35% 30%, #ffffff 0%, #d2d2d2 100%);
421
+ box-shadow:
422
+ 0 0 0 5px rgba(232, 53, 53, 0.15),
423
+ 0 0 0 10px rgba(232, 53, 53, 0.06),
424
+ 0 2px 12px rgba(0, 0, 0, 0.65),
425
+ inset 0 1px 0 rgba(255, 255, 255, 0.50);
337
426
  }
338
427
 
339
428
  .volume-label {
@@ -342,22 +431,26 @@ scale slider:active {
342
431
  font-weight: 700;
343
432
  color: rgba(255, 255, 255, 0.45);
344
433
  min-width: 42px;
434
+ font-variant-numeric: tabular-nums;
345
435
  }
346
436
 
347
437
  /* ── Settings group ──────────────────────────────────────────────────────── */
348
438
 
349
439
  .settings-group {
350
- background: rgba(255, 255, 255, 0.03);
440
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.048) 0%, rgba(255, 255, 255, 0.018) 100%);
351
441
  border-radius: 22px;
352
- border: 1px solid rgba(255, 255, 255, 0.07);
353
- box-shadow: 0 4px 28px rgba(0, 0, 0, 0.5),
354
- inset 0 1px 0 rgba(255, 255, 255, 0.05);
442
+ border: 1px solid rgba(255, 255, 255, 0.09);
443
+ box-shadow:
444
+ 0 4px 28px rgba(0, 0, 0, 0.58),
445
+ inset 0 1px 0 rgba(255, 255, 255, 0.09),
446
+ inset 0 -1px 0 rgba(0, 0, 0, 0.26);
355
447
  }
356
448
 
357
449
  .settings-row {
358
450
  background-color: transparent;
359
451
  padding: 17px 22px;
360
- border-bottom: 1px solid rgba(255, 255, 255, 0.05);
452
+ border-bottom: 1px solid rgba(255, 255, 255, 0.055);
453
+ transition: background 160ms ease;
361
454
  }
362
455
  .settings-row:last-child { border-bottom: none; }
363
456
 
@@ -373,29 +466,33 @@ scale slider:active {
373
466
  }
374
467
 
375
468
  switch {
376
- background-color: rgba(255, 255, 255, 0.10);
469
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.080) 0%, rgba(255, 255, 255, 0.048) 100%);
470
+ border: 1px solid rgba(255, 255, 255, 0.08);
377
471
  border-radius: 20px;
378
472
  min-width: 50px;
379
473
  min-height: 28px;
380
- border: none;
381
- box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.4);
382
- transition: background 200ms ease;
474
+ box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.52);
475
+ transition: background 220ms ease, box-shadow 220ms ease;
383
476
  }
384
477
  switch:checked {
385
- background-color: #e83535;
386
- box-shadow: 0 0 14px rgba(232, 53, 53, 0.45);
478
+ background: linear-gradient(160deg, #e83535 0%, #c02020 100%);
479
+ border-color: rgba(255, 100, 100, 0.18);
480
+ box-shadow:
481
+ 0 0 14px rgba(232, 53, 53, 0.32),
482
+ 0 0 36px rgba(232, 53, 53, 0.10),
483
+ inset 0 2px 6px rgba(0, 0, 0, 0.20);
387
484
  }
388
485
  switch slider {
389
- background-color: rgba(255, 255, 255, 0.55);
486
+ background: rgba(255, 255, 255, 0.55);
390
487
  border-radius: 50%;
391
488
  min-width: 22px;
392
489
  min-height: 22px;
393
490
  margin: 3px;
394
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
491
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.42);
395
492
  }
396
493
  switch:checked slider {
397
494
  background-color: #ffffff;
398
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
495
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.50);
399
496
  }
400
497
 
401
498
  /* ── Device info ─────────────────────────────────────────────────────────── */
@@ -413,33 +510,49 @@ switch:checked slider {
413
510
  font-weight: 600;
414
511
  color: rgba(255, 255, 255, 0.45);
415
512
  letter-spacing: 0.3px;
513
+ font-variant-numeric: tabular-nums;
416
514
  }
417
515
 
418
516
  /* ── Action buttons ──────────────────────────────────────────────────────── */
419
517
 
420
518
  .scan-button {
421
- background: linear-gradient(160deg, #e83535 0%, #c42424 100%);
519
+ background: linear-gradient(160deg, #e83535 0%, #c02020 100%);
422
520
  border-radius: 100px;
423
521
  color: #ffffff;
424
522
  font-family: "JetBrains Mono", monospace;
425
523
  font-weight: 700;
426
524
  font-size: 12px;
427
525
  padding: 17px 52px;
428
- border: none;
429
- box-shadow: 0 4px 28px rgba(232, 53, 53, 0.55),
430
- inset 0 1px 0 rgba(255, 255, 255, 0.2);
526
+ border: 1px solid rgba(255, 110, 110, 0.18);
527
+ box-shadow:
528
+ 0 0 0 1px rgba(232, 53, 53, 0.12),
529
+ 0 4px 24px rgba(232, 53, 53, 0.38),
530
+ 0 12px 48px rgba(232, 53, 53, 0.15),
531
+ inset 0 1px 0 rgba(255, 148, 148, 0.24),
532
+ inset 0 -1px 0 rgba(0, 0, 0, 0.38);
431
533
  letter-spacing: 2px;
432
534
  transition: all 200ms ease;
433
535
  }
434
536
  .scan-button label { color: #ffffff; }
435
537
  .scan-button:hover {
436
538
  background: linear-gradient(160deg, #f04040 0%, #cc2c2c 100%);
437
- box-shadow: 0 6px 36px rgba(232, 53, 53, 0.65),
438
- inset 0 1px 0 rgba(255, 255, 255, 0.25);
539
+ box-shadow:
540
+ 0 0 0 1px rgba(232, 53, 53, 0.20),
541
+ 0 6px 32px rgba(232, 53, 53, 0.52),
542
+ 0 16px 60px rgba(232, 53, 53, 0.22),
543
+ inset 0 1px 0 rgba(255, 148, 148, 0.30),
544
+ inset 0 -1px 0 rgba(0, 0, 0, 0.38);
439
545
  }
440
546
  .scan-button:active {
441
547
  background: linear-gradient(160deg, #c42424 0%, #a81e1e 100%);
442
- box-shadow: 0 2px 14px rgba(232, 53, 53, 0.4);
548
+ box-shadow:
549
+ 0 0 0 1px rgba(232, 53, 53, 0.08),
550
+ 0 2px 12px rgba(232, 53, 53, 0.28),
551
+ inset 0 1px 0 rgba(255, 148, 148, 0.16),
552
+ inset 0 -1px 0 rgba(0, 0, 0, 0.42);
553
+ }
554
+ .scan-button.scanning {
555
+ animation: scan-bloom 1.8s ease-in-out infinite;
443
556
  }
444
557
 
445
558
  .disconnect-button {
@@ -451,39 +564,47 @@ switch:checked slider {
451
564
  font-size: 12px;
452
565
  padding: 16px 40px;
453
566
  border: 1px solid rgba(232, 53, 53, 0.18);
454
- box-shadow: none;
567
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
455
568
  letter-spacing: 2px;
456
569
  transition: all 200ms ease;
457
570
  }
458
571
  .disconnect-button label { color: rgba(232, 53, 53, 0.75); }
459
572
  .disconnect-button:hover {
460
- background: rgba(232, 53, 53, 0.13);
461
- border-color: rgba(232, 53, 53, 0.32);
573
+ background: rgba(232, 53, 53, 0.12);
574
+ border-color: rgba(232, 53, 53, 0.30);
462
575
  color: #e83535;
463
- box-shadow: 0 0 20px rgba(232, 53, 53, 0.15);
576
+ box-shadow:
577
+ 0 0 16px rgba(232, 53, 53, 0.11),
578
+ inset 0 1px 0 rgba(255, 255, 255, 0.04);
464
579
  }
465
580
  .disconnect-button:hover label { color: #e83535; }
466
581
 
467
582
  .connect-button {
468
- background: rgba(255, 255, 255, 0.04);
583
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.052) 0%, rgba(255, 255, 255, 0.022) 100%);
469
584
  border-radius: 100px;
470
- color: rgba(255, 255, 255, 0.6);
585
+ color: rgba(255, 255, 255, 0.60);
471
586
  font-family: "JetBrains Mono", monospace;
472
587
  font-weight: 700;
473
588
  font-size: 12px;
474
589
  padding: 16px 40px;
475
590
  border: 1px solid rgba(255, 255, 255, 0.11);
476
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
591
+ box-shadow:
592
+ inset 0 1px 0 rgba(255, 255, 255, 0.08),
593
+ inset 0 -1px 0 rgba(0, 0, 0, 0.26);
477
594
  letter-spacing: 2px;
478
595
  transition: all 200ms ease;
479
596
  }
480
- .connect-button label { color: rgba(255, 255, 255, 0.6); }
597
+ .connect-button label { color: rgba(255, 255, 255, 0.60); }
481
598
  .connect-button:hover {
482
- background: rgba(255, 255, 255, 0.08);
599
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.085) 0%, rgba(255, 255, 255, 0.040) 100%);
483
600
  border-color: rgba(255, 255, 255, 0.18);
484
- color: rgba(255, 255, 255, 0.9);
601
+ color: rgba(255, 255, 255, 0.90);
602
+ box-shadow:
603
+ inset 0 1px 0 rgba(255, 255, 255, 0.12),
604
+ inset 0 -1px 0 rgba(0, 0, 0, 0.26),
605
+ 0 4px 16px rgba(0, 0, 0, 0.42);
485
606
  }
486
- .connect-button:hover label { color: rgba(255, 255, 255, 0.9); }
607
+ .connect-button:hover label { color: rgba(255, 255, 255, 0.90); }
487
608
 
488
609
  .connecting-button {
489
610
  background: rgba(255, 255, 255, 0.03);
@@ -515,11 +636,13 @@ switch:checked slider {
515
636
  letter-spacing: 4px;
516
637
  text-transform: uppercase;
517
638
  color: rgba(255, 255, 255, 0.10);
639
+ animation: fade-up 380ms ease both;
518
640
  }
519
641
  .empty-subtitle {
520
642
  font-size: 13px;
521
643
  color: rgba(255, 255, 255, 0.18);
522
644
  margin-top: 8px;
645
+ animation: fade-up 380ms 80ms ease both;
523
646
  }
524
647
 
525
648
  /* ── Nothing brand ───────────────────────────────────────────────────────── */
@@ -529,7 +652,8 @@ switch:checked slider {
529
652
  border-radius: 50%;
530
653
  min-width: 6px;
531
654
  min-height: 6px;
532
- box-shadow: 0 0 8px rgba(232, 53, 53, 0.7);
655
+ box-shadow: 0 0 6px rgba(232, 53, 53, 0.62);
656
+ animation: dot-pulse 3s ease-in-out infinite;
533
657
  }
534
658
 
535
659
  separator { background-color: rgba(255, 255, 255, 0.05); }
@@ -115,13 +115,13 @@ class EarbudVisual(Gtk.DrawingArea):
115
115
  r = 29
116
116
  bc = _battery_color(pct) if pct >= 0 else (0.18, 0.18, 0.18)
117
117
 
118
- # outer diffuse glow (battery color)
119
- for i in range(3):
120
- rg = cairo.RadialGradient(cx, cy, R - 2, cx, cy, R + 14 + i * 8)
121
- rg.add_color_stop_rgba(0, *bc, 0.10 - i * 0.025)
118
+ # outer diffuse glow 4 layers for softer falloff
119
+ for i in range(4):
120
+ rg = cairo.RadialGradient(cx, cy, R - 2, cx, cy, R + 14 + i * 9)
121
+ rg.add_color_stop_rgba(0, *bc, 0.088 - i * 0.018)
122
122
  rg.add_color_stop_rgba(1, *bc, 0)
123
123
  cr.set_source(rg)
124
- cr.arc(cx, cy, R + 14 + i * 8, 0, 2 * math.pi)
124
+ cr.arc(cx, cy, R + 14 + i * 9, 0, 2 * math.pi)
125
125
  cr.fill()
126
126
 
127
127
  # body: radial gradient for sphere depth
@@ -139,12 +139,20 @@ class EarbudVisual(Gtk.DrawingArea):
139
139
  cr.arc(cx, cy, R - 3, 0, 2 * math.pi)
140
140
  cr.stroke()
141
141
 
142
- # battery arc (colored progress)
142
+ # battery arc bloom (wider, low alpha — behind the main arc)
143
143
  if pct > 0:
144
+ angle_end = -math.pi / 2 + (pct / 100) * 2 * math.pi
145
+ cr.set_source_rgba(*bc, 0.18)
146
+ cr.set_line_width(10)
147
+ cr.set_line_cap(cairo.LineCap.ROUND)
148
+ cr.arc(cx, cy, R - 3, -math.pi / 2, angle_end)
149
+ cr.stroke()
150
+
151
+ # battery arc (solid colored progress on top)
144
152
  cr.set_source_rgba(*bc, 1.0)
145
153
  cr.set_line_width(6)
146
154
  cr.set_line_cap(cairo.LineCap.ROUND)
147
- cr.arc(cx, cy, R - 3, -math.pi / 2, -math.pi / 2 + (pct / 100) * 2 * math.pi)
155
+ cr.arc(cx, cy, R - 3, -math.pi / 2, angle_end)
148
156
  cr.stroke()
149
157
 
150
158
  # inner circle: radial gradient for glass depth
@@ -155,13 +163,28 @@ class EarbudVisual(Gtk.DrawingArea):
155
163
  cr.arc(cx, cy, r, 0, 2 * math.pi)
156
164
  cr.fill()
157
165
 
158
- # glass highlight arc (top-left crescent)
159
- cr.set_source_rgba(1.0, 1.0, 1.0, 0.10)
166
+ # specular hot-spot (small point light in upper-left)
167
+ spec = cairo.RadialGradient(cx - r * 0.42, cy - r * 0.42, 0, cx - r * 0.42, cy - r * 0.42, r * 0.40)
168
+ spec.add_color_stop_rgba(0, 1.0, 1.0, 1.0, 0.10)
169
+ spec.add_color_stop_rgba(1, 1.0, 1.0, 1.0, 0.0)
170
+ cr.set_source(spec)
171
+ cr.arc(cx, cy, r, 0, 2 * math.pi)
172
+ cr.fill()
173
+
174
+ # glass highlight arc — primary crescent
175
+ cr.set_source_rgba(1.0, 1.0, 1.0, 0.12)
160
176
  cr.set_line_width(4)
161
177
  cr.set_line_cap(cairo.LineCap.ROUND)
162
178
  cr.arc(cx, cy, r - 4, math.pi * 1.05, math.pi * 1.72)
163
179
  cr.stroke()
164
180
 
181
+ # glass highlight arc — secondary (fainter, tighter)
182
+ cr.set_source_rgba(1.0, 1.0, 1.0, 0.05)
183
+ cr.set_line_width(2.5)
184
+ cr.set_line_cap(cairo.LineCap.ROUND)
185
+ cr.arc(cx, cy, r - 9, math.pi * 1.15, math.pi * 1.62)
186
+ cr.stroke()
187
+
165
188
  # percentage text
166
189
  cr.set_source_rgba(1.0, 1.0, 1.0, 1.0 if pct >= 0 else 0.22)
167
190
  cr.select_font_face(_MONO, cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD)
@@ -175,7 +198,7 @@ class EarbudVisual(Gtk.DrawingArea):
175
198
  dot_y = cy + R + 8
176
199
  if wearing:
177
200
  rg = cairo.RadialGradient(cx, dot_y, 0, cx, dot_y, 9)
178
- rg.add_color_stop_rgba(0, 0.87, 0.18, 0.18, 0.30)
201
+ rg.add_color_stop_rgba(0, 0.87, 0.18, 0.18, 0.26)
179
202
  rg.add_color_stop_rgba(1, 0.87, 0.18, 0.18, 0.0)
180
203
  cr.set_source(rg)
181
204
  cr.arc(cx, dot_y, 9, 0, 2 * math.pi)
@@ -195,16 +218,17 @@ class EarbudVisual(Gtk.DrawingArea):
195
218
  cr.show_text(label)
196
219
 
197
220
  def _draw_case(self, cr, cx, cy, pct):
198
- R = 18
221
+ R = 20
199
222
  bc = _battery_color(pct) if pct >= 0 else (0.18, 0.18, 0.18)
200
223
 
201
- # outer diffuse glow
202
- rg = cairo.RadialGradient(cx, cy, R - 1, cx, cy, R + 14)
203
- rg.add_color_stop_rgba(0, *bc, 0.09)
204
- rg.add_color_stop_rgba(1, *bc, 0)
205
- cr.set_source(rg)
206
- cr.arc(cx, cy, R + 14, 0, 2 * math.pi)
207
- cr.fill()
224
+ # outer diffuse glow — 2 layers
225
+ for i in range(2):
226
+ rg = cairo.RadialGradient(cx, cy, R - 1, cx, cy, R + 14 + i * 9)
227
+ rg.add_color_stop_rgba(0, *bc, 0.08 - i * 0.03)
228
+ rg.add_color_stop_rgba(1, *bc, 0)
229
+ cr.set_source(rg)
230
+ cr.arc(cx, cy, R + 14 + i * 9, 0, 2 * math.pi)
231
+ cr.fill()
208
232
 
209
233
  # body
210
234
  body = cairo.RadialGradient(cx - R * 0.28, cy - R * 0.28, R * 0.08, cx, cy, R)
@@ -220,16 +244,32 @@ class EarbudVisual(Gtk.DrawingArea):
220
244
  cr.arc(cx, cy, R - 2, 0, 2 * math.pi)
221
245
  cr.stroke()
222
246
 
223
- # battery arc
247
+ # battery arc bloom (wider, lower alpha)
224
248
  if pct > 0:
249
+ angle_end = -math.pi / 2 + (pct / 100) * 2 * math.pi
250
+ cr.set_source_rgba(*bc, 0.16)
251
+ cr.set_line_width(7)
252
+ cr.set_line_cap(cairo.LineCap.ROUND)
253
+ cr.arc(cx, cy, R - 2, -math.pi / 2, angle_end)
254
+ cr.stroke()
255
+
256
+ # battery arc (solid)
225
257
  cr.set_source_rgba(*bc, 1.0)
226
258
  cr.set_line_width(4)
227
259
  cr.set_line_cap(cairo.LineCap.ROUND)
228
- cr.arc(cx, cy, R - 2, -math.pi / 2, -math.pi / 2 + (pct / 100) * 2 * math.pi)
260
+ cr.arc(cx, cy, R - 2, -math.pi / 2, angle_end)
229
261
  cr.stroke()
230
262
 
263
+ # specular hot-spot
264
+ spec = cairo.RadialGradient(cx - R * 0.42, cy - R * 0.42, 0, cx - R * 0.42, cy - R * 0.42, R * 0.48)
265
+ spec.add_color_stop_rgba(0, 1.0, 1.0, 1.0, 0.10)
266
+ spec.add_color_stop_rgba(1, 1.0, 1.0, 1.0, 0.0)
267
+ cr.set_source(spec)
268
+ cr.arc(cx, cy, R, 0, 2 * math.pi)
269
+ cr.fill()
270
+
231
271
  # glass highlight
232
- cr.set_source_rgba(1.0, 1.0, 1.0, 0.09)
272
+ cr.set_source_rgba(1.0, 1.0, 1.0, 0.11)
233
273
  cr.set_line_width(3)
234
274
  cr.set_line_cap(cairo.LineCap.ROUND)
235
275
  cr.arc(cx, cy, R - 4, math.pi * 1.05, math.pi * 1.72)
@@ -218,6 +218,7 @@ class HomePage(Gtk.Box):
218
218
  self._scanning = True
219
219
  self._scan_btn.set_label("SCANNING…")
220
220
  self._scan_btn.set_sensitive(False)
221
+ self._scan_btn.add_css_class("scanning")
221
222
  self._bt.start_discovery()
222
223
  GLib.timeout_add_seconds(30, self._scan_done)
223
224
 
@@ -225,5 +226,6 @@ class HomePage(Gtk.Box):
225
226
  self._scanning = False
226
227
  self._scan_btn.set_label("SCAN FOR DEVICES")
227
228
  self._scan_btn.set_sensitive(True)
229
+ self._scan_btn.remove_css_class("scanning")
228
230
  self._refresh_list()
229
231
  return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: something-x-dev
3
- Version: 1.8.0.dev23
3
+ Version: 1.8.0.dev24
4
4
  Summary: Something X device manager for Omarchy / Linux
5
5
  Author: Raphael
6
6
  License: MIT