-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
966 lines (886 loc) · 59.3 KB
/
index.html
File metadata and controls
966 lines (886 loc) · 59.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Феноменология духовного отчаяния</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,600;0,700;1,400&family=Lora:ital,wght@0,400;0,500;0,600;0,700;1,400&family=Inter:wght@300;400;500;600&display=swap" rel="stylesheet">
<style>
/* Typography & Palette */
:root { --radius: 0.5rem; }
body {
font-family: 'Lora', serif;
background-color: #fafaf9; /* stone-50 */
color: #292524; /* stone-800 */
overflow-x: hidden;
scroll-behavior: smooth;
}
h1, h2, h3, h4, .serif-font { font-family: 'Playfair Display', serif; }
.ui-font { font-family: 'Inter', sans-serif; }
/* Interactive Cards */
.mech-card {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer;
overflow: hidden;
height: auto;
min-height: 220px;
position: relative;
z-index: 10;
background-color: white;
}
.mech-card:hover {
transform: translateY(-4px);
box-shadow: 0 10px 20px -3px rgba(0, 0, 0, 0.15);
border-color: #a8a29e;
}
.card-details {
max-height: 0;
opacity: 0;
overflow: hidden;
transition: all 0.4s ease-out;
}
.mech-card.active .card-details {
max-height: 800px;
opacity: 1;
margin-top: 1rem;
padding-top: 1rem;
border-top: 1px solid #e7e5e4;
}
.mech-card.active {
background-color: #fffbeb; /* amber-50 */
border-color: #d97706; /* amber-600 */
}
.card-chevron { transition: transform 0.3s ease; }
.mech-card.active .card-chevron { transform: rotate(180deg); }
/* Chart */
.chart-container { position: relative; width: 100%; height: 350px; }
/* Article Typography - Left Aligned with Hyphens */
.article-content {
max-width: 75ch;
margin: 0 auto;
font-size: 1.125rem;
line-height: 1.8;
}
.article-content p {
margin-bottom: 1.5rem;
text-align: left;
-webkit-hyphens: auto;
-ms-hyphens: auto;
hyphens: auto;
}
.article-content h3 {
font-size: 1.75rem;
font-weight: 700;
margin-top: 3.5rem;
margin-bottom: 1.5rem;
color: #1c1917;
font-family: 'Playfair Display', serif;
border-bottom: 1px solid #e7e5e4;
padding-bottom: 0.5rem;
}
.article-content h4 {
font-size: 1.25rem;
font-weight: 600;
margin-top: 2rem;
margin-bottom: 1rem;
color: #44403c;
font-family: 'Inter', sans-serif;
}
.article-content ul { list-style-type: disc; padding-left: 1.5rem; margin-bottom: 1.5rem; }
.article-content li { margin-bottom: 0.5rem; }
.article-content blockquote {
border-left: 4px solid #b45309;
padding-left: 1.5rem;
margin: 2rem 0;
font-style: italic;
color: #57534e;
background: rgba(251, 191, 36, 0.05);
padding: 1.5rem;
border-radius: 0 0.5rem 0.5rem 0;
}
/* --- Floating Widget --- */
.chat-widget {
position: fixed;
bottom: 24px;
right: 24px;
z-index: 100;
pointer-events: none;
display: flex;
flex-direction: column;
align-items: flex-end;
}
.chat-window {
width: 380px;
height: 600px;
max-height: 70vh;
background: white;
border: 1px solid #e5e5e5;
border-radius: 12px;
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
display: flex;
flex-direction: column;
overflow: hidden;
opacity: 0;
transform: translateY(20px) scale(0.95);
visibility: hidden;
transition: opacity 0.3s cubic-bezier(0.16, 1, 0.3, 1), transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), visibility 0s linear 0.3s;
margin-bottom: 16px;
pointer-events: none;
}
.chat-widget.open .chat-window {
opacity: 1;
transform: translateY(0) scale(1);
visibility: visible;
pointer-events: auto;
transition-delay: 0s;
}
.chat-toggle {
width: 56px;
height: 56px;
border-radius: 28px;
background-color: #1c1917;
color: white;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
cursor: pointer;
transition: all 0.3s ease;
pointer-events: auto;
z-index: 101;
}
.chat-toggle:hover { transform: scale(1.05); background-color: #44403c; }
.chat-widget.open .chat-toggle { transform: rotate(90deg); background-color: #292524; }
/* Animations */
.fade-in { animation: fadeIn 0.5s ease-out; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.loader {
border: 2px solid #f3f3f3;
border-top: 2px solid #854d0e;
border-radius: 50%;
width: 16px;
height: 16px;
animation: spin 1s linear infinite;
}
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
/* Modal */
.modal-backdrop { background-color: rgba(0, 0, 0, 0.6); backdrop-filter: blur(2px); z-index: 200; }
/* Mobile Layout Adjustments */
@media (max-width: 768px) {
.chat-widget.open .chat-window {
position: fixed;
inset: 0;
width: 100%;
height: 100%;
max-height: 100%;
border-radius: 0;
margin-bottom: 0;
z-index: 300;
}
.chat-widget { bottom: 16px; right: 16px; }
/* Hide toggle when window is open on mobile to prevent overlap */
.chat-widget.open .chat-toggle { z-index: 50; opacity: 0; pointer-events: none; }
}
/* Side Menu (Mobile) */
.side-menu-overlay {
position: fixed;
inset: 0;
background-color: rgba(0,0,0,0.5);
z-index: 140;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease;
backdrop-filter: blur(2px);
}
.side-menu-overlay.open { opacity: 1; visibility: visible; }
.side-menu {
position: fixed;
top: 0;
right: 0;
height: 100%;
width: 280px;
background-color: #1c1917;
z-index: 150;
transform: translateX(100%);
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: -5px 0 15px rgba(0,0,0,0.1);
display: flex;
flex-direction: column;
padding: 2rem;
}
.side-menu.open { transform: translateX(0); }
</style>
</head>
<body class="antialiased min-h-screen flex flex-col">
<!-- Header -->
<header class="w-full bg-[#1c1917] text-[#e7e5e4] shadow-lg sticky top-0 z-40 border-b border-stone-800 backdrop-blur-md bg-opacity-95">
<div class="max-w-7xl mx-auto px-6 py-4 flex justify-between items-center">
<!-- Logo area -->
<div class="text-left cursor-pointer" onclick="navigateTo('main', 'top')">
<h1 class="text-lg font-bold leading-tight font-serif tracking-wide text-amber-50">Феноменология духовного отчаяния</h1>
<p class="text-[10px] text-stone-400 ui-font uppercase tracking-widest mt-1">и стратегии демонической клеветы</p>
</div>
<!-- Desktop Nav -->
<nav class="hidden md:flex items-center gap-6 ui-font text-sm font-medium text-stone-300">
<button onclick="navigateTo('main', 'top')" class="hover:text-white transition">Главная</button>
<button onclick="navigateTo('main', 'mechanism')" class="hover:text-white transition">Механика</button>
<button onclick="navigateTo('main', 'analysis')" class="hover:text-white transition">Различение</button>
<button onclick="navigateTo('main', 'witnesses')" class="hover:text-white transition">Святые</button>
<div class="h-4 w-px bg-stone-700 mx-2"></div>
<button onclick="switchView('article')" id="nav-article" class="hover:text-amber-200 transition font-bold">Полная Статья</button>
<button onclick="openSettings()" class="p-2 rounded-full hover:bg-stone-800 transition text-stone-400 hover:text-white" title="Настройки API">
<i data-lucide="key" class="w-4 h-4"></i>
</button>
</nav>
<!-- Mobile Menu Toggle -->
<button class="md:hidden text-stone-300 hover:text-white p-2" onclick="toggleSideMenu()">
<i data-lucide="menu" class="w-6 h-6"></i>
</button>
</div>
</header>
<!-- Mobile Side Menu -->
<div id="sideMenuOverlay" class="side-menu-overlay" onclick="toggleSideMenu()"></div>
<div id="sideMenu" class="side-menu ui-font text-stone-300">
<div class="flex justify-end mb-8">
<button onclick="toggleSideMenu()" class="text-stone-400 hover:text-white">
<i data-lucide="x" class="w-6 h-6"></i>
</button>
</div>
<nav class="flex flex-col gap-6 text-lg font-medium">
<button onclick="mobileNav('main', 'top')" class="text-left hover:text-amber-400 transition">Главная</button>
<button onclick="mobileNav('main', 'mechanism')" class="text-left hover:text-amber-400 transition">Механика</button>
<button onclick="mobileNav('main', 'analysis')" class="text-left hover:text-amber-400 transition">Различение</button>
<button onclick="mobileNav('main', 'witnesses')" class="text-left hover:text-amber-400 transition">Свидетельства</button>
<div class="h-px w-full bg-stone-800 my-2"></div>
<button onclick="mobileNav('article', null)" class="text-left text-amber-200 font-bold hover:text-white transition flex items-center gap-2">
<i data-lucide="book-open" class="w-4 h-4"></i> Полная Статья
</button>
<button onclick="openSettings(); toggleSideMenu()" class="text-left text-stone-400 hover:text-white transition flex items-center gap-2 text-sm mt-4">
<i data-lucide="key" class="w-4 h-4"></i> Настройки API
</button>
</nav>
</div>
<!-- Settings Modal -->
<div id="settingsModal" class="fixed inset-0 hidden modal-backdrop flex items-center justify-center p-4">
<div class="bg-[#fafaf9] rounded-xl shadow-2xl max-w-md w-full p-8 ui-font border border-stone-200 relative z-50">
<div class="flex justify-between items-center mb-6">
<h3 class="text-xl font-bold text-stone-800 font-serif">Ключ Google Gemini API</h3>
<button onclick="closeSettings()" class="text-stone-400 hover:text-stone-800">
<i data-lucide="x" class="w-6 h-6"></i>
</button>
</div>
<p class="text-sm text-stone-600 mb-4 leading-relaxed">
Для работы интеллектуального помощника и озвучивания текстов требуется ключ. Он сохраняется локально.
</p>
<input type="password" id="apiKeyInput" class="w-full p-3 border border-stone-300 rounded bg-white focus:ring-2 focus:ring-amber-500 outline-none text-stone-800 mb-4" placeholder="AIza...">
<button onclick="saveApiKey()" class="w-full bg-stone-800 hover:bg-stone-900 text-stone-50 py-3 rounded font-medium transition">Сохранить</button>
</div>
</div>
<!-- VIEW 1: MAIN INTERACTIVE DASHBOARD -->
<main id="view-main" class="flex-grow w-full max-w-6xl mx-auto px-4 py-12 space-y-24 fade-in pb-32">
<!-- Hero Title Block -->
<div id="top" class="text-center max-w-4xl mx-auto space-y-6 pt-8 relative z-20">
<h2 class="text-3xl md:text-5xl font-bold text-stone-900 leading-tight font-serif">
Феноменология духовного отчаяния
</h2>
<p class="text-lg md:text-xl text-stone-600 italic font-serif leading-relaxed">
Систематический анализ восточно-христианской аскетической традиции о ложном чувстве богооставленности.
</p>
<div class="flex flex-col sm:flex-row justify-center gap-4 pt-4">
<button onclick="switchView('article')" class="bg-stone-800 text-white px-6 py-3 rounded-md shadow hover:bg-stone-700 transition ui-font text-sm font-medium flex items-center justify-center">
<i data-lucide="file-text" class="w-4 h-4 mr-2"></i> Читать исследование
</button>
<button onclick="openChatWithFocus()" class="bg-white border border-stone-300 text-stone-700 px-6 py-3 rounded-md shadow-sm hover:bg-stone-50 transition ui-font text-sm font-medium flex items-center justify-center relative z-30">
<i data-lucide="sparkles" class="w-4 h-4 mr-2 text-amber-600"></i> Задать вопрос
</button>
</div>
</div>
<!-- Mechanism Interactive Cards -->
<section id="mechanism" class="space-y-10 scroll-mt-24 relative z-10">
<div class="text-center max-w-2xl mx-auto">
<div class="inline-flex items-center justify-center p-2 bg-stone-100 rounded-lg mb-4">
<i data-lucide="activity" class="w-5 h-5 text-stone-500 mr-2"></i>
<span class="text-xs font-bold uppercase tracking-widest text-stone-600 ui-font">Диагностика</span>
</div>
<h3 class="text-3xl font-bold text-stone-800 mb-2 font-serif">Механика Клеветы</h3>
<p class="text-stone-600 ui-font">Три стадии демонической атаки (нажмите для анализа).</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 ui-font">
<!-- Card 1 -->
<div class="mech-card group bg-white p-8 rounded-xl border border-stone-200 border-l-4 border-l-stone-400 shadow-sm" onclick="toggleCard(this)">
<div class="flex justify-between items-start">
<h4 class="font-bold text-xl text-stone-800">1. Прилог (Мысль)</h4>
<div class="p-2 bg-stone-100 rounded-full"><i data-lucide="brain-circuit" class="text-stone-500 w-5 h-5"></i></div>
</div>
<p class="text-stone-600 mt-4 leading-relaxed">Враг вбрасывает мысль от первого лица: «Я никому не нужен».</p>
<div class="card-details">
<div class="bg-amber-50 p-4 rounded-md mt-4 border border-amber-100">
<p class="text-xs font-bold uppercase text-amber-800 mb-2">Стратегия Мимикрии</p>
<p class="text-sm text-stone-700 leading-relaxed">Демон пытается слить свой голос с вашим внутренним монологом. Если вы примете эту мысль как <em>свою</em>, вы вступите в диалог, что уже является поражением.</p>
</div>
</div>
<div class="mt-6 flex items-center text-xs text-stone-400 font-bold uppercase tracking-wider group-hover:text-amber-600 transition">
<span class="card-toggle-text">Подробнее</span> <i data-lucide="chevron-down" class="w-3 h-3 ml-1 card-chevron"></i>
</div>
</div>
<!-- Card 2 -->
<div class="mech-card group bg-white p-8 rounded-xl border border-stone-200 border-l-4 border-l-red-500 shadow-sm" onclick="toggleCard(this)">
<div class="flex justify-between items-start">
<h4 class="font-bold text-xl text-stone-800">2. Аффект (Чувство)</h4>
<div class="p-2 bg-red-50 rounded-full"><i data-lucide="flame" class="text-red-500 w-5 h-5"></i></div>
</div>
<p class="text-stone-600 mt-4 leading-relaxed">Соматическая реакция: холод в груди, мрак, тревога, сжатие сердца.</p>
<div class="card-details">
<div class="bg-red-50 p-4 rounded-md mt-4 border border-red-100">
<p class="text-xs font-bold uppercase text-red-800 mb-2">Сенсорная Ложь</p>
<p class="text-sm text-stone-700 leading-relaxed">«Раз я <em>чувствую</em>, что Бог ушел, значит, это правда». Это ошибка. Чувства повреждены грехопадением и легко манипулируемы. Они не являются органом Истины.</p>
</div>
</div>
<div class="mt-6 flex items-center text-xs text-stone-400 font-bold uppercase tracking-wider group-hover:text-red-600 transition">
<span class="card-toggle-text">Подробнее</span> <i data-lucide="chevron-down" class="w-3 h-3 ml-1 card-chevron"></i>
</div>
</div>
<!-- Card 3 -->
<div class="mech-card group bg-white p-8 rounded-xl border border-stone-200 border-l-4 border-l-stone-900 shadow-sm" onclick="toggleCard(this)">
<div class="flex justify-between items-start">
<h4 class="font-bold text-xl text-stone-800">3. Отчаяние (Изоляция)</h4>
<div class="p-2 bg-stone-100 rounded-full"><i data-lucide="anchor" class="text-stone-800 w-5 h-5"></i></div>
</div>
<p class="text-stone-600 mt-4 leading-relaxed">Паралич воли и прекращение молитвы. Отказ от надежды.</p>
<div class="card-details">
<div class="bg-stone-100 p-4 rounded-md mt-4 border border-stone-200">
<p class="text-xs font-bold uppercase text-stone-800 mb-2">Инструмент Изоляции</p>
<p class="text-sm text-stone-700 leading-relaxed">
Цель не в том, чтобы доказать вашу греховность, а в том, чтобы разорвать связь. Пока человек молится — он недосягаем. Отчаяние — это духовная немота и добровольная изоляция от Источника Жизни.
</p>
</div>
</div>
<div class="mt-6 flex items-center text-xs text-stone-400 font-bold uppercase tracking-wider group-hover:text-stone-900 transition">
<span class="card-toggle-text">Подробнее</span> <i data-lucide="chevron-down" class="w-3 h-3 ml-1 card-chevron"></i>
</div>
</div>
</div>
</section>
<!-- Analysis & Chart -->
<section id="analysis" class="bg-white rounded-xl p-8 md:p-12 border border-stone-200 shadow-sm scroll-mt-24 relative z-10">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
<div>
<h3 class="text-3xl font-bold text-stone-800 mb-6 font-serif">Траектория Духовного Состояния</h3>
<p class="text-stone-600 mb-6 leading-relaxed text-lg">
Сравнение двух путей реакции на грех. <br>Враг предлагает <strong>линейное падение</strong> в отчаяние. <br>Благодать ведет через <strong>покаяние (спуск)</strong> к <strong>утешению (подъем)</strong>.
</p>
<div class="space-y-4 ui-font text-sm">
<div class="flex items-start bg-blue-50 p-4 rounded-lg border border-blue-100">
<i data-lucide="trending-up" class="w-5 h-5 text-blue-600 mt-0.5 mr-3 flex-shrink-0"></i>
<div>
<span class="text-blue-900 font-bold block mb-1">Путь Смирения (Силуан)</span>
<span class="text-stone-700 leading-relaxed">Человек принимает правду о грехе («ум во аде»), но не теряет надежды. Это рождает подъем и встречу с Христом.</span>
</div>
</div>
<div class="flex items-start bg-red-50 p-4 rounded-lg border border-red-100">
<i data-lucide="trending-down" class="w-5 h-5 text-red-600 mt-0.5 mr-3 flex-shrink-0"></i>
<div>
<span class="text-red-900 font-bold block mb-1">Путь Гордости (Иуда)</span>
<span class="text-stone-700 leading-relaxed">Человек видит грех, но замыкается на себе. Это ведет к линейной деградации надежды вплоть до полного отчаяния.</span>
</div>
</div>
</div>
</div>
<div class="bg-stone-50 p-6 rounded-xl border border-stone-100">
<div class="chart-container">
<canvas id="comparisonChart"></canvas>
</div>
<p class="text-center text-xs text-stone-400 mt-6 italic ui-font">График: Изменение уровня надежды во времени</p>
</div>
</div>
</section>
<!-- Witnesses (Saints) -->
<section id="witnesses" class="space-y-10 scroll-mt-24 relative z-10">
<h3 class="text-3xl font-bold text-center text-stone-800 font-serif">Исторические Свидетельства</h3>
<div class="flex flex-wrap justify-center gap-2 ui-font">
<button onclick="switchTab('silouan')" id="tab-silouan" class="px-6 py-2 rounded-full text-sm font-medium transition bg-stone-800 text-white shadow-lg ring-2 ring-stone-800 ring-offset-2">Прп. Силуан</button>
<button onclick="switchTab('anthony')" id="tab-anthony" class="px-6 py-2 rounded-full text-sm font-medium transition bg-white border border-stone-300 text-stone-600 hover:bg-stone-50">Прп. Антоний</button>
<button onclick="switchTab('paisios')" id="tab-paisios" class="px-6 py-2 rounded-full text-sm font-medium transition bg-white border border-stone-300 text-stone-600 hover:bg-stone-50">Прп. Паисий</button>
</div>
<div class="bg-white rounded-xl p-8 md:p-12 border border-stone-200 shadow-md relative min-h-[300px]">
<!-- Silouan -->
<div id="content-silouan" class="witness-content fade-in">
<div class="flex items-baseline justify-between mb-4">
<h4 class="text-2xl font-bold font-serif text-stone-900">«Держи ум твой во аде...»</h4>
<span class="text-xs font-bold uppercase tracking-widest text-stone-400">Афон, XX век</span>
</div>
<p class="text-stone-700 mb-8 leading-relaxed text-lg">
Преподобный Силуан 15 лет вел титаническую борьбу. Демоны являлись ему воочию, говоря: «Ты свят», ввергая в гордость, а затем: «Ты не спасешься», ввергая в отчаяние. В момент предельного истощения Христос явился ему и дал формулу победы над обеими крайностями.
</p>
<div class="bg-amber-50 border-l-4 border-amber-600 p-6 rounded-r-lg relative">
<button onclick="playTTS('Держи ум твой во аде и не отчаивайся.', this)" class="absolute top-6 right-6 text-amber-800 hover:text-amber-600 transition bg-amber-100 p-2 rounded-full" title="Прослушать">
<i data-lucide="volume-2" class="w-5 h-5"></i>
</button>
<p class="italic text-stone-800 font-serif text-xl pr-12">«Держи ум твой во аде и не отчаивайся.»</p>
<p class="text-xs text-amber-800 mt-4 font-bold uppercase tracking-wider ui-font">Божественное Откровение</p>
</div>
</div>
<!-- Anthony -->
<div id="content-anthony" class="witness-content hidden">
<div class="flex items-baseline justify-between mb-4">
<h4 class="text-2xl font-bold font-serif text-stone-900">Видение Небесного Стража</h4>
<span class="text-xs font-bold uppercase tracking-widest text-stone-400">Египет, IV век</span>
</div>
<p class="text-stone-700 mb-8 leading-relaxed text-lg">
Враг предстал в виде ужасного великана, зачитывающего список грехов Антония с раннего детства, пытаясь доказать, что он принадлежит аду. Антоний не отрицал фактов греха, но отрицал право врага судить искупленного.
</p>
<div class="bg-amber-50 border-l-4 border-amber-600 p-6 rounded-r-lg relative">
<button onclick="playTTS('То, что было до покаяния — изглажено Богом. Не поминай того.', this)" class="absolute top-6 right-6 text-amber-800 hover:text-amber-600 transition bg-amber-100 p-2 rounded-full" title="Прослушать">
<i data-lucide="volume-2" class="w-5 h-5"></i>
</button>
<p class="italic text-stone-800 font-serif text-xl pr-12">«То, что было до покаяния — изглажено Богом. Не поминай того. А после пострига — говори, если знаешь.»</p>
<p class="text-xs text-amber-800 mt-4 font-bold uppercase tracking-wider ui-font">Ответ Антония</p>
</div>
</div>
<!-- Paisios -->
<div id="content-paisios" class="witness-content hidden">
<div class="flex items-baseline justify-between mb-4">
<h4 class="text-2xl font-bold font-serif text-stone-900">Половина Правды</h4>
<span class="text-xs font-bold uppercase tracking-widest text-stone-400">Греция, XX век</span>
</div>
<p class="text-stone-700 mb-8 leading-relaxed text-lg">
Старец Паисий называл помыслы отчаяния «фильмами тангалашки» (беса). Враг показывает правду о нашем грехе, но «монтирует» пленку, вырезая кадры с Божьим милосердием. Это клевета через полуправду.
</p>
<div class="bg-amber-50 border-l-4 border-amber-600 p-6 rounded-r-lg relative">
<button onclick="playTTS('Если Бог пошлет меня в ад, я и там буду любить Его, и ад станет раем.', this)" class="absolute top-6 right-6 text-amber-800 hover:text-amber-600 transition bg-amber-100 p-2 rounded-full" title="Прослушать">
<i data-lucide="volume-2" class="w-5 h-5"></i>
</button>
<p class="italic text-stone-800 font-serif text-xl pr-12">«Если Бог пошлет меня в ад, я и там буду любить Его, и ад станет раем.»</p>
<p class="text-xs text-amber-800 mt-4 font-bold uppercase tracking-wider ui-font">Абсолютное Смирение</p>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="text-center text-stone-400 text-xs ui-font pt-10 pb-4">
<p>© 2026 Просветительский проект «Святоотеческое Наследие».</p>
</footer>
</main>
<!-- VIEW 2: FULL RESEARCH ARTICLE -->
<main id="view-article" class="hidden flex-grow w-full max-w-5xl mx-auto px-6 py-12 fade-in pb-32">
<article class="bg-white p-10 md:p-20 rounded-xl shadow-sm border border-stone-200">
<div class="text-center mb-16">
<span class="text-xs font-bold uppercase tracking-widest text-amber-700 ui-font mb-4 block">Богословское Исследование</span>
<h2 class="text-3xl md:text-5xl font-bold text-stone-900 leading-tight font-serif mb-6">
Феноменология духовного отчаяния и стратегии демонической клеветы на Божественную Любовь
</h2>
<p class="text-stone-500 italic font-serif text-lg">Систематический анализ восточно-христианской аскетической традиции</p>
<div class="w-16 h-1 bg-stone-300 mx-auto mt-8"></div>
</div>
<div class="article-content text-stone-800">
<p>
Целью данного исследования является поиск ответа на вопрос: <strong>существуют ли в Православной теологии и житиях святых свидетельства и речь о том, что на пути к спасению и в духовной жизни верующих возникали ситуации, когда враг вселял в человека неуверенность в любви Божией, в любви Христа, воздействуя на человека видением или чувствами, вызывая эмоции или мысли, которые очень убедительно показывают, что Господь не прощает и не любит?</strong> Изучение патристического наследия дает утвердительный ответ: это не просто частные случаи, а системная стратегия духовной брани.
</p>
<h3>I. Экклезиология Надежды против «Змея-наветника»</h3>
<p>
Святитель Иоанн Златоуст в своих беседах о покаянии закладывает фундамент для сопротивления отчаянию. Он противопоставляет ветхозаветный ковчег, который спасал жизнь, но не менял природу («вошел волк — вышел волк»), новозаветной Церкви. Церковь есть лечебница, где происходит онтологическая трансмутация: «входит ястреб — выходит голубь», «входит волк — выходит овца».
</p>
<p>
Златоуст особо подчеркивает: «Нет здесь змея — наветника, но Христос, открывающий тайны». Враг (наветник) стремится убедить кающегося, что его прошлая природа фатальна и неизменна. Однако в пространстве благодати этот аргумент теряет силу, так как само существование Таинств есть доказательство возможности изменения и прощения.
</p>
<h3>II. Психология Искушения: «Мирская карамелька»</h3>
<p>
Преподобный Паисий Святогорец вводит термин «мирская карамелька» для описания механизма, с помощью которого враг («тангалашка») ловит чувствительные души. Этот процесс цикличен:
</p>
<ul>
<li>Враг замечает момент естественной печали или усталости.</li>
<li>Он подбрасывает помысел отчаяния как «карамельку» — ложное утешение в саможалении.</li>
<li>Если человек принимает помысел, его воля парализуется.</li>
</ul>
<p>
Старец предлагает метод <strong>«доброго равнодушия»</strong>: не вступать в спор с помыслами о своей погибшей участи, а игнорировать их. Спор с помыслом уже означает признание его значимости.
</p>
<h3>III. Онтология Лжи: Механизм подмены реальности</h3>
<p>
Согласно учению свт. Игнатия (Брянчанинова) и прп. Исаака Сирина, падшие духи, будучи существами тонкими, не имеют доступа к суверенному центру человеческой личности — «глубине сердца». Однако они обладают способностью воздействовать на психосоматический контур человека (тело как «темница» души). Они генерируют помыслы (λογισμοί) и провоцируют сенсорные отклики — чувство холода, необъяснимой тревоги, физической тяжести в груди.
</p>
<p>
Яркий пример прямой атаки мы находим в житии святого Нифонта Кипрского. Когда он встал на путь покаяния, ему явился бес и с иронией спросил: <em>«Неужели ты не спасешься?»</em>, пытаясь навязать мысль о невозможности прощения. Нифонт отразил это не своими заслугами, а догматическим исповеданием милосердия Божия, которое превосходит грехи всего мира.
</p>
<blockquote>
«Враг старается представить Бога неумолимым, а грехи наши — непростительными. Цель одна — отсечь человека от надежды, ибо надежда есть пуповина, связывающая душу с Небом. Перережь её, и душа задохнется.»
<br><span class="text-sm not-italic mt-2 block ui-font text-stone-500">— Прп. Иоанн Лествичник (парафраз)</span>
</blockquote>
<h3>IV. Парадокс Самоукорения</h3>
<p>
В аскетической литературе существует кажущееся противоречие. С одной стороны, отцы призывают к самоукорению. С другой — предупреждают об отчаянии. Где грань? Архимандрит Софроний (Сахаров) различает <em>психологическое отчаяние</em> (депрессию, упадок сил) и <em>духовное отчаяние</em> (опыт богооставленности).
</p>
<p>
Ответ кроется в различении состояния:
</p>
<div class="overflow-x-auto my-8 border rounded-lg border-stone-200">
<table class="w-full text-left ui-font text-sm">
<thead class="bg-stone-100 text-stone-800 border-b border-stone-200">
<tr>
<th class="p-4">Состояние души</th>
<th class="p-4">Духовное лекарство</th>
<th class="p-4">Опасность (Противопоказание)</th>
</tr>
</thead>
<tbody class="divide-y divide-stone-100">
<tr>
<td class="p-4 font-bold text-stone-700">Гордость, самоуверенность</td>
<td class="p-4 text-blue-800">Самоукорение, страх Суда</td>
<td class="p-4 text-stone-500">Преждевременное утешение</td>
</tr>
<tr>
<td class="p-4 font-bold text-stone-700">Отчаяние, страх, сокрушение</td>
<td class="p-4 text-amber-700 font-bold">Надежда, память о Любви</td>
<td class="p-4 text-red-600 font-bold">Самоукорение (ведет к гибели)</td>
</tr>
</tbody>
</table>
</div>
<h3>V. Формула прп. Силуана Афонского</h3>
<p>
В XX веке этот вопрос получил исчерпывающее разрешение в откровении старцу Силуану: <strong>«Держи ум твой во аде и не отчаивайся»</strong>. Это уникальная диалектическая формула.
</p>
<p>
Первая часть императива (<em>«ум во аде»</em>) есть признание правды о своей падшести (против гордости). Вторая часть (<em>«не отчаивайся»</em>) есть признание правды о Боге-Любви (против уныния). Враг всегда пытается разорвать эту формулу, предлагая либо гордость без покаяния, либо ад без надежды.
</p>
<h3>VI. Заключение</h3>
<p>
Чувство того, что «Господь не прощает», является гносеологической ошибкой, навязанной извне. Преодоление её лежит не в области эмоций (которые повреждены), а в области волевого исповедания веры в Благость Божию <em>вопреки</em> очевидности своих грехов.
</p>
<div class="mt-8 pt-6 border-t border-stone-100 text-xs text-stone-500">
<p><strong>Источники:</strong></p>
<ul class="list-none pl-0 mt-2 space-y-1">
<li>1. Свт. Иоанн Златоуст. «Беседы о покаянии».</li>
<li>2. Прп. Иоанн Лествичник. «Лествица» (Слово 23, 26).</li>
<li>3. Свт. Игнатий (Брянчанинов). «Слово о смерти», «Аскетические опыты».</li>
<li>4. Житие св. Нифонта Кипрского.</li>
<li>5. Прп. Паисий Святогорец. «Слова. Том V: Страсти и добродетели».</li>
<li>6. Архим. Софроний (Сахаров). «Старец Силуан».</li>
</ul>
</div>
</div>
<div class="mt-16 pt-8 border-t border-stone-200 text-center">
<button onclick="switchView('main'); window.scrollTo(0,0);" class="bg-stone-800 text-white px-10 py-4 rounded-full hover:bg-stone-700 transition ui-font font-medium shadow-lg flex items-center justify-center mx-auto">
<i data-lucide="arrow-left" class="w-4 h-4 mr-2"></i> Вернуться к Интерактиву
</button>
</div>
</article>
</main>
<!-- FLOATING CHAT WIDGET (Shadcn Style) -->
<div id="chat-widget" class="chat-widget ui-font">
<!-- Chat Window -->
<div class="chat-window">
<!-- Header -->
<div class="p-4 border-b border-stone-200 bg-stone-50 flex justify-between items-center">
<div>
<h3 class="font-bold text-stone-800 text-sm">Духовный Собеседник</h3>
<p class="text-[10px] text-stone-500 uppercase tracking-wider">Powered by Gemini</p>
</div>
<button onclick="toggleChatWidget()" class="text-stone-400 hover:text-stone-800">
<i data-lucide="x" class="w-4 h-4"></i>
</button>
</div>
<!-- Content Area -->
<div class="flex-grow p-4 overflow-y-auto bg-white flex flex-col gap-3" id="chat-messages">
<!-- Welcome Message -->
<div class="bg-stone-100 p-3 rounded-lg rounded-tl-none self-start max-w-[90%] text-sm text-stone-700 border border-stone-200">
Приветствую. Если вас тревожит помысел или нужно утешение, напишите здесь. Я проанализирую это на основе трудов Святых Отцов (Силуана, Софрония).
</div>
</div>
<!-- Input Area -->
<div class="p-4 border-t border-stone-200 bg-stone-50">
<textarea id="widgetInput" rows="2" class="w-full p-3 text-sm border border-stone-300 rounded-md focus:ring-2 focus:ring-stone-500 focus:border-stone-500 outline-none resize-none mb-3 bg-white" placeholder="Опишите вашу мысль..."></textarea>
<div class="flex gap-2">
<button onclick="sendChat('analyze')" class="flex-1 bg-white border border-stone-300 hover:bg-stone-50 text-stone-700 py-2 rounded-md text-xs font-bold transition">
Разбор
</button>
<button onclick="sendChat('comfort')" class="flex-1 bg-stone-800 hover:bg-stone-700 text-white py-2 rounded-md text-xs font-bold transition">
Утешение
</button>
</div>
</div>
</div>
<!-- Main Button -->
<div class="chat-toggle" onclick="toggleChatWidget()">
<i data-lucide="message-circle" class="w-6 h-6"></i>
</div>
</div>
<script>
// Init
document.addEventListener('DOMContentLoaded', function() {
lucide.createIcons();
initChart();
checkApiKey();
});
// 1. Navigation Logic
function switchView(viewName) {
const mainView = document.getElementById('view-main');
const articleView = document.getElementById('view-article');
const navArticle = document.getElementById('nav-article');
if (viewName === 'main') {
mainView.classList.remove('hidden');
articleView.classList.add('hidden');
navArticle.classList.remove('text-amber-500');
window.scrollTo(0,0);
} else {
mainView.classList.add('hidden');
articleView.classList.remove('hidden');
navArticle.classList.add('text-amber-500');
window.scrollTo(0,0);
}
}
function navigateTo(view, sectionId) {
switchView(view);
setTimeout(() => {
const el = document.getElementById(sectionId);
if(el) el.scrollIntoView({behavior: 'smooth'});
}, 100);
}
// Mobile Nav Helper
function mobileNav(view, sectionId) {
toggleSideMenu();
if (view === 'article') {
switchView('article');
} else {
navigateTo(view, sectionId);
}
}
// 2. Side Menu Logic
function toggleSideMenu() {
const menu = document.getElementById('sideMenu');
const overlay = document.getElementById('sideMenuOverlay');
menu.classList.toggle('open');
overlay.classList.toggle('open');
}
// 3. Chat Widget Logic
function toggleChatWidget() {
const widget = document.getElementById('chat-widget');
const toggleBtn = widget.querySelector('.chat-toggle');
widget.classList.toggle('open');
const isOpen = widget.classList.contains('open');
// Robust Icon Replacement
toggleBtn.innerHTML = ''; // Clear first
const icon = document.createElement('i');
if (isOpen) {
icon.setAttribute('data-lucide', 'x');
icon.className = 'w-6 h-6';
} else {
icon.setAttribute('data-lucide', 'message-circle');
icon.className = 'w-6 h-6';
}
toggleBtn.appendChild(icon);
lucide.createIcons();
}
function openChatWithFocus() {
const widget = document.getElementById('chat-widget');
if (!widget.classList.contains('open')) {
toggleChatWidget();
}
setTimeout(() => {
const input = document.getElementById('widgetInput');
if(input) input.focus();
}, 300);
}
async function sendChat(mode) {
const input = document.getElementById('widgetInput');
const text = input.value.trim();
if (!text) return;
const chatBox = document.getElementById('chat-messages');
// User Message
const userMsg = document.createElement('div');
userMsg.className = "bg-stone-800 text-white p-3 rounded-lg rounded-tr-none self-end max-w-[90%] text-sm mb-2 shadow-sm";
userMsg.textContent = text;
chatBox.appendChild(userMsg);
// Clear input & Scroll
input.value = '';
chatBox.scrollTop = chatBox.scrollHeight;
// Loading state
const loadingMsg = document.createElement('div');
loadingMsg.id = 'chat-loading';
loadingMsg.className = "bg-stone-100 p-3 rounded-lg rounded-tl-none self-start max-w-[90%] text-sm text-stone-500 flex items-center gap-2 border border-stone-200";
loadingMsg.innerHTML = '<div class="loader w-3 h-3 border-stone-400 border-t-transparent"></div> Обращаюсь к преданию...';
chatBox.appendChild(loadingMsg);
chatBox.scrollTop = chatBox.scrollHeight;
// API Call
const key = localStorage.getItem('gemini_api_key');
if (!key) {
document.getElementById('chat-loading').innerHTML = "Пожалуйста, введите API ключ в настройках.";
openSettings();
return;
}
let prompt = "";
if (mode === 'analyze') {
prompt = `Act as a phenomenologist of the spirit in the tradition of Archimandrite Sophrony and St. Silouan. Analyze the *existential texture* of this thought: "${text}".
How does it isolate the person? Is it a 'dark fire' or a 'cold void'? Avoid moralizing clichés. Focus on the ontological difference between the 'I' and the 'intrusion'.
Reference Sophrony's concept of 'hypostatic prayer' or Silouan's 'love for enemies' as a criterion for truth.
Structure in Russian HTML:
<b>Диагноз:</b> (Existential source)<br>
<b>Анализ:</b> (Deep phenomenological breakdown)<br>
<b>Совет:</b> (Practical, non-systemic advice).`;
} else {
prompt = `Speak with the voice of St. Silouan or a wise Pietist friend to comfort this person: "${text}".
Focus on the *living experience* of Christ's love, not legalistic forgiveness.
Acknowledge the pain of 'God's silence'. Remind them that this abyss is where Christ descends.
Be poetic, honest, and deeply personal. No 'church bureaucracy' language.
Output in Russian HTML.`;
}
try {
const req = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-09-2025:generateContent?key=${key}`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
contents: [{parts: [{text: text}]}],
systemInstruction: {parts: [{text: prompt}]}
})
});
const data = await req.json();
const out = data.candidates?.[0]?.content?.parts?.[0]?.text || "Ошибка получения ответа.";
const botMsg = document.createElement('div');
botMsg.className = "bg-white p-4 rounded-lg rounded-tl-none self-start max-w-[95%] text-sm text-stone-800 border border-stone-200 shadow-sm leading-relaxed";
botMsg.innerHTML = out;
chatBox.removeChild(loadingMsg);
chatBox.appendChild(botMsg);
chatBox.scrollTop = chatBox.scrollHeight;
} catch(e) {
loadingMsg.innerHTML = "Ошибка соединения. Проверьте ключ.";
}
}
// 4. Interactive Cards Logic
function toggleCard(element) {
const allCards = document.querySelectorAll('.mech-card');
const isActive = element.classList.contains('active');
// Reset all
allCards.forEach(card => {
card.classList.remove('active');
const textSpan = card.querySelector('.card-toggle-text');
if(textSpan) textSpan.innerText = 'Подробнее';
});
// Toggle clicked
if (!isActive) {
element.classList.add('active');
const textSpan = element.querySelector('.card-toggle-text');
if(textSpan) textSpan.innerText = 'Свернуть';
}
}
// 5. Chart Logic
function initChart() {
const ctx = document.getElementById('comparisonChart').getContext('2d');
const data = {
labels: ['Помысел (Старт)', 'Принятие/Борьба', 'Кульминация', 'Итог'],
datasets: [
{
label: 'Путь Врага (Отчаяние)',
data: [0, -4, -8, -10],
borderColor: '#ef4444',
backgroundColor: 'rgba(239, 68, 68, 0.1)',
borderWidth: 3,
tension: 0.3,
fill: true
},
{
label: 'Путь Смирения (Силуан)',
data: [0, -3, -5, 8],
borderColor: '#3b82f6',
backgroundColor: 'rgba(59, 130, 246, 0.1)',
borderWidth: 3,
tension: 0.4,
fill: true
}
]
};
new Chart(ctx, {
type: 'line',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
min: -10, max: 10,
title: { display: true, text: 'Уровень Надежды / Утешения' },
grid: { color: '#e5e7eb' }
},
x: {
grid: { display: false }
}
},
plugins: {
legend: { position: 'bottom' },
tooltip: {
callbacks: {
label: function(context) {
return context.dataset.label + ": " + context.raw;
}
}
}
}
}
});
}
// 6. Tabs
function switchTab(id) {
document.querySelectorAll('.witness-content').forEach(el => el.classList.add('hidden'));
document.getElementById(`content-${id}`).classList.remove('hidden');
['silouan', 'anthony', 'paisios'].forEach(btnId => {
const btn = document.getElementById(`tab-${btnId}`);
if (btnId === id) {
btn.className = "px-6 py-2 rounded-full text-sm font-medium transition bg-stone-800 text-white shadow-lg ring-2 ring-stone-800 ring-offset-2";
} else {
btn.className = "px-6 py-2 rounded-full text-sm font-medium transition bg-white border border-stone-300 text-stone-600 hover:bg-stone-50";
}
});
}
// 7. Settings & API Utilities
function checkApiKey() {}
function openSettings() { document.getElementById('settingsModal').classList.remove('hidden'); }
function closeSettings() { document.getElementById('settingsModal').classList.add('hidden'); }
function saveApiKey() {
const val = document.getElementById('apiKeyInput').value.trim();
if(val) localStorage.setItem('gemini_api_key', val);
closeSettings();
}
async function playTTS(text, btn) {
const key = localStorage.getItem('gemini_api_key');
if(!key) { openSettings(); return; }
const originalHtml = btn.innerHTML;
btn.innerHTML = '<div class="loader w-4 h-4 border-amber-800 border-t-transparent"></div>';
btn.disabled = true;
try {
const req = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-tts:generateContent?key=${key}`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
contents: [{parts: [{text: text}]}],
generationConfig: {
responseModalities: ["AUDIO"],
speechConfig: { voiceConfig: { prebuiltVoiceConfig: { voiceName: "Charon" } } }
}
})
});
const data = await req.json();
const audioData = data.candidates?.[0]?.content?.parts?.[0]?.inlineData?.data;
if(audioData) playPCM(audioData);
} catch(e) { console.error(e); alert("Ошибка воспроизведения"); }
finally { btn.innerHTML = originalHtml; btn.disabled = false; }
}
function playPCM(base64) {
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for(let i=0; i<binary.length; i++) bytes[i] = binary.charCodeAt(i);
const ints = new Int16Array(bytes.buffer);
const floats = new Float32Array(ints.length);
for(let i=0; i<ints.length; i++) floats[i] = ints[i] / 32768;
const buffer = audioCtx.createBuffer(1, floats.length, 24000);
buffer.getChannelData(0).set(floats);
const src = audioCtx.createBufferSource();
src.buffer = buffer;
src.connect(audioCtx.destination);
src.start(0);
}
</script>
</body>
</html>