|
581 | 581 | class="max-w-[1100px] mx-auto mt-2 mb-16 px-10 max-sm:px-5 w-full" |
582 | 582 | id="self-hosting-card" |
583 | 583 | > |
584 | | - <div class="feature-card block border border-(--crit-border) rounded-lg bg-(--crit-bg-secondary) p-6 opacity-60"> |
| 584 | + <a |
| 585 | + href="/self-hosting" |
| 586 | + class="feature-card block border border-(--crit-border) rounded-lg bg-(--crit-bg-secondary) p-6 hover:border-(--crit-accent) transition-colors" |
| 587 | + > |
585 | 588 | <div class="flex items-center justify-between max-sm:flex-col max-sm:items-start max-sm:gap-4"> |
586 | 589 | <div> |
587 | | - <div class="flex items-center gap-3 mb-2"> |
588 | | - <span class="font-mono text-xs tracking-widest uppercase text-(--crit-fg-muted)"> |
589 | | - Coming Soon |
590 | | - </span> |
591 | | - </div> |
592 | 590 | <h3 class="text-lg font-semibold tracking-tight mb-1">Self-Host Crit Web</h3> |
593 | 591 | <p class="text-sm text-(--crit-fg-secondary) leading-relaxed max-w-[520px]"> |
594 | 592 | Run your own instance with Docker. One command to start, automatic migrations, works with any Postgres database. |
|
602 | 600 | <div class="text-(--crit-green)">✓ crit-web running on :4000</div> |
603 | 601 | </div> |
604 | 602 | </div> |
605 | | - </div> |
| 603 | + </a> |
606 | 604 | </section> |
607 | 605 | </div> |
608 | | - |
609 | | -<script> |
610 | | - document.querySelectorAll(".copy-btn").forEach(btn => { |
611 | | - const defaultIcon = btn.querySelector(".icon-default"); |
612 | | - const copiedIcon = btn.querySelector(".icon-copied"); |
613 | | - btn.addEventListener("click", () => { |
614 | | - const raw = btn.previousElementSibling.textContent.trim(); |
615 | | - const text = raw.replace(/^\$\s+/, ""); |
616 | | - navigator.clipboard.writeText(text).then(() => { |
617 | | - btn.style.color = "var(--crit-green)"; |
618 | | - defaultIcon.classList.add("hidden"); |
619 | | - copiedIcon.classList.remove("hidden"); |
620 | | - setTimeout(() => { |
621 | | - btn.style.color = ""; |
622 | | - defaultIcon.classList.remove("hidden"); |
623 | | - copiedIcon.classList.add("hidden"); |
624 | | - }, 2000); |
625 | | - }); |
626 | | - }); |
627 | | - }); |
628 | | - |
629 | | - // Feature cards scroll-triggered reveal |
630 | | - const featuresGrid = document.getElementById("features-grid"); |
631 | | - if (featuresGrid) { |
632 | | - const observer = new IntersectionObserver((entries) => { |
633 | | - entries.forEach(entry => { |
634 | | - if (entry.isIntersecting) { |
635 | | - const cards = featuresGrid.querySelectorAll(".feature-card"); |
636 | | - cards.forEach((card, i) => { |
637 | | - setTimeout(() => card.classList.add("revealed"), i * 80); |
638 | | - }); |
639 | | - // Chain the self-hosting card after the last feature card |
640 | | - const selfHosting = document.querySelector("#self-hosting-card .feature-card"); |
641 | | - if (selfHosting) { |
642 | | - setTimeout(() => selfHosting.classList.add("revealed"), cards.length * 80); |
643 | | - } |
644 | | - observer.unobserve(entry.target); |
645 | | - } |
646 | | - }); |
647 | | - }, { threshold: 0.05 }); |
648 | | - observer.observe(featuresGrid); |
649 | | - } |
650 | | - |
651 | | - document.querySelectorAll(".install-tab").forEach(tab => { |
652 | | - tab.addEventListener("click", () => { |
653 | | - document.querySelectorAll(".install-tab").forEach(t => { |
654 | | - t.classList.remove("border-(--crit-accent)", "text-(--crit-accent)"); |
655 | | - t.classList.add("border-transparent", "text-(--crit-fg-muted)"); |
656 | | - }); |
657 | | - document.querySelectorAll(".install-panel").forEach(p => p.classList.add("hidden")); |
658 | | - tab.classList.add("border-(--crit-accent)", "text-(--crit-accent)"); |
659 | | - tab.classList.remove("border-transparent", "text-(--crit-fg-muted)"); |
660 | | - document.getElementById(tab.dataset.target).classList.remove("hidden"); |
661 | | - }); |
662 | | - }); |
663 | | -</script> |
0 commit comments