sensivity 2.5.28 → 2.5.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sensivity",
3
- "version": "2.5.28",
3
+ "version": "2.5.30",
4
4
  "description": "Sensivity Control Panel",
5
5
  "main": "launcher.js",
6
6
  "bin": {
Binary file
@@ -1,21 +1,21 @@
1
1
  :root {
2
- --bg: #081d2a;
3
- --bg2: #111116;
4
- --bg3: #15151b;
5
- --bg4: #1b1b25;
6
- --bg5: #242434;
7
- --sidebar: #202432;
8
- --sidebar2: #1b2030;
9
- --border: #262633;
10
- --border2: #30243a;
11
- --accent: #c10cff;
12
- --accent2: #8a35e8;
13
- --accent-dim: rgba(193, 12, 255, .22);
2
+ --bg: #000;
3
+ --bg2: #050605;
4
+ --bg3: #0b0d0b;
5
+ --bg4: #111411;
6
+ --bg5: #171c18;
7
+ --sidebar: #080a08;
8
+ --sidebar2: #040504;
9
+ --border: #1b251f;
10
+ --border2: #223528;
11
+ --accent: #20f568;
12
+ --accent2: #0fb84c;
13
+ --accent-dim: rgba(49, 255, 122, .2);
14
14
  --gold: var(--accent);
15
- --gold-dim: rgba(193, 12, 255, .18);
15
+ --gold-dim: rgba(49, 255, 122, .16);
16
16
  --text: #f2f2f6;
17
- --text2: #a7a2b7;
18
- --text3: #686477;
17
+ --text2: #c3cdc6;
18
+ --text3: #7f8b83;
19
19
  --danger: #f15d62;
20
20
  --green: #52e37c;
21
21
  --panel-w: min(1120px, 92vw);
@@ -29,6 +29,7 @@
29
29
  html, body { min-height: 100%; }
30
30
 
31
31
  body {
32
+ position: relative;
32
33
  font-family: var(--font);
33
34
  color: var(--text);
34
35
  height: 100dvh;
@@ -42,10 +43,8 @@ body {
42
43
  justify-content: center;
43
44
  padding: 18px;
44
45
  background:
45
- linear-gradient(118deg, transparent 0 18%, rgba(12, 115, 157, .62) 18% 31%, transparent 31% 100%),
46
- linear-gradient(152deg, transparent 0 58%, rgba(5, 61, 86, .88) 58% 72%, transparent 72% 100%),
47
- linear-gradient(23deg, rgba(16, 134, 178, .78) 0 38%, transparent 38% 100%),
48
- #063345;
46
+ radial-gradient(circle at 50% 44%, rgba(32, 245, 104, .08), transparent 32%),
47
+ linear-gradient(180deg, #000, #020302 72%);
49
48
  }
50
49
 
51
50
  body::before,
@@ -58,38 +57,71 @@ body::after {
58
57
  }
59
58
  body::before {
60
59
  background:
61
- linear-gradient(108deg, rgba(2, 33, 48, .9) 0 17%, transparent 17% 100%),
62
- linear-gradient(112deg, transparent 0 72%, rgba(16, 100, 133, .7) 72% 100%),
63
- linear-gradient(18deg, rgba(13, 88, 119, .64) 0 22%, transparent 22% 100%);
60
+ radial-gradient(circle at 12% 30%, rgba(32, 245, 104, .08), transparent 22%),
61
+ radial-gradient(circle at 88% 66%, rgba(32, 245, 104, .07), transparent 24%);
64
62
  }
65
63
  body::after {
66
- background:
67
- linear-gradient(72deg, transparent 0 64%, rgba(4, 34, 48, .9) 64% 82%, transparent 82%),
68
- linear-gradient(14deg, transparent 0 58%, rgba(0, 20, 31, .78) 58% 100%);
69
- opacity: .92;
64
+ z-index: 0;
65
+ background-image:
66
+ radial-gradient(circle, rgba(49, 255, 122, .72) 0 1px, transparent 2px),
67
+ radial-gradient(circle, rgba(49, 255, 122, .35) 0 1px, transparent 2px),
68
+ radial-gradient(circle, rgba(255,255,255,.18) 0 1px, transparent 2px);
69
+ background-size: 78px 78px, 126px 126px, 210px 210px;
70
+ background-position: 0 0, 32px 42px, 80px 120px;
71
+ opacity: .72;
72
+ animation: sensivityParticles 13s linear infinite;
73
+ mask-image: radial-gradient(ellipse at center, #000 0 58%, transparent 82%);
70
74
  }
71
75
 
76
+ #bg-brand {
77
+ position: fixed;
78
+ inset: 0;
79
+ z-index: 0;
80
+ pointer-events: none;
81
+ overflow: hidden;
82
+ }
83
+
84
+ .brand-mark {
85
+ position: absolute;
86
+ color: rgba(32, 245, 104, .18);
87
+ font-size: clamp(22px, 3vw, 46px);
88
+ line-height: .9;
89
+ font-weight: 950;
90
+ text-shadow: 0 0 26px rgba(32, 245, 104, .22);
91
+ }
92
+ .brand-mark.m1 { left: 5vw; top: 8vh; transform: rotate(-6deg); }
93
+ .brand-mark.m2 { right: 5vw; top: 14vh; text-align: right; transform: rotate(5deg); }
94
+ .brand-mark.m3 { left: 7vw; bottom: 9vh; transform: rotate(4deg); }
95
+ .brand-mark.m4 { right: 7vw; bottom: 12vh; text-align: right; transform: rotate(-5deg); }
96
+
72
97
  ::-webkit-scrollbar { width: 4px; height: 4px; }
73
98
  ::-webkit-scrollbar-track { background: transparent; }
74
- ::-webkit-scrollbar-thumb { background: #343146; border-radius: 2px; }
99
+ ::-webkit-scrollbar-thumb { background: #2b3c30; border-radius: 2px; }
100
+
101
+ @keyframes sensivityParticles {
102
+ from { background-position: 0 0, 32px 42px, 80px 120px; }
103
+ to { background-position: 96px -240px, -72px -180px, 180px -120px; }
104
+ }
75
105
 
76
106
  #app {
107
+ position: relative;
108
+ z-index: 1;
77
109
  width: var(--panel-w);
78
110
  height: var(--panel-h);
79
111
  min-height: 520px;
80
112
  display: flex;
81
113
  overflow: hidden;
82
- background: rgba(16, 16, 21, .96);
83
- border: 1px solid rgba(73, 58, 88, .55);
114
+ background: rgba(2, 3, 2, .98);
115
+ border: 1px solid rgba(32, 245, 104, .28);
84
116
  border-radius: var(--radius);
85
- box-shadow: 0 28px 90px rgba(0, 0, 0, .42);
117
+ box-shadow: 0 28px 90px rgba(0, 0, 0, .62);
86
118
  }
87
119
 
88
120
  #sidebar {
89
121
  width: 210px;
90
122
  flex: 0 0 210px;
91
123
  background: linear-gradient(180deg, var(--sidebar), var(--sidebar2));
92
- border-right: 1px solid #2b2a39;
124
+ border-right: 1px solid #242c27;
93
125
  display: flex;
94
126
  flex-direction: column;
95
127
  overflow: hidden;
@@ -99,11 +131,23 @@ body::after {
99
131
  height: 70px;
100
132
  display: flex;
101
133
  align-items: center;
102
- padding: 0 28px;
134
+ gap: 12px;
135
+ padding: 0 22px;
103
136
  color: #f9f9ff;
104
- font-size: 25px;
137
+ font-size: 20px;
105
138
  font-weight: 900;
106
- letter-spacing: .5px;
139
+ letter-spacing: 0;
140
+ }
141
+ .brand img {
142
+ width: 34px;
143
+ height: 34px;
144
+ object-fit: contain;
145
+ filter: drop-shadow(0 0 12px rgba(49, 255, 122, .28));
146
+ }
147
+ .brand span {
148
+ min-width: 0;
149
+ overflow: hidden;
150
+ text-overflow: ellipsis;
107
151
  }
108
152
 
109
153
  .nav-scroll {
@@ -119,7 +163,7 @@ body::after {
119
163
  font-size: 12px;
120
164
  line-height: 1;
121
165
  font-weight: 900;
122
- letter-spacing: .2px;
166
+ letter-spacing: 0;
123
167
  }
124
168
 
125
169
  .tab-btn {
@@ -165,7 +209,7 @@ body::after {
165
209
  width: 4px;
166
210
  border-radius: 3px 0 0 3px;
167
211
  background: var(--accent);
168
- box-shadow: 0 0 16px rgba(193, 12, 255, .75);
212
+ box-shadow: 0 0 16px rgba(49, 255, 122, .72);
169
213
  }
170
214
 
171
215
  #content {
@@ -174,7 +218,7 @@ body::after {
174
218
  display: flex;
175
219
  flex-direction: column;
176
220
  overflow: hidden;
177
- background: rgba(18, 18, 23, .94);
221
+ background: rgba(3, 4, 3, .98);
178
222
  }
179
223
 
180
224
  #topbar {
@@ -184,8 +228,8 @@ body::after {
184
228
  align-items: center;
185
229
  gap: 18px;
186
230
  padding: 0 22px;
187
- border-bottom: 1px solid #25242e;
188
- background: #141419;
231
+ border-bottom: 1px solid #242b26;
232
+ background: #0d100e;
189
233
  }
190
234
 
191
235
  .top-title {
@@ -195,7 +239,7 @@ body::after {
195
239
  gap: 12px;
196
240
  }
197
241
  .tb-icon {
198
- color: #6e7284;
242
+ color: #87918a;
199
243
  display: inline-flex;
200
244
  }
201
245
  .tb-icon svg {
@@ -209,16 +253,16 @@ body::after {
209
253
  display: block;
210
254
  font-size: 19px;
211
255
  font-weight: 800;
212
- color: #5e6070;
256
+ color: #a8b2ab;
213
257
  }
214
258
  .top-secondary {
215
259
  display: block;
216
260
  margin-top: 1px;
217
- color: #b9b5c6;
261
+ color: #31f474;
218
262
  font-size: 11px;
219
263
  font-weight: 800;
220
264
  text-transform: uppercase;
221
- letter-spacing: .5px;
265
+ letter-spacing: 0;
222
266
  }
223
267
 
224
268
  .sub-tabs {
@@ -235,7 +279,7 @@ body::after {
235
279
  border: 1px solid transparent;
236
280
  border-radius: 4px;
237
281
  background: transparent;
238
- color: #6c6978;
282
+ color: #89948c;
239
283
  padding: 7px 10px;
240
284
  cursor: pointer;
241
285
  font-family: var(--font);
@@ -243,9 +287,9 @@ body::after {
243
287
  font-weight: 800;
244
288
  }
245
289
  .sub-tab.active {
246
- color: #fff;
247
- border-color: rgba(193, 12, 255, .3);
248
- background: rgba(193, 12, 255, .08);
290
+ color: #f7fff9;
291
+ border-color: rgba(49, 255, 122, .34);
292
+ background: rgba(49, 255, 122, .08);
249
293
  }
250
294
  .profile-dot {
251
295
  width: 36px;
@@ -254,14 +298,26 @@ body::after {
254
298
  border-radius: 50%;
255
299
  display: grid;
256
300
  place-items: center;
257
- color: #17171d;
258
- background: radial-gradient(circle at 35% 25%, #fff, #e8e8ef 42%, #bfc0ca 100%);
259
- font-weight: 900;
260
- box-shadow: inset 0 0 0 1px rgba(0,0,0,.16);
301
+ background: #050705;
302
+ border: 1px solid rgba(49, 255, 122, .28);
303
+ box-shadow: inset 0 0 0 1px rgba(255,255,255,.04), 0 0 18px rgba(49, 255, 122, .12);
304
+ }
305
+ .profile-dot img {
306
+ width: 23px;
307
+ height: 23px;
308
+ object-fit: contain;
261
309
  }
262
310
 
263
- #pages {
311
+ #workspace {
264
312
  flex: 1;
313
+ min-height: 0;
314
+ display: flex;
315
+ overflow: hidden;
316
+ }
317
+
318
+ #pages {
319
+ flex: 1 1 auto;
320
+ min-width: 0;
265
321
  overflow-y: auto;
266
322
  overflow-x: hidden;
267
323
  padding: 20px;
@@ -272,26 +328,39 @@ body::after {
272
328
  align-content: start;
273
329
  }
274
330
 
275
- #pages.has-preview {
276
- grid-template-columns: minmax(240px, 1fr) minmax(280px, 1.08fr);
331
+ #esp-preview-shell {
332
+ display: none;
333
+ flex: 0 0 372px;
334
+ min-width: 0;
335
+ padding: 20px 20px 20px 0;
336
+ overflow: hidden;
337
+ }
338
+
339
+ #workspace.has-preview #pages {
340
+ flex-basis: calc(100% - 372px);
341
+ grid-template-columns: 1fr;
342
+ }
343
+
344
+ #workspace.has-preview #esp-preview-shell {
345
+ display: block;
277
346
  }
278
347
 
279
348
  .child {
280
349
  min-width: 0;
281
- background: rgba(21, 21, 27, .72);
282
- border: 1px solid rgba(55, 42, 66, .75);
283
- border-top-color: rgba(193, 12, 255, .8);
350
+ background: rgba(10, 11, 10, .94);
351
+ border: 1px solid rgba(43, 55, 47, .78);
352
+ border-top-color: rgba(49, 255, 122, .72);
284
353
  border-radius: 8px;
285
354
  padding: 18px 18px 16px;
286
355
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .018);
287
356
  }
288
- .child:hover { border-color: rgba(91, 70, 106, .9); border-top-color: rgba(193, 12, 255, 1); }
357
+ .child:hover { border-color: rgba(68, 93, 76, .9); border-top-color: rgba(49, 255, 122, .95); }
289
358
  .child h3 {
290
359
  font-size: 12px;
291
- color: #6f6b79;
360
+ color: #95a39a;
292
361
  margin-bottom: 16px;
293
362
  font-weight: 900;
294
- letter-spacing: .1px;
363
+ letter-spacing: 0;
295
364
  }
296
365
  .empty-state {
297
366
  grid-column: 1 / -1;
@@ -312,7 +381,7 @@ body::after {
312
381
  .ctrl:last-child { margin-bottom: 0; }
313
382
  .ctrl > label:not(.tgl) {
314
383
  min-width: 0;
315
- color: #666371;
384
+ color: #aeb8b0;
316
385
  font-size: 13px;
317
386
  line-height: 1.25;
318
387
  font-weight: 800;
@@ -320,7 +389,7 @@ body::after {
320
389
  text-overflow: ellipsis;
321
390
  white-space: nowrap;
322
391
  }
323
- .ctrl:hover > label:not(.tgl) { color: #aaa6b8; }
392
+ .ctrl:hover > label:not(.tgl) { color: #eef6f0; }
324
393
 
325
394
  .tgl {
326
395
  width: 34px;
@@ -336,8 +405,8 @@ body::after {
336
405
  inset: 0;
337
406
  cursor: pointer;
338
407
  border-radius: 999px;
339
- background: #222433;
340
- border: 1px solid #2c2d40;
408
+ background: #171a17;
409
+ border: 1px solid #2a322d;
341
410
  transition: background .18s ease, border-color .18s ease, box-shadow .18s ease;
342
411
  }
343
412
  .tgl .knob {
@@ -347,14 +416,14 @@ body::after {
347
416
  width: 12px;
348
417
  height: 12px;
349
418
  border-radius: 50%;
350
- background: #595e74;
419
+ background: #69736b;
351
420
  transform: translateY(-50%);
352
421
  transition: transform .18s ease, background .18s ease;
353
422
  }
354
423
  .tgl input:checked + .track {
355
- background: #2b1342;
356
- border-color: rgba(193, 12, 255, .58);
357
- box-shadow: 0 0 12px rgba(193, 12, 255, .3);
424
+ background: #102318;
425
+ border-color: rgba(49, 255, 122, .56);
426
+ box-shadow: 0 0 12px rgba(49, 255, 122, .26);
358
427
  }
359
428
  .tgl input:checked + .track .knob { transform: translate(14px, -50%); background: var(--accent); }
360
429
 
@@ -362,12 +431,13 @@ body::after {
362
431
  .rng {
363
432
  width: 100%;
364
433
  display: grid;
365
- grid-template-columns: 44px 1fr;
434
+ grid-template-columns: 54px 1fr;
366
435
  align-items: center;
367
- gap: 12px;
436
+ gap: 14px;
437
+ padding: 2px 0 4px;
368
438
  }
369
439
  .rng-val {
370
- color: #6f6b79;
440
+ color: #d3ded6;
371
441
  font-size: 12px;
372
442
  font-weight: 900;
373
443
  text-align: right;
@@ -376,20 +446,50 @@ body::after {
376
446
  .rng input[type=range] {
377
447
  -webkit-appearance: none;
378
448
  width: 100%;
379
- height: 6px;
380
- background: #111118;
449
+ height: 22px;
450
+ background: transparent;
381
451
  border-radius: 999px;
382
452
  outline: none;
453
+ cursor: pointer;
454
+ --range-percent: 0%;
455
+ }
456
+ .rng input[type=range]::-webkit-slider-runnable-track {
457
+ height: 8px;
458
+ border-radius: 999px;
459
+ border: 1px solid rgba(32, 245, 104, .2);
460
+ background:
461
+ linear-gradient(90deg, rgba(32, 245, 104, .78) 0 var(--range-percent), #1c221e var(--range-percent) 100%);
462
+ box-shadow: inset 0 0 0 1px rgba(0,0,0,.35);
383
463
  }
384
464
  .rng input[type=range]::-webkit-slider-thumb {
385
465
  -webkit-appearance: none;
386
- width: 16px;
387
- height: 16px;
466
+ width: 18px;
467
+ height: 18px;
468
+ margin-top: -6px;
388
469
  border-radius: 50%;
389
- background: #6e5a86;
390
- border: 0;
470
+ background: #0f1511;
471
+ border: 3px solid #5d8269;
472
+ cursor: pointer;
473
+ box-shadow: 0 0 0 3px rgba(32, 245, 104, .1), 0 0 18px rgba(32, 245, 104, .18);
474
+ }
475
+ .rng input[type=range]::-moz-range-track {
476
+ height: 8px;
477
+ border-radius: 999px;
478
+ border: 1px solid rgba(32, 245, 104, .2);
479
+ background: #1c221e;
480
+ }
481
+ .rng input[type=range]::-moz-range-progress {
482
+ height: 8px;
483
+ border-radius: 999px;
484
+ background: rgba(32, 245, 104, .78);
485
+ }
486
+ .rng input[type=range]::-moz-range-thumb {
487
+ width: 18px;
488
+ height: 18px;
489
+ border-radius: 50%;
490
+ background: #0f1511;
491
+ border: 3px solid #5d8269;
391
492
  cursor: pointer;
392
- box-shadow: 0 0 0 3px rgba(193, 12, 255, .1);
393
493
  }
394
494
  .rng input[type=range]:active::-webkit-slider-thumb { background: var(--accent); }
395
495
 
@@ -399,17 +499,17 @@ body::after {
399
499
  min-width: 130px;
400
500
  max-width: 170px;
401
501
  height: 34px;
402
- border: 1px solid #1c1c25;
502
+ border: 1px solid #242d27;
403
503
  border-radius: 4px;
404
- background: #18181f;
405
- color: #d8d5e3;
504
+ background: #0d0f0d;
505
+ color: #ecf4ee;
406
506
  font: 800 12px var(--font);
407
507
  outline: none;
408
508
  padding: 0 10px;
409
509
  }
410
- .ctrl select { color: #787485; cursor: pointer; }
510
+ .ctrl select { color: #c1cbc4; cursor: pointer; }
411
511
  .ctrl input:focus,
412
- .ctrl select:focus { border-color: rgba(193, 12, 255, .75); }
512
+ .ctrl select:focus { border-color: rgba(49, 255, 122, .7); }
413
513
 
414
514
  .color-actions {
415
515
  display: flex;
@@ -426,7 +526,7 @@ body::after {
426
526
  position: relative;
427
527
  overflow: hidden;
428
528
  display: inline-block;
429
- box-shadow: 0 0 0 1px rgba(255,255,255,.08), 0 0 14px rgba(193, 12, 255, .15);
529
+ box-shadow: 0 0 0 1px rgba(255,255,255,.08), 0 0 14px rgba(49, 255, 122, .14);
430
530
  }
431
531
  .clr-btn input[type=color] { opacity: 0; position: absolute; inset: -4px; cursor: pointer; }
432
532
  .clr-btn .swatch { width: 100%; height: 100%; display: block; }
@@ -444,10 +544,12 @@ body::after {
444
544
  .key-btn.listening {
445
545
  color: #fff;
446
546
  border-color: var(--accent);
447
- box-shadow: 0 0 16px rgba(193, 12, 255, .35);
547
+ box-shadow: 0 0 16px rgba(49, 255, 122, .32);
448
548
  }
449
549
 
450
550
  #statusbar {
551
+ position: relative;
552
+ z-index: 1;
451
553
  width: var(--panel-w);
452
554
  min-height: 42px;
453
555
  display: flex;
@@ -455,10 +557,10 @@ body::after {
455
557
  gap: 10px;
456
558
  margin-top: 8px;
457
559
  padding: 0 14px;
458
- border: 1px solid rgba(73, 58, 88, .55);
560
+ border: 1px solid rgba(32, 245, 104, .24);
459
561
  border-radius: var(--radius);
460
- background: rgba(17, 17, 22, .94);
461
- color: #716f80;
562
+ background: rgba(2, 3, 2, .96);
563
+ color: #9aa69f;
462
564
  font-size: 12px;
463
565
  }
464
566
  #statusbar .s-dot {
@@ -479,13 +581,13 @@ body::after {
479
581
  color: #fff;
480
582
  cursor: pointer;
481
583
  font: 900 12px var(--font);
482
- box-shadow: 0 0 16px rgba(193, 12, 255, .24);
584
+ box-shadow: 0 0 16px rgba(49, 255, 122, .22);
483
585
  }
484
586
  #statusbar .s-btn:hover { filter: brightness(1.1); }
485
587
  #statusbar .s-btn:disabled { opacity: .35; cursor: not-allowed; box-shadow: none; }
486
588
  #statusbar .s-btn.stop { background: var(--danger); box-shadow: 0 0 16px rgba(241, 93, 98, .24); }
487
589
  #statusbar .kill-btn {
488
- background: #211827;
590
+ background: #151916;
489
591
  color: #aaa5b8;
490
592
  box-shadow: none;
491
593
  }
@@ -497,27 +599,27 @@ body::after {
497
599
  align-items: center;
498
600
  justify-content: center;
499
601
  z-index: 1000;
500
- background: rgba(7, 7, 11, .96);
602
+ background: #000;
501
603
  }
502
604
  #license-box {
503
605
  width: min(410px, calc(100vw - 34px));
504
606
  padding: 34px 28px;
505
607
  text-align: center;
506
- background: #141419;
507
- border: 1px solid rgba(193, 12, 255, .28);
608
+ background: #050605;
609
+ border: 1px solid rgba(32, 245, 104, .32);
508
610
  border-top-color: var(--accent);
509
611
  border-radius: 8px;
510
- box-shadow: 0 24px 70px rgba(0,0,0,.5);
612
+ box-shadow: 0 24px 70px rgba(0,0,0,.88);
511
613
  }
512
- #license-box .logo-icon { width: 48px; height: 48px; margin: 0 auto 14px; stroke: var(--accent); fill: none; stroke-width: 1.4; }
614
+ #license-box .logo-icon { width: 56px; height: 56px; margin: 0 auto 14px; object-fit: contain; filter: drop-shadow(0 0 16px rgba(49, 255, 122, .24)); }
513
615
  #license-box h1 { font-size: 23px; font-weight: 900; margin-bottom: 4px; }
514
616
  #license-box h1 span { color: var(--accent); }
515
617
  #license-box .subtitle { color: var(--text3); font-size: 12px; margin-bottom: 20px; font-weight: 800; }
516
618
  #license-box input[type=text] {
517
619
  width: 100%;
518
620
  height: 42px;
519
- background: #18181f;
520
- border: 1px solid #262633;
621
+ background: #0a0c0a;
622
+ border: 1px solid #26302a;
521
623
  color: #fff;
522
624
  padding: 0 14px;
523
625
  border-radius: 4px;
@@ -526,7 +628,7 @@ body::after {
526
628
  margin-bottom: 12px;
527
629
  text-align: center;
528
630
  }
529
- #license-box input[type=text]:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(193, 12, 255, .15); }
631
+ #license-box input[type=text]:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(49, 255, 122, .14); }
530
632
  #license-box button {
531
633
  width: 100%;
532
634
  height: 40px;
@@ -549,13 +651,13 @@ body::after {
549
651
  align-items: center;
550
652
  justify-content: center;
551
653
  z-index: 2000;
552
- background: rgba(7, 7, 11, .93);
654
+ background: rgba(0, 0, 0, .96);
553
655
  }
554
656
  #qr-overlay.show { display: flex; }
555
657
  #qr-box {
556
658
  width: min(340px, calc(100vw - 30px));
557
- background: #141419;
558
- border: 1px solid rgba(193, 12, 255, .32);
659
+ background: #050605;
660
+ border: 1px solid rgba(49, 255, 122, .3);
559
661
  border-radius: 8px;
560
662
  padding: 22px;
561
663
  text-align: center;
@@ -563,22 +665,33 @@ body::after {
563
665
  }
564
666
  #qr-box img { width: min(240px, 74vw) !important; height: auto !important; border-radius: 4px !important; }
565
667
 
566
- .esp-preview-card {
567
- grid-column: 2;
568
- grid-row: 1 / span 2;
569
- position: sticky;
570
- top: 0;
668
+ .esp-preview-panel {
669
+ height: 100%;
571
670
  min-height: 430px;
671
+ background: rgba(8, 10, 8, .96);
672
+ border: 1px solid rgba(43, 55, 47, .78);
673
+ border-top-color: rgba(49, 255, 122, .78);
674
+ border-radius: 8px;
675
+ padding: 18px;
676
+ box-shadow: inset 0 1px 0 rgba(255,255,255,.02), 0 18px 42px rgba(0,0,0,.18);
677
+ }
678
+ .esp-preview-panel h3 {
679
+ font-size: 12px;
680
+ color: #819086;
681
+ margin-bottom: 16px;
682
+ font-weight: 900;
683
+ letter-spacing: 0;
572
684
  }
573
685
  .esp-stage {
574
- height: 368px;
686
+ height: calc(100% - 32px);
687
+ min-height: 360px;
575
688
  position: relative;
576
689
  overflow: hidden;
577
690
  border-radius: 6px;
578
691
  background:
579
- linear-gradient(180deg, rgba(38, 41, 58, .82) 0 54%, rgba(24, 33, 28, .92) 54%),
580
- radial-gradient(circle at 72% 42%, rgba(193, 12, 255, .18), transparent 28%);
581
- border: 1px solid #222230;
692
+ linear-gradient(180deg, rgba(22, 27, 24, .9) 0 54%, rgba(12, 23, 15, .94) 54%),
693
+ radial-gradient(circle at 72% 42%, rgba(49, 255, 122, .13), transparent 28%);
694
+ border: 1px solid #202922;
582
695
  }
583
696
  .esp-grid-bg {
584
697
  position: absolute;
@@ -629,6 +742,7 @@ body::after {
629
742
  inset: 18px 16px 12px;
630
743
  border: var(--esp-thick) dashed var(--esp-color);
631
744
  filter: drop-shadow(0 0 7px var(--esp-color));
745
+ z-index: 3;
632
746
  }
633
747
  .esp-box.solid { border-style: solid; }
634
748
  .esp-box.corner { border: 0; }
@@ -657,14 +771,17 @@ body::after {
657
771
  border: 2px solid var(--esp-color);
658
772
  border-radius: 50%;
659
773
  filter: drop-shadow(0 0 8px var(--esp-color));
774
+ z-index: 6;
660
775
  }
661
776
  .esp-skeleton {
662
777
  position: absolute;
663
778
  left: 50%;
664
- top: 43px;
665
- width: 54px;
666
- height: 112px;
779
+ top: 60px;
780
+ width: 58px;
781
+ height: 102px;
667
782
  transform: translateX(-50%);
783
+ z-index: 5;
784
+ pointer-events: none;
668
785
  }
669
786
  .esp-skeleton span {
670
787
  position: absolute;
@@ -672,11 +789,11 @@ body::after {
672
789
  box-shadow: 0 0 8px var(--esp-color);
673
790
  }
674
791
  .esp-skeleton.dashed span { background: repeating-linear-gradient(180deg, var(--esp-color) 0 7px, transparent 7px 11px); }
675
- .esp-skeleton .spine { left: 50%; top: 0; width: var(--esp-thick); height: 72px; transform: translateX(-50%); }
676
- .esp-skeleton .arms { left: 12px; top: 27px; width: 30px; height: var(--esp-thick); transform: rotate(10deg); }
677
- .esp-skeleton .leg { bottom: 0; width: var(--esp-thick); height: 54px; transform-origin: top; }
678
- .esp-skeleton .leg.left { left: 26px; transform: rotate(18deg); }
679
- .esp-skeleton .leg.right { left: 28px; transform: rotate(-18deg); }
792
+ .esp-skeleton .spine { left: 50%; top: 0; width: var(--esp-thick); height: 60px; transform: translateX(-50%); }
793
+ .esp-skeleton .arms { left: 12px; top: 24px; width: 34px; height: var(--esp-thick); transform: rotate(8deg); }
794
+ .esp-skeleton .leg { bottom: 0; width: var(--esp-thick); height: 46px; transform-origin: top; }
795
+ .esp-skeleton .leg.left { left: 27px; transform: rotate(17deg); }
796
+ .esp-skeleton .leg.right { left: 30px; transform: rotate(-17deg); }
680
797
  .esp-bar {
681
798
  position: absolute;
682
799
  top: 20px;
@@ -686,6 +803,7 @@ body::after {
686
803
  border-radius: 999px;
687
804
  overflow: hidden;
688
805
  box-shadow: 0 0 0 1px rgba(255,255,255,.08);
806
+ z-index: 4;
689
807
  }
690
808
  .esp-bar.health { left: 5px; }
691
809
  .esp-bar.armor { right: 5px; }
@@ -706,6 +824,7 @@ body::after {
706
824
  font-weight: 900;
707
825
  white-space: nowrap;
708
826
  text-shadow: 0 1px 4px #000, 0 0 8px var(--esp-color);
827
+ z-index: 7;
709
828
  }
710
829
  .esp-text.top { left: 50%; top: 0; transform: translate(-50%, -100%); }
711
830
  .esp-text.bottom { left: 50%; bottom: -2px; transform: translate(-50%, 100%); }
@@ -721,6 +840,7 @@ body::after {
721
840
  background: var(--esp-color);
722
841
  box-shadow: 0 0 8px var(--esp-color);
723
842
  transform-origin: top;
843
+ z-index: 2;
724
844
  }
725
845
  .esp-line.place-0 { bottom: 0; top: auto; transform: translateX(-50%) rotate(0deg); }
726
846
  .esp-line.place-1 { top: 50%; transform: translate(-50%, -4px) rotate(0deg); }
@@ -735,6 +855,7 @@ body::after {
735
855
  transform: rotate(-19deg);
736
856
  transform-origin: left center;
737
857
  box-shadow: 0 0 8px var(--esp-color);
858
+ z-index: 2;
738
859
  }
739
860
  .esp-offscreen {
740
861
  position: absolute;
@@ -769,8 +890,8 @@ body::after {
769
890
  border-radius: 0;
770
891
  }
771
892
  #sidebar {
772
- width: 74px;
773
- flex-basis: 74px;
893
+ width: 66px;
894
+ flex-basis: 66px;
774
895
  }
775
896
  .brand {
776
897
  height: 58px;
@@ -779,25 +900,15 @@ body::after {
779
900
  font-size: 0;
780
901
  letter-spacing: 0;
781
902
  }
782
- .brand::after {
783
- content: 'S';
784
- display: grid;
785
- place-items: center;
786
- width: 34px;
787
- height: 34px;
788
- border-radius: 50%;
789
- color: #16161d;
790
- background: #f3f2f7;
791
- font-size: 18px;
792
- font-weight: 900;
793
- }
903
+ .brand img { width: 34px; height: 34px; }
904
+ .brand span { display: none; }
794
905
  .nav-scroll { padding: 6px; }
795
906
  .nav-heading {
796
907
  display: none;
797
908
  }
798
909
  .tab-btn {
799
- width: 58px;
800
- height: 50px;
910
+ width: 52px;
911
+ height: 48px;
801
912
  padding: 0;
802
913
  justify-content: center;
803
914
  gap: 0;
@@ -807,7 +918,7 @@ body::after {
807
918
  #topbar {
808
919
  height: auto;
809
920
  min-height: 64px;
810
- padding: 10px 12px;
921
+ padding: 10px 14px;
811
922
  flex-wrap: wrap;
812
923
  gap: 8px;
813
924
  }
@@ -826,17 +937,31 @@ body::after {
826
937
  padding: 7px 9px;
827
938
  font-size: 11px;
828
939
  }
829
- #pages,
830
- #pages.has-preview {
940
+ #workspace {
941
+ overflow-y: auto;
942
+ flex-direction: column;
943
+ }
944
+ #pages {
945
+ flex: 0 0 auto;
946
+ overflow: visible;
831
947
  grid-template-columns: 1fr;
832
- gap: 12px;
833
- padding: 12px;
948
+ gap: 14px;
949
+ padding: 14px;
950
+ }
951
+ #workspace.has-preview #pages {
952
+ flex-basis: auto;
953
+ }
954
+ #esp-preview-shell {
955
+ order: -1;
956
+ flex: 0 0 auto;
957
+ padding: 14px 14px 0;
958
+ overflow: visible;
834
959
  }
835
960
  .child {
836
- padding: 15px 14px;
961
+ padding: 17px 16px;
837
962
  }
838
963
  .ctrl {
839
- min-height: 42px;
964
+ min-height: 46px;
840
965
  gap: 12px;
841
966
  }
842
967
  .ctrl > label:not(.tgl) {
@@ -853,11 +978,11 @@ body::after {
853
978
  max-width: 142px;
854
979
  font-size: 12px;
855
980
  }
856
- .esp-preview-card {
857
- grid-row: auto;
858
- min-height: 390px;
981
+ .esp-preview-panel {
982
+ min-height: 360px;
983
+ height: auto;
859
984
  }
860
- .esp-stage { height: 330px; }
985
+ .esp-stage { height: 300px; min-height: 300px; }
861
986
  #statusbar {
862
987
  position: fixed;
863
988
  left: 0;
@@ -886,23 +1011,20 @@ body::after {
886
1011
 
887
1012
  @media (max-width: 600px) {
888
1013
  #sidebar {
889
- width: 58px;
890
- flex-basis: 58px;
1014
+ width: 54px;
1015
+ flex-basis: 54px;
891
1016
  }
892
1017
  .tab-btn {
893
- width: 44px;
1018
+ width: 42px;
894
1019
  height: 44px;
895
1020
  }
896
1021
  .tab-btn svg { width: 17px; height: 17px; }
897
1022
  .brand { font-size: 0; }
898
1023
  #topbar { padding: 9px 10px; }
899
1024
  .sub-tab { font-size: 10px; padding: 6px 8px; }
900
- .rng { grid-template-columns: 38px 1fr; gap: 8px; }
1025
+ .rng { grid-template-columns: 46px 1fr; gap: 10px; }
901
1026
  .color-row { align-items: flex-start; }
902
1027
  .color-actions { flex-shrink: 0; }
903
- .esp-stage { height: 300px; }
904
- .esp-preview-card {
905
- grid-column: auto;
906
- position: static;
907
- }
1028
+ .esp-stage { height: 280px; min-height: 280px; }
1029
+ .esp-preview-panel { min-height: 334px; }
908
1030
  }
package/public/index.html CHANGED
@@ -10,12 +10,16 @@
10
10
  </head>
11
11
  <body>
12
12
 
13
+ <div id="bg-brand" aria-hidden="true">
14
+ <span class="brand-mark m1">SENSIVITY<br>BEST PRIVATE</span>
15
+ <span class="brand-mark m2">SENSIVITY<br>BEST PRIVATE</span>
16
+ <span class="brand-mark m3">SENSIVITY<br>BEST PRIVATE</span>
17
+ <span class="brand-mark m4">SENSIVITY<br>BEST PRIVATE</span>
18
+ </div>
19
+
13
20
  <div id="license-overlay">
14
21
  <div id="license-box">
15
- <svg class="logo-icon" viewBox="0 0 24 24">
16
- <path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4z"/>
17
- <path d="M9 12l2 2 4-4"/>
18
- </svg>
22
+ <img class="logo-icon" src="/assets/logo.png" alt="Sensivity">
19
23
  <h1>Sensivity <span>License</span></h1>
20
24
  <p class="subtitle">Enter your key to unlock</p>
21
25
  <input type="text" id="license-key" placeholder="SENSIVITY-XXXX-XXXX-XXXX-XXXX-XXXXXXXX" onkeydown="if(event.key==='Enter')submitLicense()">
@@ -28,7 +32,10 @@
28
32
  <div id="sidebar"></div>
29
33
  <div id="content">
30
34
  <div id="topbar"></div>
31
- <div id="pages"></div>
35
+ <div id="workspace">
36
+ <div id="pages"></div>
37
+ <aside id="esp-preview-shell"></aside>
38
+ </div>
32
39
  </div>
33
40
  </div>
34
41
  <div id="statusbar">
package/public/js/app.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const SOCKET = (typeof io !== 'undefined') ? io() : null;
2
2
  let state = {}, currentSection = 0, currentSub = 0;
3
3
  let licenseAccepted = false, cheatRunning = false, listeningKeybind = null;
4
+ let espSyncTimer = null;
4
5
 
5
6
  const SECTION_GROUPS = [
6
7
  { label: 'AIMBOT', ids: ['aim'] },
@@ -48,7 +49,7 @@ function renderSidebar() {
48
49
  }).join('');
49
50
 
50
51
  el.innerHTML = `
51
- <div class="brand">SENSIVITY</div>
52
+ <div class="brand"><img src="/assets/logo.png" alt="Sensivity"><span>SENSIVITY</span></div>
52
53
  <div class="nav-scroll">${grouped}</div>`;
53
54
  }
54
55
 
@@ -67,21 +68,24 @@ function renderTopbar() {
67
68
  <div class="sub-tabs">
68
69
  ${subs.map((x, i) => `<button class="sub-tab${i === currentSub ? ' active' : ''}" onclick="setSub(${i})">${x.label}</button>`).join('')}
69
70
  </div>
70
- <div class="profile-dot">S</div>`;
71
+ <div class="profile-dot"><img src="/assets/logo.png" alt=""></div>`;
71
72
  }
72
73
 
73
74
  function renderPage() {
74
75
  const sub = currentSubData();
75
76
  const pg = document.getElementById('pages');
77
+ const showPreview = shouldShowEspPreview();
78
+ const workspace = document.getElementById('workspace');
79
+ if (workspace) workspace.classList.toggle('has-preview', showPreview);
76
80
  if (!sub || !sub.children || !sub.children.length) {
77
81
  pg.innerHTML = '<div class="child empty-state">No settings</div>';
82
+ renderEspPreviewShell(false);
78
83
  return;
79
84
  }
80
85
 
81
86
  const children = sub.children.map(ch => `<div class="child"><h3>${ch.label}</h3>${(ch.controls || []).map(ctrl).join('')}</div>`).join('');
82
- const preview = shouldShowEspPreview() ? renderEspPreviewCard() : '';
83
- pg.classList.toggle('has-preview', shouldShowEspPreview());
84
- pg.innerHTML = preview + children;
87
+ pg.innerHTML = children;
88
+ renderEspPreviewShell(showPreview);
85
89
  }
86
90
 
87
91
  function prettyLabel(key) {
@@ -96,9 +100,9 @@ function ctrl(c) {
96
100
  case 'checkbox':
97
101
  return `<div class="ctrl"><label>${prettyLabel(c.key)}</label><label class="tgl"><input type="checkbox" id="${id}"${vs ? ' checked' : ''} onchange="set('${c.key}','checkbox',this.checked)"><span class="track"><span class="knob"></span></span></label></div>`;
98
102
  case 'slider_int':
99
- return `<div class="ctrl range-ctrl"><label>${prettyLabel(c.key)}</label><div class="rng"><span class="rng-val">${vs || 0}</span><input type="range" id="${id}" min="${c.min || 0}" max="${c.max || 100}" value="${vs || 0}" oninput="sliderUp('${c.key}','slider_int',this)"></div></div>`;
103
+ return `<div class="ctrl range-ctrl"><label>${prettyLabel(c.key)}</label><div class="rng"><span class="rng-val">${vs || 0}</span><input type="range" id="${id}" min="${c.min || 0}" max="${c.max || 100}" value="${vs || 0}" style="--range-percent:${rangePercent(c, vs || 0)}%" oninput="sliderUp('${c.key}','slider_int',this)"></div></div>`;
100
104
  case 'slider_float':
101
- return `<div class="ctrl range-ctrl"><label>${prettyLabel(c.key)}</label><div class="rng"><span class="rng-val">${parseFloat(vs || 0).toFixed(1)}</span><input type="range" id="${id}" min="${c.min || 0}" max="${c.max || 100}" step="${c.step || 0.1}" value="${vs || 0}" oninput="sliderUp('${c.key}','slider_float',this)"></div></div>`;
105
+ return `<div class="ctrl range-ctrl"><label>${prettyLabel(c.key)}</label><div class="rng"><span class="rng-val">${parseFloat(vs || 0).toFixed(1)}</span><input type="range" id="${id}" min="${c.min || 0}" max="${c.max || 100}" step="${c.step || 0.1}" value="${vs || 0}" style="--range-percent:${rangePercent(c, vs || 0)}%" oninput="sliderUp('${c.key}','slider_float',this)"></div></div>`;
102
106
  case 'dropdown':
103
107
  return `<div class="ctrl"><label>${prettyLabel(c.key)}</label><select id="${id}" onchange="set('${c.key}','dropdown',this.selectedIndex)">${(c.items || []).map((x, i) => `<option value="${i}"${i === vs ? ' selected' : ''}>${x}</option>`).join('')}</select></div>`;
104
108
  case 'color_checkbox': {
@@ -116,7 +120,12 @@ function set(k, t, v) {
116
120
  state[k] = state[k] || { value: false, color: [1, 1, 1, 1] };
117
121
  if (typeof v === 'object') state[k] = v;
118
122
  } else state[k] = v;
123
+ if (shouldAutoEnablePlayerEsp(k, t, state[k])) {
124
+ state['Enable ESP'] = true;
125
+ emit('Enable ESP', 'checkbox', true);
126
+ }
119
127
  emit(k, t, state[k]);
128
+ queuePlayerEspSync(k);
120
129
  rerender();
121
130
  }
122
131
 
@@ -124,7 +133,9 @@ function sliderUp(k, t, el) {
124
133
  const v = t === 'slider_int' ? parseInt(el.value) : parseFloat(el.value);
125
134
  state[k] = v;
126
135
  el.previousElementSibling.textContent = t === 'slider_int' ? v : v.toFixed(1);
136
+ updateRangeFill(el);
127
137
  emit(k, t, v);
138
+ queuePlayerEspSync(k);
128
139
  if (shouldShowEspPreview()) updateEspPreview();
129
140
  }
130
141
 
@@ -134,6 +145,7 @@ function colorUp(k, hex) {
134
145
  cur.color = [r, g, b, cur.color[3] || 1];
135
146
  state[k] = cur;
136
147
  emit(k, 'color_checkbox', cur);
148
+ queuePlayerEspSync(k);
137
149
  rerender();
138
150
  }
139
151
 
@@ -141,6 +153,46 @@ function emit(k, t, v) {
141
153
  if (SOCKET && SOCKET.connected) SOCKET.emit('setConfig', { key: k, type: t, value: v });
142
154
  }
143
155
 
156
+ function rangePercent(c, value) {
157
+ const min = Number(c.min || 0);
158
+ const max = Number(c.max || 100);
159
+ const val = Number(value || 0);
160
+ if (max <= min) return 0;
161
+ return Math.max(0, Math.min(100, ((val - min) / (max - min)) * 100)).toFixed(2);
162
+ }
163
+
164
+ function updateRangeFill(el) {
165
+ const min = Number(el.min || 0);
166
+ const max = Number(el.max || 100);
167
+ const val = Number(el.value || 0);
168
+ const pct = max <= min ? 0 : Math.max(0, Math.min(100, ((val - min) / (max - min)) * 100));
169
+ el.style.setProperty('--range-percent', pct.toFixed(2) + '%');
170
+ }
171
+
172
+ function visualPlayerControls() {
173
+ const visuals = SCHEMA.sections.find(s => s.id === 'visuals');
174
+ const player = visuals && (visuals.subs || []).find(sub => sub.id === 'vplayer');
175
+ if (!player) return [];
176
+ return (player.children || []).flatMap(ch => ch.controls || []);
177
+ }
178
+
179
+ function shouldAutoEnablePlayerEsp(key, type, value) {
180
+ if (key === 'Enable ESP' || type !== 'color_checkbox') return false;
181
+ if (!visualPlayerControls().some(c => c.key === key)) return false;
182
+ return !!(value && value.value) && !state['Enable ESP'];
183
+ }
184
+
185
+ function queuePlayerEspSync(changedKey) {
186
+ const controls = visualPlayerControls();
187
+ if (!controls.some(c => c.key === changedKey)) return;
188
+ clearTimeout(espSyncTimer);
189
+ espSyncTimer = setTimeout(() => {
190
+ controls.forEach(c => {
191
+ if (state[c.key] !== undefined) emit(c.key, c.type, state[c.key]);
192
+ });
193
+ }, 35);
194
+ }
195
+
144
196
  function setSection(i) {
145
197
  currentSection = i;
146
198
  currentSub = 0;
@@ -205,8 +257,10 @@ document.addEventListener('mousedown', function(e) {
205
257
  });
206
258
 
207
259
  function toggleCheat() {
208
- if (!SOCKET || !SOCKET.connected) return;
209
- SOCKET.emit(cheatRunning ? 'stopCheat' : 'startCheat');
260
+ if (!SOCKET) return;
261
+ const eventName = cheatRunning ? 'stopCheat' : 'startCheat';
262
+ SOCKET.emit(eventName);
263
+ if (!SOCKET.connected && typeof SOCKET.connect === 'function') SOCKET.connect();
210
264
  }
211
265
 
212
266
  function updateStatus() {
@@ -244,7 +298,13 @@ function shouldShowEspPreview() {
244
298
  }
245
299
 
246
300
  function renderEspPreviewCard() {
247
- return `<div class="child esp-preview-card"><h3>Live Preview</h3><div class="esp-stage" id="esp-stage">${espPreviewMarkup()}</div></div>`;
301
+ return `<div class="esp-preview-panel"><h3>Live Preview</h3><div class="esp-stage" id="esp-stage">${espPreviewMarkup()}</div></div>`;
302
+ }
303
+
304
+ function renderEspPreviewShell(showPreview) {
305
+ const shell = document.getElementById('esp-preview-shell');
306
+ if (!shell) return;
307
+ shell.innerHTML = showPreview ? renderEspPreviewCard() : '';
248
308
  }
249
309
 
250
310
  function updateEspPreview() {
@@ -191,7 +191,7 @@ const SCHEMA = {
191
191
  label: 'Player',
192
192
  children: [
193
193
  { id: 'espMain', label: 'ESP Settings', controls: [
194
- { key: 'Enable ESP', type: 'checkbox', def: false },
194
+ { key: 'Enable ESP', type: 'checkbox', def: false, bind: true },
195
195
  { key: 'ESP Distance', type: 'slider_int', def: 0, min: 0, max: 3000 },
196
196
  { key: 'ESP Show Local Player', type: 'checkbox', def: false },
197
197
  { key: 'ESP Ignore Invisible', type: 'checkbox', def: false },
@@ -343,7 +343,13 @@ const SCHEMA = {
343
343
  subs: [{
344
344
  id: 'wmain',
345
345
  label: 'Teleport',
346
- children: []
346
+ children: [
347
+ { id: 'worldTeleport', label: 'World Teleport', controls: [
348
+ { key: 'Enable Freecam', type: 'checkbox', def: false, bind: true },
349
+ { key: 'Freecam Speed', type: 'slider_float', def: 100, min: 1, max: 1000, step: 1 },
350
+ { key: 'Freecam Teleport', type: 'checkbox', def: false, bind: true },
351
+ ]},
352
+ ]
347
353
  }]
348
354
  },
349
355
  {