File size: 122,647 Bytes
6ece400
7f2f296
6ece400
51086f9
 
 
 
1669e26
 
 
6ece400
 
 
209a2f8
1669e26
 
7f2f296
1669e26
6ece400
 
 
 
adfc6f1
209a2f8
51086f9
b4fdf52
6ece400
adfc6f1
209a2f8
b4fdf52
51086f9
b4fdf52
 
6ece400
 
 
064121d
51086f9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7f2f296
51086f9
 
 
 
 
 
 
 
b4fdf52
209a2f8
51086f9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b4fdf52
51086f9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1669e26
b4fdf52
209a2f8
 
 
 
8be7b60
209a2f8
 
1669e26
209a2f8
 
1669e26
 
 
209a2f8
 
 
 
 
 
 
 
51086f9
209a2f8
b4fdf52
 
209a2f8
 
 
 
 
b4fdf52
 
 
51086f9
b4fdf52
209a2f8
1669e26
 
209a2f8
 
1669e26
 
 
 
b4fdf52
1669e26
 
209a2f8
1669e26
 
 
 
 
209a2f8
b4fdf52
209a2f8
51086f9
 
b4fdf52
 
 
209a2f8
1669e26
 
51086f9
1669e26
 
 
 
51086f9
 
 
 
 
 
 
 
 
209a2f8
51086f9
 
 
 
 
 
 
 
 
 
209a2f8
1669e26
209a2f8
51086f9
209a2f8
 
 
 
b4fdf52
51086f9
b4fdf52
 
 
 
 
 
51086f9
b4fdf52
1669e26
 
209a2f8
51086f9
1669e26
51086f9
 
 
 
 
 
209a2f8
b4fdf52
51086f9
1669e26
51086f9
 
1669e26
 
 
51086f9
 
 
 
 
 
 
 
b4fdf52
209a2f8
1669e26
 
 
 
209a2f8
1669e26
 
 
 
b4fdf52
1669e26
 
209a2f8
1669e26
209a2f8
1669e26
 
 
 
 
209a2f8
51086f9
 
1669e26
 
 
209a2f8
 
1669e26
b4fdf52
 
 
51086f9
b4fdf52
 
209a2f8
 
1669e26
b4fdf52
 
b9ed7ff
7141429
6ece400
51086f9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3038ff6
 
 
 
 
51086f9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6ece400
ddc57d5
 
 
 
6ece400
ddc57d5
6ece400
6b0b418
ddc57d5
51086f9
6ece400
 
 
 
ddc57d5
adfc6f1
f1210e5
b7de50a
6ece400
51086f9
 
 
 
 
 
 
 
 
 
 
1669e26
209a2f8
 
 
 
97409a4
 
6ece400
51086f9
 
 
 
ddc57d5
 
51086f9
 
 
 
 
 
 
 
4c23ad6
a5574a4
1669e26
adfc6f1
 
 
 
1669e26
 
209a2f8
 
f296f61
 
 
 
 
1669e26
 
209a2f8
f1210e5
d222b1d
6ece400
51086f9
7f2f296
 
b9ed7ff
f296f61
6ece400
 
adfc6f1
 
f296f61
3817336
6ece400
adfc6f1
209a2f8
51086f9
209a2f8
b4fdf52
 
adfc6f1
 
 
 
 
f296f61
adfc6f1
b4fdf52
adfc6f1
51086f9
adfc6f1
 
51086f9
 
6ece400
adfc6f1
 
 
51086f9
adfc6f1
 
f1210e5
adfc6f1
7f2f296
b4fdf52
adfc6f1
f1210e5
064121d
6b0b418
 
b4fdf52
 
6b0b418
 
 
 
 
51086f9
 
 
 
 
6b0b418
 
 
51086f9
 
 
 
 
 
 
 
 
b4fdf52
51086f9
 
 
 
 
6b0b418
 
51086f9
 
 
 
 
 
 
 
b4fdf52
51086f9
 
b4fdf52
 
 
51086f9
 
 
b4fdf52
6b0b418
 
 
51086f9
6b0b418
 
 
 
 
 
 
 
 
b4fdf52
51086f9
 
 
 
6b0b418
 
1669e26
6b0b418
 
51086f9
6b0b418
 
b4fdf52
 
6b0b418
51086f9
6b0b418
 
51086f9
b4fdf52
6b0b418
 
51086f9
 
 
 
6b0b418
51086f9
b4fdf52
6b0b418
51086f9
6b0b418
 
 
 
 
 
 
f296f61
51086f9
 
b4fdf52
 
51086f9
b4fdf52
f296f61
6b0b418
 
 
 
 
 
 
 
b4fdf52
1669e26
51086f9
209a2f8
1669e26
209a2f8
1669e26
 
51086f9
1669e26
b4fdf52
51086f9
 
1669e26
b4fdf52
 
 
 
f296f61
51086f9
1669e26
209a2f8
 
1669e26
 
 
 
b4fdf52
 
209a2f8
 
b4fdf52
 
1669e26
 
 
209a2f8
6b0b418
 
209a2f8
1669e26
6b0b418
1669e26
f296f61
b4fdf52
 
 
 
 
51086f9
f296f61
51086f9
f296f61
 
51086f9
 
b4fdf52
 
51086f9
 
 
b4fdf52
 
 
 
 
1669e26
209a2f8
1669e26
 
 
 
 
 
209a2f8
1669e26
 
 
 
209a2f8
b4fdf52
1669e26
 
 
 
b4fdf52
209a2f8
b4fdf52
 
 
 
 
 
 
209a2f8
8be7b60
b4fdf52
 
f296f61
 
 
 
 
 
 
 
b4fdf52
 
1669e26
6b0b418
209a2f8
6b0b418
1669e26
b4fdf52
1669e26
 
209a2f8
 
1669e26
6b0b418
209a2f8
6b0b418
 
f296f61
51086f9
b4fdf52
51086f9
 
 
 
 
 
 
6b0b418
 
b4fdf52
6b0b418
f296f61
b4fdf52
6b0b418
 
 
209a2f8
51086f9
6b0b418
b4fdf52
6b0b418
 
 
 
 
b4fdf52
6b0b418
51086f9
 
 
 
 
 
 
 
 
 
 
b4fdf52
 
51086f9
 
b4fdf52
 
 
 
6b0b418
b4fdf52
51086f9
209a2f8
 
1669e26
b4fdf52
1669e26
6b0b418
209a2f8
6b0b418
51086f9
6b0b418
51086f9
6b0b418
b4fdf52
6b0b418
 
51086f9
b4fdf52
6b0b418
 
 
b4fdf52
6b0b418
51086f9
6b0b418
b4fdf52
 
 
 
6b0b418
 
b4fdf52
 
 
 
 
 
 
51086f9
 
 
 
 
 
 
 
b4fdf52
 
209a2f8
 
6b0b418
b4fdf52
6b0b418
b4fdf52
 
6b0b418
b4fdf52
6b0b418
 
b4fdf52
 
 
 
51086f9
 
 
 
b4fdf52
 
 
 
 
 
6b0b418
 
b4fdf52
 
6b0b418
 
 
b4fdf52
6b0b418
 
 
 
 
 
b4fdf52
 
 
 
 
 
6b0b418
b4fdf52
6b0b418
 
 
51086f9
 
 
b4fdf52
51086f9
6b0b418
 
51086f9
b4fdf52
 
 
 
 
 
 
6b0b418
 
 
51086f9
 
 
 
 
6b0b418
b4fdf52
 
 
6b0b418
51086f9
 
 
 
 
 
 
 
6b0b418
 
 
b4fdf52
f296f61
6b0b418
 
 
b4fdf52
51086f9
b4fdf52
51086f9
6b0b418
 
f296f61
 
51086f9
b4fdf52
 
 
 
 
 
 
 
 
 
 
6b0b418
b4fdf52
 
51086f9
f296f61
b4fdf52
 
 
 
 
 
 
 
 
 
 
6b0b418
 
b4fdf52
6b0b418
 
 
b4fdf52
 
6b0b418
b4fdf52
 
f296f61
b4fdf52
 
6b0b418
 
b4fdf52
 
6b0b418
 
b4fdf52
 
 
 
 
 
 
 
6b0b418
b4fdf52
 
 
 
 
6b0b418
b4fdf52
 
 
 
 
6b0b418
b4fdf52
 
 
 
 
 
 
6b0b418
b4fdf52
6b0b418
b4fdf52
51086f9
b4fdf52
 
51086f9
b4fdf52
 
6b0b418
 
 
 
51086f9
6b0b418
51086f9
f296f61
51086f9
 
 
f296f61
51086f9
 
 
 
 
 
 
 
 
 
 
 
 
 
f296f61
b4fdf52
51086f9
 
b4fdf52
51086f9
 
 
6b0b418
b4fdf52
51086f9
 
6b0b418
51086f9
6b0b418
 
 
4559e6a
f296f61
4559e6a
51086f9
f296f61
51086f9
 
 
 
 
 
b4fdf52
 
 
51086f9
 
b4fdf52
 
 
 
 
 
 
 
 
 
 
 
 
51086f9
b4fdf52
 
51086f9
b4fdf52
51086f9
 
 
b4fdf52
 
51086f9
b4fdf52
51086f9
 
 
 
 
 
 
 
 
 
 
 
 
b4fdf52
 
51086f9
b4fdf52
51086f9
b4fdf52
 
 
 
1669e26
 
b4fdf52
 
 
51086f9
 
 
 
 
 
 
 
b4fdf52
 
51086f9
b4fdf52
 
 
 
 
 
51086f9
 
 
 
 
 
 
 
b4fdf52
 
 
1669e26
f296f61
b4fdf52
 
 
 
 
1669e26
 
 
b4fdf52
51086f9
f296f61
6b0b418
 
 
b4fdf52
 
 
 
 
 
 
 
6b0b418
 
b4fdf52
 
 
f296f61
 
6b0b418
 
 
b4fdf52
 
1669e26
b4fdf52
 
4559e6a
b4fdf52
f296f61
b4fdf52
f296f61
 
4559e6a
b4fdf52
209a2f8
b4fdf52
 
1669e26
209a2f8
6b0b418
b4fdf52
 
 
 
 
51086f9
b4fdf52
 
 
 
 
51086f9
 
 
 
 
 
b4fdf52
 
 
 
 
 
51086f9
 
 
 
 
 
b4fdf52
 
 
51086f9
 
 
 
 
 
 
 
 
b4fdf52
 
51086f9
 
b4fdf52
 
1669e26
b4fdf52
1669e26
b4fdf52
 
209a2f8
b4fdf52
 
209a2f8
 
b4fdf52
 
 
209a2f8
b4fdf52
209a2f8
 
b4fdf52
51086f9
b4fdf52
51086f9
b4fdf52
 
51086f9
b4fdf52
 
209a2f8
 
 
b4fdf52
 
 
51086f9
 
 
 
 
b4fdf52
 
 
51086f9
 
b4fdf52
 
 
 
51086f9
 
b4fdf52
 
 
 
51086f9
209a2f8
51086f9
b4fdf52
51086f9
b4fdf52
 
 
 
51086f9
209a2f8
51086f9
209a2f8
b4fdf52
 
209a2f8
 
 
b4fdf52
 
51086f9
 
 
 
 
 
 
 
b4fdf52
 
51086f9
b4fdf52
51086f9
 
 
 
b4fdf52
51086f9
b4fdf52
51086f9
 
b4fdf52
209a2f8
b4fdf52
51086f9
209a2f8
51086f9
 
 
 
 
 
 
6b0b418
b4fdf52
51086f9
b4fdf52
51086f9
b4fdf52
 
 
 
 
 
51086f9
b4fdf52
 
51086f9
209a2f8
 
 
b4fdf52
51086f9
 
 
 
 
 
 
 
b4fdf52
 
 
51086f9
 
b4fdf52
51086f9
b4fdf52
51086f9
 
209a2f8
6b0b418
b4fdf52
 
51086f9
b4fdf52
 
 
 
 
51086f9
b4fdf52
 
 
 
51086f9
 
b4fdf52
51086f9
209a2f8
6b0b418
51086f9
b4fdf52
51086f9
b4fdf52
 
51086f9
 
 
 
b4fdf52
51086f9
 
 
b4fdf52
 
51086f9
b4fdf52
 
 
51086f9
b4fdf52
 
51086f9
b4fdf52
51086f9
 
b4fdf52
 
 
 
 
 
6b0b418
b4fdf52
51086f9
 
 
 
 
 
 
 
 
 
f296f61
51086f9
209a2f8
51086f9
b4fdf52
1669e26
51086f9
 
6b0b418
b4fdf52
 
 
 
 
 
 
 
 
 
 
 
 
51086f9
 
 
b4fdf52
 
6b0b418
51086f9
 
 
 
 
6b0b418
51086f9
 
b4fdf52
 
51086f9
 
 
 
6b0b418
f296f61
b4fdf52
 
 
 
6b0b418
b4fdf52
 
209a2f8
b4fdf52
 
f296f61
51086f9
f296f61
b4fdf52
51086f9
 
 
 
 
 
 
f296f61
b4fdf52
 
 
 
f296f61
6b0b418
b4fdf52
 
 
 
6b0b418
b4fdf52
 
6b0b418
51086f9
 
b4fdf52
 
 
 
 
51086f9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f296f61
51086f9
 
 
6b0b418
209a2f8
51086f9
6b0b418
b4fdf52
 
6b0b418
51086f9
 
 
 
6b0b418
b4fdf52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6b0b418
 
b4fdf52
 
 
6b0b418
1669e26
6b0b418
b4fdf52
 
 
 
 
51086f9
 
 
 
 
b4fdf52
6b0b418
51086f9
 
 
b4fdf52
51086f9
b4fdf52
51086f9
 
 
 
 
 
4559e6a
b4fdf52
f296f61
b4fdf52
 
f296f61
 
b4fdf52
 
 
4559e6a
 
 
b4fdf52
51086f9
1669e26
 
b4fdf52
6b0b418
b4fdf52
 
 
 
6b0b418
b4fdf52
 
6b0b418
b4fdf52
6b0b418
b4fdf52
6b0b418
 
 
b4fdf52
 
6b0b418
b4fdf52
51086f9
b4fdf52
 
1669e26
b4fdf52
 
 
 
 
1669e26
51086f9
209a2f8
51086f9
b4fdf52
 
 
 
51086f9
209a2f8
 
 
f296f61
b4fdf52
51086f9
 
 
 
 
 
 
b4fdf52
 
51086f9
 
 
b4fdf52
51086f9
b4fdf52
 
51086f9
b4fdf52
 
 
 
 
 
209a2f8
b4fdf52
51086f9
b4fdf52
 
51086f9
b4fdf52
 
51086f9
b4fdf52
 
 
51086f9
 
 
 
 
 
 
b4fdf52
 
51086f9
b4fdf52
 
51086f9
b4fdf52
 
 
209a2f8
b4fdf52
 
 
 
 
6b0b418
51086f9
 
b4fdf52
 
51086f9
 
 
 
 
 
 
 
b4fdf52
51086f9
 
 
 
b4fdf52
 
6b0b418
 
b4fdf52
 
 
 
 
51086f9
 
 
 
b4fdf52
6b0b418
51086f9
 
 
6b0b418
b4fdf52
 
6b0b418
 
b4fdf52
6b0b418
 
 
7f2f296
 
51086f9
7f2f296
 
 
adfc6f1
7f2f296
51086f9
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
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
console.log("Script execution started.");

// --- Sidebar Functionality ---
// (Ваш оригинальный код для Sidebar остается без изменений)
let activeFolderElement = null; // DOM element of the currently active folder for new file creation
let activeSidebarFileId = null; // ID of the file whose content is loaded into fileContentForAI
const sidebarFileContents = new Map(); // Stores content of files in sidebar: fileId -> content
let folderIdCounter = 0;
let fileIdCounter = 0;

function initializeSidebar() {
    const sidebar = document.getElementById('sidebar');
    const sidebarToggle = document.getElementById('sidebar-toggle');
    const sidebarTitle = document.getElementById('sidebar-title');
    const newFolderBtn = document.getElementById('new-folder-btn');
    const newFileBtn = document.getElementById('new-file-btn');

    if (sidebarToggle) {
        sidebarToggle.addEventListener('click', function() {
            sidebar.classList.toggle('sidebar-collapsed');
            const icon = sidebarToggle.querySelector('.material-icons-round');
            if (sidebar.classList.contains('sidebar-collapsed')) {
                icon.textContent = 'chevron_right';
                if(sidebarTitle) sidebarTitle.style.display = 'none';
                 // Use more specific selector if possible, or ensure class exists
                document.querySelectorAll('.folder-name, .file-name, #sidebar-controls, .folder-toggle-icon, .folder-actions').forEach(el => el.style.display = 'none');
            } else {
                icon.textContent = 'chevron_left';
                if(sidebarTitle) sidebarTitle.style.display = 'inline';
                document.querySelectorAll('.folder-name, .file-name, #sidebar-controls, .folder-toggle-icon, .folder-actions').forEach(el => el.style.display = 'inline');
                 // Ensure expanded state icons are correct
                document.querySelectorAll('.folder.expanded .folder-toggle-icon').forEach(icon => icon.textContent = 'expand_less');
                document.querySelectorAll('.folder:not(.expanded) .folder-toggle-icon').forEach(icon => icon.textContent = 'expand_more');
            }
        });
    }

    // Use event delegation on a stable parent for folder clicks
    const sidebarFoldersContainer = document.getElementById('sidebar-folders'); // Assuming you have a container
    if (sidebarFoldersContainer) {
        sidebarFoldersContainer.addEventListener('click', function(event) {
            const header = event.target.closest('.folder-header');
            if (header) {
                const folder = header.parentElement;
                const icon = header.querySelector('.folder-toggle-icon');
                const isToggleButton = event.target.closest('.folder-toggle-icon');
                const isActionButton = event.target.closest('.folder-actions');

                 // Toggle expansion only if clicking header itself or toggle icon, but NOT actions
                 if (!isActionButton) {
                    folder.classList.toggle('expanded');
                    if (icon) { // Check if icon exists
                       icon.textContent = folder.classList.contains('expanded') ? 'expand_less' : 'expand_more';
                    }
                 }

                 // Set active folder ONLY if clicking the header area (excluding toggle/actions)
                 if (!isToggleButton && !isActionButton) {
                     if (activeFolderElement && activeFolderElement !== folder) {
                        activeFolderElement.classList.remove('active-folder');
                    }
                    activeFolderElement = folder;
                    activeFolderElement.classList.add('active-folder');
                    console.log("Active folder set to:", activeFolderElement.id || activeFolderElement.querySelector('.folder-name')?.textContent || 'Unknown Folder');
                }
            }
        });
    } else {
         console.warn("Sidebar folders container not found for event delegation.");
         // Fallback to original direct binding (less efficient for many folders)
         document.querySelectorAll('.folder-header').forEach(header => {
             header.addEventListener('click', function(event) {
                 // Allow clicks on icons within header to not set active folder
                 if (event.target.closest('.folder-actions') || event.target.closest('.folder-toggle-icon')) return;

                 const folder = this.parentElement;
                 folder.classList.toggle('expanded');
                 const icon = this.querySelector('.folder-toggle-icon');
                  if (icon) { // Check if icon exists
                      icon.textContent = folder.classList.contains('expanded') ? 'expand_less' : 'expand_more';
                  }


                 // Set active folder
                 if (activeFolderElement && activeFolderElement !== folder) {
                     activeFolderElement.classList.remove('active-folder');
                 }
                 activeFolderElement = folder;
                 activeFolderElement.classList.add('active-folder');
                 console.log("Active folder set to:", activeFolderElement.id || activeFolderElement.querySelector('.folder-name')?.textContent || 'Unknown Folder');
             });
         });
          // Separate handler for toggle icon if needed with fallback
         document.querySelectorAll('.folder-toggle-icon').forEach(icon => {
             icon.addEventListener('click', function() {
                 const folder = this.closest('.folder');
                 if (folder) {
                     folder.classList.toggle('expanded');
                     this.textContent = folder.classList.contains('expanded') ? 'expand_less' : 'expand_more';
                 }
             });
         });
    }


    // Initial setup for existing files if any (though typically added dynamically)
    document.querySelectorAll('.file').forEach(file => {
        attachFileClickListener(file);
    });

    if (newFolderBtn) {
        newFolderBtn.addEventListener('click', createNewFolder);
    }
    if (newFileBtn) {
        newFileBtn.addEventListener('click', createNewFileInActiveFolder);
    }
}

function attachFileClickListener(fileElement) {
    fileElement.addEventListener('click', function() {
        document.querySelectorAll('.file').forEach(f => f.classList.remove('active'));
        this.classList.add('active');
        activeSidebarFileId = this.dataset.fileId;
        fileContentForAI = sidebarFileContents.get(activeSidebarFileId) || "";

        // Update UI to reflect active file
        const fileName = this.dataset.fileName || 'Selected File';
        if(mainInput) {
            mainInput.value = `File: ${fileName}\nTask: Summarize this file.`;
            mainInput.placeholder = `Task for file: ${fileName}...`;
        }
        if (fileInfoEl) fileInfoEl.style.display = 'none'; // Hide general upload info
        if (urlInfoEl) urlInfoEl.style.display = 'none';   // Hide URL info
        console.log(`Active file set: ${activeSidebarFileId}, content loaded for AI.`);
        if (fileInput) fileInput.value = null; // Clear file input if a sidebar file is selected
         // Ensure the correct tab is active if needed (e.g., switch back from video)
         if (videoStreamPanel && videoStreamPanel.classList.contains('active')) {
             // Optionally switch back to output or code tab
             document.querySelector('.tab-button[data-tab="output"]')?.click(); // Use optional chaining
         }
    });
}

function createNewFolder() {
    const folderName = prompt("Enter new folder name:", "New Folder");
    if (!folderName || folderName.trim() === "") return;

    folderIdCounter++;
    const newFolderId = `folder-dynamic-${folderIdCounter}`;
    const sanitizedFolderName = DOMPurify.sanitize(folderName);

    const folderDiv = document.createElement('div');
    folderDiv.className = 'folder';
    folderDiv.id = newFolderId;

    const headerDiv = document.createElement('div');
    headerDiv.className = 'folder-header';
    headerDiv.innerHTML = `
        <span class="folder-icon material-icons-round">folder</span>
        <span class="folder-name">${sanitizedFolderName}</span>
        <span class="folder-toggle-icon material-icons-round">expand_more</span>
        <span class="folder-actions" style="/* display:none; */"> <!-- Actions can be visible if needed -->
            <!-- Optional: Add folder-specific actions here if needed -->
            <!-- <button class="icon-button"><span class="material-icons-round">edit</span></button> -->
            <!-- <button class="icon-button"><span class="material-icons-round">delete</span></button> -->
        </span>
    `;

    const contentDiv = document.createElement('div');
    contentDiv.className = 'folder-content';

    folderDiv.appendChild(headerDiv);
    folderDiv.appendChild(contentDiv);

    const sidebarFoldersContainer = document.getElementById('sidebar-folders'); // Target specific container
    // Find a good place to insert, e.g., before the 'General Uploads' folder or at the end
    const generalUploadsFolder = document.getElementById('uploads-dropzone'); // Assuming this is a folder
    if (sidebarFoldersContainer) {
         if (generalUploadsFolder && generalUploadsFolder.parentElement === sidebarFoldersContainer) {
             sidebarFoldersContainer.insertBefore(folderDiv, generalUploadsFolder);
         } else {
             sidebarFoldersContainer.appendChild(folderDiv); // Append to container if dropzone not found there
         }
    } else {
         // Fallback if specific container not found
         const mainSidebar = document.getElementById('sidebar');
         if (generalUploadsFolder && mainSidebar) {
             mainSidebar.insertBefore(folderDiv, generalUploadsFolder);
         } else if (mainSidebar) {
             mainSidebar.appendChild(folderDiv);
         } else {
              console.error("Cannot add folder: Neither #sidebar-folders nor #sidebar found.");
              return;
         }
    }


    // Make new folder active and expand it
    if (activeFolderElement) activeFolderElement.classList.remove('active-folder');
    activeFolderElement = folderDiv;
    activeFolderElement.classList.add('active-folder');
    activeFolderElement.classList.add('expanded'); // Expand new folder by default
    const newIcon = headerDiv.querySelector('.folder-toggle-icon');
    if (newIcon) newIcon.textContent = 'expand_less'; // Update icon

    console.log(`Folder "${sanitizedFolderName}" created and set as active.`);

     // Check sidebar collapse state and hide text if needed
     const mainSidebar = document.getElementById('sidebar');
     if (mainSidebar && mainSidebar.classList.contains('sidebar-collapsed')) {
          document.querySelectorAll(`#${newFolderId} .folder-name, #${newFolderId} .folder-toggle-icon, #${newFolderId} .folder-actions`).forEach(el => el.style.display = 'none');
     }
}

function createNewFileInActiveFolder() {
    // Enhanced logic to find a folder if none is active
    if (!activeFolderElement) {
        console.log("No active folder selected. Trying to find a default or first folder.");
        activeFolderElement = document.getElementById('uploads-dropzone') || // Prioritize specific dropzone folder
                              document.querySelector('#sidebar-folders .folder'); // Fallback to the first folder
        if (activeFolderElement) {
             if (!activeFolderElement.classList.contains('active-folder')) {
                 if(document.querySelector('.folder.active-folder')) document.querySelector('.folder.active-folder').classList.remove('active-folder');
                 activeFolderElement.classList.add('active-folder');
             }
             console.log("Using folder:", activeFolderElement.id || activeFolderElement.querySelector('.folder-name')?.textContent);
        } else {
            alert("No folder available (active, default, or first found) to add a file to. Please create a folder first.");
            return;
        }
    }

     // Ensure the target folder (active or found) is expanded
     if (!activeFolderElement.classList.contains('expanded')) {
        activeFolderElement.classList.add('expanded');
        const icon = activeFolderElement.querySelector('.folder-toggle-icon');
        if (icon) icon.textContent = 'expand_less';
        console.log("Expanded target folder:", activeFolderElement.id || activeFolderElement.querySelector('.folder-name')?.textContent);
     }


    const fileName = prompt("Enter new file name (e.g., script.js, notes.txt):", "new_file.txt");
    if (!fileName || fileName.trim() === "") return;

    fileIdCounter++;
    const newFileId = `file-dynamic-${fileIdCounter}`;
    const sanitizedFileName = DOMPurify.sanitize(fileName);

    const fileDiv = document.createElement('div');
    fileDiv.className = 'file';
    fileDiv.dataset.fileId = newFileId;
    fileDiv.dataset.fileName = sanitizedFileName;

    fileDiv.innerHTML = `
        <span class="file-icon material-icons-round">description</span>
        <span class="file-name">${sanitizedFileName}</span>
    `;

    const folderContent = activeFolderElement.querySelector('.folder-content');
    if (folderContent) {
        folderContent.appendChild(fileDiv);
    } else {
        console.error("Could not find .folder-content in active folder:", activeFolderElement);
        // As a fallback, append to activeFolderElement itself if .folder-content is missing (less ideal structure)
        activeFolderElement.appendChild(fileDiv);
    }


    sidebarFileContents.set(newFileId, ""); // New file is empty initially
    attachFileClickListener(fileDiv);

    // Check sidebar collapse state and hide text if needed
     const mainSidebar = document.getElementById('sidebar');
     if (mainSidebar && mainSidebar.classList.contains('sidebar-collapsed')) {
          fileDiv.querySelector('.file-name').style.display = 'none';
     }

    // Optionally, make the new file active
    fileDiv.click(); // Simulate click to make it active and load its (empty) content

    const activeFolderName = activeFolderElement.querySelector('.folder-name')?.textContent || activeFolderElement.id;
    console.log(`File "${fileName}" created in folder "${activeFolderName}" with ID ${newFileId}.`);
}


// --- Module Imports ---
// (Ваш оригинальный код импорта остается без изменений)
let GoogleGenerativeAI, marked, DOMPurify;
try {
    const gaModule = await import('https://esm.sh/@google/generative-ai');
    GoogleGenerativeAI = gaModule.GoogleGenerativeAI;
    const markedModule = await import('https://esm.sh/marked');
    marked = markedModule.marked;
    const domPurifyModule = await import('https://esm.sh/dompurify');
    DOMPurify = domPurifyModule.default;

    if (!GoogleGenerativeAI || !marked || !DOMPurify || typeof Chart === 'undefined' || typeof pdfjsLib === 'undefined' || typeof Babel === 'undefined') {
         let missing = [];
         if(!GoogleGenerativeAI) missing.push("GoogleGenerativeAI");
         if(!marked) missing.push("marked");
         if(!DOMPurify) missing.push("DOMPurify");
         if(typeof Chart === 'undefined') missing.push("Chart.js");
         if(typeof pdfjsLib === 'undefined') missing.push("pdf.js");
         if(typeof Babel === 'undefined') missing.push("Babel");
        if (missing.length > 0) throw new Error(`Critical modules failed to load: ${missing.join(', ')}.`);
    }
    console.log("Core & external libraries seem available.");
} catch (error) {
    console.error("Fatal Error: Could not load core dependencies:", error);
    const errorMsgEl = document.getElementById('init-error-message') || { textContent: "" };
    const sdkErrorOverlayEl = document.getElementById('sdk-error-overlay') || { classList: { add: () => {} }};
    errorMsgEl.textContent = `Failed to load critical libraries: ${error.message}. Check network, console, and ensure all script tags are correct.`;
    sdkErrorOverlayEl.classList.add('visible');
    throw error; // Stop further execution
}

// --- UI Element References ---
// (Ваши оригинальные ссылки на UI элементы остаются без изменений)
const codeInputArea = document.getElementById('code-input-area');
const mainInput = document.getElementById('main-input');
const sendBtn = document.getElementById('send-btn');
const researchBtn = document.getElementById('research-btn');
const stopBtn = document.getElementById('stop-btn');
const uploadBtnLabel = document.getElementById('upload-btn-label');
const fileInput = document.getElementById('file-input');
const fileInfoEl = document.getElementById('file-info'); // General file info, less prominent now
const fileNameEl = document.getElementById('file-name');   // General file name, less prominent
const urlInfoEl = document.getElementById('url-info');
const urlInfoTextEl = document.getElementById('url-info-text');
const fetchUrlBtn = document.getElementById('fetch-url-btn');
const aiOverlay = document.getElementById('ai-overlay');
const aiStatusText = document.getElementById('ai-status-text');
const initStatusText = document.getElementById('init-status-text');
const sdkErrorOverlay = document.getElementById('sdk-error-overlay');
const reloadButton = document.getElementById('reload-button');
const outputFrame = document.getElementById('output-frame');
const fullCodeContent = document.getElementById('full-code-content');
const researchProgressEl = document.getElementById('research-progress');
const languageSelector = document.getElementById('language-selector');
const tabButtons = document.querySelectorAll('.tab-button');
const videoStreamPanel = document.getElementById('video-stream-panel');
const videoElement = document.getElementById('video-element');
const videoCanvas = document.getElementById('video-canvas');
const startStreamBtn = document.getElementById('start-stream-btn');
const stopStreamBtn = document.getElementById('stop-stream-btn');
const aiPlanContainer = document.getElementById('ai-plan-container');
const aiPlanContent = document.getElementById('ai-plan-content');


// --- Application State ---
// (Ваше оригинальное состояние приложения остается без изменений)
let genAI;
let model;
let generationInProgress = false;
let stopGenerationFlag = false;
let generatedCode = '';
let fileContentForAI = ""; // Primarily managed by sidebar file clicks or URL fetch now
let pyodide;
let pyodideLoadingPromise = null;
let currentLanguage = "HTML/CSS/JS (Web Page)";
window.currentAiChart = null;
let screenStream = null;
let currentScreenFrameDataUrl = "";

// --- Configuration Constants ---
// *** ВОССТАНОВЛЕНО: Ваш оригинальный API ключ и Имя модели ***
const API_KEY = "AIzaSyBCURZf72ZWwMN2SHZ7XCQoNgExV4WMX8E";
const MODEL_NAME = "gemini-2.0-flash-thinking-exp-1219"; // Ensure multimodal for screen analysis
// *** КОНЕЦ ВОССТАНОВЛЕНИЯ ***
const CORS_PROXY_URL_PREFIX = "https://api.allorigins.win/raw?url=";

// --- NEW: Solver Hyperparameters ---
const solverParams = {
    // Temperatures (Core) - Controls randomness/creativity vs focus
    initial_gen_temp_single: 1.0,      // Max exploration for Initial Plan/Idea Generation (G)
    refine_temp: 0.8,                  // High exploration for Research/Refinement (R) - Slightly reduced for more focused research
    verify_temp: 0.2,                  // High precision/determinism for Verification/Critique steps (Conceptual) (C)
    synthesis_temp: 0.85,              // Balanced synthesis for final Code/Analysis/Synthesis (S)

    // Sampling - Fine-tune token selection diversity
    topP: 0.98,                        // Wide nucleus for diversity, allows less probable tokens
    topK: 80,                          // Allow reasonably diverse tokens, prevents overly niche choices

    // Retry logic (Conceptual - influences prompt design)
    max_retries: 3,                    // Number of internal thought/retry cycles the AI should simulate

    // Token Limits (Adjust based on model & typical use cases - Gemini 1.5 handles large contexts well)
    // These should be generous for complex tasks, but check model limits if changing MODEL_NAME
    max_initial_tokens: 100000,          // Max tokens for the Plan generation response
    max_critique_tokens: 100000,         // Max tokens for critique steps (if implemented separately)
    max_refine_tokens: 100000,           // Max tokens for refinement/research responses
    max_synthesis_tokens: 100000,       // Max tokens for the final code/analysis generation // Adjusted slightly down from extreme max
    max_reasoning_tokens: 100000,       // Max tokens for internal reasoning (e.g., within Synthesis)

    // --- PPO-like Prompting Control Parameters (Conceptual - embedded in prompts) ---
    // These guide the *style* and *focus* of the generation within the prompts.
    // Values represent desired emphasis (0.0 = ignore, 1.0 = maximum focus).

    // For Default Mode (Code/Math/Complex Tasks Focus - MAXIMIZED emphasis)
    depth_focus_max: 0.95,             // Emphasize extreme depth, comprehensive understanding, consider edge cases.
    creativity_focus_max: 0.90,        // Emphasize high creativity, novel approaches, unique solutions, diverse ideas.
    analytical_rigor_max: 0.98,        // Demand extreme rigor, correctness, logical consistency, precision, verification.
    alternative_exploration_max: 0.95, // Demand wide exploration of alternatives, compare approaches, justify choices.
    efficiency_focus_max: 0.90,        // Explicit focus on optimal efficiency, performance, conciseness, resourcefulness.

    // For Simple Mode (Generic/Simpler Tasks Focus - MODERATE emphasis)
    depth_focus_simple: 0.65,          // Encourage moderate depth/insight, cover main points.
    creativity_focus_simple: 0.70,     // Encourage considering alternatives/angles, standard creative elements.
    analytical_rigor_simple: 0.75,     // Encourage reasonable accuracy/clarity, logical flow.
    alternative_exploration_simple: 0.60, // Encourage awareness of options, standard approaches.
    efficiency_focus_simple: 0.50,     // Mild awareness of efficiency, standard practices.
};


const SUPPORTED_LANGUAGES = [
    "HTML/CSS/JS (Web Page)", "JavaScript (Standalone)", "TypeScript",
    "React Component", "Next.js Page (Client-Side)", "Python (Pyodide)",
    "Java (Code Display)", "Go (Code Display)", "Node.js (Code Display)",
    "Flutter (Dart Code Display)", "Unity (C# Script Display)", "Data Analysis (from text/file/URL/screen)"
];
const DATA_ANALYSIS_LANG = "Data Analysis (from text/file/URL/screen)";


// --- Helper Functions ---
// (Ваши оригинальные вспомогательные функции остаются без изменений)
function showError(message) {
    console.error("showError called:", message);
    const errorMsgEl = document.getElementById('init-error-message');
    if (errorMsgEl) errorMsgEl.textContent = message;
    if (sdkErrorOverlay) sdkErrorOverlay.classList.add('visible');
    else alert("A critical error occurred: " + message);
}

function updateButtonStates(isGenerating) {
    if (sendBtn) sendBtn.disabled = isGenerating;
    if (researchBtn) researchBtn.disabled = isGenerating;
    if (fetchUrlBtn) fetchUrlBtn.disabled = isGenerating;
    if (fileInput) fileInput.disabled = isGenerating;
    if (uploadBtnLabel) {
        uploadBtnLabel.style.cursor = isGenerating ? 'not-allowed' : 'pointer';
        uploadBtnLabel.style.opacity = isGenerating ? 0.5 : 1;
    }
    if (startStreamBtn) startStreamBtn.disabled = isGenerating || screenStream !== null;
    if (stopBtn) stopBtn.style.display = isGenerating ? 'block' : 'none';
    if (!isGenerating && stopBtn) stopBtn.disabled = false; // Re-enable stop button when not generating

    const newFolderBtn = document.getElementById('new-folder-btn');
    const newFileBtn = document.getElementById('new-file-btn');
    if(newFolderBtn) newFolderBtn.disabled = isGenerating;
    if(newFileBtn) newFileBtn.disabled = isGenerating;
}

function showAiOverlay(visible, statusText = "Thinking...") {
    if (!aiOverlay || !aiStatusText || !researchProgressEl) {
        console.warn("AI Overlay elements not found.");
        return;
    }
    aiStatusText.textContent = statusText;
    aiOverlay.classList.toggle('visible', visible);

    // Determine if research progress should be shown
    const isResearching = statusText.toLowerCase().includes("researching");
    // Check for a potential data attribute, defaulting to false if not present or not "true"
    const showProgressAttr = researchProgressEl.dataset.showProgress === "true";
    const showResearchProgress = visible && isResearching && showProgressAttr;

    researchProgressEl.classList.toggle('hidden', !showResearchProgress);
}

function clearInputSourceInfo(preserveActiveFile = false) {
    if (fileInfoEl) fileInfoEl.style.display = 'none';
    if (fileNameEl) fileNameEl.textContent = '';
    if (urlInfoEl) urlInfoEl.style.display = 'none';
    if (urlInfoTextEl) urlInfoTextEl.textContent = '';
    if (!preserveActiveFile) {
        fileContentForAI = "";
        activeSidebarFileId = null; // Clear which sidebar file is active for AI
        document.querySelectorAll('.file.active').forEach(f => f.classList.remove('active'));
        if(mainInput && languageSelector) { // Reset placeholder if not preserving active file
             mainInput.placeholder = languageSelector.value === DATA_ANALYSIS_LANG ?
                `Describe task for content (file, URL, screen)...` :
                `Enter task for ${languageSelector.value.split('(')[0].trim()}...`;
        }
    }
    currentScreenFrameDataUrl = "";
    if (fileInput) fileInput.value = null;
}

// --- Initialization ---
// (Ваша оригинальная инициализация остается без изменений)
async function initializeApp() {
    console.log("initializeApp started");
    try {
        initializeSidebar(); // Initialize sidebar first

        if(initStatusText) initStatusText.textContent = "Initializing UI...";
        setupLanguageSelector();
        setupEventListeners();
        clearInputSourceInfo(); // Initial clear

        if(initStatusText) initStatusText.textContent = "Initializing Gemini...";
        if (!GoogleGenerativeAI) throw new Error("GoogleGenerativeAI SDK is not loaded.");
        genAI = new GoogleGenerativeAI(API_KEY);
        // *** Используем ваше имя модели ***
        model = genAI.getGenerativeModel({ model: MODEL_NAME });
        console.log(`Gemini model ${MODEL_NAME} initialized.`);


        if(codeInputArea) codeInputArea.disabled = false;
        if(mainInput) mainInput.disabled = false;
        updateButtonStates(false);

        if(mainInput) mainInput.placeholder = `Enter task, paste URL, use screen share, upload file, or select a file from workspace...`;
        if(codeInputArea) codeInputArea.placeholder = "Results will appear here...";
        if(initStatusText) initStatusText.textContent = "Gemini Ready. Loading Pyodide (background)...";

        // Use existing Pyodide loading logic
        pyodideLoadingPromise = loadPyodideInstance().then(() => {
            if(initStatusText) {
                initStatusText.textContent = initStatusText.textContent.replace("Loading Pyodide (background)...", "Ready (Gemini, Pyodide)");
                 console.log("Pyodide loaded successfully in background.");
            }
        }).catch(err => {
            console.warn("Pyodide background load failed:", err);
            if(initStatusText) {
                initStatusText.textContent = initStatusText.textContent.replace("Loading Pyodide (background)...", "Ready (Gemini; Pyodide failed)");
            }
        });

    } catch (error) {
        console.error("Initialization error in initializeApp:", error);
        showError(`Failed to initialize application: ${error.message}. Ensure API Key is correct and model name exists.`);
    }
}

function setupLanguageSelector() {
    if(!languageSelector) return;
    // Clear existing options before adding new ones
    languageSelector.innerHTML = '';
    SUPPORTED_LANGUAGES.forEach(lang => {
        const option = document.createElement('option');
        option.value = lang; option.textContent = lang;
        languageSelector.appendChild(option);
    });
    // Set default based on your original code or desired default
    const defaultLang = DATA_ANALYSIS_LANG; // Or "HTML/CSS/JS (Web Page)" if preferred
    languageSelector.value = defaultLang;
    currentLanguage = defaultLang;
    handleLanguageChange({target: languageSelector}); // Update placeholder initially
}

async function loadPyodideInstance() {
     // Check if already loading or loaded
    if (pyodideLoadingPromise) {
         console.log("Pyodide already loading/loaded (promise exists).");
         return pyodideLoadingPromise;
     }
    if (pyodide) {
        console.log("Pyodide instance already available.");
        return Promise.resolve(pyodide);
    }


    if (typeof loadPyodide === "undefined") {
         console.error("Pyodide main script (loadPyodide) not loaded.");
         throw new Error("Pyodide main script not loaded.");
     }
    console.log("Attempting to load Pyodide...");
    try {
        // Store the promise immediately
        pyodideLoadingPromise = loadPyodide({
             // indexURL: "https://cdn.jsdelivr.net/pyodide/v0.25.0/full/" // Optional: specify version
        });
        const inst = await pyodideLoadingPromise;
        console.log("Pyodide core loaded. Loading micropip...");
        await inst.loadPackage(["micropip"]);
        console.log("Micropip loaded.");
        pyodide = inst;
        // No need to clear pyodideLoadingPromise here, it resolves with the instance
        console.log("Pyodide instance initialized successfully.");
        return pyodide;
    } catch (error) {
        console.error("Pyodide loading error:", error);
        pyodide = null; // Ensure pyodide is null on failure
        pyodideLoadingPromise = Promise.reject(error); // Ensure promise rejects
        throw error; // Re-throw error
    }
}

// --- Event Listeners Setup ---
// (Ваша оригинальная настройка слушателей, но убедитесь, что send/research вызывают *WithPlan* версии)
function setupEventListeners() {
    console.log("Setting up event listeners.");
    if(reloadButton) reloadButton.addEventListener('click', () => window.location.reload());
    if(tabButtons) {
        tabButtons.forEach(button => {
            button.addEventListener('click', () => {
                tabButtons.forEach(btn => btn.classList.remove('active'));
                button.classList.add('active');
                const tabName = button.dataset.tab;

                document.getElementById('output-tab')?.classList.toggle('hidden', tabName !== 'output');
                document.getElementById('output-tab')?.classList.toggle('active', tabName === 'output');
                document.getElementById('code-tab')?.classList.toggle('hidden', tabName !== 'code');
                document.getElementById('code-tab')?.classList.toggle('active', tabName === 'code');
                const screenSharePanel = document.getElementById('video-stream-panel');
                if (screenSharePanel) {
                    screenSharePanel.classList.toggle('hidden', tabName !== 'video');
                    screenSharePanel.classList.toggle('active', tabName === 'video');
                }
                 handleLanguageChange({target: languageSelector}); // Update placeholder on tab change
            });
        });
         // Ensure initial state is correct (e.g., 'output' tab is visible)
         document.querySelector('.tab-button[data-tab="output"]')?.click();
    }
    if(fileInput) fileInput.addEventListener('change', handleFileUploadToSidebar); // Uses original handler
    if(fetchUrlBtn) fetchUrlBtn.addEventListener('click', handleFetchUrl);
    if(languageSelector) languageSelector.addEventListener('change', handleLanguageChange);
    // *** Убедитесь, что используются новые обработчики с планированием ***
    if(sendBtn) sendBtn.addEventListener('click', handleSendRequestWithPlan);
    if(researchBtn) {
        researchBtn.addEventListener('click', () => {
            const activeFileEl = activeSidebarFileId ? document.querySelector(`.file[data-file-id="${activeSidebarFileId}"]`) : null;
            const fileNameHint = activeFileEl ? `Topic related to file: ${activeFileEl.dataset.fileName}` : "";
            const query = mainInput.value.trim() || fileNameHint || fileContentForAI.substring(0, 100); // Use file content snippet as last resort topic

            if (query) {
                // *** Убедитесь, что используется новый обработчик с планированием ***
                performResearchWithPlan(query);
            } else {
                alert("Please enter a topic, select a file, provide content via URL/upload, or use screen share to provide context for research.");
            }
        });
    }
    if(mainInput) {
        mainInput.addEventListener('keypress', (e) => {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                const screenSharePanelActive = videoStreamPanel && videoStreamPanel.classList.contains('active');
                 // Prioritize active file/screen over URL in input, fetch URL only if input looks like URL AND no file/screen active
                 if (isValidURL(mainInput.value.trim()) && !screenSharePanelActive && !activeSidebarFileId && !fileContentForAI) { // Check fileContent too
                     handleFetchUrl();
                 } else {
                     // *** Убедитесь, что используется новый обработчик с планированием ***
                    handleSendRequestWithPlan();
                }
            }
        });
    }
    if(stopBtn) stopBtn.addEventListener('click', handleStopGeneration);
    if(startStreamBtn) startStreamBtn.addEventListener('click', startScreenStream);
    if(stopStreamBtn) stopStreamBtn.addEventListener('click', stopScreenStream);
}


// --- File, URL Processing ---
// (Ваши оригинальные функции обработки файлов и URL остаются без изменений)
async function handleFileUploadToSidebar(event) {
    const file = event.target.files[0];
    if (!file) return;

    let targetFolderElement = activeFolderElement;
    // Enhanced Folder Finding Logic from your original code
    if (!targetFolderElement) {
        targetFolderElement = document.getElementById('uploads-dropzone') || // Prioritize specific dropzone folder
                              document.querySelector('#sidebar-folders .folder') || // Fallback to the first folder in container
                              document.querySelector('.folder'); // Last resort: any folder
        if (targetFolderElement) {
             if (!targetFolderElement.classList.contains('active-folder')) {
                 if(document.querySelector('.folder.active-folder')) document.querySelector('.folder.active-folder').classList.remove('active-folder');
                 targetFolderElement.classList.add('active-folder');
             }
             activeFolderElement = targetFolderElement; // Set it as active for consistency
             console.log("No active folder for upload, using default/first folder:", activeFolderElement.id || activeFolderElement.querySelector('.folder-name')?.textContent);
        } else {
            alert("Error: No folder available to upload the file to. Please create a folder first.");
            clearInputSourceInfo();
            if (fileInput) fileInput.value = null;
            return;
        }
    }

     // Ensure target folder is expanded
    if (!targetFolderElement.classList.contains('expanded')) {
        targetFolderElement.classList.add('expanded');
         const icon = targetFolderElement.querySelector('.folder-toggle-icon');
         if(icon) icon.textContent = 'expand_less';
    }


    // Use the general file info elements temporarily for status during processing
    if(fileNameEl) fileNameEl.textContent = file.name;
    if(fileInfoEl) fileInfoEl.style.display = 'flex';
    showAiOverlay(true, `Processing ${file.name} for sidebar...`);

    try {
        let textContent = "";
        const fileType = file.name.split('.').pop().toLowerCase();
        const MAX_FILE_SIZE_MB = 50; // Example limit: 50MB
        if (file.size > MAX_FILE_SIZE_MB * 1024 * 1024) {
             throw new Error(`File size (${(file.size / 1024 / 1024).toFixed(1)}MB) exceeds the ${MAX_FILE_SIZE_MB}MB limit.`);
        }

        // Your original file reading logic
        if (fileType === 'pdf') textContent = await readPdfFile(file);
        else if (['txt', 'md', 'csv', 'js', 'py', 'html', 'css', 'json', 'xml', 'java', 'c', 'cpp', 'cs', 'go', 'rb', 'php', 'swift', 'kt', 'dart', 'rs'].includes(fileType)) textContent = await readGenericTextFile(file);
        else if (fileType === 'docx') {
            if (typeof mammoth !== 'undefined') textContent = await readDocxFileWithMammoth(file);
            else { textContent = `(mammoth.js not loaded for .docx: ${file.name})`; console.warn("Enable mammoth.js for .docx.");}
        } else if (fileType === 'doc') { textContent = `(.doc not supported: ${file.name})`; console.warn(".doc not supported.");
        } else { textContent = `(Unsupported readable type .${fileType}: ${file.name}, uploaded as reference)`; console.warn(`Unsupported type .${fileType} for direct reading, file added by name only.`);}


        // Truncate reasonably, adjust limit as needed
        const MAX_CONTENT_LENGTH = 500000; // Your original limit
        if (textContent.length > MAX_CONTENT_LENGTH) {
            console.warn(`Truncating file content from ${textContent.length} to ${MAX_CONTENT_LENGTH} characters.`);
            textContent = textContent.substring(0, MAX_CONTENT_LENGTH);
        }

        fileIdCounter++;
        const newFileId = `file-uploaded-${fileIdCounter}`;
        const sanitizedFileName = DOMPurify.sanitize(file.name);

        const fileDiv = document.createElement('div');
        fileDiv.className = 'file';
        fileDiv.dataset.fileId = newFileId;
        fileDiv.dataset.fileName = sanitizedFileName;
        fileDiv.innerHTML = `<span class="file-icon material-icons-round">description</span><span class="file-name">${sanitizedFileName}</span>`;

        const folderContent = targetFolderElement.querySelector('.folder-content');
        if (folderContent) {
            folderContent.appendChild(fileDiv);
        } else { // Fallback if no .folder-content div
             console.warn("Target folder missing '.folder-content' div, appending file directly to folder element.", targetFolderElement);
            targetFolderElement.appendChild(fileDiv);
        }


        sidebarFileContents.set(newFileId, textContent); // Store extracted content
        attachFileClickListener(fileDiv);

         // Check sidebar collapse state and hide text if needed
         const mainSidebar = document.getElementById('sidebar');
         if (mainSidebar && mainSidebar.classList.contains('sidebar-collapsed')) {
             fileDiv.querySelector('.file-name').style.display = 'none';
         }

        fileDiv.click(); // Make the newly uploaded file active

        // Switch to Data Analysis if not already selected
        if(languageSelector && languageSelector.value !== DATA_ANALYSIS_LANG) {
             languageSelector.value = DATA_ANALYSIS_LANG;
             handleLanguageChange({target: languageSelector}); // Trigger language change effects
        }
        if(mainInput) { // Updated placeholder and value after click()
            mainInput.placeholder = `Task for uploaded file: ${sanitizedFileName}...`;
            mainInput.value = `File: ${sanitizedFileName}\nTask: Analyze this uploaded file.`;
            mainInput.focus();
        }
         const activeFolderName = targetFolderElement.querySelector('.folder-name')?.textContent || targetFolderElement.id;
        console.log(`File "${file.name}" uploaded to folder "${activeFolderName}" and set as active.`);

    } catch (error) {
        console.error("File processing error for sidebar:", error);
        if(mainInput) mainInput.value = `Error processing ${file.name}: ${error.message}.`;
        alert(`Error processing file: ${error.message}`);
         clearInputSourceInfo(); // Clear info on error
    } finally {
        showAiOverlay(false);
        if (fileInfoEl) fileInfoEl.style.display = 'none'; // Hide general processing info
        if (fileInput) fileInput.value = null; // Clear file input
    }
}

function readGenericTextFile(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = event => resolve(event.target.result); reader.onerror = error => reject(error); reader.readAsText(file); }); }
async function readPdfFile(file) {
    if (typeof pdfjsLib === 'undefined') throw new Error("pdf.js library is not loaded.");
    // Use the worker source defined in your original code if present, or the CDN fallback
    if (!pdfjsLib.GlobalWorkerOptions.workerSrc) {
         // Check if pdfjsLib is defined before accessing GlobalWorkerOptions
         if (typeof pdfjsLib !== 'undefined') {
             pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.worker.min.js'; // Your original version
             console.log("Set pdf.js worker source to CDN fallback.");
         } else {
              throw new Error("pdf.js library defined but GlobalWorkerOptions not accessible.");
         }
    }
    const arrayBuffer = await file.arrayBuffer(); const pdf = await pdfjsLib.getDocument({data: arrayBuffer}).promise;
    let fullText = ""; for (let i = 1; i <= pdf.numPages; i++) { try {const page = await pdf.getPage(i); const textContent = await page.getTextContent(); fullText += textContent.items.map(item => item.str).join(" ") + "\n";} catch (pageError){ console.error(`Error processing PDF page ${i}:`, pageError); fullText += `\n[Error reading page ${i}]\n`;}} return fullText;
}
async function readDocxFileWithMammoth(file) { if (typeof mammoth === 'undefined') throw new Error("mammoth.js not loaded."); const arrayBuffer = await file.arrayBuffer(); const result = await mammoth.extractRawText({ arrayBuffer: arrayBuffer }); return result.value; }
function isValidURL(string) { try { const url = new URL(string); return url.protocol === "http:" || url.protocol === "https:"; } catch (_) { return false; }}

async function handleFetchUrl() {
    const url = mainInput.value.trim(); if (!isValidURL(url)) { alert("Invalid URL. Please enter a full URL including http:// or https://"); return; }
    clearInputSourceInfo(); // This will clear activeSidebarFileId
    if(urlInfoTextEl) urlInfoTextEl.textContent = url.length > 50 ? url.substring(0,47)+"..." : url; // Increased length slightly
    if(urlInfoEl) urlInfoEl.style.display = 'flex';
    showAiOverlay(true, `Fetching ${url.substring(0,50)}...`);
    try {
        const response = await fetch(`${CORS_PROXY_URL_PREFIX}${encodeURIComponent(url)}`);
        if (!response.ok) {
            const errorText = await response.text();
            console.error("Fetch error response:", errorText);
            throw new Error(`Fetch failed: ${response.status} ${response.statusText}. Proxy or target server issue. Details: ${errorText.substring(0,150)}`);
        }
         // Your original HTML parsing logic
        const html = await response.text();
        const doc = new DOMParser().parseFromString(html, "text/html");
        const article = doc.querySelector('article, main, [role="main"], .main, #main, .content, #content, body'); // Your original selector
        let text = "";
        if (article) {
            article.querySelectorAll('script, style, noscript, iframe, header, footer, nav, aside').forEach(el => el.remove());
            text = article.textContent || "";
        } else {
             console.warn("Could not find main content element using selectors, falling back to body text content.");
            text = doc.body ? doc.body.textContent || "" : ""; // Fallback to body
        }

        // Clean up whitespace and limit size using your original limit
        const MAX_URL_CONTENT_LENGTH = 500000; // Your original limit
        fileContentForAI = text.replace(/\s\s+/g, ' ').trim();
        if (fileContentForAI.length > MAX_URL_CONTENT_LENGTH) {
            console.warn(`Truncating URL content from ${fileContentForAI.length} to ${MAX_URL_CONTENT_LENGTH} characters.`);
            fileContentForAI = fileContentForAI.substring(0, MAX_URL_CONTENT_LENGTH);
        }


        activeSidebarFileId = null; // Ensure no sidebar file is considered active
        document.querySelectorAll('.file.active').forEach(f => f.classList.remove('active'));

        if (!fileContentForAI.trim()) console.warn("Extracted text from URL is empty or only whitespace.");

        if(languageSelector) languageSelector.value = DATA_ANALYSIS_LANG;
        currentLanguage = DATA_ANALYSIS_LANG;
        if(mainInput) {
            mainInput.placeholder = `Task for URL content...`; mainInput.value = `URL: ${url}\nTask: Summarize.`; mainInput.focus();
        }
         console.log(`Successfully fetched and processed content from URL: ${url}`);
    } catch (error) {
        console.error("URL fetch or processing error:", error);
        if(mainInput) mainInput.value = `Error fetching ${url}: ${error.message}.`;
        fileContentForAI = "";
        alert(`URL Error: ${error.message}. This could be due to the CORS proxy, the target website blocking requests, network issues, or errors during content extraction.`);
        clearInputSourceInfo(); // Clear info on error
    } finally { showAiOverlay(false); }
}


// --- Screen Share Functions ---
// (Ваши оригинальные функции Screen Share остаются без изменений)
async function startScreenStream() {
    if (screenStream) {
        console.log("Screen stream already active.");
        return;
    }
    if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) {
        try {
            screenStream = await navigator.mediaDevices.getDisplayMedia({
                video: { cursor: "always" }, // Recommend showing cursor
                audio: false
             });
            if(videoElement) {
                 videoElement.srcObject = screenStream;
                 videoElement.onloadedmetadata = () => {
                      // Use promise-based play()
                      videoElement.play().catch(e => console.error("Video play failed:", e));
                 };
                 // Handle potential errors during loading
                 videoElement.onerror = (e) => {
                     console.error("Video element error:", e);
                     alert("Error loading video stream.");
                     stopScreenStream(false);
                 };
            }
            if(startStreamBtn) startStreamBtn.classList.add('hidden');
            if(stopStreamBtn) stopStreamBtn.classList.remove('hidden');
            console.log("Screen sharing started.");
            // Handle stop via browser UI
            screenStream.getVideoTracks()[0].onended = () => {
                console.log("Screen sharing stopped by user or browser UI.");
                stopScreenStream(false); // Don't log again inside stop function
            };
             updateButtonStates(generationInProgress); // Update buttons now that stream is active
        } catch (err) {
            console.error("Screen share access error: ", err);
             // Provide more specific feedback if possible
             if (err.name === 'NotAllowedError') {
                 alert("Screen share permission denied. Please allow screen sharing in the browser prompt.");
             } else if (err.name === 'NotFoundError') {
                  // This error might mean no screen selected, or sometimes transient issues
                  alert("No screen/window selected, or screen sharing is unavailable. Please try again.");
             } else if (err.name === 'NotReadableError') {
                 alert("Screen source cannot be read. This might be due to hardware issues or operating system permissions. Please try sharing a different window or screen.");
             }
             else {
                 alert("Screen share access error: " + err.message + "\nMake sure you select a screen/window to share.");
             }
            if (screenStream) stopScreenStream(false); // Ensure cleanup if partially started
             updateButtonStates(generationInProgress); // Update buttons after failure
        }
    } else {
        alert("Screen Sharing (getDisplayMedia API) is not supported by your browser!");
         updateButtonStates(generationInProgress); // Update buttons if API not supported
    }
}

function stopScreenStream(logMessage = true) {
    if (screenStream) {
        screenStream.getTracks().forEach(track => track.stop());
        if(videoElement) videoElement.srcObject = null;
        screenStream = null;
        if(startStreamBtn) startStreamBtn.classList.remove('hidden');
        if(stopStreamBtn) stopStreamBtn.classList.add('hidden');
        currentScreenFrameDataUrl = ""; // Clear last captured frame
        if (logMessage) console.log("Screen sharing stopped.");
    } else {
        // Ensure buttons are in the correct state even if called redundantly
         if(startStreamBtn) startStreamBtn.classList.remove('hidden');
         if(stopStreamBtn) stopStreamBtn.classList.add('hidden');
    }
    updateButtonStates(generationInProgress); // Always update buttons after stopping attempt
}

async function captureScreenFrameAsDataURL() {
    // Added check for readyState >= HAVE_METADATA from your original code
    if (!screenStream || !videoElement || !videoElement.srcObject || videoElement.readyState < videoElement.HAVE_METADATA) {
        console.warn("Screen stream not active or video element not ready for capture.", {stream: !!screenStream, video: !!videoElement, srcObj: !!videoElement?.srcObject, readyState: videoElement?.readyState});
        if (!screenStream) alert("Screen sharing is not active. Please start sharing first.");
        else alert("Video stream is not ready yet (readyState < HAVE_METADATA). Please wait a moment and try again.");
        return null;
    }
    // Added check for dimensions from your original code
    if (videoElement.videoWidth === 0 || videoElement.videoHeight === 0) {
         console.warn("Video element has zero dimensions. Cannot capture frame.");
         alert("Cannot capture screen: Video dimensions are zero. Ensure content is visible in the stream and not minimized.");
         return null;
    }

    if (videoCanvas && videoElement) {
        videoCanvas.width = videoElement.videoWidth;
        videoCanvas.height = videoElement.videoHeight;
        const ctx = videoCanvas.getContext('2d');
        if (!ctx) {
             console.error("Failed to get 2D context from canvas.");
             alert("Failed to get drawing context for screen capture.");
             return null;
        }
        try {
            ctx.drawImage(videoElement, 0, 0, videoCanvas.width, videoCanvas.height);
            // Use JPEG for smaller size, adjust quality as needed
            return videoCanvas.toDataURL('image/jpeg', 0.85); // 85% quality JPEG
        } catch (e) {
            // Check for SecurityError specifically
            if (e.name === 'SecurityError') {
                 console.error("Error converting canvas to Data URL (Canvas Tainted):", e);
                 alert("Security Error: Could not capture screen frame. The content being shared (e.g., protected video, cross-origin iframe) prevents capture due to security restrictions ('tainted canvas'). Try sharing a different window or application.");
            } else {
                 console.error("Error converting canvas to Data URL:", e);
                 alert(`Could not capture screen frame due to an unexpected error: ${e.message}`);
            }
            return null;
        }
    } else {
        console.error("Video canvas or video element not found for capture.");
        return null;
    }
}



// --- Language/Code Handling ---
// (Ваши оригинальные функции обработки языка/кода остаются без изменений)
function handleLanguageChange(e) {
    currentLanguage = e.target.value;
    const screenSharePanelActive = videoStreamPanel && videoStreamPanel.classList.contains('active');
    if(mainInput) {
         // Logic to update placeholder based on context (from your original code)
         if (activeSidebarFileId && sidebarFileContents.has(activeSidebarFileId)) {
             const activeFileEl = document.querySelector(`.file[data-file-id="${activeSidebarFileId}"]`);
             if (activeFileEl) mainInput.placeholder = `Task for file: ${activeFileEl.dataset.fileName}...`;
             else mainInput.placeholder = `Task for selected file...`; // Fallback
         } else if (screenSharePanelActive) {
             mainInput.placeholder = "Describe task for the screen content...";
         } else if (currentLanguage === DATA_ANALYSIS_LANG) {
             mainInput.placeholder = `Describe task for content (file, URL, screen)...`;
         } else {
             mainInput.placeholder = `Enter task for ${currentLanguage.split('(')[0].trim()}...`;
         }
    }
    console.log("Language changed to:", currentLanguage);

    // Trigger Pyodide load if Python selected and not already loaded/loading (your original logic)
    if (currentLanguage === "Python (Pyodide)" && !pyodide && !pyodideLoadingPromise) {
        if(initStatusText && !initStatusText.textContent.includes("Pyodide")) {
             initStatusText.textContent = initStatusText.textContent.replace("Ready", "Loading Pyodide for Python tasks...");
             console.log("Initiating Pyodide load due to language selection.");
             loadPyodideInstance().then(() => {
                 if(initStatusText) initStatusText.textContent = initStatusText.textContent.replace("Loading Pyodide for Python tasks...", "Pyodide Ready.");
             }).catch(err => {
                 if(initStatusText) initStatusText.textContent = initStatusText.textContent.replace("Loading Pyodide for Python tasks...", "Pyodide Failed.");
             });
        } else if (pyodideLoadingPromise) {
             console.log("Pyodide is already loading.");
        }
    }
}
function handleStopGeneration() { if (generationInProgress) { stopGenerationFlag = true; if(stopBtn) stopBtn.disabled = true; if(aiStatusText) aiStatusText.textContent = "Stopping..."; console.log("Stop generation requested by user.");}}

async function runPythonCode(pythonCode) {
    if (!pyodide) {
        if(initStatusText && !initStatusText.textContent.includes("Pyodide failed") && !initStatusText.textContent.includes("Pyodide Ready")) initStatusText.textContent += " Waiting for Pyodide...";
        console.log("Python execution waiting for Pyodide...");
        try {
            // Use the existing promise or start loading if needed
            await (pyodideLoadingPromise || loadPyodideInstance());
            if (!pyodide) throw new Error("Pyodide failed to load previously.");
            if(initStatusText && initStatusText.textContent.includes("Waiting for Pyodide")) initStatusText.textContent = initStatusText.textContent.replace(" Waiting for Pyodide...", " Pyodide ready. Retrying Python.");
            console.log("Pyodide ready, retrying Python execution.");
        } catch (error) {
            console.error("Pyodide not available for Python execution:", error);
            if(outputFrame) outputFrame.srcdoc = `<div style='color:red;padding:20px;font-family:monospace;white-space:pre-wrap;background:#fff0f0;border:1px solid red;border-radius:8px;'><h3>Pyodide Error</h3><p>Pyodide (Python runtime) is not available or failed to load.</p><p><b>Cannot run Python code.</b></p><p>Error details: ${DOMPurify.sanitize(error.message)}</p></div>`;
            return; // Stop execution
        }
    }
    // Ensure output frame exists before proceeding
    if (!outputFrame) {
         console.error("Output frame not found for Python execution.");
         return;
    }

    outputFrame.srcdoc = `<div style="padding:20px;font-family:monospace;white-space:pre-wrap;background:#f0f0f0;border-radius:8px;">🐍 Running Python via Pyodide...</div>`;
    let pyStartTime = performance.now();
    try {
        console.log("Attempting to load packages from imports...");
        await pyodide.loadPackagesFromImports(pythonCode,
             { messageCallback: (msg) => console.log("Pyodide package msg:", msg) , errorCallback: (err) => console.warn("Pyodide package err:", err) } // Add callbacks for visibility
         );
        console.log("Packages loaded (or none needed). Executing Python code...");
        let capturedOutput = "";
        // Configure stdout and stderr capture
        pyodide.setStdout({ batched: (str) => capturedOutput += str + "\n" });
        pyodide.setStderr({ batched: (str) => capturedOutput += `<span style='color:red;'>Error: ${str}</span>\n` }); // Style stderr

        // Execute the Python code
        await pyodide.runPythonAsync(pythonCode);
        let pyEndTime = performance.now();
        console.log(`Python execution finished in ${(pyEndTime - pyStartTime).toFixed(2)} ms.`);

        // Display the captured output
        const outputHTML = capturedOutput.trim() ? DOMPurify.sanitize(capturedOutput) : "<span style='color:grey;'>Python code executed successfully. No explicit print output detected.</span>";
        outputFrame.srcdoc = `<div style="padding:20px;font-family:monospace;white-space:pre-wrap;background:#f9f9f9;border:1px solid #eee;border-radius:8px;"><h3>🐍 Python Output</h3>${outputHTML}</div>`;

    } catch (error) {
        let pyEndTime = performance.now();
        console.error("Python execution error:", error);
        // Display a detailed error message in the output frame
         const errorMessage = error.message ? error.message.replace(/</g, "&lt;").replace(/>/g, "&gt;") : "Unknown Python execution error"; // Basic sanitization for display
        outputFrame.srcdoc = `<div style='padding:20px;font-family:monospace;white-space:pre-wrap;color:red;background:#fff0f0;border:1px solid red;border-radius:8px;'><h3>🐍 Python Execution Error</h3><p>Execution failed after ${(pyEndTime - pyStartTime).toFixed(2)} ms.</p><pre>${DOMPurify.sanitize(errorMessage)}</pre></div>`;
    } finally {
         // Reset stdout/stderr to default if necessary (optional, usually not needed per execution)
         // pyodide.setStdout({});
         // pyodide.setStderr({});
    }
}

function transpileToRunnableJS(code, lang) {
    // Your original transpilation logic
    let displayLang = lang;
    if (lang === "TypeScript" && typeof Babel !== 'undefined') {
        try {
            const { code: jsCode } = Babel.transform(code, { presets: ['typescript'], filename: 'component.tsx' }); // Use .tsx filename hint for Babel
            code = `// Transpiled from TypeScript:\n${jsCode}`;
            displayLang = "JavaScript (from TypeScript)";
        } catch (e) {
            console.warn("TypeScript transpilation failed:", e);
            code = `// TypeScript (transpilation failed: ${e.message})\n${code}`;
            displayLang = "TypeScript (Transpilation Error)"; // Indicate error
        }
    } else if ((lang === "React Component" || lang === "Next.js Page (Client-Side)") && typeof Babel !== 'undefined') {
         try {
            // Ensure 'react' preset is used
            const { code: jsCode } = Babel.transform(code, { presets: ['react', 'env'], filename: 'component.jsx' }); // Add 'env' preset for modern JS, use .jsx hint
            code = `// Transpiled from JSX (React/Next.js):\n${jsCode}\n\n/* Note: This is a basic transpile for syntax viewing. Full React/Next.js functionality (state, hooks, lifecycle, routing) requires a proper build environment. */`;
            displayLang = "JavaScript (from JSX)";
        } catch (e) {
            console.warn("JSX transpilation failed:", e);
            code = `// JSX (transpilation failed: ${e.message})\n${code}`;
            displayLang = "JSX (Transpilation Error)"; // Indicate error
        }
    } else if (lang === "JavaScript (Standalone)") {
         displayLang = "JavaScript (Standalone)";
         // No notes needed unless you want to add context notes here too
    } else {
         // Handle other languages for display only
         displayLang = lang.replace(' (Code Display)','');
         code = `// Displaying code for: ${displayLang}\n// Live execution/transpilation not supported in this environment.\n\n${code}`;
    }

    // Consistent display wrapper using <pre>
    return `<div style="padding:15px; background-color: #282c34; color: #abb2bf; font-family: 'Courier New', Courier, monospace; font-size: 0.9em; border-radius: 8px; overflow:auto; height:100%;box-sizing:border-box;">
                <h4 style="color:#61afef; margin-top:0; margin-bottom:10px; border-bottom: 1px solid #3f434a; padding-bottom:5px;">${displayLang} Preview</h4>
                <pre style="margin:0; white-space:pre-wrap; word-break:break-all;">${DOMPurify.sanitize(code)}</pre>
            </div>`;
}


// --- Main Actions (Send Request, Research) with Planning Step ---

// *** NEW: Enhanced generatePlan function (using new detailed prompts) ***
async function generatePlan(taskDescription, contextSummary, taskType) {
    if (!aiPlanContainer || !aiPlanContent) {
        console.warn("AI Plan UI elements not found.");
        return "PLAN_UI_MISSING"; // Indicate UI missing
    }
    aiPlanContainer.classList.remove('hidden');
    aiPlanContent.innerHTML = "<i>🧠 Generating strategic plan...</i>";
    showAiOverlay(true, `Phase 1: Generating Plan for ${taskType}...`);
    console.log(`Generating plan for task type: ${taskType}`);

    // Determine focus level (simple vs max) - using MAX for planning as default
    const focusParams = solverParams; // Use MAX focus for planning

    const planPrompt = `
You are an expert AI Strategist and Project Planner. Your goal is to devise a concise, actionable, step-by-step plan to fulfill the user's request effectively and efficiently.

**User's Core Request:**
"${taskDescription}"

**Provided Context Summary:**
${contextSummary ? `"${contextSummary.substring(0, 300)}..."` : "No specific file/URL/screen context provided beyond the task description."}

**Task Type:** ${taskType}

**Your Task:**
Generate a step-by-step plan in Markdown bullet points. Critically analyze the request and context. Outline the key stages required to achieve the user's goal with high quality. Strive for creativity and thoroughness in the plan itself. Consider potential challenges and build steps to address them. Think about how to add extra value or detail based on the request.

**Guiding Principles (Emphasize these in your planning process):**
*   **Depth of Analysis (${focusParams.depth_focus_max}):** Thoroughly understand the requirements, nuances, and potential challenges. Go beyond the surface level. Think about edge cases and complexities.
*   **Analytical Rigor (${focusParams.analytical_rigor_max}):** Ensure the plan is logical, complete, and addresses the core objectives accurately. Anticipate verification needs.
*   **Creative Problem Solving & Detail (${focusParams.creativity_focus_max}):** Consider innovative or highly effective approaches. Plan steps that encourage adding creative details, examples, or richer features as requested by the user. How can the output be made *better* than a basic fulfillment?
*   **Exploration of Alternatives (${focusParams.alternative_exploration_max}):** Briefly consider different high-level strategies or structures if relevant, selecting the most promising. Justify complex choices implicitly through the plan steps.
*   **Efficiency (${focusParams.efficiency_focus_max}):** Aim for a plan that leads to a solution without unnecessary complexity or redundancy, while still achieving depth and quality.

**Output Format Instructions:**
*   Begin the plan *directly* with Markdown bullet points (\`- \` or \`* \`).
*   **NO conversational preamble**, introduction, or concluding remarks. Just the plan.
*   Keep the plan concise and focused on major steps (typically 4-8 steps, allowing for more detail).
*   Each step should be a clear action or analysis phase. Incorporate considerations for detail and creativity within the steps where appropriate.
*   Example Structure (more detailed):
    *   Deeply analyze user request: identify core function, desired style, specific features (e.g., "interactive elements", "data visualization type"), and constraints.
    *   Outline main structure/sections (e.g., HTML layout, Python class structure, report sections).
    *   Design and develop core logic/component A (consider alternative implementations briefly). Add detailed comments.
    *   Implement feature B with creative elements (e.g., unique CSS animations, varied data examples, insightful analysis points).
    *   Integrate components, ensuring smooth interaction and data flow.
    *   Refine UI/UX, add polishing details, enhance visual appeal or clarity.
    *   Perform final verification against requirements, check edge cases, ensure robustness.
    *   Format output according to specifications (e.g., self-contained HTML, clean Python script, structured Markdown).

**Generate the detailed, creative, and actionable plan now.**
`;

    // *** Используем параметры из solverParams ***
    const generationConfig = {
        temperature: solverParams.initial_gen_temp_single,
        topP: solverParams.topP,
        topK: solverParams.topK,
        maxOutputTokens: solverParams.max_initial_tokens,
    };

    try {
        console.log("Sending plan generation request to Gemini:", { prompt: planPrompt.substring(0, 500) + "...", config: generationConfig });
        const result = await model.generateContent(planPrompt, generationConfig); // Pass config as second arg

        // Handle potential stop request during generation
        if (stopGenerationFlag) {
             console.log("Plan generation stopped by user flag.");
             throw new Error("Plan generation stopped by user.");
         }

        const response = result?.response; // Use optional chaining
        const planText = response?.text ? response.text() : ""; // Safely access text()

        if (!planText.trim()) {
            console.error("Received empty plan from AI.", response); // Log the full response for debugging
             throw new Error("Received empty plan from AI.");
        }

        console.log("Plan received:\n", planText);
        if (aiPlanContent) {
            // Sanitize and render markdown
            // Ensure marked is available
            if (typeof marked !== 'undefined' && typeof marked.parse === 'function') {
                aiPlanContent.innerHTML = DOMPurify.sanitize(marked.parse(planText));
            } else {
                 console.warn("marked library not available for rendering plan.");
                 // Fallback to preformatted text
                 aiPlanContent.innerHTML = `<pre style="white-space: pre-wrap; word-wrap: break-word;">${DOMPurify.sanitize(planText)}</pre>`;
            }
        }
        return planText; // Return the raw plan text for the next step

    } catch (error) {
        console.error(`Error generating plan for ${taskType}:`, error);
        if (aiPlanContent) {
            aiPlanContent.innerHTML = `<p style="color:red;font-weight:bold;">Error Generating Plan</p><p style="color:red;">${DOMPurify.sanitize(error.message)}</p>`;
        }
        // Rethrow to be caught by the main handler and stop the process
        throw new Error(`Plan generation failed: ${error.message}`);
    }
}


// *** NEW: Enhanced handleSendRequestWithPlan function (using new detailed prompts and solverParams) ***
async function handleSendRequestWithPlan() {
    const taskDescription = mainInput ? mainInput.value.trim() : "";
    let capturedScreenImageDataUrl = null;
    const isScreenShareTabActive = videoStreamPanel && videoStreamPanel.classList.contains('active');
    let planText = ""; // To store the generated plan

    console.log("--- Starting New Request Cycle ---");
    console.log("Task:", taskDescription);
    console.log("Active File ID:", activeSidebarFileId);
    console.log("File Content Snippet:", fileContentForAI.substring(0, 100) + (fileContentForAI.length > 100 ? "..." : ""));
    console.log("Screen Share Tab Active:", isScreenShareTabActive);
    console.log("Current Language:", currentLanguage);


    // 1. Input Validation & Context Determination
    if (!taskDescription && !fileContentForAI && !(isScreenShareTabActive && screenStream)) {
        alert("Please enter a task, provide content (from sidebar, URL, upload), or activate screen share with a running stream.");
        updateButtonStates(false);
        if(aiPlanContainer) aiPlanContainer.classList.add('hidden'); // Hide plan container if no action
        return;
    }

    generationInProgress = true;
    stopGenerationFlag = false;
    updateButtonStates(true);
    if(aiPlanContainer) aiPlanContainer.classList.remove('hidden'); // Show plan container
    if(aiPlanContent) aiPlanContent.innerHTML = ""; // Clear previous plan view

    // Clear previous results
    if(codeInputArea) codeInputArea.value = "";
    if(outputFrame) outputFrame.srcdoc = `<p style="padding:20px; font-style:italic; color: #555;">Initiating request... waiting for plan.</p>`;
    if(fullCodeContent) fullCodeContent.textContent = "";
    if (window.currentAiChart) { window.currentAiChart.destroy(); window.currentAiChart = null; }


    let currentRequestMode; // "code_generation", "data_analysis", "screen_analysis"
    let contextSummaryForPlan = "";
    let mainRequestContent; // Will hold the prompt/parts for the main generation call


    try {
        // 2. Capture Screen (if applicable) BEFORE planning
        if (isScreenShareTabActive && screenStream) {
            showAiOverlay(true, `Capturing screen frame...`);
            capturedScreenImageDataUrl = await captureScreenFrameAsDataURL();
            if (!capturedScreenImageDataUrl) {
                // Error already shown by capture function if alert was used
                throw new Error("Screen capture failed. Cannot proceed.");
            }
            console.log("Screen frame captured successfully.");
            currentRequestMode = "screen_analysis";
            contextSummaryForPlan = "Real-time screen capture provided.";
             // Ensure Data Analysis mode is selected for screen tasks if language selector exists
             if (languageSelector && currentLanguage !== DATA_ANALYSIS_LANG) {
                console.log("Switching language to Data Analysis for screen task.");
                languageSelector.value = DATA_ANALYSIS_LANG;
                currentLanguage = DATA_ANALYSIS_LANG; // Update state immediately
            }
        } else if (activeSidebarFileId || fileContentForAI || currentLanguage === DATA_ANALYSIS_LANG) {
             // Prioritize active file name if available
            const activeFileEl = activeSidebarFileId ? document.querySelector(`.file[data-file-id="${activeSidebarFileId}"]`) : null;
            const fileNameHint = activeFileEl ? `File: ${activeFileEl.dataset.fileName}` : (fileContentForAI ? "Provided text/data content" : "General data analysis task");
            currentRequestMode = "data_analysis";
            contextSummaryForPlan = `${fileNameHint} (Content length: ${fileContentForAI.length} chars).`;
             // Ensure Data Analysis mode is selected if file content is primary input
             if (languageSelector && currentLanguage !== DATA_ANALYSIS_LANG && (activeSidebarFileId || fileContentForAI)) {
                 console.log("Switching language to Data Analysis for file/text task.");
                 languageSelector.value = DATA_ANALYSIS_LANG;
                 currentLanguage = DATA_ANALYSIS_LANG; // Update state immediately
             }
        } else {
            currentRequestMode = "code_generation";
            contextSummaryForPlan = `Target Language: ${currentLanguage}. No specific file content provided; focus on the task description.`;
             // Ensure language is NOT Data Analysis if it's a pure code gen task
             if (languageSelector && currentLanguage === DATA_ANALYSIS_LANG) {
                 console.warn("Data Analysis language selected, but no data context found. Reverting to default code language.");
                 // Revert to a sensible default like HTML/JS or the first language in the list
                 const defaultCodeLang = SUPPORTED_LANGUAGES.find(l => l !== DATA_ANALYSIS_LANG) || "HTML/CSS/JS (Web Page)";
                 languageSelector.value = defaultCodeLang;
                 currentLanguage = defaultCodeLang;
                 contextSummaryForPlan = `Target Language: ${currentLanguage}. No specific file content provided; focus on the task description.`; // Update context summary
             }
        }
         console.log(`Determined Request Mode: ${currentRequestMode}`);
         console.log(`Context for Plan: ${contextSummaryForPlan}`);


        // 3. Generate Plan
        planText = await generatePlan(taskDescription, contextSummaryForPlan, currentRequestMode);
        // generatePlan throws on error, so we only proceed if successful.
        if (stopGenerationFlag) throw new Error("Stopped by user after plan generation.");
        showAiOverlay(true, `Phase 2: Executing Plan for ${currentRequestMode}...`);
        if(outputFrame) outputFrame.srcdoc = `<p style="padding:20px; font-style:italic; color: #333;">Plan received. Generating content based on plan...</p>`;

        // 4. Prepare and Execute Main Generation Request based on Plan
        const focusParams = solverParams; // Use MAX focus for generation by default
        const chartCanvasHTML = `<div style="width:100%;height:100%;display:flex;align-items:center;justify-content:center;padding:10px;box-sizing:border-box;"><div style="width:95%;max-width:700px;height:95%;max-height:500px;"><canvas id="aiChart"></canvas></div></div>`;

        // --- Define Enhanced Prompts ---
        let mainPromptText = "";

        if (currentRequestMode === "screen_analysis") {
            if (!capturedScreenImageDataUrl) throw new Error("Internal Error: Screen analysis mode but no image data captured.");
            const base64ImageData = capturedScreenImageDataUrl.split(',')[1];
            const mimeType = capturedScreenImageDataUrl.substring(capturedScreenImageDataUrl.indexOf(':') + 1, capturedScreenImageDataUrl.indexOf(';'));

             // *** NEW DETAILED SCREEN ANALYSIS PROMPT ***
            mainPromptText = `
You are an exceptionally perceptive AI Visual Analyst Assistant. Your purpose is to meticulously analyze the provided screen image and respond to the user's task with insight, detail, and clarity, adhering strictly to the generated plan. Go beyond simple descriptions; infer purpose and relationships where appropriate based on standard UI/UX conventions, but clearly state when making inferences.

**User's Task/Question regarding this screen image:**
"${taskDescription || "Provide a highly detailed, comprehensive description of everything visible on this screen, including potential functions and relationships between elements."}"

**Generated Strategic Plan (Follow this precisely):**
--- PLAN START ---
${planText}
--- PLAN END ---

**Your Core Directives:**
1.  **Execute the Plan:** Follow the steps outlined in the plan above meticulously.
2.  **Image Focus & Detail:** Base your entire analysis *exclusively* on the visual information present in the provided image. **Do NOT speculate** about content outside the frame, hidden elements, user intentions, or application states not visually confirmed. Describe layout, text content, icons, colors, widgets, and their arrangement with high fidelity.
3.  **Analytical Depth & Rigor (${focusParams.depth_focus_max}, ${focusParams.analytical_rigor_max}):** Analyze details intensely. Identify key UI elements (buttons, input fields, menus, text blocks, images, containers). Describe their apparent state (enabled/disabled, selected, etc.). Analyze relationships between components (e.g., this button likely affects that list). Use rigorous observation.
4.  **Infer Purpose (Carefully):** Based on standard UI/UX patterns and visual cues, infer the likely purpose or function of elements (e.g., "This appears to be a search bar," "This button likely submits the form"). Clearly distinguish observation ("I see a button labeled 'Save'") from inference ("This button likely saves the current data").
5.  **Creativity in Observation (${focusParams.creativity_focus_max}):** Notice subtle details, visual hierarchy, potential usability issues, or interesting design choices visible in the image.
6.  **Clarity and Structure:** Present your findings in clear, well-structured Markdown format. Use headings, lists, and bolding logically to create an easy-to-understand analysis. Be detailed but avoid unnecessary jargon.

**Output Format Instructions:**
*   Output **ONLY** the final analysis in Markdown format.
*   Do **NOT** include any preamble, conversational text, apologies, or self-references like "Based on the image..." or "As an AI...". Start directly with the Markdown content (e.g., a heading like "# Screen Analysis").
*   Use appropriate Markdown for structure (headings, lists, bolding, code blocks for text snippets if helpful) to enhance readability.

**Analyze the provided screen image now according to the plan and these directives.**
`;
            // Gemini expects content in a specific parts structure for multimodal
             // Ensure parts are correctly formatted as an array
             mainRequestContent = [
                 { text: mainPromptText }, // Text part first
                 { inlineData: { mimeType: mimeType, data: base64ImageData } } // Then the image part
             ];


        } else if (currentRequestMode === "data_analysis") {
             // *** NEW DETAILED DATA ANALYSIS PROMPT ***
             mainPromptText = `
You are a sophisticated AI Data Scientist and Content Analyst, capable of deep insights and creative presentation. Your objective is to analyze the provided text/data context based on the user's task, execute the provided plan with exceptional rigor, and generate the *single most appropriate and insightful* output format: a well-styled raw HTML Table, a detailed raw Chart.js JSON configuration object, or a comprehensive and nuanced Markdown text analysis. Add value beyond the literal request where appropriate.

**User's Task:**
"${taskDescription}"

**Provided Content Context (approx. first ${fileContentForAI.length} chars):**
"""
${fileContentForAI || "No explicit content/data was provided. Analyze the user's task itself. If appropriate, generate illustrative example data conforming to the task's implied domain or explain complex concepts with high clarity."}
"""

**Generated Strategic Plan (Follow this precisely):**
--- PLAN START ---
${planText}
--- PLAN END ---

**Your Core Directives:**
1.  **Execute the Plan:** Adhere strictly to the steps in the generated plan, aiming for the highest quality outcome at each stage.
2.  **Deep & Insightful Analysis (${focusParams.depth_focus_max}, ${focusParams.analytical_rigor_max}):** Perform a thorough, multi-faceted analysis. Identify not just surface patterns but also underlying trends, correlations, anomalies, or key themes as required by the plan and task. Apply rigorous analytical thinking and statistical concepts if applicable and possible with the given data.
3.  **Creative & Optimal Format Selection (${focusParams.creativity_focus_max}, ${focusParams.efficiency_focus_max}):** Based on your deep analysis, determine the **single best format** for conveying the insights most effectively and creatively:
    *   **HTML Table:** Choose for structured, multi-dimensional data. Make it detailed. **Include inline CSS within `<style>` tags inside the table's parent `<div>` or directly on elements for good presentation** (borders, padding, alignment, perhaps subtle hover effects or striping). Ensure it's well-formed.
    *   **Chart.js JSON:** Choose for visualizing quantitative relationships. Select the *most effective* chart type (line for trends, bar for comparisons, pie for proportions, scatter for correlations, etc.). Generate a *complete* configuration including appropriate labels, titles, legends, tooltips, and potentially custom styling options within the \`options\` object to make the chart clear and visually appealing.
    *   **Markdown Text:** Choose for qualitative analysis, summaries, explanations, code analysis, Q&A, or when data is insufficient/unstructured for tables/charts. Make the analysis **rich and insightful**, well-structured with headings/lists, potentially including code snippets (\`\`\`), blockquotes, or bolding for emphasis. Go beyond a simple summary.
4.  **Alternative Exploration (${focusParams.alternative_exploration_max}):** Internally consider alternative analysis techniques or visualization types. Justify your final choice implicitly through the quality and appropriateness of the output.
5.  **Value Add:** Where appropriate, provide additional context, explain the significance of findings, or suggest next steps for analysis based on the results.

**CRITICAL Output Format Instructions:**
*   You **MUST** output **ONLY ONE** type of response: the raw HTML code for a table (potentially wrapped in a div with style), the raw JSON object for a Chart.js configuration, OR the raw Markdown text for analysis.
*   **NO PREAMBLE OR EXPLANATIONS:** Do **NOT** include any introductory text, conversational filler, apologies, or explanations about your format choice (e.g., "Here is the HTML table:", "I chose Markdown because...").
*   **RAW HTML (Styled):** If outputting a table, start directly with potentially a `<div>` containing `<style>` and then `<table>`, ending with `</table></div>`. Add meaningful inline CSS or CSS in the style block.
*   **RAW JSON (Complete):** If outputting Chart.js JSON, start directly with \`{\` and end with \`}\`. It MUST be valid JSON. Use the structure \`{ "type": "chartjs", "config": { "type": "chartType", "data": {...}, "options": {...} } }\`. Ensure 'config' is detailed and well-structured for Chart.js.
*   **RAW MARKDOWN (Rich):** If outputting text analysis, start directly with the Markdown content. Structure it well and make it insightful.
*   **Insufficient Data:** If the content is truly insufficient for the task, **default to Markdown** and provide a *detailed* explanation of why the task cannot be completed, what specific information is missing, and perhaps how the user could provide better data.

**Generate your single, high-quality response now, following the plan and adhering strictly to these directives.**
`;
             // Ensure content is formatted correctly as an array of parts if needed by the model, otherwise just text
             mainRequestContent = [{ text: mainPromptText }]; // Assuming text input is sufficient

        } else { // code_generation
            let languageInstructions = "";
             // *** Using NEW DETAILED Language Instructions ***
            switch(currentLanguage){
                case "HTML/CSS/JS (Web Page)": languageInstructions = `Generate a single, complete, self-contained HTML file. Embed CSS within \`<style>\` tags in the \`<head>\`. Embed JavaScript within \`<script>\` tags before the closing \`</body>\`. Ensure the code is functional, demonstrates the requested features robustly, and includes creative elements. Use modern HTML5, CSS3, and ES6+ JavaScript. Prioritize semantic HTML, accessibility (ARIA attributes, keyboard navigation considerations), and responsive design (using media queries or flexible layouts). Add detailed comments explaining architecture, complex logic, and CSS choices. Make it visually appealing and interactive. Incorporate diverse examples or variations requested by the user.`; break;
                case "Python (Pyodide)": languageInstructions = `Generate Python code specifically for execution in a Pyodide environment. Use standard Python 3.9+ features. Leverage built-in libraries (math, random, collections, json, etc.) extensively. If external packages (numpy, pandas, matplotlib) are absolutely necessary and justified, structure the code assuming they *might* be loaded via \`micropip\` or are already present. Use \`print()\` for all user-facing output. Write clean, PEP 8 compliant, idiomatic Python. Include clear docstrings for functions/classes and inline comments for complex sections. Implement error handling (try-except blocks) where appropriate. Structure the code logically with functions or classes for reusability. Provide varied and illustrative examples within the code or comments if applicable.`; break;
                case "JavaScript (Standalone)": languageInstructions = `Generate standalone JavaScript code (ES6+/ES2020+). Assume a modern browser environment by default, clearly state if Node.js is targeted or required. Avoid browser-specific APIs (like \`document\`, \`window\`) if aiming for cross-environment compatibility or Node.js. Implement robust error handling. Use modern features like async/await, classes, modules (if appropriate for structure, though output should be a single block). Add detailed JSDoc comments (\`/** ... */\`) for all functions, classes, and complex variables. Ensure code is well-structured, readable, and includes creative or detailed examples as per the task.`; break;
                case "TypeScript": languageInstructions = `Generate high-quality TypeScript code (.ts). Utilize strong typing rigorously: provide explicit type annotations for all variables, function parameters, and return values. Define and use interfaces or type aliases for all non-trivial data structures. Leverage advanced TypeScript features like generics, mapped types, conditional types where appropriate to enhance type safety and code clarity. Adhere to TypeScript best practices and common style guides. Include comprehensive TSDoc comments. Implement classes or functions as appropriate. Ensure the code is well-organized, handles potential null/undefined values safely (strict null checks implied), and includes creative details or variations.`; break;
                case "React Component": languageInstructions = `Generate a single, well-structured React functional component using JSX syntax (.jsx/.tsx). Import React and hooks (\`useState\`, \`useEffect\`, \`useContext\`, \`useRef\`, \`useCallback\`, \`useMemo\`) correctly and use them idiomatically. Implement state management logically. Handle side effects cleanly within \`useEffect\`. Write reusable and composable component code. Use TypeScript for prop types (define an \`interface Props\`) for robustness. Add detailed comments explaining the component's purpose, state, props, effects, and any complex logic. Incorporate creative UI elements, handle user interactions effectively, and pay attention to accessibility. Make it feature-rich based on the request.`; break;
                case "Next.js Page (Client-Side)": languageInstructions = `Generate a Next.js page component, explicitly marked with \`'use client';\` at the top. Use React functional component syntax with Hooks effectively. Include necessary imports from React and Next.js (\`next/link\`, \`next/image\`, \`next/router\`, etc.) where appropriate. Structure the component logically for a page. Manage state and side effects correctly on the client. Add detailed comments and implement TypeScript prop types. Focus on building a complete and creative page section according to the user's task, considering client-side rendering implications. Handle loading and error states gracefully if data fetching is implied.`; break;
                default: languageInstructions = `Generate high-quality, idiomatic code for ${currentLanguage.replace(' (Code Display)','').trim()}. Follow language-specific conventions and best practices rigorously. Ensure the code is clear, robust, well-commented (explaining the 'why' not just the 'what'), and thoroughly addresses all aspects of the user's task. Prioritize correctness, maintainability, and security. Include detailed examples or creative variations where applicable. Handle potential errors gracefully.`;
            }

             // *** NEW DETAILED CODE GENERATION PROMPT ***
            mainPromptText = `
You are a World-Class AI Software Engineer and Architect specializing in ${currentLanguage}. Your mission is to generate exceptional, production-quality code that precisely fulfills the user's request, adheres strictly to the generated plan, and embodies the principles of clarity, robustness, efficiency, and creativity. Go significantly beyond a basic implementation; aim for excellence.

**User Task:**
"${taskDescription}"

**Target Language/Framework:** ${currentLanguage}

**Specific Language Instructions & Advanced Best Practices:**
${languageInstructions}

**Generated Strategic Plan (Follow this precisely and meticulously):**
--- PLAN START ---
${planText}
--- PLAN END ---

**Core Directives & Quality Requirements (Apply Maximum Emphasis - Strive for Perfection):**
1.  **Execute the Plan Faithfully:** Implement every step of the plan thoroughly. Ensure the final code directly reflects the planned architecture and features.
2.  **Code Quality, Correctness & Robustness (${focusParams.analytical_rigor_max}):** Generate code that is not only syntactically perfect but also logically flawless, highly robust, and resilient to errors. Implement comprehensive error handling (e.g., try-catch, validation, handling edge cases, defensive programming). Write code that is demonstrably correct.
3.  **Depth, Completeness & Detail (${focusParams.depth_focus_max}):** Create a comprehensive, feature-rich solution. Fully implement all requested and implied functionality. Add numerous creative details, illustrative examples, configuration options, or variations that enhance the solution's value and demonstrate deep understanding. The output should feel complete, not like a mere skeleton.
4.  **Creativity, Innovation & "Wow Factor" (${focusParams.creativity_focus_max}):** Where the task allows, incorporate creative algorithms, elegant design patterns, unique user interface elements, or novel approaches that make the solution stand out. Generate diverse ideas and implement them thoughtfully. Add that extra touch that impresses.
5.  **Considered Alternatives & Justification (${focusParams.alternative_exploration_max}):** Internally evaluate different algorithms, data structures, or design patterns. Choose the optimal approach, balancing trade-offs (clarity, performance, maintainability). If the choice is non-obvious or particularly interesting, add brief comments explaining the rationale.
6.  **Efficiency & Optimization (${focusParams.efficiency_focus_max}):** Write code that is highly efficient in terms of time and space complexity where relevant, following language-specific best practices for performance tuning without sacrificing clarity unnecessarily.
7.  **Readability, Maintainability & Documentation:** Produce exceptionally clean, well-formatted code adhering to strict style guides (e.g., PEP 8, Prettier). Use highly descriptive names. Write extensive comments and documentation (e.g., docstrings, JSDoc, TSDoc) that make the code easy to understand, use, and maintain.

**CRITICAL Output Format Instructions:**
*   Output **ONLY** the raw code for the specified language (${currentLanguage}).
*   **NO MARKDOWN BACKTICKS** (\`\`\`) surrounding the code block whatsoever.
*   **NO EXPLANATIONS, PREAMBLE, CHATTY TEXT, OR META-COMMENTS about the code generation process.** Just the code itself, starting from the very first character (e.g., \`<!DOCTYPE html>\`, \`import ...\`, \`package ...\`, \`def ...\`, \`function ...\`, etc.) and ending with the last character of the code.

**Generate the exceptional ${currentLanguage} code now, adhering strictly to the plan and all directives.**
`;
             // Ensure content is formatted correctly for the model
             mainRequestContent = [{ text: mainPromptText }];
        }


        // 5. Execute the Main Generation Call
        // *** Используем параметры из solverParams ***
        const generationConfig = {
            temperature: solverParams.synthesis_temp, // Balanced temperature for synthesis
            topP: solverParams.topP,
            topK: solverParams.topK,
            maxOutputTokens: solverParams.max_synthesis_tokens, // Generous token limit for final output
             // stopSequences: ["```"] // Optional: Try to force stop if it insists on markdown, but risky
        };

        console.log(`Sending main ${currentRequestMode} request to Gemini:`, { config: generationConfig, promptSnippet: typeof mainRequestContent === 'string' ? mainRequestContent.substring(0,300) + "..." : mainRequestContent[0].text.substring(0,300) + "..."});

        // *** Отправляем запрос модели ***
        const result = await model.generateContent(mainRequestContent, generationConfig); // Pass config

        // Check for stop flag *after* the async call returns
        if (stopGenerationFlag) throw new Error("Stopped by user during content generation.");

        const response = result?.response; // Use optional chaining
        let rawRspTxt = "";
        // Check for response and text() method before calling (more robust check)
        if (response && typeof response.text === 'function') {
             rawRspTxt = response.text();
         } else if (response && response.candidates && response.candidates.length > 0 && response.candidates[0].content && response.candidates[0].content.parts && response.candidates[0].content.parts.length > 0 && typeof response.candidates[0].content.parts[0].text === 'string') {
             // Attempt to access candidate text if primary text() fails
             rawRspTxt = response.candidates[0].content.parts[0].text;
             console.warn("Recovered text from candidate structure.");
         } else {
             // Log the response structure if it's unusual and text extraction failed
             console.error("Unexpected response structure or no text found:", response);
             throw new Error("Received no valid text content from Gemini response.");
         }


        if (!rawRspTxt.trim()) {
             console.warn("Received empty or whitespace-only response from AI.");
             // Handle potentially empty but non-error responses gracefully
             generatedCode = `// AI returned an empty response for the task: ${taskDescription}`;
         } else {
             console.log("Raw response received (first 500 chars):", rawRspTxt.substring(0, 500));
             // More aggressive cleaning - remove potential markdown fences AND optional language hints
             generatedCode = rawRspTxt.replace(/^```(?:[a-zA-Z0-9_ .-]+)?\s*\n?([\s\S]*?)\n?```$/gm, '$1').trim();
             // Also remove potential leading/trailing whitespace left after cleaning
             generatedCode = generatedCode.trim();
         }


        // 6. Process and Display Results
         console.log("Processing and displaying results for mode:", currentRequestMode);
         showAiOverlay(true, `Finalizing ${currentRequestMode} results...`); // Update status


        // Используем вашу оригинальную логику отображения результатов
        if (currentRequestMode === "screen_analysis" || (currentRequestMode === "data_analysis" && !(generatedCode.startsWith("{") && generatedCode.endsWith("}")) && !generatedCode.toLowerCase().includes("<table"))) {
             // Default to Markdown rendering for screen analysis or non-chart/table data analysis
             let htmlOutput = "";
             if (typeof marked !== 'undefined' && typeof marked.parse === 'function') {
                 htmlOutput = DOMPurify.sanitize(marked.parse(generatedCode));
             } else {
                 console.warn("marked library not available for rendering screen/data analysis.");
                 htmlOutput = `<pre style="white-space: pre-wrap; word-wrap: break-word;">${DOMPurify.sanitize(generatedCode)}</pre>`; // Fallback
             }
            if(outputFrame) outputFrame.srcdoc = `<div style="padding:20px;background:white;border-radius:8px;max-height:100%;overflow-y:auto;font-family: Inter, sans-serif; line-height:1.6;">${htmlOutput}</div>`;
            if(codeInputArea) codeInputArea.value = generatedCode; // Show raw Markdown/text
            if(fullCodeContent) fullCodeContent.textContent = generatedCode;
             console.log(`Displayed ${currentRequestMode} results as Markdown.`);

        } else if (currentRequestMode === "data_analysis") {
            let isChart = false, isTable = false, chartCfg = null;
             // Check for Chart.js JSON structure (assuming the AI followed the prompt)
            if (generatedCode.startsWith("{") && generatedCode.endsWith("}")) {
                try {
                     const potentialJson = JSON.parse(generatedCode);
                     // Check for the specific structure requested in the prompt
                     if(potentialJson.type === "chartjs" && potentialJson.config && typeof potentialJson.config === 'object' && potentialJson.config.type && potentialJson.config.data) {
                         isChart = true;
                         chartCfg = potentialJson.config; // Use the 'config' part directly
                         console.log("Detected Chart.js JSON output.");
                     } else {
                         console.warn("Response is JSON but not the expected Chart.js structure. Treating as Markdown.");
                     }
                 } catch(e) {
                     console.warn("Response looked like JSON but failed to parse. Treating as Markdown:", e, generatedCode.substring(0,100));
                 }
            }
             // Check for HTML Table (more lenient check)
             if (!isChart && generatedCode.toLowerCase().trim().startsWith("<table") && generatedCode.toLowerCase().trim().endsWith("</table>")) {
                 isTable = true;
                 console.log("Detected HTML Table output.");
            }
              // Check for HTML Table with potential wrapper div+style
             if (!isChart && !isTable && generatedCode.toLowerCase().trim().startsWith("<div") && generatedCode.includes("<table")) {
                 isTable = true; // Assume it's the styled table output
                 console.log("Detected styled HTML Table output (wrapped in div).");
             }


            if(isChart && outputFrame && chartCfg){
                outputFrame.srcdoc = chartCanvasHTML; // Load the canvas container
                 outputFrame.onload = () => {
                     // Ensure onload runs only once
                    if (outputFrame.dataset.chartLoaded === 'true') return;
                    outputFrame.dataset.chartLoaded = 'true'; // Mark as loaded

                    try {
                        const chartCtx = outputFrame.contentWindow.document.getElementById('aiChart');
                        if(chartCtx) {
                            if(window.currentAiChart) window.currentAiChart.destroy(); // Destroy previous chart instance

                             // Check if Chart is already loaded in iframe
                            if (outputFrame.contentWindow.Chart) {
                                console.log("Chart.js already loaded in iframe. Rendering chart.");
                                window.currentAiChart = new outputFrame.contentWindow.Chart(chartCtx, chartCfg);
                            } else {
                                 // Load Chart.js dynamically into the iframe
                                console.log("Loading Chart.js into iframe...");
                                const script = outputFrame.contentWindow.document.createElement('script');
                                script.src = "https://cdn.jsdelivr.net/npm/chart.js"; // Ensure Chart.js is loaded
                                script.onload = () => {
                                     console.log("Chart.js loaded. Rendering chart.");
                                     // Ensure Chart constructor is available
                                     if (outputFrame.contentWindow.Chart) {
                                         window.currentAiChart = new outputFrame.contentWindow.Chart(chartCtx, chartCfg);
                                     } else {
                                          console.error("Chart constructor not found on iframe window after script load.");
                                          throw new Error("Chart constructor not found after script load.");
                                     }
                                };
                                script.onerror = () => {
                                     console.error("Failed to load Chart.js script into iframe.");
                                     if(outputFrame.contentDocument && outputFrame.contentDocument.body) outputFrame.contentDocument.body.innerHTML=`<div style='padding:10px;color:red'>Chart Error: Failed to load Chart.js library.</div>`;
                                }
                                outputFrame.contentWindow.document.head.appendChild(script);
                            }
                        } else {
                            throw new Error("Chart canvas element ('aiChart') not found in iframe after loading.");
                        }
                    } catch(e) {
                        console.error("Chart rendering error:", e);
                         // Display error and the config JSON in the iframe
                         if(outputFrame.contentDocument && outputFrame.contentDocument.body) outputFrame.contentDocument.body.innerHTML=`<div style='padding:10px;color:red'>Chart Rendering Error: ${DOMPurify.sanitize(e.message)}</div><h4 style='margin:10px;'>Generated Chart.js Config:</h4><pre style='font-size:0.8em;white-space:pre-wrap;word-break:break-all;background:#eee;padding:10px;border-radius:4px;'>${DOMPurify.sanitize(JSON.stringify(chartCfg,null,2))}</pre>`;
                    }
                    // Reset marker after processing
                    setTimeout(() => { outputFrame.dataset.chartLoaded = 'false'; }, 100);
                 };
                 // Store the raw JSON in the code areas
                if(codeInputArea) codeInputArea.value = JSON.stringify({ type: "chartjs", config: chartCfg }, null, 2); // Store the full wrapper structure
                if(fullCodeContent) fullCodeContent.textContent = codeInputArea.value;

            } else if (isTable && outputFrame){
                 // Sanitize table HTML allowing common table elements AND style tags/attributes
                 const sanitizedHtml = DOMPurify.sanitize(generatedCode,{
                      USE_PROFILES: {html: true},
                      ADD_TAGS: ['style', 'div'], // Allow style tag and wrapper div
                      ADD_ATTR: ['style'] // Allow inline style attributes
                 });
                outputFrame.srcdoc = `<div style="padding:10px;overflow:auto;background:white;border-radius:8px;">${sanitizedHtml}</div>`;
                if(codeInputArea) codeInputArea.value=generatedCode; // Store raw potentially styled HTML
                if(fullCodeContent) fullCodeContent.textContent=generatedCode;
                 console.log("Displayed data analysis results as HTML Table.");
            } else { // Fallback for data_analysis (Markdown)
                 let htmlOutput = "";
                 if (typeof marked !== 'undefined' && typeof marked.parse === 'function') {
                     htmlOutput = DOMPurify.sanitize(marked.parse(generatedCode));
                 } else {
                     console.warn("marked library not available for rendering data analysis markdown.");
                     htmlOutput = `<pre style="white-space: pre-wrap; word-wrap: break-word;">${DOMPurify.sanitize(generatedCode)}</pre>`; // Fallback
                 }
                if(outputFrame) outputFrame.srcdoc = `<div style="padding:20px;background:white;border-radius:8px;max-height:100%;overflow-y:auto;font-family: Inter, sans-serif;line-height:1.6;">${htmlOutput}</div>`;
                if(codeInputArea) codeInputArea.value=generatedCode; // Store raw Markdown
                if(fullCodeContent) fullCodeContent.textContent=generatedCode;
                 console.log("Displayed data analysis results as Markdown (fallback).");
            }


        } else { // code_generation
            console.log(`Processing code generation result for: ${currentLanguage}`);
            if(aiStatusText) aiStatusText.textContent = `Rendering ${currentLanguage} preview...`;
            if(outputFrame) {
                // Reset onload handler before setting srcdoc for non-chart cases
                outputFrame.onload = null;
                 outputFrame.dataset.chartLoaded = 'false'; // Reset chart loaded flag

                switch (currentLanguage) {
                    case "HTML/CSS/JS (Web Page)":
                         console.log("Setting outputFrame.srcdoc directly for HTML.");
                         outputFrame.srcdoc = generatedCode; // Assumes self-contained HTML
                         break;
                    case "Python (Pyodide)":
                         console.log("Running Python code via Pyodide.");
                         await runPythonCode(generatedCode); // Async function
                         break;
                    case "JavaScript (Standalone)":
                    case "TypeScript":
                    case "React Component":
                    case "Next.js Page (Client-Side)":
                         console.log(`Transpiling and previewing ${currentLanguage}.`);
                         outputFrame.srcdoc = transpileToRunnableJS(generatedCode, currentLanguage);
                         break;
                    default: // Other languages for display only
                         console.log(`Displaying code for ${currentLanguage} without execution.`);
                         outputFrame.srcdoc = transpileToRunnableJS(generatedCode, currentLanguage); // Use transpiler function for consistent display
                }
            }
            if(codeInputArea) codeInputArea.value = generatedCode; // Store raw generated code
            if(fullCodeContent) fullCodeContent.textContent = generatedCode;
             console.log("Displayed code generation results.");
        }

    } catch (error) {
        console.error("--- AI Request/Processing Error ---:", error);
        const errTxt = stopGenerationFlag ? "Operation stopped by user." : `Error: ${error.message}`;
        // Display error prominently
        if(aiPlanContent && planText) { // If plan succeeded but execution failed
            aiPlanContent.innerHTML += `<p style="color:red; font-weight:bold; margin-top:15px;">Execution Failed!</p><p style="color:red;">${DOMPurify.sanitize(errTxt)}</p>`;
        } else if (aiPlanContent) { // Plan generation itself failed (message already set)
             aiPlanContent.innerHTML += `<p style="color:red; font-weight:bold; margin-top:15px;">Content Generation Failed (due to plan error)</p>`;
        } else {
             // If plan UI itself failed or error happened before plan UI setup
             if(outputFrame) outputFrame.srcdoc = `<div style='color:red; padding:20px; font-family: Inter, sans-serif; border: 2px solid red; background: #fff0f0; border-radius: 8px;'><h3>Request Failed</h3><p style="font-weight:bold;">${DOMPurify.sanitize(errTxt)}</p><p>Check the console (F12) for more details.</p></div>`;
        }
        if(codeInputArea) codeInputArea.value += `\n\n--- ERROR ---\n${DOMPurify.sanitize(errTxt)}`;
        if(outputFrame && !outputFrame.srcdoc.includes("Request Failed")) { // Avoid overwriting specific Pyodide errors etc.
            outputFrame.srcdoc = `<div style='color:red; padding:20px; font-family: Inter, sans-serif; border: 2px solid red; background: #fff0f0; border-radius: 8px;'><h3>Request Failed</h3><p style="font-weight:bold;">${DOMPurify.sanitize(errTxt)}</p><p>Check the console (F12) for more details. Possible issues include API key problems, network errors, invalid input, or internal AI errors.</p></div>`;
        }

         // Specific check for multimodal model issues using your original logic
        if (error.message && (error.message.toLowerCase().includes("does not support image input") || error.message.toLowerCase().includes("multimodal"))) {
             // Check if body exists before appending
             if(outputFrame.contentDocument && outputFrame.contentDocument.body) {
                outputFrame.contentDocument.body.innerHTML += `<p style='color:orange;padding:0 20px 20px 20px; font-weight:bold;'>Note: The selected model ('${MODEL_NAME}') might not fully support image analysis required for screen sharing tasks. Ensure you are using a multimodal model if required.</p>`;
             } else {
                  outputFrame.srcdoc += `<p style='color:orange;padding:0 20px 20px 20px; font-weight:bold;'>Note: The selected model ('${MODEL_NAME}') might not fully support image analysis required for screen sharing tasks. Ensure you are using a multimodal model if required.</p>`;
             }
        }

    } finally {
        generationInProgress = false;
        stopGenerationFlag = false; // Reset flag
        updateButtonStates(false);
        showAiOverlay(false);
        currentScreenFrameDataUrl = ""; // Clear captured frame data
        // Don't hide aiPlanContainer here, leave plan (and potential error message) visible for reference
        console.log("--- Request Cycle Finished ---");
    }
}


// *** NEW: Enhanced performResearchWithPlan function (using new detailed prompts and solverParams) ***
async function performResearchWithPlan(topic) {
    if (!topic) { alert("Please provide a topic to research."); return; }
    if (generationInProgress) { alert("Another AI task is currently in progress. Please wait."); return; }

    console.log(`--- Starting New Research Cycle ---`);
    console.log(`Research Topic: ${topic}`);
    generationInProgress = true;
    stopGenerationFlag = false;
    updateButtonStates(true);
    if(aiPlanContainer) aiPlanContainer.classList.remove('hidden'); // Show plan container
    if(aiPlanContent) aiPlanContent.innerHTML = ""; // Clear previous plan view

    // Clear previous results
    if(codeInputArea) codeInputArea.value = "";
    if(outputFrame) outputFrame.srcdoc = `<p style="padding:20px; font-style:italic; color: #555;">Initiating research... waiting for plan.</p>`;
    if(fullCodeContent) fullCodeContent.textContent = "";
    if (window.currentAiChart) { window.currentAiChart.destroy(); window.currentAiChart = null; }

    let planText = "";

    try {
        // 1. Generate Research Plan
        const contextSummaryForPlan = `Research topic: "${topic}". Aim for depth, accuracy, and comprehensive synthesis.`;
        planText = await generatePlan(topic, contextSummaryForPlan, "research");
        // generatePlan throws on error
        if (stopGenerationFlag) throw new Error("Research stopped by user after plan generation.");
        showAiOverlay(true, `Phase 2: Executing Research Plan for: ${topic.substring(0, 50)}...`);
        if(outputFrame) outputFrame.srcdoc = `<p style="padding:20px; font-style:italic; color: #333;">Plan received. Researching topic: "${DOMPurify.sanitize(topic)}"...</p>`;

        // 2. Prepare and Execute Research Request based on Plan
        const focusParams = solverParams; // Use MAX focus for research quality

         // *** NEW DETAILED RESEARCH PROMPT ***
        const researchPrompt = `
You are an expert AI Research Assistant and Knowledge Synthesizer with access to a vast knowledge base. Your task is to conduct meticulous, in-depth research on the given topic, rigorously following the generated plan, and present a comprehensive, accurate, well-structured, and insightful summary of findings in Markdown format.

**Research Topic:**
"${topic}"

**Generated Strategic Plan (Follow this precisely and exhaustively):**
--- PLAN START ---
${planText}
--- PLAN END ---

**Core Directives & Quality Requirements:**
1.  **Execute the Plan Faithfully:** Adhere strictly to the research steps outlined in the plan. Ensure all facets mentioned in the plan are covered.
2.  **Comprehensiveness, Depth & Nuance (${focusParams.depth_focus_max}):** Gather information from diverse, reliable perspectives. Explore the topic deeply, covering key concepts, definitions, historical context, current state-of-the-art, methodologies, applications, debates, criticisms, and future trends as relevant and guided by the plan. Uncover non-obvious details.
3.  **Accuracy, Verification & Rigor (${focusParams.analytical_rigor_max}):** Prioritize factual accuracy above all. Cross-reference information where possible (conceptually). Synthesize information logically, coherently, and critically. Clearly distinguish established facts from theories, opinions, or speculations. Avoid making unsubstantiated claims.
4.  **Synthesis, Structure & Clarity (${focusParams.efficiency_focus_max}):** Do not merely list facts. Synthesize the information into a cohesive, well-organized narrative or structured report using clear Markdown (headings, subheadings, nested lists, bolding, italics, blockquotes). Ensure a logical flow and high readability. Define key terms.
5.  **Exploration of Perspectives & Creativity (${focusParams.alternative_exploration_max}, ${focusParams.creativity_focus_max}):** If the topic involves multiple viewpoints, theories, controversies, or approaches, represent them accurately and fairly. Present the information in an engaging and insightful manner.
6.  **Further Reading (Contextual & General):** Where appropriate, suggest *general areas*, *key concepts*, *influential figures*, or *seminal types of works* for further reading. **Do NOT invent fake URLs, specific book titles, or specific paper citations.** Focus on conceptual pointers that guide further exploration (e.g., "Further reading could explore behavioral economics principles," "Key figures in this field include...").
7.  **Acknowledge Limitations & Ambiguities:** If the topic is highly niche, information is genuinely scarce or contradictory, or there are significant unresolved questions, state this explicitly and clearly within the report. Do not invent information.

**CRITICAL Output Format Instructions:**
*   Output **ONLY** the final research findings in rich Markdown format.
*   **NO PREAMBLE OR CONVERSATIONAL TEXT:** Do not include introductions like "Here is the research on..." or "Based on my knowledge...". Start directly with the Markdown content (e.g., a top-level heading like \`# Research on: ${topic}\`).
*   Use Markdown extensively and effectively for structure, emphasis, and readability.

**Conduct the deep research and generate the comprehensive Markdown report now, following the plan and all directives.**
`;

        // *** Используем параметры из solverParams ***
        const generationConfig = {
            temperature: solverParams.refine_temp, // Use refine_temp for research/synthesis
            topP: solverParams.topP,
            topK: solverParams.topK,
            maxOutputTokens: solverParams.max_refine_tokens, // Allow ample space for research findings
        };

         console.log("Sending research request to Gemini:", { config: generationConfig, promptSnippet: researchPrompt.substring(0, 500) + "..." });
        // *** Отправляем запрос модели ***
        const result = await model.generateContent(researchPrompt, generationConfig); // Pass config

        // Check for stop flag *after* the async call returns
        if (stopGenerationFlag) throw new Error("Research stopped by user during generation.");

        const response = result?.response; // Use optional chaining
         let researchText = "";
         if (response && typeof response.text === 'function') {
             researchText = response.text();
         } else if (response && response.candidates && response.candidates.length > 0 && response.candidates[0].content && response.candidates[0].content.parts && response.candidates[0].content.parts.length > 0 && typeof response.candidates[0].content.parts[0].text === 'string') {
            researchText = response.candidates[0].content.parts[0].text;
            console.warn("Recovered research text from candidate structure.");
         }
         else {
             console.error("Unexpected response structure or no text found for research:", response);
             throw new Error("Received no valid text content from Gemini for research.");
         }


        if (!researchText.trim()) {
             console.warn("Received empty or whitespace-only research response from AI.");
             researchText = `*The AI returned an empty response for the research topic: "${topic}". Information might be unavailable, the topic might be too obscure, or the request could not be processed.*`;
         }

        // Basic cleaning - remove potential ``` markdown fences
        const cleanedResearchText = researchText.replace(/^```(?:markdown)?\s*\n?([\s\S]*?)\n?```$/gm, '$1').trim();
        console.log("Raw research response received (first 500 chars):", cleanedResearchText.substring(0, 500));


        // 3. Display Research Results
        if(aiStatusText) aiStatusText.textContent = `Finalizing research results for: ${topic.substring(0, 50)}...`;

        // Используем вашу оригинальную логику отображения
        if(codeInputArea) codeInputArea.value = `# Research on: ${topic}\n\n${cleanedResearchText}`;
        if(fullCodeContent) fullCodeContent.textContent = codeInputArea.value; // Show raw markdown in full code view too

        let htmlOutput = "";
         if (typeof marked !== 'undefined' && typeof marked.parse === 'function') {
            htmlOutput = DOMPurify.sanitize(marked.parse(cleanedResearchText)); // Render Markdown to HTML
         } else {
             console.warn("marked library not available for rendering research results.");
             htmlOutput = `<pre style="white-space: pre-wrap; word-wrap: break-word;">${DOMPurify.sanitize(cleanedResearchText)}</pre>`; // Fallback
         }

        if(outputFrame) {
             // Reset onload handler before setting srcdoc
             outputFrame.onload = null;
             outputFrame.dataset.chartLoaded = 'false'; // Reset chart loaded flag
            outputFrame.srcdoc = `<div style="padding:20px;background:white;border-radius:8px;max-height:100%;overflow-y:auto;font-family: Inter, sans-serif; line-height:1.6;"><h2>Research: ${DOMPurify.sanitize(topic)}</h2>${htmlOutput}</div>`;
        }
         console.log("Displayed research results as Markdown.");

    } catch (error) {
        console.error("--- Research Error ---:", error);
        const errTxt = stopGenerationFlag ? "Research operation stopped by user." : `Research Error: ${error.message}`;
        // Display error prominently
         if(aiPlanContent && planText) { // If plan succeeded but execution failed
            aiPlanContent.innerHTML += `<p style="color:red; font-weight:bold; margin-top:15px;">Research Execution Failed!</p><p style="color:red;">${DOMPurify.sanitize(errTxt)}</p>`;
        } else if (aiPlanContent) { // Plan generation itself failed (message already set)
             aiPlanContent.innerHTML += `<p style="color:red; font-weight:bold; margin-top:15px;">Research Failed (due to plan error)</p>`;
        } else {
            if(outputFrame) outputFrame.srcdoc = `<div style='color:red; padding:20px; font-family: Inter, sans-serif; border: 2px solid red; background: #fff0f0; border-radius: 8px;'><h3>Research Failed</h3><p style="font-weight:bold;">${DOMPurify.sanitize(errTxt)}</p><p>Check the console (F12) for more details.</p></div>`;
        }
        if(codeInputArea) codeInputArea.value += `\n\n--- RESEARCH ERROR ---\n${DOMPurify.sanitize(errTxt)}`;
        if(outputFrame && !outputFrame.srcdoc.includes("Research Failed")) { // Avoid overwriting plan errors if possible
            outputFrame.srcdoc = `<div style='color:red; padding:20px; font-family: Inter, sans-serif; border: 2px solid red; background: #fff0f0; border-radius: 8px;'><h3>Research Failed</h3><p style="font-weight:bold;">${DOMPurify.sanitize(errTxt)}</p><p>Check the console (F12) for more details.</p></div>`;
        }
    } finally {
        generationInProgress = false;
        stopGenerationFlag = false; // Reset flag
        updateButtonStates(false);
        showAiOverlay(false);
        console.log("--- Research Cycle Finished ---");
    }
}


// --- Start Application ---
// (Ваш оригинальный код запуска остается без изменений)
if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initializeApp);
} else {
    initializeApp();
}
console.log("Script execution reached end (async ops may continue).");