From c36b6f9bbad6c1da4304824ca7854b2596f73af4 Mon Sep 17 00:00:00 2001 From: PenguineWalkOS Date: Sun, 12 Jul 2026 13:23:43 -0400 Subject: [PATCH 1/9] Add stranger onboarding and client pathways --- .../features/gaugegap/AudiencePathways.jsx | 241 ++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 brainsnn-r3f-app/src/features/gaugegap/AudiencePathways.jsx diff --git a/brainsnn-r3f-app/src/features/gaugegap/AudiencePathways.jsx b/brainsnn-r3f-app/src/features/gaugegap/AudiencePathways.jsx new file mode 100644 index 0000000..039dc2d --- /dev/null +++ b/brainsnn-r3f-app/src/features/gaugegap/AudiencePathways.jsx @@ -0,0 +1,241 @@ +import React from 'react'; +import { + ArrowRight, + Building2, + CheckCircle2, + GraduationCap, + Megaphone, + Microscope, + ShieldCheck, + Sparkles, +} from 'lucide-react'; +import { Button } from '../../components/ui/Button.jsx'; +import { track } from '../../lib/analytics.js'; +import '../../styles/audience-pathways.css'; + +const VISITOR_ROUTES = [ + { + id: 'wonder', + icon: Sparkles, + eyebrow: 'I have two minutes', + title: 'Show me something wild', + text: 'Start with the Butterfly Effect and change one number until the future splits.', + action: 'Open the fastest wow', + lab: 'attractor', + }, + { + id: 'teach', + icon: GraduationCap, + eyebrow: 'I teach or explain', + title: 'Give me a lesson people remember', + text: 'Paint cellular life, contain an outbreak, or let a class compete on the same model.', + action: 'Open a classroom-ready lab', + lab: 'life', + }, + { + id: 'research', + icon: Microscope, + eyebrow: 'I need depth', + title: 'Show me the instrument underneath', + text: 'Move beyond spectacle into parameters, assumptions, limitations and reproducible states.', + action: 'Enter research mode', + route: 'research', + }, + { + id: 'client', + icon: Building2, + eyebrow: 'I have an audience or client', + title: 'Build an interactive experience for us', + text: 'Turn a difficult idea, product story or research concept into something people can play and share.', + action: 'See client pilots', + target: 'clients', + }, +]; + +const CLIENT_PATHWAYS = [ + { + id: 'education', + icon: GraduationCap, + title: 'Schools, museums and training', + text: 'Transform an abstract concept into a guided lab, exhibit or workshop challenge.', + outcomes: ['Branded interactive lesson', 'Facilitator prompts and missions', 'Shareable student run states'], + }, + { + id: 'media', + icon: Megaphone, + title: 'Publishers and creators', + text: 'Turn an article, episode or complex story into a playable explanation that earns a second click.', + outcomes: ['Playable story companion', 'Short-form visual assets', 'Challenge links for distribution'], + }, + { + id: 'brand', + icon: Building2, + title: 'Brands and campaigns', + text: 'Build a memorable product or campaign experience without reducing the idea to another landing page.', + outcomes: ['Campaign microsite concept', 'Custom scoring and missions', 'Launch and analytics plan'], + }, + { + id: 'research', + icon: Microscope, + title: 'Research and innovation teams', + text: 'Create a browser instrument that preserves settings, communicates limits and produces reviewable outputs.', + outcomes: ['Reproducible experiment state', 'Model and assumption layer', 'Evidence and export workflow'], + }, +]; + +const TRUST_LEVELS = [ + { + label: 'Play', + title: 'Explore the behavior', + text: 'A fast visual model designed to build intuition and curiosity.', + }, + { + label: 'Teach', + title: 'Explain the mechanism', + text: 'Controls, missions and model notes connect the spectacle to the underlying idea.', + }, + { + label: 'Verify', + title: 'Expose the boundary', + text: 'Research releases preserve parameters, assumptions, limitations and reproducible outputs.', + }, +]; + +function openLab(lab) { + const url = new URL(window.location.href); + url.searchParams.set('lab', lab); + url.searchParams.delete('run'); + url.searchParams.delete('state'); + url.hash = 'playground'; + window.history.replaceState({}, '', url); + window.dispatchEvent(new CustomEvent('gaugegap:lab', { detail: { lab } })); + window.requestAnimationFrame(() => document.getElementById('playground')?.scrollIntoView({ behavior: 'smooth', block: 'start' })); +} + +export function VisitorRoutes({ onResearch }) { + function chooseRoute(route) { + track('gaugegap_pathway_selected', { pathway: route.id }); + if (route.lab) openLab(route.lab); + if (route.route === 'research') onResearch?.(); + if (route.target) document.getElementById(route.target)?.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + + return ( +
+
+

Start with what brought you here

+

You should know where to click in five seconds.

+

GaugeGap serves curious visitors, educators, researchers and organizations. Pick the path that matches your job right now.

+
+
+ {VISITOR_ROUTES.map((route) => { + const Icon = route.icon; + return ( + + ); + })} +
+
+ ); +} + +function openClientBrief(pathway) { + const subject = encodeURIComponent(`GaugeGap pilot — ${pathway.title}`); + const body = encodeURIComponent([ + 'Hi GaugeGap team,', + '', + `I am exploring a ${pathway.title.toLowerCase()} project.`, + '', + 'Audience:', + 'Concept or topic:', + 'What I want people to understand or do:', + 'Target launch window:', + '', + 'Please suggest the smallest useful pilot.', + ].join('\n')); + track('gaugegap_client_cta_clicked', { pathway: pathway.id }); + window.location.href = `mailto:hello@brainsnn.com?subject=${subject}&body=${body}`; +} + +export function ClientPathways() { + return ( +
+
+
+

For organizations and client work

+

Do not buy another explanation page. Build something people can operate.

+

GaugeGap can turn a hard idea into a branded interactive experience with a clear mission, measurable behavior and a deeper evidence layer.

+
+
+ +
+ Start with one useful pilot + One audience, one concept, one interaction and one success measure. Expand only after people use it. +
+
+
+ +
+ {CLIENT_PATHWAYS.map((pathway) => { + const Icon = pathway.icon; + return ( +
+ +

{pathway.title}

+

{pathway.text}

+
    + {pathway.outcomes.map((outcome) =>
  • {outcome}
  • )} +
+ +
+ ); + })} +
+ +
+
+ Typical first pilot + Concept → playable prototype → client review → launch-ready experience +
+
+ Custom interactionBranded interfaceMission and scoringShareable statesModel notes +
+ +
+
+ ); +} + +export function TrustLadder({ onResearch }) { + return ( +
+
+

Know what you are looking at

+

Fun is the front door. The claim boundary stays visible.

+

Not every interactive model is a research result. GaugeGap separates intuition-building experiences from releases that expose enough detail for technical review.

+
+
+ {TRUST_LEVELS.map((level, index) => ( +
+ {String(index + 1).padStart(2, '0')} + {level.label} +

{level.title}

+

{level.text}

+
+ ))} +
+
+

Current public arcade: educational numerical models for exploration. Research mode is where assumptions, diagnostics and limitations must be made explicit.

+ +
+
+ ); +} From d250d78be86265a0e995dc4183163039798d9d3d Mon Sep 17 00:00:00 2001 From: PenguineWalkOS Date: Sun, 12 Jul 2026 13:24:17 -0400 Subject: [PATCH 2/9] Style visitor and client conversion sections --- .../src/styles/audience-pathways.css | 224 ++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 brainsnn-r3f-app/src/styles/audience-pathways.css diff --git a/brainsnn-r3f-app/src/styles/audience-pathways.css b/brainsnn-r3f-app/src/styles/audience-pathways.css new file mode 100644 index 0000000..e77ec6d --- /dev/null +++ b/brainsnn-r3f-app/src/styles/audience-pathways.css @@ -0,0 +1,224 @@ +.gg-visitor-routes, +.gg-client-section, +.gg-trust-section { + position: relative; + z-index: 1; + width: min(100% - 36px, 1320px); + margin: 0 auto; +} + +.gg-visitor-routes { padding: clamp(54px, 7vw, 92px) 0 22px; } +.gg-client-section { padding: clamp(72px, 9vw, 126px) 0; scroll-margin-top: 92px; } +.gg-trust-section { padding: 34px 0 clamp(72px, 9vw, 118px); } + +.gg-audience-heading { max-width: 850px; } +.gg-audience-heading h2 { + margin: 10px 0 14px; + font-family: var(--bsn-font-display); + font-size: clamp(2.25rem, 5vw, 4.8rem); + line-height: 0.98; + letter-spacing: -0.04em; +} +.gg-audience-heading > p:last-child { + margin: 0; + color: var(--bsn-text-secondary); + font-size: 1.04rem; + line-height: 1.68; +} + +.gg-route-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 14px; + margin-top: 28px; +} + +.gg-route-card { + min-height: 250px; + display: flex; + flex-direction: column; + align-items: flex-start; + padding: 20px; + border: 1px solid rgba(255,255,255,0.09); + border-radius: 20px; + color: var(--bsn-text); + background: radial-gradient(circle at 90% 0%, rgba(125,249,255,0.09), transparent 38%), rgba(9,10,20,0.78); + text-align: left; + cursor: pointer; + transition: transform 180ms ease, border-color 180ms ease, background 180ms ease; +} +.gg-route-card:hover, +.gg-route-card:focus-visible { + transform: translateY(-4px); + border-color: rgba(125,249,255,0.48); + background: radial-gradient(circle at 90% 0%, rgba(125,249,255,0.15), transparent 42%), rgba(12,13,27,0.96); +} +.gg-route-icon, +.gg-client-icon { + width: 44px; + height: 44px; + display: grid; + place-items: center; + border: 1px solid rgba(125,249,255,0.28); + border-radius: 13px; + color: var(--bsn-cyan); + background: rgba(125,249,255,0.055); +} +.gg-route-card small { + margin-top: 18px; + color: var(--bsn-cyan); + font-family: var(--bsn-font-mono); + font-size: 0.68rem; + letter-spacing: 0.08em; + text-transform: uppercase; +} +.gg-route-card strong { margin-top: 8px; font-size: 1.1rem; } +.gg-route-card p { + margin: 11px 0 18px; + color: var(--bsn-text-secondary); + font-size: 0.88rem; + line-height: 1.55; +} +.gg-route-card em { + margin-top: auto; + display: inline-flex; + align-items: center; + gap: 7px; + color: #e8ffff; + font-style: normal; + font-size: 0.78rem; + font-weight: 850; +} + +.gg-client-intro { + display: grid; + grid-template-columns: minmax(0, 1.45fr) minmax(280px, 0.55fr); + gap: 28px; + align-items: end; +} +.gg-client-promise { + display: flex; + gap: 14px; + padding: 19px; + border: 1px solid rgba(217,255,101,0.22); + border-radius: 18px; + color: #efffc0; + background: rgba(217,255,101,0.045); +} +.gg-client-promise div { display: grid; gap: 7px; } +.gg-client-promise strong { font-size: 0.96rem; } +.gg-client-promise span { color: var(--bsn-text-secondary); font-size: 0.82rem; line-height: 1.48; } + +.gg-client-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 14px; + margin-top: 30px; +} +.gg-client-card { + min-height: 350px; + display: flex; + flex-direction: column; + padding: 21px; + border: 1px solid rgba(255,255,255,0.09); + border-radius: 21px; + background: linear-gradient(180deg, rgba(15,16,31,0.92), rgba(6,7,15,0.94)); +} +.gg-client-card h3 { margin: 20px 0 9px; font-size: 1.12rem; } +.gg-client-card > p { margin: 0; color: var(--bsn-text-secondary); font-size: 0.88rem; line-height: 1.55; } +.gg-client-card ul { display: grid; gap: 9px; margin: 20px 0; padding: 0; list-style: none; } +.gg-client-card li { display: flex; gap: 8px; color: var(--bsn-text-secondary); font-size: 0.79rem; line-height: 1.4; } +.gg-client-card li svg { flex: 0 0 auto; margin-top: 1px; color: #d9ff65; } +.gg-client-card button { + margin-top: auto; + display: inline-flex; + align-items: center; + gap: 8px; + width: fit-content; + padding: 0; + border: 0; + color: var(--bsn-cyan); + background: transparent; + font-weight: 850; + cursor: pointer; +} + +.gg-pilot-strip { + display: grid; + grid-template-columns: minmax(230px, 0.7fr) minmax(0, 1.3fr) auto; + align-items: center; + gap: 22px; + margin-top: 18px; + padding: 21px; + border: 1px solid rgba(125,249,255,0.18); + border-radius: 20px; + background: radial-gradient(circle at 70% 50%, rgba(139,92,246,0.1), transparent 38%), rgba(8,9,19,0.9); +} +.gg-pilot-strip > div:first-child { display: grid; gap: 6px; } +.gg-pilot-strip small { color: var(--bsn-cyan); font-family: var(--bsn-font-mono); text-transform: uppercase; letter-spacing: 0.08em; } +.gg-pilot-strip strong { font-size: 0.92rem; line-height: 1.42; } +.gg-pilot-steps { display: flex; flex-wrap: wrap; gap: 8px; } +.gg-pilot-steps span { + padding: 7px 10px; + border: 1px solid rgba(255,255,255,0.08); + border-radius: 999px; + color: var(--bsn-text-secondary); + background: rgba(255,255,255,0.025); + font-size: 0.72rem; +} + +.gg-trust-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 14px; + margin-top: 26px; +} +.gg-trust-grid article { + position: relative; + padding: 21px; + border: 1px solid rgba(255,255,255,0.08); + border-radius: 18px; + background: rgba(8,9,18,0.72); +} +.gg-trust-grid article > span { + position: absolute; + top: 15px; + right: 17px; + color: rgba(255,255,255,0.28); + font-family: var(--bsn-font-mono); + font-size: 0.7rem; +} +.gg-trust-grid small { color: var(--bsn-cyan); font-family: var(--bsn-font-mono); letter-spacing: 0.1em; text-transform: uppercase; } +.gg-trust-grid h3 { margin: 13px 0 8px; font-size: 1.08rem; } +.gg-trust-grid p { margin: 0; color: var(--bsn-text-secondary); font-size: 0.85rem; line-height: 1.5; } +.gg-trust-note { + display: flex; + align-items: center; + justify-content: space-between; + gap: 22px; + margin-top: 16px; + padding: 18px 20px; + border-left: 3px solid #d9ff65; + background: rgba(217,255,101,0.035); +} +.gg-trust-note p { margin: 0; max-width: 840px; color: var(--bsn-text-secondary); line-height: 1.55; } +.gg-trust-note strong { color: #efffc0; } + +@media (max-width: 1050px) { + .gg-route-grid, + .gg-client-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } + .gg-client-intro { grid-template-columns: 1fr; align-items: start; } + .gg-pilot-strip { grid-template-columns: 1fr; align-items: start; } +} + +@media (max-width: 700px) { + .gg-visitor-routes, + .gg-client-section, + .gg-trust-section { width: min(100% - 24px, 1320px); } + .gg-route-grid, + .gg-client-grid, + .gg-trust-grid { grid-template-columns: 1fr; } + .gg-route-card { min-height: 220px; } + .gg-client-card { min-height: 0; } + .gg-trust-note { align-items: flex-start; flex-direction: column; } +} From 159a3f49a19fcfcb5f8ceb5309e2b65241aade9b Mon Sep 17 00:00:00 2001 From: PenguineWalkOS Date: Sun, 12 Jul 2026 13:25:15 -0400 Subject: [PATCH 3/9] Improve experiment discovery, accessibility and initial loading --- .../features/gaugegap/ExperimentArcade.jsx | 177 ++++++++++++++---- 1 file changed, 136 insertions(+), 41 deletions(-) diff --git a/brainsnn-r3f-app/src/features/gaugegap/ExperimentArcade.jsx b/brainsnn-r3f-app/src/features/gaugegap/ExperimentArcade.jsx index 1584074..719717c 100644 --- a/brainsnn-r3f-app/src/features/gaugegap/ExperimentArcade.jsx +++ b/brainsnn-r3f-app/src/features/gaugegap/ExperimentArcade.jsx @@ -1,29 +1,52 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { Suspense, lazy, useEffect, useMemo, useRef, useState } from 'react'; import { Activity, Bug, Car, CircleDot, Dna, Gauge, Grid3X3, Leaf, Orbit, Shield, Shuffle, Sparkles, Waves, Wind } from 'lucide-react'; -import { AttractorPlayground } from './AttractorPlayground.jsx'; -import { FireflySyncLab, ReactionDiffusionLab, WaveInterferenceLab } from './CollectivePlaygrounds.jsx'; -import { FlockMindLab, OutbreakZeroLab } from './AgentPlaygrounds.jsx'; -import { ChaosTwinsLab, GravityForgeLab } from './PhysicsPlaygrounds.jsx'; -import { AntTrailLab, TrafficTamerLab } from './PlayfulPlaygrounds.jsx'; -import { EcosystemBalanceLab, LifePainterLab } from './WorldPlaygrounds.jsx'; import { ArcadeProgress, useArcadeProgress } from './ArcadeProgress.jsx'; +import { track } from '../../lib/analytics.js'; import '../../styles/arcade.css'; import '../../styles/deep-arcade.css'; import '../../styles/fun-arcade.css'; +function lazyNamed(loader, exportName) { + return lazy(() => loader().then((module) => ({ default: module[exportName] }))); +} + +const LAB_COMPONENTS = { + attractor: lazyNamed(() => import('./AttractorPlayground.jsx'), 'AttractorPlayground'), + fireflies: lazyNamed(() => import('./CollectivePlaygrounds.jsx'), 'FireflySyncLab'), + waves: lazyNamed(() => import('./CollectivePlaygrounds.jsx'), 'WaveInterferenceLab'), + reaction: lazyNamed(() => import('./CollectivePlaygrounds.jsx'), 'ReactionDiffusionLab'), + gravity: lazyNamed(() => import('./PhysicsPlaygrounds.jsx'), 'GravityForgeLab'), + flock: lazyNamed(() => import('./AgentPlaygrounds.jsx'), 'FlockMindLab'), + outbreak: lazyNamed(() => import('./AgentPlaygrounds.jsx'), 'OutbreakZeroLab'), + pendulum: lazyNamed(() => import('./PhysicsPlaygrounds.jsx'), 'ChaosTwinsLab'), + ants: lazyNamed(() => import('./PlayfulPlaygrounds.jsx'), 'AntTrailLab'), + traffic: lazyNamed(() => import('./PlayfulPlaygrounds.jsx'), 'TrafficTamerLab'), + life: lazyNamed(() => import('./WorldPlaygrounds.jsx'), 'LifePainterLab'), + ecosystem: lazyNamed(() => import('./WorldPlaygrounds.jsx'), 'EcosystemBalanceLab'), +}; + const EXPERIMENTS = [ - { id: 'attractor', number: '001', title: 'Butterfly Effect', short: 'Shape chaos', description: 'Tune a Lorenz system until order and turbulence balance on the same orbit.', icon: Gauge, accent: 'cyan', mechanic: 'Tune' }, - { id: 'fireflies', number: '002', title: 'Firefly Sync', short: 'Create collective rhythm', description: 'Give hundreds of independent clocks one weak connection and watch a shared pulse emerge.', icon: Sparkles, accent: 'lime', mechanic: 'Synchronize' }, - { id: 'waves', number: '003', title: 'Wave Eraser', short: 'Find perfect silence', description: 'Move through two overlapping waves and hunt for the places where energy disappears.', icon: Waves, accent: 'violet', mechanic: 'Explore' }, - { id: 'reaction', number: '004', title: 'Living Chemistry', short: 'Draw a new species', description: 'Paint two virtual chemicals and grow coral, cells, worms and mazes from local reactions.', icon: Dna, accent: 'pink', mechanic: 'Create' }, - { id: 'gravity', number: '005', title: 'Gravity Forge', short: 'Build a solar system', description: 'Launch planets into a live n-body field and see whether your orbital architecture survives.', icon: Orbit, accent: 'amber', mechanic: 'Construct' }, - { id: 'flock', number: '006', title: 'Flock Mind', short: 'Steer emergence', description: 'Act as predator or beacon while leaderless agents coordinate through only local rules.', icon: Wind, accent: 'blue', mechanic: 'Influence' }, - { id: 'outbreak', number: '007', title: 'Outbreak Zero', short: 'Contain the network', description: 'Choose patient zero, spend twelve vaccines and break the transmission graph before it turns red.', icon: Shield, accent: 'red', mechanic: 'Intervene' }, - { id: 'pendulum', number: '008', title: 'Chaos Twins', short: 'Race two futures', description: 'Start two double pendulums almost identically and measure how quickly their futures separate.', icon: CircleDot, accent: 'orange', mechanic: 'Predict' }, - { id: 'ants', number: '009', title: 'Ant Trail Architect', short: 'Design without a planner', description: 'Place food and barriers while a leaderless colony discovers and reinforces efficient routes.', icon: Bug, accent: 'mint', mechanic: 'Route' }, - { id: 'traffic', number: '010', title: 'Traffic Tamer', short: 'Beat the intersection', description: 'Control signal phases under rising demand and keep every queue from becoming a citywide jam.', icon: Car, accent: 'yellow', mechanic: 'Control' }, - { id: 'life', number: '011', title: 'Life Painter', short: 'Paint computation', description: 'Draw living cells and let four tiny rules transform them into moving, evolving machines.', icon: Grid3X3, accent: 'teal', mechanic: 'Invent' }, - { id: 'ecosystem', number: '012', title: 'Ecosystem Keeper', short: 'Balance a living world', description: 'Add energy, prey or predators and keep the entire food web alive through delayed feedback.', icon: Leaf, accent: 'green', mechanic: 'Balance' }, + { id: 'attractor', number: '001', title: 'Butterfly Effect', short: 'Shape chaos', description: 'Tune a Lorenz system until order and turbulence balance on the same orbit.', icon: Gauge, accent: 'cyan', mechanic: 'Tune', category: 'physics', featured: true }, + { id: 'fireflies', number: '002', title: 'Firefly Sync', short: 'Create collective rhythm', description: 'Give hundreds of independent clocks one weak connection and watch a shared pulse emerge.', icon: Sparkles, accent: 'lime', mechanic: 'Synchronize', category: 'systems', featured: true }, + { id: 'waves', number: '003', title: 'Wave Eraser', short: 'Find perfect silence', description: 'Move through two overlapping waves and hunt for the places where energy disappears.', icon: Waves, accent: 'violet', mechanic: 'Explore', category: 'physics' }, + { id: 'reaction', number: '004', title: 'Living Chemistry', short: 'Draw a new species', description: 'Paint two virtual chemicals and grow coral, cells, worms and mazes from local reactions.', icon: Dna, accent: 'pink', mechanic: 'Create', category: 'life' }, + { id: 'gravity', number: '005', title: 'Gravity Forge', short: 'Build a solar system', description: 'Launch planets into a live n-body field and see whether your orbital architecture survives.', icon: Orbit, accent: 'amber', mechanic: 'Construct', category: 'physics' }, + { id: 'flock', number: '006', title: 'Flock Mind', short: 'Steer emergence', description: 'Act as predator or beacon while leaderless agents coordinate through only local rules.', icon: Wind, accent: 'blue', mechanic: 'Influence', category: 'systems' }, + { id: 'outbreak', number: '007', title: 'Outbreak Zero', short: 'Contain the network', description: 'Choose patient zero, spend twelve vaccines and break the transmission graph before it turns red.', icon: Shield, accent: 'red', mechanic: 'Intervene', category: 'society' }, + { id: 'pendulum', number: '008', title: 'Chaos Twins', short: 'Race two futures', description: 'Start two double pendulums almost identically and measure how quickly their futures separate.', icon: CircleDot, accent: 'orange', mechanic: 'Predict', category: 'physics' }, + { id: 'ants', number: '009', title: 'Ant Trail Architect', short: 'Design without a planner', description: 'Place food and barriers while a leaderless colony discovers and reinforces efficient routes.', icon: Bug, accent: 'mint', mechanic: 'Route', category: 'life', featured: true }, + { id: 'traffic', number: '010', title: 'Traffic Tamer', short: 'Beat the intersection', description: 'Control signal phases under rising demand and keep every queue from becoming a citywide jam.', icon: Car, accent: 'yellow', mechanic: 'Control', category: 'society', featured: true }, + { id: 'life', number: '011', title: 'Life Painter', short: 'Paint computation', description: 'Draw living cells and let four tiny rules transform them into moving, evolving machines.', icon: Grid3X3, accent: 'teal', mechanic: 'Invent', category: 'systems' }, + { id: 'ecosystem', number: '012', title: 'Ecosystem Keeper', short: 'Balance a living world', description: 'Add energy, prey or predators and keep the entire food web alive through delayed feedback.', icon: Leaf, accent: 'green', mechanic: 'Balance', category: 'life' }, +]; + +const FILTERS = [ + { id: 'featured', label: 'Start here' }, + { id: 'all', label: 'All 12' }, + { id: 'physics', label: 'Physics' }, + { id: 'life', label: 'Life' }, + { id: 'systems', label: 'Complex systems' }, + { id: 'society', label: 'Society' }, ]; function initialExperiment() { @@ -32,26 +55,58 @@ function initialExperiment() { return EXPERIMENTS.some((experiment) => experiment.id === requested) ? requested : 'attractor'; } +function initialFilter() { + if (typeof window === 'undefined') return 'featured'; + const query = new URLSearchParams(window.location.search); + const requested = query.get('group'); + if (FILTERS.some((filter) => filter.id === requested)) return requested; + return query.get('lab') ? 'all' : 'featured'; +} + +function LabLoading({ title }) { + return ( +
+ + Loading {title} + Only the selected experiment is being loaded. +
+ ); +} + export function ExperimentArcade() { const [active, setActive] = useState(initialExperiment); + const [filter, setFilter] = useState(initialFilter); + const cardRefs = useRef(new Map()); const activeExperiment = useMemo(() => EXPERIMENTS.find((experiment) => experiment.id === active) || EXPERIMENTS[0], [active]); + const visibleExperiments = useMemo(() => { + if (filter === 'all') return EXPERIMENTS; + if (filter === 'featured') return EXPERIMENTS.filter((experiment) => experiment.featured); + return EXPERIMENTS.filter((experiment) => experiment.category === filter); + }, [filter]); const { progress, recordVisit, dailyLab, level, levelProgress, achievements } = useArcadeProgress(EXPERIMENTS); + const ActiveLab = LAB_COMPONENTS[active] || LAB_COMPONENTS.attractor; useEffect(() => { recordVisit(active); }, [active, recordVisit]); useEffect(() => { function selectFromEvent(event) { const next = event.detail?.lab; - if (EXPERIMENTS.some((experiment) => experiment.id === next)) setActive(next); + if (EXPERIMENTS.some((experiment) => experiment.id === next)) { + setFilter('all'); + setActive(next); + } } window.addEventListener('gaugegap:lab', selectFromEvent); return () => window.removeEventListener('gaugegap:lab', selectFromEvent); }, []); function selectExperiment(id, scroll = true) { + const experiment = EXPERIMENTS.find((entry) => entry.id === id); setActive(id); + track('gaugegap_lab_selected', { labId: id, category: experiment?.category || 'unknown' }); const url = new URL(window.location.href); url.searchParams.set('lab', id); + url.searchParams.set('group', filter); if (id !== 'attractor') url.searchParams.delete('run'); url.searchParams.delete('state'); url.hash = 'playground'; @@ -59,9 +114,40 @@ export function ExperimentArcade() { if (scroll) window.requestAnimationFrame(() => document.getElementById('playground')?.scrollIntoView({ behavior: 'smooth', block: 'start' })); } + function chooseFilter(nextFilter) { + setFilter(nextFilter); + track('gaugegap_filter_selected', { filter: nextFilter }); + const nextVisible = nextFilter === 'all' + ? EXPERIMENTS + : nextFilter === 'featured' + ? EXPERIMENTS.filter((experiment) => experiment.featured) + : EXPERIMENTS.filter((experiment) => experiment.category === nextFilter); + if (!nextVisible.some((experiment) => experiment.id === active) && nextVisible[0]) setActive(nextVisible[0].id); + const url = new URL(window.location.href); + url.searchParams.set('group', nextFilter); + window.history.replaceState({}, '', url); + } + function surpriseMe() { const available = EXPERIMENTS.filter((experiment) => experiment.id !== active); - selectExperiment(available[Math.floor(Math.random() * available.length)].id); + setFilter('all'); + const next = available[Math.floor(Math.random() * available.length)]; + track('gaugegap_surprise_clicked', { labId: next.id }); + selectExperiment(next.id); + } + + function handleCardKeyDown(event, id) { + const currentIndex = visibleExperiments.findIndex((experiment) => experiment.id === id); + let nextIndex = currentIndex; + if (event.key === 'ArrowRight' || event.key === 'ArrowDown') nextIndex = (currentIndex + 1) % visibleExperiments.length; + if (event.key === 'ArrowLeft' || event.key === 'ArrowUp') nextIndex = (currentIndex - 1 + visibleExperiments.length) % visibleExperiments.length; + if (event.key === 'Home') nextIndex = 0; + if (event.key === 'End') nextIndex = visibleExperiments.length - 1; + if (nextIndex === currentIndex) return; + event.preventDefault(); + const next = visibleExperiments[nextIndex]; + selectExperiment(next.id, false); + window.requestAnimationFrame(() => cardRefs.current.get(next.id)?.focus()); } return ( @@ -69,21 +155,39 @@ export function ExperimentArcade() {

GaugeGap science arcade

-

Twelve experiments. Twelve ways to play with reality.

-

Tune, synchronize, explore, draw, construct, influence, intervene, predict, route, control, invent and balance. The library now behaves like an arcade—not a catalogue of charts.

+

Start with four. Explore all twelve when you are ready.

+

The stranger-friendly route shows the strongest first experiences. Filters reveal the full library without making the first visit feel like a wall of choices.

- selectExperiment(dailyLab.id)} /> + { setFilter('all'); selectExperiment(dailyLab.id); }} /> + +
+ {FILTERS.map((entry) => ( + + ))} + {visibleExperiments.length} shown +
- {EXPERIMENTS.map((experiment) => { + {visibleExperiments.map((experiment) => { const Icon = experiment.icon; const selected = experiment.id === active; const visited = progress.visited.includes(experiment.id); return ( -
-
+
Experiment {activeExperiment.number} loaded{activeExperiment.title}
- {active === 'attractor' ? : null} - {active === 'fireflies' ? : null} - {active === 'waves' ? : null} - {active === 'reaction' ? : null} - {active === 'gravity' ? : null} - {active === 'flock' ? : null} - {active === 'outbreak' ? : null} - {active === 'pendulum' ? : null} - {active === 'ants' ? : null} - {active === 'traffic' ? : null} - {active === 'life' ? : null} - {active === 'ecosystem' ? : null} + }> + +
- The retention layer now adds - Daily missionsXP and levelsVisit streaksAchievementsTwelve tactile mechanics + Designed for a first-time visitor + Four recommended startsTopic filtersKeyboard navigationOn-demand loadingShareable challenges
); From 9406400b027643413275a239705667b5b8659f47 Mon Sep 17 00:00:00 2001 From: PenguineWalkOS Date: Sun, 12 Jul 2026 13:25:33 -0400 Subject: [PATCH 4/9] Style arcade filters and lazy-loading state --- .../src/styles/arcade-discovery.css | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 brainsnn-r3f-app/src/styles/arcade-discovery.css diff --git a/brainsnn-r3f-app/src/styles/arcade-discovery.css b/brainsnn-r3f-app/src/styles/arcade-discovery.css new file mode 100644 index 0000000..d1f9a35 --- /dev/null +++ b/brainsnn-r3f-app/src/styles/arcade-discovery.css @@ -0,0 +1,72 @@ +.gg-arcade-filters { + display: flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; + margin: 22px 0 16px; +} + +.gg-arcade-filters button { + min-height: 38px; + padding: 0 13px; + border: 1px solid rgba(255,255,255,0.09); + border-radius: 999px; + color: var(--bsn-text-secondary); + background: rgba(255,255,255,0.025); + font-size: 0.76rem; + font-weight: 800; + cursor: pointer; +} + +.gg-arcade-filters button:hover, +.gg-arcade-filters button:focus-visible, +.gg-arcade-filters button.active { + border-color: rgba(125,249,255,0.46); + color: #e9ffff; + background: rgba(125,249,255,0.075); +} + +.gg-arcade-filters > span { + margin-left: auto; + color: var(--bsn-text-muted); + font-family: var(--bsn-font-mono); + font-size: 0.68rem; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.gg-lab-loading { + min-height: 520px; + display: grid; + place-items: center; + align-content: center; + gap: 10px; + border-radius: 22px; + color: var(--bsn-text-secondary); + background: radial-gradient(circle at 50% 40%, rgba(125,249,255,0.08), transparent 34%), #03050b; + text-align: center; +} + +.gg-lab-loading > span { + width: 34px; + height: 34px; + border: 2px solid rgba(125,249,255,0.18); + border-top-color: #7df9ff; + border-radius: 50%; + animation: gg-lab-spin 800ms linear infinite; +} + +.gg-lab-loading strong { color: #e9ffff; } +.gg-lab-loading small { color: var(--bsn-text-muted); } + +@keyframes gg-lab-spin { to { transform: rotate(360deg); } } + +@media (max-width: 700px) { + .gg-arcade-filters { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .gg-arcade-filters button { width: 100%; } + .gg-arcade-filters > span { grid-column: 1 / -1; margin-left: 0; text-align: right; } + .gg-lab-loading { min-height: 420px; } +} From fcc2d327c5700047e816aaac492677f227a80e5f Mon Sep 17 00:00:00 2001 From: PenguineWalkOS Date: Sun, 12 Jul 2026 13:25:46 -0400 Subject: [PATCH 5/9] Track the public GaugeGap and client funnel --- brainsnn-r3f-app/src/lib/analytics.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/brainsnn-r3f-app/src/lib/analytics.js b/brainsnn-r3f-app/src/lib/analytics.js index ab9756c..d35417e 100644 --- a/brainsnn-r3f-app/src/lib/analytics.js +++ b/brainsnn-r3f-app/src/lib/analytics.js @@ -30,6 +30,15 @@ const allowedEvents = new Set([ 'share_card_shared', 'share_card_downloaded', 'brain3d_fallback_used', + 'gaugegap_landing_viewed', + 'gaugegap_hero_play_clicked', + 'gaugegap_lab_clicked', + 'gaugegap_lab_selected', + 'gaugegap_filter_selected', + 'gaugegap_surprise_clicked', + 'gaugegap_pathway_selected', + 'gaugegap_client_cta_clicked', + 'gaugegap_research_cta_clicked', ]); export function track(eventName, properties = {}) { From 3201a11222629e800346c2778fbf35e88fa9d887 Mon Sep 17 00:00:00 2001 From: PenguineWalkOS Date: Sun, 12 Jul 2026 13:26:42 -0400 Subject: [PATCH 6/9] Rebuild the public journey around strangers and clients --- brainsnn-r3f-app/src/app/GaugeGapLanding.jsx | 121 +++++++++++-------- 1 file changed, 69 insertions(+), 52 deletions(-) diff --git a/brainsnn-r3f-app/src/app/GaugeGapLanding.jsx b/brainsnn-r3f-app/src/app/GaugeGapLanding.jsx index 7a079d4..82156e8 100644 --- a/brainsnn-r3f-app/src/app/GaugeGapLanding.jsx +++ b/brainsnn-r3f-app/src/app/GaugeGapLanding.jsx @@ -2,56 +2,58 @@ import React, { useEffect } from 'react'; import { ArrowRight, BrainCircuit, - Bug, - Car, CheckCircle2, ChevronDown, - CircleDot, - Dna, FlaskConical, - Gauge, - Grid3X3, Layers3, - Leaf, Microscope, - Orbit, Play, Share2, Shield, Sparkles, WandSparkles, - Waves, - Wind, Zap, } from 'lucide-react'; import { Button } from '../components/ui/Button.jsx'; import { ExperimentArcade } from '../features/gaugegap/ExperimentArcade.jsx'; +import { ClientPathways, TrustLadder, VisitorRoutes } from '../features/gaugegap/AudiencePathways.jsx'; import { track } from '../lib/analytics.js'; import '../styles/gaugegap.css'; +import '../styles/arcade-discovery.css'; const CONTENT_SAMPLE = 'Everyone says this breakthrough changes everything. Here is what the evidence actually shows, what remains uncertain, and the one result worth paying attention to.'; -const LABS = [ - { id: 'attractor', eyebrow: 'Live experiment 001', title: 'Butterfly Effect Lab', description: 'Tune a chaotic system until order and turbulence balance on the same orbit.', icon: Gauge, action: 'Shape chaos' }, - { id: 'fireflies', eyebrow: 'Live experiment 002', title: 'Firefly Sync Lab', description: 'Connect hundreds of independent clocks and watch collective rhythm emerge without a leader.', icon: Sparkles, action: 'Sync the swarm' }, - { id: 'waves', eyebrow: 'Live experiment 003', title: 'Wave Eraser', description: 'Move a detector through overlapping waves and find the exact places where energy disappears.', icon: Waves, action: 'Find silence' }, - { id: 'reaction', eyebrow: 'Live experiment 004', title: 'Living Chemistry', description: 'Draw into a reaction-diffusion field and grow coral, cells, worms and mazes from two chemicals.', icon: Dna, action: 'Grow a species' }, - { id: 'gravity', eyebrow: 'Live experiment 005', title: 'Gravity Forge', description: 'Launch planets into a live n-body field and build an orbital system that does not destroy itself.', icon: Orbit, action: 'Build a system' }, - { id: 'flock', eyebrow: 'Live experiment 006', title: 'Flock Mind', description: 'Steer a leaderless crowd as predator or beacon while local rules create group intelligence.', icon: Wind, action: 'Steer emergence' }, - { id: 'outbreak', eyebrow: 'Live experiment 007', title: 'Outbreak Zero', description: 'Pick patient zero, spend twelve vaccines and interrupt the contact graph before it turns red.', icon: Shield, action: 'Contain it' }, - { id: 'pendulum', eyebrow: 'Live experiment 008', title: 'Chaos Twins', description: 'Race two nearly identical double pendulums and measure when their futures stop agreeing.', icon: CircleDot, action: 'Race the futures' }, - { id: 'ants', eyebrow: 'Live experiment 009', title: 'Ant Trail Architect', description: 'Place food and barriers while a leaderless colony discovers and reinforces its own road system.', icon: Bug, action: 'Build ant roads' }, - { id: 'traffic', eyebrow: 'Live experiment 010', title: 'Traffic Tamer', description: 'Control signal phases under rising demand and keep every queue from becoming a citywide jam.', icon: Car, action: 'Run the lights' }, - { id: 'life', eyebrow: 'Live experiment 011', title: 'Life Painter', description: 'Paint living cells and let four tiny rules transform them into moving computational machines.', icon: Grid3X3, action: 'Paint a universe' }, - { id: 'ecosystem', eyebrow: 'Live experiment 012', title: 'Ecosystem Keeper', description: 'Add plants, prey or predators and keep an entire food web alive through delayed feedback.', icon: Leaf, action: 'Balance the world' }, - { id: 'soliton', eyebrow: 'Research engine', title: 'Soliton Collision Lab', description: 'Launch nonlinear waves, change their amplitude and watch them pass through one another without losing identity.', icon: Zap, action: 'Open research lab' }, - { id: 'content', eyebrow: 'BrainSNN crossover', title: 'Mind-Hack Autopsy', description: 'Paste viral content and expose the emotional pressure, trust cost and attention mechanics hiding inside it.', icon: BrainCircuit, action: 'Scan a viral claim' }, +const DEEPER_TOOLS = [ + { + id: 'soliton', + eyebrow: 'Research workspace', + title: 'Soliton Collision Lab', + description: 'Move from a visual demonstration into nonlinear-wave controls, diagnostics and model-specific outputs.', + icon: Zap, + action: 'Open research mode', + }, + { + id: 'content', + eyebrow: 'BrainSNN engine', + title: 'Mind-Hack Autopsy', + description: 'Paste content and expose attention pressure, emotional charge, trust cost and manipulation signals.', + icon: BrainCircuit, + action: 'Test the decision engine', + }, + { + id: 'reconstruct', + eyebrow: 'Claim boundary', + title: 'Reconstruct a Stronger Claim', + description: 'Separate what the evidence supports from what the story merely implies, then rebuild the claim responsibly.', + icon: Shield, + action: 'Build a defensible claim', + }, ]; const LOOP = [ - { number: '01', title: 'Play', text: 'Touch the variables before reading the lesson. The system teaches through response.' }, - { number: '02', title: 'Return', text: 'Daily missions, XP, levels and achievements create a reason to explore another system tomorrow.' }, - { number: '03', title: 'Publish', text: 'Share the visual, challenge link, score and explanation from the same experiment state.' }, + { number: '01', title: 'Play', text: 'Touch the system before reading the explanation. Immediate response earns attention.' }, + { number: '02', title: 'Understand', text: 'Missions, model notes and visible limits connect the experience to the underlying mechanism.' }, + { number: '03', title: 'Publish', text: 'Share the run, challenge and explanation from the same experiment state.' }, ]; const ARCADE_IDS = new Set(['attractor', 'fireflies', 'waves', 'reaction', 'gravity', 'flock', 'outbreak', 'pendulum', 'ants', 'traffic', 'life', 'ecosystem']); @@ -62,9 +64,18 @@ export function GaugeGapLanding({ onStart, onNavigate, onOpenReconstruct }) { track('gaugegap_landing_viewed'); }, []); + function scrollTo(id) { + document.getElementById(id)?.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + function scrollToPlayground() { track('gaugegap_hero_play_clicked'); - document.getElementById('playground')?.scrollIntoView({ behavior: 'smooth', block: 'start' }); + scrollTo('playground'); + } + + function openResearch() { + track('gaugegap_research_cta_clicked'); + onNavigate?.('research'); } function openLab(id) { @@ -79,8 +90,9 @@ export function GaugeGapLanding({ onStart, onNavigate, onOpenReconstruct }) { window.dispatchEvent(new CustomEvent('gaugegap:lab', { detail: { lab: id } })); scrollToPlayground(); } - if (id === 'soliton') onNavigate?.('research'); + if (id === 'soliton') openResearch(); if (id === 'content') onStart?.(CONTENT_SAMPLE); + if (id === 'reconstruct') onOpenReconstruct?.(); } return ( @@ -93,12 +105,12 @@ export function GaugeGapLanding({ onStart, onNavigate, onOpenReconstruct }) {
- +
@@ -108,26 +120,26 @@ export function GaugeGapLanding({ onStart, onNavigate, onOpenReconstruct }) {
-

Science you can touch, remix and master

-

Don’t just learn the universe. Play with it.

+

Playable science for curious people and ambitious organizations

+

Do not just explain the idea. Let people operate it.

- Twelve live experiments turn difficult science into games, daily missions and shareable challenges. - Build ant roads, tame traffic, paint cellular life, balance ecosystems—and keep climbing your Foundry passport. + GaugeGap is the public science arcade. BrainSNN is the analysis and publishing engine underneath. + Together they turn difficult systems into interactive missions, shareable discoveries and client-ready experiences.

- +
12 liveDistinct experiments
-
DailyMissions and streaks
-
LocalXP and achievements
+
4 pathsClear first steps
+
ClientCustom pilot pathway
OpenModels and limits
-
Daily arcade live12 worlds
+
Live systemStart in seconds
-

Complete today’s system challenge.

Earn XP, extend your streak and unlock the next badge+50 XP
- +

Find the edge of chaos.

No signup. No tutorial wall. The model responds immediately.2 min
+
- + +
-

The audience growth engine

Every experiment becomes a reason to return.

The simulator creates spectacle. The passport creates continuity. Sharing turns one person’s discovery into the next person’s first challenge.

+

The engagement engine

A useful interaction should continue after the first click.

The visual earns attention. The model earns understanding. The shared state brings the next person into the same system.

{LOOP.map((item) =>
{item.number}

{item.title}

{item.text}

)}
-
One session createsXP progressDaily streakChallenge linkVisual loopResearch state
+
One experience can createInteractive lessonChallenge linkVisual assetModel noteResearch state
+ +
-

Foundry experiments

Come for the game. Stay for the instrument.

Each lab starts with a tactile mission, then opens into equations, assumptions, reproducible settings and exportable evidence.

+

Beyond the public arcade

Three deeper tools. Three different jobs.

The arcade builds intuition. These workspaces analyze content, expose claim boundaries and support deeper technical exploration.

- {LABS.map((lab, index) => { const Icon = lab.icon; return

{lab.eyebrow}

{lab.title}

{lab.description}
; })} + {DEEPER_TOOLS.map((lab, index) => { const Icon = lab.icon; return

{lab.eyebrow}

{lab.title}

{lab.description}
; })}
-

Twelve worlds are already running

Pick a system. Complete the mission. Come back stronger tomorrow.

The next person should arrive through your challenge—and find a reason to begin their own streak.

+ + +

Choose the next useful step

Play a system—or build one for the people you need to reach.

The public arcade proves the interaction model. A focused client pilot applies it to your own audience, concept and outcome.

-
G

GaugeGap FoundryPlayable science and publishing infrastructure by BrainSNN.

Simulations are educational numerical models, not proof of physical claims. Exact assumptions and limitations belong with every research release.

© {new Date().getFullYear()} GaugeGap Foundry · BrainSNN.com

+
G

GaugeGap FoundryPlayable science and interactive client experiences by BrainSNN.

Public simulations are educational numerical models, not proof of physical claims. Research releases must state assumptions, diagnostics and limitations.

© {new Date().getFullYear()} GaugeGap Foundry · BrainSNN.com

); } From 1c9e44ce2e5b03c4cc7f231c4ba3f1cdb4c21ca7 Mon Sep 17 00:00:00 2001 From: PenguineWalkOS Date: Sun, 12 Jul 2026 13:27:18 -0400 Subject: [PATCH 7/9] Align canonical metadata with the public www host --- brainsnn-r3f-app/index.html | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/brainsnn-r3f-app/index.html b/brainsnn-r3f-app/index.html index 0d70f1c..3b0751c 100644 --- a/brainsnn-r3f-app/index.html +++ b/brainsnn-r3f-app/index.html @@ -5,27 +5,27 @@ GaugeGap Foundry | Play with the impossible - + - + - - - - + + + + - - + +