Our Personal Data Server from scratch!
at fix/small-bugs 899 lines 16 kB view raw
1@import "./tokens.css"; 2 3@property --accent { 4 syntax: "<color>"; 5 inherits: true; 6 initial-value: #1a1d1d; 7} 8 9@property --secondary { 10 syntax: "<color>"; 11 inherits: true; 12 initial-value: #1a1d1d; 13} 14 15*, 16*::before, 17*::after { 18 box-sizing: border-box; 19} 20 21body { 22 margin: 0; 23 font-family: 24 "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; 25 font-size: var(--text-base); 26 line-height: var(--leading-normal); 27 color: var(--text-primary); 28 background: var(--bg-primary); 29 -webkit-font-smoothing: antialiased; 30 -moz-osx-font-smoothing: grayscale; 31 transition: background-color 0.3s ease; 32 overflow-wrap: anywhere; 33 word-break: break-word; 34} 35 36h1, h2, h3, h4, h5, h6 { 37 margin: 0; 38 line-height: var(--leading-tight); 39} 40 41h1 { 42 font-size: var(--text-2xl); 43} 44h2 { 45 font-size: var(--text-xl); 46} 47h3 { 48 font-size: var(--text-lg); 49} 50h4 { 51 font-size: var(--text-base); 52} 53 54p { 55 margin: 0; 56} 57 58a { 59 color: var(--accent); 60 text-decoration: underline; 61 text-underline-offset: 2px; 62} 63 64a:hover { 65 color: var(--accent-hover); 66} 67 68::selection { 69 background: var(--secondary-muted); 70} 71 72input, 73select, 74textarea { 75 font-family: inherit; 76 font-size: var(--text-base); 77 line-height: var(--leading-normal); 78 padding: var(--space-4); 79 border: 1px solid var(--border-dark); 80 border-radius: var(--radius-md); 81 background: var(--bg-input); 82 color: var(--text-primary); 83 transition: 84 border-color var(--transition-normal), 85 box-shadow var(--transition-normal); 86 width: 100%; 87} 88 89input:focus, 90select:focus, 91textarea:focus { 92 outline: none; 93 border-color: var(--accent); 94 box-shadow: var(--shadow-focus); 95} 96 97input:disabled, 98select:disabled, 99textarea:disabled { 100 background: var(--bg-input-disabled); 101 color: var(--text-muted); 102 cursor: not-allowed; 103} 104 105input::placeholder, 106textarea::placeholder { 107 color: var(--text-muted); 108} 109 110select { 111 cursor: pointer; 112 appearance: none; 113 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M6 8L1 3h10z'/%3E%3C/svg%3E"); 114 background-repeat: no-repeat; 115 background-position: right var(--space-4) center; 116 padding-right: var(--space-7); 117} 118 119button { 120 font-family: inherit; 121 font-size: var(--text-base); 122 font-weight: var(--font-medium); 123 line-height: var(--leading-normal); 124 padding: var(--space-4) var(--space-6); 125 border: none; 126 border-radius: var(--radius-md); 127 cursor: pointer; 128 transition: 129 background var(--transition-normal), 130 border-color var(--transition-normal), 131 opacity var(--transition-normal); 132 background: var(--accent); 133 color: var(--text-inverse); 134} 135 136button:hover:not(:disabled) { 137 background: var(--accent-hover); 138} 139 140button:disabled { 141 opacity: 0.6; 142 cursor: not-allowed; 143} 144 145button.secondary { 146 background: transparent; 147 color: var(--accent); 148 border: 1px solid var(--accent); 149} 150 151button.secondary:hover:not(:disabled) { 152 background: var(--accent); 153 color: var(--text-inverse); 154} 155 156button.tertiary { 157 background: transparent; 158 color: var(--text-secondary); 159 padding: var(--space-3) var(--space-4); 160} 161 162button.tertiary:hover:not(:disabled) { 163 color: var(--text-primary); 164 background: var(--bg-tertiary); 165} 166 167button.danger { 168 background: var(--error-text); 169} 170 171button.danger:hover:not(:disabled) { 172 background: #900; 173} 174 175button.danger-outline { 176 background: transparent; 177 border: 1px solid var(--error-border); 178 color: var(--error-text); 179} 180 181button.danger-outline:hover:not(:disabled) { 182 background: var(--error-bg); 183 border-color: var(--error-text); 184} 185 186button.ghost { 187 background: transparent; 188 color: var(--text-secondary); 189 border: 1px solid var(--border-dark); 190} 191 192button.ghost:hover:not(:disabled) { 193 background: var(--bg-secondary); 194 color: var(--text-primary); 195} 196 197button.link { 198 background: none; 199 border: none; 200 color: var(--accent); 201 padding: var(--space-2); 202 font-size: var(--text-sm); 203 font-weight: var(--font-normal); 204} 205 206button.link:hover:not(:disabled) { 207 background: none; 208 text-decoration: underline; 209} 210 211button.sm { 212 padding: var(--space-2) var(--space-3); 213 font-size: var(--text-xs); 214} 215 216button.icon { 217 background: none; 218 border: none; 219 color: var(--text-secondary); 220 padding: var(--space-1); 221 font-size: var(--text-base); 222} 223 224button.icon:hover:not(:disabled) { 225 background: none; 226 color: var(--text-primary); 227} 228 229label { 230 display: block; 231 font-size: var(--text-sm); 232 font-weight: var(--font-medium); 233 color: var(--text-primary); 234 margin-bottom: var(--space-2); 235} 236 237fieldset { 238 border: none; 239 border-left: 3px solid var(--accent); 240 border-radius: var(--radius-lg); 241 padding: var(--space-5); 242 padding-left: var(--space-6); 243 margin: 0; 244 background: var(--bg-secondary); 245} 246 247fieldset legend { 248 font-size: var(--text-xs); 249 font-weight: var(--font-semibold); 250 text-transform: uppercase; 251 letter-spacing: 0.05em; 252 padding: 0; 253 margin-left: calc(-1 * var(--space-1)); 254 margin-bottom: var(--space-3); 255 color: var(--text-secondary); 256 float: left; 257 width: 100%; 258} 259 260fieldset legend + * { 261 clear: both; 262} 263 264code { 265 font-family: var(--font-mono); 266 font-size: 0.9em; 267 background: var(--bg-tertiary); 268 padding: var(--space-1) var(--space-2); 269 border-radius: var(--radius-sm); 270} 271 272pre { 273 font-family: var(--font-mono); 274 font-size: var(--text-sm); 275 background: var(--bg-tertiary); 276 padding: var(--space-4); 277 border-radius: var(--radius-md); 278 overflow-x: auto; 279 margin: 0; 280} 281 282hr { 283 border: none; 284 border-top: 1px solid var(--border-color); 285 margin: var(--space-6) 0; 286} 287 288.field { 289 display: flex; 290 flex-direction: column; 291 gap: var(--space-2); 292} 293 294.field + .field { 295 margin-top: var(--space-5); 296} 297 298.form-row .field + .field { 299 margin-top: 0; 300} 301 302.hint { 303 font-size: var(--text-xs); 304 color: var(--text-secondary); 305 margin-top: var(--space-1); 306} 307 308.hint.warning { 309 color: var(--warning-text); 310} 311 312.hint.error { 313 color: var(--error-text); 314} 315 316.hint.success { 317 color: var(--success-text); 318} 319 320.message { 321 padding: var(--space-4); 322 border-radius: var(--radius-md); 323 font-size: var(--text-sm); 324} 325 326.message.success { 327 background: var(--success-bg); 328 border: 1px solid var(--success-border); 329 color: var(--success-text); 330} 331 332.message.error { 333 background: var(--error-bg); 334 border: 1px solid var(--error-border); 335 color: var(--error-text); 336} 337 338.message.warning { 339 background: var(--warning-bg); 340 border: 1px solid var(--warning-border); 341 color: var(--warning-text); 342} 343 344.badge { 345 display: inline-block; 346 padding: var(--space-1) var(--space-3); 347 border-radius: var(--radius-md); 348 font-size: var(--text-xs); 349 font-weight: var(--font-medium); 350} 351 352.badge.success { 353 background: var(--success-bg); 354 color: var(--success-text); 355} 356 357.badge.warning { 358 background: var(--warning-bg); 359 color: var(--warning-text); 360} 361 362.badge.error { 363 background: var(--error-bg); 364 color: var(--error-text); 365} 366 367.badge.accent { 368 background: var(--accent); 369 color: var(--text-inverse); 370} 371 372.card { 373 background: var(--bg-card); 374 border: 1px solid var(--border-color); 375 border-radius: var(--radius-xl); 376 padding: var(--space-6); 377 overflow: hidden; 378 min-width: 0; 379} 380 381.section { 382 background: var(--bg-secondary); 383 border-radius: var(--radius-xl); 384 padding: var(--space-6); 385 overflow: hidden; 386 min-width: 0; 387} 388 389.section + .section { 390 margin-top: var(--space-6); 391} 392 393.page { 394 max-width: var(--width-lg); 395 margin: 0 auto; 396 padding: var(--space-7); 397} 398 399.page-sm { 400 max-width: var(--width-md); 401 margin: 0 auto; 402 padding: var(--space-7); 403} 404 405.page-lg { 406 max-width: var(--width-xl); 407 margin: 0 auto; 408 padding: var(--space-7); 409} 410 411.page-header { 412 margin-bottom: var(--space-6); 413} 414 415.page-header h1 { 416 margin: 0 0 var(--space-3) 0; 417} 418 419.page-header .subtitle { 420 color: var(--text-secondary); 421 margin: 0; 422} 423 424.loading { 425 display: flex; 426 flex-direction: column; 427 align-items: center; 428 gap: var(--space-4); 429 padding: var(--space-8); 430} 431 432.loading p { 433 color: var(--text-secondary); 434 margin: 0; 435} 436 437.back-link { 438 display: inline-block; 439 color: var(--text-secondary); 440 font-size: var(--text-sm); 441 margin-bottom: var(--space-3); 442 text-decoration: none; 443} 444 445.back-link:hover { 446 color: var(--accent); 447 text-decoration: none; 448} 449 450.text-muted { 451 color: var(--text-muted); 452} 453 454.text-secondary { 455 color: var(--text-secondary); 456} 457 458.text-sm { 459 font-size: var(--text-sm); 460} 461 462.text-xs { 463 font-size: var(--text-xs); 464} 465 466.text-center { 467 text-align: center; 468} 469 470.mono { 471 font-family: var(--font-mono); 472} 473 474.mt-4 { 475 margin-top: var(--space-4); 476} 477.mt-5 { 478 margin-top: var(--space-5); 479} 480.mt-6 { 481 margin-top: var(--space-6); 482} 483.mb-4 { 484 margin-bottom: var(--space-4); 485} 486.mb-5 { 487 margin-bottom: var(--space-5); 488} 489.mb-6 { 490 margin-bottom: var(--space-6); 491} 492 493.split-layout { 494 display: grid; 495 grid-template-columns: 1fr; 496 gap: var(--space-6); 497} 498 499@media (min-width: 800px) { 500 .split-layout { 501 grid-template-columns: 1fr 1fr; 502 align-items: start; 503 } 504 .split-layout.sidebar-right { 505 grid-template-columns: 1.5fr 1fr; 506 } 507 .split-layout.sidebar-left { 508 grid-template-columns: 1fr 1.5fr; 509 } 510} 511 512.split-layout > * { 513 min-width: 0; 514} 515 516.form-row { 517 display: grid; 518 grid-template-columns: 1fr; 519 gap: var(--space-4); 520} 521 522@media (min-width: 600px) { 523 .form-row { 524 grid-template-columns: repeat(2, 1fr); 525 } 526 .form-row.thirds { 527 grid-template-columns: repeat(3, 1fr); 528 } 529} 530 531.full-width { 532 grid-column: 1 / -1; 533} 534 535.info-panel { 536 background: var(--bg-secondary); 537 border-radius: var(--radius-xl); 538 padding: var(--space-6); 539 height: fit-content; 540 overflow: hidden; 541 min-width: 0; 542} 543 544.info-panel h3 { 545 margin: 0 0 var(--space-3) 0; 546 font-size: var(--text-base); 547 font-weight: var(--font-semibold); 548} 549 550.info-panel p { 551 margin: 0 0 var(--space-4) 0; 552 font-size: var(--text-sm); 553 color: var(--text-secondary); 554} 555 556.info-panel p:last-child { 557 margin-bottom: 0; 558} 559 560.spinner { 561 width: 40px; 562 height: 40px; 563 border: 3px solid var(--border-color); 564 border-top-color: var(--accent); 565 border-radius: 50%; 566 animation: spin 1s linear infinite; 567} 568 569.spinner.sm { 570 width: 20px; 571 height: 20px; 572 border-width: 2px; 573} 574 575.spinner.md { 576 width: 32px; 577 height: 32px; 578} 579 580.spinner.lg { 581 width: 60px; 582 height: 60px; 583 border-width: 4px; 584} 585 586@keyframes spin { 587 to { 588 transform: rotate(360deg); 589 } 590} 591 592.skeleton { 593 background: var(--bg-secondary); 594 border-radius: var(--radius-md); 595 animation: skeleton-pulse 1.5s ease-in-out infinite; 596} 597 598.skeleton-card { 599 height: 100px; 600 background: var(--bg-secondary); 601 border: 1px solid var(--border-color); 602 border-radius: var(--radius-xl); 603 animation: skeleton-pulse 1.5s ease-in-out infinite; 604} 605 606.skeleton-line { 607 height: var(--space-4); 608 background: var(--bg-secondary); 609 border-radius: var(--radius-sm); 610 animation: skeleton-pulse 1.5s ease-in-out infinite; 611} 612 613@keyframes skeleton-pulse { 614 0%, 100% { 615 opacity: 1; 616 } 617 50% { 618 opacity: 0.5; 619 } 620} 621 622.section-hint { 623 font-size: var(--text-sm); 624 color: var(--text-secondary); 625 margin: 0 0 var(--space-5) 0; 626} 627 628.radio-group { 629 display: flex; 630 flex-direction: column; 631 gap: var(--space-4); 632} 633 634.radio-label { 635 display: flex; 636 align-items: flex-start; 637 gap: var(--space-3); 638 cursor: pointer; 639 font-size: var(--text-base); 640 font-weight: var(--font-normal); 641 margin-bottom: 0; 642} 643 644.radio-label input[type="radio"] { 645 margin-top: var(--space-1); 646 width: auto; 647} 648 649.radio-content { 650 display: flex; 651 flex-direction: column; 652 gap: var(--space-1); 653} 654 655.radio-hint { 656 font-size: var(--text-xs); 657 color: var(--text-secondary); 658} 659 660.radio-label.disabled { 661 opacity: 0.5; 662 cursor: not-allowed; 663} 664 665.radio-hint.disabled-hint { 666 color: var(--warning-text); 667} 668 669.warning-box { 670 margin-top: var(--space-5); 671 padding: var(--space-5); 672 background: var(--warning-bg); 673 border: 1px solid var(--warning-border); 674 border-radius: var(--radius-lg); 675 font-size: var(--text-sm); 676} 677 678.warning-box strong { 679 display: block; 680 margin-bottom: var(--space-3); 681 color: var(--warning-text); 682} 683 684.warning-box ul { 685 margin: var(--space-4) 0 0 0; 686 padding-left: var(--space-5); 687} 688 689.warning-box li { 690 margin-bottom: var(--space-3); 691 line-height: var(--leading-normal); 692} 693 694.warning-box li:last-child { 695 margin-bottom: 0; 696} 697 698.migrate-callout { 699 display: flex; 700 gap: var(--space-4); 701 padding: var(--space-5); 702 background: var(--accent-muted); 703 border: 1px solid var(--accent); 704 border-radius: var(--radius-xl); 705 margin-bottom: var(--space-6); 706} 707 708.migrate-icon { 709 font-size: var(--text-2xl); 710 line-height: 1; 711 color: var(--accent); 712} 713 714.migrate-content { 715 flex: 1; 716} 717 718.migrate-content strong { 719 display: block; 720 color: var(--text-primary); 721 margin-bottom: var(--space-2); 722} 723 724.migrate-content p { 725 margin: 0 0 var(--space-3) 0; 726 font-size: var(--text-sm); 727 color: var(--text-secondary); 728 line-height: var(--leading-relaxed); 729} 730 731.migrate-link { 732 font-size: var(--text-sm); 733 font-weight: var(--font-medium); 734 color: var(--accent); 735 text-decoration: none; 736} 737 738.migrate-link:hover { 739 text-decoration: underline; 740} 741 742.app-password-step { 743 display: flex; 744 flex-direction: column; 745 gap: var(--space-5); 746 max-width: var(--width-md); 747 margin: 0 auto; 748} 749 750.app-password-step .warning-box { 751 margin-top: 0; 752} 753 754.app-password-step .warning-box p { 755 margin: 0; 756 color: var(--warning-text); 757} 758 759.app-password-display { 760 background: var(--bg-card); 761 border: 2px solid var(--accent); 762 border-radius: var(--radius-xl); 763 padding: var(--space-6); 764 text-align: center; 765} 766 767.app-password-label { 768 font-size: var(--text-sm); 769 color: var(--text-secondary); 770 margin-bottom: var(--space-4); 771} 772 773.app-password-code { 774 display: block; 775 font-size: var(--text-xl); 776 font-family: var(--font-mono); 777 letter-spacing: 0.1em; 778 padding: var(--space-5); 779 background: var(--bg-input); 780 border-radius: var(--radius-md); 781 margin-bottom: var(--space-4); 782 user-select: all; 783} 784 785.copy-btn { 786 padding: var(--space-3) var(--space-5); 787 font-size: var(--text-sm); 788} 789 790.checkbox-label { 791 display: flex; 792 align-items: center; 793 gap: var(--space-3); 794 cursor: pointer; 795 font-weight: var(--font-normal); 796} 797 798.checkbox-label input[type="checkbox"] { 799 width: auto; 800 padding: 0; 801} 802 803.form-section { 804 min-width: 0; 805} 806 807.form-links { 808 margin-top: var(--space-6); 809} 810 811.form-links .link-text { 812 text-align: center; 813 color: var(--text-secondary); 814} 815 816.form-links .link-text a { 817 color: var(--accent); 818} 819 820.contact-fields { 821 display: flex; 822 flex-direction: column; 823 gap: var(--space-4); 824} 825 826.contact-fields .field { 827 margin-bottom: 0; 828} 829 830.provider-badge { 831 display: flex; 832 align-items: center; 833 gap: var(--space-3); 834 padding: var(--space-4); 835 background: var(--bg-secondary); 836 border-radius: var(--radius-md); 837} 838 839.provider-details { 840 display: flex; 841 flex-direction: column; 842} 843 844.provider-name { 845 font-weight: var(--font-semibold); 846} 847 848.provider-username { 849 font-size: var(--text-sm); 850 color: var(--text-secondary); 851} 852 853.error-container { 854 text-align: center; 855 padding: var(--space-8); 856} 857 858.error-icon { 859 width: 48px; 860 height: 48px; 861 border-radius: 50%; 862 background: var(--error-text); 863 color: var(--text-inverse); 864 display: flex; 865 align-items: center; 866 justify-content: center; 867 font-size: var(--text-xl); 868 font-weight: var(--font-bold); 869 margin: 0 auto var(--space-4); 870} 871 872.error-container h2 { 873 margin-bottom: var(--space-2); 874} 875 876.error-container p { 877 color: var(--text-secondary); 878 margin-bottom: var(--space-6); 879} 880 881.info-list { 882 margin: 0; 883 padding-left: var(--space-5); 884} 885 886.info-list li { 887 margin-bottom: var(--space-2); 888 font-size: var(--text-sm); 889 color: var(--text-secondary); 890 line-height: var(--leading-relaxed); 891} 892 893.info-list li:last-child { 894 margin-bottom: 0; 895} 896 897.required { 898 color: var(--error-text); 899}