diff --git a/docs/site/index.html b/docs/site/index.html index 25a2325..ba6dd5b 100644 --- a/docs/site/index.html +++ b/docs/site/index.html @@ -11,91 +11,116 @@ -
-
-

- Go · Charm · Bubble Tea · … -

-

OUTPOST 404

-

- Remote survival colony ops in your terminal. Balance scarce resources, survive random - events, and complete the Signal Beacon before the outpost collapses. +

+ + +
+
+

// SIGNAL INTERCEPTED — COLONY DESIGNATION 404

+

OUTPOST 404

+

+ Remote survival colony ops in your terminal.
+ Balance scarce resources, survive random events,
+ and complete the Signal Beacon before the outpost collapses.

-
- Download - Install - Source on GitHub +
+
+ PWR + +
+
+ FOOD + +
+
+ MORALE + +
+
+ BEACON + +
-
+ +

+ RELEASE … + // Go · Charm · Bubble Tea +

+
+ + + +
-
-

Latest release

-
-
Loading release…
+
+

[SYS.RELEASE] Latest Binary

+
+
Querying release feed…
-
-

Mission

-
-
- Win +
+

[OPS.BRIEF] Mission Parameters

+
+
+

WIN CONDITIONS

    -
  • Survive 45 days — reach day 46 with vitals above zero
  • -
  • Signal Beacon — complete 5 parts before collapse
  • +
  • Survive 45 days — reach day 46 with vitals above zero
  • +
  • Signal Beacon — complete all 5 parts before collapse
-
- Lose +
+

COLLAPSE TRIGGERS

    -
  • Power, food, morale, or population hits zero
  • -
  • Collapse is checked before a survival win on the final day
  • +
  • Power, food, morale, or population reaches zero
  • +
  • Collapse is checked before survival win on the final day
-
-

Install

-
-

Homebrew

+
+

[CMD.INSTALL] Deployment

+
+

Homebrew

brew install ericdahl-dev/tap/outpost-404
-

Go

+

Go toolchain

go install github.com/ericdahl-dev/outpost-404/cmd/outpost@latest
-

From source

+

From source

git clone https://github.com/ericdahl-dev/outpost-404.git
 cd outpost-404
 go run ./cmd/outpost
-
-

Run

-
-
$ outpost
-
# fixed seed for reproducible events
-
$ outpost -seed 42
-
# optional JSONL session log
-
$ outpost -log ./logs/my-run.jsonl
+
+

[CMD.EXEC] Launch

+
+
+
$ outpost
+
# fixed seed for reproducible events
+
$ outpost -seed 42
+
# optional JSONL session log
+
$ outpost -log ./logs/my-run.jsonl
+
-
-

Controls

-
+
+

[SYS.INPUT] Controls

+
@@ -110,7 +135,7 @@

Controls

- + @@ -118,43 +143,45 @@

Controls

-
-

Headless tools

-
+
+

[DEV.TOOLS] Headless Operations

+

Balance scripts and session replay for tuning and regression checks:

-
outpost -simulate scripts/conservative.json -seed 99
-outpost -simulate scripts/survival_45.json -seeds 1,7,42
-outpost -replay ./logs/my-run.jsonl
-

- See the repo - balance guide +

+
$ outpost -simulate scripts/conservative.json -seed 99
+
$ outpost -simulate scripts/survival_45.json -seeds 1,7,42
+
$ outpost -replay ./logs/my-run.jsonl
+
+

+ See the + balance guide for reference seeds and baseline expectations.

-
-

Stack

-
+
+

[SYS.ARCH] Stack

+

Built with the - Charm stack: Bubble Tea, - Lip Gloss, and Bubbles. Game rules live in internal/game; the TUI in - internal/ui. Content is JSON-driven (data/buildings.json, - data/events.json). + Charm stack: + Bubble Tea, Lip Gloss, and Bubbles. Game rules live in + internal/game; the TUI in internal/ui. + Content is JSON-driven — data/buildings.json, + data/events.json.

-
+ + diff --git a/docs/site/release.js b/docs/site/release.js index 6d98b98..23c63b9 100644 --- a/docs/site/release.js +++ b/docs/site/release.js @@ -130,4 +130,16 @@ } loadLatestRelease(); + + var entries = document.querySelectorAll('.log-entry'); + if ('IntersectionObserver' in window) { + var io = new IntersectionObserver(function(records) { + records.forEach(function(r) { + if (r.isIntersecting) { r.target.classList.add('visible'); io.unobserve(r.target); } + }); + }, { threshold: 0.08 }); + entries.forEach(function(el) { io.observe(el); }); + } else { + entries.forEach(function(el) { el.classList.add('visible'); }); + } })(); diff --git a/docs/site/style.css b/docs/site/style.css index 4a4cd3f..6d0bd8a 100644 --- a/docs/site/style.css +++ b/docs/site/style.css @@ -1,265 +1,611 @@ -:root { - --bg: #0c0f0a; - --panel: #141a12; - --border: #2a3526; - --text: #c8d4bc; - --muted: #7a8a72; - --accent: #9bdc6a; - --warn: #e8b86a; - --danger: #e07a6a; - --mono: "IBM Plex Mono", "SF Mono", "Menlo", "Consolas", monospace; - --sans: "IBM Plex Sans", system-ui, sans-serif; -} - -* { - box-sizing: border-box; -} - -html { - scroll-behavior: smooth; -} +/* ============================================================ + OUTPOST 404 — site styles + Aesthetic: cinematic glitch / CRT terminal / distress signal + ============================================================ */ +/* -- Design tokens ------------------------------------------ */ +:root { + --bg: #060806; + --bg2: #0b0f0a; + --panel: #0f140d; + --border: #1e2b1a; + --border-hi: #2e4228; + --text: #b8cdb0; + --muted: #5e7256; + --dim: #3a4e35; + --accent: #7ddc50; + --accent-hi: #aaff77; + --warn: #e8b044; + --danger: #dd5e4a; + --beacon: #50c8dd; + --mono: "JetBrains Mono", "Share Tech Mono", "SF Mono", "Menlo", monospace; + --display: "VT323", "Share Tech Mono", monospace; +} + +/* -- Reset -------------------------------------------------- */ +*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } +html { scroll-behavior: smooth; } + +/* -- Base --------------------------------------------------- */ body { - margin: 0; - min-height: 100vh; background: var(--bg); color: var(--text); - font-family: var(--sans); - font-size: 1.05rem; - line-height: 1.6; + font-family: var(--mono); + font-size: 0.95rem; + line-height: 1.7; + overflow-x: hidden; } -body::before { - content: ""; +a { color: var(--accent); text-underline-offset: 3px; } +a:hover { color: var(--accent-hi); } + +code { + font-family: var(--mono); + font-size: 0.88em; + color: var(--warn); + background: rgba(232,176,68,0.08); + padding: 0.1em 0.35em; + border-radius: 2px; +} + +/* -- Atmosphere layers -------------------------------------- */ +.scanlines { + pointer-events: none; position: fixed; inset: 0; - pointer-events: none; + z-index: 9999; background: repeating-linear-gradient( 0deg, transparent, - transparent 2px, - rgba(0, 0, 0, 0.12) 2px, - rgba(0, 0, 0, 0.12) 4px + transparent 3px, + rgba(0,0,0,0.18) 3px, + rgba(0,0,0,0.18) 4px ); - opacity: 0.35; + mix-blend-mode: multiply; } -a { - color: var(--accent); +.noise { + pointer-events: none; + position: fixed; + inset: 0; + z-index: 9998; + opacity: 0.028; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); + background-size: 256px 256px; + animation: noise-drift 8s steps(10) infinite; } -a:hover { - color: #c8f0a8; +@keyframes noise-drift { + 0% { background-position: 0 0; } + 25% { background-position: 40px -30px; } + 50% { background-position: -20px 50px; } + 75% { background-position: 60px 20px; } + 100% { background-position: 0 0; } } -.wrap { +/* -- HERO --------------------------------------------------- */ +.hero { position: relative; - max-width: 52rem; - margin: 0 auto; - padding: 2.5rem 1.5rem 4rem; + min-height: 100svh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 4rem 2rem 5rem; + background: + radial-gradient(ellipse 80% 60% at 50% 40%, rgba(60,100,40,0.18) 0%, transparent 70%), + var(--bg); + overflow: hidden; +} + +.hero::before, +.hero::after { + content: ""; + position: absolute; + width: 120px; + height: 120px; + opacity: 0.25; + animation: bracket-pulse 4s ease-in-out infinite; +} +.hero::before { + top: 2rem; left: 2rem; + border-top: 1px solid var(--accent); + border-left: 1px solid var(--accent); + animation-delay: 0s; +} +.hero::after { + bottom: 2rem; right: 2rem; + border-bottom: 1px solid var(--accent); + border-right: 1px solid var(--accent); + animation-delay: 2s; } -header { - border: 1px solid var(--border); - background: var(--panel); - padding: 1.75rem 1.5rem; - margin-bottom: 2rem; +@keyframes bracket-pulse { + 0%, 100% { opacity: 0.15; } + 50% { opacity: 0.45; } +} + +.hero-inner { + position: relative; + z-index: 1; + text-align: center; + max-width: 700px; + width: 100%; } -h1 { - margin: 0 0 0.35rem; +.hero-eyebrow { font-family: var(--mono); - font-size: clamp(1.6rem, 5vw, 2.2rem); - font-weight: 600; - letter-spacing: 0.04em; + font-size: 0.7rem; + letter-spacing: 0.18em; + color: var(--muted); + margin-bottom: 1.5rem; + animation: fade-up 0.6s ease both; +} + +/* -- GLITCH TITLE ------------------------------------------- */ +.hero-title { + font-family: var(--display); + font-size: clamp(4.5rem, 16vw, 9rem); + font-weight: 400; + line-height: 1; + letter-spacing: 0.06em; color: var(--accent); + position: relative; + display: inline-block; + margin-bottom: 1.75rem; + text-shadow: + 0 0 40px rgba(125,220,80,0.35), + 0 0 80px rgba(125,220,80,0.12); + animation: fade-up 0.6s 0.1s ease both, flicker 12s 3s infinite; +} + +.hero-title::before, +.hero-title::after { + content: attr(data-text); + position: absolute; + inset: 0; + pointer-events: none; +} + +.hero-title::before { + color: var(--danger); + clip-path: polygon(0 20%, 100% 20%, 100% 40%, 0 40%); + animation: glitch-r 5s 1.2s steps(1) infinite; + opacity: 0; +} + +.hero-title::after { + color: var(--beacon); + clip-path: polygon(0 55%, 100% 55%, 100% 70%, 0 70%); + animation: glitch-b 5s 1.8s steps(1) infinite; + opacity: 0; +} + +@keyframes glitch-r { + 0%, 90%, 100% { opacity: 0; transform: none; } + 91% { opacity: 1; transform: translate(-3px, 0) skewX(-2deg); } + 93% { opacity: 1; transform: translate(3px, 1px) skewX(1deg); } + 95% { opacity: 0; } +} + +@keyframes glitch-b { + 0%, 88%, 100% { opacity: 0; transform: none; } + 89% { opacity: 1; transform: translate(4px, -1px) skewX(1deg); } + 92% { opacity: 1; transform: translate(-2px, 0); } + 94% { opacity: 0; } +} + +@keyframes flicker { + 0%, 97%, 100% { opacity: 1; } + 97.5% { opacity: 0.6; } + 98% { opacity: 1; } + 98.4% { opacity: 0.4; } + 98.8% { opacity: 1; } } -.tagline { - margin: 0 0 1.25rem; +/* -- Hero copy ---------------------------------------------- */ +.hero-tagline { + font-family: var(--mono); + font-size: 0.88rem; + line-height: 1.9; color: var(--muted); - font-size: 1rem; + margin-bottom: 2.5rem; + animation: fade-up 0.6s 0.2s ease both; } -.cta { +/* -- Vital bars --------------------------------------------- */ +.hero-vitals { display: flex; flex-wrap: wrap; - gap: 0.75rem; + justify-content: center; + gap: 0.6rem 1.5rem; + margin-bottom: 2.5rem; + animation: fade-up 0.6s 0.3s ease both; +} + +.vital { + display: flex; + align-items: center; + gap: 0.55rem; + font-size: 0.7rem; + letter-spacing: 0.12em; +} + +.vital-label { + color: var(--muted); + min-width: 3.5rem; + text-align: right; +} + +.vital-bar { + width: 90px; + height: 6px; + background: var(--border); + position: relative; + overflow: hidden; +} + +.vital-bar::after { + content: ""; + position: absolute; + inset: 0; + background: repeating-linear-gradient( + 90deg, + transparent, + transparent 3px, + rgba(0,0,0,0.4) 3px, + rgba(0,0,0,0.4) 4px + ); +} + +.vital-fill { + display: block; + height: 100%; + width: var(--pct, 50%); + background: var(--accent); + animation: bar-fill 1.2s cubic-bezier(0.16,1,0.3,1) both; + transform-origin: left; +} + +.vital-bar--warn .vital-fill { background: var(--warn); } +.vital-bar--beacon .vital-fill { background: var(--beacon); } + +@keyframes bar-fill { + from { transform: scaleX(0); } + to { transform: scaleX(1); } +} + +/* -- Hero CTA ----------------------------------------------- */ +.hero-cta { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 0.65rem; + margin-bottom: 2rem; + animation: fade-up 0.6s 0.4s ease both; } .btn { display: inline-block; font-family: var(--mono); - font-size: 0.9rem; - padding: 0.55rem 1rem; - border: 1px solid var(--border); - background: #1a2218; - color: var(--accent); + font-size: 0.8rem; + letter-spacing: 0.08em; + padding: 0.55rem 1.1rem; + border: 1px solid var(--border-hi); + background: transparent; + color: var(--muted); text-decoration: none; + transition: color 0.15s, border-color 0.15s, background 0.15s, text-shadow 0.15s; } .btn:hover { + color: var(--accent); border-color: var(--accent); - background: #243020; + background: rgba(125,220,80,0.06); + text-shadow: 0 0 12px rgba(125,220,80,0.5); } .btn-primary { border-color: var(--accent); - background: #243020; + color: var(--accent); + background: rgba(125,220,80,0.07); } -section { - margin-bottom: 2rem; +.btn-primary:hover { + background: rgba(125,220,80,0.14); + text-shadow: 0 0 16px rgba(125,220,80,0.7); +} + +.hero-version { + font-size: 0.7rem; + color: var(--dim); + letter-spacing: 0.1em; + animation: fade-up 0.6s 0.5s ease both; } -h2 { +.version-tag { color: var(--accent); } + +.hero-scroll-hint { + position: absolute; + bottom: 1.5rem; + left: 50%; + transform: translateX(-50%); font-family: var(--mono); - font-size: 1rem; - font-weight: 600; - letter-spacing: 0.12em; - text-transform: uppercase; - color: var(--warn); - margin: 0 0 0.75rem; - padding-bottom: 0.35rem; - border-bottom: 1px solid var(--border); + font-size: 0.75rem; + color: var(--dim); + animation: scroll-bob 2.5s ease-in-out infinite; } -.panel { - border: 1px solid var(--border); - background: var(--panel); - padding: 1.25rem 1.5rem; +@keyframes scroll-bob { + 0%, 100% { transform: translateX(-50%) translateY(0); opacity: 0.4; } + 50% { transform: translateX(-50%) translateY(6px); opacity: 0.9; } } -pre, -.terminal { - font-family: var(--mono); - font-size: 0.85rem; - background: #080a08; - border: 1px solid var(--border); - padding: 1rem 1.1rem; - overflow-x: auto; - margin: 0.75rem 0 0; +@keyframes fade-up { + from { opacity: 0; transform: translateY(12px); } + to { opacity: 1; transform: translateY(0); } } -.terminal .prompt { - color: var(--accent); - user-select: none; +/* -- Main content ------------------------------------------- */ +.wrap { + max-width: 56rem; + margin: 0 auto; + padding: 4rem 1.5rem 6rem; +} + +/* -- Log entry sections ------------------------------------- */ +.log-entry { + margin-bottom: 3.5rem; + position: relative; + padding-left: 1.5rem; + border-left: 2px solid var(--border); + transition: border-color 0.3s; + opacity: 0; + transform: translateY(16px); + transition: opacity 0.55s ease, transform 0.55s ease, border-color 0.3s; +} + +.log-entry:hover { + border-left-color: var(--border-hi); } -.terminal .dim { +.log-entry.visible { + opacity: 1; + transform: none; +} + +.log-label { + font-family: var(--mono); + font-size: 0.72rem; + letter-spacing: 0.16em; + font-weight: 600; + text-transform: uppercase; color: var(--muted); + margin-bottom: 1.25rem; + display: flex; + align-items: center; + gap: 0.65rem; } -.grid { +.log-tag { + color: var(--warn); + letter-spacing: 0.08em; +} + +/* -- Mission blocks ----------------------------------------- */ +.log-grid { display: grid; gap: 1rem; } @media (min-width: 640px) { - .grid-2 { - grid-template-columns: 1fr 1fr; - } + .log-grid { grid-template-columns: 1fr 1fr; } } -table { - width: 100%; - border-collapse: collapse; - font-size: 0.95rem; +.mission-block { + background: var(--panel); + border: 1px solid var(--border); + padding: 1.25rem; } -th, -td { - text-align: left; - padding: 0.5rem 0.75rem; - border-bottom: 1px solid var(--border); +.mission-block ul { + list-style: none; + margin-top: 0.65rem; } -th { - font-family: var(--mono); - font-size: 0.8rem; - color: var(--muted); - font-weight: 500; +.mission-block li { + padding: 0.3rem 0 0.3rem 1.1rem; + position: relative; + font-size: 0.88rem; } -td:first-child { +.mission-win li::before { content: "+"; position: absolute; left: 0; color: var(--accent); } +.mission-lose li::before { content: "!"; position: absolute; left: 0; color: var(--danger); } + +.mission-header { font-family: var(--mono); - color: var(--warn); + font-size: 0.7rem; + letter-spacing: 0.14em; + font-weight: 600; } -ul { - margin: 0.5rem 0 0; - padding-left: 1.25rem; +.mission-win .mission-header { color: var(--accent); } +.mission-lose .mission-header { color: var(--danger); } + +/* -- Install methods ---------------------------------------- */ +.install-method { + font-size: 0.72rem; + letter-spacing: 0.12em; + color: var(--muted); + margin: 1rem 0 0.35rem; } -li { - margin-bottom: 0.35rem; +.install-method:first-of-type { margin-top: 0; } + +/* -- Preformatted code -------------------------------------- */ +pre { + font-family: var(--mono); + font-size: 0.82rem; + background: #020402; + border: 1px solid var(--border); + border-left: 3px solid var(--border-hi); + padding: 0.9rem 1.1rem; + overflow-x: auto; + line-height: 1.65; + color: var(--text); } -footer { - margin-top: 3rem; - padding-top: 1.5rem; - border-top: 1px solid var(--border); - font-size: 0.9rem; - color: var(--muted); +pre code { + background: none; + padding: 0; + color: inherit; + font-size: inherit; } -.badge { - display: inline-block; +/* -- Terminal block ----------------------------------------- */ +.terminal { font-family: var(--mono); - font-size: 0.75rem; - padding: 0.15rem 0.45rem; + font-size: 0.82rem; + background: #020402; border: 1px solid var(--border); - color: var(--muted); - margin-right: 0.35rem; + border-left: 3px solid var(--accent); + padding: 0.9rem 1.1rem; + line-height: 1.9; + overflow-x: auto; + position: relative; } -.version-pill { +.terminal::before { + content: "\25CF \25CF \25CF"; + display: block; + color: var(--dim); + font-size: 0.6rem; + letter-spacing: 0.3rem; + margin-bottom: 0.7rem; +} + +.prompt { color: var(--accent); - border-color: var(--accent); - margin-left: 0.25rem; + user-select: none; +} + +/* -- Table -------------------------------------------------- */ +table { + width: 100%; + border-collapse: collapse; + font-size: 0.87rem; +} + +th, td { + text-align: left; + padding: 0.55rem 0.85rem; + border-bottom: 1px solid var(--border); +} + +th { + font-family: var(--mono); + font-size: 0.68rem; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--dim); + font-weight: 400; +} + +td:first-child { + font-family: var(--mono); + color: var(--warn); + width: 7rem; } +tr:hover td { color: var(--text); } +tr:hover td:first-child { color: var(--accent-hi); } + +/* -- Release assets ----------------------------------------- */ .release-title { - margin: 0 0 0.5rem; + color: var(--text); + font-size: 0.9rem; + margin-bottom: 0.25rem; } .asset-list { list-style: none; - margin: 0.75rem 0 0; - padding: 0; + margin: 0.85rem 0 0; display: grid; - gap: 0.5rem; + gap: 0.4rem; } .asset-list a { display: block; font-family: var(--mono); - font-size: 0.9rem; - padding: 0.5rem 0.75rem; + font-size: 0.82rem; + padding: 0.5rem 0.85rem; border: 1px solid var(--border); - background: #080a08; + background: #020402; text-decoration: none; + color: var(--text); + transition: border-color 0.15s, color 0.15s; } .asset-list a:hover { border-color: var(--accent); + color: var(--accent); } .release-notes { margin-top: 1.25rem; - font-size: 0.95rem; + font-size: 0.88rem; color: var(--muted); } .release-notes h3 { font-family: var(--mono); - font-size: 0.85rem; - letter-spacing: 0.08em; + font-size: 0.7rem; + letter-spacing: 0.14em; text-transform: uppercase; color: var(--warn); margin: 0 0 0.5rem; } .release-notes ul { - padding-left: 1.25rem; + list-style: none; + padding: 0; +} + +.release-notes li { + padding: 0.2rem 0 0.2rem 1rem; + position: relative; +} + +.release-notes li::before { + content: "\2192"; + position: absolute; + left: 0; + color: var(--dim); +} + +/* -- Utilities ---------------------------------------------- */ +.dim { color: var(--muted); } +.small { font-size: 0.82rem; margin-top: 0.75rem; } + +/* -- Footer ------------------------------------------------- */ +footer { + border-top: 1px solid var(--border); + padding-top: 1.5rem; + margin-top: 2rem; + font-size: 0.78rem; + color: var(--dim); + text-align: center; + letter-spacing: 0.05em; +} + +footer a { color: var(--muted); } +footer a:hover { color: var(--accent); } + +/* -- Responsive --------------------------------------------- */ +@media (max-width: 480px) { + .hero-vitals { gap: 0.5rem 1rem; } + .vital-bar { width: 70px; } + .hero-cta { gap: 0.5rem; } + .wrap { padding: 2.5rem 1rem 4rem; } + .log-entry { padding-left: 0.9rem; } }
rRepair systems
tTrade food for credits
sWork on Signal Beacon
n / spaceNext day
n / spaceAdvance to next day
?Help
qQuit