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,334
Folders
408
Scanned Size
3.84 GB
PHP Files
886
Editable Text Files
12,595
File viewer
guarded to /htdocs
/gaylord/gaylord/old/GayLord_Spatial_v1.0/backups/INDEX_18PLUS.php
<?php declare(strict_types=1); const GL_APP = 'GayLord'; const GL_MIN_AGE = 18; const GL_UPLOAD_MAX = 20_000_000; ini_set('display_errors', isset($_GET['debug']) ? '1' : '0'); ini_set('log_errors', '1'); error_reporting(E_ALL); $privateDir = __DIR__ . '/_gaylord_private'; $uploadDir = $privateDir . '/uploads'; foreach ([$privateDir,$uploadDir] as $dir) { if (!is_dir($dir)) @mkdir($dir, 0700, true); } session_name('GAYLORDFRESH'); session_start(); header('X-Content-Type-Options: nosniff'); header('Referrer-Policy: strict-origin-when-cross-origin'); header('Permissions-Policy: geolocation=(self), camera=(self), microphone=()'); function e(?string $v): string { return htmlspecialchars((string)$v, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); } function csrf(): string { if (empty($_SESSION['csrf'])) $_SESSION['csrf'] = bin2hex(random_bytes(24)); return $_SESSION['csrf']; } function verify_csrf(): void { if (!hash_equals((string)($_SESSION['csrf'] ?? ''), (string)($_POST['csrf'] ?? ''))) { http_response_code(419); exit('Session expired. Reload.'); } } function redirect_to(string $url): never { header('Location: '.$url, true, 303); exit; } function flash(string $type,string $message): void { $_SESSION['flash'][]=['type'=>$type,'message'=>$message]; } function pull_flashes(): array { $x=$_SESSION['flash']??[]; unset($_SESSION['flash']); return is_array($x)?$x:[]; } function age_from_birthdate(string $birth): int { try { return (new DateTimeImmutable($birth))->diff(new DateTimeImmutable('today'))->y; } catch(Throwable) { return 0; } } function db(): PDO { static $pdo; if ($pdo instanceof PDO) return $pdo; $dsn = getenv('GAYLORD_DSN') ?: 'sqlite:' . __DIR__ . '/_gaylord_private/gaylord_fresh.sqlite'; $pdo = new PDO($dsn, getenv('GAYLORD_DB_USER') ?: null, getenv('GAYLORD_DB_PASS') ?: null, [ PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES=>false, ]); if (str_starts_with($dsn,'sqlite:')) { $pdo->exec('PRAGMA foreign_keys=ON'); $pdo->exec('PRAGMA journal_mode=WAL'); } migrate($pdo); return $pdo; } function migrate(PDO $pdo): void { $mysql=$pdo->getAttribute(PDO::ATTR_DRIVER_NAME)==='mysql'; $id=$mysql?'BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY':'INTEGER PRIMARY KEY AUTOINCREMENT'; $dt=$mysql?'TIMESTAMP DEFAULT CURRENT_TIMESTAMP':"TEXT DEFAULT (datetime('now'))"; $pdo->exec("CREATE TABLE IF NOT EXISTS users(id $id, username VARCHAR(40) UNIQUE NOT NULL, email VARCHAR(190) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, display_name VARCHAR(90) NOT NULL, birthdate VARCHAR(10) NOT NULL, created_at $dt)"); $pdo->exec("CREATE TABLE IF NOT EXISTS profiles(user_id BIGINT PRIMARY KEY, pronouns VARCHAR(50) DEFAULT '', orientation VARCHAR(60) DEFAULT '', relationship_status VARCHAR(60) DEFAULT '', relationship_structure VARCHAR(60) DEFAULT '', looking_for VARCHAR(160) DEFAULT '', personality VARCHAR(60) DEFAULT '', communication_style VARCHAR(60) DEFAULT '', social_energy VARCHAR(60) DEFAULT '', love_language VARCHAR(160) DEFAULT '', occupation VARCHAR(100) DEFAULT '', education VARCHAR(100) DEFAULT '', body_type VARCHAR(60) DEFAULT '', height VARCHAR(40) DEFAULT '', exercise VARCHAR(60) DEFAULT '', smoking VARCHAR(60) DEFAULT '', drinking VARCHAR(60) DEFAULT '', pets VARCHAR(60) DEFAULT '', children VARCHAR(60) DEFAULT '', future_children VARCHAR(60) DEFAULT '', travel_style VARCHAR(80) DEFAULT '', nightlife VARCHAR(60) DEFAULT '', about_me TEXT DEFAULT '', interests TEXT DEFAULT '', boundaries TEXT DEFAULT '', privacy_level VARCHAR(40) DEFAULT 'members', city VARCHAR(100) DEFAULT '', latitude DECIMAL(10,7) NULL, longitude DECIMAL(10,7) NULL, share_location INTEGER DEFAULT 0, theme VARCHAR(40) DEFAULT 'auto', cover_media_id BIGINT NULL, avatar_media_id BIGINT NULL)"); $pdo->exec("CREATE TABLE IF NOT EXISTS profile_answers(id $id,user_id BIGINT NOT NULL,question_key VARCHAR(80) NOT NULL,answer TEXT NOT NULL,visibility VARCHAR(30) DEFAULT 'members',updated_at $dt)"); $pdo->exec("CREATE TABLE IF NOT EXISTS threads(id $id,created_at $dt)"); $pdo->exec("CREATE TABLE IF NOT EXISTS thread_members(thread_id BIGINT NOT NULL,user_id BIGINT NOT NULL,last_read_id BIGINT DEFAULT 0,PRIMARY KEY(thread_id,user_id))"); $pdo->exec("CREATE TABLE IF NOT EXISTS messages(id $id,thread_id BIGINT NOT NULL,sender_id BIGINT NOT NULL,body TEXT NOT NULL,created_at $dt)"); $pdo->exec("CREATE TABLE IF NOT EXISTS groups(id $id,owner_id BIGINT NOT NULL,name VARCHAR(100) NOT NULL,tagline VARCHAR(160) DEFAULT '',description TEXT DEFAULT '',category VARCHAR(60) DEFAULT 'Community',privacy VARCHAR(30) DEFAULT 'public',vibe VARCHAR(60) DEFAULT 'Cosmic',art_style VARCHAR(40) DEFAULT 'cosmic',image_media_id BIGINT NULL,created_at $dt)"); $pdo->exec("CREATE TABLE IF NOT EXISTS group_members(group_id BIGINT NOT NULL,user_id BIGINT NOT NULL,role VARCHAR(30) DEFAULT 'member',joined_at $dt,PRIMARY KEY(group_id,user_id))"); $pdo->exec("CREATE TABLE IF NOT EXISTS group_posts(id $id,group_id BIGINT NOT NULL,user_id BIGINT NOT NULL,body TEXT NOT NULL,created_at $dt)"); $pdo->exec("CREATE TABLE IF NOT EXISTS media(id $id,user_id BIGINT NOT NULL,kind VARCHAR(30) DEFAULT 'profile',storage_name VARCHAR(255) NOT NULL,original_name VARCHAR(255) NOT NULL,mime VARCHAR(90) NOT NULL,created_at $dt)"); $pdo->exec("CREATE TABLE IF NOT EXISTS notifications(id $id,user_id BIGINT NOT NULL,title VARCHAR(140) NOT NULL,body VARCHAR(500) NOT NULL,is_read INTEGER DEFAULT 0,created_at $dt)"); $pdo->exec("CREATE TABLE IF NOT EXISTS events(id $id,user_id BIGINT NOT NULL,title VARCHAR(140) NOT NULL,description TEXT DEFAULT '',location VARCHAR(180) DEFAULT '',starts_at VARCHAR(32) NOT NULL,ends_at VARCHAR(32) DEFAULT '',visibility VARCHAR(30) DEFAULT 'members',created_at $dt)"); $pdo->exec("CREATE TABLE IF NOT EXISTS albums(id $id,user_id BIGINT NOT NULL,title VARCHAR(140) NOT NULL,description TEXT DEFAULT '',visibility VARCHAR(30) DEFAULT 'members',cover_media_id BIGINT NULL,created_at $dt)"); $pdo->exec("CREATE TABLE IF NOT EXISTS album_media(album_id BIGINT NOT NULL,media_id BIGINT NOT NULL,PRIMARY KEY(album_id,media_id))"); $pdo->exec("CREATE TABLE IF NOT EXISTS reels(id $id,user_id BIGINT NOT NULL,caption VARCHAR(500) DEFAULT '',media_id BIGINT NOT NULL,visibility VARCHAR(30) DEFAULT 'members',created_at $dt)"); $pdo->exec("CREATE TABLE IF NOT EXISTS adult_links(id $id,user_id BIGINT NOT NULL,title VARCHAR(500) NOT NULL,url TEXT NOT NULL,thumbnail_url TEXT DEFAULT '',source VARCHAR(60) DEFAULT 'manual',created_at $dt)"); $pdo->exec("CREATE TABLE IF NOT EXISTS applications(id $id,user_id BIGINT NOT NULL,name VARCHAR(120) NOT NULL,api_key VARCHAR(120) NOT NULL,callback_url VARCHAR(255) DEFAULT '',is_enabled INTEGER DEFAULT 1,created_at $dt)"); $pdo->exec("CREATE TABLE IF NOT EXISTS developer_logs(id $id,user_id BIGINT NOT NULL,level VARCHAR(20) DEFAULT 'info',event_name VARCHAR(120) NOT NULL,message TEXT DEFAULT '',created_at $dt)"); if (!$mysql) { $pdo->exec('CREATE INDEX IF NOT EXISTS idx_messages_thread ON messages(thread_id,id)'); $pdo->exec('CREATE INDEX IF NOT EXISTS idx_group_posts_group ON group_posts(group_id,id)'); } } function seed_adult_bookmarks(int $uid): void { $s=db()->prepare('SELECT COUNT(*) FROM adult_links WHERE user_id=?');$s->execute([$uid]); if((int)$s->fetchColumn()>0)return; $items=[["Dallas Steele and Sir Jet at Gay0Day","https://gay0day.com/videos/126994/dallas-steele-and-sir-jet/"],["R","https://gay0day.com/videos/292387/athletic-william-seed-tries-bottoming-with-a-muscular-top-for-the-first-time-and-he-loves-it-men/"],["Rocco Gay Porn Videos at Gay0Day","https://gay0day.com/search/rocco/"],["Max Konnor & Wess Russel watch online","https://gay0day.com/videos/85344/max-konnor-wess-russel/"],["CB - Jake Jaxsons All Saints - Part 4 watch online","https://gay0day.com/videos/153900/cb-jake-jaxson-s-all-saints-part-4/"],["Steven Lee & Cazden Hunter watch online","https://gay0day.com/videos/128758/steven-lee-cazden-hunter/"],["BIG WHITE DICK FOR HORNY BLACK ASS - XVIDEOS.COM","https://www.xvideos.com/video.ikfmtlvb1b7/big_white_dick_for_horny_black_ass"],["Two arabs fucking a white twink - XVIDEOS.COM","https://www.xvideos.com/video.kloccdo93de/two_arabs_fucking_a_white_twink"],["Muscles","https://www.xvideos.com/c/Gay_muscles-129"],["Guy on Guy on Girl Stack! MMF Bisexual Threesome with Steve Rickz, Aliya Brynn, and Inkfit - XVIDEOS.COM","https://www.xvideos.com/video.upombbode18/guy_on_guy_on_girl_stack_mmf_bisexual_threesome_with_steve_rickz_aliya_brynn_and_inkfit"],["ActiveDuty - Sexy Adonis Services Tatted Hunk - XVIDEOS.COM","https://www.xvideos.com/video.uoubvef3a1a/activeduty_-_sexy_adonis_services_tatted_hunk"],["Bi MMF Threesome! Horny Babe Gets Pussy Pounded & Jock Gets Hard Rough Anal - Steve Rickz, Christian Wilde, Rocky Emerson - XVIDEOS.COM","https://www.xvideos.com/video.ucivkpf9b47/bi_mmf_threesome_horny_babe_gets_pussy_pounded_and_jock_gets_hard_rough_anal_-_steve_rickz_christian_wilde_rocky_emerson#show-related"],["Myvid4 - XVIDEOS.COM","https://www.xvideos.com/video.kpvttlk3e29/myvid4"],["Apprentice Dex Devall grabbing every inch of Master Kyler Drakes cock with his internal muscles - XVIDEOS.COM","https://www.xvideos.com/video.ucklpbodfe9/apprentice_dex_devall_grabbing_every_inch_of_master_kyler_drakes_cock_with_his_internal_muscles"],["white and black dude having rough anal sex hot interracial scene - XNXX.COM","https://www.xnxx.com/video-qma5jf0/white_and_black_dude_having_rough_anal_sex_hot_interracial_scene"],["Raws Rocco & Dionisio - XNXX.COM","https://www.xnxx.com/video-uw92da9/raws_rocco_and_dionisio#show-related"],["Gay Hoopla - Gay Porn Maker - XNXX.COM","https://www.xnxx.com/porn-maker/gay-hoopla"],["BLACKED Blonde takes on Huge BBC - XNXX.COM","https://www.xnxx.com/video-fwpgd15/blacked_blonde_takes_on_huge_bbc"],["Rocco Raw Seth Knight - XNXX.COM","https://www.xnxx.com/video-unv6d11/rocco_raw_seth_knight"],["Hairy gay bear fucking his hunky boyfriend - XVIDEOS.COM","https://www.xvideos.com/video11789195/hairy_gay_bear_fucking_his_hunky_boyfriend"],["Porn Pays - XVIDEOS.COM","https://www.xvideos.com/video47552609/porn_pays#show-related"],["Muscle gay threesome with cumshot - XVIDEOS.COM","https://www.xvideos.com/video27593945/muscle_gay_threesome_with_cumshot"],["Sean Takes Joshs Big Cock In His Ass Before Justin Gets A Chance To Fuck Seans Bubble Butt - Sean Cody - XVIDEOS.COM","https://www.xvideos.com/video64651629/sean_takes_joshs_big_cock_in_his_ass_before_justin_gets_a_chance_to_fuck_seans_bubble_butt_-_sean_cody"],["Two Juicy Hunks Collide! Muscle Micky Fucks Juicy Jeremy! - XVIDEOS.COM","https://www.xvideos.com/video69972383/two_juicy_hunks_collide_muscle_micky_fucks_juicy_jeremy_#show-related"],["A Stepbrothers Obsession - XVIDEOS.COM","https://www.xvideos.com/video49029023/a_stepbrothers_obsession#show-related"],["A Random Dude Comes In The Cabin Starts Looking Around When He Stumbles Upon The Group Sex Upstairs - Sean Cody - XVIDEOS.COM","https://www.xvideos.com/video67077749/a_random_dude_comes_in_the_cabin_starts_looking_around_when_he_stumbles_upon_the_group_sex_upstairs_-_sean_cody#"],["The thickest roll I've ever seen - XVIDEOS.COM","https://www.xvideos.com/video63226419/the_thickest_roll_i_ve_ever_seen#show-related"],["Muscular amateur jock pounds dude butt - XVIDEOS.COM","https://www.xvideos.com/video8317968/muscular_amateur_jock_pounds_dude_butt"],["Seth Sweet - XVIDEOS.COM","https://www.xvideos.com/video317021/seth_sweet#show-related"],["Muscular amateur jock pounds dude butt - XVIDEOS.COM","https://www.xvideos.com/video8317968/muscular_amateur_jock_pounds_dude_butt#show-related"],["Gentlemen at the office | xHamster","https://xhamster.com/videos/gentlemen-at-the-office-3452092"],["Rico Marlon s Raw Orgy - Dylan James, Michael Roman watch online","https://gay0day.com/videos/315/rico-marlon-s-raw-orgy-dylan-james-michael-roman/"],["Massive Cocked Kyler Drayke Cumpilation - Activeduty: Gay Muscular Big Cock Porn | xHamster","https://xhamster.com/videos/massive-cocked-kyler-drayke-cumpilation-activeduty-xhRNO1v"],["Raunchy Soldiers Flip Fuck The Fuck Out Of Each Other | xHamster","https://xhamster.com/videos/raunchy-soldiers-flip-fuck-the-fuck-out-of-each-other-xhpDcxp"],["BEST 207 | xHamster","https://xhamster.com/videos/best-207-xhg5F7h"],["Gay Sex : Maximilia Barmin & Skinny gay (Bareback) | xHamster","https://xhamster.com/videos/gay-sex-maximilia-barmin-skinny-gay-bareback-xhgQ2bh"],["Just met and fucked insanely watch online","https://ca3h.com/videos/4856/just-met-and-fucked-insanely/"],["Navy Bareback | xHamster","https://xhamster.com/videos/navy-bareback-xhLRsgy"],["Francois Sagat and Ricky Roman (ASCO P3) | xHamster","https://xhamster.com/videos/francois-sagat-and-ricky-roman-asco-p3-xhctOXM"],["tayte & ricky | xHamster","https://xhamster.com/videos/tayte-ricky-11131226"],["Seeding My Stud Watching Him Cum | xHamster","https://xhamster.com/videos/seeding-my-stud-watching-him-cum-10026836"],["Full 51 Min Movie - that Summer - Hunk College City Boy Dicks Down Beefy Straight Country Boy - Nextdoorstudios: Gay Porn | xHamster","https://xhamster.com/videos/full-51-min-movie-that-summer-hunk-college-city-boy-dicks-down-beefy-straight-country-boy-nextdoorstudios-xhpWxT8"],["Devils Film - Hot Bisexual Threesome with Cute Wife Spencer Bradley Her Husband and Her Lover | xHamster","https://xhamster.com/videos/devils-film-hot-bisexual-threesome-with-cute-wife-spencer-bradley-her-husband-and-her-lover-xhhXUvl"],["Free Recommended Gay Punishment Porn Videos | xHamster","https://xhamster.com/gay/tags/gay-punishment/recommended"],["Lewd Stepfathers Explore Unorthodox Step-parenting Methods with Their Mischievous Stepsons: Gay Porn | xHamster","https://xhamster.com/videos/lewd-stepfathers-explore-unorthodox-step-parenting-methods-with-their-mischievous-stepsons-xhsco5z"],["Venyveras: Gay Blowjob Masturbation Porn feat. Carter Dane | xHamster","https://xhamster.com/videos/venyveras-9344909"],["Threesome Muscle Fuck with Creampie Bareback the Best: Gay Big Cock Porn feat. Ricky Roman | xHamster","https://xhamster.com/videos/threesome-muscle-fuck-with-creampie-bareback-the-best-xh5scAi"],["teen Logan Seduces lusty Steve Rogers iGayTube TV","https://www.igaytube.tv/teen-logan-seduces-lusty-steve-rogers_1130031.html"],["tasty Tatts iGayTube TV","https://www.igaytube.tv/tasty-tatts_580564.html"],["Breaking in Julian: Gay Big Ass Big Cock Porn by Guys in Sweatpants | xHamster","https://xhamster.com/videos/breaking-in-julian-xhFNoAj"],["Submission Bondage Dildo Anal Play: Gay Old & Young Porn feat. Alexander Volkov | xHamster","https://xhamster.com/videos/submission-bondage-dildo-anal-play-13358200"],["Muscular Gay Porn Videos | xHamster","https://xhamster.com/gay/categories/muscular"],["Boomer Banks and Thyle Knoxx Rfc: Gay Couple Porn | xHamster","https://xhamster.com/videos/boomer-banks-and-thyle-knoxx-rfc-xhvTcxM"],["Fucking the Straight Guy from the Gym: Gay Porn | xHamster","https://xhamster.com/videos/fucking-the-straight-guy-from-the-gym-xhFpcCa"],["Malik Tn and Tony Axel Satc P2: Gay Couple Big Cock Porn | xHamster","https://xhamster.com/videos/malik-tn-and-tony-axel-satc-p2-xhwPw8Y"],["Rail that Ass Raw Sc1: Gay Anal Porn feat. Drake Rogers | xHamster","https://xhamster.com/videos/rail-that-ass-raw-sc1-xhOlpIM"],["Shaved bearded bear carrying 26cm hard pike of the male - XVIDEOS.COM","https://www.xvideos.com/video.uedfkeh5230/shaved_bearded_bear_carrying_26cm_hard_pike_of_the_male"],["Gay - Sean Cody - XNXX.COM","https://www.xnxx.com/video-tg47tef/gay_-_sean_cody"],["30 Df L L: Gay Group Sex Anal Porn | xHamster","https://xhamster.com/videos/30-df-l-l-xhWaUjl"],["Please let us know how to get motivated and enthusiastic about the best way to get back with you - XNXX.COM","https://www.xnxx.com/video-mfuw9dd/please_let_us_know_how_to_get_motivated_and_enthusiastic_about_the_best_way_to_get_back_with_you#show-related"],["brand new passive withstood my big dick without a condom - XNXX.COM","https://www.xnxx.com/video-16hmtb7e/brand_new_passive_withstood_my_big_dick_without_a_condom#show-related"],["FalconStudios - Beautiful Inked Hunk Pounds His Lil Jock Blonde Boy Toy - XVIDEOS.COM","https://www.xvideos.com/video.updlfokde41/falconstudios_-_beautiful_inked_hunk_pounds_his_lil_jock_blonde_boy_toy"],["Strong and hot passive taking a big dick in the ass - XVIDEOS.COM","https://www.xvideos.com/video.ufppabh77f6/strong_and_hot_passive_taking_a_big_dick_in_the_ass"],["Big dick male thrusting hard into the muscular man - XVIDEOS.COM","https://www.xvideos.com/video.ufkiathba6d/big_dick_male_thrusting_hard_into_the_muscular_man"],["Bald guy fucking tattooed passive - XVIDEOS.COM","https://www.xvideos.com/video.ufkilav5586/bald_guy_fucking_tattooed_passive#show-related"],["Raging Stallion Official - Gay Channel page - XVIDEOS.COM","https://www.xvideos.com/ragingstallionofficial"],["I do anal with my black friend for the first time - XVIDEOS.COM","https://www.xvideos.com/video.ubkkeuo2e3c/i_do_anal_with_my_black_friend_for_the_first_time#show-related"],["gay-big-dick videos - XVIDEOS.COM","https://www.xvideos.com/tags/t:gay/gay-big-dick"],["Erick Hall Big Cock fucks Gage Palmer Big Butt doing Splits Bareback - XVIDEOS.COM","https://www.xvideos.com/video.ubhblhh25c5/erick_hall_big_cock_fucks_gage_palmer_big_butt_doing_splits_bareback#show-related"],["Rafael Alencar and Me - XVIDEOS.COM","https://www.xvideos.com/video.kcfffldfee9/rafael_alencar_and_me#show-related"],["Ebony jock spills load after white cock anal - XVIDEOS.COM","https://www.xvideos.com/video.mvtcmi357e/ebony_jock_spills_load_after_white_cock_anal"],["Horny ebony assfuck threesome ends in cum - XVIDEOS.COM","https://www.xvideos.com/video.ktuefav2995/horny_ebony_assfuck_threesome_ends_in_cum"],["Cutler Fucks and Breeds Siren's Smooth Tight Bubble Butt with His Monster Uncut Cock: Gay Porn | xHamster","https://xhamster.com/videos/cutler-fucks-and-breeds-sirens-smooth-tight-bubble-butt-with-his-monster-uncut-cock-xhOcXtT"],["Begging for Raw Cock Sc3: Portuguese Gay Couple Anal Porn | xHamster","https://xhamster.com/videos/begging-for-raw-cock-sc3-xhUj7jv"],["Big Cock Pounding Hard: Gay Couple Porn feat. Diego Mineiro | xHamster","https://xhamster.com/videos/big-cock-pounding-hard-xhCyVvQ"],["Power: Gay Porn feat. Eric Evans | xHamster","https://xhamster.com/videos/power-10115274"],["hot gay group bareback - XVIDEOS.COM","https://www.xvideos.com/video.ifmbhdh70c8/hot_gay_group_bareback"],["xvideos.com fbe1f046789f903ae600722cecb0dd53 - XVIDEOS.COM","https://www.xvideos.com/video.hkecuam1f7a/xvideos.com_fbe1f046789f903ae600722cecb0dd53"],["BIG DICK FUCKS THE ASS OF THE NAUGHTY BLACK GUY - XVIDEOS.COM","https://www.xvideos.com/video.ohkibfm6535/big_dick_fucks_the_ass_of_the_naughty_black_guy#show-related"],["Optum","https://new.optumrx.com/secure/medication-list/medication-details/000010587111"],["Two Big Cocked Monsters and a Horny Slut - XVIDEOS.COM","https://www.xvideos.com/video.udbieah1c18/two_big_cocked_monsters_and_a_horny_slut#show-related"],["'noir male gay' Search - XNXX.COM","https://www.xnxx.com/search/gay/noir+male+gay"],["Gay Porn Categories List | GayPorn.com","https://gayporn.com/categories"],["FalconStudios Brent Corrigan bottoms for Skyy Knox","https://gay0day.com/videos/147531/falconstudios-brent-corrigan-bottoms-for-skyy-knox/"],["Pink Pussy Blonde Enjoying Maximos Cock- Gabriely Della - XVIDEOS.COM","https://www.xvideos.com/video.ouutuucd5d7/maximo_garcia_and_baby_nicols_in_a_sexy_pussy_fuck_"]]; $ins=db()->prepare('INSERT INTO adult_links(user_id,title,url,thumbnail_url,source) VALUES(?,?,?,?,?)'); foreach($items as $item){ $url=(string)$item[1]; $thumb='https://image.thum.io/get/width/720/crop/430/noanimate/'.rawurlencode($url); $ins->execute([$uid,(string)$item[0],$url,$thumb,'Safari Rated X import']); } } function adult_favicon(string $url): string { $host=(string)(parse_url($url,PHP_URL_HOST)?:''); return 'https://www.google.com/s2/favicons?domain='.rawurlencode($host).'&sz=128'; } function current_user(): ?array { if (empty($_SESSION['uid'])) return null; $s=db()->prepare('SELECT u.*,p.* FROM users u LEFT JOIN profiles p ON p.user_id=u.id WHERE u.id=?'); $s->execute([(int)$_SESSION['uid']]); return $s->fetch() ?: null; } function require_user(): array { $u=current_user(); if(!$u){ flash('error','Please sign in first.'); redirect_to('./'); } return $u; } function media_url(int $id): string { return './?action=media&id='.$id; } function save_upload(string $field,int $uid,string $kind='profile',bool $allowVideo=false): ?int { if (empty($_FILES[$field]) || !is_array($_FILES[$field]) || (int)$_FILES[$field]['error']===UPLOAD_ERR_NO_FILE) return null; $f=$_FILES[$field]; if ((int)$f['error']!==UPLOAD_ERR_OK || (int)$f['size']<=0 || (int)$f['size']>GL_UPLOAD_MAX) throw new RuntimeException('Upload failed or is too large. Maximum size is 20 MB.'); $mime=(string)(new finfo(FILEINFO_MIME_TYPE))->file((string)$f['tmp_name']); $allowed=['image/jpeg'=>'jpg','image/png'=>'png','image/webp'=>'webp']; if($allowVideo)$allowed+=['video/mp4'=>'mp4','video/webm'=>'webm','video/quicktime'=>'mov']; if(!isset($allowed[$mime])) throw new RuntimeException($allowVideo?'Use JPEG, PNG, WebP, MP4, WebM, or MOV.':'Only JPEG, PNG, or WebP images are allowed.'); $name=bin2hex(random_bytes(20)).'.'.$allowed[$mime]; $path=$GLOBALS['uploadDir'].'/'.$name; if(!move_uploaded_file((string)$f['tmp_name'],$path)) throw new RuntimeException('Could not save the upload.'); @chmod($path,0600); $s=db()->prepare('INSERT INTO media(user_id,kind,storage_name,original_name,mime) VALUES(?,?,?,?,?)'); $s->execute([$uid,$kind,$name,basename((string)$f['name']),$mime]); return (int)db()->lastInsertId(); } $action=(string)($_GET['action']??''); if($action==='media'){ $me=require_user(); $s=db()->prepare('SELECT * FROM media WHERE id=?'); $s->execute([(int)($_GET['id']??0)]); $m=$s->fetch(); if(!$m){http_response_code(404);exit('Not found');} $path=$uploadDir.'/'.basename((string)$m['storage_name']); if(!is_file($path)){http_response_code(404);exit('Not found');} header('Content-Type: '.$m['mime']); header('Content-Length: '.filesize($path)); header('Cache-Control: private, max-age=900'); readfile($path); exit; } if($_SERVER['REQUEST_METHOD']==='POST'){ verify_csrf(); $pa=(string)($_POST['action']??''); try{ if($pa==='register'){ $username=trim((string)($_POST['username']??''));$email=strtolower(trim((string)($_POST['email']??'')));$name=trim((string)($_POST['display_name']??''));$birth=(string)($_POST['birthdate']??'');$password=(string)($_POST['password']??''); if(!preg_match('/^[A-Za-z0-9_]{3,40}$/',$username)) throw new RuntimeException('Username must be 3–40 letters, numbers, or underscores.'); if(!filter_var($email,FILTER_VALIDATE_EMAIL)) throw new RuntimeException('Enter a valid email.'); if(age_from_birthdate($birth)<GL_MIN_AGE) throw new RuntimeException('GayLord is for adults 18+ only.'); if(strlen($password)<10) throw new RuntimeException('Password must be at least 10 characters.'); $s=db()->prepare('INSERT INTO users(username,email,password_hash,display_name,birthdate) VALUES(?,?,?,?,?)'); $s->execute([$username,$email,password_hash($password,PASSWORD_DEFAULT),$name,$birth]); $uid=(int)db()->lastInsertId(); db()->prepare('INSERT INTO profiles(user_id) VALUES(?)')->execute([$uid]); $_SESSION['uid']=$uid; session_regenerate_id(true); redirect_to('./?view=profile'); } if($pa==='login'){ $id=strtolower(trim((string)($_POST['identity']??'')));$password=(string)($_POST['password']??''); $s=db()->prepare('SELECT * FROM users WHERE lower(email)=? OR lower(username)=? LIMIT 1');$s->execute([$id,$id]);$u=$s->fetch(); if(!$u || !password_verify($password,(string)$u['password_hash'])) throw new RuntimeException('Sign-in information did not match.'); $_SESSION['uid']=(int)$u['id'];session_regenerate_id(true);redirect_to('./?view=home'); } if($pa==='logout'){$_SESSION=[];session_destroy();redirect_to('./');} $me=require_user();$uid=(int)$me['id']; if($pa==='save_profile'){ $fields=['pronouns','orientation','relationship_status','relationship_structure','looking_for','personality','communication_style','social_energy','love_language','occupation','education','body_type','height','exercise','smoking','drinking','pets','children','future_children','travel_style','nightlife','about_me','interests','boundaries','privacy_level','city','theme']; $values=[];foreach($fields as $f)$values[$f]=trim((string)($_POST[$f]??'')); $avatar=save_upload('avatar',$uid,'avatar');$cover=save_upload('cover',$uid,'cover'); $set=[];$params=[];foreach($fields as $f){$set[]="$f=?";$params[]=$values[$f];} if($avatar){$set[]='avatar_media_id=?';$params[]=$avatar;} if($cover){$set[]='cover_media_id=?';$params[]=$cover;} $params[]=$uid;db()->prepare('UPDATE profiles SET '.implode(',',$set).' WHERE user_id=?')->execute($params); flash('success','Profile saved.');redirect_to('./?view=profile'); } if($pa==='save_interview'){ $answers=json_decode((string)($_POST['answers_json']??'{}'),true); if(!is_array($answers))$answers=[]; db()->prepare('DELETE FROM profile_answers WHERE user_id=?')->execute([$uid]); $ins=db()->prepare('INSERT INTO profile_answers(user_id,question_key,answer,visibility) VALUES(?,?,?,?)'); foreach($answers as $k=>$v){$ins->execute([$uid,(string)$k,is_array($v)?implode(', ',$v):(string)$v,'matches']);} flash('success','Guided interview saved and profile suggestions updated.');redirect_to('./?view=profile'); } if($pa==='create_group'){ $name=trim((string)($_POST['name']??'')); if($name==='') throw new RuntimeException('Group name is required.'); $image=save_upload('group_image',$uid,'group'); $s=db()->prepare('INSERT INTO groups(owner_id,name,tagline,description,category,privacy,vibe,art_style,image_media_id) VALUES(?,?,?,?,?,?,?,?,?)'); $s->execute([$uid,$name,trim((string)$_POST['tagline']),trim((string)$_POST['description']),trim((string)$_POST['category']),trim((string)$_POST['privacy']),trim((string)$_POST['vibe']),trim((string)$_POST['art_style']),$image]); $gid=(int)db()->lastInsertId();db()->prepare("INSERT INTO group_members(group_id,user_id,role) VALUES(?,?,'owner')")->execute([$gid,$uid]); flash('success','Group created.');redirect_to('./?view=groups&group='.$gid); } if($pa==='join_group'){ $gid=(int)($_POST['group_id']??0);$driver=db()->getAttribute(PDO::ATTR_DRIVER_NAME); if($driver==='mysql')db()->prepare('INSERT IGNORE INTO group_members(group_id,user_id) VALUES(?,?)')->execute([$gid,$uid]); else db()->prepare('INSERT OR IGNORE INTO group_members(group_id,user_id) VALUES(?,?)')->execute([$gid,$uid]); redirect_to('./?view=groups&group='.$gid); } if($pa==='group_post'){ $gid=(int)($_POST['group_id']??0);$body=trim((string)($_POST['body']??''));if($body==='')throw new RuntimeException('Write a post first.'); db()->prepare('INSERT INTO group_posts(group_id,user_id,body) VALUES(?,?,?)')->execute([$gid,$uid,$body]);redirect_to('./?view=groups&group='.$gid); } if($pa==='start_thread'){ $other=(int)($_POST['other_id']??0);if($other<=0||$other===$uid)throw new RuntimeException('Choose another member.'); db()->beginTransaction();db()->exec('INSERT INTO threads DEFAULT VALUES');$tid=(int)db()->lastInsertId();$s=db()->prepare('INSERT INTO thread_members(thread_id,user_id) VALUES(?,?)');$s->execute([$tid,$uid]);$s->execute([$tid,$other]);db()->commit();redirect_to('./?view=messages&thread='.$tid); } if($pa==='send_message'){ $tid=(int)($_POST['thread_id']??0);$body=trim((string)($_POST['body']??''));if($body==='')throw new RuntimeException('Message is empty.'); $s=db()->prepare('SELECT 1 FROM thread_members WHERE thread_id=? AND user_id=?');$s->execute([$tid,$uid]);if(!$s->fetchColumn())throw new RuntimeException('Conversation unavailable.'); db()->prepare('INSERT INTO messages(thread_id,sender_id,body) VALUES(?,?,?)')->execute([$tid,$uid,$body]);redirect_to('./?view=messages&thread='.$tid); } if($pa==='create_event'){ $title=trim((string)($_POST['title']??''));$starts=trim((string)($_POST['starts_at']??''));if($title===''||$starts==='')throw new RuntimeException('Event title and start time are required.'); db()->prepare('INSERT INTO events(user_id,title,description,location,starts_at,ends_at,visibility) VALUES(?,?,?,?,?,?,?)')->execute([$uid,$title,trim((string)($_POST['description']??'')),trim((string)($_POST['location']??'')),$starts,trim((string)($_POST['ends_at']??'')),trim((string)($_POST['visibility']??'members'))]); db()->prepare('INSERT INTO notifications(user_id,title,body) VALUES(?,?,?)')->execute([$uid,'Event created',$title.' was added to your calendar.']);flash('success','Event created.');redirect_to('./?view=events'); } if($pa==='create_album'){ $title=trim((string)($_POST['title']??''));if($title==='')throw new RuntimeException('Album title is required.');$cover=save_upload('cover',$uid,'album'); db()->prepare('INSERT INTO albums(user_id,title,description,visibility,cover_media_id) VALUES(?,?,?,?,?)')->execute([$uid,$title,trim((string)($_POST['description']??'')),trim((string)($_POST['visibility']??'members')),$cover]);flash('success','Album created.');redirect_to('./?view=albums'); } if($pa==='add_adult_link'){ $title=trim((string)($_POST['title']??''));$url=trim((string)($_POST['url']??'')); if($title===''||!filter_var($url,FILTER_VALIDATE_URL))throw new RuntimeException('Enter a title and valid URL.'); $thumb=trim((string)($_POST['thumbnail_url']??''));if($thumb===''||!filter_var($thumb,FILTER_VALIDATE_URL))$thumb='https://image.thum.io/get/width/720/crop/430/noanimate/'.rawurlencode($url); db()->prepare('INSERT INTO adult_links(user_id,title,url,thumbnail_url,source) VALUES(?,?,?,?,?)')->execute([$uid,$title,$url,$thumb,'manual']); flash('success','18+ thumbnail added.');redirect_to('./?view=reels'); } if($pa==='upload_reel'){ $mid=save_upload('reel',$uid,'reel',true);if(!$mid)throw new RuntimeException('Choose a reel video or image.'); db()->prepare('INSERT INTO reels(user_id,caption,media_id,visibility) VALUES(?,?,?,?)')->execute([$uid,trim((string)($_POST['caption']??'')),$mid,trim((string)($_POST['visibility']??'members'))]); db()->prepare('INSERT INTO notifications(user_id,title,body) VALUES(?,?,?)')->execute([$uid,'Reel uploaded','Your reel is now available.']);flash('success','Reel uploaded.');redirect_to('./?view=reels'); } if($pa==='mark_alerts_read'){db()->prepare('UPDATE notifications SET is_read=1 WHERE user_id=?')->execute([$uid]);redirect_to('./?view=notifications');} if($pa==='save_settings'){ $theme=trim((string)($_POST['theme']??'auto'));$privacy=trim((string)($_POST['privacy_level']??'members'));db()->prepare('UPDATE profiles SET theme=?,privacy_level=? WHERE user_id=?')->execute([$theme,$privacy,$uid]);flash('success','Application settings saved.');redirect_to('./?view=settings'); } if($pa==='create_application'){ $name=trim((string)($_POST['name']??''));if($name==='')throw new RuntimeException('Application name is required.');$key='gl_'.bin2hex(random_bytes(24)); db()->prepare('INSERT INTO applications(user_id,name,api_key,callback_url) VALUES(?,?,?,?)')->execute([$uid,$name,$key,trim((string)($_POST['callback_url']??''))]);flash('success','Application created. Copy its API key below.');redirect_to('./?view=developer'); } if($pa==='developer_message'){ $event=trim((string)($_POST['event_name']??''));$message=trim((string)($_POST['message']??''));if($event===''||$message==='')throw new RuntimeException('Event name and message are required.'); db()->prepare('INSERT INTO developer_logs(user_id,level,event_name,message) VALUES(?,?,?,?)')->execute([$uid,trim((string)($_POST['level']??'info')),$event,$message]); db()->prepare('INSERT INTO notifications(user_id,title,body) VALUES(?,?,?)')->execute([$uid,'Developer event: '.$event,$message]);flash('success','Developer message sent and event logged.');redirect_to('./?view=developer'); } }catch(Throwable $ex){flash('error',$ex->getMessage());redirect_to($_SERVER['HTTP_REFERER']??'./');} } $me=current_user();$flashes=pull_flashes();$view=(string)($_GET['view']??($me?'home':'welcome')); $allowed=['welcome','home','discover','messages','groups','events','marketplace','albums','reels','spatial','profile','progress','notifications','settings','safety','developer'];if(!in_array($view,$allowed,true))$view=$me?'home':'welcome'; $users=[];$groups=[];$threads=[];$threadMessages=[];$selectedThread=0;$selectedGroup=null;$groupPosts=[];$events=[];$albums=[];$reels=[];$adultLinks=[];$alerts=[];$applications=[];$devLogs=[];$avatarUrl='';$coverUrl=''; if($me){ $uid=(int)$me['id']; $users=db()->query("SELECT u.id,u.display_name,u.username,p.city,p.looking_for,p.personality,p.avatar_media_id FROM users u LEFT JOIN profiles p ON p.user_id=u.id WHERE u.id<>$uid ORDER BY u.id DESC LIMIT 24")->fetchAll(); $groups=db()->query("SELECT g.*,u.display_name owner_name,(SELECT COUNT(*) FROM group_members gm WHERE gm.group_id=g.id) member_count FROM groups g JOIN users u ON u.id=g.owner_id ORDER BY g.id DESC LIMIT 50")->fetchAll(); $s=db()->prepare("SELECT t.id,MAX(m.created_at) last_message,(SELECT body FROM messages m2 WHERE m2.thread_id=t.id ORDER BY m2.id DESC LIMIT 1) last_body,(SELECT u.display_name FROM thread_members tm2 JOIN users u ON u.id=tm2.user_id WHERE tm2.thread_id=t.id AND tm2.user_id<>? LIMIT 1) other_name FROM threads t JOIN thread_members tm ON tm.thread_id=t.id LEFT JOIN messages m ON m.thread_id=t.id WHERE tm.user_id=? GROUP BY t.id ORDER BY last_message DESC");$s->execute([$uid,$uid]);$threads=$s->fetchAll(); $selectedThread=(int)($_GET['thread']??($threads[0]['id']??0)); if($selectedThread){$s=db()->prepare('SELECT m.*,u.display_name FROM messages m JOIN users u ON u.id=m.sender_id WHERE m.thread_id=? ORDER BY m.id');$s->execute([$selectedThread]);$threadMessages=$s->fetchAll();} $gid=(int)($_GET['group']??0);if($gid){$s=db()->prepare('SELECT g.*,u.display_name owner_name,(SELECT COUNT(*) FROM group_members gm WHERE gm.group_id=g.id) member_count FROM groups g JOIN users u ON u.id=g.owner_id WHERE g.id=?');$s->execute([$gid]);$selectedGroup=$s->fetch()?:null;if($selectedGroup){$s=db()->prepare('SELECT gp.*,u.display_name FROM group_posts gp JOIN users u ON u.id=gp.user_id WHERE gp.group_id=? ORDER BY gp.id DESC');$s->execute([$gid]);$groupPosts=$s->fetchAll();}} $s=db()->prepare('SELECT * FROM events WHERE user_id=? ORDER BY starts_at ASC');$s->execute([$uid]);$events=$s->fetchAll(); $s=db()->prepare('SELECT * FROM albums WHERE user_id=? ORDER BY id DESC');$s->execute([$uid]);$albums=$s->fetchAll(); $s=db()->prepare('SELECT r.*,m.mime FROM reels r JOIN media m ON m.id=r.media_id WHERE r.user_id=? ORDER BY r.id DESC');$s->execute([$uid]);$reels=$s->fetchAll(); seed_adult_bookmarks($uid);$s=db()->prepare('SELECT * FROM adult_links WHERE user_id=? ORDER BY id DESC');$s->execute([$uid]);$adultLinks=$s->fetchAll(); $s=db()->prepare('SELECT * FROM notifications WHERE user_id=? ORDER BY id DESC LIMIT 100');$s->execute([$uid]);$alerts=$s->fetchAll(); $s=db()->prepare('SELECT * FROM applications WHERE user_id=? ORDER BY id DESC');$s->execute([$uid]);$applications=$s->fetchAll(); $s=db()->prepare('SELECT * FROM developer_logs WHERE user_id=? ORDER BY id DESC LIMIT 100');$s->execute([$uid]);$devLogs=$s->fetchAll(); if(!empty($me['avatar_media_id']))$avatarUrl=media_url((int)$me['avatar_media_id']); if(!empty($me['cover_media_id']))$coverUrl=media_url((int)$me['cover_media_id']); } ?> <!doctype html> <html lang="en" data-theme="<?=e($me['theme']??'auto')?>"> <head> <meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><meta name="theme-color" content="#090914"> <title><?=e(GL_APP)?> Spatial</title> <link rel="preconnect" href="https://unpkg.com"><link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"> <style> :root{color-scheme:dark;--bg:#050711;--panel:rgba(14,18,32,.72);--panel2:rgba(24,29,49,.62);--line:rgba(255,255,255,.13);--text:#f7f9ff;--muted:#9ca9c1;--a1:#6f5cff;--a2:#2fd8ff;--a3:#ff4fa3;--a4:#ffd85a;--good:#56e58a;--bad:#ff647d;--nav:240px;--top:72px;--safe:env(safe-area-inset-bottom);--radius:24px} *{box-sizing:border-box}html,body{margin:0;width:100%;height:100%;overflow:hidden;background:var(--bg);color:var(--text);font-family:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}button,input,textarea,select{font:inherit}a{color:inherit;text-decoration:none}button{cursor:pointer}.muted{color:var(--muted)} .bg{position:fixed;inset:0;z-index:-5;background:radial-gradient(circle at 15% 12%,color-mix(in srgb,var(--a2) 18%,transparent),transparent 30%),radial-gradient(circle at 82% 18%,color-mix(in srgb,var(--a1) 22%,transparent),transparent 34%),radial-gradient(circle at 50% 90%,color-mix(in srgb,var(--a3) 16%,transparent),transparent 40%),linear-gradient(150deg,#03040a,#080b18 55%,#060612);overflow:hidden}.bg:before{content:"";position:absolute;inset:-30%;background:conic-gradient(from 20deg,transparent,color-mix(in srgb,var(--a1) 10%,transparent),transparent,color-mix(in srgb,var(--a3) 10%,transparent),transparent);animation:spin 35s linear infinite}.bg:after{content:"";position:absolute;inset:0;background-image:radial-gradient(2px 2px at 10% 20%,#fff,transparent 70%),radial-gradient(1.5px 1.5px at 70% 25%,var(--a2),transparent 70%),radial-gradient(2px 2px at 85% 70%,var(--a4),transparent 70%);background-size:240px 240px,320px 320px,420px 420px;opacity:.35;animation:drift 28s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}@keyframes drift{to{transform:translateY(60px)}} .app{display:grid;grid-template-columns:var(--nav) minmax(0,1fr);grid-template-rows:var(--top) minmax(0,1fr);height:100%}.side{grid-row:1/3;padding:15px 12px;display:flex;flex-direction:column;gap:12px;background:rgba(5,8,16,.9);backdrop-filter:blur(22px);border-right:1px solid var(--line);overflow:auto}.brandbox{display:flex;align-items:center;gap:11px;padding:5px 5px 16px;border-bottom:1px solid var(--line)}.mark{width:50px;height:50px;border-radius:17px;display:grid;place-items:center;background:linear-gradient(145deg,var(--a4),var(--a3),var(--a2));color:#08080c;font-weight:1000;box-shadow:0 0 32px color-mix(in srgb,var(--a2) 25%,transparent)}.brandname{font-size:20px;font-weight:1000}.nav{display:grid;gap:5px}.nav a{display:grid;grid-template-columns:40px 1fr;gap:9px;align-items:center;padding:9px 10px;border-radius:15px;color:#a9b3c5;border:1px solid transparent}.nav a:hover,.nav a.active{color:#fff;background:linear-gradient(90deg,color-mix(in srgb,var(--a1) 20%,transparent),color-mix(in srgb,var(--a2) 8%,transparent));border-color:color-mix(in srgb,var(--a1) 35%,transparent);box-shadow:inset 3px 0 0 var(--a4)}.ni{width:36px;height:36px;border-radius:12px;display:grid;place-items:center;background:rgba(255,255,255,.06);color:var(--a4);font-weight:900}.sidefoot{margin-top:auto;padding:12px;border-top:1px solid var(--line);font-size:12px;color:var(--muted)} .top{grid-column:2;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:0 20px;background:rgba(6,9,17,.68);backdrop-filter:blur(22px);border-bottom:1px solid var(--line)}.wordmark{font-size:28px;font-weight:1000;background:linear-gradient(90deg,var(--a4),var(--a3),var(--a1),var(--a2));-webkit-background-clip:text;color:transparent;background-size:220% auto;animation:flow 8s linear infinite}@keyframes flow{to{background-position:220% 0}}.topactions{display:flex;align-items:center;gap:8px}.chip,.btn{border:1px solid var(--line);background:rgba(18,24,41,.72);color:#fff;border-radius:14px;padding:10px 13px;font-weight:800}.btn.primary{background:linear-gradient(135deg,var(--a4),color-mix(in srgb,var(--a4) 70%,var(--a3)));color:#121216;border:0}.btn.accent{background:linear-gradient(135deg,var(--a1),var(--a2));border:0}.workspace{grid-column:2;min-width:0;min-height:0;overflow:auto;padding:clamp(14px,2vw,28px)}.glass{background:linear-gradient(180deg,rgba(22,28,47,.74),rgba(9,13,24,.64));border:1px solid var(--line);border-radius:var(--radius);backdrop-filter:blur(22px) saturate(135%);box-shadow:0 26px 80px rgba(0,0,0,.34)}.section{padding:20px}.hero{min-height:290px;padding:clamp(26px,4vw,54px);position:relative;overflow:hidden;background:linear-gradient(145deg,color-mix(in srgb,var(--a1) 25%,rgba(7,10,18,.92)),color-mix(in srgb,var(--a3) 18%,rgba(7,10,18,.9)))}.hero:after{content:"∞";position:absolute;right:3%;bottom:-16%;font-size:min(30vw,420px);font-weight:1000;color:rgba(255,255,255,.035)}.hero h1{font-size:clamp(44px,7vw,96px);line-height:.9;letter-spacing:-.065em;margin:10px 0 16px}.hero p{max-width:760px;color:#c7d0df;font-size:18px}.kicker{font-size:11px;font-weight:900;letter-spacing:.16em;color:var(--a2)}.grid{display:grid;gap:16px}.g4{grid-template-columns:repeat(4,minmax(0,1fr))}.g3{grid-template-columns:repeat(3,minmax(0,1fr))}.g2{grid-template-columns:repeat(2,minmax(0,1fr))}.sectionhead{display:flex;align-items:end;justify-content:space-between;gap:16px;margin:24px 0 13px}.sectionhead h2{margin:0;font-size:clamp(25px,3vw,40px)}.metric{font-size:42px;font-weight:1000}.card{padding:18px;min-width:0}.field{display:grid;gap:7px;margin:12px 0}.field label{font-size:13px;font-weight:800}.field input,.field textarea,.field select{width:100%;border:1px solid var(--line);background:rgba(5,8,15,.72);color:#fff;border-radius:14px;padding:12px}.field textarea{min-height:100px;resize:vertical}.formgrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.profilehero{position:relative;min-height:390px;overflow:hidden}.profilecover{position:absolute;inset:0;background:radial-gradient(circle at 70% 30%,color-mix(in srgb,var(--a2) 36%,transparent),transparent 30%),linear-gradient(145deg,#18172a,#08101b)}.profilecover img{width:100%;height:100%;object-fit:cover;filter:saturate(1.2) contrast(1.04);opacity:.72}.profilecover:after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 20%,rgba(5,7,13,.92) 92%)}.profileblend{position:absolute;left:clamp(22px,4vw,52px);bottom:28px;display:flex;align-items:end;gap:20px}.portrait{width:clamp(150px,18vw,240px);aspect-ratio:4/5;border-radius:42% 42% 26px 26px;overflow:hidden;background:linear-gradient(145deg,var(--a3),var(--a1),var(--a2));box-shadow:0 0 0 4px rgba(255,255,255,.3),0 0 60px color-mix(in srgb,var(--a2) 36%,transparent);mask-image:linear-gradient(to bottom,#000 76%,transparent 100%)}.portrait img{width:100%;height:100%;object-fit:cover}.profilecopy h1{font-size:clamp(36px,5vw,68px);margin:0}.tabs{display:flex;gap:8px;overflow:auto;padding-bottom:4px}.tabs a,.tabs button{white-space:nowrap;border:1px solid var(--line);background:rgba(255,255,255,.05);color:#dbe2ef;padding:9px 12px;border-radius:999px}.tabs .active{background:linear-gradient(135deg,var(--a1),var(--a2));border:0}.profilelayout{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(300px,.6fr);gap:16px}.profileart{min-height:320px;display:grid;place-items:center;position:relative;overflow:hidden}.profileart:before{content:"";position:absolute;width:85%;height:55%;border:4px solid var(--a4);border-radius:50%;transform:rotate(12deg);box-shadow:0 0 35px var(--a4),0 0 70px var(--a2);filter:blur(.3px)}.profileart:after{content:"∞";font-size:160px;color:transparent;-webkit-text-stroke:3px var(--a2);filter:drop-shadow(0 0 20px var(--a2))}.interview{max-width:760px;margin:auto;padding:26px}.question{font-size:clamp(28px,4vw,48px);line-height:1.05;margin:10px 0 24px}.answers{display:grid;gap:10px}.answer{padding:14px;border-radius:16px;border:1px solid var(--line);background:rgba(255,255,255,.05);text-align:left}.answer.selected{background:linear-gradient(135deg,color-mix(in srgb,var(--a1) 40%,transparent),color-mix(in srgb,var(--a2) 22%,transparent));border-color:var(--a2)}.progressbar{height:8px;border-radius:999px;background:rgba(255,255,255,.08);overflow:hidden}.progressbar i{display:block;height:100%;background:linear-gradient(90deg,var(--a1),var(--a2),var(--a3));width:0}.profilegrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px}.person{min-height:320px;position:relative;overflow:hidden;padding:0}.personart{height:100%;background:linear-gradient(145deg,var(--a1),var(--a2));position:absolute;inset:0}.personart img{width:100%;height:100%;object-fit:cover}.personart:after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 35%,rgba(3,5,10,.95) 92%)}.personinfo{position:absolute;left:16px;right:16px;bottom:15px}.groupgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px}.groupcard{overflow:hidden;padding:0}.groupart{height:180px;position:relative;background:linear-gradient(135deg,var(--a1),var(--a3),var(--a2));overflow:hidden}.groupart img{width:100%;height:100%;object-fit:cover}.groupart.cosmic:after{content:"";position:absolute;inset:0;background:radial-gradient(circle at 30% 30%,rgba(255,255,255,.25),transparent 20%),conic-gradient(from 120deg,transparent,rgba(255,255,255,.18),transparent);mix-blend-mode:screen;animation:spin 14s linear infinite}.groupbody{padding:16px}.chatlayout{display:grid;grid-template-columns:320px minmax(0,1fr);gap:14px;min-height:620px}.threadlist{padding:10px;overflow:auto}.thread{display:block;padding:12px;border-radius:15px;border:1px solid var(--line);background:rgba(255,255,255,.04);margin-bottom:8px}.thread.active{border-color:var(--a2);background:color-mix(in srgb,var(--a1) 18%,transparent)}.chat{display:flex;flex-direction:column;overflow:hidden}.messages{flex:1;overflow:auto;padding:18px;display:flex;flex-direction:column;gap:10px}.bubble{max-width:76%;padding:11px 13px;border-radius:17px;background:rgba(255,255,255,.09)}.bubble.mine{align-self:flex-end;background:linear-gradient(135deg,var(--a1),var(--a2));color:#fff}.composer{display:flex;gap:8px;padding:12px;border-top:1px solid var(--line)}.composer textarea{flex:1;min-height:52px;max-height:120px;border:1px solid var(--line);background:rgba(5,8,15,.75);color:#fff;border-radius:14px;padding:12px}.mapwrap{height:620px;position:relative;overflow:hidden}.map{height:100%;background:#07111a}.mapcontrols{position:absolute;z-index:600;left:14px;top:14px;right:14px;display:flex;justify-content:space-between;gap:10px;pointer-events:none}.mapcontrols>*{pointer-events:auto}.mapbottom{position:absolute;z-index:600;left:14px;right:14px;bottom:14px;display:flex;gap:10px;overflow:auto;padding:10px;background:rgba(6,10,18,.72);backdrop-filter:blur(18px);border:1px solid var(--line);border-radius:18px}.mapmember{flex:0 0 190px;padding:10px;border-radius:15px;background:rgba(255,255,255,.07)}.screensaver{position:fixed;inset:0;z-index:5000;display:none;place-items:center;background:radial-gradient(circle at 50% 45%,color-mix(in srgb,var(--a1) 30%,#02030a),#02030a 70%);overflow:hidden}.screensaver.active{display:grid}.ssorb{width:min(58vw,580px);aspect-ratio:1;border-radius:50%;display:grid;place-items:center;background:radial-gradient(circle at 32% 25%,#fff,var(--a2) 7%,var(--a1) 32%,var(--a3) 57%,#03040a 75%);box-shadow:0 0 80px var(--a2),0 0 160px color-mix(in srgb,var(--a3) 50%,transparent);animation:ssfloat 5s ease-in-out infinite}.ssorb span{font-size:clamp(80px,15vw,180px);font-weight:1000}.sstime{position:absolute;bottom:8%;text-align:center}.sstime strong{font-size:clamp(40px,8vw,100px);display:block}.sshint{position:absolute;top:4%;font-size:12px;letter-spacing:.16em;color:#b7c2d5}@keyframes ssfloat{50%{transform:translateY(-12px) rotateY(10deg);filter:hue-rotate(130deg)}}.flash{padding:12px 14px;border-radius:14px;margin-bottom:12px;background:rgba(77,212,120,.14);border:1px solid rgba(77,212,120,.34)}.flash.error{background:rgba(255,80,100,.14);border-color:rgba(255,80,100,.34)} @media(max-width:1100px){.g4{grid-template-columns:repeat(2,minmax(0,1fr))}.g3{grid-template-columns:repeat(2,minmax(0,1fr))}.profilelayout{grid-template-columns:1fr}.formgrid{grid-template-columns:repeat(2,minmax(0,1fr))}} @media(max-width:900px){:root{--nav:0px;--top:60px}.app{grid-template-columns:1fr;grid-template-rows:var(--top) minmax(0,1fr) 78px}.top{grid-column:1}.workspace{grid-column:1;padding:10px 10px 18px}.side{grid-column:1;grid-row:3;flex-direction:row;padding:7px;overflow-x:auto;overflow-y:hidden;border-right:0;border-top:1px solid var(--line)}.brandbox,.sidefoot{display:none}.nav{display:flex}.nav a{flex:0 0 72px;display:grid;grid-template-columns:1fr;grid-template-rows:36px auto;place-items:center;gap:2px;padding:5px;font-size:9px}.ni{width:34px;height:34px}.nav a.active{box-shadow:inset 0 3px 0 var(--a4)}.topactions .chip{display:none}.hero{min-height:340px}.chatlayout{grid-template-columns:1fr}.threadlist{max-height:220px}.profilehero{min-height:500px}.profileblend{left:18px;right:18px;bottom:22px;display:grid;grid-template-columns:130px 1fr}.portrait{width:130px}.mapwrap{height:62dvh;min-height:470px}} @media(max-width:620px){.g4,.g3,.g2,.formgrid{grid-template-columns:1fr}.wordmark{font-size:23px}.top{padding:0 10px}.topactions .btn{padding:8px 10px;font-size:12px}.hero h1{font-size:48px}.section{padding:14px}.profilegrid{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.person{min-height:265px}.groupgrid{grid-template-columns:1fr}.profileblend{grid-template-columns:110px 1fr;gap:12px}.portrait{width:110px}.profilecopy h1{font-size:34px}.mapwrap{height:58dvh;min-height:420px}} .media-preview{width:100%;aspect-ratio:16/10;object-fit:cover;border-radius:18px;background:#050711}.eventrow{display:grid;grid-template-columns:120px minmax(0,1fr) auto;gap:16px;align-items:center}.eventdate{font-size:20px;font-weight:1000}.statusdot{display:inline-block;width:9px;height:9px;border-radius:50%;background:var(--good);margin-right:7px}.codebox{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;word-break:break-all;background:#050711;border:1px solid var(--line);padding:12px;border-radius:12px}.logline{border-left:3px solid var(--a2);padding:10px 12px;margin:8px 0;background:rgba(255,255,255,.04);border-radius:0 12px 12px 0}@media(max-width:620px){.eventrow{grid-template-columns:1fr}.eventrow .btn{width:100%}} .adultgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:15px}.adultcard{overflow:hidden;padding:0}.adultthumb{display:block;position:relative;aspect-ratio:16/10;background:linear-gradient(135deg,var(--a1),var(--a3));overflow:hidden}.adultthumb>img.preview{width:100%;height:100%;object-fit:cover;display:block}.adultthumb:after{content:"18+";position:absolute;right:10px;top:10px;padding:7px 9px;border-radius:10px;background:rgba(5,7,13,.82);border:1px solid rgba(255,255,255,.24);font-weight:1000;font-size:12px}.adultmeta{padding:14px}.adultmeta h3{font-size:17px;line-height:1.25;margin:0 0 9px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.adultsite{display:flex;align-items:center;gap:8px;min-width:0}.adultsite img{width:24px;height:24px;border-radius:7px;background:#fff}.adultsite span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.adult-actions{display:flex;gap:8px;margin-top:12px}.adult-actions .btn{flex:1} @media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important}} /* 2026-07 animated brand + iPhone readability pass */ :root{ --tap:48px; --mobile-font:16px; } /* Animated GayLord identity */ .wordmark,.brandname{position:relative;isolation:isolate;display:inline-flex;align-items:center;letter-spacing:-.055em;transform-style:preserve-3d} .wordmark span,.brandname span{display:inline-block;background:linear-gradient(180deg,#fff 0 14%,var(--a4) 28%,var(--a3) 48%,var(--a1) 68%,var(--a2) 88%,#fff 100%);background-size:100% 240%;-webkit-background-clip:text;background-clip:text;color:transparent;filter:drop-shadow(0 0 10px color-mix(in srgb,var(--a2) 32%,transparent));animation:glBrandWave 3.8s ease-in-out infinite,glBrandColor 8s linear infinite;transform-origin:50% 85%} .wordmark span:nth-child(2),.brandname span:nth-child(2){animation-delay:-.22s}.wordmark span:nth-child(3),.brandname span:nth-child(3){animation-delay:-.44s}.wordmark span:nth-child(4),.brandname span:nth-child(4){animation-delay:-.66s}.wordmark span:nth-child(5),.brandname span:nth-child(5){animation-delay:-.88s}.wordmark span:nth-child(6),.brandname span:nth-child(6){animation-delay:-1.1s}.wordmark span:nth-child(7),.brandname span:nth-child(7){animation-delay:-1.32s} .wordmark:after{content:"";position:absolute;left:-4%;right:-4%;bottom:-7px;height:3px;border-radius:999px;background:linear-gradient(90deg,transparent,var(--a4),var(--a3),var(--a1),var(--a2),transparent);background-size:220% 100%;box-shadow:0 0 18px color-mix(in srgb,var(--a2) 48%,transparent);animation:glBrandLine 4.6s linear infinite} @keyframes glBrandWave{0%,100%{transform:translate3d(0,0,0) rotateX(0) scale(1)}45%{transform:translate3d(0,-3px,18px) rotateX(10deg) scale(1.035)}60%{transform:translate3d(0,1px,0) rotateX(-4deg) scale(.995)}} @keyframes glBrandColor{to{background-position:0 240%}} @keyframes glBrandLine{to{background-position:220% 0}} .brandbox{position:relative;overflow:hidden;border-radius:20px;background:linear-gradient(145deg,rgba(255,255,255,.045),rgba(255,255,255,.008));box-shadow:inset 0 0 0 1px rgba(255,255,255,.04)} .brandbox:after{content:"";position:absolute;inset:-60% -35%;pointer-events:none;background:linear-gradient(110deg,transparent 38%,rgba(255,255,255,.22) 50%,transparent 62%);transform:translateX(-75%) rotate(8deg);animation:glBrandSweep 5.2s ease-in-out infinite} @keyframes glBrandSweep{0%,45%{transform:translateX(-75%) rotate(8deg)}75%,100%{transform:translateX(78%) rotate(8deg)}} .mark{position:relative;isolation:isolate;overflow:visible;animation:glMarkFloat 3.6s ease-in-out infinite,glMarkHue 13s linear infinite} .mark:before,.mark:after{content:"";position:absolute;inset:-7px;border-radius:23px;border:1px solid color-mix(in srgb,var(--a2) 55%,transparent);box-shadow:0 0 18px color-mix(in srgb,var(--a2) 35%,transparent);animation:glMarkOrbit 4.4s linear infinite;pointer-events:none} .mark:after{inset:-12px;border-color:color-mix(in srgb,var(--a4) 48%,transparent);animation-direction:reverse;animation-duration:6.2s} @keyframes glMarkFloat{50%{transform:translateY(-3px) rotateZ(2deg) scale(1.04)}} @keyframes glMarkHue{to{filter:hue-rotate(360deg)}} @keyframes glMarkOrbit{to{transform:rotate(360deg)}} /* More motion, without compromising layout */ .glass{position:relative;overflow:hidden;transition:transform .28s ease,border-color .28s ease,box-shadow .28s ease} .glass:before{content:"";position:absolute;inset:0;pointer-events:none;background:linear-gradient(120deg,rgba(255,255,255,.07),transparent 26%,transparent 72%,color-mix(in srgb,var(--a2) 10%,transparent));mix-blend-mode:screen;opacity:.6} @media(hover:hover){.glass:hover{transform:translateY(-3px);border-color:color-mix(in srgb,var(--a2) 30%,var(--line));box-shadow:0 32px 90px rgba(0,0,0,.42),0 0 36px color-mix(in srgb,var(--a1) 12%,transparent)}} .hero{background-size:180% 180%;animation:glHeroShift 16s ease-in-out infinite alternate} .hero:after{animation:glInfinityFloat 8s ease-in-out infinite} @keyframes glHeroShift{to{background-position:100% 100%}} @keyframes glInfinityFloat{50%{transform:translateY(-14px) rotate(-5deg);filter:drop-shadow(0 0 24px color-mix(in srgb,var(--a2) 30%,transparent))}} .profileart:before{animation:glCompatOrbit 8s linear infinite;transform-origin:center} .profileart:after{animation:glInfinityPulse 3.4s ease-in-out infinite} @keyframes glCompatOrbit{to{transform:rotate(372deg)}} @keyframes glInfinityPulse{50%{transform:scale(1.08);filter:drop-shadow(0 0 34px var(--a2)) drop-shadow(0 0 20px var(--a4))}} /* Accessible touch targets everywhere */ .btn,.chip,.tabs a,.tabs button,.answer{min-height:var(--tap);display:inline-flex;align-items:center;justify-content:center;line-height:1.2} .field input,.field select{min-height:52px}.field textarea{font-size:16px;line-height:1.45}.field input,.field select{font-size:16px} .nav a{min-height:48px}.ni{flex:0 0 auto} /* iPhone / narrow mobile: larger type, buttons and single-column cards */ @media(max-width:900px){ :root{--top:70px;--tap:50px} .app{grid-template-rows:var(--top) minmax(0,1fr) calc(90px + var(--safe))} .top{padding:0 12px;padding-top:env(safe-area-inset-top);min-height:var(--top)} .workspace{padding:14px 12px 24px;font-size:var(--mobile-font);line-height:1.45} .side{height:calc(90px + var(--safe));padding:8px 8px calc(8px + var(--safe));gap:6px} .nav a{flex-basis:82px;grid-template-rows:42px auto;min-height:72px;font-size:11px;font-weight:800;line-height:1.05;padding:6px 4px} .ni{width:42px;height:42px;border-radius:14px;font-size:15px} .topactions{gap:7px} .topactions .btn{min-width:50px;padding:11px 14px;font-size:14px} .wordmark{font-size:28px} .sectionhead{align-items:flex-start;gap:12px}.sectionhead h2{font-size:clamp(30px,8vw,40px)} .muted{font-size:15px;line-height:1.45;color:#b9c4d8} .kicker{font-size:12px;letter-spacing:.14em} .btn{padding:13px 16px;font-size:15px;border-radius:15px} .chip{padding:12px 14px;font-size:14px} .field{gap:9px;margin:15px 0}.field label{font-size:15px;line-height:1.25}.field input,.field select,.field textarea{padding:14px 15px;border-radius:16px} .tabs{gap:10px;padding-bottom:8px}.tabs a,.tabs button{padding:12px 16px;font-size:15px} .hero p{font-size:17px;line-height:1.5} .profilehero{min-height:540px} .profileblend{align-items:end} .profilecopy p{font-size:15px;line-height:1.45} .chatlayout{min-height:calc(100dvh - 190px)} .composer{padding:12px;gap:10px}.composer textarea{font-size:16px;min-height:56px} .mapcontrols{left:10px;right:10px;top:10px}.mapbottom{left:10px;right:10px;bottom:10px} } @media(max-width:620px){ :root{--radius:22px} .top{padding-inline:10px}.wordmark{font-size:26px}.topactions .btn{font-size:13px;padding:10px 12px} .workspace{padding:12px 10px 22px} .section{padding:17px}.card{padding:17px} .hero{padding:24px 20px;min-height:390px}.hero h1{font-size:clamp(44px,14vw,62px);line-height:.94}.hero p{font-size:16px} .profilegrid{grid-template-columns:1fr;gap:14px}.person{min-height:430px}.personinfo{left:18px;right:18px;bottom:18px}.personinfo h3{font-size:26px;margin-bottom:8px} .groupgrid{grid-template-columns:1fr}.groupart{height:250px}.groupbody h3{font-size:24px}.groupbody{padding:18px} .profileblend{grid-template-columns:120px minmax(0,1fr);left:16px;right:16px;bottom:18px}.portrait{width:120px}.profilecopy h1{font-size:38px}.profilecopy .chip{margin-top:8px} .question{font-size:34px}.answer{font-size:16px;padding:15px 16px;justify-content:flex-start} .thread{padding:14px}.bubble{max-width:88%;font-size:16px;line-height:1.45} .mapmember{flex-basis:220px;padding:12px} } @media(max-width:390px){ .wordmark{font-size:24px}.topactions .btn{padding:9px 10px;min-width:46px} .nav a{flex-basis:76px;font-size:10px} .profileblend{grid-template-columns:96px minmax(0,1fr)}.portrait{width:96px}.profilecopy h1{font-size:32px} } @supports(-webkit-touch-callout:none){ .workspace,.side{-webkit-overflow-scrolling:touch} input,select,textarea{font-size:16px!important} } </style> </head> <body> <div class="bg"></div> <?php if(!$me): ?> <div style="height:100%;display:grid;place-items:center;padding:20px;overflow:auto"> <div class="glass" style="width:min(1040px,100%);display:grid;grid-template-columns:1.1fr .9fr;overflow:hidden"> <section class="hero" style="border-radius:0"><div class="kicker">GAYLORD SPATIAL · 18+</div><h1>Enter your universe.</h1><p>A fresh social experience with artistic profiles, meaningful questions, groups, messaging, spatial discovery, and a built-in cosmic screensaver.</p><div class="ssorb" style="width:230px;margin-top:24px"><span>GL</span></div></section> <section class="section"> <?php foreach($flashes as $f): ?><div class="flash <?=e($f['type'])?>"><?=e($f['message'])?></div><?php endforeach; ?> <div class="tabs"><button class="active" data-auth="login">Sign in</button><button data-auth="register">Create account</button></div> <form method="post" data-auth-panel="login"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="login"><div class="field"><label>Email or username</label><input name="identity" required></div><div class="field"><label>Password</label><input name="password" type="password" required></div><button class="btn primary" style="width:100%">Enter GayLord</button></form> <form method="post" data-auth-panel="register" hidden><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="register"><div class="field"><label>Display name</label><input name="display_name" required></div><div class="field"><label>Username</label><input name="username" required></div><div class="field"><label>Email</label><input name="email" type="email" required></div><div class="field"><label>Birthdate</label><input name="birthdate" type="date" required></div><div class="field"><label>Password</label><input name="password" type="password" minlength="10" required></div><button class="btn primary" style="width:100%">Create account</button></form> </section> </div> </div> <?php else: ?> <div class="app"> <aside class="side"><div class="brandbox"><div class="mark">GL</div><div><div class="brandname" aria-label="GayLord"><span>G</span><span>a</span><span>y</span><span>L</span><span>o</span><span>r</span><span>d</span></div><small class="muted">SPATIAL NETWORK</small></div></div> <nav class="nav"> <?php $nav=[['home','⌂','Home'],['discover','◇','Discover'],['messages','✉','Messages'],['groups','◎','Groups'],['events','□','Events'],['marketplace','M','Marketplace'],['albums','▣','Albums'],['reels','18+','Reels'],['spatial','◉','Spatial'],['profile','P','Profile'],['progress','⚡','Progress'],['notifications','●','Alerts'],['settings','⚙','Settings'],['safety','!','Safety'],['developer','</>','Developer']];foreach($nav as $n):?><a href="?view=<?=$n[0]?>" class="<?=$view===$n[0]?'active':''?>"><span class="ni"><?=$n[1]?></span><span><?=$n[2]?></span></a><?php endforeach; ?> </nav><div class="sidefoot">● Network online<br><?=e($me['display_name'])?></div></aside> <header class="top"><div class="wordmark" aria-label="GayLord"><span>G</span><span>a</span><span>y</span><span>L</span><span>o</span><span>r</span><span>d</span></div><div class="topactions"><div class="chip" id="clock">LIVE</div><button class="btn" id="themeBtn" type="button" aria-label="Change color theme">Color</button><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="logout"><button class="btn">Sign out</button></form></div></header> <main class="workspace"> <?php foreach($flashes as $f): ?><div class="flash <?=e($f['type'])?>"><?=e($f['message'])?></div><?php endforeach; ?> <?php if($view==='home'): ?> <section class="glass hero"><div class="kicker">GAYLORD SPATIAL NETWORK</div><h1>Where connection becomes art.</h1><p>Discover people, build expressive groups, explore the spatial field, and let the guided profile engine reveal who you are—without external AI.</p><div style="display:flex;gap:10px;flex-wrap:wrap"><a class="btn primary" href="?view=profile">Build profile</a><a class="btn accent" href="?view=discover">Explore members</a><a class="btn" href="?view=groups">Find groups</a></div></section> <div class="sectionhead"><div><h2>Your universe</h2><div class="muted">Sectional glass modules that adapt to phone and desktop.</div></div></div> <div class="grid g4"><article class="glass card"><div class="kicker">PROFILE DEPTH</div><div class="metric">72%</div><p class="muted">Finish the guided questions.</p></article><article class="glass card"><div class="kicker">DISCOVERY</div><div class="metric"><?=count($users)?></div><p class="muted">Members in your network.</p></article><article class="glass card"><div class="kicker">GROUPS</div><div class="metric"><?=count($groups)?></div><p class="muted">Communities ready to explore.</p></article><article class="glass card"><div class="kicker">STREAK</div><div class="metric">5</div><p class="muted">Days of profile progress.</p></article></div> <div class="sectionhead"><div><h2>Featured members</h2><div class="muted">Art-forward profiles.</div></div><a class="btn" href="?view=discover">View all</a></div> <div class="profilegrid"><?php foreach(array_slice($users,0,6) as $u):?><article class="glass person"><div class="personart"><?php if(!empty($u['avatar_media_id'])):?><img src="<?=e(media_url((int)$u['avatar_media_id']))?>" alt=""><?php endif;?></div><div class="personinfo"><h3><?=e($u['display_name'])?></h3><div class="muted"><?=e($u['city']?:'Somewhere in the Kosmos')?> · <?=e($u['personality']?:'Open to connection')?></div><form method="post" style="margin-top:10px"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="start_thread"><input type="hidden" name="other_id" value="<?=$u['id']?>"><button class="btn primary">Message</button></form></div></article><?php endforeach;?></div> <?php elseif($view==='discover'): ?> <div class="sectionhead"><div><div class="kicker">DISCOVERY</div><h2>Discover</h2><div class="muted">Profiles blended like living artwork.</div></div></div><div class="profilegrid"><?php foreach($users as $u):?><article class="glass person"><div class="personart"><?php if(!empty($u['avatar_media_id'])):?><img src="<?=e(media_url((int)$u['avatar_media_id']))?>" alt=""><?php endif;?></div><div class="personinfo"><h3><?=e($u['display_name'])?></h3><div class="muted"><?=e($u['looking_for']?:'Open to connection')?></div><form method="post" style="margin-top:10px"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="start_thread"><input type="hidden" name="other_id" value="<?=$u['id']?>"><button class="btn primary">Message</button></form></div></article><?php endforeach;?></div> <?php elseif($view==='messages'): ?> <div class="sectionhead"><div><div class="kicker">MESSAGES</div><h2>Inbox</h2></div></div><div class="chatlayout"><aside class="glass threadlist"><?php if(!$threads):?><div class="muted">Start a conversation from Discover.</div><?php endif;foreach($threads as $t):?><a class="thread <?=$selectedThread==(int)$t['id']?'active':''?>" href="?view=messages&thread=<?=$t['id']?>"><strong><?=e($t['other_name']?:'Conversation')?></strong><div class="muted"><?=e($t['last_body']?:'No messages yet')?></div></a><?php endforeach;?></aside><section class="glass chat"><?php if($selectedThread):?><div class="messages"><?php foreach($threadMessages as $m):?><div class="bubble <?=((int)$m['sender_id']===(int)$me['id'])?'mine':''?>"><strong><?=e($m['display_name'])?></strong><div><?=nl2br(e($m['body']))?></div></div><?php endforeach;?></div><form method="post" class="composer"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="send_message"><input type="hidden" name="thread_id" value="<?=$selectedThread?>"><textarea name="body" placeholder="Write a message..."></textarea><button class="btn primary">Send</button></form><?php else:?><div style="display:grid;place-items:center;height:100%" class="muted">Select a conversation.</div><?php endif;?></section></div> <?php elseif($view==='groups'): ?> <div class="sectionhead"><div><div class="kicker">GROUPS</div><h2>Groups with identity</h2><div class="muted">Create artistic group covers, events, posts, and community spaces.</div></div><button class="btn primary" onclick="document.getElementById('createGroup').showModal()">Create group</button></div> <?php if($selectedGroup):?><section class="glass profilehero"><div class="profilecover"><?php if(!empty($selectedGroup['image_media_id'])):?><img src="<?=e(media_url((int)$selectedGroup['image_media_id']))?>" alt=""><?php endif;?></div><div class="profileblend"><div class="portrait" style="aspect-ratio:1;border-radius:30px"><?php if(!empty($selectedGroup['image_media_id'])):?><img src="<?=e(media_url((int)$selectedGroup['image_media_id']))?>" alt=""><?php endif;?></div><div class="profilecopy"><div class="kicker"><?=e($selectedGroup['category'])?></div><h1><?=e($selectedGroup['name'])?></h1><p><?=e($selectedGroup['tagline'])?></p><div class="chip"><?=e((string)$selectedGroup['member_count'])?> members</div></div></div></section><div class="grid g2" style="margin-top:16px"><section class="glass section"><h3>About</h3><p><?=nl2br(e($selectedGroup['description']))?></p><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="join_group"><input type="hidden" name="group_id" value="<?=$selectedGroup['id']?>"><button class="btn primary">Join group</button></form></section><section class="glass section"><h3>Post to group</h3><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="group_post"><input type="hidden" name="group_id" value="<?=$selectedGroup['id']?>"><div class="field"><textarea name="body" placeholder="Share something..."></textarea></div><button class="btn primary">Post</button></form></section></div><div class="sectionhead"><h2>Group activity</h2></div><div class="grid g2"><?php foreach($groupPosts as $p):?><article class="glass card"><strong><?=e($p['display_name'])?></strong><p><?=nl2br(e($p['body']))?></p></article><?php endforeach;?></div><?php else:?><div class="groupgrid"><?php foreach($groups as $g):?><a class="glass groupcard" href="?view=groups&group=<?=$g['id']?>"><div class="groupart <?=e($g['art_style'])?>"><?php if(!empty($g['image_media_id'])):?><img src="<?=e(media_url((int)$g['image_media_id']))?>" alt=""><?php endif;?></div><div class="groupbody"><div class="kicker"><?=e($g['category'])?></div><h3><?=e($g['name'])?></h3><p class="muted"><?=e($g['tagline'])?></p><div class="chip"><?=$g['member_count']?> members</div></div></a><?php endforeach;?></div><?php endif;?> <dialog id="createGroup" class="glass" style="width:min(700px,94vw);color:#fff;background:#0b1020;border:1px solid var(--line);border-radius:24px"><form method="post" enctype="multipart/form-data"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="create_group"><h2>Create a group</h2><div class="formgrid"><div class="field"><label>Name</label><input name="name" required></div><div class="field"><label>Tagline</label><input name="tagline"></div><div class="field"><label>Category</label><select name="category"><option>Community</option><option>Events</option><option>Creative</option><option>Nightlife</option><option>Travel</option><option>Dating</option><option>Support</option><option>Adult</option></select></div><div class="field"><label>Privacy</label><select name="privacy"><option>public</option><option>approval</option><option>invite</option><option>hidden</option></select></div><div class="field"><label>Vibe</label><select name="vibe"><option>Cosmic</option><option>Chill</option><option>Wild</option><option>Artsy</option><option>Flirty</option><option>Deep talk</option></select></div><div class="field"><label>Art style</label><select name="art_style"><option value="cosmic">Cosmic</option><option value="neon">Neon</option><option value="editorial">Editorial</option><option value="dream">Dream blur</option><option value="industrial">Dark industrial</option></select></div></div><div class="field"><label>Description</label><textarea name="description"></textarea></div><div class="field"><label>Group profile art</label><input type="file" name="group_image" accept="image/*"></div><div style="display:flex;gap:8px;justify-content:flex-end"><button type="button" class="btn" onclick="this.closest('dialog').close()">Cancel</button><button class="btn primary">Create</button></div></form></dialog> <?php elseif($view==='spatial'): ?> <div class="sectionhead"><div><div class="kicker">SPATIAL FIELD</div><h2>Nearby now</h2><div class="muted">Uses the template map layout with controls inside the map.</div></div></div><section class="glass mapwrap"><div class="mapcontrols"><div class="chip" id="mapStatus">Demo field</div><button class="btn primary" id="locateBtn">Use my location</button></div><div id="map" class="map"></div><div class="mapbottom"><?php foreach(array_slice($users,0,8) as $u):?><div class="mapmember"><strong><?=e($u['display_name'])?></strong><div class="muted"><?=e($u['city']?:'Nearby')?> · <?=e($u['looking_for']?:'Connect')?></div></div><?php endforeach;?></div></section> <?php elseif($view==='profile'): ?> <section class="glass profilehero"><div class="profilecover"><?php if($coverUrl):?><img src="<?=e($coverUrl)?>" alt=""><?php endif;?></div><div class="profileblend"><div class="portrait"><?php if($avatarUrl):?><img src="<?=e($avatarUrl)?>" alt=""><?php endif;?></div><div class="profilecopy"><div class="kicker">YOUR UNIVERSE</div><h1><?=e($me['display_name'])?></h1><p><?=e($me['about_me']?:'Your story becomes art here.')?></p><div class="tabs"><button class="active" data-profile-tab="edit">Edit profile</button><button data-profile-tab="interview">Guided interview</button><button data-profile-tab="preview">Preview art</button></div></div></div></section> <section data-profile-panel="edit" class="glass section" style="margin-top:16px"><form method="post" enctype="multipart/form-data"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="save_profile"><div class="sectionhead"><div><h2>Deep profile</h2><div class="muted">Dropdown-first, complete, and phone friendly.</div></div><button class="btn primary">Save profile</button></div><div class="formgrid"> <?php $selects=['pronouns'=>['He/Him','She/Her','They/Them','Any pronouns','Ask me'],'orientation'=>['Gay','Bisexual','Queer','Pansexual','Questioning','Other'],'relationship_status'=>['Single','Dating','Partnered','Married','It is complicated'],'relationship_structure'=>['Monogamous','Open','Polyamorous','Exploring','Undecided'],'looking_for'=>['Relationship','Dating','Friends','Casual','Community','Creative collaboration','Travel partner'],'personality'=>['Introvert','Ambivert','Extrovert','Adventurous','Reflective','Playful'],'communication_style'=>['Direct','Gentle','Detailed','Playful','Low-key'],'social_energy'=>['Quiet','Balanced','Highly social','Depends on the day'],'love_language'=>['Quality time','Physical touch','Words of affirmation','Acts of service','Gifts'],'education'=>['High school','Trade school','Some college','Associate','Bachelor','Master','Doctorate','Other'],'body_type'=>['Slim','Average','Athletic','Muscular','Stocky','Large','Other'],'exercise'=>['Never','Sometimes','Weekly','Regularly','Daily'],'smoking'=>['Never','Socially','Regularly','Quitting'],'drinking'=>['Never','Socially','Regularly','Sober'],'pets'=>['None','Dogs','Cats','Both','Other'],'children'=>['No','Yes','Prefer not to say'],'future_children'=>['No','Yes','Maybe','Undecided'],'travel_style'=>['Homebody','Occasional trips','Frequent traveler','Digital nomad'],'nightlife'=>['Not my thing','Sometimes','Weekends','Frequently'],'privacy_level'=>['public','members','matches','friends','private'],'theme'=>['auto','cosmic-blue','neon-violet','solar-gold','electric-pink','aurora-green','midnight']];foreach($selects as $name=>$opts):?><div class="field"><label><?=e(ucwords(str_replace('_',' ',$name)))?></label><select name="<?=$name?>"><option value="">Choose...</option><?php foreach($opts as $o):?><option value="<?=e($o)?>" <?=($me[$name]??'')===$o?'selected':''?>><?=e($o)?></option><?php endforeach;?></select></div><?php endforeach;?></div> <div class="formgrid"><div class="field"><label>Occupation</label><input name="occupation" value="<?=e($me['occupation'])?>"></div><div class="field"><label>Height</label><input name="height" value="<?=e($me['height'])?>"></div><div class="field"><label>City / general area</label><input name="city" value="<?=e($me['city'])?>"></div></div><div class="field"><label>About me</label><textarea name="about_me"><?=e($me['about_me'])?></textarea></div><div class="field"><label>Interests</label><textarea name="interests" placeholder="Art, music, travel, games..."><?=e($me['interests'])?></textarea></div><div class="field"><label>Boundaries and consent expectations</label><textarea name="boundaries"><?=e($me['boundaries'])?></textarea></div><div class="grid g2"><div class="field"><label>Profile portrait</label><input type="file" name="avatar" accept="image/*"></div><div class="field"><label>Cover artwork</label><input type="file" name="cover" accept="image/*"></div></div></form></section> <section data-profile-panel="interview" class="glass interview" style="margin-top:16px" hidden><div class="progressbar"><i id="interviewProgress"></i></div><div class="kicker" style="margin-top:18px">GUIDED PROFILE ENGINE · NO EXTERNAL AI</div><div class="question" id="questionText"></div><div class="answers" id="answerList"></div><div style="display:flex;justify-content:space-between;gap:8px;margin-top:18px"><button class="btn" id="prevQuestion">Back</button><button class="btn primary" id="nextQuestion">Continue</button></div><form method="post" id="interviewForm"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="save_interview"><input type="hidden" name="answers_json" id="answersJson"></form></section> <section data-profile-panel="preview" class="profilelayout" style="margin-top:16px" hidden><article class="glass profileart"></article><article class="glass section"><div class="kicker">COMPATIBILITY SIGNALS</div><h2>Profile balance</h2><p class="muted">Communication 88% · Relationship goals 91% · Lifestyle 76%</p><div class="progressbar"><i style="width:86%"></i></div><h3 style="margin-top:20px">Local summary</h3><p><?=e($me['about_me']?:'Complete the interview to generate a hardwired profile summary.')?></p></article></section> <?php elseif($view==='progress'): ?> <div class="sectionhead"><div><div class="kicker">SIMON MISSION ENGINE</div><h2>Progress and achievements</h2><div class="muted">Hardwired recommendations, no external AI.</div></div></div><div class="grid g3"><article class="glass card"><div class="metric">🔥 5</div><h3>Day streak</h3><p class="muted">Keep exploring your profile.</p></article><article class="glass card"><div class="metric">82%</div><h3>Profile depth</h3><p class="muted">Answer three compatibility questions.</p></article><article class="glass card"><div class="metric">12</div><h3>Achievements</h3><p class="muted">Community Explorer unlocked.</p></article></div><div class="sectionhead"><h2>Daily missions</h2></div><div class="grid g2"><article class="glass card"><h3>Complete 3 profile questions</h3><div class="progressbar"><i style="width:66%"></i></div></article><article class="glass card"><h3>Join a group</h3><div class="progressbar"><i style="width:25%"></i></div></article><article class="glass card"><h3>Review privacy settings</h3><div class="progressbar"><i style="width:100%"></i></div></article><article class="glass card"><h3>Add profile cover art</h3><div class="progressbar"><i style="width:40%"></i></div></article></div> <?php elseif($view==='events'): ?> <div class="sectionhead"><div><div class="kicker">EVENTS</div><h2>Events</h2><div class="muted">Create, schedule, and log events.</div></div><button class="btn primary" onclick="document.getElementById('eventDialog').showModal()">Add event</button></div> <div class="grid"><?php if(!$events):?><section class="glass hero"><h1>No events yet.</h1><p>Add your first event using the button above.</p></section><?php endif;foreach($events as $ev):?><article class="glass card eventrow"><div class="eventdate"><?=e(date('M j, Y',strtotime((string)$ev['starts_at'])))?><div class="muted"><?=e(date('g:i A',strtotime((string)$ev['starts_at'])))?></div></div><div><h3><?=e($ev['title'])?></h3><div class="muted"><?=e($ev['location']?:'Location not set')?> · <?=e($ev['visibility'])?></div><p><?=nl2br(e($ev['description']))?></p></div><span class="chip"><span class="statusdot"></span>Scheduled</span></article><?php endforeach;?></div> <dialog id="eventDialog" class="glass" style="width:min(700px,94vw);color:#fff;background:#0b1020;border:1px solid var(--line);border-radius:24px"><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="create_event"><h2>Add event</h2><div class="field"><label>Title</label><input name="title" required></div><div class="formgrid"><div class="field"><label>Starts</label><input type="datetime-local" name="starts_at" required></div><div class="field"><label>Ends</label><input type="datetime-local" name="ends_at"></div><div class="field"><label>Visibility</label><select name="visibility"><option>members</option><option>public</option><option>private</option></select></div></div><div class="field"><label>Location</label><input name="location"></div><div class="field"><label>Description</label><textarea name="description"></textarea></div><div style="display:flex;justify-content:flex-end;gap:8px"><button type="button" class="btn" onclick="this.closest('dialog').close()">Cancel</button><button class="btn primary">Save event</button></div></form></dialog> <?php elseif($view==='albums'): ?> <div class="sectionhead"><div><div class="kicker">ALBUMS</div><h2>Albums</h2><div class="muted">Create visual collections with cover art.</div></div><button class="btn primary" onclick="document.getElementById('albumDialog').showModal()">Add album</button></div><div class="groupgrid"><?php foreach($albums as $a):?><article class="glass groupcard"><div class="groupart"><?php if($a['cover_media_id']):?><img src="<?=e(media_url((int)$a['cover_media_id']))?>" alt=""><?php endif;?></div><div class="groupbody"><div class="kicker"><?=e($a['visibility'])?></div><h3><?=e($a['title'])?></h3><p class="muted"><?=e($a['description'])?></p></div></article><?php endforeach;?></div> <dialog id="albumDialog" class="glass" style="width:min(650px,94vw);color:#fff;background:#0b1020;border:1px solid var(--line);border-radius:24px"><form method="post" enctype="multipart/form-data"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="create_album"><h2>Create album</h2><div class="field"><label>Title</label><input name="title" required></div><div class="field"><label>Description</label><textarea name="description"></textarea></div><div class="field"><label>Cover image</label><input type="file" name="cover" accept="image/*"></div><div class="field"><label>Visibility</label><select name="visibility"><option>members</option><option>public</option><option>private</option></select></div><button class="btn primary">Create album</button></form></dialog> <?php elseif($view==='reels'): ?> <div class="sectionhead"><div><div class="kicker">18+ LIBRARY</div><h2>18+ thumbnails</h2><div class="muted">Your Rated X Safari bookmarks are imported as visual link cards. Select a thumbnail to open the original page in a new tab.</div></div><div style="display:flex;gap:8px;flex-wrap:wrap"><button class="btn" onclick="document.getElementById('adultLinkDialog').showModal()">Add 18+ link</button><button class="btn primary" onclick="document.getElementById('reelDialog').showModal()">Upload reel</button></div></div> <div class="adultgrid"><?php foreach($adultLinks as $link):?><?php $host=(string)(parse_url((string)$link['url'],PHP_URL_HOST)?:'External site');?><article class="glass adultcard"><a class="adultthumb" href="<?=e($link['url'])?>" target="_blank" rel="noopener noreferrer"><img class="preview" loading="lazy" referrerpolicy="no-referrer" src="<?=e($link['thumbnail_url'])?>" alt="<?=e($link['title'])?> thumbnail" onerror="this.style.display='none'"></a><div class="adultmeta"><h3><?=e($link['title'])?></h3><div class="adultsite muted"><img loading="lazy" src="<?=e(adult_favicon((string)$link['url']))?>" alt=""><span><?=e($host)?></span></div><div class="adult-actions"><a class="btn primary" href="<?=e($link['url'])?>" target="_blank" rel="noopener noreferrer">Open</a></div></div></article><?php endforeach;?></div> <div class="sectionhead"><div><h2>Your uploaded reels</h2><div class="muted">Uploaded video and image media stored inside GayLord.</div></div></div><div class="grid g3"><?php if(!$reels):?><article class="glass card muted">No uploaded reels yet.</article><?php endif;foreach($reels as $r):?><article class="glass card"><?php if(str_starts_with((string)$r['mime'],'video/')):?><video class="media-preview" controls playsinline preload="metadata" src="<?=e(media_url((int)$r['media_id']))?>"></video><?php else:?><img class="media-preview" src="<?=e(media_url((int)$r['media_id']))?>" alt=""><?php endif;?><p><?=e($r['caption'])?></p><div class="muted"><?=e($r['visibility'])?> · <?=e($r['created_at'])?></div></article><?php endforeach;?></div> <dialog id="adultLinkDialog" class="glass" style="width:min(650px,94vw);color:#fff;background:#0b1020;border:1px solid var(--line);border-radius:24px"><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="add_adult_link"><h2>Add an 18+ thumbnail</h2><div class="field"><label>Title</label><input name="title" required></div><div class="field"><label>Page URL</label><input name="url" type="url" required placeholder="https://..."></div><div class="field"><label>Optional picture URL</label><input name="thumbnail_url" type="url" placeholder="Leave blank for an automatic page snapshot"></div><button class="btn primary">Add thumbnail</button></form></dialog> <dialog id="reelDialog" class="glass" style="width:min(650px,94vw);color:#fff;background:#0b1020;border:1px solid var(--line);border-radius:24px"><form method="post" enctype="multipart/form-data"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="upload_reel"><h2>Upload reel</h2><div class="field"><label>Video or image</label><input type="file" name="reel" accept="video/mp4,video/webm,video/quicktime,image/*" required></div><div class="field"><label>Caption</label><textarea name="caption"></textarea></div><div class="field"><label>Visibility</label><select name="visibility"><option>members</option><option>public</option><option>private</option></select></div><button class="btn primary">Upload</button></form></dialog> <?php elseif($view==='notifications'): ?> <div class="sectionhead"><div><div class="kicker">ALERTS</div><h2>Alerts</h2><div class="muted">System, social, event, and developer notifications.</div></div><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="mark_alerts_read"><button class="btn">Mark all read</button></form></div><div class="grid"><?php if(!$alerts):?><section class="glass card muted">No alerts yet.</section><?php endif;foreach($alerts as $a):?><article class="glass card"><div class="kicker"><?=$a['is_read']?'READ':'NEW'?></div><h3><?=e($a['title'])?></h3><p><?=e($a['body'])?></p><div class="muted"><?=e($a['created_at'])?></div></article><?php endforeach;?></div> <?php elseif($view==='settings'): ?> <div class="sectionhead"><div><div class="kicker">SETTINGS</div><h2>Application settings</h2><div class="muted">Control theme and account visibility.</div></div></div><section class="glass section"><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="save_settings"><div class="formgrid"><div class="field"><label>Theme</label><select name="theme"><?php foreach(['auto','cosmic-blue','neon-violet','solar-gold','electric-pink','aurora-green','midnight'] as $o):?><option value="<?=e($o)?>" <?=($me['theme']??'')===$o?'selected':''?>><?=e(ucwords(str_replace('-',' ',$o)))?></option><?php endforeach;?></select></div><div class="field"><label>Profile visibility</label><select name="privacy_level"><?php foreach(['public','members','matches','friends','private'] as $o):?><option value="<?=e($o)?>" <?=($me['privacy_level']??'')===$o?'selected':''?>><?=e(ucfirst($o))?></option><?php endforeach;?></select></div></div><button class="btn primary">Save settings</button></form></section> <?php elseif($view==='developer'): ?> <div class="sectionhead"><div><div class="kicker">DEVELOPER MODE</div><h2>Applications, messages, and event logs</h2><div class="muted">Create an application, issue an API key, send a developer message, and log an event.</div></div></div><div class="grid g3"><article class="glass card"><div class="kicker">PHP</div><div class="metric"><?=e(PHP_VERSION)?></div></article><article class="glass card"><div class="kicker">DATABASE</div><div class="metric"><?=e(db()->getAttribute(PDO::ATTR_DRIVER_NAME))?></div></article><article class="glass card"><div class="kicker">LOGS</div><div class="metric"><?=count($devLogs)?></div></article></div> <div class="grid g2" style="margin-top:16px"><section class="glass section"><h3>Create application</h3><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="create_application"><div class="field"><label>Application name</label><input name="name" required></div><div class="field"><label>Callback URL</label><input name="callback_url" type="url" placeholder="https://example.com/callback"></div><button class="btn primary">Create application</button></form></section><section class="glass section"><h3>Send message + log event</h3><form method="post"><input type="hidden" name="csrf" value="<?=e(csrf())?>"><input type="hidden" name="action" value="developer_message"><div class="formgrid"><div class="field"><label>Level</label><select name="level"><option>info</option><option>warning</option><option>error</option><option>success</option></select></div><div class="field"><label>Event name</label><input name="event_name" placeholder="album.created" required></div></div><div class="field"><label>Message</label><textarea name="message" required></textarea></div><button class="btn accent">Send and log</button></form></section></div> <div class="sectionhead"><h2>Applications</h2></div><div class="grid g2"><?php if(!$applications):?><article class="glass card muted">No applications yet.</article><?php endif;foreach($applications as $app):?><article class="glass card"><div class="kicker"><?=$app['is_enabled']?'ACTIVE':'DISABLED'?></div><h3><?=e($app['name'])?></h3><div class="codebox"><?=e($app['api_key'])?></div><p class="muted"><?=e($app['callback_url']?:'No callback URL')?></p></article><?php endforeach;?></div> <div class="sectionhead"><h2>Event log</h2></div><section class="glass section"><?php if(!$devLogs):?><p class="muted">No developer events logged.</p><?php endif;foreach($devLogs as $log):?><div class="logline"><strong><?=e(strtoupper($log['level']))?> · <?=e($log['event_name'])?></strong><div><?=nl2br(e($log['message']))?></div><small class="muted"><?=e($log['created_at'])?></small></div><?php endforeach;?></section> <?php else: ?> <div class="sectionhead"><div><div class="kicker"><?=e(strtoupper($view))?></div><h2><?=e(ucwords($view))?></h2><div class="muted">This fresh module has its production placeholder and shares the new single-shell layout.</div></div></div><section class="glass hero"><h1><?=e(ucwords($view))?></h1><p>The route, mobile layout, navigation state, theme system, and database foundation are ready for the next functional pass.</p></section> <?php endif;?> </main></div> <div class="screensaver" id="screensaver"><div class="sshint">MOVE · TAP · PRESS A KEY TO RETURN</div><div class="ssorb"><span>GL</span></div><div class="sstime"><strong id="ssClock">00:00</strong><span id="ssDate"></span></div></div> <?php endif;?> <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> <script> (()=>{'use strict'; const themePalettes=[['#6f5cff','#2fd8ff','#ff4fa3','#ffd85a'],['#00c8ff','#5b7cff','#a855f7','#ff4fa3'],['#ff3b6b','#ff8a3d','#ffd84d','#55e6c1'],['#14f1d9','#00a8ff','#7048ff','#ff4fb8'],['#f4c95d','#ff6d7a','#6d5dfc','#55d7ff']];let ti=0;function applyTheme(p){const r=document.documentElement;r.style.setProperty('--a1',p[0]);r.style.setProperty('--a2',p[1]);r.style.setProperty('--a3',p[2]);r.style.setProperty('--a4',p[3]);localStorage.setItem('gl_palette',JSON.stringify(p));}try{const s=JSON.parse(localStorage.getItem('gl_palette')||'null');if(Array.isArray(s))applyTheme(s);}catch(e){} const tb=document.getElementById('themeBtn');if(tb)tb.onclick=()=>{ti=(ti+1)%themePalettes.length;applyTheme(themePalettes[ti]);}; setInterval(()=>{const c=document.getElementById('clock');if(c)c.textContent=new Date().toLocaleTimeString([],{hour:'2-digit',minute:'2-digit'});const s=document.getElementById('ssClock');if(s)s.textContent=new Date().toLocaleTimeString([],{hour:'2-digit',minute:'2-digit'});const d=document.getElementById('ssDate');if(d)d.textContent=new Date().toLocaleDateString([],{weekday:'long',month:'long',day:'numeric'});},1000); const ss=document.getElementById('screensaver');let idle;function resetIdle(){if(ss)ss.classList.remove('active');clearTimeout(idle);idle=setTimeout(()=>ss&&ss.classList.add('active'),120000);}['mousemove','mousedown','keydown','touchstart','scroll'].forEach(ev=>addEventListener(ev,resetIdle,{passive:true}));resetIdle(); document.querySelectorAll('[data-auth]').forEach(b=>b.onclick=()=>{document.querySelectorAll('[data-auth]').forEach(x=>x.classList.toggle('active',x===b));document.querySelectorAll('[data-auth-panel]').forEach(p=>p.hidden=p.dataset.authPanel!==b.dataset.auth);}); document.querySelectorAll('[data-profile-tab]').forEach(b=>b.onclick=()=>{document.querySelectorAll('[data-profile-tab]').forEach(x=>x.classList.toggle('active',x===b));document.querySelectorAll('[data-profile-panel]').forEach(p=>p.hidden=p.dataset.profilePanel!==b.dataset.profileTab);}); const q=[ {k:'goal',q:'What kind of connection are you hoping to build?',o:['Relationship','Dating','Friendship','Casual','Community','Creative collaboration']}, {k:'structure',q:'Which relationship structure feels most honest for you?',o:['Monogamous','Open','Polyamorous','Exploring','Undecided']}, {k:'communication',q:'How do you prefer difficult conversations to happen?',o:['Direct and immediate','Gentle and gradual','Detailed and thoughtful','After time to process']}, {k:'energy',q:'What social rhythm feels most natural?',o:['Quiet and intimate','Balanced','Highly social','Depends on the day']}, {k:'affection',q:'What makes you feel most valued?',o:['Quality time','Physical touch','Words of affirmation','Acts of service','Thoughtful gifts']}, {k:'independence',q:'How much independence do you want in a relationship?',o:['A lot','Balanced','Mostly shared life','It depends']}, {k:'conflict',q:'What usually causes you to pull away?',o:['Feeling ignored','Pressure','Dishonesty','Conflict','Loss of freedom','Emotional distance']}, {k:'privacy',q:'Who should see your deeper answers?',o:['Everyone','Members','Matches only','Friends only','Private']} ];let qi=0,ans={};const qt=document.getElementById('questionText'),al=document.getElementById('answerList'),pg=document.getElementById('interviewProgress');function draw(){if(!qt)return;const item=q[qi];qt.textContent=item.q;al.innerHTML='';item.o.forEach(o=>{const b=document.createElement('button');b.type='button';b.className='answer'+(ans[item.k]===o?' selected':'');b.textContent=o;b.onclick=()=>{ans[item.k]=o;draw();};al.appendChild(b);});pg.style.width=((qi+1)/q.length*100)+'%';}draw();const prev=document.getElementById('prevQuestion'),next=document.getElementById('nextQuestion');if(prev)prev.onclick=()=>{qi=Math.max(0,qi-1);draw();};if(next)next.onclick=()=>{if(qi<q.length-1){qi++;draw();}else{document.getElementById('answersJson').value=JSON.stringify(ans);document.getElementById('interviewForm').submit();}}; if(document.getElementById('map')){const map=L.map('map',{zoomControl:true}).setView([32.7767,-96.7970],10);L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{maxZoom:18}).addTo(map);const pts=[[32.79,-96.8],[32.85,-96.9],[32.72,-96.78],[32.95,-96.75],[32.68,-96.92]];pts.forEach((p,i)=>L.circleMarker(p,{radius:11,color:'#fff',weight:3,fillColor:themePalettes[0][i%4],fillOpacity:.95}).addTo(map));document.getElementById('locateBtn').onclick=()=>navigator.geolocation?navigator.geolocation.getCurrentPosition(pos=>{map.setView([pos.coords.latitude,pos.coords.longitude],13);L.circleMarker([pos.coords.latitude,pos.coords.longitude],{radius:12,color:'#fff',fillColor:'#ffd85a',fillOpacity:1}).addTo(map).bindPopup('You').openPopup();document.getElementById('mapStatus').textContent='Approximate location active';},()=>document.getElementById('mapStatus').textContent='Location unavailable'):null;setTimeout(()=>map.invalidateSize(),300);} })(); </script> </body></html>
Save file
Quick jump
open a path
Open