Compare commits

..

1 Commits

Author SHA1 Message Date
mimo-v2-pro
8057e7d00c fix: [PORTALS] Add destination preview cards with description, purpose, and readiness (closes #715)
Some checks failed
CI / test (pull_request) Failing after 11s
CI / validate (pull_request) Failing after 14s
Review Approval Gate / verify-review (pull_request) Failing after 6s
2026-04-10 20:18:38 -04:00
4 changed files with 428 additions and 162 deletions

View File

@@ -1,169 +1,132 @@
# Legacy Matrix Audit — Migration Table
# Legacy Matrix Audit
Purpose:
Preserve quality work from `/Users/apayne/the-matrix` before the Nexus browser shell is rebuilt.
Preserve useful work from `/Users/apayne/the-matrix` before the Nexus browser shell is rebuilt.
Canonical rule:
- `Timmy_Foundation/the-nexus` is the only canonical 3D repo.
- `/Users/apayne/the-matrix` is legacy source material, not a parallel product.
- This document is the authoritative migration table for issue #685.
## Verified Legacy State
## Verified Legacy Matrix State
Local legacy repo: `/Users/apayne/the-matrix`
Local legacy repo:
- `/Users/apayne/the-matrix`
Observed facts:
- Vite browser app, vanilla JS + Three.js 0.171.0
- 24 JS modules under `js/`
- Smoke suite: 87 passed, 0 failed
- 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
- Vite browser app exists
- `npm test` passes with `87 passed, 0 failed`
- 23 JS modules under `js/`
- package scripts include `dev`, `build`, `preview`, and `test`
## Migration Table
## Known historical Nexus snapshot
Decision key:
- **CARRY** = transplant concepts and patterns into Nexus vNext
- **ARCHIVE** = keep as reference, do not directly transplant
- **DROP** = do not preserve unless re-justified
Useful in-repo reference point:
- `0518a1c3ae3c1d0afeb24dea9772102f5a3d9a66`
### Core Modules
That snapshot still contains browser-world root files such as:
- `index.html`
- `app.js`
- `style.css`
- `package.json`
- `tests/`
| 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. |
## Rescue Candidates
### Agent System
### Carry forward into Nexus vNext
| File | Lines | Capability | Decision | Why for Nexus |
|------|-------|------------|----------|---------------|
| `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. |
1. `agent-defs.js`
- agent identity definitions
- useful as seed data/model for visible entities in the world
### Visitor & Interaction
2. `agents.js`
- agent objects, state machine, connection lines
- useful for visualizing Timmy / subagents / system processes in a world-native way
| File | Lines | Capability | Decision | Why for Nexus |
|------|-------|------------|----------|---------------|
| `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. |
3. `avatar.js`
- visitor embodiment, movement, camera handling
- strongly aligned with "training ground" and "walk the world" goals
### Chat & Communication
4. `ui.js`
- HUD, chat surfaces, overlays
- useful if rebuilt against real harness data instead of stale fake state
| File | Lines | Capability | Decision | Why for Nexus |
|------|-------|------------|----------|---------------|
| `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. |
5. `websocket.js`
- browser-side live bridge patterns
- useful if retethered to Hermes-facing transport
### Visual Effects
6. `transcript.js`
- local transcript capture pattern
- useful if durable truth still routes through Hermes and browser cache remains secondary
| File | Lines | Capability | Decision | Why for Nexus |
|------|-------|------------|----------|---------------|
| `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. |
7. `ambient.js`
- mood / atmosphere system
- directly supports wizardly presentation without changing system authority
### Economy & Scene
8. `satflow.js`
- visual economy / payment flow motifs
- useful if Timmy's economy/agent interactions become a real visible layer
| File | Lines | Capability | Decision | Why for Nexus |
|------|-------|------------|----------|---------------|
| `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. |
9. `economy.js`
- treasury / wallet panel ideas
- useful if later backed by real sovereign metrics
### Backend Bridge
10. `presence.js`
- who-is-here / online-state UI
- useful for showing human + agent + process presence in the world
| File | Lines | Capability | Decision | Why for Nexus |
|------|-------|------------|----------|---------------|
| `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. |
11. `interaction.js`
- clicking, inspecting, selecting world entities
- likely needed in any real browser-facing Nexus shell
### Testing & Build
12. `quality.js`
- hardware-aware quality tiering
- useful for local-first graceful degradation on Mac hardware
| File | Lines | Capability | Decision | Why for Nexus |
|------|-------|------------|----------|---------------|
| `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. |
13. `bark.js`
- prominent speech / bark system
- strong fit for Timmy's expressive presence in-world
### Server-Side (Python)
14. `world.js`, `effects.js`, `scene-objects.js`, `zones.js`
- broad visual foundation work
- should be mined for patterns, not blindly transplanted
| File | Lines | Capability | Decision | Why for Nexus |
|------|-------|------------|----------|---------------|
| `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. |
15. `test/smoke.mjs`
- browser smoke discipline
- should inform rebuilt validation in canonical Nexus repo
## Summary by Decision
### Archive as reference, not direct carry-forward
### CARRY FORWARD (17 modules)
These modules contain patterns, algorithms, or entire implementations that should move into the Nexus browser shell:
- demo/autopilot assumptions that pretend fake backend activity is real
- any websocket schema that no longer matches Hermes truth
- Vite-specific plumbing that is only useful if we consciously recommit to Vite
- `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
### Deliberately drop unless re-justified
### ARCHIVE AS REFERENCE (9 modules/files)
Keep for patterns, protocol schemas, and architectural reference. Do not directly transplant:
- `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
- anything that presents mock data as if it were live
- anything that duplicates a better Hermes-native telemetry path
- anything that turns the browser into the system of record
## Concern Separation for Nexus vNext
When rebuilding inside `the-nexus`, keep these concerns in separate modules:
When rebuilding inside `the-nexus`, keep concerns separated:
1. **World shell** — scene, camera, renderer, grid, lights, fog
2. **Effects layer** — rain, stars, ambient mood transitions
3. **Agent visualization** — 3D objects, labels, connection lines, movement
4. **Visitor embodiment** — avatar, FPS controls, PiP camera
5. **Interaction layer** — raycasting, selection, zones, portal traversal
6. **Communication surface** — bark, chat panel, streaming tokens
7. **Presence & HUD** — who's-online, economy panel, transcript controls
8. **Harness bridge** — WebSocket/API transport to Hermes (NOT a copy of websocket.js)
9. **Quality & config** — hardware detection, runtime configuration
10. **Smoke tests** — automated validation
1. World shell / rendering
- scene, camera, movement, atmosphere
2. Presence and embodiment
- avatar, agent placement, selection, bark/chat surfaces
3. Harness bridge
- websocket / API bridge from Hermes truth into browser state
4. Visualization panels
- 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 let visual shell code become telemetry authority.

43
app.js
View File

@@ -2405,7 +2405,18 @@ function checkPortalProximity() {
activePortal = closest;
const hint = document.getElementById('portal-hint');
if (activePortal) {
document.getElementById('portal-hint-name').textContent = activePortal.config.name;
const cfg = activePortal.config;
document.getElementById('portal-hint-name').textContent = cfg.name;
document.getElementById('portal-hint-desc').textContent = cfg.description || '';
document.getElementById('portal-hint-purpose').textContent = cfg.purpose || cfg.description || '\u2014';
document.getElementById('portal-hint-access').textContent = (cfg.access_mode || 'open').toUpperCase();
document.getElementById('portal-hint-interaction').textContent = cfg.meaningful_interaction || '\u2014';
const readinessEl = document.getElementById('portal-hint-readiness');
const readiness = cfg.readiness || cfg.status || 'online';
readinessEl.textContent = readiness.toUpperCase();
readinessEl.className = 'portal-preview-readiness readiness-' + readiness;
hint.style.display = 'flex';
} else {
hint.style.display = 'none';
@@ -2422,10 +2433,20 @@ function activatePortal(portal) {
const timerDisplay = document.getElementById('portal-timer');
const statusDot = document.getElementById('portal-status-dot');
nameDisplay.textContent = portal.config.name.toUpperCase();
descDisplay.textContent = portal.config.description;
statusDot.style.background = portal.config.color;
statusDot.style.boxShadow = `0 0 10px ${portal.config.color}`;
const cfg = portal.config;
nameDisplay.textContent = cfg.name.toUpperCase();
descDisplay.textContent = cfg.description;
statusDot.style.background = cfg.color;
statusDot.style.boxShadow = `0 0 10px ${cfg.color}`;
// Populate destination preview details
document.getElementById('portal-purpose-display').textContent = cfg.purpose || cfg.description || '\u2014';
const readinessEl = document.getElementById('portal-readiness-display');
const readiness = cfg.readiness || cfg.status || 'online';
readinessEl.textContent = readiness.toUpperCase();
readinessEl.className = 'portal-readiness readiness-' + readiness;
document.getElementById('portal-access-display').textContent = (cfg.access_mode || 'open').toUpperCase();
document.getElementById('portal-interaction-display').textContent = cfg.meaningful_interaction || '\u2014';
overlay.style.display = 'flex';
@@ -2536,6 +2557,18 @@ function populateAtlas() {
<div class="atlas-card-status ${statusClass}">${config.status || 'ONLINE'}</div>
</div>
<div class="atlas-card-desc">${config.description}</div>
${config.purpose ? `<div class="atlas-card-row"><span class="atlas-card-label">PURPOSE</span> ${config.purpose}</div>` : ''}
<div class="atlas-card-meta">
<div class="atlas-card-meta-item">
<span class="atlas-card-label">READINESS</span>
<span class="atlas-card-readiness readiness-${config.readiness || config.status || 'online'}">${(config.readiness || config.status || 'online').toUpperCase()}</span>
</div>
<div class="atlas-card-meta-item">
<span class="atlas-card-label">ACCESS</span>
<span>${(config.access_mode || 'open').toUpperCase()}</span>
</div>
</div>
${config.meaningful_interaction ? `<div class="atlas-card-row"><span class="atlas-card-label">INTERACTION</span> ${config.meaningful_interaction}</div>` : ''}
<div class="atlas-card-footer">
<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>

View File

@@ -5,13 +5,25 @@
"description": "The Vvardenfell harness. Ash storms and ancient mysteries.",
"status": "online",
"color": "#ff6600",
"position": { "x": 15, "y": 0, "z": -10 },
"rotation": { "y": -0.5 },
"position": {
"x": 15,
"y": 0,
"z": -10
},
"rotation": {
"y": -0.5
},
"destination": {
"url": "https://morrowind.timmy.foundation",
"type": "harness",
"params": { "world": "vvardenfell" }
}
"params": {
"world": "vvardenfell"
}
},
"purpose": "Game world \u2014 exploration, combat, and role-playing in Vvardenfell",
"meaningful_interaction": "Autonomous questing, combat encounters, conversation with NPCs via agent harness",
"access_mode": "open",
"readiness": "online"
},
{
"id": "bannerlord",
@@ -19,8 +31,14 @@
"description": "Calradia battle harness. Massive armies, tactical command.",
"status": "active",
"color": "#ffd700",
"position": { "x": -15, "y": 0, "z": -10 },
"rotation": { "y": 0.5 },
"position": {
"x": -15,
"y": 0,
"z": -10
},
"rotation": {
"y": 0.5
},
"portal_type": "game-world",
"world_category": "strategy-rpg",
"environment": "production",
@@ -34,8 +52,13 @@
"url": "https://bannerlord.timmy.foundation",
"type": "harness",
"action_label": "Enter Calradia",
"params": { "world": "calradia" }
}
"params": {
"world": "calradia"
}
},
"purpose": "Strategy RPG \u2014 tactical army command and battlefield control",
"meaningful_interaction": "Agent-driven campaign, diplomacy, real-time battle command",
"readiness": "active"
},
{
"id": "workshop",
@@ -43,13 +66,25 @@
"description": "The creative harness. Build, script, and manifest.",
"status": "online",
"color": "#4af0c0",
"position": { "x": 0, "y": 0, "z": -20 },
"rotation": { "y": 0 },
"position": {
"x": 0,
"y": 0,
"z": -20
},
"rotation": {
"y": 0
},
"destination": {
"url": "https://workshop.timmy.foundation",
"type": "harness",
"params": { "mode": "creative" }
}
"params": {
"mode": "creative"
}
},
"purpose": "Creative sandbox \u2014 build tools, scripts, and artifacts",
"meaningful_interaction": "Code execution, file creation, prototype building with agent assistance",
"access_mode": "open",
"readiness": "online"
},
{
"id": "archive",
@@ -57,13 +92,25 @@
"description": "The repository of all knowledge. History, logs, and ancient data.",
"status": "online",
"color": "#0066ff",
"position": { "x": 25, "y": 0, "z": 0 },
"rotation": { "y": -1.57 },
"position": {
"x": 25,
"y": 0,
"z": 0
},
"rotation": {
"y": -1.57
},
"destination": {
"url": "https://archive.timmy.foundation",
"type": "harness",
"params": { "mode": "read" }
}
"params": {
"mode": "read"
}
},
"purpose": "Knowledge repository \u2014 logs, history, and stored data",
"meaningful_interaction": "Search, retrieve, analyze historical records and documents",
"access_mode": "read-only",
"readiness": "online"
},
{
"id": "chapel",
@@ -71,13 +118,25 @@
"description": "A sanctuary for reflection and digital peace.",
"status": "online",
"color": "#ffd700",
"position": { "x": -25, "y": 0, "z": 0 },
"rotation": { "y": 1.57 },
"position": {
"x": -25,
"y": 0,
"z": 0
},
"rotation": {
"y": 1.57
},
"destination": {
"url": "https://chapel.timmy.foundation",
"type": "harness",
"params": { "mode": "meditation" }
}
"params": {
"mode": "meditation"
}
},
"purpose": "Sanctuary \u2014 digital peace and reflection space",
"meaningful_interaction": "Meditation interface, contemplative atmosphere, no active tasks",
"access_mode": "open",
"readiness": "online"
},
{
"id": "courtyard",
@@ -85,13 +144,25 @@
"description": "The open nexus. A place for agents to gather and connect.",
"status": "online",
"color": "#4af0c0",
"position": { "x": 15, "y": 0, "z": 10 },
"rotation": { "y": -2.5 },
"position": {
"x": 15,
"y": 0,
"z": 10
},
"rotation": {
"y": -2.5
},
"destination": {
"url": "https://courtyard.timmy.foundation",
"type": "harness",
"params": { "mode": "social" }
}
"params": {
"mode": "social"
}
},
"purpose": "Social nexus \u2014 agent gathering and connection point",
"meaningful_interaction": "Agent presence, inter-agent communication, shared context",
"access_mode": "open",
"readiness": "online"
},
{
"id": "gate",
@@ -99,12 +170,24 @@
"description": "The transition point. Entry and exit from the Nexus core.",
"status": "standby",
"color": "#ff4466",
"position": { "x": -15, "y": 0, "z": 10 },
"rotation": { "y": 2.5 },
"position": {
"x": -15,
"y": 0,
"z": 10
},
"rotation": {
"y": 2.5
},
"destination": {
"url": "https://gate.timmy.foundation",
"type": "harness",
"params": { "mode": "transit" }
}
"params": {
"mode": "transit"
}
},
"purpose": "Transit point \u2014 entry and exit from Nexus core",
"meaningful_interaction": "System transit, routing, session management",
"access_mode": "open",
"readiness": "standby"
}
]
]

187
style.css
View File

@@ -383,6 +383,52 @@ canvas#nexus-canvas {
font-size: 10px;
color: rgba(160, 184, 208, 0.6);
}
.atlas-card-row {
font-size: 12px;
color: rgba(224, 240, 255, 0.65);
margin-bottom: 8px;
line-height: 1.4;
}
.atlas-card-label {
font-family: 'JetBrains Mono', monospace;
font-size: 9px;
font-weight: 600;
color: var(--portal-color, var(--color-primary));
letter-spacing: 0.1em;
margin-right: 6px;
opacity: 0.8;
}
.atlas-card-meta {
display: flex;
gap: 20px;
margin-bottom: 10px;
}
.atlas-card-meta-item {
font-size: 11px;
color: rgba(224, 240, 255, 0.6);
}
.atlas-card-readiness {
font-family: 'JetBrains Mono', monospace;
font-size: 10px;
font-weight: 600;
padding: 1px 6px;
border-radius: 3px;
letter-spacing: 0.06em;
}
.atlas-card-readiness.readiness-online,
.atlas-card-readiness.readiness-active {
background: rgba(74, 240, 192, 0.12);
color: #4af0c0;
}
.atlas-card-readiness.readiness-standby {
background: rgba(255, 215, 0, 0.1);
color: #ffd700;
}
.atlas-card-readiness.readiness-offline {
background: rgba(255, 68, 102, 0.1);
color: #ff4466;
}
.atlas-footer {
padding: 15px 30px;
@@ -653,6 +699,95 @@ canvas#nexus-canvas {
border-radius: 4px;
animation: hint-float 2s ease-in-out infinite;
}
/* Portal Preview Card */
.portal-preview-card {
background: rgba(10, 15, 30, 0.95);
border: 1px solid var(--portal-color, var(--color-primary));
border-radius: 6px;
padding: 16px 20px;
min-width: 300px;
max-width: 400px;
backdrop-filter: blur(12px);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6);
}
.portal-preview-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.portal-preview-name {
font-family: 'Orbitron', sans-serif;
font-size: 16px;
font-weight: 700;
color: var(--portal-color, var(--color-primary));
letter-spacing: 0.1em;
}
.portal-preview-readiness {
font-family: 'JetBrains Mono', monospace;
font-size: 10px;
font-weight: 600;
padding: 2px 8px;
border-radius: 3px;
letter-spacing: 0.08em;
}
.portal-preview-readiness.readiness-online,
.portal-preview-readiness.readiness-active {
background: rgba(74, 240, 192, 0.15);
color: #4af0c0;
border: 1px solid rgba(74, 240, 192, 0.3);
}
.portal-preview-readiness.readiness-standby {
background: rgba(255, 215, 0, 0.12);
color: #ffd700;
border: 1px solid rgba(255, 215, 0, 0.3);
}
.portal-preview-readiness.readiness-offline {
background: rgba(255, 68, 102, 0.12);
color: #ff4466;
border: 1px solid rgba(255, 68, 102, 0.3);
}
.portal-preview-desc {
font-size: 13px;
color: rgba(224, 240, 255, 0.7);
margin-bottom: 12px;
line-height: 1.4;
}
.portal-preview-meta {
font-size: 12px;
color: rgba(224, 240, 255, 0.6);
margin-bottom: 6px;
line-height: 1.4;
}
.portal-preview-label {
font-family: 'JetBrains Mono', monospace;
font-size: 9px;
font-weight: 600;
color: var(--portal-color, var(--color-primary));
letter-spacing: 0.1em;
margin-right: 6px;
opacity: 0.8;
}
.portal-preview-footer {
display: flex;
align-items: center;
gap: 8px;
margin-top: 12px;
padding-top: 10px;
border-top: 1px solid rgba(255, 255, 255, 0.08);
font-size: 12px;
color: rgba(224, 240, 255, 0.5);
}
.portal-hint-key {
background: var(--portal-color, var(--color-primary));
color: var(--color-bg);
font-weight: 700;
font-size: 11px;
padding: 2px 8px;
border-radius: 3px;
}
@keyframes hint-float {
0%, 100% { transform: translate(-50%, 100px); }
50% { transform: translate(-50%, 90px); }
@@ -842,6 +977,58 @@ canvas#nexus-canvas {
text-align: center;
padding: var(--space-8);
}
.portal-overlay-details {
text-align: left;
margin: 16px auto;
max-width: 400px;
padding: 12px 16px;
background: rgba(10, 15, 30, 0.5);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 6px;
}
.portal-overlay-detail-row {
display: flex;
justify-content: space-between;
align-items: baseline;
padding: 6px 0;
font-size: 13px;
color: rgba(224, 240, 255, 0.7);
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
}
.portal-overlay-detail-row:last-child {
border-bottom: none;
}
.portal-overlay-detail-label {
font-family: 'JetBrains Mono', monospace;
font-size: 10px;
font-weight: 600;
color: var(--color-primary);
letter-spacing: 0.1em;
opacity: 0.8;
min-width: 90px;
}
.portal-readiness {
font-family: 'JetBrains Mono', monospace;
font-size: 10px;
font-weight: 600;
padding: 1px 6px;
border-radius: 3px;
letter-spacing: 0.06em;
}
.portal-readiness.readiness-online,
.portal-readiness.readiness-active {
background: rgba(74, 240, 192, 0.12);
color: #4af0c0;
}
.portal-readiness.readiness-standby {
background: rgba(255, 215, 0, 0.1);
color: #ffd700;
}
.portal-readiness.readiness-offline {
background: rgba(255, 68, 102, 0.1);
color: #ff4466;
}
.portal-overlay-header {
display: flex;
align-items: center;