ghostykit 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -35,7 +35,7 @@ import {
35
35
  createPostStreamTransport,
36
36
  createSseTransport,
37
37
  readSse
38
- } from "../chunks/chunk-D6JXJWYM.js";
38
+ } from "../chunks/chunk-XZHX2NZT.js";
39
39
  import {
40
40
  applyReferences,
41
41
  cleanUserText,
@@ -43,6 +43,9 @@ import {
43
43
  systemNoteOf
44
44
  } from "../chunks/chunk-6U545WJG.js";
45
45
 
46
+ // src/react/Piloto.tsx
47
+ import { AnimatePresence as AnimatePresence3 } from "motion/react";
48
+
46
49
  // ../../node_modules/lucide-react/dist/esm/createLucideIcon.mjs
47
50
  import { forwardRef as forwardRef2, createElement as createElement3 } from "react";
48
51
 
@@ -262,8 +265,25 @@ function createLucideIcon(iconDataOrName, iconNode = [], aliases = []) {
262
265
  return Component;
263
266
  }
264
267
 
265
- // ../../node_modules/lucide-react/dist/esm/icons/app-window.mjs
268
+ // ../../node_modules/lucide-react/dist/esm/icons/activity.mjs
266
269
  var __iconData = {
270
+ name: "activity",
271
+ size: 24,
272
+ node: [
273
+ [
274
+ "path",
275
+ {
276
+ d: "M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2",
277
+ key: "169zse"
278
+ }
279
+ ]
280
+ ]
281
+ };
282
+ __iconData.node;
283
+ var Activity = createLucideIcon(__iconData);
284
+
285
+ // ../../node_modules/lucide-react/dist/esm/icons/app-window.mjs
286
+ var __iconData2 = {
267
287
  name: "app-window",
268
288
  size: 24,
269
289
  node: [
@@ -273,11 +293,11 @@ var __iconData = {
273
293
  ["path", { d: "M6 4v4", key: "1svtjw" }]
274
294
  ]
275
295
  };
276
- __iconData.node;
277
- var AppWindow = createLucideIcon(__iconData);
296
+ __iconData2.node;
297
+ var AppWindow = createLucideIcon(__iconData2);
278
298
 
279
299
  // ../../node_modules/lucide-react/dist/esm/icons/arrow-down.mjs
280
- var __iconData2 = {
300
+ var __iconData3 = {
281
301
  name: "arrow-down",
282
302
  size: 24,
283
303
  node: [
@@ -285,11 +305,11 @@ var __iconData2 = {
285
305
  ["path", { d: "m19 12-7 7-7-7", key: "1idqje" }]
286
306
  ]
287
307
  };
288
- __iconData2.node;
289
- var ArrowDown = createLucideIcon(__iconData2);
308
+ __iconData3.node;
309
+ var ArrowDown = createLucideIcon(__iconData3);
290
310
 
291
311
  // ../../node_modules/lucide-react/dist/esm/icons/arrow-up-right.mjs
292
- var __iconData3 = {
312
+ var __iconData4 = {
293
313
  name: "arrow-up-right",
294
314
  size: 24,
295
315
  node: [
@@ -297,11 +317,11 @@ var __iconData3 = {
297
317
  ["path", { d: "M7 17 17 7", key: "1vkiza" }]
298
318
  ]
299
319
  };
300
- __iconData3.node;
301
- var ArrowUpRight = createLucideIcon(__iconData3);
320
+ __iconData4.node;
321
+ var ArrowUpRight = createLucideIcon(__iconData4);
302
322
 
303
323
  // ../../node_modules/lucide-react/dist/esm/icons/arrow-up.mjs
304
- var __iconData4 = {
324
+ var __iconData5 = {
305
325
  name: "arrow-up",
306
326
  size: 24,
307
327
  node: [
@@ -309,20 +329,8 @@ var __iconData4 = {
309
329
  ["path", { d: "M12 19V5", key: "x0mq9r" }]
310
330
  ]
311
331
  };
312
- __iconData4.node;
313
- var ArrowUp = createLucideIcon(__iconData4);
314
-
315
- // ../../node_modules/lucide-react/dist/esm/icons/at-sign.mjs
316
- var __iconData5 = {
317
- name: "at-sign",
318
- size: 24,
319
- node: [
320
- ["circle", { cx: "12", cy: "12", r: "4", key: "4exip2" }],
321
- ["path", { d: "M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-4 8", key: "7n84p3" }]
322
- ]
323
- };
324
332
  __iconData5.node;
325
- var AtSign = createLucideIcon(__iconData5);
333
+ var ArrowUp = createLucideIcon(__iconData5);
326
334
 
327
335
  // ../../node_modules/lucide-react/dist/esm/icons/book-open.mjs
328
336
  var __iconData6 = {
@@ -470,8 +478,23 @@ var __iconData16 = {
470
478
  __iconData16.node;
471
479
  var Cpu = createLucideIcon(__iconData16);
472
480
 
473
- // ../../node_modules/lucide-react/dist/esm/icons/external-link.mjs
481
+ // ../../node_modules/lucide-react/dist/esm/icons/crosshair.mjs
474
482
  var __iconData17 = {
483
+ name: "crosshair",
484
+ size: 24,
485
+ node: [
486
+ ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
487
+ ["line", { x1: "22", x2: "18", y1: "12", y2: "12", key: "l9bcsi" }],
488
+ ["line", { x1: "6", x2: "2", y1: "12", y2: "12", key: "13hhkx" }],
489
+ ["line", { x1: "12", x2: "12", y1: "6", y2: "2", key: "10w3f3" }],
490
+ ["line", { x1: "12", x2: "12", y1: "22", y2: "18", key: "15g9kq" }]
491
+ ]
492
+ };
493
+ __iconData17.node;
494
+ var Crosshair = createLucideIcon(__iconData17);
495
+
496
+ // ../../node_modules/lucide-react/dist/esm/icons/external-link.mjs
497
+ var __iconData18 = {
475
498
  name: "external-link",
476
499
  size: 24,
477
500
  node: [
@@ -480,11 +503,11 @@ var __iconData17 = {
480
503
  ["path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6", key: "a6xqqp" }]
481
504
  ]
482
505
  };
483
- __iconData17.node;
484
- var ExternalLink = createLucideIcon(__iconData17);
506
+ __iconData18.node;
507
+ var ExternalLink = createLucideIcon(__iconData18);
485
508
 
486
509
  // ../../node_modules/lucide-react/dist/esm/icons/file-pen-line.mjs
487
- var __iconData18 = {
510
+ var __iconData19 = {
488
511
  name: "file-pen-line",
489
512
  size: 24,
490
513
  node: [
@@ -507,11 +530,11 @@ var __iconData18 = {
507
530
  ],
508
531
  aliases: ["file-signature"]
509
532
  };
510
- __iconData18.node;
511
- var FilePenLine = createLucideIcon(__iconData18);
533
+ __iconData19.node;
534
+ var FilePenLine = createLucideIcon(__iconData19);
512
535
 
513
536
  // ../../node_modules/lucide-react/dist/esm/icons/file-spreadsheet.mjs
514
- var __iconData19 = {
537
+ var __iconData20 = {
515
538
  name: "file-spreadsheet",
516
539
  size: 24,
517
540
  node: [
@@ -529,11 +552,11 @@ var __iconData19 = {
529
552
  ["path", { d: "M14 17h2", key: "10kma7" }]
530
553
  ]
531
554
  };
532
- __iconData19.node;
533
- var FileSpreadsheet = createLucideIcon(__iconData19);
555
+ __iconData20.node;
556
+ var FileSpreadsheet = createLucideIcon(__iconData20);
534
557
 
535
558
  // ../../node_modules/lucide-react/dist/esm/icons/file-text.mjs
536
- var __iconData20 = {
559
+ var __iconData21 = {
537
560
  name: "file-text",
538
561
  size: 24,
539
562
  node: [
@@ -550,11 +573,11 @@ var __iconData20 = {
550
573
  ["path", { d: "M16 17H8", key: "z1uh3a" }]
551
574
  ]
552
575
  };
553
- __iconData20.node;
554
- var FileText = createLucideIcon(__iconData20);
576
+ __iconData21.node;
577
+ var FileText = createLucideIcon(__iconData21);
555
578
 
556
579
  // ../../node_modules/lucide-react/dist/esm/icons/folder.mjs
557
- var __iconData21 = {
580
+ var __iconData22 = {
558
581
  name: "folder",
559
582
  size: 24,
560
583
  node: [
@@ -567,11 +590,11 @@ var __iconData21 = {
567
590
  ]
568
591
  ]
569
592
  };
570
- __iconData21.node;
571
- var Folder = createLucideIcon(__iconData21);
593
+ __iconData22.node;
594
+ var Folder = createLucideIcon(__iconData22);
572
595
 
573
596
  // ../../node_modules/lucide-react/dist/esm/icons/gauge.mjs
574
- var __iconData22 = {
597
+ var __iconData23 = {
575
598
  name: "gauge",
576
599
  size: 24,
577
600
  node: [
@@ -579,11 +602,11 @@ var __iconData22 = {
579
602
  ["path", { d: "M3.34 19a10 10 0 1 1 17.32 0", key: "19p75a" }]
580
603
  ]
581
604
  };
582
- __iconData22.node;
583
- var Gauge = createLucideIcon(__iconData22);
605
+ __iconData23.node;
606
+ var Gauge = createLucideIcon(__iconData23);
584
607
 
585
608
  // ../../node_modules/lucide-react/dist/esm/icons/globe.mjs
586
- var __iconData23 = {
609
+ var __iconData24 = {
587
610
  name: "globe",
588
611
  size: 24,
589
612
  node: [
@@ -592,11 +615,11 @@ var __iconData23 = {
592
615
  ["path", { d: "M2 12h20", key: "9i4pu4" }]
593
616
  ]
594
617
  };
595
- __iconData23.node;
596
- var Globe = createLucideIcon(__iconData23);
618
+ __iconData24.node;
619
+ var Globe = createLucideIcon(__iconData24);
597
620
 
598
621
  // ../../node_modules/lucide-react/dist/esm/icons/image.mjs
599
- var __iconData24 = {
622
+ var __iconData25 = {
600
623
  name: "image",
601
624
  size: 24,
602
625
  node: [
@@ -605,11 +628,29 @@ var __iconData24 = {
605
628
  ["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }]
606
629
  ]
607
630
  };
608
- __iconData24.node;
609
- var Image = createLucideIcon(__iconData24);
631
+ __iconData25.node;
632
+ var Image = createLucideIcon(__iconData25);
633
+
634
+ // ../../node_modules/lucide-react/dist/esm/icons/inbox.mjs
635
+ var __iconData26 = {
636
+ name: "inbox",
637
+ size: 24,
638
+ node: [
639
+ ["polyline", { points: "22 12 16 12 14 15 10 15 8 12 2 12", key: "o97t9d" }],
640
+ [
641
+ "path",
642
+ {
643
+ d: "M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z",
644
+ key: "oot6mr"
645
+ }
646
+ ]
647
+ ]
648
+ };
649
+ __iconData26.node;
650
+ var Inbox = createLucideIcon(__iconData26);
610
651
 
611
652
  // ../../node_modules/lucide-react/dist/esm/icons/list-checks.mjs
612
- var __iconData25 = {
653
+ var __iconData27 = {
613
654
  name: "list-checks",
614
655
  size: 24,
615
656
  node: [
@@ -620,21 +661,21 @@ var __iconData25 = {
620
661
  ["path", { d: "m3 7 2 2 4-4", key: "1obspn" }]
621
662
  ]
622
663
  };
623
- __iconData25.node;
624
- var ListChecks = createLucideIcon(__iconData25);
664
+ __iconData27.node;
665
+ var ListChecks = createLucideIcon(__iconData27);
625
666
 
626
667
  // ../../node_modules/lucide-react/dist/esm/icons/loader-circle.mjs
627
- var __iconData26 = {
668
+ var __iconData28 = {
628
669
  name: "loader-circle",
629
670
  size: 24,
630
671
  node: [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]],
631
672
  aliases: ["loader-2"]
632
673
  };
633
- __iconData26.node;
634
- var LoaderCircle = createLucideIcon(__iconData26);
674
+ __iconData28.node;
675
+ var LoaderCircle = createLucideIcon(__iconData28);
635
676
 
636
677
  // ../../node_modules/lucide-react/dist/esm/icons/mic.mjs
637
- var __iconData27 = {
678
+ var __iconData29 = {
638
679
  name: "mic",
639
680
  size: 24,
640
681
  node: [
@@ -643,11 +684,31 @@ var __iconData27 = {
643
684
  ["rect", { x: "9", y: "2", width: "6", height: "13", rx: "3", key: "s6n7sd" }]
644
685
  ]
645
686
  };
646
- __iconData27.node;
647
- var Mic = createLucideIcon(__iconData27);
687
+ __iconData29.node;
688
+ var Mic = createLucideIcon(__iconData29);
689
+
690
+ // ../../node_modules/lucide-react/dist/esm/icons/octagon-x.mjs
691
+ var __iconData30 = {
692
+ name: "octagon-x",
693
+ size: 24,
694
+ node: [
695
+ ["path", { d: "m15 9-6 6", key: "1uzhvr" }],
696
+ [
697
+ "path",
698
+ {
699
+ d: "M2.586 16.726A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2h6.624a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586z",
700
+ key: "2d38gg"
701
+ }
702
+ ],
703
+ ["path", { d: "m9 9 6 6", key: "z0biqf" }]
704
+ ],
705
+ aliases: ["x-octagon"]
706
+ };
707
+ __iconData30.node;
708
+ var OctagonX = createLucideIcon(__iconData30);
648
709
 
649
710
  // ../../node_modules/lucide-react/dist/esm/icons/paperclip.mjs
650
- var __iconData28 = {
711
+ var __iconData31 = {
651
712
  name: "paperclip",
652
713
  size: 24,
653
714
  node: [
@@ -660,11 +721,11 @@ var __iconData28 = {
660
721
  ]
661
722
  ]
662
723
  };
663
- __iconData28.node;
664
- var Paperclip = createLucideIcon(__iconData28);
724
+ __iconData31.node;
725
+ var Paperclip = createLucideIcon(__iconData31);
665
726
 
666
727
  // ../../node_modules/lucide-react/dist/esm/icons/rotate-ccw.mjs
667
- var __iconData29 = {
728
+ var __iconData32 = {
668
729
  name: "rotate-ccw",
669
730
  size: 24,
670
731
  node: [
@@ -672,11 +733,11 @@ var __iconData29 = {
672
733
  ["path", { d: "M3 3v5h5", key: "1xhq8a" }]
673
734
  ]
674
735
  };
675
- __iconData29.node;
676
- var RotateCcw = createLucideIcon(__iconData29);
736
+ __iconData32.node;
737
+ var RotateCcw = createLucideIcon(__iconData32);
677
738
 
678
739
  // ../../node_modules/lucide-react/dist/esm/icons/search.mjs
679
- var __iconData30 = {
740
+ var __iconData33 = {
680
741
  name: "search",
681
742
  size: 24,
682
743
  node: [
@@ -684,11 +745,11 @@ var __iconData30 = {
684
745
  ["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
685
746
  ]
686
747
  };
687
- __iconData30.node;
688
- var Search = createLucideIcon(__iconData30);
748
+ __iconData33.node;
749
+ var Search = createLucideIcon(__iconData33);
689
750
 
690
751
  // ../../node_modules/lucide-react/dist/esm/icons/send.mjs
691
- var __iconData31 = {
752
+ var __iconData34 = {
692
753
  name: "send",
693
754
  size: 24,
694
755
  node: [
@@ -702,11 +763,11 @@ var __iconData31 = {
702
763
  ["path", { d: "m21.854 2.147-10.94 10.939", key: "12cjpa" }]
703
764
  ]
704
765
  };
705
- __iconData31.node;
706
- var Send = createLucideIcon(__iconData31);
766
+ __iconData34.node;
767
+ var Send = createLucideIcon(__iconData34);
707
768
 
708
769
  // ../../node_modules/lucide-react/dist/esm/icons/shield-alert.mjs
709
- var __iconData32 = {
770
+ var __iconData35 = {
710
771
  name: "shield-alert",
711
772
  size: 24,
712
773
  node: [
@@ -721,34 +782,20 @@ var __iconData32 = {
721
782
  ["path", { d: "M12 16h.01", key: "1drbdi" }]
722
783
  ]
723
784
  };
724
- __iconData32.node;
725
- var ShieldAlert = createLucideIcon(__iconData32);
726
-
727
- // ../../node_modules/lucide-react/dist/esm/icons/square-terminal.mjs
728
- var __iconData33 = {
729
- name: "square-terminal",
730
- size: 24,
731
- node: [
732
- ["path", { d: "m7 11 2-2-2-2", key: "1lz0vl" }],
733
- ["path", { d: "M11 13h4", key: "1p7l4v" }],
734
- ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }]
735
- ],
736
- aliases: ["terminal-square"]
737
- };
738
- __iconData33.node;
739
- var SquareTerminal = createLucideIcon(__iconData33);
785
+ __iconData35.node;
786
+ var ShieldAlert = createLucideIcon(__iconData35);
740
787
 
741
788
  // ../../node_modules/lucide-react/dist/esm/icons/square.mjs
742
- var __iconData34 = {
789
+ var __iconData36 = {
743
790
  name: "square",
744
791
  size: 24,
745
792
  node: [["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }]]
746
793
  };
747
- __iconData34.node;
748
- var Square = createLucideIcon(__iconData34);
794
+ __iconData36.node;
795
+ var Square = createLucideIcon(__iconData36);
749
796
 
750
797
  // ../../node_modules/lucide-react/dist/esm/icons/users-round.mjs
751
- var __iconData35 = {
798
+ var __iconData37 = {
752
799
  name: "users-round",
753
800
  size: 24,
754
801
  node: [
@@ -758,11 +805,11 @@ var __iconData35 = {
758
805
  ],
759
806
  aliases: ["users-2"]
760
807
  };
761
- __iconData35.node;
762
- var UsersRound = createLucideIcon(__iconData35);
808
+ __iconData37.node;
809
+ var UsersRound = createLucideIcon(__iconData37);
763
810
 
764
811
  // ../../node_modules/lucide-react/dist/esm/icons/x.mjs
765
- var __iconData36 = {
812
+ var __iconData38 = {
766
813
  name: "x",
767
814
  size: 24,
768
815
  node: [
@@ -770,8 +817,8 @@ var __iconData36 = {
770
817
  ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
771
818
  ]
772
819
  };
773
- __iconData36.node;
774
- var X = createLucideIcon(__iconData36);
820
+ __iconData38.node;
821
+ var X = createLucideIcon(__iconData38);
775
822
 
776
823
  // src/react/Piloto.tsx
777
824
  import {
@@ -1173,7 +1220,7 @@ function useChunkRegistry() {
1173
1220
  return useMemo2(() => /* @__PURE__ */ new Map(), []);
1174
1221
  }
1175
1222
  var UNTOUCHED = /* @__PURE__ */ new Set(["pre", "code", "svg", "math", "script", "style"]);
1176
- var STYLE = `piloto-chunk ${CHUNK_MS}ms linear both`;
1223
+ var STYLE = `gs-tramo ${CHUNK_MS}ms linear both`;
1177
1224
  function chunksPlugin(state) {
1178
1225
  return () => (tree) => {
1179
1226
  let total = 0;
@@ -1243,7 +1290,7 @@ var ChunkedBlock = memo(function ChunkedBlock2(props) {
1243
1290
  // src/react/Markdown.tsx
1244
1291
  import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1245
1292
  function LinkSafetyModal({ isOpen, onClose, onConfirm, url }) {
1246
- const { strings: t, theme, skin } = usePiloto();
1293
+ const { strings: t, skin } = usePiloto();
1247
1294
  const [copied, setCopied] = useState3(false);
1248
1295
  if (!isOpen) return null;
1249
1296
  const copy = async () => {
@@ -1256,37 +1303,37 @@ function LinkSafetyModal({ isOpen, onClose, onConfirm, url }) {
1256
1303
  window.open(url, "_blank", "noopener,noreferrer");
1257
1304
  onConfirm();
1258
1305
  };
1259
- return /* @__PURE__ */ jsx3("div", { ...rootProps(theme, skin), style: { display: "contents" }, children: /* @__PURE__ */ jsx3("div", { className: "piloto-overlay fixed inset-0 z-[1000] flex items-center justify-center bg-black/60 px-4", onClick: onClose, role: "presentation", children: /* @__PURE__ */ jsxs2(
1306
+ return /* @__PURE__ */ jsx3("div", { ...rootProps("dark", skin), style: { display: "contents" }, children: /* @__PURE__ */ jsx3("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 px-4", onClick: onClose, role: "presentation", children: /* @__PURE__ */ jsxs2(
1260
1307
  "div",
1261
1308
  {
1262
- className: "piloto-dialog w-full max-w-md rounded-(--piloto-radius-card) border border-border-primary bg-background-primary p-6 text-text-primary shadow-(--piloto-shadow-card)",
1309
+ className: "w-full max-w-md rounded-2xl border border-border-primary bg-background-primary p-6 shadow-2xl",
1263
1310
  onClick: (e) => e.stopPropagation(),
1264
1311
  role: "dialog",
1265
1312
  "aria-modal": "true",
1266
1313
  "aria-label": t.linkTitle,
1267
1314
  children: [
1268
1315
  /* @__PURE__ */ jsxs2("div", { className: "flex items-start justify-between gap-4", children: [
1269
- /* @__PURE__ */ jsxs2("h2", { className: "flex items-center gap-2 text-base font-semibold", children: [
1316
+ /* @__PURE__ */ jsxs2("h2", { className: "flex items-center gap-2 text-base text-text-primary", children: [
1270
1317
  /* @__PURE__ */ jsx3(ExternalLink, { className: "h-4 w-4 text-text-secondary" }),
1271
1318
  t.linkTitle
1272
1319
  ] }),
1273
1320
  /* @__PURE__ */ jsx3("button", { type: "button", onClick: onClose, "aria-label": t.close, className: "text-text-secondary transition hover:text-text-primary", children: /* @__PURE__ */ jsx3(X, { className: "h-4 w-4" }) })
1274
1321
  ] }),
1275
- /* @__PURE__ */ jsx3("p", { className: "mt-4 break-all rounded-(--piloto-radius-input) border border-border-primary bg-background-secondary px-3 py-2.5 font-mono text-xs", children: url }),
1322
+ /* @__PURE__ */ jsx3("p", { className: "mt-4 break-all rounded-xl border border-border-primary bg-background-secondary px-3 py-2.5 font-mono text-xs text-text-primary", children: url }),
1276
1323
  /* @__PURE__ */ jsxs2("div", { className: "mt-5 flex gap-2", children: [
1277
1324
  /* @__PURE__ */ jsx3(
1278
1325
  "button",
1279
1326
  {
1280
1327
  type: "button",
1281
1328
  onClick: copy,
1282
- className: "flex flex-1 items-center justify-center gap-2 rounded-(--piloto-radius-button) border border-border-primary bg-background-secondary px-4 py-2 text-sm transition hover:border-text-tertiary",
1329
+ className: "flex flex-1 items-center justify-center gap-2 rounded-xl border border-border-primary bg-background-secondary px-4 py-2 text-sm text-text-primary transition hover:border-text-tertiary",
1283
1330
  children: copied ? /* @__PURE__ */ jsxs2(Fragment, { children: [
1284
1331
  /* @__PURE__ */ jsx3(Check, { className: "h-4 w-4 text-text-success" }),
1285
1332
  t.linkCopied
1286
1333
  ] }) : t.linkCopy
1287
1334
  }
1288
1335
  ),
1289
- /* @__PURE__ */ jsx3("button", { type: "button", onClick: open, className: "piloto-primary flex-1 rounded-(--piloto-radius-button) px-4 py-2 text-sm transition hover:opacity-90", children: t.linkOpen })
1336
+ /* @__PURE__ */ jsx3("button", { type: "button", onClick: open, className: "flex-1 rounded-xl bg-text-primary px-4 py-2 text-sm text-text-inverse transition hover:opacity-90", children: t.linkOpen })
1290
1337
  ] })
1291
1338
  ]
1292
1339
  }
@@ -1307,11 +1354,19 @@ function Markdown({ children, animate = false, className }) {
1307
1354
  } : void 0;
1308
1355
  return (
1309
1356
  // `min-w-0 break-words` y el scroll interno en pre/tablas: una URL larga no ensancha el chat.
1310
- /* @__PURE__ */ jsx3("div", { onClickCapture: onClick, className: `piloto-md min-w-0 max-w-full break-words ${className ?? ""}`, children: animate ? /* @__PURE__ */ jsx3(ChunksContext.Provider, { value: { registry, part: 0 }, children: /* @__PURE__ */ jsx3(Streamdown, { BlockComponent: ChunkedBlock, linkSafety, children: text }) }) : /* @__PURE__ */ jsx3(Streamdown, { linkSafety, children: text }) })
1357
+ /* @__PURE__ */ jsx3(
1358
+ "div",
1359
+ {
1360
+ onClickCapture: onClick,
1361
+ className: `ghosty-md min-w-0 max-w-full break-words ${className ?? "text-text-primary"} [&_pre]:max-w-full [&_pre]:overflow-x-auto [&_table]:block [&_table]:max-w-full [&_table]:overflow-x-auto`,
1362
+ children: animate ? /* @__PURE__ */ jsx3(ChunksContext.Provider, { value: { registry, part: 0 }, children: /* @__PURE__ */ jsx3(Streamdown, { BlockComponent: ChunkedBlock, linkSafety, children: text }) }) : /* @__PURE__ */ jsx3(Streamdown, { linkSafety, children: text })
1363
+ }
1364
+ )
1311
1365
  );
1312
1366
  }
1313
1367
 
1314
1368
  // src/react/Steps.tsx
1369
+ import { AnimatePresence, motion } from "motion/react";
1315
1370
  import { useState as useState4 } from "react";
1316
1371
 
1317
1372
  // src/react/InlineMarkdown.tsx
@@ -1347,22 +1402,32 @@ function InlineMarkdown({ children }) {
1347
1402
  // src/react/Steps.tsx
1348
1403
  import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1349
1404
  function ClawIcon({ className }) {
1350
- return /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round", className: `piloto-claw ${className ?? ""}`, "aria-hidden": "true", children: /* @__PURE__ */ jsxs3("g", { className: "piloto-claw-rig", children: [
1405
+ return /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round", className: `gs-garra ${className ?? ""}`, "aria-hidden": "true", children: /* @__PURE__ */ jsxs3("g", { className: "gs-garra-rig", children: [
1351
1406
  /* @__PURE__ */ jsx5("path", { d: "M12 2v4" }),
1352
1407
  /* @__PURE__ */ jsx5("rect", { x: "8.5", y: "6", width: "7", height: "3.5", rx: "1" }),
1353
- /* @__PURE__ */ jsx5("g", { className: "piloto-claw-l", children: /* @__PURE__ */ jsx5("path", { d: "M9.5 9.5 6 14l2 4.5" }) }),
1354
- /* @__PURE__ */ jsx5("g", { className: "piloto-claw-r", children: /* @__PURE__ */ jsx5("path", { d: "M14.5 9.5 18 14l-2 4.5" }) }),
1408
+ /* @__PURE__ */ jsx5("g", { className: "gs-garra-l", children: /* @__PURE__ */ jsx5("path", { d: "M9.5 9.5 6 14l2 4.5" }) }),
1409
+ /* @__PURE__ */ jsx5("g", { className: "gs-garra-r", children: /* @__PURE__ */ jsx5("path", { d: "M14.5 9.5 18 14l-2 4.5" }) }),
1355
1410
  /* @__PURE__ */ jsx5("path", { d: "M12 9.5v4" })
1356
1411
  ] }) });
1357
1412
  }
1413
+ function RobotArmIcon({ className }) {
1414
+ return /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 512 512", fill: "currentColor", className, "aria-hidden": "true", children: /* @__PURE__ */ jsx5("path", { d: "M301.4 51.96c-46.6.1-85.3 18.16-105.2 50.84c-13.2 21.8-16.8 49.4-9.2 78q3 11.4 8.4 23.1q1.65-1.95 3.6-3.9c7.8-7.8 16.8-13.6 26.4-17.5c-1.5-3.8-2.7-7.4-3.6-10.9c-5.5-20.7-2.7-37 5.2-50.1c15.9-26.16 57.6-42.41 114.7-28.49l8.6-34.98c-16.9-4.11-33.3-6.09-48.9-6.07M454 161.7l-35 8.6c13.9 57.1-2.3 98.8-28.5 114.7c-13.1 7.9-29.4 10.7-50.1 5.2c-3.5-.9-7.1-2.1-10.7-3.5c-3.9 9.6-9.8 18.6-17.6 26.4c-1.3 1.3-2.5 2.5-3.9 3.6c7.8 3.5 15.4 6.3 23 8.3c28.6 7.6 56.2 4 78-9.2c43.6-26.5 61.3-86.6 44.8-154.1m-198.4 32.8c-15.9 0-31.8 6-43.9 18.2c-24.3 24.3-24.2 63.4 0 87.7c24.3 24.2 63.4 24.2 87.7 0c24.3-24.3 24.2-63.4 0-87.7c-12.1-12.2-28-18.2-43.8-18.2m0 21.1c10.5 0 21 4 28.9 11.9c16 15.9 16 42.1.1 58c-16 16-42.1 15.9-58 0s-16-42 0-58c7.9-8 18.5-11.9 29-11.9m0 17.9c-5.9 0-11.7 2.3-16.3 6.8c-9.1 9-9.1 23.4 0 32.5c9 9 23.5 9 32.5 0c9.1-9.1 9.1-23.5 0-32.5c-4.5-4.5-10.3-6.8-16.2-6.8m-80 25.1l-54.5 54.5l43.7 43.7l34.2 34.1l54.4-54.5c-19.8-.5-39.4-8.3-54.4-23.3c-15.1-15.1-22.9-34.7-23.4-54.5M63.41 313.2l8.11 40.6l86.68 86.7l40.6 8.1l-8.1-40.6l-86.7-86.6zM18.1 358.5l8.13 40.7l86.57 86.6l40.7 8.1l-8.1-40.6l-86.59-86.7zm-.1 57.9v64.8l32.45-32.4zm45.2 45.2L30.8 494h64.78z" }) });
1415
+ }
1416
+ function ArcadeIcon({ className }) {
1417
+ return /* @__PURE__ */ jsxs3("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.8, className, "aria-hidden": "true", children: [
1418
+ /* @__PURE__ */ jsx5("path", { d: "M11 8.5L9.8 9l-7.448 3.386a.6.6 0 0 0-.352.546v.136a.6.6 0 0 0 .352.546l8.82 4.01a2 2 0 0 0 1.656 0l8.82-4.01a.6.6 0 0 0 .352-.546v-.136a.6.6 0 0 0-.352-.546L14.2 9L13 8.5" }),
1419
+ /* @__PURE__ */ jsx5("path", { d: "M22 13v4.112a.6.6 0 0 1-.354.547l-8.825 3.972a2 2 0 0 1-1.642 0l-8.825-3.972A.6.6 0 0 1 2 17.112V13" }),
1420
+ /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 8a3 3 0 1 1 0-6a3 3 0 0 1 0 6" }),
1421
+ /* @__PURE__ */ jsx5("path", { d: "M11 8v5a1 1 0 1 0 2 0V8" }),
1422
+ /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M16 13h1" })
1423
+ ] });
1424
+ }
1358
1425
  var DEFAULT_TOOL_ICONS = {
1359
1426
  tool_search: Search,
1360
- bash: SquareTerminal,
1361
- shell: SquareTerminal,
1362
- terminal: SquareTerminal,
1363
- execute: SquareTerminal,
1364
- code: SquareTerminal,
1365
- script: SquareTerminal,
1427
+ bash: RobotArmIcon,
1428
+ shell: RobotArmIcon,
1429
+ terminal: RobotArmIcon,
1430
+ execute: RobotArmIcon,
1366
1431
  read: FileText,
1367
1432
  read_file: FileText,
1368
1433
  write: FilePenLine,
@@ -1374,19 +1439,26 @@ var DEFAULT_TOOL_ICONS = {
1374
1439
  search: Search,
1375
1440
  web_search: Globe,
1376
1441
  web_fetch: Globe,
1377
- fetch: Globe,
1378
- browser: Globe,
1379
1442
  site_publish: Globe,
1380
1443
  pdf: FileText,
1444
+ connector: ArcadeIcon,
1445
+ fetch: Globe,
1446
+ browser: Globe,
1381
1447
  todo: ListChecks,
1382
1448
  list: ListChecks,
1449
+ code: RobotArmIcon,
1450
+ script: RobotArmIcon,
1383
1451
  folder: Folder,
1452
+ mcp: ArcadeIcon,
1384
1453
  image: Image,
1385
1454
  delegate: UsersRound,
1386
1455
  guide: BookOpen,
1387
1456
  deliver: Send,
1388
1457
  sheet: FileSpreadsheet,
1389
- view: AppWindow
1458
+ view: AppWindow,
1459
+ collect: Inbox,
1460
+ status: Activity,
1461
+ stop: OctagonX
1390
1462
  };
1391
1463
  function iconFor(t, icons) {
1392
1464
  const name = toolName(t);
@@ -1396,39 +1468,47 @@ var VISIBLE = 5;
1396
1468
  function AgentSteps({ tools, live }) {
1397
1469
  const { strings: t, toolVerbs } = usePiloto();
1398
1470
  const [open, setOpen] = useState4(false);
1399
- const label = (x) => stepLabel(x, toolVerbs, t.step);
1400
1471
  const failed = tools.filter((x) => x.status === "failed").length;
1401
- const groups = groupSteps(tools, label);
1472
+ const groups = groupSteps(tools, (x) => stepLabel(x, toolVerbs, t.step));
1402
1473
  const shown = groups.slice(-VISIBLE);
1403
1474
  const hidden = groups.length - shown.length;
1404
- return /* @__PURE__ */ jsxs3("div", { className: "piloto-steps mb-3 rounded-(--piloto-radius-card) px-3 py-2.5 transition-[background-color,border-color] duration-300", "data-live": live || void 0, children: [
1405
- /* @__PURE__ */ jsx5("button", { type: "button", onClick: () => setOpen((v) => !v), "aria-expanded": open, title: open ? t.stepsCollapse : t.stepsExpand, className: "block w-full cursor-pointer text-left", children: open ? /* @__PURE__ */ jsxs3("span", { className: "flex items-center gap-1.5 text-xs font-medium text-text-primary", children: [
1406
- /* @__PURE__ */ jsx5(ChevronRight, { className: "h-3.5 w-3.5 shrink-0 rotate-90 text-text-tertiary" }),
1407
- /* @__PURE__ */ jsxs3("span", { className: "truncate", children: [
1408
- summarizeTools(tools, toolVerbs),
1409
- failed > 0 && /* @__PURE__ */ jsxs3("span", { className: "text-text-danger", children: [
1410
- ", ",
1411
- t.withProblems(failed)
1412
- ] })
1413
- ] })
1414
- ] }) : /* @__PURE__ */ jsxs3("ul", { className: "flex flex-col gap-1.5", children: [
1415
- hidden > 0 && /* @__PURE__ */ jsx5("li", { className: "text-[11px] font-medium text-text-tertiary", children: t.earlierSteps(hidden) }),
1416
- shown.map((g) => /* @__PURE__ */ jsx5(StepLine, { tool: g.tool, times: g.times, live }, g.tool.id))
1417
- ] }) }),
1418
- open && /* @__PURE__ */ jsx5("ul", { className: "mt-2 flex flex-col gap-1", children: tools.map((x) => /* @__PURE__ */ jsx5(ToolRow, { tool: x }, x.id)) })
1419
- ] });
1475
+ return /* @__PURE__ */ jsxs3(
1476
+ "div",
1477
+ {
1478
+ className: `piloto-steps mb-3 rounded-2xl border px-3 py-2.5 transition-[background-color,border-color] duration-300 ${live ? "border-transparent bg-transparent" : "border-border-primary bg-background-primary hover:bg-background-secondary/60"}`,
1479
+ children: [
1480
+ /* @__PURE__ */ jsx5("button", { type: "button", onClick: () => setOpen((v) => !v), "aria-expanded": open, title: open ? t.stepsCollapse : t.stepsExpand, className: "block w-full cursor-pointer text-left", children: open ? /* @__PURE__ */ jsxs3("span", { className: "flex items-center gap-1.5 text-xs font-medium text-text-primary", children: [
1481
+ /* @__PURE__ */ jsx5(ChevronRight, { className: "h-3.5 w-3.5 shrink-0 rotate-90 text-text-tertiary" }),
1482
+ /* @__PURE__ */ jsxs3("span", { className: "truncate", children: [
1483
+ summarizeTools(tools, toolVerbs),
1484
+ failed > 0 && /* @__PURE__ */ jsxs3("span", { className: "text-text-danger", children: [
1485
+ " \xB7 ",
1486
+ t.withProblems(failed)
1487
+ ] })
1488
+ ] })
1489
+ ] }) : /* @__PURE__ */ jsxs3("ul", { className: "flex flex-col gap-1.5", children: [
1490
+ hidden > 0 && /* @__PURE__ */ jsx5("li", { className: "text-[11px] font-medium text-text-tertiary", children: t.earlierSteps(hidden) }),
1491
+ shown.map((g) => /* @__PURE__ */ jsx5(StepLine, { tool: g.tool, times: g.times, live }, g.tool.id))
1492
+ ] }) }),
1493
+ open && /* @__PURE__ */ jsx5("div", { className: "mt-2", children: /* @__PURE__ */ jsx5("ul", { className: "flex flex-col gap-1", children: tools.map((x) => /* @__PURE__ */ jsx5(ToolRow, { tool: x }, x.id)) }) })
1494
+ ]
1495
+ }
1496
+ );
1420
1497
  }
1421
1498
  function StepLine({ tool, times, live }) {
1422
1499
  const { strings: t, toolVerbs, toolIcons } = usePiloto();
1423
- const Icon2 = iconFor(tool, toolIcons);
1500
+ const KindIcon = iconFor(tool, toolIcons);
1424
1501
  const spins = isRunning(tool) && live;
1425
1502
  const label = stepLabel(tool, toolVerbs, t.step);
1426
- return /* @__PURE__ */ jsxs3("li", { className: "piloto-step flex min-w-0 items-center gap-2 text-[13px] leading-6 text-text-secondary", children: [
1503
+ return /* @__PURE__ */ jsxs3("li", { className: "gs-paso-in flex min-w-0 items-center gap-2 text-[13px] leading-6 text-text-secondary", children: [
1427
1504
  /* @__PURE__ */ jsx5("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center", "aria-label": spins ? t.running : tool.status === "failed" ? t.failed : t.done, children: spins ? /* @__PURE__ */ jsx5(LoaderCircle, { className: "h-4 w-4 animate-spin text-text-info" }) : tool.status === "failed" ? /* @__PURE__ */ jsx5(CircleX, { className: "h-4 w-4 text-text-danger" }) : /* @__PURE__ */ jsx5(CircleCheck, { className: "h-4 w-4 text-text-success" }) }),
1428
- /* @__PURE__ */ jsx5(Icon2, { className: "h-[22px] w-[22px] shrink-0 text-text-secondary" }),
1505
+ /* @__PURE__ */ jsx5(KindIcon, { className: "h-[22px] w-[22px] shrink-0 text-text-secondary" }),
1429
1506
  /* @__PURE__ */ jsxs3("span", { className: "min-w-0 truncate", children: [
1430
1507
  /* @__PURE__ */ jsx5("span", { className: spins ? "text-text-primary" : void 0, children: label }),
1431
- tool.detail && /* @__PURE__ */ jsx5("span", { className: "piloto-step-detail", children: tool.detail }),
1508
+ tool.detail && /* @__PURE__ */ jsxs3("span", { className: "text-text-tertiary", children: [
1509
+ " \xB7 ",
1510
+ tool.detail
1511
+ ] }),
1432
1512
  times > 1 && /* @__PURE__ */ jsxs3("span", { className: "ml-1 tabular-nums text-text-tertiary", children: [
1433
1513
  "\xD7",
1434
1514
  times
@@ -1445,45 +1525,47 @@ var STATUS = {
1445
1525
  function ToolRow({ tool }) {
1446
1526
  const { strings: t, toolVerbs, toolIcons } = usePiloto();
1447
1527
  const s = STATUS[tool.status ?? "pending"] ?? STATUS.pending;
1528
+ const StatusIcon = s.Icon;
1448
1529
  const KindIcon = iconFor(tool, toolIcons);
1449
- return /* @__PURE__ */ jsxs3("li", { className: "piloto-tool-row flex items-start gap-2.5 rounded-(--piloto-radius-input) border border-border-secondary bg-background-secondary/50 px-3 py-2 transition-colors hover:border-border-primary hover:bg-background-secondary", children: [
1530
+ return /* @__PURE__ */ jsxs3("li", { className: "flex items-start gap-2.5 rounded-lg border border-border-secondary bg-background-secondary/50 px-3 py-2 transition-colors hover:border-border-primary hover:bg-background-secondary", children: [
1450
1531
  /* @__PURE__ */ jsx5("span", { className: "mt-px flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-background-primary text-text-secondary shadow-sm", children: /* @__PURE__ */ jsx5(KindIcon, { className: "h-3.5 w-3.5" }) }),
1451
1532
  /* @__PURE__ */ jsxs3("span", { className: "min-w-0 flex-1", children: [
1452
- /* @__PURE__ */ jsx5("span", { className: "block min-w-0 truncate text-xs font-medium text-text-primary", children: stepLabel(tool, toolVerbs, tool.id) }),
1533
+ /* @__PURE__ */ jsx5("span", { className: "flex items-baseline gap-2", children: /* @__PURE__ */ jsx5("span", { className: "min-w-0 truncate text-xs font-medium text-text-primary", children: stepLabel(tool, toolVerbs, tool.id) }) }),
1453
1534
  tool.detail && /* @__PURE__ */ jsx5("span", { className: "mt-0.5 block truncate text-[11px] text-text-tertiary", children: tool.detail }),
1454
1535
  tool.path && /* @__PURE__ */ jsx5("span", { className: "mt-0.5 block truncate font-mono text-[10px] text-text-tertiary", children: tool.path })
1455
1536
  ] }),
1456
- /* @__PURE__ */ jsx5("span", { className: "mt-0.5 shrink-0", title: t[s.key], "aria-label": t[s.key], children: /* @__PURE__ */ jsx5(s.Icon, { className: `h-3.5 w-3.5 ${s.className}` }) })
1457
- ] });
1458
- }
1459
- function Narration({ steps, children }) {
1460
- return /* @__PURE__ */ jsxs3("ul", { className: "piloto-narration mb-3 flex flex-col gap-1.5", children: [
1461
- steps.map((p, i) => /* @__PURE__ */ jsxs3("li", { className: "piloto-fade-up flex items-start gap-2 text-text-secondary", children: [
1462
- /* @__PURE__ */ jsx5("span", { className: "mt-[3px] grid size-4 shrink-0 place-items-center rounded-full bg-brand-500/15 text-brand-600", children: /* @__PURE__ */ jsx5(CheckMini, {}) }),
1463
- /* @__PURE__ */ jsx5("span", { className: "piloto-narration-text min-w-0", children: /* @__PURE__ */ jsx5(InlineMarkdown, { children: p }) })
1464
- ] }, i)),
1465
- children
1537
+ /* @__PURE__ */ jsx5("span", { className: "mt-0.5 shrink-0", title: t[s.key], "aria-label": t[s.key], children: /* @__PURE__ */ jsx5(StatusIcon, { className: `h-3.5 w-3.5 ${s.className}` }) })
1466
1538
  ] });
1467
1539
  }
1468
- function CheckMini() {
1469
- return /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 24 24", width: "11", height: "11", fill: "none", stroke: "currentColor", strokeWidth: 3, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx5("path", { d: "M20 6 9 17l-5-5" }) });
1540
+ function Narration({ steps }) {
1541
+ return /* @__PURE__ */ jsx5("ul", { className: "gs-narracion mb-3 flex flex-col gap-1.5", children: /* @__PURE__ */ jsx5(AnimatePresence, { initial: false, children: steps.map((p, i) => /* @__PURE__ */ jsxs3(
1542
+ motion.li,
1543
+ {
1544
+ initial: { opacity: 0, y: 4 },
1545
+ animate: { opacity: 1, y: 0 },
1546
+ transition: { duration: 0.25, ease: "easeOut" },
1547
+ className: "flex items-start gap-2 text-text-secondary",
1548
+ children: [
1549
+ /* @__PURE__ */ jsx5("span", { className: "mt-[3px] grid size-4 shrink-0 place-items-center rounded-full bg-brand-500/15 text-brand-500", children: /* @__PURE__ */ jsx5(Check, { size: 11, strokeWidth: 3 }) }),
1550
+ /* @__PURE__ */ jsx5("span", { className: "piloto-narration-text min-w-0", children: /* @__PURE__ */ jsx5(InlineMarkdown, { children: p }) })
1551
+ ]
1552
+ },
1553
+ i
1554
+ )) }) });
1470
1555
  }
1471
1556
 
1472
1557
  // src/react/Bubble.tsx
1473
1558
  import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1474
- async function copyText(text) {
1475
- try {
1476
- await navigator.clipboard.writeText(text);
1477
- return true;
1478
- } catch {
1479
- return false;
1480
- }
1559
+ function AnswerText({ text, live, whole = false }) {
1560
+ const { visible, animate } = useTextAtPace(text, live, whole);
1561
+ if (!visible) return null;
1562
+ return /* @__PURE__ */ jsx6("div", { className: "gs-prosa", children: /* @__PURE__ */ jsx6(Markdown, { animate, children: visible }) });
1481
1563
  }
1482
1564
  function UserBubble({ turn }) {
1483
1565
  const { strings: t, formatUserText } = usePiloto();
1484
1566
  const note = systemNoteOf(turn.text);
1485
1567
  if (note) {
1486
- return /* @__PURE__ */ jsx6("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxs4("span", { className: "piloto-system-note max-w-[80%] truncate rounded-full bg-background-secondary px-3 py-1 text-[11px] text-text-tertiary", children: [
1568
+ return /* @__PURE__ */ jsx6("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxs4("span", { className: "max-w-[80%] truncate rounded-full bg-background-secondary px-3 py-1 text-[11px] text-text-tertiary", children: [
1487
1569
  "\u23F0 ",
1488
1570
  note
1489
1571
  ] }) });
@@ -1492,16 +1574,26 @@ function UserBubble({ turn }) {
1492
1574
  const atts = turn.attachments ?? [];
1493
1575
  const inBubble = atts.filter((a) => a.mimeType.startsWith("image/") && (a.data || a.uri) || a.mimeType.startsWith("audio/") && a.uri);
1494
1576
  const docs = atts.filter((a) => !inBubble.includes(a));
1495
- return /* @__PURE__ */ jsxs4("div", { className: "piloto-user group/msg flex flex-col items-end gap-1", children: [
1577
+ return /* @__PURE__ */ jsxs4("div", { className: "group/msg flex flex-col items-end gap-1", children: [
1496
1578
  turn.steer && /* @__PURE__ */ jsxs4("span", { className: "text-[11px] text-text-tertiary", children: [
1497
1579
  "\u21AA ",
1498
1580
  t.steered
1499
1581
  ] }),
1500
- docs.length > 0 && /* @__PURE__ */ jsx6("div", { className: "mb-1 flex max-w-[75%] flex-wrap justify-end gap-2", children: docs.map((a, i) => /* @__PURE__ */ jsxs4("span", { className: "piloto-attachment-card inline-flex max-w-[16rem] items-center gap-1.5 rounded-(--piloto-radius-input) border border-border-primary bg-background-primary px-2.5 py-1.5 text-xs text-text-secondary", children: [
1501
- /* @__PURE__ */ jsx6(FileText, { className: "h-3.5 w-3.5 shrink-0" }),
1502
- a.uri ? /* @__PURE__ */ jsx6("a", { href: a.uri, target: "_blank", rel: "noopener noreferrer", className: "truncate hover:underline", children: a.name ?? a.mimeType }) : /* @__PURE__ */ jsx6("span", { className: "truncate", children: a.name ?? a.mimeType })
1503
- ] }, i)) }),
1504
- (inBubble.length > 0 || visible.trim()) && /* @__PURE__ */ jsxs4("div", { className: "piloto-bubble-user max-w-[75%] whitespace-pre-wrap break-words rounded-(--piloto-radius-bubble) px-4 py-3 text-[15px] leading-[22px]", children: [
1582
+ docs.length > 0 && /* @__PURE__ */ jsx6("div", { className: "mb-1 flex max-w-[75%] flex-wrap justify-end gap-2", children: docs.map((a, i) => /* @__PURE__ */ jsxs4(
1583
+ "a",
1584
+ {
1585
+ href: a.uri,
1586
+ target: "_blank",
1587
+ rel: "noopener noreferrer",
1588
+ className: "inline-flex max-w-[16rem] items-center gap-1.5 rounded-lg border border-border-primary px-2 py-1 text-xs text-text-tertiary",
1589
+ children: [
1590
+ /* @__PURE__ */ jsx6("span", { "aria-hidden": true, children: "\u{1F4C4}" }),
1591
+ /* @__PURE__ */ jsx6("span", { className: "truncate", children: a.name ?? a.mimeType })
1592
+ ]
1593
+ },
1594
+ i
1595
+ )) }),
1596
+ (inBubble.length > 0 || visible.trim()) && /* @__PURE__ */ jsxs4("div", { className: "gc-msg-user max-w-[75%] whitespace-pre-wrap break-words rounded-(--piloto-radius-bubble) bg-(--piloto-user-bubble) px-4 py-3 font-sans text-base leading-[22px] text-(--piloto-user-text)", children: [
1505
1597
  inBubble.length > 0 && /* @__PURE__ */ jsx6("div", { className: `flex flex-wrap justify-end gap-1.5 ${visible.trim() ? "mb-2" : ""}`, children: inBubble.map(
1506
1598
  (a, i) => a.mimeType.startsWith("image/") ? /* @__PURE__ */ jsx6("img", { src: a.data ? `data:${a.mimeType};base64,${a.data}` : a.uri, alt: "", className: "h-20 w-20 rounded-lg object-cover" }, i) : /* @__PURE__ */ jsx6("audio", { src: a.uri, controls: true, preload: "metadata", className: "h-9 max-w-[16rem]" }, i)
1507
1599
  ) }),
@@ -1518,33 +1610,30 @@ function CopyUserMessage({ text }) {
1518
1610
  {
1519
1611
  type: "button",
1520
1612
  onClick: async () => {
1521
- if (await copyText(text)) {
1613
+ try {
1614
+ await navigator.clipboard.writeText(text);
1522
1615
  setCopied(true);
1523
1616
  setTimeout(() => setCopied(false), 1500);
1617
+ } catch {
1524
1618
  }
1525
1619
  },
1526
1620
  "aria-label": copied ? t.copied : t.copyMessage,
1527
1621
  title: copied ? t.copied : t.copy,
1528
- className: `piloto-copy-user grid h-7 w-7 place-items-center rounded-md text-text-tertiary transition-opacity hover:bg-background-secondary hover:text-text-primary focus-visible:opacity-100 [@media(hover:none)]:opacity-100 ${copied ? "opacity-100" : "opacity-0 group-hover/msg:opacity-100"}`,
1622
+ className: `grid h-7 w-7 place-items-center rounded-md text-text-tertiary transition-opacity hover:bg-black/5 hover:text-text-primary focus-visible:opacity-100 [@media(hover:none)]:opacity-100 ${copied ? "opacity-100" : "opacity-0 group-hover/msg:opacity-100"}`,
1529
1623
  children: copied ? /* @__PURE__ */ jsx6(Check, { className: "h-3.5 w-3.5 text-text-success" }) : /* @__PURE__ */ jsx6(Copy, { className: "h-3.5 w-3.5" })
1530
1624
  }
1531
1625
  );
1532
1626
  }
1533
- function AnswerText({ text, live, whole = false }) {
1534
- const { visible, animate } = useTextAtPace(text, live, whole);
1535
- if (!visible) return null;
1536
- return /* @__PURE__ */ jsx6(Markdown, { animate, children: visible });
1537
- }
1538
1627
  function ReplyOptionButtons({ options, onPick }) {
1539
1628
  const { strings: t } = usePiloto();
1540
- return /* @__PURE__ */ jsx6("ul", { className: "piloto-options mt-3 flex flex-col gap-2", "aria-label": t.replyOptions, children: options.items.map((item, i) => {
1629
+ return /* @__PURE__ */ jsx6("ul", { className: "mt-3 flex flex-col gap-2", "aria-label": t.replyOptions, children: options.items.map((item, i) => {
1541
1630
  const clean = cleanReplyOption(item);
1542
- return /* @__PURE__ */ jsx6("li", { className: "piloto-chunk-in", children: /* @__PURE__ */ jsxs4(
1631
+ return /* @__PURE__ */ jsx6("li", { style: { animation: "gs-tramo 400ms linear both" }, children: /* @__PURE__ */ jsxs4(
1543
1632
  "button",
1544
1633
  {
1545
1634
  type: "button",
1546
1635
  onClick: () => onPick(clean),
1547
- className: "piloto-option group flex w-full cursor-pointer items-center gap-3 rounded-(--piloto-radius-input) border border-border-primary bg-background-primary px-4 py-2.5 text-left text-sm text-text-primary transition-colors hover:border-brand-300 hover:bg-background-secondary",
1636
+ className: "group flex w-full cursor-pointer items-center gap-3 rounded-xl border border-border-primary bg-background-primary px-4 py-2.5 text-left font-sans text-sm text-text-primary transition-colors hover:border-brand-300 hover:bg-background-secondary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand-600",
1548
1637
  children: [
1549
1638
  options.numbered && /* @__PURE__ */ jsxs4("span", { className: "shrink-0 tabular-nums text-text-tertiary", children: [
1550
1639
  i + 1,
@@ -1561,7 +1650,7 @@ function UsageStats({ used, size, cost }) {
1561
1650
  const { strings: t } = usePiloto();
1562
1651
  if (!used && !cost) return null;
1563
1652
  const pct = size > 0 ? Math.min(100, Math.round(used / size * 100)) : 0;
1564
- return /* @__PURE__ */ jsxs4("div", { className: "piloto-usage mt-2 flex items-center gap-4 text-[11px] text-text-tertiary", children: [
1653
+ return /* @__PURE__ */ jsxs4("div", { className: "mt-2 flex items-center gap-4 text-[11px] text-text-tertiary", children: [
1565
1654
  /* @__PURE__ */ jsxs4("span", { className: "flex items-center gap-1", children: [
1566
1655
  /* @__PURE__ */ jsx6(Gauge, { className: "h-3 w-3" }),
1567
1656
  used.toLocaleString(t.numberLocale),
@@ -1573,19 +1662,21 @@ function UsageStats({ used, size, cost }) {
1573
1662
  ] })
1574
1663
  ] });
1575
1664
  }
1576
- function TurnFooter({ text, seconds, onRetry, showCopy = true }) {
1665
+ function TurnFooter({ text, seconds, onRetry, showCopy = true, showDuration = true }) {
1577
1666
  const { strings: t } = usePiloto();
1578
1667
  const [copied, setCopied] = useState5(false);
1579
- return /* @__PURE__ */ jsxs4("div", { className: "piloto-footer mt-2 flex items-center gap-3 text-xs text-text-tertiary", children: [
1580
- seconds ? /* @__PURE__ */ jsx6("span", { children: t.worked(seconds) }) : null,
1668
+ return /* @__PURE__ */ jsxs4("div", { className: "mt-2 flex items-center gap-3 text-xs text-text-tertiary", children: [
1669
+ seconds && showDuration ? /* @__PURE__ */ jsx6("span", { children: t.worked(seconds) }) : null,
1581
1670
  showCopy && /* @__PURE__ */ jsxs4(
1582
1671
  "button",
1583
1672
  {
1584
1673
  type: "button",
1585
1674
  onClick: async () => {
1586
- if (await copyText(text)) {
1675
+ try {
1676
+ await navigator.clipboard.writeText(text);
1587
1677
  setCopied(true);
1588
1678
  setTimeout(() => setCopied(false), 1500);
1679
+ } catch {
1589
1680
  }
1590
1681
  },
1591
1682
  className: "flex items-center gap-1 transition-colors hover:text-text-primary",
@@ -1604,18 +1695,18 @@ function TurnFooter({ text, seconds, onRetry, showCopy = true }) {
1604
1695
  function DeliveryChips({ deliveries }) {
1605
1696
  const shown = deliveries.filter((d) => !d.capture);
1606
1697
  if (!shown.length) return null;
1607
- return /* @__PURE__ */ jsx6("div", { className: "mt-2 flex flex-wrap gap-1.5", children: shown.map((d, i) => /* @__PURE__ */ jsxs4("span", { className: "piloto-delivery inline-flex max-w-[16rem] items-center gap-1.5 rounded-(--piloto-radius-input) border border-border-primary px-2 py-1 text-xs text-text-secondary", children: [
1608
- /* @__PURE__ */ jsx6(FileText, { className: "h-3.5 w-3.5 shrink-0" }),
1698
+ return /* @__PURE__ */ jsx6("div", { className: "mt-2 flex flex-wrap gap-1.5", children: shown.map((d, i) => /* @__PURE__ */ jsxs4("span", { className: "inline-flex max-w-[16rem] items-center gap-1.5 rounded-lg border border-border-primary px-2 py-1 text-xs text-text-tertiary", children: [
1699
+ /* @__PURE__ */ jsx6("span", { "aria-hidden": true, children: "\u{1F4C4}" }),
1609
1700
  /* @__PURE__ */ jsx6("span", { className: "truncate", children: d.name })
1610
1701
  ] }, i)) });
1611
1702
  }
1612
- function AgentBubble({ turn, live, onRetry, onOption, showUsage = true, showCopy = true, renderDeliveries }) {
1703
+ function AgentBubble({ turn, live, onRetry, onOption, showUsage = true, showCopy = true, showDuration = true, renderDeliveries }) {
1613
1704
  const { strings: t } = usePiloto();
1614
1705
  const narrated = splitNarration(turn.text ?? "", turn.cuts);
1615
1706
  const visible = narrated.rest;
1616
1707
  const options = onOption && !live && visible ? extractReplyOptions(visible) : null;
1617
- return /* @__PURE__ */ jsxs4("div", { className: "piloto-agent min-w-0 max-w-[92%]", children: [
1618
- turn.thought && /* @__PURE__ */ jsxs4("details", { className: "piloto-thought mb-3 text-xs text-text-secondary", children: [
1708
+ return /* @__PURE__ */ jsxs4("div", { className: "gc-msg-agent min-w-0 max-w-[90%]", children: [
1709
+ turn.thought && /* @__PURE__ */ jsxs4("details", { className: "mb-3 text-xs text-text-secondary", children: [
1619
1710
  /* @__PURE__ */ jsx6("summary", { className: "cursor-pointer select-none", children: t.thinking }),
1620
1711
  /* @__PURE__ */ jsx6("p", { className: "mt-2 whitespace-pre-wrap border-l-2 border-border-secondary pl-3", children: turn.thought })
1621
1712
  ] }),
@@ -1625,63 +1716,76 @@ function AgentBubble({ turn, live, onRetry, onOption, showUsage = true, showCopy
1625
1716
  options.before && /* @__PURE__ */ jsx6(AnswerText, { text: options.before, live }),
1626
1717
  /* @__PURE__ */ jsx6(ReplyOptionButtons, { options, onPick: onOption })
1627
1718
  ] }) : (
1628
- // Cada tramo nuevo tras una herramienta monta su propio ritmo (empieza de cero). Lo que llegó
1629
- // entero fuera de un turno se escribe al mismo ritmo; al recargar ya sale completo.
1719
+ // Cada tramo nuevo tras una herramienta monta su propio ritmo (empieza de cero).
1630
1720
  visible && /* @__PURE__ */ jsx6(AnswerText, { text: visible, live: live || !!turn.arrived, whole: !!turn.arrived }, `r${narrated.steps.length}`)
1631
1721
  ),
1632
1722
  renderDeliveries ? renderDeliveries(turn, live) : turn.deliveries?.length ? /* @__PURE__ */ jsx6(DeliveryChips, { deliveries: turn.deliveries }) : null,
1633
1723
  turn.decisions?.length ? /* @__PURE__ */ jsx6(DecisionLines, { decisions: turn.decisions }) : null,
1634
1724
  showUsage && turn.usage && /* @__PURE__ */ jsx6(UsageStats, { ...turn.usage }),
1635
- turn.text && !live && /* @__PURE__ */ jsx6(TurnFooter, { text: turn.text, seconds: turn.seconds, onRetry, showCopy })
1725
+ turn.text && !live && /* @__PURE__ */ jsx6(TurnFooter, { text: turn.text, seconds: turn.seconds, onRetry, showCopy, showDuration })
1636
1726
  ] });
1637
1727
  }
1638
1728
 
1639
1729
  // src/react/Chips.tsx
1640
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1641
- function ReferenceChips({
1642
- references,
1643
- onRemove,
1644
- onActivate
1645
- }) {
1730
+ import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1731
+ function ReferenceChips({ references, onRemove, onActivate }) {
1646
1732
  const { strings: t } = usePiloto();
1647
1733
  if (!references.length) return null;
1648
- return /* @__PURE__ */ jsx7("div", { className: "piloto-references flex flex-wrap gap-1.5", children: references.map((r) => /* @__PURE__ */ jsxs5("span", { className: "piloto-reference inline-flex max-w-full items-center gap-1.5 rounded-full border py-1 pl-2.5 pr-1 text-xs text-text-primary", children: [
1649
- /* @__PURE__ */ jsx7(AtSign, { className: "h-3 w-3 shrink-0 text-brand-600" }),
1650
- /* @__PURE__ */ jsx7("button", { type: "button", onClick: () => onActivate?.(r), className: "shrink-0 font-semibold underline-offset-2 hover:underline", children: r.label }),
1651
- r.hint && /* @__PURE__ */ jsxs5("span", { className: "truncate text-text-secondary", children: [
1652
- "\xAB",
1653
- r.hint,
1654
- "\xBB"
1655
- ] }),
1656
- /* @__PURE__ */ jsx7(
1657
- "button",
1658
- {
1659
- type: "button",
1660
- onClick: () => onRemove(r.id),
1661
- "aria-label": t.removeReference,
1662
- className: "grid size-5 shrink-0 cursor-pointer place-items-center rounded-full text-text-tertiary hover:bg-background-secondary hover:text-text-primary",
1663
- children: /* @__PURE__ */ jsx7(X, { className: "h-3 w-3" })
1664
- }
1665
- )
1666
- ] }, r.id)) });
1734
+ const pointed = references.filter((r) => r.prompt);
1735
+ const plain = references.filter((r) => !r.prompt);
1736
+ return /* @__PURE__ */ jsxs5(Fragment4, { children: [
1737
+ pointed.map((r) => /* @__PURE__ */ jsx7("div", { className: "mb-2 flex", children: /* @__PURE__ */ jsxs5("span", { className: "inline-flex max-w-full items-center gap-1.5 rounded-full border border-brand-500/40 bg-brand-500/10 py-1 pl-2.5 pr-1 text-xs text-text-primary", children: [
1738
+ /* @__PURE__ */ jsx7(Crosshair, { size: 13, className: "shrink-0 text-brand-500" }),
1739
+ /* @__PURE__ */ jsx7("span", { className: "shrink-0 font-semibold", children: r.label }),
1740
+ r.hint && /* @__PURE__ */ jsxs5("span", { className: "truncate text-text-secondary", children: [
1741
+ "\xAB",
1742
+ r.hint,
1743
+ "\xBB"
1744
+ ] }),
1745
+ /* @__PURE__ */ jsx7(
1746
+ "button",
1747
+ {
1748
+ type: "button",
1749
+ onClick: () => onRemove(r.id),
1750
+ "aria-label": t.removeReference,
1751
+ className: "grid size-5 shrink-0 cursor-pointer place-items-center rounded-full text-text-tertiary hover:bg-background-secondary hover:text-text-primary",
1752
+ children: /* @__PURE__ */ jsx7(X, { size: 12 })
1753
+ }
1754
+ )
1755
+ ] }) }, r.id)),
1756
+ plain.length > 0 && /* @__PURE__ */ jsx7("div", { className: "flex flex-wrap gap-1.5", children: plain.map((r) => /* @__PURE__ */ jsxs5("span", { className: "inline-flex items-center gap-1 rounded-full border border-border-primary bg-background-secondary py-0.5 pl-2 pr-1 text-xs text-text-primary", children: [
1757
+ /* @__PURE__ */ jsx7("button", { type: "button", onClick: () => onActivate?.(r), className: "underline-offset-2 hover:underline", children: r.label }),
1758
+ /* @__PURE__ */ jsx7(
1759
+ "button",
1760
+ {
1761
+ type: "button",
1762
+ onClick: () => onRemove(r.id),
1763
+ "aria-label": t.removeReference,
1764
+ className: "flex h-4 w-4 items-center justify-center rounded-full text-text-tertiary hover:bg-background-tertiary hover:text-text-primary",
1765
+ children: /* @__PURE__ */ jsx7(X, { className: "h-3 w-3" })
1766
+ }
1767
+ )
1768
+ ] }, r.id)) })
1769
+ ] });
1667
1770
  }
1668
- function Suggestions({ items, onPick, onPrefill }) {
1771
+ function Suggestions({ items, onPick, onPrefill, disabled }) {
1669
1772
  if (!items.length) return null;
1670
- return /* @__PURE__ */ jsx7("div", { className: "piloto-suggestions mt-3 flex flex-wrap justify-center gap-2", children: items.map((s, i) => /* @__PURE__ */ jsx7(
1773
+ return /* @__PURE__ */ jsx7("div", { className: "mt-4 flex flex-wrap justify-center gap-2", children: items.map((c) => /* @__PURE__ */ jsx7(
1671
1774
  "button",
1672
1775
  {
1673
1776
  type: "button",
1674
- onClick: () => onPrefill && /:\s*$/.test(s) ? onPrefill(s) : onPick(s),
1675
- className: "piloto-suggestion rounded-full border border-border-primary bg-background-primary px-3.5 py-1.5 text-sm text-text-secondary transition-colors hover:border-brand-300 hover:text-text-primary",
1676
- children: s
1777
+ onClick: () => onPrefill && /:\s*$/.test(c) ? onPrefill(c) : onPick(c),
1778
+ disabled,
1779
+ className: "gc-chip rounded-full bg-irongray/10 px-3.5 py-1.5 text-xs font-medium text-metal transition-colors hover:bg-irongray/20 hover:text-dark disabled:opacity-40",
1780
+ children: c
1677
1781
  },
1678
- i
1782
+ c
1679
1783
  )) });
1680
1784
  }
1681
1785
 
1682
1786
  // src/react/Composer.tsx
1683
1787
  import { useCallback, useEffect as useEffect3, useRef as useRef3, useState as useState6 } from "react";
1684
- import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1788
+ import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1685
1789
  var MAX_HEIGHT = 240;
1686
1790
  var BY_EXTENSION = {
1687
1791
  png: "image/png",
@@ -1972,10 +2076,9 @@ function Composer({
1972
2076
  }
1973
2077
  };
1974
2078
  const canSend = Boolean(value.trim() || files.length > 0 || references.length > 0);
1975
- const iconButton = "flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-text-secondary transition-colors hover:bg-background-secondary hover:text-text-primary disabled:opacity-30";
1976
- return /* @__PURE__ */ jsx8("div", { className: "piloto-composer rounded-(--piloto-radius-input)", children: /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-2 p-3", children: [
1977
- withFiles && dragging && /* @__PURE__ */ jsx8("div", { className: "piloto-drop pointer-events-none fixed inset-0 z-[1000] flex items-center justify-center p-6", children: /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-center gap-2 rounded-(--piloto-radius-card) border-2 border-dashed border-brand-500 bg-background-primary px-10 py-8 text-center shadow-(--piloto-shadow-card)", children: [
1978
- /* @__PURE__ */ jsx8(Paperclip, { className: "size-7 text-brand-600" }),
2079
+ return /* @__PURE__ */ jsx8("div", { className: "gc-input rounded-(--piloto-radius-input) border-(length:--piloto-border-width) border-outlines bg-(--piloto-composer-bg) shadow-(--piloto-shadow-input) transition-colors focus-within:border-brand-300", children: /* @__PURE__ */ jsxs6("div", { className: `flex flex-col gap-2 p-3 transition-shadow ${withFiles && dragging ? "rounded-2xl bg-background-secondary/40 ring-2 ring-inset ring-ring-info" : ""}`, children: [
2080
+ withFiles && dragging && /* @__PURE__ */ jsx8("div", { className: "pointer-events-none fixed inset-0 z-50 flex items-center justify-center bg-background-primary/80 p-6 backdrop-blur-sm", children: /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-center gap-2 rounded-3xl border-2 border-dashed border-brand-500 bg-background-primary px-10 py-8 text-center shadow-lg", children: [
2081
+ /* @__PURE__ */ jsx8(Paperclip, { className: "size-7 text-brand-500" }),
1979
2082
  /* @__PURE__ */ jsx8("p", { className: "text-base font-semibold text-text-primary", children: t.dropFiles }),
1980
2083
  /* @__PURE__ */ jsx8("p", { className: "text-xs text-text-secondary", children: t.dropHint })
1981
2084
  ] }) }),
@@ -1997,7 +2100,7 @@ function Composer({
1997
2100
  /* @__PURE__ */ jsx8(LoaderCircle, { className: "h-3.5 w-3.5 animate-spin" }),
1998
2101
  files.length > 1 ? t.uploadingN(files.length) : t.uploading
1999
2102
  ] }),
2000
- files.length > 0 && /* @__PURE__ */ jsx8("div", { className: "flex flex-wrap gap-2", children: files.map((a) => /* @__PURE__ */ jsxs6("div", { className: "relative h-16 w-16 overflow-hidden rounded-lg border border-border-primary bg-background-secondary", children: [
2103
+ withFiles && files.length > 0 && /* @__PURE__ */ jsx8("div", { className: "flex flex-wrap gap-2", children: files.map((a) => /* @__PURE__ */ jsxs6("div", { className: "relative h-16 w-16 overflow-hidden rounded-lg border border-border-primary bg-background-secondary", children: [
2001
2104
  mimeOf(a.file).startsWith("image/") ? /* @__PURE__ */ jsx8("img", { src: a.url, alt: a.file.name, className: "h-full w-full object-cover" }) : (
2002
2105
  // Un PDF pintado con <img> es un recuadro roto: nombre, extensión y peso.
2003
2106
  /* @__PURE__ */ jsxs6("span", { className: "flex h-full w-full flex-col items-center justify-center gap-1 px-1 text-center", title: a.file.name, children: [
@@ -2012,7 +2115,7 @@ function Composer({
2012
2115
  type: "button",
2013
2116
  onClick: () => removeFile(a.id),
2014
2117
  "aria-label": t.removeAttachment,
2015
- className: "absolute right-0.5 top-0.5 flex h-5 w-5 items-center justify-center rounded-full bg-background-inverse/80 text-text-inverse shadow-sm transition-colors hover:bg-background-inverse",
2118
+ className: "absolute top-0.5 right-0.5 flex h-5 w-5 items-center justify-center rounded-full bg-background-inverse/80 text-text-inverse shadow-sm transition-colors hover:bg-background-inverse",
2016
2119
  children: /* @__PURE__ */ jsx8(X, { className: "h-3 w-3" })
2017
2120
  }
2018
2121
  )
@@ -2030,18 +2133,29 @@ function Composer({
2030
2133
  recRef.current?.stop();
2031
2134
  },
2032
2135
  "aria-label": t.cancelVoice,
2136
+ title: t.cancelVoice,
2033
2137
  className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-text-secondary hover:bg-background-secondary hover:text-text-primary",
2034
2138
  children: /* @__PURE__ */ jsx8(X, { className: "h-4 w-4" })
2035
2139
  }
2036
2140
  ),
2037
- /* @__PURE__ */ jsx8("span", { className: "piloto-rec-dot h-2 w-2 shrink-0 rounded-full" }),
2141
+ /* @__PURE__ */ jsx8("span", { className: "h-2 w-2 shrink-0 animate-pulse rounded-full bg-red-500" }),
2038
2142
  /* @__PURE__ */ jsxs6("span", { className: "w-10 shrink-0 font-mono text-xs tabular-nums text-text-secondary", children: [
2039
2143
  Math.floor(seconds / 60),
2040
2144
  ":",
2041
2145
  String(seconds % 60).padStart(2, "0")
2042
2146
  ] }),
2043
2147
  /* @__PURE__ */ jsx8("div", { className: "flex h-6 min-w-0 flex-1 items-center gap-[2px] overflow-hidden", children: Array.from({ length: 60 }, (_, i) => wave[wave.length - 60 + i] ?? 0).map((v, i) => /* @__PURE__ */ jsx8("span", { className: "w-[3px] shrink-0 rounded-full bg-text-secondary/70", style: { height: `${Math.max(3, Math.round(v * 22))}px` } }, i)) }),
2044
- /* @__PURE__ */ jsx8("button", { type: "button", onClick: toggleRecording, "aria-label": t.stopAndSendVoice, className: "piloto-send flex h-8 w-8 shrink-0 items-center justify-center rounded-full", children: /* @__PURE__ */ jsx8(ArrowUp, { className: "h-4 w-4" }) })
2148
+ /* @__PURE__ */ jsx8(
2149
+ "button",
2150
+ {
2151
+ type: "button",
2152
+ onClick: toggleRecording,
2153
+ "aria-label": t.stopAndSendVoice,
2154
+ title: t.send,
2155
+ className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-brand-500 text-white hover:bg-brand-600",
2156
+ children: /* @__PURE__ */ jsx8(ArrowUp, { className: "h-4 w-4" })
2157
+ }
2158
+ )
2045
2159
  ] })
2046
2160
  ) : /* @__PURE__ */ jsx8(
2047
2161
  "textarea",
@@ -2060,12 +2174,12 @@ function Composer({
2060
2174
  onRemoveReference?.(references[references.length - 1].id);
2061
2175
  }
2062
2176
  },
2063
- className: "piloto-textarea max-h-60 min-h-[24px] w-full flex-none resize-none overflow-y-auto bg-transparent px-1 text-sm leading-6 text-text-primary outline-none placeholder:text-text-tertiary"
2177
+ className: "max-h-60 min-h-[24px] w-full flex-none resize-none overflow-y-auto bg-transparent px-1 text-sm leading-6 text-text-primary outline-none placeholder:text-text-tertiary"
2064
2178
  }
2065
2179
  ),
2066
2180
  /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-2", children: [
2067
- /* @__PURE__ */ jsxs6("div", { className: "flex min-w-0 flex-1 items-center gap-1.5 overflow-hidden", children: [
2068
- withFiles && /* @__PURE__ */ jsxs6(Fragment4, { children: [
2181
+ /* @__PURE__ */ jsxs6("div", { className: "@container flex min-w-0 flex-1 items-center gap-1.5 overflow-hidden", children: [
2182
+ withFiles && /* @__PURE__ */ jsxs6(Fragment5, { children: [
2069
2183
  /* @__PURE__ */ jsx8(
2070
2184
  "button",
2071
2185
  {
@@ -2078,10 +2192,11 @@ function Composer({
2078
2192
  disabled: busy || !canSeeImages || files.length >= maxFiles,
2079
2193
  "aria-label": canSeeImages ? t.attachImage : t.noImages,
2080
2194
  title: canSeeImages ? t.attachImage : t.noImages,
2081
- className: iconButton,
2195
+ className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-text-secondary transition-colors hover:bg-background-secondary hover:text-text-primary disabled:opacity-30",
2082
2196
  children: /* @__PURE__ */ jsx8(Image, { className: "h-4 w-4" })
2083
2197
  }
2084
2198
  ),
2199
+ extras,
2085
2200
  /* @__PURE__ */ jsx8(
2086
2201
  "button",
2087
2202
  {
@@ -2094,16 +2209,27 @@ function Composer({
2094
2209
  disabled: busy || files.length >= maxFiles,
2095
2210
  "aria-label": t.attachFile,
2096
2211
  title: t.attachFile,
2097
- className: iconButton,
2212
+ className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-text-secondary transition-colors hover:bg-background-secondary hover:text-text-primary disabled:opacity-40",
2098
2213
  children: /* @__PURE__ */ jsx8(Paperclip, { className: "h-4 w-4" })
2099
2214
  }
2100
2215
  )
2101
2216
  ] }),
2102
- extras,
2217
+ !withFiles && extras,
2103
2218
  models.length > 0 && onModelChange && /* @__PURE__ */ jsx8(ModelPicker, { models, current: currentModel, onChange: onModelChange })
2104
2219
  ] }),
2105
2220
  /* @__PURE__ */ jsxs6("div", { className: "flex shrink-0 items-center gap-1.5", children: [
2106
- canRecord && !recording && /* @__PURE__ */ jsx8("button", { type: "button", onClick: toggleRecording, disabled: busy || transcribing, "aria-label": t.recordVoice, title: t.voiceNote, className: `${iconButton} h-8 w-8`, children: transcribing ? /* @__PURE__ */ jsx8(LoaderCircle, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx8(Mic, { className: "h-4 w-4" }) }),
2221
+ canRecord && !recording && /* @__PURE__ */ jsx8(
2222
+ "button",
2223
+ {
2224
+ type: "button",
2225
+ onClick: toggleRecording,
2226
+ disabled: busy || transcribing,
2227
+ "aria-label": t.recordVoice,
2228
+ title: t.voiceNote,
2229
+ className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-text-secondary transition-colors hover:bg-background-secondary hover:text-text-primary disabled:opacity-40",
2230
+ children: transcribing ? /* @__PURE__ */ jsx8("span", { className: "h-3.5 w-3.5 animate-spin rounded-full border-2 border-current border-t-transparent" }) : /* @__PURE__ */ jsx8(Mic, { className: "h-4 w-4" })
2231
+ }
2232
+ ),
2107
2233
  /* @__PURE__ */ jsx8(
2108
2234
  "button",
2109
2235
  {
@@ -2111,8 +2237,7 @@ function Composer({
2111
2237
  onClick: busy ? onStop : () => void submit(),
2112
2238
  disabled: !busy && !canSend || uploading,
2113
2239
  "aria-label": busy ? t.stop : uploading ? t.uploading : t.send,
2114
- "data-ready": busy || canSend || uploading || void 0,
2115
- className: "piloto-send flex h-8 w-8 items-center justify-center rounded-full transition-colors",
2240
+ className: `gc-send flex h-8 w-8 items-center justify-center rounded-full transition-colors ${busy || canSend || uploading ? "bg-brand-500 text-white hover:bg-brand-600" : "bg-background-disabled text-text-disabled"}`,
2116
2241
  children: busy ? /* @__PURE__ */ jsx8(Square, { className: "h-3 w-3 fill-current" }) : uploading ? /* @__PURE__ */ jsx8(LoaderCircle, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx8(ArrowUp, { className: "h-4 w-4" })
2117
2242
  }
2118
2243
  )
@@ -2137,7 +2262,7 @@ function ModelPicker({ models, current, onChange }) {
2137
2262
  document.removeEventListener("keydown", escape);
2138
2263
  };
2139
2264
  }, [open]);
2140
- if (!models.length) return null;
2265
+ if (models.length === 0) return null;
2141
2266
  const active = models.find((m) => m.value === current) ?? null;
2142
2267
  return /* @__PURE__ */ jsxs6("div", { ref: box, className: "relative", children: [
2143
2268
  /* @__PURE__ */ jsxs6(
@@ -2146,7 +2271,7 @@ function ModelPicker({ models, current, onChange }) {
2146
2271
  type: "button",
2147
2272
  "aria-expanded": open,
2148
2273
  onClick: () => setOpen((v) => !v),
2149
- className: "flex max-w-56 items-center gap-1.5 rounded-full border border-border-primary px-2.5 py-1 text-xs text-text-secondary transition-colors hover:bg-background-secondary hover:text-text-primary",
2274
+ className: "flex max-w-56 items-center gap-1.5 rounded-full border border-border-primary px-2.5 py-1 text-xs text-text-secondary transition-colors outline-none hover:bg-background-secondary hover:text-text-primary",
2150
2275
  children: [
2151
2276
  /* @__PURE__ */ jsx8(Cpu, { className: "h-3.5 w-3.5 shrink-0" }),
2152
2277
  /* @__PURE__ */ jsx8("span", { className: "truncate", children: active?.name ?? t.model }),
@@ -2154,7 +2279,8 @@ function ModelPicker({ models, current, onChange }) {
2154
2279
  ]
2155
2280
  }
2156
2281
  ),
2157
- open && /* @__PURE__ */ jsx8("div", { className: "piloto-menu absolute bottom-full left-0 z-20 mb-1 max-h-80 min-w-52 overflow-y-auto rounded-(--piloto-radius-input) border border-border-primary bg-background-primary py-1 shadow-(--piloto-shadow-card)", children: models.map((m) => /* @__PURE__ */ jsxs6(
2282
+ open && // Hacia ARRIBA: el selector vive pegado al borde inferior del input.
2283
+ /* @__PURE__ */ jsx8("div", { className: "absolute bottom-full left-0 z-20 mb-1 max-h-80 min-w-52 overflow-y-auto rounded-xl border border-border-primary bg-background-primary py-1 shadow-lg", children: models.map((m) => /* @__PURE__ */ jsxs6(
2158
2284
  "button",
2159
2285
  {
2160
2286
  type: "button",
@@ -2173,14 +2299,30 @@ function ModelPicker({ models, current, onChange }) {
2173
2299
  ] });
2174
2300
  }
2175
2301
 
2302
+ // src/react/connectingGate.ts
2303
+ var CONNECTING_DELAY_MS = 1200;
2304
+ var CONNECTING_MIN_MS = 700;
2305
+ var initialGate = (now, connected) => ({ shownAt: null, waitingSince: connected ? null : now });
2306
+ function stepGate(g, connected, now, delay = CONNECTING_DELAY_MS, min = CONNECTING_MIN_MS) {
2307
+ const waitingSince = connected ? null : g.waitingSince ?? now;
2308
+ let shownAt = g.shownAt;
2309
+ if (shownAt === null && waitingSince !== null && now - waitingSince >= delay) shownAt = now;
2310
+ if (shownAt !== null && connected && now - shownAt >= min) shownAt = null;
2311
+ const gate = { shownAt, waitingSince };
2312
+ let recheckAt = null;
2313
+ if (shownAt === null && waitingSince !== null) recheckAt = waitingSince + delay;
2314
+ else if (shownAt !== null && connected) recheckAt = shownAt + min;
2315
+ return { gate, visible: shownAt !== null, recheckAt };
2316
+ }
2317
+
2176
2318
  // src/react/Status.tsx
2177
- import { AnimatePresence, motion } from "motion/react";
2319
+ import { AnimatePresence as AnimatePresence2, motion as motion2 } from "motion/react";
2178
2320
  import { useEffect as useEffect4, useState as useState7 } from "react";
2179
2321
  import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
2180
2322
  var WAKING_GIVEUP_S = 45;
2181
2323
  var STILL_WORKING_S = 90;
2182
2324
  function TypingDots() {
2183
- return /* @__PURE__ */ jsx9("div", { className: "piloto-typing", "aria-hidden": true, children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx9("span", { className: "piloto-typing-dot" }, i)) });
2325
+ return /* @__PURE__ */ jsx9("div", { className: "gc-typing flex gap-1", children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx9("span", { className: "gc-typing-dot h-2 w-2 animate-bounce rounded-full", style: { "--i": i } }, i)) });
2184
2326
  }
2185
2327
  function WaitLabel({
2186
2328
  phase,
@@ -2198,20 +2340,31 @@ function WaitLabel({
2198
2340
  }, []);
2199
2341
  const seconds = Math.max(0, Math.floor((now - (since || mounted)) / 1e3));
2200
2342
  const phrases = t.thinkingPhrases;
2201
- const what = phase !== "session" ? t.waitPhase[phase] : phrases?.length ? (
2202
- // Frases propias de la app (el widget de un cliente): rotan cada 4 s.
2203
- elsewhere || seconds >= STILL_WORKING_S ? t.stillWorking : phrases[Math.floor(seconds / 4) % phrases.length]
2204
- ) : elsewhere ? t.stillWorking : t.howItGoes(seconds);
2343
+ const what = phase !== "session" ? t.waitPhase[phase] : phrases?.length ? elsewhere || seconds >= STILL_WORKING_S ? t.stillWorking : phrases[Math.floor(seconds / 4) % phrases.length] : elsewhere ? t.stillWorking : t.howItGoes(seconds);
2205
2344
  const lost = phase === "waking" && seconds >= WAKING_GIVEUP_S;
2206
- return /* @__PURE__ */ jsx9("div", { className: "piloto-wait flex flex-col gap-0.5 text-sm text-text-secondary", children: lost ? /* @__PURE__ */ jsxs7("p", { className: "text-text-primary", children: [
2345
+ return /* @__PURE__ */ jsx9("div", { className: "flex flex-col gap-0.5 text-sm text-text-secondary", children: lost ? /* @__PURE__ */ jsxs7("p", { className: "text-text-primary", children: [
2207
2346
  t.cantStart,
2208
2347
  " ",
2209
2348
  /* @__PURE__ */ jsx9("button", { type: "button", onClick: onLost, className: "cursor-pointer underline underline-offset-2", children: t.retry })
2210
2349
  ] }) : (
2211
- // La frase cambia con fundido (sale y entra): de golpe se leía brusco.
2350
+ // La frase cambia con fundido (sale y entra), como en claude.ai.
2212
2351
  /* @__PURE__ */ jsxs7("p", { className: "flex items-center", children: [
2213
- /* @__PURE__ */ jsx9(AnimatePresence, { mode: "wait", initial: false, children: /* @__PURE__ */ jsx9(motion.span, { className: "piloto-wait-text", initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.3, ease: "easeInOut" }, children: what }, what) }),
2214
- showDuration && /* @__PURE__ */ jsx9("span", { className: "piloto-wait-time", children: formatDuration(seconds) })
2352
+ /* @__PURE__ */ jsx9(AnimatePresence2, { mode: "wait", initial: false, children: /* @__PURE__ */ jsx9(
2353
+ motion2.span,
2354
+ {
2355
+ className: "gc-wait-text",
2356
+ initial: { opacity: 0 },
2357
+ animate: { opacity: 1 },
2358
+ exit: { opacity: 0 },
2359
+ transition: { duration: 0.3, ease: "easeInOut" },
2360
+ children: what
2361
+ },
2362
+ what
2363
+ ) }),
2364
+ showDuration && /* @__PURE__ */ jsxs7("span", { className: "tabular-nums text-text-tertiary", children: [
2365
+ "\xA0\xB7 ",
2366
+ formatDuration(seconds)
2367
+ ] })
2215
2368
  ] })
2216
2369
  ) });
2217
2370
  }
@@ -2219,48 +2372,74 @@ var PHASES = ["waking", "connecting", "session"];
2219
2372
  function ConnectingState({ phase, error, avatar, onRetry }) {
2220
2373
  const { strings: t } = usePiloto();
2221
2374
  const current = PHASES.indexOf(phase);
2222
- return /* @__PURE__ */ jsxs7(motion.div, { initial: { opacity: 0, y: 8 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.3 }, className: "piloto-connecting flex min-h-[40vh] flex-col items-center justify-center gap-8 text-center", children: [
2223
- /* @__PURE__ */ jsxs7("div", { className: "relative flex h-20 w-20 items-center justify-center", children: [
2224
- !error && [0, 1].map((i) => /* @__PURE__ */ jsx9(
2225
- motion.span,
2226
- {
2227
- className: "absolute inset-0 rounded-full border border-border-primary",
2228
- initial: { scale: 0.6, opacity: 0.8 },
2229
- animate: { scale: 1.6, opacity: 0 },
2230
- transition: { duration: 2.2, repeat: Infinity, ease: "easeOut", delay: i * 1.1 }
2231
- },
2232
- i
2233
- )),
2234
- /* @__PURE__ */ jsx9(
2235
- motion.div,
2236
- {
2237
- className: "grid h-12 w-12 place-items-center",
2238
- animate: error ? { scale: 1, filter: "grayscale(1)" } : { scale: [1, 1.06, 1] },
2239
- transition: error ? { duration: 0.3 } : { duration: 2.2, repeat: Infinity, ease: "easeInOut" },
2240
- children: avatar ?? /* @__PURE__ */ jsx9("span", { className: "piloto-avatar-default" })
2241
- }
2242
- )
2243
- ] }),
2244
- /* @__PURE__ */ jsx9("ol", { className: "flex flex-col gap-3 text-left", children: t.connectSteps.map((step, i) => {
2245
- const done = !error && i < current;
2246
- const active = !error && i === current;
2247
- const failed = !!error && i === current;
2248
- return /* @__PURE__ */ jsxs7("li", { className: "flex items-center gap-3", children: [
2249
- /* @__PURE__ */ jsx9("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center", children: done ? /* @__PURE__ */ jsx9("span", { className: "piloto-pop flex h-5 w-5 items-center justify-center rounded-full bg-background-success", children: /* @__PURE__ */ jsx9(Check, { className: "h-3 w-3 text-text-inverse", strokeWidth: 3 }) }) : active ? /* @__PURE__ */ jsx9("span", { className: "piloto-pulse h-2.5 w-2.5 rounded-full bg-text-primary" }) : failed ? /* @__PURE__ */ jsx9("span", { className: "h-2.5 w-2.5 rounded-full bg-text-danger" }) : /* @__PURE__ */ jsx9("span", { className: "h-2 w-2 rounded-full bg-border-primary" }) }),
2250
- /* @__PURE__ */ jsxs7("div", { className: "leading-tight", children: [
2251
- /* @__PURE__ */ jsxs7("p", { className: `text-sm ${active || failed ? "text-text-primary" : done ? "text-text-secondary" : "text-text-tertiary"}`, children: [
2252
- step.label,
2253
- active && /* @__PURE__ */ jsx9("span", { className: "piloto-ellipsis inline-block w-4 text-left", children: "\u2026" })
2254
- ] }),
2255
- active && /* @__PURE__ */ jsx9("p", { className: "text-xs text-text-tertiary", children: step.hint })
2375
+ return /* @__PURE__ */ jsxs7(
2376
+ motion2.div,
2377
+ {
2378
+ initial: { opacity: 0, y: 8 },
2379
+ animate: { opacity: 1, y: 0 },
2380
+ exit: { opacity: 0, y: -8 },
2381
+ transition: { duration: 0.3 },
2382
+ className: "flex min-h-[50vh] flex-col items-center justify-center gap-8 text-center",
2383
+ children: [
2384
+ /* @__PURE__ */ jsxs7("div", { className: "relative flex h-20 w-20 items-center justify-center", children: [
2385
+ !error && [0, 1].map((i) => /* @__PURE__ */ jsx9(
2386
+ motion2.span,
2387
+ {
2388
+ className: "absolute inset-0 rounded-full border border-border-primary",
2389
+ initial: { scale: 0.6, opacity: 0.8 },
2390
+ animate: { scale: 1.6, opacity: 0 },
2391
+ transition: { duration: 2.2, repeat: Infinity, ease: "easeOut", delay: i * 1.1 }
2392
+ },
2393
+ i
2394
+ )),
2395
+ /* @__PURE__ */ jsx9(
2396
+ motion2.div,
2397
+ {
2398
+ className: "grid h-12 w-12 place-items-center",
2399
+ animate: error ? { scale: 1, filter: "grayscale(1)" } : { scale: [1, 1.06, 1] },
2400
+ transition: error ? { duration: 0.3 } : { duration: 2.2, repeat: Infinity, ease: "easeInOut" },
2401
+ children: avatar ?? /* @__PURE__ */ jsx9("span", { className: "h-12 w-12 rounded-full bg-brand-500" })
2402
+ }
2403
+ )
2404
+ ] }),
2405
+ /* @__PURE__ */ jsx9("ol", { className: "flex flex-col gap-3 text-left", children: t.connectSteps.map((step, i) => {
2406
+ const done = !error && i < current;
2407
+ const active = !error && i === current;
2408
+ const failed = !!error && i === current;
2409
+ return /* @__PURE__ */ jsxs7("li", { className: "flex items-center gap-3", children: [
2410
+ /* @__PURE__ */ jsx9("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center", children: /* @__PURE__ */ jsx9(AnimatePresence2, { mode: "wait", initial: false, children: done ? /* @__PURE__ */ jsx9(motion2.span, { initial: { scale: 0 }, animate: { scale: 1 }, className: "flex h-5 w-5 items-center justify-center rounded-full bg-background-success", children: /* @__PURE__ */ jsx9(Check, { className: "h-3 w-3 text-text-success", strokeWidth: 3 }) }, "done") : active ? /* @__PURE__ */ jsx9(
2411
+ motion2.span,
2412
+ {
2413
+ className: "h-2.5 w-2.5 rounded-full bg-text-primary",
2414
+ animate: { scale: [1, 1.5, 1], opacity: [1, 0.5, 1] },
2415
+ transition: { duration: 1.1, repeat: Infinity, ease: "easeInOut" }
2416
+ },
2417
+ "active"
2418
+ ) : failed ? /* @__PURE__ */ jsx9("span", { className: "h-2.5 w-2.5 rounded-full bg-text-danger" }, "failed") : /* @__PURE__ */ jsx9("span", { className: "h-2 w-2 rounded-full bg-border-primary" }, "idle") }) }),
2419
+ /* @__PURE__ */ jsxs7("div", { className: "leading-tight", children: [
2420
+ /* @__PURE__ */ jsxs7("p", { className: `text-sm ${active || failed ? "text-text-primary" : done ? "text-text-secondary" : "text-text-tertiary"}`, children: [
2421
+ step.label,
2422
+ active && /* @__PURE__ */ jsx9(
2423
+ motion2.span,
2424
+ {
2425
+ className: "inline-block w-4 text-left",
2426
+ animate: { opacity: [0, 1, 1, 0] },
2427
+ transition: { duration: 1.4, repeat: Infinity, times: [0, 0.2, 0.8, 1] },
2428
+ children: "\u2026"
2429
+ }
2430
+ )
2431
+ ] }),
2432
+ active && /* @__PURE__ */ jsx9("p", { className: "text-xs text-text-tertiary", children: step.hint })
2433
+ ] })
2434
+ ] }, i);
2435
+ }) }),
2436
+ error && /* @__PURE__ */ jsxs7(motion2.div, { initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, className: "flex max-w-md flex-col items-center gap-3", children: [
2437
+ /* @__PURE__ */ jsx9("p", { className: "text-sm text-text-danger", children: error }),
2438
+ onRetry && /* @__PURE__ */ jsx9("button", { type: "button", onClick: onRetry, className: "rounded-full border border-border-primary px-4 py-1.5 text-sm text-text-primary hover:bg-background-secondary", children: t.connectRetry })
2256
2439
  ] })
2257
- ] }, i);
2258
- }) }),
2259
- error && /* @__PURE__ */ jsxs7("div", { className: "flex max-w-md flex-col items-center gap-3", children: [
2260
- /* @__PURE__ */ jsx9("p", { className: "text-sm text-text-danger", children: error }),
2261
- onRetry && /* @__PURE__ */ jsx9("button", { type: "button", onClick: onRetry, className: "rounded-full border border-border-primary px-4 py-1.5 text-sm text-text-primary hover:bg-background-secondary", children: t.connectRetry })
2262
- ] })
2263
- ] });
2440
+ ]
2441
+ }
2442
+ );
2264
2443
  }
2265
2444
 
2266
2445
  // src/react/usePilot.ts
@@ -2436,7 +2615,7 @@ function useSseTransport(base, opts) {
2436
2615
  }
2437
2616
 
2438
2617
  // src/react/Piloto.tsx
2439
- import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
2618
+ import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
2440
2619
  var useIsoLayoutEffect = typeof window === "undefined" ? useEffect6 : useLayoutEffect;
2441
2620
  var ANCHOR_GAP = 24;
2442
2621
  var Piloto = forwardRef3(function Piloto2(props, handle) {
@@ -2603,59 +2782,78 @@ var Piloto = forwardRef3(function Piloto2(props, handle) {
2603
2782
  const pageInProgress = last?.role === "assistant" && (Boolean(last.planning) || (last.pages ?? []).some((p) => !p.error && (!p.readyAt || p.review?.status === "running")));
2604
2783
  const toolRunning = busy && last?.role === "assistant" && ((last.tools ?? []).some(isRunning) || pageInProgress);
2605
2784
  const empty = turns.length === 0 && !busy;
2606
- const placeholder = !connected ? t.placeholderConnecting : props.placeholder ?? (props.agentName ? t.placeholder(props.agentName) : t.placeholderDefault);
2785
+ const perTurn = !external && transport?.stream === "per-turn";
2786
+ const ready = connected || perTurn;
2787
+ const placeholder = !ready ? t.placeholderConnecting : props.placeholder ?? (props.agentName ? t.placeholder(props.agentName) : t.placeholderDefault);
2607
2788
  const showFiles = features.attachments ?? Boolean(props.upload);
2608
- const [slowConnect, setSlowConnect] = useState9(false);
2789
+ const gateRef = useRef5(initialGate(Date.now(), ready));
2790
+ const [showConnecting, setShowConnecting] = useState9(false);
2609
2791
  useEffect6(() => {
2610
- if (connected) return setSlowConnect(false);
2611
- const id = setTimeout(() => setSlowConnect(true), 800);
2792
+ let id;
2793
+ const tick = () => {
2794
+ const r = stepGate(gateRef.current, ready, Date.now());
2795
+ gateRef.current = r.gate;
2796
+ setShowConnecting(r.visible);
2797
+ if (r.recheckAt !== null) id = setTimeout(tick, Math.max(0, r.recheckAt - Date.now()));
2798
+ };
2799
+ tick();
2612
2800
  return () => clearTimeout(id);
2613
- }, [connected]);
2614
- const composer = /* @__PURE__ */ jsx10("div", { ref: composerBox, children: /* @__PURE__ */ jsx10(
2615
- Composer,
2616
- {
2617
- initialValue: draft.text,
2618
- onSubmit: send,
2619
- onStop: pilot.stop,
2620
- busy,
2621
- canSteer: (external ? true : transport?.steer) !== false,
2622
- placeholder,
2623
- canSeeImages: state.canSeeImages,
2624
- attachments: showFiles,
2625
- upload: props.upload,
2626
- transcribe: props.transcribe,
2627
- voiceNoteText: props.voiceNoteText,
2628
- models: features.models === false ? [] : state.models,
2629
- currentModel: state.currentModel,
2630
- onModelChange: pilot.setModel,
2631
- references: refs,
2632
- onRemoveReference: (id) => setRefs(refsRef.current.filter((r) => r.id !== id)),
2633
- onActivateReference: props.onReferenceClick,
2634
- extras: slots.composerExtras
2635
- },
2636
- draft.n
2637
- ) });
2801
+ }, [ready]);
2802
+ const pointedRefs = refs.filter((r) => r.prompt);
2803
+ const plainRefs = refs.filter((r) => !r.prompt);
2804
+ const removeRef = (id) => setRefs(refsRef.current.filter((r) => r.id !== id));
2805
+ const composer = /* @__PURE__ */ jsxs8("div", { ref: composerBox, children: [
2806
+ /* @__PURE__ */ jsx10(ReferenceChips, { references: pointedRefs, onRemove: removeRef, onActivate: props.onReferenceClick }),
2807
+ /* @__PURE__ */ jsx10(
2808
+ Composer,
2809
+ {
2810
+ initialValue: draft.text,
2811
+ onSubmit: send,
2812
+ onStop: pilot.stop,
2813
+ busy,
2814
+ canSteer: (external ? true : transport?.steer) !== false,
2815
+ placeholder,
2816
+ canSeeImages: state.canSeeImages,
2817
+ attachments: showFiles,
2818
+ upload: props.upload,
2819
+ transcribe: props.transcribe,
2820
+ voiceNoteText: props.voiceNoteText,
2821
+ models: features.models === false ? [] : state.models,
2822
+ currentModel: state.currentModel,
2823
+ onModelChange: pilot.setModel,
2824
+ references: plainRefs,
2825
+ onRemoveReference: removeRef,
2826
+ onActivateReference: props.onReferenceClick,
2827
+ extras: slots.composerExtras
2828
+ },
2829
+ draft.n
2830
+ )
2831
+ ] });
2638
2832
  const permissionCards = cards.map((p) => /* @__PURE__ */ jsx10(ConfirmCard, { request: p, onRespond: respond, onSettled: settle, onExpire: pilot.expirePermission }, p.id));
2639
2833
  return /* @__PURE__ */ jsx10(PilotoContext.Provider, { value: config, children: /* @__PURE__ */ jsx10("div", { ...rootProps(theme, props.skin), "data-busy": busy || void 0, className: `piloto ${props.className ?? ""}`, style: props.style, children: empty ? (
2640
- // Si no cabe (panel bajo, saludo largo), se desplaza en vez de recortarse: el centrado es con
2641
- // márgenes automáticos, que nunca empujan contenido fuera del contenedor.
2642
- /* @__PURE__ */ jsxs8("div", { className: "piloto-empty", children: [
2834
+ // Un hilo vacío enseña lo mismo que la portada: la cara, el saludo, la caja y por dónde
2835
+ // empezar. Si no cabe (panel bajo), se desplaza: `safe center` nunca empuja nada fuera.
2836
+ /* @__PURE__ */ jsxs8("div", { className: "gs-scroll flex min-h-0 flex-1 flex-col items-center justify-center overflow-y-auto px-4 pb-[10vh] [justify-content:safe_center]", children: [
2643
2837
  slots.headerActions && /* @__PURE__ */ jsx10("div", { className: "absolute right-4 top-3 flex gap-2", children: slots.headerActions }),
2644
- /* @__PURE__ */ jsxs8("div", { className: "piloto-empty-inner", children: [
2645
- !connected && slowConnect ? /* @__PURE__ */ jsx10(ConnectingState, { phase, error, avatar: props.avatar }) : slots.emptyState ?? /* @__PURE__ */ jsxs8("div", { className: "piloto-welcome mb-6 flex flex-col items-center gap-3 text-center", children: [
2646
- props.avatar,
2647
- props.welcome && // Un saludo largo (una explicación) va en letra de lectura; uno corto, en la de cartel.
2648
- /* @__PURE__ */ jsx10("div", { className: "piloto-welcome-text", "data-long": typeof props.welcome === "string" && props.welcome.length > 60 ? "" : void 0, children: props.welcome })
2649
- ] }),
2650
- /* @__PURE__ */ jsxs8("div", { className: "w-full max-w-3xl", children: [
2651
- slots.aboveComposer,
2652
- composer,
2653
- props.suggestions && /* @__PURE__ */ jsx10(Suggestions, { items: props.suggestions, onPick: (s) => send(s), onPrefill: (s) => setDraftState((d) => ({ text: s, n: d.n + 1 })) })
2654
- ] })
2838
+ /* @__PURE__ */ jsx10(AnimatePresence3, { mode: "wait", initial: false, children: showConnecting ? /* @__PURE__ */ jsx10(ConnectingState, { phase, error, avatar: props.avatar }, "connecting") : /* @__PURE__ */ jsx10("div", { children: slots.emptyState ?? /* @__PURE__ */ jsxs8("div", { className: "mb-6 flex flex-col items-center", children: [
2839
+ props.avatar && /* @__PURE__ */ jsx10("div", { className: "mb-3", children: props.avatar }),
2840
+ props.welcome && // Un saludo largo (una explicación del copiloto) baja a letra de lectura.
2841
+ /* @__PURE__ */ jsx10(
2842
+ "h1",
2843
+ {
2844
+ className: typeof props.welcome === "string" && props.welcome.length > 60 ? "max-w-xl text-center text-base font-medium leading-6 text-metal" : "text-center text-3xl font-extrabold tracking-tight text-dark",
2845
+ children: props.welcome
2846
+ }
2847
+ )
2848
+ ] }) }, "welcome") }),
2849
+ /* @__PURE__ */ jsxs8("div", { className: "w-full max-w-3xl", children: [
2850
+ slots.aboveComposer,
2851
+ composer,
2852
+ props.suggestions && /* @__PURE__ */ jsx10(Suggestions, { items: props.suggestions, onPick: (s) => send(s), onPrefill: (s) => setDraftState((d) => ({ text: s, n: d.n + 1 })) })
2655
2853
  ] })
2656
2854
  ] })
2657
- ) : /* @__PURE__ */ jsxs8(Fragment5, { children: [
2658
- slots.headerActions && /* @__PURE__ */ jsx10("div", { className: "flex shrink-0 justify-end gap-2 px-4 pt-3", children: slots.headerActions }),
2855
+ ) : /* @__PURE__ */ jsxs8(Fragment6, { children: [
2856
+ slots.headerActions && /* @__PURE__ */ jsx10("div", { className: "flex shrink-0 justify-end gap-2 px-4 pt-3 sm:px-6", children: slots.headerActions }),
2659
2857
  /* @__PURE__ */ jsxs8(
2660
2858
  "div",
2661
2859
  {
@@ -2670,9 +2868,9 @@ var Piloto = forwardRef3(function Piloto2(props, handle) {
2670
2868
  if (touchY.current != null && y != null && y > touchY.current + 4) release();
2671
2869
  },
2672
2870
  onKeyDown: (e) => ["ArrowUp", "PageUp", "Home"].includes(e.key) && release(),
2673
- className: "piloto-scroll relative min-h-0 flex-1 overflow-y-auto overflow-x-hidden",
2871
+ className: "gs-scroll relative min-h-0 flex-1 overflow-y-auto overflow-x-hidden",
2674
2872
  children: [
2675
- /* @__PURE__ */ jsxs8("div", { ref: column, className: "piloto-column mx-auto flex w-full flex-col gap-6 px-4 py-6", children: [
2873
+ /* @__PURE__ */ jsxs8("div", { ref: column, className: "mx-auto flex w-full max-w-[784px] flex-col gap-6 px-4 py-8 sm:px-6", children: [
2676
2874
  turns.map((turn, i) => {
2677
2875
  const isLast = i === turns.length - 1;
2678
2876
  const live = busy && isLast;
@@ -2685,6 +2883,7 @@ var Piloto = forwardRef3(function Piloto2(props, handle) {
2685
2883
  onOption: isLast && !busy && features.replyOptions !== false ? (text) => send(text) : void 0,
2686
2884
  showUsage: features.usage !== false,
2687
2885
  showCopy: features.copy !== false,
2886
+ showDuration: features.duration !== false,
2688
2887
  renderDeliveries: slots.renderDeliveries
2689
2888
  }
2690
2889
  ) }, i);
@@ -2694,26 +2893,26 @@ var Piloto = forwardRef3(function Piloto2(props, handle) {
2694
2893
  /* @__PURE__ */ jsx10(TypingDots, {}),
2695
2894
  /* @__PURE__ */ jsx10(WaitLabel, { phase, since: state.turnStartedAt, elsewhere: state.elsewhere, onLost: pilot.abandonAndRetry, showDuration: features.duration !== false })
2696
2895
  ] }),
2697
- interrupted && !busy && /* @__PURE__ */ jsxs8("p", { className: "piloto-interrupted text-sm text-text-secondary", children: [
2896
+ interrupted && !busy && /* @__PURE__ */ jsxs8("p", { className: "text-sm text-text-secondary", children: [
2698
2897
  /me quedé a medias|i stopped halfway/i.test(last?.text ?? "") ? t.interruptedOurFault : t.interrupted(interrupted.reason),
2699
2898
  " ",
2700
2899
  /* @__PURE__ */ jsx10("button", { type: "button", onClick: pilot.resume, className: "cursor-pointer text-text-primary underline underline-offset-2", children: interrupted.canContinue ? t.continueTurn : t.resume })
2701
2900
  ] }),
2702
- notice && /* @__PURE__ */ jsx10("p", { className: "piloto-notice text-sm text-text-tertiary", children: notice }),
2703
- error && /* @__PURE__ */ jsx10("p", { className: "piloto-error text-sm text-text-danger", children: error })
2901
+ notice && /* @__PURE__ */ jsx10("p", { className: "text-sm text-text-tertiary", children: notice }),
2902
+ error && /* @__PURE__ */ jsx10("p", { className: "text-sm text-text-danger", children: error })
2704
2903
  ] }),
2705
2904
  /* @__PURE__ */ jsx10("div", { ref: spacer, "aria-hidden": true })
2706
2905
  ]
2707
2906
  }
2708
2907
  ),
2709
- /* @__PURE__ */ jsxs8("div", { className: "piloto-dock relative mx-auto w-full px-4 pb-4", children: [
2908
+ /* @__PURE__ */ jsxs8("div", { className: "relative mx-auto w-full max-w-[784px] px-4 pb-4 sm:px-6 sm:pb-6", children: [
2710
2909
  !atBottom && /* @__PURE__ */ jsx10(
2711
2910
  "button",
2712
2911
  {
2713
2912
  type: "button",
2714
2913
  onClick: toBottom,
2715
2914
  "aria-label": t.goToLatest,
2716
- className: "piloto-to-bottom absolute -top-12 left-1/2 z-10 flex h-9 w-9 -translate-x-1/2 items-center justify-center rounded-full border border-border-primary bg-background-secondary text-text-secondary shadow-(--piloto-shadow-card) transition hover:text-text-primary",
2915
+ className: "absolute -top-12 left-1/2 z-10 flex h-9 w-9 -translate-x-1/2 items-center justify-center rounded-full border border-border-primary bg-background-secondary text-text-secondary shadow-lg transition hover:text-text-primary",
2717
2916
  children: /* @__PURE__ */ jsx10(ArrowDown, { className: "h-4 w-4" })
2718
2917
  }
2719
2918
  ),