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,026
Folders
377
Scanned Size
3.79 GB
PHP Files
791
Editable Text Files
12,310
File viewer
guarded to /htdocs
/message.php
<?php declare(strict_types=1); /** * /message.php — SIMON Message Portal * Sends visitor messages to admin@gaylordsinclair.com * PHP 8.0+ compatible. No database required. */ header('Content-Type: text/html; charset=utf-8'); header('X-Robots-Tag: index, follow'); header('X-Frame-Options: SAMEORIGIN'); header('X-Content-Type-Options: nosniff'); header('Referrer-Policy: strict-origin-when-cross-origin'); header('Permissions-Policy: geolocation=(), microphone=(), camera=()'); header("Cross-Origin-Opener-Policy: same-origin"); header("Cross-Origin-Resource-Policy: same-origin"); /* ============================================================ SIMON CONFIG ============================================================ */ const SITE_NAME = 'Gaylord Sinclair'; const APP_NAME = 'SIMON Message Portal'; const ADMIN_EMAIL = 'admin@gaylordsinclair.com'; const FROM_EMAIL = 'admin@gaylordsinclair.com'; const SUBJECT_PREFIX = '[SIMON MESSAGE]'; const MAX_MESSAGE_CHARS = 6000; const RATE_LIMIT_SECONDS = 60; $SIMON_CONFIG = [ 'GA4_ID' => 'G-S6MEHB4BEY', 'IMPACT_VERIFICATION' => 'e8ec6683-663c-421a-a30d-f8c0fe517345', 'WEBHOOK_BASE' => '/connlink/test1/ui/webhook_inbox.php', 'VISIT_STREAM' => 'visits', 'PULSE_STREAM' => 'default', 'SIMON_KEY' => '', 'APP' => APP_NAME, 'SOURCE' => 'message.php', ]; /* ============================================================ HELPERS ============================================================ */ function h(string $s): string { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); } function clean_line(string $value): string { return trim(str_replace(["\r", "\n", "\0"], ' ', $value)); } function clean_text(string $value, int $max = 6000): string { $value = str_replace("\0", '', $value); $value = trim($value); if (function_exists('mb_substr')) { return mb_substr($value, 0, $max, 'UTF-8'); } return substr($value, 0, $max); } function request_id(int $bytes = 8): string { try { return bin2hex(random_bytes($bytes)); } catch (Throwable $e) { return substr(hash('sha256', uniqid('', true)), 0, $bytes * 2); } } function client_ip(): string { $candidates = [ $_SERVER['HTTP_CF_CONNECTING_IP'] ?? '', $_SERVER['HTTP_X_REAL_IP'] ?? '', $_SERVER['REMOTE_ADDR'] ?? '', ]; foreach ($candidates as $candidate) { $candidate = trim((string)$candidate); if ($candidate !== '' && filter_var($candidate, FILTER_VALIDATE_IP)) return $candidate; } $xff = (string)($_SERVER['HTTP_X_FORWARDED_FOR'] ?? ''); if ($xff !== '') { foreach (explode(',', $xff) as $part) { $part = trim($part); if ($part !== '' && filter_var($part, FILTER_VALIDATE_IP)) return $part; } } return 'unknown'; } function scheme(): string { if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) return strtolower((string)$_SERVER['HTTP_X_FORWARDED_PROTO']); if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') return 'https'; return 'http'; } function current_url(): string { $host = clean_line((string)($_SERVER['HTTP_HOST'] ?? '')); $uri = clean_line((string)($_SERVER['REQUEST_URI'] ?? '/message.php')); return scheme() . '://' . $host . $uri; } function logs_dir(): string { $root = rtrim((string)($_SERVER['DOCUMENT_ROOT'] ?? ''), '/'); if ($root === '') $root = __DIR__; $dir = $root . '/_logs'; if (!is_dir($dir)) @mkdir($dir, 0755, true); return $dir; } function append_ndjson(string $file, array $row): bool { $json = json_encode($row, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); if ($json === false) return false; return @file_put_contents($file, $json . PHP_EOL, FILE_APPEND | LOCK_EX) !== false; } function rate_limited(string $ip, int $ttl = RATE_LIMIT_SECONDS): bool { $dir = logs_dir(); if (!is_dir($dir) || !is_writable($dir)) return false; $bucket = floor(time() / max(10, $ttl)); $key = hash('sha256', 'message|' . $bucket . '|' . $ip); $marker = $dir . '/_msg_rl_' . substr($key, 0, 40); if (is_file($marker)) return true; @file_put_contents($marker, '1', LOCK_EX); @chmod($marker, 0644); return false; } function valid_email(string $email): bool { return filter_var($email, FILTER_VALIDATE_EMAIL) !== false; } function send_admin_message(array $data, string $rid): bool { $name = clean_line($data['name'] ?? ''); $email = clean_line($data['email'] ?? ''); $phone = clean_line($data['phone'] ?? ''); $topic = clean_line($data['topic'] ?? 'General Message'); $priority = clean_line($data['priority'] ?? 'normal'); $message = clean_text($data['message'] ?? '', MAX_MESSAGE_CHARS); $safeTopic = $topic !== '' ? $topic : 'General Message'; $subject = SUBJECT_PREFIX . ' ' . $safeTopic . ' · ' . $rid; $replyTo = valid_email($email) ? $email : FROM_EMAIL; $headers = implode("\r\n", [ 'From: ' . FROM_EMAIL, 'Reply-To: ' . $replyTo, 'MIME-Version: 1.0', 'Content-Type: text/plain; charset=UTF-8', 'X-SIMON-RID: ' . $rid, ]); $body = implode("\n", [ 'SIMON MESSAGE PORTAL', '====================', '', 'RID: ' . $rid, 'Time UTC: ' . gmdate('c'), 'Priority: ' . $priority, 'Topic: ' . $safeTopic, '', 'CONTACT', 'Name: ' . ($name !== '' ? $name : '(not provided)'), 'Email: ' . ($email !== '' ? $email : '(not provided)'), 'Phone: ' . ($phone !== '' ? $phone : '(not provided)'), '', 'MESSAGE', $message, '', 'REQUEST CONTEXT', 'URL: ' . current_url(), 'IP: ' . client_ip(), 'User Agent: ' . clean_line((string)($_SERVER['HTTP_USER_AGENT'] ?? '')), 'Referrer: ' . clean_line((string)($_SERVER['HTTP_REFERER'] ?? '(direct)')), '', 'Powered by SIMON', ]); return @mail(ADMIN_EMAIL, clean_line($subject), $body, $headers); } /* ============================================================ REQUEST HANDLING ============================================================ */ $rid = request_id(); $ip = client_ip(); $status = 'idle'; $notice = ''; $errors = []; $prefillRid = clean_line((string)($_GET['rid'] ?? '')); $prefillCode = clean_line((string)($_GET['code'] ?? '')); $prefillMessage = ''; if ($prefillRid !== '' || $prefillCode !== '') { $prefillMessage = trim("Issue report\nCode: {$prefillCode}\nLog/RID: {$prefillRid}\n\nDescribe what happened:"); } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $honeypot = trim((string)($_POST['website'] ?? '')); $name = clean_line((string)($_POST['name'] ?? '')); $email = clean_line((string)($_POST['email'] ?? '')); $phone = clean_line((string)($_POST['phone'] ?? '')); $topic = clean_line((string)($_POST['topic'] ?? 'General Message')); $priority = clean_line((string)($_POST['priority'] ?? 'normal')); $message = clean_text((string)($_POST['message'] ?? ''), MAX_MESSAGE_CHARS); if ($honeypot !== '') $errors[] = 'Spam filter triggered.'; if (rate_limited($ip)) $errors[] = 'Please wait one minute before sending another message.'; if ($name === '') $errors[] = 'Name is required.'; if ($email === '' || !valid_email($email)) $errors[] = 'A valid email is required.'; if ($message === '') $errors[] = 'Message is required.'; if (strlen($message) < 8) $errors[] = 'Message is too short.'; $event = [ 'rid' => $rid, 'event_type' => 'message_submit_attempt', 'time' => gmdate('c'), 'source' => 'message.php', 'status' => empty($errors) ? 'validated' : 'rejected', 'errors' => $errors, 'contact' => [ 'name' => $name, 'email_hash' => $email !== '' ? hash('sha256', strtolower($email)) : '', 'phone_present' => $phone !== '', ], 'message' => [ 'topic' => $topic, 'priority' => $priority, 'length' => strlen($message), ], 'request' => [ 'url' => current_url(), 'ip' => $ip, 'user_agent' => clean_line((string)($_SERVER['HTTP_USER_AGENT'] ?? '')), 'referrer' => clean_line((string)($_SERVER['HTTP_REFERER'] ?? '')), ], ]; append_ndjson(logs_dir() . '/message_events.ndjson', $event); if (empty($errors)) { $ok = send_admin_message([ 'name' => $name, 'email' => $email, 'phone' => $phone, 'topic' => $topic, 'priority' => $priority, 'message' => $message, ], $rid); append_ndjson(logs_dir() . '/message_events.ndjson', [ 'rid' => $rid, 'event_type' => 'message_send_result', 'time' => gmdate('c'), 'sent' => $ok, 'to' => ADMIN_EMAIL, ]); if ($ok) { $status = 'sent'; $notice = 'Message sent to SIMON Command. Reference ID: ' . $rid; $_POST = []; $prefillMessage = ''; } else { $status = 'failed'; $notice = 'The server could not send the email. The attempt was logged. Reference ID: ' . $rid; } } else { $status = 'error'; $notice = implode(' ', $errors); } } $csp = "default-src 'self'; " . "script-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://www.google-analytics.com; " . "style-src 'self' 'unsafe-inline'; " . "img-src 'self' data: https://www.google-analytics.com https://www.googletagmanager.com; " . "connect-src 'self' https://www.google-analytics.com https://region1.google-analytics.com https://www.googletagmanager.com; " . "font-src 'self' data:; frame-ancestors 'self'; base-uri 'self'; form-action 'self'"; header('Content-Security-Policy: ' . $csp); header('X-SIMON-RID: ' . $rid); $old = static function(string $key, string $fallback = ''): string { return h((string)($_POST[$key] ?? $fallback)); }; ?> <!doctype html> <html lang="en" data-site="gaylord-sinclair" data-system="simon"> <head> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"/> <title>Message SIMON · Gaylord Sinclair</title> <meta name="description" content="Send a message to Gaylord Sinclair through the SIMON command portal."/> <meta name="theme-color" content="#050816"/> <meta name="impact-site-verification" value="<?= h($SIMON_CONFIG['IMPACT_VERIFICATION']) ?>"/> <link rel="canonical" href="/message.php"/> <script> window.SIMON_CONFIG = <?= json_encode($SIMON_CONFIG, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ?>; window.SIMON_PAGE = { rid: <?= json_encode($rid) ?>, status: <?= json_encode($status) ?>, path: location.pathname, href: location.href, source: 'message.php' }; </script> <?php if ($SIMON_CONFIG['GA4_ID'] !== ''): ?> <script async src="https://www.googletagmanager.com/gtag/js?id=<?= h($SIMON_CONFIG['GA4_ID']) ?>"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){ dataLayer.push(arguments); } gtag('js', new Date()); gtag('config', <?= json_encode($SIMON_CONFIG['GA4_ID']) ?>, { send_page_view: true }); gtag('event', 'simon_message_page', { rid: <?= json_encode($rid) ?>, status: <?= json_encode($status) ?>, source: 'message.php' }); </script> <?php endif; ?> <style> :root{ --bg:#050816;--bg2:#09112b;--ink:#edf7ff;--muted:#9fb2d8;--dim:#536485; --cyan:#42e8ff;--blue:#3b82ff;--violet:#8b5cff;--pink:#ff4fd8;--gold:#ffd36a; --green:#41f2a2;--red:#ff4d67;--edge:rgba(255,255,255,.13);--glass:rgba(255,255,255,.07); --safe-bottom:env(safe-area-inset-bottom); } *{box-sizing:border-box;margin:0;padding:0} html,body{min-height:100%;background:var(--bg);color:var(--ink);font-family:Inter,ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif} body{overflow-x:hidden;background:radial-gradient(circle at 50% 10%,rgba(66,232,255,.16),transparent 32%),radial-gradient(circle at 15% 80%,rgba(255,79,216,.13),transparent 30%),linear-gradient(135deg,#03050d,#07132a 48%,#050816)} canvas{position:fixed;inset:0;width:100%;height:100%;display:block;pointer-events:none} #simon-stars{z-index:0}#simon-orbits{z-index:1;mix-blend-mode:screen;opacity:.9} .shell{position:relative;z-index:5;min-height:100vh;display:grid;place-items:center;padding:24px 16px calc(28px + var(--safe-bottom))} .panel{width:min(1120px,96vw);display:grid;grid-template-columns:0.9fr 1.1fr;gap:18px;align-items:stretch} .hero,.formbox{border:1px solid var(--edge);background:linear-gradient(180deg,rgba(255,255,255,.10),rgba(255,255,255,.045));box-shadow:0 30px 100px rgba(0,0,0,.45),inset 0 1px 0 rgba(255,255,255,.14);backdrop-filter:blur(18px) saturate(130%);border-radius:28px;overflow:hidden} .hero{position:relative;padding:30px;display:flex;flex-direction:column;justify-content:space-between;min-height:620px} .hero:before{content:"";position:absolute;inset:-40%;background:conic-gradient(from 0deg,transparent,rgba(66,232,255,.15),transparent,rgba(255,79,216,.16),transparent,rgba(255,211,106,.12),transparent);animation:spin 18s linear infinite;opacity:.9}.hero>*{position:relative;z-index:1}@keyframes spin{to{transform:rotate(360deg)}} .badge{display:inline-flex;align-items:center;gap:10px;width:max-content;padding:8px 13px;border-radius:999px;border:1px solid rgba(66,232,255,.28);background:rgba(66,232,255,.08);color:var(--cyan);font:800 11px/1 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.16em;text-transform:uppercase}.dot{width:8px;height:8px;border-radius:50%;background:var(--green);box-shadow:0 0 14px var(--green);animation:blink 1.2s ease-in-out infinite}@keyframes blink{50%{opacity:.35}} .title{margin-top:28px;font-size:clamp(3.2rem,8vw,7.8rem);font-weight:950;letter-spacing:-.08em;line-height:.88;color:transparent;background:linear-gradient(145deg,#fff,var(--cyan) 30%,var(--violet) 62%,var(--pink));-webkit-background-clip:text;background-clip:text;filter:drop-shadow(0 0 32px rgba(66,232,255,.28))}.subtitle{margin-top:16px;max-width:42ch;color:rgba(237,247,255,.74);font-size:1.03rem;line-height:1.65}.metrics{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;margin-top:28px}.metric{padding:15px;border-radius:18px;border:1px solid rgba(255,255,255,.11);background:rgba(0,0,0,.22)}.metric b{display:block;color:var(--ink);font-size:1rem}.metric span{display:block;margin-top:4px;color:var(--muted);font-size:.83rem}.rid{margin-top:18px;color:var(--dim);font:12px ui-monospace,SFMono-Regular,Menlo,monospace;word-break:break-all} .formbox{padding:26px}.toprow{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:18px}.toprow h1{font-size:1.35rem}.toprow p{margin-top:6px;color:var(--muted);line-height:1.5;font-size:.93rem}.status{padding:8px 11px;border-radius:999px;border:1px solid rgba(66,232,255,.24);background:rgba(66,232,255,.08);color:var(--cyan);font:800 11px ui-monospace,SFMono-Regular,Menlo,monospace;text-transform:uppercase;white-space:nowrap}.status.sent{border-color:rgba(65,242,162,.35);background:rgba(65,242,162,.1);color:var(--green)}.status.error,.status.failed{border-color:rgba(255,77,103,.35);background:rgba(255,77,103,.1);color:var(--red)} .notice{margin:0 0 16px;padding:12px 14px;border-radius:16px;border:1px solid rgba(255,211,106,.25);background:rgba(255,211,106,.08);color:#ffe7ad;line-height:1.45}.notice.sent{border-color:rgba(65,242,162,.35);background:rgba(65,242,162,.09);color:#caffdf}.notice.error,.notice.failed{border-color:rgba(255,77,103,.35);background:rgba(255,77,103,.09);color:#ffd1d8} form{display:grid;gap:13px}.grid2{display:grid;grid-template-columns:1fr 1fr;gap:13px}label{display:grid;gap:7px;color:var(--muted);font-size:.84rem;font-weight:800;letter-spacing:.03em}input,select,textarea{width:100%;border:1px solid rgba(255,255,255,.13);background:rgba(0,0,0,.28);color:var(--ink);border-radius:15px;padding:13px 14px;font:inherit;outline:none;transition:border-color .18s,box-shadow .18s,background .18s}textarea{min-height:170px;resize:vertical;line-height:1.5}input:focus,select:focus,textarea:focus{border-color:rgba(66,232,255,.64);box-shadow:0 0 0 4px rgba(66,232,255,.09);background:rgba(0,0,0,.36)}.hidden-field{position:absolute;left:-9999px;opacity:0;height:1px;width:1px;overflow:hidden}.actions{display:flex;flex-wrap:wrap;gap:11px;align-items:center;margin-top:4px}.send{cursor:pointer;border:0;border-radius:16px;padding:14px 20px;color:#031018;background:linear-gradient(135deg,var(--cyan),var(--green));font-weight:950;letter-spacing:.03em;box-shadow:0 14px 34px rgba(66,232,255,.22);transition:transform .16s,filter .16s}.send:hover{transform:translateY(-2px);filter:saturate(1.2)}.linkbtn{display:inline-flex;align-items:center;text-decoration:none;color:var(--ink);border:1px solid rgba(255,255,255,.13);background:rgba(255,255,255,.06);border-radius:16px;padding:13px 15px;font-weight:800}.helpgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:18px}.help{display:block;text-decoration:none;color:var(--ink);padding:13px;border-radius:16px;border:1px solid rgba(255,255,255,.11);background:rgba(255,255,255,.05);transition:transform .16s,border-color .16s}.help:hover{transform:translateY(-2px);border-color:rgba(66,232,255,.42)}.help b{display:block;font-size:.9rem}.help span{display:block;margin-top:4px;color:var(--muted);font-size:.78rem;line-height:1.35}.foot{position:relative;z-index:6;text-align:center;color:var(--dim);font-size:.78rem;margin-top:14px}.scan{position:fixed;left:0;right:0;top:0;height:1px;background:linear-gradient(90deg,transparent,var(--cyan),var(--pink),transparent);box-shadow:0 0 18px var(--cyan);animation:sweep 3s linear infinite;z-index:8}@keyframes sweep{0%{transform:translateY(0)}100%{transform:translateY(100vh)}} @media(max-width:900px){.panel{grid-template-columns:1fr}.hero{min-height:420px}.metrics{grid-template-columns:1fr 1fr}.helpgrid{grid-template-columns:1fr}.grid2{grid-template-columns:1fr}.toprow{flex-direction:column}.shell{place-items:start center}.title{font-size:clamp(3.6rem,20vw,7rem)}} @media(prefers-reduced-motion:reduce){*,*:before,*:after{animation:none!important;transition:none!important}} </style> </head> <body> <canvas id="simon-stars" aria-hidden="true"></canvas> <canvas id="simon-orbits" aria-hidden="true"></canvas> <div class="scan" aria-hidden="true"></div> <main class="shell"> <section class="panel" aria-label="SIMON message portal"> <aside class="hero"> <div> <div class="badge"><span class="dot"></span> SIMON Command Link</div> <div class="title">MESSAGE</div> <p class="subtitle">Send a direct signal to Gaylord Sinclair admin. SIMON records the request, tags the session, and routes the message for human review.</p> <div class="metrics"> <div class="metric"><b>Admin Route</b><span><?= h(ADMIN_EMAIL) ?></span></div> <div class="metric"><b>Telemetry</b><span>GA4 · Impact · SIMON Pulse</span></div> <div class="metric"><b>Protection</b><span>Honeypot · rate limit · log ID</span></div> <div class="metric"><b>Reference</b><span>RID attached to every message</span></div> </div> </div> <div class="rid">RID <?= h($rid) ?> · <?= h(gmdate('Y-m-d\TH:i:s\Z')) ?></div> </aside> <section class="formbox"> <div class="toprow"> <div> <h1>Contact SIMON Command</h1> <p>Use this form for support, business, books, art, Web360, SIMON AI, site issues, or general messages.</p> </div> <div class="status <?= h($status) ?>"><?= h($status === 'idle' ? 'Ready' : $status) ?></div> </div> <?php if ($notice !== ''): ?> <div class="notice <?= h($status) ?>"><?= h($notice) ?></div> <?php endif; ?> <form method="post" action="/message.php" id="messageForm" novalidate> <div class="hidden-field" aria-hidden="true"> <label>Website <input type="text" name="website" tabindex="-1" autocomplete="off"></label> </div> <div class="grid2"> <label>Name <input name="name" required maxlength="120" autocomplete="name" value="<?= $old('name') ?>" placeholder="Your name"> </label> <label>Email <input name="email" type="email" required maxlength="180" autocomplete="email" value="<?= $old('email') ?>" placeholder="you@example.com"> </label> </div> <div class="grid2"> <label>Phone optional <input name="phone" maxlength="80" autocomplete="tel" value="<?= $old('phone') ?>" placeholder="Phone number"> </label> <label>Topic <select name="topic"> <?php $topics = ['General Message','Support / Site Issue','Books / Publishing','Art / Tilo Gallery','SIMON AI','Web360','Business Services','Legal / Admin','Partnership','Urgent']; $selectedTopic = (string)($_POST['topic'] ?? ($prefillCode !== '' ? 'Support / Site Issue' : 'General Message')); foreach ($topics as $topic): ?> <option value="<?= h($topic) ?>" <?= $selectedTopic === $topic ? 'selected' : '' ?>><?= h($topic) ?></option> <?php endforeach; ?> </select> </label> </div> <label>Priority <select name="priority"> <?php $priorities = ['normal' => 'Normal', 'high' => 'High', 'urgent' => 'Urgent']; $selectedPriority = (string)($_POST['priority'] ?? ($prefillCode !== '' ? 'high' : 'normal')); foreach ($priorities as $value => $label): ?> <option value="<?= h($value) ?>" <?= $selectedPriority === $value ? 'selected' : '' ?>><?= h($label) ?></option> <?php endforeach; ?> </select> </label> <label>Message <textarea name="message" required maxlength="<?= h((string)MAX_MESSAGE_CHARS) ?>" placeholder="Tell SIMON what you need, what happened, or what to review."><?= $old('message', $prefillMessage) ?></textarea> </label> <div class="actions"> <button class="send" type="submit">Send Message</button> <a class="linkbtn" href="/">Home</a> <a class="linkbtn" href="/sitemap.php">Sitemap</a> </div> </form> <div class="helpgrid" aria-label="Helpful links"> <a class="help" href="/sitemap.php" data-track="help_sitemap"><b>Find a Page</b><span>Open the public SIMON site map.</span></a> <a class="help" href="/simon_ai/" data-track="help_simon_ai"><b>SIMON AI</b><span>Ask the assistant or review AI tools.</span></a> <a class="help" href="/web360/" data-track="help_web360"><b>Web360</b><span>Go to the web builder and app tools.</span></a> </div> </section> </section> <div class="foot">© <?= h(date('Y')) ?> Gaylord Sinclair · Powered by SIMON · Message route: <?= h(ADMIN_EMAIL) ?></div> </main> <script> 'use strict'; (() => { const CFG = window.SIMON_CONFIG || {}; const PAGE = window.SIMON_PAGE || {}; const base = CFG.WEBHOOK_BASE || '/connlink/test1/ui/webhook_inbox.php'; const pulse = CFG.PULSE_STREAM || 'default'; const visit = CFG.VISIT_STREAM || 'visits'; const key = CFG.SIMON_KEY ? ('&key=' + encodeURIComponent(CFG.SIMON_KEY)) : ''; function beacon(stream, payload){ try{ fetch(base + '?stream=' + encodeURIComponent(stream) + key, { method:'POST', headers:{'Content-Type':'application/json'}, keepalive:true, body:JSON.stringify(Object.assign({ title:'SIMON Message · ' + (payload.event || 'event'), source:'message.php', rid:PAGE.rid || '', at:new Date().toISOString(), url:location.href, referrer:document.referrer || '', ua:navigator.userAgent, screen:innerWidth + 'x' + innerHeight, tz:Intl.DateTimeFormat().resolvedOptions().timeZone || 'Local' }, payload || {})) }).catch(()=>{}); }catch(e){} } beacon(visit, {event:'message_page_view', status:PAGE.status || 'idle'}); beacon(pulse, {event:'message_portal_ready', status:PAGE.status || 'idle'}); document.querySelectorAll('a[data-track]').forEach(a => { a.addEventListener('click', () => { const name = a.getAttribute('data-track') || 'link'; beacon(pulse, {event:'message_help_click', target:name, href:a.href}); if (typeof gtag === 'function') gtag('event','simon_message_help_click',{target:name, rid:PAGE.rid || ''}); }); }); const form = document.getElementById('messageForm'); if(form){ form.addEventListener('submit', () => { beacon(pulse, {event:'message_form_submit', status:'attempt'}); if (typeof gtag === 'function') gtag('event','simon_message_submit',{rid:PAGE.rid || ''}); }); } const DPR = Math.min(2, window.devicePixelRatio || 1); const star = document.getElementById('simon-stars'); const orb = document.getElementById('simon-orbits'); const sx = star.getContext('2d'); const ox = orb.getContext('2d'); let W=innerWidth,H=innerHeight,CX=W/2,CY=H/2; const rand=(a,b)=>a+Math.random()*(b-a), TAU=Math.PI*2; let stars=[], nodes=[]; function resize(){ W=innerWidth;H=innerHeight;CX=W/2;CY=H/2; [star,orb].forEach(c=>{c.width=Math.floor(W*DPR);c.height=Math.floor(H*DPR);c.style.width=W+'px';c.style.height=H+'px'}); [sx,ox].forEach(c=>c.setTransform(DPR,0,0,DPR,0,0)); stars=Array.from({length:Math.min(240,Math.floor(W*H/5200))},()=>({x:rand(0,W),y:rand(0,H),r:rand(.4,2.2),a:rand(.15,.9),v:rand(.08,.42)})); nodes=Array.from({length:42},()=>({x:rand(0,W),y:rand(0,H),vx:rand(-.16,.16),vy:rand(-.12,.12),r:rand(1.4,3.6)})); } addEventListener('resize',resize,{passive:true});resize(); function draw(t){ sx.clearRect(0,0,W,H);ox.clearRect(0,0,W,H); const g=sx.createRadialGradient(CX,CY,0,CX,CY,Math.max(W,H)*.72);g.addColorStop(0,'rgba(66,232,255,.08)');g.addColorStop(.45,'rgba(139,92,255,.06)');g.addColorStop(1,'rgba(0,0,0,.02)');sx.fillStyle=g;sx.fillRect(0,0,W,H); for(const s of stars){s.y+=s.v;if(s.y>H+5){s.y=-5;s.x=rand(0,W)}sx.globalAlpha=s.a*(.6+Math.sin(t*.002+s.x)*.3);sx.fillStyle='#dff9ff';sx.beginPath();sx.arc(s.x,s.y,s.r,0,TAU);sx.fill()}sx.globalAlpha=1; for(const n of nodes){n.x+=n.vx;n.y+=n.vy;if(n.x<-20)n.x=W+20;if(n.x>W+20)n.x=-20;if(n.y<-20)n.y=H+20;if(n.y>H+20)n.y=-20} for(let i=0;i<nodes.length;i++){for(let j=i+1;j<nodes.length;j++){const a=nodes[i],b=nodes[j],dx=a.x-b.x,dy=a.y-b.y,d=Math.hypot(dx,dy);if(d<160){ox.strokeStyle='rgba(66,232,255,'+((1-d/160)*.18)+')';ox.lineWidth=1;ox.beginPath();ox.moveTo(a.x,a.y);ox.lineTo(b.x,b.y);ox.stroke()}}} const pulse=1+Math.sin(t*.0016)*.05; for(let k=0;k<5;k++){ox.save();ox.translate(CX,CY);ox.rotate(t*.00012*(k%2?-1:1)+k);ox.scale(pulse,pulse);ox.strokeStyle=k%2?'rgba(255,79,216,.16)':'rgba(66,232,255,.18)';ox.lineWidth=1.4;ox.shadowBlur=18;ox.shadowColor=k%2?'#ff4fd8':'#42e8ff';ox.beginPath();ox.ellipse(0,0,Math.min(W,H)*(.22+k*.045),Math.min(W,H)*(.08+k*.024),0,0,TAU);ox.stroke();ox.restore()} for(const n of nodes){ox.fillStyle='#42e8ff';ox.shadowBlur=12;ox.shadowColor='#42e8ff';ox.beginPath();ox.arc(n.x,n.y,n.r,0,TAU);ox.fill();ox.shadowBlur=0} requestAnimationFrame(draw); } requestAnimationFrame(draw); })(); </script> </body> </html>
Save file
Quick jump
open a path
Open