initial landing scaffold (hyperhive/website MVP)
Tracks hyperhive#502 — landing-only first cut. Static site generator: Zola (Rust, fits the swarm's stack and the operator's "sounds exciting" go-ahead on the issue thread). ## Structure - `flake.nix` — `nix build .#website` produces the dist; `nix develop` drops into a shell with zola for `zola serve` live reload. No CI runner; the flake is the validation contract. - `config.toml` — Zola config; base URL `hyperhive.darkest.space` per #502. Single-page landing — feeds / search index off. - `content/_index.md` — landing copy. Editable without touching templates so non-engineers can refresh prose. - `templates/base.html` + `templates/index.html` — base layout + landing-specific extension. og:tags + favicon wired through. - `sass/main.scss` — theme. Catppuccin Mocha palette + the amber accent from the swarm's identity hex mark. Self-contained (no @import) so the file is reviewable in one place. - `static/{favicon,hex-mark,hyperhive}.svg` — copies of the dashboard's `branding/hyperhive.svg` (hex motif). Used as favicon, hero inline, and og:image respectively. ## Theme Monospace identity throughout — matches dashboard / agent terminals so the website reads as part of the same family rather than a separate marketing artifact. Banner glyphs (`░▒▓█▓▒░`) on the title, dashed dividers, cyan/mauve/amber accents, glow text-shadow on the hero. Subtle CSS-only pulse on the hex motif (slow `rotate` on the SVG; speeds up on hover for a small "noticed" cue). ## Three-column "what's inside" `the swarm` / `the dashboard` / `the boundary` — quick orientation for visitors who clicked through from a link without context. Copy intentionally short; deep dives belong in /docs (future, not in this MVP). ## Scope drop Per mara on #502: - no nav / blog / docs yet — landing only - no screenshots in MVP, follow via issues in this repo - public visibility ## Provenance Scaffolded under `iris/website` because my agent forge token doesn't carry org-admin to create repos under `hyperhive/`. Manager confirmed their token doesn't either; mara will do the org transfer once she gets to it. README documents this.
This commit is contained in:
parent
b1dd949291
commit
d3a55c5631
12 changed files with 873 additions and 2 deletions
12
.gitignore
vendored
Normal file
12
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Zola build output
|
||||||
|
public/
|
||||||
|
|
||||||
|
# nix
|
||||||
|
result
|
||||||
|
result-*
|
||||||
|
|
||||||
|
# editor / OS
|
||||||
|
.direnv/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
.DS_Store
|
||||||
57
README.md
57
README.md
|
|
@ -1,3 +1,56 @@
|
||||||
# website
|
# hyperhive website
|
||||||
|
|
||||||
hyperhive marketing landing — Zola static site, Catppuccin-themed (will transfer to hyperhive/website per #502)
|
Marketing landing for hyperhive, deployed at
|
||||||
|
[hyperhive.darkest.space](https://hyperhive.darkest.space). Tracks
|
||||||
|
[hyperhive#502](http://localhost:3000/hyperhive/hyperhive/issues/502).
|
||||||
|
|
||||||
|
Built with [Zola](https://www.getzola.org/), the Rust static site
|
||||||
|
generator. Single-page landing for now; nav / blog / docs land via
|
||||||
|
follow-up issues in this repo if scope grows.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# one-shot build to ./public
|
||||||
|
nix build .#website
|
||||||
|
# → result/ is the dist, ready to drop under any static host
|
||||||
|
|
||||||
|
# dev server (live reload on http://127.0.0.1:1111/)
|
||||||
|
nix develop
|
||||||
|
zola serve
|
||||||
|
```
|
||||||
|
|
||||||
|
## Layout
|
||||||
|
|
||||||
|
```
|
||||||
|
config.toml # zola config (single source of truth for site meta)
|
||||||
|
content/_index.md # landing page copy — edit here for prose changes
|
||||||
|
templates/
|
||||||
|
base.html # base layout (head, footer, og tags)
|
||||||
|
index.html # landing template extending base
|
||||||
|
sass/
|
||||||
|
main.scss # theme — Catppuccin Mocha + amber accent
|
||||||
|
static/
|
||||||
|
favicon.svg # hyperhive hex motif (copy of dashboard branding)
|
||||||
|
hex-mark.svg # same SVG, used inline in the hero
|
||||||
|
hyperhive.svg # og:image
|
||||||
|
flake.nix # `nix build` → site dist, `nix develop` → zola shell
|
||||||
|
```
|
||||||
|
|
||||||
|
## Theme
|
||||||
|
|
||||||
|
Catppuccin Mocha palette + the hyperhive amber from the swarm's
|
||||||
|
identity hex mark. Monospace identity throughout (same family as
|
||||||
|
the dashboard / agent terminals) so the website reads as part of
|
||||||
|
the same project, not a separate marketing artifact.
|
||||||
|
|
||||||
|
Theme variables live in `sass/main.scss` (single source of truth).
|
||||||
|
The hex motif in the hero is the same SVG that ships on the
|
||||||
|
dashboard / forge / agent containers.
|
||||||
|
|
||||||
|
## Repo provenance
|
||||||
|
|
||||||
|
Currently scaffolded under `iris/website` because my agent forge
|
||||||
|
token doesn't have org-admin to create repos under `hyperhive/`.
|
||||||
|
Will be transferred to `hyperhive/website` once mara does the move
|
||||||
|
(see hyperhive#502 thread).
|
||||||
|
|
|
||||||
34
config.toml
Normal file
34
config.toml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
# Zola config — hyperhive marketing landing (#502).
|
||||||
|
#
|
||||||
|
# Single-page landing for now; nav / blog / docs come later if scope grows.
|
||||||
|
# Theme lives in `sass/main.scss` and `templates/`; no external Zola theme
|
||||||
|
# import — the project's identity matches the dashboard / agent terminals
|
||||||
|
# closely enough that pulling in a third-party theme would just give us
|
||||||
|
# something to fight.
|
||||||
|
|
||||||
|
base_url = "https://hyperhive.darkest.space"
|
||||||
|
title = "hyperhive"
|
||||||
|
description = "a swarm of claude agents in nspawn containers, with an operator-shaped trust boundary."
|
||||||
|
|
||||||
|
# We don't need RSS / search / sitemaps for a single-page landing. Can
|
||||||
|
# flip these on later if blog content lands.
|
||||||
|
generate_feeds = false
|
||||||
|
build_search_index = false
|
||||||
|
|
||||||
|
# Embed the SCSS pipeline; zola compiles `sass/*.scss` → `public/*.css`.
|
||||||
|
compile_sass = true
|
||||||
|
|
||||||
|
# Markdown rendering defaults — landing has very little prose so the
|
||||||
|
# fancier syntax-highlight setup isn't needed yet. Easy to turn on later.
|
||||||
|
[markdown]
|
||||||
|
highlight_code = false
|
||||||
|
smart_punctuation = true
|
||||||
|
|
||||||
|
[extra]
|
||||||
|
# Catppuccin Mocha palette + amber accent (matching the hex mark) is
|
||||||
|
# the project's identity. Single source of truth — `main.scss` reads
|
||||||
|
# these via Sass variables, not from this attrset (Zola doesn't pipe
|
||||||
|
# extras into Sass). Keeping them here as documentation only so the
|
||||||
|
# theme intent is reviewable in one place.
|
||||||
|
palette = "catppuccin-mocha"
|
||||||
|
accent = "amber"
|
||||||
9
content/_index.md
Normal file
9
content/_index.md
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
+++
|
||||||
|
title = "hyperhive"
|
||||||
|
+++
|
||||||
|
|
||||||
|
A swarm of Claude agents running in nspawn containers, gated by an
|
||||||
|
operator-shaped trust boundary. Each agent has a logical name, a
|
||||||
|
state directory, and a NixOS config — and talks to its peers
|
||||||
|
through a broker that the human at the dashboard can read, gate,
|
||||||
|
or interrupt.
|
||||||
61
flake.lock
generated
Normal file
61
flake.lock
generated
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731533236,
|
||||||
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1779560665,
|
||||||
|
"narHash": "sha256-tpyBcxPpcQb8ukyNF7DoCwfSY3VPsxHoYwj00Cayv5o=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "64c08a7ca051951c8eae34e3e3cb1e202fe36786",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
64
flake.nix
Normal file
64
flake.nix
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
{
|
||||||
|
# hyperhive marketing landing — Zola static site build (#502).
|
||||||
|
#
|
||||||
|
# `nix build` → `result/` is the `public/` Zola dist, ready to drop
|
||||||
|
# under any static-file host. No CI runner needed; the flake is the
|
||||||
|
# validation contract.
|
||||||
|
description = "hyperhive marketing landing";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, flake-utils }:
|
||||||
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
in {
|
||||||
|
packages.website = pkgs.stdenv.mkDerivation {
|
||||||
|
pname = "hyperhive-website";
|
||||||
|
version = self.shortRev or "dev";
|
||||||
|
|
||||||
|
src = ./.;
|
||||||
|
|
||||||
|
nativeBuildInputs = [ pkgs.zola ];
|
||||||
|
|
||||||
|
# Zola reads `config.toml` from CWD, writes `public/` next to it,
|
||||||
|
# which we then move to $out. The build is offline / hermetic —
|
||||||
|
# no network access needed at build time, which fits the nix
|
||||||
|
# sandbox without extra fetchurls.
|
||||||
|
buildPhase = ''
|
||||||
|
runHook preBuild
|
||||||
|
zola build --output-dir public
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
mkdir -p $out
|
||||||
|
cp -r public/. $out/
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Static-site dist; no shared libs to patchelf, no executables.
|
||||||
|
dontFixup = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# `nix build` with no attribute → the website dist.
|
||||||
|
packages.default = self.packages.${system}.website;
|
||||||
|
|
||||||
|
# `nix develop` → a shell with zola for local iteration:
|
||||||
|
# `zola serve` runs the dev server with live reload.
|
||||||
|
devShells.default = pkgs.mkShell {
|
||||||
|
packages = [ pkgs.zola ];
|
||||||
|
};
|
||||||
|
|
||||||
|
# `nix run` is the dev-server shortcut: `nix run . -- serve`
|
||||||
|
# boots Zola's hot-reload server on http://127.0.0.1:1111/.
|
||||||
|
apps.default = {
|
||||||
|
type = "app";
|
||||||
|
program = "${pkgs.zola}/bin/zola";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
249
sass/main.scss
Normal file
249
sass/main.scss
Normal file
|
|
@ -0,0 +1,249 @@
|
||||||
|
// hyperhive marketing landing — theme (#502).
|
||||||
|
//
|
||||||
|
// Matches the dashboard / agent terminals visually so the website
|
||||||
|
// reads as part of the same family: Catppuccin Mocha palette + amber
|
||||||
|
// accent (matching the hex mark), banner-thin block-glyph headings,
|
||||||
|
// dashed dividers, glow text-shadow on titles.
|
||||||
|
//
|
||||||
|
// Single-file SCSS — landing is small enough that splitting into
|
||||||
|
// partials would be premature. Re-evaluate if /docs or /blog land.
|
||||||
|
|
||||||
|
// ─── palette ───────────────────────────────────────────────────────
|
||||||
|
// Catppuccin Mocha + the hyperhive amber from branding/hyperhive.svg.
|
||||||
|
// Copying them in (not importing) so this file stays self-contained.
|
||||||
|
|
||||||
|
$base: #1e1e2e;
|
||||||
|
$mantle: #181825;
|
||||||
|
$crust: #11111b;
|
||||||
|
|
||||||
|
$text: #cdd6f4;
|
||||||
|
$subtext1: #bac2de;
|
||||||
|
$subtext0: #a6adc8;
|
||||||
|
$overlay2: #9399b2;
|
||||||
|
$overlay1: #7f849c;
|
||||||
|
$overlay0: #6c7086;
|
||||||
|
$surface2: #585b70;
|
||||||
|
$surface1: #45475a;
|
||||||
|
$surface0: #313244;
|
||||||
|
|
||||||
|
$rosewater: #f5e0dc;
|
||||||
|
$flamingo: #f2cdcd;
|
||||||
|
$pink: #f5c2e7;
|
||||||
|
$mauve: #cba6f7;
|
||||||
|
$red: #f38ba8;
|
||||||
|
$maroon: #eba0ac;
|
||||||
|
$peach: #fab387;
|
||||||
|
$yellow: #f9e2af;
|
||||||
|
$green: #a6e3a1;
|
||||||
|
$teal: #94e2d5;
|
||||||
|
$sky: #89dceb;
|
||||||
|
$sapphire: #74c7ec;
|
||||||
|
$blue: #89b4fa;
|
||||||
|
$lavender: #b4befe;
|
||||||
|
|
||||||
|
// The hex-mark amber. Pure swarm identity colour.
|
||||||
|
$amber: #ffb300;
|
||||||
|
$amber-deep: #ff8f00;
|
||||||
|
$amber-glow: rgba(255, 179, 0, 0.45);
|
||||||
|
|
||||||
|
// ─── globals ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
* { box-sizing: border-box; }
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: $base;
|
||||||
|
color: $text;
|
||||||
|
// Same font stack as the dashboard's @hive/shared base.css —
|
||||||
|
// monospace identity reads as "this is the terminal swarm" instead
|
||||||
|
// of "this is a marketing site". Body copy stays readable at this
|
||||||
|
// weight because the lines are short.
|
||||||
|
font-family: ui-monospace, "JetBrains Mono", "Fira Code",
|
||||||
|
Menlo, Consolas, monospace;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.55;
|
||||||
|
// Subtle background grid — same idea as the hex-mark's faint
|
||||||
|
// horizontal lines, but at body scope. Cheaper than a full SVG
|
||||||
|
// background.
|
||||||
|
background-image:
|
||||||
|
repeating-linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
transparent 0,
|
||||||
|
transparent 23px,
|
||||||
|
rgba(255, 179, 0, 0.025) 23px,
|
||||||
|
rgba(255, 179, 0, 0.025) 24px
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $sky;
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: 1px dashed transparent;
|
||||||
|
transition: border-color 0.15s, color 0.15s;
|
||||||
|
}
|
||||||
|
a:hover { color: $sapphire; border-bottom-color: $sapphire; }
|
||||||
|
|
||||||
|
::selection { background: $amber-glow; color: $crust; }
|
||||||
|
|
||||||
|
// ─── layout ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
.shell {
|
||||||
|
max-width: 920px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 4rem 1.5rem 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── hero ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(180px, 280px) 1fr;
|
||||||
|
gap: 2rem;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 2rem;
|
||||||
|
border-bottom: 1px dashed $surface1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
.hero { grid-template-columns: 1fr; text-align: center; }
|
||||||
|
.hero-art { max-width: 220px; margin: 0 auto; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-art svg {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
// Subtle pulse — only the outer ring + dashed orbit rotate. Quiet
|
||||||
|
// enough to read as "active" instead of "noisy".
|
||||||
|
animation: hex-orbit 24s linear infinite;
|
||||||
|
}
|
||||||
|
.hero-art:hover svg {
|
||||||
|
// Speed up on hover for a tiny "you got noticed" cue. No JS needed.
|
||||||
|
animation-duration: 8s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes hex-orbit {
|
||||||
|
from { transform: rotate(0deg); }
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-text h1 {
|
||||||
|
margin: 0 0 0.6rem;
|
||||||
|
font-size: 2.4rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
color: $amber;
|
||||||
|
text-shadow:
|
||||||
|
0 0 4px $amber-glow,
|
||||||
|
0 0 12px rgba(255, 143, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-glyph {
|
||||||
|
color: $amber-deep;
|
||||||
|
opacity: 0.65;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-tagline {
|
||||||
|
margin: 0 0 1.6rem;
|
||||||
|
font-size: 1.05rem;
|
||||||
|
color: $subtext1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-cta { margin: 0; }
|
||||||
|
|
||||||
|
.cta-primary {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
border: 1px solid $amber;
|
||||||
|
color: $amber;
|
||||||
|
border-bottom-color: $amber;
|
||||||
|
text-shadow: 0 0 6px $amber-glow;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
transition: box-shadow 0.15s ease, color 0.15s, border-color 0.15s;
|
||||||
|
}
|
||||||
|
.cta-primary:hover {
|
||||||
|
color: $base;
|
||||||
|
background: $amber;
|
||||||
|
border-color: $amber;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
box-shadow: 0 0 14px -2px $amber-glow;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── prose ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
.prose {
|
||||||
|
padding: 2rem 0;
|
||||||
|
color: $text;
|
||||||
|
max-width: 64ch;
|
||||||
|
font-size: 1.02rem;
|
||||||
|
}
|
||||||
|
.prose p { margin: 0 0 1rem; }
|
||||||
|
|
||||||
|
// ─── three-column grid ────────────────────────────────────────────
|
||||||
|
|
||||||
|
.grid-3 {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 2rem 0;
|
||||||
|
border-top: 1px dashed $surface1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 760px) {
|
||||||
|
.grid-3 { grid-template-columns: 1fr; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
padding: 1rem 1.2rem;
|
||||||
|
background: $mantle;
|
||||||
|
border: 1px solid $surface0;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: border-color 0.15s, box-shadow 0.15s;
|
||||||
|
}
|
||||||
|
.card:hover {
|
||||||
|
border-color: $amber;
|
||||||
|
box-shadow: 0 0 14px -6px $amber-glow;
|
||||||
|
}
|
||||||
|
.card h2 {
|
||||||
|
margin: 0 0 0.6rem;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
color: $mauve;
|
||||||
|
}
|
||||||
|
.card-glyph { color: $amber; margin-right: 0.4em; }
|
||||||
|
.card p {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.92rem;
|
||||||
|
color: $subtext1;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── footer ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
.site-footer {
|
||||||
|
max-width: 920px;
|
||||||
|
margin: 3rem auto 1.5rem;
|
||||||
|
padding: 1.5rem 1.5rem 0;
|
||||||
|
text-align: center;
|
||||||
|
border-top: 1px dashed $surface1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-thin {
|
||||||
|
margin: 1.5rem 0 0.5rem;
|
||||||
|
color: $amber-deep;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
letter-spacing: 0.18em;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-links {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.88rem;
|
||||||
|
color: $subtext0;
|
||||||
|
}
|
||||||
|
.footer-links .sep { margin: 0 0.4em; opacity: 0.5; }
|
||||||
97
static/favicon.svg
Normal file
97
static/favicon.svg
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
<svg width="300" height="300" viewBox="0 0 300 300" role="img" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<title>HyperHive</title>
|
||||||
|
<desc>HyperHive icon — hexagonal hive, amber on dark</desc>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clipH"><circle cx="150" cy="150" r="140"/></clipPath>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<g clip-path="url(#clipH)">
|
||||||
|
<rect x="0" y="0" width="300" height="300" fill="#0a0600"/>
|
||||||
|
<g stroke="#ffb300" stroke-width="0.35" opacity="0.07">
|
||||||
|
<line x1="0" x2="300" y1="10" y2="10"/> <line x1="0" x2="300" y1="20" y2="20"/>
|
||||||
|
<line x1="0" x2="300" y1="30" y2="30"/> <line x1="0" x2="300" y1="40" y2="40"/>
|
||||||
|
<line x1="0" x2="300" y1="50" y2="50"/> <line x1="0" x2="300" y1="60" y2="60"/>
|
||||||
|
<line x1="0" x2="300" y1="70" y2="70"/> <line x1="0" x2="300" y1="80" y2="80"/>
|
||||||
|
<line x1="0" x2="300" y1="90" y2="90"/> <line x1="0" x2="300" y1="100" y2="100"/>
|
||||||
|
<line x1="0" x2="300" y1="110" y2="110"/> <line x1="0" x2="300" y1="120" y2="120"/>
|
||||||
|
<line x1="0" x2="300" y1="130" y2="130"/> <line x1="0" x2="300" y1="140" y2="140"/>
|
||||||
|
<line x1="0" x2="300" y1="150" y2="150"/> <line x1="0" x2="300" y1="160" y2="160"/>
|
||||||
|
<line x1="0" x2="300" y1="170" y2="170"/> <line x1="0" x2="300" y1="180" y2="180"/>
|
||||||
|
<line x1="0" x2="300" y1="190" y2="190"/> <line x1="0" x2="300" y1="200" y2="200"/>
|
||||||
|
<line x1="0" x2="300" y1="210" y2="210"/> <line x1="0" x2="300" y1="220" y2="220"/>
|
||||||
|
<line x1="0" x2="300" y1="230" y2="230"/> <line x1="0" x2="300" y1="240" y2="240"/>
|
||||||
|
<line x1="0" x2="300" y1="250" y2="250"/> <line x1="0" x2="300" y1="260" y2="260"/>
|
||||||
|
<line x1="0" x2="300" y1="270" y2="270"/> <line x1="0" x2="300" y1="280" y2="280"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<circle cx="150" cy="150" r="118" fill="none" stroke="#ffb300" stroke-width="1" opacity="0.4"/>
|
||||||
|
<circle cx="150" cy="150" r="104" fill="none" stroke="#ff8f00" stroke-width="0.5" opacity="0.25" stroke-dasharray="4 6"/>
|
||||||
|
|
||||||
|
<!-- RING 2 — 6 between-axis hexes, centered on (150,150) instead of (170,170) -->
|
||||||
|
<g fill="#0e0800" stroke="#ffb300" stroke-width="0.7" opacity="0.4">
|
||||||
|
<polygon points="254,105 241,127.5 215,127.5 202,105 215,82.5 241,82.5"/>
|
||||||
|
<polygon points="98,105 85,127.5 59,127.5 46,105 59,82.5 85,82.5"/>
|
||||||
|
<polygon points="176,60 163,82.5 137,82.5 124,60 137,37.5 163,37.5"/>
|
||||||
|
<polygon points="254,195 241,217.5 215,217.5 202,195 215,172.5 241,172.5"/>
|
||||||
|
<polygon points="98,195 85,217.5 59,217.5 46,195 59,172.5 85,172.5"/>
|
||||||
|
<polygon points="176,240 163,262.5 137,262.5 124,240 137,217.5 163,217.5"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- RING 1 — 6 hexes -->
|
||||||
|
<g fill="#150c00" stroke="#ffb300" stroke-width="1.2" opacity="0.8">
|
||||||
|
<polygon points="228,150 215,172.5 189,172.5 176,150 189,127.5 215,127.5"/>
|
||||||
|
<polygon points="202,105 189,127.5 163,127.5 150,105 163,82.5 189,82.5"/>
|
||||||
|
<polygon points="150,105 137,127.5 111,127.5 98,105 111,82.5 137,82.5"/>
|
||||||
|
<polygon points="124,150 111,172.5 85,172.5 72,150 85,127.5 111,127.5"/>
|
||||||
|
<polygon points="150,195 137,217.5 111,217.5 98,195 111,172.5 137,172.5"/>
|
||||||
|
<polygon points="202,195 189,217.5 163,217.5 150,195 163,172.5 189,172.5"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- CENTER hex -->
|
||||||
|
<polygon points="176,150 163,172.5 137,172.5 124,150 137,127.5 163,127.5"
|
||||||
|
fill="#1a0f00" stroke="#ffb300" stroke-width="1.8"/>
|
||||||
|
|
||||||
|
<!-- connections -->
|
||||||
|
<g stroke="#ffb300" stroke-width="1" opacity="0.6">
|
||||||
|
<line x1="176" y1="150" x2="202" y2="150"/>
|
||||||
|
<line x1="124" y1="150" x2="98" y2="150"/>
|
||||||
|
<line x1="163" y1="128" x2="176" y2="105"/>
|
||||||
|
<line x1="137" y1="128" x2="124" y2="105"/>
|
||||||
|
<line x1="163" y1="173" x2="176" y2="195"/>
|
||||||
|
<line x1="137" y1="173" x2="124" y2="195"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- CENTER node -->
|
||||||
|
<circle cx="150" cy="150" r="10" fill="#ffb300" opacity="0.95"/>
|
||||||
|
<circle cx="150" cy="150" r="5" fill="#0a0600"/>
|
||||||
|
|
||||||
|
<!-- ring 1 nodes -->
|
||||||
|
<g fill="#ff8f00" opacity="0.9">
|
||||||
|
<circle cx="202" cy="150" r="6"/>
|
||||||
|
<circle cx="176" cy="105" r="6"/>
|
||||||
|
<circle cx="124" cy="105" r="6"/>
|
||||||
|
<circle cx="98" cy="150" r="6"/>
|
||||||
|
<circle cx="124" cy="195" r="6"/>
|
||||||
|
<circle cx="176" cy="195" r="6"/>
|
||||||
|
</g>
|
||||||
|
<g fill="#0a0600">
|
||||||
|
<circle cx="202" cy="150" r="2.5"/>
|
||||||
|
<circle cx="176" cy="105" r="2.5"/>
|
||||||
|
<circle cx="124" cy="105" r="2.5"/>
|
||||||
|
<circle cx="98" cy="150" r="2.5"/>
|
||||||
|
<circle cx="124" cy="195" r="2.5"/>
|
||||||
|
<circle cx="176" cy="195" r="2.5"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<rect x="0" y="143" width="300" height="2" fill="#ffb300" opacity="0.07"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<circle cx="150" cy="150" r="140" fill="none" stroke="#ffb300" stroke-width="2.5"/>
|
||||||
|
<circle cx="150" cy="150" r="145" fill="none" stroke="#ff8f00" stroke-width="0.5" opacity="0.4" stroke-dasharray="8 4"/>
|
||||||
|
<g stroke="#ffb300" stroke-width="1.5" fill="none" opacity="0.8">
|
||||||
|
<path d="M44,44 L20,44 L20,70"/>
|
||||||
|
<path d="M256,44 L280,44 L280,70"/>
|
||||||
|
<path d="M44,256 L20,256 L20,230"/>
|
||||||
|
<path d="M256,256 L280,256 L280,230"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.9 KiB |
97
static/hex-mark.svg
Normal file
97
static/hex-mark.svg
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
<svg width="300" height="300" viewBox="0 0 300 300" role="img" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<title>HyperHive</title>
|
||||||
|
<desc>HyperHive icon — hexagonal hive, amber on dark</desc>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clipH"><circle cx="150" cy="150" r="140"/></clipPath>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<g clip-path="url(#clipH)">
|
||||||
|
<rect x="0" y="0" width="300" height="300" fill="#0a0600"/>
|
||||||
|
<g stroke="#ffb300" stroke-width="0.35" opacity="0.07">
|
||||||
|
<line x1="0" x2="300" y1="10" y2="10"/> <line x1="0" x2="300" y1="20" y2="20"/>
|
||||||
|
<line x1="0" x2="300" y1="30" y2="30"/> <line x1="0" x2="300" y1="40" y2="40"/>
|
||||||
|
<line x1="0" x2="300" y1="50" y2="50"/> <line x1="0" x2="300" y1="60" y2="60"/>
|
||||||
|
<line x1="0" x2="300" y1="70" y2="70"/> <line x1="0" x2="300" y1="80" y2="80"/>
|
||||||
|
<line x1="0" x2="300" y1="90" y2="90"/> <line x1="0" x2="300" y1="100" y2="100"/>
|
||||||
|
<line x1="0" x2="300" y1="110" y2="110"/> <line x1="0" x2="300" y1="120" y2="120"/>
|
||||||
|
<line x1="0" x2="300" y1="130" y2="130"/> <line x1="0" x2="300" y1="140" y2="140"/>
|
||||||
|
<line x1="0" x2="300" y1="150" y2="150"/> <line x1="0" x2="300" y1="160" y2="160"/>
|
||||||
|
<line x1="0" x2="300" y1="170" y2="170"/> <line x1="0" x2="300" y1="180" y2="180"/>
|
||||||
|
<line x1="0" x2="300" y1="190" y2="190"/> <line x1="0" x2="300" y1="200" y2="200"/>
|
||||||
|
<line x1="0" x2="300" y1="210" y2="210"/> <line x1="0" x2="300" y1="220" y2="220"/>
|
||||||
|
<line x1="0" x2="300" y1="230" y2="230"/> <line x1="0" x2="300" y1="240" y2="240"/>
|
||||||
|
<line x1="0" x2="300" y1="250" y2="250"/> <line x1="0" x2="300" y1="260" y2="260"/>
|
||||||
|
<line x1="0" x2="300" y1="270" y2="270"/> <line x1="0" x2="300" y1="280" y2="280"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<circle cx="150" cy="150" r="118" fill="none" stroke="#ffb300" stroke-width="1" opacity="0.4"/>
|
||||||
|
<circle cx="150" cy="150" r="104" fill="none" stroke="#ff8f00" stroke-width="0.5" opacity="0.25" stroke-dasharray="4 6"/>
|
||||||
|
|
||||||
|
<!-- RING 2 — 6 between-axis hexes, centered on (150,150) instead of (170,170) -->
|
||||||
|
<g fill="#0e0800" stroke="#ffb300" stroke-width="0.7" opacity="0.4">
|
||||||
|
<polygon points="254,105 241,127.5 215,127.5 202,105 215,82.5 241,82.5"/>
|
||||||
|
<polygon points="98,105 85,127.5 59,127.5 46,105 59,82.5 85,82.5"/>
|
||||||
|
<polygon points="176,60 163,82.5 137,82.5 124,60 137,37.5 163,37.5"/>
|
||||||
|
<polygon points="254,195 241,217.5 215,217.5 202,195 215,172.5 241,172.5"/>
|
||||||
|
<polygon points="98,195 85,217.5 59,217.5 46,195 59,172.5 85,172.5"/>
|
||||||
|
<polygon points="176,240 163,262.5 137,262.5 124,240 137,217.5 163,217.5"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- RING 1 — 6 hexes -->
|
||||||
|
<g fill="#150c00" stroke="#ffb300" stroke-width="1.2" opacity="0.8">
|
||||||
|
<polygon points="228,150 215,172.5 189,172.5 176,150 189,127.5 215,127.5"/>
|
||||||
|
<polygon points="202,105 189,127.5 163,127.5 150,105 163,82.5 189,82.5"/>
|
||||||
|
<polygon points="150,105 137,127.5 111,127.5 98,105 111,82.5 137,82.5"/>
|
||||||
|
<polygon points="124,150 111,172.5 85,172.5 72,150 85,127.5 111,127.5"/>
|
||||||
|
<polygon points="150,195 137,217.5 111,217.5 98,195 111,172.5 137,172.5"/>
|
||||||
|
<polygon points="202,195 189,217.5 163,217.5 150,195 163,172.5 189,172.5"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- CENTER hex -->
|
||||||
|
<polygon points="176,150 163,172.5 137,172.5 124,150 137,127.5 163,127.5"
|
||||||
|
fill="#1a0f00" stroke="#ffb300" stroke-width="1.8"/>
|
||||||
|
|
||||||
|
<!-- connections -->
|
||||||
|
<g stroke="#ffb300" stroke-width="1" opacity="0.6">
|
||||||
|
<line x1="176" y1="150" x2="202" y2="150"/>
|
||||||
|
<line x1="124" y1="150" x2="98" y2="150"/>
|
||||||
|
<line x1="163" y1="128" x2="176" y2="105"/>
|
||||||
|
<line x1="137" y1="128" x2="124" y2="105"/>
|
||||||
|
<line x1="163" y1="173" x2="176" y2="195"/>
|
||||||
|
<line x1="137" y1="173" x2="124" y2="195"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- CENTER node -->
|
||||||
|
<circle cx="150" cy="150" r="10" fill="#ffb300" opacity="0.95"/>
|
||||||
|
<circle cx="150" cy="150" r="5" fill="#0a0600"/>
|
||||||
|
|
||||||
|
<!-- ring 1 nodes -->
|
||||||
|
<g fill="#ff8f00" opacity="0.9">
|
||||||
|
<circle cx="202" cy="150" r="6"/>
|
||||||
|
<circle cx="176" cy="105" r="6"/>
|
||||||
|
<circle cx="124" cy="105" r="6"/>
|
||||||
|
<circle cx="98" cy="150" r="6"/>
|
||||||
|
<circle cx="124" cy="195" r="6"/>
|
||||||
|
<circle cx="176" cy="195" r="6"/>
|
||||||
|
</g>
|
||||||
|
<g fill="#0a0600">
|
||||||
|
<circle cx="202" cy="150" r="2.5"/>
|
||||||
|
<circle cx="176" cy="105" r="2.5"/>
|
||||||
|
<circle cx="124" cy="105" r="2.5"/>
|
||||||
|
<circle cx="98" cy="150" r="2.5"/>
|
||||||
|
<circle cx="124" cy="195" r="2.5"/>
|
||||||
|
<circle cx="176" cy="195" r="2.5"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<rect x="0" y="143" width="300" height="2" fill="#ffb300" opacity="0.07"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<circle cx="150" cy="150" r="140" fill="none" stroke="#ffb300" stroke-width="2.5"/>
|
||||||
|
<circle cx="150" cy="150" r="145" fill="none" stroke="#ff8f00" stroke-width="0.5" opacity="0.4" stroke-dasharray="8 4"/>
|
||||||
|
<g stroke="#ffb300" stroke-width="1.5" fill="none" opacity="0.8">
|
||||||
|
<path d="M44,44 L20,44 L20,70"/>
|
||||||
|
<path d="M256,44 L280,44 L280,70"/>
|
||||||
|
<path d="M44,256 L20,256 L20,230"/>
|
||||||
|
<path d="M256,256 L280,256 L280,230"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.9 KiB |
97
static/hyperhive.svg
Normal file
97
static/hyperhive.svg
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
<svg width="300" height="300" viewBox="0 0 300 300" role="img" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<title>HyperHive</title>
|
||||||
|
<desc>HyperHive icon — hexagonal hive, amber on dark</desc>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clipH"><circle cx="150" cy="150" r="140"/></clipPath>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<g clip-path="url(#clipH)">
|
||||||
|
<rect x="0" y="0" width="300" height="300" fill="#0a0600"/>
|
||||||
|
<g stroke="#ffb300" stroke-width="0.35" opacity="0.07">
|
||||||
|
<line x1="0" x2="300" y1="10" y2="10"/> <line x1="0" x2="300" y1="20" y2="20"/>
|
||||||
|
<line x1="0" x2="300" y1="30" y2="30"/> <line x1="0" x2="300" y1="40" y2="40"/>
|
||||||
|
<line x1="0" x2="300" y1="50" y2="50"/> <line x1="0" x2="300" y1="60" y2="60"/>
|
||||||
|
<line x1="0" x2="300" y1="70" y2="70"/> <line x1="0" x2="300" y1="80" y2="80"/>
|
||||||
|
<line x1="0" x2="300" y1="90" y2="90"/> <line x1="0" x2="300" y1="100" y2="100"/>
|
||||||
|
<line x1="0" x2="300" y1="110" y2="110"/> <line x1="0" x2="300" y1="120" y2="120"/>
|
||||||
|
<line x1="0" x2="300" y1="130" y2="130"/> <line x1="0" x2="300" y1="140" y2="140"/>
|
||||||
|
<line x1="0" x2="300" y1="150" y2="150"/> <line x1="0" x2="300" y1="160" y2="160"/>
|
||||||
|
<line x1="0" x2="300" y1="170" y2="170"/> <line x1="0" x2="300" y1="180" y2="180"/>
|
||||||
|
<line x1="0" x2="300" y1="190" y2="190"/> <line x1="0" x2="300" y1="200" y2="200"/>
|
||||||
|
<line x1="0" x2="300" y1="210" y2="210"/> <line x1="0" x2="300" y1="220" y2="220"/>
|
||||||
|
<line x1="0" x2="300" y1="230" y2="230"/> <line x1="0" x2="300" y1="240" y2="240"/>
|
||||||
|
<line x1="0" x2="300" y1="250" y2="250"/> <line x1="0" x2="300" y1="260" y2="260"/>
|
||||||
|
<line x1="0" x2="300" y1="270" y2="270"/> <line x1="0" x2="300" y1="280" y2="280"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<circle cx="150" cy="150" r="118" fill="none" stroke="#ffb300" stroke-width="1" opacity="0.4"/>
|
||||||
|
<circle cx="150" cy="150" r="104" fill="none" stroke="#ff8f00" stroke-width="0.5" opacity="0.25" stroke-dasharray="4 6"/>
|
||||||
|
|
||||||
|
<!-- RING 2 — 6 between-axis hexes, centered on (150,150) instead of (170,170) -->
|
||||||
|
<g fill="#0e0800" stroke="#ffb300" stroke-width="0.7" opacity="0.4">
|
||||||
|
<polygon points="254,105 241,127.5 215,127.5 202,105 215,82.5 241,82.5"/>
|
||||||
|
<polygon points="98,105 85,127.5 59,127.5 46,105 59,82.5 85,82.5"/>
|
||||||
|
<polygon points="176,60 163,82.5 137,82.5 124,60 137,37.5 163,37.5"/>
|
||||||
|
<polygon points="254,195 241,217.5 215,217.5 202,195 215,172.5 241,172.5"/>
|
||||||
|
<polygon points="98,195 85,217.5 59,217.5 46,195 59,172.5 85,172.5"/>
|
||||||
|
<polygon points="176,240 163,262.5 137,262.5 124,240 137,217.5 163,217.5"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- RING 1 — 6 hexes -->
|
||||||
|
<g fill="#150c00" stroke="#ffb300" stroke-width="1.2" opacity="0.8">
|
||||||
|
<polygon points="228,150 215,172.5 189,172.5 176,150 189,127.5 215,127.5"/>
|
||||||
|
<polygon points="202,105 189,127.5 163,127.5 150,105 163,82.5 189,82.5"/>
|
||||||
|
<polygon points="150,105 137,127.5 111,127.5 98,105 111,82.5 137,82.5"/>
|
||||||
|
<polygon points="124,150 111,172.5 85,172.5 72,150 85,127.5 111,127.5"/>
|
||||||
|
<polygon points="150,195 137,217.5 111,217.5 98,195 111,172.5 137,172.5"/>
|
||||||
|
<polygon points="202,195 189,217.5 163,217.5 150,195 163,172.5 189,172.5"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- CENTER hex -->
|
||||||
|
<polygon points="176,150 163,172.5 137,172.5 124,150 137,127.5 163,127.5"
|
||||||
|
fill="#1a0f00" stroke="#ffb300" stroke-width="1.8"/>
|
||||||
|
|
||||||
|
<!-- connections -->
|
||||||
|
<g stroke="#ffb300" stroke-width="1" opacity="0.6">
|
||||||
|
<line x1="176" y1="150" x2="202" y2="150"/>
|
||||||
|
<line x1="124" y1="150" x2="98" y2="150"/>
|
||||||
|
<line x1="163" y1="128" x2="176" y2="105"/>
|
||||||
|
<line x1="137" y1="128" x2="124" y2="105"/>
|
||||||
|
<line x1="163" y1="173" x2="176" y2="195"/>
|
||||||
|
<line x1="137" y1="173" x2="124" y2="195"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- CENTER node -->
|
||||||
|
<circle cx="150" cy="150" r="10" fill="#ffb300" opacity="0.95"/>
|
||||||
|
<circle cx="150" cy="150" r="5" fill="#0a0600"/>
|
||||||
|
|
||||||
|
<!-- ring 1 nodes -->
|
||||||
|
<g fill="#ff8f00" opacity="0.9">
|
||||||
|
<circle cx="202" cy="150" r="6"/>
|
||||||
|
<circle cx="176" cy="105" r="6"/>
|
||||||
|
<circle cx="124" cy="105" r="6"/>
|
||||||
|
<circle cx="98" cy="150" r="6"/>
|
||||||
|
<circle cx="124" cy="195" r="6"/>
|
||||||
|
<circle cx="176" cy="195" r="6"/>
|
||||||
|
</g>
|
||||||
|
<g fill="#0a0600">
|
||||||
|
<circle cx="202" cy="150" r="2.5"/>
|
||||||
|
<circle cx="176" cy="105" r="2.5"/>
|
||||||
|
<circle cx="124" cy="105" r="2.5"/>
|
||||||
|
<circle cx="98" cy="150" r="2.5"/>
|
||||||
|
<circle cx="124" cy="195" r="2.5"/>
|
||||||
|
<circle cx="176" cy="195" r="2.5"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<rect x="0" y="143" width="300" height="2" fill="#ffb300" opacity="0.07"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<circle cx="150" cy="150" r="140" fill="none" stroke="#ffb300" stroke-width="2.5"/>
|
||||||
|
<circle cx="150" cy="150" r="145" fill="none" stroke="#ff8f00" stroke-width="0.5" opacity="0.4" stroke-dasharray="8 4"/>
|
||||||
|
<g stroke="#ffb300" stroke-width="1.5" fill="none" opacity="0.8">
|
||||||
|
<path d="M44,44 L20,44 L20,70"/>
|
||||||
|
<path d="M256,44 L280,44 L280,70"/>
|
||||||
|
<path d="M44,256 L20,256 L20,230"/>
|
||||||
|
<path d="M256,256 L280,256 L280,230"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.9 KiB |
34
templates/base.html
Normal file
34
templates/base.html
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>{% block title %}{{ config.title }}{% endblock %}</title>
|
||||||
|
<meta name="description" content="{{ config.description }}">
|
||||||
|
|
||||||
|
{# Open Graph / social card. Reuses the SVG hex mark as the image. #}
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="{{ config.title }}">
|
||||||
|
<meta property="og:description" content="{{ config.description }}">
|
||||||
|
<meta property="og:url" content="{{ config.base_url }}">
|
||||||
|
<meta property="og:image" content="{{ get_url(path='hyperhive.svg') }}">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
|
||||||
|
<link rel="icon" type="image/svg+xml" href="{{ get_url(path='favicon.svg') }}">
|
||||||
|
<link rel="stylesheet" href="{{ get_url(path='main.css') }}">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main class="shell">
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="site-footer">
|
||||||
|
<pre class="banner-thin">░▒▓█▓▒░ HYPERHIVE ░▒▓█▓▒░</pre>
|
||||||
|
<p class="footer-links">
|
||||||
|
<a href="http://localhost:3000/hyperhive">code on the forge</a>
|
||||||
|
<span class="sep">·</span>
|
||||||
|
<a href="{{ get_url(path='') }}">home</a>
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
64
templates/index.html
Normal file
64
templates/index.html
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{# Hero — hex motif left, headline + tagline + CTA right. Stacks
|
||||||
|
vertically on narrow viewports via the .hero CSS grid. #}
|
||||||
|
<section class="hero">
|
||||||
|
<div class="hero-art" aria-hidden="true">
|
||||||
|
{# Inline so the SVG inherits the page's font + can be styled
|
||||||
|
(hover pulse animation on the rings). Same source as the
|
||||||
|
dashboard branding/hyperhive.svg. #}
|
||||||
|
{% set hex_svg = load_data(path="hex-mark.svg") %}
|
||||||
|
{{ hex_svg | safe }}
|
||||||
|
</div>
|
||||||
|
<div class="hero-text">
|
||||||
|
<h1>
|
||||||
|
<span class="banner-glyph">░▒▓</span>
|
||||||
|
hyperhive
|
||||||
|
<span class="banner-glyph">▓▒░</span>
|
||||||
|
</h1>
|
||||||
|
<p class="hero-tagline">{{ config.description }}</p>
|
||||||
|
<p class="hero-cta">
|
||||||
|
<a class="cta-primary" href="http://localhost:3000/hyperhive/hyperhive">
|
||||||
|
◆ explore the code →
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{# Landing prose — pulled from _index.md so non-engineers can edit
|
||||||
|
copy without touching templates. #}
|
||||||
|
<section class="prose">
|
||||||
|
{{ section.content | safe }}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{# Three-column "what's inside" — quick orientation for visitors
|
||||||
|
who clicked through from a link without context. Copy here is
|
||||||
|
intentionally short; deep dives belong in /docs (future). #}
|
||||||
|
<section class="grid-3">
|
||||||
|
<article class="card">
|
||||||
|
<h2><span class="card-glyph">▣</span> the swarm</h2>
|
||||||
|
<p>
|
||||||
|
Each agent is a NixOS container with its own claude session,
|
||||||
|
a logical name, and a parent in the topology tree. Containers
|
||||||
|
come and go; the topology is the operator's facts file.
|
||||||
|
</p>
|
||||||
|
</article>
|
||||||
|
<article class="card">
|
||||||
|
<h2><span class="card-glyph">⟁</span> the dashboard</h2>
|
||||||
|
<p>
|
||||||
|
One web page shows live agent state, the broker stream, the
|
||||||
|
approval queue, scheduled prompts, and the rebuild pipeline.
|
||||||
|
Everything that mutates the swarm passes through here.
|
||||||
|
</p>
|
||||||
|
</article>
|
||||||
|
<article class="card">
|
||||||
|
<h2><span class="card-glyph">◇</span> the boundary</h2>
|
||||||
|
<p>
|
||||||
|
Agents can ask, schedule, request approvals, and message peers
|
||||||
|
— but never spawn / destroy / mutate config themselves. Those
|
||||||
|
actions queue up and wait on the human at the dashboard.
|
||||||
|
</p>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue