Our Personal Data Server from scratch! tranquil.farm
oauth atproto pds rust postgresql objectstorage fun

refactor(frontend): extract admin, settings, app passwords styles #60

merged opened by oyster.cafe targeting main from refactor/extract-scoped-styles
Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:3fwecdnvtcscjnrx2p4n7alz/sh.tangled.repo.pull/3mhdc5fbu4522
+16 -950
Diff #0
+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
··· 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
··· 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
sign up or login to add to the discussion
oyster.cafe submitted #0
1 commit
expand
refactor(frontend): extract admin, settings, app passwords styles
expand 0 comments
pull request successfully merged