forked from nautilus-os/GUST
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGUST-Patcher.html
More file actions
2047 lines (1916 loc) · 123 KB
/
Copy pathGUST-Patcher.html
File metadata and controls
2047 lines (1916 loc) · 123 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>GUST Patcher</title>
<link rel="preconnect" href="https://fonts.googleapis.com"/>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600&family=Space+Grotesk:wght@400;500;600;700&display=swap"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"/>
<style>
:root {
--bg0: #0d0f12;
--bg1: #181c21;
--bg2: #1c2026;
--bg3: #252b33;
--bg-elevated: #161a1f;
--main-bg: #13161a;
--surface: rgba(255,255,255,.08);
--surface2: rgba(255,255,255,.14);
--bd: #4f5963;
--bd2: #5a6370;
--tx: #f0f4f8;
--tx2: #b8c4d0;
--tx3: #7d8a98;
--ac: #9de5ff;
--ac2: #70d4ff;
--ok: #8aefb0;
--warn: #f8dc75;
--err: #ff9595;
--radius-sm: 8px;
--radius-md: 10px;
--radius-lg: 20px;
--radius-full: 9999px;
--shadow-sm: 0 1px 3px rgba(0,0,0,.35);
--shadow-md: 0 8px 24px rgba(0,0,0,.45);
--ui: 'Space Grotesk','Segoe UI',sans-serif;
--mono: 'JetBrains Mono','SF Mono',ui-monospace,monospace;
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%;background:var(--bg0);color:var(--tx);font-family:var(--ui);overflow:hidden}
button,input,select,textarea{font:inherit}
::selection{background:rgba(141,217,255,.25);color:var(--tx)}
.app{height:100%;display:flex;flex-direction:column}
/* Titlebar */
.titlebar{display:flex;align-items:center;gap:12px;padding:8px 12px;background:var(--bg0);border-bottom:1px solid var(--bd);}
.brand{display:flex;align-items:center;gap:8px;color:var(--ac);font-weight:700;font-size:14px;white-space:nowrap;height:42px;padding:0 2px;}
.brand-letters{display:inline-flex;letter-spacing:3px;font-size:22px;font-weight:800;}
.brand-sub{font-size:22px;font-weight:800;color:var(--ac);margin-left:2px;letter-spacing:3px;}
.titlebar-actions{display:flex;align-items:center;gap:8px;margin-left:auto;}
/* GUST animations (exact copy) */
@keyframes gust-icon{0%{opacity:0;transform:translateX(-44px);filter:blur(8px)}65%{opacity:1;transform:translateX(4px);filter:blur(0)}100%{opacity:1;transform:translateX(0)}}
@keyframes gust-letter{0%{opacity:0;transform:translateX(-28px) skewX(-12deg);filter:blur(6px)}60%{opacity:1;transform:translateX(3px) skewX(2deg);filter:blur(0)}80%{transform:translateX(-1px) skewX(-.5deg)}100%{opacity:1;transform:translateX(0) skewX(0);filter:blur(0)}}
@keyframes gust-sub{0%{opacity:0;transform:translateY(4px)}100%{opacity:1;transform:translateY(0)}}
.gust-icon-anim{animation:gust-icon .7s cubic-bezier(.22,1,.36,1) both;animation-play-state:paused}
.gust-letter-G{animation:gust-letter .65s cubic-bezier(.22,1,.36,1) .10s both;animation-play-state:paused}
.gust-letter-U{animation:gust-letter .65s cubic-bezier(.22,1,.36,1) .20s both;animation-play-state:paused}
.gust-letter-S{animation:gust-letter .65s cubic-bezier(.22,1,.36,1) .30s both;animation-play-state:paused}
.gust-letter-T{animation:gust-letter .65s cubic-bezier(.22,1,.36,1) .40s both;animation-play-state:paused}
.gust-sub-anim{animation:gust-sub .45s ease-out .65s both;animation-play-state:paused}
.brand-anim-ready .gust-icon-anim,
.brand-anim-ready .gust-letter-G,
.brand-anim-ready .gust-letter-U,
.brand-anim-ready .gust-letter-S,
.brand-anim-ready .gust-letter-T,
.brand-anim-ready .gust-sub-anim{animation-play-state:running}
/* Buttons */
.btn-primary{display:flex;align-items:center;gap:7px;padding:0 16px;height:36px;background:var(--ac);color:#0b1015;font-weight:700;font-size:13px;border:none;border-radius:8px;cursor:pointer;transition:opacity .15s,transform .1s}
.btn-primary:hover{opacity:.85}
.btn-primary:active{transform:scale(.97)}
.btn-primary:disabled{opacity:.4;cursor:not-allowed;transform:none}
.btn-secondary{display:flex;align-items:center;gap:7px;padding:0 14px;height:36px;background:var(--bg2);color:var(--tx2);font-weight:500;font-size:13px;border:1px solid var(--bd);border-radius:8px;cursor:pointer;transition:background .12s,color .12s}
.btn-secondary:hover{background:var(--bg3);color:var(--tx)}
/* Layout */
.layout{flex:1;display:flex;overflow:hidden}
/* Sidebar — 200px wide, matching GUST exactly */
.sidebar{width:200px;min-width:200px;height:100%;background:rgba(13,15,18,.7);border-right:1px solid var(--bd);display:flex;flex-direction:column;backdrop-filter:blur(8px);overflow:hidden;}
.sidebar-scroll{flex:1;overflow-y:auto;overflow-x:hidden;padding:24px 0;}
.sidebar-scroll::-webkit-scrollbar{width:3px}
.sidebar-scroll::-webkit-scrollbar-track{background:transparent}
.sidebar-scroll::-webkit-scrollbar-thumb{background:var(--bd);border-radius:3px}
.sidebar nav{display:flex;flex-direction:column;gap:2px;padding:0 12px;}
/* Nav items — GUST values: padding 9px 14px, radius 8px, size 13px, tx3 */
.settings-nav-item{display:flex;align-items:center;gap:10px;padding:9px 14px;border-radius:8px;border:none;background:transparent;color:var(--tx3);font-size:13px;font-weight:500;font-family:var(--ui);cursor:pointer;text-align:left;width:100%;transition:background .12s,color .12s}
.settings-nav-item i{width:16px;text-align:center;font-size:13px;transition:color .12s}
.settings-nav-item:hover{background:var(--surface);color:var(--tx2)}
.settings-nav-item.active{background:rgba(157,229,255,.1);color:var(--ac)}
.settings-nav-item.active i{color:var(--ac)}
.nav-label{flex:1}
/* ── Sidebar icon micro-animations ── */
@keyframes _gust-pulse { 0%,100%{transform:scale(1)} 50%{transform:scale(1.22)} }
@keyframes _gust-spin { from{transform:rotate(0deg)} to{transform:rotate(360deg)} }
@keyframes _gust-spinrev { from{transform:rotate(0deg)} to{transform:rotate(-360deg)} }
@keyframes _gust-bob { 0%,100%{transform:translateY(0)} 40%{transform:translateY(-4px)} 70%{transform:translateY(2px)} }
@keyframes _gust-shake { 0%,100%{transform:rotate(0)} 20%{transform:rotate(-12deg)} 50%{transform:rotate(12deg)} 75%{transform:rotate(-7deg)} }
@keyframes _gust-ping { 0%{transform:scale(1)} 40%{transform:scale(1.28)} 65%{transform:scale(.88)} 100%{transform:scale(1)} }
@keyframes _gust-tilt { 0%,100%{transform:rotate(0deg)} 30%{transform:rotate(-14deg)} 70%{transform:rotate(10deg)} }
@keyframes _gust-pop { 0%{transform:scale(1)} 35%{transform:scale(1.3)} 60%{transform:scale(.92)} 80%{transform:scale(1.08)} 100%{transform:scale(1)} }
@keyframes _gust-beam { 0%,100%{transform:scaleX(1) scaleY(1)} 40%{transform:scaleX(1.2) scaleY(.85)} 70%{transform:scaleX(.9) scaleY(1.1)} }
@keyframes _gust-flick { 0%,100%{transform:rotate(0) scale(1)} 25%{transform:rotate(-8deg) scale(1.15)} 60%{transform:rotate(6deg) scale(.95)} }
@keyframes _gust-jolt { 0%,100%{transform:translateX(0)} 20%{transform:translateX(-4px)} 50%{transform:translateX(5px)} 75%{transform:translateX(-2px)} }
@keyframes _gust-stamp { 0%{transform:scale(1) translateY(0)} 35%{transform:scale(.82) translateY(3px)} 65%{transform:scale(1.12) translateY(-2px)} 100%{transform:scale(1) translateY(0)} }
/* Connection — wired: pulse like signal */
.settings-nav-item[data-section="connection"]:hover i { animation: _gust-pulse .55s cubic-bezier(.34,1.56,.64,1) forwards; }
/* Search — magnifying glass: bob */
.settings-nav-item[data-section="search"]:hover i { animation: _gust-bob .45s ease forwards; }
/* Privacy — shield: ping */
.settings-nav-item[data-section="privacy"]:hover i { animation: _gust-ping .4s ease forwards; }
/* Cache — database: beam (squish like stacking) */
.settings-nav-item[data-section="cache"]:hover i { animation: _gust-beam .45s ease forwards; }
/* Files & Media — film: shake (film reel clatter) */
.settings-nav-item[data-section="filesandmedia"]:hover i { animation: _gust-shake .45s ease forwards; }
/* Appearance — palette: spin */
.settings-nav-item[data-section="appearance"]:hover i { animation: _gust-spin .5s cubic-bezier(.34,1.56,.64,1) forwards; }
/* Home Screen — house: bob */
.settings-nav-item[data-section="homescreen"]:hover i { animation: _gust-bob .42s ease forwards; }
/* Shortcuts — keyboard: tilt (like pressing a key) */
.settings-nav-item[data-section="shortcuts"]:hover i { animation: _gust-tilt .4s ease forwards; }
/* Tutorial (Core) — map: pop */
.settings-nav-item[data-section="core-tutorial"]:hover i { animation: _gust-pop .45s ease forwards; }
/* Language — globe: spin reverse */
.settings-nav-item[data-section="language"]:hover i { animation: _gust-spinrev .5s cubic-bezier(.34,1.56,.64,1) forwards; }
/* Tab System — window-restore: flick (like flipping a tab) */
.settings-nav-item[data-section="core-tabs"]:hover i { animation: _gust-flick .4s ease forwards; }
/* Ad Blocker (Core) — shield: ping */
.settings-nav-item[data-section="core-adblock"]:hover i { animation: _gust-ping .4s ease forwards; }
/* Dev Tools — server: jolt (like a server rack vibrating) */
.settings-nav-item[data-section="core-devtools"]:hover i { animation: _gust-jolt .4s ease forwards; }
/* Metrics — chart: stamp (bars pressing down) */
.settings-nav-item[data-section="core-metrics"]:hover i { animation: _gust-stamp .45s ease forwards; }
/* Fallback — rotate-left: simple spin like reload button */
.settings-nav-item[data-section="fallback"]:hover i { transform: rotate(-180deg); transition: transform .35s cubic-bezier(.34,1.56,.64,1); }
/* #/# badge */
.nav-count{margin-left:auto;font-size:10px;font-weight:600;font-family:var(--mono);color:var(--tx3)}
.nav-count.lit{color:var(--ac)}
.sidebar-divider{border:none;border-top:1px solid var(--bd);margin:4px 4px;flex-shrink:0}
.sidebar-core-label{font-size:10px;font-weight:700;letter-spacing:.1em;color:var(--tx3);text-transform:uppercase;padding:8px 14px 4px;flex-shrink:0}
/* Main — GUST: padding 40px 48px, gap 32px */
.main{flex:1;overflow-y:auto;padding:40px 48px;display:flex;flex-direction:column;gap:32px;background:var(--main-bg)}
.main::-webkit-scrollbar{width:5px}
.main::-webkit-scrollbar-track{background:transparent}
.main::-webkit-scrollbar-thumb{background:var(--bd);border-radius:3px}
/* Settings sections — GUST: display none, flex-col, gap 16px */
.settings-section{display:none;flex-direction:column;gap:16px}
.settings-section.active{display:flex}
/* Settings card — GUST: bg2, bd, radius 12px */
.settings-card{background:var(--bg2);border:1px solid var(--bd);border-radius:12px;overflow:hidden}
/* Card head — GUST: padding 13px 18px, size 13px, weight 600, color tx, bg bg1 */
.settings-card-head{padding:13px 18px;font-size:13px;font-weight:600;color:var(--tx);background:var(--bg1);border-bottom:1px solid var(--bd);display:flex;align-items:center;gap:8px}
.settings-card-head i{color:var(--ac)}
/* Card body — GUST: padding 18px */
.settings-card-body{padding:18px}
/* GUST hint — 11px, tx3 */
.settings-hint{font-size:11px;color:var(--tx3);margin-top:6px;line-height:1.5}
/* GUST label — uppercase, 12px, tx3 */
.settings-label{font-size:12px;color:var(--tx3);margin-bottom:8px;display:block;text-transform:uppercase}
/* Patch rows */
.patch-row{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:10px 0}
.patch-row+.patch-row{border-top:1px solid var(--bd)}
.patch-row-info{flex:1;min-width:0}
.patch-row-label{font-size:13px;font-weight:500;color:var(--tx);margin-bottom:2px}
.patch-row-desc{font-size:11px;color:var(--tx3);line-height:1.5}
.broken-tag{font-size:10px;font-weight:700;color:#ff4444;margin-left:4px}
/* Checkbox — styled to match GUST's switch on/off feel */
.patch-check{width:22px;height:22px;border-radius:6px;border:2px solid var(--bd);background:var(--bg3);cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px;transition:border-color .15s,background .15s}
.patch-check.checked{border-color:var(--ac);background:rgba(157,229,255,.15)}
.patch-check.checked::after{content:'\f00c';font-family:'Font Awesome 6 Free';font-weight:900;font-size:11px;color:var(--ac)}
.patch-check.master-disabled{opacity:0.28;cursor:not-allowed;pointer-events:none;}
.patch-row.master-disabled{opacity:0.35;pointer-events:none;transition:opacity .18s;}
.settings-card.master-disabled{opacity:0.35;pointer-events:none;transition:opacity .18s;}
/* Sidebar master toggle bar */
.sidebar-master-bar{display:flex;align-items:center;gap:14px;padding:13px 18px;background:var(--bg2);border:2px solid var(--ac);border-radius:12px;margin-bottom:0;}
.sidebar-master-bar-icon{width:34px;height:34px;border-radius:9px;background:rgba(157,229,255,0.1);display:flex;align-items:center;justify-content:center;color:var(--ac);font-size:14px;flex-shrink:0;}
.sidebar-master-bar-info{flex:1;min-width:0;}
.sidebar-master-bar-label{font-size:13px;font-weight:700;color:var(--tx);margin-bottom:2px;}
.sidebar-master-bar-desc{font-size:11px;color:var(--tx3);line-height:1.4;}
.sidebar-master-check{width:24px;height:24px;border-radius:7px;border:2px solid rgba(157,229,255,0.35);background:rgba(157,229,255,0.06);cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:border-color .15s,background .15s;}
.sidebar-master-check.checked{border-color:var(--ac);background:rgba(157,229,255,0.15);}
.sidebar-master-check.checked::after{content:'\f00c';font-family:'Font Awesome 6 Free';font-weight:900;font-size:12px;color:var(--ac);}
/* Section header */
.section-head{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap}
.section-title{font-size:18px;font-weight:700;color:var(--tx)}
.select-btns{display:flex;align-items:center;gap:6px}
.select-btn{font-size:11px;color:var(--ac);background:none;border:none;cursor:pointer;padding:2px 0;opacity:.65;transition:opacity .12s}
.select-btn:hover{opacity:1}
.select-sep{color:var(--bd2);font-size:10px}
/* Status bar */
.status-bar{padding:8px 16px;background:var(--bg-elevated);border-top:1px solid var(--bd);display:flex;align-items:center;gap:12px;font-size:12px;color:var(--tx3)}
/* Loading overlay */
.loading-overlay{position:fixed;inset:0;background:rgba(13,15,18,.88);backdrop-filter:blur(8px);z-index:9999;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px}
.loading-spinner{width:40px;height:40px;border:3px solid var(--bd);border-top-color:var(--ac);border-radius:50%;animation:spin .8s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.loading-text{font-size:14px;color:var(--tx2)}
.loading-sub{font-size:12px;color:var(--tx3)}
/* Error */
.error-box{background:rgba(255,149,149,.07);border:1px solid rgba(255,149,149,.25);border-radius:12px;padding:20px;display:flex;flex-direction:column;align-items:center;gap:10px;text-align:center}
.error-box i{font-size:28px;color:var(--err)}
.error-box h3{color:var(--err);font-size:14px}
.error-box p{color:var(--tx3);font-size:12px;line-height:1.6}
/* ── Homepage section ── */
.homepage-section{display:none;flex-direction:column;align-items:center;justify-content:flex-start;min-height:100%;width:100%}
.homepage-section.active{display:flex}
.homepage-hero{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:80px 40px 28px;width:100%}
.homepage-brand-wrap{display:flex;align-items:center;gap:14px}
.hp-brand-letters{display:inline-flex;letter-spacing:5px;font-size:56px;font-weight:800;color:var(--ac)}
.hp-brand-sub{font-size:56px;font-weight:800;color:var(--ac);margin-left:4px;letter-spacing:4px}
.hp-icon{font-size:64px;color:var(--ac)}
.homepage-tagline{font-size:13px;font-weight:700;color:#ffffff;margin-top:10px;letter-spacing:0.04em}
.homepage-credits{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--tx3);margin-top:16px}
.homepage-credits .heart{color:#f87171}
.homepage-credits strong{color:var(--tx2);font-weight:600}
.homepage-presets{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px;width:100%;max-width:720px;padding:0 40px 52px}
.preset-card{background:var(--bg2);border:1px solid var(--bd);border-radius:16px;overflow:hidden;display:flex;flex-direction:column;transition:border-color .18s,transform .15s,box-shadow .18s}
.preset-card:hover{border-color:var(--bd2);transform:translateY(-3px);box-shadow:0 16px 40px rgba(0,0,0,.5)}
.preset-card-head{padding:18px 20px 14px;background:var(--bg1);border-bottom:1px solid var(--bd);display:flex;align-items:center;gap:12px}
.preset-card-icon{width:40px;height:40px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:17px;flex-shrink:0}
.preset-card-icon.blue{background:rgba(157,229,255,.12);color:var(--ac)}
.preset-card-icon.green{background:rgba(138,239,176,.12);color:var(--ok)}
.preset-card-icon.amber{background:rgba(248,220,117,.12);color:var(--warn)}
.preset-card-title{font-size:15px;font-weight:700;color:var(--tx);line-height:1.2}
.preset-card-subtitle{font-size:11px;color:var(--tx3);margin-top:2px}
.preset-card-body{padding:16px 20px 12px;flex:1;display:flex;flex-direction:column;gap:5px}
.preset-card-desc{font-size:13px;color:var(--tx2);line-height:1.6;flex:1}
.preset-card-tags{display:flex;flex-wrap:wrap;gap:4px;margin-top:5px}
.preset-tag{font-size:10px;font-weight:600;padding:2px 7px;border-radius:99px;background:rgba(255,255,255,.06);color:var(--tx3);border:1px solid var(--bd)}
.preset-tag.ac{background:rgba(157,229,255,.1);color:var(--ac);border-color:rgba(157,229,255,.2)}
.preset-tag.ok{background:rgba(138,239,176,.1);color:var(--ok);border-color:rgba(138,239,176,.2)}
.preset-tag.warn{background:rgba(248,220,117,.1);color:var(--warn);border-color:rgba(248,220,117,.2)}
.preset-card-footer{padding:12px 20px 18px}
.preset-dl-btn{display:flex;align-items:center;justify-content:center;gap:7px;width:100%;padding:0;height:38px;border-radius:9px;font-weight:700;font-size:13px;border:none;cursor:pointer;transition:opacity .15s,transform .1s;font-family:var(--ui);margin-bottom:6px}
.preset-dl-btn.primary{background:var(--ac);color:#0b1015}
.preset-dl-btn.secondary{background:var(--bg3);color:var(--tx2);border:1px solid var(--bd)}
.preset-dl-btn:hover{opacity:.85}
.preset-dl-btn:active{transform:scale(.97)}
.preset-dl-btn:disabled{opacity:.4;cursor:not-allowed;transform:none}
.preset-source-note{font-size:10px;color:var(--tx3);text-align:center;display:flex;align-items:center;justify-content:center;gap:4px}
.recommended-badge{display:inline-flex;align-items:center;gap:4px;font-size:10px;font-weight:700;padding:2px 8px;border-radius:99px;background:rgba(157,229,255,.13);color:var(--ac);border:1px solid rgba(157,229,255,.35);letter-spacing:.04em;text-transform:uppercase;}
/* Tutorial overlay */
#patcherTutorialOverlay{position:fixed;inset:0;z-index:99999;pointer-events:all;display:none}
#patcherTutorialBackdrop{position:absolute;inset:0;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);transition:opacity .35s;opacity:0;pointer-events:all}
#patcherTutorialSvg{position:absolute;inset:0;width:100%;height:100%;pointer-events:all;transition:opacity .35s;opacity:0}
#patcherTutorialCard{position:absolute;width:360px;background:var(--bg2);border:1px solid var(--ac);border-radius:16px;padding:24px 26px 20px;box-shadow:0 12px 50px rgba(0,0,0,.7),0 0 0 1px rgba(100,210,255,.08);pointer-events:all;transition:opacity .25s,transform .25s;opacity:0;transform:translateY(8px);z-index:10}
#patcherTutorialArrow{position:absolute;width:12px;height:12px;background:var(--bg2);border:1px solid var(--ac);display:none;transform:rotate(45deg);z-index:-1}
#patcherTutorialRing{position:absolute;pointer-events:none;border:1.5px solid #9de5ff;border-radius:8px;display:none;z-index:3}
</style>
</head>
<body>
<div class="app">
<div class="loading-overlay" id="loadingOverlay">
<div class="loading-spinner"></div>
<div class="loading-text">Fetching GUST source…</div>
<div class="loading-sub" id="loadingSub">Connecting…</div>
</div>
<div class="titlebar">
<div class="brand">
<i class="fas fa-wind gust-icon-anim" style="font-size:18px"></i>
<span class="brand-letters"><span class="gust-letter-G">G</span><span class="gust-letter-U">U</span><span class="gust-letter-S">S</span><span class="gust-letter-T">T</span></span>
<span class="brand-sub gust-sub-anim">Patcher</span>
</div>
<div style="display:flex;align-items:center;gap:5px;font-size:13px;font-weight:700;color:#ffffff;margin-left:-4px;white-space:nowrap;position:relative;top:3px;">Made with <i class="fas fa-heart" style="color:#f87171;font-size:12px;margin:0 2px;"></i> by <strong style="font-weight:700;">Nautilus Labs</strong></div>
<div class="titlebar-actions">
<button class="btn-secondary" id="reloadSourceBtn"><i class="fas fa-rotate-right"></i> Refresh Source</button>
<button class="btn-secondary" id="pasteSourceBtn" title="Paste GUST source manually"><i class="fas fa-paste"></i> Paste Source</button>
<button class="btn-secondary" id="githubBtn" onclick="window.open('https://github.com/nautilus-os/GUST','_blank')" title="View GUST on GitHub" style="padding:0;width:36px;justify-content:center;"><i class="fab fa-github" style="font-size:17px;line-height:1"></i></button>
<button class="btn-primary" id="downloadBtn" disabled><i class="fas fa-download"></i> Download Patched GUST</button>
</div>
</div>
<div class="layout">
<div class="sidebar">
<div class="sidebar-scroll">
<div class="sidebar-core-label" style="padding-top:8px;">Patcher</div>
<nav id="settingsNav" style="padding:0 12px;margin-bottom:8px;">
<button class="settings-nav-item active" data-section="homepage"><i class="fas fa-house-chimney"></i><span class="nav-label">Home</span></button>
</nav>
<hr class="sidebar-divider" style="margin:4px 12px 8px">
<div class="sidebar-core-label">Settings</div>
<nav id="settingsNav2" style="padding:0 12px;">
<button class="settings-nav-item" data-section="connection"><i class="fas fa-network-wired"></i><span class="nav-label">Connection</span><span class="nav-count" id="nc-connection"></span></button>
<button class="settings-nav-item" data-section="fallback"><i class="fas fa-rotate-left"></i><span class="nav-label">Fallback</span><span class="nav-count" id="nc-fallback"></span></button>
<button class="settings-nav-item" data-section="search"><i class="fas fa-magnifying-glass"></i><span class="nav-label">Search</span><span class="nav-count" id="nc-search"></span></button>
<button class="settings-nav-item" data-section="privacy"><i class="fas fa-shield-halved"></i><span class="nav-label">Privacy</span><span class="nav-count" id="nc-privacy"></span></button>
<button class="settings-nav-item" data-section="cache"><i class="fas fa-database"></i><span class="nav-label">Cache</span><span class="nav-count" id="nc-cache"></span></button>
<button class="settings-nav-item" data-section="filesandmedia"><i class="fas fa-photo-film"></i><span class="nav-label">Files & Media</span><span class="nav-count" id="nc-filesandmedia"></span></button>
<button class="settings-nav-item" data-section="appearance"><i class="fas fa-palette"></i><span class="nav-label">Appearance</span><span class="nav-count" id="nc-appearance"></span></button>
<button class="settings-nav-item" data-section="homescreen"><i class="fas fa-house"></i><span class="nav-label">Home Screen</span><span class="nav-count" id="nc-homescreen"></span></button>
<button class="settings-nav-item" data-section="shortcuts"><i class="fas fa-keyboard"></i><span class="nav-label">Shortcuts</span><span class="nav-count" id="nc-shortcuts"></span></button>
<button class="settings-nav-item" data-section="language"><i class="fas fa-language"></i><span class="nav-label">Language</span><span class="nav-count" id="nc-language"></span></button>
</nav>
<hr class="sidebar-divider" style="margin-top:8px">
<div class="sidebar-core-label">Core Features</div>
<nav id="coreNav" style="padding:0 12px">
<button class="settings-nav-item" data-section="core-tutorial"><i class="fas fa-map"></i><span class="nav-label">Tutorial</span><span class="nav-count" id="nc-core-tutorial"></span></button>
<button class="settings-nav-item" data-section="core-tabs"><i class="fas fa-window-restore"></i><span class="nav-label">Tab System</span><span class="nav-count" id="nc-core-tabs"></span></button>
<button class="settings-nav-item" data-section="core-adblock"><i class="fas fa-shield-halved"></i><span class="nav-label">Ad Blocker</span><span class="nav-count" id="nc-core-adblock"></span></button>
<button class="settings-nav-item" data-section="core-devtools"><i class="fas fa-server"></i><span class="nav-label">Dev Tools</span><span class="nav-count" id="nc-core-devtools"></span></button>
<button class="settings-nav-item" data-section="core-metrics"><i class="fas fa-chart-simple"></i><span class="nav-label">Metrics</span><span class="nav-count" id="nc-core-metrics"></span></button>
</nav>
</div>
</div>
<div class="main" id="mainContent">
<!-- HOMEPAGE -->
<div class="homepage-section active" data-section="homepage">
<div class="homepage-hero">
<div class="homepage-brand-wrap">
<i class="fas fa-wind hp-icon gust-icon-anim" id="hp-wind-icon"></i>
<span class="hp-brand-letters">
<span class="gust-letter-G">G</span><span class="gust-letter-U">U</span><span class="gust-letter-S">S</span><span class="gust-letter-T">T</span>
</span>
<span class="hp-brand-sub gust-sub-anim">Patcher</span>
</div>
<div class="homepage-tagline">Customize your GUST build before you download it.</div>
</div>
<div class="homepage-presets" id="homepagePresets">
<!-- Card 1: Base GUST -->
<div class="preset-card">
<div class="preset-card-head">
<div class="preset-card-icon blue"><i class="fab fa-github"></i></div>
<div style="flex:1;min-width:0;">
<div style="display:flex;align-items:center;gap:7px;flex-wrap:wrap;"><span class="preset-card-title">Base GUST</span><span class="recommended-badge"><i class="fas fa-star" style="font-size:8px;"></i> Recommended</span></div>
<div class="preset-card-subtitle">Straight from GitHub</div>
</div>
</div>
<div class="preset-card-body">
<div class="preset-card-desc">Download the latest unmodified GUST source directly from the official GitHub repository with no custom patches applied. The most stable version of GUST, and the team at Nautilus Labs's recommended build.</div>
</div>
<div class="preset-card-footer">
<button class="preset-dl-btn primary" id="presetBaseBtn" onclick="downloadBaseGUST()"><i class="fas fa-download"></i> Download Base GUST</button>
</div>
</div>
<!-- Card 2: GUST Lite Preset -->
<div class="preset-card">
<div class="preset-card-head">
<div class="preset-card-icon green"><i class="fas fa-feather"></i></div>
<div>
<div class="preset-card-title">GUST Lite</div>
<div class="preset-card-subtitle">Trimmed-down build</div>
</div>
</div>
<div class="preset-card-body">
<div class="preset-card-desc">Removes thread controls, favicon proxying, WebRTC blocking, smart request headers, spellcheck, request & page user-agent spoofing, dev console logs, dev inspector, metrics, and the language picker.</div>
</div>
<div class="preset-card-footer">
<button class="preset-dl-btn primary" id="presetStealthBtn" onclick="downloadPreset('stealth')" disabled><i class="fas fa-download"></i> Download GUST Lite</button>
</div>
</div>
</div>
</div>
<!-- LANGUAGE -->
<div class="settings-section" data-section="language">
<div class="section-head"><div class="section-title">Language</div><div class="select-btns"><button class="select-btn" onclick="selectAll('language',true)">Select all</button><span class="select-sep">·</span><button class="select-btn" onclick="selectAll('language',false)">None</button></div></div>
<div class="sidebar-master-bar">
<div class="sidebar-master-bar-icon"><i class="fas fa-table-list"></i></div>
<div class="sidebar-master-bar-info">
<div class="sidebar-master-bar-label">Show Language in Settings Sidebar</div>
<div class="sidebar-master-bar-desc">Uncheck to remove the <strong>Language</strong> entry from GUST's Settings sidebar. The (non-functional) language picker panel will be hidden and its nav entry removed entirely.</div>
</div>
<div class="sidebar-master-check checked" data-patch="sidebar-nav-language" data-section="language" data-master-for="language" onclick="toggleSidebarMaster(this)"></div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-language"></i> Language <span class="broken-tag">[BROKEN]</span></div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Preferred language picker <span class="broken-tag">broken</span></div><div class="patch-row-desc">Removes the language selector from Settings. It is non-functional in base GUST — no behaviour change.</div></div><div class="patch-check checked" data-patch="language" data-section="language" onclick="togglePatch(this)"></div></div>
</div>
</div>
</div>
<!-- CONNECTION -->
<div class="settings-section" data-section="connection">
<div class="section-head"><div class="section-title">Connection</div><div class="select-btns"><button class="select-btn" onclick="selectAll('connection',true)">Select all</button><span class="select-sep">·</span><button class="select-btn" onclick="selectAll('connection',false)">None</button></div></div>
<div class="sidebar-master-bar">
<div class="sidebar-master-bar-icon"><i class="fas fa-table-list"></i></div>
<div class="sidebar-master-bar-info">
<div class="sidebar-master-bar-label">Show Connection in Settings Sidebar</div>
<div class="sidebar-master-bar-desc">Uncheck to remove the <strong>Connection</strong> entry from GUST's Settings sidebar. WISP URL, thread controls, WebRTC blocking, and smart headers will all be hidden from Settings and locked to their defaults.</div>
</div>
<div class="sidebar-master-check checked" data-patch="sidebar-nav-connection" data-section="connection" data-master-for="wisp-url threads webrtc-block media-headers" onclick="toggleSidebarMaster(this)"></div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-network-wired"></i> WISP Server</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">WebSocket URL input</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the WISP server URL input from Settings. The default server (wss://wisp.mercurywork.shop/) will always be used with no way to change it at runtime.</div></div><div class="patch-check checked" data-patch="wisp-url" data-section="connection" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-sliders"></i> Concurrent Requests</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Idle & active thread steppers</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the thread count controls and retry counters from Settings. Defaults (idle: 3, active: 6, retries: 3) will be locked in permanently.</div></div><div class="patch-check checked" data-patch="threads" data-section="connection" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-ban"></i> WebRTC Blocking</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Block WebRTC connections</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> WebRTC blocking and remove its toggle from Settings. P2P connections will be able to bypass the WISP proxy and may leak the real IP.</div></div><div class="patch-check checked" data-patch="webrtc-block" data-section="connection" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-shield-halved"></i> Smart Request Headers</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Spoof Sec-Fetch & Referer headers</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> smart header spoofing and remove its toggle from Settings. Some CDNs may reject requests with missing or incorrect fetch metadata headers.</div></div><div class="patch-check checked" data-patch="media-headers" data-section="connection" onclick="togglePatch(this)"></div></div>
</div>
</div>
</div>
<!-- FALLBACK -->
<div class="settings-section" data-section="fallback">
<div class="section-head"><div class="section-title">Fallback WISP</div><div class="select-btns"><button class="select-btn" onclick="selectAll('fallback',true)">Select all</button><span class="select-sep">·</span><button class="select-btn" onclick="selectAll('fallback',false)">None</button></div></div>
<div class="sidebar-master-bar">
<div class="sidebar-master-bar-icon"><i class="fas fa-table-list"></i></div>
<div class="sidebar-master-bar-info">
<div class="sidebar-master-bar-label">Show Fallback in Settings Sidebar</div>
<div class="sidebar-master-bar-desc">Uncheck to remove the <strong>Fallback</strong> entry from GUST's Settings sidebar. The fallback toggle, fallback WISP URL, retry policy, and error triggers will all be hidden from Settings.</div>
</div>
<div class="sidebar-master-check checked" data-patch="sidebar-nav-fallback" data-section="fallback" data-master-for="fallback-enabled fallback-wisp fallback-retries fallback-triggers" onclick="toggleSidebarMaster(this)"></div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-toggle-on"></i> Fallback Toggle</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Enable fallback WISP switch</div><div class="patch-row-desc"><strong>Uncheck to permanently disable</strong> the entire fallback system and remove its toggle from Settings. If the primary WISP fails, GUST will show an error immediately with no retry or fallback attempt.</div></div><div class="patch-check" data-patch="fallback-enabled" data-section="fallback" data-master-for="fallback-wisp fallback-retries fallback-triggers" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card" data-child-of="fallback-enabled">
<div class="settings-card-head"><i class="fas fa-server"></i> Fallback WISP URL</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Fallback server URL input</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the fallback WISP URL input, save, and reset buttons from Settings. No fallback server can be configured at runtime — only useful if the fallback toggle is kept enabled.</div></div><div class="patch-check" data-patch="fallback-wisp" data-section="fallback" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card" data-child-of="fallback-enabled">
<div class="settings-card-head"><i class="fas fa-clock-rotate-left"></i> Retry Policy</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Main & fallback retry counters + delay</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the main retry attempts, fallback retry attempts, and retry delay steppers from Settings. Defaults (3 main retries, 3 fallback retries, 3s delay) will be locked in permanently.</div></div><div class="patch-check" data-patch="fallback-retries" data-section="fallback" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card" data-child-of="fallback-enabled">
<div class="settings-card-head"><i class="fas fa-triangle-exclamation"></i> Error Triggers</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">5xx / timeout / DNS trigger toggles</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the error trigger switches from Settings. Fallback will trigger on all generic connection errors by default (5xx and timeout triggers default on, DNS trigger default off).</div></div><div class="patch-check" data-patch="fallback-triggers" data-section="fallback" onclick="togglePatch(this)"></div></div>
</div>
</div>
</div>
<!-- SEARCH -->
<div class="settings-section" data-section="search">
<div class="section-head"><div class="section-title">Search</div><div class="select-btns"><button class="select-btn" onclick="selectAll('search',true)">Select all</button><span class="select-sep">·</span><button class="select-btn" onclick="selectAll('search',false)">None</button></div></div>
<div class="sidebar-master-bar">
<div class="sidebar-master-bar-icon"><i class="fas fa-table-list"></i></div>
<div class="sidebar-master-bar-info">
<div class="sidebar-master-bar-label">Show Search in Settings Sidebar</div>
<div class="sidebar-master-bar-desc">Uncheck to remove the <strong>Search</strong> entry from GUST's Settings sidebar. The search engine picker, spellcheck toggle, and favicon proxy option will all be hidden from Settings.</div>
</div>
<div class="sidebar-master-check checked" data-patch="sidebar-nav-search" data-section="search" data-master-for="search-engine spellcheck search-favicon" onclick="toggleSidebarMaster(this)"></div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-magnifying-glass"></i> Default Search Engine</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Search engine picker</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the search engine selector from Settings. Brave Search will be locked in as the default with no way to change it.</div></div><div class="patch-check checked" data-patch="search-engine" data-section="search" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-spell-check"></i> Spellcheck <span class="broken-tag">[BROKEN]</span></div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Enable spellcheck <span class="broken-tag">broken</span></div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the spellcheck toggle from Settings. It is non-functional in base GUST — unchecking has no behavioural effect.</div></div><div class="patch-check checked" data-patch="spellcheck" data-section="search" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-image"></i> Tab Favicons</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Proxy favicons through WISP</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> favicon proxying through WISP and remove its toggle from Settings. Google's favicon service will be used instead — favicons may not load on some networks.</div></div><div class="patch-check checked" data-patch="search-favicon" data-section="search" onclick="togglePatch(this)"></div></div>
</div>
</div>
</div>
<!-- PRIVACY -->
<div class="settings-section" data-section="privacy">
<div class="section-head"><div class="section-title">Privacy</div><div class="select-btns"><button class="select-btn" onclick="selectAll('privacy',true)">Select all</button><span class="select-sep">·</span><button class="select-btn" onclick="selectAll('privacy',false)">None</button></div></div>
<div class="sidebar-master-bar">
<div class="sidebar-master-bar-icon"><i class="fas fa-table-list"></i></div>
<div class="sidebar-master-bar-info">
<div class="sidebar-master-bar-label">Show Privacy in Settings Sidebar</div>
<div class="sidebar-master-bar-desc">Uncheck to remove the <strong>Privacy</strong> entry from GUST's Settings sidebar. Ad blocking, JS proxy, user-agent spoofing, and custom filter rules will all be hidden from Settings.</div>
</div>
<div class="sidebar-master-check checked" data-patch="sidebar-nav-privacy" data-section="privacy" data-master-for="adblock-toggle js-proxy ua-request ua-page custom-filters" onclick="toggleSidebarMaster(this)"></div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-shield-halved"></i> Privacy & Blocking</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Ad & Tracker Blocking toggle</div><div class="patch-row-desc"><strong>Uncheck to permanently disable</strong> ad/tracker blocking and remove its toggle from Settings and the toolbar. Cannot be re-enabled at runtime.</div></div><div class="patch-check checked" data-patch="adblock-toggle" data-section="privacy" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-code"></i> JavaScript Proxy</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Proxy scripts through GUST</div><div class="patch-row-desc"><strong>Uncheck to permanently disable</strong> JS proxying and remove its toggle from Settings. Scripts will load directly — may cause CORS errors or breakage on some sites.</div></div><div class="patch-check checked" data-patch="js-proxy" data-section="privacy" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-user-secret"></i> User-Agent Spoofing</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Request User-Agent field</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the request UA input from Settings. The browser's native User-Agent will be sent on all proxy requests.</div></div><div class="patch-check checked" data-patch="ua-request" data-section="privacy" onclick="togglePatch(this)"></div></div>
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Page navigator.userAgent field</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the page UA input from Settings. The real browser value will be exposed to pages via navigator.userAgent.</div></div><div class="patch-check checked" data-patch="ua-page" data-section="privacy" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-filter"></i> Blocklist & Filters</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Custom Filter Rules textarea</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the custom CSS filter textarea from Settings. Per-page hide rules cannot be added or edited at runtime.</div></div><div class="patch-check checked" data-patch="custom-filters" data-section="privacy" onclick="togglePatch(this)"></div></div>
</div>
</div>
</div>
<!-- CACHE -->
<div class="settings-section" data-section="cache">
<div class="section-head"><div class="section-title">Cache</div><div class="select-btns"><button class="select-btn" onclick="selectAll('cache',true)">Select all</button><span class="select-sep">·</span><button class="select-btn" onclick="selectAll('cache',false)">None</button></div></div>
<div class="sidebar-master-bar">
<div class="sidebar-master-bar-icon"><i class="fas fa-table-list"></i></div>
<div class="sidebar-master-bar-info">
<div class="sidebar-master-bar-label">Show Cache in Settings Sidebar</div>
<div class="sidebar-master-bar-desc">Uncheck to remove the <strong>Cache</strong> entry from GUST's Settings sidebar. Tab caching and the Clear Cache / Reset Everything buttons will both be hidden from Settings.</div>
</div>
<div class="sidebar-master-check checked" data-patch="sidebar-nav-cache" data-section="cache" data-master-for="tab-cache clear-cache" onclick="toggleSidebarMaster(this)"></div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-layer-group"></i> Tab Caching</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Keep tabs loaded in background</div><div class="patch-row-desc"><strong>Uncheck to permanently disable</strong> tab caching and remove its toggle from Settings. Background tabs will always be fully reloaded when switched to.</div></div><div class="patch-check checked" data-patch="tab-cache" data-section="cache" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-database"></i> Resource Cache</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Clear Cache & Reset All buttons</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the Clear Cache and Reset Everything buttons from Settings. Cached data can only be cleared by wiping browser storage manually.</div></div><div class="patch-check checked" data-patch="clear-cache" data-section="cache" onclick="togglePatch(this)"></div></div>
</div>
</div>
</div>
<!-- FILES & MEDIA -->
<div class="settings-section" data-section="filesandmedia">
<div class="section-head"><div class="section-title">Files & Media</div><div class="select-btns"><button class="select-btn" onclick="selectAll('filesandmedia',true)">Select all</button><span class="select-sep">·</span><button class="select-btn" onclick="selectAll('filesandmedia',false)">None</button></div></div>
<div class="sidebar-master-bar">
<div class="sidebar-master-bar-icon"><i class="fas fa-table-list"></i></div>
<div class="sidebar-master-bar-info">
<div class="sidebar-master-bar-label">Show Files & Media in Settings Sidebar</div>
<div class="sidebar-master-bar-desc">Uncheck to remove the <strong>Files & Media</strong> entry from GUST's Settings sidebar. Range requests, auto-download, and all inline viewer toggles (PDF, image, video, audio, text) will be hidden from Settings.</div>
</div>
<div class="sidebar-master-check checked" data-patch="sidebar-nav-filesandmedia" data-section="filesandmedia" data-master-for="media-range media-download media-pdf media-img media-video media-audio media-text" onclick="toggleSidebarMaster(this)"></div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-film"></i> Media Range Requests</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Enable Range request support</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> Range requests and remove their toggle from Settings. Seeking in video and audio will not work.</div></div><div class="patch-check checked" data-patch="media-range" data-section="filesandmedia" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-download"></i> Unknown File Types</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Auto-download unknown files</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> auto-downloading of unknown MIME types and remove the toggle from Settings. Unknown file types will fail silently instead of downloading.</div></div><div class="patch-check checked" data-patch="media-download" data-section="filesandmedia" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-file-pdf"></i> PDF Viewer</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Built-in PDF viewer</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> the PDF viewer and remove its toggle from Settings. PDF files will be downloaded instead of opening inline.</div></div><div class="patch-check checked" data-patch="media-pdf" data-section="filesandmedia" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-image"></i> Image Viewer</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Built-in image viewer</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> the image viewer and remove its toggle from Settings. Images will open as raw files or download rather than rendering inline.</div></div><div class="patch-check checked" data-patch="media-img" data-section="filesandmedia" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-film"></i> Video Player</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Built-in video player</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> the video player and remove its toggle from Settings. Video files will not play inline.</div></div><div class="patch-check checked" data-patch="media-video" data-section="filesandmedia" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-music"></i> Audio Player</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Built-in audio player</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> the audio player and remove its toggle from Settings. Audio files will not play inline.</div></div><div class="patch-check checked" data-patch="media-audio" data-section="filesandmedia" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-file-lines"></i> Text / Code Viewer</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Built-in text viewer</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> the text/code viewer and remove its toggle from Settings. Plain text and code files will be downloaded instead of rendering.</div></div><div class="patch-check checked" data-patch="media-text" data-section="filesandmedia" onclick="togglePatch(this)"></div></div>
</div>
</div>
</div>
<!-- APPEARANCE -->
<div class="settings-section" data-section="appearance">
<div class="section-head"><div class="section-title">Appearance</div><div class="select-btns"><button class="select-btn" onclick="selectAll('appearance',true)">Select all</button><span class="select-sep">·</span><button class="select-btn" onclick="selectAll('appearance',false)">None</button></div></div>
<div class="sidebar-master-bar">
<div class="sidebar-master-bar-icon"><i class="fas fa-table-list"></i></div>
<div class="sidebar-master-bar-info">
<div class="sidebar-master-bar-label">Show Appearance in Settings Sidebar</div>
<div class="sidebar-master-bar-desc">Uncheck to remove the <strong>Appearance</strong> entry from GUST's Settings sidebar. Font size, panel width persistence, panel position, and fullscreen-on-launch will all be hidden from Settings.</div>
</div>
<div class="sidebar-master-check checked" data-patch="sidebar-nav-appearance" data-section="appearance" data-master-for="font-size panel-widths panels-left auto-fullscreen" onclick="toggleSidebarMaster(this)"></div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-text-width"></i> Font Size</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Font size slider</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the font size slider from Settings. UI text size will be locked at the default with no way to adjust it.</div></div><div class="patch-check checked" data-patch="font-size" data-section="appearance" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-arrows-left-right"></i> Panel Widths</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Remember panel widths</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> panel width persistence and remove its toggle from Settings. Panels will reset to default width on every load.</div></div><div class="patch-check checked" data-patch="panel-widths" data-section="appearance" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-table-columns"></i> Panel Position</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Panels on the left</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> the left-panels option and remove its toggle from Settings. Panels will always be on the right.</div></div><div class="patch-check checked" data-patch="panels-left" data-section="appearance" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-expand"></i> Fullscreen on Launch</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Start in fullscreen</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> auto-fullscreen on launch and remove its toggle from Settings. GUST will always open in a normal window.</div></div><div class="patch-check checked" data-patch="auto-fullscreen" data-section="appearance" onclick="togglePatch(this)"></div></div>
</div>
</div>
</div>
<!-- HOME SCREEN -->
<div class="settings-section" data-section="homescreen">
<div class="section-head"><div class="section-title">Home Screen</div><div class="select-btns"><button class="select-btn" onclick="selectAll('homescreen',true)">Select all</button><span class="select-sep">·</span><button class="select-btn" onclick="selectAll('homescreen',false)">None</button></div></div>
<div class="sidebar-master-bar">
<div class="sidebar-master-bar-icon"><i class="fas fa-table-list"></i></div>
<div class="sidebar-master-bar-info">
<div class="sidebar-master-bar-label">Show Home Screen in Settings Sidebar</div>
<div class="sidebar-master-bar-desc">Uncheck to remove the <strong>Home Screen</strong> entry from GUST's Settings sidebar. The bookmarks bar toggle, wallpaper controls, and clock options will all be hidden from Settings.</div>
</div>
<div class="sidebar-master-check checked" data-patch="sidebar-nav-homescreen" data-section="homescreen" data-master-for="bookmarks-bar nt-wallpaper nt-clock nt-clock24" onclick="toggleSidebarMaster(this)"></div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-bookmark"></i> Bookmarks Bar</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Show Bookmarks Bar</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> the bookmarks bar and remove its toggle from Settings. Bookmarks will only be accessible via the history panel.</div></div><div class="patch-check checked" data-patch="bookmarks-bar" data-section="homescreen" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-image"></i> New Tab Wallpaper</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Background image controls</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the wallpaper change and reset buttons from Settings. The new tab background will be locked to the default gradient.</div></div><div class="patch-check checked" data-patch="nt-wallpaper" data-section="homescreen" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-clock"></i> Home Page Clock</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Show clock on new tab</div><div class="patch-row-desc"><strong>Uncheck to permanently hide</strong> the clock on the new tab page and remove its toggle from Settings.</div></div><div class="patch-check checked" data-patch="nt-clock" data-section="homescreen" onclick="togglePatch(this)"></div></div>
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">24-hour clock</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> 24-hour format and remove its toggle from Settings. The clock will always display in 12-hour format.</div></div><div class="patch-check checked" data-patch="nt-clock24" data-section="homescreen" onclick="togglePatch(this)"></div></div>
</div>
</div>
</div>
<!-- SHORTCUTS -->
<div class="settings-section" data-section="shortcuts">
<div class="section-head"><div class="section-title">Shortcuts</div><div class="select-btns"><button class="select-btn" onclick="selectAll('shortcuts',true)">Select all</button><span class="select-sep">·</span><button class="select-btn" onclick="selectAll('shortcuts',false)">None</button></div></div>
<div class="sidebar-master-bar">
<div class="sidebar-master-bar-icon"><i class="fas fa-table-list"></i></div>
<div class="sidebar-master-bar-info">
<div class="sidebar-master-bar-label">Show Shortcuts in Settings Sidebar</div>
<div class="sidebar-master-bar-desc">Uncheck to remove the <strong>Shortcuts</strong> entry from GUST's Settings sidebar. The keyboard shortcuts enable/disable toggle and the full key binding list will be hidden from Settings.</div>
</div>
<div class="sidebar-master-check checked" data-patch="sidebar-nav-shortcuts" data-section="shortcuts" data-master-for="shortcuts-panel" onclick="toggleSidebarMaster(this)"></div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-keyboard"></i> Keyboard Shortcuts</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Enable shortcuts toggle + shortcut list</div><div class="patch-row-desc"><strong>Uncheck to permanently disable</strong> keyboard shortcuts and remove the enable/disable toggle and key binding list from Settings.</div></div><div class="patch-check checked" data-patch="shortcuts-panel" data-section="shortcuts" onclick="togglePatch(this)"></div></div>
</div>
</div>
</div>
<!-- CORE: TUTORIAL -->
<div class="settings-section" data-section="core-tutorial">
<div class="section-head"><div class="section-title">Tutorial</div><div class="select-btns"><button class="select-btn" onclick="selectAll('core-tutorial',true)">Select all</button><span class="select-sep">·</span><button class="select-btn" onclick="selectAll('core-tutorial',false)">None</button></div></div>
<div class="sidebar-master-bar">
<div class="sidebar-master-bar-icon"><i class="fas fa-table-list"></i></div>
<div class="sidebar-master-bar-info">
<div class="sidebar-master-bar-label">Show Tutorial in Settings Sidebar</div>
<div class="sidebar-master-bar-desc">Uncheck to remove the <strong>Tutorial</strong> entry from GUST's Settings sidebar. The tutorial overlay, auto-launch on first load, and the restart button in Settings will all be hidden.</div>
</div>
<div class="sidebar-master-check checked" data-patch="sidebar-nav-tutorial" data-section="core-tutorial" data-master-for="tutorial-include tutorial-auto tutorial-settings" onclick="toggleSidebarMaster(this)"></div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-map"></i> Interactive Tutorial</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Include tutorial overlay & steps</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the guided tour overlay entirely and pre-mark it as done so it never appears. When unchecked, the two options below are also forced off.</div></div><div class="patch-check checked" data-patch="tutorial-include" data-section="core-tutorial" data-master-for="tutorial-auto tutorial-settings" onclick="togglePatch(this)"></div></div>
<div class="patch-row" data-child-of="tutorial-include"><div class="patch-row-info"><div class="patch-row-label">Auto-start on first load</div><div class="patch-row-desc"><strong>Uncheck to suppress</strong> the tutorial auto-launch on first open by pre-seeding the done flag. The overlay is still present if triggered manually from Settings.</div></div><div class="patch-check checked" data-patch="tutorial-auto" data-section="core-tutorial" onclick="togglePatch(this)"></div></div>
<div class="patch-row" data-child-of="tutorial-include"><div class="patch-row-info"><div class="patch-row-label">Tutorial nav entry in Settings</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the Tutorial nav item from the Settings sidebar so users cannot manually re-launch the tour.</div></div><div class="patch-check checked" data-patch="tutorial-settings" data-section="core-tutorial" onclick="togglePatch(this)"></div></div>
</div>
</div>
</div>
<!-- CORE: TABS -->
<div class="settings-section" data-section="core-tabs">
<div class="section-head"><div class="section-title">Tab System</div><div class="select-btns"><button class="select-btn" onclick="selectAll('core-tabs',true)">Select all</button><span class="select-sep">·</span><button class="select-btn" onclick="selectAll('core-tabs',false)">None</button></div></div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-window-restore"></i> Tab System</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Drag-to-reorder tabs</div><div class="patch-row-desc"><strong>Uncheck to disable</strong> tab dragging by blocking the pointer events that drive it. Tabs cannot be grabbed or reordered — no ghost, no slot indicator, no reorder.</div></div><div class="patch-check checked" data-patch="tab-drag" data-section="core-tabs" onclick="togglePatch(this)"></div></div>
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Right-click context menu on tabs</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the tab context menu element. Right-clicking a tab will do nothing.</div></div><div class="patch-check checked" data-patch="tab-context" data-section="core-tabs" onclick="togglePatch(this)"></div></div>
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Audio mute controls on tabs</div><div class="patch-row-desc"><strong>Uncheck to hide</strong> the mute icon on tabs that are playing audio. Audio will still play — it just cannot be muted from the tab strip.</div></div><div class="patch-check checked" data-patch="tab-mute" data-section="core-tabs" onclick="togglePatch(this)"></div></div>
</div>
</div>
</div>
<!-- CORE: AD BLOCKER -->
<div class="settings-section" data-section="core-adblock">
<div class="section-head"><div class="section-title">Ad Blocker</div><div class="select-btns"><button class="select-btn" onclick="selectAll('core-adblock',true)">Select all</button><span class="select-sep">·</span><button class="select-btn" onclick="selectAll('core-adblock',false)">None</button></div></div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-shield-halved"></i> Ad Blocker</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Adblock shield toolbar button & panel</div><div class="patch-row-desc"><strong>Uncheck to remove</strong> the shield toolbar button and the floating adblock modal that shows per-page block counts and the on/off power button.</div></div><div class="patch-check checked" data-patch="adblock-panel" data-section="core-adblock" onclick="togglePatch(this)"></div></div>
</div>
</div>
</div>
<!-- CORE: DEV TOOLS -->
<div class="settings-section" data-section="core-devtools">
<div class="section-head"><div class="section-title">Dev Tools</div><div class="select-btns"><button class="select-btn" onclick="selectAll('core-devtools',true)">Select all</button><span class="select-sep">·</span><button class="select-btn" onclick="selectAll('core-devtools',false)">None</button></div></div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-server"></i> Browser Logs</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Log panel & toolbar toggle button</div><div class="patch-row-desc"><strong>Uncheck to hide</strong> the logs toolbar button and the log panel. Real-time request logging will be completely unavailable to the user.</div></div><div class="patch-check checked" data-patch="dev-logs" data-section="core-devtools" onclick="togglePatch(this)"></div></div>
</div>
</div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-code"></i> Page Inspector</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Element inspector panel & toolbar button</div><div class="patch-row-desc"><strong>Uncheck to hide</strong> the inspector toolbar button and the elements panel. DOM and CSS inspection will be completely unavailable to the user.</div></div><div class="patch-check checked" data-patch="dev-inspector" data-section="core-devtools" onclick="togglePatch(this)"></div></div>
</div>
</div>
</div>
<!-- CORE: METRICS -->
<div class="settings-section" data-section="core-metrics">
<div class="section-head"><div class="section-title">Metrics</div><div class="select-btns"><button class="select-btn" onclick="selectAll('core-metrics',true)">Select all</button><span class="select-sep">·</span><button class="select-btn" onclick="selectAll('core-metrics',false)">None</button></div></div>
<div class="settings-card">
<div class="settings-card-head"><i class="fas fa-chart-simple"></i> Browser Metrics</div>
<div class="settings-card-body">
<div class="patch-row"><div class="patch-row-info"><div class="patch-row-label">Metrics modal & toolbar button</div><div class="patch-row-desc"><strong>Uncheck to hide</strong> the metrics toolbar button and the stats popup. Live performance and network data will be completely unavailable to the user.</div></div><div class="patch-check checked" data-patch="metrics" data-section="core-metrics" onclick="togglePatch(this)"></div></div>
</div>
</div>
</div>
</div>
</div>
<div class="status-bar">
<i class="fas fa-circle-info" style="color:var(--ac)" id="statusIcon"></i>
<span id="statusText">Loading source…</span>
<span style="margin-left:auto;display:flex;align-items:center;gap:14px">
<span style="display:flex;align-items:center;gap:6px">
<span style="color:var(--tx3)">Enabled:</span>
<span style="color:var(--ac);font-weight:600;font-family:var(--mono)" id="totalCount">0/0</span>
</span>
<span style="display:flex;align-items:center;gap:6px">
<span style="color:var(--tx3)">Patches removed:</span>
<span style="color:var(--warn);font-weight:600;font-family:var(--mono)" id="removedCount">0</span>
</span>
<span style="display:flex;align-items:center;gap:6px" id="fileSizeWrap" style="display:none">
<span style="color:var(--tx3)">File size:</span>
<span style="color:var(--ok);font-weight:600;font-family:var(--mono)" id="fileSizeCount">—</span>
</span>
</span>
</div>
<div id="patcherTutorialOverlay">
<div id="patcherTutorialBackdrop"></div>
<svg id="patcherTutorialSvg" xmlns="http://www.w3.org/2000/svg">
<defs>
<mask id="patcherSpotMask">
<rect width="100%" height="100%" fill="white"/>
<rect id="patcherSpotRect" x="0" y="0" width="0" height="0" rx="12" fill="black"/>
</mask>
</defs>
<rect width="100%" height="100%" fill="rgba(0,0,0,0.48)" mask="url(#patcherSpotMask)" id="patcherSpotOverlay"/>
<rect id="patcherSpotRing" x="0" y="0" width="0" height="0" rx="12" fill="none" stroke="var(--ac)" stroke-width="1"/>
</svg>
<div id="patcherTutorialRing"></div>
<div id="patcherTutorialCloneWrap" style="position:absolute;inset:0;pointer-events:none;z-index:2;"></div>
<div id="patcherTutorialCard">
<div id="patcherTutorialDots" style="display:flex;gap:5px;margin-bottom:16px;"></div>
<div id="patcherTutorialArrow"></div>
<div style="display:flex;align-items:flex-start;gap:14px;margin-bottom:14px;">
<div id="patcherTutorialIcon" style="width:42px;height:42px;border-radius:11px;background:rgba(100,210,255,.12);display:flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--ac);font-size:18px;"></div>
<div style="flex:1;">
<div id="patcherTutorialTitle" style="font-size:15px;font-weight:700;color:var(--tx);margin-bottom:5px;line-height:1.2;"></div>
<div id="patcherTutorialBody" style="font-size:13.5px;color:var(--tx2);line-height:1.6;"></div>
</div>
</div>
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:18px;">
<button id="patcherTutorialSkip" style="background:none;border:none;color:var(--tx3);font-size:12px;cursor:pointer;padding:0;">Skip tour</button>
<div style="display:flex;gap:8px;">
<button id="patcherTutorialBack" style="background:var(--bg3);border:1px solid var(--bd);color:var(--tx2);border-radius:8px;padding:7px 18px;font-size:13px;cursor:pointer;display:none;font-family:var(--ui)"><i class="fas fa-arrow-left" style="margin-right:5px;"></i>Back</button>
<button id="patcherTutorialNext" style="background:var(--ac);border:none;color:#000;border-radius:8px;padding:7px 20px;font-size:13px;font-weight:700;cursor:pointer;font-family:var(--ui)">Next</button>
</div>
</div>
</div>
</div>
</div>
<script>
let sourceHTML = '', sourceLoaded = false;
const RAW_URL = 'https://raw.githubusercontent.com/nautilus-os/GUST/refs/heads/main/index.html';
const GH_URL = 'https://github.com/nautilus-os/GUST/raw/refs/heads/main/index.html';
// Default checked state for all patches (all checked by default)
function resetCheckboxesToDefault() {
document.querySelectorAll('.patch-check[data-patch]').forEach(el => {
el.classList.add('checked');
el.classList.remove('master-disabled');
delete el.dataset.savedCheckedBySidebar;
});
document.querySelectorAll('.sidebar-master-check[data-patch]').forEach(el => {
el.classList.add('checked');
});
// Re-apply master states after reset
document.querySelectorAll('.settings-card').forEach(c => c.classList.remove('master-disabled'));
updateCounts();
}
function playBrandAnimation() {
const brand = document.querySelector('.brand');
brand.classList.remove('brand-anim-ready');
const animated = brand.querySelectorAll('.gust-icon-anim, .gust-letter-G, .gust-letter-U, .gust-letter-S, .gust-letter-T, .gust-sub-anim');
animated.forEach(el => { el.style.animation = 'none'; el.style.opacity = '0'; });
void brand.offsetWidth;
animated.forEach(el => { el.style.animation = ''; el.style.opacity = ''; });
void brand.offsetWidth;
brand.classList.add('brand-anim-ready');
// Also replay homepage brand animation
const hpWrap = document.querySelector('.homepage-brand-wrap');
if (hpWrap) {
hpWrap.classList.remove('brand-anim-ready');
const hpAnimated = hpWrap.querySelectorAll('.gust-icon-anim, .gust-letter-G, .gust-letter-U, .gust-letter-S, .gust-letter-T, .gust-sub-anim');
hpAnimated.forEach(el => { el.style.animation = 'none'; el.style.opacity = '0'; });
void hpWrap.offsetWidth;
hpAnimated.forEach(el => { el.style.animation = ''; el.style.opacity = ''; });
void hpWrap.offsetWidth;
hpWrap.classList.add('brand-anim-ready');
}
}
function updateCounts() {
const all = document.querySelectorAll('.patch-check[data-section]');
let totalOn = 0, totalAll = 0;
const map = {};
all.forEach(el => {
const s = el.dataset.section;
if (!map[s]) map[s] = {on:0,total:0};
map[s].total++; totalAll++;
if (el.classList.contains('checked')) { map[s].on++; totalOn++; }
});
// Also count sidebar master bars
document.querySelectorAll('.sidebar-master-check[data-section]').forEach(el => {
const s = el.dataset.section;
if (!map[s]) map[s] = {on:0,total:0};
map[s].total++; totalAll++;
if (el.classList.contains('checked')) { map[s].on++; totalOn++; }
});
Object.keys(map).forEach(s => {
const b = document.getElementById('nc-' + s);
if (!b) return;
b.textContent = map[s].on + '/' + map[s].total;
b.classList.toggle('lit', map[s].on > 0);
});
document.getElementById('totalCount').textContent = totalOn + '/' + totalAll;
const removed = totalAll - totalOn;
const rc = document.getElementById('removedCount');
if (rc) { rc.textContent = removed; rc.style.color = removed > 0 ? 'var(--warn)' : 'var(--tx3)'; }
const dlBtn = document.getElementById('downloadBtn');
if (dlBtn && !dlBtn.disabled && sourceLoaded) {
dlBtn.disabled = totalOn === 0;
}
}
function applyMasterState(masterPatch, isChecked) {
const masterKey = masterPatch.dataset.patch;
const children = (masterPatch.dataset.masterFor || '').split(' ').filter(Boolean);
// Dim/undim child cards
document.querySelectorAll(`[data-child-of="${masterKey}"]`).forEach(el => {
el.classList.toggle('master-disabled', !isChecked);
});
children.forEach(childPatch => {
document.querySelectorAll(`.patch-check[data-patch="${childPatch}"]`).forEach(el => {
if (!isChecked) {
// Save current checked state before disabling, then uncheck
el.dataset.savedChecked = el.classList.contains('checked') ? '1' : '0';
el.classList.remove('checked');
el.classList.add('master-disabled');
} else {
el.classList.remove('master-disabled');
// Restore previously saved state (default to checked if no saved state)
const saved = el.dataset.savedChecked;
if (saved === '0') {
el.classList.remove('checked');
} else {
el.classList.add('checked');
}
delete el.dataset.savedChecked;
}
});
});
}
function togglePatch(el) {
// Don't toggle children of a disabled master
if (el.classList.contains('master-disabled')) return;
const wasChecked = el.classList.contains('checked');
el.classList.toggle('checked');
const isChecked = el.classList.contains('checked');
// If this is a master, cascade to children
if (el.dataset.masterFor) applyMasterState(el, isChecked);
updateCounts();
}
function toggleSidebarMaster(el) {
el.classList.toggle('checked');
const isChecked = el.classList.contains('checked');
const children = (el.dataset.masterFor || '').split(' ').filter(Boolean);
// Dim/enable all settings cards and patch rows in this section
const section = el.closest('.settings-section');
if (section) {
section.querySelectorAll('.settings-card').forEach(card => {
card.classList.toggle('master-disabled', !isChecked);
});
section.querySelectorAll('.patch-check').forEach(check => {
if (!isChecked) {
check.dataset.savedCheckedBySidebar = check.classList.contains('checked') ? '1' : '0';
check.classList.remove('checked');
check.classList.add('master-disabled');
} else {
check.classList.remove('master-disabled');
const saved = check.dataset.savedCheckedBySidebar;
if (saved === '0') {
check.classList.remove('checked');
} else {
check.classList.add('checked');
}
delete check.dataset.savedCheckedBySidebar;
// Re-apply any nested master state
if (check.dataset.masterFor) applyMasterState(check, check.classList.contains('checked'));
}
});
}
updateCounts();
}
function selectAll(sec, state) {
// Toggle the sidebar master bar first
const masterBar = document.querySelector(`.sidebar-master-check[data-section="${sec}"]`);
if (masterBar) {
masterBar.classList.toggle('checked', state);
if (!state) {
// Disabling sidebar master — dim all cards and uncheck all patches
const section = masterBar.closest('.settings-section');
if (section) {
section.querySelectorAll('.settings-card').forEach(card => card.classList.add('master-disabled'));
section.querySelectorAll('.patch-check').forEach(check => {