commit da6806c3cb7becb33a5ab83d726f5402168a8634 Author: dev-agent Date: Tue Jan 20 22:22:39 2026 +0000 feat: initial .NET 9 static site for SilverDOCK deployment diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..628565b --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,46 @@ +name: Deploy via SilverDOCK + +on: + workflow_dispatch: + inputs: + target_host: + description: 'Target Docker host' + required: true + default: '10.0.0.51' + hostname: + description: 'Hostname for the site' + required: true + default: 'privacyfirst.local' + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Deploy SilverDOCK Container + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ github.event.inputs.target_host }} + username: sysadmin + password: ${{ secrets.SSH_PASSWORD }} + script: | + # Login to Gitea container registry + docker login git.silverlabs.uk -u sysadmin -p ${{ secrets.GITEA_TOKEN }} + + # Pull latest SilverDOCK image + docker pull git.silverlabs.uk/silverlabs/silverdock:latest + + # Stop and remove existing container + docker stop privacyfirst || true + docker rm privacyfirst || true + + # Run SilverDOCK with privacyfirstwebsite repo + docker run -d \ + --name privacyfirst \ + --restart unless-stopped \ + -p 5080:8080 \ + -e REPOSITORY_URL=https://git.silverlabs.uk/SilverLABS/privacyfirstwebsite.git \ + -e GIT_TOKEN=${{ secrets.GITEA_TOKEN }} \ + -e SILVERDOCK_UI_HOSTNAME=${{ github.event.inputs.hostname }} \ + -v privacyfirst-keys:/app/keys \ + -v privacyfirst-source:/app/source \ + git.silverlabs.uk/silverlabs/silverdock:latest diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eab1aad --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# Build results +bin/ +obj/ + +# IDE +.vs/ +.vscode/ +*.user +*.suo + +# OS +.DS_Store +Thumbs.db + +# Logs +*.log diff --git a/PrivacyFirstWebsite.csproj b/PrivacyFirstWebsite.csproj new file mode 100644 index 0000000..0c27b6c --- /dev/null +++ b/PrivacyFirstWebsite.csproj @@ -0,0 +1,7 @@ + + + net9.0 + enable + enable + + diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..39d3ade --- /dev/null +++ b/Program.cs @@ -0,0 +1,8 @@ +var builder = WebApplication.CreateBuilder(args); +var app = builder.Build(); + +app.UseDefaultFiles(); +app.UseStaticFiles(); +app.MapFallbackToFile("index.html"); + +app.Run(); diff --git a/appsettings.json b/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/wwwroot/css/style.css b/wwwroot/css/style.css new file mode 100644 index 0000000..0560a9b --- /dev/null +++ b/wwwroot/css/style.css @@ -0,0 +1,2453 @@ +/* ========================================================================== + Privacy First - Dark Sovereignty Theme + A premium dark aesthetic with sharp accent colors + ========================================================================== */ + +/* -------------------------------------------------------------------------- + CSS Custom Properties + -------------------------------------------------------------------------- */ +:root { + /* Colors */ + --bg-primary: #0a0a0f; + --bg-secondary: #12121a; + --bg-tertiary: #1a1a24; + --bg-elevated: #22222e; + + --accent-primary: #00d4aa; + --accent-primary-rgb: 0, 212, 170; + --accent-secondary: #7c5cff; + --accent-secondary-rgb: 124, 92, 255; + --accent-warning: #ff6b35; + --accent-warning-rgb: 255, 107, 53; + + --text-primary: #f0f0f5; + --text-secondary: #8888a0; + --text-muted: #5a5a70; + + --border-subtle: #2a2a3a; + --border-accent: #3a3a4a; + + /* Gradients */ + --gradient-primary: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary)); + --gradient-dark: linear-gradient(180deg, var(--bg-primary) 0%, var(--bg-secondary) 100%); + --gradient-glow: radial-gradient(ellipse at center, rgba(var(--accent-primary-rgb), 0.15) 0%, transparent 70%); + + /* Typography */ + --font-heading: 'JetBrains Mono', 'Fira Code', monospace; + --font-body: 'Outfit', 'Inter', sans-serif; + --font-accent: 'Playfair Display', Georgia, serif; + + /* Spacing */ + --space-xs: 0.25rem; + --space-sm: 0.5rem; + --space-md: 1rem; + --space-lg: 1.5rem; + --space-xl: 2rem; + --space-2xl: 3rem; + --space-3xl: 4rem; + --space-4xl: 6rem; + + /* Sizing */ + --container-max: 1200px; + --container-narrow: 800px; + + /* Border Radius */ + --radius-sm: 4px; + --radius-md: 8px; + --radius-lg: 12px; + --radius-xl: 16px; + --radius-full: 9999px; + + /* Shadows */ + --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.3); + --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.4); + --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.5); + --shadow-glow: 0 0 40px rgba(var(--accent-primary-rgb), 0.3); + + /* Transitions */ + --transition-fast: 150ms ease; + --transition-base: 250ms ease; + --transition-slow: 400ms ease; + + /* Z-Index Scale */ + --z-negative: -1; + --z-base: 0; + --z-dropdown: 100; + --z-sticky: 200; + --z-fixed: 300; + --z-modal: 400; + --z-tooltip: 500; +} + +/* -------------------------------------------------------------------------- + Reset & Base Styles + -------------------------------------------------------------------------- */ +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +html { + scroll-behavior: smooth; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +body { + font-family: var(--font-body); + font-size: 16px; + line-height: 1.6; + color: var(--text-primary); + background-color: var(--bg-primary); + overflow-x: hidden; +} + +/* Selection */ +::selection { + background-color: rgba(var(--accent-primary-rgb), 0.3); + color: var(--text-primary); +} + +/* Focus styles */ +:focus-visible { + outline: 2px solid var(--accent-primary); + outline-offset: 2px; +} + +/* Links */ +a { + color: var(--accent-primary); + text-decoration: none; + transition: color var(--transition-fast); +} + +a:hover { + color: var(--accent-secondary); +} + +/* Images */ +img { + max-width: 100%; + height: auto; + display: block; +} + +/* Lists */ +ul, ol { + list-style: none; +} + +/* Buttons */ +button { + font-family: inherit; + font-size: inherit; + cursor: pointer; + border: none; + background: none; +} + +/* Inputs */ +input, textarea { + font-family: inherit; + font-size: inherit; +} + +/* -------------------------------------------------------------------------- + Typography + -------------------------------------------------------------------------- */ +h1, h2, h3, h4, h5, h6 { + font-family: var(--font-heading); + font-weight: 600; + line-height: 1.2; + color: var(--text-primary); +} + +h1 { font-size: clamp(2.5rem, 5vw, 4rem); } +h2 { font-size: clamp(2rem, 4vw, 3rem); } +h3 { font-size: clamp(1.25rem, 2vw, 1.5rem); } +h4 { font-size: 1.125rem; } + +p { + color: var(--text-secondary); +} + +.gradient-text { + background: var(--gradient-primary); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.glow-text { + text-shadow: 0 0 40px rgba(var(--accent-primary-rgb), 0.5); +} + +/* -------------------------------------------------------------------------- + Layout + -------------------------------------------------------------------------- */ +.container { + width: 100%; + max-width: var(--container-max); + margin: 0 auto; + padding: 0 var(--space-lg); +} + +.text-center { + text-align: center; +} + +/* Section styles */ +section { + padding: var(--space-4xl) 0; + position: relative; +} + +.section-label { + font-family: var(--font-heading); + font-size: 0.875rem; + font-weight: 500; + color: var(--accent-primary); + text-transform: uppercase; + letter-spacing: 0.1em; + margin-bottom: var(--space-md); +} + +.section-title { + margin-bottom: var(--space-lg); +} + +.section-description { + font-size: 1.125rem; + max-width: 600px; +} + +.section-header { + text-align: center; + margin-bottom: var(--space-3xl); +} + +.section-header .section-description { + margin: 0 auto; +} + +/* -------------------------------------------------------------------------- + Buttons + -------------------------------------------------------------------------- */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--space-sm); + font-family: var(--font-heading); + font-weight: 500; + font-size: 0.9375rem; + padding: 0.75rem 1.5rem; + border-radius: var(--radius-md); + transition: all var(--transition-base); + white-space: nowrap; + text-decoration: none; +} + +.btn__icon { + width: 18px; + height: 18px; +} + +/* Primary button */ +.btn--primary { + background: var(--gradient-primary); + color: var(--bg-primary); + border: none; + box-shadow: 0 4px 20px rgba(var(--accent-primary-rgb), 0.3); +} + +.btn--primary:hover { + transform: translateY(-2px); + box-shadow: 0 6px 30px rgba(var(--accent-primary-rgb), 0.4); + color: var(--bg-primary); +} + +/* Outline button */ +.btn--outline { + background: transparent; + color: var(--text-primary); + border: 1px solid var(--border-accent); +} + +.btn--outline:hover { + border-color: var(--accent-primary); + background: rgba(var(--accent-primary-rgb), 0.1); + color: var(--text-primary); +} + +/* Ghost button */ +.btn--ghost { + background: transparent; + color: var(--text-secondary); +} + +.btn--ghost:hover { + color: var(--text-primary); + background: rgba(255, 255, 255, 0.05); +} + +/* Accent button */ +.btn--accent { + background: var(--accent-warning); + color: white; +} + +.btn--accent:hover { + background: #ff8555; + color: white; +} + +/* Button sizes */ +.btn--sm { + padding: 0.5rem 1rem; + font-size: 0.875rem; +} + +.btn--lg { + padding: 1rem 2rem; + font-size: 1rem; +} + +.btn--xl { + padding: 1.25rem 2.5rem; + font-size: 1.125rem; +} + +.btn--block { + width: 100%; +} + +/* -------------------------------------------------------------------------- + Navigation + -------------------------------------------------------------------------- */ +.header { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: var(--z-fixed); + padding: var(--space-md) 0; + transition: all var(--transition-base); +} + +.header.scrolled { + background: rgba(10, 10, 15, 0.9); + backdrop-filter: blur(20px); + border-bottom: 1px solid var(--border-subtle); +} + +.nav { + display: flex; + align-items: center; + justify-content: space-between; +} + +.nav__logo { + display: flex; + align-items: center; + gap: 0.625rem; + color: var(--text-primary); + text-decoration: none; +} + +.logo-icon { + width: 36px; + height: 36px; + display: flex; + align-items: center; + justify-content: center; + position: relative; +} + +.logo-icon svg { + width: 100%; + height: 100%; +} + +.logo-text { + font-family: var(--font-body); + font-weight: 600; + font-size: 1.375rem; + letter-spacing: -0.02em; + color: var(--text-primary); +} + +.logo-text .logo-accent { + font-size: 1.1em; + font-weight: 700; + background: linear-gradient(135deg, #ffffff 0%, rgba(255,255,255,0.7) 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.logo-divider { + width: 1px; + height: 20px; + background: var(--border-accent); + margin: 0 0.25rem; +} + +.logo-tagline { + font-family: var(--font-body); + font-size: 0.6875rem; + font-weight: 400; + color: var(--text-muted); + letter-spacing: 0.05em; + text-transform: uppercase; +} + +.nav__list { + display: flex; + align-items: center; + gap: var(--space-xl); +} + +.nav__link { + color: var(--text-secondary); + font-size: 0.9375rem; + transition: color var(--transition-fast); +} + +.nav__link:hover { + color: var(--text-primary); +} + +.nav__actions { + display: flex; + align-items: center; + gap: var(--space-md); +} + +.nav__toggle, +.nav__close { + display: none; +} + +/* Mobile navigation */ +@media (max-width: 1023px) { + .nav__menu { + position: fixed; + top: 0; + right: -100%; + width: 100%; + max-width: 320px; + height: 100vh; + background: var(--bg-secondary); + padding: var(--space-3xl) var(--space-xl); + transition: right var(--transition-base); + z-index: var(--z-modal); + } + + .nav__menu.active { + right: 0; + } + + .nav__list { + flex-direction: column; + align-items: flex-start; + gap: var(--space-lg); + } + + .nav__link { + font-size: 1.125rem; + } + + .nav__close { + display: block; + position: absolute; + top: var(--space-lg); + right: var(--space-lg); + font-size: 2rem; + color: var(--text-secondary); + } + + .nav__toggle { + display: flex; + flex-direction: column; + gap: 4px; + padding: var(--space-sm); + } + + .nav__toggle span { + width: 24px; + height: 2px; + background: var(--text-primary); + transition: all var(--transition-fast); + } + + .nav__actions { + display: none; + } +} + +/* -------------------------------------------------------------------------- + Hero Section + -------------------------------------------------------------------------- */ +.hero { + min-height: 100vh; + display: flex; + align-items: center; + padding-top: 80px; + position: relative; + overflow: hidden; +} + +.hero__canvas { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: var(--z-negative); +} + +.hero__gradient { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: + radial-gradient(ellipse at 20% 80%, rgba(var(--accent-primary-rgb), 0.1) 0%, transparent 50%), + radial-gradient(ellipse at 80% 20%, rgba(var(--accent-secondary-rgb), 0.1) 0%, transparent 50%); + z-index: var(--z-negative); +} + +.hero__container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--space-3xl); + align-items: center; +} + +.hero__badge { + display: inline-flex; + align-items: center; + gap: var(--space-sm); + padding: var(--space-sm) var(--space-md); + background: rgba(var(--accent-primary-rgb), 0.1); + border: 1px solid rgba(var(--accent-primary-rgb), 0.3); + border-radius: var(--radius-full); + font-size: 0.875rem; + color: var(--accent-primary); + margin-bottom: var(--space-lg); +} + +.pulse { + width: 8px; + height: 8px; + background: var(--accent-primary); + border-radius: 50%; + animation: pulse 2s ease-in-out infinite; +} + +@keyframes pulse { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.5; transform: scale(1.2); } +} + +.hero__title { + margin-bottom: var(--space-lg); +} + +.hero__description { + font-size: 1.25rem; + margin-bottom: var(--space-xl); + max-width: 540px; +} + +.hero__cta { + display: flex; + flex-wrap: wrap; + gap: var(--space-md); + margin-bottom: var(--space-2xl); +} + +.hero__trust { + display: flex; + flex-wrap: wrap; + gap: var(--space-lg); +} + +.trust-badge { + display: flex; + align-items: center; + gap: var(--space-sm); + color: var(--text-secondary); + font-size: 0.875rem; +} + +.trust-badge svg { + width: 18px; + height: 18px; + color: var(--accent-primary); +} + +/* Hero mockup */ +.hero__mockup { + background: var(--bg-secondary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-xl); + overflow: hidden; + box-shadow: var(--shadow-lg); +} + +.mockup__header { + display: flex; + align-items: center; + gap: var(--space-sm); + padding: var(--space-md); + background: var(--bg-tertiary); + border-bottom: 1px solid var(--border-subtle); +} + +.mockup__dot { + width: 12px; + height: 12px; + border-radius: 50%; + background: var(--border-accent); +} + +.mockup__dot:first-child { background: #ff5f56; } +.mockup__dot:nth-child(2) { background: #ffbd2e; } +.mockup__dot:nth-child(3) { background: #27ca40; } + +.mockup__title { + margin-left: auto; + font-size: 0.75rem; + color: var(--text-muted); +} + +.mockup__content { + padding: var(--space-xl); +} + +.mockup__stat { + display: flex; + flex-direction: column; + margin-bottom: var(--space-lg); +} + +.mockup__stat-value { + font-family: var(--font-heading); + font-size: 2rem; + font-weight: 700; + color: var(--accent-primary); +} + +.mockup__stat-label { + font-size: 0.875rem; + color: var(--text-secondary); +} + +.mockup__services { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: var(--space-sm); + margin-top: var(--space-xl); +} + +.mockup__service { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--space-xs); + padding: var(--space-md); + background: var(--bg-tertiary); + border-radius: var(--radius-md); + font-size: 0.75rem; + color: var(--text-secondary); + border: 1px solid transparent; + transition: all var(--transition-fast); +} + +.mockup__service.active { + border-color: var(--accent-primary); + color: var(--text-primary); +} + +.service-icon { + font-size: 1.5rem; +} + +/* Scroll indicator */ +.hero__scroll { + position: absolute; + bottom: var(--space-xl); + left: 50%; + transform: translateX(-50%); + display: flex; + flex-direction: column; + align-items: center; + gap: var(--space-sm); + color: var(--text-muted); + font-size: 0.75rem; +} + +.scroll-indicator { + width: 24px; + height: 40px; + border: 2px solid var(--border-accent); + border-radius: 12px; + position: relative; +} + +.scroll-indicator::before { + content: ''; + position: absolute; + top: 8px; + left: 50%; + transform: translateX(-50%); + width: 4px; + height: 8px; + background: var(--accent-primary); + border-radius: 2px; + animation: scroll 2s ease-in-out infinite; +} + +@keyframes scroll { + 0%, 100% { top: 8px; opacity: 1; } + 50% { top: 20px; opacity: 0.3; } +} + +/* Responsive hero */ +@media (max-width: 1023px) { + .hero__container { + grid-template-columns: 1fr; + text-align: center; + } + + .hero__description { + margin: 0 auto var(--space-xl); + } + + .hero__cta { + justify-content: center; + } + + .hero__trust { + justify-content: center; + } + + .hero__visual { + order: -1; + } + + .hero__scroll { + display: none; + } +} + +/* -------------------------------------------------------------------------- + Problem Section + -------------------------------------------------------------------------- */ +.problem { + background: var(--bg-secondary); + padding: var(--space-4xl) 0; +} + +.problem__content { + text-align: center; + margin-bottom: var(--space-3xl); +} + +.problem__title { + max-width: 700px; + margin: 0 auto; +} + +.problem__comparison { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: var(--space-xl); + margin-bottom: var(--space-3xl); +} + +.comparison-card { + background: var(--bg-tertiary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-xl); + padding: var(--space-xl); +} + +.comparison-card__header { + display: flex; + align-items: center; + gap: var(--space-md); + margin-bottom: var(--space-lg); +} + +.comparison-card__icon { + font-size: 1.5rem; +} + +.comparison-card__header h3 { + font-size: 1.25rem; +} + +.comparison-card__list li { + display: flex; + align-items: flex-start; + gap: var(--space-sm); + padding: var(--space-sm) 0; + color: var(--text-secondary); + font-size: 0.9375rem; +} + +.x-mark { + color: #ff4757; + font-weight: 600; +} + +.check-mark { + color: var(--accent-primary); + font-weight: 600; +} + +.comparison-card--bad { + border-color: rgba(255, 71, 87, 0.3); +} + +.comparison-card--good { + border-color: rgba(var(--accent-primary-rgb), 0.3); + background: linear-gradient(135deg, var(--bg-tertiary), rgba(var(--accent-primary-rgb), 0.05)); +} + +.problem__stats { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: var(--space-lg); +} + +.stat-card { + text-align: center; + padding: var(--space-lg); + background: var(--bg-tertiary); + border-radius: var(--radius-lg); + border: 1px solid var(--border-subtle); +} + +.stat-card__value { + display: block; + font-family: var(--font-heading); + font-size: 2rem; + font-weight: 700; + color: var(--accent-primary); + margin-bottom: var(--space-sm); +} + +.stat-card__label { + font-size: 0.875rem; + color: var(--text-secondary); +} + +@media (max-width: 767px) { + .problem__comparison { + grid-template-columns: 1fr; + } + + .problem__stats { + grid-template-columns: repeat(2, 1fr); + } +} + +/* -------------------------------------------------------------------------- + Services Section + -------------------------------------------------------------------------- */ +.services { + padding: var(--space-4xl) 0; +} + +.services__grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--space-xl); +} + +.service-card { + background: var(--bg-secondary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-xl); + padding: var(--space-xl); + transition: all var(--transition-base); +} + +.service-card:hover { + transform: translateY(-4px); + border-color: var(--accent-primary); + box-shadow: 0 8px 40px rgba(var(--accent-primary-rgb), 0.15); +} + +.service-card__icon { + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(135deg, rgba(var(--accent-primary-rgb), 0.2), rgba(var(--accent-secondary-rgb), 0.2)); + border-radius: var(--radius-md); + margin-bottom: var(--space-lg); +} + +.service-card__icon svg { + width: 24px; + height: 24px; + color: var(--accent-primary); +} + +.service-card__title { + margin-bottom: var(--space-md); +} + +.service-card__description { + font-size: 0.9375rem; + margin-bottom: var(--space-lg); +} + +.service-card__features { + margin-bottom: var(--space-lg); +} + +.service-card__features li { + position: relative; + padding-left: var(--space-lg); + font-size: 0.875rem; + color: var(--text-secondary); + margin-bottom: var(--space-sm); +} + +.service-card__features li::before { + content: '•'; + position: absolute; + left: 0; + color: var(--accent-primary); +} + +.service-card__link { + display: inline-flex; + align-items: center; + gap: var(--space-sm); + font-size: 0.875rem; + color: var(--accent-primary); + font-weight: 500; +} + +.service-card__link svg { + width: 16px; + height: 16px; + transition: transform var(--transition-fast); +} + +.service-card__link:hover svg { + transform: translateX(4px); +} + +@media (max-width: 1023px) { + .services__grid { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (max-width: 639px) { + .services__grid { + grid-template-columns: 1fr; + } +} + +/* -------------------------------------------------------------------------- + Platform Section + -------------------------------------------------------------------------- */ +.platform { + background: var(--bg-secondary); + padding: var(--space-4xl) 0; +} + +.platform__grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--space-3xl); + align-items: center; +} + +.platform__description { + font-size: 1.125rem; + margin-bottom: var(--space-xl); +} + +.platform__features { + margin-bottom: var(--space-xl); +} + +.platform__feature { + display: flex; + gap: var(--space-md); + margin-bottom: var(--space-lg); +} + +.platform__feature-icon { + flex-shrink: 0; + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + background: var(--bg-tertiary); + border-radius: var(--radius-md); + color: var(--accent-primary); +} + +.platform__feature-icon svg { + width: 20px; + height: 20px; +} + +.platform__feature h4 { + margin-bottom: var(--space-xs); +} + +.platform__feature p { + font-size: 0.875rem; +} + +/* Code window */ +.code-window { + background: var(--bg-tertiary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-xl); + overflow: hidden; + box-shadow: var(--shadow-lg); +} + +.code-window__header { + display: flex; + align-items: center; + gap: var(--space-sm); + padding: var(--space-md); + background: var(--bg-elevated); + border-bottom: 1px solid var(--border-subtle); +} + +.code-window__dot { + width: 12px; + height: 12px; + border-radius: 50%; + background: var(--border-accent); +} + +.code-window__dot:first-child { background: #ff5f56; } +.code-window__dot:nth-child(2) { background: #ffbd2e; } +.code-window__dot:nth-child(3) { background: #27ca40; } + +.code-window__title { + margin-left: auto; + font-size: 0.75rem; + color: var(--text-muted); +} + +.code-window__content { + padding: var(--space-lg); + overflow-x: auto; +} + +.code-window__content code { + font-family: var(--font-heading); + font-size: 0.8125rem; + line-height: 1.8; + color: var(--text-secondary); +} + +.code-keyword { color: var(--accent-secondary); } +.code-property { color: var(--accent-primary); } +.code-comment { color: var(--text-muted); font-style: italic; } + +/* Platform apps */ +.platform__apps { + margin-top: var(--space-xl); + text-align: center; +} + +.platform__apps-label { + display: block; + font-size: 0.75rem; + color: var(--text-muted); + text-transform: uppercase; + letter-spacing: 0.1em; + margin-bottom: var(--space-md); +} + +.platform__app-icons { + display: flex; + justify-content: center; + gap: var(--space-md); +} + +.app-icon { + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + background: var(--bg-tertiary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-md); + font-size: 1.5rem; + transition: all var(--transition-fast); +} + +.app-icon:hover { + border-color: var(--accent-primary); + transform: translateY(-2px); +} + +@media (max-width: 1023px) { + .platform__grid { + grid-template-columns: 1fr; + } + + .platform__visual { + order: -1; + } +} + +/* -------------------------------------------------------------------------- + Passport Section + -------------------------------------------------------------------------- */ +.passport { + padding: var(--space-4xl) 0; + position: relative; + overflow: hidden; +} + +.passport__glow { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 800px; + height: 800px; + background: radial-gradient(ellipse at center, rgba(var(--accent-secondary-rgb), 0.1) 0%, transparent 70%); + pointer-events: none; +} + +.passport__grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--space-3xl); + align-items: center; + position: relative; +} + +/* Passport card mockup */ +.passport-card { + background: linear-gradient(135deg, var(--bg-secondary), var(--bg-tertiary)); + border: 1px solid var(--border-accent); + border-radius: var(--radius-xl); + padding: var(--space-xl); + box-shadow: var(--shadow-lg), 0 0 60px rgba(var(--accent-secondary-rgb), 0.1); + max-width: 360px; + margin: 0 auto; +} + +.passport-card__header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: var(--space-xl); +} + +.passport-card__logo { + width: 36px; + height: 40px; +} + +.passport-card__logo svg { + width: 100%; + height: 100%; +} + +.passport-card__badge { + font-family: var(--font-heading); + font-size: 0.625rem; + font-weight: 600; + letter-spacing: 0.2em; + color: var(--text-muted); + padding: var(--space-xs) var(--space-sm); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-sm); +} + +.passport-card__content { + display: flex; + align-items: center; + gap: var(--space-lg); + margin-bottom: var(--space-xl); +} + +.passport-card__avatar { + width: 64px; + height: 64px; + display: flex; + align-items: center; + justify-content: center; + background: var(--bg-tertiary); + border-radius: 50%; + color: var(--text-muted); +} + +.passport-card__avatar svg { + width: 32px; + height: 32px; +} + +.passport-card__name { + display: block; + font-family: var(--font-heading); + font-size: 1.125rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: var(--space-xs); +} + +.passport-card__id { + font-size: 0.75rem; + color: var(--text-muted); + font-family: var(--font-heading); +} + +.passport-card__services { + display: flex; + gap: var(--space-sm); + margin-bottom: var(--space-lg); +} + +.passport-card__service { + padding: var(--space-sm) var(--space-md); + background: var(--bg-tertiary); + border-radius: var(--radius-sm); + font-size: 0.75rem; + color: var(--text-muted); + border: 1px solid transparent; +} + +.passport-card__service.active { + border-color: var(--accent-primary); + color: var(--accent-primary); +} + +.passport-card__footer { + padding-top: var(--space-md); + border-top: 1px solid var(--border-subtle); +} + +.passport-card__status { + display: flex; + align-items: center; + gap: var(--space-sm); + font-size: 0.75rem; + color: var(--text-secondary); +} + +.status-dot { + width: 8px; + height: 8px; + background: var(--accent-primary); + border-radius: 50%; + animation: pulse 2s ease-in-out infinite; +} + +/* Passport content */ +.passport__description { + font-size: 1.125rem; + margin-bottom: var(--space-xl); +} + +.passport__features { + margin-bottom: var(--space-xl); +} + +.passport__feature { + display: flex; + align-items: center; + gap: var(--space-md); + padding: var(--space-sm) 0; + color: var(--text-secondary); +} + +.passport__feature svg { + width: 20px; + height: 20px; + color: var(--accent-primary); + flex-shrink: 0; +} + +.passport__cta { + display: flex; + flex-wrap: wrap; + gap: var(--space-md); +} + +@media (max-width: 1023px) { + .passport__grid { + grid-template-columns: 1fr; + } +} + +/* -------------------------------------------------------------------------- + Marketplace Section + -------------------------------------------------------------------------- */ +.marketplace { + background: var(--bg-secondary); + padding: var(--space-4xl) 0; +} + +.marketplace__demo { + margin-bottom: var(--space-3xl); +} + +/* Search mockup */ +.search-mockup { + background: var(--bg-tertiary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-xl); + overflow: hidden; + max-width: 700px; + margin: 0 auto; + box-shadow: var(--shadow-lg); +} + +.search-mockup__bar { + display: flex; + align-items: center; + gap: var(--space-md); + padding: var(--space-lg); + background: var(--bg-elevated); + border-bottom: 1px solid var(--border-subtle); +} + +.search-mockup__bar svg { + width: 20px; + height: 20px; + color: var(--text-muted); +} + +.search-mockup__bar input { + flex: 1; + background: none; + border: none; + color: var(--text-primary); + outline: none; +} + +.search-mockup__bar input::placeholder { + color: var(--text-muted); +} + +.search-mockup__btn { + padding: var(--space-sm) var(--space-lg); + background: var(--accent-primary); + color: var(--bg-primary); + border-radius: var(--radius-md); + font-family: var(--font-heading); + font-weight: 500; + font-size: 0.875rem; +} + +.search-mockup__results { + padding: var(--space-lg); +} + +.search-result { + display: flex; + align-items: center; + gap: var(--space-lg); + padding: var(--space-md); + border-radius: var(--radius-md); + transition: background var(--transition-fast); +} + +.search-result:hover { + background: var(--bg-secondary); +} + +.search-result__image { + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + background: var(--bg-secondary); + border-radius: var(--radius-md); + font-size: 1.5rem; +} + +.search-result__info { + flex: 1; +} + +.search-result__title { + display: block; + font-weight: 500; + color: var(--text-primary); + margin-bottom: var(--space-xs); +} + +.search-result__vendor { + font-size: 0.75rem; + color: var(--text-muted); +} + +.search-result__price { + font-family: var(--font-heading); + font-weight: 600; + color: var(--accent-primary); +} + +.search-mockup__footer { + padding: var(--space-md) var(--space-lg); + background: var(--bg-secondary); + border-top: 1px solid var(--border-subtle); +} + +.privacy-indicator { + display: flex; + align-items: center; + gap: var(--space-sm); + font-size: 0.75rem; + color: var(--accent-primary); +} + +.privacy-indicator svg { + width: 14px; + height: 14px; +} + +/* Marketplace features */ +.marketplace__features { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: var(--space-lg); + margin-bottom: var(--space-2xl); +} + +.marketplace__feature { + text-align: center; + padding: var(--space-lg); + background: var(--bg-tertiary); + border-radius: var(--radius-lg); + border: 1px solid var(--border-subtle); +} + +.marketplace__feature-icon { + font-size: 2rem; + margin-bottom: var(--space-md); +} + +.marketplace__feature h4 { + margin-bottom: var(--space-sm); +} + +.marketplace__feature p { + font-size: 0.875rem; +} + +@media (max-width: 767px) { + .marketplace__features { + grid-template-columns: repeat(2, 1fr); + } +} + +/* -------------------------------------------------------------------------- + AppStore Section + -------------------------------------------------------------------------- */ +.appstore { + padding: var(--space-4xl) 0; + position: relative; + overflow: hidden; +} + +.appstore__bg { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: + radial-gradient(ellipse at 30% 50%, rgba(var(--accent-secondary-rgb), 0.15) 0%, transparent 50%), + radial-gradient(ellipse at 70% 50%, rgba(var(--accent-warning-rgb), 0.1) 0%, transparent 50%); + z-index: var(--z-negative); +} + +.appstore__content { + text-align: center; + max-width: 700px; + margin: 0 auto; +} + +.coming-soon-badge { + display: inline-flex; + align-items: center; + gap: var(--space-sm); + padding: var(--space-sm) var(--space-lg); + background: rgba(var(--accent-warning-rgb), 0.1); + border: 1px solid rgba(var(--accent-warning-rgb), 0.3); + border-radius: var(--radius-full); + font-family: var(--font-heading); + font-size: 0.875rem; + font-weight: 500; + color: var(--accent-warning); + margin-bottom: var(--space-xl); +} + +.glow-pulse { + width: 8px; + height: 8px; + background: var(--accent-warning); + border-radius: 50%; + animation: glow-pulse 2s ease-in-out infinite; +} + +@keyframes glow-pulse { + 0%, 100% { + opacity: 1; + box-shadow: 0 0 10px var(--accent-warning); + } + 50% { + opacity: 0.6; + box-shadow: 0 0 20px var(--accent-warning); + } +} + +.appstore__title { + margin-bottom: var(--space-lg); +} + +.appstore__description { + font-size: 1.125rem; + margin-bottom: var(--space-2xl); +} + +.appstore__categories { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: var(--space-lg); + margin-bottom: var(--space-2xl); +} + +.app-category { + padding: var(--space-xl); + background: var(--bg-secondary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-lg); + transition: all var(--transition-base); +} + +.app-category:hover { + border-color: var(--accent-secondary); + transform: translateY(-4px); +} + +.app-category__icon { + display: block; + font-size: 2.5rem; + margin-bottom: var(--space-md); +} + +.app-category__name { + display: block; + font-family: var(--font-heading); + font-weight: 600; + color: var(--text-primary); + margin-bottom: var(--space-xs); +} + +.app-category__desc { + font-size: 0.75rem; + color: var(--text-muted); +} + +/* Notify form */ +.appstore__notify { + max-width: 450px; + margin: 0 auto; +} + +.appstore__notify p { + margin-bottom: var(--space-md); + color: var(--text-secondary); +} + +.notify-form { + display: flex; + gap: var(--space-sm); + margin-bottom: var(--space-sm); +} + +.notify-form__input { + flex: 1; + padding: var(--space-md) var(--space-lg); + background: var(--bg-secondary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-md); + color: var(--text-primary); + outline: none; + transition: border-color var(--transition-fast); +} + +.notify-form__input:focus { + border-color: var(--accent-primary); +} + +.notify-form__input::placeholder { + color: var(--text-muted); +} + +.notify-form__note { + font-size: 0.75rem; + color: var(--text-muted); +} + +@media (max-width: 767px) { + .appstore__categories { + grid-template-columns: repeat(2, 1fr); + } + + .notify-form { + flex-direction: column; + } +} + +/* -------------------------------------------------------------------------- + Network Section + -------------------------------------------------------------------------- */ +.network { + background: var(--bg-secondary); + padding: var(--space-4xl) 0; +} + +.network__grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--space-3xl); + align-items: center; +} + +.network__description { + font-size: 1.125rem; + margin-bottom: var(--space-xl); +} + +.network__features { + margin-bottom: var(--space-xl); +} + +.network__feature { + display: flex; + gap: var(--space-md); + margin-bottom: var(--space-lg); +} + +.network__feature-icon { + flex-shrink: 0; + width: 44px; + height: 44px; + display: flex; + align-items: center; + justify-content: center; + background: var(--bg-tertiary); + border-radius: var(--radius-md); + color: var(--accent-primary); +} + +.network__feature-icon svg { + width: 22px; + height: 22px; +} + +.network__feature h4 { + margin-bottom: var(--space-xs); +} + +.network__feature p { + font-size: 0.875rem; +} + +/* Network diagram */ +.network-diagram { + position: relative; + width: 300px; + height: 300px; + margin: 0 auto; +} + +.network-node { + position: absolute; + width: 60px; + height: 60px; + display: flex; + align-items: center; + justify-content: center; + background: var(--bg-tertiary); + border: 2px solid var(--border-accent); + border-radius: 50%; + font-family: var(--font-heading); + font-size: 0.625rem; + font-weight: 600; + color: var(--text-secondary); + z-index: 1; +} + +.network-node--center { + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background: var(--accent-primary); + color: var(--bg-primary); + border-color: var(--accent-primary); +} + +.network-node--tor { + top: 15%; + left: 15%; + border-color: var(--accent-secondary); +} + +.network-node--ipfs { + top: 15%; + right: 15%; + border-color: var(--accent-primary); +} + +.network-node--exit { + bottom: 15%; + left: 15%; + border-color: var(--accent-warning); +} + +.network-node--relay1 { + bottom: 15%; + right: 15%; +} + +.network-node--relay2 { + top: 50%; + right: 0; + transform: translateY(-50%); +} + +.network-lines { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.network-line { + stroke: var(--border-accent); + stroke-width: 1; + stroke-dasharray: 5, 5; + animation: dash 20s linear infinite; +} + +@keyframes dash { + to { stroke-dashoffset: -100; } +} + +@media (max-width: 1023px) { + .network__grid { + grid-template-columns: 1fr; + } + + .network__visual { + order: -1; + } +} + +/* -------------------------------------------------------------------------- + Control Panel Section + -------------------------------------------------------------------------- */ +.control-panel { + padding: var(--space-4xl) 0; +} + +/* Control panel mockup */ +.control-panel__mockup { + margin-bottom: var(--space-2xl); +} + +.cp-window { + background: var(--bg-secondary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-xl); + overflow: hidden; + box-shadow: var(--shadow-lg); + max-width: 900px; + margin: 0 auto; +} + +.cp-window__header { + display: flex; + align-items: center; + gap: var(--space-sm); + padding: var(--space-md); + background: var(--bg-tertiary); + border-bottom: 1px solid var(--border-subtle); +} + +.cp-window__dot { + width: 12px; + height: 12px; + border-radius: 50%; + background: var(--border-accent); +} + +.cp-window__dot:first-child { background: #ff5f56; } +.cp-window__dot:nth-child(2) { background: #ffbd2e; } +.cp-window__dot:nth-child(3) { background: #27ca40; } + +.cp-window__title { + margin-left: auto; + font-size: 0.75rem; + color: var(--text-muted); +} + +.cp-window__content { + display: flex; + min-height: 350px; +} + +.cp-sidebar { + width: 200px; + padding: var(--space-lg); + background: var(--bg-tertiary); + border-right: 1px solid var(--border-subtle); +} + +.cp-sidebar__item { + display: flex; + align-items: center; + gap: var(--space-sm); + padding: var(--space-md); + border-radius: var(--radius-md); + font-size: 0.875rem; + color: var(--text-secondary); + margin-bottom: var(--space-sm); + transition: all var(--transition-fast); + cursor: pointer; +} + +.cp-sidebar__item:hover { + background: var(--bg-secondary); + color: var(--text-primary); +} + +.cp-sidebar__item.active { + background: var(--bg-secondary); + color: var(--accent-primary); +} + +.cp-sidebar__item svg { + width: 18px; + height: 18px; +} + +.cp-main { + flex: 1; + padding: var(--space-xl); +} + +.cp-stats { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: var(--space-md); + margin-bottom: var(--space-xl); +} + +.cp-stat { + padding: var(--space-lg); + background: var(--bg-tertiary); + border-radius: var(--radius-md); + text-align: center; +} + +.cp-stat__value { + display: block; + font-family: var(--font-heading); + font-size: 1.5rem; + font-weight: 700; + color: var(--accent-primary); + margin-bottom: var(--space-xs); +} + +.cp-stat__label { + font-size: 0.75rem; + color: var(--text-muted); +} + +.cp-actions { + display: flex; + gap: var(--space-md); +} + +.cp-action { + display: flex; + align-items: center; + gap: var(--space-sm); + padding: var(--space-md) var(--space-lg); + background: var(--bg-tertiary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-md); + font-size: 0.875rem; + color: var(--text-secondary); + transition: all var(--transition-fast); +} + +.cp-action:hover { + border-color: var(--accent-primary); + color: var(--text-primary); +} + +.cp-action svg { + width: 16px; + height: 16px; +} + +/* Control panel features */ +.control-panel__features { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: var(--space-xl); +} + +.cp-feature { + display: flex; + align-items: center; + gap: var(--space-sm); + padding: var(--space-md) var(--space-lg); + background: var(--bg-secondary); + border-radius: var(--radius-full); + font-size: 0.875rem; + color: var(--text-secondary); +} + +.cp-feature svg { + width: 18px; + height: 18px; + color: var(--accent-primary); +} + +@media (max-width: 767px) { + .cp-window__content { + flex-direction: column; + } + + .cp-sidebar { + width: 100%; + border-right: none; + border-bottom: 1px solid var(--border-subtle); + } + + .cp-stats { + grid-template-columns: repeat(2, 1fr); + } + + .cp-actions { + flex-direction: column; + } +} + +/* -------------------------------------------------------------------------- + Pricing Section + -------------------------------------------------------------------------- */ +.pricing { + background: var(--bg-secondary); + padding: var(--space-4xl) 0; +} + +/* Pricing toggle */ +.pricing__toggle { + display: flex; + align-items: center; + justify-content: center; + gap: var(--space-lg); + margin-bottom: var(--space-2xl); +} + +.pricing__toggle-label { + font-size: 0.9375rem; + color: var(--text-secondary); + transition: color var(--transition-fast); +} + +.pricing__toggle-label.active { + color: var(--text-primary); +} + +.pricing__discount { + display: inline-block; + padding: var(--space-xs) var(--space-sm); + background: rgba(var(--accent-primary-rgb), 0.1); + border-radius: var(--radius-sm); + font-size: 0.75rem; + color: var(--accent-primary); + margin-left: var(--space-sm); +} + +.pricing__toggle-switch { + width: 52px; + height: 28px; + background: var(--bg-tertiary); + border-radius: var(--radius-full); + position: relative; + cursor: pointer; + border: 1px solid var(--border-subtle); +} + +.pricing__toggle-slider { + position: absolute; + top: 3px; + left: 3px; + width: 20px; + height: 20px; + background: var(--accent-primary); + border-radius: 50%; + transition: transform var(--transition-base); +} + +.pricing__toggle-switch.annual .pricing__toggle-slider { + transform: translateX(24px); +} + +/* Pricing grid */ +.pricing__grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--space-xl); + margin-bottom: var(--space-2xl); +} + +.pricing-card { + background: var(--bg-tertiary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-xl); + padding: var(--space-xl); + position: relative; + transition: all var(--transition-base); +} + +.pricing-card:hover { + transform: translateY(-4px); + border-color: var(--border-accent); +} + +.pricing-card--featured { + border-color: var(--accent-primary); + background: linear-gradient(180deg, var(--bg-tertiary), rgba(var(--accent-primary-rgb), 0.05)); +} + +.pricing-card--featured:hover { + border-color: var(--accent-primary); +} + +.pricing-card__badge { + position: absolute; + top: 0; + left: 50%; + transform: translate(-50%, -50%); + padding: var(--space-sm) var(--space-lg); + background: var(--accent-primary); + color: var(--bg-primary); + font-family: var(--font-heading); + font-size: 0.75rem; + font-weight: 600; + border-radius: var(--radius-full); +} + +.pricing-card__header { + margin-bottom: var(--space-lg); +} + +.pricing-card__name { + margin-bottom: var(--space-sm); +} + +.pricing-card__description { + font-size: 0.875rem; +} + +.pricing-card__price { + margin-bottom: var(--space-xl); + padding-bottom: var(--space-lg); + border-bottom: 1px solid var(--border-subtle); +} + +.pricing-card__currency { + font-family: var(--font-heading); + font-size: 1.5rem; + color: var(--text-secondary); + vertical-align: top; +} + +.pricing-card__amount { + font-family: var(--font-heading); + font-size: 3rem; + font-weight: 700; + color: var(--text-primary); +} + +.pricing-card__amount--custom { + font-size: 2.5rem; +} + +.pricing-card__period { + font-size: 0.875rem; + color: var(--text-muted); +} + +.pricing-card__features { + margin-bottom: var(--space-xl); +} + +.pricing-card__features li { + display: flex; + align-items: center; + gap: var(--space-sm); + padding: var(--space-sm) 0; + font-size: 0.9375rem; + color: var(--text-secondary); +} + +.pricing-card__features svg { + width: 18px; + height: 18px; + color: var(--accent-primary); + flex-shrink: 0; +} + +/* Guarantee */ +.pricing__guarantee { + display: flex; + align-items: center; + justify-content: center; + gap: var(--space-lg); + padding: var(--space-xl); + background: var(--bg-tertiary); + border-radius: var(--radius-xl); + border: 1px solid var(--border-subtle); + max-width: 600px; + margin: 0 auto; +} + +.pricing__guarantee svg { + width: 48px; + height: 48px; + color: var(--accent-primary); + flex-shrink: 0; +} + +.pricing__guarantee strong { + display: block; + margin-bottom: var(--space-xs); +} + +.pricing__guarantee p { + font-size: 0.875rem; + margin: 0; +} + +@media (max-width: 1023px) { + .pricing__grid { + grid-template-columns: 1fr; + max-width: 400px; + margin: 0 auto var(--space-2xl); + } + + .pricing-card--featured { + order: -1; + } +} + +/* -------------------------------------------------------------------------- + Trust Section + -------------------------------------------------------------------------- */ +.trust { + padding: var(--space-4xl) 0; +} + +.trust__grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--space-xl); +} + +.trust-card { + padding: var(--space-xl); + background: var(--bg-secondary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-xl); + text-align: center; + transition: all var(--transition-base); +} + +.trust-card:hover { + transform: translateY(-4px); + border-color: var(--accent-primary); +} + +.trust-card__icon { + width: 64px; + height: 64px; + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(135deg, rgba(var(--accent-primary-rgb), 0.1), rgba(var(--accent-secondary-rgb), 0.1)); + border-radius: var(--radius-lg); + margin: 0 auto var(--space-lg); +} + +.trust-card__icon svg { + width: 32px; + height: 32px; + color: var(--accent-primary); +} + +.trust-card h3 { + margin-bottom: var(--space-md); +} + +.trust-card p { + font-size: 0.9375rem; +} + +@media (max-width: 1023px) { + .trust__grid { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (max-width: 639px) { + .trust__grid { + grid-template-columns: 1fr; + } +} + +/* -------------------------------------------------------------------------- + CTA Section + -------------------------------------------------------------------------- */ +.cta { + padding: var(--space-4xl) 0; + position: relative; + overflow: hidden; +} + +.cta__bg { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: + radial-gradient(ellipse at 50% 50%, rgba(var(--accent-primary-rgb), 0.15) 0%, transparent 60%); + z-index: var(--z-negative); +} + +.cta__content { + text-align: center; + max-width: 700px; + margin: 0 auto; +} + +.cta__title { + margin-bottom: var(--space-lg); +} + +.cta__description { + font-size: 1.25rem; + margin-bottom: var(--space-xl); +} + +.cta__actions { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: var(--space-md); +} + +/* -------------------------------------------------------------------------- + Footer + -------------------------------------------------------------------------- */ +.footer { + background: var(--bg-secondary); + border-top: 1px solid var(--border-subtle); + padding: var(--space-3xl) 0 var(--space-xl); +} + +.footer__grid { + display: grid; + grid-template-columns: 1fr 2fr; + gap: var(--space-3xl); + margin-bottom: var(--space-2xl); +} + +.footer__logo { + display: flex; + align-items: center; + gap: 0.625rem; + color: var(--text-primary); + text-decoration: none; + margin-bottom: var(--space-md); +} + +.footer__logo .logo-icon { + width: 32px; + height: 32px; +} + +.footer__logo .logo-text { + font-family: var(--font-body); + font-weight: 600; + font-size: 1.25rem; + letter-spacing: -0.02em; +} + +.footer__tagline { + font-size: 0.875rem; + margin-bottom: var(--space-lg); +} + +.footer__social { + display: flex; + gap: var(--space-md); +} + +.social-link { + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + background: var(--bg-tertiary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-md); + color: var(--text-secondary); + transition: all var(--transition-fast); +} + +.social-link:hover { + border-color: var(--accent-primary); + color: var(--accent-primary); +} + +.social-link svg { + width: 18px; + height: 18px; +} + +.footer__links { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: var(--space-xl); +} + +.footer__column h4 { + font-size: 0.875rem; + font-weight: 600; + margin-bottom: var(--space-lg); +} + +.footer__column ul li { + margin-bottom: var(--space-sm); +} + +.footer__column a { + color: var(--text-secondary); + font-size: 0.875rem; + transition: color var(--transition-fast); +} + +.footer__column a:hover { + color: var(--text-primary); +} + +.footer__bottom { + display: flex; + justify-content: space-between; + align-items: center; + padding-top: var(--space-xl); + border-top: 1px solid var(--border-subtle); +} + +.footer__copyright, +.footer__credit { + font-size: 0.875rem; + color: var(--text-muted); +} + +.footer__credit a { + color: var(--accent-primary); +} + +@media (max-width: 1023px) { + .footer__grid { + grid-template-columns: 1fr; + } + + .footer__links { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (max-width: 639px) { + .footer__links { + grid-template-columns: 1fr; + } + + .footer__bottom { + flex-direction: column; + gap: var(--space-sm); + text-align: center; + } +} + +/* -------------------------------------------------------------------------- + Animations & Reveal + -------------------------------------------------------------------------- */ +.reveal { + opacity: 0; + transform: translateY(30px); + transition: opacity 0.6s ease, transform 0.6s ease; +} + +.reveal.active { + opacity: 1; + transform: translateY(0); +} + +.reveal--delay-1 { transition-delay: 0.1s; } +.reveal--delay-2 { transition-delay: 0.2s; } +.reveal--delay-3 { transition-delay: 0.3s; } + +/* -------------------------------------------------------------------------- + Utility Classes + -------------------------------------------------------------------------- */ +.visually-hidden { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} diff --git a/wwwroot/index.html b/wwwroot/index.html new file mode 100644 index 0000000..e0d24f1 --- /dev/null +++ b/wwwroot/index.html @@ -0,0 +1,1322 @@ + + + + + + + + + + + + + + + + + Privacy First | Privacy-Focused Internet Services + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+
+
+ + Now in Public Beta +
+ +

+ The Internet,
+ Reimagined for Privacy +

+ +

+ Take back control of your digital life. Privacy First delivers enterprise-grade + hosting, encrypted communications, and secure cloud services—built from the + ground up with your privacy as the foundation. +

+ + + +
+
+ + + + No Tracking +
+
+ + + + + No Data Mining +
+
+ + + + + No Compromise +
+
+
+ +
+
+
+ + + + Privacy Dashboard +
+
+
+ 0 + Data Points Collected +
+
+ 256-bit + AES Encryption +
+
+ 100% + Your Data, Your Control +
+
+
+ 🌐 + Hosting +
+
+ 📧 + Email +
+
+ ☁️ + Storage +
+
+ 🔐 + VPN +
+
+
+
+
+
+ +
+ Scroll to explore +
+
+
+ + +
+
+
+ +

+ The internet wasn't built for privacy.
+ We're changing that. +

+
+ +
+
+
+ ⚠️ +

Traditional Providers

+
+
    +
  • Scan your emails for advertising
  • +
  • Sell your browsing data to third parties
  • +
  • Track every click and keystroke
  • +
  • Retain data indefinitely without consent
  • +
  • Comply with mass surveillance requests
  • +
+
+ +
+
+ 🛡️ +

Privacy First

+
+
    +
  • Zero-knowledge encryption on all data
  • +
  • No data monetization—ever
  • +
  • Minimal data collection by design
  • +
  • Automatic data purging on request
  • +
  • Warrant canary & transparency reports
  • +
+
+
+ +
+
+ 2,200+ + Data breaches in 2024 +
+
+ 1B+ + Records exposed yearly +
+
+ $9.44M + Average breach cost +
+
+ 72% + Distrust big tech with data +
+
+
+
+ + +
+
+
+ +

Privacy-First Services

+

+ Every service we build starts with a simple question: + "How can we deliver this with the least amount of user data possible?" +

+
+ +
+
+
+ + + + +
+

Web Hosting

+

+ Privacy-first hosting with encrypted storage, automatic SSL, + and no server-side analytics. Your website, your data. +

+
    +
  • Encrypted at rest & in transit
  • +
  • DDoS protection included
  • +
  • One-click WordPress & Blazor
  • +
+ + Learn More + + + + +
+ +
+
+ + + + +
+

Email Services

+

+ End-to-end encrypted email with zero content scanning. + Your conversations stay between you and your recipients. +

+
    +
  • PGP encryption built-in
  • +
  • Custom domains supported
  • +
  • No advertising, ever
  • +
+ + Learn More + + + + +
+ +
+
+ + + +
+

Cloud Storage

+

+ Zero-knowledge encrypted file storage. We can't see your files + even if we wanted to—and we don't want to. +

+
    +
  • Client-side encryption
  • +
  • Secure file sharing
  • +
  • Version history
  • +
+ + Learn More + + + + +
+ +
+
+ + + + +
+

VPN & Network

+

+ Anonymous browsing with a strict no-logs policy. + Browse freely without leaving a trace. +

+
    +
  • WireGuard protocol
  • +
  • Kill switch enabled
  • +
  • Multi-hop routing available
  • +
+ + Learn More + + + + +
+ +
+
+ + + + + +
+

Domain Registration

+

+ Register domains with private WHOIS by default. + Keep your personal information off public records. +

+
    +
  • Private WHOIS included
  • +
  • DNSSEC support
  • +
  • Secure DNS hosting
  • +
+ + Learn More + + + + +
+ +
+
+ + + + + +
+

Database Hosting

+

+ Encrypted PostgreSQL and MySQL hosting with automated + backups. Your data stays yours. +

+
    +
  • Encrypted connections
  • +
  • Automated daily backups
  • +
  • Point-in-time recovery
  • +
+ + Learn More + + + + +
+
+
+
+ + +
+
+
+
+ +

Build on SilverSHELL

+

+ Our multi-tenant cloud platform lets you build privacy-first + applications without compromising on features. Deploy Blazor + WebAssembly apps, .NET APIs, and more—all with built-in + encryption and zero tracking. +

+ +
+
+
+ + + + +
+
+

.NET 9 Ready

+

Latest framework with AOT compilation support

+
+
+ +
+
+ + + + + +
+
+

Multi-Tenant Architecture

+

Complete data isolation between tenants

+
+
+ +
+
+ + + +
+
+

Security by Default

+

JWT auth, encryption, and CORS built-in

+
+
+
+ + + View Documentation + + + + + + +
+ +
+
+
+ + + + Program.cs +
+
var builder = WebApplication.CreateBuilder(args);
+
+// Privacy-first configuration
+builder.Services.AddSilverShell(options => {
+    options.EnableEncryption = true;
+    options.DisableTracking = true;
+    options.DataRetention = TimeSpan.Zero;
+});
+
+builder.Services.AddAuthentication()
+    .AddPrivacyFirstJwt();
+
+var app = builder.Build();
+
+app.UsePrivacyHeaders();
+app.MapSilverShellEndpoints();
+
+app.Run();
+
+ +
+ App Ecosystem +
+
🛒
+
📊
+
👥
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+ + PASSPORT +
+
+
+ + + +
+
+ anonymous_user + ID: ****-****-7X2K +
+
+
+
Hosting
+
Email
+
Storage
+
+ +
+
+ +
+ +

One Identity.
Complete Control.

+ +

+ Passport is your single sign-on for all Privacy First services. + We've reimagined identity management with privacy at the core—we only + ask for a username. Everything else is optional. +

+ +
+
+ + + + + Minimal data collection—username only required +
+
+ + + + + Manage all connected apps in one place +
+
+ + + + + Export your data anytime—it's yours +
+
+ + + + + GDPR compliant by design, not afterthought +
+
+ + +
+
+
+
+ + +
+
+
+ +

Discover Without Being Discovered

+

+ Search products across multiple vendors without creating an account. + No tracking, no profile building, no creepy personalized ads following you around. +

+
+ +
+
+
+ + + + + + +
+ +
+
+
📱
+
+ Privacy Phone Case + SecureShop + $29.99 +
+
+
+
🔐
+
+ Hardware Security Key + CryptoGear + $45.00 +
+
+
+
📡
+
+ Faraday Bag + PrivacyTools + $19.99 +
+
+
+ + +
+
+ +
+
+ 🔍 +

Anonymous Search

+

No login required for browsing

+
+
+ 🌐 +

Multi-Provider

+

Results from multiple vendors

+
+
+ 🚫 +

No Profiling

+

Zero behavioral tracking

+
+
+ 💳 +

Crypto Payments

+

Pay anonymously with BTC/XMR

+
+
+ + +
+
+ + +
+
+
+
+
+ + Coming Soon +
+ +

+ The Privacy-First
+ App Ecosystem +

+ +

+ A curated marketplace of privacy-respecting applications. + Every app reviewed for data collection practices. + No surveillance-ware allowed. +

+ +
+
+ 📱 + Android Apps + APK distribution +
+
+ 🌐 + PWA Apps + Web applications +
+
+ 🧩 + Plugins + Platform extensions +
+
+ 🔧 + Browser Extensions + Privacy tools +
+
+ +
+

Get notified when we launch

+
+ + +
+ We'll only use this to notify you. Obviously. +
+
+
+
+ + +
+
+
+
+ +

The Censorship-Resistant Internet

+ +

+ PrivateWeb is our distributed privacy network for users who need + the highest level of anonymity. Built on Tor and IPFS, it provides + censorship-resistant hosting and communication. +

+ +
+
+
+ + + + + +
+
+

Tor Integration

+

Onion routing for anonymous access

+
+
+ +
+
+ + + +
+
+

IPFS Storage

+

Distributed, immutable file storage

+
+
+ +
+
+ + + + +
+
+

Warrant Canary

+

Transparent security reporting

+
+
+
+ + + Join the Network + + + + +
+ +
+
+
+ You +
+
+ Tor +
+
+ IPFS +
+
+ Exit +
+
+ Relay +
+
+ Relay +
+ + + + + + + + +
+
+
+
+
+ + +
+
+
+ +

Enterprise-Grade Control

+

+ PrivateWebCP gives you complete control over your services + with a clean, intuitive interface. +

+
+ +
+
+
+ + + + PrivateWebCP - Control Panel +
+
+ +
+
+
+ 3 + Active Sites +
+
+ 12.4 GB + Storage Used +
+
+ 99.9% + Uptime +
+
+ 🟢 + All Systems +
+
+
+ + + +
+
+
+
+
+ +
+
+ + + + One-Click Provisioning +
+
+ + + + + Automated SSL/TLS +
+
+ + + + Resource Monitoring +
+
+ + + + + Scheduled Backups +
+
+
+
+ + +
+
+
+ +

Privacy Shouldn't Be a Premium

+

+ Transparent pricing with no hidden fees. + All plans include our core privacy protections. +

+
+ +
+ Monthly + + + Annual + Save 20% + +
+ +
+
+
+

Individual

+

Perfect for personal projects and privacy-conscious individuals

+
+
+ $ + 9.99 + /month +
+
    +
  • 1 Website
  • +
  • 5 GB Encrypted Storage
  • +
  • 1 Email Account
  • +
  • Free SSL Certificate
  • +
  • Basic VPN Access
  • +
  • Community Support
  • +
+ Get Started +
+ + + +
+
+

Enterprise

+

For organizations requiring dedicated resources and SLA

+
+
+ Custom +
+
    +
  • Unlimited Websites
  • +
  • Unlimited Storage
  • +
  • Unlimited Email
  • +
  • Dedicated Resources
  • +
  • Custom VPN Endpoints
  • +
  • SLA Guarantee
  • +
  • White-label Option
  • +
  • Dedicated Support
  • +
+ Contact Sales +
+
+ +
+ + + +
+ 30-Day Money-Back Guarantee +

Try Privacy First risk-free. Not satisfied? Full refund, no questions asked.

+
+
+
+
+ + +
+
+
+ +

Built on Transparency

+
+ +
+
+
+ + + + +
+

Zero-Knowledge Encryption

+

Your data is encrypted before it leaves your device. We can't read it even if we wanted to.

+
+ +
+
+ + + + + + +
+

Transparency Reports

+

We publish regular reports on data requests. See exactly how we handle legal inquiries.

+
+ +
+
+ + + + +
+

Warrant Canary

+

Updated daily. If we receive a secret subpoena, you'll know—because the canary will stop singing.

+
+ +
+
+ + + + +
+

Open Source Core

+

Our core encryption libraries are open source. Audit the code yourself—we encourage it.

+
+ +
+
+ + + + +
+

GDPR Compliant

+

Full compliance with EU data protection regulations. Your rights are our priority.

+
+ +
+
+ + + + + +
+

No Hidden Trackers

+

We don't use Google Analytics, Facebook Pixel, or any third-party tracking scripts.

+
+
+
+
+ + +
+
+
+
+

Ready to Take Back Your Privacy?

+

+ Join thousands of users who've made the switch to privacy-first internet services. + Start with our 30-day free trial—no credit card required. +

+ +
+
+
+
+ + + + + + + + diff --git a/wwwroot/js/main.js b/wwwroot/js/main.js new file mode 100644 index 0000000..c1d6558 --- /dev/null +++ b/wwwroot/js/main.js @@ -0,0 +1,616 @@ +/** + * Privacy First - Main JavaScript + * Handles animations, interactions, and visual effects + */ + +(function() { + 'use strict'; + + // ========================================================================== + // Configuration + // ========================================================================== + + const CONFIG = { + particles: { + count: 80, + color: '#00d4aa', + colorSecondary: '#7c5cff', + maxDistance: 120, + speed: 0.3, + mouseRadius: 150 + }, + scroll: { + revealOffset: 100, + headerOffset: 50 + } + }; + + // ========================================================================== + // Particle System + // ========================================================================== + + class ParticleSystem { + constructor(canvasId) { + this.canvas = document.getElementById(canvasId); + if (!this.canvas) return; + + this.ctx = this.canvas.getContext('2d'); + this.particles = []; + this.mouse = { x: null, y: null }; + this.animationId = null; + + this.init(); + this.addEventListeners(); + this.animate(); + } + + init() { + this.resize(); + this.createParticles(); + } + + resize() { + this.width = this.canvas.width = this.canvas.offsetWidth; + this.height = this.canvas.height = this.canvas.offsetHeight; + } + + createParticles() { + this.particles = []; + const count = Math.min(CONFIG.particles.count, Math.floor((this.width * this.height) / 15000)); + + for (let i = 0; i < count; i++) { + this.particles.push({ + x: Math.random() * this.width, + y: Math.random() * this.height, + vx: (Math.random() - 0.5) * CONFIG.particles.speed, + vy: (Math.random() - 0.5) * CONFIG.particles.speed, + radius: Math.random() * 2 + 1, + color: Math.random() > 0.5 ? CONFIG.particles.color : CONFIG.particles.colorSecondary, + alpha: Math.random() * 0.5 + 0.3 + }); + } + } + + addEventListeners() { + window.addEventListener('resize', () => { + this.resize(); + this.createParticles(); + }); + + this.canvas.addEventListener('mousemove', (e) => { + const rect = this.canvas.getBoundingClientRect(); + this.mouse.x = e.clientX - rect.left; + this.mouse.y = e.clientY - rect.top; + }); + + this.canvas.addEventListener('mouseleave', () => { + this.mouse.x = null; + this.mouse.y = null; + }); + } + + drawParticle(particle) { + this.ctx.beginPath(); + this.ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI * 2); + this.ctx.fillStyle = particle.color; + this.ctx.globalAlpha = particle.alpha; + this.ctx.fill(); + this.ctx.globalAlpha = 1; + } + + drawConnections() { + for (let i = 0; i < this.particles.length; i++) { + for (let j = i + 1; j < this.particles.length; j++) { + const dx = this.particles[i].x - this.particles[j].x; + const dy = this.particles[i].y - this.particles[j].y; + const distance = Math.sqrt(dx * dx + dy * dy); + + if (distance < CONFIG.particles.maxDistance) { + const alpha = (1 - distance / CONFIG.particles.maxDistance) * 0.3; + this.ctx.beginPath(); + this.ctx.moveTo(this.particles[i].x, this.particles[i].y); + this.ctx.lineTo(this.particles[j].x, this.particles[j].y); + this.ctx.strokeStyle = CONFIG.particles.color; + this.ctx.globalAlpha = alpha; + this.ctx.lineWidth = 0.5; + this.ctx.stroke(); + this.ctx.globalAlpha = 1; + } + } + } + } + + updateParticle(particle) { + // Mouse interaction + if (this.mouse.x !== null && this.mouse.y !== null) { + const dx = particle.x - this.mouse.x; + const dy = particle.y - this.mouse.y; + const distance = Math.sqrt(dx * dx + dy * dy); + + if (distance < CONFIG.particles.mouseRadius) { + const force = (CONFIG.particles.mouseRadius - distance) / CONFIG.particles.mouseRadius; + particle.vx += (dx / distance) * force * 0.02; + particle.vy += (dy / distance) * force * 0.02; + } + } + + // Apply velocity + particle.x += particle.vx; + particle.y += particle.vy; + + // Apply friction + particle.vx *= 0.99; + particle.vy *= 0.99; + + // Boundary check + if (particle.x < 0 || particle.x > this.width) { + particle.vx *= -1; + particle.x = Math.max(0, Math.min(this.width, particle.x)); + } + if (particle.y < 0 || particle.y > this.height) { + particle.vy *= -1; + particle.y = Math.max(0, Math.min(this.height, particle.y)); + } + } + + animate() { + this.ctx.clearRect(0, 0, this.width, this.height); + + // Update and draw particles + this.particles.forEach(particle => { + this.updateParticle(particle); + this.drawParticle(particle); + }); + + // Draw connections + this.drawConnections(); + + this.animationId = requestAnimationFrame(() => this.animate()); + } + + destroy() { + if (this.animationId) { + cancelAnimationFrame(this.animationId); + } + } + } + + // ========================================================================== + // Scroll Reveal + // ========================================================================== + + class ScrollReveal { + constructor() { + this.elements = document.querySelectorAll('.reveal'); + this.init(); + } + + init() { + // Initial check + this.checkElements(); + + // Scroll listener with throttle + let ticking = false; + window.addEventListener('scroll', () => { + if (!ticking) { + window.requestAnimationFrame(() => { + this.checkElements(); + ticking = false; + }); + ticking = true; + } + }); + } + + checkElements() { + this.elements.forEach(element => { + if (this.isInViewport(element)) { + element.classList.add('active'); + } + }); + } + + isInViewport(element) { + const rect = element.getBoundingClientRect(); + return ( + rect.top <= (window.innerHeight || document.documentElement.clientHeight) - CONFIG.scroll.revealOffset + ); + } + } + + // ========================================================================== + // Header Controller + // ========================================================================== + + class HeaderController { + constructor() { + this.header = document.getElementById('header'); + this.lastScroll = 0; + this.init(); + } + + init() { + window.addEventListener('scroll', () => this.handleScroll()); + this.handleScroll(); // Initial check + } + + handleScroll() { + const currentScroll = window.pageYOffset; + + if (currentScroll > CONFIG.scroll.headerOffset) { + this.header.classList.add('scrolled'); + } else { + this.header.classList.remove('scrolled'); + } + + this.lastScroll = currentScroll; + } + } + + // ========================================================================== + // Mobile Navigation + // ========================================================================== + + class MobileNav { + constructor() { + this.toggle = document.getElementById('nav-toggle'); + this.close = document.getElementById('nav-close'); + this.menu = document.getElementById('nav-menu'); + this.links = document.querySelectorAll('.nav__link'); + + if (this.toggle && this.menu) { + this.init(); + } + } + + init() { + this.toggle.addEventListener('click', () => this.openMenu()); + this.close.addEventListener('click', () => this.closeMenu()); + + // Close on link click + this.links.forEach(link => { + link.addEventListener('click', () => this.closeMenu()); + }); + + // Close on outside click + document.addEventListener('click', (e) => { + if (!this.menu.contains(e.target) && !this.toggle.contains(e.target)) { + this.closeMenu(); + } + }); + + // Close on escape + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape') { + this.closeMenu(); + } + }); + } + + openMenu() { + this.menu.classList.add('active'); + document.body.style.overflow = 'hidden'; + } + + closeMenu() { + this.menu.classList.remove('active'); + document.body.style.overflow = ''; + } + } + + // ========================================================================== + // Pricing Toggle + // ========================================================================== + + class PricingToggle { + constructor() { + this.toggle = document.getElementById('pricing-toggle'); + this.labels = document.querySelectorAll('.pricing__toggle-label'); + this.amounts = document.querySelectorAll('.pricing-card__amount[data-monthly]'); + this.isAnnual = false; + + if (this.toggle) { + this.init(); + } + } + + init() { + this.toggle.addEventListener('click', () => this.handleToggle()); + this.updateLabels(); + } + + handleToggle() { + this.isAnnual = !this.isAnnual; + this.toggle.classList.toggle('annual', this.isAnnual); + this.updatePrices(); + this.updateLabels(); + } + + updatePrices() { + this.amounts.forEach(amount => { + const monthly = amount.dataset.monthly; + const annual = amount.dataset.annual; + amount.textContent = this.isAnnual ? annual : monthly; + }); + } + + updateLabels() { + this.labels.forEach(label => { + const period = label.dataset.period; + if (period === 'annual') { + label.classList.toggle('active', this.isAnnual); + } else { + label.classList.toggle('active', !this.isAnnual); + } + }); + } + } + + // ========================================================================== + // Smooth Scroll + // ========================================================================== + + class SmoothScroll { + constructor() { + this.links = document.querySelectorAll('a[href^="#"]'); + this.init(); + } + + init() { + this.links.forEach(link => { + link.addEventListener('click', (e) => this.handleClick(e, link)); + }); + } + + handleClick(e, link) { + const href = link.getAttribute('href'); + if (href === '#') return; + + const target = document.querySelector(href); + if (target) { + e.preventDefault(); + const headerOffset = 80; + const elementPosition = target.getBoundingClientRect().top; + const offsetPosition = elementPosition + window.pageYOffset - headerOffset; + + window.scrollTo({ + top: offsetPosition, + behavior: 'smooth' + }); + } + } + } + + // ========================================================================== + // Typing Effect for Hero + // ========================================================================== + + class TypeWriter { + constructor(element, words, wait = 2000) { + this.element = element; + this.words = words; + this.txt = ''; + this.wordIndex = 0; + this.wait = parseInt(wait, 10); + this.isDeleting = false; + this.type(); + } + + type() { + const current = this.wordIndex % this.words.length; + const fullTxt = this.words[current]; + + if (this.isDeleting) { + this.txt = fullTxt.substring(0, this.txt.length - 1); + } else { + this.txt = fullTxt.substring(0, this.txt.length + 1); + } + + this.element.innerHTML = `${this.txt}`; + + let typeSpeed = 100; + + if (this.isDeleting) { + typeSpeed /= 2; + } + + if (!this.isDeleting && this.txt === fullTxt) { + typeSpeed = this.wait; + this.isDeleting = true; + } else if (this.isDeleting && this.txt === '') { + this.isDeleting = false; + this.wordIndex++; + typeSpeed = 500; + } + + setTimeout(() => this.type(), typeSpeed); + } + } + + // ========================================================================== + // Form Handlers + // ========================================================================== + + class FormHandler { + constructor() { + this.notifyForm = document.querySelector('.notify-form'); + if (this.notifyForm) { + this.init(); + } + } + + init() { + this.notifyForm.addEventListener('submit', (e) => this.handleSubmit(e)); + } + + handleSubmit(e) { + e.preventDefault(); + const input = this.notifyForm.querySelector('input[type="email"]'); + const button = this.notifyForm.querySelector('button'); + + if (input.value && this.validateEmail(input.value)) { + button.textContent = 'Subscribed!'; + button.disabled = true; + input.disabled = true; + + setTimeout(() => { + button.textContent = 'Notify Me'; + button.disabled = false; + input.disabled = false; + input.value = ''; + }, 3000); + } + } + + validateEmail(email) { + const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return re.test(email); + } + } + + // ========================================================================== + // Mockup Animations + // ========================================================================== + + class MockupAnimations { + constructor() { + this.mockupServices = document.querySelectorAll('.mockup__service'); + this.passportServices = document.querySelectorAll('.passport-card__service'); + this.init(); + } + + init() { + // Cycle through mockup services + if (this.mockupServices.length > 0) { + this.cycleServices(this.mockupServices, 2500); + } + + // Cycle through passport services + if (this.passportServices.length > 0) { + this.cycleServices(this.passportServices, 3000); + } + } + + cycleServices(services, interval) { + let currentIndex = 0; + + setInterval(() => { + services.forEach(s => s.classList.remove('active')); + currentIndex = (currentIndex + 1) % services.length; + services[currentIndex].classList.add('active'); + }, interval); + } + } + + // ========================================================================== + // Intersection Observer for Stats Animation + // ========================================================================== + + class StatsAnimation { + constructor() { + this.stats = document.querySelectorAll('.stat-card__value, .cp-stat__value'); + this.animated = new Set(); + this.init(); + } + + init() { + const observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting && !this.animated.has(entry.target)) { + this.animateValue(entry.target); + this.animated.add(entry.target); + } + }); + }, { threshold: 0.5 }); + + this.stats.forEach(stat => observer.observe(stat)); + } + + animateValue(element) { + const text = element.textContent; + const match = text.match(/^([\d,.]+)/); + + if (!match) return; + + const finalValue = parseFloat(match[1].replace(/,/g, '')); + const suffix = text.replace(match[1], ''); + const duration = 1500; + const startTime = performance.now(); + + const animate = (currentTime) => { + const elapsed = currentTime - startTime; + const progress = Math.min(elapsed / duration, 1); + + // Easing function + const easeOutQuart = 1 - Math.pow(1 - progress, 4); + const currentValue = finalValue * easeOutQuart; + + // Format number + let displayValue; + if (finalValue >= 1000) { + displayValue = Math.floor(currentValue).toLocaleString(); + } else if (finalValue >= 100) { + displayValue = Math.floor(currentValue); + } else if (finalValue % 1 !== 0) { + displayValue = currentValue.toFixed(1); + } else { + displayValue = Math.floor(currentValue); + } + + element.textContent = displayValue + suffix; + + if (progress < 1) { + requestAnimationFrame(animate); + } else { + element.textContent = text; // Restore original + } + }; + + requestAnimationFrame(animate); + } + } + + // ========================================================================== + // Initialize Everything + // ========================================================================== + + function init() { + // Initialize particle system + new ParticleSystem('particle-canvas'); + + // Initialize scroll reveal + new ScrollReveal(); + + // Initialize header controller + new HeaderController(); + + // Initialize mobile navigation + new MobileNav(); + + // Initialize pricing toggle + new PricingToggle(); + + // Initialize smooth scroll + new SmoothScroll(); + + // Initialize form handlers + new FormHandler(); + + // Initialize mockup animations + new MockupAnimations(); + + // Initialize stats animation + new StatsAnimation(); + + // Log init complete + console.log('Privacy First website initialized'); + } + + // Run on DOM ready + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); + } else { + init(); + } + +})();