Repository navigation
Expand file tree
/
Copy pathindex.html
More file actions
964 lines (953 loc) · 138 KB
/
Copy pathindex.html
File metadata and controls
964 lines (953 loc) · 138 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
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<title>OpenBox Game Launcher</title>
<link rel="stylesheet" href="/static/app.css">
<link id="themeStylesheet" rel="stylesheet">
</head>
<body>
<section id="migrationGate" class="migration-gate" hidden aria-labelledby="migrationGateTitle">
<div class="migration-gate-card">
<h2 id="migrationGateTitle" data-i18n="migration.title">Your library was upgraded</h2>
<p data-i18n="migration.intro">OpenBox upgraded the library file to the new format. A copy of the old file is kept. OpenBox 3.0 does not roll it back; OpenBox 2.1.0 can restore library.v6.backup.json.</p>
<dl class="migration-gate-facts">
<dt data-i18n="migration.from">Before</dt><dd id="migrationFrom"></dd>
<dt data-i18n="migration.to">After</dt><dd id="migrationTo"></dd>
<dt data-i18n="migration.games">Games</dt><dd id="migrationGames"></dd>
<dt data-i18n="migration.backup">Copy of the old library</dt><dd id="migrationBackup"></dd>
</dl>
<section id="migrationReadiness" class="migration-gate-readiness" hidden>
<h3 data-i18n="migration.readiness_title">Before you continue</h3>
<ul id="migrationReadinessList"></ul>
</section>
<div class="extras">
<button type="button" class="icon-button" id="migrationBackupButton" data-i18n="migration.backup_first">Back up first</button>
<button type="button" class="icon-button" id="migrationOpen" data-i18n="migration.open">Open the library</button>
</div>
<p class="description" id="migrationStatus" aria-live="polite"></p>
</div>
</section>
<header class="topbar">
<div class="brand"><img class="mark" src="/static/logo.png" alt="OpenBox">OpenBox</div>
<nav class="topbar-zone" aria-label="Library">
<button class="menu-button primary-nav" id="libraryButton" data-i18n="nav.library">Library</button>
<div class="topbar-tools add-menu-wrap" id="addMenuWrap">
<button class="menu-button primary-nav" id="addMenuButton" aria-haspopup="menu"
aria-expanded="false" aria-controls="addMenu" data-i18n="nav.add_games">Add games</button>
<div class="tool-menu add-menu" id="addMenu" role="menu">
<div role="group" aria-label="Add games" data-tool-group="add" data-i18n-aria-label="nav.add_group_add">
<button class="menu-button" id="addButton" role="menuitem" data-i18n="nav.add_menu_game">Add one game…</button>
<button class="menu-button" id="importButton" role="menuitem" data-i18n="nav.add_menu_folder">Scan a folder…</button>
<button class="menu-button" id="addShelfButton" role="menuitem" data-i18n="nav.add_menu_shelf">Add a game without files…</button>
<button class="menu-button" id="setupLibraryButton" role="menuitem" data-i18n="nav.add_menu_setup">Guided setup…</button>
</div>
<div role="group" aria-label="Import from a game store" data-tool-group="stores" data-i18n-aria-label="nav.add_group_stores">
<button class="menu-button" role="menuitem" data-add-action="steam" data-i18n="nav.add_menu_steam">Steam</button>
<button class="menu-button" role="menuitem" data-add-action="heroic" data-feature="heroic" data-i18n="nav.add_menu_heroic">Heroic</button>
<button class="menu-button" role="menuitem" data-add-action="lutris" data-feature="lutris" data-i18n="nav.add_menu_lutris">Lutris</button>
<button class="menu-button" role="menuitem" data-add-action="store" data-i18n="nav.add_menu_store">More game stores…</button>
</div>
</div>
</div>
</nav>
<nav class="topbar-zone" aria-label="Actions">
<button class="menu-button" id="bigBoxButton" data-i18n="nav.big_box" data-i18n-title="nav.big_box_hint" title="Fullscreen, controller-friendly mode">Big Box</button>
<button class="menu-button" id="sessionsButton" data-i18n="nav.running">Running now</button>
<button class="menu-button" id="queueButton" data-i18n="nav.queue">Play queue</button>
<button class="menu-button activity-button" id="activityButton" aria-label="Activity" data-i18n-aria-label="nav.activity"><span class="activity-label" data-i18n="nav.activity">Activity</span><span class="activity-count" id="activityCount" aria-live="polite" hidden>0</span></button>
</nav>
<nav class="topbar-zone topbar-zone-tools" aria-label="Tools">
<noscript><details class="topbar-tools"><summary class="menu-button">Tools</summary></details></noscript>
<div class="topbar-tools" id="toolsWrap">
<button class="menu-button" id="toolsButton" aria-haspopup="menu" aria-expanded="false" aria-controls="toolMenu" data-i18n="nav.tools">Tools</button>
<div class="tool-menu" id="toolMenu" role="menu">
<div role="group" aria-label="Start here" data-tool-group="start" data-i18n-aria-label="tools.group_start">
<button class="menu-button" id="metadataButton" role="menuitem" tabindex="-1"><span data-i18n="tools.metadata">Artwork & details</span><small class="menu-hint" data-i18n="tools.hint_metadata">Artwork and game details</small></button>
<button class="menu-button" id="mediaButton" role="menuitem" tabindex="-1"><span data-i18n="tools.media">Media files</span><small class="menu-hint" data-i18n="tools.hint_media">Images, video, and music</small></button>
<button class="menu-button" id="healthButton" role="menuitem" tabindex="-1"><span data-i18n="tools.health">Library checkup</span><small class="menu-hint" data-i18n="tools.hint_health">Find and fix library problems</small></button>
<button class="menu-button" id="emulatorsButton" role="menuitem" tabindex="-1"><span data-i18n="tools.emulators">Emulators & controllers</span><small class="menu-hint" data-i18n="tools.hint_emulators">Install and configure</small></button>
<button class="menu-button" id="themesButton" role="menuitem" tabindex="-1"><span data-i18n="tools.themes">Themes</span><small class="menu-hint" data-i18n="tools.hint_themes">Change the look</small></button>
<button class="menu-button" id="settingsButton" role="menuitem" tabindex="-1"><span data-i18n="tools.settings">Settings</span><small class="menu-hint" data-i18n="tools.hint_settings">All options</small></button>
<button class="menu-button" id="helpButton" role="menuitem" tabindex="-1"><span data-i18n="tools.help">Help & shortcuts</span><small class="menu-hint" data-i18n="tools.hint_help">Start here, glossary, shortcuts</small></button>
</div>
<div role="group" aria-label="Library" data-tool-group="library" data-i18n-aria-label="tools.group_library">
<button class="menu-button" id="constellationButton" role="menuitem" tabindex="-1"><span data-i18n="tools.constellation">Game connections</span><small class="menu-hint" data-i18n="tools.hint_constellation">See how games connect</small></button>
<button class="menu-button" id="masteryButton" role="menuitem" tabindex="-1"><span data-i18n="tools.mastery">Completion ranking</span><small class="menu-hint" data-i18n="tools.hint_mastery">Completion ranking</small></button>
<button class="menu-button" id="bulkButton" role="menuitem" tabindex="-1" data-i18n="tools.bulk_edit">Bulk edit</button>
<button class="menu-button" id="tagsButton" role="menuitem" tabindex="-1" data-i18n="tools.tags">Tags</button>
<button class="menu-button" id="playlistsButton" role="menuitem" tabindex="-1" data-i18n="tools.playlists">Playlists</button>
<button class="menu-button" id="backupButton" role="menuitem" tabindex="-1" data-i18n="tools.backup">Backup</button>
<button class="menu-button" id="historyButton" role="menuitem" tabindex="-1" data-i18n="tools.history">History</button>
<button class="menu-button" id="timeMachineButton" role="menuitem" tabindex="-1"><span data-i18n="tools.time_machine">Library history</span><small class="menu-hint" data-i18n="tools.hint_time_machine">Review and undo changes</small></button>
<button class="menu-button" id="achievementsButton" role="menuitem" tabindex="-1"><span data-i18n="tools.achievements">RetroAchievements account</span><small class="menu-hint" data-i18n="tools.hint_achievements">Connect RetroAchievements</small></button>
<button class="menu-button" id="saveFilterButton" role="menuitem" tabindex="-1"><span data-i18n="tools.save_filter">Save current search</span></button>
<button class="menu-button" id="savePresetButton" role="menuitem" tabindex="-1"><span data-i18n="tools.save_preset">Save current view</span></button>
</div>
<div role="group" aria-label="Imports & extras" data-tool-group="sources" data-i18n-aria-label="tools.group_sources">
<button class="menu-button" id="storefrontButton" role="menuitem" tabindex="-1"><span data-i18n="tools.storefronts">Game stores</span><small class="menu-hint" data-i18n="tools.hint_storefronts">Steam, Heroic, Lutris, and more</small></button>
<button class="menu-button" id="steamButton" role="menuitem" tabindex="-1" data-i18n="tools.import_steam">Import Steam</button>
<button class="menu-button" id="heroicButton" role="menuitem" tabindex="-1" data-feature="heroic" data-i18n="tools.import_heroic">Import Heroic</button>
<button class="menu-button" id="lutrisButton" role="menuitem" tabindex="-1" data-feature="lutris" data-i18n="tools.import_lutris">Import Lutris</button>
<button class="menu-button" id="gogButton" role="menuitem" tabindex="-1" data-feature="native_storefronts" hidden data-i18n="tools.import_gog">Import GOG</button>
<button class="menu-button" id="eaButton" role="menuitem" tabindex="-1" data-feature="native_storefronts" hidden data-i18n="tools.import_ea">Import EA app</button>
<button class="menu-button" id="ubisoftButton" role="menuitem" tabindex="-1" data-feature="native_storefronts" hidden data-i18n="tools.import_ubisoft">Import Ubisoft Connect</button>
<button class="menu-button" id="arcadeButton" role="menuitem" tabindex="-1" data-i18n="tools.import_arcade">Import Arcade</button>
<button class="menu-button" id="pico8Button" role="menuitem" tabindex="-1" data-i18n="tools.import_pico8">Import PICO-8</button>
<button class="menu-button" id="msu1Button" role="menuitem" tabindex="-1" data-i18n="tools.import_msu1">Import MSU-1</button>
<button class="menu-button" id="whdloadButton" role="menuitem" tabindex="-1" data-i18n="tools.import_whdload">Import WHDLoad</button>
<button class="menu-button" id="arcadeRoomButton" role="menuitem" tabindex="-1"><span data-i18n="tools.arcade_room">3D arcade room</span><small class="menu-hint" data-i18n="tools.hint_arcade_room">Walk around a 3D arcade</small></button>
<button class="menu-button" id="householdButton" role="menuitem" tabindex="-1"><span data-i18n="tools.household">Family sharing</span><small class="menu-hint" data-i18n="tools.hint_household">Share stats with family</small></button>
</div>
<div role="group" aria-label="More" data-tool-group="more" data-i18n-aria-label="tools.group_more">
<button class="menu-button" id="discoveryButton" role="menuitem" tabindex="-1"><span data-i18n="tools.discovery">Find something to play</span><small class="menu-hint" data-i18n="tools.hint_discovery">Find something to play</small></button>
<button class="menu-button" id="netplayButton" role="menuitem" tabindex="-1"><span data-i18n="tools.netplay">Online play</span><small class="menu-hint" data-i18n="tools.hint_netplay">Play online with friends</small></button>
<button class="menu-button" id="pluginsButton" role="menuitem" tabindex="-1"><span data-i18n="tools.plugins">Plugins</span><small class="menu-hint" data-i18n="tools.hint_plugins">Extend OpenBox</small></button>
<button class="menu-button" id="whatsNewButton" role="menuitem" tabindex="-1" data-i18n="common.whats_new">What's New</button>
<button class="menu-button" id="fullscreenButton" role="menuitem" tabindex="-1" data-i18n="nav.fullscreen">Fullscreen</button>
<button class="menu-button" id="reportIssueButton" role="menuitem" tabindex="-1" data-i18n="help.report_issue">Report a problem</button>
<button class="menu-button" id="webhooksButton" role="menuitem" tabindex="-1" data-i18n="tools.webhooks">Webhooks</button>
<button class="menu-button" id="notificationsButton" role="menuitem" tabindex="-1" data-i18n="tools.notifications">Notifications</button>
</div>
</div>
</div>
</nav>
<span class="top-status" id="status" data-i18n="library.local_library">Local library</span>
</header>
<div class="startup-error-banner" id="startupErrorBanner" role="status" hidden>
<span id="startupErrorText"></span>
<button type="button" class="icon-button" id="startupErrorDismiss" aria-label="Dismiss startup message">×</button>
</div>
<div class="workspace">
<aside class="sidebar" aria-label="Library filters" data-i18n-aria-label="library.library_filters">
<label class="field" data-sidebar-section="search"><span data-i18n="sidebar.search">Search</span><input id="sidebarSearch" type="search" aria-label="Search library" data-i18n-aria-label="sidebar.search"></label>
<label class="field" data-sidebar-section="view"><span data-i18n="sidebar.view">View</span><select id="view"><option value="all" data-i18n="sidebar.all_games">All games</option><option value="favorites" data-i18n="sidebar.favorites">Favorites</option><option value="recent" data-i18n="sidebar.recently_played">Recently played</option><option value="never" data-i18n="sidebar.never_played">Never played</option><option value="playing" data-i18n="sidebar.in_progress">In progress</option><option value="completed" data-i18n="sidebar.completed">Completed</option><option value="unplayed" data-i18n="sidebar.unplayed">Unplayed</option><option value="installed" data-i18n="sidebar.installed_only">Installed only</option><option value="owned" data-i18n="sidebar.owned_not_installed">Owned / not installed</option><option value="saves" data-i18n="sidebar.has_saves">Has saves</option><option value="shelf" data-i18n="sidebar.shelf_entries">Shelf entries</option><option value="hidden" data-i18n="sidebar.hidden">Hidden</option><option value="missing" data-i18n="sidebar.missing_files">Missing files</option></select></label>
<label class="field" data-sidebar-section="filters"><span data-i18n="sidebar.esrb">ESRB</span><select id="esrbFilter"><option value="" data-i18n="sidebar.any_rating">Any rating</option><option>E</option><option>E10+</option><option>T</option><option>M</option><option>AO</option><option>RP</option><option data-i18n="sidebar.unrated">Unrated</option></select></label>
<div class="field" data-sidebar-section="filters"><span>Source</span><div class="extras"><select id="sourceFilter"><option value="">Any source</option></select><label class="check"><input type="checkbox" id="sourceExclude"> Exclude</label></div></div>
<div class="section-title" data-sidebar-section="filters" data-i18n="sidebar.categories">Categories</div>
<nav class="platforms" id="platformCategories" data-sidebar-section="filters"></nav>
<div class="section-title" data-sidebar-section="platforms" data-i18n="sidebar.platforms">Platforms</div>
<nav class="platforms" id="platforms" data-sidebar-section="platforms"></nav>
<div class="section-title" data-sidebar-section="playlists" data-i18n="sidebar.playlists">Playlists</div>
<nav class="platforms" id="playlists" data-sidebar-section="playlists"></nav>
<div class="section-title" data-sidebar-section="filters" data-i18n="sidebar.filter_presets">Filter presets</div>
<nav class="platforms" id="filterPresets" data-sidebar-section="filters"></nav>
<div class="section-title" data-sidebar-section="filters" data-i18n="sidebar.smart_collections">Collections</div>
<nav class="platforms" id="smartCollections" data-sidebar-section="filters"></nav>
<div class="section-title" data-sidebar-section="explorer" data-i18n="sidebar.explorer">Explorer</div>
<nav class="platforms" id="explorerFacets" data-sidebar-section="explorer"></nav>
</aside>
<main class="library" aria-label="Game library" data-i18n-aria-label="library.game_library">
<div class="library-head">
<div><h1 id="libraryTitle" data-i18n="library.all_games">All Games</h1><p id="libraryMeta" aria-live="polite">0 games</p></div>
<div class="query-chips" id="queryChips" aria-label="Active filters" data-i18n-aria-label="library.active_filters"></div>
<select class="search" id="sort" aria-label="Sort games"><option value="title" data-i18n="library.sort_title">Title</option><option value="rating" data-i18n="library.sort_rating">Rating</option><option value="user_rating" data-i18n="library.sort_my_rating">My rating</option><option value="recent" data-i18n="library.sort_recent">Recently played</option><option value="recent_activity" data-i18n="library.sort_recent_activity">Recent activity</option><option value="playtime" data-i18n="library.sort_playtime">Play time</option><option value="added" data-i18n="library.sort_added">Date added</option><option value="platform" data-i18n="library.sort_platform">Platform</option><option value="genre" data-i18n="library.sort_genre">Genre</option></select>
<select class="search" id="imageGroup" aria-label="Image group"><option value="default" data-i18n="library.image_group_default">Use default</option><option value="cover" data-i18n="library.image_group_cover">Box fronts</option><option value="background" data-i18n="library.image_group_background">Backgrounds</option><option value="screenshot" data-i18n="library.image_group_screenshot">Screenshots</option><option value="clear_logo" data-i18n="library.image_group_clear_logo">Clear logos</option><option value="fanart" data-i18n="library.image_group_fanart">Fanart</option><option value="banner" data-i18n="library.image_group_banner">Banners</option><option value="box_back" data-i18n="library.image_group_box_back">Box backs</option><option value="box_spine" data-i18n="library.image_group_box_spine">Box spines</option><option value="box_3d" data-i18n="library.image_group_box_3d">3D boxes</option><option value="title_screen" data-i18n="library.image_group_title_screen">Title screens</option><option value="cart_front" data-i18n="library.image_group_cart_front">Cart fronts</option><option value="cart_back" data-i18n="library.image_group_cart_back">Cart backs</option><option value="disc" data-i18n="library.image_group_disc">Discs</option><option value="advertisement" data-i18n="library.image_group_advertisement">Ads / flyers</option><option value="manual" data-i18n="library.image_group_manual">Manuals</option></select>
<select class="search" id="grouping" aria-label="Group covers"><option value="shape" data-i18n="library.group_by_shape">Group by shape</option><option value="none" data-i18n="library.no_grouping">No grouping</option></select>
<button class="icon-button" id="filterDrawerButton" aria-haspopup="dialog" aria-controls="filterDrawer" data-i18n="library.filters">Filters</button>
<button class="icon-button" id="viewToggleButton" data-i18n="library.list_view">List view</button>
<button class="icon-button" id="surpriseButton" data-i18n="library.surprise_me">Surprise me</button>
</div>
<section id="homeHero" class="home-hero" hidden aria-label="Jump back in" data-i18n-aria-label="library.jump_back_in"></section>
<button type="button" class="drop-zone" id="dropZone" data-i18n="library.drop_zone">Drop ROM folders or game files here to import</button>
<div class="arrange-wrap">
<section class="grid" id="grid"><div class="card-skeleton" aria-hidden="true"></div><div class="card-skeleton" aria-hidden="true"></div><div class="card-skeleton" aria-hidden="true"></div><div class="card-skeleton" aria-hidden="true"></div><div class="card-skeleton" aria-hidden="true"></div><div class="card-skeleton" aria-hidden="true"></div><div class="card-skeleton" aria-hidden="true"></div><div class="card-skeleton" aria-hidden="true"></div></section>
<div class="arrange-bar" id="arrangeBar" hidden role="button" tabindex="0" aria-label="Jump through the current view" data-i18n-aria-label="library.jump_view"></div>
</div>
<section id="insightsPanel" class="insights-panel" aria-label="Play insights" data-i18n-aria-label="library.play_insights"></section>
</main>
<aside class="details" id="details" aria-label="Game details" data-i18n-aria-label="library.game_details" data-moments-host="detail"><div class="details-resize-handle" id="detailsResizeHandle" role="separator" aria-orientation="vertical" aria-label="Resize details pane" tabindex="0" data-i18n-aria-label="library.resize_details"></div><div class="detail-empty" id="detailEmptyInitial"><span data-i18n="library.select_game_prompt">Select a game to see its details.</span><span class="detail-empty-hint" data-i18n="library.select_game_hint">Use the arrow keys to browse and Enter to open.</span></div></aside>
</div>
<dialog id="filterDrawer" aria-modal="true" aria-labelledby="filterDrawerTitle">
<div class="dialog-head"><h2 id="filterDrawerTitle">Filters</h2><button type="button" id="closeFilterDrawer" aria-label="Close filters">×</button></div>
<div class="filter-drawer-body" id="filterDrawerBody"></div>
</dialog>
<dialog id="gameDialog" aria-modal="true" aria-labelledby="dialogTitle">
<form id="gameForm">
<div class="dialog-head game-editor-head"><h2 id="dialogTitle">Add game</h2><button type="button" id="closeDialog" aria-label="Close Add game dialog">×</button></div>
<nav class="game-editor-nav" id="gameEditorNav" aria-label="Editor sections">
<button type="button" class="game-editor-nav-item active" data-game-section="basics">Basics</button>
<button type="button" class="game-editor-nav-item" data-game-section="launch">Launch</button>
<button type="button" class="game-editor-nav-item" data-game-section="media">Media</button>
<button type="button" class="game-editor-nav-item" data-game-section="saves">Saves & Documents</button>
<button type="button" class="game-editor-nav-item" data-game-section="advanced">Advanced</button>
</nav>
<div class="form-grid game-editor-sections">
<section class="wide game-editor-section" data-game-section="basics" aria-labelledby="gameSectionBasics">
<h3 id="gameSectionBasics">Basics</h3>
<label class="field wide"><span data-i18n="game.entry_type">Entry type</span><select name="entry_type" id="gameEntryType"><option value="playable" data-i18n="game.entry_playable">Playable game</option><option value="shelf" data-i18n="game.entry_shelf">Shelf entry (no local file)</option></select></label>
<p class="wide description" id="gameShelfHint" data-i18n="game.shelf_hint" hidden>A shelf entry stays in your collection without a local file. Use Set up launch from its details when you have a file to play.</p>
<label class="field"><span>Name</span><input name="name" required></label>
<label class="field"><span>Platform</span><input name="platform"></label>
<label class="field"><span>Genre</span><input name="genre"></label>
<label class="field"><span>Year</span><input name="year"></label>
<label class="field"><span>Developer</span><input name="developer"></label>
<label class="field"><span>Publisher</span><input name="publisher"></label>
<label class="field"><span>Series</span><input name="series"></label>
<label class="field"><span>Region</span><input name="region"></label>
<label class="field"><span>Play mode</span><input name="play_mode"></label>
<label class="field"><span>Sort title</span><input name="sort_title"></label>
<label class="field"><span>Progress</span><select name="progress"><option value="">Not set</option><option value="Unplayed">Unplayed</option><option>Playing</option><option>Paused</option><option>Beaten</option><option>Completed</option><option>Mastered</option><option>Abandoned</option></select></label>
<label class="field"><span>ESRB</span><select name="esrb"><option value="">Not set</option><option>E</option><option>E10+</option><option>T</option><option>M</option><option>AO</option><option>RP</option><option>EC</option><option>Unrated</option></select></label>
<label class="field"><span>Rating, 0 to 5</span><input name="rating" type="number" min="0" max="5" step="0.5"></label>
<label class="field"><span data-i18n="price.paid">Price paid</span><input name="price_paid" type="number" min="0" step="0.01"></label>
<label class="field"><span data-i18n="price.currency">Currency</span><input name="price_currency" maxlength="3" placeholder="USD"></label>
<label class="field"><span>Max players</span><input name="max_players"></label>
<label class="field"><span>Wikipedia URL</span><input name="wikipedia_url"></label>
<label class="field"><span>Video URL</span><input name="video_url"></label>
<label class="field wide"><span>Alternate names, semicolon separated</span><input name="alternate_names"></label>
<label class="field wide"><span>Description</span><textarea name="description"></textarea></label>
<label class="field wide"><span>Private notes</span><textarea name="notes"></textarea></label>
</section>
<section class="wide game-editor-section" data-game-section="launch" aria-labelledby="gameSectionLaunch" hidden>
<h3 id="gameSectionLaunch">Launch</h3>
<label class="field wide path-field"><span>Game or ROM path</span><span class="path-input-row"><input name="path" required><button type="button" class="path-browse" data-browse-for="path" data-browse-kind="file">Browse</button></span></label>
<label class="field"><span>Controller support</span><input name="controller_support" placeholder="Gamepad, keyboard"></label>
<div class="wide extras" id="controllerTypeChoices" aria-label="Controller support types"></div>
<label class="field"><span>Disc count</span><input name="disc_count" type="number" min="0" max="99"></label>
<label class="field wide"><span>Launch command, optional override</span><input name="launch"></label>
<label class="field wide"><span>Launch profile override</span><select name="launch_profile"><option value="">Default platform profile</option></select></label>
<label class="field wide" data-feature="gamescope"><span>Gamescope preset override</span><select name="gamescope_preset"><option value="">Global setting</option></select></label>
<label class="field wide"><span>Environment overrides, one per line: KEY=value</span><textarea name="launch_env" rows="3" placeholder="PROTON_NO_ESYNC=1"></textarea></label>
<label class="check"><input type="checkbox" name="extract_archive">Extract archive before launch</label>
<label class="check"><input type="checkbox" name="launch_confirm">Always confirm before launch</label>
<label class="check"><input type="checkbox" name="hide_in_bigbox"> Hide in Big Box</label>
<label class="check"><input type="checkbox" name="hidden">Hide from normal views</label>
<label class="check"><input type="checkbox" name="broken"> Mark as broken</label>
<label class="check"><input type="checkbox" name="portable"> Mark as portable</label>
<label class="field"><span>Archive member</span><input name="archive_member"></label>
<label class="field wide path-field"><span>Additional applications, one per line: Name | Path | Command</span><span class="path-input-row"><textarea name="applications"></textarea><button type="button" class="path-browse" data-browse-for="applications" data-browse-kind="multi">Browse</button></span></label>
<label class="field wide path-field"><span>Alternate versions, one per line: Name | Path | Command</span><span class="path-input-row"><textarea name="versions"></textarea><button type="button" class="path-browse" data-browse-for="versions" data-browse-kind="multi">Browse</button></span></label>
</section>
<section class="wide game-editor-section" data-game-section="media" aria-labelledby="gameSectionMedia" hidden>
<h3 id="gameSectionMedia">Media</h3>
<label class="field wide path-field"><span>Video snap path</span><span class="path-input-row"><input name="video_snap"><button type="button" class="path-browse" data-browse-for="video_snap" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>Theme video path</span><span class="path-input-row"><input name="video_theme"><button type="button" class="path-browse" data-browse-for="video_theme" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>Trailer path</span><span class="path-input-row"><input name="video_trailer"><button type="button" class="path-browse" data-browse-for="video_trailer" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>Recording path</span><span class="path-input-row"><input name="video_recording"><button type="button" class="path-browse" data-browse-for="video_recording" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field"><span>Cover image path</span><span class="path-input-row"><input name="cover"><button type="button" class="path-browse" data-browse-for="cover" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field"><span>Background image path</span><span class="path-input-row"><input name="background"><button type="button" class="path-browse" data-browse-for="background" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>Video path</span><span class="path-input-row"><input name="video"><button type="button" class="path-browse" data-browse-for="video" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>Music path</span><span class="path-input-row"><input name="music"><button type="button" class="path-browse" data-browse-for="music" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field"><span>Clear logo path</span><span class="path-input-row"><input name="clear_logo"><button type="button" class="path-browse" data-browse-for="clear_logo" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>Fanart path</span><span class="path-input-row"><input name="fanart"><button type="button" class="path-browse" data-browse-for="fanart" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>Banner path</span><span class="path-input-row"><input name="banner"><button type="button" class="path-browse" data-browse-for="banner" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field"><span>Icon path</span><span class="path-input-row"><input name="icon"><button type="button" class="path-browse" data-browse-for="icon" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>Box back path</span><span class="path-input-row"><input name="box_back"><button type="button" class="path-browse" data-browse-for="box_back" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>Box spine path</span><span class="path-input-row"><input name="box_spine"><button type="button" class="path-browse" data-browse-for="box_spine" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>3D box path</span><span class="path-input-row"><input name="box_3d"><button type="button" class="path-browse" data-browse-for="box_3d" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>Title screen path</span><span class="path-input-row"><input name="title_screen"><button type="button" class="path-browse" data-browse-for="title_screen" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>Cart front path</span><span class="path-input-row"><input name="cart_front"><button type="button" class="path-browse" data-browse-for="cart_front" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>Cart back path</span><span class="path-input-row"><input name="cart_back"><button type="button" class="path-browse" data-browse-for="cart_back" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>Disc path</span><span class="path-input-row"><input name="disc"><button type="button" class="path-browse" data-browse-for="disc" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>Advertisement / flyer path</span><span class="path-input-row"><input name="advertisement"><button type="button" class="path-browse" data-browse-for="advertisement" data-browse-kind="file">Browse</button></span></label>
<label class="field wide path-field media-rare" hidden><span>Manual path</span><span class="path-input-row"><input name="manual"><button type="button" class="path-browse" data-browse-for="manual" data-browse-kind="file">Browse</button></span></label>
<button type="button" class="icon-button media-more-toggle" id="mediaMoreToggle" aria-expanded="false" data-i18n="dialog.media_show_more_initial">Show more media types</button>
<label class="field wide path-field"><span>Screenshot paths, one per line</span><span class="path-input-row"><textarea name="screenshots"></textarea><button type="button" class="path-browse" data-browse-for="screenshots" data-browse-kind="multi">Browse</button></span></label>
</section>
<section class="wide game-editor-section" data-game-section="saves" aria-labelledby="gameSectionSaves" hidden>
<h3 id="gameSectionSaves">Saves & Documents</h3>
<label class="field wide path-field"><span>Documents, one per line: Name | Path</span><span class="path-input-row"><textarea name="documents"></textarea><button type="button" class="path-browse" data-browse-for="documents" data-browse-kind="multi">Browse</button></span></label>
<label class="field wide path-field"><span>Save paths, one per line</span><span class="path-input-row"><textarea name="save_paths"></textarea><button type="button" class="path-browse" data-browse-for="save_paths" data-browse-kind="multi">Browse</button></span></label>
</section>
<section class="wide game-editor-section" data-game-section="advanced" aria-labelledby="gameSectionAdvanced" hidden>
<h3 id="gameSectionAdvanced">Advanced</h3>
<label class="field wide"><span>Cover model</span><select name="cover_model"><option value="">Use platform / global setting</option><option value="box">Box</option><option value="jewel">Jewel case</option><option value="long_jewel">Long jewel case</option><option value="double_jewel">Double jewel case</option><option value="cassette">Cassette</option><option value="none">Flat cover</option></select></label>
<label class="field wide"><span>RetroAchievements Game ID, optional manual match</span><input name="ra_game_id" inputmode="numeric"></label>
<div class="wide form-grid" id="customFieldInputs"></div>
</section>
</div>
<div class="dialog-actions game-editor-actions">
<div class="dialog-nav" id="gameDialogNav">
<button type="button" class="icon-button" id="prevGameDialog" aria-label="Previous game">← Previous</button>
<button type="button" class="icon-button" id="nextGameDialog" aria-label="Next game">Next →</button>
</div>
<button type="button" class="icon-button" id="cancelDialog">Cancel</button>
<button class="primary" type="submit">Save</button>
</div>
</form>
</dialog>
<dialog id="emulatorSettingsDialog" aria-modal="true" aria-labelledby="emulatorSettingsTitle">
<form id="emulatorSettingsForm">
<div class="dialog-head"><h2 id="emulatorSettingsTitle">Emulator settings</h2><button type="button" id="closeEmulatorSettings" aria-label="Close emulator settings dialog">×</button></div>
<div class="form-grid" id="emulatorSettingsBody"></div>
<div class="dialog-actions"><button type="button" class="icon-button" id="cancelEmulatorSettings">Cancel</button><button class="primary" type="submit">Save</button></div>
</form>
</dialog>
<dialog id="profilesDialog" aria-modal="true" class="profiles-dialog" aria-labelledby="profilesDialogTitle">
<form id="profilesForm">
<div class="dialog-head"><h2 id="profilesDialogTitle">Emulator profiles</h2><button type="button" id="closeProfiles" aria-label="Close Emulator profiles dialog">×</button></div>
<div class="form-grid">
<label class="field wide"><span>One profile per line: Platform = command. Use {path} for the ROM.</span><textarea id="profilesText"></textarea></label>
<div class="wide" id="detectedProfiles"></div>
<div class="wide" data-feature="handheld_perf"><div class="section-title">Handheld performance</div><p class="description">Set a TDP limit (watts) applied via ryzenadj when a game from this profile launches, and an optional restore limit when the session ends. Requires ryzenadj on PATH.</p><div class="form-grid" id="perfProfiles"></div></div>
<div class="wide detail-card" id="defsPanel">
<div class="section-title" data-i18n="defs.title">Emulator definitions</div>
<p class="description" id="defsStatus"></p>
<div class="extras">
<button type="button" class="icon-button" id="defsCheck" data-i18n="defs.check">Check for definition updates</button>
<button type="button" class="primary" id="defsInstall" data-i18n="defs.install" hidden>Install update</button>
<button type="button" class="icon-button" id="defsRollback" data-i18n="defs.rollback" hidden>Roll back to bundled</button>
</div>
<p class="description" id="defsDetail" role="status"></p>
</div>
<div class="wide"><div class="section-title">Install and configure</div><div class="emulator-list" id="emulatorCatalog"></div></div>
</div>
<div class="dialog-actions"><button type="button" class="icon-button" id="cancelProfiles">Cancel</button><button class="primary">Save</button></div>
</form>
</dialog>
<dialog id="themesDialog" aria-modal="true" aria-labelledby="themesDialogTitle">
<form id="themesForm">
<div class="dialog-head"><h2 id="themesDialogTitle">Themes</h2><button type="button" id="closeThemes" aria-label="Close Themes dialog">×</button></div>
<div class="form-grid">
<p class="wide description">Stock themes ship with OpenBox. Import your own CSS to restyle the library, detail pane, dialogs, and Big Box.</p>
<label class="field wide"><span>Apply to</span><select id="themeScope"><option value="">All platforms</option></select></label>
<p class="wide description" data-i18n="themes.gallery_hint">Pick a theme below, then choose Apply. Themes change colors, not layout.</p>
<div class="theme-gallery" id="themeGallery"></div>
<label class="field wide"><span data-i18n="themes.active_theme">Active theme</span><select id="themeSelect"><option value="">Default</option></select></label>
<button type="button" class="icon-button" id="importTheme">Import CSS theme</button>
<button type="button" class="icon-button" id="openThemeFolder">Open themes folder</button>
</div>
<div class="dialog-actions"><button type="button" class="icon-button" id="cancelThemes">Cancel</button><button class="primary">Apply</button></div>
</form>
</dialog>
<dialog id="netplayDialog" aria-modal="true" aria-labelledby="netplayTitle">
<div class="dialog-head"><h2 id="netplayTitle">RetroArch netplay lobby</h2><button type="button" id="closeNetplay" aria-label="Close netplay lobby">×</button></div>
<p class="description">Copy a room address into RetroArch's netplay menu. OpenBox does not host or launch rooms.</p>
<div class="storefront-status" id="netplayLobby"></div>
</dialog>
<dialog id="bigBoxAchievementsDialog" aria-modal="true" aria-labelledby="bigBoxAchievementsTitle">
<div class="dialog-head"><h2 id="bigBoxAchievementsTitle">Achievements</h2><button type="button" id="closeBigBoxAchievements" aria-label="Close achievements">×</button></div>
<div id="bigBoxAchievementsContent"></div>
</dialog>
<dialog id="achievementsDialog" aria-modal="true" aria-labelledby="achievementsDialogTitle">
<form id="achievementsForm">
<div class="dialog-head"><h2 id="achievementsDialogTitle">RetroAchievements</h2><button type="button" id="closeAchievements" aria-label="Close RetroAchievements dialog">×</button></div>
<div class="form-grid">
<label class="field"><span>Username</span><input id="raUsername" required></label>
<label class="field"><span>Web API key</span><input id="raApiKey" type="password" autocomplete="off"></label>
<div class="wide description" id="raProfile">Get your web API key from your RetroAchievements settings.</div>
<button type="button" class="icon-button" id="injectRa">Inject credentials into emulators</button>
</div>
<div class="dialog-actions"><button type="button" class="icon-button" id="cancelAchievements">Cancel</button><button class="primary">Connect account</button></div>
</form>
</dialog>
<dialog id="pluginsDialog" aria-modal="true" aria-labelledby="pluginsDialogTitle">
<div class="dialog-head"><h2 id="pluginsDialogTitle">Plugins</h2><button type="button" id="closePlugins" aria-label="Close Plugins dialog">×</button></div>
<div class="form-grid">
<div class="wide description">Plugins are trusted local Python code. Install only packages you trust.</div>
<div class="wide extras">
<button type="button" class="icon-button" id="pluginTabInstalled" data-i18n="plugins.tab_installed">Installed</button>
<button type="button" class="icon-button" id="pluginTabBrowse" data-i18n="plugins.tab_browse">Browse</button>
</div>
<div class="wide emulator-list" id="pluginList"></div>
<div class="wide emulator-list" id="pluginBrowse" hidden></div>
<button type="button" class="icon-button" id="browsePluginCatalog">Browse community catalog</button>
<button type="button" class="icon-button" id="installPlugin">Install or update package</button>
</div>
<div class="dialog-actions"><button type="button" class="primary" id="donePlugins">Done</button></div>
</dialog>
<dialog id="metadataDialog" aria-modal="true" aria-labelledby="metadataDialogTitle">
<div class="dialog-head"><h2 id="metadataDialogTitle">LaunchBox Games Database</h2><button type="button" id="closeMetadata" aria-label="Close LaunchBox Games Database dialog">×</button></div>
<form id="metadataSearchForm" class="form-grid">
<label class="field wide"><span>Game title</span><input id="metadataQuery" required></label>
<button class="icon-button" id="syncMetadata" type="button">Download database</button>
<button class="icon-button" id="searchIgdb" type="button">Search IGDB</button>
<button class="icon-button" id="searchScreenscraper" type="button">Search ScreenScraper</button>
<button class="icon-button" id="hashMatchScreenscraper" type="button">ScreenScraper hash-match</button>
<button class="icon-button" id="searchSteamgrid" type="button" data-i18n="metadata.steamgrid_search" hidden>Search SteamGridDB</button>
<button class="icon-button" id="bulkSteamgrid" type="button" data-i18n="metadata.steamgrid_bulk" hidden>Fill missing art via SteamGridDB</button>
<button class="primary" type="submit">Search</button>
<button class="icon-button" id="autoMatchMetadata" type="button">Auto-match library</button>
<div class="wide section-title" data-i18n="metadata.launchbox_heading">LaunchBox migration</div>
<div class="wide detail-card">
<p class="description" data-i18n="metadata.launchbox_description">Preview a LaunchBox XML export before adding or merging games. The preview is bound to this file and your current library.</p>
<label class="field wide"><span data-i18n="metadata.launchbox_xml">LaunchBox XML file</span><span class="path-input-row"><input id="launchboxXmlPath" type="text" data-i18n-placeholder="metadata.launchbox_xml_placeholder" placeholder="/path/to/Platforms.xml"><button type="button" class="path-browse" id="browseLaunchBoxXml" data-i18n="common.browse">Browse</button></span></label>
<div class="form-grid">
<label class="field"><span data-i18n="metadata.launchbox_source_root">Source path root (optional)</span><input id="launchboxSourceRoot" type="text" placeholder="C:\\Games"></label>
<label class="field"><span data-i18n="metadata.launchbox_destination_root">Local path root (optional)</span><input id="launchboxDestinationRoot" type="text" placeholder="/home/user/Games"></label>
<label class="field wide"><span data-i18n="metadata.launchbox_emulator_map">Emulator mappings (one LaunchBox ID=OpenBox adapter per line)</span><textarea id="launchboxEmulatorMap" rows="2" placeholder="launchbox-emulator-id=retroarch"></textarea></label>
<label class="check wide"><input type="checkbox" id="launchboxOverwrite"> <span data-i18n="metadata.launchbox_overwrite">Overwrite existing path and metadata fields</span></label>
</div>
<div class="extras"><button type="button" class="icon-button" id="previewLaunchBox" data-i18n="metadata.launchbox_preview">Preview migration</button><button type="button" class="primary" id="applyLaunchBox" data-i18n="metadata.launchbox_apply" hidden disabled>Apply preview</button></div>
<p class="wide description" id="launchboxStatus" aria-live="polite"></p>
<div class="wide metadata-results" id="launchboxReport" hidden></div>
</div>
<div class="wide section-title" data-i18n="metadata.esde_heading">ES-DE import</div>
<div class="wide detail-card">
<p class="description" data-i18n="metadata.esde_description">Preview an ES-DE gamelist.xml before adding or merging games. Paths remain local references.</p>
<label class="field wide"><span data-i18n="metadata.esde_xml">ES-DE gamelist.xml</span><span class="path-input-row"><input id="esdeXmlPath" type="text" data-i18n-placeholder="metadata.esde_xml_placeholder" placeholder="/path/to/gamelist.xml"><button type="button" class="path-browse" id="browseEsdeXml" data-i18n="common.browse">Browse</button></span></label>
<div class="extras"><button type="button" class="icon-button" id="previewEsde" data-i18n="metadata.esde_preview">Preview ES-DE import</button><button type="button" class="primary" id="applyEsde" data-i18n="metadata.esde_apply" hidden disabled>Apply preview</button></div>
<p class="wide description" id="esdeStatus" aria-live="polite"></p>
<div class="wide metadata-results" id="esdeReport" hidden></div>
</div>
<div class="wide description" id="metadataStatus"></div>
<div class="wide detail-card" id="metadataCoverage" style="display:none"><div class="facts" id="metadataCoverageFacts"></div></div>
<div class="wide extras" id="metadataProviderFilters"></div>
<div class="wide metadata-results" id="metadataResults"></div>
<label class="check"><input type="checkbox" id="metadataCover" checked> Box front</label>
<label class="check"><input type="checkbox" id="metadataBackground" checked> Background</label>
<label class="check"><input type="checkbox" id="metadataScreenshots" checked> Screenshots</label>
<label class="check"><input type="checkbox" id="metadataBoxBack"> Box back</label>
<label class="check"><input type="checkbox" id="metadataBoxSpine"> Box spine</label>
<label class="check"><input type="checkbox" id="metadataBox3d"> 3D box</label>
<label class="check"><input type="checkbox" id="metadataClearLogo"> Clear logo</label>
<label class="check"><input type="checkbox" id="metadataFanart"> Fanart</label>
<label class="check"><input type="checkbox" id="metadataBanner"> Banner</label>
<label class="check"><input type="checkbox" id="metadataIcon"> Icon</label>
<label class="check"><input type="checkbox" id="metadataTitleScreen"> Title screen</label>
<label class="check"><input type="checkbox" id="metadataCartFront"> Cart front</label>
<label class="check"><input type="checkbox" id="metadataCartBack"> Cart back</label>
<label class="check"><input type="checkbox" id="metadataDisc"> Disc</label>
<label class="check"><input type="checkbox" id="metadataAdvertisement"> Advertisement / flyer</label>
<label class="check"><input type="checkbox" id="metadataManual"> Manual</label>
<label class="check"><input type="checkbox" id="metadataOverwrite"> Replace existing fields and media</label>
</form>
<div class="dialog-actions"><button type="button" class="primary" id="doneMetadata">Done</button></div>
</dialog>
<dialog id="mediaManagerDialog" aria-modal="true" aria-labelledby="mediaManagerDialogTitle">
<div class="dialog-head"><h2 id="mediaManagerDialogTitle">Media Manager</h2><button type="button" id="closeMediaManager" aria-label="Close Media Manager dialog">×</button></div>
<div class="form-grid">
<div class="wide detail-card" id="mediaAudit"></div>
<label class="check"><input type="checkbox" id="bulkCover" checked> Box fronts</label>
<label class="check"><input type="checkbox" id="bulkBackground" checked> Backgrounds</label>
<label class="check"><input type="checkbox" id="bulkScreenshots" checked> Screenshots</label>
<label class="check"><input type="checkbox" id="bulkPoster"> Posters</label>
<label class="check"><input type="checkbox" id="bulkSquare"> Square art</label>
<label class="check"><input type="checkbox" id="bulkBoxBack"> Box backs</label>
<label class="check"><input type="checkbox" id="bulkBoxSpine"> Box spines</label>
<label class="check"><input type="checkbox" id="bulkBox3d"> 3D boxes</label>
<label class="check"><input type="checkbox" id="bulkClearLogo"> Clear logos</label>
<label class="check"><input type="checkbox" id="bulkFanart"> Fanart</label>
<label class="check"><input type="checkbox" id="bulkBanner"> Banners</label>
<label class="check"><input type="checkbox" id="bulkIcon"> Icons</label>
<label class="check"><input type="checkbox" id="bulkTitleScreen"> Title screens</label>
<label class="check"><input type="checkbox" id="bulkCartFront"> Cart fronts</label>
<label class="check"><input type="checkbox" id="bulkCartBack"> Cart backs</label>
<label class="check"><input type="checkbox" id="bulkDisc"> Discs</label>
<label class="check"><input type="checkbox" id="bulkAdvertisement"> Ads / flyers</label>
<label class="check"><input type="checkbox" id="bulkManual"> Manuals</label>
<label class="check"><input type="checkbox" id="bulkVideoSnap"> Video snaps</label>
<label class="check"><input type="checkbox" id="bulkVideoTheme"> Theme videos</label>
<label class="check"><input type="checkbox" id="bulkVideoTrailer"> Trailers</label>
<label class="check"><input type="checkbox" id="bulkMusic"> Music</label>
<label class="check"><input type="checkbox" id="bulkOverwrite"> Replace existing media</label>
<button type="button" class="primary" id="startBulkMedia">Download for matched games</button>
<button type="button" class="icon-button" id="retryBulkMedia" disabled>Retry failed</button>
<button type="button" class="icon-button" id="cleanupMedia">Find duplicate media</button>
<button type="button" class="icon-button" id="applyCleanupMedia" hidden>Delete duplicate media</button>
<div class="wide detail-card" id="mediaQueueStatus"></div>
<div class="wide extras"><button type="button" class="icon-button" id="pauseMediaQueue">Pause queue</button><button type="button" class="icon-button" id="resumeMediaQueue">Resume queue</button><button type="button" class="icon-button" id="cancelMediaQueue">Cancel queue</button><button type="button" class="icon-button" id="refreshMediaQueue">Refresh queue</button><button type="button" class="icon-button" id="cleanupMediaCache">Clear old media cache</button></div>
<div class="wide description" id="bulkMediaStatus"></div>
</div>
<div class="dialog-actions"><button type="button" class="primary" id="doneMediaManager">Done</button></div>
</dialog>
<dialog id="healthDialog" aria-modal="true" aria-labelledby="healthDialogTitle">
<div class="dialog-head"><h2 id="healthDialogTitle" data-i18n="health.title">Library checkup</h2><button type="button" id="closeHealth" aria-label="Close library checkup" data-i18n-aria-label="health.close">×</button></div>
<div class="form-grid">
<div class="wide detail-card" id="healthSummary"></div>
<div class="wide extras" id="auditSourceTools" hidden>
<label class="field"><span>Source</span><select id="auditSourceFilter"><option value="">All sources</option></select></label>
<span class="extras" id="auditSourceChips"></span>
</div>
<div class="wide metadata-results" id="healthIssues"></div>
<div class="wide detail-card" id="jobsPanel" hidden></div>
<button type="button" class="icon-button" id="scanAllSaves">Scan library for saves</button>
<button type="button" class="icon-button" id="dedupeButton">Remove duplicate entries</button>
</div>
<div class="dialog-actions"><button type="button" class="primary" id="doneHealth">Done</button></div>
</dialog>
<dialog id="healthScoreDialog" aria-modal="true" aria-labelledby="healthScoreDialogTitle">
<div class="dialog-head"><h2 id="healthScoreDialogTitle" data-i18n="health.title">Library health</h2><button type="button" id="closeHealthScore" aria-label="Close library health dialog">×</button></div>
<div class="dialog-body" id="healthScoreBody"></div>
<div class="dialog-actions"><button type="button" class="primary" id="doneHealthScore" data-i18n="common.done">Done</button></div>
</dialog>
<dialog id="bulkDialog" aria-modal="true" aria-labelledby="bulkDialogTitle">
<form id="bulkForm">
<div class="dialog-head"><h2 id="bulkDialogTitle">Bulk Edit</h2><button type="button" id="closeBulk" aria-label="Close Bulk Edit dialog">×</button></div>
<div class="form-grid">
<p class="wide description" id="bulkCount"></p>
<label class="field"><span>Platform, blank keeps current</span><input name="platform"></label>
<label class="field"><span>Genre, blank keeps current</span><input name="genre"></label>
<label class="field"><span>Progress</span><select name="progress"><option value="">Keep current</option><option value="Unplayed">Unplayed</option><option>Playing</option><option>Paused</option><option>Beaten</option><option>Completed</option><option>Mastered</option><option>Abandoned</option><option value="__clear">Clear</option></select></label>
<label class="field"><span data-i18n="bulk.my_rating">My rating</span><select name="user_rating"><option value="">Keep current</option><option value="0">Clear</option><option>1</option><option>2</option><option>3</option><option>4</option><option>5</option></select></label><label class="field"><span>Rating</span><select name="rating"><option value="">Keep current</option><option value="0">0</option><option value="0.5">0.5</option><option value="1">1</option><option value="1.5">1.5</option><option value="2">2</option><option value="2.5">2.5</option><option value="3">3</option><option value="3.5">3.5</option><option value="4">4</option><option value="4.5">4.5</option><option value="5">5</option></select></label>
<label class="field"><span>Favorite</span><select name="favorite"><option value="">Keep current</option><option value="true">Yes</option><option value="false">No</option></select></label>
<label class="field"><span>Hidden</span><select name="hidden"><option value="">Keep current</option><option value="true">Yes</option><option value="false">No</option></select></label>
<label class="field"><span>ESRB</span><select name="esrb"><option value="">Keep current</option><option>E</option><option>E10+</option><option>T</option><option>M</option><option>AO</option><option>RP</option><option>Unrated</option></select></label>
<label class="field"><span data-i18n="bulk.price_paid">Price paid</span><input name="price_paid" type="number" min="0" step="0.01" placeholder="Keep current"></label>
<label class="field"><span data-i18n="bulk.price_currency">Currency</span><input name="price_currency" maxlength="3" placeholder="USD"></label>
<label class="check wide"><input type="checkbox" name="price_clear"> <span data-i18n="bulk.clear_price">Clear price paid</span></label>
<label class="check wide"><input type="checkbox" name="reset_stats"> Reset play count, play time, and last played date</label>
<label class="check wide"><input type="checkbox" name="migrate_media"> <span id="bulkMigrateMediaLabel">Move media files for the selected games when the platform changes</span></label>
<label class="field"><span>Find text</span><input name="find_text" placeholder="Leave blank to skip"></label>
<label class="field"><span>Replace with</span><input name="replace_text"></label>
<label class="field"><span>Find in field</span><select name="find_field"><option value="name">Name</option><option value="notes">Notes</option><option value="genre">Genre</option><option value="developer">Developer</option><option value="publisher">Publisher</option><option value="platform">Platform</option><option value="region">Region</option><option value="source">Source</option></select></label>
</div>
<div class="dialog-actions"><button type="button" class="icon-button" id="cancelBulk">Cancel</button><button class="primary">Apply</button></div>
</form>
</dialog>
<dialog id="playlistsDialog" aria-modal="true" aria-labelledby="playlistsDialogTitle">
<div class="dialog-head"><h2 id="playlistsDialogTitle">Playlists</h2><button type="button" id="closePlaylists" aria-label="Close Playlists dialog">×</button></div>
<div class="form-grid">
<div class="wide extras"><button type="button" class="primary" id="newManualPlaylist">New manual playlist</button><button type="button" class="icon-button" id="newFilterPlaylist">New filter playlist</button></div>
<div class="wide description">Manual playlists keep an ordered set of games. Filter playlists update from their rules.</div>
<div class="wide playlist-manager-list" id="playlistManagerList"></div>
</div>
<div class="dialog-actions"><button type="button" class="primary" id="donePlaylists">Done</button></div>
</dialog>
<dialog id="backupDialog" aria-modal="true" aria-labelledby="backupDialogTitle">
<div class="dialog-head"><h2 id="backupDialogTitle">Backups</h2><button type="button" id="closeBackups" aria-label="Close Backups dialog">×</button></div>
<div class="form-grid">
<div class="wide extras"><button type="button" class="primary" id="createNamedBackup">Create backup</button><button type="button" class="icon-button" id="refreshBackups">Refresh</button></div>
<div class="wide description">Backups include selected library data, settings, media, plugins, and themes. Restore creates a safety copy first.</div>
<div class="wide backup-list" id="backupList"></div>
<div class="wide backup-preview" id="backupPreview" hidden></div>
</div>
<div class="dialog-actions"><button type="button" class="primary" id="doneBackups">Done</button></div>
</dialog>
<dialog id="sessionsDialog" aria-modal="true" aria-labelledby="sessionsDialogTitle">
<div class="dialog-head"><h2 id="sessionsDialogTitle">Running Games</h2><button type="button" id="closeSessions" aria-label="Close Running Games dialog">×</button></div>
<div class="form-grid"><div class="wide emulator-list" id="sessionList"></div></div>
<div class="dialog-actions"><button type="button" class="primary" id="doneSessions">Done</button></div>
</dialog>
<dialog id="historyDialog" aria-modal="true" aria-labelledby="historyDialogTitle">
<div class="dialog-head"><h2 id="historyDialogTitle">Play Session History</h2><button type="button" id="closeHistory" aria-label="Close Play Session History dialog">×</button></div>
<div class="dialog-tabs" role="tablist" aria-label="History tabs">
<button type="button" class="dialog-tab active" role="tab" id="historyTabList" aria-selected="true" data-i18n="timeline.list">List</button>
<button type="button" class="dialog-tab" role="tab" id="historyTabTimeline" aria-selected="false" data-i18n="timeline.timeline">Timeline</button>
</div>
<div class="form-grid" id="historyListPane"><div class="wide history-list" id="historyList"></div></div>
<div class="form-grid" id="historyTimelinePane" hidden><div class="wide timeline" id="timelineContainer"></div></div>
<div class="dialog-actions"><button type="button" class="primary" id="doneHistory">Done</button></div>
</dialog>
<dialog id="timeMachineDialog" aria-modal="true" aria-labelledby="timeMachineDialogTitle">
<div class="dialog-head"><h2 id="timeMachineDialogTitle" data-i18n="time_machine.title">Library Time Machine</h2><button type="button" id="closeTimeMachine" aria-label="Close Time Machine">×</button></div>
<div class="dialog-tabs" role="tablist" aria-label="Time Machine views">
<button type="button" class="dialog-tab active" role="tab" id="tmEventsTab" aria-selected="true" data-i18n="time_machine.timeline">Timeline</button>
<button type="button" class="dialog-tab" role="tab" id="tmAsOfTab" aria-selected="false" data-i18n="time_machine.as_of">Browse as of</button>
<button type="button" class="dialog-tab" role="tab" id="tmCompareTab" aria-selected="false" data-i18n="time_machine.compare">Compare</button>
</div>
<div class="form-grid" id="timeMachineEventsPane">
<label class="field"><span data-i18n="time_machine.kind">Kind</span><select id="tmKind"><option value="" data-i18n="time_machine.all_kinds">All events</option><option value="add" data-i18n="time_machine.kind_add">Add</option><option value="edit" data-i18n="time_machine.kind_edit">Edit</option><option value="delete" data-i18n="time_machine.kind_delete">Delete</option><option value="restore" data-i18n="time_machine.kind_restore">Restore</option><option value="revert" data-i18n="time_machine.kind_revert">Revert</option></select></label>
<label class="field"><span data-i18n="time_machine.days">Days</span><input id="tmDays" type="number" min="1" placeholder="400"></label>
<label class="field"><span data-i18n="time_machine.game">Game ID</span><input id="tmGame" type="search" autocomplete="off"></label>
<div class="field"><span> </span><button type="button" class="icon-button" id="tmRefresh" data-i18n="time_machine.refresh">Refresh</button></div>
<div class="wide timeline" id="timeMachineEventsBody"><p class="muted" data-i18n="time_machine.loading">Loading Time Machine…</p></div>
</div>
<div class="form-grid" id="timeMachineAsOfPane" hidden>
<label class="field"><span data-i18n="time_machine.date">Date</span><input id="tmAsOfDate" type="date"></label>
<div class="field"><span> </span><button type="button" class="icon-button" id="tmAsOfButton" data-i18n="time_machine.reconstruct">Reconstruct</button></div>
<p class="wide description" id="timeMachineAsOfMeta"></p>
<div class="wide" id="timeMachineAsOfBody"><p class="muted" data-i18n="time_machine.no_date">Choose a date.</p></div>
</div>
<div class="form-grid" id="timeMachineComparePane" hidden>
<label class="field"><span data-i18n="time_machine.compare_before">From (optional)</span><input id="tmCompareBefore" type="date"></label>
<label class="field"><span data-i18n="time_machine.compare_after">To</span><input id="tmCompareAfter" type="date"></label>
<div class="field"><span> </span><button type="button" class="icon-button" id="tmCompareButton" data-i18n="time_machine.compare_run">Compare</button></div>
<p class="wide description" id="timeMachineCompareMeta" data-i18n="time_machine.compare_hint">Pick a date, or two dates to see what changed between them.</p>
<div class="wide timeline" id="timeMachineCompareBody"></div>
</div>
<div class="dialog-actions"><button type="button" class="primary" id="doneTimeMachine" data-i18n="common.done">Done</button></div>
</dialog>
<dialog id="recapDialog" aria-modal="true" aria-labelledby="recapDialogTitle">
<div class="dialog-head"><h2 id="recapDialogTitle" data-i18n="recap.title">Session Recap</h2><button type="button" id="closeRecap" aria-label="Close Session Recap dialog">×</button></div>
<div class="recap-card" id="recapCard"></div>
<div class="dialog-actions"><button type="button" class="primary" id="recapDone" data-i18n="recap.done">Done</button></div>
</dialog>
<dialog id="welcomeDialog" hidden aria-hidden="true"></dialog>
<dialog id="setupCenter" aria-modal="true" aria-labelledby="setupCenterTitle" class="setup-center-dialog">
<div class="dialog-head setup-center-head"><h2 id="setupCenterTitle" data-i18n="setup.title">Set up your library</h2><button type="button" id="closeSetupCenter" aria-label="Close setup" data-i18n-aria-label="setup.close">×</button></div>
<div class="setup-center-body" id="setupCenterBody" role="region" aria-label="Setup workflow">
<p class="description">Guided library setup loads here.</p>
</div>
</dialog>
<dialog id="featureDialog" aria-modal="true" aria-labelledby="featureDialogTitle">
<div class="dialog-head"><h2 id="featureDialogTitle">OpenBox</h2><button type="button" id="closeFeature" aria-label="Close feature dialog">×</button></div>
<div class="form-grid"><div class="wide" id="featureContent"></div></div>
<div class="dialog-actions"><button type="button" class="primary" id="doneFeature">Done</button></div>
</dialog>
<div class="shutdown-overlay" id="shutdownOverlay" hidden>
<div class="shutdown-panel">
<h2>Shutting down OpenBox</h2>
<p id="shutdownMessage">Closing running games and startup applications...</p>
<div class="dialog-actions"><button type="button" class="icon-button" id="forceShutdown">Force close</button></div>
</div>
</div>
<dialog id="helpDialog" aria-modal="true" aria-labelledby="helpTitle" class="help-dialog">
<div class="dialog-head"><h2 id="helpTitle" data-i18n="help.title">Help & shortcuts</h2>
<button type="button" id="closeHelp" aria-label="Close Help" data-i18n-aria-label="help.close">×</button></div>
<div class="dialog-tabs" role="tablist" id="helpTabs"></div>
<div class="help-body" id="helpBody"></div>
</dialog>
<dialog id="settingsDialog" aria-modal="true" aria-labelledby="settingsDialogTitle">
<form id="settingsForm">
<div class="dialog-head"><h2 id="settingsDialogTitle">OpenBox Settings</h2><button type="button" id="closeSettings" aria-label="Close OpenBox Settings dialog">×</button></div>
<div class="settings-shell">
<nav class="settings-nav" id="settingsNav" aria-label="Settings categories">
<button type="button" class="settings-nav-item active" data-settings-category="library" data-i18n="settings.library">Library</button>
<button type="button" class="settings-nav-item" data-settings-category="imports" data-i18n="settings.imports">Imports</button>
<button type="button" class="settings-nav-item" data-settings-category="metadata" data-i18n="settings.metadata_media">Metadata & Media</button>
<button type="button" class="settings-nav-item" data-settings-category="launching" data-i18n="settings.launching">Launching</button>
<button type="button" class="settings-nav-item" data-settings-category="sessions" data-i18n="settings.sessions_saves">Sessions & Saves</button>
<button type="button" class="settings-nav-item" data-settings-category="bigbox" data-i18n="settings.bigbox">Big Box</button>
<button type="button" class="settings-nav-item" data-settings-category="integrations" data-i18n="settings.integrations">Integrations</button>
<button type="button" class="settings-nav-item" data-settings-category="appearance" data-i18n="settings.appearance">Appearance</button>
<button type="button" class="settings-nav-item" data-settings-category="controller" data-i18n="settings.controller">Controller</button>
<button type="button" class="settings-nav-item" data-settings-category="plugins" data-i18n="tools.plugins">Plugins</button>
<button type="button" class="settings-nav-item" data-settings-category="advanced" data-i18n="settings.advanced">Advanced</button>
<button type="button" class="settings-nav-item" data-settings-category="about" data-i18n="settings.about">About</button>
</nav>
<div class="form-grid settings-panels">
<p class="wide settings-category-help" id="settingsCategoryHelp" data-settings-exempt="true"></p>
<div class="wide settings-field settings-panel detail-card" data-settings-panel="about" data-setting="about version platform data folder native window browser webview">
<dl class="about-facts">
<dt data-i18n="settings.about_version">Version</dt><dd id="aboutVersion"></dd>
<dt data-i18n="settings.about_platform">Platform</dt><dd id="aboutPlatform"></dd>
<dt data-i18n="settings.about_data_dir">Data folder</dt><dd id="aboutDataDir"></dd>
<dt data-i18n="settings.about_host">Window</dt><dd id="aboutHost"></dd>
<dt data-i18n="settings.about_state_schema">Library format</dt><dd id="aboutStateSchema"></dd>
<dt data-i18n="settings.about_api_version">API version</dt><dd id="aboutApiVersion"></dd>
<dt data-i18n="settings.about_plugin_api">Plugin API</dt><dd id="aboutPluginApi"></dd>
<dt data-i18n="settings.about_backup_format">Backup format</dt><dd id="aboutBackupFormat"></dd>
</dl>
<div class="extras"><button type="button" class="icon-button" id="compatReportButton" data-i18n="settings.compat_button">Show compatibility report</button></div>
<div id="compatReport" class="description" hidden></div>
<p class="description" data-i18n="settings.about_support">OpenBox is free and open source. If it saves you time, a coffee helps cover hosting and development.</p>
<div class="extras"><button type="button" class="icon-button" id="aboutSupport" data-i18n="settings.about_support_button">Buy me a coffee</button></div>
</div>
<label class="field wide settings-field" data-settings-exempt="search" data-setting="search watched folders cloud screensaver startup shutdown session history backup progress automation image group controller gamepad"><span data-i18n="settings.search_settings">Search settings</span><input id="settingsSearch" class="settings-search" type="search" data-i18n-placeholder="settings.search_placeholder" placeholder="Type to filter settings"><span class="description" id="settingsSearchCount" aria-live="polite"></span></label>
<label class="field wide settings-field settings-panel" data-settings-panel="library imports" data-setting="watched folders import auto"><span data-i18n="settings.watched_folders">Automatically watched game folders, one absolute path per line</span><span class="path-input-row"><textarea id="watchFolders"></textarea><button type="button" class="path-browse" data-browse-for="watchFolders" data-browse-kind="folder">Browse</button></span></label>
<div class="wide settings-field settings-panel detail-card" data-settings-panel="library imports" data-setting="memories screenshots import steam retroarch dolphin folders auto">
<label class="check"><input type="checkbox" id="memoriesImportEnabled"><span data-i18n="settings.memories_import_enabled">Import screenshots from Steam, RetroArch, and Dolphin folders</span></label>
<label class="field wide"><span data-i18n="settings.memories_import_roots">Additional screenshot folders, one absolute path per line</span><textarea id="memoriesImportRoots"></textarea></label>
<div class="extras"><button type="button" class="icon-button" id="memoriesImportNow" data-i18n="settings.memories_import_now">Scan for screenshots now</button><span class="description" id="memoriesImportStatus"></span></div>
</div>
<div class="wide settings-field settings-panel" data-settings-panel="library" data-setting="library cleanup remove steam imports"><button type="button" class="icon-button" id="removeSteamGames" data-i18n="settings.remove_steam">Remove all imported Steam games</button><span class="description" data-i18n="settings.remove_steam_desc">Removes library entries only. Game files and media stay on disk.</span></div>
<div class="wide settings-field settings-panel" data-settings-panel="library" data-setting="library integrity check missing unreadable paths"><strong data-i18n="library_storage.integrity_title">Library integrity</strong> <span class="description" data-i18n="library_storage.integrity_help">Reads the library file and every game path. Nothing is changed.</span><div class="extras"><button type="button" class="icon-button" id="libraryIntegrityCheck" data-i18n="library_storage.integrity_check">Check integrity</button></div><div id="libraryIntegrityResult" class="description" hidden></div></div>
<div class="wide settings-field settings-panel" data-settings-panel="library" data-setting="media manifest checksums integrity verify"><label class="check"><input type="checkbox" id="mediaManifestEnabled" checked><span data-i18n="library_storage.manifest_enabled">Record media checksums</span></label><span class="description" data-i18n="library_storage.manifest_help">Tracks the size, timestamp, and SHA-256 of downloaded and captured media so the integrity check can tell a changed file from an untouched one. Turning this off skips manifest writes and media hashing.</span></div>
<div class="wide settings-field settings-panel" data-settings-panel="library" data-setting="library move folder portable paths relocate"><strong data-i18n="library_storage.move_title">Move library</strong> <span class="description" data-i18n="library_storage.move_help">Preview shows what a move changes. Apply runs exactly the previewed plan and refuses if the library changed since the preview. Games inside the new folder get portable paths.</span><label class="field"><span data-i18n="library_storage.move_folder">New library folder</span><span class="path-input-row"><input id="libraryMoveFolder" autocomplete="off"><button type="button" class="path-browse" id="libraryMoveBrowse" data-i18n="library_storage.move_browse">Browse</button></span></label><div class="extras"><button type="button" class="icon-button" id="libraryMovePreview" data-i18n="library_storage.move_preview">Preview move</button><button type="button" class="icon-button" id="libraryMoveApply" data-i18n="library_storage.move_apply" disabled>Apply move</button></div><div id="libraryMoveResult" class="description" aria-live="polite" hidden></div></div>
<div class="wide settings-field settings-panel" data-settings-panel="advanced" data-setting="diagnostic support troubleshooting logs"><button type="button" class="icon-button" id="copyDiagnosticLog" data-i18n="settings.copy_diagnostic">Copy diagnostic log</button><span class="description" data-i18n="settings.copy_diagnostic_desc">Review it before sharing because it can include game names and local file paths.</span></div>
<label class="field wide settings-field settings-panel" data-settings-panel="integrations" data-setting="cloud sync syncthing dropbox nextcloud"><span data-i18n="settings.cloud_folder">Mounted Nextcloud, Syncthing, Dropbox, or other cloud folder for game-stat syncing</span><span class="path-input-row"><input id="cloudFolder"><button type="button" class="path-browse" data-browse-for="cloudFolder" data-browse-kind="folder">Browse</button></span></label>
<div class="wide settings-field settings-panel" data-settings-panel="integrations" data-setting="cloud sync"><button type="button" class="icon-button" id="syncCloud" data-i18n="settings.sync_now">Sync statistics now</button><span class="description" id="cloudStatus"></span></div>
<div class="wide settings-field settings-panel detail-card" data-settings-panel="integrations" data-setting="library catalog sync causal cloud">
<label class="check"><input type="checkbox" id="librarySyncEnabled"><span data-i18n="settings.library_sync_enabled">Enable opt-in library catalog sync</span></label>
<p class="description" data-i18n="settings.library_sync_description">Safely syncs catalog metadata through the mounted cloud folder. File paths, launch settings, credentials, and play statistics stay local.</p>
<div class="extras">
<button type="button" class="icon-button" id="librarySyncPreview" data-i18n="settings.library_sync_preview">Preview catalog changes</button>
<button type="button" class="icon-button" id="librarySyncApply" data-i18n="settings.library_sync_apply" disabled>Apply reviewed changes</button>
<button type="button" class="icon-button" id="librarySyncPublish" data-i18n="settings.library_sync_publish">Publish local changes</button>
</div>
<p class="description" id="librarySyncStatus" aria-live="polite"></p>
<div id="librarySyncPreviewResults" hidden></div>
<div id="librarySyncConflicts" hidden></div>
</div>
<div class="wide settings-field settings-panel" data-settings-panel="metadata integrations" data-setting="api tokens credentials igdb screenscraper steamgriddb gameyfin retroachievements"><fieldset class="field wide"><legend>Integration tokens</legend><p class="description">Tokens stay local and are never shown after saving. Leave a field blank to keep its current token.</p><div id="integrationTokenRows"></div></fieldset></div>
<div class="wide settings-field settings-panel" data-settings-panel="metadata integrations" data-setting="steam account achievements playtime api key credentials"><fieldset class="field wide"><legend>Steam account</legend><p class="description">Optional. The API key is stored in a private file and never shown again. Steam playtime and achievements stay secondary to local values.</p><label class="field"><span>Steam Web API key</span><input id="steamApiKey" type="password" autocomplete="off" placeholder="Leave blank to keep current"></label><label class="field"><span>Steam ID (64-bit)</span><input id="steamId" inputmode="numeric"></label><div class="extras"><button type="button" class="icon-button" id="saveSteamCredentials">Save Steam account</button><button type="button" class="icon-button" id="testSteamCredentials">Test connection</button><button type="button" class="icon-button" id="refreshSteamStats">Refresh playtime and achievements</button><span class="description" id="steamStatus">Not checked</span></div></fieldset></div>
<div class="wide settings-field settings-panel detail-card" data-settings-panel="metadata integrations" data-setting="steamgriddb artwork grid cover provider api key credentials">
<label class="check"><input type="checkbox" id="steamgridEnabled" checked> <span data-i18n="settings.steamgrid_enabled">Enable SteamGridDB artwork provider</span></label>
<span class="description" data-i18n="settings.steamgrid_credentials">API key lives in ~/.env: STEAMGRIDDB_API_KEY</span>
<div class="extras"><span class="description" id="steamgridStatus" data-i18n="settings.steamgrid_unchecked">Not checked</span><button type="button" class="icon-button" id="testSteamgrid" data-i18n="settings.steamgrid_check">Check SteamGridDB</button></div>
</div>
<label class="field wide settings-field settings-panel" data-settings-panel="library appearance" data-setting="default image group viewing cover background screenshot clear logo fanart banner icon box back box spine 3d box title screen cart front cart back disc ads flyers manuals"><span data-i18n="settings.default_image_group">Default image group</span><select id="defaultImageGroup"><option value="cover">Box fronts</option><option value="background">Backgrounds</option><option value="screenshot">Screenshots</option><option value="clear_logo">Clear logos</option><option value="fanart">Fanart</option><option value="banner">Banners</option><option value="icon">Icons</option><option value="box_back">Box backs</option><option value="box_spine">Box spines</option><option value="box_3d">3D boxes</option><option value="title_screen">Title screens</option><option value="cart_front">Cart fronts</option><option value="cart_back">Cart backs</option><option value="disc">Discs</option><option value="advertisement">Ads / flyers</option><option value="manual">Manuals</option></select></label>
<div class="wide settings-field settings-panel" data-settings-panel="library appearance" data-setting="badges favorite installed missing media saves documents versions storefront achievements high scores progress rating broken portable controller"><span data-i18n="settings.visible_badges">Visible game badges</span><div class="badge-row">
<label class="check"><input type="checkbox" data-badge-setting="favorite"> <span data-i18n="settings.badge_favorite">Favorite</span></label>
<label class="check"><input type="checkbox" data-badge-setting="installed"> <span data-i18n="settings.badge_installed">Installed</span></label>
<label class="check"><input type="checkbox" data-badge-setting="missing_media"> <span data-i18n="settings.badge_missing_media">Missing media</span></label>
<label class="check"><input type="checkbox" data-badge-setting="saves"> <span data-i18n="settings.badge_saves">Saves</span></label>
<label class="check"><input type="checkbox" data-badge-setting="documents"> <span data-i18n="settings.badge_documents">Documents</span></label>
<label class="check"><input type="checkbox" data-badge-setting="versions"> <span data-i18n="settings.badge_versions">Versions</span></label>
<label class="check"><input type="checkbox" data-badge-setting="storefront"> <span data-i18n="settings.badge_storefront">Storefront</span></label>
<label class="check"><input type="checkbox" data-badge-setting="achievements"> <span data-i18n="settings.badge_achievements">Achievements</span></label>
<label class="check"><input type="checkbox" data-badge-setting="highscores"> <span data-i18n="settings.badge_highscores">High scores</span></label>
<label class="check"><input type="checkbox" data-badge-setting="progress"> <span data-i18n="settings.badge_progress">Progress</span></label>
<label class="check"><input type="checkbox" data-badge-setting="rating"> <span data-i18n="settings.badge_rating">Rating</span></label>
<label class="check"><input type="checkbox" data-badge-setting="broken"> <span data-i18n="settings.badge_broken">Broken</span></label>
<label class="check"><input type="checkbox" data-badge-setting="portable"> <span data-i18n="settings.badge_portable">Portable</span></label>
<label class="check"><input type="checkbox" data-badge-setting="controller"> <span data-i18n="settings.badge_controller">Controller</span></label>
</div></div>
<label class="field wide settings-field settings-panel" data-settings-panel="bigbox" data-setting="screensaver big box attract"><span data-i18n="settings.screensaver_delay">Big Box screensaver delay in seconds, 0 disables it</span><input id="screensaverSeconds" type="number" min="0" max="3600"></label>
<label class="field wide settings-field settings-panel" data-settings-panel="advanced" data-setting="startup applications commands"><span data-i18n="settings.startup_commands">Applications to start with OpenBox, one shell-free command per line</span><textarea id="startupCommands"></textarea></label>
<label class="field wide settings-field settings-panel" data-settings-panel="advanced" data-setting="shutdown applications commands exit"><span data-i18n="settings.shutdown_commands">Applications to start when OpenBox exits, one shell-free command per line</span><textarea id="shutdownCommands"></textarea></label>
<div class="wide settings-field settings-panel" data-settings-panel="plugins" data-setting="plugins plugin settings hooks commands permissions"><p class="description">Per-plugin settings from enabled plugins. Plugin permissions and trust stay in the Plugins dialog.</p><div id="settingsPluginForms"></div></div>
<label class="check settings-field settings-panel" data-settings-panel="sessions" data-setting="session history tracking data play time"><input type="checkbox" id="trackSessionHistory" checked> <span data-i18n="settings.track_history">Track play session history</span></label>
<label class="check settings-field settings-panel" data-settings-panel="sessions" data-setting="session recap card summary end"><input type="checkbox" id="sessionRecapEnabled" checked> Show session recap when a session ends</label>
<label class="check settings-field settings-panel" data-settings-panel="sessions" data-setting="quick resume save state suspend sessions saves"><input type="checkbox" id="quickResumeEnabled" checked> <span data-i18n="settings.quick_resume_enabled">Quick Resume — capture a resume state when a session ends</span></label>
<label class="check settings-field settings-panel" data-settings-panel="sessions" data-setting="moments auto capture first boot achievement milestone"><input type="checkbox" id="momentsAutocapture" checked> <span data-i18n="settings.moments_autocapture">Auto-capture moments (first boot, achievements, milestones)</span></label>
<label class="field settings-field settings-panel" data-settings-panel="sessions" data-setting="state retention resume states keep"><span data-i18n="settings.state_retention">Resume states kept per game</span><input id="stateRetention" type="number" min="1" max="20"></label>
<label class="check settings-field settings-panel" data-settings-panel="sessions" data-setting="save management backup restore tracking"><input type="checkbox" id="saveManagementEnabled"> <span>Enable save management and backups</span></label>
<label class="check settings-field settings-panel" data-settings-panel="sessions" data-setting="backup on close saves"><input type="checkbox" id="backupOnClose"> <span data-i18n="settings.backup_on_close">Back up saves when a game session ends</span></label>
<label class="check settings-field settings-panel" data-settings-panel="sessions" data-setting="automatic backup weekly library"><input type="checkbox" id="backupAutoEnabled"> Back up the library automatically each week</label>
<label class="field settings-field settings-panel" data-settings-panel="sessions" data-setting="library health rescan cadence"><span data-i18n="settings.health_rescan">Library health rescan</span><select id="healthRescanCadence"><option value="daily" data-i18n="settings.health_rescan_daily">Daily</option><option value="weekly" data-i18n="settings.health_rescan_weekly" selected>Weekly</option><option value="on_startup" data-i18n="settings.health_rescan_on_startup">On startup</option><option value="off" data-i18n="settings.health_rescan_off">Off</option></select></label>
<label class="field settings-field settings-panel" data-settings-panel="sessions" data-setting="automatic backup retention keep"><span>Automatic backups kept</span><input id="backupAutoKeep" type="number" min="1" max="52"></label>
<p class="wide description settings-field settings-panel" data-settings-panel="sessions" data-setting="automatic backup last" id="lastAutoBackupLine" hidden></p>
<label class="check settings-field settings-panel" data-settings-panel="sessions" data-setting="obs recording attach auto"><input type="checkbox" id="obsAutoAttach" checked> <span data-i18n="settings.obs_auto_attach">Auto-attach latest OBS recording when a session ends</span></label>
<label class="check settings-field settings-panel" data-settings-panel="integrations sessions" data-setting="obs replay buffer clips"><input type="checkbox" id="obsReplayEnabled"> Enable OBS replay-buffer clips</label>
<label class="check settings-field settings-panel" data-settings-panel="integrations" data-setting="retroachievements hardcore achievements"><input type="checkbox" id="raHardcore"> Write RetroAchievements hardcore mode to emulator configs</label>
<label class="field wide settings-field settings-panel" data-settings-panel="integrations" data-setting="obs websocket endpoint"><span>OBS WebSocket endpoint (optional)</span><input id="obsWebsocketUrl" placeholder="ws://127.0.0.1:4455"></label>
<label class="field wide settings-field settings-panel" data-settings-panel="integrations sessions" data-setting="obs websocket password"><span>OBS WebSocket password (optional)</span><input id="obsWebsocketPassword" type="password" autocomplete="off"></label>
<label class="check settings-field settings-panel" data-settings-panel="integrations" data-setting="household family stats sharing local"><input type="checkbox" id="householdStatsSharing"> Share household play statistics with explicitly linked local devices</label>
<label class="check settings-field settings-panel" data-settings-panel="bigbox sessions" data-setting="museum arcade kiosk pin lock"><input type="checkbox" id="museumKioskEnabled"> Require a PIN before entering Kiosk mode (convenience boundary)</label>
<label class="field settings-field settings-panel" data-settings-panel="bigbox sessions" data-setting="museum arcade kiosk pin"><span>Kiosk PIN, 4–12 digits</span><span class="path-input-row"><input id="museumKioskPin" type="password" inputmode="numeric" autocomplete="new-password" placeholder="Leave blank to keep the current PIN"><button type="button" class="path-browse" id="clearMuseumKioskPin">Clear PIN</button></span></label>
<label class="field wide settings-field settings-panel" data-settings-panel="sessions bigbox" data-setting="obs recording folder path"><span>OBS recording folder, optional override</span><span class="path-input-row"><input id="obsRecordingPath" placeholder="~/Videos"><button type="button" class="path-browse" data-browse-for="obsRecordingPath" data-browse-kind="folder">Browse</button></span></label>
<label class="field settings-field settings-panel" data-settings-panel="sessions" data-setting="save backup limit retention"><span data-i18n="settings.save_backup_limit">Save backup retention limit, 0 keeps all</span><input id="saveBackupLimit" type="number" min="0" max="500"></label>
<label class="field settings-field settings-panel" data-settings-panel="metadata" data-setting="media download limit queue welcome wizard"><span data-i18n="settings.media_download_limit">Media download limit during imports, 0 unlimited</span><input id="mediaDownloadLimit" type="number" min="0" max="10000"></label>
<label class="field settings-field settings-panel" data-settings-panel="metadata" data-setting="media download limit per platform kind queue"><span>Per platform and media kind limit, 0 unlimited</span><input id="mediaDownloadLimitPerGroup" type="number" min="0" max="100"></label>
<label class="field settings-field settings-panel" data-settings-panel="metadata" data-setting="metadata provider priority launchbox screenscraper igdb steamgriddb plugin"><span>Metadata provider priority, one per line</span><textarea id="metadataProviderPriority" placeholder="launchbox, screenscraper, igdb, steamgriddb"></textarea></label>
<label class="check settings-field settings-panel" data-settings-panel="metadata" data-setting="plugin metadata priority provider"><input type="checkbox" id="pluginMetadataPriority"> Prefer plugin metadata providers in bulk downloads</label>
<label class="field wide settings-field settings-panel" data-settings-panel="metadata" data-setting="auto import media types cover background screenshots poster square video video snap theme trailer music box back spine 3d clear logo fanart banner icon title screen cart front cart back disc ads flyers manuals"><span data-i18n="settings.auto_import_media">Auto-import media types, comma separated</span><input id="autoImportMediaTypes" placeholder="cover, background, screenshots, video_snap, music"></label>
<label class="field wide settings-field settings-panel" data-settings-panel="metadata" data-setting="region priority metadata images"><span data-i18n="settings.region_priority">Region priority, comma separated</span><input id="regionPriority"></label>
<label class="field wide settings-field settings-panel" data-settings-panel="appearance bigbox" data-setting="library music background big box"><span>Library background music path</span><span class="path-input-row"><input id="libraryMusic"><button type="button" class="path-browse" data-browse-for="libraryMusic" data-browse-kind="file">Browse</button></span></label>
<label class="check settings-field settings-panel" data-settings-panel="appearance" data-setting="video bgm mix background music"><input type="checkbox" id="videoBgmMix"> <span data-i18n="settings.video_bgm_mix">Mix video audio with background music</span></label>
<label class="field settings-field settings-panel" data-settings-panel="bigbox" data-setting="big box mode hybrid coverflow stage"><span data-i18n="settings.bigbox_layout">Big Box layout</span><select id="bigBoxMode"><option value="stage">Stage</option><option value="hybrid">Hybrid</option><option value="coverflow">CoverFlow</option></select></label>
<label class="check settings-field settings-panel" data-settings-panel="bigbox" data-setting="show playlist actions big box menu"><input type="checkbox" id="showPlaylistActions" checked> <span data-i18n="settings.show_playlist_actions">Show playlist actions in Big Box</span></label>
<label class="check settings-field settings-panel" data-settings-panel="bigbox" data-setting="big box start launch boot startup"><input type="checkbox" id="bigBoxStartAtLaunch"> <span data-i18n="settings.bigbox_start_at_launch">Start in Big Box mode</span></label>
<label class="check settings-field settings-panel" data-settings-panel="bigbox" data-setting="dynamic play button launch"><input type="checkbox" id="dynamicPlayButton" checked> <span data-i18n="settings.dynamic_play_button">Use dynamic Play button labels</span></label>
<label class="check settings-field settings-panel" data-settings-panel="appearance library" data-setting="insights play dashboard heatmap show"><input type="checkbox" id="showInsights" checked> Show Play Insights in the library</label>
<label class="check settings-field settings-panel" data-settings-panel="appearance library" data-setting="launch readiness badges won't launch needs attention grid"><input type="checkbox" id="showLaunchBadges" checked> <span data-i18n="settings.show_launch_badges">Show launch readiness badges on the grid</span></label>
<label class="check settings-field settings-panel" data-settings-panel="appearance" data-setting="mood match cover adaptive theming color"><input type="checkbox" id="moodMatchEnabled"> <span data-i18n="settings.mood_match">Adaptive cover theming</span></label>
<label class="check settings-field settings-panel" data-settings-panel="appearance bigbox" data-setting="mood match big box adaptive theming color"><input type="checkbox" id="moodMatchBigbox"> <span data-i18n="settings.mood_match_bigbox">Adaptive theming in Big Box</span></label>
<fieldset class="field wide settings-field settings-panel" data-settings-panel="library" data-setting="hidden sidebar sections filters platforms playlists"><legend data-i18n="settings.hidden_sidebar">Hidden sidebar sections</legend>
<label class="check"><input type="checkbox" data-hide-section="search"> <span data-i18n="sidebar.search">Search</span></label>
<label class="check"><input type="checkbox" data-hide-section="view"> <span data-i18n="sidebar.view">View</span></label>
<label class="check"><input type="checkbox" data-hide-section="filters"> <span data-i18n="sidebar.filters">Filters</span></label>
<label class="check"><input type="checkbox" data-hide-section="platforms"> <span data-i18n="sidebar.platforms">Platforms</span></label>
<label class="check"><input type="checkbox" data-hide-section="playlists"> <span data-i18n="sidebar.playlists">Playlists</span></label>
<label class="check"><input type="checkbox" data-hide-section="explorer"> <span data-i18n="sidebar.explorer">Explorer</span></label>
</fieldset>
<fieldset class="field wide settings-field settings-panel" data-settings-panel="library" data-setting="sidebar order sections filters platforms playlists explorer"><legend>Sidebar section order</legend><div id="sidebarOrderList" class="extras"></div></fieldset>
<label class="field wide settings-field settings-panel" data-settings-panel="metadata integrations" data-setting="emumovies credentials media"><span data-i18n="settings.emumovies_user">EmuMovies username</span><input id="emumoviesUsername"></label>
<label class="field settings-field settings-panel" data-settings-panel="metadata integrations" data-setting="emumovies credentials media"><span data-i18n="settings.emumovies_pass">EmuMovies password</span><input id="emumoviesPassword" type="password" autocomplete="off"></label>
<label class="check settings-field settings-panel" data-settings-panel="sessions" data-setting="progress automation playing paused idle days minutes"><input type="checkbox" id="progressAutomationEnabled"> <span data-i18n="settings.progress_automation">Enable game progress automation</span></label>
<label class="field settings-field settings-panel" data-settings-panel="sessions" data-setting="progress automation playing minutes"><span data-i18n="settings.progress_playing_minutes">Mark as Playing after minutes played</span><input id="progressAutomationMinutes" type="number" min="0" max="100000"></label>
<label class="field settings-field settings-panel" data-settings-panel="sessions" data-setting="progress automation paused idle days"><span data-i18n="settings.progress_paused_days">Mark as Paused after days without play</span><input id="progressAutomationIdleDays" type="number" min="0" max="3650"></label>
<label class="field wide settings-field settings-panel" data-settings-panel="sessions" data-setting="progress automation allowed values whitelist"><span>Progress values allowed by automation and the game editor, comma separated</span><input id="progressValues" placeholder="Unplayed, Playing, Paused, Beaten, Completed, Mastered, Abandoned"></label>
<label class="field settings-field settings-panel" data-settings-panel="sessions" data-setting="progress first play completion status"><span data-i18n="settings.progress_first_play">Progress status on first play</span><select id="progressOnFirstPlay"><option value="">None</option><option value="Playing">Playing</option><option value="Paused">Paused</option><option value="Beaten">Beaten</option><option value="Completed">Completed</option><option value="Mastered">Mastered</option></select></label>
<label class="check settings-field settings-panel" data-settings-panel="sessions" data-setting="progress suggest backlog playing"><input type="checkbox" id="backlogProgressSuggest"> <span data-i18n="settings.backlog_progress_suggest">Suggest marking games as Playing on first play</span></label>
<label class="field settings-field settings-panel" data-settings-panel="launching" data-setting="tracking mode process folder wine proton"><span data-i18n="settings.tracking_mode">Default session tracking mode</span><select id="trackingMode"><option value="default">Default</option><option value="process">Process</option><option value="original_process">Original process</option><option value="folder">Install folder</option><option value="process_name">Process name</option></select></label>
<label class="field settings-field settings-panel" data-settings-panel="launching" data-setting="handheld performance tdp ryzenadj apply limits" data-feature="handheld_perf"><span data-i18n="settings.apply_perf">Apply handheld performance limits</span><select id="applyPerf"><option value="auto">Auto (handheld only)</option><option value="always">Always</option><option value="off">Off</option></select></label>
<label class="field settings-field settings-panel" data-settings-panel="launching" data-setting="tracking delay seconds launch"><span data-i18n="settings.tracking_delay">Tracking start delay in seconds</span><input id="trackingDelay" type="number" min="0" max="600"></label>
<label class="field settings-field settings-panel" data-settings-panel="launching" data-setting="tracking frequency poll seconds"><span data-i18n="settings.tracking_frequency">Tracking poll frequency in seconds</span><input id="trackingFrequency" type="number" min="0.5" max="60" step="0.5"></label>
<label class="check settings-field settings-panel" data-settings-panel="launching" data-setting="auto close steam heroic lutris storefront"><input type="checkbox" id="autoCloseStoreClients"> <span data-i18n="settings.auto_close_clients">Close storefront clients after a session ends</span></label>
<label class="field wide settings-field settings-panel" data-settings-panel="imports launching" data-setting="emulator scan folder rom wizard"><span>ROM scan folder for emulator definitions</span><span class="path-input-row"><input id="emulatorScanFolder" placeholder="/path/to/roms"><button type="button" class="path-browse" data-browse-for="emulatorScanFolder" data-browse-kind="folder">Browse</button></span></label>
<div class="wide settings-field settings-panel" data-settings-panel="imports launching" data-setting="emulator scan folder rom wizard"><button type="button" class="icon-button" id="scanEmulatorFolder" data-i18n="settings.scan_rom_folder">Scan ROM folder</button></div>
<label class="field settings-field settings-panel" data-settings-panel="appearance" data-setting="font family typography serif mono humanist"><span>Font family</span><select id="fontFamilySetting"><option value="system">System sans</option><option value="serif">Serif</option><option value="mono">Monospace</option><option value="humanist">Humanist sans</option></select></label>
<label class="field settings-field settings-panel" data-settings-panel="appearance" data-setting="localization"><span data-i18n="settings.interface_language">Interface language</span><select id="localeSetting"><option value="en">English</option></select></label>
<label class="field settings-field settings-panel" data-settings-panel="library" data-setting="library view list grid columns"><span data-i18n="settings.default_library_view">Default library view</span><select id="libraryViewSetting"><option value="grid" data-i18n="settings.view_grid">Grid</option><option value="list" data-i18n="settings.view_list">List</option></select></label>
<label class="field settings-field settings-panel" data-settings-panel="library" data-setting="currency price money"><span data-i18n="settings.currency">Currency</span><input id="currencySetting" maxlength="3" placeholder="USD"></label>
<label class="field settings-field settings-panel" data-settings-panel="library" data-setting="library view grid grouping cover aspect ratio shape none"><span data-i18n="settings.group_covers_shape">Group covers by shape</span><select id="groupingSetting"><option value="shape" data-i18n="settings.group_by_shape">Group by cover shape</option><option value="none">No grouping</option></select></label>
<label class="field wide settings-field settings-panel" data-settings-panel="metadata" data-setting="custom fields metadata premium"><span data-i18n="settings.custom_fields">Custom fields, one per line: Name|Option1,Option2</span><textarea id="customFieldDefs" placeholder="Cabinet|Upright,Cocktail"></textarea></label>
<label class="field settings-field settings-panel" data-settings-panel="appearance library" data-setting="reader theme light dark"><span>Document reader theme</span><select id="readerTheme"><option value="light">Light</option><option value="dark">Dark</option></select></label>
<label class="field settings-field settings-panel" data-settings-panel="appearance library" data-setting="reader spread single two page"><span>Document reader layout</span><select id="readerSpread"><option value="single">Single page</option><option value="spread">Two-page spread</option></select></label>
<label class="field settings-field settings-panel" data-settings-panel="appearance library" data-setting="cover model box jewel cassette 3d"><span>Cover model</span><select id="coverModelSetting"><option value="box">Box</option><option value="jewel">Jewel case</option><option value="long_jewel">Long jewel case</option><option value="double_jewel">Double jewel case</option><option value="cassette">Cassette</option><option value="none">Flat cover</option></select></label>
<label class="field settings-field settings-panel" data-settings-panel="appearance library" data-setting="cover model rotation lock free horizontal vertical"><span>3D rotation lock</span><select id="modelRotationLock"><option value="free">Free rotation</option><option value="horizontal">Lock horizontal</option><option value="vertical">Lock vertical</option></select></label>
<label class="check settings-field settings-panel" data-settings-panel="bigbox" data-setting="video controls big box playback"><input type="checkbox" id="bigboxVideoControls" checked> Show video controls in Big Box</label>
<label class="field settings-field settings-panel" data-settings-panel="bigbox" data-setting="video volume big box audio"><span>Big Box video volume, 0–1</span><input id="bigboxVideoVolume" type="number" min="0" max="1" step="0.05"></label>
<label class="check settings-field settings-panel" data-settings-panel="bigbox appearance" data-setting="video backdrop blur big box"><input type="checkbox" id="bigboxVideoBackdrop"> Use a blurred video backdrop in Big Box</label>
<label class="check settings-field settings-panel" data-settings-panel="bigbox" data-setting="startup video loop repeat"><input type="checkbox" id="bigboxStartupVideoLoop"> Loop the Big Box startup video</label>
<label class="check settings-field settings-panel" data-settings-panel="bigbox appearance" data-setting="theme sounds music sound effects"><input type="checkbox" id="bigboxSoundsEnabled" checked> Play theme music and navigation sounds in Big Box</label>
<label class="field wide settings-field settings-panel" data-settings-panel="bigbox appearance" data-setting="big box startup video attract"><span>Big Box startup video path</span><span class="path-input-row"><input id="bigboxStartupVideo"><button type="button" class="path-browse" data-browse-for="bigboxStartupVideo" data-browse-kind="file">Browse</button></span></label>
<label class="field wide settings-field settings-panel" data-settings-panel="bigbox" data-setting="big box shutdown applications exit leave"><span data-i18n="settings.bigbox_shutdown_apps">Applications to run when leaving Big Box, one command per line</span><textarea id="bigboxShutdownCommands"></textarea></label>
<label class="field settings-field settings-panel" data-settings-panel="bigbox" data-setting="attract mode screensaver big box"><span data-i18n="settings.attract_delay">Demo mode delay in seconds</span><input id="attractModeSeconds" type="number" min="0" max="3600"></label>
<label class="check settings-field settings-panel" data-settings-panel="advanced" data-setting="system tray minimize close"><input type="checkbox" id="trayEnabled"> <span data-i18n="settings.tray_enabled">Enable desktop tray integration</span></label>
<label class="check settings-field settings-panel" data-settings-panel="advanced" data-setting="system tray minimize close"><input type="checkbox" id="minimizeToTray"> <span data-i18n="settings.minimize_to_tray">Minimize to tray when window closes</span></label>
<label class="field wide settings-field settings-panel" data-settings-panel="sessions advanced" data-setting="ludusavi hoard saves backup"><span>Ludusavi backup path, optional</span><span class="path-input-row"><input id="ludusaviBackupPath" placeholder="Leave blank for Ludusavi default"><button type="button" class="path-browse" data-browse-for="ludusaviBackupPath" data-browse-kind="folder">Browse</button></span></label>
<div class="wide settings-field settings-panel" data-settings-panel="appearance" data-setting="media packs themes badges controller"><button type="button" class="icon-button" id="applyMediaPack" data-i18n="settings.apply_media_pack">Apply bundled media pack</button><span class="description" id="mediaPackStatus"></span></div>
<div class="wide section-title settings-field settings-panel" data-settings-panel="controller" data-setting="controller gamepad mapping" data-i18n="settings.controller_mapping">Standard Gamepad Button Mapping</div>
<label class="field settings-field settings-panel" data-settings-panel="controller" data-setting="controller gamepad play"><span data-i18n="settings.controller_play">Play</span><input data-controller="play" data-setting="controller gamepad play" type="number" min="0" max="31"></label>
<label class="field settings-field settings-panel" data-settings-panel="controller" data-setting="controller gamepad back"><span data-i18n="settings.controller_back">Back</span><input data-controller="back" data-setting="controller gamepad back" type="number" min="0" max="31"></label>
<label class="field settings-field settings-panel" data-settings-panel="controller" data-setting="controller gamepad favorite"><span data-i18n="settings.controller_favorite">Favorite</span><input data-controller="favorite" data-setting="controller gamepad favorite" type="number" min="0" max="31"></label>
<label class="field settings-field settings-panel" data-settings-panel="controller" data-setting="controller gamepad random"><span data-i18n="settings.controller_random">Random game</span><input data-controller="random" data-setting="controller gamepad random" type="number" min="0" max="31"></label>
<label class="field settings-field settings-panel" data-settings-panel="controller" data-setting="controller gamepad page"><span data-i18n="settings.controller_prev_page">Previous page</span><input data-controller="page_left" data-setting="controller gamepad page" type="number" min="0" max="31"></label>
<label class="field settings-field settings-panel" data-settings-panel="controller" data-setting="controller gamepad page"><span data-i18n="settings.controller_next_page">Next page</span><input data-controller="page_right" data-setting="controller gamepad page" type="number" min="0" max="31"></label>
<label class="field settings-field settings-panel" data-settings-panel="controller" data-setting="controller gamepad pause"><span data-i18n="settings.controller_pause">Running-game menu</span><input data-controller="pause" data-setting="controller gamepad pause" type="number" min="0" max="31"></label>
<label class="field settings-field settings-panel" data-settings-panel="controller" data-setting="controller gamepad menu filter sort"><span data-i18n="settings.controller_menu">Filter and sort menu</span><input data-controller="menu" data-setting="controller gamepad menu filter sort" type="number" min="0" max="31"></label>
<p class="wide description settings-field settings-panel" data-settings-panel="controller" data-setting="controller gamepad conflict" id="controllerMapError" role="alert" hidden></p>
<label class="field settings-field settings-panel" data-settings-panel="controller" data-setting="pointer navigation wheel trackball spinner"><span>Pointer and wheel navigation</span><select id="pointerNavEnabled"><option value="on">On</option><option value="off">Off</option></select></label>
<label class="field settings-field settings-panel" data-settings-panel="controller" data-setting="mouse wheel navigation"><span>Mouse wheel navigation</span><select id="mouseWheelNav"><option value="on">On</option><option value="off">Off</option></select></label>
<label class="field settings-field settings-panel" data-settings-panel="controller" data-setting="spinner sensitivity trackball wheel"><span>Spinner sensitivity, 1–20</span><input id="spinnerSensitivity" type="number" min="1" max="20"></label>
<label class="field settings-field settings-panel" data-settings-panel="controller bigbox" data-setting="big box wheel speed"><span>Big Box wheel speed, 0.25–3.0</span><input id="bigBoxWheelSpeed" type="number" min="0.25" max="3" step="0.05"></label>
<label class="field settings-field settings-panel" data-settings-panel="controller bigbox" data-setting="big box back hold menu"><span>Hold Back to open the Big Box menu, seconds (0 disables)</span><input id="bigBoxBackHold" type="number" min="0" max="2" step="0.1"></label>
<label class="check settings-field settings-panel" data-settings-panel="controller bigbox" data-setting="battery indicator"><input type="checkbox" id="batteryIndicator" checked> Show the battery indicator in Big Box</label>
<label class="field wide settings-field settings-panel" data-settings-panel="controller" data-setting="controller types gamepad arcade stick racing wheel light gun"><span>Controller types, one per line: id|name|kind</span><textarea id="controllerTypesSetting" placeholder="gamepad|Gamepad|gamepad"></textarea></label>
<fieldset class="field wide settings-field settings-panel" data-settings-panel="controller" data-setting="keyboard mapping shortcuts"><legend>Keyboard shortcuts</legend><div id="keyboardMapInputs" class="extras"></div><p class="description" id="keyboardMapError" role="alert" hidden></p></fieldset>
<label class="field wide settings-field settings-panel" data-settings-panel="bigbox" data-setting="hide platforms categories playlists big box"><span>Hide from Big Box: platforms, categories, playlists (comma separated)</span><input id="bigBoxHiddenPlatforms" placeholder="Platforms"><input id="bigBoxHiddenCategories" placeholder="Categories"><input id="bigBoxHiddenPlaylists" placeholder="Playlists"></label>
<div class="wide section-title settings-panel" data-feature="gamescope" data-settings-panel="controller" data-setting="gamescope preset steam deck">Gamescope Presets</div>
<label class="field wide settings-field settings-panel" data-feature="gamescope" data-settings-panel="controller" data-setting="gamescope preset steam deck"><span>Gamescope preset</span><select id="gamescopePreset"><option value="">None</option></select></label>
<div class="wide settings-field settings-panel" data-feature="gamescope" data-settings-panel="controller" data-setting="gamescope custom presets editor">
<span>Custom gamescope presets</span>
<div id="gamescopeCustomPresets" class="gamescope-preset-list"></div>
<button type="button" class="icon-button" id="addGamescopePreset">Add custom preset</button>
</div>
<label class="check settings-field settings-panel" data-settings-panel="controller" data-setting="mangohud overlay performance fps" data-feature="mangohud"><input type="checkbox" id="mangohudEnabled"> Enable MangoHud performance overlay</label>
<div class="wide settings-field settings-panel" data-settings-panel="controller" data-setting="controller gamepad test"><div class="controller-bench" id="controllerBench"><svg class="gamepad-svg" viewBox="0 0 200 120" aria-label="Gamepad test"><rect x="10" y="30" width="180" height="60" rx="30" class="gamepad-body"/><circle cx="50" cy="60" r="12" class="gamepad-stick"/><circle cx="150" cy="60" r="12" class="gamepad-stick"/><circle cx="80" cy="50" r="5" class="gamepad-btn"/><circle cx="120" cy="50" r="5" class="gamepad-btn"/><circle cx="100" cy="65" r="5" class="gamepad-btn"/><circle cx="100" cy="40" r="5" class="gamepad-btn"/></svg><p class="description" id="controllerBenchStatus">Connect a controller to test inputs.</p></div></div>
<button type="button" class="icon-button settings-field settings-panel" data-settings-panel="imports" data-setting="watched folders import scan" id="scanWatched" data-i18n="settings.scan_watched">Scan watched folders now</button>
<button type="button" class="icon-button settings-field settings-panel" data-settings-panel="advanced" data-setting="welcome wizard setup" id="reopenWelcome" data-i18n="settings.reopen_setup">Reopen setup</button>
<div class="wide detail-card settings-field settings-panel" data-settings-panel="advanced" data-setting="application updates desktop shortcut"><h3 data-i18n="settings.application">Application</h3><p class="description" id="updateStatus"></p><div class="extras"><button type="button" class="icon-button" id="checkUpdate">Check for updates</button><button type="button" class="primary" id="installUpdate" hidden>Install verified update</button><button type="button" class="icon-button" id="installDesktop" data-feature="desktop_entry">Install desktop shortcut</button></div></div>
<div class="wide detail-card settings-field settings-panel" data-settings-panel="advanced" data-setting="export library json csv games"><h3>Export library</h3><p class="description">Export game rows as JSON or CSV. Exports contain game data only — never settings or credentials.</p><div class="extras"><select id="exportFormat" aria-label="Export format"><option value="json">JSON</option><option value="csv">CSV</option></select><select id="exportScope" aria-label="Export scope"><option value="all">Whole library</option><option value="platform">One platform</option><option value="playlist">One playlist</option></select><input id="exportScopeName" placeholder="Scope name" hidden><label class="check"><input type="checkbox" id="exportMediaPaths"> Include media paths</label><button type="button" class="primary" id="exportLibrary">Export…</button></div><p class="description" id="exportStatus"></p></div>
</div>
</div>
<div class="dialog-actions"><button type="button" class="icon-button" id="cancelSettings">Cancel</button><button class="primary">Save</button></div>
</form>
</dialog>
<dialog id="discoveryDialog" aria-modal="true" aria-labelledby="discoveryDialogTitle">
<div class="dialog-head"><h2 id="discoveryDialogTitle">Game Discovery Center</h2><button type="button" id="closeDiscovery" aria-label="Close Game Discovery Center dialog">×</button></div>
<div class="form-grid"><div class="wide discovery-grid" id="discoveryContent"></div></div>
<div class="dialog-actions"><button type="button" class="primary" id="doneDiscovery">Done</button></div>
</dialog>
<dialog id="storefrontDialog" aria-modal="true" aria-labelledby="storefrontDialogTitle">
<div class="dialog-head"><h2 id="storefrontDialogTitle">Storefront Manager</h2><button type="button" id="closeStorefront" aria-label="Close Storefront Manager dialog">×</button></div>
<div class="form-grid">
<p class="wide description">Import owned and installed games from Steam, Heroic, Epic, Lutris, Gameyfin, GOG, EA app, and Ubisoft Connect. Install or uninstall Gameyfin titles on demand from the library or Big Box. Epic, GOG, EA app, and Ubisoft Connect read the launchers installed on Windows.</p>
<div class="wide extras"><button type="button" class="primary" id="importSteamStore">Import Steam</button><button type="button" class="icon-button" id="importHeroicStore" data-feature="heroic">Import Heroic</button><button type="button" class="icon-button" id="importEpicStore" data-feature="epic" data-i18n="storefront.import_epic">Import Epic</button><button type="button" class="icon-button" id="importLutrisStore" data-feature="lutris">Import Lutris</button><button type="button" class="icon-button" id="importGameyfinStore">Import Gameyfin</button><button type="button" class="icon-button" id="importGogStore" data-feature="native_storefronts" hidden data-i18n="storefront.import_gog">Import GOG</button><button type="button" class="icon-button" id="importEaStore" data-feature="native_storefronts" hidden data-i18n="storefront.import_ea">Import EA app</button><button type="button" class="icon-button" id="importUbisoftStore" data-feature="native_storefronts" hidden data-i18n="storefront.import_ubisoft">Import Ubisoft Connect</button><button type="button" class="icon-button" id="importScummvmStore">Import ScummVM</button><button type="button" class="icon-button" id="importRpcs3Store">Import RPCS3</button><button type="button" class="icon-button" id="importVita3kStore">Import Vita3K</button></div>
<label class="check"><input type="checkbox" id="storefrontAutoImportSteam"> Auto-import Steam on startup</label>
<label class="field"><span>Steam platform</span><input id="storefrontSteamPlatform" placeholder="PC"></label>
<label class="check"><input type="checkbox" id="storefrontSteamUninstalled"> Include owned but uninstalled Steam games</label>
<label class="check" data-feature="heroic"><input type="checkbox" id="storefrontAutoImportHeroic"> Auto-import Heroic on startup</label>
<label class="field" data-feature="heroic"><span>Heroic platform</span><input id="storefrontHeroicPlatform" placeholder="PC"></label>
<label class="check" data-feature="heroic"><input type="checkbox" id="storefrontHeroicUninstalled"> Include owned but uninstalled Heroic games</label>
<label class="check" data-feature="native_storefronts" hidden><input type="checkbox" id="storefrontAutoImportGog"> Auto-import GOG on startup</label>
<label class="check" data-feature="native_storefronts" hidden><input type="checkbox" id="storefrontAutoImportEa"> Auto-import EA app on startup</label>
<label class="check" data-feature="native_storefronts" hidden><input type="checkbox" id="storefrontAutoImportUbisoft"> Auto-import Ubisoft Connect on startup</label>
<label class="check" data-feature="epic"><input type="checkbox" id="storefrontAutoImportEpic" data-i18n="storefront.auto_epic"> Auto-import Epic on startup</label>
<label class="check" data-feature="lutris"><input type="checkbox" id="storefrontAutoImportLutris"> Auto-import Lutris on startup</label>
<label class="field" data-feature="lutris"><span>Lutris platform</span><input id="storefrontLutrisPlatform" placeholder="PC"></label>
<label class="check" data-feature="lutris"><input type="checkbox" id="storefrontLutrisUninstalled"> Include owned but uninstalled Lutris games</label>
<label class="check"><input type="checkbox" id="storefrontAutoImportGameyfin"> Auto-import Gameyfin on startup</label>
<label class="field"><span>Gameyfin platform</span><input id="storefrontGameyfinPlatform" placeholder="PC"></label>
<label class="check"><input type="checkbox" id="storefrontGameyfinUninstalled"> Include owned but uninstalled Gameyfin games</label>
<label class="field wide"><span>Platforms excluded from automatic imports, comma-separated</span><input id="autoImportExcludedPlatforms" placeholder="Windows, Arcade"></label>
<label class="check"><input type="checkbox" id="storefrontOnlyNew"> Import only games not already in the library</label>
<div class="wide extras"><button type="button" class="icon-button" id="scanStorefronts">Refresh storefront status</button><span class="description" id="storefrontScanStatus"></span></div>
<div class="wide storefront-status" id="storefrontStatusList"></div>
<div class="wide section-title">Gameyfin server</div>
<label class="field wide"><span>Gameyfin URL</span><input id="storefrontGameyfinUrl" placeholder="http://192.168.1.10:8080"></label>
<label class="field"><span>Username</span><input id="storefrontGameyfinUsername" autocomplete="username"></label>
<label class="field"><span>Password</span><input id="storefrontGameyfinPassword" type="password" autocomplete="current-password" placeholder="Leave blank to keep current"></label>
<label class="field wide"><span>Local install folder</span><input id="storefrontGameyfinInstallDir" placeholder="~/Games/Gameyfin"></label>
<div class="wide extras"><button type="button" class="icon-button" id="testGameyfin">Test Gameyfin connection</button><span class="description" id="storefrontGameyfinStatus"></span></div>
<div class="wide section-title">Plugin storefronts</div>
<div class="wide storefront-status" id="storefrontPlugins"></div>
<div class="wide section-title">Browse storefront catalogs</div>
<label class="field"><span>Source</span><select id="storefrontSource"><option value="steam">Steam</option><option value="heroic" data-feature="heroic">Heroic</option><option value="lutris" data-feature="lutris">Lutris</option><option value="gameyfin">Gameyfin</option></select></label>
<div class="wide extras"><button type="button" class="icon-button" id="loadStorefrontCatalog">Load catalog</button><button type="button" class="icon-button" id="importStorefrontInstalled">Import installed</button><button type="button" class="primary" id="importStorefrontUninstalled">Import owned / uninstalled</button></div>
<div class="wide storefront-catalog" id="storefrontCatalog"></div>
</div>
<div class="dialog-actions"><button type="button" class="primary" id="saveStorefront">Save storefront settings</button></div>
</dialog>
<dialog class="media-dialog" id="mediaDialog" aria-label="Media viewer"><span class="media-counter" id="mediaCounter" aria-live="polite"></span><span class="media-meta" id="mediaDialogMeta"></span><button type="button" class="media-nav" id="mediaPrev" aria-label="Previous screenshot">‹</button><button type="button" class="media-nav" id="mediaNext" aria-label="Next screenshot">›</button><div class="media-stage"></div><div class="media-tools"><button type="button" id="mediaIntegerScale" aria-pressed="false" data-i18n="media.integer_scale">Integer scale</button><button type="button" id="mediaFullscreen" aria-pressed="false" data-i18n="media.fullscreen">Fullscreen</button></div><button type="button" id="closeMedia" aria-label="Close screenshot">×</button></dialog>
<dialog class="reader-dialog" id="readerDialog" aria-labelledby="readerTitle">
<div class="dialog-head"><h2 id="readerTitle">Document</h2><button type="button" id="closeReader" aria-label="Close Document reader">×</button></div>
<div class="reader-toolbar"><button type="button" class="icon-button" id="readerPrev">Previous page</button><button type="button" class="icon-button" id="readerNext">Next page</button><span class="description" id="readerPageLabel">Page 1</span><button type="button" class="icon-button" data-reader-layout="single" aria-pressed="true">Single page</button><button type="button" class="icon-button" data-reader-layout="spread" aria-pressed="false">Two-page spread</button><button type="button" class="icon-button" data-reader-theme="light" aria-pressed="true">Light</button><button type="button" class="icon-button" data-reader-theme="dark" aria-pressed="false">Dark</button><button type="button" class="icon-button" id="readerOpenExternal" hidden>Open in system viewer</button></div>
<div class="reader-viewport" id="readerViewport"><iframe id="readerFrame" title="Document reader"></iframe></div>
</dialog>
<div class="toasts" id="toasts" popover="manual"></div>
<div class="visually-hidden" id="toastLive" role="status" aria-live="polite" aria-atomic="true"></div>
<div class="gamepad-hint" id="gamepadHint" role="status" hidden></div>
<div class="error-banner" id="errorBanner" role="alert" hidden>
<span id="errorBannerText"></span>
<button type="button" class="icon-button" id="errorBannerCopy">Copy details</button>
<button type="button" class="icon-button" id="errorBannerDismiss" aria-label="Dismiss error">×</button>
</div>
<div class="context-menu" id="contextMenu" role="menu" hidden>
<button type="button" class="icon-button" id="contextPlay" role="menuitem">Play</button>
<button type="button" class="icon-button" id="contextFavorite" role="menuitem">Toggle favorite</button>
<button type="button" class="icon-button" id="contextEdit" role="menuitem">Edit metadata</button>
<button type="button" class="icon-button" id="contextProgress" role="menuitem">Mark progress</button>
<select id="contextPlaylist" role="menuitem" aria-label="Playlist"><option value="">Add to playlist...</option></select>
<button type="button" class="icon-button" id="contextAddPlaylist" role="menuitem">Add selected game</button>
<button type="button" class="icon-button" id="contextNewPlaylist" role="menuitem">New playlist from game</button>
<button type="button" class="icon-button" id="contextDna" role="menuitem" data-i18n="dna.more_like_this">More like this</button>
<button type="button" class="icon-button" id="contextResetStats" role="menuitem">Reset play statistics</button>
<button type="button" class="icon-button" id="contextRemove" role="menuitem">Remove from library</button>
</div>
<section class="lifecycle" id="lifecycle" role="status" aria-live="polite" hidden><div><small id="lifecycleKind"></small><h2 id="lifecycleGame"></h2><p id="lifecycleMessage"></p></div></section>
<section class="bigbox" id="bigBox" role="dialog" aria-modal="true" aria-label="Big Box" hidden tabindex="0">
<video class="bigbox-startup-video" id="bigBoxStartupVideo" muted playsinline hidden></video>
<video class="bigbox-video-backdrop" id="bigBoxBackdrop" muted loop playsinline aria-hidden="true" hidden></video>
<div class="bigbox-head"><strong>OpenBox</strong><input class="hybrid-search" id="bigBoxHybridSearch" type="search" placeholder="Search this platform" hidden><button type="button" class="dna-mode single" id="bigBoxDnaToggle" data-dna-mode="title" title="Smart search is 100% local" hidden>Title</button><span class="bigbox-status" id="bigBoxStatus"></span><span class="bigbox-battery" id="bigBoxBattery" hidden></span><span id="bigBoxCounter"></span></div>
<div class="bigbox-stage" id="bigBoxStage"></div>
<div class="bigbox-foot"><span>← → Browse</span><span>Enter / A Play</span><span>P Pause</span><span>M Filters</span><span>F / X Favorite</span><span>Esc / B Back</span></div>
<div class="bigbox-menu" id="bigBoxMenu" role="dialog" aria-modal="true" aria-label="Big Box menu" hidden>
<div class="bigbox-menu-panel">
<h2>Filter and Sort</h2>
<label class="field"><span>Show</span><select id="bigBoxFilter"><option value="all">Current library view</option><option value="installed">Installed games</option><option value="owned">All owned games</option><option value="favorites">Favorites</option><option value="playing">In progress</option><option value="completed">Completed</option></select></label>
<label class="field"><span>Sort</span><select id="bigBoxSort"><option value="title">Title</option><option value="rating">Rating</option><option value="recent">Recently played</option><option value="recent_activity">Recent activity</option><option value="playtime">Play time</option><option value="random">Shuffle</option></select></label>
<label class="field"><span>Quick preset</span><select id="bigBoxQuickPreset"><option value="">None</option></select></label>
<label class="field"><span>Achievements</span><select id="bigBoxRaFilter"><option value="all">All games</option><option value="matched">RetroAchievements matched</option><option value="unmatched">Not matched</option></select></label>
<div class="dialog-actions"><button class="icon-button" id="closeBigBoxMenu" type="button">Cancel</button><button class="primary" id="applyBigBoxMenu" type="button">Apply</button></div>
<div class="dialog-actions"><button class="icon-button" id="partyMenuButton" type="button" data-i18n="party.open">Game Night</button><button class="icon-button" id="bigBoxNetplay" type="button" data-i18n="tools.netplay">Online play</button></div>
</div>
</div>
<div class="screensaver" id="screenSaver" role="dialog" aria-modal="true" aria-label="Screensaver" hidden><video id="screenSaverVideo" muted autoplay loop></video><div class="screensaver-copy"><div class="hero-kicker" id="screenSaverPlatform"></div><h2 id="screenSaverTitle"></h2><p class="screensaver-stats" id="screenSaverStats" aria-live="polite"></p><p>Press Play to launch, or any other control to return.</p></div></div>
<div class="bigbox-pause" id="bigBoxPause" role="dialog" aria-modal="true" aria-label="Running game" hidden><div class="bigbox-pause-panel"><h2 id="bigBoxPauseTitle">Running game</h2><p class="description" id="bigBoxPauseMeta"></p><div class="extras" id="bigBoxPauseActions"></div><div class="description" id="bigBoxPauseHighscores"></div><div class="dialog-actions"><button class="icon-button" id="closeBigBoxPause" type="button" data-i18n="bigbox.pause_close">Close</button></div></div></div>
<div class="bigbox-osk" id="bigBoxOsk" hidden></div>
<div class="party-overlay" id="partyOverlay" hidden></div>
</section>
<dialog id="pickerDialog" aria-modal="true" aria-labelledby="pickerDialogTitle">
<form id="pickerForm">
<div class="dialog-head"><h2 id="pickerDialogTitle" data-i18n="picker.title">What should I play?</h2><button type="button" id="closePicker" aria-label="Close picker dialog">×</button></div>
<div class="form-grid picker-grid">
<label class="field"><span data-i18n="picker.time">Time I have</span><select id="pickerTime"><option value="0" data-i18n="picker.time_any">Any</option><option value="30">30 min</option><option value="45">45 min</option><option value="60">1 h</option><option value="90">1.5 h</option><option value="120">2 h</option></select></label>
<label class="field"><span data-i18n="picker.mood">Mood</span><select id="pickerMood"><option value="any" data-i18n="picker.mood_any">Any</option><option value="action" data-i18n="picker.mood_action">Action</option><option value="chill" data-i18n="picker.mood_chill">Chill</option><option value="story" data-i18n="picker.mood_story">Story</option><option value="retro" data-i18n="picker.mood_retro">Retro</option><option value="party" data-i18n="picker.mood_party">Party</option></select></label>
<label class="field"><span data-i18n="picker.familiarity">Familiarity</span><select id="pickerFamiliarity"><option value="any" data-i18n="picker.familiarity_any">Either</option><option value="new" data-i18n="picker.familiarity_new">Something new</option><option value="favorite" data-i18n="picker.familiarity_favorite">A favorite</option></select></label>
<label class="field"><span data-i18n="picker.players">Players</span><input id="pickerPlayers" type="number" min="1" max="8" value="1"></label>
<div class="wide" id="pickerSpinning" hidden><p class="description" data-i18n="common.loading">Loading...</p></div>
<div class="wide" id="pickerResult" hidden>
<div class="picker-card" id="pickerResultCard"></div>
</div>
<div class="wide" id="pickerResultEmpty" hidden><p class="description" data-i18n="picker.empty">No games match — loosen a filter.</p></div>
<div class="dialog-actions wide">
<button type="button" class="icon-button" id="pickerRandom" data-i18n="picker.random">Just surprise me</button>
<button type="button" class="icon-button" id="closePicker2">Cancel</button>
<button type="button" class="primary" id="pickerSpin" data-i18n="picker.spin">Pick</button>
</div>
</div>
</form>
</dialog>
<dialog id="wrappedDialog" aria-modal="true" aria-labelledby="wrappedDialogTitle" class="wide-dialog">
<form>
<div class="dialog-head wrapped-head">
<h2 id="wrappedDialogTitle" data-i18n="wrapped.title">Your Year in Games</h2>
<div class="wrapped-actions">
<label class="field inline"><span data-i18n="wrapped.year">Year</span><select id="wrappedYear"></select></label>
<button type="button" class="icon-button" id="wrappedPrint" data-i18n="wrapped.print">Print</button>
<button type="button" id="closeWrapped" aria-label="Close wrapped dialog">×</button>
</div>
</div>
<div id="wrappedBody" class="dialog-body"></div>
</form>
</dialog>
<dialog id="masteryDialog" aria-modal="true" aria-labelledby="masteryDialogTitle">
<form>
<div class="dialog-head"><h2 id="masteryDialogTitle" data-i18n="mastery.title">Mastery</h2><button type="button" id="closeMastery" aria-label="Close mastery dialog">×</button></div>
<div class="mastery-wrap">
<label class="field inline"><span data-i18n="mastery.decade">Decade</span><select id="masteryDecadeFilter"><option value="" data-i18n="mastery.all">All</option><option value="pre-1980" data-i18n="mastery.pre_1980">pre-1980</option><option value="1980s">1980s</option><option value="1990s">1990s</option><option value="2000s">2000s</option><option value="2010s">2010s</option><option value="2020s">2020s</option></select></label>
<div id="masteryOverall"></div>
<div id="masteryBody"></div>
</div>
</form>
</dialog>
<dialog id="constellationDialog" aria-modal="true" aria-labelledby="constellationDialogTitle">
<form>
<div class="dialog-head"><h2 id="constellationDialogTitle" data-i18n="constellation.title">Constellation</h2><button type="button" id="closeConstellation" aria-label="Close constellation dialog">×</button></div>
<div class="constellation-wrap">
<div class="constellation-controls">
<label class="field"><span data-i18n="constellation.limit">Limit</span><select id="constellationLimit"><option value="200">200</option><option value="400" selected>400</option><option value="800">800</option><option value="1000">1000</option></select></label>
<div class="constellation-legend" id="constellationKinds"></div>
<button type="button" class="icon-button" id="constellationRelayout" data-i18n="constellation.relayout">Re-layout</button>
</div>
<div class="constellation-canvas" id="constellationCanvasWrap">
<canvas id="constellationCanvas" class="constellation-canvas" aria-label="Library relationship graph"></canvas>
<div id="constellationTooltip" class="constellation-tooltip" hidden></div>
</div>
<p id="constellationLoading" class="description" data-i18n="common.loading">Loading...</p>
<p id="constellationEmpty" class="description" data-i18n="constellation.empty" hidden>No connections yet — run a metadata sync first.</p>
</div>
</form>
</dialog>
<script type="module" src="/static/app.js"></script>
<script type="module" src="/static/osk.js"></script>
</body>
</html>