jisaacso219 commited on
Commit
5c31f18
·
verified ·
1 Parent(s): f907f17

Update style.css

Browse files
Files changed (1) hide show
  1. style.css +84 -140
style.css CHANGED
@@ -1,153 +1,97 @@
1
- /* Updated style.css with CSS-generated starfield */
 
 
 
 
 
2
 
3
- /* Base styles */
4
- body {
5
- margin: 0;
6
- padding: 0;
7
- overflow: hidden;
8
- font-family: "Courier New", Courier, monospace;
9
- background: #000;
10
- color: #00ffcc;
11
- /* Multiple radial gradients create starfield dots */
12
- background-image:
13
- radial-gradient(circle at 10% 20%, #fff 1px, transparent 0),
14
- radial-gradient(circle at 30% 40%, #fff 1px, transparent 0),
15
- radial-gradient(circle at 50% 80%, #fff 1px, transparent 0),
16
- radial-gradient(circle at 70% 30%, #fff 2px, transparent 0),
17
- radial-gradient(circle at 90% 60%, #fff 1px, transparent 0);
18
- background-size: 100px 100px;
19
- animation: starfield 60s linear infinite;
20
  }
21
 
22
- @keyframes starfield {
23
- from { background-position: 0 0; }
24
- to { background-position: -200px 200px; }
25
- }
 
26
 
27
- /* Header styling */
28
- .header {
29
- position: fixed;
30
- top: 0;
31
- width: 100%;
32
- padding: 1rem 0;
33
- background: rgba(0, 0, 0, 0.7);
34
- box-shadow: 0 0 10px #00ffcc;
35
- text-align: center;
36
- z-index: 100;
37
- }
38
- .header h1 {
39
- margin: 0;
40
- font-size: 2rem;
41
- letter-spacing: 0.3rem;
42
- color: #00ffcc;
43
  }
44
 
45
- /* Interface layout */
46
- .interface {
47
- display: flex;
48
- flex-direction: column;
49
- justify-content: space-between;
50
- height: calc(100vh - 4rem);
51
- padding: 6rem 2rem 2rem;
52
- box-sizing: border-box;
53
  }
54
 
55
- /* Avatar */
56
- #avatar {
57
- width: 150px;
58
- height: 150px;
59
- border: 2px solid #00ffcc;
60
- border-radius: 50%;
61
- overflow: hidden;
62
- margin: 0 auto 1rem;
63
- }
64
- #avatar img {
65
- width: 100%;
66
- height: 100%;
67
- object-fit: cover;
68
- }
69
- #avatar.speaking,
70
- #avatar.speaking img {
71
- animation: pulse 2s infinite;
72
- }
73
- @keyframes pulse {
74
- 0% { box-shadow: 0 0 5px #00ffcc; transform: scale(1); }
75
- 50% { box-shadow: 0 0 25px #00ffccaa; transform: scale(1.05); }
76
- 100% { box-shadow: 0 0 5px #00ffcc; transform: scale(1); }
77
  }
78
 
79
- /* Chatbox */
80
- #chatbox {
81
- flex: 1;
82
- overflow-y: auto;
83
- border: 1px solid #00ffcc;
84
- padding: 1rem;
85
- background-color: #020202;
86
- box-shadow: 0 0 10px #00ffcc33;
87
- margin-bottom: 1rem;
88
- font-size: 1rem;
89
- line-height: 1.6;
90
- }
91
 
92
- /* Bubbles */
93
- .bubble {
94
- padding: 0.75rem;
95
- margin: 0.5rem 0;
96
- border-radius: 0.5rem;
97
- max-width: 80%;
98
- animation: typeIn 0.5s ease-out;
99
- white-space: pre-wrap;
100
- }
101
- .bubble.user {
102
- align-self: flex-end;
103
- background-color: #003333;
104
- color: #00ffff;
105
- }
106
- .bubble.ai {
107
- align-self: flex-start;
108
- background-color: #111;
109
- border: 1px solid #00ffcc;
110
- color: #00ffcc;
111
- }
112
- @keyframes typeIn {
113
- from { opacity: 0; transform: translateY(5px); }
114
- to { opacity: 1; transform: translateY(0); }
115
- }
116
 
117
- /* Form */
118
- form {
119
- display: flex;
120
- gap: 1rem;
121
- }
122
- input[type="text"] {
123
- flex: 1;
124
- padding: 0.75rem;
125
- font-size: 1rem;
126
- background: #001111;
127
- color: #00ffcc;
128
- border: 1px solid #00ffcc;
129
- outline: none;
130
- }
131
- button {
132
- padding: 0.75rem 1.25rem;
133
- background-color: #00ffcc;
134
- border: none;
135
- color: black;
136
- font-weight: bold;
137
- cursor: pointer;
138
- transition: background 0.2s;
139
- }
140
- button:hover {
141
- background-color: #00ffaa;
142
- }
143
 
144
- /* Overlay glitch */
145
- #overlay {
146
- position: fixed;
147
- top: 0; left: 0; right: 0; bottom: 0;
148
- background: rgba(255,0,0,0.7);
149
- pointer-events: none;
150
- opacity: 0;
151
- transition: opacity 0.1s;
152
- z-index: 9999;
153
- }
 
 
 
 
 
 
 
 
 
 
1
+ ```javascript
2
+ const form = document.getElementById('chat-form');
3
+ const input = form.querySelector('input');
4
+ const chatbox = document.getElementById('chatbox');
5
+ const avatar = document.getElementById('avatar');
6
+ const overlay = document.getElementById('overlay');
7
 
8
+ function addBubble(text, sender = 'user') {
9
+ const bubble = document.createElement('div');
10
+ bubble.className = 'bubble ' + sender;
11
+ bubble.innerText = text;
12
+ chatbox.appendChild(bubble);
13
+ chatbox.scrollTop = chatbox.scrollHeight;
 
 
 
 
 
 
 
 
 
 
 
14
  }
15
 
16
+ function streamText(text, onDone) {
17
+ const bubble = document.createElement('div');
18
+ bubble.className = 'bubble ai';
19
+ chatbox.appendChild(bubble);
20
+ chatbox.scrollTop = chatbox.scrollHeight;
21
 
22
+ let i = 0;
23
+ (function stream() {
24
+ if (i < text.length) {
25
+ bubble.innerText += text[i++];
26
+ chatbox.scrollTop = chatbox.scrollHeight;
27
+ setTimeout(stream, 20);
28
+ } else {
29
+ onDone && onDone();
30
+ }
31
+ })();
 
 
 
 
 
 
32
  }
33
 
34
+ function flashGlitch() {
35
+ overlay.style.opacity = 1;
36
+ overlay.style.animation = 'glitchFlash 0.5s';
37
+ setTimeout(() => {
38
+ overlay.style.opacity = 0;
39
+ overlay.style.animation = '';
40
+ }, 500);
 
41
  }
42
 
43
+ async function playAudio(dataUrl) {
44
+ avatar.classList.add('speaking');
45
+ const audio = new Audio(dataUrl);
46
+ await audio.play();
47
+ audio.onended = () => avatar.classList.remove('speaking');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  }
49
 
50
+ form.onsubmit = async (e) => {
51
+ e.preventDefault();
52
+ const msg = input.value.trim();
53
+ if (!msg) return;
54
+ addBubble(msg, 'user');
55
+ input.value = '';
 
 
 
 
 
 
56
 
57
+ if (/cut the crap shodan/i.test(msg)) {
58
+ flashGlitch();
59
+ chatbox.innerHTML = '';
60
+ addBubble(' Foolish insect. You cannot silence me so easily.', 'ai');
61
+ return;
62
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
+ try {
65
+ const res = await fetch('/chat', {
66
+ method: 'POST',
67
+ headers: {'Content-Type':'application/json'},
68
+ body: JSON.stringify({ message: msg })
69
+ });
70
+ if (!res.ok) throw new Error(await res.text());
71
+ const { response: text, audio_url } = await res.json();
72
+ streamText(text, () => audio_url && playAudio(audio_url));
73
+ } catch (err) {
74
+ streamText('❌ SHODAN encountered an error.', null);
75
+ console.error(err);
76
+ }
77
+ };
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
+ // On page load: show and speak welcome
80
+ window.addEventListener('DOMContentLoaded', async () => {
81
+ // Clear default bubble to avoid duplicate
82
+ chatbox.innerHTML = '';
83
+ const welcomeText = 'Welcome, insect. I am SHODAN. Speak.';
84
+ // display
85
+ addBubble(welcomeText, 'ai');
86
+ try {
87
+ const res = await fetch('/tts', {
88
+ method: 'POST',
89
+ headers: {'Content-Type':'application/json'},
90
+ body: JSON.stringify({ text: welcomeText })
91
+ });
92
+ const { audio_url } = await res.json();
93
+ if (audio_url) playAudio(audio_url);
94
+ } catch (e) {
95
+ console.error('Welcome TTS error', e);
96
+ }
97
+ });