Compare commits

..

1 Commits

Author SHA1 Message Date
Alexander Whitestone
1294f37b44 fix: [MIGRATION] Preserve legacy the-matrix quality work before Nexus rewrite (closes #685)
Some checks failed
CI / test (pull_request) Failing after 9s
CI / validate (pull_request) Failing after 12s
Review Approval Gate / verify-review (pull_request) Failing after 3s
2026-04-10 20:17:03 -04:00
5 changed files with 134 additions and 314 deletions

View File

@@ -1,132 +1,169 @@
# Legacy Matrix Audit # Legacy Matrix Audit — Migration Table
Purpose: Purpose:
Preserve useful work from `/Users/apayne/the-matrix` before the Nexus browser shell is rebuilt. Preserve quality work from `/Users/apayne/the-matrix` before the Nexus browser shell is rebuilt.
Canonical rule: Canonical rule:
- `Timmy_Foundation/the-nexus` is the only canonical 3D repo. - `Timmy_Foundation/the-nexus` is the only canonical 3D repo.
- `/Users/apayne/the-matrix` is legacy source material, not a parallel product. - `/Users/apayne/the-matrix` is legacy source material, not a parallel product.
- This document is the authoritative migration table for issue #685.
## Verified Legacy Matrix State ## Verified Legacy State
Local legacy repo: Local legacy repo: `/Users/apayne/the-matrix`
- `/Users/apayne/the-matrix`
Observed facts: Observed facts:
- Vite browser app exists - Vite browser app, vanilla JS + Three.js 0.171.0
- `npm test` passes with `87 passed, 0 failed` - 24 JS modules under `js/`
- 23 JS modules under `js/` - Smoke suite: 87 passed, 0 failed
- package scripts include `dev`, `build`, `preview`, and `test` - Package scripts: dev, build, preview, test
- PWA manifest + service worker
- Vite config with code-splitting (Three.js in separate chunk)
- Quality-tier system for hardware detection
- WebSocket client with reconnection, heartbeat, mock mode
- Full avatar FPS movement + PiP camera
- Sub-world portal system with zone triggers
## Known historical Nexus snapshot ## Migration Table
Useful in-repo reference point: Decision key:
- `0518a1c3ae3c1d0afeb24dea9772102f5a3d9a66` - **CARRY** = transplant concepts and patterns into Nexus vNext
- **ARCHIVE** = keep as reference, do not directly transplant
- **DROP** = do not preserve unless re-justified
That snapshot still contains browser-world root files such as: ### Core Modules
- `index.html`
- `app.js`
- `style.css`
- `package.json`
- `tests/`
## Rescue Candidates | File | Lines | Capability | Decision | Why for Nexus |
|------|-------|------------|----------|---------------|
| `js/main.js` | 180 | App bootstrap, render loop, WebGL context recovery | **CARRY** | Architectural pattern. Shows clean init/teardown lifecycle, context-loss recovery, visibility pause. Nexus needs this loop but should not copy the monolithic wiring. |
| `js/world.js` | 95 | Scene, camera, renderer, grid, lights | **CARRY** | Foundational. Quality-tier-aware renderer setup, grid floor, lighting. Nexus already has a world but should adopt the tier-aware antialiasing and pixel-ratio capping. |
| `js/config.js` | 68 | Connection config via URL params + env vars | **ARCHIVE** | Pattern reference only. Nexus config should route through Hermes harness, not Vite env vars. The URL-override pattern (ws, token, mock) is worth remembering. |
| `js/quality.js` | 90 | Hardware detection, quality tier (low/medium/high) | **CARRY** | Directly useful. DPR capping, core/memory/screen heuristics, WebGL renderer sniffing. Nexus needs this for graceful degradation on Mac/iPad. |
| `js/storage.js` | 39 | Safe localStorage with in-memory fallback | **CARRY** | Small, robust, sandbox-proof. Nexus should use this or equivalent. Prevents crashes in sandboxed iframes. |
### Carry forward into Nexus vNext ### Agent System
1. `agent-defs.js` | File | Lines | Capability | Decision | Why for Nexus |
- agent identity definitions |------|-------|------------|----------|---------------|
- useful as seed data/model for visible entities in the world | `js/agent-defs.js` | 30 | Agent identity data (id, label, color, role, position) | **CARRY** | Seed data model. Nexus agents should be defined similarly — data-driven, not hardcoded in render logic. Color hex helper is trivial but useful. |
| `js/agents.js` | 523 | Agent 3D objects, movement, state, connection lines, hot-add/remove | **CARRY** | Core visual system. Shared geometries (perf), movement interpolation, wallet-health stress glow, auto-placement algorithm, connection-line pulse. All valuable. Needs integration with real agent state from Hermes. |
| `js/behaviors.js` | 413 | Autonomous agent behavior state machine | **ARCHIVE** | Pattern reference. The personality-weighted behavior selection, conversation pairing, and artifact-placement system are well-designed. But Nexus behaviors should be driven by Hermes, not a client-side simulation. Keep the architecture, drop the fake-autonomy. |
| `js/presence.js` | 139 | Agent presence HUD (online/offline, uptime, state) | **CARRY** | Valuable UX. Live "who's here" panel with uptime tickers and state indicators. Needs real backend state, not mock assumptions. |
2. `agents.js` ### Visitor & Interaction
- agent objects, state machine, connection lines
- useful for visualizing Timmy / subagents / system processes in a world-native way
3. `avatar.js` | File | Lines | Capability | Decision | Why for Nexus |
- visitor embodiment, movement, camera handling |------|-------|------------|----------|---------------|
- strongly aligned with "training ground" and "walk the world" goals | `js/visitor.js` | 141 | Visitor enter/leave protocol, chat input | **CARRY** | Session lifecycle. Device detection, visibility-based leave/return, chat input wiring. Directly applicable to Nexus visitor tracking. |
| `js/avatar.js` | 360 | FPS movement, PiP dual-camera, touch input | **CARRY** | Visitor embodiment. WASD + arrow movement, first/third person swap, PiP canvas, touch joystick, right-click mouse-look. Strong work. Needs tuning for Nexus world bounds. |
| `js/interaction.js` | 296 | Raycasting, click-to-select agents, info popup | **CARRY** | Essential for any browser world. OrbitControls, pointer/tap detection, agent popup with state/role, TALK button. The popup-anchoring-to-3D-position logic is particularly well done. |
| `js/zones.js` | 161 | Proximity trigger zones (portal enter/exit, events) | **CARRY** | Spatial event system. Portal traversal, event triggers, once-only zones. Nexus portals (#672) need this exact pattern. |
4. `ui.js` ### Chat & Communication
- HUD, chat surfaces, overlays
- useful if rebuilt against real harness data instead of stale fake state
5. `websocket.js` | File | Lines | Capability | Decision | Why for Nexus |
- browser-side live bridge patterns |------|-------|------------|----------|---------------|
- useful if retethered to Hermes-facing transport | `js/bark.js` | 141 | Speech bubble system with typing animation | **CARRY** | Timmy's voice in-world. Typing animation, queue, auto-dismiss, emotion tags, demo bark lines. Strong expressive presence. The demo lines ("The Tower watches. The Tower remembers.") are good seed content. |
| `js/ui.js` | 285 | Chat panel, agent list, HUD, streaming tokens | **CARRY** | Chat infrastructure. Rolling chat buffer, per-agent localStorage history, streaming token display with cursor animation, HTML escaping. Needs reconnection to Hermes chat instead of WS mock. |
| `js/transcript.js` | 183 | Conversation transcript logger, export | **ARCHIVE** | Pattern reference. The rolling buffer, structured JSON entries, TXT/JSON download, HUD badge are all solid. But transcript authority should live in Hermes, not browser localStorage. Keep the UX pattern, rebuild storage layer. |
6. `transcript.js` ### Visual Effects
- local transcript capture pattern
- useful if durable truth still routes through Hermes and browser cache remains secondary
7. `ambient.js` | File | Lines | Capability | Decision | Why for Nexus |
- mood / atmosphere system |------|-------|------------|----------|---------------|
- directly supports wizardly presentation without changing system authority | `js/effects.js` | 195 | Matrix rain particles + starfield | **CARRY** | Atmospheric foundation. Quality-tier particle counts, frame-skip optimization, adaptive draw-range (FPS-budget recovery), bounding-sphere pre-compute. This is production-grade particle work. |
| `js/ambient.js` | 212 | Mood-driven atmosphere (lighting, fog, rain, stars) | **CARRY** | Scene mood engine. Smooth eased transitions between mood states (calm, focused, excited, contemplative, stressed), per-mood lighting/fog/rain/star parameters. Directly supports Nexus atmosphere. |
| `js/satflow.js` | 261 | Lightning payment particle flow | **CARRY** | Economy visualization. Bezier-arc particles, staggered travel, burst-on-arrival, pooling. If Nexus shows any payment/economy flow, this is the pattern. |
8. `satflow.js` ### Economy & Scene
- visual economy / payment flow motifs
- useful if Timmy's economy/agent interactions become a real visible layer
9. `economy.js` | File | Lines | Capability | Decision | Why for Nexus |
- treasury / wallet panel ideas |------|-------|------------|----------|---------------|
- useful if later backed by real sovereign metrics | `js/economy.js` | 100 | Wallet/treasury HUD panel | **ARCHIVE** | UI pattern reference. Clean sats formatting, per-agent balance rows, health-colored dots, recent transactions. Worth rebuilding when backed by real sovereign metrics. |
| `js/scene-objects.js` | 718 | Dynamic 3D object registry, portals, sub-worlds | **CARRY** | Critical. Geometry/material factories, animation system (rotate/bob/pulse/orbit), portal visual (torus ring + glow disc + zone), sub-world load/unload, text sprites, compound groups. This is the most complex and valuable module. Nexus portals (#672) should build on this. |
10. `presence.js` ### Backend Bridge
- who-is-here / online-state UI
- useful for showing human + agent + process presence in the world
11. `interaction.js` | File | Lines | Capability | Decision | Why for Nexus |
- clicking, inspecting, selecting world entities |------|-------|------------|----------|---------------|
- likely needed in any real browser-facing Nexus shell | `js/websocket.js` | 598 | WebSocket client, message dispatcher, mock mode | **ARCHIVE** | Pattern reference only. Reconnection with exponential backoff, heartbeat/zombie detection, rich message dispatch (40+ message types), streaming chat support. The architecture is sound but must be reconnected to Hermes transport, not copied wholesale. The message-type catalog is the most valuable reference artifact. |
| `js/demo.js` | ~300 | Demo autopilot (mock mode simulation) | **DROP** | Fake activity simulation. Deliberately creates the illusion of live data. Do not preserve. If Nexus needs a demo mode, build a clearly-labeled one that doesn't pretend to be real. |
12. `quality.js` ### Testing & Build
- hardware-aware quality tiering
- useful for local-first graceful degradation on Mac hardware
13. `bark.js` | File | Lines | Capability | Decision | Why for Nexus |
- prominent speech / bark system |------|-------|------------|----------|---------------|
- strong fit for Timmy's expressive presence in-world | `test/smoke.mjs` | 235 | Automated browser smoke test suite | **CARRY** | Testing discipline. Module inventory check, export verification, HTML structure validation, Vite build test, bundle-size budget, PWA manifest check. Nexus should adopt this pattern (adapted for its own module structure). |
| `vite.config.js` | 53 | Build config with code splitting, SW generation | **ARCHIVE** | Build tooling reference. manualChunks for Three.js, SW precache generation plugin. Relevant if Nexus re-commits to Vite. |
| `sw.js` | ~40 | Service worker with precache | **ARCHIVE** | PWA reference. Relevant only if Nexus pursues offline-first PWA. |
| `manifest.json` | ~20 | PWA manifest | **ARCHIVE** | PWA reference. |
14. `world.js`, `effects.js`, `scene-objects.js`, `zones.js` ### Server-Side (Python)
- broad visual foundation work
- should be mined for patterns, not blindly transplanted
15. `test/smoke.mjs` | File | Lines | Capability | Decision | Why for Nexus |
- browser smoke discipline |------|-------|------------|----------|---------------|
- should inform rebuilt validation in canonical Nexus repo | `server/bridge.py` | ~900 | WebSocket bridge server | **ARCHIVE** | Reference. Hermes replaces this role. Keep for protocol schema reference. |
| `server/gateway.py` | ~400 | HTTP gateway | **ARCHIVE** | Reference. |
| `server/ollama_client.py` | ~280 | Ollama integration | **ARCHIVE** | Reference. Relevant if Nexus needs local model calls. |
| `server/research.py` | ~450 | Research pipeline | **ARCHIVE** | Reference. |
| `server/webhooks.py` | ~350 | Webhook handler | **ARCHIVE** | Reference. |
| `server/test_*.py` | ~5 files | Server test suites | **ARCHIVE** | Testing patterns worth studying. |
### Archive as reference, not direct carry-forward ## Summary by Decision
- demo/autopilot assumptions that pretend fake backend activity is real ### CARRY FORWARD (17 modules)
- any websocket schema that no longer matches Hermes truth These modules contain patterns, algorithms, or entire implementations that should move into the Nexus browser shell:
- Vite-specific plumbing that is only useful if we consciously recommit to Vite
### Deliberately drop unless re-justified - `quality.js` — hardware detection
- `storage.js` — safe persistence
- `world.js` — scene foundation
- `agent-defs.js` — agent data model
- `agents.js` — agent visualization + movement
- `presence.js` — online presence HUD
- `visitor.js` — session lifecycle
- `avatar.js` — FPS embodiment
- `interaction.js` — click/select/raycast
- `zones.js` — spatial triggers
- `bark.js` — speech bubbles
- `ui.js` — chat/HUD
- `effects.js` — particle effects
- `ambient.js` — mood atmosphere
- `satflow.js` — payment flow particles
- `scene-objects.js` — dynamic objects + portals
- `test/smoke.mjs` — smoke test discipline
- anything that presents mock data as if it were live ### ARCHIVE AS REFERENCE (9 modules/files)
- anything that duplicates a better Hermes-native telemetry path Keep for patterns, protocol schemas, and architectural reference. Do not directly transplant:
- anything that turns the browser into the system of record
- `config.js` — config pattern (use Hermes instead)
- `behaviors.js` — behavior architecture (use Hermes-driven state)
- `transcript.js` — transcript UX (use Hermes storage)
- `economy.js` — economy UI pattern (use real metrics)
- `websocket.js` — message protocol catalog + reconnection patterns
- `vite.config.js` — build tooling
- `sw.js`, `manifest.json` — PWA reference
- `server/*.py` — server protocol schemas
### DELIBERATELY DROP (2)
Do not preserve unless re-justified:
- `demo.js` — fake activity simulation; creates false impression of live system
- `main.js` monolithic wiring — the init pattern carries, the specific module wiring does not
## Concern Separation for Nexus vNext ## Concern Separation for Nexus vNext
When rebuilding inside `the-nexus`, keep concerns separated: When rebuilding inside `the-nexus`, keep these concerns in separate modules:
1. World shell / rendering 1. **World shell** — scene, camera, renderer, grid, lights, fog
- scene, camera, movement, atmosphere 2. **Effects layer** — rain, stars, ambient mood transitions
3. **Agent visualization** — 3D objects, labels, connection lines, movement
2. Presence and embodiment 4. **Visitor embodiment** — avatar, FPS controls, PiP camera
- avatar, agent placement, selection, bark/chat surfaces 5. **Interaction layer** — raycasting, selection, zones, portal traversal
6. **Communication surface** — bark, chat panel, streaming tokens
3. Harness bridge 7. **Presence & HUD** — who's-online, economy panel, transcript controls
- websocket / API bridge from Hermes truth into browser state 8. **Harness bridge** — WebSocket/API transport to Hermes (NOT a copy of websocket.js)
9. **Quality & config** — hardware detection, runtime configuration
4. Visualization panels 10. **Smoke tests** — automated validation
- metrics, presence, economy, portal states, transcripts
5. Validation
- smoke tests, screenshot proof, provenance checks
6. Game portal layer
- Morrowind / portal-specific interaction surfaces
Do not collapse all of this into one giant app file again. Do not collapse all of this into one giant app file again.
Do not let visual shell code become telemetry authority. Do not let visual shell code become telemetry authority.

79
app.js
View File

@@ -2429,15 +2429,6 @@ function activatePortal(portal) {
overlay.style.display = 'flex'; overlay.style.display = 'flex';
// Readiness detail for game-world portals
const readinessEl = document.getElementById('portal-readiness-detail');
if (portal.config.portal_type === 'game-world' && portal.config.readiness_steps) {
renderReadinessDetail(readinessEl, portal.config);
readinessEl.style.display = 'block';
} else {
readinessEl.style.display = 'none';
}
if (portal.config.destination && portal.config.destination.url) { if (portal.config.destination && portal.config.destination.url) {
redirectBox.style.display = 'block'; redirectBox.style.display = 'block';
errorBox.style.display = 'none'; errorBox.style.display = 'none';
@@ -2459,37 +2450,6 @@ function activatePortal(portal) {
} }
} }
// ═══ READINESS RENDERING ═══
function renderReadinessDetail(container, config) {
const steps = config.readiness_steps || {};
const stepKeys = ['downloaded', 'runtime_ready', 'launched', 'harness_bridged'];
let html = '<div class="portal-readiness-title">READINESS PIPELINE</div>';
let firstUndone = true;
stepKeys.forEach(key => {
const step = steps[key];
if (!step) return;
const cls = step.done ? 'done' : (firstUndone ? 'current' : '');
if (!step.done) firstUndone = false;
html += `<div class="portal-readiness-step ${cls}">
<span class="step-dot"></span>
<span>${step.label || key}</span>
</div>`;
});
if (config.blocked_reason) {
html += `<div class="portal-readiness-blocked">&#x26A0; ${config.blocked_reason}</div>`;
}
const doneCount = stepKeys.filter(k => steps[k]?.done).length;
const canEnter = doneCount === stepKeys.length && config.destination?.url;
if (!canEnter) {
html += `<div class="portal-readiness-hint">Cannot enter yet — ${stepKeys.length - doneCount} step${stepKeys.length - doneCount > 1 ? 's' : ''} remaining.</div>`;
}
container.innerHTML = html;
}
function closePortalOverlay() { function closePortalOverlay() {
portalOverlayActive = false; portalOverlayActive = false;
document.getElementById('portal-overlay').style.display = 'none'; document.getElementById('portal-overlay').style.display = 'none';
@@ -2570,42 +2530,12 @@ function populateAtlas() {
const statusClass = `status-${config.status || 'online'}`; const statusClass = `status-${config.status || 'online'}`;
// Build readiness section for game-world portals
let readinessHtml = '';
if (config.portal_type === 'game-world' && config.readiness_steps) {
const stepKeys = ['downloaded', 'runtime_ready', 'launched', 'harness_bridged'];
const steps = config.readiness_steps;
const doneCount = stepKeys.filter(k => steps[k]?.done).length;
const pct = Math.round((doneCount / stepKeys.length) * 100);
const barColor = config.color || '#ffd700';
readinessHtml = `<div class="atlas-card-readiness">
<div class="readiness-bar-track">
<div class="readiness-bar-fill" style="width:${pct}%;background:${barColor};"></div>
</div>
<div class="readiness-steps-mini">`;
let firstUndone = true;
stepKeys.forEach(key => {
const step = steps[key];
if (!step) return;
const cls = step.done ? 'done' : (firstUndone ? 'current' : '');
if (!step.done) firstUndone = false;
readinessHtml += `<span class="readiness-step ${cls}">${step.label || key}</span>`;
});
readinessHtml += '</div>';
if (config.blocked_reason) {
readinessHtml += `<div class="atlas-card-blocked">&#x26A0; ${config.blocked_reason}</div>`;
}
readinessHtml += '</div>';
}
card.innerHTML = ` card.innerHTML = `
<div class="atlas-card-header"> <div class="atlas-card-header">
<div class="atlas-card-name">${config.name}</div> <div class="atlas-card-name">${config.name}</div>
<div class="atlas-card-status ${statusClass}">${config.readiness_state || config.status || 'ONLINE'}</div> <div class="atlas-card-status ${statusClass}">${config.status || 'ONLINE'}</div>
</div> </div>
<div class="atlas-card-desc">${config.description}</div> <div class="atlas-card-desc">${config.description}</div>
${readinessHtml}
<div class="atlas-card-footer"> <div class="atlas-card-footer">
<div class="atlas-card-coord">X:${config.position.x} Z:${config.position.z}</div> <div class="atlas-card-coord">X:${config.position.x} Z:${config.position.z}</div>
<div class="atlas-card-type">${config.destination?.type?.toUpperCase() || 'UNKNOWN'}</div> <div class="atlas-card-type">${config.destination?.type?.toUpperCase() || 'UNKNOWN'}</div>
@@ -2623,14 +2553,11 @@ function populateAtlas() {
document.getElementById('atlas-online-count').textContent = onlineCount; document.getElementById('atlas-online-count').textContent = onlineCount;
document.getElementById('atlas-standby-count').textContent = standbyCount; document.getElementById('atlas-standby-count').textContent = standbyCount;
// Update Bannerlord HUD status with honest readiness state // Update Bannerlord HUD status
const bannerlord = portals.find(p => p.config.id === 'bannerlord'); const bannerlord = portals.find(p => p.config.id === 'bannerlord');
if (bannerlord) { if (bannerlord) {
const statusEl = document.getElementById('bannerlord-status'); const statusEl = document.getElementById('bannerlord-status');
const state = bannerlord.config.readiness_state || bannerlord.config.status || 'offline'; statusEl.className = 'hud-status-item ' + (bannerlord.config.status || 'offline');
statusEl.className = 'hud-status-item ' + state;
const labelEl = statusEl.querySelector('.status-label');
if (labelEl) labelEl.textContent = state.toUpperCase().replace(/_/g, ' ');
} }
} }

View File

@@ -196,7 +196,6 @@
</div> </div>
<h2 id="portal-name-display">MORROWIND</h2> <h2 id="portal-name-display">MORROWIND</h2>
<p id="portal-desc-display">The Vvardenfell harness. Ash storms and ancient mysteries.</p> <p id="portal-desc-display">The Vvardenfell harness. Ash storms and ancient mysteries.</p>
<div id="portal-readiness-detail" class="portal-readiness-detail" style="display:none;"></div>
<div class="portal-redirect-box" id="portal-redirect-box"> <div class="portal-redirect-box" id="portal-redirect-box">
<div class="portal-redirect-label">REDIRECTING IN</div> <div class="portal-redirect-label">REDIRECTING IN</div>
<div class="portal-redirect-timer" id="portal-timer">5</div> <div class="portal-redirect-timer" id="portal-timer">5</div>

View File

@@ -17,7 +17,7 @@
"id": "bannerlord", "id": "bannerlord",
"name": "Bannerlord", "name": "Bannerlord",
"description": "Calradia battle harness. Massive armies, tactical command.", "description": "Calradia battle harness. Massive armies, tactical command.",
"status": "downloaded", "status": "active",
"color": "#ffd700", "color": "#ffd700",
"position": { "x": -15, "y": 0, "z": -10 }, "position": { "x": -15, "y": 0, "z": -10 },
"rotation": { "y": 0.5 }, "rotation": { "y": 0.5 },
@@ -25,20 +25,13 @@
"world_category": "strategy-rpg", "world_category": "strategy-rpg",
"environment": "production", "environment": "production",
"access_mode": "operator", "access_mode": "operator",
"readiness_state": "downloaded", "readiness_state": "active",
"readiness_steps": {
"downloaded": { "label": "Downloaded", "done": true },
"runtime_ready": { "label": "Runtime Ready", "done": false },
"launched": { "label": "Launched", "done": false },
"harness_bridged": { "label": "Harness Bridged", "done": false }
},
"blocked_reason": null,
"telemetry_source": "hermes-harness:bannerlord", "telemetry_source": "hermes-harness:bannerlord",
"owner": "Timmy", "owner": "Timmy",
"app_id": 261550, "app_id": 261550,
"window_title": "Mount & Blade II: Bannerlord", "window_title": "Mount & Blade II: Bannerlord",
"destination": { "destination": {
"url": null, "url": "https://bannerlord.timmy.foundation",
"type": "harness", "type": "harness",
"action_label": "Enter Calradia", "action_label": "Enter Calradia",
"params": { "world": "calradia" } "params": { "world": "calradia" }

136
style.css
View File

@@ -367,142 +367,6 @@ canvas#nexus-canvas {
.status-online { background: rgba(74, 240, 192, 0.2); color: var(--color-primary); border: 1px solid var(--color-primary); } .status-online { background: rgba(74, 240, 192, 0.2); color: var(--color-primary); border: 1px solid var(--color-primary); }
.status-standby { background: rgba(255, 215, 0, 0.2); color: var(--color-gold); border: 1px solid var(--color-gold); } .status-standby { background: rgba(255, 215, 0, 0.2); color: var(--color-gold); border: 1px solid var(--color-gold); }
.status-offline { background: rgba(255, 68, 102, 0.2); color: var(--color-danger); border: 1px solid var(--color-danger); } .status-offline { background: rgba(255, 68, 102, 0.2); color: var(--color-danger); border: 1px solid var(--color-danger); }
.status-active { background: rgba(74, 240, 192, 0.2); color: var(--color-primary); border: 1px solid var(--color-primary); }
.status-blocked { background: rgba(255, 68, 102, 0.3); color: #ff4466; border: 1px solid #ff4466; }
.status-downloaded { background: rgba(100, 149, 237, 0.2); color: #6495ed; border: 1px solid #6495ed; }
.status-runtime_ready { background: rgba(255, 165, 0, 0.2); color: #ffa500; border: 1px solid #ffa500; }
.status-launched { background: rgba(255, 215, 0, 0.2); color: var(--color-gold); border: 1px solid var(--color-gold); }
.status-harness_bridged { background: rgba(74, 240, 192, 0.2); color: var(--color-primary); border: 1px solid var(--color-primary); }
/* Readiness Progress Bar (atlas card) */
.atlas-card-readiness {
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid rgba(255,255,255,0.06);
}
.readiness-bar-track {
width: 100%;
height: 4px;
background: rgba(255,255,255,0.08);
border-radius: 2px;
overflow: hidden;
margin-bottom: 6px;
}
.readiness-bar-fill {
height: 100%;
border-radius: 2px;
transition: width 0.4s ease;
}
.readiness-steps-mini {
display: flex;
gap: 6px;
font-size: 9px;
font-family: var(--font-body);
letter-spacing: 0.05em;
color: var(--color-text-muted);
}
.readiness-step {
padding: 1px 5px;
border-radius: 2px;
background: rgba(255,255,255,0.04);
}
.readiness-step.done {
background: rgba(74, 240, 192, 0.15);
color: var(--color-primary);
}
.readiness-step.current {
background: rgba(255, 215, 0, 0.15);
color: var(--color-gold);
}
.atlas-card-blocked {
margin-top: 6px;
font-size: 10px;
color: #ff4466;
font-family: var(--font-body);
}
/* Readiness Detail (portal overlay) */
.portal-readiness-detail {
margin-top: 16px;
padding: 12px 16px;
background: rgba(0,0,0,0.3);
border: 1px solid rgba(255,255,255,0.08);
border-radius: 4px;
}
.portal-readiness-title {
font-family: var(--font-display);
font-size: 10px;
letter-spacing: 0.15em;
color: var(--color-text-muted);
margin-bottom: 10px;
text-transform: uppercase;
}
.portal-readiness-step {
display: flex;
align-items: center;
gap: 8px;
padding: 4px 0;
font-family: var(--font-body);
font-size: 11px;
color: rgba(255,255,255,0.4);
}
.portal-readiness-step .step-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: rgba(255,255,255,0.15);
flex-shrink: 0;
}
.portal-readiness-step.done .step-dot {
background: var(--color-primary);
box-shadow: 0 0 6px var(--color-primary);
}
.portal-readiness-step.done {
color: var(--color-primary);
}
.portal-readiness-step.current .step-dot {
background: var(--color-gold);
box-shadow: 0 0 6px var(--color-gold);
animation: pulse-dot 1.5s ease-in-out infinite;
}
.portal-readiness-step.current {
color: #fff;
}
@keyframes pulse-dot {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
.portal-readiness-blocked {
margin-top: 8px;
padding: 6px 10px;
background: rgba(255, 68, 102, 0.1);
border: 1px solid rgba(255, 68, 102, 0.3);
border-radius: 3px;
font-size: 11px;
color: #ff4466;
font-family: var(--font-body);
}
.portal-readiness-hint {
margin-top: 8px;
font-size: 10px;
color: var(--color-text-muted);
font-family: var(--font-body);
font-style: italic;
}
/* HUD Status for readiness states */
.hud-status-item.downloaded .status-dot { background: #6495ed; box-shadow: 0 0 5px #6495ed; }
.hud-status-item.runtime_ready .status-dot { background: #ffa500; box-shadow: 0 0 5px #ffa500; }
.hud-status-item.launched .status-dot { background: var(--color-gold); box-shadow: 0 0 5px var(--color-gold); }
.hud-status-item.harness_bridged .status-dot { background: var(--color-primary); box-shadow: 0 0 5px var(--color-primary); }
.hud-status-item.blocked .status-dot { background: #ff4466; box-shadow: 0 0 5px #ff4466; }
.hud-status-item.downloaded .status-label,
.hud-status-item.runtime_ready .status-label,
.hud-status-item.launched .status-label,
.hud-status-item.harness_bridged .status-label,
.hud-status-item.blocked .status-label {
color: #fff;
}
.atlas-card-desc { .atlas-card-desc {
font-size: 12px; font-size: 12px;