invent): * - Full-viewport black stage; cycling CSS gradient backgrounds (bg1–bg7). * - Center living pinwheel: 7 color spokes + center hub; CSS gradients only (no required images). * - Spokes orbit; label counter-spin so text stays upright; wheel NEVER pauses on hover. * - Hub visible "?". DNA line: MAP · pinwheel · AB hub. * - Empire entrance overlay (chat DNA): Options · Mirrors · Donate + features + I AGREE ENTER. * - After ENTER the map IS the product — no dense post-enter chrome maze. */ declare(strict_types=1); /** AB hub domain tag: com | org | net (from Host header; default com). */ function nsp_hub_variant(): string { $h = strtolower((string)($_SERVER['HTTP_HOST'] ?? '')); $h = preg_replace('/:\d+$/', '', $h) ?? $h; $h = preg_replace('/^www\./', '', $h) ?? $h; if (str_contains($h, 'nosignup.org') || $h === 'org') return 'org'; if (str_contains($h, 'nosignup.net') || $h === 'net') return 'net'; return 'com'; } function nsp_hub_label(): string { $v = nsp_hub_variant(); return 'Nosignup.' . strtoupper($v === 'com' ? 'Com' : ($v === 'org' ? 'Org' : 'Net')); } /** * Hardcoded website / sketch memory for center "?". * Equal-weight random with NSU product URLs (see front-end pool). * kind sketch → same origin ?sketch=id | kind url → external. * Tack projects here — the PHP file is the repository. */ function nsp_sketch_catalog(): array { return [ ['id' => 'morse', 'kind' => 'sketch', 'label' => 'Morse (binaural trainer)', 'href' => '?sketch=morse'], ['id' => 'asl', 'kind' => 'sketch', 'label' => 'ASL (binaural skill deck)', 'href' => '?sketch=asl'], // Add more custom sites here: ['id'=>'x','kind'=>'sketch','label'=>'…','href'=>'?sketch=x'], ]; } /** NSU empire products always in the ? pool (equal weight with sketches). */ function nsp_product_pool(): array { return [ ['id' => 'trade', 'kind' => 'url', 'label' => 'Trade', 'href' => 'https://nosignup.trade/'], ['id' => 'chat', 'kind' => 'url', 'label' => 'Chat', 'href' => 'https://nosignup.chat/'], ['id' => 'work', 'kind' => 'url', 'label' => 'Work', 'href' => 'https://nosignup.work/'], ['id' => 'market', 'kind' => 'url', 'label' => 'Market', 'href' => 'https://nosignup.market/'], ['id' => 'date', 'kind' => 'url', 'label' => 'Date', 'href' => 'https://nosignup.date/'], ['id' => 'fun', 'kind' => 'url', 'label' => 'Fun', 'href' => 'https://nosignup.fun/'], ['id' => 'info', 'kind' => 'url', 'label' => 'Info', 'href' => 'https://nosignup.info/'], ]; } function nsp_hub_random_pool(): array { return array_merge(nsp_product_pool(), nsp_sketch_catalog()); } /* ---- SITE-LOCAL CONTROL PANEL (renter key; not OS root) ---- */ function nsp_vault_dir(): string { $sib = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'vault'; $loc = __DIR__ . DIRECTORY_SEPARATOR . 'vault'; foreach ([$sib, $loc] as $d) { if (is_dir($d) || @mkdir($d, 0700, true)) { if (is_dir($d) && is_writable($d)) return $d; } } return $sib; } function nsp_data_dir(): string { $d = __DIR__ . DIRECTORY_SEPARATOR . 'data'; if (!is_dir($d)) @mkdir($d, 0755, true); $ht = $d . DIRECTORY_SEPARATOR . '.htaccess'; if (!is_file($ht)) @file_put_contents($ht, "Require all denied\nDeny from all\n"); return $d; } function nsp_hash_file(): string { return nsp_data_dir() . DIRECTORY_SEPARATOR . 'admin.pass.hash'; } function nsp_vault_write(string $plain): void { $d = nsp_vault_dir(); @chmod($d, 0700); @file_put_contents($d . DIRECTORY_SEPARATOR . 'README.txt', "NOSIGNUP.COM VAULT - ROOT/OPERATOR ONLY\nClear password for /controlpanel.\nWallet seeds: WALLET_SEEDS.txt\n" . gmdate('c') . "\n", LOCK_EX); @file_put_contents($d . DIRECTORY_SEPARATOR . 'ADMIN_PASSWORD.txt', $plain . "\n", LOCK_EX); @chmod($d . DIRECTORY_SEPARATOR . 'ADMIN_PASSWORD.txt', 0600); $ht = $d . DIRECTORY_SEPARATOR . '.htaccess'; if (!is_file($ht)) @file_put_contents($ht, "Require all denied\nDeny from all\n"); } function nsp_json(array $x, int $c = 200): void { http_response_code($c); header('Content-Type: application/json; charset=UTF-8'); header('Cache-Control: no-store'); echo json_encode($x, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); exit; } function nsp_pass_set(string $pass): void { $pass = trim($pass); if (strlen($pass) < 8) nsp_json(['ok' => false, 'err' => 'admin pass min 8 chars'], 400); $h = password_hash($pass, PASSWORD_DEFAULT); if ($h === false) nsp_json(['ok' => false, 'err' => 'hash fail'], 500); file_put_contents(nsp_hash_file(), $h . "\n", LOCK_EX); @chmod(nsp_hash_file(), 0600); nsp_vault_write($pass); } function nsp_pass_is_set(): bool { return is_file(nsp_hash_file()) && trim((string)file_get_contents(nsp_hash_file())) !== ''; } function nsp_ok(?string $pass): bool { if ($pass === null || $pass === '') return false; if (!nsp_pass_is_set()) return false; $h = trim((string)file_get_contents(nsp_hash_file())); return $h !== '' && password_verify(trim($pass), $h); } function nsp_require(): void { $p = (string)($_POST['admin_pass'] ?? $_GET['admin_pass'] ?? ''); if (!nsp_ok($p)) nsp_json(['ok' => false, 'err' => 'admin auth'], 401); } function nsp_handle_admin_api(string $api): bool { if (!str_starts_with($api, 'admin_')) return false; if ($api === 'admin_status') { nsp_json(['ok' => true, 'admin_pass_set' => nsp_pass_is_set(), 'site' => 'com', 'vault_hint' => nsp_vault_dir(), 'version' => 'com']); } if ($api === 'admin_setup' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') { if (nsp_pass_is_set()) nsp_json(['ok' => false, 'err' => 'already set'], 400); nsp_pass_set((string)($_POST['admin_pass'] ?? '')); nsp_json(['ok' => true, 'msg' => 'hash+vault set', 'vault_hint' => nsp_vault_dir()]); } if ($api === 'admin_login' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') { nsp_require(); nsp_json(['ok' => true, 'msg' => 'ok', 'site' => 'com', 'vault_hint' => nsp_vault_dir(), 'version' => 'com']); } if ($api === 'admin_change_pass' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') { nsp_require(); nsp_pass_set((string)($_POST['new_pass'] ?? '')); nsp_json(['ok' => true, 'msg' => 'rotated']); } if ($api === 'admin_get_source' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') { nsp_require(); $raw = (string)file_get_contents(__FILE__); nsp_json(['ok' => true, 'bytes' => strlen($raw), 'sha256' => hash('sha256', $raw), 'source' => $raw]); } if ($api === 'admin_put_source' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') { nsp_require(); $src = (string)($_POST['source'] ?? ''); if (strlen($src) < 100 || strpos($src, ' false, 'err' => 'bad source'], 400); $bak = __FILE__ . '.bak.' . time(); @copy(__FILE__, $bak); if (file_put_contents(__FILE__, $src, LOCK_EX) === false) nsp_json(['ok' => false, 'err' => 'write failed'], 500); nsp_json(['ok' => true, 'msg' => 'replaced', 'backup' => basename($bak), 'sha256' => hash('sha256', $src)]); } nsp_json(['ok' => false, 'err' => 'unknown admin api'], 404); return true; } function nsp_render_controlpanel(): void { header('Content-Type: text/html; charset=UTF-8'); header('Cache-Control: no-store'); $v = nsp_hub_variant(); $site = nsp_hub_label() . ' MAP · AB hub'; $h = htmlspecialchars($site); echo ''; echo '' . $h . ' Control
'; echo '

DNA · MAP · AB hub · pinwheel · ' . htmlspecialchars($v) . '

'; echo '

' . $h . ' · Control Panel

'; echo '

Site-local renter key for THIS domain only (com/org/net AB triad shares UI code, not vaults). UTTER control of THIS index.php. Not OS root. Independent vault per host. Mirrors free tributaries. Product UI matches the other two hub domains for ad A/B.

'; echo '
'; echo '
'; echo '

Vault: -

'; echo '

Change password

'; echo '

Source (utter control)

'; echo '
'; echo '

← back

'; exit; } /** * In-file skill sketches: Morse (v1) + ASL deck shell (same binaural practice/test scheme). * Unfinished growth path — tack more skills onto radios + catalog; PHP is the memory. */ function nsp_render_skill_sketch(string $skill): void { $skill = $skill === 'asl' ? 'asl' : 'morse'; $v = nsp_hub_variant(); $title = $skill === 'asl' ? 'ASL · binaural skill deck' : 'Morse · binaural trainer'; header('Content-Type: text/html; charset=UTF-8'); header('Cache-Control: no-store'); $hubHome = './'; $morseJson = json_encode([ 'A'=>'.-','B'=>'-...','C'=>'-.-.','D'=>'-..','E'=>'.','F'=>'..-.','G'=>'--.','H'=>'....', 'I'=>'..','J'=>'.---','K'=>'-.-','L'=>'.-..','M'=>'--','N'=>'-.','O'=>'---','P'=>'.--.', 'Q'=>'--.-','R'=>'.-.','S'=>'...','T'=>'-','U'=>'..-','V'=>'...-','W'=>'.--','X'=>'-..-', 'Y'=>'-.--','Z'=>'--..','0'=>'-----','1'=>'.----','2'=>'..---','3'=>'...--','4'=>'....-', '5'=>'.....','6'=>'-....','7'=>'--...','8'=>'---..','9'=>'----.', ], JSON_UNESCAPED_SLASHES); // Compact ASL letter hints (scaffold — full video/camera later; same practice/test shell) $aslJson = json_encode([ 'A'=>'fist thumb side','B'=>'flat hand thumb in','C'=>'C shape','D'=>'index up rest touch', 'E'=>'fist fingertips','F'=>'OK circle three up','G'=>'index+thumb side','H'=>'two fingers side', 'I'=>'pinky up','J'=>'pinky draw J','K'=>'index mid V thumb','L'=>'L shape', 'M'=>'three over thumb','N'=>'two over thumb','O'=>'O circle','P'=>'K pointing down', 'Q'=>'G pointing down','R'=>'cross index mid','S'=>'fist thumb front','T'=>'thumb under index', 'U'=>'two fingers up','V'=>'peace V','W'=>'three fingers','X'=>'hook index', 'Y'=>'thumb+pinky','Z'=>'index draw Z', ], JSON_UNESCAPED_SLASHES); echo ''; echo ''; echo '' . htmlspecialchars($title) . '
'; echo '
← MAPsketch · ' . htmlspecialchars($skill) . ' · binaural'; echo '' . ($skill === 'morse' ? 'ASL →' : 'Morse →') . '
'; echo '
·
Pick a stream · START to practice
idle · no account · browser-local only
'; echo '
'; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo '

Unfinished skill deck · Morse v1 + ASL scaffold · same practice/test shell · tack more skills in PHP catalog · free · no signup

'; echo '
'; } if (isset($_GET['src']) || isset($_GET['download']) || (isset($_GET['api']) && $_GET['api'] === 'src')) { $raw = (string)file_get_contents(__FILE__); header('Content-Type: text/plain; charset=UTF-8'); header('X-Content-Type-Options: nosniff'); header('X-NS-Sha256: ' . hash('sha256', $raw)); if (isset($_GET['download'])) { header('Content-Disposition: attachment; filename="nosignup-com.php"'); } echo $raw; exit; } $api = (string)($_GET['api'] ?? $_POST['api'] ?? ''); if ($api !== '' && str_starts_with($api, 'admin_')) { nsp_handle_admin_api($api); } $wantPanel = isset($_GET['controlpanel']) || (isset($_SERVER['REQUEST_URI']) && preg_match('#/controlpanel/?(\?|$)#', (string)$_SERVER['REQUEST_URI'])); if ($wantPanel && $api === '') { nsp_render_controlpanel(); } /* In-file sketch / custom-site memory — served from this PHP */ $sketch = strtolower(preg_replace('/[^a-z0-9_-]/', '', (string)($_GET['sketch'] ?? '')) ?? ''); if ($sketch === 'morse' || $sketch === 'asl' || $sketch === 'train') { nsp_render_skill_sketch($sketch === 'train' ? 'morse' : $sketch); exit; } $nsHubVar = nsp_hub_variant(); $nsHubTitle = nsp_hub_label(); $nsHubPoolJson = json_encode(nsp_hub_random_pool(), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); ?> <?= htmlspecialchars($nsHubTitle) ?> · MAP sketchpad hub