File size: 133,317 Bytes
e9a8482
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60707b0
 
 
 
 
 
 
 
 
e9a8482
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2448214
e9a8482
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60707b0
 
55d8ff9
60707b0
 
 
6070a7b
e9a8482
1886035
e9a8482
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60707b0
e9a8482
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60707b0
7e4117d
e9a8482
 
 
 
 
 
 
bf7fb45
55d8ff9
 
 
6070a7b
60707b0
 
bf7fb45
e9a8482
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e47e051
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
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Core, el núcleo de un ERP Agéntico | Operaciones Inteligentes 2030</title>
<meta name="description" content="Core, el núcleo de un ERP Agéntico: demo local de operaciones con agentes ALPHA, BETA y GAMMA, cumplimiento por país y datos ficticios en SQLite.">
<meta property="og:title" content="Core, el núcleo de un ERP Agéntico | Operaciones Inteligentes 2030">
<meta property="og:description" content="Demo local con agentes de inventario, pedidos y proveedores; datos ficticios solo en tu navegador.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://fivetechsoft.github.io/Core/">
<script defer src="vendor/chart.js/4.4.8/chart.umd.js"></script>
<script src="vendor/sql.js/1.13.0/sql-wasm.js"></script>
<style>
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');

  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }

  body {
    font-family: 'Inter', system-ui, sans-serif;
    background: #0a0e17;
    color: #e0e6ed;
    min-height: 100vh;
    overflow-x: hidden;
    background-image: 
      radial-gradient(ellipse at 70% 20%, rgba(30, 60, 120, 0.4) 0%, transparent 50%),
      radial-gradient(ellipse at 20% 80%, rgba(20, 40, 80, 0.3) 0%, transparent 50%),
      linear-gradient(180deg, #0a0e17 0%, #0d1525 100%);
  }

  .bg-city {
    position: fixed;
    inset: 0;
    background:
      radial-gradient(ellipse 65% 48% at 80% 8%, rgba(52, 82, 151, .23), transparent 74%),
      radial-gradient(ellipse 50% 58% at 24% 82%, rgba(37, 80, 114, .14), transparent 72%),
      linear-gradient(160deg, #090f1d 0%, #0c172b 54%, #080e19 100%);
    z-index: 0;
    pointer-events: none;
  }

  .container {
    position: relative;
    z-index: 1;
    display: flex;
    min-height: 100vh;
    padding: 20px;
    gap: 16px;
  }

  /* ===== SIDEBAR ===== */
  .sidebar {
    width: 220px;
    background: rgba(12, 18, 32, 0.92);
    border: 1px solid rgba(80, 140, 255, 0.25);
    border-radius: 16px;
    padding: 18px 12px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    backdrop-filter: blur(12px);
    box-shadow: 0 0 30px rgba(40, 100, 255, 0.15);
  }

  .logo {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px 18px;
    border-bottom: 1px solid rgba(80, 140, 255, 0.2);
    margin-bottom: 10px;
  }

  .logo-icon {
    width: 36px;
    height: 36px;
    background: linear-gradient(135deg, #3b82f6, #8b5cf6);
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 14px;
    color: white;
    box-shadow: 0 0 15px rgba(99, 102, 241, 0.5);
  }

  .logo-text {
    font-size: 18px;
    font-weight: 700;
    letter-spacing: 1px;
    background: linear-gradient(90deg, #60a5fa, #a78bfa);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
  }

  .nav-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 10px;
    cursor: pointer;
    font-size: 13.5px;
    font-weight: 500;
    color: #94a3b8;
    transition: all 0.2s;
  }

  .nav-item:hover {
    background: rgba(59, 130, 246, 0.12);
    color: #e0e6ed;
  }

  .nav-item.active {
    background: linear-gradient(90deg, rgba(59, 130, 246, 0.25), rgba(139, 92, 246, 0.15));
    color: #60a5fa;
    border: 1px solid rgba(96, 165, 250, 0.3);
  }

  .nav-item .icon {
    width: 18px;
    text-align: center;
    font-size: 15px;
  }

  /* ===== MAIN PANEL ===== */
  .main {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 14px;
  }

  .header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: rgba(12, 18, 32, 0.9);
    border: 1px solid rgba(80, 140, 255, 0.3);
    border-radius: 14px;
    padding: 12px 20px;
    backdrop-filter: blur(10px);
  }

  .header-title h1 {
    font-size: 18px;
    font-weight: 600;
    letter-spacing: 0.5px;
  }

  .header-title h1 {position:relative;display:inline-block;overflow:hidden}.header-title h1::after{content:'';position:absolute;inset:-5px auto -5px -60%;width:35%;background:linear-gradient(95deg,transparent,#effbff55,transparent);transform:skewX(-22deg);animation:ap-title-shimmer 13s ease-in-out infinite;pointer-events:none}@keyframes ap-title-shimmer{0%,45%,100%{left:-60%;opacity:0}49%{opacity:1}85%{left:135%;opacity:1}90%{opacity:0}}body[data-theme="light"] .header-title h1::after{background:linear-gradient(95deg,transparent,#548cd65e,transparent)}@media(prefers-reduced-motion:reduce){.header-title h1::after{animation:none;display:none}}
  .header-right {
    display: flex;
    align-items: center;
    gap: 16px;
  }

  .header-right .notif {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(59, 130, 246, 0.15);
    border: 1px solid rgba(96, 165, 250, 0.3);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    position: relative;
  }

  .header-right .notif::after {
    content: '';
    position: absolute;
    top: 6px;
    right: 8px;
    width: 8px;
    height: 8px;
    background: #ef4444;
    border-radius: 50%;
    border: 2px solid #0c1220;
  }

  .avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: linear-gradient(135deg, #6366f1, #a855f7);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 600;
    font-size: 14px;
  }

  .metrics {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
  }

  .metric-card {
    background: rgba(12, 18, 32, 0.9);
    border: 1px solid rgba(80, 140, 255, 0.25);
    border-radius: 14px;
    padding: 16px 18px;
    backdrop-filter: blur(10px);
    position: relative;
    overflow: hidden;
  }

  .metric-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: linear-gradient(90deg, #3b82f6, #8b5cf6);
  }

  .metric-label {
    font-size: 12px;
    color: #94a3b8;
    margin-bottom: 6px;
    font-weight: 500;
  }

  .metric-value {
    font-size: 26px;
    font-weight: 700;
    letter-spacing: -0.5px;
  }

  .metric-change {
    font-size: 12px;
    margin-top: 4px;
    display: flex;
    align-items: center;
    gap: 4px;
  }

  .metric-change.up { color: #22c55e; }
  .metric-change.neutral { color: #60a5fa; }

  .mid-row {
    display: grid;
    grid-template-columns: 280px 1fr;
    gap: 12px;
  }

  .agents-card, .alerts-card {
    background: rgba(12, 18, 32, 0.9);
    border: 1px solid rgba(80, 140, 255, 0.25);
    border-radius: 14px;
    padding: 16px;
    backdrop-filter: blur(10px);
  }

  .section-title {
    font-size: 13px;
    font-weight: 600;
    color: #94a3b8;
    margin-bottom: 12px;
    text-transform: uppercase;
    letter-spacing: 0.8px;
  }

  .agent-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 10px;
    background: rgba(30, 41, 59, 0.5);
    margin-bottom: 8px;
    border: 1px solid rgba(80, 140, 255, 0.15);
  }

  .agent-badge {
    width: 28px;
    height: 28px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 12px;
    color: white;
  }

  .agent-badge.a { background: linear-gradient(135deg, #3b82f6, #2563eb); }
  .agent-badge.b { background: linear-gradient(135deg, #8b5cf6, #7c3aed); }
  .agent-badge.g { background: linear-gradient(135deg, #06b6d4, #0891b2); }

  .agent-info { flex: 1; }
  .agent-name { font-size: 13px; font-weight: 600; }
  .agent-role { font-size: 11px; color: #94a3b8; }

  .agent-status {
    font-size: 11px;
    color: #22c55e;
    font-weight: 500;
    display: flex;
    align-items: center;
    gap: 4px;
  }

  .agent-status::before {
    content: '';
    width: 6px;
    height: 6px;
    background: #22c55e;
    border-radius: 50%;
    box-shadow: 0 0 6px #22c55e;
  }

  .alert-item {
    display: flex;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 10px;
    margin-bottom: 8px;
    background: rgba(30, 41, 59, 0.4);
    border-left: 3px solid;
  }

  .alert-item.low { border-color: #f59e0b; }
  .alert-item.anomaly { border-color: #ef4444; }
  .alert-item.risk { border-color: #22c55e; }

  .alert-icon { font-size: 16px; margin-top: 2px; }
  .alert-content { flex: 1; }
  .alert-title { font-size: 13px; font-weight: 600; margin-bottom: 2px; }
  .alert-desc { font-size: 12px; color: #94a3b8; line-height: 1.4; }
  .alert-desc strong { color: #60a5fa; }

  .charts-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
  }

  .chart-card {
    background: rgba(12, 18, 32, 0.9);
    border: 1px solid rgba(80, 140, 255, 0.25);
    border-radius: 14px;
    padding: 16px;
    backdrop-filter: blur(10px);
    height: 260px;
  }

  .chart-card h3 {
    font-size: 13px;
    font-weight: 600;
    color: #94a3b8;
    margin-bottom: 10px;
    text-transform: uppercase;
    letter-spacing: 0.6px;
  }

  .chart-container {
    height: calc(100% - 30px);
    position: relative;
  }

  /* ===== CHAT WINDOW (MOVIBLE) ===== */
  .chat-window {
    position: fixed;
    resize: both;
    min-width: 320px;
    min-height: 280px;
    max-width: calc(100vw - 20px);
    max-height: calc(100vh - 20px);
    bottom: 30px;
    left: 250px;
    width: 380px;
    background: rgba(12, 18, 32, 0.95);
    border: 1px solid rgba(139, 92, 246, 0.4);
    border-radius: 16px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5), 0 0 30px rgba(139, 92, 246, 0.2);
    overflow: hidden;
    z-index: 100;
    backdrop-filter: blur(16px);
    user-select: none; /* evita selección de texto mientras se arrastra */
  }

  .chat-header {
    background: linear-gradient(90deg, rgba(99, 102, 241, 0.3), rgba(139, 92, 246, 0.2));
    padding: 12px 16px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 1px solid rgba(139, 92, 246, 0.3);
    cursor: grab; /* indica que se puede arrastrar */
  }

  .chat-header:active {
    cursor: grabbing;
  }

  .chat-header h4 {
    font-size: 13px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .chat-header .close {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: rgba(255,255,255,0.1);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-size: 12px;
  }

  .chat-body {
    padding: 14px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    height: calc(100% - 150px);
    min-height: 120px;
    overflow-y: auto;
    user-select: text; /* permite seleccionar texto en los mensajes */
  }

  .chat-msg {
    max-width: 90%;
    padding: 10px 14px;
    border-radius: 12px;
    font-size: 13px;
    line-height: 1.45;
  }

  .chat-msg.user {
    align-self: flex-end;
    background: rgba(59, 130, 246, 0.25);
    border: 1px solid rgba(96, 165, 250, 0.3);
    border-bottom-right-radius: 4px;
  }

  .chat-msg.ai {
    align-self: flex-start;
    background: rgba(30, 41, 59, 0.8);
    border: 1px solid rgba(139, 92, 246, 0.25);
    border-bottom-left-radius: 4px;
  }

  .chat-msg p{margin:0 0 8px}.chat-msg p:last-child{margin-bottom:0}.chat-msg ul{margin:5px 0 8px 20px;padding:0}.chat-msg li{margin:3px 0}.chat-msg code{font:12px ui-monospace,SFMono-Regular,monospace;background:#34476655;border-radius:3px;padding:1px 3px;overflow-wrap:anywhere}.chat-msg pre{white-space:pre-wrap;overflow-wrap:anywhere;background:#0c172b;border-radius:7px;padding:8px;margin:7px 0}.chat-msg pre code{background:transparent;padding:0}.chat-msg strong{font-weight:700}.ap-demo-warning{color:#f8cc82;font-size:11px;line-height:1.45;margin:10px 0}.ap-demo-badge{display:block;color:#f8cc82;font-size:9px;letter-spacing:.04em;font-weight:700;margin-top:4px;line-height:1.3;overflow-wrap:anywhere}body[data-theme="light"] .ap-demo-warning,body[data-theme="light"] .ap-demo-badge{color:#85551c}
  .chat-msg.ai .agent-tag {
    color: #a78bfa;
    font-weight: 600;
  }

  .chat-footer {
    padding: 10px 14px 14px;
    display: flex;
    gap: 8px;
  }

  .chat-footer input {
    flex: 1;
    background: rgba(30, 41, 59, 0.6);
    border: 1px solid rgba(80, 140, 255, 0.25);
    border-radius: 10px;
    padding: 10px 14px;
    color: #e0e6ed;
    font-size: 13px;
    outline: none;
  }

  .chat-footer input::placeholder {
    color: #64748b;
  }

  .chat-footer button.ap-mic.is-listening {background:#dc315c;box-shadow:0 0 0 4px rgba(220,49,92,.19);animation:ap-mic-pulse 1.3s ease-in-out infinite;}
  @keyframes ap-mic-pulse {50%{box-shadow:0 0 0 9px rgba(220,49,92,.04)}}
  @media(prefers-reduced-motion:reduce){.chat-footer button.ap-mic.is-listening{animation:none}}
  .chat-footer button {
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    border: none;
    border-radius: 10px;
    width: 40px;
    color: white;
    cursor: pointer;
    font-size: 16px;
  }

  .projector {
    position: fixed;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    width: 120px;
    height: 20px;
    background: radial-gradient(ellipse, rgba(59, 130, 246, 0.6), transparent 70%);
    border-radius: 50%;
    box-shadow: 0 0 40px rgba(59, 130, 246, 0.5);
    z-index: 5;
  }

  @media (max-width: 1200px) {
    .metrics { grid-template-columns: repeat(2, 1fr); }
    .mid-row { grid-template-columns: 1fr; }
    .charts-row { grid-template-columns: 1fr; }
    .chat-window { left: 20px; width: 340px; }
  }
  .ap-human { border: 1px solid rgba(96,165,250,.4); background: rgba(59,130,246,.17); border-radius:50%; width:36px; height:36px; font-size:20px; cursor:pointer; color:#fff; }
  .ap-human:hover { background:rgba(59,130,246,.38); }
  .chat-window { height: 340px; }
  #ap-chat-panel { height:calc(100% - 86px); display:flex; flex-direction:column; }
  #ap-chat-panel .chat-body { flex:1; height:auto; min-height:80px; }
  #ap-supervision-panel { height:calc(100% - 86px); }
  .ap-model-bar { display:flex; align-items:center; gap:8px; padding:6px 10px; background:#17213a; border-bottom:1px solid #344361; font-size:.8em; }
  .ap-model-bar button { background:#2b7fff; color:#fff; border:0; border-radius:6px; padding:5px 10px; cursor:pointer; font-size:.92em; }
  .ap-model-bar button:disabled { opacity:.5; cursor:default; }
  .ap-model-bar span { color:#9fb3d1; }
  .ap-model-progress { height:6px; background:#0e1526; }
  .ap-model-progress div { height:100%; width:0%; background:#2b7fff; transition:width .3s; }
  body[data-theme="light"] .ap-model-bar { background:#eef3fb; border-color:#c9d6e8; }
  body[data-theme="light"] .ap-model-bar span { color:#4a5f7d; }
  body[data-theme="light"] .ap-model-progress { background:#dbe4f0; }
  .ap-tabs { display:flex; border-bottom:1px solid #344361; }.ap-tabs button { flex:1; background:#17213a; color:#e0e6ed; border:0; padding:10px; cursor:pointer; }
  [hidden] { display:none !important; }
  #ap-supervision-panel { padding:12px; overflow:auto; user-select:text; }
  .ap-panel-title { font-size:12px; text-transform:uppercase; font-weight:700; color:#a5b4fc; margin:10px 0; }
  #ap-state { font-size:12px; margin:9px 0; color:#94a3b8; }
  #ap-stock,#ap-orders { max-height:92px; overflow:auto; margin:8px 0; }
  .ap-line { font-size:12px; padding:5px 0; border-bottom:1px solid #30415a; }
  .ap-warn { color:#fbbf24; }
  .ap-action,.ap-proposal button { background:#183d70; border:1px solid #4079be; color:#fff; border-radius:6px; padding:6px 10px; cursor:pointer; margin:4px 5px 4px 0; }
  .ap-action:hover,.ap-proposal button:hover { background:#29508a; }
  .ap-proposal { border-left:3px solid #4e95ec; padding:8px; margin:7px 0; background:#101e32; font-size:12px; line-height:1.5; }
  .ap-proposal small { color:#aabbd0; }.ap-status { color:#fbbf24; }
  @media (max-width: 800px) { .chat-window { max-width:calc(100vw - 20px); left:10px; } }
  .ap-mode { padding:7px 10px; border:1px solid #4e75aa; background:#152743; color:#dbeafe; border-radius:10px; white-space:nowrap; cursor:pointer; font-size:12px; font-weight:600; }
  .ap-mode[aria-pressed="true"] { border-color:#17a58a; background:#114237; color:#b8fce5; }
  @media (max-width:800px) { .header-right { gap:5px; }.ap-mode { max-width:105px; overflow:hidden; text-overflow:ellipsis; } }
  .ap-dialog { position:fixed; inset:0; z-index:999; background:rgba(4,8,17,.78); display:grid; place-items:center; padding:15px; }
  .ap-dialog form { width:min(440px,100%); background:#15213a; border:1px solid #5471a1; border-radius:14px; padding:22px; box-shadow:0 20px 60px #0009; }
  .ap-dialog h3 {font-size:17px; margin-bottom:9px;}.ap-dialog p {font-size:13px; color:#bdc8dc; line-height:1.5; margin-bottom:14px;}
  .ap-dialog label {display:block; font-size:13px; margin:10px 0;}.ap-dialog input,.ap-dialog textarea {display:block; width:100%; padding:9px; margin-top:5px; background:#0c1428; border:1px solid #4e658b; color:#fff; border-radius:6px; font:inherit;}
  .ap-dialog-buttons {display:flex; justify-content:flex-end; gap:8px; margin-top:15px;}.ap-dialog button {background:#24528e; color:white; border:1px solid #5780ba; border-radius:6px; padding:8px 12px; cursor:pointer;}
  #ap-cycle { color:#8ba6c9; font-size:11px; margin:5px 0; }
  #ap-feed { max-height:135px; overflow:auto; border-top:1px solid #30415a; }
  .ap-feed-item { display:flex; align-items:baseline; gap:7px; border-bottom:1px solid #273952; padding:5px 1px; font-size:11px; }
  .ap-feed-item time { color:#75a7ed; }.ap-feed-item strong { color:#c4b5fd; }.ap-feed-item small { color:#8199b8; margin-left:auto; }
  .agent-status.ap-working::before { animation:ap-heartbeat 1s ease-in-out infinite; box-shadow:0 0 10px #52b8f8; }
  @keyframes ap-heartbeat { 50% { transform:scale(1.65);opacity:.45; } }
  @media (prefers-reduced-motion:reduce) { .agent-status.ap-working::before {animation:none;} }

  #ap-bell {font-size:17px;color:inherit;flex:none;}#ap-bell-count {position:absolute;right:-5px;top:-7px;min-width:18px;padding:2px 4px;background:#e84257;border-radius:20px;color:white;font-size:10px;font-weight:700;border:1px solid white;}
  #ap-bell::after {display:none;}
  .ap-notices {position:absolute;z-index:20;right:87px;top:75px;width:min(390px,calc(100vw - 30px));max-height:390px;overflow:auto;background:#122039;border:1px solid #5471a1;border-radius:12px;padding:14px;box-shadow:0 20px 45px #0008;}
  .ap-notices h3 {font-size:14px;margin-bottom:10px}.ap-notice {padding:10px 3px;border-top:1px solid #304565;font-size:12px;line-height:1.5}.ap-notice small {display:block;color:#aebbd0}.ap-notices button {margin-top:8px;padding:5px 8px;background:#24528e;border:1px solid #5780ba;color:white;border-radius:6px;cursor:pointer}.ap-notice em {color:#a5b4fc;font-style:normal;font-weight:600;}
  body[data-theme="light"] .ap-notices {background:white;border-color:#c9d8ee;box-shadow:0 20px 45px #25416b30;}body[data-theme="light"] .ap-notice {border-color:#dae5f1}body[data-theme="light"] .ap-notice small {color:#536781}
  .ap-headlines{position:fixed;z-index:24;bottom:68px;left:0;right:0;height:33px;background:#182d50ed;border-top:1px solid #4a86c0;color:#eaf3ff;display:flex;align-items:center;overflow:hidden;font-size:12px;letter-spacing:.02em}.ap-headlines-label{background:#d62d54;color:white;font-weight:800;letter-spacing:.1em;display:flex;align-items:center;white-space:nowrap;height:100%;padding:0 14px;z-index:2}.ap-headlines-clip{overflow:hidden;flex:1;white-space:nowrap}.ap-headlines-clip>div{display:inline-block;padding-left:100%;animation:ap-headline-roll 24s linear infinite}@keyframes ap-headline-roll{to{transform:translateX(-100%)}}body[data-theme="light"] .ap-headlines{background:#e3edf9;color:#213b5b}body:has(.ap-ticker[hidden]) .ap-headlines{bottom:0}body:has(.ap-ticker:not([hidden])){padding-bottom:101px}body:has(.ap-ticker[hidden]){padding-bottom:33px}@media(prefers-reduced-motion:reduce){.ap-headlines-clip>div{animation:none;padding-left:12px;overflow:hidden;text-overflow:ellipsis;max-width:100%}}
  .ap-tv {position:fixed;inset:0;z-index:50;background:radial-gradient(circle at 50% 38%,#233b79 0%,#0a142a 44%,#07101f 100%);color:#e8f4ff;overflow:hidden;display:flex;flex-direction:column;font-family:Inter,system-ui,sans-serif}.ap-tv-top{display:flex;align-items:center;justify-content:space-between;padding:22px 36px;border-bottom:1px solid #44699b;background:#071126bb;letter-spacing:.16em;font-size:17px;font-weight:800}.ap-tv-top small{display:block;color:#66b7ff;font-size:10px;margin-top:5px}.ap-tv-top time{font-variant-numeric:tabular-nums;font-size:24px}.ap-tv-top button{padding:10px 15px;background:#1b3b67;color:#fff;border:1px solid #5a85b8;border-radius:8px;cursor:pointer}.ap-tv-stage{flex:1;display:flex;flex-direction:column;justify-content:center;text-align:center;padding:10px 45px;min-height:0}.ap-tv-head small{color:#6eceff;letter-spacing:.3em;font-weight:700}.ap-tv-head h1{font-size:clamp(30px,4.4vw,70px);letter-spacing:-.04em;line-height:1.1;margin:10px 0}.ap-tv-head p{color:#adc8e6;font-size:clamp(13px,1.5vw,20px)}.ap-tv-viz{height:min(38vh,310px);margin:auto 0}.ap-tv-viz svg{width:100%;height:100%;overflow:visible}.ap-tv-viz text{fill:#eaf6ff;font-size:24px;font-weight:800;letter-spacing:.1em}.ap-tv-viz .ap-tv-node-sub{font-size:11px;fill:#96bde5}.ap-tv-node{fill:#13274bbd;stroke:#7ab9fa;stroke-width:2;filter:drop-shadow(0 0 16px #4a8fee)}.ap-tv-path{animation:ap-dash 20s linear infinite}@keyframes ap-dash{to{stroke-dashoffset:-360}}.ap-tv-pulse{filter:drop-shadow(0 0 16px #89e5ff)}.ap-tv-cards{display:flex;gap:15px;justify-content:center;margin:0 auto 25px;max-width:1050px;width:100%}.ap-tv-cards div{background:#173259aa;border:1px solid #5c84af;border-radius:12px;padding:16px;flex:1;text-align:left}.ap-tv-cards small{display:block;color:#8abce9}.ap-tv-cards strong{font-size:clamp(18px,2.4vw,31px)}.ap-tv-lower{background:#172d56;border-top:2px solid #59b3ff;padding:14px 30px;display:flex;align-items:center;gap:22px;min-height:60px}.ap-tv-live{background:#e33159;color:white;padding:8px 12px;border-radius:3px;font-size:11px;font-weight:800;white-space:nowrap}.ap-tv-lower strong{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ap-tv-lower small{font-size:10px;color:#83aad2}.ap-tv:has(~ #ap-ticker:not([hidden])){bottom:101px}.ap-tv:has(~ #ap-ticker[hidden]){bottom:33px}.ap-tv~#ap-ticker{z-index:51}.ap-tv~#ap-ticker+.ap-dialog{z-index:999}body:has(.ap-tv:not([hidden])) .ap-headlines{z-index:52}body[data-theme="light"] .ap-tv{background:radial-gradient(circle at 50% 30%,#e5f2ff,#bfd8f4 65%,#a9c9ec);color:#123154}body[data-theme="light"] .ap-tv-top{background:#eaf4ffdd;border-color:#8bacce}body[data-theme="light"] .ap-tv-head p{color:#3e5d7c}body[data-theme="light"] .ap-tv-cards div{background:#f7fbffbd;border-color:#98bde2}body[data-theme="light"] .ap-tv-node{fill:#cfebff;stroke:#478bc9}body[data-theme="light"] .ap-tv-viz text{fill:#173d66}body[data-theme="light"] .ap-tv-viz .ap-tv-node-sub{fill:#3e648a}@media(max-width:700px){.ap-tv-top{padding:12px;font-size:12px}.ap-tv-top time{font-size:16px}.ap-tv-stage{padding:10px}.ap-tv-cards{gap:5px}.ap-tv-cards div{padding:8px}.ap-tv-viz{height:28vh}.ap-tv-lower{padding:8px;gap:8px}.ap-tv-lower small{display:none}}@media(prefers-reduced-motion:reduce){.ap-tv-path{animation:none}.ap-tv-pulse{display:none}}
  .ap-live-dot{display:inline-block;width:7px;height:7px;background:#ff4268;border-radius:50%;box-shadow:0 0 10px #ff4268;animation:ap-onair 2s ease-in-out infinite}@keyframes ap-onair{50%{opacity:.4}}@media(prefers-reduced-motion:reduce){.ap-live-dot{animation:none}}#ap-broadcast-clock{display:block;margin-top:2px;font-variant-numeric:tabular-nums;color:#a9c8e6;font-size:11px;letter-spacing:.05em}body[data-theme="light"] #ap-broadcast-clock{color:#a9c8e6}.ap-spotlight strong{font-weight:800;letter-spacing:-.03em}.ap-spotlight:before{content:'ÚLTIMA HORA · OPERACIONES';display:block;color:#a5d8ff;font-size:10px;letter-spacing:.2em;margin-bottom:8px;font-weight:700}body[data-theme="light"] .ap-spotlight:before{color:#225ca2}
  .ap-ticker {position:fixed;z-index:24;bottom:0;left:0;right:0;display:flex;align-items:center;height:68px;padding:5px 16px;gap:12px;background:#0c1828e8;border-top:1px solid #4e75aa;backdrop-filter:blur(16px);color:#dbeafe;box-shadow:0 -10px 40px #101c4348}.ap-ticker-label{font-weight:700;font-size:11px;letter-spacing:.1em;min-width:145px}.ap-ticker-label small{display:block;font-weight:400;letter-spacing:0;margin-top:3px;font-size:10px;color:#98a9bd}.ap-ticker-widget{flex:1;min-width:0;height:55px;overflow:hidden}.ap-tv-credit{font-size:10px;color:#9cc7ff;white-space:nowrap;text-decoration:none}body[data-theme="light"] .ap-ticker{background:#0c1828f2;color:#dbeafe;border-color:#4e75aa}body[data-theme="light"] .ap-ticker-label small{color:#98a9bd}@media(max-width:800px){.ap-ticker-label{min-width:74px}.ap-ticker-label small{display:none}.ap-tv-credit{display:none}}
  .ap-focus {position:fixed;z-index:30;inset:0;pointer-events:none;--fx:50%;--fy:50%;background:radial-gradient(circle 110px at var(--fx) var(--fy),transparent 0,transparent 45%,#08132948 100%);transition:--fx .7s,--fy .7s;animation:focusFade 2.7s ease-in-out both;}@keyframes focusFade {0%,100%{opacity:0}30%,73%{opacity:1}}body[data-theme="light"] .ap-focus{background:radial-gradient(circle 110px at var(--fx) var(--fy),transparent 0,transparent 45%,#4a688833 100%)}@media(prefers-reduced-motion:reduce){.ap-focus{animation:none;display:none}}
  .ap-spotlight {position:fixed;z-index:35;right:24px;top:100px;width:min(410px,calc(100vw - 40px));border-radius:20px;border:1px solid #9ec9ff9c;background:linear-gradient(135deg,#153c63d9,#262554c9);backdrop-filter:blur(24px);box-shadow:0 20px 60px #1c6fe677, inset 0 1px #ffffff55;color:white;text-align:left;padding:22px;cursor:pointer;animation:ap-spot-in .7s cubic-bezier(.2,.9,.2,1) both;}
  .ap-spotlight small {display:block;color:#a5d8ff;font-weight:700;letter-spacing:.12em;text-transform:uppercase;margin-bottom:8px}.ap-spotlight strong {display:block;font-size:23px;line-height:1.2}.ap-spotlight span {display:block;font-size:13px;margin-top:10px;line-height:1.4}.ap-spotlight .ap-spotlight-hint {color:#a5d8ff;font-size:11px;text-transform:uppercase;letter-spacing:.08em}
  @keyframes ap-spot-in {from{opacity:0;transform:translateX(110%) scale(.96)}to{opacity:1;transform:translateX(0) scale(1)}}
  body[data-theme="light"] .ap-spotlight {background:linear-gradient(135deg,#eaf7ffeb,#e9e9ffdb);color:#18304b;box-shadow:0 20px 60px #4b78af48;border-color:#89baff}body[data-theme="light"] .ap-spotlight :is(small,.ap-spotlight-hint){color:#225ca2}
  @media(prefers-reduced-motion:reduce){.ap-spotlight{animation:none}}@media(max-width:800px){.ap-spotlight{top:auto;bottom:15px;right:15px}}
  .nav-item {border:0; width:100%; background:transparent; text-align:left; font:inherit; flex-shrink:0;}
  .sidebar {max-height:calc(100vh - 40px); overflow-y:auto; position:sticky; top:20px;}
  .ap-theme {width:36px;height:36px;flex:none;border:1px solid #4e75aa;background:#152743;color:#fff;border-radius:10px;cursor:pointer;font-size:17px;}
  .ap-view {background:rgba(12,18,32,.92);border:1px solid rgba(80,140,255,.25);border-radius:14px;padding:22px;min-height:500px;}
  .ap-view h2 {font-size:22px;margin:0 0 7px}.ap-view h3 {font-size:14px;color:#a5b4fc;margin:0 0 14px}
  .ap-view-lead {color:#94a3b8;font-size:13px;margin-bottom:20px;line-height:1.5}
  .ap-grid {display:grid;grid-template-columns:repeat(auto-fit,minmax(225px,1fr));gap:14px;margin:16px 0}
  .ap-tile {background:#17243b;border:1px solid #304565;border-radius:12px;padding:17px;min-height:96px;line-height:1.5}
  .ap-tile small {color:#aebbd0;display:block;font-size:11px}.ap-tile b {font-size:19px;display:block;margin-top:8px}
  .ap-table-wrap {overflow:auto;border:1px solid #304565;border-radius:12px;margin-top:16px}
  .ap-table {width:100%;border-collapse:collapse;text-align:left;font-size:12px;min-width:560px}
  .ap-table th,.ap-table td {padding:12px;border-bottom:1px solid #304565;vertical-align:top}.ap-table th {color:#a5b4fc;background:#1b2a43}.ap-table tr:last-child td {border:0}
  .ap-pill {color:#fbbf24;font-weight:600}.ap-tools {display:flex;gap:9px;flex-wrap:wrap;margin:14px 0}
  .ap-view button {background:#24528e;border:1px solid #5780ba;border-radius:8px;color:#fff;padding:9px 12px;cursor:pointer}
  .ap-view button:hover {background:#3069a8}button:disabled{opacity:.55;cursor:not-allowed!important}
  body[data-theme="light"] {background:#f3f6fc;color:#17283f;background-image:radial-gradient(ellipse at 70% 20%,#e1edff 0%,transparent 55%),linear-gradient(#f7f9ff,#eaf1fb)}
  body[data-theme="light"] .bg-city {background:radial-gradient(ellipse 60% 55% at 85% 5%,#dce9ff,transparent),linear-gradient(145deg,#f8faff,#eaf2fc)}
  body[data-theme="light"] :is(.sidebar,.header,.metric-card,.agents-card,.alerts-card,.chart-card,.chat-window,.ap-view) {background:rgba(255,255,255,.94);border-color:#cad9ef;box-shadow:0 9px 30px #25416b13}
  body[data-theme="light"] :is(.ap-tile,.agent-item,.ap-proposal,.chat-msg.ai) {background:#f1f6fd;border-color:#d2e0f1}
  body[data-theme="light"] :is(.nav-item,.metric-label,.agent-role,.ap-view-lead,.ap-tile small) {color:#536781}
  body[data-theme="light"] :is(.nav-item:hover,.nav-item.active) {color:#185db6;background:#e9f2ff}
  body[data-theme="light"] :is(.ap-tabs button,.chat-footer input,.ap-dialog form,.ap-dialog input,.ap-dialog textarea,.ap-mode,.ap-theme) {background:#f0f6fe;color:#17283f;border-color:#bed0e9}
  body[data-theme="light"] :is(.chat-body,.chat-footer,#ap-supervision-panel) {background:#fff;color:#17283f}
  body[data-theme="light"] :is(.ap-line,.ap-feed-item,.ap-table th,.ap-table td) {border-color:#d8e3f1}
  body[data-theme="light"] .ap-table th {background:#eaf2fd;color:#24549a}
  body[data-theme="light"] :is(.ap-view h3,.ap-panel-title) {color:#395ab0}
  body[data-theme="light"] :is(.ap-dialog p,.ap-proposal small) {color:#536781}
  body[data-theme="light"] .chat-msg.user {color:#18314f;background:#d7e9fc}
  body[data-theme="light"] #ap-cycle {color:#536781}
  @media(max-width:800px){.sidebar{position:static;max-height:none}.ap-view{padding:14px}}

  .agent-item{width:100%;text-align:left;color:#e6efff;font-family:inherit;cursor:pointer;transition:transform .2s,background .2s,border-color .2s,box-shadow .2s}.agent-item:hover{transform:translateX(3px);border-color:#7eafff}.agent-item:focus-visible{outline:2px solid #85c2ff;outline-offset:2px}.agent-item.is-selected{background:linear-gradient(110deg,rgba(46,107,200,.28),rgba(127,68,220,.19));border-color:#91baff;box-shadow:0 0 0 1px #587cbb88,0 14px 35px #335c9c35}.agent-item[aria-pressed=true] .agent-name{color:#cbe5ff}body[data-theme=light] .agent-item{color:#1b304f}body[data-theme=light] .agent-item.is-selected{background:linear-gradient(110deg,#dceafa,#efe9ff);border-color:#689fee}body[data-theme=light] .agent-item[aria-pressed=true] .agent-name{color:#1a4b86}.charts-row[hidden],.ap-agent-center[hidden]{display:none!important}.ap-agent-center:not([hidden]){display:flex;flex-direction:column;gap:18px;min-width:0;min-height:420px;padding:22px;border:1px solid #5b83ba88;border-radius:15px;background:radial-gradient(circle at 100% 0%,#263d7438,transparent 38%),#0b1425;box-shadow:0 20px 60px #09172f40}.ap-agent-hero{display:flex;align-items:center;gap:17px}.ap-agent-hero .agent-badge{width:58px;height:58px;font-size:27px;border-radius:15px;box-shadow:0 0 28px #5978e977}.ap-agent-hero h2{font-size:27px;margin:0}.ap-agent-hero p{color:#a8bfdc;font-size:12px;margin:3px 0}.ap-agent-back{margin-left:auto;background:#1c3c6e;color:#f3f8ff;border:1px solid #6990c8;border-radius:9px;padding:9px 12px;cursor:pointer}.ap-agent-story{color:#a9bdd8;font-size:13px;line-height:1.5;margin:0}.ap-agent-center .ap-grid{margin:0}.ap-agent-timeline{position:relative;padding-left:23px;border-left:1px solid #385b91;margin-left:8px;display:grid;gap:13px}.ap-agent-event{position:relative;padding:12px 14px;border:1px solid #355380;border-radius:10px;background:#13223b}.ap-agent-event:before{content:'';position:absolute;left:-30px;top:16px;width:10px;height:10px;border-radius:50%;background:#6ea5ff;box-shadow:0 0 12px #70acff}.ap-agent-event strong{display:block;font-size:13px}.ap-agent-event small{display:block;margin-top:5px;color:#a6bbd5;font-size:11px}.ap-agent-center h3{font-size:12px;letter-spacing:.1em;color:#9dc0ec;margin:0}.ap-agent-empty{padding:16px;color:#a9bdd8;background:#17253e;border-radius:9px;font-size:12px}body[data-theme=light] .ap-agent-center:not([hidden]){background:radial-gradient(circle at 100% 0%,#bed7ff88,transparent 40%),#fff;border-color:#bdcee5;color:#1b304f;box-shadow:0 12px 30px #2847721a}body[data-theme=light] :is(.ap-agent-hero p,.ap-agent-story,.ap-agent-event small){color:#526a87}body[data-theme=light] .ap-agent-event{background:#f5f9fe;border-color:#d3e1f0}body[data-theme=light] .ap-agent-empty{background:#f1f6fd;color:#526a87}@media(max-width:650px){.ap-agent-hero{flex-wrap:wrap}.ap-agent-back{margin-left:0}}
  .header{box-shadow:0 0 0 1px #4477d144,0 12px 40px #256de226;animation:ap-header-glow 7s ease-in-out infinite}.header-title h1{text-shadow:0 0 18px #86aaff66,0 0 35px #618cf744}.header-title h1::after{width:48%;background:linear-gradient(95deg,transparent,#bce8ff12,#f5ffffbc,#91c6ff15,transparent);animation-duration:11s}.metric-card,.agents-card,.alerts-card,.chart-card,.ap-agent-center{transition:box-shadow .3s,border-color .3s}.metric-card:hover,.agents-card:hover,.alerts-card:hover,.chart-card:hover,.ap-agent-center:hover{border-color:#8bb7ff;box-shadow:0 0 0 1px #729ef766,0 18px 50px #397cf033}.agent-status:not(.ap-working)::before{animation:ap-beacon 2.4s ease-in-out infinite}.agent-badge{box-shadow:0 0 13px #5b82f477}.agent-item.is-selected{box-shadow:0 0 0 1px #6eb8ff,0 0 24px #409af16b}.ap-agent-hero .agent-badge{animation:ap-agent-orbit 4s ease-in-out infinite}@keyframes ap-header-glow{50%{box-shadow:0 0 0 1px #91c4ff77,0 12px 46px #627afb50}}@keyframes ap-beacon{50%{box-shadow:0 0 0 5px #24d48524,0 0 17px #39e99a;transform:scale(1.25)}}@keyframes ap-agent-orbit{50%{box-shadow:0 0 15px #7fd7ff,0 0 33px #6565ff99}}body[data-theme=light] .header{box-shadow:0 0 0 1px #8eb9fa,0 15px 40px #2b76d538}body[data-theme=light] .header-title h1{text-shadow:0 0 16px #519cf788}body[data-theme=light] .header-title h1::after{background:linear-gradient(95deg,transparent,#64aaff33,#1279eab8,#64aaff33,transparent)}body[data-theme=light] :is(.metric-card:hover,.agents-card:hover,.alerts-card:hover,.chart-card:hover){box-shadow:0 0 0 1px #6e9cde,0 15px 35px #3879d446}@media(prefers-reduced-motion:reduce){.header,.agent-status:not(.ap-working)::before,.ap-agent-hero .agent-badge{animation:none}.header-title h1::after{animation:none;display:none}}
  .ap-compliance-hero{padding:24px;border-radius:16px;border:1px solid #5687cb;background:radial-gradient(circle at 50% 0%,#425ba044,transparent 60%),#101c33;box-shadow:0 0 32px #587cff2e;margin-bottom:20px}.ap-compliance-hero small{color:#a6c3ee;text-transform:uppercase;letter-spacing:.16em;font-size:10px}.ap-compliance-hero h2{font-size:26px;margin:8px 0}.ap-compliance-hero p{max-width:700px;color:#adc3df;font-size:13px;line-height:1.5}.ap-pyramid{display:grid;justify-items:center;gap:6px;margin:24px 0}.ap-pyramid-level{width:var(--width);max-width:100%;min-height:66px;display:flex;align-items:center;justify-content:space-between;gap:16px;padding:13px 11%;border:1px solid #91b7fb;border-radius:8px;color:#f7faff;background:linear-gradient(115deg,#264d9b,#4b388b);box-shadow:0 8px 25px #132c6470, inset 0 0 17px #9dc2ff1d;clip-path:polygon(6% 0,94% 0,100% 100%,0 100%)}.ap-pyramid-level b{font-size:14px}.ap-pyramid-level small{font-size:10px;color:#d4e5fc}.ap-pyramid-level:nth-child(2){background:linear-gradient(115deg,#235b9c,#3b468d)}.ap-pyramid-level:nth-child(3){background:linear-gradient(115deg,#1d6b9c,#315389)}.ap-pyramid-level:nth-child(4){background:linear-gradient(115deg,#167887,#2c5984)}.ap-pyramid-level:nth-child(5){background:linear-gradient(115deg,#28716e,#28577b)}.ap-compliance-note{font-size:12px;line-height:1.5;color:#a8bad5}.ap-compliance-pill{display:inline-block;padding:3px 7px;border-radius:5px;font-size:10px;font-weight:700;margin-left:6px}.ap-compliance-pill.review{background:#af671e33;color:#ffd49a;border:1px solid #ad722c}.ap-compliance-pill.pass{background:#236e573d;color:#8ff0c4;border:1px solid #3a9e79}.ap-compliance-pill.block{background:#b63d4933;color:#ffadb5;border:1px solid #cc5463}body[data-theme=light] .ap-compliance-hero{background:radial-gradient(circle at 50% 0%,#a8c9ff88,transparent 65%),#f4f8ff;border-color:#a9c8ed}body[data-theme=light] .ap-compliance-hero :is(h2,p,small),body[data-theme=light] .ap-compliance-note{color:#315075}body[data-theme=light] .ap-compliance-pill.review{color:#8b4c0e;background:#fff2df}body[data-theme=light] .ap-compliance-pill.pass{color:#165d42;background:#e1f6eb}body[data-theme=light] .ap-compliance-pill.block{color:#a62c3d;background:#fde9eb}@media(max-width:650px){.ap-pyramid-level{clip-path:none;width:100%!important}.ap-pyramid-level b{font-size:12px}}
  .ap-law-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:12px;margin:16px 0 25px}.ap-law-card{border:1px solid #5277a8;background:#152540;border-radius:12px;padding:15px;box-shadow:0 8px 24px #12336255}.ap-law-card small{display:block;color:#9abce8;font-size:10px;letter-spacing:.08em}.ap-law-card strong{display:block;margin:7px 0;font-size:13px}.ap-law-card p{color:#a9bbd2;font-size:12px;line-height:1.4}.ap-law-card a{color:#8dc7ff;font-size:11px}.ap-payroll-form{display:flex;flex-wrap:wrap;gap:12px;align-items:end;padding:18px;border:1px solid #456d9d;border-radius:12px;background:#142440}.ap-payroll-form label{display:grid;gap:6px;color:#c7d8ec;font-size:12px}.ap-payroll-form input{padding:9px;border-radius:7px;border:1px solid #6995c6;background:#0b1728;color:#fff;max-width:220px}.ap-payroll-output{margin:12px 0;padding:15px;border-radius:9px;background:#272b45;color:#e8e4fd;font-size:13px;line-height:1.7}body[data-theme=light] .ap-law-card{background:#f5f9ff;color:#243d5f;border-color:#c5d9f2}body[data-theme=light] .ap-law-card :is(p,small){color:#526985}body[data-theme=light] .ap-law-card a{color:#12599d}body[data-theme=light] .ap-payroll-form{background:#eaf2ff;color:#1d3e65}body[data-theme=light] .ap-payroll-form label{color:#284b70}body[data-theme=light] .ap-payroll-form input{background:#fff;color:#152f4e}body[data-theme=light] .ap-payroll-output{background:#f4f0ff;color:#363057}
  body[data-theme=light] .ap-compliance-hero .ap-pyramid-level small{color:#eff7ff;text-shadow:0 1px 4px #102e6188}
  .ap-legal-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(245px,1fr));gap:14px;margin:16px 0 25px}.ap-legal-agent{padding:17px;border-radius:13px;border:1px solid #5077ab;background:linear-gradient(145deg,#162c4b,#111f36);box-shadow:0 9px 24px #0c203b44;min-width:0}.ap-legal-agent header{display:flex;gap:11px;align-items:flex-start;justify-content:space-between}.ap-legal-agent h3{font-size:17px;margin:0 0 6px}.ap-legal-agent small{font-size:10px;letter-spacing:.1em;color:#a9c8ee;text-transform:uppercase}.ap-legal-agent p,.ap-legal-agent li{font-size:12px;line-height:1.45;color:#c5d7ef}.ap-legal-agent ul{padding-left:17px;margin:8px 0 12px}.ap-legal-agent b{color:#e8f3ff}.ap-legal-status{font-size:10px;white-space:nowrap;padding:5px 7px;border-radius:20px;border:1px solid #b98c49;color:#ffdb9e;background:#925d2033}.ap-legal-agent .ap-legal-scope{margin-top:12px;padding-top:10px;border-top:1px solid #4a658b;color:#adcaec}.ap-legal-flow{border:1px solid #597ead;border-radius:12px;background:#10243c;padding:16px;margin:20px 0;color:#d9e9ff;font-size:12px;line-height:1.5}body[data-theme=light] .ap-legal-agent{background:linear-gradient(145deg,#f8fbff,#eaf2ff);border-color:#bdd2ed}body[data-theme=light] .ap-legal-agent :is(h3,b){color:#183857}body[data-theme=light] .ap-legal-agent :is(p,li,small,.ap-legal-scope){color:#435f7e}body[data-theme=light] .ap-legal-status{color:#81500c;background:#ffedca}body[data-theme=light] .ap-legal-flow{background:#f2f7ff;color:#28476e;border-color:#bfd4ee}
  .ap-jurisdiction{display:flex;align-items:center;gap:12px;flex-wrap:wrap;border:1px solid #628bbd;border-radius:11px;padding:12px 16px;margin-bottom:19px;background:#18304d;color:#e8f2ff;font-size:12px}.ap-jurisdiction select,.ap-cost-form input,.ap-cost-form select{background:#0c1d33;color:#f0f7ff;border:1px solid #7098c7;border-radius:7px;padding:9px}.ap-cost-form{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:12px;padding:17px;border:1px solid #587eb0;border-radius:12px;background:#162943}.ap-cost-form label{font-size:12px;color:#d3e4fc;display:grid;gap:6px}.ap-cost-form button{align-self:end;border:1px solid #82b3ea;border-radius:8px;background:#305c94;color:#fff;padding:10px;cursor:pointer}.ap-cost-kpis{margin:18px 0}.ap-cost-kpis b{font-size:20px}.ap-cost-note{border-left:3px solid #d99b54;padding:9px 13px;background:#95601b2b;font-size:12px;line-height:1.5;margin:12px 0}body[data-theme=light] .ap-jurisdiction,body[data-theme=light] .ap-cost-form{background:#eef5ff;color:#28476b;border-color:#b9d0ec}body[data-theme=light] .ap-cost-form label{color:#375676}body[data-theme=light] .ap-jurisdiction select,body[data-theme=light] .ap-cost-form :is(input,select){background:#fff;color:#1e3958}body[data-theme=light] .ap-cost-note{background:#fff2da;color:#6a491d}
  .ap-recruit-hero{padding:23px;border-radius:16px;border:1px solid #638ec1;background:radial-gradient(circle at 15% 0,#416bc066,transparent 45%),linear-gradient(135deg,#12243e,#162540 72%,#223458);margin-bottom:17px}.ap-recruit-hero small{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:#a8d2fa}.ap-recruit-hero h2{font-size:27px;margin:8px 0}.ap-recruit-hero p{max-width:760px;color:#c4d8f1;font-size:13px;line-height:1.5}.ap-recruit-categories{display:grid;grid-template-columns:repeat(auto-fit,minmax(155px,1fr));gap:10px;margin:15px 0}.ap-recruit-category{border:1px solid #5279a8;background:#152b49;border-radius:12px;padding:13px;min-width:0}.ap-recruit-category small{display:block;color:#a7c2e8;font-size:11px}.ap-recruit-category strong{font-size:19px;display:block;margin-top:6px;color:#eef6ff}.ap-recruit-radar{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:11px;margin:14px 0 25px}.ap-recruit-radar>div{border-radius:12px;border:1px solid #5277a2;background:linear-gradient(135deg,#142943,#162d4b);padding:14px}.ap-recruit-radar strong{display:block;font-size:13px;color:#e7f3ff}.ap-recruit-radar small{font-size:11px;color:#a9c4e2;line-height:1.5}.ap-recruit-form{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:10px;padding:15px;border:1px solid #6688b4;border-radius:12px;background:#162943;margin:15px 0}.ap-recruit-form label{font-size:11px;color:#d2e3f7;display:grid;gap:5px}.ap-recruit-form :is(input,select){border:1px solid #7198c3;background:#0d1e34;border-radius:7px;color:#fff;padding:9px;min-width:0}.ap-recruit-form button,.ap-recruit-move{border:1px solid #88b5e5;background:#2d598a;border-radius:7px;padding:9px;color:white;cursor:pointer}.ap-recruit-form button{align-self:end}.ap-recruit-board{display:grid;grid-template-columns:repeat(4,minmax(210px,1fr));gap:12px;overflow-x:auto;padding:2px 0 10px}.ap-recruit-column{border:1px solid #476c9c;border-radius:13px;background:#11243e;padding:12px;min-width:210px}.ap-recruit-column h3{font-size:13px;margin:2px 3px 13px}.ap-recruit-card{padding:12px;border:1px solid #668bb9;border-radius:10px;background:#1c3556;margin-bottom:10px;box-shadow:0 5px 15px #09172a44}.ap-recruit-card small{color:#acd0fb;font-size:10px;text-transform:uppercase;letter-spacing:.05em}.ap-recruit-card strong{display:block;margin:5px 0;font-size:12px;overflow-wrap:anywhere}.ap-recruit-card p{font-size:11px;color:#c7d8ed;line-height:1.4;overflow-wrap:anywhere}.ap-recruit-move{font-size:10px;padding:6px 8px}.ap-recruit-empty{color:#9cb6d4;font-size:11px;line-height:1.5;padding:9px}body[data-theme=light] .ap-recruit-hero,body[data-theme=light] .ap-recruit-category,body[data-theme=light] .ap-recruit-radar>div,body[data-theme=light] .ap-recruit-form,body[data-theme=light] .ap-recruit-column,body[data-theme=light] .ap-recruit-card{background:#f5f9ff;border-color:#b8d0eb;color:#254367}body[data-theme=light] .ap-recruit-hero :is(h2,p,small),body[data-theme=light] .ap-recruit-category :is(small,strong),body[data-theme=light] .ap-recruit-radar :is(small,strong),body[data-theme=light] .ap-recruit-form label,body[data-theme=light] .ap-recruit-card :is(small,p,strong),body[data-theme=light] .ap-recruit-empty{color:#365879}body[data-theme=light] .ap-recruit-form :is(input,select){background:white;color:#263f5a}@media(max-width:800px){.ap-recruit-radar{grid-template-columns:1fr}.ap-recruit-board{grid-template-columns:repeat(4,minmax(210px,1fr))}}
  .ap-squad{border-radius:15px;border:1px solid #6395c3;background:radial-gradient(ellipse at 50% 20%,#367a6640,transparent 63%),#0d2b39;padding:18px;margin:20px 0}.ap-squad header{font-size:12px;font-weight:700;letter-spacing:.08em;color:#a9ecdb}.ap-squad-pitch{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;margin-top:15px}.ap-squad-role{border:1px solid #4f9e8d;background:#163f46bd;border-radius:12px;text-align:center;padding:16px;min-width:0}.ap-squad-role span{display:block;font-size:22px;margin-bottom:5px}.ap-squad-role strong{display:block;color:#e0fff3;font-size:12px}.ap-squad-role small{font-size:10px;color:#b2decf}.ap-candidate-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(245px,1fr));gap:12px;margin:15px 0}.ap-candidate-card{padding:15px;border:1px solid #5a80aa;border-radius:12px;background:#192d4a}.ap-candidate-card strong{font-size:14px;color:#e3f3ff}.ap-candidate-card p,.ap-candidate-card small{font-size:11px;color:#bad0ea;line-height:1.5}.ap-candidate-card button{border:1px solid #84b4ed;background:#315b8d;color:white;padding:8px;border-radius:7px;cursor:pointer;font-size:11px}.ap-candidate-card .ap-legal-status{display:inline-block;margin:8px 0}.ap-candidate-form{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;padding:15px;border:1px solid #5685b4;border-radius:12px;background:#162943}.ap-candidate-form label{display:grid;gap:5px;font-size:11px}.ap-candidate-form :is(input,select,textarea){background:#0e2038;border:1px solid #638db9;border-radius:7px;padding:9px;color:#fff;min-width:0}.ap-candidate-form textarea{min-height:74px}.ap-candidate-form button{align-self:end;padding:10px;border-radius:8px;border:1px solid #84b8ec;background:#315b92;color:#fff;cursor:pointer}body[data-theme=light] .ap-squad{background:#ecf8f1;border-color:#9bcbb6}body[data-theme=light] .ap-squad header{color:#24634d}body[data-theme=light] .ap-squad-role{background:#f7fffb;border-color:#b5d4c7}body[data-theme=light] .ap-squad-role :is(strong,small){color:#295647}body[data-theme=light] .ap-candidate-card,body[data-theme=light] .ap-candidate-form{background:#f5f9ff;border-color:#bfd3eb;color:#2e4c6d}body[data-theme=light] .ap-candidate-card :is(strong,p,small){color:#305475}body[data-theme=light] .ap-candidate-form :is(input,select,textarea){background:#fff;color:#274561}@media(max-width:650px){.ap-squad-pitch{grid-template-columns:1fr}}
  .ap-activity-form{display:flex;gap:12px;flex-wrap:wrap;align-items:end;padding:15px;border:1px solid #5685b4;border-radius:12px;background:#162943;margin:16px 0}.ap-activity-form label{display:grid;gap:6px;font-size:12px;color:#d3e4fc}.ap-activity-form :is(input,select){background:#0e2038;border:1px solid #638db9;border-radius:7px;padding:9px;color:#fff;min-width:0}.ap-activity-form .ap-activity-search{flex:1 1 200px}.ap-activity-meta{color:#a9c4e2;font-size:12px;margin:12px 0 0}body[data-theme=light] .ap-activity-form{background:#eef5ff;border-color:#b9d0ec}body[data-theme=light] .ap-activity-form label{color:#28476b}body[data-theme=light] .ap-activity-form :is(input,select){background:#fff;color:#1e3958}body[data-theme=light] .ap-activity-meta{color:#435f7e}
  /* Navegación táctil y shell adaptable */
  .ap-menu-toggle,.ap-menu-close{display:none}.ap-menu-backdrop{position:fixed;inset:0;z-index:79;background:#061226b8;backdrop-filter:blur(3px)}
  .container,.main,.header,.metrics,.mid-row,.charts-row,.ap-view{min-width:0}.main{min-width:0}.sidebar{flex:0 0 220px}.ap-table-wrap{max-width:100%}
  :is(.nav-item,.ap-theme,.ap-mode,.ap-human,.notif,.ap-menu-toggle,.ap-menu-close):focus-visible{outline:3px solid #9ad0ff;outline-offset:2px}
  @media(max-width:1050px){.container{padding:12px;gap:12px}.sidebar{flex-basis:190px;width:190px}.header{flex-wrap:wrap;gap:10px}.header-right{gap:7px;flex-wrap:wrap}.header-title h1{font-size:16px}.mid-row{grid-template-columns:minmax(0,1fr)}.charts-row{grid-template-columns:minmax(0,1fr)}}
  @media(max-width:1050px) and (min-width:761px){.ap-mode{max-width:none!important}}
  @media(max-width:760px){.ap-menu-toggle{position:fixed;z-index:90;top:10px;left:10px;display:inline-flex;align-items:center;gap:7px;min-height:44px;padding:7px 11px;border:1px solid #6f9dd5;border-radius:10px;background:#19375d;color:#fff;font:600 12px Inter,system-ui,sans-serif;box-shadow:0 6px 18px #020e25aa;cursor:pointer}.ap-menu-close{display:block;align-self:flex-end;border:1px solid #6f9dd5;border-radius:8px;background:#173259;color:white;min-height:40px;padding:7px 12px;cursor:pointer}.container{display:block;padding:10px;min-width:0;z-index:80;pointer-events:none}.container .sidebar,.container .main{pointer-events:auto}.container:has(.sidebar.is-open) .main{pointer-events:none}.main{position:relative;z-index:1}.main{width:100%;gap:10px}.sidebar{position:fixed!important;z-index:80;inset:0 auto 0 0;top:0!important;width:min(300px,85vw);max-width:min(300px,85vw);height:100dvh;max-height:100dvh!important;overflow-y:auto;transform:translateX(-105%);transition:transform .22s ease;box-shadow:0 15px 35px #020c20bb}.sidebar.is-open{transform:translateX(0);z-index:80!important}.header{padding:62px 12px 12px;display:block;min-width:0}.header-title h1{font-size:clamp(15px,4vw,19px);overflow-wrap:anywhere}.header-right{margin-top:12px;display:flex;gap:7px;flex-wrap:wrap}.header-right .ap-theme,.header-right .ap-human,.header-right .notif{width:44px;height:44px;min-width:44px}.header-right .ap-mode{min-height:44px;max-width:none}.metrics{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.metric-card{padding:12px;min-width:0}.metric-value{font-size:clamp(17px,5.5vw,24px);overflow-wrap:anywhere}.mid-row,.charts-row{grid-template-columns:minmax(0,1fr)}.chart-card{min-width:0;overflow:hidden}.chart-container{min-width:0;max-width:100%;overflow:hidden}.chart-container canvas{max-width:100%!important}.bg-city{width:100vw}.ap-view{padding:13px;min-width:0}.ap-headlines{bottom:55px;height:30px;max-width:100vw}.ap-headlines-label{font-size:9px;padding:0 8px}.ap-ticker{height:55px;max-width:100vw;padding:3px 8px;gap:6px}.ap-ticker-label{min-width:62px;font-size:9px}.ap-ticker-widget{height:48px}.ap-spotlight{bottom:92px!important;max-width:calc(100vw - 30px)}body:has(.ap-ticker:not([hidden])){padding-bottom:85px}body:has(.ap-ticker[hidden]){padding-bottom:30px}body[data-theme=light] .ap-menu-toggle{background:#eaf3ff;color:#21466c}}
  @media(max-width:480px){.metrics{grid-template-columns:repeat(2,minmax(0,1fr))}.ap-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.ap-legal-grid,.ap-law-list,.ap-candidate-list{grid-template-columns:minmax(0,1fr)}.ap-recruit-categories{grid-template-columns:repeat(2,minmax(0,1fr))}.ap-recruit-board{grid-template-columns:repeat(4,minmax(230px,1fr))}.ap-cost-form,.ap-candidate-form,.ap-recruit-form{grid-template-columns:minmax(0,1fr)}.ap-candidate-form label[style]{grid-column:auto!important}.ap-squad-pitch{grid-template-columns:minmax(0,1fr)}.chat-window{position:fixed!important;inset:0!important;left:0!important;top:0!important;right:0!important;bottom:0!important;width:100vw!important;height:100dvh!important;min-width:0!important;min-height:0!important;max-width:none!important;max-height:none!important;border-radius:0!important;resize:none!important;z-index:110}.chat-header{cursor:default}.chat-footer input{min-width:0}.ap-notices{position:fixed;top:72px;left:10px;right:10px;width:auto;max-height:60vh}.ap-spotlight{display:none!important}}
  @media(prefers-reduced-motion:reduce){.sidebar{transition:none}}
  .agents-card{display:flex;flex-direction:column}.ap-news{margin-top:auto;padding-top:18px;border-top:1px solid #304565}.ap-news-head{font-size:10px;letter-spacing:.1em;font-weight:800;color:#e4f2ff}.ap-news-head small{display:block;color:#85a8ca;font-size:9px;margin-top:3px}.ap-video{position:relative;aspect-ratio:16/9;background:#070d18;margin-top:10px;border:1px solid #507eac;border-radius:9px;overflow:hidden}.ap-video iframe{width:100%;height:100%;border:0}.ap-video-error:not([hidden]){position:absolute;inset:0;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:9px;padding:18px;background:#07101ef5;color:#ecf4ff;text-align:center;font-size:12px;z-index:2}.ap-video-error a{color:#8fceff}.ap-news p{font-size:10px;color:#90a9c6;margin-top:8px}.ap-news a{color:#80c2ff}body[data-theme="light"] .ap-news{border-color:#d3e1f0}body[data-theme="light"] .ap-news-head{color:#2c4a70}body[data-theme="light"] .ap-news p{color:#536781}
</style>
</head>
<body>
  <div class="bg-city"></div>

  <button type="button" id="ap-menu-toggle" class="ap-menu-toggle" aria-label="Abrir menú de secciones" aria-controls="ap-sidebar" aria-expanded="false">☰ <span>Secciones</span></button>
  <div id="ap-menu-backdrop" class="ap-menu-backdrop" hidden></div>
  <div class="container">
    <aside class="sidebar" id="ap-sidebar" aria-label="Secciones">
      <button type="button" class="ap-menu-close" id="ap-menu-close" aria-label="Cerrar menú de secciones">Cerrar ✕</button>
      <div class="logo">
        <div class="logo-icon">IA</div>
        <div class="logo-text">Core<small style="display:block;font-size:10px;font-weight:400;opacity:.7;line-height:1.2">Núcleo de un ERP Agéntico</small></div>
      </div>
      <button type="button" class="nav-item active" data-view="0"><span class="icon">📊</span> Dashboard</button>
      <button type="button" class="nav-item" data-view="1"><span class="icon">💰</span> Finanzas</button>
      <button type="button" class="nav-item" data-view="2"><span class="icon">📦</span> Suministro</button>
      <button type="button" class="nav-item" data-view="3"><span class="icon">🚚</span> Logística IA</button>
      <button type="button" class="nav-item" data-view="4"><span class="icon">📋</span> Gestión de Stock</button>
      <button type="button" class="nav-item" data-view="5"><span class="icon">🛒</span> Ventas</button>
      <button type="button" class="nav-item" data-view="6"><span class="icon">🎯</span> CRM Predictivo</button>
      <button type="button" class="nav-item" data-view="7"><span class="icon">💲</span> Precios Dinámicos</button>
      <button type="button" class="nav-item" data-view="8"><span class="icon">👥</span> RRHH</button>
      <button type="button" class="nav-item" data-view="9"><span class="icon">🧠</span> Talento IA</button>
      <button type="button" class="nav-item" data-view="10"><span class="icon">📅</span> Planificación</button>
      <button type="button" class="nav-item" data-view="11"><span class="icon">🏭</span> Producción</button>
      <button type="button" class="nav-item" data-view="12"><span class="icon">📈</span> Reportes Avanzados</button>
      <button type="button" class="nav-item" data-view="13"><span class="icon">🤖</span> Agentes IA</button>
      <button type="button" class="nav-item" data-view="21"><span class="icon">💬</span> Intervenciones</button>
      <button type="button" class="nav-item" data-view="14"><span class="icon">⚖️</span> Cumplimiento</button>
      <button type="button" class="nav-item" data-view="15"><span class="icon">🇨🇴</span> Nómina Colombia</button>
      <button type="button" class="nav-item" data-view="16"><span class="icon">🧭</span> Subagentes jurídicos</button>
      <button type="button" class="nav-item" data-view="17"><span class="icon">📊</span> Costes de mano de obra</button>
      <button type="button" class="nav-item" data-view="18"><span class="icon">🌱</span> Reclutamiento y cambio</button>
      <button type="button" class="nav-item" data-view="19"><span class="icon">⚽</span> Currícula · equipo</button>
      <button type="button" class="nav-item" data-view="20"><span class="icon">🧾</span> Registro de actividad</button>
    </aside>

    <main class="main">
      <header class="header">
        <div class="header-title">
          <h1>ERP | OPERACIONES INTELIGENTES 2030</h1>
        </div>
        <div class="header-right">
          <button id="ap-tv-toggle" class="ap-theme" aria-label="Modo TV" title="Modo TV">📺</button>
          <button id="ap-fullscreen" class="ap-theme" type="button" aria-label="Entrar en pantalla completa" title="Entrar en pantalla completa" aria-pressed="false">⛶</button>
          <button id="ap-ticker-toggle" class="ap-theme" aria-label="Mostrar u ocultar mercados" title="Mostrar u ocultar mercados">📈</button>
          <button id="ap-sound" class="ap-theme" aria-label="Silenciar efectos" title="Silenciar efectos">🔊</button>
          <button id="ap-theme" class="ap-theme" aria-label="Cambiar tema" title="Cambiar tema">☀️</button>
          <button id="ap-mode" class="ap-mode" aria-label="Cambiar modo del ERP">👤 Supervisado</button>
          <button id="ap-agents" class="ap-mode" aria-label="Activar o detener el motor automático de agentes" aria-pressed="true">🤖 Agentes</button>
          <button class="ap-human" title="Supervisión humana" aria-label="Supervisión humana" onclick="AP.tab('supervision')">👤</button>
          <button type="button" id="ap-bell" class="notif" aria-label="Avisos" aria-expanded="false">🔔<span id="ap-bell-count" hidden></span></button>
          <div class="avatar">U</div>
        </div>
      </header>
      <aside id="ap-notices" class="ap-notices" hidden></aside>

      <div id="ap-dashboard">
      <section class="metrics">
        <div class="metric-card">
          <div class="metric-label">Valor de pedidos</div>
          <div class="metric-value" id="ap-order-value">...</div>
          <div class="metric-change neutral">Pedidos registrados</div>
        </div>
        <div class="metric-card">
          <div class="metric-label">Unidades reservadas</div>
          <div class="metric-value" id="ap-reservations">...</div>
          <div class="metric-change neutral">Inventario</div>
        </div>
        <div class="metric-card">
          <div class="metric-label">SKU sin alerta de stock</div>
          <div class="metric-value" id="ap-stock-metric">...</div>
          <div class="metric-change neutral">Estado de inventario</div>
        </div>
        <div class="metric-card">
          <div class="metric-label">Decisiones pendientes</div>
          <div class="metric-value" id="ap-pending-metric">...</div>
          <div class="metric-change neutral">Supervisión humana</div>
        </div>
      </section>

      <section class="mid-row">
        <div class="agents-card">
          <div class="section-title">Agentes</div>
          <button type="button" class="agent-item" data-agent="ALPHA" aria-label="Ver actividad de ALPHA" aria-pressed="false">
            <div class="agent-badge a">A</div>
            <div class="agent-info">
              <div class="agent-name">ALPHA</div>
              <div class="agent-role">Inventario</div>
            </div>
            <div class="agent-status" id="ap-agent-alpha">Disponible</div>
          </button>
          <button type="button" class="agent-item" data-agent="BETA" aria-label="Ver actividad de BETA" aria-pressed="false">
            <div class="agent-badge b">B</div>
            <div class="agent-info">
              <div class="agent-name">BETA</div>
              <div class="agent-role">Ventas</div>
            </div>
            <div class="agent-status" id="ap-agent-beta">En espera</div>
          </button>
          <button type="button" class="agent-item" data-agent="GAMMA" aria-label="Ver actividad de GAMMA" aria-pressed="false">
            <div class="agent-badge g">G</div>
            <div class="agent-info">
              <div class="agent-name">GAMMA</div>
              <div class="agent-role">Logística</div>
            </div>
            <div class="agent-status" id="ap-agent-gamma">Proveedores</div>
          </button>
          <section class="ap-news"><div class="ap-news-head"><span class="ap-live-dot"></span> NOTICIAS INTERNACIONALES <small>FRANCE 24 · EN DIRECTO</small></div><div class="ap-video"><iframe id="ap-news-player" src="https://www.youtube-nocookie.com/embed/HvZt-nh9sGg?autoplay=1&mute=1&cc_load_policy=1&playsinline=1&enablejsapi=1" title="FRANCE 24 English en directo" allow="autoplay; encrypted-media; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" loading="lazy" allowfullscreen></iframe><div id="ap-video-error" class="ap-video-error" hidden><strong>No se pudo cargar la emisión.</strong><a href="https://www.youtube.com/watch?v=HvZt-nh9sGg" target="_blank" rel="noopener noreferrer">Abrir FRANCE 24 en YouTube ↗</a></div></div><p>Emisión oficial en silencio. Si el reproductor no carga, <a href="https://www.youtube.com/watch?v=HvZt-nh9sGg" target="_blank" rel="noopener noreferrer">ver el directo en YouTube ↗</a>.</p></section>
        </div>

        <section id="ap-agent-center" class="ap-agent-center" aria-live="polite" hidden></section>
        <div class="alerts-card">
          <div class="section-title">Inventario</div>
          <div id="ap-state">Cargando datos...</div>
          <div id="ap-stock"></div>
          <button class="ap-action" id="ap-analyze">Analizar inventario con ALPHA</button>
          <div class="section-title" style="margin-top:16px">Pedidos</div>
          <div id="ap-orders"></div>
          <div class="section-title" style="margin-top:12px">Actividad en vivo</div>
          <div id="ap-cycle"></div>
          <div id="ap-feed"></div>
        </div>
      </section>

      <section class="charts-row">
        <div class="chart-card">
          <h3>Pronóstico de demanda T3/T4</h3>
          <div class="chart-container">
            <canvas id="demandChart"></canvas>
          </div>
        </div>
        <div class="chart-card">
          <h3>Costo de Operaciones</h3>
          <div class="chart-container">
            <canvas id="costChart"></canvas>
          </div>
        </div>
      </section>
      </div>
      <section id="ap-view" class="ap-view" hidden></section>
    </main>
  </div>

  <!-- CHAT WINDOW MOVIBLE -->
  <div class="chat-window" id="chatWindow" hidden>
    <div class="chat-header" id="chatHeader">
      <h4>💬 CHAT CON CORE IA</h4>
      <button type="button" class="close" onclick="AP.closeChat()" aria-label="Cerrar chat">✕</button>
    </div>
    <div class="ap-tabs"><button id="ap-tab-chat">Chat</button><button id="ap-tab-supervision">Supervisión <span id="ap-pending">0</span></button></div>
    <div id="ap-chat-panel">
      <div class="ap-model-bar">
        <button id="ap-model-load" type="button">⬇️ Descargar MiMo 9B (~5,8 GB)</button>
        <button id="ap-model-stop" type="button" hidden>⏹ Detener</button>
        <span id="ap-model-state">Comprobando módulo del modelo…</span>
      </div>
      <div class="ap-model-progress" id="ap-model-progress" hidden><div></div></div>
      <div class="chat-body" role="log" aria-label="Conversación con ALPHA" aria-live="polite" aria-relevant="additions"><div class="chat-msg ai">Consulta el inventario con ALPHA. El asistente usa un modelo MiMo 9B que se ejecuta en tu navegador: descárgalo con el botón de arriba la primera vez. Las propuestas requieren tu aprobación. Aviso: en las pruebas actuales este modelo falla al generar con el runtime probado (en investigación).</div></div>
      <div class="chat-footer">
        <button id="ap-websearch" class="ap-mic" type="button" aria-pressed="false">🔎</button>
        <input type="text" placeholder="Escribe un mensaje..." id="chatInput" aria-label="Mensaje para ALPHA" autocomplete="off">
        <button id="ap-mic" class="ap-mic" type="button" aria-label="Dictar mensaje" title="Dictar mensaje" aria-pressed="false">🎙️</button>
        <button onclick="sendMessage()" aria-label="Enviar mensaje">➤</button>
      </div>
    </div>
    <div id="ap-supervision-panel" hidden>
      <div class="ap-panel-title">Propuestas de compra</div>
      <div id="ap-queue"></div>
      <div class="ap-panel-title">Actividad reciente</div>
      <div id="ap-audit"></div>
      <p class="ap-demo-warning">DEMO FICTICIA · Datos locales de julio de 2030. Los pedidos nuevos son simulados y no llegan de una tienda real.</p><button class="ap-action" id="ap-reset" type="button">Restablecer solo esta demo</button>
    </div>
  </div>

  <div id="ap-headlines" class="ap-headlines"><span class="ap-headlines-label">EN PORTADA</span><div class="ap-headlines-clip"><div id="ap-headlines-text"></div></div></div>
  <div id="ap-tv" class="ap-tv" hidden><div class="ap-tv-top"><div><span class="ap-live-dot"></span> CORE · EN DIRECTO <small>OPERACIONES INTELIGENTES</small></div><time id="ap-tv-clock"></time><button id="ap-tv-close" aria-label="Salir del modo TV">Salir ✕</button></div><div class="ap-tv-stage"><div class="ap-tv-head"><small id="ap-tv-kicker">INTELIGENCIA DE OPERACIONES</small><h1 id="ap-tv-title">El negocio, en movimiento</h1><p id="ap-tv-subtitle"></p></div><div id="ap-tv-viz" class="ap-tv-viz"><svg viewBox="0 0 900 330" aria-label="Flujo de agentes entre ventas, inventario y suministro" role="img"><defs><linearGradient id="ap-tv-line"><stop stop-color="#318ffb"/><stop offset=".5" stop-color="#a967ed"/><stop offset="1" stop-color="#39d8c2"/></linearGradient></defs><path d="M130 165 Q350 10 450 165 Q550 320 770 165" fill="none" stroke="url(#ap-tv-line)" stroke-width="3" stroke-dasharray="10 8" class="ap-tv-path"/><circle cx="130" cy="165" r="64" class="ap-tv-node"/><circle cx="450" cy="165" r="64" class="ap-tv-node"/><circle cx="770" cy="165" r="64" class="ap-tv-node"/><text x="130" y="157" text-anchor="middle">BETA</text><text x="450" y="157" text-anchor="middle">ALPHA</text><text x="770" y="157" text-anchor="middle">GAMMA</text><text x="130" y="184" text-anchor="middle" class="ap-tv-node-sub">VENTAS</text><text x="450" y="184" text-anchor="middle" class="ap-tv-node-sub">INVENTARIO</text><text x="770" y="184" text-anchor="middle" class="ap-tv-node-sub">SUMINISTRO</text><circle r="9" fill="#e4f8ff" class="ap-tv-pulse"><animateMotion dur="5s" repeatCount="indefinite" path="M130 165 Q350 10 450 165 Q550 320 770 165"/></circle></svg></div><div id="ap-tv-cards" class="ap-tv-cards"></div></div><div id="ap-tv-lower" class="ap-tv-lower"><span class="ap-tv-live">● EN VIVO</span><strong id="ap-tv-story"></strong><small>FIVETECH · DATOS LOCALES</small></div></div>
  <div id="ap-ticker" class="ap-ticker" hidden><div class="ap-ticker-label"><span class="ap-live-dot"></span> MERCADOS <small>Datos según disponibilidad de cada bolsa</small><time id="ap-broadcast-clock"></time></div><div class="ap-ticker-widget tradingview-widget-container"><div class="tradingview-widget-container__widget"></div><script type="text/javascript" src="https://s3.tradingview.com/external-embedding/embed-widget-ticker-tape.js" async>{"symbols":[{"proName":"NASDAQ:AAPL","description":"Apple"},{"proName":"NASDAQ:MSFT","description":"Microsoft"},{"proName":"NASDAQ:NVDA","description":"Nvidia"},{"proName":"NASDAQ:AMZN","description":"Amazon"},{"proName":"NASDAQ:GOOGL","description":"Alphabet"},{"proName":"NASDAQ:TSLA","description":"Tesla"},{"proName":"FOREXCOM:SPXUSD","description":"S&P 500"}],"showSymbolLogo":true,"colorTheme":"dark","isTransparent":true,"displayMode":"adaptive","locale":"es"}</script></div><a href="https://www.tradingview.com/" target="_blank" rel="noopener noreferrer" class="ap-tv-credit">TradingView ↗</a></div>
  <div id="ap-dialog" class="ap-dialog" role="dialog" aria-modal="true" aria-label="Confirmar acción" hidden></div>
  <div id="ap-focus" class="ap-focus" hidden></div>
  <button type="button" id="ap-spotlight" class="ap-spotlight" hidden aria-label="Abrir aviso destacado"><small id="ap-spotlight-agent"></small><strong id="ap-spotlight-title"></strong><span id="ap-spotlight-detail"></span><span class="ap-spotlight-hint">Ver detalles ↗</span></button>
  <div class="projector"></div>

<script>
  // ========== DRAG & DROP del chat ==========
  const chatWindow = document.getElementById('chatWindow');
  const chatHeader = document.getElementById('chatHeader');

  let isDragging = false;
  let offsetX = 0;
  let offsetY = 0;

  chatHeader.addEventListener('mousedown', (e) => {
    // No iniciar drag si se hace clic en el botón de cerrar
    if (e.target.classList.contains('close')) return;

    isDragging = true;
    const rect = chatWindow.getBoundingClientRect();
    offsetX = e.clientX - rect.left;
    offsetY = e.clientY - rect.top;

    chatWindow.style.transition = 'none'; // desactiva transiciones mientras se mueve
    document.body.style.cursor = 'grabbing';
  });

  document.addEventListener('mousemove', (e) => {
    if (!isDragging) return;

    let newX = e.clientX - offsetX;
    let newY = e.clientY - offsetY;

    // Limitar para que no se salga de la pantalla
    const maxX = window.innerWidth - chatWindow.offsetWidth;
    const maxY = window.innerHeight - chatWindow.offsetHeight;

    newX = Math.max(0, Math.min(newX, maxX));
    newY = Math.max(0, Math.min(newY, maxY));

    chatWindow.style.left = newX + 'px';
    chatWindow.style.top = newY + 'px';
    chatWindow.style.bottom = 'auto'; // importante para que top tenga prioridad
    chatWindow.style.right = 'auto';
  });

  document.addEventListener('mouseup', () => {
    if (isDragging) {
      isDragging = false;
      document.body.style.cursor = '';
      chatWindow.style.transition = ''; // restaura transiciones
    }
  });

  // ========== Charts ==========
  const APChartsInit = () => { if (typeof Chart === 'undefined') return;
  const demandCtx = document.getElementById('demandChart').getContext('2d');
  new Chart(demandCtx, {
    type: 'bar',
    data: {
      labels: ['T1', 'T2', 'T3', 'T4'],
      datasets: [
        {
          type: 'line',
          label: 'Pronóstico',
          data: [320, 480, 620, 780],
          borderColor: '#60a5fa',
          backgroundColor: 'rgba(96, 165, 250, 0.1)',
          borderWidth: 2,
          tension: 0.3,
          pointBackgroundColor: '#60a5fa',
          pointRadius: 4,
          fill: false
        },
        {
          type: 'bar',
          label: 'Real',
          data: [280, 420, 580, 720],
          backgroundColor: [
            'rgba(59, 130, 246, 0.7)',
            'rgba(99, 102, 241, 0.7)',
            'rgba(139, 92, 246, 0.7)',
            'rgba(168, 85, 247, 0.7)'
          ],
          borderRadius: 6,
          barPercentage: 0.6
        }
      ]
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: { legend: { display: false } },
      scales: {
        x: { grid: { color: 'rgba(80, 140, 255, 0.08)' }, ticks: { color: '#94a3b8', font: { size: 11 } } },
        y: { grid: { color: 'rgba(80, 140, 255, 0.08)' }, ticks: { color: '#94a3b8', font: { size: 11 } }, beginAtZero: true }
      }
    }
  });

  const costCtx = document.getElementById('costChart').getContext('2d');
  new Chart(costCtx, {
    type: 'line',
    data: {
      labels: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],
      datasets: [
        {
          label: 'Costo',
          data: [2100, 2400, 2800, 3200, 3600, 4100, 3800, 4200, 4500, 3900, 3600, 3400],
          borderColor: '#f59e0b',
          backgroundColor: 'rgba(245, 158, 11, 0.15)',
          borderWidth: 2.5,
          tension: 0.35,
          pointBackgroundColor: '#f59e0b',
          pointRadius: 3,
          fill: true
        },
        {
          label: 'Presupuesto',
          data: [2000, 2300, 2600, 3000, 3400, 3800, 3600, 4000, 4300, 3800, 3500, 3300],
          borderColor: '#22c55e',
          borderWidth: 1.5,
          borderDash: [5, 5],
          tension: 0.3,
          pointRadius: 0,
          fill: false
        }
      ]
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: { legend: { display: false } },
      scales: {
        x: { grid: { color: 'rgba(80, 140, 255, 0.08)' }, ticks: { color: '#94a3b8', font: { size: 10 } } },
        y: { grid: { color: 'rgba(80, 140, 255, 0.08)' }, ticks: { color: '#94a3b8', font: { size: 11 } }, beginAtZero: false }
      }
    }
  });
  if (typeof applyTheme === 'function') applyTheme();
  };
  if (typeof Chart !== 'undefined') APChartsInit();
  else document.addEventListener('DOMContentLoaded', APChartsInit, { once: true });

  document.querySelectorAll('.nav-item').forEach(item => {
    item.addEventListener('click', () => {
      document.querySelectorAll('.nav-item').forEach(i => i.classList.remove('active'));
      item.classList.add('active');
    });
  });
</script>
<script>
'use strict';
const APCompliance={
  // Didactic hierarchy, not a catalog of enacted law or a legal opinion.
  levels:[['constitucion','Constitución',1,'Norma superior (ejemplo de jerarquía)'],['ley','Leyes',2,'Mandatos legales (sin texto jurídico cargado)'],['reglamento','Reglamentos',3,'Desarrollo reglamentario (sin fuente cargada)'],['sector','Normas sectoriales',4,'Dependen de jurisdicción y sector'],['interna','Políticas internas',5,'Reglas de operación de esta demo']],
  colombia:[
    ['CO-CONST-25-53',1,'Constitución Política, arts. 25 y 53','Trabajo digno y remuneración mínima vital y móvil','https://www.suin-juriscol.gov.co/viewDocument.asp?ruta=Constitucion%2F1687988'],
    ['CO-CST',2,'Código Sustantivo del Trabajo','Salario, jornada, descansos y prestaciones; revisar artículos y reformas','https://www.funcionpublica.gov.co/eva/gestornormativo/norma.php?i=199983'],
    ['CO-LEY-2466-2025',2,'Ley 2466 de 2025','Reforma laboral; vigencia escalonada por disposición','https://www.funcionpublica.gov.co/eva/gestornormativo/norma.php?i=260676'],
    ['CO-DECRETO-159-2026',3,'Decreto 159 de 2026','Salario mínimo transitorio 2026; estado judicial requiere revisión','https://www.cancilleria.gov.co/normograma/compilacion/docs/decreto_0159_2026.htm'],
    ['CO-DECRETO-1470-2025',3,'Decreto 1470 de 2025','Auxilio de transporte 2026 y condiciones','https://cancilleria.gov.co/normograma/compilacion/docs/decreto_1470_2025.htm'],
    ['CO-CE-AUTO-2026',4,'Consejo de Estado: auto cautelar 2026','Suspensión provisional de Decreto 1469 y orden de acto sustituto; revisar providencias posteriores','https://www.alcaldiabogota.gov.co/sisjur/normas/Norma1.jsp?dt=S&i=192123'],
    ['CO-CC-C815-1999',4,'Corte Constitucional, C-815/99','Criterios constitucionales para fijar salario mínimo','https://www.corteconstitucional.gov.co/relatoria/1999/C-815-99.htm']
  ],
  agents:[
    ['mercantil','Mercantil','Compras, proveedores, operaciones comerciales y sociedades','Propuestas de compra y contratos comerciales','Constitución → legislación mercantil → reglamentos aplicables → actos y decisiones → política interna','Sin fuentes ni reglas de jurisdicción cargadas'],
    ['laboral','Laboral','Vínculos de trabajo, jornada, remuneración y seguridad social','Alta y cambios de personal, nómina, jornada','Constitución → leyes y código laboral → reglamentos → jurisprudencia aplicable → política interna','Caso Colombia disponible solo como demo de fuentes; Venezuela sin fuentes laborales cargadas'],
    ['civil','Civil · contratación','Formación, ejecución, garantías y terminación de contratos civiles','Borradores de contrato, renovaciones y cláusulas','Constitución → legislación civil → reglamentos aplicables → jurisprudencia → cláusulas y política interna','Sin análisis de cláusulas implementado'],
    ['tributario-nacional','Tributario · nacional','IVA, ISLR, aportes parafiscales patronales y tributos sectoriales, según país','Operaciones gravadas, facturación, nómina patronal y declaraciones','Constitución → leyes tributarias → reglamentos → actos administrativos y jurisprudencia → control interno','País y régimen por definir; no se calcula ni declara'],
    ['tributario-regional','Tributario · regional','Tributos de región, estado o departamento según territorio aplicable','Operaciones, establecimientos e inmuebles con nexo regional','Constitución → ley nacional habilitante → norma regional → decisiones aplicables → control interno','Región y competencia por definir'],
    ['tributario-local','Tributario · local','Tributos municipales o distritales según domicilio y actividad','Establecimientos, actividades, inmuebles y permisos locales','Constitución → ley habilitante → ordenanza o acuerdo local → decisiones aplicables → control interno','Municipio y competencia por definir'],
    ['administrativo','Administrativo','Interacciones con entidades públicas y posibles faltas en la actuación de funcionarios, con revisión de hechos y competencia','Quejas o reclamos, peticiones, recursos frente a actos administrativos y eventual responsabilidad estatal','Constitución → procedimiento administrativo y leyes aplicables → reglamentos → acto y expediente → precedentes pertinentes','País, entidad, hechos, plazos y vía competente por verificar; no presenta escritos ni acusa a personas']
  ],
  
  evaluate(ap,input){const layers=ap.query("SELECT * FROM compliance_norms WHERE id LIKE 'DEMO-%' ORDER BY level,id");if(!layers.length)return {status:'review',norm_id:null,reason:'Sin jerarquía de normas cargada'};const unknown=layers.find(x=>x.level<5&&!x.source_url);if(unknown)return {status:'review',norm_id:unknown.id,reason:'Faltan fuentes jurídicas vigentes para '+unknown.name+'; requiere evaluación humana'};return {status:'review',norm_id:'DEMO-interna-propuesta',reason:'Revisión humana requerida por política interna ilustrativa'};},
  badge(ap,id){const c=ap.one('SELECT c.status,c.norm_id,c.reason FROM compliance_checks c WHERE c.proposal_id=?',[id]);const r=c||{status:'review',norm_id:'SIN-REVISAR',reason:'Propuesta anterior sin comprobación documentada'};return '<span class="ap-compliance-pill '+r.status+'" title="'+ap.esc(r.norm_id+' · '+r.reason)+'">'+(r.status==='pass'?'● Conforme':r.status==='block'?'● Bloqueado':'● Revisar')+' · '+ap.esc(r.norm_id)+'</span>'},
  country(){return localStorage.getItem('ap-country')==='VE'?'VE':'CO'},
  jurisdictionPicker(){const country=this.country();return '<div class="ap-jurisdiction"><label for="ap-country">País para la vista jurídica</label><select id="ap-country" aria-label="País para la vista jurídica"><option value="CO"'+(country==='CO'?' selected':'')+'>Colombia</option><option value="VE"'+(country==='VE'?' selected':'')+'>Venezuela</option></select><span>Selector de análisis local; no convierte normas de un país en reglas de otro.</span></div>'},
  assessEvidence(text){const t=String(text).toLocaleLowerCase('es'),values=[['colaboración',/colabor|equipo|coordin/],['aprendizaje',/aprend|formaci[oó]n|mejor/],['responsabilidad',/responsab|entreg|seguim/]],hits=values.filter(x=>x[1].test(t)).map(x=>x[0]),specific=/\b(\d{1,3}%|\d+ (meses|años|proyectos|clientes|entregas)|resultado|ejemplo|proyecto|implement)\b/i.test(t),score=hits.length*20+(specific?20:0),explanation='Señales textuales encontradas: '+(hits.join(', ')||'ninguna')+'. '+(specific?'Incluye ejemplo o resultado específico.':'Falta un ejemplo o resultado específico; pide evidencia antes de avanzar.')+' Revisión humana necesaria: las palabras clave no prueban ajuste cultural.';return {score,explanation,status:score>=60?'review':'needs_evidence'}},
  candidateView(){const ap=AP,esc=v=>ap.esc(v??''),rows=ap.query('SELECT * FROM candidate_screenings ORDER BY created_at DESC,id'),roles=[['⚙','Operaciones','Fabricación / servicio'],['🤝','Relaciones','Clientes y aliados'],['🔭','Exploración','Mercados y productos']];return '<div class="ap-recruit-hero"><small>RRHH · TRABAJO AGÉNTICO SEPARADO · DEMO SUPERVISADA</small><h2>Currícula y alineación cultural</h2><p>Las ofertas se muestran como posiciones de un equipo. Un cribado de texto explica señales observables de colaboración, aprendizaje y responsabilidad; no decide contrataciones ni sustituye entrevistas. Solo una persona puede aprobar el paso de un perfil al tablero de reclutamiento.</p></div><div class="ap-squad"><header>⚽ ALINEACIÓN · POSICIONES DE EJEMPLO, NO VACANTES PUBLICADAS</header><div class="ap-squad-pitch">'+roles.map(([icon,title,note])=>'<div class="ap-squad-role"><span>'+icon+'</span><strong>'+title+'</strong><small>'+note+'</small></div>').join('')+'</div></div><p class="ap-cost-note">Criterios definidos para esta demostración: evidencia relacionada con el puesto, colaboración, aprendizaje y responsabilidad. No se solicitan ni evalúan edad, género, origen, foto u otros atributos protegidos. La puntuación es un filtro de señales textuales, no una valoración de la persona o de su compatibilidad cultural real. Todo avance o rechazo requiere juicio humano.</p><h3>Analizar resumen voluntario de un perfil</h3><form id="ap-candidate-form" class="ap-candidate-form"><label>Alias (sin datos personales)<input name="alias" maxlength="60" required placeholder="Perfil A"></label><label>Posición<select name="role">'+roles.map(x=>'<option>'+esc(x[1])+'</option>').join('')+'</select></label><label style="grid-column:span 2">Evidencia laboral aportada<textarea name="evidence" maxlength="700" required placeholder="Ejemplos de trabajo en equipo, aprendizaje, responsabilidades y resultados, sin datos sensibles"></textarea></label><button type="submit">Analizar señales</button></form><p id="ap-candidate-feedback" class="ap-compliance-note" role="status">No pegues currículos con datos sensibles aquí. Ningún documento se sube ni se lee de forma autónoma.</p><h3>Revisión humana · '+rows.length+' perfiles locales</h3><div class="ap-candidate-list">'+(rows.length?rows.map(x=>'<article class="ap-candidate-card"><small>'+(x.demo?'PERFIL FICTICIO · DEMO':'PERFIL LOCAL')+' · '+esc(x.role)+'</small><br><strong>'+esc(x.alias)+'</strong><p>'+esc(x.evidence)+'</p><span class="ap-legal-status">'+(x.status==='approved'?'Avance aprobado por humano':x.status==='needs_evidence'?'Solicitar evidencia':'Revisión humana pendiente')+'</span><p><b>Señales '+x.score+'/80:</b> '+esc(x.explanation)+'</p>'+(x.status==='review'?'<button type="button" data-approve-candidate="'+esc(x.id)+'">Aprobar avance al reclutamiento</button>':'')+'</article>').join(''):'<p class="ap-recruit-empty">Sin perfiles. Introduce un escenario ficticio para probar el flujo.</p>')+'</div><p class="ap-compliance-note">La recomendación de avance exige 60/80 señales y una aprobación explícita de una persona. Un valor menor pide más evidencia, nunca rechazo automático. El proceso real necesita criterios aprobados, protección de datos, evaluación de sesgo y consentimiento.</p>'},
  recruitmentView(){const ap=AP,esc=v=>ap.esc(v??''),kinds=['Colaboradores internos','Aliados','Productos','Clientes','Mercados'],stages=['Detectado','Exploración','Evaluación','Incorporación'],all=ap.query('SELECT * FROM recruitment_pipeline ORDER BY created_at DESC,id'),counts=kinds.map(k=>[k,all.filter(x=>x.kind===k).length]),cards=stages.map((stage,i)=>'<div class="ap-recruit-column"><h3>'+esc(stage)+' · '+all.filter(x=>x.stage===stage).length+'</h3>'+((items)=>items.length?items.map(x=>'<article class="ap-recruit-card"><small>'+esc(x.kind)+(x.demo?' · DEMO':' · REGISTRO LOCAL')+'</small><strong>'+esc(x.title)+'</strong>'+(x.note?'<p>'+esc(x.note)+'</p>':'')+(x.signal?'<p>Señal aportada: '+esc(x.signal)+'</p>':'')+(i<stages.length-1?'<button class="ap-recruit-move" type="button" data-recruit-id="'+esc(x.id)+'" data-next-stage="'+esc(stages[i+1])+'">Mover a '+esc(stages[i+1])+'</button>':'')+'</article>').join(''):'<p class="ap-recruit-empty">Sin registros en esta etapa.</p>')(all.filter(x=>x.stage===stage))+'</div>').join('');return '<div class="ap-recruit-hero"><small>RRHH · CAPTACIÓN · GESTIÓN DEL CAMBIO EXTERNO</small><h2>Radar de oportunidades</h2><p>Cinco flujos de captación para acompañar cambios del mercado, la regulación y el ambiente. Un registro en el tablero no equivale a contratación, alianza, lanzamiento ni venta.</p></div><div class="ap-recruit-categories">'+counts.map(([k,n])=>'<div class="ap-recruit-category"><small>'+esc(k)+'</small><strong>'+n+' <small>registros</small></strong></div>').join('')+'</div><h3>Radar externo</h3><div class="ap-recruit-radar"><div><strong>↗ Mercado</strong><small>Nuevos clientes, mercados, aliados y productos. Esperando señales aportadas por el equipo.</small></div><div><strong>⚖ Regulaciones</strong><small>Impactos jurídicos y laborales por país; ningún cambio normativo se monitoriza automáticamente.</small></div><div><strong>◌ Ambiente</strong><small>Riesgos y oportunidades ambientales. Sin datos externos conectados ni alertas en tiempo real.</small></div></div><h3>Registrar oportunidad o escenario</h3><form id="ap-recruit-form" class="ap-recruit-form"><label>Flujo<select name="kind">'+kinds.map(k=>'<option>'+esc(k)+'</option>').join('')+'</select></label><label>Nombre breve<input name="title" maxlength="100" required placeholder="Ej.: Perfil de mantenimiento"></label><label>Señal externa (opcional)<input name="signal" maxlength="160" placeholder="Origen verificado por el equipo"></label><label>Nota (opcional)<input name="note" maxlength="180" placeholder="Siguiente paso propuesto"></label><button type="submit">Guardar en Detectado</button></form><p class="ap-compliance-note" id="ap-recruit-feedback" role="status">Datos locales en este navegador. El radar no inventa vacantes, candidatos, aliados ni señales externas; alimenta el tablero solo con lo registrado aquí.</p><h3>Flujo de seguimiento</h3><div class="ap-recruit-board">'+cards+'</div><p class="ap-compliance-note">Colaboradores internos enlaza con RRHH/Laboral; aliados y productos con Suministro/Mercantil; clientes y mercados con CRM/Ventas. El enlace es organizativo, sin automatizar decisiones ni conectar expedientes externos.</p>'},
  costView(){const ap=AP,esc=v=>ap.esc(v??''),country=this.country(),cur=country==='VE'?'VES':'COP',entries=ap.query('SELECT * FROM labor_cost_entries WHERE country=? ORDER BY period DESC,created_at DESC LIMIT 100',[country]),period=entries.length?entries[0].period:'',current=entries.filter(x=>x.period===period),operational=current.filter(x=>x.area==='Operativa'),support=current.filter(x=>x.area==='Soporte'),sum=a=>a.reduce((n,x)=>n+x.amount_cents,0),op=sum(operational),sup=sum(support),fmt=n=>new Intl.NumberFormat('es-ES',{minimumFractionDigits:2,maximumFractionDigits:2}).format(n/100)+' '+cur,groups=['Fabricación','Comercialización','Servicios'],rows=groups.map(name=>{const o=sum(operational.filter(x=>x.structure===name)),allocated=op?Math.round(sup*o/op):null;return [name,fmt(o),op?(o/op*100).toFixed(1)+' %':'Sin base',allocated===null?'Sin base operativa':fmt(allocated),'Solo MO operativa a coste; reparto de soporte solo analítico']});return this.jurisdictionPicker()+'<div class="ap-compliance-hero"><small>RRHH · LABORAL · ESTRUCTURA FINANCIERA</small><h2>Mano de obra por área</h2><p>Fabricación, Comercialización y Servicios. La MO operativa se presenta como coste; la MO de soporte administrativo como gasto no recuperable. Su reparto proporcional a la MO operativa sirve únicamente para análisis y proyección, nunca para capitalizar el gasto.</p></div><p class="ap-cost-note">Modelo de análisis definido por el usuario, no una regla contable universal ni una certificación ISO 9001. Valida el plan de cuentas y la política contable antes de registrar asientos o valorar inventario. No hay asientos automáticos.</p><form id="ap-cost-form" class="ap-cost-form"><label>Periodo (mes)<input name="period" type="month" required></label><label>Estructura<select name="structure"><option>Fabricación</option><option>Comercialización</option><option>Servicios</option></select></label><label>Área<select name="area"><option>Operativa</option><option>Soporte</option></select></label><label>MO del periodo ('+cur+')<input name="amount" type="number" min="0" step="0.01" required placeholder="Importe real o de escenario"></label><button type="submit">Guardar escenario local</button></form><p class="ap-compliance-note" id="ap-cost-feedback" role="status">Usa un periodo y datos propios. Cada entrada queda en SQLite local, separada por país.</p><div class="ap-cost-kpis">'+APViews.tiles([['Periodo analizado',period||'Sin datos'],['MO operativa · coste',fmt(op)],['MO soporte · gasto',fmt(sup)],['Soporte / MO operativa',op?(sup/op*100).toFixed(1)+' %':'Sin base operativa']])+'</div><h3>Proyección y reparto analítico'+(period?' · '+esc(period):'')+'</h3>'+APViews.table(['Estructura','MO operativa a coste','Peso en base operativa','Soporte imputado solo para análisis','Tratamiento'],rows)+'<p class="ap-compliance-note">Fórmula analítica: soporte total × (MO operativa de la estructura / MO operativa total). Si no hay MO operativa, no se reparte. El reparto no altera los importes de coste ni gasto guardados. Moneda '+cur+'; no mezcla países ni convierte divisas.</p><h3>Entradas locales</h3>'+APViews.table(['Periodo','Estructura','Área','Importe','Tratamiento'],entries.map(x=>[x.period,x.structure,x.area,fmt(x.amount_cents),x.area==='Operativa'?'Coste':'Gasto no recuperable']))},
  agentsView(){const ap=AP,esc=v=>ap.esc(v??''),agents=ap.query('SELECT * FROM legal_subagents ORDER BY CASE id WHEN \u0027mercantil\u0027 THEN 1 WHEN \u0027laboral\u0027 THEN 2 WHEN \u0027civil\u0027 THEN 3 WHEN \u0027tributario-nacional\u0027 THEN 4 WHEN \u0027tributario-regional\u0027 THEN 5 WHEN \u0027tributario-local\u0027 THEN 6 ELSE 7 END'),proposals=ap.query('SELECT id,sku FROM purchase_proposals ORDER BY rowid DESC LIMIT 20');return this.jurisdictionPicker()+'<div class="ap-compliance-hero"><small>ORQUESTACIÓN JURÍDICA · DISEÑO LOCAL</small><h2>Subagentes jurídicos</h2><p>Siete ámbitos de revisión y un enrutamiento propuesto por tipo de operación. La jerarquía de cada ámbito es un esquema, no un conjunto de normas vigentes: sin país, territorio, sector y reglas verificadas, estos subagentes no emiten dictámenes ni aprueban propuestas.</p></div><div class="ap-legal-flow"><b>Ruta de una propuesta</b><br>Tipo de operación → país y territorio → ámbitos competentes → fuentes y vigencia → revisión humana → decisión registrada. Hoy solo existe el estado local de cumplimiento general; esta ruta jurídica no ejecuta revisiones automáticas ni envía declaraciones.</div><h3>Ámbitos y cobertura</h3><div class="ap-legal-grid">'+agents.map(x=>'<article class="ap-legal-agent"><header><div><small>SUBAGENTE · '+esc(x.id)+'</small><h3>'+esc(x.name)+'</h3></div><span class="ap-legal-status">'+(x.status==='demo'&&this.country()==='CO'?'Demo de fuentes':'Por configurar')+'</span></header><p>'+(x.id==='tributario-nacional'?'Tributos nacionales: IVA, '+(this.country()==='VE'?'ISLR':'renta')+', parafiscales patronales y sectoriales, sujetos al régimen aplicable.':esc(x.subject))+'</p><p><b>Revisaría:</b> '+esc(x.routing)+'</p><p><b>Pirámide de referencia:</b></p><ul>'+x.hierarchy.split(' → ').map(t=>'<li>'+esc(t)+'</li>').join('')+'</ul><p class="ap-legal-scope">'+esc(x.configuration_note)+'</p></article>').join('')+'</div><h3>Propuestas locales · ruta sugerida</h3><p class="ap-compliance-note">Las propuestas de compra del ERP son candidatas a revisión mercantil. Un análisis tributario dependerá del país, el territorio, el tipo de operación y el régimen fiscal; no se infiere la aplicabilidad de IVA, ISLR ni tributos regionales/locales. Esto es clasificación visual, no revisión efectuada.</p>'+APViews.table(['Propuesta','SKU','Ámbito candidato','Estado jurídico'],proposals.map(x=>[x.id,x.sku,'Mercantil · tributario por determinar','Sin revisión de subagentes']))+'<p class="ap-compliance-note">Administrativo ayuda a ordenar posibles reclamaciones ante entidades públicas; una queja, petición, recurso o acción exige identificar país, entidad, hechos, acto, plazos y cauce competente. No genera ni presenta denuncias, no atribuye faltas a funcionarios y no sustituye asesoría jurídica.</p><p class="ap-compliance-note">Civil y Laboral se activarán para contratos o actos de personal cuando existan documentos y datos con ámbito definido. No se han creado subagentes ejecutores ni obligaciones fiscales. Ninguna propuesta es aprobada por esta vista.</p>'},
  payrollView(){const ap=AP,esc=v=>ap.esc(v??''),norms=ap.query("SELECT * FROM compliance_norms WHERE id LIKE 'CO-%' ORDER BY level,id"),rules=ap.query('SELECT * FROM payroll_rules ORDER BY id');return '<div class="ap-compliance-hero"><small>COLOMBIA · JURÍDICO-LABORAL · DEMO</small><h2>Nómina con trazabilidad normativa</h2><p>La cadena de fuentes recorre Constitución, código y leyes, decretos y providencias. Solo se listan normas verificadas en fuentes oficiales o institucionales. Una providencia posterior puede cambiar la regla aplicable: esta demo no emite nómina ni certifica cumplimiento.</p><div class="ap-pyramid">'+[['Constitución',55],['Leyes y Código Laboral',68],['Decretos salariales',80],['Providencias',92]].map((x,i)=>'<div class="ap-pyramid-level" style="--width:'+x[1]+'%"><b>'+x[0]+'</b><small>NIVEL '+(i+1)+'</small></div>').join('')+'</div></div><h3>Fuentes jurídicas enlazadas</h3><div class="ap-law-list">'+norms.map(x=>'<div class="ap-law-card"><small>NIVEL '+x.level+' · '+esc(x.id)+'</small><strong>'+esc(x.name)+'</strong><p>'+esc(x.scope)+'</p><a target="_blank" rel="noopener noreferrer" href="'+esc(x.source_url)+'">Consultar fuente ↗</a></div>').join('')+'</div><h3>Conceptos de nómina y reglas</h3>'+APViews.table(['Concepto','Regla / fuente','Valor orientativo','Estado'],rules.map(x=>[x.concept,x.norm_id+' · '+x.formula_note,x.value_text||'Por configurar',x.status==='requires_review'?'Revisión jurídica pendiente':'Sin parametrizar']))+'<h3>Simulador no liquidable</h3><p class="ap-compliance-note">Introduce salario base y días trabajados. Solo se prorratea el salario ordinario para visualizar la estructura; horas extra, recargos, prestaciones, aportes y auxilio se dejan pendientes. No uses este resultado para pagar, contratar ni declarar.</p><form id="ap-payroll-form" class="ap-payroll-form"><label>Salario mensual de ejemplo (COP)<input name="salary" type="number" min="0" step="1" placeholder="Salario de ejemplo" required></label><label>Días trabajados de ejemplo (0 a 30)<input name="days" type="number" min="0" max="30" step="1" value="30" required></label><button type="submit">Ver desglose ilustrativo</button></form><div id="ap-payroll-output" class="ap-payroll-output" role="status">Pendiente de datos de ejemplo. Ningún valor se guarda como nómina.</div><p class="ap-compliance-note">Importes de 2026 citados como referencia de los decretos indicados, no como vigencia definitiva: hubo medidas cautelares y deben comprobarse cambios posteriores. La jurisdicción, convenio, modalidad, periodo, jornada, IBC y topes deben validarse antes de habilitar un cálculo real.</p>'},
  view(){const ap=AP,esc=v=>ap.esc(v??''),layers=ap.query("SELECT * FROM compliance_norms WHERE id LIKE 'DEMO-%' ORDER BY level,id"),checks=ap.query('SELECT p.id,p.sku,q.status AS decision,c.status AS check_status,c.norm_id,c.reason FROM purchase_proposals p JOIN approval_queue q ON q.proposal_id=p.id LEFT JOIN compliance_checks c ON c.proposal_id=p.id ORDER BY p.rowid DESC LIMIT 30');return this.jurisdictionPicker()+'<div class="ap-compliance-hero"><small>CAPA DE CUMPLIMIENTO · DEMOSTRACIÓN</small><h2>Jerarquía normativa</h2><p>Modelo visual inspirado en la pirámide de Kelsen. Las normas de este entorno son ejemplos, no normas jurídicas verificadas. Sin jurisdicción, sector y fuentes vigentes, ninguna propuesta obtiene una certificación legal ni se autoaprueba por esta capa.</p><div class="ap-pyramid">'+this.levels.map((x,i)=>'<div class="ap-pyramid-level" style="--width:'+(50+i*12)+'%"><b>'+esc(x[1])+'</b><small>NIVEL '+x[2]+'</small></div>').join('')+'</div><p class="ap-compliance-note">Se comprueban primero los niveles superiores; una ausencia de fuentes o conflicto requiere revisión humana. Esta demo solo trabaja sobre propuestas locales y no ejecuta compras, pagos o cambios de stock.</p></div><h3>Normas registradas · ejemplos</h3>'+APViews.table(['Nivel','Identificador','Alcance','Fuente'],layers.map(x=>[x.level,x.id,x.scope,x.source_url||'No aportada · ejemplo']))+'<h3>Propuestas y revisión</h3>'+APViews.table(['Propuesta','SKU','Decisión local','Semáforo','Norma / motivo'],checks.map(x=>[x.id,x.sku,x.decision,x.check_status==='pass'?'🟢 Conforme':x.check_status==='block'?'🔴 Bloqueado':'🟠 Revisión humana', (x.norm_id||'SIN-REVISAR')+' · '+(x.reason||'Sin comprobación documentada')]))+'<p class="ap-compliance-note">No es asesoramiento jurídico. Antes de activar reglas reales, indique jurisdicción, actividad, fuentes oficiales aplicables y responsable legal para validarlas.</p>'}
};
const APFormat={
  // Model text stays inert: no HTML, URLs or browser actions are derived from it.
  inline(parent,text){const re=/(\*\*([^*\n]{1,400})\*\*|`([^`\n]{1,400})`)/g;let from=0,m;while((m=re.exec(text))){parent.append(document.createTextNode(text.slice(from,m.index)));const el=document.createElement(m[2]?'strong':'code');el.textContent=m[2]||m[3];parent.append(el);from=re.lastIndex}parent.append(document.createTextNode(text.slice(from)))},
  render(el,value){const text=String(value??'').slice(0,20000).replace(/\r\n?/g,'\n');let list=null,code=null;for(const line of text.split('\n')){if(/^\s*`{3}/.test(line)){if(code){el.append(code);code=null}else{list=null;code=document.createElement('pre')}continue}if(code){const span=document.createElement('code');span.textContent=line+'\n';code.append(span);continue}const bullet=line.match(/^\s*[-*]\s+(.+)$/);if(bullet){if(!list){list=document.createElement('ul');el.append(list)}const li=document.createElement('li');this.inline(li,bullet[1]);list.append(li);continue}list=null;if(!line.trim())continue;const p=document.createElement('p');this.inline(p,line.replace(/^#{1,4}\s+/,''));el.append(p)}if(code)el.append(code);if(!el.childNodes.length)el.textContent=text}
};
const AP = {
  model: 'MiMo-V2.6-Distill-Qwen-9B (local en este navegador)',
  models: null,
  db: null, busy: false, store: null, cycleBusy:false, cycleTimer:null, cycleIntervalMs:30000, lastModelCycleAt:0, mode: localStorage.getItem('adaptapro-mode')==='autonomo'?'autonomo':'supervisado', agentsOn: localStorage.getItem('adaptapro-agents')!=='off',
  money: n => 'USD '+new Intl.NumberFormat('en-US',{minimumFractionDigits:2,maximumFractionDigits:2}).format(n/100),
  esc: s => String(s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c])),
  rows(...a){return APData.rows(...a);},
  one(...a){return APData.one(...a);},
  query(...a){return APData.query(...a);},
  exec(...a){return APData.exec(...a);},
  storage(...a){return APData.storage(...a);},
  loadBytes(...a){return APData.loadBytes(...a);},
  persist(...a){return APData.persist(...a);},
  reset(...a){return APCommands.reset(...a);},
  tx(...a){return APData.tx(...a);},
  loadSeed(...a){return APData.loadSeed(...a);},
  migrationPlan(...a){return APData.migrationPlan(...a);},
  userVersion(...a){return APData.userVersion(...a);},
  applyMigrations(...a){return APData.applyMigrations(...a);},
  async init(){
    try{
      await new Promise((resolve,reject)=>{if(globalThis.__apCoreReady)return resolve();globalThis.addEventListener('ap-core-ready',resolve,{once:true});setTimeout(()=>reject(Error('Módulos del núcleo no cargados')),20000);});
      const SQL=await initSqlJs({locateFile:f=>'vendor/sql.js/1.13.0/'+f});
      this.store=await this.storage();const saved=await this.loadBytes();this.db=saved?new SQL.Database(saved):new SQL.Database();this.db.run('PRAGMA foreign_keys=ON');
      const seed=await this.loadSeed();
      await this.applyMigrations();
      if(!saved){this.tx(()=>{for(const [table,items] of Object.entries(seed)){if(table==='meta')continue;for(const item of items){const keys=Object.keys(item);this.db.run(`INSERT INTO ${table} (${keys.join(',')}) VALUES (${keys.map(()=>'?').join(',')})`,keys.map(k=>item[k]));}}});}
      else{this.tx(()=>{for(const table of ['workforce','production_jobs','planning_tasks'])for(const item of seed[table]||[]){const keys=Object.keys(item);this.db.run('INSERT OR IGNORE INTO '+table+' ('+keys.join(',')+') VALUES ('+keys.map(()=>'?').join(',')+')',keys.map(k=>item[k]));}});this.db.run("UPDATE purchase_proposals SET currency='USD' WHERE currency='EUR'");}
      await this.persist();APPacks.load().catch(e=>console.warn('Registro de packs no disponible: '+e.message));this.render();this.updateMode();this.updateAgents();this.note('Demo local ficticia (semilla de julio de 2030). Modo '+this.mode+'.');this.startCycle();
    }catch(e){this.note('No se pudieron cargar los datos: '+e.message,true);console.error(e);}
  },
  updateAgents(...a){return APCommands.updateAgents(...a);},
  toggleAgents(...a){return APCommands.toggleAgents(...a);},
  updateMode(...a){return APPolicy.updateMode(...a);},
  toggleMode(...a){return APPolicy.toggleMode(...a);},
  note(text,error=false){const e=document.getElementById('ap-state');if(e){e.textContent=text;e.style.color=error?'#fca5a5':'#94a3b8';}},
  render(){
    if(!this.db)return;
    const stock=this.rows('SELECT * FROM stock_status ORDER BY sku');
    const queue=this.rows(`SELECT q.*,p.sku,p.proposed_qty,p.unit_cost_cents,p.currency,p.rationale,p.supplier_id,p.agent_id,
       s.name AS supplier FROM approval_queue q JOIN purchase_proposals p ON p.id=q.proposal_id JOIN suppliers s ON s.id=p.supplier_id ORDER BY p.created_at DESC`);
    const pending=queue.filter(x=>x.status==='pendiente');
    const stockEl=document.getElementById('ap-stock');
    stockEl.innerHTML=stock.map(x=>`<div class="ap-line"><b>${this.esc(x.sku)}</b> ${this.esc(x.name)} · ${x.available} disponibles / ${x.on_hand} físicos ${x.needs_restock?'<span class="ap-warn">· Reposición necesaria</span>':''}</div>`).join('');
    document.getElementById('ap-queue').innerHTML=queue.map(x=>`<div class="ap-proposal"><b>${this.esc(x.proposal_id)} · ${this.esc(x.sku)}</b> · ${x.proposed_qty} unidades · ${this.money(x.proposed_qty*x.unit_cost_cents)}<br><small>${this.esc(x.supplier)} · ${this.esc(x.rationale)}</small><br><span class="ap-status">${this.esc(x.status)}</span> ${APCompliance.badge(this,x.proposal_id)} ${x.status==='pendiente'?`<button data-decision="aprobada" data-id="${this.esc(x.proposal_id)}" title="Revisión humana necesaria; no certifica cumplimiento legal">Revisar y decidir</button><button data-decision="rechazada" data-id="${this.esc(x.proposal_id)}">Rechazar</button>`:''} ${x.status==='aprobada'&&!this.one('SELECT id FROM stock_movements WHERE proposal_id=?',[x.proposal_id])?`<button data-receive="${this.esc(x.proposal_id)}">Registrar recepción</button>`:''}</div>`).join('')||'<p>No hay propuestas.</p>';
    document.getElementById('ap-pending').textContent=pending.length;
    document.getElementById('ap-pending-metric').textContent=pending.length;
    const total=this.one('SELECT coalesce(sum(quantity*unit_price_cents),0) AS n FROM sales_order_lines');
    document.getElementById('ap-order-value').textContent=this.money(total.n);
    const reservations=this.one('SELECT coalesce(sum(reserved),0) AS n FROM inventory');
    document.getElementById('ap-reservations').textContent=reservations.n;
    document.getElementById('ap-audit').innerHTML=this.rows('SELECT actor,action,entity_id,occurred_at FROM audit_log ORDER BY rowid DESC LIMIT 6').map(e=>`<div class="ap-line">${this.esc(e.actor)} · ${this.esc(e.action)} · ${this.esc(e.entity_id)}</div>`).join('');
    const feed=document.getElementById('ap-feed');feed.innerHTML=this.rows('SELECT actor,action,entity_id,occurred_at FROM audit_log ORDER BY rowid DESC LIMIT 7').map(e=>`<div class="ap-feed-item"><time>${this.esc(new Date(e.occurred_at).toLocaleTimeString('es-ES',{hour:'2-digit',minute:'2-digit'}))}</time><strong>${this.esc(e.actor)}</strong> · ${this.esc(e.action.replaceAll('_',' '))}<small>${this.esc(e.entity_id)}</small></div>`).join('');
    document.getElementById('ap-orders').innerHTML=this.rows('SELECT id,customer_name,region,status FROM sales_orders ORDER BY rowid DESC LIMIT 8').map(e=>`<div class="ap-line"><b>${this.esc(e.id)}</b> · ${this.esc(e.customer_name)} · ${this.esc(e.region)} · ${this.esc(e.status)}</div>`).join('');
    document.querySelectorAll('[data-decision]').forEach(b=>b.onclick=()=>this.command({cmd:'propuesta_decidir',payload:{id:b.dataset.id,status:b.dataset.decision}}).catch(e=>this.note(e.message,true)));
    document.querySelectorAll('[data-receive]').forEach(b=>b.onclick=()=>this.command({cmd:'recepcion_registrar',payload:{id:b.dataset.receive}}).catch(e=>this.note(e.message,true)));
    const low=stock.filter(x=>x.needs_restock).length;
    const metric=document.getElementById('ap-stock-metric');if(metric)metric.textContent=stock.length-low+'/'+stock.length;
  },
  decide(...a){return APCommands.decide(...a);},
  receive(...a){return APCommands.receive(...a);},
  command(...a){return APBus.command(...a);},
  confirmAction(...a){return APPolicy.confirmAction(...a);},
  decisionForm(...a){return APPolicy.decisionForm(...a);},
  audit(...a){return APPolicy.audit(...a);},
  context(...a){return APCommands.context(...a);},
  propose(...a){return APCommands.propose(...a);},
  modelCall(...a){return APCommands.modelCall(...a);},
  closeChat(){const e=document.getElementById('chatWindow');e.hidden=true;e.style.display='none';localStorage.setItem('adaptapro-chat-open','false');},
  tab(which){const e=document.getElementById('chatWindow');e.hidden=false;e.style.display='block';localStorage.setItem('adaptapro-chat-open','true');document.getElementById('ap-chat-panel').hidden=which!=='chat';document.getElementById('ap-supervision-panel').hidden=which!=='supervision';},
  append(text,who){const el=document.createElement('div');el.className='chat-msg '+who;if(who==='ai')APFormat.render(el,text);else el.textContent=String(text);const body=document.querySelector('.chat-body');body.append(el);body.scrollTop=body.scrollHeight;},
  appendStream(text){if(!text)return;const body=document.querySelector('.chat-body');if(!this._streamEl){const el=document.createElement('div');el.className='chat-msg ai';body.append(el);this._streamEl=el;}this._streamEl.textContent=text;body.scrollTop=body.scrollHeight;},
  appendFinal(text){const el=this._streamEl;this._streamEl=null;if(el){if(text&&String(text).trim())APFormat.render(el,text);else el.remove();}else if(text&&String(text).trim())this.append(text,'ai');},
  setAgentState(agent,label,working){const el=document.getElementById('ap-agent-'+agent);if(el){el.textContent=label;el.classList.toggle('ap-working',working);}},
  startCycle(...a){return APCommands.startCycle(...a);},
  cycle(...a){return APCommands.cycle(...a);},
  ask(...a){return APCommands.ask(...a);},
};
window.AP=AP;
const APMic={button:document.getElementById('ap-mic'),recognition:null,active:false,start(){const Speech=window.SpeechRecognition||window.webkitSpeechRecognition;if(!Speech){this.button.disabled=true;this.button.title='Dictado no disponible en este navegador. Prueba Chrome.';this.button.setAttribute('aria-label',this.button.title);document.getElementById('chatInput').placeholder='Dictado no disponible aquí; escribe o prueba Chrome';return}if(this.active){this.recognition.stop();return}const input=document.getElementById('chatInput'),recognition=new Speech();this.recognition=recognition;recognition.lang='es-ES';recognition.continuous=false;recognition.interimResults=true;const prefix=input.value.trim();recognition.onstart=()=>{this.active=true;this.button.classList.add('is-listening');this.button.textContent='⏹';this.button.title='Detener dictado';this.button.setAttribute('aria-label','Detener dictado');this.button.setAttribute('aria-pressed','true')};recognition.onresult=e=>{let words='';for(let i=0;i<e.results.length;i++)words+=e.results[i][0].transcript;input.value=(prefix?prefix+' ':'')+words;input.focus()};recognition.onerror=e=>{if(e.error==='not-allowed'||e.error==='service-not-allowed')input.placeholder='Permite el micrófono en el navegador para dictar';else if(e.error!=='no-speech'&&e.error!=='aborted')input.placeholder='No se pudo dictar; puedes escribir el mensaje'};recognition.onend=()=>{this.active=false;this.button.classList.remove('is-listening');this.button.textContent='🎙️';this.button.title='Dictar mensaje';this.button.setAttribute('aria-label','Dictar mensaje');this.button.setAttribute('aria-pressed','false')};try{recognition.start()}catch(e){recognition.onend();input.placeholder='No se pudo iniciar el dictado; escribe el mensaje'}}};document.getElementById('ap-mic').addEventListener('click',()=>APMic.start());
const apWebBtn=document.getElementById('ap-websearch');function updateWebBtn(){const on=localStorage.getItem('adaptapro-web-search')==='true';apWebBtn.setAttribute('aria-pressed',String(on));apWebBtn.classList.toggle('is-listening',on);apWebBtn.style.opacity=on?'1':'0.5';apWebBtn.title=on?'Búsqueda web ACTIVADA: el texto que escribas se envía también a Tavily y Wikipedia (gratuito, con límites); no se añade automáticamente inventario ni auditoría. No incluyas información confidencial. Pulsa para desactivar.':'Búsqueda web desactivada. Si la activas, el texto que escribas se envía también a Tavily y Wikipedia para buscar contexto; no se añade automáticamente inventario ni auditoría. No incluyas información confidencial.';}
const apModelBtn=document.getElementById('ap-model-load'),apModelState=document.getElementById('ap-model-state'),apModelProg=document.getElementById('ap-model-progress'),apModelBar=apModelProg.querySelector('div'),apModelStop=document.getElementById('ap-model-stop');
apModelStop.addEventListener('click',()=>{if(globalThis.APLocalModel)APLocalModel.stop();});
setInterval(()=>{if(globalThis.APLocalModel){const gen=APLocalModel.state==='generating';apModelStop.hidden=!gen;if(gen)apModelUI();else if(apModelState.textContent==='Generando…')apModelUI();}},500);
function apModelUI(){if(!globalThis.APLocalModel){apModelState.textContent='Cargando módulo del modelo…';apModelBtn.disabled=true;return;}const st=APLocalModel.state;apModelBtn.disabled=st==='downloading';apModelBtn.hidden=st==='ready';if(st==='generating'){apModelState.textContent='Generando…';apModelProg.hidden=true;}else if(st==='ready'){apModelState.textContent='MiMo 9B descargado en este navegador (WASM/CPU). Aviso: en las pruebas actuales la generación falla con el runtime probado (en investigación); si te ocurre, el chat mostrará el error sin cambiar de modelo.';apModelProg.hidden=true;}else if(st==='downloading'){apModelProg.hidden=false;}else{apModelProg.hidden=true;apModelState.textContent=st==='error'?'Error al cargar: '+APLocalModel.error+'. Pulsa el botón para reintentar.':'Modelo local (WASM/CPU, sin aceleración garantizada). Descarga inicial aprox. 5,8 GB; se reutiliza mientras se conserve la caché de este navegador. Necesita memoria libre suficiente: en equipos justos puede ir lento o no cargar. Aviso: en las pruebas actuales este modelo se descarga pero falla al generar con el runtime de navegador probado; estamos investigándolo.';}}
apModelBtn.addEventListener('click',async()=>{apModelBtn.disabled=true;apModelProg.hidden=false;apModelState.textContent='Preparando descarga…';try{await APLocalModel.load((loaded,total)=>{const pct=Math.min(100,Math.round(loaded/total*100));apModelBar.style.width=pct+'%';apModelState.textContent='Descargando MiMo 9B… '+pct+'% ('+Math.round(loaded/1048576)+' MB de '+Math.round(total/1048576)+' MB)';});}catch(e){}apModelUI();});
if(globalThis.APLocalModel)apModelUI();else addEventListener('ap-core-ready',apModelUI,{once:true});
apWebBtn.addEventListener('click',()=>{const on=localStorage.getItem('adaptapro-web-search')!=='true';localStorage.setItem('adaptapro-web-search',String(on));updateWebBtn();AP.append(on?'🔎 Búsqueda web ACTIVADA. A partir de ahora, el texto que escribas se enviará también a Tavily y Wikipedia para buscar contexto (servicios externos, uso gratuito con límites). Las fuentes se citan tras cada respuesta. Se envía el texto que escribas; no se añade automáticamente inventario ni auditoría. No incluyas información confidencial.':'🔎 Búsqueda web desactivada. Tus mensajes ya no se envían a servicios de búsqueda.','ai');});updateWebBtn();
function sendMessage(){const input=document.getElementById('chatInput');const text=input.value.trim();if(!text)return;input.value='';AP.ask(text);}
document.getElementById('chatInput').addEventListener('keydown',e=>{if(e.key==='Enter')sendMessage();});
document.getElementById('ap-analyze').addEventListener('click',()=>AP.ask('Revisa el stock disponible y los pedidos. Si hay riesgo de rotura, crea una propuesta de reposición pendiente de supervisión.'));
document.getElementById('ap-reset').addEventListener('click',()=>AP.reset());
document.getElementById('ap-mode').addEventListener('click',()=>AP.toggleMode());
document.getElementById('ap-agents').addEventListener('click',()=>AP.toggleAgents());
const apChat=document.getElementById('chatWindow');if(localStorage.getItem('adaptapro-chat-open')==='true'){apChat.hidden=false;apChat.style.display='block'}try{const saved=JSON.parse(localStorage.getItem('adaptapro-chat-size')||'null');if(saved?.width&&saved?.height){apChat.style.width=Math.min(saved.width,innerWidth-20)+'px';apChat.style.height=Math.min(saved.height,innerHeight-20)+'px';}}catch(e){}
new ResizeObserver(()=>{localStorage.setItem('adaptapro-chat-size',JSON.stringify({width:apChat.offsetWidth,height:apChat.offsetHeight}));}).observe(apChat);
document.getElementById('ap-tab-chat').addEventListener('click',()=>AP.tab('chat'));
document.getElementById('ap-tab-supervision').addEventListener('click',()=>AP.tab('supervision'));
document.querySelector('.ap-human').addEventListener('click',()=>AP.tab('supervision'));

const APMenu={button:document.getElementById('ap-menu-toggle'),sidebar:document.getElementById('ap-sidebar'),backdrop:document.getElementById('ap-menu-backdrop'),close(){this.sidebar.classList.remove('is-open');this.backdrop.hidden=true;this.button.setAttribute('aria-expanded','false');this.button.setAttribute('aria-label','Abrir menú de secciones');if(this.button.dataset.wasOpen==='true')this.button.focus();delete this.button.dataset.wasOpen},open(){this.button.dataset.wasOpen='true';this.sidebar.classList.add('is-open');this.backdrop.hidden=false;this.button.setAttribute('aria-expanded','true');this.button.setAttribute('aria-label','Cerrar menú de secciones');document.getElementById('ap-menu-close').focus()}};APMenu.button.onclick=()=>APMenu.sidebar.classList.contains('is-open')?APMenu.close():APMenu.open();document.getElementById('ap-menu-close').onclick=()=>APMenu.close();APMenu.backdrop.onclick=()=>APMenu.close();document.addEventListener('keydown',e=>{if(e.key==='Escape')APMenu.close()});window.addEventListener('resize',()=>{if(innerWidth>760)APMenu.close()});
document.querySelectorAll('[data-view]').forEach(b=>b.addEventListener('click',()=>APViews.show(b.dataset.view)));
const APAgentCenter={selected:null,
  show(agent){if(!['ALPHA','BETA','GAMMA'].includes(agent)||!AP.db)return;this.selected=agent;document.querySelectorAll('[data-agent]').forEach(b=>{const on=b.dataset.agent===agent;b.classList.toggle('is-selected',on);b.setAttribute('aria-pressed',String(on))});document.getElementById('ap-agent-center').hidden=false;document.querySelector('.alerts-card').hidden=true;document.querySelector('.charts-row').hidden=true;this.render();document.getElementById('ap-agent-center').scrollIntoView({block:'nearest',behavior:'smooth'})},
  back(){this.selected=null;document.querySelectorAll('[data-agent]').forEach(b=>{b.classList.remove('is-selected');b.setAttribute('aria-pressed','false')});document.getElementById('ap-agent-center').hidden=true;document.querySelector('.alerts-card').hidden=false;document.querySelector('.charts-row').hidden=false},
  render(){if(!this.selected||!AP.db)return;const a=this.selected,esc=v=>AP.esc(v??''),events=AP.query('SELECT occurred_at,action,entity_id,details_json FROM audit_log WHERE actor=? ORDER BY rowid DESC LIMIT 20',[a]),total=AP.one('SELECT count(*) AS n FROM audit_log WHERE actor=?',[a]).n,config={ALPHA:{icon:'A',badge:'a',role:'Inventario y propuestas',story:'Analiza el stock, detecta alertas y registra propuestas locales. Aprobar una propuesta no compra ni recibe mercancía.'},BETA:{icon:'B',badge:'b',role:'Ventas y demanda',story:'Registra pedidos del motor local y señala señales de demanda. Los pedidos aquí no prueban cobros ni entregas.'},GAMMA:{icon:'G',badge:'g',role:'Logística y proveedores',story:'Compara proveedores activos, costes y plazos antes de asociarlos a una propuesta local. No gestiona envíos reales.'}}[a],summary=a==='ALPHA'?[["SKU con alerta",AP.one('SELECT count(*) AS n FROM stock_status WHERE needs_restock=1').n],["Propuestas creadas",AP.one("SELECT count(*) AS n FROM purchase_proposals WHERE agent_id='ALPHA'").n],["Eventos registrados",total]]:a==='BETA'?[["Pedidos locales",AP.one('SELECT count(*) AS n FROM sales_orders').n],["Pendientes",AP.one("SELECT count(*) AS n FROM sales_orders WHERE status='pendiente'").n],["Eventos registrados",total]]:[["Proveedores activos",AP.one('SELECT count(*) AS n FROM suppliers WHERE active=1').n],["Selecciones registradas",AP.one("SELECT count(*) AS n FROM audit_log WHERE actor='GAMMA' AND action='proveedor_seleccionado'").n],["Eventos registrados",total]];
    let related='';if(a==='ALPHA'){const rows=AP.query("SELECT p.id,p.sku,p.proposed_qty,a.status FROM purchase_proposals p JOIN approval_queue a ON a.proposal_id=p.id WHERE p.agent_id='ALPHA' ORDER BY p.rowid DESC LIMIT 8");related='<h3>PROPUESTAS LOCALES</h3>'+(rows.length?APViews.table(['Propuesta','SKU','Unidades','Estado'],rows.map(x=>[x.id,x.sku,x.proposed_qty,x.status])):'<p class="ap-agent-empty">Todavía no hay propuestas de ALPHA.</p>')}else if(a==='BETA'){const rows=AP.query('SELECT id,customer_name,status,placed_at FROM sales_orders ORDER BY rowid DESC LIMIT 8');related='<h3>PEDIDOS EN LA BASE LOCAL</h3>'+APViews.table(['Pedido','Cliente','Estado','Fecha'],rows.map(x=>[x.id,x.customer_name,x.status,x.placed_at.slice(0,10)]))}else{const rows=AP.query('SELECT s.name,sp.sku,s.lead_days FROM supplier_products sp JOIN suppliers s ON s.id=sp.supplier_id WHERE s.active=1 ORDER BY s.lead_days LIMIT 8');related='<h3>PROVEEDORES ACTIVOS</h3>'+APViews.table(['Proveedor','SKU','Plazo'],rows.map(x=>[x.name,x.sku,x.lead_days+' días']))}
    const timeline=events.length?events.map(x=>'<div class="ap-agent-event"><strong>'+esc(x.action.replaceAll('_',' '))+'</strong><small>'+esc(x.entity_id)+' · '+esc(x.occurred_at.slice(0,19).replace('T',' '))+'</small></div>').join(''):'<p class="ap-agent-empty">Aún no hay eventos de '+a+' en la auditoría. La vista se actualizará cuando se registre actividad.</p>';
    const box=document.getElementById('ap-agent-center');box.innerHTML='<div class="ap-agent-hero"><div class="agent-badge '+config.badge+'">'+config.icon+'</div><div><h2>'+a+'</h2><p>'+config.role+' · SQLite local</p></div><button class="ap-agent-back" type="button">← Volver al panel</button></div><p class="ap-agent-story">'+config.story+'</p>'+APViews.tiles(summary)+related+'<h3>HISTORIAL DE ACTIVIDAD · '+total+' EVENTOS</h3><div class="ap-agent-timeline">'+timeline+'</div>';box.querySelector('.ap-agent-back').onclick=()=>this.back();}
};document.querySelectorAll('[data-agent]').forEach(b=>b.addEventListener('click',()=>APAgentCenter.show(b.dataset.agent)));

function applyTheme(){const light=localStorage.getItem('adaptapro-theme')==='light';document.body.dataset.theme=light?'light':'dark';document.getElementById('ap-theme').textContent=light?'🌙':'☀️';document.getElementById('ap-theme').title=light?'Activar modo oscuro':'Activar modo claro';const color=light?'#536781':'#94a3b8';for(const chart of Object.values(typeof Chart!=='undefined'?Chart.instances:{})){for(const axis of Object.values(chart.options.scales||{})){axis.ticks.color=color;axis.grid.color=light?'#dde7f2':'rgba(80, 140, 255, 0.08)';}chart.update('none');}}
document.getElementById('ap-theme').addEventListener('click',()=>{localStorage.setItem('adaptapro-theme',document.body.dataset.theme==='light'?'dark':'light');applyTheme()});applyTheme();
const APFullscreen={button:document.getElementById('ap-fullscreen'),update(){const active=!!document.fullscreenElement;this.button.textContent=active?'⤡':'⛶';this.button.setAttribute('aria-pressed',String(active));this.button.setAttribute('aria-label',active?'Salir de pantalla completa':'Entrar en pantalla completa');this.button.title=active?'Salir de pantalla completa':'Entrar en pantalla completa'},async toggle(){try{if(document.fullscreenElement)await document.exitFullscreen();else await document.documentElement.requestFullscreen()}catch(e){this.button.title='Pantalla completa no disponible en este navegador'}this.update()}};APFullscreen.button.addEventListener('click',()=>APFullscreen.toggle());document.addEventListener('fullscreenchange',()=>APFullscreen.update());APFullscreen.update();
function updateTicker(){const shown=localStorage.getItem('adaptapro-ticker')!=='false';document.getElementById('ap-ticker').hidden=!shown;const b=document.getElementById('ap-ticker-toggle');b.title=shown?'Ocultar mercados':'Mostrar mercados';b.setAttribute('aria-label',b.title);b.setAttribute('aria-pressed',String(shown))};document.getElementById('ap-ticker-toggle').addEventListener('click',()=>{localStorage.setItem('adaptapro-ticker',String(document.getElementById('ap-ticker').hidden));updateTicker()});updateTicker();setInterval(()=>{const clock=document.getElementById('ap-broadcast-clock');if(clock)clock.textContent=new Date().toLocaleTimeString('es-ES',{hour:'2-digit',minute:'2-digit',second:'2-digit'})},1000);
const APHeadlines={update(){if(!AP.db)return;const notices=APNotices.items(),last=AP.one('SELECT actor,action,entity_id FROM audit_log ORDER BY rowid DESC LIMIT 1'),arr=[];for(const n of notices.slice(0,3))arr.push(n.agent+' · '+n.title+' · '+n.detail);if(last)arr.push(last.actor+' · '+last.action.replaceAll('_',' ')+' · '+last.entity_id);document.getElementById('ap-headlines-text').textContent=arr.join('     ◆     ')||'Operaciones en curso · sin alertas activas';}};
const APTV={active:false,index:0,lastRotate:0,
  update(){if(!this.active||!AP.db)return;const titles=['El negocio, en movimiento','Ventas conectadas al inventario','La cadena de suministro responde','Decisiones con supervisión humana'];const subs=['Tres agentes colaboran sobre la misma base local','BETA registra pedidos; ALPHA vigila los umbrales','GAMMA compara proveedores y plazos','Autónomo propone; cumplimiento exige revisión humana'];const n=this.index%titles.length;document.getElementById('ap-tv-title').textContent=titles[n];document.getElementById('ap-tv-subtitle').textContent=subs[n];const count=AP.one('SELECT count(*) AS n FROM sales_orders').n,alerts=AP.one('SELECT count(*) AS n FROM stock_status WHERE needs_restock=1').n,pending=AP.one("SELECT count(*) AS n FROM approval_queue WHERE status='pendiente'").n;document.getElementById('ap-tv-cards').innerHTML=[['Pedidos',count],['SKU en alerta',alerts],['Decisiones pendientes',pending]].map(([k,v])=>'<div><small>'+k+'</small><strong>'+v+'</strong></div>').join('');const e=AP.one('SELECT actor,action,entity_id FROM audit_log ORDER BY rowid DESC LIMIT 1');document.getElementById('ap-tv-story').textContent=e?e.actor+' · '+e.action.replaceAll('_',' ')+' · '+e.entity_id:'Esperando actividad de agentes';document.getElementById('ap-tv-clock').textContent=new Date().toLocaleTimeString('es-ES',{hour:'2-digit',minute:'2-digit',second:'2-digit'});},
  async toggle(force){this.active=force??!this.active;const el=document.getElementById('ap-tv');el.hidden=!this.active;document.getElementById('ap-tv-toggle').setAttribute('aria-pressed',String(this.active));if(this.active){this.index=0;this.update();try{await document.documentElement.requestFullscreen()}catch(e){}}else if(document.fullscreenElement){try{await document.exitFullscreen()}catch(e){}}},
  tick(){if(!this.active)return;this.update();if(Date.now()-this.lastRotate>12000){this.index++;this.lastRotate=Date.now();this.update()}}
};document.getElementById('ap-tv-toggle').onclick=()=>APTV.toggle();document.getElementById('ap-tv-close').onclick=()=>APTV.toggle(false);document.addEventListener('keydown',e=>{if(e.key==='Escape'&&APTV.active)APTV.toggle(false)});document.addEventListener('fullscreenchange',()=>{if(!document.fullscreenElement&&APTV.active)APTV.toggle(false)});setInterval(()=>APTV.tick(),1000);
const APNotices={
  read(){try{return new Set(JSON.parse(localStorage.getItem('adaptapro-notices-read')||'[]'))}catch{return new Set()}},
  items(){if(!AP.db)return [];const rows=AP.rows.bind(AP),items=[];
    for(const x of rows("SELECT p.id,p.sku FROM purchase_proposals p JOIN approval_queue a ON a.proposal_id=p.id WHERE a.status='pendiente'"))items.push({id:'pending:'+x.id,agent:'ALPHA',title:'Decisión pendiente',detail:x.id+' · '+x.sku,view:2});
    for(const x of rows("SELECT p.id,p.sku FROM purchase_proposals p JOIN approval_queue a ON a.proposal_id=p.id WHERE a.status='aprobada' AND a.decided_by='modo_automatico'"))items.push({id:'auto:'+x.id,agent:'ALPHA',title:'Propuesta aprobada en Autónomo',detail:x.id+' · '+x.sku+' · revisar en Suministro. La aprobación local no compra ni recibe stock.',view:2});
    for(const x of rows('SELECT sku,available,reorder_point FROM stock_status WHERE needs_restock=1'))items.push({id:'stock:'+x.sku,agent:'ALPHA',title:'Stock bajo',detail:x.sku+' · '+x.available+' disponibles, umbral '+x.reorder_point,view:4});
    for(const x of rows("SELECT o.id,l.sku FROM sales_orders o JOIN sales_order_lines l ON l.order_id=o.id JOIN stock_status s ON s.sku=l.sku WHERE o.status='pendiente' AND s.needs_restock=1 ORDER BY o.placed_at DESC LIMIT 3"))items.push({id:'risk:'+x.id+':'+x.sku,agent:'BETA',title:'Pedido con riesgo de stock',detail:x.id+' · '+x.sku+' bajo umbral. No se dispone de fecha de entrega.',view:5});
    const recent=rows("SELECT count(*) AS n FROM audit_log WHERE action='pedido_generado'")[0]?.n||0;if(recent>=4)items.push({id:'demand:'+Math.floor(recent/4),agent:'BETA',title:'Actividad de demanda',detail:recent+' pedidos añadidos por el motor local; revisar tendencia.',view:5});
    return items;
  },
  render(){const items=this.items(),read=this.read(),unread=items.filter(x=>!read.has(x.id));const count=document.getElementById('ap-bell-count');count.hidden=!unread.length;count.textContent=unread.length>9?'9+':unread.length;const box=document.getElementById('ap-notices');box.innerHTML='<h3>Avisos · '+unread.length+' sin leer</h3>'+(!items.length?'<p class="ap-view-lead">Sin avisos activos.</p>':items.map(x=>'<div class="ap-notice"><em>'+AP.esc(x.agent)+'</em> · '+AP.esc(x.title)+(read.has(x.id)?' ✓':'')+'<small>'+AP.esc(x.detail)+'</small><button data-notice-view="'+x.view+'" data-notice-id="'+AP.esc(x.id)+'">Ver y marcar leído</button></div>').join(''));
    box.querySelectorAll('[data-notice-id]').forEach(b=>b.onclick=()=>{const set=this.read();set.add(b.dataset.noticeId);localStorage.setItem('adaptapro-notices-read',JSON.stringify([...set]));APViews.show(b.dataset.noticeView);box.hidden=true;this.render()});
  }
};
document.getElementById('ap-bell').onclick=()=>{const b=document.getElementById('ap-notices');b.hidden=!b.hidden;document.getElementById('ap-bell').setAttribute('aria-expanded',!b.hidden);APNotices.render()};
const APSpotlight={timer:null,lastKey:'',lastShown:0,
  update(){if(document.hidden||!AP.db)return;const candidates=APNotices.items().filter(x=>x.id!==this.lastKey&&['auto:','stock:','risk:'].some(k=>x.id.startsWith(k)));if(!candidates.length||Date.now()-this.lastShown<180000)return;const x=candidates[0];this.lastKey=x.id;this.lastShown=Date.now();const b=document.getElementById('ap-spotlight');document.getElementById('ap-spotlight-agent').textContent=x.agent+' · FIVETECH';document.getElementById('ap-spotlight-title').textContent=x.title;document.getElementById('ap-spotlight-detail').textContent=x.detail;b.hidden=false;b.onclick=()=>{APViews.show(x.view);b.hidden=true;clearTimeout(this.timer)};clearTimeout(this.timer);APSound.play('chime');this.timer=setTimeout(()=>{b.hidden=true},8500);
  }
};
const APSound={context:null,armed:false,muted:localStorage.getItem('adaptapro-muted')==='true',
  play(kind){if(this.muted||!this.armed||document.hidden)return;try{const C=window.AudioContext||window.webkitAudioContext;if(!C)return;this.context||=new C();if(this.context.state!=='running')return;const now=this.context.currentTime,notes=kind==='approval'?[420,610]:kind==='autonomous'?[550,820,1050]:[660,880];notes.forEach((freq,i)=>{const osc=this.context.createOscillator(),gain=this.context.createGain(),start=now+i*.11;osc.type='sine';osc.frequency.setValueAtTime(freq,start);gain.gain.setValueAtTime(.0001,start);gain.gain.exponentialRampToValueAtTime(.035,start+.02);gain.gain.exponentialRampToValueAtTime(.0001,start+.32);osc.connect(gain).connect(this.context.destination);osc.start(start);osc.stop(start+.34)})}catch(e){}},
  update(){const b=document.getElementById('ap-sound');b.textContent=this.muted?'🔇':'🔊';b.title=this.muted?'Activar sonidos':'Silenciar sonidos';b.setAttribute('aria-label',b.title)}
};
APSound.update();document.addEventListener('pointerdown',()=>{APSound.armed=true;try{const C=window.AudioContext||window.webkitAudioContext;if(C){APSound.context||=new C();APSound.context.resume().catch(()=>{})}}catch(e){}},{once:true});document.getElementById('ap-sound').onclick=()=>{APSound.muted=!APSound.muted;localStorage.setItem('adaptapro-muted',APSound.muted);APSound.update()};
const APFocus={last:0,seen:new Set(),show(){if(!AP.db||document.hidden||Date.now()-this.last<180000||matchMedia('(prefers-reduced-motion: reduce)').matches)return;const item=APNotices.items().find(x=>!this.seen.has(x.id)&&['pending:','stock:','auto:'].some(k=>x.id.startsWith(k)));if(!item)return;this.seen.add(item.id);this.last=Date.now();const target=item.id.startsWith('pending:')?document.getElementById('ap-mode'):item.id.startsWith('stock:')?document.getElementById('ap-stock-metric'):document.getElementById('ap-bell');if(!target)return;const r=target.getBoundingClientRect(),f=document.getElementById('ap-focus');f.style.setProperty('--fx',r.x+r.width/2+'px');f.style.setProperty('--fy',r.y+r.height/2+'px');f.hidden=false;setTimeout(()=>f.hidden=true,2750)}};
setInterval(()=>APFocus.show(),30000);
setInterval(()=>APSpotlight.update(),20000);
const oldRender=AP.render.bind(AP);AP.render=function(){oldRender();APNotices.render();APHeadlines.update();if(APViews.current)APViews.show(APViews.current);if(APAgentCenter.selected)APAgentCenter.render()};

AP.init();
window.onYouTubeIframeAPIReady=function(){try{new YT.Player('ap-news-player',{events:{onError:()=>{document.getElementById('ap-video-error').hidden=false}}})}catch(e){/* The direct stream link remains available. */}};

</script>
<script async src="https://www.youtube.com/iframe_api"></script>
<script async defer src="https://accounts.google.com/gsi/client"></script>
<script type="module" src="./core/index.mjs"></script>
  <script type="module" src="./instinct-ui.mjs"></script>
</body>
</html>