SIMON Master Console Rebuild
True command center for SIMON + WEB360
This rebuild gives you a cleaner production spine: interactive tree, live viewer, guarded editor, dynamic graphics, architecture map, and note storage. It is designed to sit beside your existing
console.php
and become the stronger replacement path.
Dashboard
Tree
Viewer
System Map
File Registry
Notes
Files
15,310
Folders
408
Scanned Size
3.84 GB
PHP Files
891
Editable Text Files
12,571
File viewer
guarded to /htdocs
/simon/old/master.php
<?php /** * SIMON Intelligence — Unified Master Console * Suggested path: /htdocs/simon/console.php * * Single-file command center that consolidates: * /simon/console.php * /simon/dashboard.php * /simon/projects.php * /simon/accounting.php * /simon/assets.php * /simon/investor.php * /simon/roadmap.php * /simon/links.php * /simon/analytics.php * /simon/security_console.php * /simon/social_dashboard.php * /simon/forecast.php * /simon/ai_review.php */ declare(strict_types=1); date_default_timezone_set('America/Chicago'); error_reporting(E_ALL); ini_set('display_errors', '0'); const SIMON_NAME = 'SIMON Intelligence'; const SIMON_SUBTITLE = 'Unified Master Console'; const SIMON_VERSION = 'v4.0 Unified'; $baseDir = __DIR__; $dataDir = $baseDir . '/data'; $logsDir = $baseDir . '/logs'; $configDir = $baseDir . '/config'; $apiDir = $baseDir . '/api'; $rootDir = dirname(__DIR__); if (!is_dir($dataDir)) { @mkdir($dataDir, 0775, true); } function h(?string $value): string { return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); } function read_json(string $path, array $fallback = []): array { if (!is_file($path)) return $fallback; $raw = @file_get_contents($path); if ($raw === false || trim($raw) === '') return $fallback; $decoded = json_decode($raw, true); return is_array($decoded) ? $decoded : $fallback; } function money(float $value): string { return '$' . number_format($value, 0); } function money2(float $value): string { return '$' . number_format($value, 2); } function compact_num(float $value): string { $abs = abs($value); if ($abs >= 1000000000) return number_format($value / 1000000000, 2) . 'B'; if ($abs >= 1000000) return number_format($value / 1000000, 2) . 'M'; if ($abs >= 1000) return number_format($value / 1000, 1) . 'K'; return number_format($value, 0); } function pct(float $value, int $decimals = 0): string { return number_format($value, $decimals) . '%'; } function avg_numeric(array $values): float { $nums = array_values(array_filter($values, static fn($v) => is_numeric($v))); if (!$nums) return 0.0; return array_sum($nums) / count($nums); } function clampf(float $v, float $min, float $max): float { return max($min, min($max, $v)); } function status_class(string $status): string { $s = strtolower(trim($status)); return match ($s) { 'online', 'healthy', 'stable', 'active', 'done', 'complete', 'connected', 'good', 'nominal' => 'ok', 'warning', 'warn', 'degraded', 'pending', 'partial', 'in progress', 'in_progress', 'planned' => 'warn', 'offline', 'critical', 'failed', 'blocked', 'missing', 'error' => 'bad', default => 'neutral', }; } function file_health(string $path): array { return [ 'exists' => is_file($path), 'readable' => is_readable($path), 'writable' => is_writable($path), 'size' => is_file($path) ? (int)filesize($path) : 0, 'mtime' => is_file($path) ? (int)filemtime($path) : 0, 'path' => $path, ]; } function format_bytes(int $bytes): string { $units = ['B','KB','MB','GB','TB']; $i = 0; $size = (float)$bytes; while ($size >= 1024 && $i < count($units) - 1) { $size /= 1024; $i++; } return number_format($size, $i === 0 ? 0 : 2) . ' ' . $units[$i]; } function rel_path(string $root, string $full): string { $root = rtrim(str_replace('\\', '/', realpath($root) ?: $root), '/'); $full = str_replace('\\', '/', $full); if (str_starts_with($full, $root)) { $rel = substr($full, strlen($root)); return $rel === '' ? '/' : $rel; } return $full; } function scan_tree(string $root, int $maxDepth = 3): array { $out = []; $rootReal = realpath($root) ?: $root; $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($rootReal, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST ); foreach ($iterator as $file) { $depth = $iterator->getDepth(); if ($depth > $maxDepth) continue; $path = $file->getPathname(); $name = $file->getFilename(); if (str_starts_with($name, '.')) continue; $out[] = [ 'name' => $name, 'path' => rel_path($rootReal, $path), 'type' => $file->isDir() ? 'dir' : 'file', 'size' => $file->isFile() ? (int)$file->getSize() : 0, 'mtime' => (int)$file->getMTime(), 'ext' => $file->isFile() ? strtolower(pathinfo($name, PATHINFO_EXTENSION)) : '', ]; } return $out; } $defaultProjects = [ ['title' => 'SIMON Intelligence', 'status' => 'Active', 'phase' => 'Foundation', 'completion_percent' => 74, 'owner' => 'Keith', 'priority' => 'High'], ['title' => 'WEB360 Studio', 'status' => 'Active', 'phase' => 'Builder Engine', 'completion_percent' => 69, 'owner' => 'Keith', 'priority' => 'High'], ['title' => 'SIMON Social Matrix', 'status' => 'Planned', 'phase' => 'Automation', 'completion_percent' => 28, 'owner' => 'Keith', 'priority' => 'High'], ['title' => 'Investor Relations Suite', 'status' => 'In Progress', 'phase' => 'Reporting', 'completion_percent' => 42, 'owner' => 'Keith', 'priority' => 'Medium'], ['title' => 'Security Console', 'status' => 'In Progress', 'phase' => 'Infrastructure', 'completion_percent' => 38, 'owner' => 'Keith', 'priority' => 'High'], ]; $defaultTasks = [ ['title' => 'Build API request proxy', 'status' => 'todo', 'priority' => 'high', 'module' => 'API Gateway'], ['title' => 'Wire live tracking system', 'status' => 'in_progress', 'priority' => 'high', 'module' => 'Links'], ['title' => 'Finish investor metrics view', 'status' => 'todo', 'priority' => 'medium', 'module' => 'Investor'], ['title' => 'Polish console tabs shell', 'status' => 'done', 'priority' => 'medium', 'module' => 'Console'], ['title' => 'Create AI recommendation weights', 'status' => 'in_progress', 'priority' => 'high', 'module' => 'AI Review'], ]; $defaultAssets = [ ['name' => 'SIMON Intelligence Platform', 'category' => 'software', 'value' => 250000, 'status' => 'active'], ['name' => 'WEB360 Studio', 'category' => 'software', 'value' => 180000, 'status' => 'active'], ['name' => 'Books / Art / Comics Portfolio', 'category' => 'content', 'value' => 120000, 'status' => 'active'], ['name' => 'Social Automation Engine', 'category' => 'software', 'value' => 200000, 'status' => 'planned'], ['name' => 'Investor Console', 'category' => 'software', 'value' => 95000, 'status' => 'in progress'], ]; $defaultLinkEvents = [ ['destination_url' => '/books/', 'link_type' => 'internal', 'revenue_value' => 120, 'clicks' => 124], ['destination_url' => '/web360/', 'link_type' => 'internal', 'revenue_value' => 240, 'clicks' => 198], ['destination_url' => '/simon/', 'link_type' => 'internal', 'revenue_value' => 180, 'clicks' => 167], ['destination_url' => 'https://apps.apple.com/', 'link_type' => 'external', 'revenue_value' => 60, 'clicks' => 22], ]; $defaultMacros = [ ['name' => 'Launch Project Macro', 'scope' => 'projects', 'status' => 'ready'], ['name' => 'Link Audit Macro', 'scope' => 'links', 'status' => 'ready'], ['name' => 'Investor Summary Macro', 'scope' => 'reports', 'status' => 'draft'], ['name' => 'Daily AI Review', 'scope' => 'intelligence', 'status' => 'planned'], ]; $defaultAnalytics = [ 'traffic' => ['visits_today' => 189, 'visits_7d' => 1320, 'visits_30d' => 5840, 'conversion_rate' => 4.2, 'bounce_rate' => 36.4, 'avg_session_minutes' => 3.8], 'channels' => [ ['name' => 'Organic', 'visits' => 2140], ['name' => 'Direct', 'visits' => 1380], ['name' => 'Social', 'visits' => 1170], ['name' => 'Referral', 'visits' => 650], ['name' => 'Paid', 'visits' => 500], ], 'top_pages' => [ ['path' => '/web360/', 'views' => 1240], ['path' => '/simon/', 'views' => 1115], ['path' => '/books/', 'views' => 760], ['path' => '/art/', 'views' => 605], ['path' => '/infinity/', 'views' => 480], ], ]; $defaultSystem = [ 'status' => 'Nominal', 'api' => 'Connected', 'storage' => 'Healthy', 'uptime' => '99.9%', 'modules' => [ ['name' => 'SIMON Core', 'status' => 'online'], ['name' => 'WEB360', 'status' => 'online'], ['name' => 'API Gateway', 'status' => 'in progress'], ['name' => 'Social Matrix', 'status' => 'planned'], ['name' => 'Security Layer', 'status' => 'online'], ['name' => 'Forecast Engine', 'status' => 'warning'], ['name' => 'AI Review', 'status' => 'in progress'], ], 'server' => [ 'php_version' => PHP_VERSION, 'environment' => 'Production', 'storage_mode' => 'JSON', 'last_sync' => date('Y-m-d H:i:s'), ], ]; $defaultAccounting = [ 'revenue_streams' => [ ['name' => 'Books', 'amount' => 1200], ['name' => 'Art', 'amount' => 900], ['name' => 'Software / WEB360', 'amount' => 2200], ['name' => 'Services / Consulting', 'amount' => 1500], ], 'expenses' => [ ['name' => 'Hosting', 'amount' => 125], ['name' => 'Domains', 'amount' => 48], ['name' => 'AI APIs', 'amount' => 420], ['name' => 'Design / Assets', 'amount' => 165], ['name' => 'Marketing', 'amount' => 280], ], 'cash_on_hand' => 1330, 'monthly_recurring' => 2400, 'outstanding_debt' => 6300, ]; $projects = read_json($dataDir . '/projects.json', $defaultProjects); $tasks = read_json($dataDir . '/tasks.json', $defaultTasks); $assets = read_json($dataDir . '/assets.json', $defaultAssets); $linkEvents = read_json($dataDir . '/link_events.json', $defaultLinkEvents); $macros = read_json($dataDir . '/macros.json', $defaultMacros); $analytics = read_json($dataDir . '/analytics.json', $defaultAnalytics); $system = read_json($dataDir . '/system.json', $defaultSystem); $accounting = read_json($dataDir . '/accounting.json', $defaultAccounting); $recommendations = read_json($dataDir . '/recommendations.json', []); $brokenLinks = read_json($dataDir . '/broken_links.json', []); $memoryData = read_json($dataDir . '/memory.json', []); $logsData = read_json($dataDir . '/logs.json', []); $pages = [ 'console' => 'Console', 'dashboard' => 'Dashboard', 'projects' => 'Projects', 'accounting' => 'Accounting', 'assets' => 'Assets', 'investor' => 'Investor', 'roadmap' => 'Roadmap', 'links' => 'Links', 'analytics' => 'Analytics', 'security_console' => 'Security', 'social_dashboard' => 'Social', 'forecast' => 'Forecast', 'ai_review' => 'AI Review', ]; $current = isset($_GET['view']) && isset($pages[$_GET['view']]) ? (string)$_GET['view'] : 'console'; $totalProjects = count($projects); $totalTasks = count($tasks); $totalAssets = count($assets); $totalMacros = count($macros); $totalLinkEvents = count($linkEvents); $avgCompletion = $totalProjects > 0 ? round(avg_numeric(array_map(fn($p) => (float)($p['completion_percent'] ?? $p['completion'] ?? 0), $projects))) : 0; $assetValue = array_sum(array_map(fn($a) => (float)($a['value'] ?? 0), $assets)); $linkRevenue = array_sum(array_map(fn($e) => (float)($e['revenue_value'] ?? 0), $linkEvents)); $clicksTotal = array_sum(array_map(fn($e) => (int)($e['clicks'] ?? 0), $linkEvents)); $todoCount = 0; $progressCount = 0; $doneCount = 0; foreach ($tasks as $task) { $s = strtolower((string)($task['status'] ?? 'todo')); if (in_array($s, ['done','complete','completed'], true)) $doneCount++; elseif (in_array($s, ['in_progress','in progress','active'], true)) $progressCount++; else $todoCount++; } $moduleHealth = 0; if (!empty($system['modules'])) { $healthy = 0; foreach ($system['modules'] as $m) { if (in_array(strtolower((string)($m['status'] ?? '')), ['online','active','healthy','connected'], true)) $healthy++; } $moduleHealth = (int)round(($healthy / count($system['modules'])) * 100); } $revenueStreams = $accounting['revenue_streams'] ?? []; $expenses = $accounting['expenses'] ?? []; $totalRevenue = array_sum(array_map(fn($r) => (float)($r['amount'] ?? 0), $revenueStreams)); $totalExpenses = array_sum(array_map(fn($e) => (float)($e['amount'] ?? 0), $expenses)); $cashOnHand = (float)($accounting['cash_on_hand'] ?? 0); $monthlyRecurring = (float)($accounting['monthly_recurring'] ?? 0); $outstandingDebt = (float)($accounting['outstanding_debt'] ?? 0); $netMonthly = $totalRevenue - $totalExpenses; $traffic = $analytics['traffic'] ?? []; $channels = $analytics['channels'] ?? []; $topPages = $analytics['top_pages'] ?? []; $visitsToday = (int)($traffic['visits_today'] ?? 0); $visits7d = (int)($traffic['visits_7d'] ?? 0); $visits30d = (int)($traffic['visits_30d'] ?? 0); $conversionRate = (float)($traffic['conversion_rate'] ?? 0); $bounceRate = (float)($traffic['bounce_rate'] ?? 0); $avgSession = (float)($traffic['avg_session_minutes'] ?? 0); $platformValue = $assetValue * (1 + ($avgCompletion / 350) + ($moduleHealth / 500) + (min($clicksTotal, 5000) / 25000)); $readinessScore = (int)round(clampf(($avgCompletion * 0.42) + ($moduleHealth * 0.26) + ($conversionRate * 5) + ((100 - $bounceRate) * 0.18), 0, 100)); $growthSignal = clampf(($conversionRate * 8) + ((100 - $bounceRate) * 0.4) + ($avgCompletion * 0.35) + ($moduleHealth * 0.2), 0, 100); $forecastRevenue30 = $totalRevenue * (1 + ($growthSignal / 500)); $forecastRevenue90 = $totalRevenue * (1 + ($growthSignal / 220)); $coreFiles = [ '/simon/console.php', '/simon/dashboard.php', '/simon/projects.php', '/simon/accounting.php', '/simon/assets.php', '/simon/investor.php', '/simon/roadmap.php', '/simon/links.php', '/simon/analytics.php', '/simon/security_console.php', '/simon/social_dashboard.php', '/simon/forecast.php', '/simon/ai_review.php', '/simon/api/simon_request.php', '/simon/config/settings.php', '/simon/config/secrets.php', ]; $coreHealth = []; $missingCore = []; foreach ($coreFiles as $f) { $full = $rootDir . $f; $health = file_health($full); $coreHealth[] = ['file' => $f] + $health; if (!$health['exists']) $missingCore[] = $f; } $timeline = [ ['phase' => 'Phase 1', 'name' => 'Foundation', 'status' => 'Current', 'value' => '$15K–$35K', 'focus' => 'Core shell, console, layout, project/task/asset modules'], ['phase' => 'Phase 2', 'name' => 'Intelligence Layer', 'status' => 'Next', 'value' => '+$20K–$50K', 'focus' => 'Scoring, recommendations, memory, analytics intelligence'], ['phase' => 'Phase 3', 'name' => 'Automation + Tracking', 'status' => 'Next', 'value' => '+$25K–$60K', 'focus' => 'Macro execution, link tracking, social workflow automation'], ['phase' => 'Phase 4', 'name' => 'Infrastructure + Security', 'status' => 'Future', 'value' => '+$15K–$40K', 'focus' => 'Health checks, logs, backups, permissions, threat watch'], ['phase' => 'Phase 5', 'name' => 'Commercialization', 'status' => 'Future', 'value' => '+$40K–$150K+', 'focus' => 'Subscriptions, onboarding, SaaS packaging, multi-user roles'], ]; $automationIdeas = [ 'Auto-scan folders and refresh file registry.', 'Auto-score project priority based on completion, revenue, and risk.', 'Generate investor summaries from tasks, assets, and analytics.', 'Publish social drafts to queue by platform and campaign.', 'Run broken-link detection and surface monetization fixes.', 'Watch logs for recurring PHP/API failures and recommend repairs.', 'Detect stale modules and propose rebuild or merge actions.', 'Summarize weekly growth, traffic, and conversion shifts.', ]; $improvements = [ 'Unify every separate page into one routed console, then leave lightweight wrappers for legacy URLs.', 'Add a viewer/editor layer for guarded text-file inspection.', 'Replace static system status with real endpoint health checks.', 'Move from JSON-only to optional database abstraction later.', 'Track social content lifecycle from draft → approved → queued → published.', 'Add security severity scoring for missing config, secrets exposure, and writable sensitive paths.', ]; $socialApis = [ ['platform' => 'Meta / Facebook / Instagram', 'pros' => 'Strong publishing ecosystem, ads integration, business tools', 'cons' => 'App review friction, permissions complexity', 'features' => 'Scheduling, performance sync, campaign attribution'], ['platform' => 'X / Twitter', 'pros' => 'Fast distribution, brand/news reach', 'cons' => 'API pricing/limits can shift', 'features' => 'Post queue, engagement pull, alert triggers'], ['platform' => 'TikTok', 'pros' => 'High discovery potential', 'cons' => 'Publishing/analytics access can be restrictive', 'features' => 'Video queue metadata, reel ideas, trend watch'], ['platform' => 'LinkedIn', 'pros' => 'Investor/professional visibility', 'cons' => 'Slower organic lift for entertainment content', 'features' => 'Thought leadership scheduling, B2B reporting'], ['platform' => 'YouTube', 'pros' => 'Evergreen search and long-form value', 'cons' => 'Heavier media workflow', 'features' => 'Video release timeline, metadata audit, CTA tracking'], ]; $newsIdeas = [ 'Product launch updates', 'Feature milestones', 'Investor notes', 'Book/art release sync', 'Security advisories', 'Platform roadmap announcements', ]; $fileTree = scan_tree($rootDir, 2); usort($fileTree, fn($a, $b) => strcmp($a['path'], $b['path'])); $displayTree = array_slice($fileTree, 0, 160); $brainStatus = [ ['label' => 'Routing', 'score' => 86], ['label' => 'Memory', 'score' => 71], ['label' => 'Forecasting', 'score' => 67], ['label' => 'Automation', 'score' => 42], ['label' => 'Security Awareness', 'score' => 59], ['label' => 'Commercial Readiness', 'score' => $readinessScore], ]; $recentLogs = []; if (is_array($logsData)) { $slice = array_slice(array_reverse($logsData), 0, 8); foreach ($slice as $entry) { if (is_string($entry)) { $recentLogs[] = ['time' => '', 'type' => 'log', 'message' => $entry]; } elseif (is_array($entry)) { $recentLogs[] = [ 'time' => (string)($entry['time'] ?? $entry['timestamp'] ?? ''), 'type' => (string)($entry['type'] ?? $entry['level'] ?? 'log'), 'message' => (string)($entry['message'] ?? $entry['event'] ?? json_encode($entry)), ]; } } } if (!$recentLogs) { $recentLogs = [ ['time' => date('Y-m-d H:i:s'), 'type' => 'system', 'message' => 'Unified master console loaded.'], ['time' => date('Y-m-d H:i:s'), 'type' => 'health', 'message' => 'Module health computed from system.json/defaults.'], ['time' => date('Y-m-d H:i:s'), 'type' => 'watch', 'message' => count($missingCore) . ' core files currently flagged missing.'], ]; } $aiNotes = $recommendations ?: [ ['title' => 'Unify routes', 'message' => 'Keep one master console and route legacy module pages through wrappers.'], ['title' => 'Strengthen monetization', 'message' => 'Project maturity is ahead of monetization. Push more visibility into links, offers, and investor views.'], ['title' => 'Fix missing files', 'message' => 'Security and roadmap confidence improve if core missing files are stubbed or redirected.'], ]; ?><!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"> <title><?= h(SIMON_NAME) ?> — <?= h(SIMON_SUBTITLE) ?></title> <meta name="theme-color" content="#081120"> <style> :root{ --bg:#050913;--bg2:#081224;--panel:rgba(10,18,36,.84);--panel2:rgba(16,24,46,.95);--line:rgba(112,177,255,.14); --text:#eef6ff;--muted:#98abc8;--cyan:#70e7ff;--blue:#69a5ff;--violet:#9b7cff;--green:#57efaa;--amber:#ffd36f;--red:#ff7b92;--pink:#ff7bd1; --shadow:0 24px 90px rgba(0,0,0,.42);--radius:22px;--sidebar:310px; } *{box-sizing:border-box} html,body{margin:0;padding:0} body{ min-height:100vh;color:var(--text);font-family:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Arial,sans-serif; background: radial-gradient(circle at 15% 10%, rgba(112,231,255,.12), transparent 20%), radial-gradient(circle at 82% 12%, rgba(155,124,255,.12), transparent 22%), radial-gradient(circle at 50% 110%, rgba(255,123,209,.08), transparent 24%), linear-gradient(180deg,var(--bg),var(--bg2)); } body:before{ content:"";position:fixed;inset:0;pointer-events:none;opacity:.45; background: radial-gradient(circle at 20% 25%, rgba(112,231,255,.18), transparent 10%), radial-gradient(circle at 78% 18%, rgba(255,123,209,.10), transparent 12%), radial-gradient(circle at 60% 70%, rgba(155,124,255,.10), transparent 14%); filter:blur(32px); } .wrap{max-width:1700px;margin:0 auto;padding:20px;position:relative;z-index:1} .layout{display:grid;grid-template-columns:var(--sidebar) 1fr;gap:18px;align-items:start} .sidebar,.topbar,.card{border:1px solid var(--line);border-radius:28px;background:linear-gradient(180deg,var(--panel),var(--panel2));box-shadow:var(--shadow)} .sidebar{position:sticky;top:20px;padding:18px;overflow:hidden} .sidebar:before,.topbar:before{content:"";position:absolute;inset:-20%;background: radial-gradient(circle at 15% 28%, rgba(112,231,255,.18), transparent 20%), radial-gradient(circle at 76% 18%, rgba(255,123,209,.10), transparent 18%), radial-gradient(circle at 55% 80%, rgba(155,124,255,.12), transparent 20%);filter:blur(28px);pointer-events:none} .sidebar,.topbar{position:relative} .sidebar-inner,.topbar-inner{position:relative;z-index:2} .brand-top{display:grid;grid-template-columns:88px 1fr;gap:16px;align-items:center} .orb{width:84px;height:84px;border-radius:50%;margin:auto;background: radial-gradient(circle at 35% 30%, rgba(255,255,255,.96), rgba(112,231,255,.76) 18%, rgba(105,165,255,.3) 42%, rgba(155,124,255,.14) 58%, transparent 68%); box-shadow:0 0 30px rgba(112,231,255,.38),0 0 70px rgba(105,165,255,.16),inset 0 0 24px rgba(255,255,255,.12);position:relative;animation:pulse 5s ease-in-out infinite} .orb:before,.orb:after{content:"";position:absolute;inset:-12px;border-radius:50%;border:1px solid rgba(112,231,255,.18);animation:spin 12s linear infinite} .orb:after{inset:-22px;border-color:rgba(155,124,255,.16);animation-direction:reverse;animation-duration:18s} @keyframes spin{to{transform:rotate(360deg)}} @keyframes pulse{50%{transform:scale(1.04)}} .branding h1{margin:0;font-size:30px;line-height:1.02}.branding .sub{margin-top:6px;color:#d8e8fb;font-size:14px}.branding .company{margin-top:8px;color:var(--cyan);font-size:11px;font-weight:800;letter-spacing:.12em;text-transform:uppercase}.branding .tagline{margin-top:10px;color:#dff6ff;font-size:12px} .quickstats{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:16px}.stat{padding:12px;border-radius:18px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.06)}.stat .label{font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em}.stat .value{font-size:22px;font-weight:900;margin-top:6px} .side-title{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.14em;margin:18px 0 10px;padding:0 4px} .menu{display:grid;gap:8px}.menubtn{display:block;border:1px solid var(--line);background:rgba(255,255,255,.04);color:var(--text);padding:12px 14px;border-radius:14px;font-weight:800;text-decoration:none;transition:.2s ease}.menubtn:hover,.menubtn.active{background:linear-gradient(180deg, rgba(105,165,255,.22), rgba(155,124,255,.16));border-color:rgba(112,231,255,.34);box-shadow:0 10px 30px rgba(0,0,0,.18)} .content{min-width:0}.topbar{padding:18px 20px;overflow:hidden}.topbar h2{margin:0;font-size:30px}.meta{color:var(--muted);font-size:14px;margin-top:6px}.pills{display:flex;gap:10px;flex-wrap:wrap}.pill{padding:10px 12px;border-radius:999px;background:rgba(255,255,255,.04);border:1px solid var(--line);font-size:12px;color:#dff3ff;text-transform:uppercase;letter-spacing:.06em} .info-bar{margin-top:14px;display:grid;grid-template-columns:2fr 1.4fr 1.4fr 1.2fr;gap:10px}.info-pill{padding:12px 14px;border-radius:16px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.06)}.info-pill strong{display:block;font-size:15px}.info-pill span{display:block;color:var(--muted);font-size:12px;margin-top:4px} .grid{display:grid;gap:18px;margin-top:18px}.grid-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-2{grid-template-columns:repeat(2,minmax(0,1fr))} .card{padding:18px}.card h2{margin:0 0 14px;font-size:20px}.card h3{margin:0 0 10px;font-size:16px}.metric .label{font-size:12px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em}.metric .value{font-size:34px;font-weight:900;margin-top:8px}.metric .hint{margin-top:8px;color:var(--muted);font-size:13px} .table{width:100%;border-collapse:collapse}.table th,.table td{padding:12px 10px;border-bottom:1px solid rgba(255,255,255,.07);text-align:left;vertical-align:top}.table th{font-size:12px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em} .badge{display:inline-flex;align-items:center;padding:7px 10px;border-radius:999px;border:1px solid var(--line);font-size:12px;font-weight:800}.ok{background:rgba(87,239,170,.10);color:#bff7db}.warn{background:rgba(255,211,111,.10);color:#ffe8b5}.bad{background:rgba(255,123,146,.10);color:#ffd6de}.neutral{background:rgba(112,231,255,.10);color:#d5f8ff} .list{display:grid;gap:12px}.item{padding:14px;border-radius:16px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06)}.item .meta{margin-top:6px;color:var(--muted);font-size:13px} .bar{height:10px;border-radius:999px;background:rgba(255,255,255,.07);overflow:hidden;border:1px solid rgba(255,255,255,.04)}.bar span{display:block;height:100%;background:linear-gradient(90deg,var(--cyan),var(--violet),var(--pink))} .code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;white-space:pre-wrap;color:#dbf1ff;background:#08101d;padding:16px;border-radius:16px;border:1px solid rgba(255,255,255,.06)} .flowgrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}.flowcard{padding:14px;border-radius:18px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06)}.flowcard .step{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em}.flowcard .title{margin-top:8px;font-size:17px;font-weight:900}.flowcard .text{margin-top:6px;color:var(--muted);font-size:13px} .kpi{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}.kbox{padding:14px;border-radius:16px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06)}.kbox .k{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em}.kbox .v{font-size:24px;font-weight:900;margin-top:6px} .timeline{display:grid;gap:12px}.phase{padding:16px;border-radius:18px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06)}.phase-head{display:flex;justify-content:space-between;gap:12px;align-items:center;margin-bottom:8px} .tree{max-height:520px;overflow:auto}.tree-row{display:flex;justify-content:space-between;gap:14px;padding:10px 12px;border-radius:14px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06);margin-bottom:8px}.tree-path{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;color:#dff6ff}.muted{color:var(--muted)} .log{display:grid;gap:10px}.log-item{padding:12px 14px;border-radius:14px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06)}.log-item .t{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em} .canvas-wrap{height:220px;border-radius:18px;border:1px solid var(--line);overflow:hidden;background:#050d19} .footer{margin-top:18px;text-align:center;color:var(--muted);font-size:12px} @media (max-width:1380px){.layout{grid-template-columns:1fr}.sidebar{position:relative;top:0}.grid-4,.grid-3,.grid-2,.flowgrid,.kpi,.info-bar{grid-template-columns:1fr 1fr}} @media (max-width:760px){.brand-top,.grid-4,.grid-3,.grid-2,.flowgrid,.kpi,.quickstats,.info-bar{grid-template-columns:1fr}.pills{margin-top:10px}} </style> </head> <body> <div class="wrap"> <div class="layout"> <aside class="sidebar"> <div class="sidebar-inner"> <div class="brand-top"> <div class="orb"></div> <div class="branding"> <h1><?= h(SIMON_NAME) ?></h1> <div class="sub"><?= h(SIMON_SUBTITLE) ?></div> <div class="company">Gaylord Sinclair LLC</div> <div class="tagline">Build • Operate • Analyze • Optimize • Monetize</div> </div> </div> <div class="quickstats"> <div class="stat"><div class="label">Readiness</div><div class="value"><?= h((string)$readinessScore) ?>%</div></div> <div class="stat"><div class="label">Modules</div><div class="value"><?= h((string)$moduleHealth) ?>%</div></div> <div class="stat"><div class="label">Projects</div><div class="value"><?= h((string)$totalProjects) ?></div></div> <div class="stat"><div class="label">Value</div><div class="value"><?= h(money($platformValue)) ?></div></div> </div> <div class="side-title">Unified Page Routing</div> <nav class="menu"> <?php foreach ($pages as $key => $label): ?> <a class="menubtn <?= $current === $key ? 'active' : '' ?>" href="?view=<?= h($key) ?>"><?= h($label) ?></a> <?php endforeach; ?> </nav> </div> </aside> <main class="content"> <section class="topbar"> <div class="topbar-inner"> <div> <h2><?= h($pages[$current]) ?></h2> <div class="meta">Unified replacement for /simon/console.php, dashboard, projects, accounting, assets, investor, roadmap, links, analytics, security_console, social_dashboard, forecast, and ai_review.</div> </div> <div class="pills"> <span class="pill">Version <?= h(SIMON_VERSION) ?></span> <span class="pill">Status <?= h((string)($system['status'] ?? 'Nominal')) ?></span> <span class="pill">API <?= h((string)($system['api'] ?? 'Connected')) ?></span> <span class="pill">Storage <?= h((string)($system['storage'] ?? 'Healthy')) ?></span> </div> </div> <div class="info-bar"> <div class="info-pill"><strong>Header Reel Info Bar</strong><span>Live KPI strip for status, revenue, traffic, and build health.</span></div> <div class="info-pill"><strong>Brain Status</strong><span><?= h((string)$moduleHealth) ?>% operational confidence</span></div> <div class="info-pill"><strong>Cosmic Storm</strong><span>Animated background canvas below for SIMON command-center feel.</span></div> <div class="info-pill"><strong>File Watch</strong><span><?= count($missingCore) ?> missing or unwired core files</span></div> </div> </section> <?php if ($current === 'console'): ?> <div class="grid grid-4"> <div class="card metric"><div class="label">Projects</div><div class="value"><?= $totalProjects ?></div><div class="hint">Average completion <?= $avgCompletion ?>%</div></div> <div class="card metric"><div class="label">Tasks</div><div class="value"><?= $totalTasks ?></div><div class="hint">Todo <?= $todoCount ?> · In progress <?= $progressCount ?> · Done <?= $doneCount ?></div></div> <div class="card metric"><div class="label">Assets</div><div class="value"><?= $totalAssets ?></div><div class="hint">Tracked value <?= h(money($assetValue)) ?></div></div> <div class="card metric"><div class="label">Link Revenue</div><div class="value"><?= h(money($linkRevenue)) ?></div><div class="hint">Clicks <?= number_format($clicksTotal) ?></div></div> </div> <div class="grid grid-2"> <div class="card"> <h2>Command overview</h2> <div class="canvas-wrap"><canvas id="stormCanvas"></canvas></div> <div class="list" style="margin-top:14px;"> <div class="item"><strong>Unified spine</strong><div class="meta">One file routes all page surfaces and keeps legacy pages simple.</div></div> <div class="item"><strong>Loop logic</strong><div class="meta">Scan → Analyze → Score → Recommend → Execute → Log → Learn</div></div> <div class="item"><strong>AI feed</strong><div class="meta">Recommendations, risk checks, forecast changes, automation candidates.</div></div> </div> </div> <div class="card"> <h2>Recent logs</h2> <div class="log"> <?php foreach ($recentLogs as $log): ?> <div class="log-item"> <div class="t"><?= h((string)$log['type']) ?><?= !empty($log['time']) ? ' · ' . h((string)$log['time']) : '' ?></div> <div><?= h((string)$log['message']) ?></div> </div> <?php endforeach; ?> </div> </div> </div> <?php elseif ($current === 'dashboard'): ?> <div class="grid grid-4"> <div class="card metric"><div class="label">Readiness Score</div><div class="value"><?= $readinessScore ?>%</div><div class="hint">Execution + traffic + conversion + module health</div></div> <div class="card metric"><div class="label">Visits 30d</div><div class="value"><?= number_format($visits30d) ?></div><div class="hint">Today <?= number_format($visitsToday) ?></div></div> <div class="card metric"><div class="label">Conversion</div><div class="value"><?= pct($conversionRate,1) ?></div><div class="hint">Bounce <?= pct($bounceRate,1) ?></div></div> <div class="card metric"><div class="label">Platform Value</div><div class="value"><?= h(compact_num($platformValue)) ?></div><div class="hint">Modeled from assets + maturity + traction</div></div> </div> <div class="grid grid-2"> <div class="card"> <h2>Operator snapshot</h2> <div class="kpi"> <div class="kbox"><div class="k">Revenue</div><div class="v"><?= h(money($totalRevenue)) ?></div></div> <div class="kbox"><div class="k">Expenses</div><div class="v"><?= h(money($totalExpenses)) ?></div></div> <div class="kbox"><div class="k">Net</div><div class="v"><?= h(money($netMonthly)) ?></div></div> </div> <table class="table" style="margin-top:14px;"> <thead><tr><th>Metric</th><th>Value</th></tr></thead> <tbody> <tr><td>Monthly recurring</td><td><?= h(money($monthlyRecurring)) ?></td></tr> <tr><td>Cash on hand</td><td><?= h(money($cashOnHand)) ?></td></tr> <tr><td>Outstanding debt</td><td><?= h(money($outstandingDebt)) ?></td></tr> <tr><td>Average session</td><td><?= number_format($avgSession,1) ?> min</td></tr> </tbody> </table> </div> <div class="card"> <h2>AI ways to improve</h2> <div class="list"> <?php foreach ($improvements as $idea): ?><div class="item"><?= h($idea) ?></div><?php endforeach; ?> </div> </div> </div> <?php elseif ($current === 'projects'): ?> <div class="card"> <h2>Projects registry</h2> <table class="table"> <thead><tr><th>Project</th><th>Status</th><th>Phase</th><th>Owner</th><th>Priority</th><th>Completion</th></tr></thead> <tbody> <?php foreach ($projects as $p): $completion=(int)($p['completion_percent'] ?? $p['completion'] ?? 0); ?> <tr> <td><?= h((string)($p['title'] ?? $p['name'] ?? 'Untitled')) ?></td> <td><span class="badge <?= status_class((string)($p['status'] ?? '')) ?>"><?= h((string)($p['status'] ?? '')) ?></span></td> <td><?= h((string)($p['phase'] ?? '—')) ?></td> <td><?= h((string)($p['owner'] ?? '—')) ?></td> <td><?= h((string)($p['priority'] ?? '—')) ?></td> <td style="min-width:180px;"><?= $completion ?>%<div class="bar"><span style="width:<?= $completion ?>%"></span></div></td> </tr> <?php endforeach; ?> </tbody> </table> </div> <?php elseif ($current === 'accounting'): ?> <div class="grid grid-2"> <div class="card"> <h2>Revenue streams</h2> <table class="table"><thead><tr><th>Stream</th><th>Amount</th></tr></thead><tbody><?php foreach($revenueStreams as $r): ?><tr><td><?= h((string)$r['name']) ?></td><td><?= h(money2((float)$r['amount'])) ?></td></tr><?php endforeach; ?></tbody></table> </div> <div class="card"> <h2>Expenses</h2> <table class="table"><thead><tr><th>Expense</th><th>Amount</th></tr></thead><tbody><?php foreach($expenses as $e): ?><tr><td><?= h((string)$e['name']) ?></td><td><?= h(money2((float)$e['amount'])) ?></td></tr><?php endforeach; ?></tbody></table> </div> </div> <?php elseif ($current === 'assets'): ?> <div class="card"> <h2>Asset registry + value assist</h2> <table class="table"> <thead><tr><th>Asset</th><th>Category</th><th>Status</th><th>Value</th></tr></thead> <tbody><?php foreach($assets as $a): ?><tr><td><?= h((string)$a['name']) ?></td><td><?= h((string)$a['category']) ?></td><td><span class="badge <?= status_class((string)($a['status'] ?? '')) ?>"><?= h((string)($a['status'] ?? 'active')) ?></span></td><td><?= h(money((float)$a['value'])) ?></td></tr><?php endforeach; ?></tbody> </table> </div> <?php elseif ($current === 'investor'): ?> <div class="grid grid-4"> <div class="card metric"><div class="label">Estimated Platform Value</div><div class="value"><?= h(money($platformValue)) ?></div><div class="hint">Asset base + traction multiplier</div></div> <div class="card metric"><div class="label">Asset Base</div><div class="value"><?= h(money($assetValue)) ?></div><div class="hint"><?= $totalAssets ?> tracked assets</div></div> <div class="card metric"><div class="label">12-Month Low</div><div class="value"><?= h(compact_num($platformValue * 1.25)) ?></div><div class="hint">Conservative projection</div></div> <div class="card metric"><div class="label">12-Month High</div><div class="value"><?= h(compact_num($platformValue * 2.10)) ?></div><div class="hint">Aggressive projection</div></div> </div> <div class="card"> <h2>Investor narrative</h2> <div class="list"> <div class="item">SIMON acts as the orchestration layer connecting digital properties, workflows, content assets, link analytics, automation routines, and future AI-driven business operations.</div> <div class="item">WEB360 is the builder and commercial production surface, while SIMON provides routing, logic, forecasting, and operator intelligence.</div> <div class="item">The strongest next move is live API + tracking so dashboards evolve automatically from real activity.</div> </div> </div> <?php elseif ($current === 'roadmap'): ?> <div class="card"> <h2>Phase roadmap + buildout</h2> <div class="timeline"> <?php foreach($timeline as $t): ?> <div class="phase"> <div class="phase-head"><strong><?= h($t['phase'] . ' — ' . $t['name']) ?></strong><span class="badge <?= status_class($t['status']) ?>"><?= h($t['status']) ?></span></div> <div class="muted"><?= h($t['focus']) ?></div> <div style="margin-top:8px;">Value band: <strong><?= h($t['value']) ?></strong></div> </div> <?php endforeach; ?> </div> </div> <?php elseif ($current === 'links'): ?> <div class="grid grid-2"> <div class="card"> <h2>Link intelligence</h2> <table class="table"><thead><tr><th>Destination</th><th>Type</th><th>Clicks</th><th>Revenue</th></tr></thead><tbody><?php foreach($linkEvents as $e): ?><tr><td><?= h((string)$e['destination_url']) ?></td><td><?= h((string)$e['link_type']) ?></td><td><?= number_format((int)($e['clicks'] ?? 0)) ?></td><td><?= h(money2((float)($e['revenue_value'] ?? 0))) ?></td></tr><?php endforeach; ?></tbody></table> </div> <div class="card"> <h2>Broken links + opportunities</h2> <?php if ($brokenLinks): ?> <div class="list"><?php foreach($brokenLinks as $b): ?><div class="item"><?= h(is_array($b) ? (string)($b['url'] ?? json_encode($b)) : (string)$b) ?></div><?php endforeach; ?></div> <?php else: ?> <div class="item">No broken link data loaded yet. Add <code>/data/broken_links.json</code> to populate this panel.</div> <?php endif; ?> </div> </div> <?php elseif ($current === 'analytics'): ?> <div class="grid grid-2"> <div class="card"> <h2>Traffic channels</h2> <table class="table"><thead><tr><th>Channel</th><th>Visits</th></tr></thead><tbody><?php foreach($channels as $c): ?><tr><td><?= h((string)$c['name']) ?></td><td><?= number_format((int)$c['visits']) ?></td></tr><?php endforeach; ?></tbody></table> </div> <div class="card"> <h2>Top pages</h2> <table class="table"><thead><tr><th>Path</th><th>Views</th></tr></thead><tbody><?php foreach($topPages as $p): ?><tr><td><?= h((string)$p['path']) ?></td><td><?= number_format((int)$p['views']) ?></td></tr><?php endforeach; ?></tbody></table> </div> </div> <?php elseif ($current === 'security_console'): ?> <div class="grid grid-2"> <div class="card"> <h2>Core file integrity</h2> <table class="table"><thead><tr><th>File</th><th>Exists</th><th>Readable</th><th>Writable</th><th>Size</th></tr></thead><tbody><?php foreach($coreHealth as $f): ?><tr><td class="muted"><?= h($f['file']) ?></td><td><span class="badge <?= $f['exists'] ? 'ok' : 'bad' ?>"><?= $f['exists'] ? 'Yes' : 'No' ?></span></td><td><?= $f['readable'] ? 'Yes' : 'No' ?></td><td><?= $f['writable'] ? 'Yes' : 'No' ?></td><td><?= $f['exists'] ? h(format_bytes((int)$f['size'])) : '—' ?></td></tr><?php endforeach; ?></tbody></table> </div> <div class="card"> <h2>Missing file security watch</h2> <?php if ($missingCore): ?> <div class="list"><?php foreach($missingCore as $m): ?><div class="item"><strong><?= h($m) ?></strong><div class="meta">Stub, redirect, or build this file to reduce routing and integrity gaps.</div></div><?php endforeach; ?></div> <?php else: ?> <div class="item">No core files flagged missing.</div> <?php endif; ?> </div> </div> <?php elseif ($current === 'social_dashboard'): ?> <div class="grid grid-2"> <div class="card"> <h2>Social media API links — pros / cons / added features</h2> <table class="table"><thead><tr><th>Platform</th><th>Pros</th><th>Cons</th><th>Added Features</th></tr></thead><tbody><?php foreach($socialApis as $s): ?><tr><td><?= h($s['platform']) ?></td><td><?= h($s['pros']) ?></td><td><?= h($s['cons']) ?></td><td><?= h($s['features']) ?></td></tr><?php endforeach; ?></tbody></table> </div> <div class="card"> <h2>Social automation</h2> <div class="list"> <div class="item"><strong>Queue engine</strong><div class="meta">Draft → approve → schedule → publish → log.</div></div> <div class="item"><strong>Variant builder</strong><div class="meta">Platform-specific post versions from one source prompt.</div></div> <div class="item"><strong>Reel info bar</strong><div class="meta">Track hook, CTA, tags, target, approval owner, due time.</div></div> <div class="item"><strong>Future</strong><div class="meta">Trend watch, topic clustering, engagement score, follower loop analysis.</div></div> </div> </div> </div> <?php elseif ($current === 'forecast'): ?> <div class="grid grid-4"> <div class="card metric"><div class="label">Growth Signal</div><div class="value"><?= pct($growthSignal,0) ?></div><div class="hint">Composite from conversion, bounce, completion, health</div></div> <div class="card metric"><div class="label">30-Day Revenue</div><div class="value"><?= h(money($forecastRevenue30)) ?></div><div class="hint">Modeled</div></div> <div class="card metric"><div class="label">90-Day Revenue</div><div class="value"><?= h(money($forecastRevenue90)) ?></div><div class="hint">Modeled</div></div> <div class="card metric"><div class="label">Runway</div><div class="value"><?= $totalExpenses > 0 ? number_format($cashOnHand / $totalExpenses, 1) : '0' ?></div><div class="hint">Months at current spend</div></div> </div> <div class="card"> <h2>Timeline graph data</h2> <div class="code"><?php $series = []; foreach ($timeline as $i => $t) { $series[] = $t['phase'] . ' | readiness=' . min(100, max(10, $readinessScore - (25 - ($i * 8)))) . ' | value=' . $t['value']; } echo h(implode("\n", $series)); ?></div> </div> <?php elseif ($current === 'ai_review'): ?> <div class="grid grid-2"> <div class="card"> <h2>AI feed — recommendations</h2> <div class="list"> <?php foreach($aiNotes as $note): ?> <div class="item"><strong><?= h((string)($note['title'] ?? 'Recommendation')) ?></strong><div class="meta"><?= h((string)($note['message'] ?? json_encode($note))) ?></div></div> <?php endforeach; ?> </div> </div> <div class="card"> <h2>Brain status + automation list</h2> <?php foreach($brainStatus as $b): ?> <div style="margin-bottom:10px;"><div class="muted"><?= h($b['label']) ?> — <?= $b['score'] ?>%</div><div class="bar"><span style="width:<?= (int)$b['score'] ?>%"></span></div></div> <?php endforeach; ?> <div class="list" style="margin-top:14px;"><?php foreach($automationIdeas as $a): ?><div class="item"><?= h($a) ?></div><?php endforeach; ?></div> </div> </div> <?php endif; ?> <div class="grid grid-2"> <div class="card"> <h2>Asset and file tree</h2> <div class="tree"> <?php foreach($displayTree as $node): ?> <div class="tree-row"> <div> <strong><?= $node['type'] === 'dir' ? '📁' : '📄' ?> <?= h($node['name']) ?></strong> <div class="tree-path"><?= h($node['path']) ?></div> </div> <div class="muted"><?= $node['type'] === 'file' ? h(format_bytes((int)$node['size'])) : 'folder' ?></div> </div> <?php endforeach; ?> </div> </div> <div class="card"> <h2>News / press / links / future</h2> <div class="list"> <?php foreach($newsIdeas as $n): ?><div class="item"><?= h($n) ?></div><?php endforeach; ?> <div class="item"><strong>Next strongest move</strong><div class="meta">Wire real API health, social publishing, and guarded file viewer/editor into this console.</div></div> </div> </div> </div> <div class="footer">SIMON Unified Master Console · <?= h(date('F j, Y g:i A')) ?> CT</div> </main> </div> </div> <script> (function(){ const canvas = document.getElementById('stormCanvas'); if(!canvas) return; const ctx = canvas.getContext('2d'); let w,h,parts=[]; function resize(){ w = canvas.width = canvas.clientWidth * devicePixelRatio; h = canvas.height = canvas.clientHeight * devicePixelRatio; ctx.setTransform(1,0,0,1,0,0); ctx.scale(devicePixelRatio, devicePixelRatio); parts = Array.from({length: 65}, () => ({x: Math.random()*canvas.clientWidth,y: Math.random()*canvas.clientHeight,r: Math.random()*2+0.5,vx:(Math.random()-0.5)*0.35,vy:(Math.random()-0.5)*0.35,a:Math.random()*0.7+0.2})); } function draw(){ const cw = canvas.clientWidth, ch = canvas.clientHeight; ctx.clearRect(0,0,cw,ch); const g = ctx.createLinearGradient(0,0,cw,ch); g.addColorStop(0,'rgba(7,18,34,0.95)'); g.addColorStop(1,'rgba(18,10,36,0.95)'); ctx.fillStyle = g; ctx.fillRect(0,0,cw,ch); for(const p of parts){ p.x += p.vx; p.y += p.vy; if(p.x<0||p.x>cw) p.vx *= -1; if(p.y<0||p.y>ch) p.vy *= -1; ctx.beginPath(); ctx.fillStyle = 'rgba(112,231,255,'+p.a+')'; ctx.arc(p.x,p.y,p.r,0,Math.PI*2); ctx.fill(); } for(let i=0;i<parts.length;i++){ for(let j=i+1;j<parts.length;j++){ const a = parts[i], b = parts[j]; const dx = a.x-b.x, dy = a.y-b.y, d = Math.sqrt(dx*dx+dy*dy); if(d < 90){ ctx.strokeStyle = 'rgba(155,124,255,'+(0.10 - d/1000)+')'; ctx.beginPath(); ctx.moveTo(a.x,a.y); ctx.lineTo(b.x,b.y); ctx.stroke(); } } } requestAnimationFrame(draw); } window.addEventListener('resize', resize); resize(); draw(); })(); </script> </body> </html>
Save file
Quick jump
open a path
Open