ginipick commited on
Commit
12bcf64
·
verified ·
1 Parent(s): db432b2

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +395 -283
index.html CHANGED
@@ -3,190 +3,228 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Screen Analysis & OCR Tool</title>
7
- <!-- Include Tesseract.js for OCR -->
8
- <script src="https://unpkg.com/[email protected]/dist/tesseract.min.js"></script>
9
  <style>
 
 
 
 
 
 
 
 
 
10
  * {
11
  margin: 0;
12
  padding: 0;
13
  box-sizing: border-box;
14
- font-family: Arial, sans-serif;
15
  }
16
 
17
  body {
18
- background: #f0f2f5;
19
- padding: 20px;
 
 
20
  }
21
 
22
  .container {
23
- max-width: 1200px;
24
  margin: 0 auto;
25
  }
26
 
27
  .header {
28
- background: white;
29
- padding: 20px;
30
- border-radius: 8px;
31
- margin-bottom: 20px;
32
  text-align: center;
33
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
34
- }
35
-
36
- .controls {
37
  background: white;
38
- padding: 20px;
39
- border-radius: 8px;
40
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
41
- margin-bottom: 20px;
42
- display: flex;
43
- gap: 10px;
44
- flex-wrap: wrap;
45
  }
46
 
47
- button {
48
- padding: 10px 20px;
49
- border: none;
50
- border-radius: 4px;
51
- cursor: pointer;
52
- font-weight: bold;
53
- display: flex;
54
- align-items: center;
55
- gap: 8px;
56
- min-width: 120px;
57
- justify-content: center;
58
  }
59
 
60
- .start-btn {
61
- background: #4CAF50;
62
- color: white;
 
63
  }
64
 
65
- .stop-btn {
66
- background: #f44336;
67
- color: white;
 
 
68
  }
69
 
70
- .clear-btn {
71
- background: #2196F3;
72
- color: white;
 
73
  }
74
 
75
- button:disabled {
76
- background: #ccc;
77
- cursor: not-allowed;
78
  }
79
 
80
- .preview-area {
81
- background: black;
82
- border-radius: 8px;
83
- overflow: hidden;
84
- margin-bottom: 20px;
85
- position: relative;
86
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
87
  }
88
 
89
- #preview {
90
  width: 100%;
91
- aspect-ratio: 16/9;
92
- object-fit: contain;
 
 
 
93
  }
94
 
95
- .recording-dot {
96
- position: absolute;
97
- top: 20px;
98
- right: 20px;
99
- width: 12px;
100
- height: 12px;
101
- background: red;
102
- border-radius: 50%;
103
- animation: pulse 1s infinite;
104
  }
105
 
106
- @keyframes pulse {
107
- 0% { opacity: 1; }
108
- 50% { opacity: 0.5; }
109
- 100% { opacity: 1; }
 
110
  }
111
 
112
- .logs {
113
- background: white;
114
- border-radius: 8px;
115
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
116
- overflow: hidden;
 
 
 
117
  }
118
 
119
- .log-entry {
120
- padding: 20px;
121
- border-bottom: 1px solid #eee;
122
- display: grid;
123
- grid-template-columns: 300px 1fr;
124
- gap: 20px;
125
  }
126
 
127
- .screenshot-container {
128
- position: relative;
 
 
 
 
 
 
 
 
 
 
129
  }
130
 
131
- .screenshot {
132
- width: 100%;
133
- border-radius: 4px;
134
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
135
  }
136
 
137
- .change-highlight {
138
- position: absolute;
139
- border: 2px solid red;
140
- background: rgba(255,0,0,0.2);
141
- pointer-events: none;
 
142
  }
143
 
144
- .info-panel {
 
 
 
 
145
  display: flex;
146
- flex-direction: column;
147
- gap: 15px;
 
148
  }
149
 
150
- .timestamp {
151
- color: #666;
152
- font-size: 14px;
153
  }
154
 
155
- .text-content {
156
- background: #f8f9fa;
157
- padding: 15px;
158
- border-radius: 4px;
159
- font-size: 14px;
160
- line-height: 1.5;
161
- max-height: 200px;
162
- overflow-y: auto;
163
  }
164
 
165
- .actions {
 
 
 
 
 
166
  display: flex;
167
- gap: 10px;
168
- margin-top: 10px;
 
169
  }
170
 
171
- .download-btn {
172
- background: #4CAF50;
173
  color: white;
174
- padding: 8px 16px;
175
- border-radius: 4px;
176
- text-decoration: none;
177
- display: inline-flex;
178
- align-items: center;
179
- gap: 5px;
180
- font-size: 14px;
181
  }
182
 
183
- .processing {
184
- color: #666;
185
- font-style: italic;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  }
187
 
188
  @media (max-width: 768px) {
189
- .log-entry {
 
 
 
 
190
  grid-template-columns: 1fr;
191
  }
192
  }
@@ -195,200 +233,274 @@
195
  <body>
196
  <div class="container">
197
  <div class="header">
198
- <h1>Screen Analysis & OCR Tool</h1>
199
- <p>Capture, analyze, and extract text from your screen</p>
200
  </div>
201
 
202
- <div class="controls">
203
- <button id="startBtn" class="start-btn">▶ Start Capture</button>
204
- <button id="stopBtn" class="stop-btn" disabled>⬛ Stop</button>
205
- <button id="clearBtn" class="clear-btn">🗑 Clear Logs</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  </div>
207
 
208
- <div class="preview-area">
209
- <video id="preview" autoplay></video>
210
- <div class="recording-dot" style="display: none;"></div>
 
211
  </div>
212
 
213
- <div class="logs" id="logContainer"></div>
 
 
 
214
  </div>
215
 
216
  <script>
217
- let mediaStream = null;
218
- let captureInterval = null;
219
- let lastImageData = null;
220
-
221
- // Initialize Tesseract
222
- const worker = Tesseract.createWorker();
223
-
224
- (async () => {
225
- await worker.load();
226
- await worker.loadLanguage('eng');
227
- await worker.initialize('eng');
228
- })();
229
-
230
- const startBtn = document.getElementById('startBtn');
231
- const stopBtn = document.getElementById('stopBtn');
232
- const clearBtn = document.getElementById('clearBtn');
233
- const preview = document.getElementById('preview');
234
- const logContainer = document.getElementById('logContainer');
235
- const recordingDot = document.querySelector('.recording-dot');
236
-
237
- async function startCapture() {
238
- try {
239
- mediaStream = await navigator.mediaDevices.getDisplayMedia({
240
- video: { cursor: "always" }
241
- });
242
-
243
- preview.srcObject = mediaStream;
244
- startBtn.disabled = true;
245
- stopBtn.disabled = false;
246
- recordingDot.style.display = 'block';
247
-
248
- captureInterval = setInterval(captureAndAnalyze, 1000);
249
-
250
- mediaStream.getVideoTracks()[0].onended = stopCapture;
251
-
252
- } catch (err) {
253
- console.error("Error starting capture:", err);
254
  }
255
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
 
257
- function stopCapture() {
258
- if (mediaStream) {
259
- mediaStream.getTracks().forEach(track => track.stop());
260
- preview.srcObject = null;
261
- }
262
- clearInterval(captureInterval);
263
- startBtn.disabled = false;
264
- stopBtn.disabled = true;
265
- recordingDot.style.display = 'none';
266
- lastImageData = null;
267
- }
268
-
269
- function detectChanges(current, last) {
270
- const blockSize = 20;
271
- const threshold = 30;
272
- const changes = [];
273
- const width = current.width;
274
- const height = current.height;
275
-
276
- for (let y = 0; y < height; y += blockSize) {
277
- for (let x = 0; x < width; x += blockSize) {
278
- let diffCount = 0;
279
- const maxY = Math.min(y + blockSize, height);
280
- const maxX = Math.min(x + blockSize, width);
281
-
282
- for (let py = y; py < maxY; py++) {
283
- for (let px = x; px < maxX; px++) {
284
- const i = (py * width + px) * 4;
285
- if (Math.abs(current.data[i] - last.data[i]) > threshold ||
286
- Math.abs(current.data[i + 1] - last.data[i + 1]) > threshold ||
287
- Math.abs(current.data[i + 2] - last.data[i + 2]) > threshold) {
288
- diffCount++;
289
- }
290
- }
291
  }
292
-
293
- if (diffCount > (blockSize * blockSize * 0.3)) {
294
- changes.push({
295
- x: x / width * 100,
296
- y: y / height * 100,
297
- width: Math.min(blockSize / width * 100, 100 - x / width * 100),
298
- height: Math.min(blockSize / height * 100, 100 - y / height * 100)
299
- });
300
  }
301
  }
302
- }
 
 
 
 
 
303
 
304
- return changes;
305
  }
306
 
307
- async function captureAndAnalyze() {
308
- const canvas = document.createElement('canvas');
309
- canvas.width = preview.videoWidth;
310
- canvas.height = preview.videoHeight;
311
-
312
- const ctx = canvas.getContext('2d');
313
- ctx.drawImage(preview, 0, 0);
314
-
315
- const currentImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
316
- let changes = [];
317
 
318
- if (lastImageData) {
319
- changes = detectChanges(currentImageData, lastImageData);
 
320
  }
321
 
322
- lastImageData = currentImageData;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
 
324
- if (changes.length > 0 || !lastImageData) {
325
- const imageUrl = canvas.toDataURL('image/jpeg', 0.8);
326
- await addLogEntry(imageUrl, changes);
327
- }
 
 
 
 
 
 
 
 
328
  }
329
 
330
- async function performOCR(imageUrl) {
331
- try {
332
- const result = await worker.recognize(imageUrl);
333
- return result.data.text;
334
- } catch (error) {
335
- console.error('OCR Error:', error);
336
- return 'Error performing OCR';
337
  }
 
 
338
  }
339
 
340
- async function addLogEntry(imageUrl, changes) {
341
- const logEntry = document.createElement('div');
342
- logEntry.className = 'log-entry';
343
 
344
- const timestamp = new Date().toLocaleString();
345
-
346
- // Create initial structure with loading state
347
- logEntry.innerHTML = `
348
- <div class="screenshot-container">
349
- <img class="screenshot" src="${imageUrl}" alt="Screenshot">
350
- ${changes.map(change => `
351
- <div class="change-highlight" style="
352
- left: ${change.x}%;
353
- top: ${change.y}%;
354
- width: ${change.width}%;
355
- height: ${change.height}%;
356
- "></div>
357
- `).join('')}
358
- </div>
359
- <div class="info-panel">
360
- <div class="timestamp">${timestamp}</div>
361
- <div class="text-content processing">Processing text extraction...</div>
362
- <div class="actions">
363
- <a href="${imageUrl}" download="screenshot-${Date.now()}.jpg" class="download-btn">
364
- 💾 Download Image
365
- </a>
366
- </div>
367
- </div>
368
- `;
369
 
370
- logContainer.insertBefore(logEntry, logContainer.firstChild);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
 
372
- // Perform OCR
373
- const extractedText = await performOCR(imageUrl);
374
-
375
- // Update text content
376
- const textContent = logEntry.querySelector('.text-content');
377
- textContent.classList.remove('processing');
378
- textContent.textContent = extractedText || 'No text detected';
379
  }
380
 
381
- clearBtn.addEventListener('click', () => {
382
- logContainer.innerHTML = '';
383
- });
384
-
385
- startBtn.addEventListener('click', startCapture);
386
- stopBtn.addEventListener('click', stopCapture);
387
-
388
- // Cleanup when page is closed
389
- window.addEventListener('beforeunload', () => {
390
- worker.terminate();
391
- });
392
  </script>
393
  </body>
394
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Personalized Baby Name Generator</title>
 
 
7
  <style>
8
+ :root {
9
+ --primary: #FF9FB0;
10
+ --secondary: #A6D9F7;
11
+ --accent: #B6E6BD;
12
+ --dark: #2D3748;
13
+ --light: #F7FAFC;
14
+ --shadow: rgba(0, 0, 0, 0.1);
15
+ }
16
+
17
  * {
18
  margin: 0;
19
  padding: 0;
20
  box-sizing: border-box;
21
+ font-family: 'Segoe UI', Arial, sans-serif;
22
  }
23
 
24
  body {
25
+ background: linear-gradient(135deg, #f6f8fc 0%, #fff 100%);
26
+ color: var(--dark);
27
+ min-height: 100vh;
28
+ padding: 2rem;
29
  }
30
 
31
  .container {
32
+ max-width: 1000px;
33
  margin: 0 auto;
34
  }
35
 
36
  .header {
 
 
 
 
37
  text-align: center;
38
+ padding: 2rem;
 
 
 
39
  background: white;
40
+ border-radius: 1rem;
41
+ box-shadow: 0 4px 6px var(--shadow);
42
+ margin-bottom: 2rem;
 
 
 
 
43
  }
44
 
45
+ .header h1 {
46
+ color: var(--primary);
47
+ font-size: 2.5rem;
48
+ margin-bottom: 0.5rem;
 
 
 
 
 
 
 
49
  }
50
 
51
+ .generator-form {
52
+ display: grid;
53
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
54
+ gap: 2rem;
55
  }
56
 
57
+ .form-section {
58
+ background: white;
59
+ padding: 1.5rem;
60
+ border-radius: 1rem;
61
+ box-shadow: 0 4px 6px var(--shadow);
62
  }
63
 
64
+ .form-section h2 {
65
+ color: var(--secondary);
66
+ margin-bottom: 1rem;
67
+ font-size: 1.5rem;
68
  }
69
 
70
+ .input-group {
71
+ margin-bottom: 1rem;
 
72
  }
73
 
74
+ .input-group label {
75
+ display: block;
76
+ margin-bottom: 0.5rem;
77
+ color: var(--dark);
78
+ font-weight: 500;
 
 
79
  }
80
 
81
+ select, input {
82
  width: 100%;
83
+ padding: 0.75rem;
84
+ border: 2px solid #E2E8F0;
85
+ border-radius: 0.5rem;
86
+ font-size: 1rem;
87
+ transition: all 0.3s ease;
88
  }
89
 
90
+ select:focus, input:focus {
91
+ border-color: var(--primary);
92
+ outline: none;
93
+ box-shadow: 0 0 0 3px rgba(255, 159, 176, 0.2);
 
 
 
 
 
94
  }
95
 
96
+ .traits-container {
97
+ display: grid;
98
+ grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
99
+ gap: 0.5rem;
100
+ margin-top: 0.5rem;
101
  }
102
 
103
+ .trait-chip {
104
+ padding: 0.5rem;
105
+ background: var(--light);
106
+ border: 1px solid #E2E8F0;
107
+ border-radius: 2rem;
108
+ cursor: pointer;
109
+ text-align: center;
110
+ transition: all 0.3s ease;
111
  }
112
 
113
+ .trait-chip.selected {
114
+ background: var(--primary);
115
+ color: white;
116
+ border-color: var(--primary);
 
 
117
  }
118
 
119
+ .generate-btn {
120
+ background: var(--primary);
121
+ color: white;
122
+ border: none;
123
+ padding: 1rem 2rem;
124
+ border-radius: 0.5rem;
125
+ font-size: 1.1rem;
126
+ font-weight: 600;
127
+ cursor: pointer;
128
+ width: 100%;
129
+ transition: all 0.3s ease;
130
+ margin-top: 1rem;
131
  }
132
 
133
+ .generate-btn:hover {
134
+ transform: translateY(-2px);
135
+ box-shadow: 0 4px 12px rgba(255, 159, 176, 0.3);
 
136
  }
137
 
138
+ .results-section {
139
+ margin-top: 2rem;
140
+ background: white;
141
+ padding: 2rem;
142
+ border-radius: 1rem;
143
+ box-shadow: 0 4px 6px var(--shadow);
144
  }
145
 
146
+ .name-card {
147
+ background: var(--light);
148
+ padding: 1.5rem;
149
+ border-radius: 0.5rem;
150
+ margin-bottom: 1rem;
151
  display: flex;
152
+ justify-content: space-between;
153
+ align-items: center;
154
+ transition: all 0.3s ease;
155
  }
156
 
157
+ .name-card:hover {
158
+ transform: translateX(5px);
159
+ background: #F0F7FF;
160
  }
161
 
162
+ .name-details h3 {
163
+ color: var(--primary);
164
+ font-size: 1.5rem;
165
+ margin-bottom: 0.5rem;
 
 
 
 
166
  }
167
 
168
+ .name-meaning {
169
+ font-size: 0.9rem;
170
+ color: #666;
171
+ }
172
+
173
+ .personality-tags {
174
  display: flex;
175
+ gap: 0.5rem;
176
+ flex-wrap: wrap;
177
+ margin-top: 0.5rem;
178
  }
179
 
180
+ .personality-tag {
181
+ background: var(--secondary);
182
  color: white;
183
+ padding: 0.25rem 0.75rem;
184
+ border-radius: 1rem;
185
+ font-size: 0.8rem;
 
 
 
 
186
  }
187
 
188
+ .favorite-btn {
189
+ background: none;
190
+ border: none;
191
+ font-size: 1.5rem;
192
+ cursor: pointer;
193
+ transition: all 0.3s ease;
194
+ }
195
+
196
+ .favorite-btn:hover {
197
+ transform: scale(1.2);
198
+ }
199
+
200
+ .favorites-section {
201
+ margin-top: 2rem;
202
+ background: white;
203
+ padding: 2rem;
204
+ border-radius: 1rem;
205
+ box-shadow: 0 4px 6px var(--shadow);
206
+ }
207
+
208
+ .favorites-section h2 {
209
+ color: var(--primary);
210
+ margin-bottom: 1rem;
211
+ }
212
+
213
+ @keyframes fadeIn {
214
+ from { opacity: 0; transform: translateY(10px); }
215
+ to { opacity: 1; transform: translateY(0); }
216
+ }
217
+
218
+ .name-card {
219
+ animation: fadeIn 0.5s ease forwards;
220
  }
221
 
222
  @media (max-width: 768px) {
223
+ .container {
224
+ padding: 1rem;
225
+ }
226
+
227
+ .generator-form {
228
  grid-template-columns: 1fr;
229
  }
230
  }
 
233
  <body>
234
  <div class="container">
235
  <div class="header">
236
+ <h1>👶 Personalized Baby Name Generator</h1>
237
+ <p>Create the perfect name based on your family's unique characteristics</p>
238
  </div>
239
 
240
+ <div class="generator-form">
241
+ <div class="form-section">
242
+ <h2>Basic Information</h2>
243
+ <div class="input-group">
244
+ <label for="gender">Baby's Gender</label>
245
+ <select id="gender">
246
+ <option value="all">All</option>
247
+ <option value="boy">Boy</option>
248
+ <option value="girl">Girl</option>
249
+ <option value="neutral">Gender Neutral</option>
250
+ </select>
251
+ </div>
252
+
253
+ <div class="input-group">
254
+ <label for="origin">Cultural Background</label>
255
+ <select id="origin" multiple>
256
+ <option value="english">English</option>
257
+ <option value="french">French</option>
258
+ <option value="spanish">Spanish</option>
259
+ <option value="italian">Italian</option>
260
+ <option value="greek">Greek</option>
261
+ <option value="celtic">Celtic</option>
262
+ <option value="nordic">Nordic</option>
263
+ <option value="hebrew">Hebrew</option>
264
+ <option value="arabic">Arabic</option>
265
+ <option value="persian">Persian</option>
266
+ <option value="indian">Indian</option>
267
+ <option value="chinese">Chinese</option>
268
+ <option value="japanese">Japanese</option>
269
+ <option value="korean">Korean</option>
270
+ </select>
271
+ </div>
272
+ </div>
273
+
274
+ <div class="form-section">
275
+ <h2>Mother's Characteristics</h2>
276
+ <div class="input-group">
277
+ <label>Select Personality Traits</label>
278
+ <div class="traits-container" id="motherTraits">
279
+ <div class="trait-chip" data-trait="creative">Creative</div>
280
+ <div class="trait-chip" data-trait="intelligent">Intelligent</div>
281
+ <div class="trait-chip" data-trait="caring">Caring</div>
282
+ <div class="trait-chip" data-trait="strong">Strong</div>
283
+ <div class="trait-chip" data-trait="artistic">Artistic</div>
284
+ <div class="trait-chip" data-trait="adventurous">Adventurous</div>
285
+ <div class="trait-chip" data-trait="peaceful">Peaceful</div>
286
+ <div class="trait-chip" data-trait="wise">Wise</div>
287
+ </div>
288
+ </div>
289
+ </div>
290
+
291
+ <div class="form-section">
292
+ <h2>Father's Characteristics</h2>
293
+ <div class="input-group">
294
+ <label>Select Personality Traits</label>
295
+ <div class="traits-container" id="fatherTraits">
296
+ <div class="trait-chip" data-trait="protective">Protective</div>
297
+ <div class="trait-chip" data-trait="loyal">Loyal</div>
298
+ <div class="trait-chip" data-trait="brave">Brave</div>
299
+ <div class="trait-chip" data-trait="gentle">Gentle</div>
300
+ <div class="trait-chip" data-trait="ambitious">Ambitious</div>
301
+ <div class="trait-chip" data-trait="wise">Wise</div>
302
+ <div class="trait-chip" data-trait="humorous">Humorous</div>
303
+ <div class="trait-chip" data-trait="athletic">Athletic</div>
304
+ </div>
305
+ </div>
306
+ </div>
307
  </div>
308
 
309
+ <button class="generate-btn" onclick="generateNames()">Generate Perfect Names</button>
310
+
311
+ <div class="results-section" id="results">
312
+ <!-- Generated names will appear here -->
313
  </div>
314
 
315
+ <div class="favorites-section">
316
+ <h2>❤️ Favorite Names</h2>
317
+ <div id="favoritesList"></div>
318
+ </div>
319
  </div>
320
 
321
  <script>
322
+ // Extended name database with meanings and trait associations
323
+ const nameDatabase = {
324
+ boy: {
325
+ creative: ['Leonardo', 'Byron', 'Vincent', 'Aiden'],
326
+ intelligent: ['Solomon', 'Ethan', 'Adrian', 'Theodore'],
327
+ strong: ['Alexander', 'Thor', 'Viktor', 'Bruno'],
328
+ protective: ['William', 'Guardian', 'Ward', 'Reign'],
329
+ brave: ['Valor', 'Leo', 'Wyatt', 'Ethan'],
330
+ gentle: ['Oliver', 'Liam', 'Noah', 'Benjamin'],
331
+ wise: ['Sage', 'Solomon', 'Alvis', 'Kenneth']
332
+ },
333
+ girl: {
334
+ creative: ['Luna', 'Aurora', 'Aria', 'Maya'],
335
+ intelligent: ['Sophia', 'Athena', 'Claire', 'Ada'],
336
+ caring: ['Grace', 'Hannah', 'Lily', 'Mira'],
337
+ artistic: ['Melody', 'Violet', 'Iris', 'Aria'],
338
+ peaceful: ['Serena', 'Dove', 'Paz', 'Shanti'],
339
+ wise: ['Sophia', 'Minerva', 'Sage', 'Alena']
340
+ },
341
+ neutral: {
342
+ creative: ['Alex', 'River', 'Sky', 'Phoenix'],
343
+ strong: ['Morgan', 'Kai', 'Atlas', 'Storm'],
344
+ wise: ['Sage', 'Quinn', 'Blair', 'Eden'],
345
+ peaceful: ['Harmony', 'Peace', 'Robin', 'Dawn']
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  }
347
+ };
348
+
349
+ // Name meanings database
350
+ const nameMeanings = {
351
+ 'Alexander': 'Defender of the people',
352
+ 'Sophia': 'Wisdom',
353
+ 'Luna': 'Moon',
354
+ 'Ethan': 'Strong, enduring',
355
+ 'Grace': 'Elegance and divine favor',
356
+ // Add more meanings as needed
357
+ };
358
+
359
+ let favorites = new Set();
360
+ let selectedTraits = {
361
+ mother: new Set(),
362
+ father: new Set()
363
+ };
364
+
365
+ // Setup trait selection
366
+ document.querySelectorAll('.trait-chip').forEach(chip => {
367
+ chip.addEventListener('click', () => {
368
+ const parent = chip.parentElement.id;
369
+ const trait = chip.dataset.trait;
370
+ const traitSet = parent === 'motherTraits' ? selectedTraits.mother : selectedTraits.father;
371
+
372
+ chip.classList.toggle('selected');
373
+ if (traitSet.has(trait)) {
374
+ traitSet.delete(trait);
375
+ } else {
376
+ traitSet.add(trait);
377
+ }
378
+ });
379
+ });
380
 
381
+ function generateNames() {
382
+ const gender = document.getElementById('gender').value;
383
+ const origins = Array.from(document.getElementById('origin').selectedOptions).map(option => option.value);
384
+
385
+ let names = new Set();
386
+ const traits = [...selectedTraits.mother, ...selectedTraits.father];
387
+
388
+ // Generate names based on selected traits
389
+ traits.forEach(trait => {
390
+ if (gender === 'all' || gender === 'neutral') {
391
+ if (nameDatabase.neutral[trait]) {
392
+ nameDatabase.neutral[trait].forEach(name => names.add(name));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
393
  }
394
+ }
395
+ if (gender === 'all' || gender === 'boy') {
396
+ if (nameDatabase.boy[trait]) {
397
+ nameDatabase.boy[trait].forEach(name => names.add(name));
 
 
 
 
398
  }
399
  }
400
+ if (gender === 'all' || gender === 'girl') {
401
+ if (nameDatabase.girl[trait]) {
402
+ nameDatabase.girl[trait].forEach(name => names.add(name));
403
+ }
404
+ }
405
+ });
406
 
407
+ displayResults(Array.from(names));
408
  }
409
 
410
+ function displayResults(names) {
411
+ const resultsDiv = document.getElementById('results');
412
+ resultsDiv.innerHTML = '<h2>Suggested Names</h2>';
 
 
 
 
 
 
 
413
 
414
+ if (names.length === 0) {
415
+ resultsDiv.innerHTML += '<p>No names match your criteria. Try selecting different traits.</p>';
416
+ return;
417
  }
418
 
419
+ names.forEach((name, index) => {
420
+ const nameCard = document.createElement('div');
421
+ nameCard.className = 'name-card';
422
+ nameCard.style.animationDelay = `${index * 0.1}s`;
423
+
424
+ const relatedTraits = findRelatedTraits(name);
425
+ const meaning = nameMeanings[name] || 'A beautiful name';
426
+
427
+ nameCard.innerHTML = `
428
+ <div class="name-details">
429
+ <h3>${name}</h3>
430
+ <div class="name-meaning">${meaning}</div>
431
+ <div class="personality-tags">
432
+ ${relatedTraits.map(trait =>
433
+ `<span class="personality-tag">${trait}</span>`
434
+ ).join('')}
435
+ </div>
436
+ </div>
437
+ <button class="favorite-btn" onclick="toggleFavorite('${name}')">
438
+ ${favorites.has(name) ? '❤️' : '🤍'}
439
+ </button>
440
+ `;
441
+
442
+ resultsDiv.appendChild(nameCard);
443
+ });
444
+ }
445
 
446
+ function findRelatedTraits(name) {
447
+ let traits = new Set();
448
+
449
+ Object.entries(nameDatabase).forEach(([gender, traitGroups]) => {
450
+ Object.entries(traitGroups).forEach(([trait, names]) => {
451
+ if (names.includes(name)) {
452
+ traits.add(trait);
453
+ }
454
+ });
455
+ });
456
+
457
+ return Array.from(traits);
458
  }
459
 
460
+ function toggleFavorite(name) {
461
+ if (favorites.has(name)) {
462
+ favorites.delete(name);
463
+ } else {
464
+ favorites.add(name);
 
 
465
  }
466
+ updateFavorites();
467
+ generateNames(); // Refresh current results
468
  }
469
 
470
+ function updateFavorites() {
471
+ const favoritesList = document.getElementById('favoritesList');
472
+ favoritesList.innerHTML = '';
473
 
474
+ if (favorites.size === 0) {
475
+ favoritesList.innerHTML = '<p>No favorite names yet</p>';
476
+ return;
477
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
 
479
+ [...favorites].forEach(name => {
480
+ const nameCard = document.createElement('div');
481
+ nameCard.className = 'name-card';
482
+ const relatedTraits = findRelatedTraits(name);
483
+ const meaning = nameMeanings[name] || 'A beautiful name';
484
+
485
+ nameCard.innerHTML = `
486
+ <div class="name-details">
487
+ <h3>${name}</h3>
488
+ <div class="name-meaning">${meaning}</div>
489
+ <div class="personality-tags">
490
+ ${relatedTraits.map(trait =>
491
+ `<span class="personality-tag">${trait}</span>`
492
+ ).join('')}
493
+ </div>
494
+ </div>
495
+ <button class="favorite-btn" onclick="toggleFavorite('${name}')">❤️</button>
496
+ `;
497
 
498
+ favoritesList.appendChild(nameCard);
499
+ });
 
 
 
 
 
500
  }
501
 
502
+ // Initialize with empty results
503
+ generateNames();
 
 
 
 
 
 
 
 
 
504
  </script>
505
  </body>
506
  </html>