diff --git a/website/app.js b/website/app.js
index f34abc2..2a0f050 100644
--- a/website/app.js
+++ b/website/app.js
@@ -74,8 +74,14 @@ document.addEventListener('DOMContentLoaded', () => {
const isFirefox = navigator.userAgent.includes('Firefox');
if (isFirefox) {
actions.innerHTML = `
- GET IT ON MOZILLA ADD-ONS
- Download via GitHub
+
+ 🦊
+ GET IT ON MOZILLA ADD-ONS IM FIREFOX ADD-ON STORE HERUNTERLADEN
+
+
+
+ Download via GitHub Über GitHub herunterladen
+
The extension is required to join and sync videos.
Die Erweiterung ist erforderlich, um beizutreten und Videos zu synchronisieren.
@@ -83,8 +89,14 @@ document.addEventListener('DOMContentLoaded', () => {
`;
} else {
actions.innerHTML = `
- GET IT ON CHROME WEBSTORE
- Download via GitHub
+
+
+ GET IT ON CHROME WEBSTORE IM CHROME WEB STORE HERUNTERLADEN
+
+
+
+ Download via GitHub Über GitHub herunterladen
+
The extension is required to join and sync videos.
Die Erweiterung ist erforderlich, um beizutreten und Videos zu synchronisieren.
@@ -95,8 +107,12 @@ document.addEventListener('DOMContentLoaded', () => {
actions.innerHTML = `
🚀
-
Joining room automatically...
-
Your extension is taking care of it.
+
+ Joining room automatically... Raum wird automatisch betreten...
+
+
+ Your extension is taking care of it. Deine Erweiterung kümmert sich darum.
+
`;
@@ -270,6 +286,70 @@ document.addEventListener('DOMContentLoaded', () => {
}
};
+ // Extension Mockup Tab Switcher
+ const mockTabs = document.querySelectorAll('.mock-tab');
+ const mockScreens = document.querySelectorAll('.mock-screen');
+
+ mockTabs.forEach(tab => {
+ tab.addEventListener('click', () => {
+ mockTabs.forEach(t => t.classList.remove('active'));
+ mockScreens.forEach(s => s.classList.remove('active'));
+
+ tab.classList.add('active');
+ const targetId = tab.getAttribute('data-target');
+ const targetScreen = document.getElementById(targetId);
+ if (targetScreen) {
+ targetScreen.classList.add('active');
+ }
+ });
+ });
+
+ // Terminal Tab Switcher
+ const termTabBtns = document.querySelectorAll('.terminal-tab-btn');
+ const termPanes = document.querySelectorAll('.terminal-pane');
+
+ termTabBtns.forEach(btn => {
+ btn.addEventListener('click', () => {
+ termTabBtns.forEach(b => b.classList.remove('active'));
+ termPanes.forEach(p => p.classList.remove('active'));
+
+ btn.classList.add('active');
+ const targetPaneId = btn.getAttribute('data-tab');
+ const targetPane = document.getElementById(targetPaneId);
+ if (targetPane) {
+ targetPane.classList.add('active');
+ }
+ });
+ });
+
+ // Terminal Clipboard Copy
+ const copyBtn = document.querySelector('.terminal-copy-btn');
+ if (copyBtn) {
+ copyBtn.addEventListener('click', () => {
+ const activePane = document.querySelector('.terminal-pane.active');
+ if (!activePane) return;
+ const codeElement = activePane.querySelector('code');
+ if (!codeElement) return;
+
+ const textToCopy = codeElement.innerText || codeElement.textContent;
+
+ navigator.clipboard.writeText(textToCopy).then(() => {
+ const isDE = document.documentElement.classList.contains('lang-de');
+ const originalHTML = copyBtn.innerHTML;
+
+ copyBtn.innerHTML = isDE ? '✅ Kopiert!' : '✅ Copied!';
+ copyBtn.disabled = true;
+
+ setTimeout(() => {
+ copyBtn.innerHTML = originalHTML;
+ copyBtn.disabled = false;
+ }, 2000);
+ }).catch(err => {
+ console.error('Failed to copy text: ', err);
+ });
+ });
+ }
+
checkInvite();
updateDynamicVersion();
});
diff --git a/website/assets/github.svg b/website/assets/github.svg
new file mode 100644
index 0000000..8a900d1
--- /dev/null
+++ b/website/assets/github.svg
@@ -0,0 +1 @@
+
diff --git a/website/index.html b/website/index.html
index 900d904..972e6f9 100644
--- a/website/index.html
+++ b/website/index.html
@@ -56,8 +56,14 @@
@@ -71,8 +77,8 @@
Gemeinsam schauen. Perfekt synchron.
- The ultimate free watch party extension for YouTube, Twitch, and local MP4s.
- Die ultimative, kostenlose Watch-Party-Erweiterung für YouTube, Twitch und lokale MP4s.
+ The ultimate free watch party extension for YouTube, Twitch, and local MP4s. Built for extreme precision and data sovereignty.
+ Die ultimative, kostenlose Watch-Party-Erweiterung für YouTube, Twitch und lokale MP4s. Entwickelt für extreme Präzision und Datenhoheit.
+
+
+
+
+
+
+ Room
+ Sync
+ Settings
+ Dev
+
+
+
+
+
+ brave-eagle-80
+ Official Server
+
+
+
Invite Link
+
+
+ Copy
+
+
+
+
Peers in Room
+
+
+
+
🎬 Germany's Next Flopmodel - S21E12
+
● 0:55 • Playing
+
+
+
+
🎬 Germany's Next Flopmodel - S21E12
+
● 0:55 • Playing
+
+
+
+
Leave Room
+
+
+
+
+
+ ⭐ MATCH: Germany's Next Flopmodel - S21E12
+
+
+
Remote Control
+
+ ▶ Play
+ ⏸ Pause
+ ⚡ Force Sync Everyone
+
+
+
+
Last Activity Status
+
+ PAUSE
+ ● In Sync
+
+
+ Pause triggered by CoolUsername
+
+
+
+
+
+
+
+
+
Preferences
+
+
+
+
Filter Noise Tabs
+
Hide common non-video websites from the target selector.
+
+
+
+
+
+
Auto-Sync Next Episode
+
Automatically sync transitions between series episodes.
+
+
+
+
Regenerate Peer ID
+
+
+
+
+
+
Diagnostics
+
+
+
Ready State
+
HAVE_ENOUGH_DATA
+
+
+
+
+
Engine State
+
SYNCED
+
+
+
+
+
Event Stream
+
+
[18:37:32] EVENT: PLAY -> ACK
+
[18:37:32] FORCE_SYNC -> 0.05s diff
+
[18:37:38] EVENT: PAUSE -> BROADCAST
+
[18:37:42] content_heartbeat: active
+
+
+
+
+
+
@@ -97,33 +243,46 @@
Why KoalaSync? Warum KoalaSync?
- Built for performance, privacy, and simplicity. Entwickelt für Leistung, Privatsphäre und Einfachheit.
+ Built for frame-perfect performance, absolute privacy, and total simplicity.
+ Entwickelt für bildgenaue Leistung, absolute Privatsphäre und totale Einfachheit.
⚡
-
Real-time Sync Echtzeit-Synchronisation
-
Proprietary two-phase synchronization protocol ensures sub-millisecond precision across all peers.
-
Das proprietäre Zwei-Phasen-Synchronisationsprotokoll gewährleistet Sub-Millisekunden-Präzision für alle Teilnehmer.
+
+ Full Control / Instant Sync
+ Volle Kontrolle & Echtzeit
+
+
One pauses, everyone pauses. One seeks, everyone follows. Our custom two-phase sync protocol coordinates playback with sub-millisecond precision across all participants.
+
Einer pausiert, alle pausieren. Einer spult, alle folgen. Unser Zwei-Phasen-Synchronisationsprotokoll koordiniert die Wiedergabe in Echtzeit mit Sub-Millisekunden-Präzision.
🎬
-
Episode Auto-Sync Automatische Episoden-Synchronisation
-
Perfectly sync series binges. All peers wait until everyone has loaded the next episode.
-
Perfekt synchronisiertes Serien-Bingeing. Alle warten, bis jeder die nächste Episode geladen hat.
+
+ Endless Binge-Watching
+ Grenzenloses Bingen
+
+
Autoplay perfectly in sync. KoalaSync automatically detects episode transitions and holds playback until all peers have successfully loaded the next video.
+
Nächste Episode startet für jeden zeitgleich. KoalaSync erkennt den Episodenwechsel und pausiert, bis jeder Teilnehmer das neue Video fertig geladen hat.
🛡️
-
Privacy First Privatsphäre zuerst
-
Zero data persistence. Our relay server runs entirely in RAM and collects no telemetry or logs.
-
Keine Datenspeicherung. Unser Relay-Server läuft komplett im RAM und sammelt weder Telemetrie noch Logs.
+
+ Zero Accounts / Pure Privacy
+ Keine Accounts / Datenschutz
+
+
No registration, no tracking, and no database persistence. The server runs entirely in RAM, collects no telemetry or logs, and completely forgets your room when you leave.
+
Keine Registrierung, kein Tracking und keine Datenspeicherung. Der Server läuft flüchtig im RAM, sammelt keine Logs und vergisst deinen Raum sofort nach dem Verlassen.
-
⭐
-
Smart Match Intelligente Zuordnung
-
Find the right tab instantly. KoalaSync highlights and sorts matching video tabs for you.
-
Finden Sie sofort den richtigen Tab. KoalaSync markiert und sortiert passende Video-Tabs für Sie.
+
🌐
+
+ Universal HTML5 Support
+ Universeller HTML5-Support
+
+
Works on YouTube, Twitch, Netflix, Disney+, Jellyfin, Emby, and any standard webpage containing a HTML5 video element. Perfect for custom self-hosted setups.
+
Unterstützt YouTube, Twitch, Netflix, Disney+, Jellyfin, Emby und jede beliebige Webseite mit einem HTML5-Video-Tag. Ideal auch für eigene Medienbibliotheken.
@@ -144,7 +303,25 @@
Add KoalaSync to your browser from the Chrome Web Store, Firefox Add-ons, or download the latest developer ZIP from GitHub.
Füge KoalaSync aus dem Chrome Web Store, den Firefox Add-ons oder über die Entwickler-ZIP von GitHub zu deinem Browser hinzu.
-
+
+
@@ -153,7 +330,20 @@
Open the extension, enter a Room ID and Password, and hit Join. Your secure synchronization space is ready.
Öffnen Sie die Erweiterung, geben Sie eine Raum-ID und ein Passwort ein und klicken Sie auf Beitreten. Ihr sicherer Synchronisationsraum ist bereit.
-
+
+
@@ -162,7 +352,103 @@
Send the invite link to your friends. Once they join, select your video tab and enjoy perfectly synced playback.
Senden Sie den Einladungslink an Ihre Freunde. Sobald sie beitreten, wählen Sie Ihren Video-Tab aus und genießen Sie die perfekt synchronisierte Wiedergabe.
-
+
+
+
+
+
+
+
+
+
+
+
+ Self-Hosters Paradise Das Paradies für Self-Hoster
+
+
+ Maintain absolute data sovereignty. Deploy your own private high-performance relay server in under 60 seconds.
+ Behalte die absolute Datenhoheit. Richte deinen eigenen privaten Hochleistungs-Relay-Server in unter 60 Sekunden ein.
+
+
+
+
+
+
+ 📋 Copy Code Code kopieren
+
+
+
+
version: "3.8"
+
+services:
+ koalasync:
+ image: ghcr.io/shik3i/koalasync:latest
+ container_name: koalasync-relay
+ ports:
+ - "3000:3000"
+ environment:
+ - NODE_ENV=production
+ - PORT=3000
+ restart: always
+ logging:
+ driver: "json-file"
+ options:
+ max-size: "10m"
+
+
+
+
+sync.yourdomain.com {
+ reverse_proxy localhost:3000
+
+ header {
+
+ Permissions-Policy "interest-cohort=()"
+ Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
+ X-Content-Type-Options "nosniff"
+ X-Frame-Options "DENY"
+ }
+}
+
diff --git a/website/join.html b/website/join.html
index dc1fb4a..e38cdb2 100644
--- a/website/join.html
+++ b/website/join.html
@@ -48,8 +48,14 @@
☰
diff --git a/website/style.css b/website/style.css
index 053d0b8..0f7f06a 100644
--- a/website/style.css
+++ b/website/style.css
@@ -156,43 +156,45 @@ nav {
display: flex;
align-items: center;
padding-top: 8rem;
- text-align: center;
+ padding-bottom: 4rem;
}
.hero-grid {
- display: flex;
- flex-direction: column;
+ display: grid;
+ grid-template-columns: 1.2fr 1fr;
align-items: center;
- gap: 2rem;
+ gap: 4rem;
+ text-align: left;
+ width: 100%;
}
.hero-text h1 {
- font-size: 5rem;
+ font-size: 4.5rem;
font-weight: 800;
- line-height: 1;
+ line-height: 1.1;
margin-bottom: 1.5rem;
- background: linear-gradient(to bottom, #fff 30%, #6366f1);
+ background: linear-gradient(to bottom, #fff 40%, #6366f1);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.hero-text p, .hero-subtitle {
- font-size: 1.5rem;
+ font-size: 1.25rem;
color: var(--text-muted);
- margin-bottom: 3rem;
- max-width: 700px;
- margin-left: auto;
- margin-right: auto;
+ margin-bottom: 2.5rem;
+ max-width: 600px;
font-weight: 400;
+ line-height: 1.6;
}
.cta-group {
display: flex;
gap: 1rem;
+ flex-wrap: wrap;
}
.btn {
- padding: 1rem 2rem;
+ padding: 0.85rem 1.75rem;
border-radius: 12px;
font-weight: 600;
text-decoration: none;
@@ -200,6 +202,7 @@ nav {
display: inline-flex;
align-items: center;
gap: 0.5rem;
+ font-size: 0.95rem;
}
.btn-primary {
@@ -240,9 +243,9 @@ nav {
display: inline-block;
background: rgba(99, 102, 241, 0.1);
color: var(--accent);
- padding: 0.5rem 1.25rem;
+ padding: 0.4rem 1rem;
border-radius: 99px;
- font-size: 0.85rem;
+ font-size: 0.8rem;
font-weight: 700;
margin-bottom: 1.5rem;
border: 1px solid rgba(99, 102, 241, 0.3);
@@ -250,15 +253,334 @@ nav {
text-transform: uppercase;
}
+/* --- Interactive CSS Extension Mockup --- */
+.hero-mockup-wrapper {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+}
-.hero-image {
+.extension-mockup {
+ width: 320px;
+ height: 490px;
+ background: #0f172a;
+ border-radius: 20px;
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4), 0 0 20px rgba(99, 102, 241, 0.15);
+ display: flex;
+ flex-direction: column;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
+ overflow: hidden;
+ position: relative;
+ user-select: none;
+}
+
+.mock-header {
+ background: #1e293b;
+ padding: 0.85rem 1rem;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
+}
+
+.mock-header img {
+ width: 20px;
+ height: 20px;
+}
+
+.mock-header span {
+ font-weight: 800;
+ font-size: 0.95rem;
+ letter-spacing: 0.5px;
+ color: var(--text);
+}
+
+.mock-tabs {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ background: #1e293b;
+ padding: 0.25rem;
+ gap: 0.25rem;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
+}
+
+.mock-tab {
+ background: none;
+ border: none;
+ color: var(--text-muted);
+ font-size: 0.75rem;
+ font-weight: 600;
+ padding: 0.4rem 0;
+ cursor: pointer;
+ border-radius: 6px;
+ transition: all 0.2s;
+}
+
+.mock-tab:hover {
+ color: var(--text);
+}
+
+.mock-tab.active {
+ background: var(--accent);
+ color: white;
+}
+
+.mock-body {
+ flex: 1;
+ overflow-y: auto;
+ padding: 0.95rem;
+ display: flex;
+ flex-direction: column;
+ gap: 0.85rem;
+ font-size: 0.8rem;
+}
+
+.mock-screen {
display: none;
+ flex-direction: column;
+ gap: 0.85rem;
+ height: 100%;
+}
+
+.mock-screen.active {
+ display: flex;
+}
+
+/* Common Mockup Components */
+.mock-card {
+ background: #1e293b;
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ border-radius: 10px;
+ padding: 0.75rem;
+}
+
+.mock-label {
+ font-size: 0.65rem;
+ font-weight: 700;
+ color: var(--text-muted);
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ margin-bottom: 0.4rem;
+}
+
+.mock-input {
+ background: #0f172a;
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ border-radius: 6px;
+ color: white;
+ padding: 0.45rem;
+ font-size: 0.75rem;
+ width: 100%;
+ outline: none;
+}
+
+.mock-btn {
+ background: var(--accent);
+ color: white;
+ border: none;
+ border-radius: 6px;
+ padding: 0.5rem;
+ font-weight: 600;
+ font-size: 0.75rem;
+ cursor: pointer;
+ transition: background 0.2s;
+ text-align: center;
+}
+
+.mock-btn:hover {
+ background: #4f46e5;
+}
+
+/* Room Tab Details */
+.mock-joined-room {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ background: rgba(99, 102, 241, 0.1);
+ border: 1px solid rgba(99, 102, 241, 0.2);
+ border-radius: 8px;
+ padding: 0.6rem 0.75rem;
+}
+
+.mock-room-name {
+ font-weight: 700;
+ color: var(--accent);
+ font-size: 0.85rem;
+}
+
+.mock-server-badge {
+ background: rgba(99, 102, 241, 0.2);
+ color: var(--accent);
+ font-size: 0.6rem;
+ font-weight: 700;
+ padding: 2px 6px;
+ border-radius: 4px;
+}
+
+.mock-invite-box {
+ display: flex;
+ gap: 0.4rem;
+}
+
+.mock-invite-box input {
+ flex: 1;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.mock-peer-list {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.mock-peer-item {
+ display: flex;
+ flex-direction: column;
+ background: rgba(255, 255, 255, 0.02);
+ border: 1px solid rgba(255, 255, 255, 0.03);
+ border-radius: 8px;
+ padding: 0.5rem 0.6rem;
+}
+
+.mock-peer-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 0.25rem;
+}
+
+.mock-peer-name {
+ font-weight: 700;
+ color: var(--text);
+}
+
+.mock-peer-meta {
+ font-size: 0.65rem;
+ color: var(--text-muted);
+}
+
+.mock-peer-tab {
+ font-size: 0.7rem;
+ color: var(--accent);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.mock-peer-status {
+ font-size: 0.65rem;
+ color: var(--text-muted);
+ display: flex;
+ align-items: center;
+ gap: 0.25rem;
+}
+
+/* Sync Tab Details */
+.mock-target-box {
+ display: flex;
+ align-items: center;
+ gap: 0.4rem;
+ background: rgba(234, 179, 8, 0.1);
+ border: 1px solid rgba(234, 179, 8, 0.2);
+ color: #facc15;
+ padding: 0.5rem 0.6rem;
+ border-radius: 8px;
+ font-weight: 600;
+ font-size: 0.7rem;
+}
+
+.mock-ctrl-buttons {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 0.5rem;
+}
+
+.mock-btn-play { background: #22c55e; }
+.mock-btn-play:hover { background: #16a34a; }
+.mock-btn-pause { background: #ef4444; }
+.mock-btn-pause:hover { background: #dc2626; }
+.mock-btn-force { background: var(--accent); grid-column: span 2; }
+
+.mock-status-display {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.mock-status-pill {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.3rem;
+ background: rgba(34, 197, 94, 0.1);
+ border: 1px solid rgba(34, 197, 94, 0.2);
+ color: #22c55e;
+ padding: 2px 8px;
+ border-radius: 99px;
+ font-size: 0.65rem;
+ font-weight: 700;
+}
+
+.mock-log-item {
+ font-size: 0.7rem;
+ color: var(--text-muted);
+ border-left: 2px solid var(--accent);
+ padding-left: 0.4rem;
+ margin-top: 0.4rem;
+}
+
+/* Settings Tab Details */
+.mock-settings-row {
+ display: flex;
+ align-items: flex-start;
+ gap: 0.5rem;
+ margin-bottom: 0.6rem;
+}
+
+.mock-settings-row input[type="checkbox"] {
+ margin-top: 0.2rem;
+ cursor: pointer;
+}
+
+.mock-settings-row label {
+ cursor: pointer;
+ font-weight: 600;
+}
+
+.mock-settings-row p {
+ font-size: 0.65rem;
+ color: var(--text-muted);
+ margin-top: 0.1rem;
+}
+
+/* Dev Tab Details */
+.mock-diagnostic-grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 0.4rem;
+}
+
+.mock-diag-box {
+ background: rgba(255, 255, 255, 0.02);
+ border: 1px solid rgba(255, 255, 255, 0.04);
+ border-radius: 6px;
+ padding: 0.4rem;
+}
+
+.mock-diag-box .diag-val {
+ font-family: monospace;
+ font-weight: 700;
+ color: var(--accent);
+ font-size: 0.75rem;
}
/* --- Features --- */
.features-grid {
display: grid;
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 2rem;
margin-top: 4rem;
}
@@ -268,17 +590,33 @@ nav {
padding: 2.5rem;
border-radius: 24px;
border: 1px solid var(--glass-border);
- transition: transform 0.3s;
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ position: relative;
+}
+
+.feature-card::before {
+ content: '';
+ position: absolute;
+ top: 0; left: 0; right: 0; bottom: 0;
+ border-radius: 24px;
+ padding: 1px;
+ background: linear-gradient(to bottom right, rgba(99, 102, 241, 0.25), transparent);
+ -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
+ -webkit-mask-composite: xor;
+ mask-composite: exclude;
+ pointer-events: none;
}
.feature-card:hover {
- transform: translateY(-10px);
+ transform: translateY(-5px);
+ box-shadow: 0 15px 30px rgba(99, 102, 241, 0.15);
+ border-color: rgba(99, 102, 241, 0.2);
}
.feature-icon {
width: 48px;
height: 48px;
- background: var(--accent-glow);
+ background: rgba(99, 102, 241, 0.1);
color: var(--accent);
display: flex;
align-items: center;
@@ -286,28 +624,32 @@ nav {
border-radius: 12px;
margin-bottom: 1.5rem;
font-size: 1.5rem;
+ border: 1px solid rgba(99, 102, 241, 0.2);
}
.feature-card h3 {
- margin-bottom: 1rem;
- font-size: 1.5rem;
+ margin-bottom: 0.75rem;
+ font-size: 1.35rem;
+ font-weight: 700;
}
.feature-card p {
color: var(--text-muted);
+ font-size: 0.95rem;
+ line-height: 1.5;
}
/* --- How it works --- */
.steps {
display: flex;
flex-direction: column;
- gap: 4rem;
+ gap: 6rem;
}
.step {
display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 4rem;
+ grid-template-columns: 1fr 1.1fr;
+ gap: 6rem;
align-items: center;
}
@@ -316,11 +658,412 @@ nav {
}
.step-num {
- font-size: 5rem;
+ font-size: 4rem;
font-weight: 800;
- color: var(--accent-glow);
+ color: rgba(99, 102, 241, 0.15);
line-height: 1;
+ margin-bottom: 0.5rem;
+}
+
+.step-text h3 {
+ font-size: 1.85rem;
margin-bottom: 1rem;
+ font-weight: 800;
+}
+
+.step-text p {
+ color: var(--text-muted);
+ font-size: 1.05rem;
+ line-height: 1.6;
+}
+
+/* Custom CSS Mockups for step illustrations */
+.step-illustration-1, .step-illustration-2, .step-illustration-3 {
+ background: #1e293b;
+ height: 240px;
+ border-radius: 20px;
+ border: 1px solid var(--glass-border);
+ position: relative;
+ overflow: hidden;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 15px 30px rgba(0, 0, 0, 0.3);
+}
+
+/* Step 1 Illustration: Browser & Extension icon trigger */
+.illus-browser-bar {
+ width: 85%;
+ background: #0f172a;
+ border: 1px solid rgba(255,255,255,0.05);
+ border-radius: 10px;
+ overflow: hidden;
+ box-shadow: 0 10px 20px rgba(0,0,0,0.4);
+}
+
+.illus-browser-header {
+ background: #1e293b;
+ padding: 0.5rem 0.75rem;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-bottom: 1px solid rgba(255,255,255,0.05);
+}
+
+.illus-dots {
+ display: flex;
+ gap: 4px;
+}
+
+.illus-dot {
+ width: 6px;
+ height: 6px;
+ border-radius: 50%;
+ background: rgba(255,255,255,0.2);
+}
+
+.illus-address-bar {
+ background: #0f172a;
+ border: 1px solid rgba(255,255,255,0.05);
+ padding: 2px 10px;
+ border-radius: 4px;
+ width: 60%;
+ height: 14px;
+}
+
+.illus-extension-icon {
+ position: relative;
+ width: 20px;
+ height: 20px;
+ background: rgba(99, 102, 241, 0.2);
+ border: 1px solid var(--accent);
+ border-radius: 4px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ animation: pulse-border 2s infinite alternate;
+}
+
+@keyframes pulse-border {
+ 0% { box-shadow: 0 0 0 rgba(99, 102, 241, 0); border-color: rgba(99, 102, 241, 0.4); }
+ 100% { box-shadow: 0 0 8px rgba(99, 102, 241, 0.6); border-color: var(--accent); }
+}
+
+.illus-browser-body {
+ padding: 1.5rem;
+ height: 80px;
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.illus-line-placeholder {
+ height: 8px;
+ background: rgba(255,255,255,0.05);
+ border-radius: 4px;
+}
+
+/* Step 2 Illustration: Typing in Form Fields */
+.illus-form-box {
+ width: 70%;
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+ background: rgba(15, 23, 42, 0.6);
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ border-radius: 12px;
+ padding: 1rem;
+ backdrop-filter: blur(10px);
+}
+
+.illus-form-field {
+ display: flex;
+ flex-direction: column;
+ gap: 0.35rem;
+}
+
+.illus-form-input {
+ background: #0f172a;
+ border: 1px solid rgba(99, 102, 241, 0.3);
+ padding: 0.45rem;
+ border-radius: 6px;
+ height: 28px;
+ position: relative;
+ overflow: hidden;
+}
+
+.illus-typing-text {
+ font-family: monospace;
+ font-weight: 700;
+ color: var(--text);
+ font-size: 0.8rem;
+ display: flex;
+ align-items: center;
+}
+
+.illus-typing-text::after {
+ content: '|';
+ animation: blink-cursor 0.8s infinite;
+ color: var(--accent);
+}
+
+@keyframes blink-cursor {
+ 50% { opacity: 0; }
+}
+
+.illus-form-btn {
+ background: var(--accent);
+ color: white;
+ border: none;
+ border-radius: 6px;
+ padding: 0.45rem;
+ font-weight: 700;
+ font-size: 0.75rem;
+ text-align: center;
+ box-shadow: 0 4px 10px rgba(99, 102, 241, 0.3);
+}
+
+/* Step 3 Illustration: Multi-player Sync simulation */
+.illus-players-container {
+ display: flex;
+ align-items: center;
+ gap: 1.5rem;
+ width: 90%;
+}
+
+.illus-mini-player {
+ flex: 1;
+ background: #0f172a;
+ border: 1px solid rgba(255,255,255,0.05);
+ border-radius: 10px;
+ height: 120px;
+ position: relative;
+ overflow: hidden;
+}
+
+.illus-video-screen {
+ width: 100%;
+ height: 100px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: radial-gradient(circle, rgba(99,102,241,0.15) 0%, transparent 80%);
+}
+
+.illus-play-icon {
+ width: 32px;
+ height: 32px;
+ border-radius: 50%;
+ background: rgba(99, 102, 241, 0.9);
+ color: white;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 0.85rem;
+ box-shadow: 0 0 12px rgba(99, 102, 241, 0.5);
+ position: relative;
+}
+
+.illus-player-timeline {
+ height: 20px;
+ background: #1e293b;
+ display: flex;
+ align-items: center;
+ padding: 0 0.5rem;
+ border-top: 1px solid rgba(255,255,255,0.05);
+}
+
+.illus-timeline-bar {
+ flex: 1;
+ height: 3px;
+ background: rgba(255,255,255,0.1);
+ position: relative;
+ border-radius: 2px;
+}
+
+.illus-timeline-progress {
+ position: absolute;
+ top: 0; left: 0;
+ width: 60%;
+ height: 100%;
+ background: var(--accent);
+ border-radius: 2px;
+ animation: timeline-grow 4s infinite linear;
+}
+
+@keyframes timeline-grow {
+ 0% { width: 0%; }
+ 100% { width: 100%; }
+}
+
+.illus-sync-connection {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 0.25rem;
+ color: var(--accent);
+ font-size: 1.25rem;
+}
+
+.illus-sync-line {
+ width: 40px;
+ height: 2px;
+ background: linear-gradient(to right, var(--accent), var(--success));
+ position: relative;
+}
+
+.illus-sync-pulse {
+ position: absolute;
+ top: -3px;
+ left: 0;
+ width: 8px;
+ height: 8px;
+ background: #fff;
+ border-radius: 50%;
+ box-shadow: 0 0 8px #fff;
+ animation: slide-pulse 2s infinite linear;
+}
+
+@keyframes slide-pulse {
+ 0% { left: 0%; }
+ 100% { left: 100%; }
+}
+
+.illus-sync-label {
+ font-size: 0.55rem;
+ font-weight: 700;
+ background: rgba(34, 197, 94, 0.15);
+ color: #22c55e;
+ padding: 1px 6px;
+ border-radius: 4px;
+ border: 1px solid rgba(34, 197, 94, 0.25);
+ white-space: nowrap;
+}
+
+/* --- Self Hosters Terminal --- */
+.terminal-container {
+ max-width: 850px;
+ margin: 3rem auto 0 auto;
+ background: #0f172a;
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ border-radius: 16px;
+ overflow: hidden;
+ box-shadow: 0 20px 45px rgba(0,0,0,0.5);
+ text-align: left;
+}
+
+.terminal-header {
+ background: #1e293b;
+ padding: 0.85rem 1.25rem;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-bottom: 1px solid rgba(255,255,255,0.06);
+}
+
+.terminal-dots {
+ display: flex;
+ gap: 6px;
+}
+
+.terminal-dot {
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+}
+
+.terminal-dot.red { background: #ef4444; }
+.terminal-dot.yellow { background: #f59e0b; }
+.terminal-dot.green { background: #10b981; }
+
+.terminal-tabs {
+ display: flex;
+ gap: 0.5rem;
+}
+
+.terminal-tab-btn {
+ background: none;
+ border: none;
+ color: var(--text-muted);
+ font-weight: 600;
+ font-size: 0.8rem;
+ padding: 0.35rem 0.75rem;
+ border-radius: 6px;
+ cursor: pointer;
+ transition: all 0.2s;
+}
+
+.terminal-tab-btn:hover {
+ color: var(--text);
+ background: rgba(255, 255, 255, 0.03);
+}
+
+.terminal-tab-btn.active {
+ color: var(--accent);
+ background: rgba(99, 102, 241, 0.1);
+ border: 1px solid rgba(99, 102, 241, 0.2);
+}
+
+.terminal-body {
+ position: relative;
+ padding: 1.5rem;
+}
+
+.terminal-pane {
+ display: none;
+ margin: 0;
+}
+
+.terminal-pane.active {
+ display: block;
+}
+
+.terminal-pane pre {
+ margin: 0;
+ overflow-x: auto;
+}
+
+.terminal-pane code {
+ font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
+ font-size: 0.85rem;
+ line-height: 1.6;
+ color: #e2e8f0;
+}
+
+/* Syntax Highlighting */
+.t-comment { color: #64748b; font-style: italic; }
+.t-key { color: #f472b6; }
+.t-val { color: #38bdf8; }
+.t-str { color: #34d399; }
+.t-num { color: #fbbf24; }
+
+.terminal-copy-btn {
+ position: absolute;
+ top: 1rem;
+ right: 1.5rem;
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ color: var(--text-muted);
+ padding: 0.35rem 0.75rem;
+ font-size: 0.75rem;
+ font-weight: 600;
+ border-radius: 6px;
+ cursor: pointer;
+ transition: all 0.2s;
+ display: flex;
+ align-items: center;
+ gap: 0.3rem;
+}
+
+.terminal-copy-btn:hover {
+ background: rgba(255, 255, 255, 0.08);
+ color: var(--text);
+ border-color: rgba(255, 255, 255, 0.15);
+}
+
+.terminal-copy-btn:active {
+ transform: scale(0.97);
}
/* --- Footer --- */
@@ -343,6 +1086,7 @@ footer {
transform: translateY(0);
}
+
/* --- Legal Pages --- */
.legal-content {
max-width: 800px;