Microservice to bring 2FA to self hosted PDSes
0

Configure Feed

Select the types of activity you want to include in your feed.

1:root, 2:root.light-mode { 3 --brand-color: rgb(16, 131, 254); 4 --primary-color: rgb(7, 10, 13); 5 --secondary-color: rgb(66, 86, 108); 6 --bg-primary-color: rgb(255, 255, 255); 7 --bg-secondary-color: rgb(240, 242, 245); 8 --border-color: rgb(220, 225, 230); 9 --danger-color: rgb(220, 38, 38); 10 --success-color: rgb(22, 163, 74); 11 --warning-color: rgb(234, 179, 8); 12 --table-stripe: rgba(0, 0, 0, 0.02); 13} 14 15@media (prefers-color-scheme: dark) { 16 :root { 17 --brand-color: rgb(16, 131, 254); 18 --primary-color: rgb(255, 255, 255); 19 --secondary-color: rgb(133, 152, 173); 20 --bg-primary-color: rgb(7, 10, 13); 21 --bg-secondary-color: rgb(13, 18, 23); 22 --border-color: rgb(40, 45, 55); 23 --table-stripe: rgba(255, 255, 255, 0.02); 24 } 25} 26 27:root.dark-mode { 28 --brand-color: rgb(16, 131, 254); 29 --primary-color: rgb(255, 255, 255); 30 --secondary-color: rgb(133, 152, 173); 31 --bg-primary-color: rgb(7, 10, 13); 32 --bg-secondary-color: rgb(13, 18, 23); 33 --border-color: rgb(40, 45, 55); 34 --table-stripe: rgba(255, 255, 255, 0.02); 35} 36 37/* --- Reset & Base ------------------------------------------- */ 38 39* { 40 margin: 0; 41 padding: 0; 42 box-sizing: border-box; 43} 44 45body { 46 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; 47 background: var(--bg-secondary-color); 48 color: var(--primary-color); 49 text-rendering: optimizeLegibility; 50 -webkit-font-smoothing: antialiased; 51} 52 53/* --- Layout: Sidebar + Main --------------------------------- */ 54 55.layout { 56 display: flex; 57 min-height: 100vh; 58} 59 60.sidebar { 61 width: 220px; 62 background: var(--bg-primary-color); 63 border-right: 1px solid var(--border-color); 64 padding: 20px 0; 65 position: fixed; 66 top: 0; 67 left: 0; 68 bottom: 0; 69 overflow-y: auto; 70 display: flex; 71 flex-direction: column; 72} 73 74.sidebar-title { 75 font-size: 0.8125rem; 76 font-weight: 700; 77 padding: 0 20px; 78 margin-bottom: 4px; 79 white-space: nowrap; 80 overflow: hidden; 81 text-overflow: ellipsis; 82} 83 84.sidebar-subtitle { 85 font-size: 0.6875rem; 86 color: var(--secondary-color); 87 padding: 0 20px; 88 margin-bottom: 20px; 89} 90 91.sidebar nav { 92 flex: 1; 93} 94 95.sidebar nav a { 96 display: block; 97 padding: 8px 20px; 98 font-size: 0.8125rem; 99 color: var(--secondary-color); 100 text-decoration: none; 101 transition: background 0.1s, color 0.1s; 102} 103 104.sidebar nav a:hover { 105 background: var(--bg-secondary-color); 106 color: var(--primary-color); 107} 108 109.sidebar nav a.active { 110 color: var(--brand-color); 111 font-weight: 500; 112} 113 114.sidebar-footer { 115 padding: 16px 20px 0; 116 border-top: 1px solid var(--border-color); 117 margin-top: 16px; 118} 119 120.sidebar-footer .session-info { 121 font-size: 0.75rem; 122 color: var(--secondary-color); 123 margin-bottom: 8px; 124} 125 126.sidebar-footer form { 127 display: inline; 128} 129 130.sidebar-footer button { 131 background: none; 132 border: none; 133 font-size: 0.75rem; 134 color: var(--secondary-color); 135 cursor: pointer; 136 padding: 0; 137 text-decoration: underline; 138} 139 140.sidebar-footer button:hover { 141 color: var(--primary-color); 142} 143 144.main { 145 margin-left: 220px; 146 flex: 1; 147 padding: 32px; 148 max-width: 960px; 149} 150 151/* --- Common Components -------------------------------------- */ 152 153.page-title { 154 font-size: 1.5rem; 155 font-weight: 700; 156 margin-bottom: 24px; 157} 158 159.page-subtitle { 160 font-size: 0.8125rem; 161 color: var(--secondary-color); 162 font-family: 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace; 163 margin-top: -20px; 164 margin-bottom: 24px; 165 word-break: break-all; 166} 167 168.page-description { 169 font-size: 0.875rem; 170 color: var(--secondary-color); 171 margin-top: -16px; 172 margin-bottom: 24px; 173} 174 175.flash-success { 176 background: rgba(22, 163, 74, 0.1); 177 color: var(--success-color); 178 border: 1px solid rgba(22, 163, 74, 0.2); 179 border-radius: 8px; 180 padding: 10px 14px; 181 font-size: 0.875rem; 182 margin-bottom: 20px; 183} 184 185.flash-error { 186 background: rgba(220, 38, 38, 0.1); 187 color: var(--danger-color); 188 border: 1px solid rgba(220, 38, 38, 0.2); 189 border-radius: 8px; 190 padding: 10px 14px; 191 font-size: 0.875rem; 192 margin-bottom: 20px; 193} 194 195/* --- Buttons ------------------------------------------------ */ 196 197.btn { 198 display: inline-flex; 199 align-items: center; 200 justify-content: center; 201 padding: 10px 20px; 202 font-size: 0.875rem; 203 font-weight: 500; 204 border: none; 205 border-radius: 8px; 206 cursor: pointer; 207 transition: opacity 0.15s; 208 text-decoration: none; 209} 210 211.btn:hover { 212 opacity: 0.85; 213} 214 215.btn-primary { 216 background: var(--brand-color); 217 color: #fff; 218} 219 220.btn-danger { 221 background: var(--danger-color); 222 color: #fff; 223 border-color: var(--danger-color); 224} 225 226.btn-warning { 227 background: var(--warning-color); 228 color: #000; 229 border-color: var(--warning-color); 230} 231 232.btn-small { 233 padding: 6px 12px; 234 font-size: 0.75rem; 235} 236 237.btn-outline-danger { 238 background: transparent; 239 color: var(--danger-color); 240 border: 1px solid var(--danger-color); 241} 242 243/* --- Detail Sections ---------------------------------------- */ 244 245.detail-section { 246 background: var(--bg-primary-color); 247 border: 1px solid var(--border-color); 248 border-radius: 10px; 249 padding: 20px; 250 margin-bottom: 16px; 251} 252 253.detail-section h3 { 254 font-size: 0.875rem; 255 font-weight: 600; 256 margin-bottom: 12px; 257} 258 259.detail-row { 260 display: flex; 261 justify-content: space-between; 262 align-items: center; 263 padding: 8px 0; 264 font-size: 0.8125rem; 265 border-bottom: 1px solid var(--border-color); 266} 267 268.detail-row:last-child { 269 border-bottom: none; 270} 271 272.detail-row .label { 273 color: var(--secondary-color); 274 flex-shrink: 0; 275} 276 277.detail-row .value { 278 font-weight: 500; 279 word-break: break-all; 280 text-align: right; 281 max-width: 65%; 282} 283 284.detail-row .value a { 285 color: var(--brand-color); 286 text-decoration: none; 287} 288 289.detail-row .value a:hover { 290 text-decoration: underline; 291} 292 293/* --- Tables ------------------------------------------------- */ 294 295.table-container { 296 background: var(--bg-primary-color); 297 border: 1px solid var(--border-color); 298 border-radius: 10px; 299 overflow: hidden; 300} 301 302table { 303 width: 100%; 304 border-collapse: collapse; 305} 306 307thead th { 308 text-align: left; 309 padding: 12px 16px; 310 font-size: 0.75rem; 311 font-weight: 600; 312 color: var(--secondary-color); 313 text-transform: uppercase; 314 letter-spacing: 0.5px; 315 border-bottom: 1px solid var(--border-color); 316} 317 318tbody tr { 319 border-bottom: 1px solid var(--border-color); 320} 321 322tbody tr:last-child { 323 border-bottom: none; 324} 325 326tbody tr:nth-child(even) { 327 background: var(--table-stripe); 328} 329 330tbody td { 331 padding: 10px 16px; 332 font-size: 0.8125rem; 333} 334 335tbody td a { 336 color: var(--brand-color); 337 text-decoration: none; 338} 339 340tbody td a:hover { 341 text-decoration: underline; 342} 343 344/* --- Badges ------------------------------------------------- */ 345 346.badge { 347 display: inline-block; 348 padding: 2px 8px; 349 border-radius: 4px; 350 font-size: 0.75rem; 351 font-weight: 500; 352} 353 354.badge-success { 355 background: rgba(22, 163, 74, 0.1); 356 color: var(--success-color); 357} 358 359.badge-danger { 360 background: rgba(220, 38, 38, 0.1); 361 color: var(--danger-color); 362} 363 364.badge-warning { 365 background: rgba(234, 179, 8, 0.1); 366 color: var(--warning-color); 367} 368 369/* --- Forms -------------------------------------------------- */ 370 371.form-card { 372 background: var(--bg-primary-color); 373 border: 1px solid var(--border-color); 374 border-radius: 10px; 375 padding: 24px; 376 max-width: 480px; 377} 378 379.form-group { 380 margin-bottom: 16px; 381} 382 383.form-group label { 384 display: block; 385 font-size: 0.8125rem; 386 font-weight: 500; 387 margin-bottom: 6px; 388 color: var(--primary-color); 389} 390 391.form-group input { 392 width: 100%; 393 padding: 10px 12px; 394 font-size: 0.875rem; 395 border: 1px solid var(--border-color); 396 border-radius: 8px; 397 background: var(--bg-primary-color); 398 color: var(--primary-color); 399 outline: none; 400 transition: border-color 0.15s; 401} 402 403.form-group input:focus { 404 border-color: var(--brand-color); 405} 406 407.form-group .hint { 408 font-size: 0.75rem; 409 color: var(--secondary-color); 410 margin-top: 4px; 411} 412 413.search-form { 414 display: flex; 415 gap: 8px; 416 margin-bottom: 24px; 417} 418 419.search-form input { 420 flex: 1; 421 padding: 10px 12px; 422 font-size: 0.875rem; 423 border: 1px solid var(--border-color); 424 border-radius: 8px; 425 background: var(--bg-primary-color); 426 color: var(--primary-color); 427 outline: none; 428} 429 430.search-form input:focus { 431 border-color: var(--brand-color); 432} 433 434.create-form { 435 display: flex; 436 gap: 8px; 437 align-items: flex-end; 438 margin-bottom: 24px; 439} 440 441.create-form .form-group { 442 display: flex; 443 flex-direction: column; 444 gap: 4px; 445} 446 447.create-form label { 448 font-size: 0.75rem; 449 font-weight: 500; 450 color: var(--secondary-color); 451} 452 453.create-form input[type="number"] { 454 padding: 10px 12px; 455 font-size: 0.875rem; 456 border: 1px solid var(--border-color); 457 border-radius: 8px; 458 background: var(--bg-primary-color); 459 color: var(--primary-color); 460 outline: none; 461 width: 120px; 462} 463 464.create-form input[type="number"]:focus { 465 border-color: var(--brand-color); 466} 467 468/* --- Utility ------------------------------------------------ */ 469 470.mono-text { 471 font-family: 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace; 472 font-size: 0.75rem; 473} 474 475.inline-form { 476 display: inline; 477} 478 479.empty-state { 480 text-align: center; 481 padding: 40px 20px; 482 color: var(--secondary-color); 483 font-size: 0.875rem; 484} 485 486.load-more { 487 text-align: center; 488 padding: 16px; 489} 490 491.load-more a { 492 color: var(--brand-color); 493 text-decoration: none; 494 font-size: 0.875rem; 495 font-weight: 500; 496} 497 498.load-more a:hover { 499 text-decoration: underline; 500} 501 502/* --- Dashboard: Cards --------------------------------------- */ 503 504.cards { 505 display: grid; 506 grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); 507 gap: 16px; 508 margin-bottom: 32px; 509} 510 511.card { 512 background: var(--bg-primary-color); 513 border: 1px solid var(--border-color); 514 border-radius: 10px; 515 padding: 20px; 516} 517 518.card-label { 519 font-size: 0.75rem; 520 font-weight: 500; 521 color: var(--secondary-color); 522 text-transform: uppercase; 523 letter-spacing: 0.5px; 524 margin-bottom: 6px; 525} 526 527.card-value { 528 font-size: 1.25rem; 529 font-weight: 600; 530} 531 532.card-value.success { 533 color: var(--success-color); 534} 535 536.card-value.danger { 537 color: var(--danger-color); 538} 539 540/* --- Accounts: DID Cell ------------------------------------- */ 541 542.did-cell { 543 font-family: 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace; 544 font-size: 0.75rem; 545 color: var(--secondary-color); 546} 547 548/* --- Account Detail ----------------------------------------- */ 549 550.actions { 551 display: flex; 552 flex-wrap: wrap; 553 gap: 8px; 554 margin-top: 8px; 555} 556 557.actions form { 558 display: inline; 559} 560 561.actions .btn { 562 padding: 8px 16px; 563 font-size: 0.8125rem; 564 border: 1px solid var(--border-color); 565 background: var(--bg-primary-color); 566 color: var(--primary-color); 567} 568 569.actions .btn-primary { 570 background: var(--brand-color); 571 color: #fff; 572 border-color: var(--brand-color); 573} 574 575.actions .btn-danger { 576 background: var(--danger-color); 577 color: #fff; 578 border-color: var(--danger-color); 579} 580 581.actions .btn-warning { 582 background: var(--warning-color); 583 color: #000; 584 border-color: var(--warning-color); 585} 586 587.password-box { 588 background: rgba(22, 163, 74, 0.08); 589 border: 1px solid rgba(22, 163, 74, 0.2); 590 border-radius: 10px; 591 padding: 16px 20px; 592 margin-bottom: 16px; 593} 594 595.password-box .pw-label { 596 font-size: 0.75rem; 597 font-weight: 600; 598 color: var(--success-color); 599 margin-bottom: 6px; 600} 601 602.password-box .pw-value { 603 font-family: 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace; 604 font-size: 1rem; 605 font-weight: 600; 606 user-select: all; 607} 608 609.back-link { 610 display: inline-block; 611 color: var(--brand-color); 612 text-decoration: none; 613 font-size: 0.8125rem; 614 margin-bottom: 16px; 615} 616 617.back-link:hover { 618 text-decoration: underline; 619} 620 621.collection-list { 622 max-height: 200px; 623 overflow-y: auto; 624 padding: 8px 0; 625} 626 627.collection-item { 628 font-family: 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace; 629 font-size: 0.75rem; 630 padding: 4px 0; 631 color: var(--secondary-color); 632 border-bottom: 1px solid var(--border-color); 633} 634 635.collection-item:last-child { 636 border-bottom: none; 637} 638 639.threat-sig { 640 font-family: 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace; 641 font-size: 0.75rem; 642 padding: 4px 0; 643 color: var(--secondary-color); 644} 645 646/* --- Create Account ----------------------------------------- */ 647 648.success-card { 649 background: var(--bg-primary-color); 650 border: 1px solid var(--border-color); 651 border-radius: 10px; 652 padding: 24px; 653 max-width: 480px; 654} 655 656.success-card h3 { 657 font-size: 1rem; 658 font-weight: 600; 659 color: var(--success-color); 660 margin-bottom: 16px; 661} 662 663.success-card .detail-row .value { 664 display: flex; 665 align-items: center; 666 gap: 6px; 667} 668 669.password-highlight { 670 font-family: 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace; 671 background: rgba(22, 163, 74, 0.08); 672 padding: 2px 6px; 673 border-radius: 4px; 674 user-select: all; 675} 676 677.copy-btn { 678 background: none; 679 border: 1px solid var(--border-color); 680 border-radius: 4px; 681 padding: 2px 6px; 682 font-size: 0.6875rem; 683 cursor: pointer; 684 color: var(--secondary-color); 685 transition: color 0.15s, border-color 0.15s; 686 white-space: nowrap; 687} 688 689.copy-btn:hover { 690 color: var(--primary-color); 691 border-color: var(--primary-color); 692} 693 694/* --- Invite Codes ------------------------------------------- */ 695 696.code-box { 697 background: rgba(22, 163, 74, 0.08); 698 border: 1px solid rgba(22, 163, 74, 0.2); 699 border-radius: 10px; 700 padding: 16px 20px; 701 margin-bottom: 24px; 702} 703 704.code-box .code-label { 705 font-size: 0.75rem; 706 font-weight: 600; 707 color: var(--success-color); 708 margin-bottom: 6px; 709} 710 711.code-box .code-value { 712 font-family: 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace; 713 font-size: 1rem; 714 font-weight: 600; 715 user-select: all; 716} 717 718.code-cell { 719 font-family: 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace; 720 font-size: 0.75rem; 721} 722 723/* --- Login Page --------------------------------------------- */ 724 725.login-card { 726 background: var(--bg-primary-color); 727 border: 1px solid var(--border-color); 728 border-radius: 12px; 729 padding: 40px; 730 width: 100%; 731 max-width: 400px; 732 margin: 20px; 733} 734 735.login-title { 736 font-size: 1.5rem; 737 font-weight: 700; 738 text-align: center; 739 margin-bottom: 4px; 740} 741 742.login-subtitle { 743 font-size: 0.875rem; 744 color: var(--secondary-color); 745 text-align: center; 746 margin-bottom: 32px; 747} 748 749.login-card .form-group { 750 margin-bottom: 20px; 751} 752 753.login-card .form-group label { 754 font-size: 0.875rem; 755} 756 757.login-card .btn-primary { 758 width: 100%; 759} 760 761.error-msg { 762 background: rgba(220, 38, 38, 0.1); 763 color: var(--danger-color); 764 border: 1px solid rgba(220, 38, 38, 0.2); 765 border-radius: 8px; 766 padding: 10px 14px; 767 font-size: 0.875rem; 768 margin-bottom: 20px; 769} 770 771/* --- Error Page ---------------------------------------------- */ 772 773.centered { 774 display: flex; 775 align-items: center; 776 justify-content: center; 777 min-height: 100vh; 778} 779 780.error-card { 781 background: var(--bg-primary-color); 782 border: 1px solid var(--border-color); 783 border-radius: 12px; 784 padding: 40px; 785 text-align: center; 786 max-width: 480px; 787 width: 100%; 788 margin: 20px; 789} 790 791.error-card--inset { 792 margin: 60px auto; 793} 794 795.error-icon { 796 font-size: 2.5rem; 797 margin-bottom: 16px; 798 color: var(--danger-color); 799} 800 801.error-title { 802 font-size: 1.25rem; 803 font-weight: 700; 804 margin-bottom: 8px; 805} 806 807.error-message { 808 font-size: 0.875rem; 809 color: var(--secondary-color); 810 margin-bottom: 24px; 811 line-height: 1.5; 812} 813 814.error-link { 815 display: inline-flex; 816 align-items: center; 817 justify-content: center; 818 padding: 10px 20px; 819 font-size: 0.875rem; 820 font-weight: 500; 821 border: none; 822 border-radius: 8px; 823 cursor: pointer; 824 text-decoration: none; 825 background: var(--brand-color); 826 color: #fff; 827 transition: opacity 0.15s; 828} 829 830.error-link:hover { 831 opacity: 0.85; 832} 833 834/* --- Responsive --------------------------------------------- */ 835 836@media (max-width: 768px) { 837 .sidebar { 838 display: none; 839 } 840 841 .main { 842 margin-left: 0; 843 } 844}