1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta name="color-scheme" content="dark"> 7 <title>Products - LonexLabs</title> 8 <meta name="description" content="Browse our collection of professional FiveM server tools. CAD systems, Discord bots, and more."> 9 10 <!-- SEO Meta Tags --> 11 <meta name="keywords" content="FiveM, server tools, CAD system, Discord integration, roleplay, staff management, server management"> 12 <meta name="author" content="LonexLabs"> 13 <meta name="robots" content="index, follow"> 14 <link rel="canonical" href="https://lonexlabs.com/products"> 15 16 <!-- Open Graph / Facebook --> 17 <meta property="og:type" content="website"> 18 <meta property="og:url" content="https://lonexlabs.com/products"> 19 <meta property="og:title" content="Products - LonexLabs"> 20 <meta property="og:description" content="Browse our collection of professional FiveM server tools. CAD systems, Discord bots, and more."> 21 <meta property="og:image" content="https://lonexlabs.com/og-image.png"> 22 <meta property="og:image:width" content="1200"> 23 <meta property="og:image:height" content="630"> 24 <meta property="og:site_name" content="LonexLabs"> 25 <meta property="og:locale" content="en_US"> 26 27 <!-- Twitter Card --> 28 <meta name="twitter:card" content="summary_large_image"> 29 <meta name="twitter:url" content="https://lonexlabs.com/products"> 30 <meta name="twitter:title" content="Products - LonexLabs"> 31 <meta name="twitter:description" content="Browse our collection of professional FiveM server tools. CAD systems, Discord bots, and more."> 32 <meta name="twitter:image" content="https://lonexlabs.com/og-image.png"> 33 34 <!-- Theme Color --> 35 <meta name="theme-color" content="#29cd96"> 36 <meta name="msapplication-TileColor" content="#0a0a0b"> 37 38 <link rel="icon" type="image/png" href="/public/favicon.png"> 39 <link rel="preconnect" href="https://fonts.googleapis.com"> 40 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 41 <link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,[email protected],400..800&family=Geist:wght@500;600;700&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet"> 42 <link rel="stylesheet" href="/public/assets/store.css?v=1790773669"> 43 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> 44 <style> 45 /* Native UI (select popups, scrollbars, pickers) follows the document. */ 46 :root { color-scheme: dark; } 47 48 /* Dropdowns â the same control the portal and admin use. */ 49 select { 50 appearance: none; 51 -webkit-appearance: none; 52 color-scheme: dark; 53 cursor: pointer; 54 min-height: 40px; 55 padding: 9px 36px 9px 13px; 56 font: inherit; 57 font-size: 15px; 58 color: var(--lx-text, #eef0f2); 59 background-color: var(--lx-bg, #0a0b0d); 60 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%237d858e' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); 61 background-repeat: no-repeat; 62 background-position: right 12px center; 63 background-size: 14px 14px; 64 border: 1px solid var(--lx-line-2, rgba(255,255,255,.12)); 65 border-radius: 10px; 66 outline: none; 67 transition: border-color .15s; 68 } 69 select:hover, select:focus { border-color: var(--lx-line-3, rgba(255,255,255,.2)); } 70 option, optgroup { background-color: var(--lx-bg-2, #14171b); color: var(--lx-text, #eef0f2); } 71 /* Pages that style their own fields do it through a class, which outranks 72 a bare element rule; :not([hidden]) lifts this one past them so the 73 arrow survives. */ 74 body select:not([hidden]) { 75 appearance: none; 76 -webkit-appearance: none; 77 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%237d858e' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); 78 background-repeat: no-repeat; 79 background-position: right 13px center; 80 background-size: 14px 14px; 81 padding-right: 38px; 82 } 83 84 85 *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } 86 87 /* The store pages that have not been ported yet are written against 88 these names. Pointing them at the design system's tokens brings them 89 onto the same palette and gives them its corners. */ 90 :root { 91 --bg: var(--lx-bg); 92 --bg-elevated: var(--lx-bg-2); 93 --bg-card: var(--lx-bg-1); 94 --bg-card-hover: var(--lx-bg-2); 95 --border: var(--lx-line); 96 --border-light: var(--lx-line-2); 97 --text: var(--lx-text); 98 --text-dim: var(--lx-text-2); 99 --text-faint: var(--lx-text-3); 100 --accent: var(--lx-accent); 101 --accent-dim: var(--lx-accent-hi); 102 --accent-glow: rgba(41, 205, 150, 0.15); 103 --accent-soft: var(--lx-accent-soft); 104 --error: var(--lx-red); 105 --warning: var(--lx-amber); 106 --radius: var(--lx-r); 107 --radius-sm: var(--lx-r-sm); 108 --radius-lg: var(--lx-r-lg); 109 --shadow: 0 4px 24px rgba(0,0,0,0.4); 110 --shadow-lg: 0 8px 48px rgba(0,0,0,0.5); 111 } 112 113 html { scroll-behavior: smooth; } 114 115 body { 116 font-family: 'Plus Jakarta Sans', -apple-system, sans-serif; 117 background: var(--bg); 118 color: var(--text); 119 line-height: 1.6; 120 min-height: 100vh; 121 -webkit-font-smoothing: antialiased; 122 } 123 124 a { color: inherit; text-decoration: none; } 125 svg { stroke-linecap: round; stroke-linejoin: round; } 126 button, input, select, textarea { font-family: inherit; } 127 128 /* Header */ 129 .header { 130 position: fixed; 131 top: 0; 132 left: 0; 133 right: 0; 134 z-index: 100; 135 background: rgba(10, 10, 11, 0.8); 136 backdrop-filter: blur(20px); 137 border-bottom: 1px solid var(--border); 138 } 139 140 .header-inner { 141 max-width: 1360px; 142 margin: 0 auto; 143 padding: 0 24px; 144 height: 72px; 145 display: flex; 146 align-items: center; 147 justify-content: space-between; 148 } 149 150 .logo { 151 display: flex; 152 align-items: center; 153 gap: 2px; 154 } 155 156 .logo img { 157 height: 36px; 158 width: auto; 159 } 160 161 .logo-accent { color: var(--accent); } 162 163 .nav { display: flex; align-items: center; gap: 8px; } 164 165 .nav-link { 166 display: inline-flex; 167 align-items: center; 168 gap: 6px; 169 padding: 10px 18px; 170 font-size: 14px; 171 font-weight: 500; 172 color: var(--text-dim); 173 border-radius: var(--radius-sm); 174 transition: all 0.2s; 175 } 176 177 .nav-link svg { 178 flex-shrink: 0; 179 } 180 181 .nav-link:hover { color: var(--text); background: var(--bg-card); } 182 .nav-link.active { color: var(--accent); } 183 184 .nav-cta { 185 background: var(--accent); 186 color: var(--bg); 187 font-weight: 600; 188 margin-left: 8px; 189 } 190 191 .nav-cta:hover { background: var(--accent-dim); color: var(--bg); } 192 193 /* Cart */ 194 .nav-cart { 195 position: relative; 196 padding: 10px 14px !important; 197 } 198 199 .cart-badge { 200 position: absolute; 201 top: 4px; 202 right: 4px; 203 min-width: 18px; 204 height: 18px; 205 padding: 0 5px; 206 background: var(--accent); 207 color: var(--bg); 208 font-size: 11px; 209 font-weight: 700; 210 border-radius:0; 211 display: flex; 212 align-items: center; 213 justify-content: center; 214 } 215 216 /* Main */ 217 main { padding-top: 72px; } 218 219 .container { 220 max-width: 1360px; 221 margin: 0 auto; 222 padding: 0 24px; 223 } 224 225 /* Buttons */ 226 .btn { 227 display: inline-flex; 228 align-items: center; 229 justify-content: center; 230 gap: 8px; 231 padding: 12px 24px; 232 font-size: 14px; 233 font-weight: 600; 234 font-family: inherit; 235 border-radius: var(--radius-sm); 236 border: none; 237 cursor: pointer; 238 transition: all 0.2s; 239 } 240 241 .btn-primary { 242 background: var(--accent); 243 color: var(--bg); 244 } 245 246 .btn-primary:hover { 247 background: var(--accent-dim); 248 transform: translateY(-1px); 249 box-shadow: 0 4px 20px var(--accent-glow); 250 } 251 252 .btn-secondary { 253 background: var(--bg-card); 254 color: var(--text); 255 border: 1px solid var(--border); 256 } 257 258 .btn-secondary:hover { 259 background: var(--bg-card-hover); 260 border-color: var(--border-light); 261 } 262 263 .btn-github { 264 background: #ffffff; 265 color: #24292f; 266 border: 1px solid rgba(255, 255, 255, 0.2); 267 display: inline-flex; 268 align-items: center; 269 justify-content: center; 270 gap: 10px; 271 font-weight: 600; 272 } 273 274 .btn-github:hover { 275 background: #f6f8fa; 276 transform: translateY(-1px); 277 box-shadow: 0 4px 20px rgba(255, 255, 255, 0.15); 278 } 279 280 .btn-github svg { 281 fill: #24292f; 282 } 283 284 /* Tebex â third-party vendor button (mirrors .btn-github). 285 The light wordmark is official artwork: scaled only, never recoloured. */ 286 .btn-tebex { 287 background: #12141c; 288 color: #ffffff; 289 border: 1px solid rgba(255, 255, 255, 0.22); 290 display: inline-flex; 291 align-items: center; 292 justify-content: center; 293 gap: 10px; 294 font-weight: 600; 295 } 296 297 .btn-tebex:hover {
298 background: #1b1e29; 299 border-color: rgba(255, 255, 255, 0.4); 300 transform: translateY(-1px); 301 box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4); 302 } 303 304 .tebex-mark { 305 height: 30px; 306 width: auto; 307 display: block; 308 flex-shrink: 0; 309 } 310 311 .btn-lg { 312 padding: 16px 32px; 313 font-size: 16px; 314 border-radius: var(--radius); 315 } 316 317 .btn-sm { 318 padding: 8px 16px; 319 font-size: 13px; 320 } 321 322 /* Cards */ 323 .card { 324 background: var(--bg-card); 325 border: 1px solid var(--border); 326 border-radius: var(--radius-lg); 327 overflow: hidden; 328 transition: all 0.3s; 329 } 330 331 .card:hover { 332 border-color: var(--border-light); 333 transform: translateY(-2px); 334 box-shadow: var(--shadow); 335 } 336 337 /* Section */ 338 .section { 339 padding: 80px 0; 340 } 341 342 .section-header { 343 text-align: center; 344 margin-bottom: 48px; 345 } 346 347 .section-label { 348 display: inline-block; 349 padding: 6px 14px; 350 background: var(--accent-soft); 351 color: var(--accent); 352 font-size: 12px; 353 font-weight: 600; 354 text-transform: uppercase; 355 letter-spacing: 1px; 356 border-radius:0; 357 margin-bottom: 16px; 358 } 359 360 .section-title { 361 font-size: 40px; 362 font-weight: 800; 363 letter-spacing: -1px; 364 margin-bottom: 16px; 365 } 366 367 .section-subtitle { 368 font-size: 18px; 369 color: var(--text-dim); 370 max-width: 600px; 371 margin: 0 auto; 372 } 373 374 /* Footer */ 375 .footer { 376 padding: 48px 0; 377 border-top: 1px solid var(--border); 378 background: var(--bg-elevated); 379 } 380 381 .footer-inner { 382 display: flex; 383 justify-content: space-between; 384 align-items: center; 385 flex-wrap: wrap; 386 gap: 24px; 387 } 388 389 .footer-text { 390 font-size: 14px; 391 color: var(--text-dim); 392 } 393 394 .footer-links { 395 display: flex; 396 gap: 24px; 397 } 398 399 .footer-link { 400 font-size: 14px; 401 color: var(--text-dim); 402 transition: color 0.2s; 403 } 404 405 .footer-link:hover { color: var(--accent); } 406 407 /* Utilities */ 408 .text-accent { color: var(--accent); } 409 .text-dim { color: var(--text-dim); } 410 .text-center { text-align: center; } 411 .mt-4 { margin-top: 16px; } 412 .mt-8 { margin-top: 32px; } 413 .mb-4 { margin-bottom: 16px; } 414 .mb-8 { margin-bottom: 32px; } 415 416 /* Alerts */ 417 .alert { 418 padding: 16px 20px; 419 border-radius: var(--radius-sm); 420 margin-bottom: 24px; 421 font-size: 14px; 422 } 423 424 .alert-success { 425 background: rgba(41, 205, 150, 0.1); 426 border: 1px solid var(--accent); 427 color: var(--accent); 428 } 429 430 .alert-error { 431 background: rgba(239, 68, 68, 0.1); 432 border: 1px solid var(--error); 433 color: var(--error); 434 } 435 436 /* Mobile Menu Toggle */ 437 .mobile-toggle { display: none; padding: 8px; background: none; border: none; color: var(--text); cursor: pointer; position: relative; width: 40px; height: 40px; border-radius: var(--radius-sm); transition: background 0.2s; } 438 .mobile-toggle:hover { background: var(--bg-card); } 439 .mobile-toggle span { display: block; width: 20px; height: 2px; background: var(--text); position: absolute; left: 10px; transition: all 0.3s ease; border-radius:0; } 440 .mobile-toggle span:nth-child(1) { top: 12px; } 441 .mobile-toggle span:nth-child(2) { top: 19px; } 442 .mobile-toggle span:nth-child(3) { top: 26px; } 443 .mobile-toggle.open span:nth-child(1) { top: 19px; transform: rotate(45deg); } 444 .mobile-toggle.open span:nth-child(2) { opacity: 0; } 445 .mobile-toggle.open span:nth-child(3) { top: 19px; transform: rotate(-45deg); } 446 447 .mobile-nav { 448 display: none; 449 position: fixed; 450 top: 72px; 451 left: 0; 452 right: 0; 453 bottom: 0; 454 background: var(--bg); 455 z-index: 99; 456 flex-direction: column; 457 padding: 16px; 458 gap: 4px; 459 overflow-y: auto; 460 border-top: 1px solid var(--border); 461 } 462 .mobile-nav.open { display: flex; } 463 .mobile-nav .nav-link { 464 display: flex; 465 width: 100%; 466 padding: 14px 18px; 467 border-radius: var(--radius-sm); 468 font-size: 15px; 469 color: var(--text-dim); 470 } 471 .mobile-nav .nav-link:hover { background: var(--bg-card); color: var(--text); } 472 .mobile-nav .nav-link.active { color: var(--accent); } 473 .mobile-nav .nav-cta { margin-top: 8px; justify-content: center; background: var(--accent); color: var(--bg); font-weight: 600; } 474 .mobile-nav .nav-cta:hover { background: var(--accent-dim); color: var(--bg); } 475 476 /* Responsive */ 477 @media (max-width: 768px) { 478 .mobile-toggle { display: block; } 479 .header-inner { padding: 0 16px; } 480 .container { padding: 0 16px; } 481 .section { padding: 48px 0; } 482 .section-title { font-size: 28px; } 483 .nav { display: none; } 484 .footer-inner { flex-direction: column; text-align: center; } 485 } 486 487 /* Page-specific styles injected here */ 488 /* Hero */ 489.page-hero { 490 padding: 60px 0 34px; 491 border-bottom: 1px solid var(--border); 492 background: var(--bg); 493} 494 495.hero-crumbs { 496 display: flex; 497 align-items: center; 498 gap: 8px; 499 font-size: 13px; 500 color: var(--text-faint); 501 margin-bottom: 18px; 502} 503.hero-crumbs a { color: var(--text-dim); transition: color 0.15s; } 504.hero-crumbs a:hover { color: var(--accent); } 505.hero-crumbs span { opacity: 0.5; } 506 507.page-head { 508 display: flex; 509 align-items: flex-end; 510 justify-content: space-between; 511 gap: 24px; 512 flex-wrap: wrap; 513} 514 515.page-title { 516 font-size: 44px; 517 font-weight: 800; 518 letter-spacing: -1.6px; 519 line-height: 1.04; 520 margin-bottom: 14px; 521} 522 523.page-subtitle { 524 font-size: 17px; 525 color: var(--text-dim); 526 max-width: 580px; 527} 528 529@media (max-width: 560px) { .page-title { font-size: 32px; } } 530 531/* Products Layout */ 532.products-section { 533 padding: 40px 0 100px; 534} 535 536.products-layout { 537 display: grid; 538 grid-template-columns: 260px 1fr; 539 gap: 40px; 540 align-items: start; 541} 542 543/* Sidebar */ 544.sidebar { 545 position: sticky; 546 top: 100px; 547} 548 549.filter-card { 550 background: var(--bg-card); 551 border: 1px solid var(--border); 552 border-radius: var(--radius-lg); 553 overflow: hidden; 554 margin-bottom: 20px; 555} 556 557.filter-header { 558 display: flex; 559 align-items: center; 560 justify-content: space-between; 561 padding: 16px 20px; 562 border-bottom: 1px solid var(--border); 563 background: var(--bg-elevated); 564} 565 566.filter-title { 567 font-size: 13px; 568 font-weight: 600; 569 color: var(--text); 570 text-transform: uppercase; 571 letter-spacing: 0.5px; 572} 573 574.filter-clear { 575 font-size: 12px; 576 color: var(--accent); 577 cursor: pointer; 578 opacity: 0; 579 transition: opacity 0.2s; 580} 581 582.filter-card.has-selection .filter-clear { 583 opacity: 1; 584} 585 586.filter-clear:hover { 587 text-decoration: underline; 588} 589 590.filter-options { 591 padding: 8px; 592} 593 594.filter-option { 595 display: flex; 596 align-items: center; 597 gap: 12px; 598 padding: 10px 12px; 599 border-radius: var(--radius-sm); 600 cursor: pointer; 601 transition: all 0.15s; 602 font-size: 14px; 603 color: var(--text-dim); 604} 605 606.filter-option:hover { 607 background: var(--bg-elevated); 608 color: var(--text); 609} 610 611.filter-option.active { 612 background: rgba(52, 211, 153, 0.1); 613 color: var(--accent); 614} 615 616.filter-icon {
617 width: 20px; 618 display: flex; 619 align-items: center; 620 justify-content: center; 621 font-size: 14px; 622} 623 624.filter-label { 625 flex: 1; 626} 627 628.filter-count { 629 font-size: 12px; 630 color: var(--text-faint); 631 background: var(--bg); 632 padding: 2px 8px; 633 border-radius:0; 634 min-width: 24px; 635 text-align: center; 636} 637 638.filter-option.active .filter-count { 639 background: var(--accent); 640 color: var(--bg); 641} 642 643/* Results Header */ 644.results-header { 645 display: flex; 646 align-items: center; 647 justify-content: space-between; 648 margin-bottom: 24px; 649 padding-bottom: 20px; 650 border-bottom: 1px solid var(--border); 651} 652 653.results-info { 654 display: flex; 655 align-items: center; 656 gap: 16px; 657} 658 659.results-count { 660 font-size: 14px; 661 color: var(--text-dim); 662} 663 664.results-count strong { 665 color: var(--text); 666 font-weight: 600; 667} 668 669.active-filters { 670 display: flex; 671 flex-wrap: wrap; 672 gap: 8px; 673} 674 675.active-filter { 676 display: inline-flex; 677 align-items: center; 678 gap: 6px; 679 padding: 5px 10px; 680 background: rgba(52, 211, 153, 0.1); 681 border: 1px solid rgba(52, 211, 153, 0.2); 682 border-radius:0; 683 font-size: 12px; 684 color: var(--accent); 685} 686 687.active-filter-remove { 688 cursor: pointer; 689 opacity: 0.7; 690 font-size: 14px; 691 line-height: 1; 692} 693 694.active-filter-remove:hover { 695 opacity: 1; 696} 697 698.sort-select { 699 padding: 8px 12px; 700 padding-right: 32px; 701 background: var(--bg-card); 702 border: 1px solid var(--border); 703 border-radius: var(--radius-sm); 704 color: var(--text); 705 font-family: inherit; 706 font-size: 13px; 707 cursor: pointer; 708 appearance: none; 709 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%238b8f9a' viewBox='0 0 16 16'%3E%3Cpath d='M8 11L3 6h10l-5 5z'/%3E%3C/svg%3E"); 710 background-repeat: no-repeat; 711 background-position: right 10px center; 712} 713 714.sort-select:focus { 715 outline: none; 716 border-color: var(--accent); 717} 718 719/* Products Grid */ 720.products-grid { 721 display: grid; 722 grid-template-columns: repeat(3, 1fr); 723 gap: 20px; 724} 725 726.product-card { 727 display: flex; 728 flex-direction: column; 729 transition: all 0.3s ease; 730} 731 732.product-card.hidden { 733 display: none !important; 734} 735 736.product-card:hover { 737 transform: translateY(-4px); 738 box-shadow: 0 12px 40px rgba(0,0,0,0.3); 739} 740 741.product-image { 742 position: relative; 743 height: 180px; 744 background: linear-gradient(135deg, var(--bg-card-hover) 0%, var(--bg-elevated) 100%); 745 display: flex; 746 align-items: center; 747 justify-content: center; 748 overflow: hidden; 749} 750 751.product-image img { 752 width: 100%; 753 height: 100%; 754 object-fit: cover; 755} 756 757.product-image-icon { 758 color: var(--accent); 759 opacity: 0.8; 760} 761 762.product-badge { 763 position: absolute; 764 top: 12px; 765 right: 12px; 766 padding: 5px 10px; 767 background: var(--accent); 768 color: var(--bg); 769 font-size: 10px; 770 font-weight: 700; 771 text-transform: uppercase; 772 letter-spacing: 0.5px; 773 border-radius:0; 774} 775 776.product-badge-free { background: #3b82f6; } 777.product-badge-tebex { background: #12141c; border: 1px solid rgba(255,255,255,0.25); display: flex; align-items: center; padding: 6px 9px; } 778.product-badge-tebex img { height: 11px; width: auto; display: block; } 779 780/* Tebex sits in the price slot (like GitHub) â official wordmark, scaled only */ 781.product-price-tebex { display: flex; align-items: center; } 782.product-price-tebex img { height: 32px; width: auto; display: block; } 783 784/* White button, matching the GitHub card treatment for third-party vendors */ 785.btn-tebex-card { 786 background: #ffffff; 787 color: #24292f; 788 font-weight: 600; 789} 790.btn-tebex-card:hover { background: #f6f8fa; } 791.product-badge-addon { background: #8b5cf6; } 792.product-badge-github { background: #ffffff; color: #24292f; } 793 794.product-body { 795 padding: 20px; 796 flex: 1; 797 display: flex; 798 flex-direction: column; 799 border-top: 1px solid var(--border); 800} 801 802.product-name { 803 font-size: 18px; 804 font-weight: 700; 805 margin-bottom: 8px; 806 line-height: 1.3; 807} 808 809.product-desc { 810 font-size: 13px; 811 color: var(--text-dim); 812 line-height: 1.6; 813 flex: 1; 814 margin-bottom: 16px; 815} 816 817.product-features { 818 display: flex; 819 flex-wrap: wrap; 820 gap: 6px; 821 margin-bottom: 16px; 822} 823 824.product-feature { 825 padding: 3px 8px; 826 background: var(--bg-elevated); 827 border-radius:0; 828 font-size: 10px; 829 color: var(--text-dim); 830} 831 832.product-footer { 833 display: flex; 834 align-items: center; 835 justify-content: space-between; 836 padding-top: 16px; 837 border-top: 1px solid var(--border); 838} 839 840.product-price { 841 font-size: 22px; 842 font-weight: 800; 843 letter-spacing: -0.5px; 844} 845 846.product-price-free { 847 color: var(--accent); 848 font-size: 16px; 849} 850 851.product-price-github { 852 color: #ffffff; 853 font-weight: 600; 854 font-size: 16px; 855} 856 857.btn-github-card { 858 background: #ffffff; 859 color: #24292f; 860 font-weight: 600; 861} 862 863.btn-github-card:hover { 864 background: #f6f8fa; 865} 866 867/* No Results */ 868.no-results { 869 grid-column: 1 / -1; 870 text-align: center; 871 padding: 60px 20px; 872 background: var(--bg-card); 873 border: 1px solid var(--border); 874 border-radius: var(--radius-lg); 875} 876 877.no-results-icon { 878 color: var(--text-dim); 879 margin-bottom: 16px; 880 line-height: 0; 881} 882 883.no-results h3 { 884 font-size: 18px; 885 margin-bottom: 8px; 886} 887 888.no-results p { 889 color: var(--text-dim); 890 margin-bottom: 20px; 891} 892 893/* Empty State */ 894.empty-state { 895 text-align: center; 896 padding: 80px 20px; 897 color: var(--text-dim); 898} 899 900.empty-state h3 { 901 font-size: 20px; 902 margin-bottom: 8px; 903 color: var(--text); 904} 905 906/* Responsive */ 907@media (max-width: 1250px) { 908 .products-layout { 909 grid-template-columns: 220px 1fr; 910 gap: 30px; 911 } 912 .products-grid { 913 grid-template-columns: repeat(2, 1fr); 914 } 915} 916 917@media (max-width: 900px) { 918 .products-layout { 919 grid-template-columns: 1fr; 920 } 921 922 .sidebar { 923 position: static; 924 display: grid; 925 grid-template-columns: repeat(3, 1fr); 926 gap: 16px; 927 } 928 929 .filter-card { 930 margin-bottom: 0; 931 } 932 933 .products-grid { 934 grid-template-columns: repeat(2, 1fr); 935 } 936} 937 938@media (max-width: 700px) { 939 .sidebar { 940 grid-template-columns: 1fr; 941 } 942 943 .results-header { 944 flex-direction: column; 945 gap: 16px; 946 align-items: flex-start; 947 } 948 949 .results-info { 950 flex-direction: column; 951 align-items: flex-start; 952 gap: 12px; 953 } 954} 955 956@media (max-width: 600px) { 957 .page-title { font-size: 28px; } 958 .products-grid { grid-template-columns: 1fr; } 959} </style> 960
960<script defer src="https://api.pirsch.io/pa.js" id="pianjs" data-code="eiHmgjIWsb3mplztzSJLXOSFFiCTGLXI"></script>
960 961 962 <!-- Structured Data --> 963
963<script type="application/ld+json"> 964 { 965 "@context": "https://schema.org", 966 "@type": "Organization", 967 "name": "LonexLabs", 968 "url": "https://lonexlabs.com", 969 "logo": "https://lonexlabs.com/og-image.png", 970 "description": "Professional tools for FiveM server management", 971 "sameAs": [ 972 "https://discord.gg/lonexlabs" 973 ] 974 } 975 </script>
975 976
976<script type="application/ld+json"> 977 { 978 "@context": "https://schema.org", 979 "@type": "Product", 980 "name": "Store Module", 981 "description": "Add a complete, self-hosted store to your LonexCommunity, sell digital downloads, Discord roles, and product keys with Stripe and PayPal built in.", 982 "image": "https://lonexlabs.com/public/uploads/products/store-module-1783650255.jpg", 983 "brand": { 984 "@type": "Brand", 985 "name": "LonexLabs" 986 }, 987 "offers": { 988 "@type": "Offer", 989 "price": "30.00", 990 "priceCurrency": "USD", 991 "availability": "https://schema.org/InStock", 992 "url": "https://lonexlabs.com/products/store-module" 993 } 994 } 995 </script>
995 996 </head> 997<body class="pg-products"> 998 <header class="lx-site-header"> 999 <div class="lx-wrap lx-header-inner"> 1000 <a class="lx-brand" href="/" aria-label="LonexLabs home"><img src="/public/logo.svg" alt="LonexLabs" width="158" height="36"></a> 1001 1002 <nav class="lx-nav" aria-label="Primary"> 1003 <a href="/">Home</a> 1004 <a href="/products" aria-current="page">Products</a> 1005 <a href="/marketplace">Marketplace</a> 1006 <a class="lx-secondary" href="/commissions">Commissions</a> 1007 1008 <div class="lx-menu-wrap"> 1009 <button class="lx-menu-btn-nav" data-pop-trigger="resources-menu" aria-expanded="false" aria-haspopup="true"> 1010 Resources <svg class="lx-chev"><use href="#i-chev"/></svg> 1011 </button> 1012 <div class="lx-menu-pop" id="resources-menu" hidden> 1013 <a href="https://docs.lonexlabs.com/" target="_blank" rel="noopener"><svg class="lx-ic"><use href="#i-book"/></svg><b>Documentation</b><span>Install guides and API reference</span><svg class="lx-ext"><use href="#i-ext"/></svg></a> 1014 <a href="https://basecamp.lonexlabs.com/" target="_blank" rel="noopener"><svg class="lx-ic"><use href="#i-flag"/></svg><b>Basecamp</b><span>Changelogs and release notes</span><svg class="lx-ext"><use href="#i-ext"/></svg></a> 1015 <a href="https://discord.gg/lonexlabs" target="_blank" rel="noopener"><svg class="lx-ic"><use href="#i-discord"/></svg><b>Discord</b><span>Ask the team and other owners</span><svg class="lx-ext"><use href="#i-ext"/></svg></a> 1016 <div class="lx-menu-sep"></div> 1017 <a href="/support"><svg class="lx-ic"><use href="#i-life"/></svg><b>Support</b><span>Open a ticket from your dashboard</span></a> 1018 </div> 1019 </div> 1020 1021 <span style="flex:1"></span> 1022 1023 <button class="lx-nav-search" data-search-open aria-label="Search products"> 1024 <svg><use href="#i-search"/></svg> 1025 <span class="lx-label">Search productsâ¦</span> 1026 <span class="lx-kbd">âK</span> 1027 </button> 1028 1029 <div class="lx-cart-wrap"> 1030 <a class="lx-cart-link" href="/cart" aria-label="Cart, empty"><svg><use href="#i-cart"/></svg></a> 1031 </div> 1032 1033 <a class="lx-nav-cta" href="/login">Sign In</a> 1034 </nav> 1035 1036 <button class="lx-menu-btn" aria-expanded="false" aria-controls="mobile-menu" aria-label="Menu"><svg><use href="#i-menu"/></svg></button> 1037 </div> 1038 1039 <div id="mobile-menu" class="lx-wrap lx-mobile-menu" hidden> 1040 <a href="/">Home</a> 1041 <a href="/products">Products</a> 1042 <a href="/marketplace">Marketplace</a> 1043 <a href="/commissions">Commissions</a> 1044 <a href="https://docs.lonexlabs.com/" target="_blank" rel="noopener">Documentation</a> 1045 <a href="https://basecamp.lonexlabs.com/" target="_blank" rel="noopener">Basecamp</a> 1046 <a href="https://discord.gg/lonexlabs" target="_blank" rel="noopener">Discord</a> 1047 <a href="/support">Support</a> 1048 <a href="/cart">Cart</a> 1049 <a class="lx-btn lx-btn-primary lx-btn-block" href="/login">Sign In</a> 1050 </div> 1051 </header> 1052 1053 <main> 1054 1055<section class="page-hero"> 1056 <div class="container"> 1057 <nav class="hero-crumbs"> 1058 <a href="/">Home</a> 1059 <span>/</span> 1060 <span>Products</span> 1061 </nav> 1062 <div class="page-head"> 1063 <div> 1064 <h1 class="page-title">Products</h1> 1065 <p class="page-subtitle">Professional tools, integrations, and resources to power your FiveM server and community.</p> 1066 </div> 1067 </div> 1068 </div> 1069</section> 1070 1071<section class="products-section"> 1072 <div class="container"> 1073 <div class="lx-mg-banner" id="lx-mg-banner" data-key="managed-service"> 1074 <div class="lx-mg-ico"> 1075 <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> 1076 </div> 1077 <div class="lx-mg-text"> 1078 <strong>Don't want to host it yourself?</strong>
1079 <span>Let us host, set up & maintain it for you â from $5.00/mo.</span> 1080 </div> 1081 <a href="/products/managed-service" class="lx-mg-btn">Explore Managed Service</a> 1082 <button type="button" class="lx-mg-x" aria-label="Dismiss" onclick="lxDismissMgBanner()"> 1083 <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg> 1084 </button> 1085</div> 1086 1087<style> 1088.lx-mg-banner { display:flex; align-items:center; gap:16px; margin:18px 0; padding:16px 18px; border-radius:0; 1089 background: linear-gradient(90deg, rgba(41,205,150,.12), rgba(41,205,150,.04)); border:1px solid rgba(41,205,150,.3); } 1090.lx-mg-ico { flex-shrink:0; width:44px; height:44px; border-radius:0; display:flex; align-items:center; justify-content:center; 1091 background: rgba(41,205,150,.15); color: var(--accent,#29cd96); } 1092.lx-mg-text { flex:1; min-width:0; display:flex; flex-direction:column; line-height:1.35; } 1093.lx-mg-text strong { font-size:15px; } 1094.lx-mg-text span { font-size:13.5px; color: var(--text-dim,#9aa); } 1095.lx-mg-btn { flex-shrink:0; padding:10px 18px; border-radius:0; background: var(--accent,#29cd96); color:#04130d; 1096 font-weight:700; font-size:14px; text-decoration:none; white-space:nowrap; transition: transform .15s, filter .15s; } 1097.lx-mg-btn:hover { transform: translateY(-1px); filter: brightness(1.05); } 1098.lx-mg-x { flex-shrink:0; background:none; border:none; color: var(--text-dim,#9aa); cursor:pointer; padding:6px; border-radius:0; } 1099.lx-mg-x:hover { color: var(--text,#fff); } 1100@media (max-width: 640px) { 1101 .lx-mg-banner { flex-wrap:wrap; } 1102 .lx-mg-text { flex-basis:100%; order:2; } 1103 .lx-mg-btn { order:3; } 1104} 1105</style>
1106<script> 1107(function () { 1108 var b = document.getElementById('lx-mg-banner'); 1109 if (!b) return; 1110 try { if (sessionStorage.getItem('lxMgBannerDismissed') === b.dataset.key) b.style.display = 'none'; } catch (e) {} 1111 window.lxDismissMgBanner = function () { 1112 try { sessionStorage.setItem('lxMgBannerDismissed', b.dataset.key); } catch (e) {} 1113 b.style.display = 'none'; 1114 }; 1115})(); 1116</script>
1116 1117 <div class="products-layout"> 1118 <!-- Sidebar Filters --> 1119 <aside class="sidebar"> 1120 <!-- Category Filter --> 1121 <div class="filter-card" data-filter-group="category"> 1122 <div class="filter-header"> 1123 <span class="filter-title">Category</span> 1124 <span class="filter-clear" onclick="clearFilterGroup('category')">Clear</span> 1125 </div> 1126 <div class="filter-options"> 1127 <div class="filter-option active" data-filter="category" data-value="all"> 1128 <span class="filter-icon"><i class="fa-solid fa-box" style="font-size:16px"></i></span> 1129 <span class="filter-label">All Categories</span> 1130 <span class="filter-count">18</span> 1131 </div> 1132 <div class="filter-option" data-filter="category" data-value="resource"> 1133 <span class="filter-icon"><i class="fa-solid fa-box" style="font-size:16px"></i></span> 1134 <span class="filter-label">Resource</span> 1135 <span class="filter-count">13</span> 1136 </div> 1137 <div class="filter-option" data-filter="category" data-value="cad"> 1138 <span class="filter-icon"><i class="fa-solid fa-desktop" style="font-size:16px"></i></span> 1139 <span class="filter-label">CAD System</span> 1140 <span class="filter-count">1</span> 1141 </div> 1142 <div class="filter-option" data-filter="category" data-value="discord"> 1143 <span class="filter-icon"><i class="fa-solid fa-robot" style="font-size:16px"></i></span> 1144 <span class="filter-label">Discord Bot</span> 1145 <span class="filter-count">0</span> 1146 </div> 1147 <div class="filter-option" data-filter="category" data-value="community"> 1148 <span class="filter-icon"><i class="fa-solid fa-users" style="font-size:16px"></i></span> 1149 <span class="filter-label">Community</span> 1150 <span class="filter-count">4</span> 1151 </div> 1152 </div> 1153 </div> 1154 1155 <!-- Platform Filter --> 1156 <div class="filter-card" data-filter-group="platform"> 1157 <div class="filter-header"> 1158 <span class="filter-title">Platform</span> 1159 <span class="filter-clear" onclick="clearFilterGroup('platform')">Clear</span> 1160 </div> 1161 <div class="filter-options"> 1162 <div class="filter-option active" data-filter="platform" data-value="all"> 1163 <span class="filter-icon"><i class="fa-solid fa-bullseye" style="font-size:16px"></i></span> 1164 <span class="filter-label">All Platforms</span> 1165 <span class="filter-count">18</span> 1166 </div> 1167 <div class="filter-option" data-filter="platform" data-value="fivem"> 1168 <span class="filter-icon"><i class="fa-solid fa-code" style="font-size:16px"></i></span>
1169 <span class="filter-label">FiveM</span> 1170 <span class="filter-count">3</span> 1171 </div> 1172 <div class="filter-option" data-filter="platform" data-value="discord"> 1173 <span class="filter-icon"><i class="fa-solid fa-robot" style="font-size:16px"></i></span> 1174 <span class="filter-label">Discord</span> 1175 <span class="filter-count">0</span> 1176 </div> 1177 <div class="filter-option" data-filter="platform" data-value="web"> 1178 <span class="filter-icon"><i class="fa-solid fa-globe" style="font-size:16px"></i></span> 1179 <span class="filter-label">Web Application</span> 1180 <span class="filter-count">11</span> 1181 </div> 1182 <div class="filter-option" data-filter="platform" data-value="standalone"> 1183 <span class="filter-icon"><i class="fa-solid fa-database" style="font-size:16px"></i></span> 1184 <span class="filter-label">Standalone</span> 1185 <span class="filter-count">2</span> 1186 </div> 1187 <div class="filter-option" data-filter="platform" data-value="addon"> 1188 <span class="filter-icon"><i class="fa-solid fa-plug" style="font-size:16px"></i></span> 1189 <span class="filter-label">API</span> 1190 <span class="filter-count">1</span> 1191 </div> 1192 <div class="filter-option" data-filter="platform" data-value="managed"> 1193 <span class="filter-icon"><i class="fa-solid fa-star" style="font-size:16px"></i></span> 1194 <span class="filter-label">Managed</span> 1195 <span class="filter-count">1</span> 1196 </div> 1197 </div> 1198 </div> 1199 1200 <!-- Type Filter --> 1201 <div class="filter-card" data-filter-group="type"> 1202 <div class="filter-header"> 1203 <span class="filter-title">Type</span> 1204 <span class="filter-clear" onclick="clearFilterGroup('type')">Clear</span> 1205 </div> 1206 <div class="filter-options"> 1207 <div class="filter-option active" data-filter="type" data-value="all"> 1208 <span class="filter-icon"><i class="fa-solid fa-bullseye" style="font-size:16px"></i></span> 1209 <span class="filter-label">All Types</span> 1210 <span class="filter-count">18</span> 1211 </div> 1212 <div class="filter-option" data-filter="type" data-value="product"> 1213 <span class="filter-icon"><i class="fa-solid fa-box" style="font-size:16px"></i></span> 1214 <span class="filter-label">Product</span> 1215 <span class="filter-count">10</span> 1216 </div> 1217 <div class="filter-option" data-filter="type" data-value="addon">
1218 <span class="filter-icon"><i class="fa-solid fa-plug" style="font-size:16px"></i></span> 1219 <span class="filter-label">Addon</span> 1220 <span class="filter-count">5</span> 1221 </div> 1222 <div class="filter-option" data-filter="type" data-value="integration"> 1223 <span class="filter-icon"><i class="fa-solid fa-code" style="font-size:16px"></i></span> 1224 <span class="filter-label">Integration</span> 1225 <span class="filter-count">2</span> 1226 </div> 1227 <div class="filter-option" data-filter="type" data-value="service"> 1228 <span class="filter-icon"><i class="fa-solid fa-star" style="font-size:16px"></i></span> 1229 <span class="filter-label">Service</span> 1230 <span class="filter-count">1</span> 1231 </div> 1232 <div class="filter-option" data-filter="type" data-value="open-source"> 1233 <span class="filter-icon"><i class="fa-brands fa-github" style="font-size:16px"></i></span> 1234 <span class="filter-label">Open Source</span> 1235 <span class="filter-count">0</span> 1236 </div> 1237 </div> 1238 </div> 1239 </aside> 1240 1241 <!-- Products Grid --> 1242 <div class="products-main"> 1243 <div class="results-header"> 1244 <div class="results-info"> 1245 <span class="results-count">Showing <strong id="visibleCount">18</strong> products</span> 1246 <div class="active-filters" id="activeFilters"></div> 1247 </div> 1248 <select class="sort-select" id="sortSelect"> 1249 <option value="featured">Sort by: Featured</option> 1250 <option value="price-low">Price: Low to High</option> 1251 <option value="price-high">Price: High to Low</option> 1252 <option value="name-az">Name: A-Z</option> 1253 <option value="name-za">Name: Z-A</option> 1254 </select> 1255 </div> 1256 1257 <style> 1258 .lx-sort { position: relative; display: inline-block; min-width: 200px; } 1259 .lx-sort-trigger { width:100%; display:flex; align-items:center; justify-content:space-between; gap:10px; padding:10px 14px; border-radius:0; border:1px solid var(--border,#2a2d34); background:var(--bg,#16181d); color:var(--text,#e6e8eb); font-family:inherit; font-size:14px; cursor:pointer; transition:border-color .15s, box-shadow .15s; } 1260 .lx-sort-trigger:hover { border-color: var(--text-faint,#555); } 1261 .lx-sort.open .lx-sort-trigger, .lx-sort-trigger:focus { outline:none; border-color: var(--accent,#29cd96); box-shadow: 0 0 0 3px rgba(41,205,150,.15); } 1262 .lx-sort-caret { flex-shrink:0; width:16px; height:16px; color:var(--text-dim,#9aa); transition: transform .18s ease; } 1263 .lx-sort.open .lx-sort-caret { transform: rotate(180deg); } 1264 .lx-sort-menu { position:absolute; top:calc(100% + 6px); left:0; right:0; z-index:60; margin:0; padding:6px; list-style:none; background:var(--bg-elevated,#1c1f26); border:1px solid var(--border,#2a2d34); border-radius:0; box-shadow:0 16px 40px rgba(0,0,0,.45); opacity:0; transform:translateY(-6px); pointer-events:none; transition:opacity .15s ease, transform .15s ease; } 1265 .lx-sort.open .lx-sort-menu { opacity:1; transform:translateY(0); pointer-events:auto; } 1266 .lx-sort-opt { padding:9px 12px; border-radius:0; font-size:14px; cursor:pointer; color:var(--text,#e6e8eb); white-space:nowrap; } 1267 .lx-sort-opt:hover, .lx-sort-opt.active { background:var(--card-hover,rgba(255,255,255,.06)); } 1268 .lx-sort-opt.selected { background:rgba(41,205,150,.14); color:var(--accent,#29cd96); } 1269 </style> 1270
1270<script> 1271 (function () { 1272 var sel = document.getElementById('sortSelect'); 1273 if (!sel || sel.dataset.enhanced) return; 1274 sel.dataset.enhanced = '1'; 1275 1276 var wrap = document.createElement('div'); wrap.className = 'lx-sort'; 1277 var trigger = document.createElement('button'); trigger.type = 'button'; trigger.className = 'lx-sort-trigger'; 1278 trigger.setAttribute('aria-haspopup', 'listbox'); 1279 trigger.innerHTML = '<span class="lx-sort-val"></span><svg class="lx-sort-caret" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"/></svg>'; 1280 var menu = document.createElement('ul'); menu.className = 'lx-sort-menu'; menu.setAttribute('role', 'listbox'); 1281 1282 var opts = Array.prototype.slice.call(sel.options); 1283 opts.forEach(function (o) { 1284 var li = document.createElement('li'); 1285 li.className = 'lx-sort-opt'; li.setAttribute('role', 'option'); 1286 li.textContent = o.textContent; li.dataset.value = o.value; 1287 li.addEventListener('click', function () { pick(o.value); }); 1288 menu.appendChild(li); 1289 }); 1290 1291 sel.parentNode.insertBefore(wrap, sel); 1292 wrap.appendChild(trigger); wrap.appendChild(menu); wrap.appendChild(sel); 1293 sel.style.display = 'none'; 1294 1295 function render() { 1296 trigger.querySelector('.lx-sort-val').textContent = sel.options[sel.selectedIndex].textContent; 1297 menu.querySelectorAll('.lx-sort-opt').forEach(function (li) { li.classList.toggle('selected', li.dataset.value === sel.value); }); 1298 } 1299 function open() { wrap.classList.add('open'); document.addEventListener('click', outside, true); } 1300 function close() { wrap.classList.remove('open'); document.removeEventListener('click', outside, true); } 1301 function outside(e) { if (!wrap.contains(e.target)) close(); } 1302 function pick(v) { sel.value = v; sel.dispatchEvent(new Event('change', { bubbles: true })); render(); close(); } 1303 1304 trigger.addEventListener('click', function () { wrap.classList.contains('open') ? close() : open(); }); 1305 render(); 1306 })(); 1307 </script>
1307 1308 1309 <div class="products-grid" id="productsGrid"> 1310 <a href="/products/brandingremoval" 1311 class="card product-card" 1312 data-category="resource" 1313 data-platform="web" 1314 data-price-cents="3500" 1315 data-type="addon" 1316 data-featured="0" 1317 data-name="Branding Removal"> 1318 <div class="product-image"> 1319 <img src="/public/uploads/products/brandingremoval-1784024947.jpg" alt="Branding Removal"> 1320 <span class="product-badge product-badge-addon">Addon</span> 1321 </div> 1322 <div class="product-body"> 1323 <h3 class="product-name">Branding Removal</h3> 1324 <p class="product-desc">Hide all visible LonexLabs branding from supported products automatically while your Branding Removal license is active.</p> 1325 1326 <div class="product-features"> 1327 <span class="product-feature">Removes visible LonexLabs branding from supported products.</span> 1328 <span class="product-feature">No manual configuration or code changes required.</span> 1329 <span class="product-feature">Automatically applied when linked to your active license.</span> 1330 </div> 1331 1332 <div class="product-footer"> 1333 <span class="product-price">$35.00</span> 1334 <span class="btn btn-sm btn-primary">View Details</span> 1335 </div> 1336 </div> 1337 </a> 1338 <a href="/products/lonexdept" 1339 class="card product-card" 1340 data-category="resource" 1341 data-platform="fivem" 1342 data-price-cents="6000" 1343 data-type="product" 1344 data-featured="0" 1345 data-name="Department Panel"> 1346 <div class="product-image"> 1347 <img src="/public/uploads/products/lonexdept-1786268385.jpg" alt="Department Panel"> 1348 </div> 1349 <div class="product-body"> 1350 <h3 class="product-name">Department Panel</h3> 1351 <p class="product-desc">Rosters, ranks, callsigns, hours, training and discipline in one panel, with Discord roles and nicknames that follow every promotion.</p> 1352 1353 <div class="product-features"> 1354 <sp
1354an class="product-feature">Discord OAuth sign-in</span> 1355 <span class="product-feature">Role-granted access</span> 1356 <span class="product-feature">Promotion writeback</span> 1357 </div> 1358 1359 <div class="product-footer"> 1360 <span class="product-price">$60.00</span> 1361 <span class="btn btn-sm btn-primary">View Details</span> 1362 </div> 1363 </div> 1364 </a> 1365 <a href="/products/helpdesk-module" 1366 class="card product-card" 1367 data-category="community" 1368 data-platform="web" 1369 data-price-cents="1500" 1370 data-type="addon" 1371 data-featured="0" 1372 data-name="Helpdesk Module"> 1373 <div class="product-image"> 1374 <img src="/public/uploads/products/helpdesk-module-1783649428.jpg" alt="Helpdesk Module"> 1375 <span class="product-badge product-badge-addon">Addon</span> 1376 </div> 1377 <div class="product-body"> 1378 <h3 class="product-name">Helpdesk Module</h3> 1379 <p class="product-desc">Add a powerful helpdesk to your LonexCommunity installation. Members can submit tickets, staff can manage queues, and everything stays organized with categories, priorities, and full conversation history.</p> 1380 1381 <div class="product-features"> 1382 <span class="product-feature">Full ticket lifecycle management</span> 1383 <span class="product-feature">Custom categories & priorities</span> 1384 <span class="product-feature">Staff assignment & tracking</span> 1385 </div> 1386 1387 <div class="product-footer"> 1388 <span class="product-price">$15.00</span> 1389 <span class="btn btn-sm btn-primary">View Details</span> 1390 </div> 1391 </div> 1392 </a> 1393 <a href="/products/image-uploader" 1394 class="card product-card" 1395 data-category="resource" 1396 data-platform="standalone" 1397 data-price-cents="0" 1398 data-type="product" 1399 data-featured="0" 1400 data-name="Image Uploader"> 1401 <div class="product-image"> 1402 <img src="/public/uploads/products/image-uploader-1783650129.jpg" alt="Image Uploader"> 1403 <sp
1403an class="product-badge product-badge-free">Free</span> 1404 </div> 1405 <div class="product-body"> 1406 <h3 class="product-name">Image Uploader</h3> 1407 <p class="product-desc">A lightweight, IP-restricted PHP image uploader with a public gallery, built for simple, secure image hosting without a database.</p> 1408 1409 <div class="product-features"> 1410 <span class="product-feature">Upload support for JPEG, PNG, GIF, and WebP</span> 1411 <span class="product-feature">Copy-to-clipboard direct image URLs</span> 1412 <span class="product-feature">Public gallery interface</span> 1413 </div> 1414 1415 <div class="product-footer"> 1416 <span class="product-price product-price-free">Free</span> 1417 <span class="btn btn-sm btn-primary">View Details</span> 1418 </div> 1419 </div> 1420 </a> 1421 <a href="/products/lonexcad" 1422 class="card product-card" 1423 data-category="cad" 1424 data-platform="web" 1425 data-price-cents="5000" 1426 data-type="product" 1427 data-featured="1" 1428 data-name="LonexCAD"> 1429 <div class="product-image"> 1430 <img src="/public/uploads/products/lonexcad-1783898258.png" alt="LonexCAD"> 1431 <span class="product-badge">Popular</span> 1432 </div> 1433 <div class="product-body"> 1434 <h3 class="product-name">LonexCAD</h3> 1435 <p class="product-desc">Complete Computer Aided Dispatch system with real-time updates, unit management, and comprehensive record keeping.</p> 1436 1437 <div class="product-features"> 1438 <span class="product-feature">Real-time Dispatch</span> 1439 <span class="product-feature">Multi-Agency (LEO / Fire / DOT / DMV)</span> 1440 <span class="product-feature">Unit Management</span> 1441 </div> 1442 1443 <div class="product-footer"> 1444 <sp
1444an class="product-price">$50.00</span> 1445 <span class="btn btn-sm btn-primary">View Details</span> 1446 </div> 1447 </div> 1448 </a> 1449 <a href="/products/lonexcad-ingame" 1450 class="card product-card" 1451 data-category="resource" 1452 data-platform="fivem" 1453 data-price-cents="2000" 1454 data-type="addon" 1455 data-featured="0" 1456 data-name="LonexCAD In-Game"> 1457 <div class="product-image"> 1458 <img src="/public/uploads/products/lonexcad-ingame-1783650157.jpg" alt="LonexCAD In-Game"> 1459 <span class="product-badge product-badge-addon">Addon</span> 1460 </div> 1461 <div class="product-body"> 1462 <h3 class="product-name">LonexCAD In-Game</h3> 1463 <p class="product-desc">Access your CAD directly in FiveM. Run plates, check records, update your status, and view active calls - all without alt-tabbing.</p> 1464 1465 <div class="product-features"> 1466 <span class="product-feature">Native FiveM NUI interface</span> 1467 <span class="product-feature">Instant plate & civilian lookups</span> 1468 <span class="product-feature">Real-time sync with web CAD</span> 1469 </div> 1470 1471 <div class="product-footer"> 1472 <span class="product-price">$20.00</span> 1473 <span class="btn btn-sm btn-primary">View Details</span> 1474 </div> 1475 </div> 1476 </a> 1477 <a href="/products/lonexcommunity" 1478 class="card product-card" 1479 data-category="community" 1480 data-platform="web" 1481 data-price-cents="4000" 1482 data-type="product" 1483 data-featured="0" 1484 data-name="LonexCommunity"> 1485 <div class="product-image"> 1486 <img src="/public/uploads/products/lonexcommunity-1783650168.jpg" alt="LonexCommunity"> 1487 </div> 1488 <div class="product-body"> 1489 <h3 class="product-name">LonexCommunity</h3> 1490 <p class="product-desc">The ultimate community management platform for game servers. Centralize your staff management, applications, announcements, and member tools.</p> 1491 1492 <div class="product-features"> 1493 <sp
1493an class="product-feature">Staff Management Portal</span> 1494 <span class="product-feature">Application System</span> 1495 <span class="product-feature">Announcement Center</span> 1496 </div> 1497 1498 <div class="product-footer"> 1499 <span class="product-price">$40.00</span> 1500 <span class="btn btn-sm btn-primary">View Details</span> 1501 </div> 1502 </div> 1503 </a> 1504 <a href="/products/lonexdiscordapi" 1505 class="card product-card" 1506 data-category="resource" 1507 data-platform="addon" 1508 data-price-cents="0" 1509 data-type="integration" 1510 data-featured="1" 1511 data-name="LonexDiscordAPI"> 1512 <div class="product-image"> 1513 <img src="/public/uploads/products/lonexdiscordapi-1783650183.jpg" alt="LonexDiscordAPI"> 1514 <span class="product-badge product-badge-github"> 1515 <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" style="margin-right:3px;vertical-align:-1px"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg> 1516 Open Source 1517 </span> 1518 </div> 1519 <div class="product-body"> 1520 <h3 class="product-name">LonexDiscordAPI</h3> 1521 <p class="product-desc">LonexDiscordAPI is a powerful, high-performance Discord integration library for FiveM servers. It provides seamless Discord role syncing, permissions, webhooks, player data access, and server utilities.</p> 1522 1523 1524 <div class="product-footer"> 1525 <span class="product-price product-price-github"> 1526 <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="vertical-align:-3px;margin-right:4px"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg> 1527 GitHub 1528 </span>
1529 <span class="btn btn-sm btn-github-card">View Details</span> 1530 </div> 1531 </div> 1532 </a> 1533 <a href="/products/lonexdocs" 1534 class="card product-card" 1535 data-category="resource" 1536 data-platform="web" 1537 data-price-cents="2000" 1538 data-type="product" 1539 data-featured="0" 1540 data-name="LonexDocs"> 1541 <div class="product-image"> 1542 <img src="/public/uploads/products/lonexdocs-1783650192.jpg" alt="LonexDocs"> 1543 </div> 1544 <div class="product-body"> 1545 <h3 class="product-name">LonexDocs</h3> 1546 <p class="product-desc">LonexDocs is a self-hosted documentation platform built for communities that want full control over their docs.</p> 1547 1548 <div class="product-features"> 1549 <span class="product-feature">Self-hosted</span> 1550 <span class="product-feature">Installation wizard</span> 1551 <span class="product-feature">Discord OAuth</span> 1552 </div> 1553 1554 <div class="product-footer"> 1555 <span class="product-price">$20.00</span> 1556 <span class="btn btn-sm btn-primary">View Details</span> 1557 </div> 1558 </div> 1559 </a> 1560 <a href="/products/lonexrelay" 1561 class="card product-card" 1562 data-category="resource" 1563 data-platform="web" 1564 data-price-cents="4000" 1565 data-type="product" 1566 data-featured="0" 1567 data-name="LonexRelay"> 1568 <div class="product-image"> 1569 <img src="/public/uploads/products/lonexrelay-1784504606.jpg" alt="LonexRelay"> 1570 </div> 1571 <div class="product-body"> 1572 <h3 class="product-name">LonexRelay</h3> 1573 <p class="product-desc">A self-hosted product feedback board with voting, a public roadmap, and a versioned changelog with Discord sign-in built in.</p> 1574 1575 <div class="product-features"> 1576 <sp
1576an class="product-feature">Feature requests, bug reports, and ideas with voting and threaded comments</span> 1577 <span class="product-feature">Shareable reference codes for every submission (e.g. REQ-10234)</span> 1578 <span class="product-feature">Public roadmap driven live by your development pipeline</span> 1579 </div> 1580 1581 <div class="product-footer"> 1582 <span class="product-price">$40.00</span> 1583 <span class="btn btn-sm btn-primary">View Details</span> 1584 </div> 1585 </div> 1586 </a> 1587 <a href="/products/lonexstaff" 1588 class="card product-card" 1589 data-category="resource" 1590 data-platform="web" 1591 data-price-cents="6000" 1592 data-type="product" 1593 data-featured="1" 1594 data-name="LonexStaff"> 1595 <div class="product-image"> 1596 <img src="/public/uploads/products/lonexstaff-1783680275.jpg" alt="LonexStaff"> 1597 <span class="product-badge">Popular</span> 1598 </div> 1599 <div class="product-body"> 1600 <h3 class="product-name">LonexStaff</h3> 1601 <p class="product-desc">A powerful staff management panel and in-game menu for FiveM servers, combining real-time player moderation with comprehensive web-based administration.</p> 1602 1603 1604 <div class="product-footer"> 1605 <span class="product-price">$60.00</span> 1606 <span class="btn btn-sm btn-primary">View Details</span> 1607 </div> 1608 </div> 1609 </a> 1610 <a href="/products/lonexstatus" 1611 class="card product-card" 1612 data-category="resource" 1613 data-platform="web" 1614 data-price-cents="2000" 1615 data-type="product" 1616 data-featured="0" 1617 data-name="LonexStatus"> 1618 <div class="product-image"> 1619 <img src="/public/uploads/products/lonexstatus-1783650221.jpg" alt="LonexStatus"> 1620 </div> 1621 <div class="product-body"> 1622 <h3 class="product-name">LonexStatus</h3> 1623 <p class="product-desc">A self-hosted status page built for gaming communities and operators. Monitor your FiveM, Minecraft, and Rust servers, websites, APIs, Discord bots, and anything else your community depends on.</p> 1624 1625 <div class="product-features"> 1626 <sp
1626an class="product-feature">Self-hosted on your own infrastructure</span> 1627 <span class="product-feature">Public status page with 90-day uptime bars</span> 1628 <span class="product-feature">Drop-in push agents</span> 1629 </div> 1630 1631 <div class="product-footer"> 1632 <span class="product-price">$20.00</span> 1633 <span class="btn btn-sm btn-primary">View Details</span> 1634 </div> 1635 </div> 1636 </a> 1637 <a href="/products/lonexsync" 1638 class="card product-card" 1639 data-category="resource" 1640 data-platform="fivem" 1641 data-price-cents="0" 1642 data-type="product" 1643 data-featured="0" 1644 data-name="LonexSync"> 1645 <div class="product-image"> 1646 <img src="/public/uploads/products/lonexsync-1784039233.jpg" alt="LonexSync"> 1647 <span class="product-badge product-badge-tebex"> 1648 <img src="/public/brands/tebex-wordmark.png" alt="Tebex" style="height:9px;width:auto;display:block"> 1649 </span> 1650 </div> 1651 <div class="product-body"> 1652 <h3 class="product-name">LonexSync</h3> 1653 <p class="product-desc"></p> 1654 1655 1656 <div class="product-footer"> 1657 <span class="product-price product-price-tebex"> 1658 <img src="/public/brands/tebex-wordmark.png" alt="Tebex"> 1659 </span> 1660 <span class="btn btn-sm btn-tebex-card">View Details</span> 1661 </div> 1662 </div> 1663 </a> 1664 <a href="/products/training" 1665 class="card product-card" 1666 data-category="resource" 1667 data-platform="web" 1668 data-price-cents="4000" 1669 data-type="product" 1670 data-featured="0" 1671 data-name="LonexTraining"> 1672 <div class="product-image"> 1673 <img src="/public/uploads/products/training-1783650683.jpg" alt="LonexTraining"> 1674 </div> 1675 <div class="product-body"> 1676 <h3 class="product-name">LonexTraining</h3> 1677 <p class="product-desc">Complete training and assessment platform for law-enforcement and roleplay departments, live FTO-led sessions, structured asse
1677ssments, and real Discord identities.</p> 1678 1679 1680 <div class="product-footer"> 1681 <span class="product-price">$40.00</span> 1682 <span class="btn btn-sm btn-primary">View Details</span> 1683 </div> 1684 </div> 1685 </a> 1686 <a href="/products/lonexwhmcslink" 1687 class="card product-card" 1688 data-category="resource" 1689 data-platform="standalone" 1690 data-price-cents="3000" 1691 data-type="integration" 1692 data-featured="0" 1693 data-name="LonexWHMCS"> 1694 <div class="product-image"> 1695 <img src="/public/uploads/products/lonexwhmcslink-1783650233.jpg" alt="LonexWHMCS"> 1696 </div> 1697 <div class="product-body"> 1698 <h3 class="product-name">LonexWHMCS</h3> 1699 <p class="product-desc">Your WHMCS, in their Discord. Auto-assign Discord roles when customers buy products, forward invoice and ticket emails as DMs, and manage members across every guild - without leaving the WHMCS admin.</p> 1700 1701 <div class="product-features"> 1702 <span class="product-feature">Discord OAuth linking</span> 1703 <span class="product-feature">Automatic refresh token rotation</span> 1704 <span class="product-feature">Multi-guild support</span> 1705 </div> 1706 1707 <div class="product-footer"> 1708 <span class="product-price">$30.00</span> 1709 <span class="btn btn-sm btn-primary">View Details</span> 1710 </div> 1711 </div> 1712 </a> 1713 <a href="/products/managed-service" 1714 class="card product-card" 1715 data-category="resource" 1716 data-platform="managed" 1717 data-price-cents="0" 1718 data-type="service" 1719 data-featured="0" 1720 data-name="Managed Service"> 1721 <div class="product-image"> 1722 <img src="/public/uploads/products/managed-service-1783650374.jpg" alt="Managed Service"> 1723 <sp
1723an class="product-badge product-badge-free">Free</span> 1724 </div> 1725 <div class="product-body"> 1726 <h3 class="product-name">Managed Service</h3> 1727 <p class="product-desc">Let us handle all the stress!</p> 1728 1729 1730 <div class="product-footer"> 1731 <span class="product-price product-price-free">Free</span> 1732 <span class="btn btn-sm btn-primary">View Details</span> 1733 </div> 1734 </div> 1735 </a> 1736 <a href="/products/staff-module" 1737 class="card product-card" 1738 data-category="community" 1739 data-platform="web" 1740 data-price-cents="1500" 1741 data-type="addon" 1742 data-featured="0" 1743 data-name="Staff Module"> 1744 <div class="product-image"> 1745 <img src="/public/uploads/products/staff-module-1783650243.jpg" alt="Staff Module"> 1746 <span class="product-badge product-badge-addon">Addon</span> 1747 </div> 1748 <div class="product-body"> 1749 <h3 class="product-name">Staff Module</h3> 1750 <p class="product-desc">Connect your LonexStaff panel to your LonexCommunity site to display player leaderboards, staff duty hours, player profiles, and ban appeals.</p> 1751 1752 <div class="product-features"> 1753 <span class="product-feature">Player Leaderboard</span> 1754 <span class="product-feature">Staff Duty Hours</span> 1755 <span class="product-feature">Server Activity</span> 1756 </div> 1757 1758 <div class="product-footer"> 1759 <span class="product-price">$15.00</span> 1760 <span class="btn btn-sm btn-primary">View Details</span> 1761 </div> 1762 </div> 1763 </a> 1764 <a href="/products/store-module" 1765 class="card product-card" 1766 data-category="community" 1767 data-platform="web" 1768 data-price-cents="3000" 1769 data-type="addon" 1770 data-featured="0" 1771 data-name="Store Module"> 1772 <div class="product-image"> 1773 <img src="/public/uploads/products/store-module-1783650255.jpg" alt="Store Module"> 1774 <sp
1774an class="product-badge product-badge-addon">Addon</span> 1775 </div> 1776 <div class="product-body"> 1777 <h3 class="product-name">Store Module</h3> 1778 <p class="product-desc">Add a complete, self-hosted store to your LonexCommunity, sell digital downloads, Discord roles, and product keys with Stripe and PayPal built in.</p> 1779 1780 <div class="product-features"> 1781 <span class="product-feature">Full storefront</span> 1782 <span class="product-feature">Stripe & PayPal Integrated</span> 1783 <span class="product-feature">Digital downloads</span> 1784 </div> 1785 1786 <div class="product-footer"> 1787 <span class="product-price">$30.00</span> 1788 <span class="btn btn-sm btn-primary">View Details</span> 1789 </div> 1790 </div> 1791 </a> 1792 1793 <div class="no-results" id="noResults" style="display: none;"> 1794 <div class="no-results-icon"> 1795 <svg width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg> 1796 </div> 1797 <h3>No products found</h3> 1798 <p>Try adjusting your filters to find what you're looking for.</p> 1799 <button class="btn btn-secondary" onclick="clearAllFilters()">Clear All Filters</button> 1800 </div> 1801 </div> 1802 </div> 1803 </div> 1804 </div> 1805</section> 1806
1807<script> 1808// Filter state 1809const filters = { 1810 category: 'all', 1811 platform: 'all', 1812 type: 'all' 1813}; 1814 1815const filterLabels = { 1816 category: {}, 1817 platform: {}, 1818 type: {} 1819}; 1820 1821// Build labels from rendered DOM so they always match the data 1822['category', 'platform', 'type'].forEach(group => { 1823 document.querySelectorAll(`[data-filter="${group}"]`).forEach(el => { 1824 filterLabels[group][el.dataset.value] = el.querySelector('.filter-label').textContent; 1825 }); 1826}); 1827 1828// Filter click handlers 1829document.querySelectorAll('.filter-option').forEach(option => { 1830 option.addEventListener('click', () => { 1831 const filterType = option.dataset.filter; 1832 const value = option.dataset.value; 1833 1834 filters[filterType] = value; 1835 1836 // Update UI 1837 document.querySelectorAll(`[data-filter="${filterType}"]`).forEach(o => o.classList.remove('active')); 1838 option.classList.add('active'); 1839 1840 // Update filter card state 1841 const card = option.closest('.filter-card'); 1842 card.classList.toggle('has-selection', value !== 'all'); 1843 1844 applyFilters(); 1845 }); 1846}); 1847 1848function clearFilterGroup(group) { 1849 filters[group] = 'all'; 1850 document.querySelectorAll(`[data-filter="${group}"]`).forEach(o => o.classList.remove('active')); 1851 document.querySelector(`[data-filter="${group}"][data-value="all"]`).classList.add('active'); 1852 document.querySelector(`[data-filter-group="${group}"]`).classList.remove('has-selection'); 1853 applyFilters(); 1854} 1855 1856function clearAllFilters() { 1857 Object.keys(filters).forEach(key => clearFilterGroup(key)); 1858} 1859 1860function applyFilters() { 1861 const cards = document.querySelectorAll('.product-card:not(#noResults)'); 1862 let visibleCount = 0; 1863 1864 cards.forEach(card => { 1865 const matchCategory = filters.category === 'all' || card.dataset.category === filters.category; 1866 const matchPlatform = filters.platform === 'all' || card.dataset.platform === filters.platform; 1867 const matchType = filters.type === 'all' || card.dataset.type === filters.type; 1868 1869 if (matchCategory && matchPlatform && matchType) { 1870 card.classList.remove('hidden'); 1871 visibleCount++; 1872 } else { 1873 card.classList.add('hidden'); 1874 } 1875 }); 1876 1877 document.getElementById('visibleCount').textContent = visibleCount; 1878 document.getElementById('noResults').style.display = visibleCount === 0 ? '' : 'none'; 1879 1880 updateActiveFilters(); 1881 applySort(); 1882} 1883 1884function updateActiveFilters() { 1885 const container = document.getElementById('activeFilters'); 1886 container.innerHTML = ''; 1887 1888 Object.entries(filters).forEach(([key, value]) => { 1889 if (value !== 'all') { 1890 const tag = document.createElement('span'); 1891 tag.className = 'active-filter'; 1892 tag.innerHTML = `${filterLabels[key][value]} <span class="active-filter-remove" onclick="event.preventDefault();clearFilterGroup('${key}')">Ã</span>`;
1893 container.appendChild(tag); 1894 } 1895 }); 1896} 1897 1898// Sorting 1899document.getElementById('sortSelect').addEventListener('change', applySort); 1900 1901function applySort() { 1902 const sortBy = document.getElementById('sortSelect').value; 1903 const grid = document.getElementById('productsGrid'); 1904 const cards = Array.from(grid.querySelectorAll('.product-card:not(#noResults)')); 1905 1906 cards.sort((a, b) => { 1907 switch (sortBy) { 1908 case 'price-low': 1909 return parseInt(a.dataset.priceCents || 0) - parseInt(b.dataset.priceCents || 0); 1910 case 'price-high': 1911 return parseInt(b.dataset.priceCents || 0) - parseInt(a.dataset.priceCents || 0); 1912 case 'name-az': 1913 return a.dataset.name.localeCompare(b.dataset.name); 1914 case 'name-za': 1915 return b.dataset.name.localeCompare(a.dataset.name); 1916 case 'featured': 1917 default: 1918 return parseInt(b.dataset.featured || 0) - parseInt(a.dataset.featured || 0); 1919 } 1920 }); 1921 1922 cards.forEach(card => grid.appendChild(card)); 1923 grid.appendChild(document.getElementById('noResults')); 1924} 1925</script>
1925 1926 </main> 1927 1928 <footer class="lx-site-footer"> 1929 <div class="lx-wrap"> 1930 <div class="lx-footer-grid"> 1931 <div class="lx-footer-brand"> 1932 <img src="/public/logo.svg" alt="LonexLabs" width="141" height="32"> 1933 <p>Tools, integrations and digital resources for FiveM servers and online communities.</p> 1934 </div> 1935 <div class="lx-footer-col"> 1936 <h2>Store</h2> 1937 <a href="/products">Products</a> 1938 <a href="/marketplace">Marketplace</a> 1939 <a href="/commissions">Commissions</a> 1940 </div> 1941 <div class="lx-footer-col"> 1942 <h2>Customers</h2> 1943 <a href="/portal">Dashboard</a> 1944 <a href="/license-verify">Licence lookup</a> 1945 <a href="/support">Support</a> 1946 <a href="https://docs.lonexlabs.com/" target="_blank" rel="noopener">Docs</a> 1947 </div> 1948 <div class="lx-footer-col"> 1949 <h2>Company</h2> 1950 <a href="https://discord.gg/lonexlabs" target="_blank" rel="noopener">Discord</a> 1951 <a href="/terms">Terms</a> 1952 <a href="/privacy">Privacy</a> 1953 <a href="/delete-account">Delete My Data</a> 1954 </div> 1955 </div> 1956 <div class="lx-footer-base"> 1957 <span>© 2026 LonexLabs. All rights reserved.</span> 1958 <span class="lx-status-ok"><span class="lx-dot"></span>All systems operational</span> 1959 </div> 1960 </div> 1961 </footer> 1962 1963 <!-- Custom Modal --> 1964 <div class="modal-overlay" id="customModal"> 1965 <div class="modal-box"> 1966 <div class="modal-icon" id="modalIcon"> 1967 <svg width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"> 1968 <path d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/> 1969 </svg> 1970 </div> 1971 <h3 class="modal-title" id="modalTitle">Confirm Action</h3> 1972 <p class="modal-message" id="modalMessage">Are you sure you want to proceed?</p> 1973 <div class="modal-actions"> 1974 <button type="button" class="modal-btn modal-btn-cancel" id="modalCancel">Cancel</button> 1975 <button type="button" class="modal-btn modal-btn-confirm" id="modalConfirm">Confirm</button> 1976 </div> 1977 </div> 1978 </div> 1979 1980 <style> 1981 .modal-overlay { 1982 position: fixed; 1983 inset: 0; 1984 background: rgba(0, 0, 0, 0.8); 1985 backdrop-filter: blur(4px); 1986 display: flex; 1987 align-items: center; 1988 justify-content: center; 1989 z-index: 9999; 1990 opacity: 0; 1991 visibility: hidden; 1992 transition: all 0.2s ease; 1993 } 1994 .modal-overlay.active { 1995 opacity: 1; 1996 visibility: visible; 1997 } 1998 .modal-box { 1999 background: var(--bg-card); 2000 border: 1px solid var(--border); 2001 border-radius:0; 2002 padding: 28px; 2003 max-width: 420px; 2004 width: 90%; 2005 text-align: center; 2006 transform: scale(0.9) translateY(-20px); 2007 transition: transform 0.2s ease; 2008 } 2009 .modal-overlay.active .modal-box { 2010 transform: scale(1) translateY(0); 2011 } 2012 .modal-icon { 2013 width: 56px; 2014 height: 56px; 2015 border-radius: 50%; 2016 background: rgba(239, 68, 68, 0.15); 2017 color: #ef4444; 2018 display: flex; 2019 align-items: center; 2020 justify-content: center; 2021 margin: 0 auto 20px; 2022 } 2023 .modal-icon svg { 2024 width: 28px; 2025 height: 28px; 2026 } 2027 .modal-icon.warning { 2028 background: rgba(245, 158, 11, 0.15); 2029 color: #f59e0b; 2030 } 2031 .modal-icon.info { 2032 background: rgba(59, 130, 246, 0.15); 2033 color: #3b82f6; 2034 } 2035 .modal-icon.success { 2036 background: rgba(41, 205, 150, 0.15); 2037 color: var(--accent); 2038 }
2039 .modal-title { 2040 font-size: 20px; 2041 font-weight: 700; 2042 margin-bottom: 8px; 2043 color: var(--text); 2044 } 2045 .modal-message { 2046 font-size: 15px; 2047 color: var(--text-dim); 2048 margin-bottom: 28px; 2049 line-height: 1.6; 2050 } 2051 .modal-actions { 2052 display: flex; 2053 gap: 12px; 2054 justify-content: center; 2055 } 2056 .modal-btn { 2057 padding: 12px 24px; 2058 border-radius:0; 2059 font-size: 14px; 2060 font-weight: 600; 2061 cursor: pointer; 2062 transition: all 0.2s; 2063 border: none; 2064 min-width: 110px; 2065 } 2066 .modal-btn-cancel { 2067 background: var(--bg-card-hover); 2068 color: var(--text); 2069 border: 1px solid var(--border); 2070 } 2071 .modal-btn-cancel:hover { 2072 background: var(--bg-elevated); 2073 } 2074 .modal-btn-confirm { 2075 background: #ef4444; 2076 color: white; 2077 } 2078 .modal-btn-confirm:hover { 2079 background: #dc2626; 2080 } 2081 .modal-btn-confirm.primary { 2082 background: var(--accent); 2083 } 2084 .modal-btn-confirm.primary:hover { 2085 background: var(--accent-dim); 2086 } 2087 </style> 2088 2089
2089<script> 2090 // Custom modal system 2091 const modal = { 2092 el: document.getElementById('customModal'), 2093 title: document.getElementById('modalTitle'), 2094 message: document.getElementById('modalMessage'), 2095 icon: document.getElementById('modalIcon'), 2096 confirmBtn: document.getElementById('modalConfirm'), 2097 cancelBtn: document.getElementById('modalCancel'), 2098 callback: null, 2099 2100 show(options = {}) { 2101 this.title.textContent = options.title || 'Confirm Action'; 2102 this.message.textContent = options.message || 'Are you sure you want to proceed?'; 2103 this.confirmBtn.textContent = options.confirmText || 'Confirm'; 2104 this.confirmBtn.className = 'modal-btn modal-btn-confirm ' + (options.confirmClass || ''); 2105 2106 this.icon.className = 'modal-icon ' + (options.type || ''); 2107 2108 this.callback = options.onConfirm || null; 2109 this.el.classList.add('active'); 2110 document.body.style.overflow = 'hidden'; 2111 }, 2112 2113 hide() { 2114 this.el.classList.remove('active'); 2115 document.body.style.overflow = ''; 2116 this.callback = null; 2117 }, 2118 2119 confirm(title, message, onConfirm, options = {}) { 2120 this.show({ title, message, onConfirm, ...options }); 2121 } 2122 }; 2123 2124 modal.confirmBtn.addEventListener('click', () => { 2125 if (modal.callback) modal.callback(); 2126 modal.hide(); 2127 }); 2128 2129 modal.cancelBtn.addEventListener('click', () => modal.hide()); 2130 modal.el.addEventListener('click', (e) => { 2131 if (e.target === modal.el) modal.hide(); 2132 }); 2133 2134 document.addEventListener('keydown', (e) => { 2135 if (e.key === 'Escape' && modal.el.classList.contains('active')) { 2136 modal.hide(); 2137 } 2138 }); 2139 2140 // Override confirm dialogs on forms 2141 document.querySelectorAll('form[onsubmit*="confirm"]').forEach(form => { 2142 const originalOnsubmit = form.getAttribute('onsubmit'); 2143 const match = originalOnsubmit.match(/confirm\(['"](.+?)['"]\)/); 2144 2145 if (match) { 2146 form.removeAttribute('onsubmit'); 2147 let confirmed = false; 2148 2149 form.addEventListener('submit', function(e) { 2150 if (confirmed) { 2151 confirmed = false; 2152 return true; 2153 } 2154 2155 e.preventDefault(); 2156 modal.confirm( 2157 'Confirm Action', 2158 match[1], 2159 () => { 2160 confirmed = true; 2161 form.submit(); 2162 }, 2163 { type: 'warning' } 2164 ); 2165 }); 2166 } 2167 }); 2168 </script>
2168 2169 2170
2170<script> 2171 (function() { 2172 const toggle = document.getElementById('mobileToggle'); 2173 const mobileNav = document.getElementById('mobileNav'); 2174 if (!toggle || !mobileNav) return; 2175 2176 toggle.addEventListener('click', function() { 2177 this.classList.toggle('open'); 2178 mobileNav.classList.toggle('open'); 2179 document.body.style.overflow = mobileNav.classList.contains('open') ? 'hidden' : ''; 2180 }); 2181 2182 mobileNav.querySelectorAll('.nav-link').forEach(link => { 2183 link.addEventListener('click', function() { 2184 toggle.classList.remove('open'); 2185 mobileNav.classList.remove('open'); 2186 document.body.style.overflow = ''; 2187 }); 2188 }); 2189 })(); 2190 </script>
2190 2191 2192 <svg width="0" height="0" style="position:absolute" aria-hidden="true"><defs> 2193 <symbol id="i-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M13 6l6 6-6 6"/></symbol> 2194 <symbol id="i-download" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 4v11M7 10l5 5 5-5M5 20h14"/></symbol> 2195 <symbol id="i-left" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m15 6-6 6 6 6"/></symbol> 2196 <symbol id="i-right" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m9 6 6 6-6 6"/></symbol> 2197 <symbol id="i-ext" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17 17 7M8 7h9v9"/></symbol> 2198 <symbol id="i-cart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 4h2l2.4 11.2a2 2 0 0 0 2 1.6h7.7a2 2 0 0 0 1.9-1.5L21 8H6.2"/><circle cx="10" cy="20.5" r="1"/><circle cx="17" cy="20.5" r="1"/></symbol> 2199 <symbol id="i-cart-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 4h2l2.4 11.2a2 2 0 0 0 2 1.6h7.7a2 2 0 0 0 1.9-1.5L21 8H6.2"/><circle cx="10" cy="20.5" r="1"/><circle cx="17" cy="20.5" r="1"/><path d="M13 9.5v4M11 11.5h4"/></symbol> 2200 <symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M4 7h16M4 12h16M4 17h16"/></symbol> 2201 <symbol id="i-life" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="4"/><path d="m5.6 5.6 3.6 3.6M14.8 14.8l3.6 3.6M14.8 9.2l3.6-3.6M5.6 18.4l3.6-3.6"/></symbol> 2202 <symbol id="i-spark" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l2.2 6.3L20.5 10l-6.3 2.2L12 18.5l-2.2-6.3L3.5 10l6.3-1.7z"/></symbol> 2203 <symbol id="i-discord" viewBox="0 0 24 24" fill="currentColor"><path d="M20.3 4.4A19.8 19.8 0 0 0 15.4 3a13.6 13.6 0 0 0-.6 1.3 18.3 18.3 0 0 0-5.5 0A12.6 12.6 0 0 0 8.7 3a19.7 19.7 0 0 0-4.9 1.5C.5 9-.3 13.6.1 18.1a19.9 19.9 0 0 0 6 3 14 14 0 0 0 1.3-2 13 13 0 0 1-1.9-.9l.4-.3a14.2 14.2 0 0 0 12.1 0l.4.3c-.6.4-1.2.7-1.9.9.4.7.8 1.4 1.3 2a19.8 19.8 0 0 0 6-3c.5-5.2-.9-9.7-3.6-13.7zM8 15.3c-1.2 0-2.2-1.1-2.2-2.4s1-2.4 2.2-2.4 2.2 1.1 2.2 2.4-1 2.4-2.2 2.4zm8 0c-1.2 0-2.2-1.1-2.2-2.4s1-2.4 2.2-2.4 2.2 1.1 2.2 2.4-1 2.4-2.2 2.4z"/></symbol> 2204 <symbol id="i-chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></symbol> 2205 <symbol id="i-search" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></symbol>
2206 <symbol id="i-book" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5V5a2 2 0 0 1 2-2h14v15H6a2 2 0 0 0-2 2 2 2 0 0 0 2 2h14"/></symbol> 2207 <symbol id="i-flag" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2.8 20.5 7v10L12 21.2 3.5 17V7z"/><path d="M3.5 7 12 11.2 20.5 7M12 11.2v10"/></symbol> 2208 <symbol id="i-x" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M6 6l12 12M18 6 6 18"/></symbol> 2209 <symbol id="i-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="m5 12.5 4.2 4L19 7"/></symbol> 2210 <symbol id="i-lock" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="11" width="14" height="9" rx="2"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/></symbol> 2211 <symbol id="i-shield" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-3.6 8-10V5l-8-3-8 3v7c0 6.4 8 10 8 10z"/><path d="m9 12 2 2 4-4"/></symbol> 2212 <symbol id="i-zoom" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5M11 8v6M8 11h6"/></symbol> 2213 <symbol id="i-server" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><rect x="3" y="4" width="18" height="7" rx="1.5"/><rect x="3" y="13" width="18" height="7" rx="1.5"/><path d="M7 7.5h.01M7 16.5h.01"/></symbol> 2214 <symbol id="i-key" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="12" r="4"/><path d="M12 12h9M18 12v4M15 12v3"/></symbol> 2215 <symbol id="i-puzzle" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10 3.5a2 2 0 1 1 4 0V5h4a1 1 0 0 1 1 1v4h-1.5a2 2 0 1 0 0 4H19v4a1 1 0 0 1-1 1h-4v-1.5a2 2 0 1 0-4 0V19H6a1 1 0 0 1-1-1v-4h1.5a2 2 0 1 0 0-4H5V6a1 1 0 0 1 1-1h4z"/></symbol> 2216 <symbol id="i-apple" viewBox="0 0 24 24" fill="currentColor"><path d="M16.4 12.6c0-2.5 2-3.6 2.1-3.7a4.6 4.6 0 0 0-3.6-2c-1.5-.2-3 .9-3.7.9-.8 0-2-.9-3.2-.8a4.8 4.8 0 0 0-4 2.4c-1.7 3-.4 7.3 1.2 9.7.8 1.2 1.8 2.5 3 2.4 1.2 0 1.7-.8 3.1-.8s1.9.8 3.2.8c1.3 0 2.1-1.2 2.9-2.4a10 10 0 0 0 1.3-2.7 4.2 4.2 0 0 1-2.3-3.8zM14 5.3A4.2 4.2 0 0 0 15 2.2a4.3 4.3 0 0 0-2.8 1.5 4 4 0 0 0-1 3 3.6 3.6 0 0 0 2.8-1.4z"/></symbol> 2217 <symbol id="i-play" viewBox="0 0 24 24" fill="currentColor"><path d="M4.2 2.6c-.3.3-.4.7-.4 1.2v16.4c0 .5.1.9.4 1.2l9.3-9.4z" opacity=".85"/><path d="m16.6 15.1-3.1-3.1 3.1-3.1 3.6 2c1 .6 1 1.6 0 2.2z"/><path d="M13.5 12 4.2 21.4c.4.4 1 .4 1.6.1l10.8-6.4z" opacity=".7"/><path d="M13.5 12 16.6 8.9 5.8 2.5c-.6-.3-1.2-.3-1.6.1z" opacity=".95"/></symbol> 2218</defs></svg> 2219 2220<div class="lx-search-overlay" id="search-overlay" hidden role="dialog" aria-modal="true" aria-label="Search"> 2221 <div class="lx-search-panel"> 2222 <div class="lx-search-field"> 2223 <svg><use href="#i-search"/></svg> 2224 <input type="text" placeholder="Search products, vehicles and docsâ¦" aria-label="Search"> 2225 <span class="lx-esc">esc</span> 2226 </div> 2227 <div class="lx-search-results"></div> 2228 <div class="lx-search-foot"> 2229 <span><kbd>ââ</kbd>navigate</span> 2230 <span><kbd>âµ</kbd>open</span> 2231 <span><kbd>âK</kbd>toggle</span> 2232 </div> 2233 </div> 2234</div> 2235
2236<script src="/public/assets/store.js?v=1790773669"></script>
vendor: 1 bytes, line 2236
2236
2237<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v4bc70e2c01a94c73b74392e4234840661791215815920" integrity="sha512-L0ha0OXavK/8okipN9F8BtP84dg9DUhPERbBXzwI6dgTA55d2+yweo3pn5CSFYs45/r8md2+xvUPtTdvTNRfjA==" data-cf-beacon='{"version":"2024.11.0","token":"2f2f5851bc7c48afab05f8e8fa61b48f","r":1,"spa":2}' crossorigin="anonymous"></script>
2237 2238</body> 2239</html>
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.