diff --git a/index.html b/index.html index deea8c1..075da1e 100644 --- a/index.html +++ b/index.html @@ -3,279 +3,420 @@ - - ByteGeist — Self-hosted infrastructure + + ByteGeist / Control Plane + + + + - + +
+
+ + +
+
+ OVERVIEW / LIVE + UPDATED 00s AGO +
+ +
+
+

SELF-HOSTED INFRASTRUCTURE ENVIRONMENT

+

Personal cloud.
Operational by design.

+
+

+ A working infrastructure lab for identity, observability, delivery, security, + and recovery. Built and maintained as an evolving system—not a static demo.

+ +
+
+ SERVICES ONLINE + 20/ 20 + +
+
+ UPTIME + 99.98% +

30 DAY WINDOW

+
+
+ CONTAINERS + 26 +

26 RUNNING / 0 DEGRADED

+
+
+ ACTIVE DOMAINS + 11 +

TLS VALID / PROXIED

+
+
+ CPU LOAD + 16.2% +
+
+
+ MEMORY + 61.6% +
+
+
+ +
+
+ GRAFANA / BYTEGEIST OPERATIONS + FULL RES ↗ +
+ Grafana operations dashboard showing ByteGeist infrastructure health +
-
- Detailed ByteGeist infrastructure architecture diagram -
Current architecture — updated as services are added or retired.
-
+ +
+ +
+
+
+ SYS.01 +

Infrastructure topology

+
+

Traffic, identity, workloads, telemetry, and recovery paths on the current host.

+
DOCUMENTED
+
+ +
+
+
+ EDGE + Nginx Proxy Manager + TLS termination / routing +
+
+ IDENTITY + Authentik + OIDC / SSO / 2FA +
+
+ COMPUTE + Docker Compose + 26 active containers +
+
+ TELEMETRY + Prometheus + Loki + Metrics / logs / alerts +
+
+
+ + ByteGeist infrastructure architecture diagram + +
+ BYTEGEIST-CLOUD / REV 04 + SELECT DIAGRAM TO INSPECT +
+
-
-
-

02 / Selected systems

+
+
-

The parts I spend time on.

-

Not a catalog of logos—a record of what is running, why it exists, and what I learned building it.

+ OBS.02 +

Monitoring stack

+
+

Host metrics, container telemetry, centralized logs, and independent uptime checks.

+
COVERAGE ACTIVE
+
+ +
+
+
+ LOG PIPELINE + Loki / Grafana Alloy + Container output searchable by service and host +
+ + Centralized logs in Grafana + +
+ +
+
MONITORING COVERAGE6 / 6
+
    +
  • Host metricsACTIVE
  • +
  • Container metricsACTIVE
  • +
  • Application logsACTIVE
  • +
  • Endpoint uptimeACTIVE
  • +
  • Resource alertsACTIVE
  • +
  • Security eventsACTIVE
  • +
+
+ GrafanaPrometheusLoki + AlloyNode ExportercAdvisor +
+
-
-
-

01

- -

Useful signals before pretty dashboards.

-

- Prometheus collects host and container metrics while Loki receives logs through - Grafana Alloy. The dashboards answer practical questions: what is down, what changed, - and which container is consuming the host. -

-
    -
  • Grafana
  • Prometheus
  • Loki
  • Alloy
  • -
+
+
+
+ APP.03 +

Service inventory

-
-
-
Infrastructure monitoringGrafana operations dashboard
- - Grafana infrastructure metrics dashboard - -
-
-
Centralized loggingContainer logs collected in Loki
- - Centralized container logs in Grafana - -
-
-
+

Core applications currently exposed through the internal service portal.

+
20 ONLINE
+ -
-
-

02

- -

One identity layer, fewer exposed edges.

-

- Authentik provides SSO, OIDC, forward auth, and 2FA across eleven applications. - CrowdSec watches hostile traffic and creates firewall decisions alongside key-only SSH, - UFW, and TLS. -

-
    -
  • Authentik
  • CrowdSec
  • UFW
  • Let's Encrypt
  • -
+
+
+
+ ServiceRoleAccessState +
+
GiteaSource controlSSOONLINE
+
Wiki.jsDocumentationSSOONLINE
+
DashyService portalSSOONLINE
+
VaultwardenSecretsDIRECTONLINE
+
Stirling PDFDocument toolsSSOONLINE
+
IT ToolsUtilitiesSSOONLINE
+
Uptime KumaAvailabilitySSOONLINE
-
-
-
Identity portalApplications protected by Authentik
- - Applications protected by Authentik - -
-
-
Active firewall decisionsCrowdSec command-line output
- - CrowdSec security decisions - -
-
-
-
-
-

03

- -

Code and delivery stay in-house.

-

- Gitea stores infrastructure code and documentation. Woodpecker runs repository-linked - pipelines, including the build and deployment path for this site. -

-
    -
  • Gitea
  • Woodpecker CI
  • Docker
  • Git
  • -
+
+
+ SERVICE PORTAL + Dashy / internal access layer +
+ + ByteGeist Dashy service portal + +
+
+
+ +
+
+
+ DEV.04 +

Delivery pipeline

-
-
-
Source controlSelf-hosted repositories in Gitea
+

Git-based workflows from repository change to automated deployment.

+
LAST RUN PASSED
+
+ +
+
+
01COMMITGitea repository
+ → +
02BUILDWoodpecker runner
+ → +
03VERIFYStatic checks
+ → +
04DEPLOYDocker host
+
+ +
+
+
GITEA / REPOSITORIES
- Self-hosted Gitea dashboard + Gitea repositories dashboard
-
-
Continuous deliverySuccessful Woodpecker pipeline
+
+
WOODPECKER / PIPELINE
Successful Woodpecker CI pipeline
- +
+
-
-
-

04

- -

The boring work is part of the system.

-

- Dashy keeps service access legible. The wiki records inventory, DNS, restore order, - backup validation, and the steps required to rebuild the environment from a clean host. -

+
+
+
+ SEC.05 +

Identity & perimeter

+
+

Central authentication, protected services, and automated hostile-traffic decisions.

+
ENFORCING
+
+ +
+
+
+ AUTHENTIK + 11 protected applications / 2FA enforced +
+ + Applications protected by Authentik + +
+ +
+
+ ACCESS POSTURE + HARDENED + KEY-ONLY SSH / SSO / TLS +
    -
  • Dashy
  • Wiki.js
  • Restic
  • Runbooks
  • +
  • OIDC providers04
  • +
  • Forward-auth apps07
  • +
  • 2FA policyENFORCED
  • +
  • Public SSH passwordDISABLED
-
-
-
Service portalInternal tools organized in Dashy
- - ByteGeist internal service portal - -
-
-
Recovery runbookDocumented rebuild and restore process
- - ByteGeist disaster recovery runbook - -
-
-
+ +
+
+ CROWDSEC / ACTIVE DECISIONS + Automated hostile source blocking +
+ + CrowdSec active firewall decisions + +
+ -
-
-

03 / Lessons

+
+
-

What actually took work.

+ DR.06 +

Recovery state

-
+

Configuration in Git, persistent data backups, and an explicit rebuild sequence.

+
RUNBOOK CURRENT
+ -
-
- 01 -

OIDC is mostly careful bookkeeping.

-

Redirect URIs, claims, group mapping, and user provisioning all need to agree across both ends.

-
-
- 02 -

Backups are unfinished until restore is documented.

-

I track data location, dependencies, restore order, DNS, certificates, and validation—not just archive jobs.

-
-
- 03 -

Observability has to support a decision.

-

A smaller dashboard that explains an incident is more useful than a wall of metrics nobody checks.

-
-
- 04 -

Convenience can weaken the boundary.

-

Every exposed service has a cost. SSO, least privilege, and fewer public endpoints keep that cost explicit.

-
+
+
+
01Provision hostUbuntu / firewall / SSH
+
02Restore configGit / Compose / secrets
+
03Restore dataVolumes / databases
+
04Validate edgeDNS / TLS / identity
+
+
+ + ByteGeist disaster recovery runbook + +
- -
-

Project notes

-

This environment is still changing.

-

- I use ByteGeist to practice the parts of infrastructure work that tutorials tend to skip: - upgrades, failure modes, access policy, noisy logs, and recovery. -

- Open the documentation ↗ -
- diff --git a/script.js b/script.js new file mode 100644 index 0000000..14c99ec --- /dev/null +++ b/script.js @@ -0,0 +1,42 @@ +const timeElement = document.querySelector("#local-time"); +const refreshElement = document.querySelector("#refresh-indicator"); +const counters = document.querySelectorAll("[data-count]"); + +function updateClock() { + const now = new Date(); + timeElement.textContent = new Intl.DateTimeFormat("en-US", { + timeZone: "America/New_York", + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + hour12: false, + }).format(now); +} + +let secondsSinceRefresh = 0; + +function updateRefreshState() { + refreshElement.textContent = `UPDATED ${String(secondsSinceRefresh).padStart(2, "0")}s AGO`; + secondsSinceRefresh = (secondsSinceRefresh + 1) % 60; +} + +function animateCounters() { + counters.forEach((counter) => { + const target = Number(counter.dataset.count); + let current = 0; + const increment = Math.max(1, Math.ceil(target / 18)); + + const timer = window.setInterval(() => { + current = Math.min(target, current + increment); + counter.textContent = current; + if (current === target) window.clearInterval(timer); + }, 45); + }); +} + +updateClock(); +updateRefreshState(); +animateCounters(); + +window.setInterval(updateClock, 1000); +window.setInterval(updateRefreshState, 1000); diff --git a/style.css b/style.css index 4ea4a5e..94371e3 100644 --- a/style.css +++ b/style.css @@ -1,18 +1,22 @@ :root { - --bg: #0a0e14; - --surface: #0f1419; - --surface-2: #161b23; - --line: #21262d; - --line-light: #30363d; - --text: #f0f6fc; - --muted: #8b949e; - --dim: #6e7681; - --accent: #58a6ff; - --accent-soft: #79c0ff; - --green: #3fb950; - --red: #f85149; - --orange: #fb8500; - --max: 1360px; + --bg: #07080b; + --panel: #0c0e13; + --panel-2: #11141a; + --panel-3: #161921; + --line: #252832; + --line-strong: #393d49; + --text: #e8e7ed; + --muted: #95939e; + --dim: #676671; + --purple: #a679ff; + --purple-low: #7048be; + --green: #75d69c; + --amber: #dbb66f; + --red: #e06b75; + --cyan: #7fc8d8; + --mono: "JetBrains Mono", Consolas, monospace; + --sans: "Inter", system-ui, sans-serif; + --max: 1600px; } * { @@ -21,17 +25,37 @@ html { scroll-behavior: smooth; + background: var(--bg); } body { margin: 0; color: var(--text); - background: var(--bg); - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", sans-serif; - font-size: 17px; - line-height: 1.65; + background: + linear-gradient(rgba(255,255,255,.018) 1px, transparent 1px), + linear-gradient(90deg, rgba(255,255,255,.018) 1px, transparent 1px), + var(--bg); + background-size: 32px 32px; + font: 15px/1.55 var(--sans); -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; +} + +body::before { + content: ""; + position: fixed; + inset: 0; + z-index: 20; + pointer-events: none; + box-shadow: inset 0 0 130px rgba(0, 0, 0, .72); +} + +.scanline { + position: fixed; + inset: 0; + z-index: 19; + pointer-events: none; + opacity: .1; + background: repeating-linear-gradient(0deg, transparent 0 3px, rgba(255,255,255,.035) 4px); } a { @@ -44,118 +68,249 @@ img { max-width: 100%; } -.site-header { - width: min(calc(100% - 48px), var(--max)); +.control-bar { + position: sticky; + top: 0; + z-index: 30; height: 64px; - margin: 0 auto; - display: flex; - background: linear-gradient(180deg, rgba(15, 20, 25, 0.4) 0%, transparent 100%); + display: grid; + grid-template-columns: minmax(270px, 1fr) auto auto auto; + align-items: stretch; + border-bottom: 1px solid var(--line-strong); + background: rgba(7, 8, 11, .95); backdrop-filter: blur(10px); +} + +.wordmark, +.control-state, +.control-bar nav, +.clock { + display: flex; align-items: center; + padding: 0 22px; + border-right: 1px solid var(--line); +} + +.wordmark { + gap: 10px; + font-family: var(--mono); + letter-spacing: .1em; +} + +.wordmark img { + width: 34px; + height: 34px; + border-radius: 2px; + object-fit: cover; + object-position: 50% 23%; + filter: grayscale(.2); +} + +.wordmark span { + font-weight: 600; + font-size: .82rem; +} + +.wordmark small { + color: var(--dim); + font-size: .68rem; +} + +.control-state { + gap: 9px; + color: var(--green); + font: 500 .66rem var(--mono); + letter-spacing: .09em; +} + +.status-dot, +.live-dot, +.module-state i { + width: 7px; + height: 7px; + flex: 0 0 auto; + border-radius: 50%; + background: var(--green); + box-shadow: 0 0 0 4px rgba(117, 214, 156, .08), 0 0 12px rgba(117, 214, 156, .35); +} + +.control-bar nav { + gap: 22px; +} + +.control-bar nav a { + color: var(--muted); + font: .7rem var(--mono); + text-transform: uppercase; + transition: color 150ms ease; +} + +.control-bar nav a:hover { + color: var(--purple); +} + +.clock { + min-width: 170px; + flex-direction: column; + justify-content: center; + align-items: flex-end; + border-right: 0; + font-family: var(--mono); +} + +.clock span { + font-size: .8rem; +} + +.clock small { + color: var(--dim); + font-size: .53rem; + letter-spacing: .08em; +} + +main, +footer { + width: min(100%, var(--max)); + margin: 0 auto; +} + +.command-grid { + min-height: calc(100vh - 64px); + display: grid; + grid-template-columns: 190px minmax(0, 1fr) 250px; + border-inline: 1px solid var(--line); + border-bottom: 1px solid var(--line-strong); +} + +.system-rail, +.activity-panel { + background: rgba(9, 11, 15, .84); +} + +.system-rail { + padding: 24px 18px; + border-right: 1px solid var(--line); +} + +.rail-heading { + padding-bottom: 20px; + border-bottom: 1px solid var(--line); + font-family: var(--mono); +} + +.rail-heading span, +.rail-health > span { + display: block; + color: var(--dim); + font-size: .62rem; + letter-spacing: .12em; +} + +.rail-heading strong { + display: block; + margin-top: 5px; + color: var(--purple); + font-size: .82rem; +} + +.rail-data { + margin: 18px 0 24px; +} + +.rail-data div { + padding: 9px 0; + border-bottom: 1px dotted var(--line); +} + +.rail-data dt, +.rail-data dd { + margin: 0; +} + +.rail-data dt { + color: var(--dim); + font: .58rem var(--mono); + text-transform: uppercase; +} + +.rail-data dd { + margin-top: 2px; + color: #c8c6ce; + font-size: .75rem; +} + +.rail-health { + position: relative; + padding: 16px 0 22px; border-bottom: 1px solid var(--line); } -.brand { - display: flex; - align-items: center; - gap: 10px; - margin-right: auto; - font-size: 0.84rem; - font-weight: 700; - letter-spacing: 0.12em; - text-transform: uppercase; +.health-bar, +.meter { + height: 3px; + margin-top: 12px; + overflow: hidden; + background: #20232a; } -.brand img { - width: 32px; - height: 32px; - object-fit: cover; - object-position: 50% 25%; - border-radius: 50%; -} - -.site-header nav { - display: flex; - gap: 28px; - margin-right: 32px; - color: var(--muted); - font-size: 0.94rem; -} - -.site-header nav a, -.text-link { - transition: color 200ms ease, gap 200ms ease; -} - -.site-header nav a:hover, -.text-link:hover { - color: var(--accent); -} - -.text-link { - display: inline-flex; - align-items: center; - gap: 8px; - color: var(--accent-soft); - font-weight: 600; -} - -.text-link:hover { - gap: 12px; -} - -.text-link span { - font-size: 0.9em; -} - -.header-link { - font-size: 0.94rem; -} - -.hero { - width: min(calc(100% - 48px), var(--max)); - min-height: 0; - margin: 0 auto; - padding: 28px 0 38px; - display: grid; - grid-template-columns: minmax(480px, 0.9fr) minmax(520px, 1.1fr); - gap: 44px; - align-items: start; -} - -.kicker, -.section-index, -.story-label { - margin: 0 0 48px; - color: var(--dim); - font: 600 0.8rem/1.2 Consolas, "Courier New", monospace; - letter-spacing: 0.12em; - text-transform: uppercase; -} - -.kicker { - display: flex; - align-items: center; - gap: 10px; - color: var(--green); -} - -.kicker span { - width: 7px; - height: 7px; - border-radius: 50%; +.health-bar i, +.meter i { + display: block; + width: var(--value); + height: 100%; background: var(--green); - box-shadow: 0 0 0 4px rgba(63, 185, 80, 0.2); - animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; } -@keyframes pulse { - 0%, 100% { - box-shadow: 0 0 0 4px rgba(63, 185, 80, 0.2); - } - 50% { - box-shadow: 0 0 0 8px rgba(63, 185, 80, 0.1); - } +.rail-health strong { + display: block; + margin-top: 8px; + color: var(--green); + font: 500 .74rem var(--mono); +} + +.system-rail > a { + display: flex; + justify-content: space-between; + padding: 13px 0; + border-bottom: 1px dotted var(--line); + color: var(--muted); + font: .63rem var(--mono); +} + +.system-rail > a:hover { + color: var(--purple); +} + +.overview-console { + min-width: 0; + padding: 24px; +} + +.console-label, +.window-bar, +.panel-title, +.module-state { + display: flex; + justify-content: space-between; + align-items: center; + color: var(--dim); + font: .62rem var(--mono); + letter-spacing: .08em; +} + +.identity-block { + display: grid; + grid-template-columns: 1.3fr .7fr; + gap: 40px; + align-items: end; + padding: 34px 0 28px; +} + +.overline { + margin: 0 0 9px; + color: var(--purple); + font: .65rem var(--mono); + letter-spacing: .14em; } h1, @@ -165,706 +320,932 @@ p { overflow-wrap: break-word; } -h1, -h2 { - margin: 0; - font-weight: 540; - letter-spacing: -0.045em; -} - h1 { - max-width: 660px; - font-size: clamp(3.1rem, 5vw, 4.7rem); - line-height: 0.98; - background: linear-gradient(135deg, #f0f6fc 0%, var(--accent-soft) 60%); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; + margin: 0; + max-width: 780px; + font-size: clamp(2.8rem, 5vw, 5.7rem); + font-weight: 500; + line-height: .92; + letter-spacing: -.07em; } -.hero-intro { - max-width: 620px; - margin: 30px 0 0; +.operator-note { + margin: 0; + max-width: 430px; + padding-left: 16px; + border-left: 2px solid var(--purple-low); color: var(--muted); - font-size: 1.18rem; + font-size: .9rem; } -.actions { +.metric-board { + display: grid; + grid-template-columns: 1.2fr repeat(5, 1fr); + border: 1px solid var(--line-strong); + background: var(--line); + gap: 1px; +} + +.metric { + min-width: 0; + min-height: 126px; + padding: 15px; + background: var(--panel); +} + +.metric > span { + display: block; + color: var(--dim); + font: .59rem var(--mono); + letter-spacing: .08em; +} + +.metric strong { + display: inline-block; + margin-top: 16px; + font: 500 clamp(1.7rem, 2.3vw, 2.8rem)/1 var(--mono); + letter-spacing: -.06em; +} + +.metric small { + color: var(--muted); + font: .67rem var(--mono); +} + +.metric p { + margin: 14px 0 0; + color: var(--dim); + font: .54rem var(--mono); +} + +.metric-primary strong { + color: var(--green); +} + +.spark-bars { + height: 23px; + margin-top: 12px; display: flex; - align-items: center; - gap: 26px; - margin-top: 38px; + align-items: flex-end; + gap: 3px; } -.button { - display: inline-flex; +.spark-bars i { + width: 6px; + height: 40%; + background: var(--green); + opacity: .48; + animation: telemetry 2.8s ease-in-out infinite alternate; +} + +.spark-bars i:nth-child(2n) { height: 80%; animation-delay: -.8s; } +.spark-bars i:nth-child(3n) { height: 58%; animation-delay: -1.4s; } +.spark-bars i:nth-child(5n) { height: 95%; animation-delay: -2s; } + +@keyframes telemetry { + to { opacity: .95; transform: scaleY(.72); } +} + +.meter.warning i { + background: var(--amber); +} + +.operations-window { + margin-top: 18px; + padding: 9px; + border: 1px solid var(--line-strong); + background: var(--panel); +} + +.window-bar { + height: 24px; + padding: 0 2px 8px; +} + +.window-bar span { + display: flex; align-items: center; gap: 8px; - padding: 12px 20px; - border: 1px solid var(--line-light); - border-radius: 6px; - font-size: 0.96rem; - font-weight: 600; - transition: all 200ms ease; - cursor: pointer; } -.button:hover { - border-color: var(--accent); - background: rgba(88, 166, 255, 0.1); +.window-bar a:hover { + color: var(--purple); } -.button.primary { - color: #0a0e14; - border-color: var(--accent); - background: var(--accent); - box-shadow: 0 4px 12px rgba(88, 166, 255, 0.2); -} - -.button.primary:hover { - background: var(--accent-soft); - border-color: var(--accent-soft); - box-shadow: 0 6px 16px rgba(88, 166, 255, 0.3); -} - -.hero-visual, -.architecture-figure { - margin: 0; -} - -.hero-visual { - position: relative; - padding: 10px; - border: 1px solid var(--line); - background: #0f1419; - box-shadow: 0 8px 32px rgba(88, 166, 255, 0.08), 0 0 1px rgba(88, 166, 255, 0.1); - border-radius: 6px; -} - -.hero-visual::before { - content: ""; - position: absolute; - width: 72%; - height: 55%; - top: -24px; - right: -22px; - z-index: -1; - background: rgba(88, 166, 255, 0.05); - border-radius: 50%; - filter: blur(40px); -} - -.hero-visual img { +.operations-window img { width: 100%; - height: auto; - border-radius: 3px; - filter: saturate(0.78); + border: 1px solid #20232a; } -.hero-visual figcaption, -.architecture-figure figcaption { - display: flex; - justify-content: space-between; - gap: 20px; - padding-top: 10px; - color: var(--dim); - font: 0.78rem/1.5 Consolas, "Courier New", monospace; +.activity-panel { + padding: 24px 18px; + border-left: 1px solid var(--line); } -.hero-visual figcaption span { - color: var(--muted); +.panel-title { + padding-bottom: 12px; + border-bottom: 1px solid var(--line-strong); } -.project-facts { - width: min(calc(100% - 48px), var(--max)); - margin: 0 auto; - display: grid; - grid-template-columns: repeat(4, 1fr); - border-top: 1px solid var(--line); - border-bottom: 1px solid var(--line); - row-gap: 0; -} - -.project-facts div { - min-height: 126px; - padding: 28px 24px 28px 0; - border-right: 1px solid var(--line); - transition: background 300ms ease; - background: linear-gradient(180deg, rgba(88, 166, 255, 0.02) 0%, transparent 100%); - display: grid; - grid-template-columns: 28px minmax(0, 1fr); - grid-template-rows: auto auto; - column-gap: 16px; - row-gap: 6px; - align-content: center; -} - -.project-facts div:not(:first-child) { - padding-left: 24px; -} - -.project-facts div:last-child { - border-right: 0; -} - -.project-facts div:hover { - background: linear-gradient(180deg, rgba(88, 166, 255, 0.06) 0%, transparent 100%); -} - -.project-facts span, -.story-number, -.lesson-list span { - display: block; - color: var(--accent); - font: 0.72rem/1 Consolas, "Courier New", monospace; - margin-bottom: 4px; -} - -.project-facts strong { - display: block; - margin: 0; - font-size: 1.12rem; - font-weight: 600; -} - -.project-facts small { - display: block; - grid-column: 2; - color: var(--dim); - font-size: 0.9rem; - line-height: 1.5; -} - -.section-rule { - width: min(calc(100% - 48px), var(--max)); - margin: 0 auto; - padding: 92px 0; - border-bottom: 1px solid var(--line); -} - -.section-heading { - display: grid; - grid-template-columns: 280px 1fr; - gap: 48px; - margin-bottom: 48px; -} - -.section-heading.compact { - margin-bottom: 56px; -} - -.section-heading h2, -.closing h2 { - max-width: 760px; - font-size: clamp(2.5rem, 4.6vw, 4.4rem); - line-height: 1.08; - margin-bottom: 20px; - background: linear-gradient(135deg, #79c0ff 0%, #58a6ff 100%); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; -} - -.section-heading h2 { - margin-top: 0; - margin-bottom: 24px; -} - -.section-heading > div > p { - max-width: 690px; - margin: 32px 0 0; - color: var(--muted); - font-size: 1.1rem; - line-height: 1.7; -} - -.architecture-figure { - padding: 10px; - border: 1px solid var(--line); - background: #0f1419; - box-shadow: 0 8px 32px rgba(88, 166, 255, 0.08); - border-radius: 6px; -} - -.architecture-figure img { - width: 100%; - border-radius: 3px; -} - -.logo-divider { - width: min(calc(100% - 48px), var(--max)); - height: 280px; - margin: 0 auto; - overflow: hidden; - display: grid; - place-items: center; - border-bottom: 1px solid var(--line); - background: - radial-gradient(circle, rgba(88, 166, 255, 0.08), transparent 45%), - #080a0d; -} - -.logo-divider img { - width: 420px; - height: 420px; - object-fit: cover; - object-position: center 28%; - opacity: 0.72; - mix-blend-mode: screen; -} - -.principles { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 1px; - margin-top: 40px; - background: var(--line); -} - -.principles article:hover { - background: linear-gradient(135deg, rgba(88, 166, 255, 0.08) 0%, rgba(63, 185, 80, 0.08) 100%); -} - -.principles article { - min-height: 230px; - padding: 28px; - background: var(--bg); - transition: background 300ms ease; -} - -.principles span { - display: block; - color: var(--accent); - font: 0.78rem Consolas, "Courier New", monospace; - text-transform: uppercase; - letter-spacing: 0.05em; - opacity: 0.9; - margin-bottom: 12px; -} - -.principles h3, -.system-story h3, -.lesson-list h3 { - margin: 40px 0 12px; - font-size: 1.35rem; - font-weight: 580; - letter-spacing: -0.025em; - line-height: 1.2; -} - -.principles p, -.system-story p, -.lesson-list p, -.closing > p:not(.section-index), -footer p { - color: var(--muted); -} - -.principles p { - margin: 0; - font-size: 1rem; -} - -.system-story { - display: grid; - grid-template-columns: 280px minmax(0, 1fr); - gap: 28px 48px; - align-items: start; - padding: 68px 0; - border-top: 1px solid var(--line); -} - -.system-story.reverse { - grid-template-columns: 280px minmax(0, 1fr); -} - -.system-story.reverse .story-copy { - order: initial; -} - -.system-story.reverse .story-images { - order: initial; -} - -.story-copy { - display: grid; - grid-column: 1 / -1; - grid-template-columns: 280px minmax(0, 760px); - column-gap: 48px; -} - -.story-number, -.story-label { - grid-column: 1; -} - -.story-label { - margin: 18px 0 0; +.panel-title small { color: var(--green); - opacity: 0.95; } -.system-story h3 { - grid-column: 2; - grid-row: 1 / span 2; - margin: 0 0 22px; - font-size: clamp(1.8rem, 3vw, 2.75rem); -} - -.system-story p:not(.story-number, .story-label) { - grid-column: 2; +.event-list { margin: 0; - font-size: 1.06rem; -} - -.system-story ul { - grid-column: 2; - display: flex; - flex-wrap: wrap; - gap: 8px 18px; - margin: 28px 0 0; padding: 0; list-style: none; - color: var(--dim); - font: 0.8rem Consolas, "Courier New", monospace; } -.system-story li::before { - content: "+ "; - color: var(--accent); - font-weight: 600; -} - -.story-images { - grid-column: 1 / -1; +.event-list li { display: grid; - grid-template-columns: 1fr; - gap: 64px; - min-width: 0; - align-items: start; + grid-template-columns: 58px 48px 1fr; + gap: 7px; + padding: 13px 0; + border-bottom: 1px dotted var(--line); + font-family: var(--mono); } -.screenshot-exhibit { +.event-list time { + color: var(--dim); + font-size: .55rem; +} + +.event-list li > span { + font-size: .55rem; +} + +.event-ok { color: var(--green); } +.event-info { color: var(--cyan); } +.event-warn { color: var(--amber); } + +.event-list p { margin: 0; - padding-top: 24px; - border-top: 1px solid var(--line); + color: var(--muted); + font-size: .58rem; } -.screenshot-exhibit figcaption { +.deployment-status { + margin-top: 24px; + padding: 16px; + border: 1px solid var(--line); + background: var(--panel); + font-family: var(--mono); +} + +.deployment-status > span { + color: var(--dim); + font-size: .57rem; +} + +.deployment-status strong { + display: block; + margin-top: 8px; + color: var(--green); + font-size: .86rem; +} + +.deployment-status p { + margin: 3px 0 14px; + color: var(--muted); + font-size: .58rem; +} + +.deployment-status div { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 4px; +} + +.deployment-status i { + height: 3px; + background: var(--green); +} + +.terminal-mini { + margin-top: 18px; + padding: 14px; + border: 1px solid var(--line); + background: #050608; + font: .57rem/1.8 var(--mono); +} + +.terminal-mini p { + margin: 0; + color: var(--muted); +} + +.terminal-mini p span { + color: var(--purple); +} + +.terminal-mini .terminal-output { + color: var(--green); +} + +.cursor { + animation: blink .9s steps(1) infinite; +} + +@keyframes blink { 50% { opacity: 0; } } + +.module { + border-inline: 1px solid var(--line); + border-bottom: 1px solid var(--line-strong); + background: rgba(7, 8, 11, .84); +} + +.module-header { + display: grid; + grid-template-columns: 1fr minmax(260px, .75fr) auto; + gap: 40px; + align-items: end; + min-height: 132px; + padding: 28px 30px; + border-bottom: 1px solid var(--line-strong); +} + +.module-id { + color: var(--purple); + font: .61rem var(--mono); + letter-spacing: .12em; +} + +.module h2 { + margin: 7px 0 0; + font-size: clamp(1.8rem, 3vw, 3.3rem); + font-weight: 500; + line-height: 1; + letter-spacing: -.05em; +} + +.module-header > p { + margin: 0; + color: var(--muted); + font-size: .85rem; +} + +.module-state { + gap: 8px; + justify-content: flex-start; + color: var(--green); + white-space: nowrap; +} + +.topology-layout { + display: grid; + grid-template-columns: 260px minmax(0, 1fr); +} + +.stack-index { + padding: 22px; + border-right: 1px solid var(--line); +} + +.stack-index div { + padding: 17px 0; + border-bottom: 1px dotted var(--line); +} + +.stack-index span, +.stack-index small { + display: block; + font-family: var(--mono); +} + +.stack-index span { + color: var(--purple); + font-size: .57rem; +} + +.stack-index strong { + display: block; + margin-top: 4px; + font-size: .76rem; +} + +.stack-index small { + margin-top: 2px; + color: var(--dim); + font-size: .55rem; +} + +.system-map { + margin: 0; + padding: 22px; +} + +.system-map a { + display: block; + border: 1px solid var(--line); + background: #050608; +} + +.system-map img { + width: 100%; +} + +.system-map figcaption, +.evidence figcaption, +.portal-shot figcaption, +.auth-shot figcaption, +.crowdsec-shot figcaption { display: flex; justify-content: space-between; - align-items: baseline; - gap: 24px; - margin-bottom: 16px; + margin-top: 9px; + color: var(--dim); + font: .58rem var(--mono); } -.screenshot-exhibit figcaption span { - font-size: 1.18rem; - font-weight: 600; - color: var(--text); -} - -.screenshot-exhibit figcaption small { - color: var(--muted); - font-size: 0.95rem; -} - -.screenshot-exhibit a { - display: block; -} - -.screenshot-exhibit a:hover img { - box-shadow: 0 8px 24px rgba(88, 166, 255, 0.1); -} - -.story-images img { - width: 100%; - height: auto; - object-fit: contain; - border: 1px solid var(--line); - background: #08090b; - filter: saturate(0.72); - border-radius: 4px; - box-shadow: 0 4px 16px rgba(88, 166, 255, 0.06); - transition: box-shadow 300ms ease; -} - -.story-images .crowdsec-capture { - filter: none; -} - -.lesson-list { - border-top: 1px solid var(--line); -} - -.lesson-list article:hover { - background: rgba(88, 166, 255, 0.05); -} - -.lesson-list article { +.evidence-grid { display: grid; - grid-template-columns: 70px 0.85fr 1fr; - gap: 30px; - align-items: baseline; - padding: 31px 0; - border-bottom: 1px solid var(--line); - transition: background 300ms ease, padding 300ms ease; + grid-template-columns: minmax(0, 1fr) 320px; } -.lesson-list h3, -.lesson-list p { +.evidence { + margin: 0; + padding: 22px; +} + +.evidence figcaption, +.portal-shot figcaption, +.auth-shot figcaption, +.crowdsec-shot figcaption { + margin: 0 0 12px; + align-items: baseline; +} + +.evidence figcaption strong { + margin-right: auto; + margin-left: 18px; + color: var(--text); + font-size: .7rem; +} + +.evidence a, +.portal-shot a, +.auth-shot a, +.crowdsec-shot a, +.pipeline-shots a, +.recovery-layout figure a { + display: block; + overflow: hidden; + border: 1px solid var(--line); + background: #050608; +} + +.evidence img, +.portal-shot img, +.auth-shot img, +.crowdsec-shot img, +.pipeline-shots img, +.recovery-layout img { + width: 100%; + transition: filter 180ms ease, transform 250ms ease; +} + +.evidence a:hover img, +.portal-shot a:hover img, +.auth-shot a:hover img, +.pipeline-shots a:hover img, +.recovery-layout a:hover img { + filter: brightness(1.08); + transform: scale(1.003); +} + +.coverage-matrix { + padding: 22px; + border-left: 1px solid var(--line); +} + +.coverage-matrix ul { + margin: 0; + padding: 0; + list-style: none; +} + +.coverage-matrix li { + display: flex; + justify-content: space-between; + padding: 13px 0; + border-bottom: 1px dotted var(--line); + font-size: .72rem; +} + +.coverage-matrix li i { + color: var(--green); + font: normal .57rem var(--mono); +} + +.stack-list { + display: flex; + flex-wrap: wrap; + gap: 7px; + margin-top: 22px; +} + +.stack-list span { + padding: 6px 8px; + border: 1px solid var(--line); + color: var(--muted); + font: .57rem var(--mono); +} + +.service-layout { + display: grid; + grid-template-columns: 520px minmax(0, 1fr); +} + +.service-table { + border-right: 1px solid var(--line); +} + +.service-row { + display: grid; + grid-template-columns: 1fr 1.2fr .65fr .55fr; + gap: 12px; + align-items: center; + min-height: 53px; + padding: 0 22px; + border-bottom: 1px dotted var(--line); + color: var(--muted); + font-size: .69rem; +} + +.service-head { + min-height: 40px; + color: var(--dim); + background: var(--panel); + font: .56rem var(--mono); + text-transform: uppercase; +} + +.service-row strong { + color: var(--text); + font-weight: 500; +} + +.service-row i { + color: var(--green); + font: normal .55rem var(--mono); +} + +.portal-shot { + margin: 0; + padding: 22px; +} + +.pipeline { + padding: 24px; +} + +.pipeline-flow { + display: grid; + grid-template-columns: repeat(7, auto); + align-items: center; + justify-content: center; + gap: 28px; + padding: 22px; + border: 1px solid var(--line); + background: var(--panel); +} + +.pipeline-flow div { + min-width: 150px; +} + +.pipeline-flow span, +.pipeline-flow strong, +.pipeline-flow small { + display: block; + font-family: var(--mono); +} + +.pipeline-flow span { + color: var(--purple); + font-size: .57rem; +} + +.pipeline-flow strong { + margin-top: 4px; + font-size: .73rem; +} + +.pipeline-flow small { + color: var(--dim); + font-size: .55rem; +} + +.pipeline-flow b { + color: var(--dim); + font: 400 .8rem var(--mono); +} + +.pipeline-shots { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 24px; + margin-top: 24px; +} + +.pipeline-shots figure { margin: 0; } -.lesson-list h3 { - font-size: 1.15rem; +.pipeline-shots figcaption { + margin-bottom: 9px; + color: var(--dim); + font: .58rem var(--mono); } -.lesson-list p { - font-size: 1rem; +.security-layout { + display: grid; + grid-template-columns: minmax(0, 1.5fr) 320px; } -.closing { - width: min(calc(100% - 48px), 820px); - margin: 0 auto; - padding: 130px 0; - text-align: center; - background: linear-gradient(180deg, rgba(88, 166, 255, 0.02) 0%, transparent 100%); +.auth-shot, +.crowdsec-shot { + margin: 0; + padding: 22px; } -.closing h2 { - margin: 0 auto; +.security-data { + border-left: 1px solid var(--line); } -.closing > p:not(.section-index) { - max-width: 650px; - margin: 28px auto 34px; - font-size: 1.06rem; +.security-score { + padding: 24px; + border-bottom: 1px solid var(--line); + background: var(--panel); +} + +.security-score span, +.security-score small { + display: block; + color: var(--dim); + font: .57rem var(--mono); +} + +.security-score strong { + display: block; + margin: 10px 0 4px; + color: var(--green); + font: 500 1.25rem var(--mono); +} + +.security-data ul { + margin: 0; + padding: 0 22px; + list-style: none; +} + +.security-data li { + display: flex; + justify-content: space-between; + padding: 14px 0; + border-bottom: 1px dotted var(--line); + font-size: .68rem; +} + +.security-data li span { + color: var(--muted); +} + +.security-data li strong { + color: var(--text); + font: 500 .57rem var(--mono); +} + +.crowdsec-shot { + grid-column: 1 / -1; + border-top: 1px solid var(--line); +} + +.crowdsec-shot img { + width: 100%; +} + +.recovery-layout { + display: grid; + grid-template-columns: 340px minmax(0, 1fr); +} + +.recovery-sequence { + padding: 22px; + border-right: 1px solid var(--line); +} + +.recovery-sequence div { + display: grid; + grid-template-columns: 34px 1fr; + padding: 18px 0; + border-bottom: 1px dotted var(--line); +} + +.recovery-sequence span { + grid-row: 1 / span 2; + color: var(--purple); + font: .58rem var(--mono); +} + +.recovery-sequence strong { + font-size: .75rem; +} + +.recovery-sequence small { + color: var(--dim); + font: .57rem var(--mono); +} + +.recovery-layout figure { + margin: 0; + padding: 22px; } footer { - width: min(calc(100% - 48px), var(--max)); - margin: 0 auto; - padding: 30px 0 38px; display: grid; grid-template-columns: 1fr auto auto; gap: 32px; align-items: center; - border-top: 1px solid var(--line); - font-size: 0.86rem; + min-height: 90px; + padding: 18px 24px; + border-inline: 1px solid var(--line); + color: var(--dim); + font: .58rem var(--mono); } -footer .brand { - margin: 0; +.footer-mark { + display: flex; + align-items: center; + gap: 12px; } -footer .brand img { - width: 26px; - height: 26px; +.footer-mark img { + width: 38px; + height: 38px; + object-fit: cover; + object-position: 50% 23%; } -footer p { - margin: 0; +.footer-mark strong, +.footer-mark span { + display: block; } -@media (max-width: 900px) { - .hero { - min-height: auto; - grid-template-columns: 1fr; - gap: 34px; - } - - .hero-copy { - max-width: 720px; - } - - .project-facts { - grid-template-columns: repeat(2, 1fr); - } - - .project-facts div:nth-child(2) { - border-right: 0; - } - - .project-facts div:nth-child(-n + 2) { - border-bottom: 1px solid var(--line); - } - - .section-heading { - grid-template-columns: 1fr; - gap: 12px; - } - - .principles { - grid-template-columns: 1fr; - } - - .principles article { - min-height: 0; - } - - .system-story, - .system-story.reverse { - grid-template-columns: 1fr; - gap: 38px; - } - - .system-story.reverse .story-copy, - .system-story.reverse .story-images { - order: initial; - } - - .story-copy { - display: block; - max-width: 650px; - } - - footer { - grid-template-columns: 1fr; - gap: 10px; - } +.footer-mark strong { + color: var(--text); + letter-spacing: .1em; } -@media (max-width: 650px) { - .site-header, - .hero, - .project-facts, - .section-rule, - footer { - width: min(calc(100% - 32px), var(--max)); +.status-text { + color: var(--green); +} + +@media (max-width: 1180px) { + .control-bar { + grid-template-columns: 1fr auto auto; } - .site-header { - height: 66px; - } - - .site-header nav { + .control-bar nav { display: none; } - .header-link { - font-size: 0.78rem; + .command-grid { + grid-template-columns: 160px minmax(0, 1fr); } - .hero { - padding: 26px 0 36px; + .activity-panel { + grid-column: 1 / -1; + display: grid; + grid-template-columns: 1fr 280px 280px; + gap: 20px; + border-top: 1px solid var(--line); + border-left: 0; } - h1 { - font-size: clamp(2.75rem, 14vw, 4rem); + .panel-title, + .event-list { + grid-column: 1; } - .hero-intro { - font-size: 1rem; + .deployment-status { + grid-column: 2; + grid-row: 1 / span 2; + margin-top: 0; } - .actions { - align-items: flex-start; - flex-direction: column; + .terminal-mini { + grid-column: 3; + grid-row: 1 / span 2; + margin-top: 0; } - .hero-visual { - padding: 6px; + .metric-board { + grid-template-columns: repeat(3, 1fr); } - .hero-visual::before { + .service-layout, + .security-layout { + grid-template-columns: 1fr; + } + + .service-table, + .security-data { + border-right: 0; + border-left: 0; + border-bottom: 1px solid var(--line); + } +} + +@media (max-width: 820px) { + .control-bar { + grid-template-columns: 1fr auto; + } + + .control-state { display: none; } - .hero-visual figcaption { - display: block; - } - - .hero-visual figcaption span { - display: block; - } - - .project-facts { + .command-grid { grid-template-columns: 1fr; } - .project-facts div, - .project-facts div:not(:first-child) { - min-height: 0; - padding: 20px 0; - border-right: 0; - border-bottom: 1px solid var(--line); + .system-rail { + display: none; } - .project-facts div:last-child { - border-bottom: 0; - } - - .section-rule { - padding: 82px 0; - } - - .section-heading, - .section-heading.compact { - margin-bottom: 48px; - } - - .section-heading h2, - .closing h2 { - font-size: 2.55rem; - } - - .architecture-figure { - padding: 5px; - overflow-x: auto; - } - - .architecture-figure img { - min-width: 780px; - } - - .principles { - margin-top: 38px; - } - - .logo-divider { - width: calc(100% - 32px); - height: 210px; - } - - .logo-divider img { - width: 300px; - height: 300px; - } - - .system-story { - padding: 54px 0; - } - - .story-images { + .identity-block, + .module-header, + .topology-layout, + .evidence-grid, + .recovery-layout { grid-template-columns: 1fr; - gap: 44px; } - .story-images img { - height: auto; + .identity-block { + gap: 20px; } - .screenshot-exhibit figcaption { - display: block; + .operator-note { + max-width: 620px; } - .screenshot-exhibit figcaption small { - display: block; + .module-header { + gap: 16px; + align-items: start; + } + + .module-state { margin-top: 4px; } - .lesson-list article { - grid-template-columns: 40px 1fr; - gap: 14px; + .stack-index, + .coverage-matrix, + .recovery-sequence { + border-right: 0; + border-left: 0; + border-bottom: 1px solid var(--line); } - .lesson-list p { - grid-column: 2; + .pipeline-flow { + grid-template-columns: 1fr; + justify-content: stretch; } - .closing { - width: calc(100% - 32px); - padding: 90px 0; + .pipeline-flow b { + transform: rotate(90deg); + justify-self: center; + } + + .pipeline-shots { + grid-template-columns: 1fr; + } + + .activity-panel { + grid-template-columns: 1fr 1fr; + } + + .terminal-mini { + display: none; + } + + footer { + grid-template-columns: 1fr; + gap: 8px; + } +} + +@media (max-width: 560px) { + body { + font-size: 14px; + } + + .control-bar { + height: 56px; + } + + .wordmark, + .clock { + padding-inline: 12px; + } + + .wordmark small { + display: none; + } + + .clock { + min-width: 130px; + } + + .overview-console { + padding: 16px 12px; + } + + .identity-block { + padding: 26px 0 22px; + } + + h1 { + font-size: 2.7rem; + } + + .metric-board { + grid-template-columns: 1fr 1fr; + } + + .metric { + min-height: 112px; + } + + .activity-panel { + grid-template-columns: 1fr; + padding: 18px 12px; + } + + .deployment-status { + grid-column: 1; + grid-row: auto; + } + + .module-header, + .system-map, + .evidence, + .coverage-matrix, + .portal-shot, + .pipeline, + .auth-shot, + .crowdsec-shot, + .recovery-sequence, + .recovery-layout figure { + padding: 18px 12px; + } + + .module-header { + min-height: 0; + } + + .service-row { + grid-template-columns: 1fr 1fr auto; + padding: 0 12px; + } + + .service-row span:nth-child(3), + .service-head span:nth-child(3) { + display: none; + } + + .system-map { + overflow-x: auto; + } + + .system-map a { + min-width: 740px; + } + + .evidence figcaption, + .portal-shot figcaption, + .auth-shot figcaption, + .crowdsec-shot figcaption, + .system-map figcaption { + display: block; + } + + .evidence figcaption strong { + display: block; + margin: 4px 0; + } + + footer { + padding-inline: 12px; + } +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + scroll-behavior: auto !important; + animation-duration: .01ms !important; + animation-iteration-count: 1 !important; } }