diff --git a/doc/pages/index.html b/doc/pages/index.html index 9913ca0..2f18506 100644 --- a/doc/pages/index.html +++ b/doc/pages/index.html @@ -1,1706 +1,374 @@ - - - - RAVEN C2 — Command and Control Framework - - - - - - - - + + + + RAVEN C2 — Command and Control Framework + + + + + + + + + + + + +
+ +
+
+ + logo + RAVENC2 + + +
+
Navigation
+ +
+
Links
+ + GitHub Repository + + + Wiki / Docs + + + Open an Issue + +
+ +
+
+
+
+ + ADVERSARY EMULATION FRAMEWORK +
+

+ RAVEN + C2 FRAMEWORK v3.0 +

+

+ Modular, enterprise-grade Command & Control framework built in Java. + Supports Web Panel, CLI, and JavaFX GUI with mutual TLS, + AES-256-GCM encryption, and multi-protocol session handling. +

+
+
OpenJDK 17+
+
Maven 3.8+
+
AES-256-GCM
+
mTLS
+
AGPL v3
+
+ +
+ +
+
+ + + + RAVEN-C2 — operator console +
+
+
+
RAVEN C2 Web Panel
+
RAVEN C2 Sessions
+
RAVEN C2 Terminal
+
RAVEN C2 CLI
+
RAVEN C2 GUI
+
RAVEN C2 Dashboard
+
+ + +
+
+ + + + + + +
+
+
+
+ +
+ +
+ +
+
+
Overview
+

What is RAVEN C2

+ +
+
+

+ RAVEN C2 is a multi-platform adversary emulation framework built in Java. + It supports multiple interface modes — Web Panel (HTTP), CLI, and JavaFX GUI — + and manages concurrent reverse shell sessions from a single operator console + across diverse target environments. +

+

+ Engineered for operational security: all agent communication is protected by + AES-256-GCM encryption and mutual TLS authentication using PKCS12 keystores. + The framework features a full certificate lifecycle manager (CA → Server → Agent), + file transfer, thread-safe session handling, an event-driven architecture, and + multi-operator TeamServer mode. +

+
+ Java 17 + Web Panel + CLI + JavaFX GUI + mTLS + AES-GCM + version 3.0 +
+
- - - -
- -
-
- - logo - RAVENC2 - - +
+ v17 + Min JDK
- -
- -
-
-
-
- - ADVERSARY EMULATION FRAMEWORK -
-

- RAVEN - C2 FRAMEWORK v3.0 -

-

Modular, enterprise-grade Command & Control framework built in Java. Supports Web Panel, CLI, and JavaFX GUI with mutual TLS, AES-256-GCM encryption, and multi-protocol session handling.

-
-
OpenJDK 17+
-
Maven 3.8+
-
AES-256-GCM
-
mTLS
-
AGPL v3
-
- -
- -
-
- - - - RAVEN-C2 — operator console -
-
-
-
RAVEN C2 Web Panel
-
RAVEN C2 Sessions
-
RAVEN C2 Terminal
-
RAVEN C2 CLI
-
RAVEN C2 GUI
-
RAVEN C2 Dashboard
-
- - -
-
- - - - - - -
-
+
+ AGPL + License
-
- -
-
-
Overview
-

What is RAVEN C2

- -
-
-

RAVEN C2 is a multi-platform adversary emulation framework built in Java. It supports multiple interface modes — Web Panel (HTTP), CLI, and JavaFX GUI — and manages concurrent reverse shell sessions from a single operator console across diverse target environments.

-

Engineered for operational security: all agent communication is protected by AES-256-GCM encryption and mutual TLS authentication using PKCS12 keystores. The framework features a full certificate lifecycle manager (CA → Server → Agent), file transfer, thread-safe session handling, an event-driven architecture, and multi-operator TeamServer mode.

-
- Java 17 - Web Panel - CLI - JavaFX GUI - mTLS + AES-GCM - v3.0 Active -
-
- -
-
-
- Multi - Transport Security -
-
- v17 - Min JDK -
-
- AGPL - License -
-
- v3.0 - Version -
-
-
-
-
- Authorized Use Only -

This tool is for legally authorized penetration testing and red team engagements only. Unauthorized use is illegal and unethical.

-
-
-
-
+
+ v3.0 + Version
-
- -
-
-
Features
-

Core Capabilities

-

Everything a red team operator needs in a single Java-based framework.

- -
-
-
01
-
-

Multi-Interface Support

-

Operate via Web Panel (browser at port 5000), CLI mode (-C), or full JavaFX desktop GUI (-G) — whichever fits your workflow.

-
-
-
02
-
-

AES-256-GCM Encryption

-

All agent communication is encrypted end-to-end with AES-256-GCM, preventing traffic analysis and ensuring operational confidentiality.

-
-
-
03
-
-

Mutual TLS (mTLS)

-

Agent authentication via PKCS12 keystores. Full CA, server, and agent certificate lifecycle management with a single init command.

-
-
-
04
-
-

Multi-Protocol Sessions

-

Handle RAVEN agents, Meterpreter sessions, and plain reverse shells concurrently from a single operator console.

-
-
-
05
-
-

File Transfer

-

Upload payloads and download evidence files with built-in progress tracking. Evidence saved to the configurable output directory.

-
-
-
06
-
-

OPSEC Design

-

Minimal target footprint, encrypted payloads, and configurable listeners. Designed for operational security in authorized engagements.

-
-
-
07
-
-

Thread-Safe Sessions

-

Concurrent session handling backed by a thread-safe manager. Multiple agents can connect and be interacted with simultaneously.

-
-
-
08
-
-

Event-Driven Architecture

-

Decoupled event system for clean separation between the operator console, session manager, and agent handlers.

-
-
-
09
-
-

Cross-Platform

-

Runs on Windows, Linux, macOS via the JVM. Platform-specific Maven build flags available for each target OS.

-
-
-
10
-
-

Database Support

-

In-memory, SQLite, PostgreSQL, and MongoDB backends configurable via raven.properties.

-
-
-
11
-
-

Operator Roles

-

Role-based access control with four levels: SUPER, ADMIN, OPERATOR, MEMBER — each with distinct permission sets.

-
-
-
12
-
-

TeamServer Mode

-

Multi-operator collaborative C2 with dedicated REST API, allowing multiple clients to connect to the same instance simultaneously.

-
-
+
+
+
+
+ Authorized Use Only +

This tool is for legally authorized penetration testing and red team engagements only. Unauthorized use is illegal and unethical.

-
- -
-
-
Installation
-

Getting Started

-

Deploy RAVEN C2 v3.0 in under 5 minutes.

- -
-
-
-
01
-
-
-
-

Prerequisites

-

Ensure the following are installed before proceeding.

-
-
OpenJDK 17 or newerRequired
-
Apache Maven 3.8+Required
-
GitRequired
-
Linux / Termux (Debian recommended)Recommended
-
-
-
+
+
+
+
+
+ +
+
+
Features
+

Core Capabilities

+

Everything a red team operator needs in a single Java-based framework.

+ +
+
+
01
+
+

Multi-Interface Support

+

Operate via Web Panel (browser at port 5000), CLI mode (-C), or full JavaFX desktop GUI (-G) — whichever fits your workflow.

+
+
+
02
+
+

AES-256-GCM Encryption

+

All agent communication is encrypted end-to-end with AES-256-GCM, preventing traffic analysis and ensuring operational confidentiality.

+
+
+
03
+
+

Mutual TLS (mTLS)

+

Agent authentication via PKCS12 keystores. Full CA, server, and agent certificate lifecycle management with a single init command.

+
+
+
04
+
+

Multi-Protocol Sessions

+

Handle RAVEN agents, Meterpreter sessions, and plain reverse shells concurrently from a single operator console.

+
+
+
05
+
+

File Transfer

+

Upload payloads and download evidence files with built-in progress tracking. Evidence saved to the configurable output directory.

+
+
+
06
+
+

OPSEC Design

+

Minimal target footprint, encrypted payloads, and configurable listeners. Designed for operational security in authorized engagements.

+
+
+
07
+
+

Thread-Safe Sessions

+

Concurrent session handling backed by a thread-safe manager. Multiple agents can connect and be interacted with simultaneously.

+
+
+
08
+
+

Event-Driven Architecture

+

Decoupled event system for clean separation between the operator console, session manager, and agent handlers.

+
+
+
09
+
+

Cross-Platform

+

Runs on Windows, Linux, macOS via the JVM. Platform-specific Maven build flags available for each target OS.

+
+
+
10
+
+

Database Support

+

In-memory, SQLite, PostgreSQL, and MongoDB backends configurable via raven.properties.

+
+
+
11
+
+

Operator Roles

+

Role-based access control with four levels: SUPER, ADMIN, OPERATOR, MEMBER — each with distinct permission sets.

+
+
+
12
+
+

TeamServer Mode

+

Multi-operator collaborative C2 with dedicated REST API, allowing multiple clients to connect to the same instance simultaneously.

+
+
+
+
+ +
+
+
Installation
+

Getting Started

+

Deploy RAVEN C2 v3.0 in under 5 minutes.

+ +
+
+
+
01
+
+
+
+

Prerequisites

+

Ensure the following are installed before proceeding.

+
+
OpenJDK 17 or newerRequired
+
Apache Maven 3.8+Required
+
GitRequired
+
Linux / Termux (Debian recommended)Recommended
+
+
+
-
-
-
02
-
-
-
-

Clone Repository

-

Pull the source from GitHub. Use the main branch for stable usage or contrib for contribution.

-
-
- bash - -
-
git clone --branch main https://github.com/MatrixTM26/RAVEN.git
+        
+
+
02
+
+
+
+

Clone Repository

+

Pull the source from GitHub. Use the main branch for stable usage or contrib for contribution.

+
+
+ bash + +
+
git clone --branch main https://github.com/MatrixTM26/RAVEN.git
 cd RAVEN
-
-
-
+
+
+
-
-
-
03
-
-
-
-

Quick Run (Pre-built JAR)

-

A ready-to-use JAR is included in the repository. No compilation required.

-
-
- bash - -
-
java -jar output/raven.jar
-
-
-
+
+
+
03
+
+
+
+

Quick Run (Pre-built JAR)

+

A ready-to-use JAR is included in the repository. No compilation required.

+
+
+ bash + +
+
java -jar output/raven.jar
+
+
+
-
-
-
04
-
-
-
-

Build from Source

-

Compile with Maven. Use platform-specific flags for JavaFX support.

-
-
- bash - -
-
# Linux / Termux
+        
+
+
04
+
+
+
+

Build from Source

+

Compile with Maven. Use platform-specific flags for JavaFX support.

+
+
+ bash + +
+
# Linux / Termux
 mvn clean package -Djavafx.platform=linux -q
 
 # Windows
@@ -1708,24 +376,24 @@ 

Build from Source

# macOS mvn clean package -Djavafx.platform=macos -q
-
-
-
+
+
+
-
-
-
05
-
-
-
-

Initialize Certificates & Launch

-

Initialize mTLS certificates first, then start the server in your preferred interface mode.

-
-
- bash - -
-
# Initialize CA and server certificates
+        
+
+
05
+
+
+
+

Initialize Certificates & Launch

+

Initialize mTLS certificates first, then start the server in your preferred interface mode.

+
+
+ bash + +
+
# Initialize CA and server certificates
 java -jar target/raven-3.0.0.jar -i
 
 # Web Panel mode (default — http://localhost:5000)
@@ -1736,299 +404,290 @@ 

Initialize Certificates & Launch

# JavaFX GUI mode java -jar target/raven-3.0.0.jar -G
-
-
Server running — Web panel at http://localhost:5000, waiting for agents.
-
-
-
-
- -
-
-
Commands
-

Command Reference

-

CLI flags and operator console commands for RAVEN C2 v3.0.

- -
- - - - - - - - -
- -
-
-
-
OptionLong OptionDescription
-
-h-helpShow help and exit
-
-s <addr>-host <addr>C2 server bind address (default: server.properties)
-
-p <port>-port <port>C2 listener port (default: server.properties)
-
-C-cli-modeStart in CLI interface mode
-
-G-gui-modeStart in JavaFX GUI mode
-
-W-web-modeStart in Web Panel mode
-
-TSC-teamserver-cliTeamServer with CLI interface
-
-TSW-teamserver-webTeamServer with Web interface
-
-TSG-teamserver-guiTeamServer with GUI interface
-
-tp <port>-teamserver-port <port>TeamServer API port (default: server.properties)
-
-i-init-certsInitialize CA and server certificates
-
-l-listList all generated agent certificates
-
-
-
- -
-
-
-
OptionLong OptionDescription
-
-A-multiMulti-protocol auto-detect
-
-R-rawRaw TCP reverse shell only
-
-b-httpHTTP beacon only
-
-B-httpsHTTPS beacon only
-
-T-tlsTCP TLS — RAVEN agent
-
-M-mtlsMutual TLS — RAVEN agent
-
-F-fmtlsFull mTLS + HTTPS beacon
-
-
-
- -
-
-
-
CommandSyntaxDescription
-
sessionssessionsList all active agent sessions
-
agentsagentsAlias for sessions
-
useuse <id>Enter interactive shell with agent
-
sysinfosysinfo <id>Show full system info for agent
-
execexec <id> <cmd>Execute arbitrary command on agent (raw passthrough)
-
shellshell <id> <cmd>Execute via shell interpreter (sh -c / cmd /c)
-
broadcastbroadcast <id,...|all> <cmd>Broadcast command to selected or all agents
-
killkill <id>Terminate an agent session
-
pingping <id>Ping agent to verify liveness (raven: protocol)
-
reconnectreconnect <id>Ask RAVEN agent to reconnect
-
self-destructself-destruct <id>Wipe agent and terminate session (ADMIN+)
-
sleepsleep <id> <seconds>Set agent sleep interval
-
jitterjitter <id> <ms>Set agent jitter delay in ms
-
-
-
- -
-
-
-
CommandSyntaxDescription
-
whoamiwhoami <id>Current user info
-
idid <id>User ID / groups
-
hostnamehostname <id>Show agent hostname
-
unameuname <id>OS / kernel info
-
psps <id>Process list
-
netstatnetstat <id>Network connections
-
ifconfigifconfig <id>Network interfaces
-
arparp <id>ARP table
-
routeroute <id>Routing table
-
usersusers <id>Local users list
-
servicesservices <id>Running services
-
screenshotscreenshot <id>Capture desktop screenshot (raven: protocol)
-
privcheckprivcheck <id>Privilege escalation check
-
antivirusantivirus <id>Detect AV / EDR presence
-
hashdumphashdump <id>Dump credential hashes (raven: protocol)
-
keystrokekeystroke <id> <on|off>Toggle keylogger on agent
-
dumpbrowsersdumpbrowsers <id>Saved browser credentials (raven: protocol)
-
wifidumpwifidump <id>WiFi credentials dump
-
osqueryosquery <id> <sql>Run osquery SQL on agent
-
-
-
- -
-
-
-
CommandSyntaxDescription
-
lsls <id> [path]List directory
-
pwdpwd <id>Working directory
-
cdcd <id> <path>Change directory on agent
-
catcat <id> <file>Read file contents
-
headhead <id> <file> [n]First N lines of a file
-
tailtail <id> <file> [n]Last N lines of a file
-
rmrm <id> <path>Delete file / directory
-
mkdirmkdir <id> <path>Create directory
-
cpcp <id> <src> <dst>Copy file or directory
-
mvmv <id> <src> <dst>Move file or directory
-
findfind <id> <path> [name]Find files
-
grepgrep <id> <pattern> <file>Search text in file
-
hashhash <id> <file> [sha256|md5]File hash computation
-
downloaddownload <id> <remote-path>Download file from agent (raven: protocol)
-
uploadupload <id> <local-path> [remote-path]Upload file to agent (raven: protocol)
-
-
-
- -
-
-
-
CommandSyntaxDescription
-
pivotpivot <id> <host:port>Register pivot route through agent
-
portfwdportfwd <id> <lport> <rhost> <rport>Port forward through agent
-
sockssocks <id> <lport>SOCKS5 proxy through agent
-
spawnspawn <id>Spawn new agent process on target
-
shellcodeshellcode <id> <hex>Inject shellcode into agent process
-
persistpersist <id> [method]Install persistence (cron/bashrc/systemd/reg/schtask)
-
unpersistunpersist <id> [method]Remove persistence entry
-
runasrunas <id> <user> <pass> <cmd>Run command as another user
-
-
-
- -
-
-
-
OptionLong OptionDescription
-
-i-init-certsInitialize CA and server certificates
-
-s <host>-server <host>Server host used during cert init
-
-a <id>-agent <id>Generate a single agent certificate
-
-m-multiGenerate multiple agent certificates
-
-c <count>-count <count>Number of agents to generate (default: 10)
-
-u <prefix>-prefix <prefix>Username prefix for bulk agent certs
-
-ah <host>-agent-host <host>Agent callback host
-
-ap <port>-agent-port <port>Agent callback port
-
-am-agent-mtlsEnable mTLS in generated agent
-
-ps-persistentEnable persistence in generated agent
-
-hc-hide-consoleHide console window in generated agent
-
-l-listList all generated agent certificates
-
-r <id>-revoke <id>Revoke an agent certificate by ID
-
-
-
- -
-
-
-
OptionLong OptionDescription
-
-AO-add-operatorAdd a new operator
-
-RO-remove-operatorRemove an existing operator
-
-OP-operator-permissionView or update operator role
-
-u <user>-username <user>Operator username
-
-pw <pass>-password <pass>Operator password (min 8 characters)
-
-r <role>-role <role>Operator role: SUPER / ADMIN / OPERATOR / MEMBER
-
-
-
+
+ Server running — Web panel at http://localhost:5000, waiting for agents.
-
- -
-
-
Architecture
-

System Architecture

-

How RAVEN C2 v3.0 components interconnect in a live deployment.

- -
-
- - - - - - - - - OPERATOR INTERFACES - Web Panel · CLI · JavaFX GUI - - - RAVEN C2 SERVER - Session Manager · mTLS Auth · AES-256-GCM - Event System · Cert Manager · File Transfer - - - - - RAVEN AGENT - 192.168.1.42 - session-1 · mTLS - - - METERPRETER - 10.0.0.15 - session-2 · multi-proto - - - REVERSE SHELL - 172.16.0.8 - session-3 · tcp - - - + more agents - - - - - - - mTLS / AES-256-GCM - - - OUTPUT LOGS - ./output - - - - CONFIG - server.properties - - -
+
+
+
+
+ + +
+
+
Commands
+

Command Reference

+

CLI flags and operator console commands for RAVEN C2 v3.0.

+ +
+ + + + + + + + +
+ +
+
+
+
OptionLong OptionDescription
+
-h-helpShow help and exit
+
-s <addr>-host <addr>C2 server bind address (default: server.properties)
+
-p <port>-port <port>C2 listener port (default: server.properties)
+
-C-cli-modeStart in CLI interface mode
+
-G-gui-modeStart in JavaFX GUI mode
+
-W-web-modeStart in Web Panel mode
+
-TSC-teamserver-cliTeamServer with CLI interface
+
-TSW-teamserver-webTeamServer with Web interface
+
-TSG-teamserver-guiTeamServer with GUI interface
+
-tp <port>-teamserver-port <port>TeamServer API port (default: server.properties)
+
-i-init-certsInitialize CA and server certificates
+
-l-listList all generated agent certificates
+
+
+
+ +
+
+
+
OptionLong OptionDescription
+
-A-multiMulti-protocol auto-detect
+
-R-rawRaw TCP reverse shell only
+
-b-httpHTTP beacon only
+
-B-httpsHTTPS beacon only
+
-T-tlsTCP TLS — RAVEN agent
+
-M-mtlsMutual TLS — RAVEN agent
+
-F-fmtlsFull mTLS + HTTPS beacon
+
+
+
+ +
+
+
+
CommandSyntaxDescription
+
sessionssessionsList all active agent sessions
+
agentsagentsAlias for sessions
+
useuse <id>Enter interactive shell with agent
+
sysinfosysinfo <id>Show full system info for agent
+
execexec <id> <cmd>Execute arbitrary command on agent (raw passthrough)
+
shellshell <id> <cmd>Execute via shell interpreter (sh -c / cmd /c)
+
broadcastbroadcast <id,...|all> <cmd>Broadcast command to selected or all agents
+
killkill <id>Terminate an agent session
+
pingping <id>Ping agent to verify liveness (raven: protocol)
+
reconnectreconnect <id>Ask RAVEN agent to reconnect
+
self-destructself-destruct <id>Wipe agent and terminate session (ADMIN+)
+
sleepsleep <id> <seconds>Set agent sleep interval
+
jitterjitter <id> <ms>Set agent jitter delay in ms
+
+
+
+ +
+
+
+
CommandSyntaxDescription
+
whoamiwhoami <id>Current user info
+
idid <id>User ID / groups
+
hostnamehostname <id>Show agent hostname
+
unameuname <id>OS / kernel info
+
psps <id>Process list
+
netstatnetstat <id>Network connections
+
ifconfigifconfig <id>Network interfaces
+
arparp <id>ARP table
+
routeroute <id>Routing table
+
usersusers <id>Local users list
+
servicesservices <id>Running services
+
screenshotscreenshot <id>Capture desktop screenshot (raven: protocol)
+
privcheckprivcheck <id>Privilege escalation check
+
antivirusantivirus <id>Detect AV / EDR presence
+
hashdumphashdump <id>Dump credential hashes (raven: protocol)
+
keystrokekeystroke <id> <on|off>Toggle keylogger on agent
+
dumpbrowsersdumpbrowsers <id>Saved browser credentials (raven: protocol)
+
wifidumpwifidump <id>WiFi credentials dump
+
osqueryosquery <id> <sql>Run osquery SQL on agent
+
+
+
+ +
+
+
+
CommandSyntaxDescription
+
lsls <id> [path]List directory
+
pwdpwd <id>Working directory
+
cdcd <id> <path>Change directory on agent
+
catcat <id> <file>Read file contents
+
headhead <id> <file> [n]First N lines of a file
+
tailtail <id> <file> [n]Last N lines of a file
+
rmrm <id> <path>Delete file / directory
+
mkdirmkdir <id> <path>Create directory
+
cpcp <id> <src> <dst>Copy file or directory
+
mvmv <id> <src> <dst>Move file or directory
+
findfind <id> <path> [name]Find files
+
grepgrep <id> <pattern> <file>Search text in file
+
hashhash <id> <file> [sha256|md5]File hash computation
+
downloaddownload <id> <remote-path>Download file from agent (raven: protocol)
+
uploadupload <id> <local-path> [remote-path]Upload file to agent (raven: protocol)
+
+
+
+ +
+
+
+
CommandSyntaxDescription
+
pivotpivot <id> <host:port>Register pivot route through agent
+
portfwdportfwd <id> <lport> <rhost> <rport>Port forward through agent
+
sockssocks <id> <lport>SOCKS5 proxy through agent
+
spawnspawn <id>Spawn new agent process on target
+
shellcodeshellcode <id> <hex>Inject shellcode into agent process
+
persistpersist <id> [method]Install persistence (cron/bashrc/systemd/reg/schtask)
+
unpersistunpersist <id> [method]Remove persistence entry
+
runasrunas <id> <user> <pass> <cmd>Run command as another user
+
+
+
+ +
+
+
+
OptionLong OptionDescription
+
-i-init-certsInitialize CA and server certificates
+
-s <host>-server <host>Server host used during cert init
+
-a <id>-agent <id>Generate a single agent certificate
+
-m-multiGenerate multiple agent certificates
+
-c <count>-count <count>Number of agents to generate (default: 10)
+
-u <prefix>-prefix <prefix>Username prefix for bulk agent certs
+
-ah <host>-agent-host <host>Agent callback host
+
-ap <port>-agent-port <port>Agent callback port
+
-am-agent-mtlsEnable mTLS in generated agent
+
-ps-persistentEnable persistence in generated agent
+
-hc-hide-consoleHide console window in generated agent
+
-l-listList all generated agent certificates
+
-r <id>-revoke <id>Revoke an agent certificate by ID
+
+
+
+ +
+
+
+
OptionLong OptionDescription
+
-AO-add-operatorAdd a new operator
+
-RO-remove-operatorRemove an existing operator
+
-OP-operator-permissionView or update operator role
+
-u <user>-username <user>Operator username
+
-pw <pass>-password <pass>Operator password (min 8 characters)
+
-r <role>-role <role>Operator role: SUPER / ADMIN / OPERATOR / MEMBER
+
+
+
+
+
+ +
+
+
Architecture
+

System Architecture

+

How RAVEN C2 v3.0 components interconnect in a live deployment.

+ +
+
+ + + + + + + + OPERATOR INTERFACES + Web Panel · CLI · JavaFX GUI + + RAVEN C2 SERVER + Session Manager · mTLS Auth · AES-256-GCM + Event System · Cert Manager · File Transfer + + + RAVEN AGENT + 192.168.1.42 + session-1 · mTLS + + METERPRETER + 10.0.0.15 + session-2 · multi-proto + + REVERSE SHELL + 172.16.0.8 + session-3 · tcp + + + more agents + + + + + mTLS / AES-256-GCM + + OUTPUT LOGS + ./output + + + CONFIG + server.properties + + +
-
-
-
-
-

Operator Interfaces

-

Web Panel (browser), CLI terminal, and JavaFX desktop GUI — all connecting to the same C2 server core.

-
-
-
-
-
-

C2 Server Core

-

Thread-safe session manager, mTLS auth, AES-256-GCM encryption, event-driven architecture, and certificate lifecycle manager.

-
-
-
-
-
-

Multi-Protocol Agents

-

Supports RAVEN agents (mTLS), Meterpreter sessions, and plain reverse shells — all managed from one console.

-
-
-
-
-
-

Output & Config

-

All session I/O captured to timestamped logs in ./output. All settings configurable via server.properties.

-
-
-
-
+
+
+
+
+

Operator Interfaces

+

Web Panel (browser), CLI terminal, and JavaFX desktop GUI — all connecting to the same C2 server core.

-
- -
-
-
Configuration
-

Configuration Reference

-

All parameters available in config/server/raven.properties.

- -
-
- properties - -
-
# C2 listener
+          
+
+
+
+

C2 Server Core

+

Thread-safe session manager, mTLS auth, AES-256-GCM encryption, event-driven architecture, and certificate lifecycle manager.

+
+
+
+
+
+

Multi-Protocol Agents

+

Supports RAVEN agents (mTLS), Meterpreter sessions, and plain reverse shells — all managed from one console.

+
+
+
+
+
+

Output & Config

+

All session I/O captured to timestamped logs in ./output. All settings configurable via server.properties.

+
+
+
+ + +
+ +
+
+
Configuration
+

Configuration Reference

+

All parameters available in config/server/raven.properties.

+ +
+
+ properties + +
+
# C2 listener
 server.host=0.0.0.0
 server.port=4444
 server.mode=multi
@@ -2046,263 +705,152 @@ 

Configuration Reference

# Logging logging.level=INFO logging.file.enabled=false
-
- -
-
-
Server
-
-
-
KeyDefaultDescription
-
server.host0.0.0.0Bind address for C2 listener
-
server.port4444Default agent listener port
-
server.modemultiListener mode (single / multi)
-
web.host0.0.0.0Web panel bind address
-
web.port5000Web panel HTTP port
-
-
-
- -
-
Database
-
-
-
Valuedb.typeNotes
-
In-memorynoneDefault, no persistence
-
SQLitesqliteFile-based, no server required
-
PostgreSQLpostgresProduction-grade relational DB
-
MongoDBmongoDocument-oriented store
-
-
-
- -
-
Security
-
-
-
KeyDefaultDescription
-
cert.tls.protocolTLSv1.3TLS protocol version enforced
-
logging.levelINFOLog verbosity level
-
logging.file.enabledfalseEnable file-based logging
-
-
-
-
-
-
- -
-
-
-
- -

LEGAL DISCLAIMER

-
-

RAVEN C2 Framework is an offensive security tool designed exclusively for authorized penetration testing and red team engagements, controlled lab and research environments, and cybersecurity education under supervised conditions. You MUST have explicit written authorization from the system/network owner before deployment. Unauthorized use constitutes a criminal offense under applicable international and local cybercrime laws.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ +
+
+
Server
+
+
+
KeyDefaultDescription
+
server.host0.0.0.0Bind address for C2 listener
+
server.port4444Default agent listener port
+
server.modemultiListener mode (single / multi)
+
web.host0.0.0.0Web panel bind address
+
web.port5000Web panel HTTP port
-
+ + -
-
-
-
-

Ready to deploy

-

Explore the source, open issues, or contribute to RAVEN C2 on GitHub.

-
- -
+
+
Database
+
+
+
Valuedb.typeNotes
+
In-memorynoneDefault, no persistence
+
SQLitesqliteFile-based, no server required
+
PostgreSQLpostgresProduction-grade relational DB
+
MongoDBmongoDocument-oriented store
-
+ + - - - - - - + + + + + + + + + +
+
+
+
+ +

LEGAL DISCLAIMER

+
+

+ RAVEN C2 Framework is an offensive security tool designed exclusively for authorized penetration testing and red team engagements, + controlled lab and research environments, and cybersecurity education under supervised conditions. + You MUST have explicit written authorization from the system/network owner before deployment. + Unauthorized use constitutes a criminal offense under applicable international and local cybercrime laws. +

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

Ready to deploy

+

Explore the source, open issues, or contribute to RAVEN C2 on GitHub.

+
+ +
+
+
+ + + + + + + diff --git a/doc/pages/static/script/app.js b/doc/pages/static/script/app.js index 1e4383b..00b83dd 100644 --- a/doc/pages/static/script/app.js +++ b/doc/pages/static/script/app.js @@ -1,221 +1,163 @@ -const navbar = document.getElementById("navbar"); -const burgerBtn = document.getElementById("burgerBtn"); -const burgerIcon = document.getElementById("burgerIcon"); -const mobileDrawer = document.getElementById("mobileDrawer"); -const drawerOverlay = document.getElementById("drawerOverlay"); -const drawerClose = document.getElementById("drawerClose"); -const toTopBtn = document.getElementById("toTop"); -const navItems = document.querySelectorAll(".nav-item"); -const drawerItems = document.querySelectorAll(".drawer-item"); -const tabs = document.querySelectorAll(".tab"); -const tabPanels = document.querySelectorAll(".tab-panel"); -const copyBtns = document.querySelectorAll(".cb-copy"); -const reveals = document.querySelectorAll(".reveal"); - -let drawerOpen = false; - -function openDrawer() { - drawerOpen = true; - mobileDrawer.classList.add("open"); - drawerOverlay.classList.add("open"); - burgerIcon.className = "fas fa-bars"; - document.body.style.overflow = "hidden"; -} - -function closeDrawer() { - drawerOpen = false; - mobileDrawer.classList.remove("open"); - drawerOverlay.classList.remove("open"); - document.body.style.overflow = ""; -} - -burgerBtn.addEventListener("click", function () { - if (drawerOpen) closeDrawer(); - else openDrawer(); -}); - -if (drawerClose) drawerClose.addEventListener("click", closeDrawer); -if (drawerOverlay) drawerOverlay.addEventListener("click", closeDrawer); - -drawerItems.forEach(function (item) { - item.addEventListener("click", closeDrawer); -}); - -function getActiveSection() { - const ids = [ - "home", - "overview", - "features", - "installation", - "commands", - "architecture", - "config", - ]; - let active = "home"; - ids.forEach(function (id) { - const el = document.getElementById(id); - if (el && el.getBoundingClientRect().top <= 90) active = id; - }); - return active; -} +(function () { + var burgerBtn = document.getElementById('burgerBtn'); + var burgerIcon = document.getElementById('burgerIcon'); + var mobileDrawer = document.getElementById('mobileDrawer'); + var drawerOverlay = document.getElementById('drawerOverlay'); + var drawerCollapse = document.getElementById('drawerCollapse'); + var isOpen = false; + + function openDrawer() { + isOpen = true; + mobileDrawer.classList.add('open'); + drawerOverlay.classList.add('open'); + if (burgerIcon) { burgerIcon.classList.remove('fa-bars'); burgerIcon.classList.add('fa-xmark'); } + document.body.style.overflow = 'hidden'; + } -function updateNav() { - const active = getActiveSection(); - navItems.forEach(function (item) { - item.classList.toggle("active", item.dataset.section === active); - }); -} - -window.addEventListener( - "scroll", - function () { - navbar.classList.toggle("scrolled", window.scrollY > 30); - toTopBtn.classList.toggle("visible", window.scrollY > 320); - updateNav(); - checkReveals(); - }, - { passive: true }, -); - -toTopBtn.addEventListener("click", function () { - window.scrollTo({ top: 0, behavior: "smooth" }); -}); - -document.querySelectorAll("a[href^='#']").forEach(function (link) { - link.addEventListener("click", function (e) { - const id = link.getAttribute("href").slice(1); - const target = document.getElementById(id); - if (!target) return; - e.preventDefault(); - const offset = target.getBoundingClientRect().top + window.scrollY - 72; - window.scrollTo({ top: offset, behavior: "smooth" }); - closeDrawer(); - }); -}); + function closeDrawer() { + isOpen = false; + mobileDrawer.classList.remove('open'); + drawerOverlay.classList.remove('open'); + if (burgerIcon) { burgerIcon.classList.remove('fa-xmark'); burgerIcon.classList.add('fa-bars'); } + document.body.style.overflow = ''; + } -function activateTab(name) { - tabs.forEach(function (t) { - t.classList.toggle("active", t.dataset.tab === name); - }); - tabPanels.forEach(function (p) { - p.classList.toggle("active", p.id === "tab-" + name); - }); -} + function toggleDrawer() { + if (isOpen) closeDrawer(); + else openDrawer(); + } -tabs.forEach(function (t) { - t.addEventListener("click", function () { - activateTab(t.dataset.tab); - }); -}); - -function copyText(text, btn) { - navigator.clipboard - .writeText(text) - .then(function () { - showCopied(btn); - }) - .catch(function () { - const ta = document.createElement("textarea"); - ta.value = text; - ta.style.cssText = "position:fixed;opacity:0"; - document.body.appendChild(ta); - ta.select(); - document.execCommand("copy"); - document.body.removeChild(ta); - showCopied(btn); - }); -} - -function showCopied(btn) { - btn.classList.add("copied"); - btn.innerHTML = ''; - setTimeout(function () { - btn.classList.remove("copied"); - btn.innerHTML = ''; - }, 1800); -} - -copyBtns.forEach(function (btn) { - btn.addEventListener("click", function () { - const text = btn.dataset.copy; - if (text) copyText(text, btn); + if (burgerBtn) burgerBtn.addEventListener('click', toggleDrawer); + if (drawerCollapse) drawerCollapse.addEventListener('click', closeDrawer); + if (drawerOverlay) drawerOverlay.addEventListener('click', closeDrawer); + + document.querySelectorAll('.drawer-item, .drawer-gh').forEach(function (item) { + item.addEventListener('click', closeDrawer); }); -}); - -function checkReveals() { - reveals.forEach(function (el) { - if (el.classList.contains("visible")) return; - const rect = el.getBoundingClientRect(); - if (rect.top < window.innerHeight - 60) { - el.classList.add("visible"); - } + + document.addEventListener('keydown', function (e) { + if (e.key === 'Escape' && isOpen) closeDrawer(); }); -} - -(function initScreenshotSlider() { - const track = document.getElementById("screenshotTrack"); - const prevBtn = document.getElementById("ssPrev"); - const nextBtn = document.getElementById("ssNext"); - const dots = document.querySelectorAll(".screenshot-dot"); - const titleEl = document.getElementById("screenshotTitle"); - - if (!track || !prevBtn || !nextBtn) return; - - const titles = [ - "tomcat-c2 — server config", - "tomcat-c2 — main dashboard", - "tomcat-c2 — command logs", - "tomcat-c2 — agent dashboard", - "tomcat-c2 — about developer", - "tomcat-c2 — documentation pages view", - ]; - const total = dots.length; - let current = 0; + var track = document.getElementById('screenshotTrack'); + var dots = document.querySelectorAll('.screenshot-dot'); + var titleEl = document.getElementById('screenshotTitle'); + var titles = [ + 'RAVEN-C2 — web panel', + 'RAVEN-C2 — sessions', + 'RAVEN-C2 — terminal', + 'RAVEN-C2 — cli mode', + 'RAVEN-C2 — javafx gui', + 'RAVEN-C2 — dashboard' + ]; + var currentSlide = 0; + var totalSlides = 6; + var autoTimer; - function goTo(idx) { - current = (idx + total) % total; - track.style.transform = "translateX(-" + current * 100 + "%)"; + function goToSlide(n) { + currentSlide = (n + totalSlides) % totalSlides; + if (track) track.style.transform = 'translateX(-' + (currentSlide * 100) + '%)'; dots.forEach(function (d, i) { - d.classList.toggle("active", i === current); + d.classList.toggle('active', i === currentSlide); }); - if (titleEl && titles[current]) titleEl.textContent = titles[current]; + if (titleEl) titleEl.textContent = titles[currentSlide]; + } + + function startAuto() { + autoTimer = setInterval(function () { goToSlide(currentSlide + 1); }, 4000); + } + + function resetAuto() { + clearInterval(autoTimer); + startAuto(); } - prevBtn.addEventListener("click", function () { - goTo(current - 1); + var ssPrev = document.getElementById('ssPrev'); + var ssNext = document.getElementById('ssNext'); + + if (ssPrev) ssPrev.addEventListener('click', function () { goToSlide(currentSlide - 1); resetAuto(); }); + if (ssNext) ssNext.addEventListener('click', function () { goToSlide(currentSlide + 1); resetAuto(); }); + + dots.forEach(function (d) { + d.addEventListener('click', function () { + goToSlide(parseInt(d.dataset.idx)); + resetAuto(); + }); }); - nextBtn.addEventListener("click", function () { - goTo(current + 1); + + if (track) startAuto(); + + document.querySelectorAll('.tab').forEach(function (tab) { + tab.addEventListener('click', function () { + document.querySelectorAll('.tab').forEach(function (t) { t.classList.remove('active'); }); + document.querySelectorAll('.tab-panel').forEach(function (p) { p.classList.remove('active'); }); + tab.classList.add('active'); + var panel = document.getElementById('tab-' + tab.dataset.tab); + if (panel) panel.classList.add('active'); + }); }); - dots.forEach(function (dot) { - dot.addEventListener("click", function () { - goTo(parseInt(dot.dataset.idx, 10)); + document.querySelectorAll('.cb-copy').forEach(function (btn) { + btn.addEventListener('click', function () { + var text = btn.dataset.copy.replace(/ /g, '\n'); + navigator.clipboard.writeText(text).then(function () { + btn.innerHTML = ''; + setTimeout(function () { btn.innerHTML = ''; }, 1500); + }); }); }); - var autoTimer = setInterval(function () { - goTo(current + 1); - }, 4000); + var toTop = document.getElementById('toTop'); + + window.addEventListener('scroll', function () { + if (toTop) toTop.classList.toggle('visible', window.scrollY > 400); + }); + + if (toTop) toTop.addEventListener('click', function () { + window.scrollTo({ top: 0, behavior: 'smooth' }); + }); - var sliderEl = document.getElementById("heroScreenshot"); - if (sliderEl) { - sliderEl.addEventListener("mouseenter", function () { - clearInterval(autoTimer); + var navItems = document.querySelectorAll('.nav-item[data-section]'); + var drawerItems = document.querySelectorAll('.drawer-item[data-section]'); + var sections = document.querySelectorAll('section[id]'); + + window.addEventListener('scroll', function () { + var current = ''; + sections.forEach(function (sec) { + if (window.scrollY >= sec.offsetTop - 80) current = sec.id; }); - sliderEl.addEventListener("mouseleave", function () { - clearInterval(autoTimer); - autoTimer = setInterval(function () { - goTo(current + 1); - }, 4000); + navItems.forEach(function (item) { + item.classList.toggle('active', item.dataset.section === current); }); - } + drawerItems.forEach(function (item) { + item.classList.toggle('active', item.dataset.section === current); + }); + }); + + var revealEls = document.querySelectorAll('.reveal'); + var observer = new IntersectionObserver(function (entries) { + entries.forEach(function (entry) { + if (entry.isIntersecting) { + entry.target.classList.add('in'); + observer.unobserve(entry.target); + } + }); + }, { threshold: 0.08 }); + + revealEls.forEach(function (el) { observer.observe(el); }); })(); -document.addEventListener("DOMContentLoaded", function () { - activateTab("cli"); - updateNav(); - checkReveals(); - setTimeout(checkReveals, 100); -}); +;(function () { + var dsItems = document.querySelectorAll('.dsb-item[data-section]'); + var sections = document.querySelectorAll('section[id]'); + + window.addEventListener('scroll', function () { + var current = ''; + sections.forEach(function (sec) { + if (window.scrollY >= sec.offsetTop - 80) current = sec.id; + }); + dsItems.forEach(function (item) { + item.classList.toggle('active', item.dataset.section === current); + }); + }); +})(); diff --git a/doc/pages/static/script/bg.js b/doc/pages/static/script/bg.js deleted file mode 100644 index c478238..0000000 --- a/doc/pages/static/script/bg.js +++ /dev/null @@ -1,211 +0,0 @@ -(function () { - var canvas = document.getElementById("heroBg"); - if (!canvas || typeof THREE === "undefined") return; - - var W = window.innerWidth; - var H = window.innerHeight; - - var renderer = new THREE.WebGLRenderer({ - canvas: canvas, - antialias: true, - alpha: true, - }); - renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); - renderer.setSize(W, H); - renderer.setClearColor(0x0a0a0a, 1); - - var scene = new THREE.Scene(); - var fog = new THREE.FogExp2(0x0a0a0a, 0.038); - scene.fog = fog; - - var camera = new THREE.PerspectiveCamera(60, W / H, 0.1, 200); - camera.position.set(0, 0, 30); - - var RED = 0xe53935; - var RED_DIM = 0xb71c1c; - var NODE_COUNT = 80; - var EDGE_DIST = 14; - - var nodes = []; - var velocities = []; - - var nodeMat = new THREE.MeshBasicMaterial({ color: RED }); - var nodeMatDim = new THREE.MeshBasicMaterial({ - color: RED_DIM, - transparent: true, - opacity: 0.5, - }); - var nodeGeo = new THREE.SphereGeometry(0.12, 8, 8); - var nodeGeoSm = new THREE.SphereGeometry(0.07, 6, 6); - - var nodeGroup = new THREE.Group(); - scene.add(nodeGroup); - - for (var i = 0; i < NODE_COUNT; i++) { - var big = Math.random() < 0.2; - var mesh = new THREE.Mesh( - big ? nodeGeo : nodeGeoSm, - big ? nodeMat : nodeMatDim, - ); - var x = (Math.random() - 0.5) * 70; - var y = (Math.random() - 0.5) * 50; - var z = (Math.random() - 0.5) * 40; - mesh.position.set(x, y, z); - nodeGroup.add(mesh); - nodes.push(mesh); - velocities.push( - new THREE.Vector3( - (Math.random() - 0.5) * 0.012, - (Math.random() - 0.5) * 0.012, - (Math.random() - 0.5) * 0.008, - ), - ); - } - - var pulseNodes = []; - for (var pi = 0; pi < 8; pi++) { - var idx = Math.floor(Math.random() * NODE_COUNT); - var ringGeo = new THREE.RingGeometry(0.25, 0.35, 16); - var ringMat = new THREE.MeshBasicMaterial({ - color: RED, - transparent: true, - opacity: 0.6, - side: THREE.DoubleSide, - }); - var ring = new THREE.Mesh(ringGeo, ringMat); - ring.position.copy(nodes[idx].position); - ring.userData.nodeIdx = idx; - ring.userData.phase = Math.random() * Math.PI * 2; - scene.add(ring); - pulseNodes.push(ring); - } - - var edgeGroup = new THREE.Group(); - scene.add(edgeGroup); - - function rebuildEdges() { - while (edgeGroup.children.length) { - edgeGroup.remove(edgeGroup.children[0]); - } - var edgePoints = []; - for (var a = 0; a < NODE_COUNT; a++) { - for (var b = a + 1; b < NODE_COUNT; b++) { - var dist = nodes[a].position.distanceTo(nodes[b].position); - if (dist < EDGE_DIST) { - edgePoints.push({ - from: nodes[a].position.clone(), - to: nodes[b].position.clone(), - alpha: 1 - dist / EDGE_DIST, - }); - } - } - } - for (var ei = 0; ei < edgePoints.length; ei++) { - var ep = edgePoints[ei]; - var geo = new THREE.BufferGeometry().setFromPoints([ep.from, ep.to]); - var mat = new THREE.LineBasicMaterial({ - color: RED, - transparent: true, - opacity: ep.alpha * 0.18, - }); - edgeGroup.add(new THREE.Line(geo, mat)); - } - } - - rebuildEdges(); - - var gridHelper = new THREE.GridHelper(120, 40, 0xe53935, 0xe53935); - gridHelper.material.transparent = true; - gridHelper.material.opacity = 0.03; - gridHelper.position.y = -18; - scene.add(gridHelper); - - var ambientParticles = []; - var partGeo = new THREE.SphereGeometry(0.04, 4, 4); - var partMat = new THREE.MeshBasicMaterial({ - color: RED, - transparent: true, - opacity: 0.3, - }); - for (var pp = 0; pp < 120; pp++) { - var p = new THREE.Mesh(partGeo, partMat); - p.position.set( - (Math.random() - 0.5) * 100, - (Math.random() - 0.5) * 70, - (Math.random() - 0.5) * 60, - ); - p.userData.speed = (Math.random() - 0.5) * 0.005; - scene.add(p); - ambientParticles.push(p); - } - - var mouse = { x: 0, y: 0 }; - var targetRot = { x: 0, y: 0 }; - var currentRot = { x: 0, y: 0 }; - - document.addEventListener("mousemove", function (e) { - mouse.x = (e.clientX / window.innerWidth - 0.5) * 2; - mouse.y = (e.clientY / window.innerHeight - 0.5) * 2; - }); - - var edgeRebuildTimer = 0; - var clock = new THREE.Clock(); - - function animate() { - requestAnimationFrame(animate); - var delta = clock.getDelta(); - var elapsed = clock.getElapsedTime(); - - for (var ni = 0; ni < NODE_COUNT; ni++) { - nodes[ni].position.add(velocities[ni]); - var pos = nodes[ni].position; - if (pos.x > 35 || pos.x < -35) velocities[ni].x *= -1; - if (pos.y > 25 || pos.y < -25) velocities[ni].y *= -1; - if (pos.z > 20 || pos.z < -20) velocities[ni].z *= -1; - } - - edgeRebuildTimer += delta; - if (edgeRebuildTimer > 0.1) { - rebuildEdges(); - edgeRebuildTimer = 0; - } - - for (var ri = 0; ri < pulseNodes.length; ri++) { - var r = pulseNodes[ri]; - r.position.copy(nodes[r.userData.nodeIdx].position); - r.lookAt(camera.position); - var phase = r.userData.phase + elapsed * 1.5; - var scale = 0.8 + Math.sin(phase) * 0.5 + 0.5; - r.scale.setScalar(scale); - r.material.opacity = (1 - (scale - 0.8) / 1) * 0.5; - } - - for (var api = 0; api < ambientParticles.length; api++) { - ambientParticles[api].position.y += ambientParticles[api].userData.speed; - if (ambientParticles[api].position.y > 35) - ambientParticles[api].position.y = -35; - if (ambientParticles[api].position.y < -35) - ambientParticles[api].position.y = 35; - } - - targetRot.y = mouse.x * 0.08; - targetRot.x = mouse.y * -0.05; - currentRot.x += (targetRot.x - currentRot.x) * 0.04; - currentRot.y += (targetRot.y - currentRot.y) * 0.04; - - scene.rotation.x = currentRot.x; - scene.rotation.y = currentRot.y + elapsed * 0.018; - - renderer.render(scene, camera); - } - - animate(); - - window.addEventListener("resize", function () { - W = window.innerWidth; - H = window.innerHeight; - camera.aspect = W / H; - camera.updateProjectionMatrix(); - renderer.setSize(W, H); - }); -})(); diff --git a/doc/pages/static/styles/style.css b/doc/pages/static/styles/style.css index b81dbb3..4e1ad07 100644 --- a/doc/pages/static/styles/style.css +++ b/doc/pages/static/styles/style.css @@ -1,112 +1,61 @@ :root { - --canvas: #0d1117; - --canvas-inset: #010409; - --canvas-subtle: #161b22; - --canvas-overlay: #1c2128; - --border: #21262d; - --border-muted: #30363d; - --border-subtle: rgba(48, 54, 61, 0.7); - - --fg: #e6edf3; - --fg-muted: #8b949e; - --fg-subtle: #6e7681; - --fg-dim: #484f58; - - --red: #f85149; - --red-dim: #b91c1c; - --red-subtle: rgba(248, 81, 73, 0.1); - --red-border: rgba(248, 81, 73, 0.3); - - --green: #3fb950; - --green-dim: #238636; - --green-subtle: rgba(63, 185, 80, 0.1); - --green-border: rgba(63, 185, 80, 0.25); - + --black: #000000; + --grey-950: #0a0a0a; + --grey-900: #111111; + --grey-800: #1a1a1a; + --grey-700: #2a2a2a; + --grey-600: #3a3a3a; + --grey-500: #555555; + --grey-400: #777777; + --grey-300: #999999; + --grey-200: #bbbbbb; + --grey-100: #dddddd; --white: #ffffff; - --font: "Space Grotesk", sans-serif; --mono: "SFMono-Regular", "Consolas", "Liberation Mono", monospace; --display: "Tourney", sans-serif; - - --nav: 60px; - --r: 6px; - --ease: cubic-bezier(0.4, 0, 0.2, 1); + --nav: 56px; + --sidebar: 240px; } -*, -*::before, -*::after { - box-sizing: border-box; - margin: 0; - padding: 0; -} +*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } -html { - scroll-behavior: smooth; - overflow-x: hidden; -} +html { scroll-behavior: smooth; overflow-x: hidden; } body { - background: var(--canvas); - color: var(--fg); + background: var(--black); + color: var(--grey-200); font-family: var(--font); font-size: 14px; - line-height: 1.5; + line-height: 1.6; overflow-x: hidden; -webkit-font-smoothing: antialiased; } -a { - color: var(--red); - text-decoration: none; - transition: color 0.15s; -} -a:hover { - color: var(--fg); -} +a { color: var(--white); text-decoration: none; transition: color 0.15s; } +a:hover { color: var(--grey-300); } code { font-family: var(--mono); font-size: 0.8em; - background: var(--canvas-overlay); - color: var(--fg); + background: var(--grey-900); + color: var(--grey-100); padding: 2px 6px; - border-radius: 4px; - border: 1px solid var(--border-muted); + border: 1px solid var(--grey-700); } -pre code { - background: none; - border: none; - padding: 0; - font-size: 0.85rem; - color: var(--fg); -} +pre code { background: none; border: none; padding: 0; font-size: 0.85rem; color: var(--grey-200); } -.container { - max-width: 1152px; - margin: 0 auto; - padding: 0 24px; - width: 100%; -} +.container { max-width: 1152px; margin: 0 auto; padding: 0 24px; width: 100%; } +/* ── NAVBAR ─────────────────────────────────────── */ .navbar { position: fixed; - top: 0; - left: 0; - right: 0; + top: 0; left: 0; right: 0; height: var(--nav); - background: rgba(13, 17, 23, 0.95); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border-bottom: 1px solid var(--border); - z-index: 1000; - transition: background 0.2s; -} - -.navbar.scrolled { - background: rgba(13, 17, 23, 0.98); - border-bottom-color: var(--border-muted); + background: var(--black); + border-bottom: 1px solid var(--grey-800); + z-index: 100; } .nav-inner { @@ -117,156 +66,206 @@ pre code { display: flex; align-items: center; justify-content: space-between; - gap: 16px; } .nav-brand { display: flex; align-items: center; - gap: 9px; - flex-shrink: 0; - text-decoration: none; + gap: 10px; + color: var(--white); } -.nav-logo { - width: 28px; - height: 28px; - flex-shrink: 0; -} +.nav-brand:hover { color: var(--grey-300); } +.nav-logo { height: 26px; width: auto; } .nav-wordmark { font-family: var(--display); - font-size: 1rem; + font-size: 1.1rem; font-weight: 700; - color: var(--fg); - letter-spacing: 0.08em; - white-space: nowrap; + letter-spacing: 2px; + color: var(--white); } -.nav-wordmark em { - color: var(--red); - font-style: normal; -} +.nav-wordmark em { font-style: normal; color: var(--grey-400); } .nav-menu { display: flex; align-items: center; + gap: 4px; list-style: none; - gap: 0; } .nav-item { - display: block; - padding: 6px 12px; - border-radius: var(--r); - color: var(--fg-muted); - font-size: 0.82rem; + font-size: 0.8rem; font-weight: 500; - transition: color 0.12s; - white-space: nowrap; - text-decoration: none; + color: var(--grey-300); + padding: 6px 10px; + letter-spacing: 0.5px; + border: 1px solid transparent; + transition: all 0.15s; } -.nav-item:hover { - color: var(--fg); -} -.nav-item.active { - color: var(--fg); +.nav-item:hover, .nav-item.active { + color: var(--white); + border-color: var(--grey-700); } .nav-gh { display: flex; align-items: center; gap: 6px; - padding: 5px 13px; + font-size: 0.8rem; + font-weight: 500; + color: var(--grey-300); + padding: 6px 12px; + border: 1px solid var(--grey-700); margin-left: 8px; - background: var(--canvas-subtle); - border: 1px solid var(--border-muted); - border-radius: var(--r); - color: var(--fg); - font-size: 0.82rem; - font-weight: 600; - transition: all 0.12s; - white-space: nowrap; - flex-shrink: 0; - text-decoration: none; + transition: all 0.15s; } -.nav-gh:hover { - background: var(--canvas-overlay); - border-color: var(--border-muted); - color: var(--fg); -} +.nav-gh:hover { color: var(--white); border-color: var(--grey-500); } .nav-burger { display: none; background: none; - border: 1px solid var(--border-muted); - color: var(--fg-muted); - width: 36px; - height: 36px; - border-radius: var(--r); + border: 1px solid var(--grey-700); + color: var(--grey-300); + padding: 6px 10px; cursor: pointer; + font-size: 0.9rem; align-items: center; justify-content: center; - font-size: 0.9rem; - transition: all 0.12s; + transition: all 0.15s; +} + +.nav-burger:hover { color: var(--white); border-color: var(--grey-500); } + +/* ── DESKTOP GITHUB SIDEBAR ─────────────────────── */ +.page-layout { + display: flex; + max-width: 1152px; + margin: 0 auto; + padding: 0 24px; +} + +.desktop-sidebar { + width: var(--sidebar); flex-shrink: 0; + position: sticky; + top: calc(var(--nav) + 32px); + height: fit-content; + padding: 24px 0; + border-right: 1px solid var(--grey-800); + padding-right: 20px; +} + +.dsb-section-label { + font-size: 0.65rem; + font-weight: 600; + letter-spacing: 1.5px; + text-transform: uppercase; + color: var(--grey-600); + padding: 8px 0 4px; + margin-bottom: 2px; +} + +.dsb-menu { list-style: none; margin-bottom: 16px; } + +.dsb-item { + display: flex; + align-items: center; + gap: 8px; + padding: 6px 8px; + color: var(--grey-400); + font-size: 0.8rem; + font-weight: 500; + border-radius: 0; + position: relative; + transition: all 0.1s; + border-left: 2px solid transparent; + margin-left: -2px; +} + +.dsb-item:hover { color: var(--white); background: var(--grey-900); } +.dsb-item.active { color: var(--white); border-left-color: var(--white); background: var(--grey-900); } +.dsb-item i { width: 14px; font-size: 0.75rem; color: var(--grey-600); flex-shrink: 0; } +.dsb-item:hover i, .dsb-item.active i { color: var(--grey-400); } + +.dsb-divider { + height: 1px; + background: var(--grey-800); + margin: 12px 0; } -.nav-burger:hover { - border-color: var(--fg-muted); - color: var(--fg); +.dsb-section-label-links { + font-size: 0.65rem; + font-weight: 600; + letter-spacing: 1.5px; + text-transform: uppercase; + color: var(--grey-600); + padding: 4px 0; + margin-bottom: 4px; +} + +.dsb-link { + display: flex; + align-items: center; + gap: 8px; + padding: 6px 8px; + color: var(--grey-400); + font-size: 0.78rem; + font-weight: 500; + transition: color 0.1s; +} + +.dsb-link:hover { color: var(--grey-200); } +.dsb-link i { width: 14px; font-size: 0.75rem; color: var(--grey-600); flex-shrink: 0; } + +.page-content { + flex: 1; + min-width: 0; + padding-left: 40px; } +/* ── MOBILE DRAWER ───────────────────────────────── */ .drawer-overlay { + display: none; position: fixed; inset: 0; - background: rgba(1, 4, 9, 0.6); - z-index: 997; - opacity: 0; - pointer-events: none; - transition: opacity 0.25s var(--ease); - backdrop-filter: blur(2px); + background: rgba(0,0,0,0.6); + z-index: 150; + backdrop-filter: blur(3px); } -.drawer-overlay.open { - opacity: 1; - pointer-events: all; -} +.drawer-overlay.open { display: block; } .mobile-drawer { position: fixed; - top: 0; - left: 0; - bottom: 0; - width: 260px; - background: var(--canvas-subtle); - border-right: 1px solid var(--border-muted); - z-index: 998; - transform: translateX(-100%); - opacity: 0; - pointer-events: none; - transition: - transform 0.28s var(--ease), - opacity 0.28s; + top: 0; left: -280px; + width: 280px; + height: 100%; + background: var(--grey-950); + border-right: 1px solid var(--grey-800); + z-index: 200; + transition: left 0.25s cubic-bezier(0.4,0,0.2,1); display: flex; flex-direction: column; overflow-y: auto; } -.mobile-drawer.open { - transform: translateX(0); - opacity: 1; - pointer-events: all; -} +.mobile-drawer.open { left: 0; } .drawer-header { + position: sticky; + top: 0; display: flex; align-items: center; justify-content: space-between; - padding: 14px 16px; - border-bottom: 1px solid var(--border); + padding: 0 16px; + height: 56px; + background: var(--grey-950); + border-bottom: 1px solid var(--grey-800); + z-index: 1; flex-shrink: 0; } @@ -274,187 +273,157 @@ pre code { display: flex; align-items: center; gap: 8px; - text-decoration: none; -} - -.drawer-brand img { - width: 24px; - height: 24px; -} - -.drawer-brand span { + color: var(--white); font-family: var(--display); - font-size: 0.9rem; font-weight: 700; - color: var(--fg); - letter-spacing: 0.06em; + font-size: 0.9rem; + letter-spacing: 2px; } -.drawer-brand em { - color: var(--red); - font-style: normal; -} +.drawer-brand img { height: 20px; } +.drawer-brand em { font-style: normal; color: var(--grey-500); } -.drawer-close { +.drawer-collapse { background: none; - border: 1px solid var(--border-muted); - color: var(--fg-muted); - width: 28px; - height: 28px; - border-radius: 4px; + border: none; + color: var(--grey-500); + padding: 6px; cursor: pointer; + font-size: 1rem; display: flex; align-items: center; justify-content: center; - font-size: 0.8rem; - transition: all 0.12s; + width: 32px; + height: 32px; + transition: color 0.15s; } -.drawer-close:hover { - border-color: var(--fg-muted); - color: var(--fg); -} +.drawer-collapse:hover { color: var(--grey-200); } -.drawer-menu { - list-style: none; - padding: 10px 10px 20px; - display: flex; - flex-direction: column; - gap: 1px; - flex: 1; +.drawer-section-label { + padding: 16px 16px 6px; + font-size: 0.65rem; + font-weight: 600; + letter-spacing: 1.5px; + text-transform: uppercase; + color: var(--grey-600); } +.drawer-menu { list-style: none; padding: 4px 8px 8px; } + .drawer-item { display: flex; align-items: center; gap: 10px; - padding: 9px 12px; - border-radius: var(--r); - color: var(--fg-muted); - font-size: 0.875rem; + padding: 10px 12px; + color: var(--grey-400); + font-size: 0.84rem; font-weight: 500; - transition: all 0.12s; - text-decoration: none; + transition: all 0.1s; + position: relative; + border-radius: 0; + border-left: 2px solid transparent; } -.drawer-item i { - width: 16px; - color: var(--fg-subtle); - font-size: 0.85rem; -} -.drawer-item:hover { - color: var(--fg); - background: var(--canvas-overlay); -} -.drawer-item:hover i { - color: var(--fg-muted); +.drawer-item:hover { color: var(--white); background: var(--grey-900); } +.drawer-item.active { color: var(--white); background: var(--grey-900); border-left-color: var(--white); } +.drawer-item i { width: 14px; font-size: 0.78rem; color: var(--grey-600); flex-shrink: 0; } +.drawer-item:hover i, .drawer-item.active i { color: var(--grey-400); } + +.drawer-divider { + height: 1px; + background: var(--grey-800); + margin: 4px 16px 8px; } + +.drawer-section-label + .drawer-divider { display: none; } + .drawer-gh { - margin-top: auto; - border-top: 1px solid var(--border); - padding-top: 12px; - margin-left: -10px; - margin-right: -10px; - padding-left: 22px; - border-radius: 0; + margin: 4px 16px; + display: flex; + align-items: center; + gap: 8px; + padding: 10px 12px; + border: 1px solid var(--grey-700); + color: var(--grey-300); + font-size: 0.8rem; + font-weight: 500; + transition: all 0.15s; } +.drawer-gh:hover { color: var(--white); border-color: var(--grey-500); background: var(--grey-900); } +.drawer-gh i { width: 14px; font-size: 0.8rem; } + +.drawer-links-group { padding: 0 0 16px; } + +/* ── HERO ────────────────────────────────────────── */ .hero { - position: relative; min-height: 100vh; + padding-top: var(--nav); display: flex; align-items: center; - overflow: hidden; - padding-top: var(--nav); -} - -.hero-canvas { - position: absolute; - inset: 0; - width: 100%; - height: 100%; - z-index: 0; - display: block; -} - -.hero-canvas-fade { - position: absolute; - inset: 0; - z-index: 1; - background: linear-gradient( - 105deg, - rgba(13, 17, 23, 0.92) 0%, - rgba(13, 17, 23, 0.45) 50%, - rgba(13, 17, 23, 0.2) 100% - ); - pointer-events: none; + background: var(--black); + border-bottom: 1px solid var(--grey-800); } .hero-body { - position: relative; - z-index: 2; width: 100%; max-width: 1152px; margin: 0 auto; - padding: 80px 24px 88px; + padding: 80px 24px; display: grid; grid-template-columns: 1fr 1fr; - grid-template-rows: auto; - gap: 0 56px; + gap: 64px; align-items: center; } -.hero-left { - grid-column: 1; - display: flex; - flex-direction: column; -} - -.hero-screenshot { - grid-column: 2; - grid-row: 1 / 6; - align-self: center; +.hero-eyebrow { + display: inline-flex; + align-items: center; + gap: 8px; + font-size: 0.7rem; + font-weight: 600; + letter-spacing: 2px; + color: var(--grey-400); + text-transform: uppercase; + border: 1px solid var(--grey-700); + padding: 4px 10px; + margin-bottom: 24px; } .hero-heading { font-family: var(--display); - font-size: clamp(2.4rem, 4.5vw, 5.5rem); + font-size: clamp(3rem, 6vw, 5.5rem); font-weight: 900; - line-height: 0.88; - letter-spacing: -0.01em; + line-height: 0.95; + letter-spacing: -1px; + color: var(--white); margin-bottom: 24px; } -.h-line { +.hero-heading .h-sub { display: block; - color: var(--fg); -} - -.h-accent { - display: block; - color: var(--red); + font-size: 0.38em; + font-weight: 400; + letter-spacing: 4px; + color: var(--grey-500); + margin-top: 8px; } .hero-lead { - font-size: clamp(0.88rem, 1.4vw, 1rem); - color: var(--fg-muted); - max-width: 100%; + font-size: 0.95rem; + color: var(--grey-300); line-height: 1.7; - margin-bottom: 20px; + margin-bottom: 32px; + max-width: 480px; } .hero-meta { display: flex; flex-wrap: wrap; - align-items: center; gap: 0; margin-bottom: 32px; - background: var(--canvas-subtle); - border: 1px solid var(--border); - border-radius: var(--r); - width: fit-content; - max-width: 100%; - overflow: hidden; + border: 1px solid var(--grey-800); } .meta-item { @@ -462,1192 +431,849 @@ pre code { align-items: center; gap: 6px; padding: 8px 14px; - font-size: 0.78rem; - font-weight: 600; - color: var(--fg-muted); -} - -.meta-item i { - color: var(--fg-subtle); - font-size: 0.78rem; + font-size: 0.75rem; + font-weight: 500; + color: var(--grey-400); + border-right: 1px solid var(--grey-800); } -.meta-sep { - width: 1px; - height: 100%; - min-height: 34px; - background: var(--border); -} +.meta-item:last-child { border-right: none; } +.meta-item i { color: var(--grey-600); font-size: 0.8rem; } -.hero-cta { - display: flex; - flex-wrap: wrap; - gap: 10px; - margin-bottom: 52px; -} +.hero-cta { display: flex; gap: 12px; flex-wrap: wrap; } .cta-primary { display: inline-flex; align-items: center; - gap: 7px; - padding: 8px 18px; - background: var(--green-dim); - color: var(--white); - font-family: var(--font); - font-size: 0.85rem; + gap: 8px; + padding: 12px 20px; + background: var(--white); + color: var(--black); + font-size: 0.8rem; font-weight: 600; - border-radius: var(--r); - border: 1px solid var(--green-dim); + letter-spacing: 0.5px; + border: 1px solid var(--white); transition: all 0.15s; - white-space: nowrap; - text-decoration: none; } -.cta-primary:hover { - background: #2ea043; - border-color: #2ea043; - color: var(--white); -} +.cta-primary:hover { background: var(--grey-100); color: var(--black); border-color: var(--grey-100); } .cta-outline { display: inline-flex; align-items: center; - gap: 7px; - padding: 8px 18px; - background: var(--canvas-subtle); - color: var(--fg); - font-family: var(--font); - font-size: 0.85rem; + gap: 8px; + padding: 12px 20px; + background: transparent; + color: var(--grey-200); + font-size: 0.8rem; font-weight: 600; - border-radius: var(--r); - border: 1px solid var(--border-muted); + letter-spacing: 0.5px; + border: 1px solid var(--grey-700); transition: all 0.15s; - white-space: nowrap; - text-decoration: none; } -.cta-outline:hover { - background: var(--canvas-overlay); - border-color: var(--fg-muted); - color: var(--fg); +.cta-outline:hover { color: var(--white); border-color: var(--grey-500); } + +/* ── SCREENSHOT ──────────────────────────────────── */ +.hero-screenshot { + background: var(--grey-900); + border: 1px solid var(--grey-700); } -.section { - padding: 80px 0; - width: 100%; - overflow: hidden; - min-height: 100vh; +.screenshot-bar { display: flex; align-items: center; + gap: 6px; + padding: 10px 14px; + background: var(--grey-800); + border-bottom: 1px solid var(--grey-700); } -.section .container { - width: 100%; +.term-dot { width: 10px; height: 10px; border-radius: 50%; } +.term-dot.red { background: var(--grey-600); } +.term-dot.yellow { background: var(--grey-500); } +.term-dot.green { background: var(--grey-400); } + +.term-title { + margin-left: 8px; + font-family: var(--mono); + font-size: 0.72rem; + color: var(--grey-500); +} + +.screenshot-body { position: relative; overflow: hidden; aspect-ratio: 16/9; } + +.screenshot-track { + display: flex; + transition: transform 0.4s; +} + +.screenshot-slide { min-width: 100%; } +.screenshot-slide img { width: 100%; height: 100%; object-fit: cover; display: block; } + +.screenshot-nav { + position: absolute; + top: 50%; + transform: translateY(-50%); + background: rgba(0,0,0,0.6); + border: 1px solid var(--grey-700); + color: var(--grey-300); + padding: 8px 10px; + cursor: pointer; + font-size: 0.8rem; + transition: all 0.15s; +} + +.screenshot-nav:hover { color: var(--white); border-color: var(--grey-500); } +.screenshot-nav.prev { left: 10px; } +.screenshot-nav.next { right: 10px; } + +.screenshot-dots { + display: flex; + justify-content: center; + gap: 6px; + padding: 10px; + background: var(--grey-800); + border-top: 1px solid var(--grey-700); +} + +.screenshot-dot { + width: 6px; height: 6px; + background: var(--grey-600); + border: none; + cursor: pointer; + transition: background 0.15s; + padding: 0; } -.section-dark { - background: var(--canvas-inset); - border-top: 1px solid var(--border); - border-bottom: 1px solid var(--border); +.screenshot-dot.active { background: var(--white); } + +/* ── SECTIONS ────────────────────────────────────── */ +.section { + padding: 96px 0; + border-bottom: 1px solid var(--grey-800); } +.section-alt { background: var(--grey-950); } + .sec-label { display: inline-flex; align-items: center; - gap: 6px; + gap: 8px; font-size: 0.7rem; - font-weight: 700; - color: var(--fg-muted); - letter-spacing: 0.1em; + font-weight: 600; + letter-spacing: 2px; text-transform: uppercase; - margin-bottom: 12px; + color: var(--grey-500); + margin-bottom: 16px; } -.sec-label i { - color: var(--fg-subtle); -} +.sec-label i { font-size: 0.75rem; } .sec-title { font-family: var(--display); - font-size: clamp(1.6rem, 4vw, 2.5rem); + font-size: clamp(1.8rem, 3vw, 2.8rem); font-weight: 700; - color: var(--fg); - letter-spacing: 0.01em; - margin-bottom: 12px; + letter-spacing: -0.5px; + color: var(--white); + margin-bottom: 16px; } .sec-sub { font-size: 0.9rem; - color: var(--fg-muted); - max-width: 500px; - line-height: 1.65; + color: var(--grey-400); margin-bottom: 48px; + max-width: 560px; } +/* ── OVERVIEW ────────────────────────────────────── */ .overview-layout { display: grid; - grid-template-columns: 1fr 300px; - gap: 48px; + grid-template-columns: 1fr 1fr; + gap: 64px; align-items: start; } .overview-text p { - color: var(--fg-muted); - margin-bottom: 16px; - line-height: 1.75; font-size: 0.9rem; + color: var(--grey-300); + line-height: 1.75; + margin-bottom: 20px; } -.badge-row { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin-top: 10px; -} +.badge-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 28px; } .badge { display: inline-flex; align-items: center; - gap: 5px; - padding: 3px 10px; - background: var(--canvas-overlay); - border: 1px solid var(--border-muted); - border-radius: 100px; - font-size: 0.74rem; - font-weight: 600; - color: var(--fg-muted); - letter-spacing: 0.03em; - font-family: var(--mono); + gap: 6px; + font-size: 0.72rem; + font-weight: 500; + color: var(--grey-400); + padding: 4px 10px; + border: 1px solid var(--grey-700); } -.badge i { - color: var(--fg-subtle); - font-size: 0.7rem; -} -.badge.active { - color: var(--green); - border-color: var(--green-border); - background: var(--green-subtle); -} -.badge.active i { - color: var(--green); -} +.badge i { font-size: 0.75rem; } +.badge.active { color: var(--grey-200); border-color: var(--grey-500); } -.overview-cards { +.overview-cards { display: flex; flex-direction: column; gap: 12px; } + +.stat-grid { display: grid; grid-template-columns: 1fr 1fr; - gap: 8px; + gap: 12px; + margin-bottom: 12px; } .stat-card { - padding: 18px 14px; - text-align: center; - background: var(--canvas-subtle); - border: 1px solid var(--border); - border-radius: var(--r); - transition: border-color 0.2s; -} - -.stat-card:hover { - border-color: var(--border-muted); + padding: 20px; + border: 1px solid var(--grey-700); + background: var(--grey-950); } .stat-val { display: block; font-family: var(--display); - font-size: 1.55rem; + font-size: 1.6rem; font-weight: 700; - color: var(--fg); - line-height: 1; - margin-bottom: 5px; + color: var(--white); + letter-spacing: 1px; } .stat-key { display: block; - font-size: 0.68rem; - font-weight: 700; - color: var(--fg-subtle); - text-transform: uppercase; - letter-spacing: 0.08em; + font-size: 0.72rem; + color: var(--grey-500); + margin-top: 4px; + font-weight: 500; + letter-spacing: 0.5px; } .alert-card { - grid-column: span 2; display: flex; - gap: 10px; + gap: 14px; align-items: flex-start; - padding: 12px 14px; - background: rgba(248, 81, 73, 0.06); - border: 1px solid var(--red-border); - border-radius: var(--r); + padding: 16px; + border: 1px solid var(--grey-600); + background: var(--grey-950); } -.alert-icon { - color: var(--red); - font-size: 0.9rem; - margin-top: 2px; - flex-shrink: 0; -} +.alert-icon { color: var(--grey-400); font-size: 1rem; padding-top: 2px; flex-shrink: 0; } .alert-text strong { display: block; - font-size: 0.72rem; - font-weight: 700; - color: var(--red); - text-transform: uppercase; - letter-spacing: 0.06em; - margin-bottom: 3px; + font-size: 0.8rem; + font-weight: 600; + color: var(--grey-200); + margin-bottom: 4px; } -.alert-text p { - font-size: 0.76rem; - color: var(--fg-muted); - line-height: 1.55; -} +.alert-text p { font-size: 0.78rem; color: var(--grey-400); line-height: 1.6; } +/* ── FEATURES ────────────────────────────────────── */ .feat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; - border: 1px solid var(--border); - border-radius: var(--r); - overflow: hidden; - background: var(--border); + background: var(--grey-800); + border: 1px solid var(--grey-800); } .feat-card { - padding: 22px 20px; - background: var(--canvas-subtle); - transition: background 0.2s; - min-width: 0; - cursor: default; + padding: 32px 28px; + background: var(--grey-950); position: relative; + transition: background 0.15s; } -.feat-card:hover { - background: var(--canvas-overlay); -} +.feat-card:hover { background: var(--grey-900); } .feat-num { - position: absolute; - top: 14px; - right: 16px; - font-family: var(--display); - font-size: 1.6rem; - font-weight: 900; - color: var(--border-muted); - line-height: 1; + font-family: var(--mono); + font-size: 0.7rem; + color: var(--grey-700); + font-weight: 600; + letter-spacing: 1px; + margin-bottom: 16px; } .feat-ico { - width: 36px; - height: 36px; - background: var(--canvas); - border: 1px solid var(--border-muted); - border-radius: var(--r); - display: flex; - align-items: center; - justify-content: center; - color: var(--fg-muted); - font-size: 0.9rem; - margin-bottom: 12px; - transition: all 0.2s; -} - -.feat-card:hover .feat-ico { - border-color: var(--fg-subtle); - color: var(--fg); + font-size: 1.1rem; + color: var(--grey-500); + margin-bottom: 14px; } .feat-card h3 { - font-size: 0.875rem; - font-weight: 700; - color: var(--fg); - margin-bottom: 7px; -} -.feat-card p { - font-size: 0.8rem; - color: var(--fg-muted); - line-height: 1.6; + font-size: 0.9rem; + font-weight: 600; + color: var(--white); + margin-bottom: 10px; + letter-spacing: 0.3px; } -.steps { - display: flex; - flex-direction: column; -} +.feat-card p { font-size: 0.8rem; color: var(--grey-400); line-height: 1.65; } + +/* ── STEPS ───────────────────────────────────────── */ +.steps { display: flex; flex-direction: column; gap: 0; } .step { display: grid; - grid-template-columns: 64px 1fr; - gap: 20px; + grid-template-columns: 56px 1fr; + gap: 28px; padding: 32px 0; - border-bottom: 1px solid var(--border); + border-bottom: 1px solid var(--grey-800); } -.step:first-child { - padding-top: 0; -} -.step:last-child { - border-bottom: none; -} +.step:last-child { border-bottom: none; } -.step-aside { - display: flex; - flex-direction: column; - align-items: center; -} +.step-aside { display: flex; flex-direction: column; align-items: center; padding-top: 2px; } .step-idx { - font-family: var(--display); - font-size: 1.4rem; - font-weight: 900; - color: var(--border-muted); - line-height: 1; - flex-shrink: 0; + font-family: var(--mono); + font-size: 0.72rem; + font-weight: 600; + color: var(--grey-600); + border: 1px solid var(--grey-700); + padding: 4px 8px; + letter-spacing: 1px; } -.step-line { - flex: 1; - width: 1px; - background: var(--border); - margin-top: 10px; - min-height: 20px; -} +.step-line { flex: 1; width: 1px; background: var(--grey-800); margin-top: 12px; } -.step-main { - min-width: 0; - padding-top: 2px; -} .step-main h3 { - font-size: 0.95rem; - font-weight: 700; - color: var(--fg); - margin-bottom: 6px; -} -.step-main > p { - font-size: 0.85rem; - color: var(--fg-muted); - margin-bottom: 14px; - line-height: 1.65; + font-size: 1rem; + font-weight: 600; + color: var(--white); + margin-bottom: 8px; } -.req-grid { - display: flex; - flex-direction: column; - gap: 4px; -} +.step-main > p { font-size: 0.85rem; color: var(--grey-400); margin-bottom: 20px; line-height: 1.65; } + +.req-grid { display: flex; flex-direction: column; gap: 0; border: 1px solid var(--grey-800); } .req-row { display: flex; align-items: center; - gap: 10px; - padding: 8px 12px; - background: var(--canvas-subtle); - border: 1px solid var(--border); - border-radius: var(--r); - font-size: 0.84rem; - color: var(--fg); - min-width: 0; -} - -.req-row i { - color: var(--fg-subtle); - width: 16px; - flex-shrink: 0; - font-size: 0.9rem; -} -.req-row span:nth-child(2) { - flex: 1; - min-width: 0; -} - -.pill { - padding: 1px 7px; - background: var(--green-subtle); - border: 1px solid var(--green-border); - border-radius: 100px; - font-size: 0.64rem; - font-weight: 700; - color: var(--green); - text-transform: uppercase; - letter-spacing: 0.06em; - white-space: nowrap; - flex-shrink: 0; + gap: 12px; + padding: 10px 16px; + border-bottom: 1px solid var(--grey-800); + font-size: 0.82rem; + color: var(--grey-300); } -.pill.muted { - background: var(--canvas-overlay); - border-color: var(--border-muted); - color: var(--fg-subtle); -} +.req-row:last-child { border-bottom: none; } +.req-row i { color: var(--grey-600); width: 16px; text-align: center; } +.req-row .pill { margin-left: auto; font-size: 0.68rem; font-weight: 600; color: var(--grey-500); letter-spacing: 0.5px; border: 1px solid var(--grey-700); padding: 2px 8px; } +.req-row .pill.muted { color: var(--grey-600); border-color: var(--grey-800); } +/* ── CODEBLOCK ───────────────────────────────────── */ .codeblock { - background: var(--canvas-inset); - border: 1px solid var(--border-muted); - border-radius: var(--r); - overflow: hidden; - max-width: 100%; - margin-bottom: 12px; + background: var(--grey-950); + border: 1px solid var(--grey-700); + margin-top: 16px; } .cb-header { display: flex; align-items: center; justify-content: space-between; - padding: 7px 12px; - background: var(--canvas-subtle); - border-bottom: 1px solid var(--border); + padding: 8px 14px; + background: var(--grey-900); + border-bottom: 1px solid var(--grey-700); } .cb-lang { - font-size: 0.68rem; - font-weight: 700; - color: var(--fg-subtle); - text-transform: uppercase; - letter-spacing: 0.08em; font-family: var(--mono); + font-size: 0.7rem; + color: var(--grey-600); + font-weight: 600; + letter-spacing: 1px; + text-transform: uppercase; } .cb-copy { background: none; - border: 1px solid var(--border-muted); - color: var(--fg-subtle); - padding: 3px 9px; - border-radius: 4px; - font-size: 0.7rem; + border: 1px solid var(--grey-700); + color: var(--grey-500); + padding: 3px 8px; cursor: pointer; - display: flex; - align-items: center; - gap: 5px; - transition: all 0.12s; - font-family: var(--font); + font-size: 0.75rem; + transition: all 0.15s; } -.cb-copy:hover { - border-color: var(--fg-muted); - color: var(--fg); -} -.cb-copy.copied { - border-color: var(--green-border); - color: var(--green); - background: var(--green-subtle); -} +.cb-copy:hover { color: var(--grey-200); border-color: var(--grey-500); } .codeblock pre { padding: 16px; overflow-x: auto; + font-family: var(--mono); font-size: 0.82rem; line-height: 1.7; - max-width: 100%; + color: var(--grey-200); + white-space: pre; } -.cm { - color: var(--fg-dim); -} +.cm { color: var(--grey-600); } .ok-box { display: flex; align-items: center; gap: 8px; - padding: 10px 12px; - background: var(--green-subtle); - border: 1px solid var(--green-border); - border-radius: var(--r); + margin-top: 14px; + padding: 10px 14px; + border: 1px solid var(--grey-700); font-size: 0.8rem; - color: var(--green); - margin-top: 6px; + color: var(--grey-300); + background: var(--grey-950); } -.ok-box i { - flex-shrink: 0; -} - -.step-note { - display: flex; - align-items: center; - gap: 6px; - font-size: 0.78rem; - color: var(--fg-subtle); - margin-top: 8px; -} - -.step-note i { - color: var(--fg-subtle); - flex-shrink: 0; -} +.ok-box i { color: var(--grey-500); } +/* ── COMMANDS ────────────────────────────────────── */ .tab-row { display: flex; gap: 0; - border-bottom: 1px solid var(--border); - margin-bottom: 16px; - overflow-x: auto; + margin-bottom: 0; + border-bottom: 1px solid var(--grey-700); } .tab { - padding: 9px 18px; + padding: 10px 18px; background: none; border: none; border-bottom: 2px solid transparent; - color: var(--fg-muted); + color: var(--grey-500); + font-size: 0.8rem; + font-weight: 500; font-family: var(--font); - font-size: 0.82rem; - font-weight: 600; cursor: pointer; - transition: all 0.12s; - white-space: nowrap; + letter-spacing: 0.5px; margin-bottom: -1px; + transition: all 0.15s; } -.tab:hover { - color: var(--fg); -} -.tab.active { - color: var(--fg); - border-bottom-color: var(--red); -} +.tab:hover { color: var(--grey-200); } +.tab.active { color: var(--white); border-bottom-color: var(--white); } -.tab-panel { - display: none; -} -.tab-panel.active { - display: block; -} +.tab-panel { display: none; } +.tab-panel.active { display: block; } -.cmd-scroll { - overflow-x: auto; - -webkit-overflow-scrolling: touch; - border: 1px solid var(--border); - border-radius: var(--r); -} +.cmd-scroll { overflow-x: auto; } -.cmd-grid { - background: var(--canvas-subtle); - min-width: 520px; - width: 100%; -} +.cmd-grid { display: flex; flex-direction: column; border: 1px solid var(--grey-800); border-top: none; } .cmd-head { display: grid; - grid-template-columns: 130px 200px 1fr; - gap: 16px; - padding: 10px 16px; - background: var(--canvas-inset); - border-bottom: 1px solid var(--border); - font-size: 0.68rem; - font-weight: 700; - color: var(--fg-subtle); + grid-template-columns: 180px 200px 1fr; + padding: 8px 16px; + background: var(--grey-900); + border-bottom: 1px solid var(--grey-700); + font-size: 0.7rem; + font-weight: 600; + letter-spacing: 1px; text-transform: uppercase; - letter-spacing: 0.08em; - white-space: nowrap; + color: var(--grey-600); } .cmd-row { display: grid; - grid-template-columns: 130px 200px 1fr; - gap: 16px; - padding: 11px 16px; - border-bottom: 1px solid var(--border-subtle); + grid-template-columns: 180px 200px 1fr; + padding: 10px 16px; + border-bottom: 1px solid var(--grey-800); align-items: center; + font-size: 0.82rem; transition: background 0.1s; - white-space: nowrap; } -.cmd-row:last-child { - border-bottom: none; -} -.cmd-row:hover { - background: var(--canvas-overlay); -} -.cmd-row code { - font-size: 0.78rem; -} -.cmd-row span { - font-size: 0.82rem; - color: var(--fg-muted); - white-space: normal; -} +.cmd-row:last-child { border-bottom: none; } +.cmd-row:hover { background: var(--grey-900); } +.cmd-row code { font-size: 0.78rem; } +.cmd-row span { color: var(--grey-400); } +/* ── ARCHITECTURE ────────────────────────────────── */ .arch-wrap { display: grid; - grid-template-columns: 1fr 280px; - gap: 40px; + grid-template-columns: 1fr 340px; + gap: 48px; align-items: start; } .arch-diagram { - background: var(--canvas-subtle); - border: 1px solid var(--border); - border-radius: var(--r); - padding: 20px; - overflow: hidden; - min-width: 0; + border: 1px solid var(--grey-700); + background: var(--grey-950); + padding: 24px; } -.arch-diagram svg { - width: 100%; - height: auto; - display: block; -} +.arch-diagram svg { width: 100%; height: auto; display: block; } -.arch-notes { - display: flex; - flex-direction: column; - gap: 20px; -} +.arch-notes { display: flex; flex-direction: column; gap: 0; } .arch-note { display: flex; - gap: 12px; + gap: 16px; + padding: 20px 0; + border-bottom: 1px solid var(--grey-800); align-items: flex-start; } +.arch-note:last-child { border-bottom: none; } + .an-dot { - width: 7px; - height: 7px; - border-radius: 2px; - background: var(--border-muted); - margin-top: 7px; + width: 6px; height: 6px; + background: var(--grey-500); flex-shrink: 0; + margin-top: 6px; } .arch-note h4 { - font-size: 0.875rem; - font-weight: 700; - color: var(--fg); - margin-bottom: 4px; -} -.arch-note p { - font-size: 0.8rem; - color: var(--fg-muted); - line-height: 1.6; + font-size: 0.85rem; + font-weight: 600; + color: var(--white); + margin-bottom: 6px; } -.cfg-groups { - display: flex; - flex-direction: column; - gap: 24px; -} +.arch-note p { font-size: 0.8rem; color: var(--grey-400); line-height: 1.65; } + +/* ── CONFIG ──────────────────────────────────────── */ +.cfg-groups { display: flex; flex-direction: column; gap: 24px; } + +.cfg-group { border: 1px solid var(--grey-800); } .cfg-group-label { display: flex; align-items: center; - gap: 7px; - font-size: 0.78rem; - font-weight: 700; - color: var(--fg-muted); - margin-bottom: 8px; - letter-spacing: 0.03em; + gap: 8px; + padding: 10px 16px; + background: var(--grey-900); + border-bottom: 1px solid var(--grey-700); + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 1px; + text-transform: uppercase; + color: var(--grey-500); } -.cfg-group-label i { - font-size: 0.78rem; - color: var(--fg-subtle); -} +.cfg-group-label i { font-size: 0.8rem; } -.cfg-scroll { - overflow-x: auto; - -webkit-overflow-scrolling: touch; - border: 1px solid var(--border); - border-radius: var(--r); -} +.cfg-scroll { overflow-x: auto; } -.cfg-table { - background: var(--canvas-subtle); - min-width: 480px; - width: 100%; -} +.cfg-table { display: flex; flex-direction: column; } .cfg-head { display: grid; - grid-template-columns: 200px 140px 1fr; - gap: 16px; - padding: 10px 16px; - background: var(--canvas-inset); - border-bottom: 1px solid var(--border); - font-size: 0.68rem; - font-weight: 700; - color: var(--fg-subtle); + grid-template-columns: 220px 200px 1fr; + padding: 8px 16px; + background: var(--grey-950); + border-bottom: 1px solid var(--grey-800); + font-size: 0.7rem; + font-weight: 600; + letter-spacing: 1px; text-transform: uppercase; - letter-spacing: 0.08em; - white-space: nowrap; + color: var(--grey-600); } .cfg-row { display: grid; - grid-template-columns: 200px 140px 1fr; - gap: 16px; - padding: 11px 16px; - border-bottom: 1px solid var(--border-subtle); + grid-template-columns: 220px 200px 1fr; + padding: 10px 16px; + border-bottom: 1px solid var(--grey-800); align-items: center; font-size: 0.82rem; transition: background 0.1s; - white-space: nowrap; } -.cfg-row:last-child { - border-bottom: none; -} -.cfg-row:hover { - background: var(--canvas-overlay); -} -.cfg-row span { - color: var(--fg-muted); - white-space: normal; -} +.cfg-row:last-child { border-bottom: none; } +.cfg-row:hover { background: var(--grey-900); } +.cfg-row code { font-size: 0.78rem; } +.cfg-row span { color: var(--grey-400); } -.cta-section { +/* ── DISCLAIMER ──────────────────────────────────── */ +.disclaimer-section { padding: 64px 0; - background: var(--canvas-inset); - border-top: 1px solid var(--border); + border-bottom: 1px solid var(--grey-800); + background: var(--grey-950); } -.cta-box { - position: relative; - overflow: hidden; - background: var(--canvas-subtle); - border: 1px solid var(--border-muted); - border-radius: var(--r); - padding: 48px 40px; - text-align: center; +.disclaimer-box { + border: 1px solid var(--grey-700); + padding: 32px; } -.cta-glow { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 360px; - height: 240px; - background: radial-gradient( - ellipse at center, - rgba(248, 81, 73, 0.05) 0%, - transparent 70% - ); - pointer-events: none; -} - -.cta-content { - position: relative; - z-index: 1; +.disclaimer-header { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 20px; } -.cta-content h2 { +.disclaimer-header i { font-size: 1rem; color: var(--grey-400); } + +.disclaimer-header h3 { font-family: var(--display); - font-size: clamp(1.6rem, 4vw, 2.4rem); + font-size: 1rem; font-weight: 700; - color: var(--fg); - margin-bottom: 10px; + letter-spacing: 1px; + color: var(--white); } -.cta-content p { - font-size: 0.9rem; - color: var(--fg-muted); - max-width: 440px; - margin: 0 auto 24px; - line-height: 1.65; -} +.disclaimer-text { font-size: 0.82rem; color: var(--grey-400); line-height: 1.75; margin-bottom: 20px; } -.cta-btns { - display: flex; - justify-content: center; - gap: 10px; - flex-wrap: wrap; +.legal-table { width: 100%; border-collapse: collapse; margin-top: 16px; } + +.legal-table th { + text-align: left; + padding: 8px 12px; + background: var(--grey-900); + border: 1px solid var(--grey-700); + font-size: 0.72rem; + font-weight: 600; + letter-spacing: 0.5px; + color: var(--grey-500); } -.footer { - background: var(--canvas-inset); - border-top: 1px solid var(--border); - padding: 48px 0 24px; - overflow: hidden; +.legal-table td { + padding: 8px 12px; + border: 1px solid var(--grey-800); + font-size: 0.78rem; + color: var(--grey-400); } -.footer-top { - display: flex; - gap: 48px; - margin-bottom: 36px; - align-items: flex-start; +.legal-table tr:hover td { background: var(--grey-900); } + +/* ── CTA FINAL ───────────────────────────────────── */ +.cta-final { + padding: 96px 0; + border-bottom: 1px solid var(--grey-800); } -.footer-brand { +.cta-inner { + border: 1px solid var(--grey-700); + padding: 48px; display: flex; - align-items: flex-start; - gap: 10px; - flex-shrink: 0; - min-width: 180px; + align-items: center; + justify-content: space-between; + gap: 32px; } -.footer-logo { - width: 36px; - height: 36px; - flex-shrink: 0; -} -.footer-name { +.cta-inner h2 { font-family: var(--display); - font-size: 0.9rem; + font-size: 2rem; font-weight: 700; - color: var(--fg); + color: var(--white); + letter-spacing: -0.5px; } -.footer-sub { - font-size: 0.72rem; - color: var(--fg-subtle); - margin-top: 2px; + +.cta-inner p { font-size: 0.875rem; color: var(--grey-400); margin-top: 8px; } + +.cta-btns { display: flex; gap: 12px; flex-shrink: 0; } + +/* ── FOOTER ──────────────────────────────────────── */ +.footer { + padding: 48px 0 32px; + background: var(--black); } -.footer-cols { - display: flex; - gap: 36px; - flex: 1; - flex-wrap: wrap; +.footer-top { + display: grid; + grid-template-columns: 240px 1fr; + gap: 64px; + margin-bottom: 40px; + padding-bottom: 40px; + border-bottom: 1px solid var(--grey-800); } -.footer-col { - display: flex; - flex-direction: column; - gap: 8px; - min-width: 110px; +.footer-brand { display: flex; align-items: flex-start; gap: 12px; } +.footer-logo { height: 28px; } + +.footer-name { + font-family: var(--display); + font-size: 0.95rem; + font-weight: 700; + color: var(--grey-300); + letter-spacing: 2px; } +.footer-sub { font-size: 0.72rem; color: var(--grey-600); margin-top: 3px; } + +.footer-cols { display: grid; grid-template-columns: repeat(4, 1fr); gap: 32px; } + +.footer-col { display: flex; flex-direction: column; gap: 10px; } + .fcol-label { - font-size: 0.68rem; - font-weight: 700; - color: var(--fg-subtle); + font-size: 0.7rem; + font-weight: 600; + letter-spacing: 1.5px; text-transform: uppercase; - letter-spacing: 0.1em; - margin-bottom: 2px; + color: var(--grey-600); + margin-bottom: 4px; } -.footer-col a { - font-size: 0.8rem; - color: var(--fg-muted); - transition: color 0.12s; -} -.footer-col a:hover { - color: var(--fg); -} +.footer-col a { font-size: 0.8rem; color: var(--grey-500); transition: color 0.15s; } +.footer-col a:hover { color: var(--grey-200); } .footer-bottom { display: flex; justify-content: space-between; align-items: center; - padding-top: 16px; - border-top: 1px solid var(--border); - font-size: 0.74rem; - color: var(--fg-dim); - flex-wrap: wrap; - gap: 8px; + font-size: 0.75rem; + color: var(--grey-700); } +/* ── TO TOP ──────────────────────────────────────── */ .to-top { position: fixed; - bottom: 22px; - right: 22px; - width: 38px; - height: 38px; - background: var(--canvas-subtle); - border: 1px solid var(--border-muted); - border-radius: var(--r); - color: var(--fg-muted); - font-size: 0.8rem; + bottom: 24px; right: 24px; + width: 36px; height: 36px; + background: var(--grey-900); + border: 1px solid var(--grey-700); + color: var(--grey-400); cursor: pointer; - display: flex; + font-size: 0.8rem; + display: none; align-items: center; justify-content: center; - transition: all 0.12s; - opacity: 0; - pointer-events: none; - z-index: 500; + transition: all 0.15s; } -.to-top.visible { - opacity: 1; - pointer-events: all; -} -.to-top:hover { - border-color: var(--fg-muted); - color: var(--fg); - background: var(--canvas-overlay); -} +.to-top:hover { color: var(--white); border-color: var(--grey-500); } +.to-top.visible { display: flex; } -.reveal { - opacity: 0; - transform: translateY(16px); - transition: - opacity 0.5s var(--ease), - transform 0.5s var(--ease); -} +/* ── REVEAL ──────────────────────────────────────── */ +.reveal { opacity: 0; transform: translateY(16px); transition: opacity 0.4s, transform 0.4s; } +.reveal.in { opacity: 1; transform: none; } -.reveal.visible { - opacity: 1; - transform: translateY(0); -} -.reveal-d1 { - transition-delay: 0.07s; -} -.reveal-d2 { - transition-delay: 0.14s; -} -.reveal-d3 { - transition-delay: 0.21s; -} -.reveal-d4 { - transition-delay: 0.28s; -} -.reveal-d5 { - transition-delay: 0.35s; -} +/* ── RESPONSIVE 900px ────────────────────────────── */ +@media (max-width: 900px) { + .nav-menu { display: none; } + .nav-burger { display: flex; } + .desktop-sidebar { display: none; } + .page-layout { display: block; padding: 0; } + .page-content { padding-left: 0; } -.hero-screenshot { - width: 100%; - border-radius: var(--r); - overflow: hidden; - border: 1px solid var(--border-muted); - box-shadow: 0 24px 64px rgba(1, 4, 9, 0.8); -} + .hero-body { + grid-template-columns: 1fr; + gap: 32px; + padding: 48px 20px 56px; + } -.screenshot-bar { - display: flex; - align-items: center; - gap: 6px; - padding: 9px 12px; - background: var(--canvas-subtle); - border-bottom: 1px solid var(--border); -} + .hero-heading { font-size: clamp(2.8rem, 12vw, 4.5rem); } + .hero-lead { font-size: 0.875rem; margin-bottom: 24px; } -.term-dot { - width: 10px; - height: 10px; - border-radius: 50%; -} -.term-dot.red { - background: #ff5f57; -} -.term-dot.yellow { - background: #febc2e; -} -.term-dot.green { - background: #28c840; -} + .hero-meta { + display: grid; + grid-template-columns: 1fr 1fr; + border: 1px solid var(--grey-800); + } -.term-title { - font-family: var(--mono); - font-size: 0.7rem; - color: var(--fg-subtle); - margin-left: 6px; - flex: 1; -} + .meta-item { border-right: none; border-bottom: 1px solid var(--grey-800); } + .meta-item:nth-child(odd) { border-right: 1px solid var(--grey-800); } + .meta-item:nth-last-child(-n+2) { border-bottom: none; } -.screenshot-body { - background: var(--canvas-inset); - position: relative; - overflow: hidden; -} + .hero-cta { gap: 10px; } + .cta-primary, .cta-outline { padding: 11px 16px; font-size: 0.78rem; width: 100%; justify-content: center; } -.screenshot-track { - display: flex; - transition: transform 0.38s var(--ease); -} + .section { padding: 64px 0; } -.screenshot-slide { - min-width: 100%; - line-height: 0; -} + .overview-layout { grid-template-columns: 1fr; gap: 32px; } + .stat-grid { grid-template-columns: 1fr 1fr; } + .feat-grid { grid-template-columns: 1fr 1fr; } -.screenshot-slide img { - width: 100%; - height: auto; - display: block; - object-fit: cover; -} + .steps { gap: 0; } + .step { grid-template-columns: 44px 1fr; gap: 16px; padding: 24px 0; } -.screenshot-nav { - position: absolute; - top: 50%; - transform: translateY(-50%); - display: flex; - align-items: center; - justify-content: center; - width: 30px; - height: 30px; - background: rgba(13, 17, 23, 0.85); - border: 1px solid var(--border-muted); - border-radius: 4px; - color: var(--fg-muted); - font-size: 0.75rem; - cursor: pointer; - transition: all 0.12s; - z-index: 10; -} + .tab-row { overflow-x: auto; white-space: nowrap; border-bottom: 1px solid var(--grey-700); } + .tab-row::-webkit-scrollbar { display: none; } + .tab { font-size: 0.75rem; padding: 9px 14px; } -.screenshot-nav:hover { - border-color: var(--fg-muted); - color: var(--fg); -} -.screenshot-nav.prev { - left: 8px; -} -.screenshot-nav.next { - right: 8px; -} + .cmd-head, .cmd-row { grid-template-columns: 120px 1fr; } + .cmd-head span:nth-child(2), .cmd-row code:nth-child(2) { display: none; } -.screenshot-dots { - display: flex; - justify-content: center; - gap: 5px; - padding: 7px 0 9px; - background: var(--canvas-inset); -} + .arch-wrap { grid-template-columns: 1fr; gap: 32px; } -.screenshot-dot { - width: 5px; - height: 5px; - border-radius: 1px; - background: var(--border-muted); - border: none; - cursor: pointer; - transition: - background 0.15s, - width 0.15s; - padding: 0; -} + .cfg-head, .cfg-row { grid-template-columns: 160px 1fr; } + .cfg-head span:nth-child(2), .cfg-row code:nth-child(2) { display: none; } -.screenshot-dot.active { - background: var(--fg-muted); - width: 16px; -} + .disclaimer-box { padding: 20px; } + .legal-table th:nth-child(2), .legal-table td:nth-child(2) { font-size: 0.72rem; } -@media (max-width: 1024px) { - .hero-body { - grid-template-columns: 1fr; - gap: 40px 0; - } - .hero-screenshot { - grid-column: 1; - grid-row: auto; - } - .overview-layout { - grid-template-columns: 1fr; - gap: 28px; - } - .overview-cards { - grid-template-columns: repeat(4, 1fr); - } - .alert-card { - grid-column: span 4; - } - .feat-grid { - grid-template-columns: repeat(2, 1fr); - } - .arch-wrap { - grid-template-columns: 1fr; - } - .footer-top { - flex-direction: column; - gap: 28px; - } + .cta-inner { flex-direction: column; padding: 24px; gap: 20px; } + .cta-inner h2 { font-size: 1.5rem; } + .cta-btns { flex-direction: column; width: 100%; } + .cta-btns .cta-primary, .cta-btns .cta-outline { justify-content: center; } + + .footer-top { grid-template-columns: 1fr; gap: 24px; } + .footer-cols { grid-template-columns: repeat(2, 1fr); gap: 24px; } + .footer-bottom { flex-direction: column; gap: 8px; text-align: center; } + + .to-top { bottom: 16px; right: 16px; } } -@media (max-width: 768px) { - .nav-menu { - display: none; - } - .nav-burger { - display: flex; - } +/* ── RESPONSIVE 480px ────────────────────────────── */ +@media (max-width: 480px) { + .container { padding: 0 16px; } - .hero-body { - padding: 48px 24px 56px; - grid-template-columns: 1fr; - } - .hero-screenshot { - grid-column: 1; - grid-row: auto; - } + .hero-body { padding: 36px 16px 48px; } + .hero-eyebrow { font-size: 0.62rem; letter-spacing: 1.5px; } + .hero-heading { font-size: clamp(2.2rem, 13vw, 3.2rem); } + .hero-lead { font-size: 0.85rem; line-height: 1.65; margin-bottom: 20px; } - .overview-cards { - grid-template-columns: repeat(2, 1fr); - } - .alert-card { - grid-column: span 2; - } + .hero-meta { grid-template-columns: 1fr 1fr; } + .meta-item { padding: 7px 10px; font-size: 0.7rem; } - .feat-grid { - grid-template-columns: 1fr; - } + .hero-cta { flex-direction: column; gap: 8px; } + .cta-primary, .cta-outline { width: 100%; justify-content: center; padding: 12px 16px; } - .step { - grid-template-columns: 48px 1fr; - gap: 14px; - } - .step-idx { - font-size: 1.1rem; - } + .badge-row { gap: 6px; } + .badge { font-size: 0.68rem; padding: 3px 8px; } - .cta-box { - padding: 36px 22px; - } - .footer-cols { - gap: 20px; - } -} + .feat-grid { grid-template-columns: 1fr; } + .feat-card { padding: 24px 20px; } -@media (max-width: 480px) { - .hero-meta { - flex-direction: column; - width: 100%; - } - .meta-sep { - width: 100%; - min-height: 1px; - height: 1px; - } - .meta-item { - width: 100%; - } - .hero-cta { - flex-direction: column; - } - .cta-primary, - .cta-outline { - justify-content: center; - } + .step { grid-template-columns: 36px 1fr; gap: 12px; padding: 20px 0; } + .step-idx { font-size: 0.68rem; padding: 3px 7px; } - .overview-cards { - grid-template-columns: 1fr 1fr; - } + .req-row { font-size: 0.78rem; padding: 9px 12px; gap: 10px; } + .req-row .pill { font-size: 0.64rem; padding: 2px 6px; } - .footer-cols { - flex-direction: column; - gap: 18px; - } - .footer-bottom { - flex-direction: column; - text-align: center; - } + .cmd-row, .cmd-head { grid-template-columns: 100px 1fr; font-size: 0.76rem; } + .cmd-row { padding: 10px 12px; } - .section { - padding: 56px 0; - } + .cfg-row, .cfg-head { grid-template-columns: 140px 1fr; font-size: 0.76rem; } - .step { - grid-template-columns: 1fr; - } - .step-aside { - flex-direction: row; - align-items: center; - gap: 10px; - } - .step-line { - flex: unset; - width: auto; - height: 1px; - min-height: unset; - flex: 1; - margin-top: 0; - } + .codeblock pre { font-size: 0.75rem; padding: 12px; line-height: 1.65; } + .cb-header { padding: 7px 12px; } - .codeblock pre { - font-size: 0.76rem; - padding: 12px; - } + .hero-screenshot { margin: 0 -16px; } + .screenshot-body { aspect-ratio: 4/3; } + + .footer-cols { grid-template-columns: 1fr 1fr; gap: 16px; } + + .sec-title { font-size: clamp(1.5rem, 6vw, 2rem); } + .sec-sub { font-size: 0.84rem; margin-bottom: 32px; } + + .section { padding: 52px 0; } + + .cta-inner { padding: 20px; } + .cta-inner h2 { font-size: 1.3rem; } + + .disclaimer-box { padding: 16px; } + .legal-table { font-size: 0.72rem; } + .legal-table th, .legal-table td { padding: 6px 8px; } + + .ok-box { font-size: 0.75rem; } + + .stat-card { padding: 16px; } + .stat-val { font-size: 1.3rem; } + + .overview-text p { font-size: 0.84rem; } + + .tab { font-size: 0.72rem; padding: 8px 12px; } + + .arch-note { padding: 16px 0; gap: 12px; } + + .to-top { bottom: 12px; right: 12px; width: 32px; height: 32px; font-size: 0.75rem; } + + .footer-name { font-size: 0.85rem; } + .footer-sub { font-size: 0.68rem; } } diff --git a/doc/pages/static/svg/hero-bg.svg b/doc/pages/static/svg/hero-bg.svg deleted file mode 100644 index c01a77c..0000000 --- a/doc/pages/static/svg/hero-bg.svg +++ /dev/null @@ -1,230 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SYN 0x4a2f8c1e - - - - ACK 0xdeadbeef - - - - ESTABLISHED - - - - RST 0x00ff - - - - 0x1337c0de - - -