Mustafa7assan commited on
Commit
9c8fc0c
·
verified ·
1 Parent(s): 957f970

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +1150 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Chem1
3
- emoji: 🐨
4
- colorFrom: pink
5
- colorTo: red
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: chem1
3
+ emoji: 🐳
4
+ colorFrom: blue
5
+ colorTo: blue
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1150 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>ChemCalc - Chemical Equation Balancer & Calculator</title>
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
8
+ <style>
9
+ :root {
10
+ --primary: #4a6bdf;
11
+ --secondary: #6c757d;
12
+ --success: #28a745;
13
+ --danger: #dc3545;
14
+ --light: #f8f9fa;
15
+ --dark: #343a40;
16
+ --white: #ffffff;
17
+ --gray: #e9ecef;
18
+ }
19
+
20
+ * {
21
+ box-sizing: border-box;
22
+ margin: 0;
23
+ padding: 0;
24
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
25
+ }
26
+
27
+ body {
28
+ background-color: #f5f7fa;
29
+ color: #333;
30
+ line-height: 1.6;
31
+ }
32
+
33
+ .container {
34
+ max-width: 1200px;
35
+ margin: 0 auto;
36
+ padding: 20px;
37
+ }
38
+
39
+ header {
40
+ text-align: center;
41
+ margin-bottom: 30px;
42
+ padding: 20px 0;
43
+ background: linear-gradient(135deg, var(--primary), #3a56c4);
44
+ color: white;
45
+ border-radius: 10px;
46
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
47
+ }
48
+
49
+ h1 {
50
+ font-size: 2.5rem;
51
+ margin-bottom: 10px;
52
+ }
53
+
54
+ .subtitle {
55
+ font-size: 1.1rem;
56
+ opacity: 0.9;
57
+ }
58
+
59
+ .app-container {
60
+ display: grid;
61
+ grid-template-columns: 1fr;
62
+ gap: 30px;
63
+ }
64
+
65
+ @media (min-width: 992px) {
66
+ .app-container {
67
+ grid-template-columns: 1fr 1fr;
68
+ }
69
+ }
70
+
71
+ .card {
72
+ background-color: var(--white);
73
+ border-radius: 10px;
74
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
75
+ padding: 25px;
76
+ transition: transform 0.3s ease;
77
+ }
78
+
79
+ .card:hover {
80
+ transform: translateY(-5px);
81
+ }
82
+
83
+ .card-title {
84
+ font-size: 1.5rem;
85
+ margin-bottom: 20px;
86
+ color: var(--primary);
87
+ display: flex;
88
+ align-items: center;
89
+ gap: 10px;
90
+ }
91
+
92
+ .card-title i {
93
+ font-size: 1.2rem;
94
+ }
95
+
96
+ .form-group {
97
+ margin-bottom: 20px;
98
+ }
99
+
100
+ label {
101
+ display: block;
102
+ margin-bottom: 8px;
103
+ font-weight: 600;
104
+ color: var(--dark);
105
+ }
106
+
107
+ input, select, textarea {
108
+ width: 100%;
109
+ padding: 12px 15px;
110
+ border: 1px solid var(--gray);
111
+ border-radius: 6px;
112
+ font-size: 1rem;
113
+ transition: border-color 0.3s;
114
+ }
115
+
116
+ input:focus, select:focus, textarea:focus {
117
+ outline: none;
118
+ border-color: var(--primary);
119
+ box-shadow: 0 0 0 3px rgba(74, 107, 223, 0.2);
120
+ }
121
+
122
+ .btn {
123
+ display: inline-block;
124
+ padding: 12px 20px;
125
+ background-color: var(--primary);
126
+ color: white;
127
+ border: none;
128
+ border-radius: 6px;
129
+ cursor: pointer;
130
+ font-size: 1rem;
131
+ font-weight: 600;
132
+ transition: all 0.3s;
133
+ text-align: center;
134
+ }
135
+
136
+ .btn:hover {
137
+ background-color: #3a56c4;
138
+ transform: translateY(-2px);
139
+ }
140
+
141
+ .btn-block {
142
+ display: block;
143
+ width: 100%;
144
+ }
145
+
146
+ .btn-secondary {
147
+ background-color: var(--secondary);
148
+ }
149
+
150
+ .btn-secondary:hover {
151
+ background-color: #5a6268;
152
+ }
153
+
154
+ .result-container {
155
+ margin-top: 20px;
156
+ padding: 20px;
157
+ background-color: var(--light);
158
+ border-radius: 6px;
159
+ border-left: 4px solid var(--primary);
160
+ }
161
+
162
+ .result-title {
163
+ font-weight: 600;
164
+ margin-bottom: 10px;
165
+ color: var(--dark);
166
+ }
167
+
168
+ .balanced-equation {
169
+ font-size: 1.2rem;
170
+ font-weight: 600;
171
+ color: var(--success);
172
+ margin: 15px 0;
173
+ padding: 10px;
174
+ background-color: rgba(40, 167, 69, 0.1);
175
+ border-radius: 5px;
176
+ text-align: center;
177
+ }
178
+
179
+ .error-message {
180
+ color: var(--danger);
181
+ margin-top: 10px;
182
+ font-weight: 500;
183
+ }
184
+
185
+ .calculation-results {
186
+ margin-top: 20px;
187
+ }
188
+
189
+ .calculation-item {
190
+ display: flex;
191
+ justify-content: space-between;
192
+ padding: 10px 0;
193
+ border-bottom: 1px solid var(--gray);
194
+ }
195
+
196
+ .calculation-item:last-child {
197
+ border-bottom: none;
198
+ }
199
+
200
+ .calculation-label {
201
+ font-weight: 600;
202
+ }
203
+
204
+ .calculation-value {
205
+ font-weight: 500;
206
+ color: var(--primary);
207
+ }
208
+
209
+ .periodic-hint {
210
+ font-size: 0.9rem;
211
+ color: var(--secondary);
212
+ margin-top: 5px;
213
+ }
214
+
215
+ .tabs {
216
+ display: flex;
217
+ margin-bottom: 20px;
218
+ border-bottom: 1px solid var(--gray);
219
+ }
220
+
221
+ .tab {
222
+ padding: 10px 20px;
223
+ cursor: pointer;
224
+ font-weight: 600;
225
+ color: var(--secondary);
226
+ border-bottom: 3px solid transparent;
227
+ transition: all 0.3s;
228
+ }
229
+
230
+ .tab.active {
231
+ color: var(--primary);
232
+ border-bottom: 3px solid var(--primary);
233
+ }
234
+
235
+ .tab-content {
236
+ display: none;
237
+ }
238
+
239
+ .tab-content.active {
240
+ display: block;
241
+ }
242
+
243
+ footer {
244
+ text-align: center;
245
+ margin-top: 50px;
246
+ padding: 20px;
247
+ color: var(--secondary);
248
+ font-size: 0.9rem;
249
+ }
250
+
251
+ .tooltip {
252
+ position: relative;
253
+ display: inline-block;
254
+ margin-left: 5px;
255
+ color: var(--secondary);
256
+ }
257
+
258
+ .tooltip .tooltiptext {
259
+ visibility: hidden;
260
+ width: 200px;
261
+ background-color: var(--dark);
262
+ color: var(--white);
263
+ text-align: center;
264
+ border-radius: 6px;
265
+ padding: 8px;
266
+ position: absolute;
267
+ z-index: 1;
268
+ bottom: 125%;
269
+ left: 50%;
270
+ transform: translateX(-50%);
271
+ opacity: 0;
272
+ transition: opacity 0.3s;
273
+ font-size: 0.8rem;
274
+ font-weight: normal;
275
+ }
276
+
277
+ .tooltip:hover .tooltiptext {
278
+ visibility: visible;
279
+ opacity: 1;
280
+ }
281
+ </style>
282
+ </head>
283
+ <body>
284
+ <div class="container">
285
+ <header>
286
+ <h1><i class="fas fa-atom"></i> ChemCalc</h1>
287
+ <p class="subtitle">Chemical Equation Balancer & Stoichiometry Calculator</p>
288
+ </header>
289
+
290
+ <div class="app-container">
291
+ <!-- Equation Balancer Card -->
292
+ <div class="card">
293
+ <h2 class="card-title"><i class="fas fa-balance-scale"></i> Equation Balancer</h2>
294
+ <div class="form-group">
295
+ <label for="unbalanced-equation">Enter Chemical Equation:</label>
296
+ <input type="text" id="unbalanced-equation" placeholder="e.g. H2 + O2 = H2O">
297
+ <p class="periodic-hint">Use standard notation (e.g. H2SO4, Ca(OH)2, NH4+)</p>
298
+ </div>
299
+ <button id="balance-btn" class="btn btn-block">Balance Equation</button>
300
+
301
+ <div id="balancer-result" class="result-container" style="display: none;">
302
+ <p class="result-title">Balanced Equation:</p>
303
+ <div id="balanced-equation" class="balanced-equation"></div>
304
+ <div id="balancer-error" class="error-message"></div>
305
+ </div>
306
+ </div>
307
+
308
+ <!-- Stoichiometry Calculator Card -->
309
+ <div class="card">
310
+ <h2 class="card-title"><i class="fas fa-calculator"></i> Stoichiometry Calculator</h2>
311
+
312
+ <div class="tabs">
313
+ <div class="tab active" data-tab="mass">Mass</div>
314
+ <div class="tab" data-tab="moles">Moles</div>
315
+ <div class="tab" data-tab="volume">Volume</div>
316
+ <div class="tab" data-tab="concentration">Concentration</div>
317
+ </div>
318
+
319
+ <div class="tab-content active" id="mass-tab">
320
+ <div class="form-group">
321
+ <label for="stoich-equation">Chemical Equation:</label>
322
+ <input type="text" id="stoich-equation" placeholder="e.g. 2H2 + O2 = 2H2O">
323
+ </div>
324
+ <div class="form-group">
325
+ <label for="known-mass-compound">Known Compound:</label>
326
+ <input type="text" id="known-mass-compound" placeholder="e.g. H2">
327
+ </div>
328
+ <div class="form-group">
329
+ <label for="known-mass-value">Known Mass (g):</label>
330
+ <input type="number" id="known-mass-value" placeholder="e.g. 5.0">
331
+ </div>
332
+ <div class="form-group">
333
+ <label for="target-mass-compound">Target Compound:</label>
334
+ <input type="text" id="target-mass-compound" placeholder="e.g. H2O">
335
+ </div>
336
+ <button id="calculate-mass-btn" class="btn btn-block">Calculate Mass</button>
337
+ </div>
338
+
339
+ <div class="tab-content" id="moles-tab">
340
+ <div class="form-group">
341
+ <label for="moles-equation">Chemical Equation:</label>
342
+ <input type="text" id="moles-equation" placeholder="e.g. 2H2 + O2 = 2H2O">
343
+ </div>
344
+ <div class="form-group">
345
+ <label for="known-moles-compound">Known Compound:</label>
346
+ <input type="text" id="known-moles-compound" placeholder="e.g. H2">
347
+ </div>
348
+ <div class="form-group">
349
+ <label for="known-moles-value">Known Moles:</label>
350
+ <input type="number" id="known-moles-value" placeholder="e.g. 2.5">
351
+ </div>
352
+ <div class="form-group">
353
+ <label for="target-moles-compound">Target Compound:</label>
354
+ <input type="text" id="target-moles-compound" placeholder="e.g. H2O">
355
+ </div>
356
+ <button id="calculate-moles-btn" class="btn btn-block">Calculate Moles</button>
357
+ </div>
358
+
359
+ <div class="tab-content" id="volume-tab">
360
+ <div class="form-group">
361
+ <label for="volume-equation">Chemical Equation:</label>
362
+ <input type="text" id="volume-equation" placeholder="e.g. 2H2 + O2 = 2H2O">
363
+ </div>
364
+ <div class="form-group">
365
+ <label for="known-volume-compound">Known Gas Compound:</label>
366
+ <input type="text" id="known-volume-compound" placeholder="e.g. O2">
367
+ </div>
368
+ <div class="form-group">
369
+ <label for="known-volume-value">Known Volume (L):</label>
370
+ <input type="number" id="known-volume-value" placeholder="e.g. 10.0">
371
+ </div>
372
+ <div class="form-group">
373
+ <label for="target-volume-compound">Target Gas Compound:</label>
374
+ <input type="text" id="target-volume-compound" placeholder="e.g. H2">
375
+ </div>
376
+ <div class="form-group">
377
+ <label for="volume-temperature">Temperature (K):</label>
378
+ <input type="number" id="volume-temperature" placeholder="298" value="298">
379
+ </div>
380
+ <div class="form-group">
381
+ <label for="volume-pressure">Pressure (atm):</label>
382
+ <input type="number" id="volume-pressure" placeholder="1.0" value="1.0">
383
+ </div>
384
+ <button id="calculate-volume-btn" class="btn btn-block">Calculate Volume</button>
385
+ </div>
386
+
387
+ <div class="tab-content" id="concentration-tab">
388
+ <div class="form-group">
389
+ <label for="conc-equation">Chemical Equation:</label>
390
+ <input type="text" id="conc-equation" placeholder="e.g. HCl + NaOH = NaCl + H2O">
391
+ </div>
392
+ <div class="form-group">
393
+ <label for="known-conc-compound">Known Solution Compound:</label>
394
+ <input type="text" id="known-conc-compound" placeholder="e.g. HCl">
395
+ </div>
396
+ <div class="form-group">
397
+ <label for="known-conc-value">Known Concentration (M):</label>
398
+ <input type="number" id="known-conc-value" placeholder="e.g. 0.1">
399
+ </div>
400
+ <div class="form-group">
401
+ <label for="known-conc-volume">Known Volume (L):</label>
402
+ <input type="number" id="known-conc-volume" placeholder="e.g. 0.025">
403
+ </div>
404
+ <div class="form-group">
405
+ <label for="target-conc-compound">Target Solution Compound:</label>
406
+ <input type="text" id="target-conc-compound" placeholder="e.g. NaOH">
407
+ </div>
408
+ <div class="form-group">
409
+ <label for="target-conc-volume">Target Volume (L):</label>
410
+ <input type="number" id="target-conc-volume" placeholder="e.g. 0.050">
411
+ </div>
412
+ <button id="calculate-conc-btn" class="btn btn-block">Calculate Concentration</button>
413
+ </div>
414
+
415
+ <div id="stoich-result" class="result-container" style="display: none;">
416
+ <p class="result-title">Calculation Results:</p>
417
+ <div id="stoich-error" class="error-message"></div>
418
+ <div id="calculation-results" class="calculation-results"></div>
419
+ </div>
420
+ </div>
421
+
422
+ <!-- Molar Mass Calculator Card -->
423
+ <div class="card">
424
+ <h2 class="card-title"><i class="fas fa-weight-hanging"></i> Molar Mass Calculator</h2>
425
+ <div class="form-group">
426
+ <label for="compound-formula">Chemical Formula:</label>
427
+ <input type="text" id="compound-formula" placeholder="e.g. C6H12O6">
428
+ <p class="periodic-hint">Enter a single compound (e.g. H2SO4, Ca(OH)2, NH4+)</p>
429
+ </div>
430
+ <button id="calculate-molar-mass-btn" class="btn btn-block">Calculate Molar Mass</button>
431
+
432
+ <div id="molar-mass-result" class="result-container" style="display: none;">
433
+ <p class="result-title">Molar Mass Calculation:</p>
434
+ <div id="molar-mass-error" class="error-message"></div>
435
+ <div id="molar-mass-results" class="calculation-results"></div>
436
+ </div>
437
+ </div>
438
+
439
+ <!-- Mole Calculator Card -->
440
+ <div class="card">
441
+ <h2 class="card-title"><i class="fas fa-vial"></i> Mole Calculator</h2>
442
+ <div class="form-group">
443
+ <label for="mole-compound">Chemical Formula:</label>
444
+ <input type="text" id="mole-compound" placeholder="e.g. NaCl">
445
+ </div>
446
+ <div class="form-group">
447
+ <label for="mole-value">Value:</label>
448
+ <input type="number" id="mole-value" placeholder="e.g. 5.0">
449
+ </div>
450
+ <div class="form-group">
451
+ <label for="mole-unit">From Unit:</label>
452
+ <select id="mole-unit">
453
+ <option value="grams">Grams (g)</option>
454
+ <option value="moles">Moles (mol)</option>
455
+ <option value="molecules">Molecules</option>
456
+ <option value="liters">Liters (L) at STP</option>
457
+ </select>
458
+ </div>
459
+ <button id="calculate-mole-btn" class="btn btn-block">Convert</button>
460
+
461
+ <div id="mole-result" class="result-container" style="display: none;">
462
+ <p class="result-title">Conversion Results:</p>
463
+ <div id="mole-error" class="error-message"></div>
464
+ <div id="mole-results" class="calculation-results"></div>
465
+ </div>
466
+ </div>
467
+ </div>
468
+
469
+ <footer>
470
+ <p>ChemCalc &copy; 2023 | A comprehensive chemical equation and stoichiometry calculator</p>
471
+ </footer>
472
+ </div>
473
+
474
+ <script>
475
+ // Periodic table data (simplified)
476
+ const periodicTable = {
477
+ "H": { name: "Hydrogen", mass: 1.008 },
478
+ "He": { name: "Helium", mass: 4.0026 },
479
+ "Li": { name: "Lithium", mass: 6.94 },
480
+ "Be": { name: "Beryllium", mass: 9.0122 },
481
+ "B": { name: "Boron", mass: 10.81 },
482
+ "C": { name: "Carbon", mass: 12.011 },
483
+ "N": { name: "Nitrogen", mass: 14.007 },
484
+ "O": { name: "Oxygen", mass: 15.999 },
485
+ "F": { name: "Fluorine", mass: 18.998 },
486
+ "Ne": { name: "Neon", mass: 20.180 },
487
+ "Na": { name: "Sodium", mass: 22.990 },
488
+ "Mg": { name: "Magnesium", mass: 24.305 },
489
+ "Al": { name: "Aluminum", mass: 26.982 },
490
+ "Si": { name: "Silicon", mass: 28.085 },
491
+ "P": { name: "Phosphorus", mass: 30.974 },
492
+ "S": { name: "Sulfur", mass: 32.06 },
493
+ "Cl": { name: "Chlorine", mass: 35.45 },
494
+ "Ar": { name: "Argon", mass: 39.948 },
495
+ "K": { name: "Potassium", mass: 39.098 },
496
+ "Ca": { name: "Calcium", mass: 40.078 },
497
+ "Sc": { name: "Scandium", mass: 44.956 },
498
+ "Ti": { name: "Titanium", mass: 47.867 },
499
+ "V": { name: "Vanadium", mass: 50.942 },
500
+ "Cr": { name: "Chromium", mass: 51.996 },
501
+ "Mn": { name: "Manganese", mass: 54.938 },
502
+ "Fe": { name: "Iron", mass: 55.845 },
503
+ "Co": { name: "Cobalt", mass: 58.933 },
504
+ "Ni": { name: "Nickel", mass: 58.693 },
505
+ "Cu": { name: "Copper", mass: 63.546 },
506
+ "Zn": { name: "Zinc", mass: 65.38 },
507
+ "Ga": { name: "Gallium", mass: 69.723 },
508
+ "Ge": { name: "Germanium", mass: 72.630 },
509
+ "As": { name: "Arsenic", mass: 74.922 },
510
+ "Se": { name: "Selenium", mass: 78.971 },
511
+ "Br": { name: "Bromine", mass: 79.904 },
512
+ "Kr": { name: "Krypton", mass: 83.798 },
513
+ "Rb": { name: "Rubidium", mass: 85.468 },
514
+ "Sr": { name: "Strontium", mass: 87.62 },
515
+ "Y": { name: "Yttrium", mass: 88.906 },
516
+ "Zr": { name: "Zirconium", mass: 91.224 },
517
+ "Nb": { name: "Niobium", mass: 92.906 },
518
+ "Mo": { name: "Molybdenum", mass: 95.95 },
519
+ "Tc": { name: "Technetium", mass: 98.0 },
520
+ "Ru": { name: "Ruthenium", mass: 101.07 },
521
+ "Rh": { name: "Rhodium", mass: 102.91 },
522
+ "Pd": { name: "Palladium", mass: 106.42 },
523
+ "Ag": { name: "Silver", mass: 107.87 },
524
+ "Cd": { name: "Cadmium", mass: 112.41 },
525
+ "In": { name: "Indium", mass: 114.82 },
526
+ "Sn": { name: "Tin", mass: 118.71 },
527
+ "Sb": { name: "Antimony", mass: 121.76 },
528
+ "Te": { name: "Tellurium", mass: 127.60 },
529
+ "I": { name: "Iodine", mass: 126.90 },
530
+ "Xe": { name: "Xenon", mass: 131.29 },
531
+ "Cs": { name: "Cesium", mass: 132.91 },
532
+ "Ba": { name: "Barium", mass: 137.33 },
533
+ "La": { name: "Lanthanum", mass: 138.91 },
534
+ "Ce": { name: "Cerium", mass: 140.12 },
535
+ "Pr": { name: "Praseodymium", mass: 140.91 },
536
+ "Nd": { name: "Neodymium", mass: 144.24 },
537
+ "Pm": { name: "Promethium", mass: 145.0 },
538
+ "Sm": { name: "Samarium", mass: 150.36 },
539
+ "Eu": { name: "Europium", mass: 151.96 },
540
+ "Gd": { name: "Gadolinium", mass: 157.25 },
541
+ "Tb": { name: "Terbium", mass: 158.93 },
542
+ "Dy": { name: "Dysprosium", mass: 162.50 },
543
+ "Ho": { name: "Holmium", mass: 164.93 },
544
+ "Er": { name: "Erbium", mass: 167.26 },
545
+ "Tm": { name: "Thulium", mass: 168.93 },
546
+ "Yb": { name: "Ytterbium", mass: 173.05 },
547
+ "Lu": { name: "Lutetium", mass: 174.97 },
548
+ "Hf": { name: "Hafnium", mass: 178.49 },
549
+ "Ta": { name: "Tantalum", mass: 180.95 },
550
+ "W": { name: "Tungsten", mass: 183.84 },
551
+ "Re": { name: "Rhenium", mass: 186.21 },
552
+ "Os": { name: "Osmium", mass: 190.23 },
553
+ "Ir": { name: "Iridium", mass: 192.22 },
554
+ "Pt": { name: "Platinum", mass: 195.08 },
555
+ "Au": { name: "Gold", mass: 196.97 },
556
+ "Hg": { name: "Mercury", mass: 200.59 },
557
+ "Tl": { name: "Thallium", mass: 204.38 },
558
+ "Pb": { name: "Lead", mass: 207.2 },
559
+ "Bi": { name: "Bismuth", mass: 208.98 },
560
+ "Po": { name: "Polonium", mass: 209.0 },
561
+ "At": { name: "Astatine", mass: 210.0 },
562
+ "Rn": { name: "Radon", mass: 222.0 },
563
+ "Fr": { name: "Francium", mass: 223.0 },
564
+ "Ra": { name: "Radium", mass: 226.0 },
565
+ "Ac": { name: "Actinium", mass: 227.0 },
566
+ "Th": { name: "Thorium", mass: 232.04 },
567
+ "Pa": { name: "Protactinium", mass: 231.04 },
568
+ "U": { name: "Uranium", mass: 238.03 },
569
+ "Np": { name: "Neptunium", mass: 237.0 },
570
+ "Pu": { name: "Plutonium", mass: 244.0 },
571
+ "Am": { name: "Americium", mass: 243.0 },
572
+ "Cm": { name: "Curium", mass: 247.0 },
573
+ "Bk": { name: "Berkelium", mass: 247.0 },
574
+ "Cf": { name: "Californium", mass: 251.0 },
575
+ "Es": { name: "Einsteinium", mass: 252.0 },
576
+ "Fm": { name: "Fermium", mass: 257.0 },
577
+ "Md": { name: "Mendelevium", mass: 258.0 },
578
+ "No": { name: "Nobelium", mass: 259.0 },
579
+ "Lr": { name: "Lawrencium", mass: 262.0 },
580
+ "Rf": { name: "Rutherfordium", mass: 267.0 },
581
+ "Db": { name: "Dubnium", mass: 270.0 },
582
+ "Sg": { name: "Seaborgium", mass: 271.0 },
583
+ "Bh": { name: "Bohrium", mass: 270.0 },
584
+ "Hs": { name: "Hassium", mass: 277.0 },
585
+ "Mt": { name: "Meitnerium", mass: 276.0 },
586
+ "Ds": { name: "Darmstadtium", mass: 281.0 },
587
+ "Rg": { name: "Roentgenium", mass: 280.0 },
588
+ "Cn": { name: "Copernicium", mass: 285.0 },
589
+ "Nh": { name: "Nihonium", mass: 286.0 },
590
+ "Fl": { name: "Flerovium", mass: 289.0 },
591
+ "Mc": { name: "Moscovium", mass: 290.0 },
592
+ "Lv": { name: "Livermorium", mass: 293.0 },
593
+ "Ts": { name: "Tennessine", mass: 294.0 },
594
+ "Og": { name: "Oganesson", mass: 294.0 }
595
+ };
596
+
597
+ // Tab functionality
598
+ document.querySelectorAll('.tab').forEach(tab => {
599
+ tab.addEventListener('click', () => {
600
+ // Remove active class from all tabs and contents
601
+ document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
602
+ document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
603
+
604
+ // Add active class to clicked tab and corresponding content
605
+ tab.classList.add('active');
606
+ const tabId = tab.getAttribute('data-tab');
607
+ document.getElementById(`${tabId}-tab`).classList.add('active');
608
+ });
609
+ });
610
+
611
+ // Helper function to parse chemical formulas
612
+ function parseFormula(formula) {
613
+ const elements = {};
614
+ let currentElement = '';
615
+ let currentCount = '';
616
+ let inParenthesis = false;
617
+ let parenthesisContent = '';
618
+ let parenthesisMultiplier = '';
619
+
620
+ for (let i = 0; i < formula.length; i++) {
621
+ const char = formula[i];
622
+
623
+ // Handle uppercase letters (start of new element)
624
+ if (char === char.toUpperCase() && char !== char.toLowerCase()) {
625
+ if (currentElement) {
626
+ const count = currentCount ? parseInt(currentCount) : 1;
627
+ if (periodicTable[currentElement]) {
628
+ elements[currentElement] = (elements[currentElement] || 0) + count;
629
+ } else {
630
+ return { error: `Unknown element: ${currentElement}` };
631
+ }
632
+ }
633
+ currentElement = char;
634
+ currentCount = '';
635
+ }
636
+ // Handle lowercase letters (part of element symbol)
637
+ else if (char === char.toLowerCase() && char !== char.toUpperCase()) {
638
+ currentElement += char;
639
+ }
640
+ // Handle digits (count of element)
641
+ else if (!isNaN(char)) {
642
+ currentCount += char;
643
+ }
644
+ // Handle opening parenthesis
645
+ else if (char === '(') {
646
+ if (currentElement) {
647
+ const count = currentCount ? parseInt(currentCount) : 1;
648
+ if (periodicTable[currentElement]) {
649
+ elements[currentElement] = (elements[currentElement] || 0) + count;
650
+ } else {
651
+ return { error: `Unknown element: ${currentElement}` };
652
+ }
653
+ }
654
+ currentElement = '';
655
+ currentCount = '';
656
+ inParenthesis = true;
657
+ parenthesisContent = '';
658
+ parenthesisMultiplier = '';
659
+ }
660
+ // Handle closing parenthesis
661
+ else if (char === ')') {
662
+ inParenthesis = false;
663
+ i++; // Skip to next character to check for multiplier
664
+
665
+ // Get the multiplier after parenthesis
666
+ while (i < formula.length && !isNaN(formula[i])) {
667
+ parenthesisMultiplier += formula[i];
668
+ i++;
669
+ }
670
+ i--; // Adjust index since we'll increment in next loop iteration
671
+
672
+ const subElements = parseFormula(parenthesisContent);
673
+ if (subElements.error) return subElements;
674
+
675
+ const multiplier = parenthesisMultiplier ? parseInt(parenthesisMultiplier) : 1;
676
+ for (const el in subElements) {
677
+ elements[el] = (elements[el] || 0) + (subElements[el] * multiplier);
678
+ }
679
+ }
680
+ // Handle content inside parenthesis
681
+ else if (inParenthesis) {
682
+ parenthesisContent += char;
683
+ }
684
+ }
685
+
686
+ // Add the last element
687
+ if (currentElement) {
688
+ const count = currentCount ? parseInt(currentCount) : 1;
689
+ if (periodicTable[currentElement]) {
690
+ elements[currentElement] = (elements[currentElement] || 0) + count;
691
+ } else {
692
+ return { error: `Unknown element: ${currentElement}` };
693
+ }
694
+ }
695
+
696
+ return elements;
697
+ }
698
+
699
+ // Helper function to calculate molar mass
700
+ function calculateMolarMass(formula) {
701
+ const elements = parseFormula(formula);
702
+ if (elements.error) return elements;
703
+
704
+ let molarMass = 0;
705
+ for (const el in elements) {
706
+ molarMass += periodicTable[el].mass * elements[el];
707
+ }
708
+
709
+ return {
710
+ molarMass: molarMass,
711
+ elements: elements
712
+ };
713
+ }
714
+
715
+ // Helper function to parse chemical equation
716
+ function parseEquation(equation) {
717
+ // Split into reactants and products
718
+ const sides = equation.split('=').map(s => s.trim());
719
+ if (sides.length !== 2) {
720
+ return { error: "Equation must have exactly one '=' sign" };
721
+ }
722
+
723
+ const reactants = sides[0].split('+').map(s => s.trim());
724
+ const products = sides[1].split('+').map(s => s.trim());
725
+
726
+ // Parse all compounds
727
+ const allCompounds = [...reactants, ...products];
728
+ const parsedCompounds = [];
729
+
730
+ for (const compound of allCompounds) {
731
+ // Extract coefficient if present
732
+ let coefficient = 1;
733
+ let formula = compound;
734
+
735
+ const coefficientMatch = compound.match(/^(\d+)/);
736
+ if (coefficientMatch) {
737
+ coefficient = parseInt(coefficientMatch[1]);
738
+ formula = compound.slice(coefficientMatch[0].length).trim();
739
+ }
740
+
741
+ const molarMassResult = calculateMolarMass(formula);
742
+ if (molarMassResult.error) {
743
+ return { error: molarMassResult.error };
744
+ }
745
+
746
+ parsedCompounds.push({
747
+ formula: formula,
748
+ coefficient: coefficient,
749
+ molarMass: molarMassResult.molarMass,
750
+ elements: molarMassResult.elements
751
+ });
752
+ }
753
+
754
+ return {
755
+ reactants: parsedCompounds.slice(0, reactants.length),
756
+ products: parsedCompounds.slice(reactants.length),
757
+ allElements: getAllElements(parsedCompounds)
758
+ };
759
+ }
760
+
761
+ // Helper function to get all unique elements in equation
762
+ function getAllElements(compounds) {
763
+ const elements = new Set();
764
+ for (const compound of compounds) {
765
+ for (const el in compound.elements) {
766
+ elements.add(el);
767
+ }
768
+ }
769
+ return Array.from(elements);
770
+ }
771
+
772
+ // Helper function to balance equation (simplified algorithm)
773
+ function balanceEquation(equation) {
774
+ const parsed = parseEquation(equation);
775
+ if (parsed.error) return parsed;
776
+
777
+ // This is a simplified balancing algorithm
778
+ // In a real application, you would implement a more robust matrix-based approach
779
+ const { reactants, products } = parsed;
780
+
781
+ // Count total atoms per element on each side
782
+ const elementCounts = {};
783
+ for (const el of parsed.allElements) {
784
+ elementCounts[el] = { reactant: 0, product: 0 };
785
+ }
786
+
787
+ for (const compound of reactants) {
788
+ for (const el in compound.elements) {
789
+ elementCounts[el].reactant += compound.coefficient * compound.elements[el];
790
+ }
791
+ }
792
+
793
+ for (const compound of products) {
794
+ for (const el in compound.elements) {
795
+ elementCounts[el].product += compound.coefficient * compound.elements[el];
796
+ }
797
+ }
798
+
799
+ // Check if already balanced
800
+ let isBalanced = true;
801
+ for (const el in elementCounts) {
802
+ if (elementCounts[el].reactant !== elementCounts[el].product) {
803
+ isBalanced = false;
804
+ break;
805
+ }
806
+ }
807
+
808
+ if (isBalanced) {
809
+ return {
810
+ balancedEquation: equation,
811
+ coefficients: {
812
+ reactants: reactants.map(c => c.coefficient),
813
+ products: products.map(c => c.coefficient)
814
+ }
815
+ };
816
+ }
817
+
818
+ // Try to balance simple equations (this is very simplified)
819
+ if (reactants.length === 2 && products.length === 1) {
820
+ // A + B = AB type
821
+ const newCoefficients = {
822
+ reactants: [1, 1],
823
+ products: [1]
824
+ };
825
+
826
+ // Verify balance
827
+ let balanced = true;
828
+ for (const el in elementCounts) {
829
+ const left = newCoefficients.reactants[0] * (reactants[0].elements[el] || 0) +
830
+ newCoefficients.reactants[1] * (reactants[1].elements[el] || 0);
831
+ const right = newCoefficients.products[0] * (products[0].elements[el] || 0);
832
+
833
+ if (left !== right) {
834
+ balanced = false;
835
+ break;
836
+ }
837
+ }
838
+
839
+ if (balanced) {
840
+ const balancedEq = `${newCoefficients.reactants[0]}${reactants[0].formula} + ${newCoefficients.reactants[1]}${reactants[1].formula} = ${newCoefficients.products[0]}${products[0].formula}`;
841
+ return {
842
+ balancedEquation: balancedEq,
843
+ coefficients: newCoefficients
844
+ };
845
+ }
846
+ }
847
+
848
+ // If we can't balance it with simple rules, return an error
849
+ return { error: "Unable to balance this equation automatically. Try a simpler equation or balance manually." };
850
+ }
851
+
852
+ // Helper function to perform stoichiometry calculation
853
+ function performStoichiometry(equation, knownCompound, knownValue, targetCompound, calculationType) {
854
+ const parsed = parseEquation(equation);
855
+ if (parsed.error) return parsed;
856
+
857
+ // Find known and target compounds
858
+ const allCompounds = [...parsed.reactants, ...parsed.products];
859
+ const known = allCompounds.find(c => c.formula === knownCompound);
860
+ const target = allCompounds.find(c => c.formula === targetCompound);
861
+
862
+ if (!known) return { error: `Compound ${knownCompound} not found in equation` };
863
+ if (!target) return { error: `Compound ${targetCompound} not found in equation` };
864
+
865
+ // Calculate moles of known compound
866
+ let knownMoles;
867
+ if (calculationType === 'mass') {
868
+ knownMoles = knownValue / known.molarMass;
869
+ } else if (calculationType === 'moles') {
870
+ knownMoles = knownValue;
871
+ } else if (calculationType === 'volume') {
872
+ // Using ideal gas law: PV = nRT => n = PV/RT
873
+ const pressure = parseFloat(document.getElementById('volume-pressure').value) || 1.0;
874
+ const temperature = parseFloat(document.getElementById('volume-temperature').value) || 298;
875
+ const R = 0.0821; // L·atm/(K·mol)
876
+ knownMoles = (pressure * knownValue) / (R * temperature);
877
+ } else if (calculationType === 'concentration') {
878
+ const volume = parseFloat(document.getElementById('known-conc-volume').value);
879
+ if (!volume) return { error: "Known volume is required for concentration calculations" };
880
+ knownMoles = knownValue * volume;
881
+ }
882
+
883
+ // Calculate moles of target compound using stoichiometric ratios
884
+ const targetMoles = knownMoles * (target.coefficient / known.coefficient);
885
+
886
+ // Calculate final value based on calculation type
887
+ let resultValue;
888
+ if (calculationType === 'mass') {
889
+ resultValue = targetMoles * target.molarMass;
890
+ } else if (calculationType === 'moles') {
891
+ resultValue = targetMoles;
892
+ } else if (calculationType === 'volume') {
893
+ // Using ideal gas law: V = nRT/P
894
+ const pressure = parseFloat(document.getElementById('volume-pressure').value) || 1.0;
895
+ const temperature = parseFloat(document.getElementById('volume-temperature').value) || 298;
896
+ const R = 0.0821; // L·atm/(K·mol)
897
+ resultValue = (targetMoles * R * temperature) / pressure;
898
+ } else if (calculationType === 'concentration') {
899
+ const volume = parseFloat(document.getElementById('target-conc-volume').value);
900
+ if (!volume) return { error: "Target volume is required for concentration calculations" };
901
+ resultValue = targetMoles / volume;
902
+ }
903
+
904
+ return {
905
+ knownMoles: knownMoles,
906
+ targetMoles: targetMoles,
907
+ resultValue: resultValue,
908
+ calculationType: calculationType,
909
+ knownCompound: knownCompound,
910
+ targetCompound: targetCompound
911
+ };
912
+ }
913
+
914
+ // Helper function to perform mole conversions
915
+ function performMoleConversion(compound, value, fromUnit, toUnits = ['grams', 'moles', 'molecules', 'liters']) {
916
+ const molarMassResult = calculateMolarMass(compound);
917
+ if (molarMassResult.error) return molarMassResult;
918
+
919
+ const molarMass = molarMassResult.molarMass;
920
+ const AVOGADRO = 6.022e23;
921
+ const STP_VOLUME = 22.4; // L/mol at STP
922
+
923
+ // Convert input value to moles first
924
+ let moles;
925
+ switch (fromUnit) {
926
+ case 'grams':
927
+ moles = value / molarMass;
928
+ break;
929
+ case 'moles':
930
+ moles = value;
931
+ break;
932
+ case 'molecules':
933
+ moles = value / AVOGADRO;
934
+ break;
935
+ case 'liters':
936
+ moles = value / STP_VOLUME;
937
+ break;
938
+ default:
939
+ return { error: "Invalid unit" };
940
+ }
941
+
942
+ // Convert moles to all other units
943
+ const results = {};
944
+ for (const unit of toUnits) {
945
+ switch (unit) {
946
+ case 'grams':
947
+ results.grams = moles * molarMass;
948
+ break;
949
+ case 'moles':
950
+ results.moles = moles;
951
+ break;
952
+ case 'molecules':
953
+ results.molecules = moles * AVOGADRO;
954
+ break;
955
+ case 'liters':
956
+ results.liters = moles * STP_VOLUME;
957
+ break;
958
+ }
959
+ }
960
+
961
+ return {
962
+ compound: compound,
963
+ molarMass: molarMass,
964
+ initialValue: value,
965
+ initialUnit: fromUnit,
966
+ moles: moles,
967
+ results: results
968
+ };
969
+ }
970
+
971
+ // Event listeners
972
+ document.getElementById('balance-btn').addEventListener('click', () => {
973
+ const equation = document.getElementById('unbalanced-equation').value.trim();
974
+ if (!equation) {
975
+ document.getElementById('balancer-error').textContent = "Please enter an equation to balance";
976
+ document.getElementById('balancer-result').style.display = 'block';
977
+ return;
978
+ }
979
+
980
+ const result = balanceEquation(equation);
981
+ const resultContainer = document.getElementById('balancer-result');
982
+ resultContainer.style.display = 'block';
983
+
984
+ if (result.error) {
985
+ document.getElementById('balancer-error').textContent = result.error;
986
+ document.getElementById('balanced-equation').textContent = '';
987
+ } else {
988
+ document.getElementById('balancer-error').textContent = '';
989
+ document.getElementById('balanced-equation').textContent = result.balancedEquation;
990
+ }
991
+ });
992
+
993
+ // Mass calculation
994
+ document.getElementById('calculate-mass-btn').addEventListener('click', () => {
995
+ const equation = document.getElementById('stoich-equation').value.trim();
996
+ const knownCompound = document.getElementById('known-mass-compound').value.trim();
997
+ const knownValue = parseFloat(document.getElementById('known-mass-value').value);
998
+ const targetCompound = document.getElementById('target-mass-compound').value.trim();
999
+
1000
+ if (!equation || !knownCompound || isNaN(knownValue) || !targetCompound) {
1001
+ showStoichError("Please fill in all fields with valid values");
1002
+ return;
1003
+ }
1004
+
1005
+ const result = performStoichiometry(equation, knownCompound, knownValue, targetCompound, 'mass');
1006
+ displayStoichResult(result);
1007
+ });
1008
+
1009
+ // Moles calculation
1010
+ document.getElementById('calculate-moles-btn').addEventListener('click', () => {
1011
+ const equation = document.getElementById('moles-equation').value.trim();
1012
+ const knownCompound = document.getElementById('known-moles-compound').value.trim();
1013
+ const knownValue = parseFloat(document.getElementById('known-moles-value').value);
1014
+ const targetCompound = document.getElementById('target-moles-compound').value.trim();
1015
+
1016
+ if (!equation || !knownCompound || isNaN(knownValue) || !targetCompound) {
1017
+ showStoichError("Please fill in all fields with valid values");
1018
+ return;
1019
+ }
1020
+
1021
+ const result = performStoichiometry(equation, knownCompound, knownValue, targetCompound, 'moles');
1022
+ displayStoichResult(result);
1023
+ });
1024
+
1025
+ // Volume calculation
1026
+ document.getElementById('calculate-volume-btn').addEventListener('click', () => {
1027
+ const equation = document.getElementById('volume-equation').value.trim();
1028
+ const knownCompound = document.getElementById('known-volume-compound').value.trim();
1029
+ const knownValue = parseFloat(document.getElementById('known-volume-value').value);
1030
+ const targetCompound = document.getElementById('target-volume-compound').value.trim();
1031
+
1032
+ if (!equation || !knownCompound || isNaN(knownValue) || !targetCompound) {
1033
+ showStoichError("Please fill in all fields with valid values");
1034
+ return;
1035
+ }
1036
+
1037
+ const result = performStoichiometry(equation, knownCompound, knownValue, targetCompound, 'volume');
1038
+ displayStoichResult(result);
1039
+ });
1040
+
1041
+ // Concentration calculation
1042
+ document.getElementById('calculate-conc-btn').addEventListener('click', () => {
1043
+ const equation = document.getElementById('conc-equation').value.trim();
1044
+ const knownCompound = document.getElementById('known-conc-compound').value.trim();
1045
+ const knownValue = parseFloat(document.getElementById('known-conc-value').value);
1046
+ const targetCompound = document.getElementById('target-conc-compound').value.trim();
1047
+
1048
+ if (!equation || !knownCompound || isNaN(knownValue) || !targetCompound) {
1049
+ showStoichError("Please fill in all fields with valid values");
1050
+ return;
1051
+ }
1052
+
1053
+ const result = performStoichiometry(equation, knownCompound, knownValue, targetCompound, 'concentration');
1054
+ displayStoichResult(result);
1055
+ });
1056
+
1057
+ // Molar mass calculation
1058
+ document.getElementById('calculate-molar-mass-btn').addEventListener('click', () => {
1059
+ const formula = document.getElementById('compound-formula').value.trim();
1060
+ if (!formula) {
1061
+ showMolarMassError("Please enter a chemical formula");
1062
+ return;
1063
+ }
1064
+
1065
+ const result = calculateMolarMass(formula);
1066
+ const resultContainer = document.getElementById('molar-mass-result');
1067
+ resultContainer.style.display = 'block';
1068
+
1069
+ if (result.error) {
1070
+ showMolarMassError(result.error);
1071
+ document.getElementById('molar-mass-results').innerHTML = '';
1072
+ } else {
1073
+ document.getElementById('molar-mass-error').textContent = '';
1074
+
1075
+ let html = `
1076
+ <div class="calculation-item">
1077
+ <span class="calculation-label">Molar Mass:</span>
1078
+ <span class="calculation-value">${result.molarMass.toFixed(4)} g/mol</span>
1079
+ </div>
1080
+ <div class="calculation-item">
1081
+ <span class="calculation-label">Composition:</span>
1082
+ <span class="calculation-value"></span>
1083
+ </div>
1084
+ `;
1085
+
1086
+ for (const el in result.elements) {
1087
+ html += `
1088
+ <div class="calculation-item" style="padding-left: 20px;">
1089
+ <span class="calculation-label">${el} (${periodicTable[el].name}):</span>
1090
+ <span class="calculation-value">${result.elements[el]} atom(s) × ${periodicTable[el].mass.toFixed(4)} g/mol = ${(result.elements[el] * periodicTable[el].mass).toFixed(4)} g/mol</span>
1091
+ </div>
1092
+ `;
1093
+ }
1094
+
1095
+ document.getElementById('molar-mass-results').innerHTML = html;
1096
+ }
1097
+ });
1098
+
1099
+ // Mole conversion calculation
1100
+ document.getElementById('calculate-mole-btn').addEventListener('click', () => {
1101
+ const compound = document.getElementById('mole-compound').value.trim();
1102
+ const value = parseFloat(document.getElementById('mole-value').value);
1103
+ const fromUnit = document.getElementById('mole-unit').value;
1104
+
1105
+ if (!compound || isNaN(value)) {
1106
+ showMoleError("Please enter a valid compound and value");
1107
+ return;
1108
+ }
1109
+
1110
+ const result = performMoleConversion(compound, value, fromUnit);
1111
+ const resultContainer = document.getElementById('mole-result');
1112
+ resultContainer.style.display = 'block';
1113
+
1114
+ if (result.error) {
1115
+ showMoleError(result.error);
1116
+ document.getElementById('mole-results').innerHTML = '';
1117
+ } else {
1118
+ document.getElementById('mole-error').textContent = '';
1119
+
1120
+ let html = `
1121
+ <div class="calculation-item">
1122
+ <span class="calculation-label">Molar Mass:</span>
1123
+ <span class="calculation-value">${result.molarMass.toFixed(4)} g/mol</span>
1124
+ </div>
1125
+ <div class="calculation-item">
1126
+ <span class="calculation-label">Initial Value:</span>
1127
+ <span class="calculation-value">${value} ${fromUnit}</span>
1128
+ </div>
1129
+ <div class="calculation-item">
1130
+ <span class="calculation-label">Moles:</span>
1131
+ <span class="calculation-value">${result.moles.toExponential(4)} mol</span>
1132
+ </div>
1133
+ `;
1134
+
1135
+ if (fromUnit !== 'grams') {
1136
+ html += `
1137
+ <div class="calculation-item">
1138
+ <span class="calculation-label">Mass:</span>
1139
+ <span class="calculation-value">${result.results.grams.toExponential(4)} g</span>
1140
+ </div>
1141
+ `;
1142
+ }
1143
+
1144
+ if (fromUnit !== 'moles') {
1145
+ html += `
1146
+ <div class="calculation-item">
1147
+ <span class="calculation-label">Moles:</span>
1148
+ <span class="calculation-value">${result.moles.toExponential(4)} mol</span>
1149
+ </div
1150
+ </html>h