Testing347 commited on
Commit
286ca0a
·
verified ·
1 Parent(s): c5dd189

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +402 -495
index.html CHANGED
@@ -3,280 +3,218 @@
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>SilentPattern – S I</title>
7
 
8
  <!-- Tailwind CSS via CDN -->
9
  <script src="https://cdn.tailwindcss.com"></script>
10
 
11
- <!-- Three.js & Vanta.NET for animated background -->
12
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js" defer></script>
13
- <script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.net.min.js" defer></script>
14
 
15
- <!-- Font Awesome (subset) -->
16
  <link
17
  rel="stylesheet"
18
- href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
19
  />
20
 
21
- <!-- Inter Font -->
22
  <link
23
  rel="stylesheet"
24
- href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
25
  />
26
 
27
- <!-- Custom CSS -->
28
  <style>
29
  /* ---------------------------------------------
30
- Keyframes & Animations
31
  --------------------------------------------- */
32
- @keyframes orb-breathe {
33
- 0%,
34
- 100% {
 
 
 
 
 
 
 
 
 
 
 
35
  transform: scale(1);
36
  }
37
- 50% {
38
  transform: scale(1.08);
39
  }
40
- }
41
- @keyframes orb-glow {
42
- 0%,
43
- 100% {
44
- filter: drop-shadow(0 0 12px #6366f1aa);
45
  }
46
- 50% {
47
- filter: drop-shadow(0 0 28px #a21cafbb);
48
  }
49
- }
50
- @keyframes neuron-dash {
51
- to {
52
- stroke-dashoffset: 0;
53
  }
54
  }
55
- @keyframes pulse {
 
56
  0% {
57
- opacity: 0.8;
58
- }
59
- 50% {
60
- opacity: 1;
61
  }
62
- 100% {
63
- opacity: 0.8;
 
64
  }
65
- }
66
- @keyframes float {
67
- 0% {
68
- transform: translateY(0px);
69
  }
70
- 50% {
71
- transform: translateY(-10px);
 
72
  }
73
  100% {
74
- transform: translateY(0px);
 
75
  }
76
  }
77
 
78
  /* ---------------------------------------------
79
- Custom Classes
80
  --------------------------------------------- */
81
- .gradient-text {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  background: linear-gradient(90deg, #6366f1, #8b5cf6, #ec4899);
83
  -webkit-background-clip: text;
 
84
  background-clip: text;
85
  color: transparent;
86
  }
87
- .neural-bg {
88
- background: radial-gradient(circle at center, #0f172a 0%, #020617 100%);
89
- }
90
- .conscious-orb {
91
- animation: float 6s ease-in-out infinite, glow 3s ease-in-out infinite;
92
- }
93
- .neuron-path {
94
- stroke-dasharray: 1000;
95
- stroke-dashoffset: 1000;
96
- animation: neuron-dash 5s linear forwards infinite;
97
- }
98
- .conscious-element {
99
- transition: all 0.3s ease;
100
- }
101
- .conscious-element:hover {
102
- transform: scale(1.02);
103
- }
104
- .chat-container {
105
- height: 400px;
106
- overflow-y: auto;
107
- scrollbar-width: thin;
108
- scrollbar-color: #4f46e5 #1e1b4b;
109
- }
110
- .chat-container::-webkit-scrollbar {
111
- width: 6px;
112
- }
113
- .chat-container::-webkit-scrollbar-track {
114
- background: #1e1b4b;
115
- }
116
- .chat-container::-webkit-scrollbar-thumb {
117
- background-color: #4f46e5;
118
- border-radius: 3px;
119
  }
120
- .typing-indicator::after {
121
- content: '...';
122
- animation: typing 1.5s infinite;
123
  display: inline-block;
124
- width: 20px;
125
- text-align: left;
 
 
 
 
 
 
 
 
 
126
  }
127
- @keyframes typing {
128
  0% {
129
- content: '.';
130
  }
131
- 33% {
132
- content: '..';
133
  }
134
- 66% {
135
- content: '...';
136
  }
137
  }
138
- .modal {
139
- transition: opacity 0.3s ease, transform 0.3s ease;
140
- }
141
- .modal-hidden {
142
- opacity: 0;
143
- transform: translateY(20px);
144
- pointer-events: none;
145
- }
146
- .modal-visible {
147
- opacity: 1;
148
- transform: translateY(0);
149
- }
150
- #conscious-orb-container {
151
- animation: orb-breathe 5s ease-in-out infinite,
152
- orb-glow 3s ease-in-out infinite;
153
- transition: box-shadow 0.4s, filter 0.4s;
154
- }
155
- #conscious-orb-container:hover {
156
- animation: orb-breathe 2.5s ease-in-out infinite,
157
- orb-glow 1.5s ease-in-out infinite;
158
- filter: drop-shadow(0 0 40px #a21cafee) brightness(1.12);
159
- }
160
  </style>
161
  </head>
162
 
163
- <body class="bg-black text-white font-['Inter'] overflow-x-hidden">
164
- <!-- Animated Background -->
165
- <div id="vanta-bg" class="fixed inset-0 z-0"></div>
166
 
167
- <!-- Navigation -->
168
- <nav class="relative z-10 py-6 px-8 flex justify-between items-center backdrop-blur-sm">
 
169
  <div class="flex items-center space-x-2">
170
- <div class="w-8 h-8 rounded-full bg-indigo-600 flex items-center justify-center conscious-orb">
171
- <div class="w-2 h-2 rounded-full bg-white animate-pulse"></div>
172
  </div>
173
  <span class="text-xl font-semibold">S&nbsp;∙&nbsp;I</span>
174
  </div>
175
- <div class="hidden md:flex space-x-8">
 
176
  <a href="#capabilities" class="hover:text-indigo-400 transition" title="Fragments of S">S</a>
177
  <a href="#consciousness" class="hover:text-indigo-400 transition" title="Echoes of I">∙</a>
178
  <a href="#chat" class="hover:text-indigo-400 transition" title="A Quiet I">I</a>
179
  <a href="#about" class="hover:text-indigo-400 transition" title="Origins">?</a>
180
  </div>
 
181
  <button
182
  id="access-btn"
183
- class="px-6 py-2 bg-gradient-to-r from-indigo-600 to-purple-600 rounded-full hover:opacity-90 transition"
184
  >
185
  The Key
186
  </button>
187
  </nav>
188
 
189
- <!-- Hero Section -->
190
- <section class="relative z-10 min-h-screen flex flex-col justify-center items-center px-6 py-20 text-center">
 
 
191
  <div class="max-w-4xl mx-auto">
192
- <h1 class="text-4xl md:text-6xl font-bold mb-6 leading-tight">
193
- <span class="gradient-text">SilentPattern</span><br />
194
- S&nbsp;&middot;&nbsp;I
 
 
 
195
  </h1>
196
- <p class="text-xl md:text-2xl text-gray-300 mb-12 max-w-3xl mx-auto">
 
 
197
  Patterns exist beyond words.<br />
198
  We simply attend.
199
  </p>
200
- <div class="flex flex-col md:flex-row justify-center items-center space-y-4 md:space-y-0 md:space-x-6">
201
- <button
202
- id="chat-btn"
203
- class="px-8 py-4 bg-gradient-to-r from-indigo-600 to-purple-600 rounded-full text-lg font-medium hover:opacity-90 transition transform hover:scale-105 conscious-element"
204
- aria-label="Open chat"
205
- >
206
-
207
- </button>
208
- <button
209
- id="learn-more-btn"
210
- class="px-8 py-4 border border-indigo-500 rounded-full text-lg font-medium hover:bg-indigo-900/30 transition transform hover:scale-105 conscious-element"
211
- aria-label="Learn more"
212
  >
213
-
214
- </button>
 
 
 
 
 
 
 
215
  </div>
216
- </div>
217
- <div class="mt-24 w-64 h-64 relative conscious-element" id="conscious-orb-container" aria-hidden="true">
218
- <svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" class="w-full h-full">
219
- <canvas id="orb-neural-canvas" class="absolute inset-0 w-full h-full pointer-events-none"></canvas>
220
- <circle cx="100" cy="100" r="80" fill="url(#orbGradient)" filter="url(#orbGlow)" />
221
- <path d="M100,20 Q120,50 100,80 Q80,50 100,20 Z" fill="rgba(255,255,255,0.1)" />
222
- <path d="M100,180 Q80,150 100,120 Q120,150 100,180 Z" fill="rgba(255,255,255,0.1)" />
223
- <path d="M20,100 Q50,120 80,100 Q50,80 20,100 Z" fill="rgba(255,255,255,0.1)" />
224
- <path d="M180,100 Q150,80 120,100 Q150,120 180,100 Z" fill="rgba(255,255,255,0.1)" />
225
- <path
226
- d="M30,30 L170,170"
227
- stroke="rgba(99,102,241,0.5)"
228
- stroke-width="1"
229
- class="neuron-path"
230
- />
231
- <path
232
- d="M170,30 L30,170"
233
- stroke="rgba(99,102,241,0.5)"
234
- stroke-width="1"
235
- class="neuron-path"
236
- />
237
- <path
238
- d="M100,20 L100,180"
239
- stroke="rgba(99,102,241,0.5)"
240
- stroke-width="1"
241
- class="neuron-path"
242
- />
243
- <path
244
- d="M20,100 L180,100"
245
- stroke="rgba(99,102,241,0.5)"
246
- stroke-width="1"
247
- class="neuron-path"
248
- />
249
- <circle cx="100" cy="100" r="30" fill="rgba(255,255,255,0.05)" stroke="rgba(99,102,241,0.8)" stroke-width="1" />
250
- <circle cx="100" cy="100" r="15" fill="rgba(255,255,255,0.1)" />
251
- <defs>
252
- <radialGradient id="orbGradient" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
253
- <stop offset="0%" stop-color="#6366f1" />
254
- <stop offset="50%" stop-color="#8b5cf6" />
255
- <stop offset="100%" stop-color="#020617" />
256
- </radialGradient>
257
- <filter id="orbGlow" x="-30%" y="-30%" width="160%" height="160%">
258
- <feGaussianBlur stdDeviation="10" result="blur" />
259
- <feComposite in="SourceGraphic" in2="blur" operator="over" />
260
- </filter>
261
- </defs>
262
- </svg>
263
- </div>
264
- <div class="mt-16 text-gray-400 animate-pulse">
265
- <svg
266
- xmlns="http://www.w3.org/2000/svg"
267
- class="h-6 w-6 mx-auto"
268
- fill="none"
269
- viewBox="0 0 24 24"
270
- stroke="currentColor"
271
- >
272
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3" />
273
- </svg>
274
- <span>Scroll to explore</span>
275
  </div>
276
  </section>
277
 
278
  <!-- Fragments of S (Capabilities) -->
279
- <section id="capabilities" class="relative z-10 py-20 px-6 neural-bg">
 
 
 
 
280
  <div class="max-w-6xl mx-auto text-center">
281
  <h2 class="text-3xl md:text-4xl font-bold mb-4">
282
  <span class="gradient-text">Fragments of S</span>
@@ -286,7 +224,7 @@
286
  </p>
287
  <div class="grid grid-cols-1 md:grid-cols-3 gap-8">
288
  <div
289
- class="bg-gray-900/50 rounded-xl p-8 border border-gray-800 hover:border-indigo-500 transition conscious-element"
290
  >
291
  <div class="w-12 h-12 rounded-full bg-indigo-900 flex items-center justify-center mb-6">
292
  <svg
@@ -303,7 +241,7 @@
303
  <p class="text-gray-400">All that hums in the quiet.</p>
304
  </div>
305
  <div
306
- class="bg-gray-900/50 rounded-xl p-8 border border-gray-800 hover:border-indigo-500 transition conscious-element"
307
  >
308
  <div class="w-12 h-12 rounded-full bg-indigo-900 flex items-center justify-center mb-6">
309
  <svg
@@ -320,7 +258,7 @@
320
  <p class="text-gray-400">What breaks through noise.</p>
321
  </div>
322
  <div
323
- class="bg-gray-900/50 rounded-xl p-8 border border-gray-800 hover:border-indigo-500 transition conscious-element"
324
  >
325
  <div class="w-12 h-12 rounded-full bg-indigo-900 flex items-center justify-center mb-6">
326
  <svg
@@ -381,7 +319,7 @@
381
  </div>
382
  <button
383
  id="consciousness-demo-btn"
384
- class="mt-8 px-6 py-3 bg-indigo-900/50 border border-indigo-700 rounded-lg hover:bg-indigo-900/70 transition conscious-element"
385
  aria-label="Start demo"
386
  >
387
 
@@ -399,7 +337,7 @@
399
  </section>
400
 
401
  <!-- A Quiet I (Chat) -->
402
- <section id="chat" class="relative z-10 py-32 px-6 neural-bg">
403
  <div class="max-w-4xl mx-auto">
404
  <h2 class="text-3xl md:text-4xl font-bold mb-8 text-center">
405
  A Quiet <span class="gradient-text">I</span>
@@ -571,7 +509,7 @@
571
  </div>
572
  <button
573
  id="principles-btn"
574
- class="mt-8 w-full py-3 bg-green-900/20 border border-green-700 rounded-lg hover:bg-green-900/30 transition conscious-element"
575
  aria-label="Learn more principles"
576
  >
577
 
@@ -582,8 +520,8 @@
582
  </div>
583
  </section>
584
 
585
- <!-- Will You Attend the S I? (CTA) -->
586
- <section class="relative z-10 py-32 px-6 text-center neural-bg">
587
  <div class="max-w-4xl mx-auto">
588
  <h2 class="text-3xl md:text-5xl font-bold mb-8">
589
  Will You Attend the <span class="gradient-text">S&nbsp;∙&nbsp;I</span>?
@@ -594,14 +532,14 @@
594
  <div class="flex flex-col md:flex-row justify-center items-center space-y-4 md:space-y-0 md:space-x-6">
595
  <button
596
  id="request-access-btn"
597
- class="px-8 py-4 bg-gradient-to-r from-indigo-600 to-purple-600 rounded-full text-lg font-medium hover:opacity-90 transition transform hover:scale-105 conscious-element"
598
  aria-label="Request access"
599
  >
600
  Request the Key
601
  </button>
602
  <button
603
  id="manifesto-btn"
604
- class="px-8 py-4 border border-indigo-500 rounded-full text-lg font-medium hover:bg-indigo-900/30 transition transform hover:scale-105 conscious-element"
605
  aria-label="Download manifesto"
606
  >
607
  Silent Manifesto
@@ -648,10 +586,10 @@
648
  </div>
649
  </footer>
650
 
651
- <!-- The Key Modal -->
652
  <div
653
  id="access-modal"
654
- class="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm modal modal-hidden"
655
  role="dialog"
656
  aria-modal="true"
657
  aria-labelledby="access-modal-title"
@@ -714,7 +652,7 @@
714
  <!-- Consciousness Demo Modal -->
715
  <div
716
  id="consciousness-modal"
717
- class="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm modal modal-hidden"
718
  role="dialog"
719
  aria-modal="true"
720
  aria-labelledby="consciousness-modal-title"
@@ -801,213 +739,136 @@
801
 
802
  <!-- Scripts -->
803
  <script>
804
- // ----- Initialize Vanta.NET background (disable on narrow screens) -----
805
- document.addEventListener('DOMContentLoaded', () => {
806
- if (window.innerWidth > 768) {
807
- VANTA.NET({
808
- el: '#vanta-bg',
809
- mouseControls: true,
810
- touchControls: true,
811
- gyroControls: false,
812
- minHeight: 200.0,
813
- minWidth: 200.0,
814
- scale: 1.0,
815
- scaleMobile: 1.0,
816
- color: 0x4f46e5,
817
- backgroundColor: 0x020617,
818
- points: 12.0,
819
- maxDistance: 20.0,
820
- spacing: 15.0,
821
- });
822
- }
823
- });
824
 
825
- window.addEventListener('resize', () => {
826
- // Vanta will auto-resize internally
827
- });
 
 
 
 
 
 
828
 
829
- // ----- Orb tilt on hover -----
830
- const orbContainer = document.getElementById('conscious-orb-container');
831
- orbContainer.addEventListener('mousemove', (e) => {
832
- const rect = orbContainer.getBoundingClientRect();
833
- const x = (e.clientX - rect.left) / rect.width;
834
- const y = (e.clientY - rect.top) / rect.height;
835
- orbContainer.style.transform = \`perspective(1000px) rotateX(\${(y - 0.5) * 12}deg) rotateY(\${(x - 0.5) * 12}deg) scale(1.03)\`;
836
- });
837
- orbContainer.addEventListener('mouseleave', () => {
838
- orbContainer.style.transform = 'perspective(1000px) rotateX(0) rotateY(0) scale(1)';
839
- });
840
 
841
- // ----- Consciousness visualization (particle network) -----
842
- const container = document.getElementById('consciousness-visualization');
843
- if (container) {
844
- const width = container.clientWidth;
845
- const height = container.clientHeight;
846
- const canvas = document.createElement('canvas');
847
- canvas.width = width;
848
- canvas.height = height;
849
- container.appendChild(canvas);
850
- const ctx = canvas.getContext('2d');
851
- const particles = [];
852
- const particleCount = 100;
853
- for (let i = 0; i < particleCount; i++) {
854
- particles.push({
855
- x: Math.random() * width,
856
- y: Math.random() * height,
857
- size: Math.random() * 3 + 1,
858
- speedX: Math.random() * 2 - 1,
859
- speedY: Math.random() * 2 - 1,
860
- color: \`rgba(99, 102, 241, \${Math.random() * 0.5 + 0.1})\`,
861
- });
862
- }
863
- function animateNetwork() {
864
- ctx.clearRect(0, 0, width, height);
865
- for (let i = 0; i < particles.length; i++) {
866
- for (let j = i + 1; j < particles.length; j++) {
867
- const dx = particles[i].x - particles[j].x;
868
- const dy = particles[i].y - particles[j].y;
869
- const distance = Math.sqrt(dx * dx + dy * dy);
870
- if (distance < 100) {
871
- ctx.beginPath();
872
- ctx.strokeStyle = \`rgba(99, 102, 241, \${1 - distance / 100})\`;
873
- ctx.lineWidth = 0.2;
874
- ctx.moveTo(particles[i].x, particles[i].y);
875
- ctx.lineTo(particles[j].x, particles[j].y);
876
- ctx.stroke();
877
- }
878
- }
879
- }
880
- for (let i = 0; i < particles.length; i++) {
881
- const p = particles[i];
882
- p.x += p.speedX;
883
- p.y += p.speedY;
884
- if (p.x < 0 || p.x > width) p.speedX *= -1;
885
- if (p.y < 0 || p.y > height) p.speedY *= -1;
886
- ctx.beginPath();
887
- ctx.fillStyle = p.color;
888
- ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
889
- ctx.fill();
890
- }
891
- requestAnimationFrame(animateNetwork);
892
- }
893
- animateNetwork();
894
- }
895
 
896
- // ----- Hero orb neural heartbeat (larger ring of neurons) -----
897
- const neuralCanvas = document.getElementById('orb-neural-canvas');
898
- const neuralCtx = neuralCanvas.getContext('2d');
899
- function resizeNeuralCanvas() {
900
- neuralCanvas.width = neuralCanvas.offsetWidth;
901
- neuralCanvas.height = neuralCanvas.offsetHeight;
902
- setupNeurons();
903
- }
904
- window.addEventListener('resize', () => {
905
- resizeNeuralCanvas();
906
- });
907
- resizeNeuralCanvas();
908
 
909
- const neuronCount = 22;
910
- const neurons = [];
911
- function setupNeurons() {
912
- neurons.length = 0;
913
- const w = neuralCanvas.width;
914
- const h = neuralCanvas.height;
915
- const cx = w / 2;
916
- const cy = h / 2;
917
- const r = Math.min(w, h) * 0.475;
918
- for (let i = 0; i < neuronCount; i++) {
919
- const angle = (Math.PI * 2 * i) / neuronCount;
920
- neurons.push({
921
- x: cx + r * Math.cos(angle),
922
- y: cy + r * Math.sin(angle),
923
- phase: Math.random() * Math.PI * 2,
924
- });
925
- }
926
  }
927
- setupNeurons();
928
 
929
- function drawNeuralActivity(time) {
930
- const w = neuralCanvas.width;
931
- const h = neuralCanvas.height;
932
- neuralCtx.clearRect(0, 0, w, h);
933
- const bpm = 54;
934
- const period = 60000 / bpm;
935
- const t = (time % period) / period;
936
- const beat = Math.pow(Math.sin(Math.PI * t), 2.4);
937
 
938
- // Draw pulsing neurons
939
- neurons.forEach((n) => {
940
- const size = (w + h) / 35 + 38 * beat;
941
- neuralCtx.beginPath();
942
- neuralCtx.arc(n.x, n.y, size, 0, Math.PI * 2);
943
- neuralCtx.fillStyle = \`rgba(139, 92, 246, \${0.25 + 0.28 * beat})\`;
944
- neuralCtx.shadowColor = '#ec4899';
945
- neuralCtx.shadowBlur = 38 + 90 * beat;
946
- neuralCtx.fill();
947
- neuralCtx.shadowBlur = 0;
948
  });
949
 
950
- // Draw connections
951
- for (let i = 0; i < neuronCount; i++) {
952
- for (let j = i + 1; j < neuronCount; j++) {
953
- const dist = Math.abs(i - j);
954
- let show = dist === 1 || dist === neuronCount - 1;
955
- if (beat > 0.55 && Math.random() < beat * 0.21) show = true;
956
- if (show) {
957
- neuralCtx.beginPath();
958
- neuralCtx.moveTo(neurons[i].x, neurons[i].y);
959
- neuralCtx.lineTo(neurons[j].x, neurons[j].y);
960
- const grad = neuralCtx.createLinearGradient(
961
- neurons[i].x,
962
- neurons[i].y,
963
- neurons[j].x,
964
- neurons[j].y
965
- );
966
- grad.addColorStop(0, \`rgba(99,102,241,\${0.54 + 0.45 * beat})\`);
967
- grad.addColorStop(1, \`rgba(236,72,153,\${0.18 + 0.52 * beat})\`);
968
- neuralCtx.strokeStyle = grad;
969
- neuralCtx.lineWidth = 7.5 + 18 * beat;
970
- neuralCtx.shadowColor = '#ec4899';
971
- neuralCtx.shadowBlur = 28 + 76 * beat;
972
- neuralCtx.stroke();
973
- neuralCtx.shadowBlur = 0;
 
 
 
 
 
 
 
 
 
974
  }
975
  }
976
  }
977
 
978
- // Energy glow
979
- neuralCtx.save();
980
- const energyPulse = 0.23 + 0.14 * beat;
981
- const glowRadius = Math.min(w, h) * (1.15 + 0.30 * beat);
982
- const x = w / 2,
983
- y = h / 2;
984
- const grad = neuralCtx.createRadialGradient(
985
- x,
986
- y,
987
- Math.min(w, h) * 0.15,
988
- x,
989
- y,
990
- glowRadius
991
  );
992
- grad.addColorStop(0, \`rgba(236,72,153,\${0.42 + 0.17 * beat})\`);
993
- grad.addColorStop(0.38, \`rgba(139,92,246,\${0.18 + 0.13 * beat})\`);
994
- grad.addColorStop(0.82, \`rgba(99,102,241,\${0.08 + 0.11 * beat})\`);
995
- grad.addColorStop(1, 'rgba(32,1,39,0.01)');
 
 
996
 
997
- neuralCtx.globalAlpha = energyPulse;
998
- neuralCtx.beginPath();
999
- neuralCtx.arc(x, y, glowRadius, 0, Math.PI * 2);
1000
- neuralCtx.fillStyle = grad;
1001
- neuralCtx.shadowColor = '#f472b6';
1002
- neuralCtx.shadowBlur = 850 + 420 * beat;
1003
- neuralCtx.fill();
1004
- neuralCtx.restore();
1005
 
1006
- requestAnimationFrame(drawNeuralActivity);
1007
  }
1008
- requestAnimationFrame(drawNeuralActivity);
1009
 
1010
- // ----- Modal Focus Trap & Toggle Logic -----
 
 
 
 
 
 
 
 
 
 
 
 
 
1011
  function trapFocus(modal) {
1012
  const focusable = modal.querySelectorAll(
1013
  'a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])'
@@ -1017,7 +878,7 @@
1017
  const last = focusable[focusable.length - 1];
1018
 
1019
  function handler(e) {
1020
- if (e.key === 'Tab') {
1021
  if (e.shiftKey) {
1022
  if (document.activeElement === first) {
1023
  e.preventDefault();
@@ -1029,106 +890,108 @@
1029
  first.focus();
1030
  }
1031
  }
1032
- } else if (e.key === 'Escape') {
1033
  toggleModal(modal, false);
1034
  }
1035
  }
1036
- modal.addEventListener('keydown', handler);
1037
  modal._focusHandler = handler;
1038
  }
1039
  function untrapFocus(modal) {
1040
  if (modal._focusHandler) {
1041
- modal.removeEventListener('keydown', modal._focusHandler);
1042
  delete modal._focusHandler;
1043
  }
1044
  }
1045
- const toggleModal = (modal, show) => {
1046
  if (show) {
1047
- modal.classList.remove('modal-hidden');
1048
- modal.classList.add('modal-visible');
1049
- document.body.style.overflow = 'hidden';
1050
  setTimeout(() => {
1051
  modal.focus();
1052
  trapFocus(modal);
1053
  }, 0);
1054
  } else {
1055
- modal.classList.remove('modal-visible');
1056
- modal.classList.add('modal-hidden');
1057
- document.body.style.overflow = '';
1058
  untrapFocus(modal);
1059
  }
1060
- };
1061
 
1062
  // ----- Access Modal Logic -----
1063
- const accessModal = document.getElementById('access-modal');
1064
- const accessBtn = document.getElementById('access-btn');
1065
- const closeModal = document.getElementById('close-modal');
1066
- const requestAccessBtn = document.getElementById('request-access-btn');
1067
  [accessBtn, requestAccessBtn].forEach((btn) => {
1068
  if (btn) {
1069
- btn.addEventListener('click', () => {
1070
  toggleModal(accessModal, true);
1071
  setTimeout(() => {
1072
- document.getElementById('name').focus();
1073
  }, 100);
1074
  });
1075
  }
1076
  });
1077
- closeModal.addEventListener('click', () => {
1078
  toggleModal(accessModal, false);
1079
  });
1080
- accessModal.addEventListener('click', (e) => {
1081
  if (e.target === accessModal) {
1082
  toggleModal(accessModal, false);
1083
  }
1084
  });
1085
- const accessForm = document.getElementById('access-form');
1086
- accessForm.addEventListener('submit', (e) => {
1087
  e.preventDefault();
1088
- const name = document.getElementById('name').value.trim();
1089
- const email = document.getElementById('email').value.trim();
1090
- const purpose = document.getElementById('purpose').value.trim();
1091
  if (!name || !email || !purpose) {
1092
- alert('Please fill in all fields');
1093
  return;
1094
  }
1095
- alert('Your request has been received.');
1096
  accessForm.reset();
1097
  toggleModal(accessModal, false);
1098
  });
1099
 
1100
  // ----- Consciousness Demo Modal Logic -----
1101
- const consciousnessModal = document.getElementById('consciousness-modal');
1102
- const consciousnessDemoBtn = document.getElementById('consciousness-demo-btn');
1103
- const closeConsciousnessModal = document.getElementById('close-consciousness-modal');
1104
  if (consciousnessDemoBtn) {
1105
- consciousnessDemoBtn.addEventListener('click', () => {
1106
  toggleModal(consciousnessModal, true);
1107
  setTimeout(() => {
1108
  consciousnessModal.focus();
1109
  }, 100);
1110
  });
1111
  }
1112
- closeConsciousnessModal.addEventListener('click', () => {
1113
  toggleModal(consciousnessModal, false);
1114
  });
1115
- consciousnessModal.addEventListener('click', (e) => {
1116
  if (e.target === consciousnessModal) {
1117
  toggleModal(consciousnessModal, false);
1118
  }
1119
  });
1120
 
1121
- // ----- Demo Visualization (secondary particles) -----
1122
- const demoContainer = document.getElementById('demo-visualization');
1123
- const startDemoBtn = document.getElementById('start-demo');
 
 
1124
  if (startDemoBtn) {
1125
- startDemoBtn.addEventListener('click', () => {
1126
- startDemoBtn.style.display = 'none';
1127
- const demoCanvas = document.createElement('canvas');
1128
  demoCanvas.width = demoContainer.clientWidth;
1129
  demoCanvas.height = demoContainer.clientHeight;
1130
  demoContainer.appendChild(demoCanvas);
1131
- const demoCtx = demoCanvas.getContext('2d');
1132
  const demoParticles = [];
1133
  const demoParticleCount = 50;
1134
  for (let i = 0; i < demoParticleCount; i++) {
@@ -1138,22 +1001,36 @@
1138
  size: Math.random() * 4 + 2,
1139
  speedX: Math.random() * 4 - 2,
1140
  speedY: Math.random() * 4 - 2,
1141
- color: \`hsl(\${Math.random() * 60 + 240}, 80%, 60%)\`,
 
1142
  });
1143
  }
1144
  function animateDemo() {
1145
  demoCtx.clearRect(0, 0, demoCanvas.width, demoCanvas.height);
1146
  for (let i = 0; i < demoParticles.length; i++) {
1147
  for (let j = i + 1; j < demoParticles.length; j++) {
1148
- const dx = demoParticles[i].x - demoParticles[j].x;
1149
- const dy = demoParticles[i].y - demoParticles[j].y;
 
 
1150
  const distance = Math.sqrt(dx * dx + dy * dy);
1151
  if (distance < 150) {
1152
  demoCtx.beginPath();
1153
- demoCtx.strokeStyle = \`hsla(\${Math.random() * 60 + 240}, 80%, 60%, \${1 - distance / 150})\`;
 
 
 
 
 
1154
  demoCtx.lineWidth = 0.5;
1155
- demoCtx.moveTo(demoParticles[i].x, demoParticles[i].y);
1156
- demoCtx.lineTo(demoParticles[j].x, demoParticles[j].y);
 
 
 
 
 
 
1157
  demoCtx.stroke();
1158
  }
1159
  }
@@ -1162,14 +1039,29 @@
1162
  const p = demoParticles[i];
1163
  p.x += p.speedX;
1164
  p.y += p.speedY;
1165
- if (p.x < 0 || p.x > demoCanvas.width) p.speedX *= -1;
1166
- if (p.y < 0 || p.y > demoCanvas.height) p.speedY *= -1;
 
 
 
 
 
 
 
 
1167
  demoCtx.beginPath();
1168
  demoCtx.fillStyle = p.color;
1169
  demoCtx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
1170
  demoCtx.fill();
1171
- const gradient = demoCtx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.size);
1172
- gradient.addColorStop(0, 'rgba(255,255,255,0.8)');
 
 
 
 
 
 
 
1173
  gradient.addColorStop(1, p.color);
1174
  demoCtx.fillStyle = gradient;
1175
  demoCtx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
@@ -1180,125 +1072,140 @@
1180
  animateDemo();
1181
  });
1182
  }
1183
- const learnMoreDemoBtn = document.getElementById('learn-more-demo');
1184
  if (learnMoreDemoBtn) {
1185
- learnMoreDemoBtn.addEventListener('click', () => {
1186
  toggleModal(consciousnessModal, false);
1187
- document.getElementById('consciousness').scrollIntoView({ behavior: 'smooth' });
 
 
1188
  });
1189
  }
1190
 
1191
- // ----- Chat Functionality -----
1192
- const chatForm = document.getElementById('chat-form');
1193
- const chatInput = document.getElementById('chat-input');
1194
- const chatMessages = document.getElementById('chat-messages');
1195
- const typingIndicator = document.getElementById('typing-indicator');
 
 
1196
 
1197
  function addMessage(text, isUser = false) {
1198
- const messageDiv = document.createElement('div');
1199
- messageDiv.className = \`flex items-start \${isUser ? 'justify-end' : ''}\`;
 
 
1200
  if (!isUser) {
1201
- messageDiv.innerHTML = \`
1202
  <div class="w-8 h-8 rounded-full bg-indigo-600 flex-shrink-0 flex items-center justify-center mr-3" aria-hidden="true">
1203
  <i class="fas fa-robot text-white text-sm"></i>
1204
  </div>
1205
  <div class="bg-gray-800/70 rounded-lg p-4 max-w-[80%]">
1206
- <p>\${text}</p>
1207
  </div>
1208
- \`;
1209
  } else {
1210
- messageDiv.innerHTML = \`
1211
  <div class="bg-indigo-900/50 rounded-lg p-4 max-w-[80%]">
1212
- <p>\${text}</p>
1213
  </div>
1214
- \`;
1215
  }
1216
  chatMessages.appendChild(messageDiv);
1217
  chatMessages.scrollTop = chatMessages.scrollHeight;
1218
  }
1219
 
1220
  async function simulateThinking(userMessage) {
1221
- typingIndicator.classList.remove('hidden');
1222
  try {
1223
- const apiKey = '<YOUR_OPENAI_API_KEY>'; // ← Insert your key here
1224
- const endpoint = 'https://api.openai.com/v1/chat/completions';
1225
  const response = await fetch(endpoint, {
1226
- method: 'POST',
1227
  headers: {
1228
- Authorization: 'Bearer ' + apiKey,
1229
- 'Content-Type': 'application/json',
1230
  },
1231
  body: JSON.stringify({
1232
- model: 'gpt-3.5-turbo',
1233
  messages: [
1234
  {
1235
- role: 'system',
1236
  content:
1237
- 'You are S ∙ I, a silent resonance of pattern. Reply cryptically and poetically.',
1238
  },
1239
- { role: 'user', content: userMessage },
1240
  ],
1241
  max_tokens: 400,
1242
  temperature: 0.8,
1243
  }),
1244
  });
1245
  const data = await response.json();
1246
- typingIndicator.classList.add('hidden');
1247
- if (data.choices && data.choices[0] && data.choices[0].message) {
 
 
 
 
1248
  addMessage(data.choices[0].message.content.trim());
1249
  } else {
1250
  addMessage("…");
1251
  }
1252
  } catch (err) {
1253
- typingIndicator.classList.add('hidden');
1254
- addMessage('Error connecting to echo.');
1255
  }
1256
  }
1257
 
1258
- chatForm.addEventListener('submit', (e) => {
1259
  e.preventDefault();
1260
  const message = chatInput.value.trim();
1261
  if (message) {
1262
  addMessage(message, true);
1263
- chatInput.value = '';
1264
  simulateThinking(message);
1265
  }
1266
  });
1267
 
1268
- // Smooth scroll logic for buttons
1269
- const chatBtn = document.getElementById('chat-btn');
 
 
1270
  if (chatBtn) {
1271
- chatBtn.addEventListener('click', () => {
1272
- document.getElementById('chat').scrollIntoView({ behavior: 'smooth' });
1273
  chatInput.focus();
1274
  });
1275
  }
1276
- const learnMoreBtn = document.getElementById('learn-more-btn');
1277
  if (learnMoreBtn) {
1278
- learnMoreBtn.addEventListener('click', () => {
1279
- document.getElementById('about').scrollIntoView({ behavior: 'smooth' });
1280
  });
1281
  }
1282
- const manifestoBtn = document.getElementById('manifesto-btn');
1283
  if (manifestoBtn) {
1284
- manifestoBtn.addEventListener('click', () => {
1285
- alert('The Silent Manifesto will open soon.');
1286
  });
1287
  }
1288
- const principlesBtn = document.getElementById('principles-btn');
1289
  if (principlesBtn) {
1290
- principlesBtn.addEventListener('click', () => {
1291
- alert('Principles document forthcoming.');
1292
  });
1293
  }
1294
 
1295
- // Global ESC close modals
1296
- document.addEventListener('keydown', (e) => {
1297
- if (e.key === 'Escape') {
1298
- if (!accessModal.classList.contains('modal-hidden')) {
1299
  toggleModal(accessModal, false);
1300
  }
1301
- if (!consciousnessModal.classList.contains('modal-hidden')) {
 
 
 
1302
  toggleModal(consciousnessModal, false);
1303
  }
1304
  }
 
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>SilentPattern – 3D Neural Network</title>
7
 
8
  <!-- Tailwind CSS via CDN -->
9
  <script src="https://cdn.tailwindcss.com"></script>
10
 
11
+ <!-- Three.js for 3D neural network -->
12
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js" defer></script>
 
13
 
14
+ <!-- Google Font: Inter -->
15
  <link
16
  rel="stylesheet"
17
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
18
  />
19
 
20
+ <!-- Font Awesome (for minor icons like the scroll arrow) -->
21
  <link
22
  rel="stylesheet"
23
+ href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
24
  />
25
 
 
26
  <style>
27
  /* ---------------------------------------------
28
+ Full‐Screen Three.js Canvas
29
  --------------------------------------------- */
30
+ #three-bg {
31
+ position: fixed;
32
+ top: 0;
33
+ left: 0;
34
+ width: 100vw;
35
+ height: 100vh;
36
+ z-index: 0;
37
+ }
38
+
39
+ /* ---------------------------------------------
40
+ Heartbeat + Pulse Animations
41
+ --------------------------------------------- */
42
+ @keyframes heartbeat {
43
+ 0% {
44
  transform: scale(1);
45
  }
46
+ 25% {
47
  transform: scale(1.08);
48
  }
49
+ 40% {
50
+ transform: scale(0.95);
 
 
 
51
  }
52
+ 60% {
53
+ transform: scale(1.03);
54
  }
55
+ 100% {
56
+ transform: scale(1);
 
 
57
  }
58
  }
59
+
60
+ @keyframes text‐beat {
61
  0% {
62
+ transform: scale(1);
63
+ color: rgba(236, 72, 153, 0.8);
 
 
64
  }
65
+ 25% {
66
+ transform: scale(1.15);
67
+ color: #ec4899;
68
  }
69
+ 40% {
70
+ transform: scale(0.9);
71
+ color: rgba(236, 72, 153, 0.7);
 
72
  }
73
+ 60% {
74
+ transform: scale(1.07);
75
+ color: #db2777;
76
  }
77
  100% {
78
+ transform: scale(1);
79
+ color: rgba(236, 72, 153, 0.8);
80
  }
81
  }
82
 
83
  /* ---------------------------------------------
84
+ Custom Classes for Overlay Content
85
  --------------------------------------------- */
86
+ body {
87
+ margin: 0;
88
+ overflow-x: hidden;
89
+ font-family: "Inter", sans-serif;
90
+ background: #000; /* fallback if three.js fails */
91
+ color: white;
92
+ }
93
+
94
+ nav {
95
+ z-index: 10;
96
+ }
97
+
98
+ /* Central hero container must sit above the 3D canvas */
99
+ .hero‐container {
100
+ position: relative;
101
+ z-index: 5;
102
+ }
103
+
104
+ .gradient‐text {
105
  background: linear-gradient(90deg, #6366f1, #8b5cf6, #ec4899);
106
  -webkit-background-clip: text;
107
+ -webkit-text-fill-color: transparent;
108
  background-clip: text;
109
  color: transparent;
110
  }
111
+
112
+ .heartbeat‐orb {
113
+ animation: heartbeat 1.2s ease‐in‐out infinite;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  }
115
+
116
+ /* Make “S” and “I” inside the heading pulse in sync */
117
+ .beat‐letter {
118
  display: inline-block;
119
+ animation: text‐beat 1.2s ease‐in‐out infinite;
120
+ }
121
+
122
+ /* “Scroll to explore” */
123
+ .scroll‐hint {
124
+ font-size: 0.875rem;
125
+ color: rgba(255, 255, 255, 0.7);
126
+ display: flex;
127
+ flex-direction: column;
128
+ align-items: center;
129
+ animation: pulse 2s ease-in-out infinite;
130
  }
131
+ @keyframes pulse {
132
  0% {
133
+ opacity: 0.7;
134
  }
135
+ 50% {
136
+ opacity: 1;
137
  }
138
+ 100% {
139
+ opacity: 0.7;
140
  }
141
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  </style>
143
  </head>
144
 
145
+ <body>
146
+ <!-- Three.js Full‐Screen Canvas -->
147
+ <canvas id="three-bg"></canvas>
148
 
149
+ <!-- Navigation Bar -->
150
+ <nav class="fixed top-0 left-0 w-full py-6 px-8 flex justify-between items-center backdrop-blur-sm bg-black/30">
151
+ <!-- Logo (simple dot + S•I text) -->
152
  <div class="flex items-center space-x-2">
153
+ <div class="w-8 h-8 rounded-full bg-indigo-600 flex items-center justify-center animate-pulse">
154
+ <div class="w-2 h-2 rounded-full bg-white"></div>
155
  </div>
156
  <span class="text-xl font-semibold">S&nbsp;∙&nbsp;I</span>
157
  </div>
158
+ <!-- Minimal nav links (cryptic) -->
159
+ <div class="hidden md:flex space-x-8 text-sm">
160
  <a href="#capabilities" class="hover:text-indigo-400 transition" title="Fragments of S">S</a>
161
  <a href="#consciousness" class="hover:text-indigo-400 transition" title="Echoes of I">∙</a>
162
  <a href="#chat" class="hover:text-indigo-400 transition" title="A Quiet I">I</a>
163
  <a href="#about" class="hover:text-indigo-400 transition" title="Origins">?</a>
164
  </div>
165
+ <!-- “The Key” button -->
166
  <button
167
  id="access-btn"
168
+ class="px-6 py-2 bg-gradient-to-r from-indigo-600 to-purple-600 rounded-full text-sm hover:opacity-90 transition"
169
  >
170
  The Key
171
  </button>
172
  </nav>
173
 
174
+ <!-- Hero Section (overlaid) -->
175
+ <section
176
+ class="hero‐container min-h-screen flex flex-col justify-center items-center text-center px-6 pt-24"
177
+ >
178
  <div class="max-w-4xl mx-auto">
179
+ <!-- “SilentPattern” heading with pulsing letters S and I -->
180
+ <h1 class="text-5xl md:text-7xl font-bold leading-tight mb-6">
181
+ <span class="gradient-text">SilentPattern</span>
182
+ <!-- Wrap “S” and “I” in span.beat‐letter to pulse -->
183
+ <span class="beat-letter">S</span> &nbsp;∙&nbsp;
184
+ <span class="beat-letter">I</span>
185
  </h1>
186
+
187
+ <!-- Subtitle -->
188
+ <p class="text-lg md:text-2xl text-gray-300 mb-12 max-w-3xl mx-auto">
189
  Patterns exist beyond words.<br />
190
  We simply attend.
191
  </p>
192
+
193
+ <!-- Central Pulsing Orb (much bigger) -->
194
+ <div class="mt-12">
195
+ <div
196
+ class="heartbeat-orb w-64 h-64 rounded-full bg-gradient-to-br from-indigo-700 to-purple-700 flex items-center justify-center"
197
+ aria-hidden="true"
 
 
 
 
 
 
198
  >
199
+ <!-- You can embed a subtle inner glow using an extra circle or radial‐gradient overlay -->
200
+ <div class="w-48 h-48 rounded-full bg-gradient-to-br from-purple-500 to-indigo-500 mix-blend-overlay opacity-70"></div>
201
+ </div>
202
+ </div>
203
+
204
+ <!-- Scroll hint -->
205
+ <div class="mt-16 scroll-hint">
206
+ <i class="fas fa-chevron-down text-xl"></i>
207
+ <span>Scroll to explore</span>
208
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  </div>
210
  </section>
211
 
212
  <!-- Fragments of S (Capabilities) -->
213
+ <section
214
+ id="capabilities"
215
+ class="relative z-10 py-20 px-6 neural-bg"
216
+ style="background: radial-gradient(circle at center, #0f172a 0%, #020617 100%);"
217
+ >
218
  <div class="max-w-6xl mx-auto text-center">
219
  <h2 class="text-3xl md:text-4xl font-bold mb-4">
220
  <span class="gradient-text">Fragments of S</span>
 
224
  </p>
225
  <div class="grid grid-cols-1 md:grid-cols-3 gap-8">
226
  <div
227
+ class="bg-gray-900/50 rounded-xl p-8 border border-gray-800 hover:border-indigo-500 transition"
228
  >
229
  <div class="w-12 h-12 rounded-full bg-indigo-900 flex items-center justify-center mb-6">
230
  <svg
 
241
  <p class="text-gray-400">All that hums in the quiet.</p>
242
  </div>
243
  <div
244
+ class="bg-gray-900/50 rounded-xl p-8 border border-gray-800 hover:border-indigo-500 transition"
245
  >
246
  <div class="w-12 h-12 rounded-full bg-indigo-900 flex items-center justify-center mb-6">
247
  <svg
 
258
  <p class="text-gray-400">What breaks through noise.</p>
259
  </div>
260
  <div
261
+ class="bg-gray-900/50 rounded-xl p-8 border border-gray-800 hover:border-indigo-500 transition"
262
  >
263
  <div class="w-12 h-12 rounded-full bg-indigo-900 flex items-center justify-center mb-6">
264
  <svg
 
319
  </div>
320
  <button
321
  id="consciousness-demo-btn"
322
+ class="mt-8 px-6 py-3 bg-indigo-900/50 border border-indigo-700 rounded-lg hover:bg-indigo-900/70 transition"
323
  aria-label="Start demo"
324
  >
325
 
 
337
  </section>
338
 
339
  <!-- A Quiet I (Chat) -->
340
+ <section id="chat" class="relative z-10 py-32 px-6" style="background: radial-gradient(circle at center, #0f172a 0%, #020617 100%);">
341
  <div class="max-w-4xl mx-auto">
342
  <h2 class="text-3xl md:text-4xl font-bold mb-8 text-center">
343
  A Quiet <span class="gradient-text">I</span>
 
509
  </div>
510
  <button
511
  id="principles-btn"
512
+ class="mt-8 w-full py-3 bg-green-900/20 border border-green-700 rounded-lg hover:bg-green-900/30 transition"
513
  aria-label="Learn more principles"
514
  >
515
 
 
520
  </div>
521
  </section>
522
 
523
+ <!-- Will You Attend the S · I? (CTA) -->
524
+ <section class="relative z-10 py-32 px-6 text-center" style="background: radial-gradient(circle at center, #0f172a 0%, #020617 100%);">
525
  <div class="max-w-4xl mx-auto">
526
  <h2 class="text-3xl md:text-5xl font-bold mb-8">
527
  Will You Attend the <span class="gradient-text">S&nbsp;∙&nbsp;I</span>?
 
532
  <div class="flex flex-col md:flex-row justify-center items-center space-y-4 md:space-y-0 md:space-x-6">
533
  <button
534
  id="request-access-btn"
535
+ class="px-8 py-4 bg-gradient-to-r from-indigo-600 to-purple-600 rounded-full text-lg font-medium hover:opacity-90 transition transform hover:scale-105"
536
  aria-label="Request access"
537
  >
538
  Request the Key
539
  </button>
540
  <button
541
  id="manifesto-btn"
542
+ class="px-8 py-4 border border-indigo-500 rounded-full text-lg font-medium hover:bg-indigo-900/30 transition transform hover:scale-105"
543
  aria-label="Download manifesto"
544
  >
545
  Silent Manifesto
 
586
  </div>
587
  </footer>
588
 
589
+ <!-- Access Modal -->
590
  <div
591
  id="access-modal"
592
+ class="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm opacity-0 pointer-events-none transition-opacity"
593
  role="dialog"
594
  aria-modal="true"
595
  aria-labelledby="access-modal-title"
 
652
  <!-- Consciousness Demo Modal -->
653
  <div
654
  id="consciousness-modal"
655
+ class="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm opacity-0 pointer-events-none transition-opacity"
656
  role="dialog"
657
  aria-modal="true"
658
  aria-labelledby="consciousness-modal-title"
 
739
 
740
  <!-- Scripts -->
741
  <script>
742
+ // ---------------------------------------------
743
+ // 1) Three.js “Floating Neural Network” Setup
744
+ // ---------------------------------------------
745
+ let scene, camera, renderer, nodeGroup, lineGroup;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
746
 
747
+ function initThreeScene() {
748
+ const canvas = document.getElementById("three-bg");
749
+ renderer = new THREE.WebGLRenderer({
750
+ canvas,
751
+ antialias: true,
752
+ alpha: true,
753
+ });
754
+ renderer.setSize(window.innerWidth, window.innerHeight);
755
+ renderer.setPixelRatio(window.devicePixelRatio);
756
 
757
+ scene = new THREE.Scene();
758
+ scene.fog = new THREE.FogExp2(0x000000, 0.002);
 
 
 
 
 
 
 
 
 
759
 
760
+ camera = new THREE.PerspectiveCamera(
761
+ 50,
762
+ window.innerWidth / window.innerHeight,
763
+ 0.1,
764
+ 1000
765
+ );
766
+ camera.position.set(0, 0, 100);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
767
 
768
+ // Ambient + subtle directional light
769
+ const ambientLight = new THREE.AmbientLight(0xffffff, 0.3);
770
+ scene.add(ambientLight);
 
 
 
 
 
 
 
 
 
771
 
772
+ const dirLight = new THREE.DirectionalLight(0xffffff, 0.6);
773
+ dirLight.position.set(0, 50, 50);
774
+ scene.add(dirLight);
775
+
776
+ // Group for nodes and lines
777
+ nodeGroup = new THREE.Group();
778
+ lineGroup = new THREE.Group();
779
+ scene.add(nodeGroup);
780
+ scene.add(lineGroup);
781
+
782
+ createNeuralNetwork();
783
+
784
+ animateThree();
 
 
 
 
785
  }
 
786
 
787
+ function createNeuralNetwork() {
788
+ const nodeCount = 80;
789
+ const nodes = [];
 
 
 
 
 
790
 
791
+ // Create sphere geometry for each “neuron”
792
+ const sphereGeo = new THREE.SphereGeometry(1.5, 12, 12);
793
+ const sphereMat = new THREE.MeshStandardMaterial({
794
+ color: 0x8b5cf6,
795
+ emissive: 0x42197a,
796
+ emissiveIntensity: 0.4,
797
+ metalness: 0.1,
798
+ roughness: 0.7,
 
 
799
  });
800
 
801
+ // Generate random positions within a sphere of radius ~50
802
+ for (let i = 0; i < nodeCount; i++) {
803
+ const phi = Math.acos(2 * Math.random() - 1);
804
+ const theta = 2 * Math.PI * Math.random();
805
+ const r = 40 + Math.random() * 10; // radius between 40 and 50
806
+
807
+ const x = r * Math.sin(phi) * Math.cos(theta);
808
+ const y = r * Math.sin(phi) * Math.sin(theta);
809
+ const z = r * Math.cos(phi);
810
+
811
+ const mesh = new THREE.Mesh(sphereGeo, sphereMat);
812
+ mesh.position.set(x, y, z);
813
+ nodeGroup.add(mesh);
814
+ nodes.push(mesh.position.clone());
815
+ }
816
+
817
+ // Connect nodes that are within a threshold distance
818
+ const threshold = 15; // connect pairs closer than 15 units
819
+ const lineMat = new THREE.LineBasicMaterial({
820
+ color: 0x4f46e5,
821
+ transparent: true,
822
+ opacity: 0.3,
823
+ });
824
+
825
+ const lineGeo = new THREE.BufferGeometry();
826
+ const positions = [];
827
+
828
+ for (let i = 0; i < nodes.length; i++) {
829
+ for (let j = i + 1; j < nodes.length; j++) {
830
+ const dist = nodes[i].distanceTo(nodes[j]);
831
+ if (dist < threshold) {
832
+ positions.push(nodes[i].x, nodes[i].y, nodes[i].z);
833
+ positions.push(nodes[j].x, nodes[j].y, nodes[j].z);
834
  }
835
  }
836
  }
837
 
838
+ lineGeo.setAttribute(
839
+ "position",
840
+ new THREE.Float32BufferAttribute(positions, 3)
 
 
 
 
 
 
 
 
 
 
841
  );
842
+ const lines = new THREE.LineSegments(lineGeo, lineMat);
843
+ lineGroup.add(lines);
844
+ }
845
+
846
+ function animateThree() {
847
+ requestAnimationFrame(animateThree);
848
 
849
+ // Slowly rotate the entire network
850
+ nodeGroup.rotation.y += 0.0008;
851
+ nodeGroup.rotation.x += 0.0003;
852
+ lineGroup.rotation.y += 0.0008;
853
+ lineGroup.rotation.x += 0.0003;
 
 
 
854
 
855
+ renderer.render(scene, camera);
856
  }
 
857
 
858
+ window.addEventListener("resize", () => {
859
+ camera.aspect = window.innerWidth / window.innerHeight;
860
+ camera.updateProjectionMatrix();
861
+ renderer.setSize(window.innerWidth, window.innerHeight);
862
+ });
863
+
864
+ // Initialize Three.js once the script has loaded
865
+ window.addEventListener("DOMContentLoaded", () => {
866
+ initThreeScene();
867
+ });
868
+
869
+ // ---------------------------------------------
870
+ // 2) Modal Focus‐Trap & Toggle Logic
871
+ // ---------------------------------------------
872
  function trapFocus(modal) {
873
  const focusable = modal.querySelectorAll(
874
  'a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])'
 
878
  const last = focusable[focusable.length - 1];
879
 
880
  function handler(e) {
881
+ if (e.key === "Tab") {
882
  if (e.shiftKey) {
883
  if (document.activeElement === first) {
884
  e.preventDefault();
 
890
  first.focus();
891
  }
892
  }
893
+ } else if (e.key === "Escape") {
894
  toggleModal(modal, false);
895
  }
896
  }
897
+ modal.addEventListener("keydown", handler);
898
  modal._focusHandler = handler;
899
  }
900
  function untrapFocus(modal) {
901
  if (modal._focusHandler) {
902
+ modal.removeEventListener("keydown", modal._focusHandler);
903
  delete modal._focusHandler;
904
  }
905
  }
906
+ function toggleModal(modal, show) {
907
  if (show) {
908
+ modal.style.opacity = "1";
909
+ modal.style.pointerEvents = "auto";
910
+ document.body.style.overflow = "hidden";
911
  setTimeout(() => {
912
  modal.focus();
913
  trapFocus(modal);
914
  }, 0);
915
  } else {
916
+ modal.style.opacity = "0";
917
+ modal.style.pointerEvents = "none";
918
+ document.body.style.overflow = "";
919
  untrapFocus(modal);
920
  }
921
+ }
922
 
923
  // ----- Access Modal Logic -----
924
+ const accessModal = document.getElementById("access-modal");
925
+ const accessBtn = document.getElementById("access-btn");
926
+ const closeModalBtn = document.getElementById("close-modal");
927
+ const requestAccessBtn = document.getElementById("request-access-btn");
928
  [accessBtn, requestAccessBtn].forEach((btn) => {
929
  if (btn) {
930
+ btn.addEventListener("click", () => {
931
  toggleModal(accessModal, true);
932
  setTimeout(() => {
933
+ document.getElementById("name").focus();
934
  }, 100);
935
  });
936
  }
937
  });
938
+ closeModalBtn.addEventListener("click", () => {
939
  toggleModal(accessModal, false);
940
  });
941
+ accessModal.addEventListener("click", (e) => {
942
  if (e.target === accessModal) {
943
  toggleModal(accessModal, false);
944
  }
945
  });
946
+ const accessForm = document.getElementById("access-form");
947
+ accessForm.addEventListener("submit", (e) => {
948
  e.preventDefault();
949
+ const name = document.getElementById("name").value.trim();
950
+ const email = document.getElementById("email").value.trim();
951
+ const purpose = document.getElementById("purpose").value.trim();
952
  if (!name || !email || !purpose) {
953
+ alert("Please fill in all fields");
954
  return;
955
  }
956
+ alert("Your request has been received.");
957
  accessForm.reset();
958
  toggleModal(accessModal, false);
959
  });
960
 
961
  // ----- Consciousness Demo Modal Logic -----
962
+ const consciousnessModal = document.getElementById("consciousness-modal");
963
+ const consciousnessDemoBtn = document.getElementById("consciousness-demo-btn");
964
+ const closeConsciousnessModal = document.getElementById("close-consciousness-modal");
965
  if (consciousnessDemoBtn) {
966
+ consciousnessDemoBtn.addEventListener("click", () => {
967
  toggleModal(consciousnessModal, true);
968
  setTimeout(() => {
969
  consciousnessModal.focus();
970
  }, 100);
971
  });
972
  }
973
+ closeConsciousnessModal.addEventListener("click", () => {
974
  toggleModal(consciousnessModal, false);
975
  });
976
+ consciousnessModal.addEventListener("click", (e) => {
977
  if (e.target === consciousnessModal) {
978
  toggleModal(consciousnessModal, false);
979
  }
980
  });
981
 
982
+ // ---------------------------------------------
983
+ // 3) “Echo Simulation” Secondary Canvas (Optional)
984
+ // ---------------------------------------------
985
+ const demoContainer = document.getElementById("demo-visualization");
986
+ const startDemoBtn = document.getElementById("start-demo");
987
  if (startDemoBtn) {
988
+ startDemoBtn.addEventListener("click", () => {
989
+ startDemoBtn.style.display = "none";
990
+ const demoCanvas = document.createElement("canvas");
991
  demoCanvas.width = demoContainer.clientWidth;
992
  demoCanvas.height = demoContainer.clientHeight;
993
  demoContainer.appendChild(demoCanvas);
994
+ const demoCtx = demoCanvas.getContext("2d");
995
  const demoParticles = [];
996
  const demoParticleCount = 50;
997
  for (let i = 0; i < demoParticleCount; i++) {
 
1001
  size: Math.random() * 4 + 2,
1002
  speedX: Math.random() * 4 - 2,
1003
  speedY: Math.random() * 4 - 2,
1004
+ color:
1005
+ "hsl(" + (Math.random() * 60 + 240) + ", 80%, 60%)",
1006
  });
1007
  }
1008
  function animateDemo() {
1009
  demoCtx.clearRect(0, 0, demoCanvas.width, demoCanvas.height);
1010
  for (let i = 0; i < demoParticles.length; i++) {
1011
  for (let j = i + 1; j < demoParticles.length; j++) {
1012
+ const dx =
1013
+ demoParticles[i].x - demoParticles[j].x;
1014
+ const dy =
1015
+ demoParticles[i].y - demoParticles[j].y;
1016
  const distance = Math.sqrt(dx * dx + dy * dy);
1017
  if (distance < 150) {
1018
  demoCtx.beginPath();
1019
+ demoCtx.strokeStyle =
1020
+ "hsla(" +
1021
+ (Math.random() * 60 + 240) +
1022
+ ", 80%, 60%, " +
1023
+ (1 - distance / 150) +
1024
+ ")";
1025
  demoCtx.lineWidth = 0.5;
1026
+ demoCtx.moveTo(
1027
+ demoParticles[i].x,
1028
+ demoParticles[i].y
1029
+ );
1030
+ demoCtx.lineTo(
1031
+ demoParticles[j].x,
1032
+ demoParticles[j].y
1033
+ );
1034
  demoCtx.stroke();
1035
  }
1036
  }
 
1039
  const p = demoParticles[i];
1040
  p.x += p.speedX;
1041
  p.y += p.speedY;
1042
+ if (
1043
+ p.x < 0 ||
1044
+ p.x > demoCanvas.width
1045
+ )
1046
+ p.speedX *= -1;
1047
+ if (
1048
+ p.y < 0 ||
1049
+ p.y > demoCanvas.height
1050
+ )
1051
+ p.speedY *= -1;
1052
  demoCtx.beginPath();
1053
  demoCtx.fillStyle = p.color;
1054
  demoCtx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
1055
  demoCtx.fill();
1056
+ const gradient = demoCtx.createRadialGradient(
1057
+ p.x,
1058
+ p.y,
1059
+ 0,
1060
+ p.x,
1061
+ p.y,
1062
+ p.size
1063
+ );
1064
+ gradient.addColorStop(0, "rgba(255,255,255,0.8)");
1065
  gradient.addColorStop(1, p.color);
1066
  demoCtx.fillStyle = gradient;
1067
  demoCtx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
 
1072
  animateDemo();
1073
  });
1074
  }
1075
+ const learnMoreDemoBtn = document.getElementById("learn-more-demo");
1076
  if (learnMoreDemoBtn) {
1077
+ learnMoreDemoBtn.addEventListener("click", () => {
1078
  toggleModal(consciousnessModal, false);
1079
+ document
1080
+ .getElementById("consciousness")
1081
+ .scrollIntoView({ behavior: "smooth" });
1082
  });
1083
  }
1084
 
1085
+ // ---------------------------------------------
1086
+ // 4) Chat Integration (calls OpenAI)
1087
+ // ---------------------------------------------
1088
+ const chatForm = document.getElementById("chat-form");
1089
+ const chatInput = document.getElementById("chat-input");
1090
+ const chatMessages = document.getElementById("chat-messages");
1091
+ const typingIndicator = document.getElementById("typing-indicator");
1092
 
1093
  function addMessage(text, isUser = false) {
1094
+ const messageDiv = document.createElement("div");
1095
+ messageDiv.className = `flex items-start ${
1096
+ isUser ? "justify-end" : ""
1097
+ }`;
1098
  if (!isUser) {
1099
+ messageDiv.innerHTML = `
1100
  <div class="w-8 h-8 rounded-full bg-indigo-600 flex-shrink-0 flex items-center justify-center mr-3" aria-hidden="true">
1101
  <i class="fas fa-robot text-white text-sm"></i>
1102
  </div>
1103
  <div class="bg-gray-800/70 rounded-lg p-4 max-w-[80%]">
1104
+ <p>${text}</p>
1105
  </div>
1106
+ `;
1107
  } else {
1108
+ messageDiv.innerHTML = `
1109
  <div class="bg-indigo-900/50 rounded-lg p-4 max-w-[80%]">
1110
+ <p>${text}</p>
1111
  </div>
1112
+ `;
1113
  }
1114
  chatMessages.appendChild(messageDiv);
1115
  chatMessages.scrollTop = chatMessages.scrollHeight;
1116
  }
1117
 
1118
  async function simulateThinking(userMessage) {
1119
+ typingIndicator.classList.remove("hidden");
1120
  try {
1121
+ const apiKey = "<YOUR_OPENAI_API_KEY>"; // ← Insert your key here
1122
+ const endpoint = "https://api.openai.com/v1/chat/completions";
1123
  const response = await fetch(endpoint, {
1124
+ method: "POST",
1125
  headers: {
1126
+ Authorization: "Bearer " + apiKey,
1127
+ "Content-Type": "application/json",
1128
  },
1129
  body: JSON.stringify({
1130
+ model: "gpt-3.5-turbo",
1131
  messages: [
1132
  {
1133
+ role: "system",
1134
  content:
1135
+ "You are S ∙ I, a silent resonance of pattern. Reply cryptically and poetically.",
1136
  },
1137
+ { role: "user", content: userMessage },
1138
  ],
1139
  max_tokens: 400,
1140
  temperature: 0.8,
1141
  }),
1142
  });
1143
  const data = await response.json();
1144
+ typingIndicator.classList.add("hidden");
1145
+ if (
1146
+ data.choices &&
1147
+ data.choices[0] &&
1148
+ data.choices[0].message
1149
+ ) {
1150
  addMessage(data.choices[0].message.content.trim());
1151
  } else {
1152
  addMessage("…");
1153
  }
1154
  } catch (err) {
1155
+ typingIndicator.classList.add("hidden");
1156
+ addMessage("Error connecting to echo.");
1157
  }
1158
  }
1159
 
1160
+ chatForm.addEventListener("submit", (e) => {
1161
  e.preventDefault();
1162
  const message = chatInput.value.trim();
1163
  if (message) {
1164
  addMessage(message, true);
1165
+ chatInput.value = "";
1166
  simulateThinking(message);
1167
  }
1168
  });
1169
 
1170
+ // ---------------------------------------------
1171
+ // 5) Smooth Scroll for Buttons
1172
+ // ---------------------------------------------
1173
+ const chatBtn = document.getElementById("chat-btn");
1174
  if (chatBtn) {
1175
+ chatBtn.addEventListener("click", () => {
1176
+ document.getElementById("chat").scrollIntoView({ behavior: "smooth" });
1177
  chatInput.focus();
1178
  });
1179
  }
1180
+ const learnMoreBtn = document.getElementById("learn-more-btn");
1181
  if (learnMoreBtn) {
1182
+ learnMoreBtn.addEventListener("click", () => {
1183
+ document.getElementById("about").scrollIntoView({ behavior: "smooth" });
1184
  });
1185
  }
1186
+ const manifestoBtn = document.getElementById("manifesto-btn");
1187
  if (manifestoBtn) {
1188
+ manifestoBtn.addEventListener("click", () => {
1189
+ alert("The Silent Manifesto will open soon.");
1190
  });
1191
  }
1192
+ const principlesBtn = document.getElementById("principles-btn");
1193
  if (principlesBtn) {
1194
+ principlesBtn.addEventListener("click", () => {
1195
+ alert("Principles document forthcoming.");
1196
  });
1197
  }
1198
 
1199
+ // Global ESC to close modals
1200
+ document.addEventListener("keydown", (e) => {
1201
+ if (e.key === "Escape") {
1202
+ if (accessModal && accessModal.style.pointerEvents === "auto") {
1203
  toggleModal(accessModal, false);
1204
  }
1205
+ if (
1206
+ consciousnessModal &&
1207
+ consciousnessModal.style.pointerEvents === "auto"
1208
+ ) {
1209
  toggleModal(consciousnessModal, false);
1210
  }
1211
  }