1// Auth Enhancer - Apex Theme 2// Enhances authentication pages (login, register, password reset, 2fa, verify) 3// with a beautiful centered card design and improved styling 4 5(function () { 6 "use strict"; 7 8 // Translation helper - reads from window.APEX_LANG.auth 9 function _lang(key, fallback) { 10 var T = (window.APEX_LANG && window.APEX_LANG.auth) || {}; 11 return T[key] !== undefined ? T[key] : fallback; 12 } 13 14 // Execute immediately, don't wait for DOMContentLoaded 15 function initAuthEnhancer() { 16 // Only run on authentication pages 17 const path = window.location.pathname.replace(/\/+$/, ""); 18 const authFormSelector = 19 'form[action*="/user/login"], form[action*="/user/register"], form[action*="/user/password"], form[action*="/two-factor"], form[action*="/email/verify"]'; 20 const hasAuthForm = !!document.querySelector(authFormSelector); 21 const isAuthPage = 22 path.includes("user/login") || 23 path.includes("user/register") || 24 path.includes("user/password") || 25 path.includes("two-factor") || 26 path.includes("email/verify") || 27 hasAuthForm; 28 29 if (!isAuthPage) { 30 console.log("[Auth Enhancer] Not an auth page, skipping"); 31 return; 32 } 33 34 console.log("[Auth Enhancer] Auth page detected:", path); 35 36 // Inject styles immediately 37 injectStyles(); 38 39 // Wait for DOM to be ready 40 if (document.readyState === "loading") { 41 document.addEventListener("DOMContentLoaded", transformPage); 42 } else { 43 transformPage(); 44 } 45 46 // Re-run once the DOM has fully settled to re-assert the layout/title 47 setTimeout(transformPage, 180); 48 setTimeout(transformPage, 450); 49 } 50 51 function injectStyles() { 52 if (document.getElementById("auth-enhancer-styles")) return; 53 54 const style = document.createElement("style"); 55 style.id = "auth-enhancer-styles"; 56 style.textContent = ` 57 /* ============================================ 58 AUTH ENHANCER - Beautiful Login/Register Cards 59 ============================================ */ 60 61 /* Hide profile component zone and sidebar on auth pages */ 62 .page-content.auth-enhanced .apex-editable-zone[data-zone-id="global.profile"], 63 .page-content.auth-enhanced .apex-editable-zone[data-zone-id="home.sidebar-left"], 64 .page-content.auth-enhanced .col-md-7-5, 65 .page-content.auth-enhanced .col-md-4-5 { 66 display: none !important; 67 } 68 69 /* Hide all h1 titles outside the card - more specific selectors */ 70 .page-content.auth-enhanced > .row > .col-md-7-5 h1, 71 .page-content.auth-enhanced > .row > [class*="col-"] > h1, 72 .page-content.auth-enhanced .col-md-9 > h1, 73 .page-content.auth-enhanced .col-lg-6 > h1, 74 .page-content.auth-enhanced h1.no-remove, 75 .page-content.auth-enhanced h1:not(.auth-title) { 76 display: none !important; 77 } 78 79 /* Forced title wrapper that we ensure stays visible */ 80 .auth-forced-title { 81 display: block !important; 82 visibility: visible !important; 83 padding: 0 1rem 1.25rem; 84 width: 100%; 85 max-width: 520px; 86 margin: 0 auto; 87 text-align: center; 88 position: relative; 89 z-index: 3; 90 } 91 92 .auth-forced-title h1 { 93 display: block !important; 94 visibility: visible !important; 95 margin: 0; 96 font-family: var(--font-heading, 'Lexend'), sans-serif; 97 font-weight: 800; 98 font-size: 1.65rem; 99 color: var(--color2, #fff); 100 text-shadow: 0 2px 10px rgba(0, 0, 0, 0.35); 101 } 102 103 .auth-forced-title p { 104 display: block !important; 105 visibility: visible !important; 106 margin: 0.35rem 0 0; 107 color: rgba(var(--color2-rgb, 255, 255, 255), 0.65); 108 font-size: 0.9rem; 109 } 110 111 /* Override page-content layout for auth pages */ 112 .page-content.auth-enhanced { 113 display: flex !important; 114 align-items: center !important; 115 justify-content: center !important; 116 min-height: calc(100vh - 120px) !important; 117 padding: 2rem 1rem !important; 118 } 119 120 .page-content.auth-enhanced > .row { 121 display: flex !important; 122 justify-content: center !important; 123 width: 100% !important; 124 max-width: 100% !important; 125 margin: 0 !important; 126 } 127 128 /* Override column widths for auth pages */ 129 .page-content.auth-enhanced > .row > .col-md-9, 130 .page-content.auth-enhanced > .row > .col-lg-6, 131 .page-content.auth-enhanced > .row > [class*="col-md-9"], 132 .page-content.auth-enhanced > .row > [class*="col-lg-6"], 133 .page-content.auth-enhanced .auth-column { 134 flex: 0 0 auto !important; 135 width: 100% !important; 136 max-width: 500px !important; 137 padding: 0 1rem !important; 138 } 139
140 /* Remove unused auth-page-wrapper styles */ 141 142 /* Auth Card Container */ 143 .auth-card-wrapper { 144 width: 100%; 145 } 146 147 /* Auth Card Styling */ 148 .auth-enhanced-card { 149 position: relative; 150 background: linear-gradient(145deg, 151 rgba(var(--color3-rgb, 30, 30, 45), 0.95) 0%, 152 rgba(var(--color4-rgb, 20, 20, 35), 0.98) 100%) !important; 153 border-radius: 20px !important; 154 box-shadow: 155 0 25px 50px rgba(0, 0, 0, 0.4), 156 0 0 0 1px rgba(255, 255, 255, 0.08), 157 inset 0 1px 0 rgba(255, 255, 255, 0.1) !important; 158 overflow: hidden; 159 backdrop-filter: blur(20px); 160 -webkit-backdrop-filter: blur(20px); 161 border: none !important; 162 } 163 164 /* Gradient accent top border */ 165 .auth-enhanced-card::before { 166 content: ''; 167 position: absolute; 168 top: 0; 169 left: 0; 170 right: 0; 171 height: 4px; 172 background: linear-gradient(90deg, 173 var(--color5, #7c4dfd) 0%, 174 var(--color6, #a855f7) 50%, 175 var(--color5, #7c4dfd) 100%); 176 background-size: 200% 100%; 177 animation: auth-gradient-shift 4s ease-in-out infinite; 178 border-radius: 20px 20px 0 0; 179 z-index: 2; 180 } 181 182 @keyframes auth-gradient-shift { 183 0%, 100% { background-position: 0% 50%; } 184 50% { background-position: 100% 50%; } 185 } 186 187 /* Decorative glow effect */ 188 .auth-enhanced-card::after { 189 content: ''; 190 position: absolute; 191 top: -50%; 192 right: -50%; 193 width: 100%; 194 height: 100%; 195 background: radial-gradient( 196 circle at center, 197 rgba(var(--color5-rgb, 124, 77, 253), 0.08) 0%, 198 transparent 60% 199 ); 200 pointer-events: none; 201 z-index: 0; 202 } 203 204 /* Card Header with Title */ 205 .auth-card-header { 206 position: relative; 207 z-index: 1; 208 padding: 1.75rem 1.75rem 0 1.75rem; 209 text-align: center; 210 } 211 212 .auth-card-header .auth-icon { 213 width: 56px; 214 height: 56px; 215 background: linear-gradient(135deg, 216 var(--color5, #7c4dfd) 0%, 217 var(--color6, #a855f7) 100%); 218 border-radius: 50%; 219 display: flex; 220 align-items: center; 221 justify-content: center; 222 margin: 0 auto 1rem; 223 box-shadow: 224 0 10px 30px rgba(var(--color5-rgb, 124, 77, 253), 0.35), 225 0 0 0 4px rgba(255, 255, 255, 0.1); 226 animation: auth-icon-pulse 3s ease-in-out infinite; 227 } 228 229 @keyframes auth-icon-pulse { 230 0%, 100% { 231 transform: scale(1); 232 box-shadow: 233 0 10px 30px rgba(var(--color5-rgb, 124, 77, 253), 0.35), 234 0 0 0 4px rgba(255, 255, 255, 0.1); 235 } 236 50% { 237 transform: scale(1.02); 238 box-shadow: 239 0 15px 40px rgba(var(--color5-rgb, 124, 77, 253), 0.45), 240 0 0 0 6px rgba(255, 255, 255, 0.12); 241 } 242 } 243 244 .auth-card-header .auth-icon i { 245 font-size: 1.5rem; 246 color: white; 247 } 248 249 .auth-card-header .auth-title { 250 font-family: var(--font-heading, 'Lexend'), sans-serif; 251 font-weight: 700; 252 font-size: 1.5rem; 253 color: var(--color2, #fff); 254 margin-bottom: 0.35rem; 255 text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); 256 display: block !important; 257 } 258 259 .auth-card-header .auth-subtitle { 260 color: rgba(var(--color2-rgb, 255, 255, 255), 0.6); 261 font-size: 0.85rem; 262 margin-bottom: 0; 263 } 264 265 /* Card Body */ 266 .auth-enhanced-card .card-body { 267 position: relative; 268 z-index: 1; 269 padding: 2.15rem 2.25rem 2.4rem !important; 270 } 271 272 /* Form Styling */ 273 .auth-enhanced-card .form-label { 274 font-weight: 600; 275 font-size: 0.9rem; 276 color: var(--color2, #fff); 277 margin-bottom: 0.5rem; 278 text-transform: uppercase; 279 letter-spacing: 0.5px; 280 opacity: 0.9; 281 } 282 283 .auth-enhanced-card .form-control { 284 background: rgba(255, 255, 255, 0.05) !important; 285 border: 2px solid rgba(255, 255, 255, 0.1) !important; 286 border-radius: 12px !important; 287 padding: 0.85rem 1.1rem !important; 288 color: var(--color2, #fff) !important; 289 font-size: 1rem; 290 transition: all 0.3s ease; 291 } 292 293 .auth-enhanced-card .form-control::placeholder { 294 color: rgba(255, 255, 255, 0.35); 295 } 296 297 .auth-enhanced-card .form-control:focus { 298 background: rgba(255, 255, 255, 0.08) !important; 299 border-color: var(--color5, #7c4dfd) !important; 300 box-shadow: 301 0 0 0 4px rgba(var(--color5-rgb, 124, 77, 253), 0.15), 302 0 4px 20px rgba(var(--color5-rgb, 124, 77, 253), 0.2) !important; 303 outline: none; 304 } 305 306 .auth-enhanced-card .form-control.is-invalid { 307 border-color: #dc3545 !important; 308 box-shadow: 0 0 0 4px rgba(220, 53, 69, 0.15) !important; 309 } 310 311 /* Checkbox styling */ 312 .auth-enhanced-card .form-check-input { 313 width: 1.25rem; 314 height: 1.25rem; 315 border-radius: 6px; 316 background-color: rgba(255, 255, 255, 0.05); 317 border: 2px solid rgba(255, 255, 255, 0.2); 318 transition: all 0.2s ease; 319 margin-top: 0.15rem; 320 } 321 322 .auth-enhanced-card .form-check-input:checked { 323 background-color: var(--color5, #7c4dfd); 324 border-color: var(--color5, #7c4dfd); 325 background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e"); 326 background-position: center; 327 background-size: contain; 328 background-repeat: no-repeat; 329 } 330 331 .auth-enhanced-card .form-check-label { 332 font-size: 0.95rem; 333 color: rgba(255, 255, 255, 0.85); 334 margin-left: 0.5rem; 335 } 336 color: rgba(var(--color2-rgb, 255, 255, 255), 0.8); 337 font-size: 0.95rem; 338 } 339 340 /* Links styling */ 341 .auth-enhanced-card a { 342 color: var(--color5, #7c4dfd); 343 font-weight: 600; 344 transition: all 0.2s ease; 345 } 346 347 .auth-enhanced-card a:hover { 348 color: var(--color6, #a855f7); 349 text-decoration: none; 350 } 351 352 /* Button styling */ 353 .auth-enhanced-card .btn-primary { 354 background: linear-gradient(135deg, 355 var(--color5, #7c4dfd) 0%, 356 var(--color6, #a855f7) 100%) !important; 357 border: none !important; 358 border-radius: 12px !important; 359 padding: 0.9rem 2rem !important; 360 font-weight: 700; 361 font-size: 1rem; 362 text-transform: uppercase; 363 letter-spacing: 1px; 364 transition: all 0.3s ease; 365 box-shadow: 366 0 8px 25px rgba(var(--color5-rgb, 124, 77, 253), 0.35), 367 inset 0 1px 0 rgba(255, 255, 255, 0.2) !important; 368 position: relative; 369 overflow: hidden; 370 } 371 372 .auth-enhanced-card .btn-primary::before { 373 content: ''; 374 position: absolute; 375 top: 0; 376 left: -100%; 377 width: 100%; 378 height: 100%; 379 background: linear-gradient( 380 90deg, 381 transparent, 382 rgba(255, 255, 255, 0.2), 383 transparent 384 ); 385 transition: left 0.5s ease; 386 } 387 388 .auth-enhanced-card .btn-primary:hover { 389 transform: translateY(-3px); 390 box-shadow: 391 0 12px 35px rgba(var(--color5-rgb, 124, 77, 253), 0.45), 392 inset 0 1px 0 rgba(255, 255, 255, 0.25) !important; 393 } 394 395 .auth-enhanced-card .btn-primary:hover::before { 396 left: 100%; 397 } 398 399 .auth-enhanced-card .btn-primary:active { 400 transform: translateY(-1px); 401 } 402 403 /* Social login buttons */ 404 .auth-enhanced-card .btn-secondary, 405 .auth-enhanced-card .btn-outline-secondary { 406 background: rgba(255, 255, 255, 0.05); 407 border: 2px solid rgba(255, 255, 255, 0.15); 408 border-radius: 12px; 409 color: var(--color2, #fff); 410 transition: all 0.3s ease; 411 } 412 413 .auth-enhanced-card .btn-secondary:hover, 414 .auth-enhanced-card .btn-outline-secondary:hover { 415 background: rgba(255, 255, 255, 0.1); 416 border-color: rgba(255, 255, 255, 0.25); 417 transform: translateY(-2px); 418 } 419 420 /* Divider styling */ 421 .auth-enhanced-card hr { 422 border-color: rgba(255, 255, 255, 0.1); 423 margin: 1.5rem 0; 424 } 425 426 /* Invalid feedback */ 427 .auth-enhanced-card .invalid-feedback { 428 font-size: 0.85rem; 429 margin-top: 0.5rem; 430 } 431 432 /* Register link at bottom */ 433 .auth-card-footer { 434 position: relative; 435 z-index: 1; 436 text-align: center; 437 padding: 0 1.75rem 1.5rem; 438 color: rgba(var(--color2-rgb, 255, 255, 255), 0.6); 439 font-size: 0.875rem; 440 } 441 442 .auth-card-footer a { 443 color: var(--color5, #7c4dfd); 444 font-weight: 600; 445 } 446 447 /* Captcha section styling */ 448 .auth-enhanced-card .g-recaptcha, 449 .auth-enhanced-card [data-captcha], 450 .auth-enhanced-card .h-captcha { 451 display: flex; 452 justify-content: center; 453 margin: 1rem 0; 454 } 455 456 /* Mobile Responsive */ 457 @media (max-width: 576px) { 458 .page-content.auth-enhanced { 459 padding: 1rem 0 !important; 460 } 461 462 .page-content.auth-enhanced .auth-column { 463 padding: 0 !important; 464 } 465 466 .auth-page-wrapper { 467 max-width: 100%; 468 padding: 0 0.5rem; 469 } 470 471 .auth-card-header { 472 padding: 2rem 1.5rem 0 1.5rem; 473 } 474 475 .auth-card-header .auth-icon { 476 width: 60px; 477 height: 60px; 478 } 479
480 .auth-card-header .auth-icon i { 481 font-size: 1.5rem; 482 } 483 484 .auth-card-header .auth-title { 485 font-size: 1.5rem; 486 } 487 488 .auth-enhanced-card .card-body { 489 padding: 1.5rem !important; 490 } 491 492 .auth-card-footer { 493 padding: 0 1.5rem 1.5rem; 494 } 495 496 .auth-enhanced-card .btn-primary { 497 padding: 0.8rem 1.5rem !important; 498 font-size: 0.95rem; 499 } 500 } 501 502 .auth-provider-btn, 503 .auth-discord-btn { 504 display: flex; 505 align-items: center; 506 justify-content: center; 507 gap: 0.75rem; 508 width: 100%; 509 padding: 0.95rem 1.25rem; 510 border: none !important; 511 border-radius: 12px !important; 512 font-weight: 800; 513 font-size: 0.95rem; 514 text-transform: uppercase; 515 letter-spacing: 0.5px; 516 text-decoration: none !important; 517 transition: all 0.3s ease; 518 } 519 520 .auth-provider-grid { 521 display: grid; 522 grid-template-columns: 1fr; 523 gap: 0.75rem; 524 margin-bottom: 0.75rem; 525 } 526 527 .auth-provider-btn { 528 color: white !important; 529 box-shadow: 0 8px 25px rgba(0, 0, 0, 0.18); 530 } 531 532 .auth-provider-google { 533 background: #fff !important; 534 color: #3c4043 !important; 535 border: 1.5px solid #e0e0e0 !important; 536 box-shadow: 0 2px 8px rgba(60,64,67,0.08); 537 font-weight: 600; 538 } 539 .auth-provider-google .auth-provider-icon { 540 background: transparent; 541 } 542 .auth-provider-google:hover { 543 box-shadow: 0 4px 16px rgba(60,64,67,0.12); 544 filter: none; 545 } 546 547 .auth-provider-yandex { 548 background: linear-gradient(135deg, #fc3f1d 0%, #ef2a0f 100%) !important; 549 box-shadow: 0 8px 25px rgba(252, 63, 29, 0.35); 550 } 551 552 .auth-provider-btn:hover { 553 transform: translateY(-2px); 554 filter: brightness(1.05); 555 } 556 557 .auth-provider-google:hover { 558 box-shadow: 0 12px 35px rgba(66, 133, 244, 0.45); 559 } 560 561 .auth-provider-yandex:hover { 562 box-shadow: 0 12px 35px rgba(252, 63, 29, 0.45); 563 } 564 565 .auth-provider-icon { 566 display: inline-flex; 567 align-items: center; 568 justify-content: center; 569 width: 26px; 570 height: 26px; 571 border-radius: 0; 572 flex: 0 0 26px; 573 font-weight: 800; 574 line-height: 1; 575 background: transparent; 576 border: none; 577 box-shadow: none; 578 } 579 580 .auth-provider-icon svg { 581 display: block; 582 width: 100%; 583 height: 100%; 584 } 585 586 .auth-discord-btn { 587 background: #5865F2 !important; 588 color: white !important; 589 box-shadow: 0 8px 25px rgba(88, 101, 242, 0.35); 590 margin-bottom: 1rem; 591 } 592 593 .auth-discord-btn:hover { 594 background: #4752C4 !important; 595 transform: translateY(-2px); 596 box-shadow: 0 12px 35px rgba(88, 101, 242, 0.45); 597 } 598 599 .auth-discord-btn svg { 600 width: 22px; 601 height: 22px; 602 } 603 604 .auth-divider { 605 display: flex; 606 align-items: center; 607 margin: 1.25rem 0; 608 color: rgba(var(--color2-rgb, 255, 255, 255), 0.5); 609 font-size: 0.85rem; 610 text-transform: uppercase; 611 letter-spacing: 1px; 612 } 613 614 .auth-divider::before, 615 .auth-divider::after { 616 content: ''; 617 flex: 1; 618 height: 1px; 619 background: rgba(255, 255, 255, 0.15); 620 } 621 622 .auth-divider::before { 623 margin-right: 1rem; 624 } 625 626 .auth-divider::after { 627 margin-left: 1rem; 628 } 629 630 /* Animation on load */ 631 @keyframes auth-card-appear { 632 0% { 633 opacity: 0; 634 transform: translateY(30px) scale(0.95); 635 } 636 100% { 637 opacity: 1; 638 transform: translateY(0) scale(1); 639 } 640 } 641 642 .auth-enhanced-card { 643 animation: auth-card-appear 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards; 644 } 645 646 /* Floating particles background effect */ 647 .auth-particles { 648 position: fixed; 649 top: 0; 650 left: 0; 651 width: 100%; 652 height: 100%; 653 pointer-events: none; 654 z-index: 0; 655 overflow: hidden; 656 } 657 658 .auth-particle { 659 position: absolute; 660 width: 6px; 661 height: 6px; 662 background: var(--color5, #7c4dfd); 663 border-radius: 50%; 664 opacity: 0.3;
665 animation: auth-particle-float 15s infinite; 666 } 667 668 @keyframes auth-particle-float { 669 0%, 100% { 670 transform: translateY(100vh) rotate(0deg); 671 opacity: 0; 672 } 673 10% { 674 opacity: 0.3; 675 } 676 90% { 677 opacity: 0.3; 678 } 679 100% { 680 transform: translateY(-100vh) rotate(720deg); 681 opacity: 0; 682 } 683 } 684 `; 685 document.head.appendChild(style); 686 console.log("[Auth Enhancer] Styles injected"); 687 } 688 689 function removeDisabledSocialAuth(root) { 690 var selectors = []; 691 var authConfig = window.APEX_AUTH_CONFIG || {}; 692 693 if (!authConfig.googleAuthEnabled) { 694 selectors.push( 695 '.auth-provider-google, a[href*="/google-auth"], a[href*="google-auth"]' 696 ); 697 } 698 699 if (!authConfig.discordAuthEnabled) { 700 selectors.push( 701 '.auth-discord-btn, a[href*="/discord-auth"], a[href*="discord-auth"], a[href*="/discord"]' 702 ); 703 } 704 705 if (selectors.length === 0) { 706 return; 707 } 708 709 (root || document).querySelectorAll(selectors.join(", ")).forEac
709h(function (element) { 710 element.remove(); 711 }); 712 } 713 714 function transformPage() { 715 console.log("[Auth Enhancer] Transforming page..."); 716 removeDisabledSocialAuth(document); 717 718 // Add class to page-content for auth styling 719 const pageContent = document.querySelector(".page-content"); 720 if (pageContent) { 721 pageContent.classList.add("auth-enhanced"); 722 console.log("[Auth Enhancer] Added auth-enhanced class"); 723 } 724 725 // Find the card element - look for the one containing the auth form 726 const authFormSelectors = [ 727 'form[action*="/user/login"]', 728 'form[action*="/user/register"]', 729 'form[action*="/user/password"]', 730 'form[action*="/two-factor"]', 731 'form[action*="/email/verify"]', 732 "form#captcha-form", 733 ]; 734 735 let card = null; 736 for (const selector of authFormSelectors) { 737 const form = document.querySelector(selector); 738 if (form) { 739 card = form.closest(".card"); 740 if (card) break; 741 } 742 } 743 744 // Fallback: looking for card in main layout columns 745 if (!card) { 746 card = document.querySelector(".col-md-9 .card, .col-lg-6 .card"); 747 } 748 749 // Fallback: exclude known widgets if picking generic card 750 if (!card) { 751 const allCards = document.querySelectorAll(".card"); 752 for (const c of allCards) { 753 if ( 754 !c.closest(".apex-editable-zone") && 755 !c.id.includes("component") 756 ) { 757 card = c; 758 break; 759 } 760 } 761 } 762 763 if (!card) { 764 console.warn("[Auth Enhancer] No auth card found"); 765 return; 766 } 767 768 console.log("[Auth Enhancer] Card found"); 769 770 // Hide ALL h1 elements that are not our auth-title 771 document.querySelectorAll("h1").forEach((h1) => { 772 if (!h1.classList.contains("auth-title")) { 773 h1.style.cssText = 774 "display: none !important; visibility: hidden !important;"; 775 } 776 }); 777 778 // Determine title based on URL 779 const path = window.location.pathname; 780 let titleText = _lang("login_title", "Login"); 781 let iconClass = "bi-box-arrow-in-right"; 782 let subtitle = _lang("login_subtitle", "Log in to access your account"); 783 784 if (path.includes("user/register")) { 785 titleText = _lang("register_title", "Register"); 786 iconClass = "bi-person-plus"; 787 subtitle = _lang( 788 "register_subtitle", 789 "Create your account to get started", 790 ); 791 } else if (path.includes("user/password")) { 792 titleText = _lang("password_title", "Password"); 793 iconClass = "bi-key"; 794 subtitle = _lang("password_subtitle", "Reset your password"); 795 } else if (path.includes("two-factor")) { 796 titleText = _lang("2fa_title", "2FA Verification"); 797 iconClass = "bi-shield-lock"; 798 subtitle = _lang("2fa_subtitle", "Two-factor verification"); 799 } else if (path.includes("verify")) { 800 titleText = _lang("verify_title", "Verification"); 801 iconClass = "bi-envelope-check"; 802 subtitle = _lang("verify_subtitle", "Verify your email address"); 803 } 804 805 // Add enhanced class to card 806 card.classList.add("auth-enhanced-card"); 807 removeDisabledSocialAuth(card); 808 809 /* Forced title removed as per user request */ 810 811 // Only add header if not already present 812 if (!card.querySelector(".auth-card-header")) { 813 const cardHeader = document.createElement("div"); 814 cardHeader.className = "auth-card-header"; 815 cardHeader.innerHTML = ` 816 <div class="auth-icon"> 817 <i class="bi ${iconClass}"></i> 818 </div> 819 <h1 class="auth-title" style="display: block !important; visibility: visible !important;">${titleText}</h1> 820 <p class="auth-subtitle">${subtitle}</p> 821 `; 822 card.insertBefore(cardHeader, card.firstChild); 823 console.log("[Auth Enhancer] Header added with title:", titleText); 824 } 825 826 // Add social auth buttons on login/register pages 827 var authConfig = window.APEX_AUTH_CONFIG || {}; 828 if ( 829 (path.includes("user/login") || path.includes("user/register")) && 830 !card.querySelector(".auth-social-section") 831 ) { 832 var cardBody = card.querySelector(".card-body"); 833 if (cardBody) { 834 var providerButtons = []; 835 836 // Render the installed OAuth entry points directly. Some 837 // Azuriom auth plugins are not exposed through the theme's 838 // plugin manager, which previously hid valid buttons. 839 var googleAuthUrl = authConfig.googleAuthUrl || "/google-auth"; 840 var yandexAuthUrl = authConfig.yandexAuthUrl || "/yandex-auth"; 841 842 if (authConfig.googleAuthEnabled && googleAuthUrl) { 843 providerButtons.push( 844 '<a href="' + 845 googleAuthUrl + 846 '" class="auth-provider-btn auth-provider-google">' + 847 '<span class="auth-provider-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 10v4.2h5.8c-.2 1.1-1.1 2.4-2.4 3.3l-.1.1 3.1 3.1c1.8-1.7 2.8-4.2 2.8-7.1 0-.7-.1-1.4-.3-2.1H12z" fill="#4285F4"/><path d="M5.2 14.4A6.9 6.9 0 0 1 5 12c0-1 .2-2 .6-2.9l.1-.2L2.5 5.8A11.9 11.9 0 0 0 1 12c0 1.9.4 3.6 1.2 5.2l3-2.8z" fill="#EA4335"/><path d="M12 22c2.9 0 5.4-.9 7.2-2.6l-3.4-2.9c-.9.6-2.1.9-3.8.9-2.9 0-5.4-1.9-6.2-4.6l-3 2.9A11.9 11.9 0 0 0 12 22z" fill="#34A853"/><path d="M18.2 4.4A11.7 11.7 0 0 0 12 1a11.9 11.9 0 0 0-10.8 6.8l3.1 2.4c.8-2.7 3.3-4.6 6.2-4.6 1.4 0 2.6.4 3.6 1.1l2.9-2.9z" fill="#FBBC05"/></svg></span>' + 848 _lang("google_login_button", "ÐойÑи ÑеÑез Google") + 849 "</a>", 850 ); 851 } 852 853 if (yandexAuthUrl) { 854 providerButtons.push( 855 '<a href="' + 856 yandexAuthUrl + 857 '" class="auth-provider-btn auth-provider-yandex">' + 858 '<span class="auth-provider-icon"><svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2"><path d="M455.999 6h-400C28.388 6 6 28.387 6 56v399.999c0 27.612 22.388 50 50 50h400c27.612 0 50-22.388 50-50v-400c0-27.612-22.388-50-50-50z" fill="#fc3f1d" fill-rule="nonzero"/><path d="M283.718 362.624v53.781h-55.062v-90.687L124.75 99.75h57.456l80.95 176.78c15.606 33.782 20.562 45.52 20.562 86.094zM387.249 99.75l-67.55 153.093h-55.981L331.262 99.75h55.987z" fill="#fff" fill-rule="nonzero"/></svg></span>' + 859 _lang("yandex_login_button", "ÐойÑи ÑеÑез ЯндекÑ") + 860 "</a>", 861 ); 862 } 863 864 if (providerButtons.length > 0 || authConfig.discordAuthEnabled) { 865 var socialSection = document.createElement("div"); 866 socialSection.className = "auth-social-section"; 867 socialSection.innerHTML = 868 (providerButtons.length > 0 869 ? '<div class="auth-provider-grid">' + 870 providerButtons.join("") + 871 "</div>" 872 : "") + 873 (authConfig.discordAuthEnabled 874 ? '<a href="' + 875 authConfig.discordAuthUrl + 876 '" class="auth-discord-btn">' + 877 '<svg viewBox="0 0 24 24" fill="white"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18
8771.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/></svg>' + 878 _lang("discord_login_button", "ÐойÑи ÑеÑез Discord") + 879 "</a>" 880 : "") + 881 '<div class="auth-divider">' + 882 _lang("or", "or") + 883 "</div>"; 884 cardBody.insertBefore(socialSection, cardBody.firstChild); 885 removeDisabledSocialAuth(socialSection); 886 } 887 } 888 } 889 890 // Add footer links (register link only if route exists) 891 if (!card.querySelector(".auth-card-footer")) { 892 if (path.includes("user/login") && authConfig.registerRouteExists) { 893 const footer = document.createElement("div"); 894 footer.className = "auth-card-footer"; 895 footer.innerHTML = 896 "<span>" + 897 _lang("no_account", "Don't have an account?") + 898 '</span> <a href="/user/register">' + 899 _lang("sign_up", "Sign up") + 900 "</a>"; 901 card.appendChild(footer); 902 } else if (path.includes("user/register")) { 903 const footer = document.createElement("div"); 904 footer.className = "auth-card-footer"; 905 footer.innerHTML = 906 "<span>" + 907 _lang("already_account", "Already have an account?") + 908 '</span> <a href="/user/login">' + 909 _lang("sign_in", "Log in") + 910 "</a>"; 911 card.appendChild(footer); 912 } 913 } 914 915 // Mark column for CSS 916 const col = card.closest('[class*="col-"]'); 917 if (col) { 918 col.classList.add("auth-column"); 919 } 920 921 // Add particles 922 if (!document.querySelector(".auth-particles")) { 923 const particles = document.createElement("div"); 924 particles.className = "auth-particles"; 925 for (let i = 0; i < 15; i++) { 926 const p = document.createElement("div"); 927 p.className = "auth-particle"; 928 p.style.left = `${Math.random() * 100}%`; 929 p.style.animationDelay = `${Math.random() * 15}s`; 930 p.style.animationDuration = `${15 + Math.random() * 10}s`; 931 const size = 4 + Math.random() * 4; 932 p.style.width = `${size}px`; 933 p.style.height = `${size}px`; 934 particles.appendChild(p); 935 } 936 document.body.appendChild(particles); 937 } 938 939 console.log("[Auth Enhancer] Transformation complete"); 940 } 941 942 // Initialize 943 initAuthEnhancer(); 944})(); 945
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.