Spaces:
Running
Running
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=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[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>
|