+16
-950
Diff
round #0
+5
-408
frontend/src/components/dashboard/AdminContent.svelte
+5
-408
frontend/src/components/dashboard/AdminContent.svelte
···
269
269
<section class="config-section">
270
270
<h3>{$_('admin.serverConfig')}</h3>
271
271
<form onsubmit={saveServerConfig}>
272
-
<div class="field">
272
+
<div>
273
273
<label for="server-name">{$_('admin.serverName')}</label>
274
274
<input
275
275
id="server-name"
···
281
281
<span class="field-help">{$_('admin.serverNameHelp')}</span>
282
282
</div>
283
283
284
-
<div class="field">
284
+
<div>
285
285
<label for="server-logo">{$_('admin.serverLogo')}</label>
286
286
<div class="logo-section">
287
287
{#if logoPreview}
···
341
341
<section class="stats-section">
342
342
<div class="section-header-row">
343
343
<h3>{$_('admin.serverStats')}</h3>
344
-
<button type="button" class="refresh-btn" onclick={loadStats} disabled={loading}>
344
+
<button type="button" class="sm tertiary" onclick={loadStats} disabled={loading}>
345
345
{$_('admin.refreshStats')}
346
346
</button>
347
347
</div>
···
423
423
</div>
424
424
425
425
{#if selectedUser}
426
-
<div class="modal-overlay" onclick={closeUserDetail} onkeydown={(e) => e.key === 'Escape' && closeUserDetail()} role="presentation">
426
+
<div class="modal-backdrop" onclick={closeUserDetail} onkeydown={(e) => e.key === 'Escape' && closeUserDetail()} role="presentation">
427
427
<div class="modal" onclick={(e) => e.stopPropagation()} onkeydown={(e) => e.stopPropagation()} role="dialog" aria-modal="true" tabindex="-1">
428
428
<div class="modal-header">
429
429
<h2>{$_('admin.userDetails')}</h2>
···
433
433
{#if userDetailLoading}
434
434
<div class="loading">{$_('common.loading')}</div>
435
435
{/if}
436
-
<dl class="user-details">
436
+
<dl class="definition-list">
437
437
<dt>{$_('admin.handle')}</dt>
438
438
<dd>@{selectedUser.handle}</dd>
439
439
<dt>{$_('admin.did')}</dt>
···
480
480
</div>
481
481
</div>
482
482
{/if}
483
-
484
-
<style>
485
-
.admin {
486
-
max-width: var(--width-lg);
487
-
}
488
-
489
-
section {
490
-
background: var(--bg-secondary);
491
-
padding: var(--space-5);
492
-
border-radius: var(--radius-lg);
493
-
margin-bottom: var(--space-5);
494
-
}
495
-
496
-
section h3 {
497
-
margin: 0 0 var(--space-4) 0;
498
-
font-size: var(--text-base);
499
-
}
500
-
501
-
.section-header-row {
502
-
display: flex;
503
-
justify-content: space-between;
504
-
align-items: center;
505
-
margin-bottom: var(--space-4);
506
-
}
507
-
508
-
.section-header-row h3 {
509
-
margin: 0;
510
-
}
511
-
512
-
.refresh-btn {
513
-
padding: var(--space-2) var(--space-3);
514
-
font-size: var(--text-sm);
515
-
background: transparent;
516
-
border: 1px solid var(--border-color);
517
-
border-radius: var(--radius-md);
518
-
cursor: pointer;
519
-
color: var(--text-primary);
520
-
}
521
-
522
-
.refresh-btn:hover:not(:disabled) {
523
-
border-color: var(--accent);
524
-
}
525
-
526
-
.refresh-btn:disabled {
527
-
opacity: 0.6;
528
-
cursor: not-allowed;
529
-
}
530
-
531
-
.loading,
532
-
.empty {
533
-
color: var(--text-secondary);
534
-
padding: var(--space-4);
535
-
text-align: center;
536
-
}
537
-
538
-
.stats-grid {
539
-
display: grid;
540
-
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
541
-
gap: var(--space-4);
542
-
}
543
-
544
-
.stat-item {
545
-
background: var(--bg-card);
546
-
padding: var(--space-4);
547
-
border-radius: var(--radius-md);
548
-
text-align: center;
549
-
}
550
-
551
-
.stat-value {
552
-
display: block;
553
-
font-size: var(--text-2xl);
554
-
font-weight: var(--font-bold);
555
-
color: var(--accent);
556
-
}
557
-
558
-
.stat-label {
559
-
display: block;
560
-
font-size: var(--text-sm);
561
-
color: var(--text-secondary);
562
-
margin-top: var(--space-1);
563
-
}
564
-
565
-
.search-bar {
566
-
display: flex;
567
-
gap: var(--space-2);
568
-
margin-bottom: var(--space-4);
569
-
}
570
-
571
-
.search-bar input {
572
-
flex: 1;
573
-
}
574
-
575
-
.user-list {
576
-
list-style: none;
577
-
padding: 0;
578
-
margin: 0;
579
-
display: flex;
580
-
flex-direction: column;
581
-
gap: var(--space-2);
582
-
}
583
-
584
-
.user-item {
585
-
list-style: none;
586
-
}
587
-
588
-
.user-item-btn {
589
-
display: flex;
590
-
align-items: flex-start;
591
-
width: 100%;
592
-
padding: var(--space-3);
593
-
background: var(--bg-card);
594
-
border: 1px solid var(--border-color);
595
-
border-radius: var(--radius-md);
596
-
gap: var(--space-3);
597
-
cursor: pointer;
598
-
text-align: left;
599
-
color: inherit;
600
-
font: inherit;
601
-
}
602
-
603
-
.user-item-btn:hover {
604
-
border-color: var(--accent);
605
-
}
606
-
607
-
.user-info {
608
-
flex: 1;
609
-
min-width: 0;
610
-
display: flex;
611
-
flex-direction: column;
612
-
gap: var(--space-1);
613
-
}
614
-
615
-
.user-handle {
616
-
font-weight: var(--font-medium);
617
-
}
618
-
619
-
.user-did {
620
-
font-family: var(--font-mono);
621
-
font-size: var(--text-xs);
622
-
color: var(--text-secondary);
623
-
word-break: break-all;
624
-
}
625
-
626
-
.user-email {
627
-
font-size: var(--text-sm);
628
-
color: var(--text-secondary);
629
-
}
630
-
631
-
.user-date {
632
-
font-size: var(--text-xs);
633
-
color: var(--text-muted);
634
-
}
635
-
636
-
.user-badges {
637
-
display: flex;
638
-
gap: var(--space-2);
639
-
flex-shrink: 0;
640
-
}
641
-
642
-
.badge {
643
-
padding: var(--space-1) var(--space-2);
644
-
border-radius: var(--radius-md);
645
-
font-size: var(--text-xs);
646
-
}
647
-
648
-
.badge.deactivated {
649
-
background: var(--warning-bg);
650
-
color: var(--warning-text);
651
-
}
652
-
653
-
.field {
654
-
margin-bottom: var(--space-4);
655
-
}
656
-
657
-
.field label {
658
-
display: block;
659
-
font-size: var(--text-sm);
660
-
font-weight: var(--font-medium);
661
-
margin-bottom: var(--space-1);
662
-
}
663
-
664
-
.field-help {
665
-
display: block;
666
-
font-size: var(--text-xs);
667
-
color: var(--text-secondary);
668
-
margin-top: var(--space-1);
669
-
}
670
-
671
-
.logo-section {
672
-
display: flex;
673
-
flex-direction: column;
674
-
gap: var(--space-3);
675
-
}
676
-
677
-
.logo-preview {
678
-
display: flex;
679
-
align-items: center;
680
-
gap: var(--space-3);
681
-
}
682
-
683
-
.logo-preview img {
684
-
width: 48px;
685
-
height: 48px;
686
-
object-fit: contain;
687
-
border-radius: var(--radius-md);
688
-
background: var(--bg-card);
689
-
padding: var(--space-2);
690
-
}
691
-
692
-
.remove-logo {
693
-
padding: var(--space-2) var(--space-3);
694
-
font-size: var(--text-sm);
695
-
background: transparent;
696
-
border: 1px solid var(--error-border);
697
-
color: var(--error-text);
698
-
border-radius: var(--radius-md);
699
-
cursor: pointer;
700
-
}
701
-
702
-
.remove-logo:hover {
703
-
background: var(--error-bg);
704
-
}
705
-
706
-
.colors-grid {
707
-
margin-bottom: var(--space-5);
708
-
}
709
-
710
-
.colors-grid h4 {
711
-
margin: 0 0 var(--space-2) 0;
712
-
font-size: var(--text-sm);
713
-
font-weight: var(--font-medium);
714
-
}
715
-
716
-
.color-fields {
717
-
display: grid;
718
-
grid-template-columns: repeat(2, 1fr);
719
-
gap: var(--space-3);
720
-
margin-top: var(--space-3);
721
-
}
722
-
723
-
.color-field label {
724
-
display: block;
725
-
font-size: var(--text-xs);
726
-
color: var(--text-secondary);
727
-
margin-bottom: var(--space-1);
728
-
}
729
-
730
-
.color-input-row {
731
-
display: flex;
732
-
gap: var(--space-2);
733
-
align-items: center;
734
-
}
735
-
736
-
.color-input-row input[type="color"] {
737
-
width: 40px;
738
-
height: 36px;
739
-
padding: 2px;
740
-
border: 1px solid var(--border-color);
741
-
border-radius: var(--radius-md);
742
-
cursor: pointer;
743
-
flex-shrink: 0;
744
-
}
745
-
746
-
.color-input-row input[type="text"] {
747
-
flex: 1;
748
-
font-family: var(--font-mono);
749
-
font-size: var(--text-sm);
750
-
}
751
-
752
-
.load-more {
753
-
display: block;
754
-
width: 100%;
755
-
margin-top: var(--space-4);
756
-
}
757
-
758
-
.badge.verified {
759
-
background: var(--success-bg);
760
-
color: var(--success-text);
761
-
}
762
-
763
-
.badge.unverified {
764
-
background: var(--bg-tertiary);
765
-
color: var(--text-secondary);
766
-
}
767
-
768
-
.modal-overlay {
769
-
position: fixed;
770
-
inset: 0;
771
-
background: var(--overlay-bg);
772
-
display: flex;
773
-
align-items: center;
774
-
justify-content: center;
775
-
z-index: var(--z-modal);
776
-
}
777
-
778
-
.modal {
779
-
background: var(--bg-card);
780
-
border-radius: var(--radius-xl);
781
-
box-shadow: var(--shadow-lg);
782
-
max-width: var(--width-sm);
783
-
width: 90%;
784
-
max-height: 90vh;
785
-
overflow-y: auto;
786
-
}
787
-
788
-
.modal-header {
789
-
display: flex;
790
-
justify-content: space-between;
791
-
align-items: center;
792
-
padding: var(--space-4) var(--space-5);
793
-
border-bottom: 1px solid var(--border-color);
794
-
}
795
-
796
-
.modal-header h2 {
797
-
margin: 0;
798
-
font-size: var(--text-lg);
799
-
}
800
-
801
-
.close-btn {
802
-
background: none;
803
-
border: none;
804
-
font-size: var(--text-xl);
805
-
cursor: pointer;
806
-
color: var(--text-secondary);
807
-
padding: 0;
808
-
line-height: 1;
809
-
}
810
-
811
-
.close-btn:hover {
812
-
color: var(--text-primary);
813
-
}
814
-
815
-
.modal-body {
816
-
padding: var(--space-5);
817
-
}
818
-
819
-
.user-details {
820
-
display: grid;
821
-
grid-template-columns: auto 1fr;
822
-
gap: var(--space-2) var(--space-4);
823
-
margin: 0 0 var(--space-5) 0;
824
-
}
825
-
826
-
.user-details dt {
827
-
font-weight: var(--font-medium);
828
-
color: var(--text-secondary);
829
-
font-size: var(--text-sm);
830
-
}
831
-
832
-
.user-details dd {
833
-
margin: 0;
834
-
}
835
-
836
-
.user-details .mono {
837
-
font-family: var(--font-mono);
838
-
font-size: var(--text-xs);
839
-
word-break: break-all;
840
-
}
841
-
842
-
.modal-actions {
843
-
display: flex;
844
-
gap: var(--space-3);
845
-
flex-wrap: wrap;
846
-
}
847
-
848
-
.modal-actions button.danger {
849
-
background: var(--error-text);
850
-
border: 1px solid var(--error-text);
851
-
color: white;
852
-
}
853
-
854
-
.modal-actions button.danger:hover {
855
-
background: var(--error-border);
856
-
}
857
-
858
-
@media (max-width: 600px) {
859
-
.user-item {
860
-
flex-direction: column;
861
-
}
862
-
863
-
.user-item-btn {
864
-
flex-direction: column;
865
-
gap: var(--space-2);
866
-
}
867
-
868
-
.user-info {
869
-
width: 100%;
870
-
}
871
-
872
-
.user-badges {
873
-
width: 100%;
874
-
flex-wrap: wrap;
875
-
}
876
-
877
-
.search-bar {
878
-
flex-direction: column;
879
-
}
880
-
881
-
.color-fields {
882
-
grid-template-columns: 1fr;
883
-
}
884
-
}
885
-
</style>
+2
-233
frontend/src/components/dashboard/AppPasswordsContent.svelte
+2
-233
frontend/src/components/dashboard/AppPasswordsContent.svelte
···
131
131
{/if}
132
132
133
133
<form class="create-form" onsubmit={handleCreate}>
134
-
<div class="field">
134
+
<div>
135
135
<label for="app-name">{$_('appPasswords.name')}</label>
136
136
<input
137
137
id="app-name"
···
183
183
</div>
184
184
<button
185
185
type="button"
186
-
class="delete-btn"
186
+
class="sm danger-outline"
187
187
onclick={() => handleDelete(pw.name)}
188
188
disabled={deleting === pw.name}
189
189
>
···
194
194
</ul>
195
195
{/if}
196
196
</div>
197
-
198
-
<style>
199
-
.app-passwords {
200
-
max-width: var(--width-lg);
201
-
}
202
-
203
-
.new-password-banner {
204
-
background: var(--warning-bg);
205
-
border: 1px solid var(--warning-border);
206
-
border-radius: var(--radius-lg);
207
-
padding: var(--space-4);
208
-
margin-bottom: var(--space-6);
209
-
}
210
-
211
-
.new-password-banner .password-label {
212
-
font-size: var(--text-sm);
213
-
color: var(--text-primary);
214
-
margin-bottom: var(--space-2);
215
-
}
216
-
217
-
.new-password-banner .warning {
218
-
color: var(--warning-text);
219
-
font-weight: var(--font-medium);
220
-
margin: 0 0 var(--space-3) 0;
221
-
}
222
-
223
-
.acknowledge-label {
224
-
display: flex;
225
-
align-items: center;
226
-
gap: var(--space-2);
227
-
margin-bottom: var(--space-3);
228
-
cursor: pointer;
229
-
font-size: var(--text-sm);
230
-
color: var(--text-primary);
231
-
}
232
-
233
-
.acknowledge-label input[type="checkbox"] {
234
-
width: 18px;
235
-
height: 18px;
236
-
accent-color: var(--accent);
237
-
}
238
-
239
-
.password-display {
240
-
display: flex;
241
-
gap: var(--space-2);
242
-
margin-bottom: var(--space-3);
243
-
}
244
-
245
-
.password-display code {
246
-
flex: 1;
247
-
padding: var(--space-3);
248
-
background: var(--bg-card);
249
-
border-radius: var(--radius-md);
250
-
font-family: var(--font-mono);
251
-
word-break: break-all;
252
-
}
253
-
254
-
.copy-btn {
255
-
padding: var(--space-2) var(--space-3);
256
-
font-size: var(--text-sm);
257
-
}
258
-
259
-
.dismiss-btn {
260
-
width: 100%;
261
-
}
262
-
263
-
.create-form {
264
-
background: var(--bg-secondary);
265
-
padding: var(--space-5);
266
-
border-radius: var(--radius-lg);
267
-
margin-bottom: var(--space-6);
268
-
}
269
-
270
-
.create-form .field {
271
-
margin-bottom: var(--space-4);
272
-
}
273
-
274
-
.scope-selector {
275
-
display: flex;
276
-
flex-direction: column;
277
-
gap: var(--space-2);
278
-
margin-bottom: var(--space-4);
279
-
}
280
-
281
-
.scope-label {
282
-
font-size: var(--text-sm);
283
-
color: var(--text-secondary);
284
-
}
285
-
286
-
.scope-buttons {
287
-
display: flex;
288
-
flex-wrap: wrap;
289
-
gap: var(--space-2);
290
-
}
291
-
292
-
.scope-btn {
293
-
padding: var(--space-2) var(--space-4);
294
-
background: var(--bg-card);
295
-
border: 1px solid var(--border-color);
296
-
border-radius: var(--radius-md);
297
-
color: var(--text-primary);
298
-
cursor: pointer;
299
-
font-size: var(--text-sm);
300
-
transition: all 0.15s ease;
301
-
}
302
-
303
-
.scope-btn:hover:not(:disabled) {
304
-
background: var(--bg-hover);
305
-
border-color: var(--accent);
306
-
}
307
-
308
-
.scope-btn.selected {
309
-
background: var(--accent);
310
-
border-color: var(--accent);
311
-
color: var(--text-inverse);
312
-
}
313
-
314
-
.scope-btn:disabled {
315
-
opacity: 0.6;
316
-
cursor: not-allowed;
317
-
}
318
-
319
-
.loading,
320
-
.empty {
321
-
color: var(--text-secondary);
322
-
padding: var(--space-6);
323
-
text-align: center;
324
-
}
325
-
326
-
.password-list {
327
-
list-style: none;
328
-
padding: 0;
329
-
margin: 0;
330
-
display: flex;
331
-
flex-direction: column;
332
-
gap: var(--space-3);
333
-
}
334
-
335
-
.password-item {
336
-
display: flex;
337
-
justify-content: space-between;
338
-
align-items: center;
339
-
padding: var(--space-4);
340
-
background: var(--bg-secondary);
341
-
border-radius: var(--radius-lg);
342
-
gap: var(--space-4);
343
-
}
344
-
345
-
.password-info {
346
-
display: flex;
347
-
flex-direction: column;
348
-
gap: var(--space-1);
349
-
}
350
-
351
-
.password-name {
352
-
font-weight: var(--font-medium);
353
-
}
354
-
355
-
.password-meta {
356
-
display: flex;
357
-
align-items: center;
358
-
flex-wrap: wrap;
359
-
gap: var(--space-2);
360
-
font-size: var(--text-sm);
361
-
color: var(--text-secondary);
362
-
}
363
-
364
-
.scope-badge {
365
-
font-size: var(--text-xs);
366
-
padding: var(--space-1) var(--space-2);
367
-
background: var(--bg-card);
368
-
border: 1px solid var(--border-color);
369
-
border-radius: var(--radius-sm);
370
-
color: var(--text-secondary);
371
-
}
372
-
373
-
.scope-badge.full {
374
-
background: var(--success-bg);
375
-
border-color: var(--success-border);
376
-
color: var(--success-text);
377
-
}
378
-
379
-
.controller-badge {
380
-
font-size: var(--text-xs);
381
-
padding: var(--space-1) var(--space-2);
382
-
background: var(--accent-muted);
383
-
border: 1px solid var(--accent);
384
-
border-radius: var(--radius-sm);
385
-
color: var(--accent);
386
-
cursor: help;
387
-
}
388
-
389
-
.date {
390
-
color: var(--text-secondary);
391
-
}
392
-
393
-
.delete-btn {
394
-
flex-shrink: 0;
395
-
padding: var(--space-2) var(--space-3);
396
-
font-size: var(--text-sm);
397
-
background: transparent;
398
-
border: 1px solid var(--error-border);
399
-
color: var(--error-text);
400
-
border-radius: var(--radius-md);
401
-
cursor: pointer;
402
-
}
403
-
404
-
.delete-btn:hover:not(:disabled) {
405
-
background: var(--error-bg);
406
-
}
407
-
408
-
.delete-btn:disabled {
409
-
opacity: 0.6;
410
-
cursor: not-allowed;
411
-
}
412
-
413
-
@media (max-width: 500px) {
414
-
.password-item {
415
-
flex-direction: column;
416
-
align-items: stretch;
417
-
}
418
-
419
-
.delete-btn {
420
-
width: 100%;
421
-
}
422
-
423
-
.password-display {
424
-
flex-direction: column;
425
-
}
426
-
}
427
-
</style>
+9
-309
frontend/src/components/dashboard/SettingsContent.svelte
+9
-309
frontend/src/components/dashboard/SettingsContent.svelte
···
382
382
{#if emailUpdateAuthorized}
383
383
<p class="hint success">{$_('settings.emailUpdateAuthorized')}</p>
384
384
{:else}
385
-
<div class="field">
385
+
<div>
386
386
<label for="email-token">{$_('settings.verificationCode')}</label>
387
387
<input
388
388
id="email-token"
···
394
394
<p class="hint">{$_('settings.emailTokenHint')}</p>
395
395
</div>
396
396
{/if}
397
-
<div class="field">
397
+
<div>
398
398
<label for="new-email">{$_('settings.newEmail')}</label>
399
399
<input
400
400
id="new-email"
···
420
420
</form>
421
421
{:else}
422
422
<form onsubmit={(e) => { e.preventDefault(); handleRequestEmailUpdate() }}>
423
-
<div class="field">
423
+
<div>
424
424
<label for="new-email">{$_('settings.newEmail')}</label>
425
425
<input
426
426
id="new-email"
···
472
472
</div>
473
473
</div>
474
474
<form onsubmit={handleUpdateHandle}>
475
-
<div class="field">
475
+
<div>
476
476
<label for="new-handle-byo">{$_('settings.yourDomain')}</label>
477
477
<input id="new-handle-byo" type="text" bind:value={newHandle} placeholder={$_('settings.yourDomainPlaceholder')} disabled={handleLoading} required />
478
478
</div>
···
483
483
</div>
484
484
{:else}
485
485
<form onsubmit={handleUpdateHandle}>
486
-
<div class="field">
486
+
<div>
487
487
<label for="new-handle">{$_('settings.newHandle')}</label>
488
488
<HandleInput
489
489
id="new-handle"
···
529
529
<span class="backup-size">{formatBytes(backup.sizeBytes)}</span>
530
530
</div>
531
531
<div class="backup-item-actions">
532
-
<button class="small" onclick={() => handleDownloadBackup(backup.id, backup.repoRev)}>
532
+
<button class="sm" onclick={() => handleDownloadBackup(backup.id, backup.repoRev)}>
533
533
{$_('settings.backups.download')}
534
534
</button>
535
-
<button class="small danger" onclick={() => handleDeleteBackup(backup.id)}>
535
+
<button class="sm danger-outline" onclick={() => handleDeleteBackup(backup.id)}>
536
536
{$_('settings.backups.delete')}
537
537
</button>
538
538
</div>
···
586
586
<p class="warning-text">{$_('settings.deleteWarning')}</p>
587
587
{#if deleteTokenSent}
588
588
<form onsubmit={handleConfirmDelete}>
589
-
<div class="field">
589
+
<div>
590
590
<label for="delete-token">{$_('settings.confirmationCode')}</label>
591
591
<input
592
592
id="delete-token"
···
597
597
required
598
598
/>
599
599
</div>
600
-
<div class="field">
600
+
<div>
601
601
<label for="delete-password">{$_('settings.yourPassword')}</label>
602
602
<input
603
603
id="delete-password"
···
624
624
{/if}
625
625
</section>
626
626
</div>
627
-
628
-
<style>
629
-
.settings {
630
-
max-width: var(--width-lg);
631
-
}
632
-
633
-
section {
634
-
background: var(--bg-secondary);
635
-
padding: var(--space-5);
636
-
border-radius: var(--radius-lg);
637
-
margin-bottom: var(--space-5);
638
-
}
639
-
640
-
section h3 {
641
-
margin: 0 0 var(--space-3) 0;
642
-
font-size: var(--text-base);
643
-
}
644
-
645
-
.current {
646
-
color: var(--text-secondary);
647
-
font-size: var(--text-sm);
648
-
margin: 0 0 var(--space-3) 0;
649
-
}
650
-
651
-
.language-select {
652
-
width: 100%;
653
-
}
654
-
655
-
.field {
656
-
margin-bottom: var(--space-3);
657
-
}
658
-
659
-
.field label {
660
-
display: block;
661
-
margin-bottom: var(--space-1);
662
-
font-size: var(--text-sm);
663
-
font-weight: var(--font-medium);
664
-
}
665
-
666
-
.actions {
667
-
display: flex;
668
-
gap: var(--space-2);
669
-
margin-top: var(--space-3);
670
-
}
671
-
672
-
.tabs {
673
-
display: flex;
674
-
gap: var(--space-1);
675
-
margin-bottom: var(--space-4);
676
-
}
677
-
678
-
.tab {
679
-
flex: 1;
680
-
padding: var(--space-2) var(--space-4);
681
-
background: transparent;
682
-
border: 1px solid var(--border-color);
683
-
cursor: pointer;
684
-
font-size: var(--text-sm);
685
-
color: var(--text-secondary);
686
-
}
687
-
688
-
.tab:first-child {
689
-
border-radius: var(--radius-md) 0 0 var(--radius-md);
690
-
}
691
-
692
-
.tab:last-child {
693
-
border-radius: 0 var(--radius-md) var(--radius-md) 0;
694
-
}
695
-
696
-
.tab.active {
697
-
background: var(--accent);
698
-
border-color: var(--accent);
699
-
color: var(--text-inverse);
700
-
}
701
-
702
-
.loading,
703
-
.empty {
704
-
color: var(--text-secondary);
705
-
font-size: var(--text-sm);
706
-
margin-bottom: var(--space-4);
707
-
}
708
-
709
-
.backup-list {
710
-
list-style: none;
711
-
padding: 0;
712
-
margin: 0 0 var(--space-4) 0;
713
-
display: flex;
714
-
flex-direction: column;
715
-
gap: var(--space-2);
716
-
}
717
-
718
-
.backup-item {
719
-
display: flex;
720
-
justify-content: space-between;
721
-
align-items: center;
722
-
padding: var(--space-3);
723
-
background: var(--bg-card);
724
-
border: 1px solid var(--border-color);
725
-
border-radius: var(--radius-md);
726
-
}
727
-
728
-
.backup-info {
729
-
display: flex;
730
-
gap: var(--space-3);
731
-
font-size: var(--text-sm);
732
-
}
733
-
734
-
.backup-date {
735
-
font-weight: var(--font-medium);
736
-
}
737
-
738
-
.backup-size {
739
-
color: var(--text-secondary);
740
-
}
741
-
742
-
.backup-actions {
743
-
display: flex;
744
-
justify-content: space-between;
745
-
align-items: center;
746
-
margin-bottom: var(--space-4);
747
-
gap: var(--space-3);
748
-
flex-wrap: wrap;
749
-
}
750
-
751
-
.backup-toggle {
752
-
margin-bottom: var(--space-3);
753
-
}
754
-
755
-
.backup-toggle .toggle-label {
756
-
display: flex;
757
-
align-items: center;
758
-
gap: var(--space-2);
759
-
cursor: pointer;
760
-
font-size: var(--text-sm);
761
-
white-space: nowrap;
762
-
}
763
-
764
-
.backup-toggle .toggle-label input[type="checkbox"] {
765
-
width: 16px;
766
-
height: 16px;
767
-
flex-shrink: 0;
768
-
}
769
-
770
-
.backup-item-actions {
771
-
display: flex;
772
-
gap: var(--space-2);
773
-
}
774
-
775
-
.restore-section {
776
-
margin-top: var(--space-5);
777
-
padding-top: var(--space-4);
778
-
border-top: 1px solid var(--border-color);
779
-
}
780
-
781
-
.restore-section h4 {
782
-
margin: 0 0 var(--space-2) 0;
783
-
font-size: var(--text-sm);
784
-
font-weight: var(--font-medium);
785
-
}
786
-
787
-
.restore-section .hint {
788
-
margin-bottom: var(--space-3);
789
-
}
790
-
791
-
.restore-form {
792
-
display: flex;
793
-
gap: var(--space-2);
794
-
flex-wrap: wrap;
795
-
}
796
-
797
-
.restore-form input[type="file"] {
798
-
flex: 1;
799
-
min-width: 200px;
800
-
}
801
-
802
-
.restore-preview {
803
-
margin-top: var(--space-2);
804
-
font-size: var(--text-sm);
805
-
color: var(--text-secondary);
806
-
display: flex;
807
-
gap: var(--space-2);
808
-
flex-wrap: wrap;
809
-
}
810
-
811
-
.restore-preview .file-name {
812
-
font-weight: var(--font-medium);
813
-
color: var(--text-primary);
814
-
}
815
-
816
-
.export-buttons {
817
-
display: flex;
818
-
gap: var(--space-2);
819
-
flex-wrap: wrap;
820
-
}
821
-
822
-
button.small {
823
-
padding: var(--space-2) var(--space-3);
824
-
font-size: var(--text-sm);
825
-
}
826
-
827
-
.danger-zone {
828
-
border: 1px solid var(--error-border);
829
-
}
830
-
831
-
.danger-zone h3 {
832
-
color: var(--error-text);
833
-
}
834
-
835
-
.warning-text {
836
-
color: var(--text-secondary);
837
-
font-size: var(--text-sm);
838
-
margin: 0 0 var(--space-4) 0;
839
-
}
840
-
841
-
button.danger {
842
-
background: var(--error-text);
843
-
border: 1px solid var(--error-text);
844
-
color: white;
845
-
}
846
-
847
-
button.danger:hover:not(:disabled) {
848
-
background: var(--error-border);
849
-
}
850
-
851
-
button.danger:disabled {
852
-
opacity: 0.6;
853
-
cursor: not-allowed;
854
-
}
855
-
856
-
.hint {
857
-
font-size: var(--text-xs);
858
-
color: var(--text-secondary);
859
-
margin: var(--space-1) 0 0 0;
860
-
}
861
-
862
-
.hint.warning {
863
-
color: var(--warning-text);
864
-
}
865
-
866
-
.hint.success {
867
-
color: var(--success-text);
868
-
background: var(--success-bg);
869
-
padding: var(--space-2);
870
-
border-radius: var(--radius-md);
871
-
margin-bottom: var(--space-3);
872
-
}
873
-
874
-
.byo-handle {
875
-
margin-top: var(--space-3);
876
-
}
877
-
878
-
.verification-info {
879
-
background: var(--bg-card);
880
-
border: 1px solid var(--border-color);
881
-
border-radius: var(--radius-lg);
882
-
padding: var(--space-4);
883
-
margin-bottom: var(--space-4);
884
-
}
885
-
886
-
.verification-info h4 {
887
-
margin: 0 0 var(--space-2) 0;
888
-
font-size: var(--text-sm);
889
-
font-weight: var(--font-medium);
890
-
}
891
-
892
-
.verification-info h5 {
893
-
margin: var(--space-3) 0 var(--space-1) 0;
894
-
font-size: var(--text-xs);
895
-
font-weight: var(--font-medium);
896
-
color: var(--text-secondary);
897
-
}
898
-
899
-
.verification-info p {
900
-
margin: var(--space-1) 0;
901
-
font-size: var(--text-xs);
902
-
color: var(--text-secondary);
903
-
}
904
-
905
-
.method {
906
-
margin-top: var(--space-3);
907
-
padding-top: var(--space-3);
908
-
border-top: 1px solid var(--border-color);
909
-
}
910
-
911
-
.method:first-of-type {
912
-
margin-top: var(--space-2);
913
-
padding-top: 0;
914
-
border-top: none;
915
-
}
916
-
917
-
code.record {
918
-
display: block;
919
-
background: var(--bg-input);
920
-
padding: var(--space-2);
921
-
border-radius: var(--radius-md);
922
-
font-size: var(--text-xs);
923
-
word-break: break-all;
924
-
margin: var(--space-1) 0;
925
-
}
926
-
</style>
History
1 round
0 comments
oyster.cafe
submitted
#0
1 commit
expand
collapse
refactor(frontend): extract admin, settings, app passwords styles
expand 0 comments
pull request successfully merged