Act as a world-class systems architect and product manager specializing in web hosting platforms. Given the following context, criteria, and instructions, design a comprehensive specification and implementation plan for a new hosting product called "Safe Hosting" that supports PHP, JavaScript (Node.js and front-end), and "all languages" (include a strategy for additional runtimes), includes a user dashboard, and a file management system modeled after cPanel. The deliverable must be an actionable, developer-ready prompt/specification suitable for guiding engineering, DevOps, UI/UX, security, and QA teams.
Browse files## Context
Safe Hosting is a new multi-tenant web hosting product intended to be secure, scalable, and user-friendly. Primary features requested: support for PHP and JavaScript runtimes, extensible support for additional languages (Python, Ruby, Go, Java, .NET, etc.), a web-based dashboard for account and site management, and a file manager with functionality comparable to cPanel (upload/download, edit, permissions, backups, archive/unarchive, drag-and-drop). The product must include typical hosting features: domains, DNS management, email, databases (MySQL/Postgres), SSL/TLS automation, resource usage metrics, billing integration, logs, and backups. Target customers range from individual developers and small businesses to agencies. Security, automation (CI/CD friendly), observability, and ease of use are high priorities. Infrastructure can be cloud-based (AWS/Azure/GCP) or hybrid. Compliance and best practices for multi-tenant isolation must be addressed.
## Approach
- Provide a modular architecture diagram and component list describing frontend, backend, orchestration, runtime hosting, storage, networking, and integrations.
- Define detailed runtime support plan: how to support PHP (multiple versions), Node.js, and a generic mechanism for adding language runtimes (buildpacks, containers, or custom runtimes). Include process model (FPM, workers), package management, and dependency isolation per site.
- Describe multi-tenancy and isolation strategy (containerization, sandboxing, user namespaces, folder permissions, network policies) and security controls (SELinux/AppArmor, seccomp, kernel hardening, runtime vulnerability scanning).
- Define the dashboard features and workflows: onboarding, site creation, domain and DNS management, SSL issuance (Let’s Encrypt automation), database creation, email setup, file manager UI with cPanel-like features, user roles and permissions, billing/plan management, activity logs, metrics, and alerts.
- Provide detailed file manager specification: UI actions (upload, download, create/delete files and folders, rename, move, copy, edit with syntax highlighting, set permissions/ownership, change timestamps), archive/unarchive (zip/tar), chunked uploads, resumable uploads, quotas, search, preview for images and common file types, and integration with backups and versioning. Include authentication/authorization flows and optimistic locking for concurrent edits.
- Design CI/CD and deployment model: git pushes, webhooks, automated build pipelines, support for Docker-based deployments and traditional PHP deployments (FTP/SFTP, Git-FTP), environment variables, build artifacts, and rollbacks.
- Specify storage architecture: user file storage (object vs block), performance tiers, shared or per-tenant file system, NFS/CSI considerations, backups, snapshots, retention policies, and large file handling.
- Provide database hosting details: managed MySQL/Postgres instances or per-tenant containers, backup and replication strategy, access control, connection pooling.
- Define monitoring, logging, and metrics: per-tenant metrics (CPU, memory, disk, network), centralized logging, alerting, health dashboards, and audit logs.
- Define operational automation: provisioning, autoscaling, failover, update process (zero-downtime deploys), blue/green or canary strategies.
- Provide compliance, data protection, and privacy controls: encryption at rest/in transit, key management, GDPR considerations, and incident response.
- Create an implementation roadmap with milestones, estimated effort (person-months) per major component, priority order (MVP vs later phases), and recommended tech stack choices for frontend, backend, orchestration, CI/CD, and cloud provider options.
- Provide a detailed API specification for programmatic control: RESTful or GraphQL endpoints for site management, file operations, runtime management, DNS, databases, users, and billing. Include example request/response schemas and authentication (OAuth2, API keys).
- Include UI/UX wireframe descriptions (textual) for key pages: dashboard home, site overview, file manager, runtime settings, domain/DNS, database admin, SSL manager, billing, and user management.
- List acceptance criteria and QA test cases for each major feature including security tests (SAST/DAST), multi-tenant isolation tests, performance/load tests, and backup/restore tests.
- Provide a deployment checklist and runbook for operations teams, and a minimal user support knowledge base outline and common troubleshooting steps.
- Provide a developer-ready GitHub repository structure suggestion, CI pipelines, and sample Dockerfiles/buildpacks and a minimal reference implementation plan (prototype) demonstrating hosting a PHP site and a Node.js site.
## Response Format
- Start with a concise executive summary of the product and MVP scope (max 6 bullet points).
- Architecture: provide a numbered list of components with brief descriptions and interactions; include suggested technologies for each component.
- Runtimes: provide a table-like bulleted section listing each runtime (PHP, Node.js, Python, Ruby, Go, Java, .NET) with supported versions, deployment model, and notes on dependency isolation.
- Dashboard: provide feature-by-feature spec with workflows in numbered steps.
- File Manager: provide detailed feature list, UI actions, API endpoints (endpoint, method, request/response example), permission model, and concurrency considerations.
- CI/CD & Deployments: detailed steps for git-based deploys, Docker-based deploys, environment management, and rollback mechanisms.
- Storage & Databases: architecture, options, backup/replication details, and sizing considerations.
- Security & Multi-Tenancy: list of controls, isolation mechanisms, recommended policies, and monitoring practices.
- Monitoring & Logging: list of metrics, log retention, and alerting thresholds examples.
- API Spec: for each main domain (sites, files, dns, db, users, billing), provide 2–3 example endpoints with request/response JSON schemas.
- Roadmap & Estimates: a prioritized milestone list with rough effort estimates and dependencies.
- QA & Acceptance Criteria: checklist with test cases and pass/fail criteria.
- Runbook & Support: an operations checklist and top 10 troubleshooting guides.
- Repo & Reference Implementation: recommended repo layout, CI config outline, and two minimal example Dockerfiles or buildpack snippets (one PHP, one Node.js).
- All sections should be concise but actionable. Use bullet lists and numbered steps; avoid long narrative paragraphs.
## Instructions
- Avoid pronouns; use imperative or neutral voice. Use technical, precise language aimed at engineering and DevOps teams.
- Prioritize security, scalability, and developer ergonomics in every recommendation.
- Provide concrete technology recommendations but also note trade-offs and alternatives where appropriate.
- Provide sample JSON for API schemas and example CLI/API call snippets for common tasks (create site, upload file, issue SSL).
- Ensure the file manager API supports chunked and resumable uploads, file locking, and permission checks.
- For MVP, limit scope to hosting PHP and Node.js with managed MySQL; mark other languages and advanced features as Phase 2 with clear gating criteria.
- Include migration plan for existing cPanel users/sites (import tool strategy).
- Ensure compliance and privacy considerations are addressed for EU and US customers.
- Keep total length focused and actionable; target response length around 800–1,500 words.
- README.md +8 -5
- components/footer.js +150 -0
- components/navbar.js +156 -0
- dashboard.html +214 -0
- index.html +130 -19
- script.js +206 -0
- style.css +101 -18
|
@@ -1,10 +1,13 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: SafeHost Pro - Secure Multi-Runtime Hosting Platform 🚀
|
| 3 |
+
colorFrom: gray
|
| 4 |
+
colorTo: yellow
|
| 5 |
+
emoji: 🐳
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
| 8 |
+
tags:
|
| 9 |
+
- deepsite-v3
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# Welcome to your new DeepSite project!
|
| 13 |
+
This project was created with [DeepSite](https://huggingface.co/deepsite).
|
|
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class CustomFooter extends HTMLElement {
|
| 2 |
+
connectedCallback() {
|
| 3 |
+
this.attachShadow({ mode: 'open' });
|
| 4 |
+
this.shadowRoot.innerHTML = `
|
| 5 |
+
<style>
|
| 6 |
+
footer {
|
| 7 |
+
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
|
| 8 |
+
color: white;
|
| 9 |
+
padding: 3rem 2rem;
|
| 10 |
+
margin-top: auto;
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
.footer-content {
|
| 14 |
+
max-width: 1200px;
|
| 15 |
+
margin: 0 auto;
|
| 16 |
+
display: grid;
|
| 17 |
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
| 18 |
+
gap: 2rem;
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
.footer-section h3 {
|
| 22 |
+
color: #f8fafc;
|
| 23 |
+
margin-bottom: 1rem;
|
| 24 |
+
font-size: 1.125rem;
|
| 25 |
+
font-weight: 600;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
.footer-links {
|
| 29 |
+
list-style: none;
|
| 30 |
+
padding: 0;
|
| 31 |
+
margin: 0;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
.footer-links li {
|
| 35 |
+
margin-bottom: 0.5rem;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
.footer-links a {
|
| 39 |
+
color: #cbd5e1;
|
| 40 |
+
text-decoration: none;
|
| 41 |
+
transition: color 0.3s ease;
|
| 42 |
+
display: flex;
|
| 43 |
+
align-items: center;
|
| 44 |
+
gap: 0.5rem;
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
.footer-links a:hover {
|
| 48 |
+
color: #f8fafc;
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
.social-links {
|
| 52 |
+
display: flex;
|
| 53 |
+
gap: 1rem;
|
| 54 |
+
margin-top: 1rem;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
.social-links a {
|
| 58 |
+
color: #cbd5e1;
|
| 59 |
+
transition: color 0.3s ease;
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
.social-links a:hover {
|
| 63 |
+
color: #f8fafc;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
.footer-bottom {
|
| 67 |
+
max-width: 1200px;
|
| 68 |
+
margin: 2rem auto 0;
|
| 69 |
+
padding-top: 2rem;
|
| 70 |
+
border-top: 1px solid #334155;
|
| 71 |
+
text-align: center;
|
| 72 |
+
color: #94a3b8;
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
@media (max-width: 768px) {
|
| 76 |
+
footer {
|
| 77 |
+
padding: 2rem 1rem;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
.footer-content {
|
| 81 |
+
grid-template-columns: 1fr;
|
| 82 |
+
text-align: center;
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
.social-links {
|
| 86 |
+
justify-content: center;
|
| 87 |
+
}
|
| 88 |
+
}
|
| 89 |
+
</style>
|
| 90 |
+
|
| 91 |
+
<footer>
|
| 92 |
+
<div class="footer-content">
|
| 93 |
+
<div class="footer-section">
|
| 94 |
+
<h3>SafeHost Pro</h3>
|
| 95 |
+
<p style="color: #94a3b8; line-height: 1.6;">
|
| 96 |
+
Enterprise-grade multi-runtime hosting with security-first architecture and advanced file management.
|
| 97 |
+
</p>
|
| 98 |
+
<div class="social-links">
|
| 99 |
+
<a href="#"><i data-feather="github"></i></a>
|
| 100 |
+
<a href="#"><i data-feather="twitter"></i></a>
|
| 101 |
+
<a href="#"><i data-feather="linkedin"></i></a>
|
| 102 |
+
<a href="#"><i data-feather="discord"></i></a>
|
| 103 |
+
</div>
|
| 104 |
+
</div>
|
| 105 |
+
|
| 106 |
+
<div class="footer-section">
|
| 107 |
+
<h3>Product</h3>
|
| 108 |
+
<ul class="footer-links">
|
| 109 |
+
<li><a href="/features.html"><i data-feather="arrow-right"></i> Features</a></li>
|
| 110 |
+
<li><a href="/pricing.html"><i data-feather="arrow-right"></i> Pricing</a></li>
|
| 111 |
+
<li><a href="/security.html"><i data-feather="arrow-right"></i> Security</a></li>
|
| 112 |
+
<li><a href="/status.html"><i data-feather="arrow-right"></i> Status</a></li>
|
| 113 |
+
</ul>
|
| 114 |
+
</div>
|
| 115 |
+
|
| 116 |
+
<div class="footer-section">
|
| 117 |
+
<h3>Resources</h3>
|
| 118 |
+
<ul class="footer-links">
|
| 119 |
+
<li><a href="/docs.html"><i data-feather="arrow-right"></i> Documentation</a></li>
|
| 120 |
+
<li><a href="/tutorials.html"><i data-feather="arrow-right"></i> Tutorials</a></li>
|
| 121 |
+
<li><a href="/blog.html"><i data-feather="arrow-right"></i> Blog</a></li>
|
| 122 |
+
<li><a href="/api.html"><i data-feather="arrow-right"></i> API Reference</a></li>
|
| 123 |
+
</ul>
|
| 124 |
+
</div>
|
| 125 |
+
|
| 126 |
+
<div class="footer-section">
|
| 127 |
+
<h3>Support</h3>
|
| 128 |
+
<ul class="footer-links">
|
| 129 |
+
<li><a href="/help.html"><i data-feather="arrow-right"></i> Help Center</a></li>
|
| 130 |
+
<li><a href="/contact.html"><i data-feather="arrow-right"></i> Contact Us</a></li>
|
| 131 |
+
<li><a href="/community.html"><i data-feather="arrow-right"></i> Community</a></li>
|
| 132 |
+
<li><a href="/enterprise.html"><i data-feather="arrow-right"></i> Enterprise</a></li>
|
| 133 |
+
</ul>
|
| 134 |
+
</div>
|
| 135 |
+
</div>
|
| 136 |
+
|
| 137 |
+
<div class="footer-bottom">
|
| 138 |
+
<p>© 2024 SafeHost Pro. All rights reserved. Built with security in mind.</p>
|
| 139 |
+
</div>
|
| 140 |
+
</footer>
|
| 141 |
+
`;
|
| 142 |
+
|
| 143 |
+
// Initialize feather icons
|
| 144 |
+
this.shadowRoot.querySelectorAll('[data-feather]').forEach(icon => {
|
| 145 |
+
feather.replace(icon);
|
| 146 |
+
});
|
| 147 |
+
}
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
customElements.define('custom-footer', CustomFooter);
|
|
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class CustomNavbar extends HTMLElement {
|
| 2 |
+
connectedCallback() {
|
| 3 |
+
this.attachShadow({ mode: 'open' });
|
| 4 |
+
this.shadowRoot.innerHTML = `
|
| 5 |
+
<style>
|
| 6 |
+
:host {
|
| 7 |
+
display: block;
|
| 8 |
+
position: sticky;
|
| 9 |
+
top: 0;
|
| 10 |
+
z-index: 1000;
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
nav {
|
| 14 |
+
background: linear-gradient(135deg, #1e40af 0%, #3730a3 100%);
|
| 15 |
+
backdrop-filter: blur(10px);
|
| 16 |
+
padding: 1rem 2rem;
|
| 17 |
+
display: flex;
|
| 18 |
+
justify-content: space-between;
|
| 19 |
+
align-items: center;
|
| 20 |
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
| 21 |
+
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
.logo {
|
| 25 |
+
color: white;
|
| 26 |
+
font-weight: bold;
|
| 27 |
+
font-size: 1.5rem;
|
| 28 |
+
display: flex;
|
| 29 |
+
align-items: center;
|
| 30 |
+
gap: 0.5rem;
|
| 31 |
+
text-decoration: none;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
.nav-links {
|
| 35 |
+
display: flex;
|
| 36 |
+
gap: 2rem;
|
| 37 |
+
list-style: none;
|
| 38 |
+
margin: 0;
|
| 39 |
+
padding: 0;
|
| 40 |
+
align-items: center;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
.nav-links a {
|
| 44 |
+
color: rgba(255, 255, 255, 0.9);
|
| 45 |
+
text-decoration: none;
|
| 46 |
+
font-weight: 500;
|
| 47 |
+
transition: color 0.3s ease;
|
| 48 |
+
display: flex;
|
| 49 |
+
align-items: center;
|
| 50 |
+
gap: 0.5rem;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
.nav-links a:hover {
|
| 54 |
+
color: white;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
.nav-actions {
|
| 58 |
+
display: flex;
|
| 59 |
+
align-items: center;
|
| 60 |
+
gap: 1rem;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
.btn {
|
| 64 |
+
padding: 0.5rem 1.5rem;
|
| 65 |
+
border-radius: 0.5rem;
|
| 66 |
+
font-weight: 500;
|
| 67 |
+
transition: all 0.3s ease;
|
| 68 |
+
text-decoration: none;
|
| 69 |
+
display: inline-flex;
|
| 70 |
+
align-items: center;
|
| 71 |
+
gap: 0.5rem;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
.btn-primary {
|
| 75 |
+
background: rgba(255, 255, 255, 0.2);
|
| 76 |
+
color: white;
|
| 77 |
+
border: 1px solid rgba(255, 255, 255, 0.3);
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
.btn-primary:hover {
|
| 81 |
+
background: rgba(255, 255, 255, 0.3);
|
| 82 |
+
transform: translateY(-1px);
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
.btn-secondary {
|
| 86 |
+
background: white;
|
| 87 |
+
color: #1e40af;
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
.btn-secondary:hover {
|
| 91 |
+
background: #f8fafc;
|
| 92 |
+
transform: translateY(-1px);
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
.mobile-menu-btn {
|
| 96 |
+
display: none;
|
| 97 |
+
background: none;
|
| 98 |
+
border: none;
|
| 99 |
+
color: white;
|
| 100 |
+
cursor: pointer;
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
@media (max-width: 768px) {
|
| 104 |
+
nav {
|
| 105 |
+
padding: 1rem;
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
.nav-links {
|
| 109 |
+
display: none;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
.mobile-menu-btn {
|
| 113 |
+
display: block;
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
.nav-actions {
|
| 117 |
+
display: none;
|
| 118 |
+
}
|
| 119 |
+
}
|
| 120 |
+
</style>
|
| 121 |
+
|
| 122 |
+
<nav>
|
| 123 |
+
<a href="/" class="logo">
|
| 124 |
+
<i data-feather="shield"></i>
|
| 125 |
+
SafeHost Pro
|
| 126 |
+
</a>
|
| 127 |
+
|
| 128 |
+
<ul class="nav-links">
|
| 129 |
+
<li><a href="/features.html"><i data-feather="grid"></i> Features</a></li>
|
| 130 |
+
<li><a href="/pricing.html"><i data-feather="dollar-sign"></i> Pricing</a></li>
|
| 131 |
+
<li><a href="/docs.html"><i data-feather="book"></i> Docs</a></li>
|
| 132 |
+
<li><a href="/support.html"><i data-feather="help-circle"></i> Support</a></li>
|
| 133 |
+
</ul>
|
| 134 |
+
|
| 135 |
+
<div class="nav-actions">
|
| 136 |
+
<a href="/login.html" class="btn btn-primary" data-auth="hide-if-authenticated">
|
| 137 |
+
<i data-feather="log-in"></i> Sign In
|
| 138 |
+
</a>
|
| 139 |
+
<a href="/dashboard.html" class="btn btn-secondary" data-auth="show-if-authenticated" style="display: none;">
|
| 140 |
+
<i data-feather="layout"></i> Dashboard
|
| 141 |
+
</a>
|
| 142 |
+
<button class="mobile-menu-btn" id="mobile-menu-btn">
|
| 143 |
+
<i data-feather="menu"></i>
|
| 144 |
+
</button>
|
| 145 |
+
</div>
|
| 146 |
+
</nav>
|
| 147 |
+
`;
|
| 148 |
+
|
| 149 |
+
// Initialize feather icons
|
| 150 |
+
this.shadowRoot.querySelectorAll('[data-feather]').forEach(icon => {
|
| 151 |
+
feather.replace(icon);
|
| 152 |
+
});
|
| 153 |
+
}
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
customElements.define('custom-navbar', CustomNavbar);
|
|
@@ -0,0 +1,214 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
<title>Dashboard - SafeHost Pro</title>
|
| 7 |
+
<link rel="stylesheet" href="style.css">
|
| 8 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 9 |
+
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
| 10 |
+
<script src="https://unpkg.com/feather-icons"></script>
|
| 11 |
+
</head>
|
| 12 |
+
<body class="bg-gray-50 min-h-screen">
|
| 13 |
+
<custom-navbar></custom-navbar>
|
| 14 |
+
|
| 15 |
+
<div class="container mx-auto px-4 py-8">
|
| 16 |
+
<div class="grid grid-cols-1 lg:grid-cols-4 gap-6">
|
| 17 |
+
<!-- Sidebar -->
|
| 18 |
+
<aside class="lg:col-span-1">
|
| 19 |
+
<div class="bg-white rounded-xl shadow-lg p-6 sticky top-24">
|
| 20 |
+
<div class="flex items-center gap-4 mb-6">
|
| 21 |
+
<div class="w-12 h-12 bg-gradient-to-r from-blue-500 to-purple-500 rounded-full flex items-center justify-center text-white font-semibold">
|
| 22 |
+
JD
|
| 23 |
+
</div>
|
| 24 |
+
<div>
|
| 25 |
+
<h3 class="font-semibold text-gray-900">John Doe</h3>
|
| 26 |
+
<p class="text-sm text-gray-500">Pro Plan</p>
|
| 27 |
+
</div>
|
| 28 |
+
</div>
|
| 29 |
+
|
| 30 |
+
<nav class="space-y-2">
|
| 31 |
+
<a href="/dashboard.html" class="flex items-center gap-3 px-4 py-3 bg-blue-50 text-blue-600 rounded-lg font-medium">
|
| 32 |
+
<i data-feather="layout" class="w-5 h-5"></i>
|
| 33 |
+
Overview
|
| 34 |
+
</a>
|
| 35 |
+
<a href="/sites.html" class="flex items-center gap-3 px-4 py-3 text-gray-600 hover:bg-gray-50 rounded-lg transition-colors">
|
| 36 |
+
<i data-feather="globe" class="w-5 h-5"></i>
|
| 37 |
+
Sites
|
| 38 |
+
</a>
|
| 39 |
+
<a href="/file-manager.html" class="flex items-center gap-3 px-4 py-3 text-gray-600 hover:bg-gray-50 rounded-lg transition-colors">
|
| 40 |
+
<i data-feather="folder" class="w-5 h-5"></i>
|
| 41 |
+
File Manager
|
| 42 |
+
</a>
|
| 43 |
+
<a href="/databases.html" class="flex items-center gap-3 px-4 py-3 text-gray-600 hover:bg-gray-50 rounded-lg transition-colors">
|
| 44 |
+
<i data-feather="database" class="w-5 h-5"></i>
|
| 45 |
+
Databases
|
| 46 |
+
</a>
|
| 47 |
+
<a href="/domains.html" class="flex items-center gap-3 px-4 py-3 text-gray-600 hover:bg-gray-50 rounded-lg transition-colors">
|
| 48 |
+
<i data-feather="link" class="w-5 h-5"></i>
|
| 49 |
+
Domains
|
| 50 |
+
</a>
|
| 51 |
+
<a href="/settings.html" class="flex items-center gap-3 px-4 py-3 text-gray-600 hover:bg-gray-50 rounded-lg transition-colors">
|
| 52 |
+
<i data-feather="settings" class="w-5 h-5"></i>
|
| 53 |
+
Settings
|
| 54 |
+
</a>
|
| 55 |
+
</nav>
|
| 56 |
+
|
| 57 |
+
<div class="mt-8 pt-6 border-t border-gray-200">
|
| 58 |
+
<div class="flex items-center justify-between text-sm text-gray-500 mb-2">
|
| 59 |
+
<span>Storage</span>
|
| 60 |
+
<span>2.3/10 GB</span>
|
| 61 |
+
</div>
|
| 62 |
+
<div class="w-full bg-gray-200 rounded-full h-2">
|
| 63 |
+
<div class="bg-blue-500 h-2 rounded-full" style="width: 23%"></div>
|
| 64 |
+
</div>
|
| 65 |
+
</div>
|
| 66 |
+
</div>
|
| 67 |
+
</aside>
|
| 68 |
+
|
| 69 |
+
<!-- Main Content -->
|
| 70 |
+
<main class="lg:col-span-3">
|
| 71 |
+
<div class="bg-white rounded-xl shadow-lg p-6 mb-6">
|
| 72 |
+
<div class="flex justify-between items-center mb-6">
|
| 73 |
+
<h1 class="text-2xl font-bold text-gray-900">Dashboard Overview</h1>
|
| 74 |
+
<button class="bg-blue-600 text-white px-4 py-2 rounded-lg flex items-center gap-2 hover:bg-blue-700 transition-colors">
|
| 75 |
+
<i data-feather="plus" class="w-4 h-4"></i>
|
| 76 |
+
New Site
|
| 77 |
+
</button>
|
| 78 |
+
</div>
|
| 79 |
+
|
| 80 |
+
<!-- Stats Grid -->
|
| 81 |
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
|
| 82 |
+
<div class="bg-blue-50 p-4 rounded-lg">
|
| 83 |
+
<div class="flex items-center justify-between">
|
| 84 |
+
<div>
|
| 85 |
+
<p class="text-sm text-blue-600">Active Sites</p>
|
| 86 |
+
<p class="text-2xl font-bold text-gray-900">3</p>
|
| 87 |
+
</div>
|
| 88 |
+
<i data-feather="globe" class="w-8 h-8 text-blue-400"></i>
|
| 89 |
+
</div>
|
| 90 |
+
</div>
|
| 91 |
+
|
| 92 |
+
<div class="bg-green-50 p-4 rounded-lg">
|
| 93 |
+
<div class="flex items-center justify-between">
|
| 94 |
+
<div>
|
| 95 |
+
<p class="text-sm text-green-600">Databases</p>
|
| 96 |
+
<p class="text-2xl font-bold text-gray-900">2</p>
|
| 97 |
+
</div>
|
| 98 |
+
<i data-feather="database" class="w-8 h-8 text-green-400"></i>
|
| 99 |
+
</div>
|
| 100 |
+
</div>
|
| 101 |
+
|
| 102 |
+
<div class="bg-purple-50 p-4 rounded-lg">
|
| 103 |
+
<div class="flex items-center justify-between">
|
| 104 |
+
<div>
|
| 105 |
+
<p class="text-sm text-purple-600">Domains</p>
|
| 106 |
+
<p class="text-2xl font-bold text-gray-900">1</p>
|
| 107 |
+
</div>
|
| 108 |
+
<i data-feather="link" class="w-8 h-8 text-purple-400"></i>
|
| 109 |
+
</div>
|
| 110 |
+
</div>
|
| 111 |
+
|
| 112 |
+
<div class="bg-orange-50 p-4 rounded-lg">
|
| 113 |
+
<div class="flex items-center justify-between">
|
| 114 |
+
<div>
|
| 115 |
+
<p class="text-sm text-orange-600">Storage Used</p>
|
| 116 |
+
<p class="text-2xl font-bold text-gray-900">2.3 GB</p>
|
| 117 |
+
</div>
|
| 118 |
+
<i data-feather="hard-drive" class="w-8 h-8 text-orange-400"></i>
|
| 119 |
+
</div>
|
| 120 |
+
</div>
|
| 121 |
+
</div>
|
| 122 |
+
|
| 123 |
+
<!-- Recent Activity -->
|
| 124 |
+
<div>
|
| 125 |
+
<h2 class="text-lg font-semibold text-gray-900 mb-4">Recent Activity</h2>
|
| 126 |
+
<div class="space-y-3">
|
| 127 |
+
<div class="flex items-center gap-4 p-3 bg-gray-50 rounded-lg">
|
| 128 |
+
<div class="w-8 h-8 bg-green-100 rounded-full flex items-center justify-center">
|
| 129 |
+
<i data-feather="check-circle" class="w-4 h-4 text-green-600"></i>
|
| 130 |
+
</div>
|
| 131 |
+
<div class="flex-1">
|
| 132 |
+
<p class="text-sm font-medium">Site deployed successfully</p>
|
| 133 |
+
<p class="text-xs text-gray-500">my-app.safehost.pro • 2 minutes ago</p>
|
| 134 |
+
</div>
|
| 135 |
+
</div>
|
| 136 |
+
|
| 137 |
+
<div class="flex items-center gap-4 p-3 bg-gray-50 rounded-lg">
|
| 138 |
+
<div class="w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center">
|
| 139 |
+
<i data-feather="database" class="w-4 h-4 text-blue-600"></i>
|
| 140 |
+
</div>
|
| 141 |
+
<div class="flex-1">
|
| 142 |
+
<p class="text-sm font-medium">Database backup completed</p>
|
| 143 |
+
<p class="text-xs text-gray-500">production_db • 1 hour ago</p>
|
| 144 |
+
</div>
|
| 145 |
+
</div>
|
| 146 |
+
|
| 147 |
+
<div class="flex items-center gap-4 p-3 bg-gray-50 rounded-lg">
|
| 148 |
+
<div class="w-8 h-8 bg-purple-100 rounded-full flex items-center justify-center">
|
| 149 |
+
<i data-feather="shield" class="w-4 h-4 text-purple-600"></i>
|
| 150 |
+
</div>
|
| 151 |
+
<div class="flex-1">
|
| 152 |
+
<p class="text-sm font-medium">SSL certificate renewed</p>
|
| 153 |
+
<p class="text-xs text-gray-500">example.com • 3 hours ago</p>
|
| 154 |
+
</div>
|
| 155 |
+
</div>
|
| 156 |
+
</div>
|
| 157 |
+
</div>
|
| 158 |
+
</div>
|
| 159 |
+
|
| 160 |
+
<!-- Quick Actions -->
|
| 161 |
+
<div class="bg-white rounded-xl shadow-lg p-6">
|
| 162 |
+
<h2 class="text-lg font-semibold text-gray-900 mb-4">Quick Actions</h2>
|
| 163 |
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
| 164 |
+
<a href="/file-manager.html" class="p-4 border-2 border-gray-200 rounded-lg hover:border-blue-300 hover:bg-blue-50 transition-colors group">
|
| 165 |
+
<div class="flex items-center gap-3">
|
| 166 |
+
<div class="w-10 h-10 bg-blue-100 rounded-lg flex items-center justify-center group-hover:bg-blue-200 transition-colors">
|
| 167 |
+
<i data-feather="folder" class="text-blue-600"></i>
|
| 168 |
+
</div>
|
| 169 |
+
<div>
|
| 170 |
+
<p class="font-medium">File Manager</p>
|
| 171 |
+
<p class="text-sm text-gray-500">Manage your files</p>
|
| 172 |
+
</div>
|
| 173 |
+
</div>
|
| 174 |
+
</a>
|
| 175 |
+
|
| 176 |
+
<a href="/databases.html" class="p-4 border-2 border-gray-200 rounded-lg hover:border-green-300 hover:bg-green-50 transition-colors group">
|
| 177 |
+
<div class="flex items-center gap-3">
|
| 178 |
+
<div class="w-10 h-10 bg-green-100 rounded-lg flex items-center justify-center group-hover:bg-green-200 transition-colors">
|
| 179 |
+
<i data-feather="database" class="text-green-600"></i>
|
| 180 |
+
</div>
|
| 181 |
+
<div>
|
| 182 |
+
<p class="font-medium">Databases</p>
|
| 183 |
+
<p class="text-sm text-gray-500">Manage databases</p>
|
| 184 |
+
</div>
|
| 185 |
+
</div>
|
| 186 |
+
</a>
|
| 187 |
+
|
| 188 |
+
<a href="/domains.html" class="p-4 border-2 border-gray-200 rounded-lg hover:border-purple-300 hover:bg-purple-50 transition-colors group">
|
| 189 |
+
<div class="flex items-center gap-3">
|
| 190 |
+
<div class="w-10 h-10 bg-purple-100 rounded-lg flex items-center justify-center group-hover:bg-purple-200 transition-colors">
|
| 191 |
+
<i data-feather="link" class="text-purple-600"></i>
|
| 192 |
+
</div>
|
| 193 |
+
<div>
|
| 194 |
+
<p class="font-medium">Domains</p>
|
| 195 |
+
<p class="text-sm text-gray-500">Configure domains</p>
|
| 196 |
+
</div>
|
| 197 |
+
</div>
|
| 198 |
+
</a>
|
| 199 |
+
</div>
|
| 200 |
+
</div>
|
| 201 |
+
</main>
|
| 202 |
+
</div>
|
| 203 |
+
</div>
|
| 204 |
+
|
| 205 |
+
<custom-footer></custom-footer>
|
| 206 |
+
|
| 207 |
+
<script src="components/navbar.js"></script>
|
| 208 |
+
<script src="components/footer.js"></script>
|
| 209 |
+
<script src="script.js"></script>
|
| 210 |
+
<script>
|
| 211 |
+
feather.replace();
|
| 212 |
+
</script>
|
| 213 |
+
</body>
|
| 214 |
+
</html>
|
|
@@ -1,19 +1,130 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
+
<title>SafeHost Pro - Secure Web Hosting Platform</title>
|
| 7 |
+
<link rel="stylesheet" href="style.css">
|
| 8 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 9 |
+
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
| 10 |
+
<script src="https://unpkg.com/feather-icons"></script>
|
| 11 |
+
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.globe.min.js"></script>
|
| 12 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
| 13 |
+
</head>
|
| 14 |
+
<body class="bg-gray-50 min-h-screen">
|
| 15 |
+
<custom-navbar></custom-navbar>
|
| 16 |
+
|
| 17 |
+
<main class="container mx-auto px-4 py-8">
|
| 18 |
+
<!-- Hero Section -->
|
| 19 |
+
<section class="relative overflow-hidden py-20">
|
| 20 |
+
<div id="vanta-bg" class="absolute inset-0 z-0"></div>
|
| 21 |
+
<div class="relative z-10 max-w-7xl mx-auto text-center">
|
| 22 |
+
<h1 class="text-5xl md:text-6xl font-bold text-gray-900 mb-6">
|
| 23 |
+
Secure Multi-Runtime Hosting
|
| 24 |
+
</h1>
|
| 25 |
+
<p class="text-xl md:text-2xl text-gray-700 mb-8 max-w-3xl mx-auto">
|
| 26 |
+
Deploy PHP, Node.js, and multiple languages with enterprise-grade security and cPanel-like file management
|
| 27 |
+
</p>
|
| 28 |
+
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
| 29 |
+
<a href="/dashboard.html" class="bg-blue-600 hover:bg-blue-700 text-white px-8 py-3 rounded-lg font-semibold text-lg transition-colors">
|
| 30 |
+
Launch Dashboard
|
| 31 |
+
</a>
|
| 32 |
+
<a href="/features.html" class="border-2 border-blue-600 text-blue-600 hover:bg-blue-50 px-8 py-3 rounded-lg font-semibold text-lg transition-colors">
|
| 33 |
+
View Features
|
| 34 |
+
</a>
|
| 35 |
+
</div>
|
| 36 |
+
</div>
|
| 37 |
+
</section>
|
| 38 |
+
|
| 39 |
+
<!-- Features Grid -->
|
| 40 |
+
<section class="py-16">
|
| 41 |
+
<div class="text-center mb-12">
|
| 42 |
+
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 mb-4">Everything You Need</h2>
|
| 43 |
+
<p class="text-lg text-gray-600 max-w-2xl mx-auto">Multi-tenant hosting with security-first architecture</p>
|
| 44 |
+
</div>
|
| 45 |
+
|
| 46 |
+
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
| 47 |
+
<div class="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition-shadow">
|
| 48 |
+
<div class="w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center mb-4">
|
| 49 |
+
<i data-feather="code" class="text-blue-600"></i>
|
| 50 |
+
</div>
|
| 51 |
+
<h3 class="text-xl font-semibold mb-3">Multi-Runtime Support</h3>
|
| 52 |
+
<p class="text-gray-600">PHP, Node.js, Python, Ruby, Go, Java, .NET with version management</p>
|
| 53 |
+
</div>
|
| 54 |
+
|
| 55 |
+
<div class="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition-shadow">
|
| 56 |
+
<div class="w-12 h-12 bg-green-100 rounded-lg flex items-center justify-center mb-4">
|
| 57 |
+
<i data-feather="shield" class="text-green-600"></i>
|
| 58 |
+
</div>
|
| 59 |
+
<h3 class="text-xl font-semibold mb-3">Security First</h3>
|
| 60 |
+
<p class="text-gray-600">Container isolation, SELinux, vulnerability scanning, and automated SSL</p>
|
| 61 |
+
</div>
|
| 62 |
+
|
| 63 |
+
<div class="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition-shadow">
|
| 64 |
+
<div class="w-12 h-12 bg-purple-100 rounded-lg flex items-center justify-center mb-4">
|
| 65 |
+
<i data-feather="folder" class="text-purple-600"></i>
|
| 66 |
+
</div>
|
| 67 |
+
<h3 class="text-xl font-semibold mb-3">Advanced File Manager</h3>
|
| 68 |
+
<p class="text-gray-600">cPanel-like interface with drag-drop, editing, permissions, and backups</p>
|
| 69 |
+
</div>
|
| 70 |
+
|
| 71 |
+
<div class="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition-shadow">
|
| 72 |
+
<div class="w-12 h-12 bg-orange-100 rounded-lg flex items-center justify-center mb-4">
|
| 73 |
+
<i data-feather="database" class="text-orange-600"></i>
|
| 74 |
+
</div>
|
| 75 |
+
<h3 class="text-xl font-semibold mb-3">Managed Databases</h3>
|
| 76 |
+
<p class="text-gray-600">MySQL & PostgreSQL with automated backups and replication</p>
|
| 77 |
+
</div>
|
| 78 |
+
|
| 79 |
+
<div class="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition-shadow">
|
| 80 |
+
<div class="w-12 h-12 bg-red-100 rounded-lg flex items-center justify-center mb-4">
|
| 81 |
+
<i data-feather="git-merge" class="text-red-600"></i>
|
| 82 |
+
</div>
|
| 83 |
+
<h3 class="text-xl font-semibold mb-3">CI/CD Integration</h3>
|
| 84 |
+
<p class="text-gray-600">Git deployment, webhooks, Docker support, and automated pipelines</p>
|
| 85 |
+
</div>
|
| 86 |
+
|
| 87 |
+
<div class="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition-shadow">
|
| 88 |
+
<div class="w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-4">
|
| 89 |
+
<i data-feather="bar-chart-2" class="text-indigo-600"></i>
|
| 90 |
+
</div>
|
| 91 |
+
<h3 class="text-xl font-semibold mb-3">Real-time Monitoring</h3>
|
| 92 |
+
<p class="text-gray-600">Resource metrics, logs, alerts, and performance insights</p>
|
| 93 |
+
</div>
|
| 94 |
+
</div>
|
| 95 |
+
</section>
|
| 96 |
+
|
| 97 |
+
<!-- CTA Section -->
|
| 98 |
+
<section class="bg-gradient-to-r from-blue-600 to-purple-600 rounded-2xl p-12 text-center text-white mb-16">
|
| 99 |
+
<h2 class="text-3xl md:text-4xl font-bold mb-6">Ready to Deploy Securely?</h2>
|
| 100 |
+
<p class="text-xl mb-8 max-w-2xl mx-auto">Join thousands of developers trusting SafeHost Pro for their production workloads</p>
|
| 101 |
+
<a href="/signup.html" class="bg-white text-blue-600 px-8 py-4 rounded-lg font-semibold text-lg hover:bg-gray-100 transition-colors inline-block">
|
| 102 |
+
Start Free Trial
|
| 103 |
+
</a>
|
| 104 |
+
</section>
|
| 105 |
+
</main>
|
| 106 |
+
|
| 107 |
+
<custom-footer></custom-footer>
|
| 108 |
+
|
| 109 |
+
<script src="components/navbar.js"></script>
|
| 110 |
+
<script src="components/footer.js"></script>
|
| 111 |
+
<script src="script.js"></script>
|
| 112 |
+
<script>
|
| 113 |
+
feather.replace();
|
| 114 |
+
// Initialize Vanta.js background
|
| 115 |
+
VANTA.GLOBE({
|
| 116 |
+
el: "#vanta-bg",
|
| 117 |
+
mouseControls: true,
|
| 118 |
+
touchControls: true,
|
| 119 |
+
gyroControls: false,
|
| 120 |
+
minHeight: 200.00,
|
| 121 |
+
minWidth: 200.00,
|
| 122 |
+
scale: 1.00,
|
| 123 |
+
scaleMobile: 1.00,
|
| 124 |
+
color: 0x3b82f6,
|
| 125 |
+
backgroundColor: 0xf8fafc
|
| 126 |
+
});
|
| 127 |
+
</script>
|
| 128 |
+
<script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
|
| 129 |
+
</body>
|
| 130 |
+
</html>
|
|
@@ -0,0 +1,206 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// SafeHost Pro - Global JavaScript
|
| 2 |
+
class SafeHostApp {
|
| 3 |
+
constructor() {
|
| 4 |
+
this.init();
|
| 5 |
+
}
|
| 6 |
+
|
| 7 |
+
init() {
|
| 8 |
+
console.log('SafeHost Pro initialized');
|
| 9 |
+
this.setupEventListeners();
|
| 10 |
+
this.checkAuthStatus();
|
| 11 |
+
this.loadUserPreferences();
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
setupEventListeners() {
|
| 15 |
+
// Mobile menu toggle
|
| 16 |
+
const mobileMenuBtn = document.getElementById('mobile-menu-btn');
|
| 17 |
+
const mobileMenu = document.getElementById('mobile-menu');
|
| 18 |
+
|
| 19 |
+
if (mobileMenuBtn && mobileMenu) {
|
| 20 |
+
mobileMenuBtn.addEventListener('click', () => {
|
| 21 |
+
mobileMenu.classList.toggle('hidden');
|
| 22 |
+
});
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
// Theme switcher
|
| 26 |
+
const themeToggle = document.getElementById('theme-toggle');
|
| 27 |
+
if (themeToggle) {
|
| 28 |
+
themeToggle.addEventListener('click', this.toggleTheme.bind(this));
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
// Smooth scrolling for anchor links
|
| 32 |
+
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
| 33 |
+
anchor.addEventListener('click', function (e) {
|
| 34 |
+
e.preventDefault();
|
| 35 |
+
const target = document.querySelector(this.getAttribute('href'));
|
| 36 |
+
if (target) {
|
| 37 |
+
target.scrollIntoView({
|
| 38 |
+
behavior: 'smooth',
|
| 39 |
+
block: 'start'
|
| 40 |
+
});
|
| 41 |
+
}
|
| 42 |
+
});
|
| 43 |
+
});
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
checkAuthStatus() {
|
| 47 |
+
// Check if user is logged in (placeholder)
|
| 48 |
+
const token = localStorage.getItem('authToken');
|
| 49 |
+
if (token) {
|
| 50 |
+
this.updateUIForLoggedIn();
|
| 51 |
+
}
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
updateUIForLoggedIn() {
|
| 55 |
+
// Update navigation and UI for authenticated users
|
| 56 |
+
const authElements = document.querySelectorAll('[data-auth]');
|
| 57 |
+
authElements.forEach(el => {
|
| 58 |
+
const action = el.getAttribute('data-auth');
|
| 59 |
+
if (action === 'hide-if-authenticated') {
|
| 60 |
+
el.style.display = 'none';
|
| 61 |
+
} else if (action === 'show-if-authenticated') {
|
| 62 |
+
el.style.display = 'block';
|
| 63 |
+
}
|
| 64 |
+
});
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
toggleTheme() {
|
| 68 |
+
const html = document.documentElement;
|
| 69 |
+
const currentTheme = html.getAttribute('data-theme');
|
| 70 |
+
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
| 71 |
+
|
| 72 |
+
html.setAttribute('data-theme', newTheme);
|
| 73 |
+
localStorage.setItem('theme', newTheme);
|
| 74 |
+
|
| 75 |
+
this.updateThemeIcon(newTheme);
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
updateThemeIcon(theme) {
|
| 79 |
+
const themeIcon = document.getElementById('theme-icon');
|
| 80 |
+
if (themeIcon) {
|
| 81 |
+
themeIcon.setAttribute('data-feather', theme === 'dark' ? 'sun' : 'moon');
|
| 82 |
+
feather.replace();
|
| 83 |
+
}
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
loadUserPreferences() {
|
| 87 |
+
// Load saved theme preference
|
| 88 |
+
const savedTheme = localStorage.getItem('theme') || 'light';
|
| 89 |
+
document.documentElement.setAttribute('data-theme', savedTheme);
|
| 90 |
+
this.updateThemeIcon(savedTheme);
|
| 91 |
+
|
| 92 |
+
// Load other user preferences
|
| 93 |
+
const preferences = JSON.parse(localStorage.getItem('userPreferences') || '{}');
|
| 94 |
+
this.applyPreferences(preferences);
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
applyPreferences(preferences) {
|
| 98 |
+
// Apply user preferences to UI
|
| 99 |
+
if (preferences.animationsDisabled) {
|
| 100 |
+
document.body.classList.add('no-animations');
|
| 101 |
+
}
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
// API helper methods
|
| 105 |
+
async apiCall(endpoint, options = {}) {
|
| 106 |
+
const baseURL = 'https://api.safehost.pro';
|
| 107 |
+
const token = localStorage.getItem('authToken');
|
| 108 |
+
|
| 109 |
+
const defaultOptions = {
|
| 110 |
+
headers: {
|
| 111 |
+
'Content-Type': 'application/json',
|
| 112 |
+
'Authorization': token ? `Bearer ${token}` : ''
|
| 113 |
+
}
|
| 114 |
+
};
|
| 115 |
+
|
| 116 |
+
try {
|
| 117 |
+
const response = await fetch(`${baseURL}${endpoint}`, {
|
| 118 |
+
...defaultOptions,
|
| 119 |
+
...options
|
| 120 |
+
});
|
| 121 |
+
|
| 122 |
+
if (!response.ok) {
|
| 123 |
+
throw new Error(`API error: ${response.status}`);
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
return await response.json();
|
| 127 |
+
} catch (error) {
|
| 128 |
+
console.error('API call failed:', error);
|
| 129 |
+
this.showNotification('Connection error. Please try again.', 'error');
|
| 130 |
+
throw error;
|
| 131 |
+
}
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
showNotification(message, type = 'info') {
|
| 135 |
+
// Create and show notification toast
|
| 136 |
+
const toast = document.createElement('div');
|
| 137 |
+
toast.className = `fixed top-4 right-4 px-6 py-3 rounded-lg shadow-lg text-white ${
|
| 138 |
+
type === 'error' ? 'bg-red-500' :
|
| 139 |
+
type === 'success' ? 'bg-green-500' : 'bg-blue-500'
|
| 140 |
+
} z-50`;
|
| 141 |
+
toast.textContent = message;
|
| 142 |
+
|
| 143 |
+
document.body.appendChild(toast);
|
| 144 |
+
|
| 145 |
+
setTimeout(() => {
|
| 146 |
+
toast.remove();
|
| 147 |
+
}, 3000);
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
// File upload helper
|
| 151 |
+
async uploadFile(file, onProgress = null) {
|
| 152 |
+
const formData = new FormData();
|
| 153 |
+
formData.append('file', file);
|
| 154 |
+
|
| 155 |
+
try {
|
| 156 |
+
const response = await fetch('/api/upload', {
|
| 157 |
+
method: 'POST',
|
| 158 |
+
body: formData,
|
| 159 |
+
onUploadProgress: onProgress
|
| 160 |
+
});
|
| 161 |
+
|
| 162 |
+
return await response.json();
|
| 163 |
+
} catch (error) {
|
| 164 |
+
console.error('Upload failed:', error);
|
| 165 |
+
throw error;
|
| 166 |
+
}
|
| 167 |
+
}
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
// Initialize app when DOM is loaded
|
| 171 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 172 |
+
window.safeHostApp = new SafeHostApp();
|
| 173 |
+
});
|
| 174 |
+
|
| 175 |
+
// Utility functions
|
| 176 |
+
const utils = {
|
| 177 |
+
formatBytes(bytes, decimals = 2) {
|
| 178 |
+
if (bytes === 0) return '0 Bytes';
|
| 179 |
+
const k = 1024;
|
| 180 |
+
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
| 181 |
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
| 182 |
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) + ' ' + sizes[i];
|
| 183 |
+
},
|
| 184 |
+
|
| 185 |
+
formatDate(date) {
|
| 186 |
+
return new Date(date).toLocaleDateString('en-US', {
|
| 187 |
+
year: 'numeric',
|
| 188 |
+
month: 'short',
|
| 189 |
+
day: 'numeric',
|
| 190 |
+
hour: '2-digit',
|
| 191 |
+
minute: '2-digit'
|
| 192 |
+
});
|
| 193 |
+
},
|
| 194 |
+
|
| 195 |
+
debounce(func, wait) {
|
| 196 |
+
let timeout;
|
| 197 |
+
return function executedFunction(...args) {
|
| 198 |
+
const later = () => {
|
| 199 |
+
clearTimeout(timeout);
|
| 200 |
+
func(...args);
|
| 201 |
+
};
|
| 202 |
+
clearTimeout(timeout);
|
| 203 |
+
timeout = setTimeout(later, wait);
|
| 204 |
+
};
|
| 205 |
+
}
|
| 206 |
+
};
|
|
@@ -1,28 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
body {
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
}
|
| 5 |
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
}
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
font-size: 15px;
|
| 14 |
-
margin-bottom: 10px;
|
| 15 |
-
margin-top: 5px;
|
| 16 |
}
|
| 17 |
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
padding: 16px;
|
| 22 |
-
border: 1px solid lightgray;
|
| 23 |
-
border-radius: 16px;
|
| 24 |
}
|
| 25 |
|
| 26 |
-
|
| 27 |
-
|
|
|
|
|
|
|
| 28 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* SafeHost Pro - Global Styles */
|
| 2 |
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
|
| 3 |
+
|
| 4 |
+
* {
|
| 5 |
+
margin: 0;
|
| 6 |
+
padding: 0;
|
| 7 |
+
box-sizing: border-box;
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
body {
|
| 11 |
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
| 12 |
+
line-height: 1.6;
|
| 13 |
+
color: #1f2937;
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
.container {
|
| 17 |
+
max-width: 1200px;
|
| 18 |
+
margin: 0 auto;
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
/* Custom scrollbar */
|
| 22 |
+
::-webkit-scrollbar {
|
| 23 |
+
width: 8px;
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
::-webkit-scrollbar-track {
|
| 27 |
+
background: #f1f5f9;
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
::-webkit-scrollbar-thumb {
|
| 31 |
+
background: #cbd5e1;
|
| 32 |
+
border-radius: 4px;
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
::-webkit-scrollbar-thumb:hover {
|
| 36 |
+
background: #94a3b8;
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
/* Animation classes */
|
| 40 |
+
.fade-in {
|
| 41 |
+
animation: fadeIn 0.6s ease-in;
|
| 42 |
}
|
| 43 |
|
| 44 |
+
@keyframes fadeIn {
|
| 45 |
+
from { opacity: 0; transform: translateY(20px); }
|
| 46 |
+
to { opacity: 1; transform: translateY(0); }
|
| 47 |
}
|
| 48 |
|
| 49 |
+
.slide-in {
|
| 50 |
+
animation: slideIn 0.8s ease-out;
|
|
|
|
|
|
|
|
|
|
| 51 |
}
|
| 52 |
|
| 53 |
+
@keyframes slideIn {
|
| 54 |
+
from { transform: translateX(-30px); opacity: 0; }
|
| 55 |
+
to { transform: translateX(0); opacity: 1; }
|
|
|
|
|
|
|
|
|
|
| 56 |
}
|
| 57 |
|
| 58 |
+
/* Button hover effects */
|
| 59 |
+
.btn-hover {
|
| 60 |
+
transition: all 0.3s ease;
|
| 61 |
+
transform: translateY(0);
|
| 62 |
}
|
| 63 |
+
|
| 64 |
+
.btn-hover:hover {
|
| 65 |
+
transform: translateY(-2px);
|
| 66 |
+
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1);
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
/* Card hover effects */
|
| 70 |
+
.card-hover {
|
| 71 |
+
transition: all 0.3s ease;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
.card-hover:hover {
|
| 75 |
+
transform: translateY(-4px);
|
| 76 |
+
box-shadow: 0 20px 40px -10px rgba(0, 0, 0, 0.15);
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
/* Responsive text sizes */
|
| 80 |
+
@media (max-width: 640px) {
|
| 81 |
+
.responsive-text {
|
| 82 |
+
font-size: 0.875rem;
|
| 83 |
+
}
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
/* Loading spinner */
|
| 87 |
+
.spinner {
|
| 88 |
+
border: 2px solid #f3f3f3;
|
| 89 |
+
border-top: 2px solid #3b82f6;
|
| 90 |
+
border-radius: 50%;
|
| 91 |
+
width: 20px;
|
| 92 |
+
height: 20px;
|
| 93 |
+
animation: spin 1s linear infinite;
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
@keyframes spin {
|
| 97 |
+
0% { transform: rotate(0deg); }
|
| 98 |
+
100% { transform: rotate(360deg); }
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
/* Utility classes */
|
| 102 |
+
.text-gradient {
|
| 103 |
+
background: linear-gradient(135deg, #3b82f6, #8b5cf6);
|
| 104 |
+
-webkit-background-clip: text;
|
| 105 |
+
-webkit-text-fill-color: transparent;
|
| 106 |
+
background-clip: text;
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
.shadow-glow {
|
| 110 |
+
box-shadow: 0 0 20px rgba(59, 130, 246, 0.3);
|
| 111 |
+
}
|