@rslsp1/fa-app-tools 2.0.57 → 2.0.62

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.
package/dist/index.js CHANGED
@@ -1033,10 +1033,8 @@ var CompactDropdown = ({
1033
1033
  };
1034
1034
 
1035
1035
  // src/components/HistoryPanel.tsx
1036
- var import_react4 = require("react");
1037
- var import_react5 = require("motion/react");
1036
+ var import_react4 = require("motion/react");
1038
1037
  var import_jsx_runtime5 = require("react/jsx-runtime");
1039
- var PAGE_SIZE = 20;
1040
1038
  var formatFriendlyTimestamp = (timestamp) => {
1041
1039
  const date = new Date(timestamp);
1042
1040
  const now = /* @__PURE__ */ new Date();
@@ -1048,8 +1046,7 @@ var formatFriendlyTimestamp = (timestamp) => {
1048
1046
  if (date.toDateString() === yesterday.toDateString()) return `Gestern, ${timeStr}`;
1049
1047
  return `${date.toLocaleDateString([], { day: "2-digit", month: "2-digit" })}, ${timeStr}`;
1050
1048
  };
1051
- var HistoryPanel = ({ history, currentResultId, onSelect, onDelete }) => {
1052
- const [visibleCount, setVisibleCount] = (0, import_react4.useState)(PAGE_SIZE);
1049
+ var HistoryPanel = ({ history, currentResultId, onSelect, onDelete, visibleCount, onLoadMore }) => {
1053
1050
  const visibleHistory = history.slice(0, visibleCount);
1054
1051
  if (history.length === 0) {
1055
1052
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col items-center justify-center py-20 text-center gap-4 opacity-10", children: [
@@ -1057,7 +1054,7 @@ var HistoryPanel = ({ history, currentResultId, onSelect, onDelete }) => {
1057
1054
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[10px] font-bold uppercase tracking-widest", children: "Keine Historie" })
1058
1055
  ] });
1059
1056
  }
1060
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react5.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 p-4 flex flex-col gap-3 overflow-y-auto dark-scrollbar", children: [
1057
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react4.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 p-4 flex flex-col gap-3 overflow-y-auto dark-scrollbar", children: [
1061
1058
  visibleHistory.map((gen) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1062
1059
  "div",
1063
1060
  {
@@ -1093,7 +1090,7 @@ var HistoryPanel = ({ history, currentResultId, onSelect, onDelete }) => {
1093
1090
  },
1094
1091
  gen.id
1095
1092
  )),
1096
- visibleCount < history.length && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { type: "button", onClick: () => setVisibleCount((c) => c + PAGE_SIZE), className: "w-full py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-xl text-[10px] font-bold uppercase text-white/60 hover:text-white transition-all", children: [
1093
+ visibleCount < history.length && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { type: "button", onClick: onLoadMore, className: "w-full py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-xl text-[10px] font-bold uppercase text-white/60 hover:text-white transition-all", children: [
1097
1094
  history.length - visibleCount,
1098
1095
  " weitere laden"
1099
1096
  ] })
@@ -1101,11 +1098,11 @@ var HistoryPanel = ({ history, currentResultId, onSelect, onDelete }) => {
1101
1098
  };
1102
1099
 
1103
1100
  // src/components/InspectPanel.tsx
1104
- var import_react6 = require("react");
1105
- var import_react7 = require("motion/react");
1101
+ var import_react5 = require("react");
1102
+ var import_react6 = require("motion/react");
1106
1103
  var import_jsx_runtime6 = require("react/jsx-runtime");
1107
1104
  var InspectPanel = ({ currentResult, history, onSelect, workspaceTags, onTagToggle }) => {
1108
- const currentIndex = (0, import_react6.useMemo)(() => history.findIndex((h) => h.id === currentResult?.id), [history, currentResult]);
1105
+ const currentIndex = (0, import_react5.useMemo)(() => history.findIndex((h) => h.id === currentResult?.id), [history, currentResult]);
1109
1106
  if (!currentResult) {
1110
1107
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col items-center justify-center py-20 text-center gap-4 opacity-10", children: [
1111
1108
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "material-symbols-outlined text-[64px]", children: "info" }),
@@ -1113,7 +1110,7 @@ var InspectPanel = ({ currentResult, history, onSelect, workspaceTags, onTagTogg
1113
1110
  ] });
1114
1111
  }
1115
1112
  const fullDateStr = new Date(currentResult.timestamp).toLocaleString([], { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit", second: "2-digit" });
1116
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react7.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 flex flex-col overflow-hidden", children: [
1113
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react6.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 flex flex-col overflow-hidden", children: [
1117
1114
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex-shrink-0 border-b border-white/5 bg-black/20 py-3 px-4", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex gap-2 overflow-x-auto no-scrollbar pb-1", children: history.map((gen) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: () => onSelect(gen), className: `w-10 h-10 rounded-lg overflow-hidden border shrink-0 transition-all ${currentResult.id === gen.id ? "border-white scale-105 shadow-lg" : "border-white/5 opacity-40 hover:opacity-100"}`, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("img", { src: gen.base64 ? gen.base64.startsWith("data:") ? gen.base64 : `data:image/png;base64,${gen.base64}` : "", className: "w-full h-full object-cover", alt: "Thumbnail" }) }, gen.id)) }) }),
1118
1115
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex-1 overflow-y-auto p-4 flex flex-col gap-6 dark-scrollbar pb-10", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col gap-4", children: [
1119
1116
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SectionLabel, { children: "Vorschau" }),
@@ -1166,8 +1163,8 @@ var InspectPanel = ({ currentResult, history, onSelect, workspaceTags, onTagTogg
1166
1163
  };
1167
1164
 
1168
1165
  // src/components/SetupPanel.tsx
1169
- var import_react8 = require("react");
1170
- var import_react9 = require("motion/react");
1166
+ var import_react7 = require("react");
1167
+ var import_react8 = require("motion/react");
1171
1168
  var import_jsx_runtime7 = require("react/jsx-runtime");
1172
1169
  var PRESET_URLS = [
1173
1170
  "https://jsonplaceholder.typicode.com/todos/1",
@@ -1175,12 +1172,12 @@ var PRESET_URLS = [
1175
1172
  "https://esm.sh/@rslsp1/fa-app-tools@latest"
1176
1173
  ];
1177
1174
  var SetupPanel = ({ onWorkspaceImport, buildInfo }) => {
1178
- const workspaceInputRef = (0, import_react8.useRef)(null);
1179
- const [urlInput, setUrlInput] = (0, import_react8.useState)("");
1180
- const [tokenInput, setTokenInput] = (0, import_react8.useState)("");
1181
- const [testStatus, setTestStatus] = (0, import_react8.useState)("idle");
1182
- const [result, setResult] = (0, import_react8.useState)(null);
1183
- const [fetchError, setFetchError] = (0, import_react8.useState)(null);
1175
+ const workspaceInputRef = (0, import_react7.useRef)(null);
1176
+ const [urlInput, setUrlInput] = (0, import_react7.useState)("");
1177
+ const [tokenInput, setTokenInput] = (0, import_react7.useState)("");
1178
+ const [testStatus, setTestStatus] = (0, import_react7.useState)("idle");
1179
+ const [result, setResult] = (0, import_react7.useState)(null);
1180
+ const [fetchError, setFetchError] = (0, import_react7.useState)(null);
1184
1181
  const runTest = async (url) => {
1185
1182
  if (!url.trim()) return;
1186
1183
  setTestStatus("loading");
@@ -1220,7 +1217,7 @@ var SetupPanel = ({ onWorkspaceImport, buildInfo }) => {
1220
1217
  setTestStatus("error");
1221
1218
  }
1222
1219
  };
1223
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react9.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 p-6 flex flex-col gap-10 overflow-y-auto", children: [
1220
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react8.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 p-6 flex flex-col gap-10 overflow-y-auto", children: [
1224
1221
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-4", children: [
1225
1222
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-1", children: [
1226
1223
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SectionLabel, { children: "Workspace Management" }),
@@ -1343,8 +1340,7 @@ var SetupPanel = ({ onWorkspaceImport, buildInfo }) => {
1343
1340
  };
1344
1341
 
1345
1342
  // src/components/MediaLibrary.tsx
1346
- var import_react10 = require("react");
1347
- var import_react11 = require("motion/react");
1343
+ var import_react9 = require("motion/react");
1348
1344
 
1349
1345
  // src/lib/grouping.ts
1350
1346
  function groupByPrompt(items) {
@@ -1369,9 +1365,7 @@ function groupByPrompt(items) {
1369
1365
 
1370
1366
  // src/components/MediaLibrary.tsx
1371
1367
  var import_jsx_runtime8 = require("react/jsx-runtime");
1372
- var PAGE_SIZE2 = 20;
1373
- var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, onBatchDownload, onGenerateReference }) => {
1374
- const [visibleCount, setVisibleCount] = (0, import_react10.useState)(PAGE_SIZE2);
1368
+ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, onBatchDownload, onGenerateReference, visibleCount, onLoadMore }) => {
1375
1369
  const selectedCount = items.filter((i) => i.selectedForExport).length;
1376
1370
  const groups = groupByPrompt(items);
1377
1371
  const visibleGroups = groups.slice(0, visibleCount);
@@ -1392,7 +1386,7 @@ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, on
1392
1386
  "Laden"
1393
1387
  ] })
1394
1388
  ] }),
1395
- selectedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react11.motion.div, { initial: { opacity: 0, y: -10 }, animate: { opacity: 1, y: 0 }, className: "flex items-center justify-between bg-blue-500/10 border border-blue-500/20 p-2 rounded-xl", children: [
1389
+ selectedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react9.motion.div, { initial: { opacity: 0, y: -10 }, animate: { opacity: 1, y: 0 }, className: "flex items-center justify-between bg-blue-500/10 border border-blue-500/20 p-2 rounded-xl", children: [
1396
1390
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "text-[9px] font-bold uppercase text-blue-400 ml-1", children: [
1397
1391
  selectedCount,
1398
1392
  " ausgew\xE4hlt"
@@ -1413,7 +1407,7 @@ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, on
1413
1407
  visibleGroups.map((group) => {
1414
1408
  const rep = group.representative;
1415
1409
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1416
- import_react11.motion.div,
1410
+ import_react9.motion.div,
1417
1411
  {
1418
1412
  initial: { opacity: 0, scale: 0.9 },
1419
1413
  animate: { opacity: 1, scale: 1 },
@@ -1444,7 +1438,7 @@ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, on
1444
1438
  rep.id
1445
1439
  );
1446
1440
  }),
1447
- visibleCount < groups.length && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "col-span-2 flex justify-center pt-2 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("button", { type: "button", onClick: () => setVisibleCount((c) => c + PAGE_SIZE2), className: "px-4 py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-lg text-[10px] font-bold uppercase text-white/60 hover:text-white transition-all", children: [
1441
+ visibleCount < groups.length && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "col-span-2 flex justify-center pt-2 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("button", { type: "button", onClick: onLoadMore, className: "px-4 py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-lg text-[10px] font-bold uppercase text-white/60 hover:text-white transition-all", children: [
1448
1442
  groups.length - visibleCount,
1449
1443
  " weitere laden"
1450
1444
  ] }) })
@@ -1453,10 +1447,10 @@ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, on
1453
1447
  };
1454
1448
 
1455
1449
  // src/components/ListView.tsx
1456
- var import_react12 = require("react");
1450
+ var import_react10 = require("react");
1457
1451
  var import_jsx_runtime9 = require("react/jsx-runtime");
1458
1452
  var ListNode = ({ node, depth, onNodeChange, onAddChild, onDeleteNode, onMoveNode, onIndentNode, onOutdentNode, onAddSibling, isActive, isInPath, onFocus, onGenerate, onGenerateBranch, onGenerateSubtree, isGenerating, isCollapsed, toggleCollapse, renderNode, children }) => {
1459
- const inputRef = (0, import_react12.useRef)(null);
1453
+ const inputRef = (0, import_react10.useRef)(null);
1460
1454
  const hasChildren = children && children.length > 0;
1461
1455
  const handleKeyDown = (e) => {
1462
1456
  if (e.key === "Tab") {
@@ -1484,7 +1478,7 @@ var ListNode = ({ node, depth, onNodeChange, onAddChild, onDeleteNode, onMoveNod
1484
1478
  onMoveNode(node.id, "down");
1485
1479
  }
1486
1480
  };
1487
- (0, import_react12.useEffect)(() => {
1481
+ (0, import_react10.useEffect)(() => {
1488
1482
  if (isActive && inputRef.current) inputRef.current.focus();
1489
1483
  }, [isActive]);
1490
1484
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col w-full", children: [
@@ -1518,7 +1512,7 @@ var ListNode = ({ node, depth, onNodeChange, onAddChild, onDeleteNode, onMoveNod
1518
1512
  ] });
1519
1513
  };
1520
1514
  function ListView({ nodes, edges, onNodeChange, onAddChild, onDeleteNode, onMoveNode, onIndentNode, onOutdentNode, onAddSibling, focusedNodeId, onFocus, activePath, onGenerate, onGenerateBranch, onGenerateSubtree, isGeneratingNodeId }) {
1521
- const [collapsed, setCollapsed] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
1515
+ const [collapsed, setCollapsed] = (0, import_react10.useState)(/* @__PURE__ */ new Set());
1522
1516
  const toggleCollapse = (id) => {
1523
1517
  setCollapsed((prev) => {
1524
1518
  const next = new Set(prev);
@@ -1546,13 +1540,13 @@ function ListView({ nodes, edges, onNodeChange, onAddChild, onDeleteNode, onMove
1546
1540
  }
1547
1541
 
1548
1542
  // src/components/AvatarArchitectApp.tsx
1549
- var import_react27 = require("react");
1543
+ var import_react26 = require("react");
1550
1544
 
1551
1545
  // src/components/PromptTab.tsx
1552
- var import_react14 = require("react");
1546
+ var import_react12 = require("react");
1553
1547
 
1554
1548
  // src/components/CollapsibleCard.tsx
1555
- var import_react13 = require("react");
1549
+ var import_react11 = require("react");
1556
1550
  var import_jsx_runtime10 = require("react/jsx-runtime");
1557
1551
  var CollapsibleCard = ({
1558
1552
  title,
@@ -1563,7 +1557,7 @@ var CollapsibleCard = ({
1563
1557
  collapsible = true,
1564
1558
  className = ""
1565
1559
  }) => {
1566
- const [isOpen, setIsOpen] = (0, import_react13.useState)(defaultOpen);
1560
+ const [isOpen, setIsOpen] = (0, import_react11.useState)(defaultOpen);
1567
1561
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: `border border-neutral-800 rounded-lg ${className}`, children: [
1568
1562
  /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1569
1563
  "div",
@@ -1610,20 +1604,20 @@ var PromptTab = ({
1610
1604
  onTagUpdate,
1611
1605
  onTagDelete
1612
1606
  }) => {
1613
- const [selectedLabels, setSelectedLabels] = (0, import_react14.useState)(/* @__PURE__ */ new Set());
1614
- const [instructions, setInstructions] = (0, import_react14.useState)("");
1615
- const [rules, setRules] = (0, import_react14.useState)("");
1616
- const [activeCategory, setActiveCategory] = (0, import_react14.useState)(null);
1617
- const [copied, setCopied] = (0, import_react14.useState)(false);
1618
- const imgInputRef = (0, import_react14.useRef)(null);
1619
- const [addingInCat, setAddingInCat] = (0, import_react14.useState)(null);
1620
- const [newLabel, setNewLabel] = (0, import_react14.useState)("");
1621
- const [newValue, setNewValue] = (0, import_react14.useState)("");
1622
- const [editingTag, setEditingTag] = (0, import_react14.useState)(null);
1623
- const [editLabel, setEditLabel] = (0, import_react14.useState)("");
1624
- const [editValue, setEditValue] = (0, import_react14.useState)("");
1625
- const longPressTimer = (0, import_react14.useRef)(null);
1626
- const longPressActivated = (0, import_react14.useRef)(false);
1607
+ const [selectedLabels, setSelectedLabels] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
1608
+ const [instructions, setInstructions] = (0, import_react12.useState)("");
1609
+ const [rules, setRules] = (0, import_react12.useState)("");
1610
+ const [activeCategory, setActiveCategory] = (0, import_react12.useState)(null);
1611
+ const [copied, setCopied] = (0, import_react12.useState)(false);
1612
+ const imgInputRef = (0, import_react12.useRef)(null);
1613
+ const [addingInCat, setAddingInCat] = (0, import_react12.useState)(null);
1614
+ const [newLabel, setNewLabel] = (0, import_react12.useState)("");
1615
+ const [newValue, setNewValue] = (0, import_react12.useState)("");
1616
+ const [editingTag, setEditingTag] = (0, import_react12.useState)(null);
1617
+ const [editLabel, setEditLabel] = (0, import_react12.useState)("");
1618
+ const [editValue, setEditValue] = (0, import_react12.useState)("");
1619
+ const longPressTimer = (0, import_react12.useRef)(null);
1620
+ const longPressActivated = (0, import_react12.useRef)(false);
1627
1621
  const toggleTag = (label) => {
1628
1622
  setSelectedLabels((prev) => {
1629
1623
  const next = new Set(prev);
@@ -2070,7 +2064,7 @@ var PromptTab = ({
2070
2064
  };
2071
2065
 
2072
2066
  // src/components/ProjectSyncTab.tsx
2073
- var import_react15 = require("react");
2067
+ var import_react13 = require("react");
2074
2068
  init_hfStateService();
2075
2069
  var import_jsx_runtime12 = require("react/jsx-runtime");
2076
2070
  var ProjectSyncTab = ({
@@ -2091,14 +2085,14 @@ var ProjectSyncTab = ({
2091
2085
  onProjectExportBase64,
2092
2086
  onHfInitialSync
2093
2087
  }) => {
2094
- const projectInputRef = (0, import_react15.useRef)(null);
2095
- const workspaceInputRef = (0, import_react15.useRef)(null);
2096
- const [saveName, setSaveName] = (0, import_react15.useState)("");
2097
- const [isSaving, setIsSaving] = (0, import_react15.useState)(false);
2098
- const [isExporting, setIsExporting] = (0, import_react15.useState)(false);
2099
- const [syncState, setSyncState] = (0, import_react15.useState)("idle");
2100
- const [syncDiff, setSyncDiff] = (0, import_react15.useState)(null);
2101
- const [selectedLocalIds, setSelectedLocalIds] = (0, import_react15.useState)(/* @__PURE__ */ new Set());
2088
+ const projectInputRef = (0, import_react13.useRef)(null);
2089
+ const workspaceInputRef = (0, import_react13.useRef)(null);
2090
+ const [saveName, setSaveName] = (0, import_react13.useState)("");
2091
+ const [isSaving, setIsSaving] = (0, import_react13.useState)(false);
2092
+ const [isExporting, setIsExporting] = (0, import_react13.useState)(false);
2093
+ const [syncState, setSyncState] = (0, import_react13.useState)("idle");
2094
+ const [syncDiff, setSyncDiff] = (0, import_react13.useState)(null);
2095
+ const [selectedLocalIds, setSelectedLocalIds] = (0, import_react13.useState)(/* @__PURE__ */ new Set());
2102
2096
  const handleExport = async () => {
2103
2097
  if (!onProjectExport) return;
2104
2098
  setIsExporting(true);
@@ -2144,13 +2138,13 @@ var ProjectSyncTab = ({
2144
2138
  });
2145
2139
  };
2146
2140
  const isWorking = projectActionState === "working" || projectActionState === "working-full";
2147
- const [hfProjects, setHfProjects] = (0, import_react15.useState)([]);
2148
- const [hfLoading, setHfLoading] = (0, import_react15.useState)(false);
2149
- const [hfSaving, setHfSaving] = (0, import_react15.useState)(false);
2150
- const [hfError, setHfError] = (0, import_react15.useState)(null);
2151
- const [hfSaveName, setHfSaveName] = (0, import_react15.useState)("");
2152
- const [hfSyncProgress, setHfSyncProgress] = (0, import_react15.useState)(null);
2153
- const [hfSyncing, setHfSyncing] = (0, import_react15.useState)(false);
2141
+ const [hfProjects, setHfProjects] = (0, import_react13.useState)([]);
2142
+ const [hfLoading, setHfLoading] = (0, import_react13.useState)(false);
2143
+ const [hfSaving, setHfSaving] = (0, import_react13.useState)(false);
2144
+ const [hfError, setHfError] = (0, import_react13.useState)(null);
2145
+ const [hfSaveName, setHfSaveName] = (0, import_react13.useState)("");
2146
+ const [hfSyncProgress, setHfSyncProgress] = (0, import_react13.useState)(null);
2147
+ const [hfSyncing, setHfSyncing] = (0, import_react13.useState)(false);
2154
2148
  const loadHfProjects = async (token) => {
2155
2149
  setHfLoading(true);
2156
2150
  setHfError(null);
@@ -2162,7 +2156,7 @@ var ProjectSyncTab = ({
2162
2156
  setHfLoading(false);
2163
2157
  }
2164
2158
  };
2165
- (0, import_react15.useEffect)(() => {
2159
+ (0, import_react13.useEffect)(() => {
2166
2160
  if (hfToken) loadHfProjects(hfToken);
2167
2161
  }, [hfToken]);
2168
2162
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "absolute inset-0 overflow-y-auto dark-scrollbar", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "p-6 flex flex-col gap-8", children: [
@@ -2576,7 +2570,7 @@ function toPromptImages(images) {
2576
2570
  init_hfStateService();
2577
2571
 
2578
2572
  // src/hooks/useHFState.ts
2579
- var import_react16 = require("react");
2573
+ var import_react14 = require("react");
2580
2574
  init_hfStateService();
2581
2575
 
2582
2576
  // src/lib/hfReducer.ts
@@ -2709,19 +2703,19 @@ function writeOfflineBuffer(events) {
2709
2703
  }
2710
2704
  }
2711
2705
  function useHFState(token, namespace) {
2712
- const [state, setState] = (0, import_react16.useState)(null);
2713
- const [isLoading, setIsLoading] = (0, import_react16.useState)(false);
2714
- const [error, setError] = (0, import_react16.useState)(null);
2715
- const [eventCount, setEventCount] = (0, import_react16.useState)(0);
2716
- const [localOnlyCount, setLocalOnlyCount] = (0, import_react16.useState)(0);
2717
- const [forks, setForks] = (0, import_react16.useState)([]);
2718
- const [pendingBufferCount, setPendingBufferCount] = (0, import_react16.useState)(readOfflineBuffer().length);
2719
- const [lastEventTs, setLastEventTs] = (0, import_react16.useState)(0);
2720
- const [hasStateZip, setHasStateZip] = (0, import_react16.useState)(false);
2721
- const knownEventPaths = (0, import_react16.useRef)(/* @__PURE__ */ new Set());
2722
- const knownFilePaths = (0, import_react16.useRef)(/* @__PURE__ */ new Set());
2723
- const allEventsRef = (0, import_react16.useRef)([]);
2724
- const applyNewEvents = (0, import_react16.useCallback)((snapshot, newEvents) => {
2706
+ const [state, setState] = (0, import_react14.useState)(null);
2707
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(false);
2708
+ const [error, setError] = (0, import_react14.useState)(null);
2709
+ const [eventCount, setEventCount] = (0, import_react14.useState)(0);
2710
+ const [localOnlyCount, setLocalOnlyCount] = (0, import_react14.useState)(0);
2711
+ const [forks, setForks] = (0, import_react14.useState)([]);
2712
+ const [pendingBufferCount, setPendingBufferCount] = (0, import_react14.useState)(readOfflineBuffer().length);
2713
+ const [lastEventTs, setLastEventTs] = (0, import_react14.useState)(0);
2714
+ const [hasStateZip, setHasStateZip] = (0, import_react14.useState)(false);
2715
+ const knownEventPaths = (0, import_react14.useRef)(/* @__PURE__ */ new Set());
2716
+ const knownFilePaths = (0, import_react14.useRef)(/* @__PURE__ */ new Set());
2717
+ const allEventsRef = (0, import_react14.useRef)([]);
2718
+ const applyNewEvents = (0, import_react14.useCallback)((snapshot, newEvents) => {
2725
2719
  if (!newEvents.length && allEventsRef.current.length === 0) {
2726
2720
  setEventCount(0);
2727
2721
  return snapshot;
@@ -2735,7 +2729,7 @@ function useHFState(token, namespace) {
2735
2729
  if (afterConsolidation.length) setLastEventTs(Math.max(...afterConsolidation.map((e) => e.ts)));
2736
2730
  return applyEvents(snapshot, afterConsolidation);
2737
2731
  }, []);
2738
- const loadFull = (0, import_react16.useCallback)(async () => {
2732
+ const loadFull = (0, import_react14.useCallback)(async () => {
2739
2733
  if (!token || !namespace) return;
2740
2734
  setIsLoading(true);
2741
2735
  setError(null);
@@ -2783,7 +2777,7 @@ function useHFState(token, namespace) {
2783
2777
  setIsLoading(false);
2784
2778
  }
2785
2779
  }, [token, namespace, applyNewEvents]);
2786
- const pollNew = (0, import_react16.useCallback)(async () => {
2780
+ const pollNew = (0, import_react14.useCallback)(async () => {
2787
2781
  if (!token || !namespace || !state) return;
2788
2782
  try {
2789
2783
  const events = await loadPendingEvents(namespace, token, state.meta.consolidatedAt, knownFilePaths.current);
@@ -2797,15 +2791,15 @@ function useHFState(token, namespace) {
2797
2791
  } catch {
2798
2792
  }
2799
2793
  }, [token, namespace, state, applyNewEvents]);
2800
- (0, import_react16.useEffect)(() => {
2794
+ (0, import_react14.useEffect)(() => {
2801
2795
  if (token && namespace) loadFull();
2802
2796
  }, [token, namespace]);
2803
- (0, import_react16.useEffect)(() => {
2797
+ (0, import_react14.useEffect)(() => {
2804
2798
  if (!token || !namespace) return;
2805
2799
  const id = setInterval(pollNew, POLL_INTERVAL_MS);
2806
2800
  return () => clearInterval(id);
2807
2801
  }, [token, namespace, pollNew]);
2808
- const writeEvent = (0, import_react16.useCallback)(async (type, payload) => {
2802
+ const writeEvent = (0, import_react14.useCallback)(async (type, payload) => {
2809
2803
  const prevTs = lastEventTs ? [lastEventTs] : [state?.meta.consolidatedAt ?? 0];
2810
2804
  console.log("[HF] writeEvent called:", { type, namespace, tokenOk: !!token, prevTs });
2811
2805
  await pollNew();
@@ -2855,13 +2849,13 @@ function useHFState(token, namespace) {
2855
2849
  }
2856
2850
 
2857
2851
  // src/components/labs/LabsTab.tsx
2858
- var import_react23 = require("react");
2852
+ var import_react22 = require("react");
2859
2853
 
2860
2854
  // src/components/labs/LabRemix.tsx
2861
- var import_react18 = require("react");
2855
+ var import_react17 = require("react");
2862
2856
 
2863
2857
  // src/components/labs/LabImagePicker.tsx
2864
- var import_react17 = require("react");
2858
+ var import_react15 = require("react");
2865
2859
  var import_jsx_runtime13 = require("react/jsx-runtime");
2866
2860
  var LabImagePicker = ({
2867
2861
  availableItems,
@@ -2870,8 +2864,8 @@ var LabImagePicker = ({
2870
2864
  onClose,
2871
2865
  title = "Bild w\xE4hlen"
2872
2866
  }) => {
2873
- const [search, setSearch] = (0, import_react17.useState)("");
2874
- const [drillItem, setDrillItem] = (0, import_react17.useState)(null);
2867
+ const [search, setSearch] = (0, import_react15.useState)("");
2868
+ const [drillItem, setDrillItem] = (0, import_react15.useState)(null);
2875
2869
  const filtered = availableItems.filter(
2876
2870
  (item) => !search || item.prompt.toLowerCase().includes(search.toLowerCase())
2877
2871
  );
@@ -2970,16 +2964,120 @@ var LabImagePicker = ({
2970
2964
  ] });
2971
2965
  };
2972
2966
 
2973
- // src/components/labs/LabRemix.tsx
2967
+ // src/components/GenerationControls.tsx
2974
2968
  var import_jsx_runtime14 = require("react/jsx-runtime");
2969
+ var ASPECT_OPTIONS = [
2970
+ { label: "1:1", value: "1:1" },
2971
+ { label: "16:9", value: "16:9" },
2972
+ { label: "9:16", value: "9:16" }
2973
+ ];
2974
+ var MODEL_OPTIONS = [
2975
+ { value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" },
2976
+ { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" },
2977
+ { value: "Imagen 4", label: "Imagen 4" }
2978
+ ];
2979
+ var COUNT_OPTIONS = [
2980
+ { label: "1 Bild", value: "1" },
2981
+ { label: "2 Bilder", value: "2" },
2982
+ { label: "4 Bilder", value: "4" },
2983
+ { label: "8 Bilder", value: "8" }
2984
+ ];
2985
+ var GenerationControls = ({
2986
+ aspectRatio,
2987
+ onAspectRatioChange,
2988
+ model,
2989
+ onModelChange,
2990
+ imageCount,
2991
+ onImageCountChange,
2992
+ runningCount = 0,
2993
+ className
2994
+ }) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: `flex items-center gap-2 flex-wrap ${className || ""}`, children: [
2995
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CompactDropdown, { value: aspectRatio, onChange: onAspectRatioChange, options: ASPECT_OPTIONS }),
2996
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CompactDropdown, { value: model, onChange: onModelChange, options: MODEL_OPTIONS }),
2997
+ imageCount !== void 0 && onImageCountChange && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2998
+ CompactDropdown,
2999
+ {
3000
+ value: String(imageCount),
3001
+ displayValue: `${imageCount}\xD7`,
3002
+ onChange: onImageCountChange,
3003
+ options: COUNT_OPTIONS
3004
+ }
3005
+ ),
3006
+ runningCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
3007
+ "div",
3008
+ {
3009
+ className: "flex items-center gap-1 rounded-full bg-sky-500/15 border border-sky-400/30 px-2 shrink-0",
3010
+ style: { height: 24 },
3011
+ title: `${runningCount} Generierung${runningCount === 1 ? "" : "en"} l\xE4uft`,
3012
+ children: [
3013
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "material-symbols-outlined text-sky-300", style: { fontSize: 14, lineHeight: 1 }, children: "autorenew" }),
3014
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-[11px] font-bold text-sky-300 tabular-nums", children: runningCount })
3015
+ ]
3016
+ }
3017
+ )
3018
+ ] });
3019
+
3020
+ // src/hooks/useGenerationSettings.ts
3021
+ var import_react16 = require("react");
3022
+ function useGenerationSettings() {
3023
+ const [aspectRatio, setAspectRatio] = (0, import_react16.useState)(() => {
3024
+ try {
3025
+ return localStorage.getItem("aa-lab-aspect") || "1:1";
3026
+ } catch {
3027
+ return "1:1";
3028
+ }
3029
+ });
3030
+ const [model, setModel] = (0, import_react16.useState)(() => {
3031
+ try {
3032
+ return localStorage.getItem("aa-lab-model") || "\u{1F34C} Nano Banana Pro";
3033
+ } catch {
3034
+ return "\u{1F34C} Nano Banana Pro";
3035
+ }
3036
+ });
3037
+ const [imageCount, setImageCount] = (0, import_react16.useState)(() => {
3038
+ try {
3039
+ const v = parseInt(localStorage.getItem("aa-image-count") || "", 10);
3040
+ return v >= 1 && v <= 8 ? v : 4;
3041
+ } catch {
3042
+ return 4;
3043
+ }
3044
+ });
3045
+ const updateAspectRatio = (v) => {
3046
+ setAspectRatio(v);
3047
+ try {
3048
+ localStorage.setItem("aa-lab-aspect", v);
3049
+ } catch {
3050
+ }
3051
+ };
3052
+ const updateModel = (v) => {
3053
+ setModel(v);
3054
+ try {
3055
+ localStorage.setItem("aa-lab-model", v);
3056
+ } catch {
3057
+ }
3058
+ };
3059
+ const updateImageCount = (v) => {
3060
+ const n = Math.max(1, Math.min(8, parseInt(v, 10) || 4));
3061
+ setImageCount(n);
3062
+ try {
3063
+ localStorage.setItem("aa-image-count", String(n));
3064
+ } catch {
3065
+ }
3066
+ };
3067
+ return { aspectRatio, model, imageCount, updateAspectRatio, updateModel, updateImageCount };
3068
+ }
3069
+
3070
+ // src/components/labs/LabRemix.tsx
3071
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2975
3072
  var LabRemix = ({ services, onResult }) => {
2976
- const [showPicker, setShowPicker] = (0, import_react18.useState)(false);
2977
- const [selected, setSelected] = (0, import_react18.useState)(null);
2978
- const [instruction, setInstruction] = (0, import_react18.useState)("");
2979
- const [generatedPrompt, setGeneratedPrompt] = (0, import_react18.useState)("");
2980
- const [resultImage, setResultImage] = (0, import_react18.useState)(null);
2981
- const [isGeneratingPrompt, setIsGeneratingPrompt] = (0, import_react18.useState)(false);
2982
- const [isGeneratingImage, setIsGeneratingImage] = (0, import_react18.useState)(false);
3073
+ const [showPicker, setShowPicker] = (0, import_react17.useState)(false);
3074
+ const [selected, setSelected] = (0, import_react17.useState)(null);
3075
+ const [instruction, setInstruction] = (0, import_react17.useState)("");
3076
+ const [generatedPrompt, setGeneratedPrompt] = (0, import_react17.useState)("");
3077
+ const [resultImages, setResultImages] = (0, import_react17.useState)([]);
3078
+ const [isGeneratingPrompt, setIsGeneratingPrompt] = (0, import_react17.useState)(false);
3079
+ const [runningCount, setRunningCount] = (0, import_react17.useState)(0);
3080
+ const { aspectRatio, model, imageCount, updateAspectRatio, updateModel, updateImageCount } = useGenerationSettings();
2983
3081
  const handleSelectImage = (item, frame) => {
2984
3082
  services.onItemUsed(item);
2985
3083
  setSelected({
@@ -2992,7 +3090,7 @@ var LabRemix = ({ services, onResult }) => {
2992
3090
  roleForImage: ""
2993
3091
  });
2994
3092
  setGeneratedPrompt("");
2995
- setResultImage(null);
3093
+ setResultImages([]);
2996
3094
  };
2997
3095
  const handleGeneratePrompt = async () => {
2998
3096
  if (!selected || !instruction.trim()) return;
@@ -3011,34 +3109,40 @@ var LabRemix = ({ services, onResult }) => {
3011
3109
  setIsGeneratingPrompt(false);
3012
3110
  }
3013
3111
  };
3014
- const handleGenerateImage = async () => {
3112
+ const handleGenerateBatch = async () => {
3015
3113
  if (!generatedPrompt) return;
3016
- setIsGeneratingImage(true);
3017
- try {
3018
- const refIds = buildReferenceImageMediaIds(selected ? [selected] : []);
3019
- const { base64, mediaId } = await services.generateImage({
3020
- prompt: generatedPrompt,
3021
- aspectRatio: selected?.frame.aspectRatio || "1:1",
3022
- modelDisplayName: selected?.frame.model || "\u{1F34C} Nano Banana Pro",
3023
- ...refIds.length ? { referenceImageMediaIds: refIds } : {}
3024
- });
3025
- const newBase64 = `data:image/png;base64,${base64}`;
3026
- setResultImage(newBase64);
3027
- const frameId = crypto.randomUUID();
3028
- const newItem = {
3029
- id: frameId,
3030
- prompt: generatedPrompt,
3031
- tags: selected?.item.tags || [],
3032
- frames: [{ id: frameId, base64: newBase64, mediaId, source: "generated" }]
3033
- };
3034
- services.saveResult?.(newItem);
3035
- onResult?.(newItem);
3036
- } finally {
3037
- setIsGeneratingImage(false);
3114
+ const count = Math.max(1, Math.min(8, imageCount));
3115
+ const refIds = buildReferenceImageMediaIds(selected ? [selected] : []);
3116
+ const options = {
3117
+ prompt: generatedPrompt,
3118
+ aspectRatio,
3119
+ modelDisplayName: model,
3120
+ ...refIds.length ? { referenceImageMediaIds: refIds } : {}
3121
+ };
3122
+ setRunningCount((c) => c + count);
3123
+ const results = await Promise.allSettled(
3124
+ Array.from({ length: count }, () => services.generateImage(options))
3125
+ );
3126
+ setRunningCount((c) => c - count);
3127
+ for (const r of results) {
3128
+ if (r.status === "fulfilled") {
3129
+ const { base64, mediaId } = r.value;
3130
+ const newBase64 = `data:image/png;base64,${base64}`;
3131
+ setResultImages((prev) => [newBase64, ...prev]);
3132
+ const frameId = crypto.randomUUID();
3133
+ const newItem = {
3134
+ id: frameId,
3135
+ prompt: generatedPrompt,
3136
+ tags: selected?.item.tags || [],
3137
+ frames: [{ id: frameId, base64: newBase64, mediaId, source: "generated" }]
3138
+ };
3139
+ services.saveResult?.(newItem);
3140
+ onResult?.(newItem);
3141
+ }
3038
3142
  }
3039
3143
  };
3040
3144
  if (showPicker) {
3041
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3145
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3042
3146
  LabImagePicker,
3043
3147
  {
3044
3148
  availableItems: services.availableItems,
@@ -3049,15 +3153,15 @@ var LabRemix = ({ services, onResult }) => {
3049
3153
  }
3050
3154
  );
3051
3155
  }
3052
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col gap-3 p-4 overflow-y-auto dark-scrollbar", children: [
3053
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
3054
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40 mb-2", children: "Basis-Bild" }),
3055
- selected ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex gap-3 p-3 rounded-xl border border-white/10 bg-white/5", children: [
3056
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("img", { src: selected.frame.base64, className: "w-16 h-16 object-cover rounded-lg shrink-0" }),
3057
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex-1 min-w-0 flex flex-col gap-1.5", children: [
3058
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-[10px] text-white/60 leading-tight line-clamp-2", children: selected.item.prompt }),
3059
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "flex items-center gap-2 text-[10px] text-white/50", children: [
3060
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3156
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-col gap-3 p-4 overflow-y-auto dark-scrollbar", children: [
3157
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
3158
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40 mb-2", children: "Basis-Bild" }),
3159
+ selected ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex gap-3 p-3 rounded-xl border border-white/10 bg-white/5", children: [
3160
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("img", { src: selected.frame.base64, className: "w-16 h-16 object-cover rounded-lg shrink-0" }),
3161
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex-1 min-w-0 flex flex-col gap-1.5", children: [
3162
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-[10px] text-white/60 leading-tight line-clamp-2", children: selected.item.prompt }),
3163
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "flex items-center gap-2 text-[10px] text-white/50", children: [
3164
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3061
3165
  "input",
3062
3166
  {
3063
3167
  type: "checkbox",
@@ -3067,8 +3171,8 @@ var LabRemix = ({ services, onResult }) => {
3067
3171
  ),
3068
3172
  "Bild an KI (Prompt)"
3069
3173
  ] }),
3070
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "flex items-center gap-2 text-[10px] text-white/50", children: [
3071
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3174
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "flex items-center gap-2 text-[10px] text-white/50", children: [
3175
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3072
3176
  "input",
3073
3177
  {
3074
3178
  type: "checkbox",
@@ -3078,7 +3182,7 @@ var LabRemix = ({ services, onResult }) => {
3078
3182
  ),
3079
3183
  "Bild als Referenz (Generierung)"
3080
3184
  ] }),
3081
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3185
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3082
3186
  "input",
3083
3187
  {
3084
3188
  value: selected.roleForPrompt || "",
@@ -3088,22 +3192,22 @@ var LabRemix = ({ services, onResult }) => {
3088
3192
  }
3089
3193
  )
3090
3194
  ] }),
3091
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { onClick: () => setShowPicker(true), className: "text-white/30 active:text-white self-start", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "material-symbols-outlined text-[18px]", children: "swap_horiz" }) })
3092
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
3195
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { onClick: () => setShowPicker(true), className: "text-white/30 active:text-white self-start", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "material-symbols-outlined text-[18px]", children: "swap_horiz" }) })
3196
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
3093
3197
  "button",
3094
3198
  {
3095
3199
  onClick: () => setShowPicker(true),
3096
3200
  className: "w-full py-6 rounded-xl border border-dashed border-white/20 text-[11px] text-white/30 active:bg-white/5 flex items-center justify-center gap-2",
3097
3201
  children: [
3098
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "add_photo_alternate" }),
3202
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "add_photo_alternate" }),
3099
3203
  "Bild w\xE4hlen"
3100
3204
  ]
3101
3205
  }
3102
3206
  )
3103
3207
  ] }),
3104
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
3105
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40 mb-2", children: "Anweisung" }),
3106
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3208
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
3209
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40 mb-2", children: "Anweisung" }),
3210
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3107
3211
  "textarea",
3108
3212
  {
3109
3213
  value: instruction,
@@ -3114,25 +3218,24 @@ var LabRemix = ({ services, onResult }) => {
3114
3218
  }
3115
3219
  )
3116
3220
  ] }),
3117
- services.workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-[9px] text-white/20 italic", children: "Tags: Workspace-Tags k\xF6nnen unter der Anweisung erg\xE4nzt werden (folgt in n\xE4chstem Update)" }),
3118
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3221
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3119
3222
  "button",
3120
3223
  {
3121
3224
  onClick: handleGeneratePrompt,
3122
3225
  disabled: !selected || !instruction.trim() || isGeneratingPrompt,
3123
3226
  className: "w-full py-3 rounded-xl bg-white/10 text-white font-bold text-[12px] uppercase tracking-wide disabled:opacity-30 active:bg-white/15 flex items-center justify-center gap-2",
3124
- children: isGeneratingPrompt ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
3125
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "w-3 h-3 border-t border-white rounded-full animate-spin" }),
3126
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Generiere Prompt..." })
3127
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
3128
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "auto_fix_high" }),
3129
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Prompt generieren" })
3227
+ children: isGeneratingPrompt ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
3228
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "w-3 h-3 border-t border-white rounded-full animate-spin" }),
3229
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: "Generiere Prompt..." })
3230
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
3231
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "auto_fix_high" }),
3232
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: "Prompt generieren" })
3130
3233
  ] })
3131
3234
  }
3132
3235
  ),
3133
- generatedPrompt && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
3134
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40 mb-2", children: "Generierter Prompt" }),
3135
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3236
+ generatedPrompt && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-col gap-2", children: [
3237
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40", children: "Generierter Prompt" }),
3238
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3136
3239
  "textarea",
3137
3240
  {
3138
3241
  value: generatedPrompt,
@@ -3141,37 +3244,46 @@ var LabRemix = ({ services, onResult }) => {
3141
3244
  rows: 4
3142
3245
  }
3143
3246
  ),
3144
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3247
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3248
+ GenerationControls,
3249
+ {
3250
+ aspectRatio,
3251
+ onAspectRatioChange: updateAspectRatio,
3252
+ model,
3253
+ onModelChange: updateModel,
3254
+ imageCount,
3255
+ onImageCountChange: updateImageCount,
3256
+ runningCount
3257
+ }
3258
+ ),
3259
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
3145
3260
  "button",
3146
3261
  {
3147
- onClick: handleGenerateImage,
3148
- disabled: isGeneratingImage,
3149
- className: "w-full mt-2 py-3 rounded-xl bg-blue-600/80 text-white font-bold text-[12px] uppercase tracking-wide disabled:opacity-30 active:bg-blue-600 flex items-center justify-center gap-2",
3150
- children: isGeneratingImage ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
3151
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "w-3 h-3 border-t border-white rounded-full animate-spin" }),
3152
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Generiere Bild..." })
3153
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
3154
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "image" }),
3155
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Bild generieren" })
3156
- ] })
3262
+ onClick: handleGenerateBatch,
3263
+ className: "w-full py-3 rounded-xl bg-blue-600/80 text-white font-bold text-[12px] uppercase tracking-wide active:bg-blue-600 flex items-center justify-center gap-2",
3264
+ children: [
3265
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "image" }),
3266
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: "Bilder generieren" })
3267
+ ]
3157
3268
  }
3158
3269
  )
3159
3270
  ] }),
3160
- resultImage && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "rounded-xl overflow-hidden border border-white/10", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("img", { src: resultImage, className: "w-full object-cover" }) })
3271
+ resultImages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: `grid gap-2 ${resultImages.length > 1 ? "grid-cols-2" : "grid-cols-1"}`, children: resultImages.map((src, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "rounded-xl overflow-hidden border border-white/10", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("img", { src, className: "w-full object-cover" }) }, i)) })
3161
3272
  ] });
3162
3273
  };
3163
3274
 
3164
3275
  // src/components/labs/LabBlend.tsx
3165
- var import_react19 = require("react");
3166
- var import_jsx_runtime15 = require("react/jsx-runtime");
3276
+ var import_react18 = require("react");
3277
+ var import_jsx_runtime16 = require("react/jsx-runtime");
3167
3278
  var LabBlend = ({ services, onResult }) => {
3168
- const [showPickerFor, setShowPickerFor] = (0, import_react19.useState)(null);
3169
- const [selectedImages, setSelectedImages] = (0, import_react19.useState)([]);
3170
- const [instruction, setInstruction] = (0, import_react19.useState)("");
3171
- const [generatedPrompt, setGeneratedPrompt] = (0, import_react19.useState)("");
3172
- const [resultImage, setResultImage] = (0, import_react19.useState)(null);
3173
- const [isGeneratingPrompt, setIsGeneratingPrompt] = (0, import_react19.useState)(false);
3174
- const [isGeneratingImage, setIsGeneratingImage] = (0, import_react19.useState)(false);
3279
+ const [showPickerFor, setShowPickerFor] = (0, import_react18.useState)(null);
3280
+ const [selectedImages, setSelectedImages] = (0, import_react18.useState)([]);
3281
+ const [instruction, setInstruction] = (0, import_react18.useState)("");
3282
+ const [generatedPrompt, setGeneratedPrompt] = (0, import_react18.useState)("");
3283
+ const [resultImages, setResultImages] = (0, import_react18.useState)([]);
3284
+ const [isGeneratingPrompt, setIsGeneratingPrompt] = (0, import_react18.useState)(false);
3285
+ const [runningCount, setRunningCount] = (0, import_react18.useState)(0);
3286
+ const { aspectRatio, model, imageCount, updateAspectRatio, updateModel, updateImageCount } = useGenerationSettings();
3175
3287
  const handleSelectImage = (index, item, frame) => {
3176
3288
  services.onItemUsed(item);
3177
3289
  const newImg = {
@@ -3190,7 +3302,7 @@ var LabBlend = ({ services, onResult }) => {
3190
3302
  });
3191
3303
  setShowPickerFor(null);
3192
3304
  setGeneratedPrompt("");
3193
- setResultImage(null);
3305
+ setResultImages([]);
3194
3306
  };
3195
3307
  const addSlot = () => setSelectedImages((prev) => [...prev, null]);
3196
3308
  const removeSlot = (i) => setSelectedImages((prev) => prev.filter((_, idx) => idx !== i));
@@ -3208,35 +3320,41 @@ var LabBlend = ({ services, onResult }) => {
3208
3320
  setIsGeneratingPrompt(false);
3209
3321
  }
3210
3322
  };
3211
- const handleGenerateImage = async () => {
3323
+ const handleGenerateBatch = async () => {
3212
3324
  if (!generatedPrompt) return;
3213
- setIsGeneratingImage(true);
3214
- try {
3215
- const filled = selectedImages.filter(Boolean);
3216
- const refIds = buildReferenceImageMediaIds(filled);
3217
- const { base64, mediaId } = await services.generateImage({
3218
- prompt: generatedPrompt,
3219
- aspectRatio: "1:1",
3220
- modelDisplayName: "\u{1F34C} Nano Banana Pro",
3221
- ...refIds.length ? { referenceImageMediaIds: refIds } : {}
3222
- });
3223
- const newBase64 = `data:image/png;base64,${base64}`;
3224
- setResultImage(newBase64);
3225
- const frameId = crypto.randomUUID();
3226
- const newItem = {
3227
- id: frameId,
3228
- prompt: generatedPrompt,
3229
- tags: [],
3230
- frames: [{ id: frameId, base64: newBase64, mediaId, source: "generated" }]
3231
- };
3232
- services.saveResult?.(newItem);
3233
- onResult?.(newItem);
3234
- } finally {
3235
- setIsGeneratingImage(false);
3325
+ const count = Math.max(1, Math.min(8, imageCount));
3326
+ const filled = selectedImages.filter(Boolean);
3327
+ const refIds = buildReferenceImageMediaIds(filled);
3328
+ const options = {
3329
+ prompt: generatedPrompt,
3330
+ aspectRatio,
3331
+ modelDisplayName: model,
3332
+ ...refIds.length ? { referenceImageMediaIds: refIds } : {}
3333
+ };
3334
+ setRunningCount((c) => c + count);
3335
+ const results = await Promise.allSettled(
3336
+ Array.from({ length: count }, () => services.generateImage(options))
3337
+ );
3338
+ setRunningCount((c) => c - count);
3339
+ for (const r of results) {
3340
+ if (r.status === "fulfilled") {
3341
+ const { base64, mediaId } = r.value;
3342
+ const newBase64 = `data:image/png;base64,${base64}`;
3343
+ setResultImages((prev) => [newBase64, ...prev]);
3344
+ const frameId = crypto.randomUUID();
3345
+ const newItem = {
3346
+ id: frameId,
3347
+ prompt: generatedPrompt,
3348
+ tags: [],
3349
+ frames: [{ id: frameId, base64: newBase64, mediaId, source: "generated" }]
3350
+ };
3351
+ services.saveResult?.(newItem);
3352
+ onResult?.(newItem);
3353
+ }
3236
3354
  }
3237
3355
  };
3238
3356
  if (showPickerFor !== null) {
3239
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3357
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3240
3358
  LabImagePicker,
3241
3359
  {
3242
3360
  availableItems: services.availableItems,
@@ -3247,25 +3365,25 @@ var LabBlend = ({ services, onResult }) => {
3247
3365
  }
3248
3366
  );
3249
3367
  }
3250
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-col gap-3 p-4 overflow-y-auto dark-scrollbar", children: [
3251
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40", children: "Bilder" }),
3252
- selectedImages.map((img, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex gap-3 p-3 rounded-xl border border-white/10 bg-white/5", children: [
3253
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-[10px] font-bold text-white/40 w-6 shrink-0 pt-1", children: autoLabel(i) }),
3254
- img ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
3255
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("img", { src: img.frame.base64, className: "w-12 h-12 object-cover rounded-lg shrink-0", onClick: () => setShowPickerFor(i) }),
3256
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex-1 min-w-0 flex flex-col gap-1", children: [
3257
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-[10px] text-white/50 line-clamp-1", children: img.item.prompt }),
3258
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex gap-3", children: [
3259
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "flex items-center gap-1 text-[10px] text-white/40", children: [
3260
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("input", { type: "checkbox", checked: img.sendToPromptAI, onChange: (e) => updateImg(i, { sendToPromptAI: e.target.checked }) }),
3368
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col gap-3 p-4 overflow-y-auto dark-scrollbar", children: [
3369
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40", children: "Bilder" }),
3370
+ selectedImages.map((img, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex gap-3 p-3 rounded-xl border border-white/10 bg-white/5", children: [
3371
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[10px] font-bold text-white/40 w-6 shrink-0 pt-1", children: autoLabel(i) }),
3372
+ img ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3373
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("img", { src: img.frame.base64, className: "w-12 h-12 object-cover rounded-lg shrink-0", onClick: () => setShowPickerFor(i) }),
3374
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1 min-w-0 flex flex-col gap-1", children: [
3375
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-[10px] text-white/50 line-clamp-1", children: img.item.prompt }),
3376
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex gap-3", children: [
3377
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("label", { className: "flex items-center gap-1 text-[10px] text-white/40", children: [
3378
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("input", { type: "checkbox", checked: img.sendToPromptAI, onChange: (e) => updateImg(i, { sendToPromptAI: e.target.checked }) }),
3261
3379
  "KI-Prompt"
3262
3380
  ] }),
3263
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "flex items-center gap-1 text-[10px] text-white/40", children: [
3264
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("input", { type: "checkbox", checked: img.sendToImageGen, onChange: (e) => updateImg(i, { sendToImageGen: e.target.checked }) }),
3381
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("label", { className: "flex items-center gap-1 text-[10px] text-white/40", children: [
3382
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("input", { type: "checkbox", checked: img.sendToImageGen, onChange: (e) => updateImg(i, { sendToImageGen: e.target.checked }) }),
3265
3383
  "Referenz"
3266
3384
  ] })
3267
3385
  ] }),
3268
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3386
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3269
3387
  "input",
3270
3388
  {
3271
3389
  value: img.roleForPrompt || "",
@@ -3274,7 +3392,7 @@ var LabBlend = ({ services, onResult }) => {
3274
3392
  className: "bg-black/30 border border-white/10 rounded px-2 py-0.5 text-[10px] text-white/60 outline-none"
3275
3393
  }
3276
3394
  ),
3277
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3395
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3278
3396
  "input",
3279
3397
  {
3280
3398
  value: img.roleForImage || "",
@@ -3284,23 +3402,23 @@ var LabBlend = ({ services, onResult }) => {
3284
3402
  }
3285
3403
  )
3286
3404
  ] })
3287
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { onClick: () => setShowPickerFor(i), className: "flex-1 py-3 border border-dashed border-white/20 rounded-lg text-[10px] text-white/30 active:bg-white/5", children: "Bild w\xE4hlen" }),
3288
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { onClick: () => removeSlot(i), className: "text-white/20 active:text-red-400 self-start", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "close" }) })
3405
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { onClick: () => setShowPickerFor(i), className: "flex-1 py-3 border border-dashed border-white/20 rounded-lg text-[10px] text-white/30 active:bg-white/5", children: "Bild w\xE4hlen" }),
3406
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { onClick: () => removeSlot(i), className: "text-white/20 active:text-red-400 self-start", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "close" }) })
3289
3407
  ] }, i)),
3290
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
3408
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3291
3409
  "button",
3292
3410
  {
3293
3411
  onClick: addSlot,
3294
3412
  className: "w-full py-2 border border-dashed border-white/10 rounded-xl text-[10px] text-white/30 active:bg-white/5 flex items-center justify-center gap-1",
3295
3413
  children: [
3296
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "add" }),
3414
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "add" }),
3297
3415
  "Bild hinzuf\xFCgen"
3298
3416
  ]
3299
3417
  }
3300
3418
  ),
3301
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
3302
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40 mb-2", children: "Blend-Anweisung" }),
3303
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3419
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
3420
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40 mb-2", children: "Blend-Anweisung" }),
3421
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3304
3422
  "textarea",
3305
3423
  {
3306
3424
  value: instruction,
@@ -3311,24 +3429,24 @@ var LabBlend = ({ services, onResult }) => {
3311
3429
  }
3312
3430
  )
3313
3431
  ] }),
3314
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3432
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3315
3433
  "button",
3316
3434
  {
3317
3435
  onClick: handleGeneratePrompt,
3318
3436
  disabled: selectedImages.filter(Boolean).length < 2 || !instruction.trim() || isGeneratingPrompt,
3319
3437
  className: "w-full py-3 rounded-xl bg-white/10 text-white font-bold text-[12px] uppercase tracking-wide disabled:opacity-30 active:bg-white/15 flex items-center justify-center gap-2",
3320
- children: isGeneratingPrompt ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
3321
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "w-3 h-3 border-t border-white rounded-full animate-spin" }),
3322
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: "Blend l\xE4uft..." })
3323
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
3324
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "merge" }),
3325
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: "Prompts blenden" })
3438
+ children: isGeneratingPrompt ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3439
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "w-3 h-3 border-t border-white rounded-full animate-spin" }),
3440
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Blend l\xE4uft..." })
3441
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3442
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "merge" }),
3443
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Prompts blenden" })
3326
3444
  ] })
3327
3445
  }
3328
3446
  ),
3329
- generatedPrompt && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
3330
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40 mb-2", children: "Blend-Prompt" }),
3331
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3447
+ generatedPrompt && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col gap-2", children: [
3448
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40", children: "Blend-Prompt" }),
3449
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3332
3450
  "textarea",
3333
3451
  {
3334
3452
  value: generatedPrompt,
@@ -3337,38 +3455,46 @@ var LabBlend = ({ services, onResult }) => {
3337
3455
  rows: 4
3338
3456
  }
3339
3457
  ),
3340
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3458
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3459
+ GenerationControls,
3460
+ {
3461
+ aspectRatio,
3462
+ onAspectRatioChange: updateAspectRatio,
3463
+ model,
3464
+ onModelChange: updateModel,
3465
+ imageCount,
3466
+ onImageCountChange: updateImageCount,
3467
+ runningCount
3468
+ }
3469
+ ),
3470
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3341
3471
  "button",
3342
3472
  {
3343
- onClick: handleGenerateImage,
3344
- disabled: isGeneratingImage,
3345
- className: "w-full mt-2 py-3 rounded-xl bg-blue-600/80 text-white font-bold text-[12px] uppercase tracking-wide disabled:opacity-30 active:bg-blue-600 flex items-center justify-center gap-2",
3346
- children: isGeneratingImage ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
3347
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "w-3 h-3 border-t border-white rounded-full animate-spin" }),
3348
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: "Generiere..." })
3349
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
3350
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "image" }),
3351
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: "Bild generieren" })
3352
- ] })
3473
+ onClick: handleGenerateBatch,
3474
+ className: "w-full py-3 rounded-xl bg-blue-600/80 text-white font-bold text-[12px] uppercase tracking-wide active:bg-blue-600 flex items-center justify-center gap-2",
3475
+ children: [
3476
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "image" }),
3477
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Bilder generieren" })
3478
+ ]
3353
3479
  }
3354
3480
  )
3355
3481
  ] }),
3356
- resultImage && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "rounded-xl overflow-hidden border border-white/10", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("img", { src: resultImage, className: "w-full object-cover" }) })
3482
+ resultImages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: `grid gap-2 ${resultImages.length > 1 ? "grid-cols-2" : "grid-cols-1"}`, children: resultImages.map((src, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "rounded-xl overflow-hidden border border-white/10", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("img", { src, className: "w-full object-cover" }) }, i)) })
3357
3483
  ] });
3358
3484
  };
3359
3485
 
3360
3486
  // src/components/labs/LabCompare.tsx
3361
- var import_react20 = require("react");
3362
- var import_jsx_runtime16 = require("react/jsx-runtime");
3487
+ var import_react19 = require("react");
3488
+ var import_jsx_runtime17 = require("react/jsx-runtime");
3363
3489
  var LabCompare = ({ services, onResult }) => {
3364
- const [showPickerFor, setShowPickerFor] = (0, import_react20.useState)(null);
3365
- const [selectedImages, setSelectedImages] = (0, import_react20.useState)([]);
3366
- const [instruction, setInstruction] = (0, import_react20.useState)("");
3367
- const [analysis, setAnalysis] = (0, import_react20.useState)("");
3368
- const [generatedPrompt, setGeneratedPrompt] = (0, import_react20.useState)("");
3369
- const [resultImage, setResultImage] = (0, import_react20.useState)(null);
3370
- const [isAnalyzing, setIsAnalyzing] = (0, import_react20.useState)(false);
3371
- const [isGeneratingImage, setIsGeneratingImage] = (0, import_react20.useState)(false);
3490
+ const [showPickerFor, setShowPickerFor] = (0, import_react19.useState)(null);
3491
+ const [selectedImages, setSelectedImages] = (0, import_react19.useState)([]);
3492
+ const [instruction, setInstruction] = (0, import_react19.useState)("");
3493
+ const [analysis, setAnalysis] = (0, import_react19.useState)("");
3494
+ const [generatedPrompt, setGeneratedPrompt] = (0, import_react19.useState)("");
3495
+ const [resultImage, setResultImage] = (0, import_react19.useState)(null);
3496
+ const [isAnalyzing, setIsAnalyzing] = (0, import_react19.useState)(false);
3497
+ const [isGeneratingImage, setIsGeneratingImage] = (0, import_react19.useState)(false);
3372
3498
  const handleSelectImage = (index, item, frame) => {
3373
3499
  services.onItemUsed(item);
3374
3500
  const newImg = {
@@ -3426,7 +3552,7 @@ var LabCompare = ({ services, onResult }) => {
3426
3552
  }
3427
3553
  };
3428
3554
  if (showPickerFor !== null) {
3429
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3555
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3430
3556
  LabImagePicker,
3431
3557
  {
3432
3558
  availableItems: services.availableItems,
@@ -3437,19 +3563,19 @@ var LabCompare = ({ services, onResult }) => {
3437
3563
  }
3438
3564
  );
3439
3565
  }
3440
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col gap-3 p-4 overflow-y-auto dark-scrollbar", children: [
3441
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40", children: "Bilder zum Vergleichen" }),
3442
- selectedImages.map((img, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex gap-3 p-3 rounded-xl border border-white/10 bg-white/5", children: [
3443
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-[10px] font-bold text-white/40 w-6 shrink-0 pt-1", children: autoLabel(i) }),
3444
- img ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3445
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("img", { src: img.frame.base64, className: "w-12 h-12 object-cover rounded-lg shrink-0 cursor-pointer", onClick: () => setShowPickerFor(i) }),
3446
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1 min-w-0 flex flex-col gap-1", children: [
3447
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-[10px] text-white/50 line-clamp-1", children: img.item.prompt }),
3448
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("label", { className: "flex items-center gap-1 text-[10px] text-white/40", children: [
3449
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("input", { type: "checkbox", checked: img.sendToPromptAI, onChange: (e) => updateImg(i, { sendToPromptAI: e.target.checked }) }),
3566
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex flex-col gap-3 p-4 overflow-y-auto dark-scrollbar", children: [
3567
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40", children: "Bilder zum Vergleichen" }),
3568
+ selectedImages.map((img, i) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex gap-3 p-3 rounded-xl border border-white/10 bg-white/5", children: [
3569
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-[10px] font-bold text-white/40 w-6 shrink-0 pt-1", children: autoLabel(i) }),
3570
+ img ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
3571
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("img", { src: img.frame.base64, className: "w-12 h-12 object-cover rounded-lg shrink-0 cursor-pointer", onClick: () => setShowPickerFor(i) }),
3572
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex-1 min-w-0 flex flex-col gap-1", children: [
3573
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-[10px] text-white/50 line-clamp-1", children: img.item.prompt }),
3574
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("label", { className: "flex items-center gap-1 text-[10px] text-white/40", children: [
3575
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("input", { type: "checkbox", checked: img.sendToPromptAI, onChange: (e) => updateImg(i, { sendToPromptAI: e.target.checked }) }),
3450
3576
  "Bild an KI mitgeben"
3451
3577
  ] }),
3452
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3578
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3453
3579
  "input",
3454
3580
  {
3455
3581
  value: img.roleForPrompt || "",
@@ -3459,16 +3585,16 @@ var LabCompare = ({ services, onResult }) => {
3459
3585
  }
3460
3586
  )
3461
3587
  ] })
3462
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { onClick: () => setShowPickerFor(i), className: "flex-1 py-3 border border-dashed border-white/20 rounded-lg text-[10px] text-white/30 active:bg-white/5", children: "Bild w\xE4hlen" }),
3463
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { onClick: () => removeSlot(i), className: "text-white/20 active:text-red-400 self-start", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "close" }) })
3588
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { onClick: () => setShowPickerFor(i), className: "flex-1 py-3 border border-dashed border-white/20 rounded-lg text-[10px] text-white/30 active:bg-white/5", children: "Bild w\xE4hlen" }),
3589
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { onClick: () => removeSlot(i), className: "text-white/20 active:text-red-400 self-start", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "close" }) })
3464
3590
  ] }, i)),
3465
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { onClick: addSlot, className: "w-full py-2 border border-dashed border-white/10 rounded-xl text-[10px] text-white/30 active:bg-white/5 flex items-center justify-center gap-1", children: [
3466
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "add" }),
3591
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("button", { onClick: addSlot, className: "w-full py-2 border border-dashed border-white/10 rounded-xl text-[10px] text-white/30 active:bg-white/5 flex items-center justify-center gap-1", children: [
3592
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "add" }),
3467
3593
  "Bild hinzuf\xFCgen"
3468
3594
  ] }),
3469
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
3470
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40 mb-2", children: "Analyse-Anweisung" }),
3471
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3595
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { children: [
3596
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40 mb-2", children: "Analyse-Anweisung" }),
3597
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3472
3598
  "textarea",
3473
3599
  {
3474
3600
  value: instruction,
@@ -3479,27 +3605,27 @@ var LabCompare = ({ services, onResult }) => {
3479
3605
  }
3480
3606
  )
3481
3607
  ] }),
3482
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3608
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3483
3609
  "button",
3484
3610
  {
3485
3611
  onClick: handleAnalyze,
3486
3612
  disabled: selectedImages.filter(Boolean).length < 1 || !instruction.trim() || isAnalyzing,
3487
3613
  className: "w-full py-3 rounded-xl bg-white/10 text-white font-bold text-[12px] uppercase tracking-wide disabled:opacity-30 active:bg-white/15 flex items-center justify-center gap-2",
3488
- children: isAnalyzing ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3489
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "w-3 h-3 border-t border-white rounded-full animate-spin" }),
3490
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Analysiere..." })
3491
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3492
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "compare" }),
3493
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Analysieren" })
3614
+ children: isAnalyzing ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
3615
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "w-3 h-3 border-t border-white rounded-full animate-spin" }),
3616
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: "Analysiere..." })
3617
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
3618
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "compare" }),
3619
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: "Analysieren" })
3494
3620
  ] })
3495
3621
  }
3496
3622
  ),
3497
- analysis && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
3498
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40 mb-2", children: "Analyse" }),
3499
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "bg-white/5 border border-white/10 rounded-xl px-3 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-[12px] text-white/70 leading-relaxed whitespace-pre-wrap", children: analysis }) }),
3500
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "mt-3", children: [
3501
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40 mb-2", children: "Als Prompt nutzen" }),
3502
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3623
+ analysis && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { children: [
3624
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40 mb-2", children: "Analyse" }),
3625
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "bg-white/5 border border-white/10 rounded-xl px-3 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-[12px] text-white/70 leading-relaxed whitespace-pre-wrap", children: analysis }) }),
3626
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "mt-3", children: [
3627
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40 mb-2", children: "Als Prompt nutzen" }),
3628
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3503
3629
  "textarea",
3504
3630
  {
3505
3631
  value: generatedPrompt,
@@ -3509,36 +3635,37 @@ var LabCompare = ({ services, onResult }) => {
3509
3635
  rows: 3
3510
3636
  }
3511
3637
  ),
3512
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3638
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3513
3639
  "button",
3514
3640
  {
3515
3641
  onClick: handleGenerateImage,
3516
3642
  disabled: !generatedPrompt.trim() || isGeneratingImage,
3517
3643
  className: "w-full mt-2 py-3 rounded-xl bg-blue-600/80 text-white font-bold text-[12px] uppercase tracking-wide disabled:opacity-30 active:bg-blue-600 flex items-center justify-center gap-2",
3518
- children: isGeneratingImage ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3519
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "w-3 h-3 border-t border-white rounded-full animate-spin" }),
3520
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Generiere..." })
3521
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3522
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "image" }),
3523
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Bild generieren" })
3644
+ children: isGeneratingImage ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
3645
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "w-3 h-3 border-t border-white rounded-full animate-spin" }),
3646
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: "Generiere..." })
3647
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
3648
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "image" }),
3649
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: "Bild generieren" })
3524
3650
  ] })
3525
3651
  }
3526
3652
  )
3527
3653
  ] })
3528
3654
  ] }),
3529
- resultImage && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "rounded-xl overflow-hidden border border-white/10", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("img", { src: resultImage, className: "w-full object-cover" }) })
3655
+ resultImage && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "rounded-xl overflow-hidden border border-white/10", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("img", { src: resultImage, className: "w-full object-cover" }) })
3530
3656
  ] });
3531
3657
  };
3532
3658
 
3533
3659
  // src/components/labs/LabLoop.tsx
3534
- var import_react21 = require("react");
3535
- var import_jsx_runtime17 = require("react/jsx-runtime");
3660
+ var import_react20 = require("react");
3661
+ var import_jsx_runtime18 = require("react/jsx-runtime");
3536
3662
  var LabLoop = ({ services, onResult }) => {
3537
- const [rounds, setRounds] = (0, import_react21.useState)([]);
3538
- const [currentInstruction, setCurrentInstruction] = (0, import_react21.useState)("");
3539
- const [showPickerForRound, setShowPickerForRound] = (0, import_react21.useState)(null);
3540
- const [pendingImages, setPendingImages] = (0, import_react21.useState)([]);
3541
- const [isGenerating, setIsGenerating] = (0, import_react21.useState)(false);
3663
+ const [rounds, setRounds] = (0, import_react20.useState)([]);
3664
+ const [currentInstruction, setCurrentInstruction] = (0, import_react20.useState)("");
3665
+ const [showPickerForRound, setShowPickerForRound] = (0, import_react20.useState)(null);
3666
+ const [pendingImages, setPendingImages] = (0, import_react20.useState)([]);
3667
+ const [isGenerating, setIsGenerating] = (0, import_react20.useState)(false);
3668
+ const { aspectRatio, model, updateAspectRatio, updateModel } = useGenerationSettings();
3542
3669
  const currentPrompt = rounds.length > 0 ? rounds[rounds.length - 1].prompt : "";
3543
3670
  const handleAddImage = (item, frame) => {
3544
3671
  services.onItemUsed(item);
@@ -3572,8 +3699,8 @@ var LabLoop = ({ services, onResult }) => {
3572
3699
  });
3573
3700
  const { base64, mediaId } = await services.generateImage({
3574
3701
  prompt: newPrompt,
3575
- aspectRatio: "1:1",
3576
- modelDisplayName: "\u{1F34C} Nano Banana Pro"
3702
+ aspectRatio,
3703
+ modelDisplayName: model
3577
3704
  });
3578
3705
  const newBase64 = `data:image/png;base64,${base64}`;
3579
3706
  const newFrame = { id: crypto.randomUUID(), base64: newBase64, mediaId, source: "generated" };
@@ -3599,7 +3726,7 @@ var LabLoop = ({ services, onResult }) => {
3599
3726
  }
3600
3727
  };
3601
3728
  if (showPickerForRound !== null) {
3602
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3729
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3603
3730
  LabImagePicker,
3604
3731
  {
3605
3732
  availableItems: services.availableItems,
@@ -3610,32 +3737,32 @@ var LabLoop = ({ services, onResult }) => {
3610
3737
  }
3611
3738
  );
3612
3739
  }
3613
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex flex-col gap-3 p-4 overflow-y-auto dark-scrollbar", children: [
3614
- rounds.map((round, i) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex gap-3 p-3 rounded-xl border border-white/10 bg-white/5", children: [
3615
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex flex-col items-center gap-1 shrink-0", children: [
3616
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "text-[9px] font-bold text-white/30", children: [
3740
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex flex-col gap-3 p-4 overflow-y-auto dark-scrollbar", children: [
3741
+ rounds.map((round, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex gap-3 p-3 rounded-xl border border-white/10 bg-white/5", children: [
3742
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex flex-col items-center gap-1 shrink-0", children: [
3743
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "text-[9px] font-bold text-white/30", children: [
3617
3744
  "R",
3618
3745
  i + 1
3619
3746
  ] }),
3620
- round.frame && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("img", { src: round.frame.base64, className: "w-12 h-12 object-cover rounded-lg" })
3747
+ round.frame && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("img", { src: round.frame.base64, className: "w-12 h-12 object-cover rounded-lg" })
3621
3748
  ] }),
3622
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex-1 min-w-0", children: [
3623
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("p", { className: "text-[9px] text-white/30 italic mb-1", children: [
3749
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex-1 min-w-0", children: [
3750
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("p", { className: "text-[9px] text-white/30 italic mb-1", children: [
3624
3751
  '"',
3625
3752
  round.instruction,
3626
3753
  '"'
3627
3754
  ] }),
3628
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-[10px] text-white/60 leading-tight line-clamp-3", children: round.prompt })
3755
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-[10px] text-white/60 leading-tight line-clamp-3", children: round.prompt })
3629
3756
  ] })
3630
3757
  ] }, i)),
3631
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "rounded-xl border border-white/20 bg-white/5 p-3 flex flex-col gap-3", children: [
3632
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40", children: rounds.length === 0 ? "Runde 1 \u2014 Erster Prompt" : `Runde ${rounds.length + 1}` }),
3633
- currentPrompt && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("p", { className: "text-[10px] text-white/40 italic line-clamp-2", children: [
3758
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "rounded-xl border border-white/20 bg-white/5 p-3 flex flex-col gap-3", children: [
3759
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-[9px] font-bold uppercase tracking-widest text-white/40", children: rounds.length === 0 ? "Runde 1 \u2014 Erster Prompt" : `Runde ${rounds.length + 1}` }),
3760
+ currentPrompt && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("p", { className: "text-[10px] text-white/40 italic line-clamp-2", children: [
3634
3761
  'Letzter Prompt: "',
3635
3762
  currentPrompt,
3636
3763
  '"'
3637
3764
  ] }),
3638
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3765
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3639
3766
  "textarea",
3640
3767
  {
3641
3768
  value: currentInstruction,
@@ -3645,10 +3772,10 @@ var LabLoop = ({ services, onResult }) => {
3645
3772
  rows: 3
3646
3773
  }
3647
3774
  ),
3648
- pendingImages.map((img, i) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex gap-2 items-center", children: [
3649
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("img", { src: img.frame.base64, className: "w-8 h-8 object-cover rounded" }),
3650
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-[10px] text-white/40", children: img.label }),
3651
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3775
+ pendingImages.map((img, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex gap-2 items-center", children: [
3776
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("img", { src: img.frame.base64, className: "w-8 h-8 object-cover rounded" }),
3777
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-[10px] text-white/40", children: img.label }),
3778
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3652
3779
  "input",
3653
3780
  {
3654
3781
  value: img.roleForPrompt || "",
@@ -3657,36 +3784,43 @@ var LabLoop = ({ services, onResult }) => {
3657
3784
  className: "flex-1 bg-black/30 border border-white/10 rounded px-2 py-0.5 text-[10px] text-white/60 outline-none"
3658
3785
  }
3659
3786
  ),
3660
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("label", { className: "flex items-center gap-1 text-[9px] text-white/30", children: [
3661
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("input", { type: "checkbox", checked: img.sendToPromptAI, onChange: (e) => updatePendingImage(i, { sendToPromptAI: e.target.checked }) }),
3787
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-1 text-[9px] text-white/30", children: [
3788
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("input", { type: "checkbox", checked: img.sendToPromptAI, onChange: (e) => updatePendingImage(i, { sendToPromptAI: e.target.checked }) }),
3662
3789
  "KI"
3663
3790
  ] }),
3664
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { onClick: () => setPendingImages((prev) => prev.filter((_, idx) => idx !== i)), className: "text-white/20 active:text-red-400", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "close" }) })
3791
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { onClick: () => setPendingImages((prev) => prev.filter((_, idx) => idx !== i)), className: "text-white/20 active:text-red-400", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "close" }) })
3665
3792
  ] }, i)),
3666
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
3793
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
3667
3794
  "button",
3668
3795
  {
3669
3796
  onClick: () => setShowPickerForRound(rounds.length),
3670
3797
  className: "text-[10px] text-white/30 active:text-white/60 flex items-center gap-1 self-start",
3671
3798
  children: [
3672
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "add_photo_alternate" }),
3799
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "add_photo_alternate" }),
3673
3800
  "Referenzbild hinzuf\xFCgen"
3674
3801
  ]
3675
3802
  }
3676
3803
  ),
3677
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3804
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3805
+ GenerationControls,
3806
+ {
3807
+ aspectRatio,
3808
+ onAspectRatioChange: updateAspectRatio,
3809
+ model,
3810
+ onModelChange: updateModel,
3811
+ runningCount: isGenerating ? 1 : 0
3812
+ }
3813
+ ),
3814
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
3678
3815
  "button",
3679
3816
  {
3680
3817
  onClick: handleRunRound,
3681
- disabled: !currentInstruction.trim() || isGenerating,
3818
+ disabled: !currentInstruction.trim(),
3682
3819
  className: "w-full py-3 rounded-xl bg-white/10 text-white font-bold text-[12px] uppercase tracking-wide disabled:opacity-30 active:bg-white/15 flex items-center justify-center gap-2",
3683
- children: isGenerating ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
3684
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "w-3 h-3 border-t border-white rounded-full animate-spin" }),
3685
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: "Runde l\xE4uft..." })
3686
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
3687
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "loop" }),
3688
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { children: "Runde starten" })
3689
- ] })
3820
+ children: [
3821
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "loop" }),
3822
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: "Runde starten" })
3823
+ ]
3690
3824
  }
3691
3825
  )
3692
3826
  ] })
@@ -3694,8 +3828,8 @@ var LabLoop = ({ services, onResult }) => {
3694
3828
  };
3695
3829
 
3696
3830
  // src/components/labs/LabFrameExtractor.tsx
3697
- var import_react22 = require("react");
3698
- var import_jsx_runtime18 = require("react/jsx-runtime");
3831
+ var import_react21 = require("react");
3832
+ var import_jsx_runtime19 = require("react/jsx-runtime");
3699
3833
  var formatTime = (s) => {
3700
3834
  const m = Math.floor(s / 60);
3701
3835
  const sec = (s % 60).toFixed(1);
@@ -3708,15 +3842,15 @@ var LabFrameExtractor = ({
3708
3842
  onResult,
3709
3843
  resolveVideoUrl
3710
3844
  }) => {
3711
- const videoRef = (0, import_react22.useRef)(null);
3712
- const canvasRef = (0, import_react22.useRef)(null);
3713
- const cancelledRef = (0, import_react22.useRef)(false);
3714
- const [selectedItem, setSelectedItem] = (0, import_react22.useState)(null);
3715
- const [videoSrc, setVideoSrc] = (0, import_react22.useState)(null);
3716
- const [videoReady, setVideoReady] = (0, import_react22.useState)(false);
3717
- const [frames, setFrames] = (0, import_react22.useState)([]);
3718
- const [isExtracting, setIsExtracting] = (0, import_react22.useState)(false);
3719
- const [intervalSec, setIntervalSec] = (0, import_react22.useState)("1");
3845
+ const videoRef = (0, import_react21.useRef)(null);
3846
+ const canvasRef = (0, import_react21.useRef)(null);
3847
+ const cancelledRef = (0, import_react21.useRef)(false);
3848
+ const [selectedItem, setSelectedItem] = (0, import_react21.useState)(null);
3849
+ const [videoSrc, setVideoSrc] = (0, import_react21.useState)(null);
3850
+ const [videoReady, setVideoReady] = (0, import_react21.useState)(false);
3851
+ const [frames, setFrames] = (0, import_react21.useState)([]);
3852
+ const [isExtracting, setIsExtracting] = (0, import_react21.useState)(false);
3853
+ const [intervalSec, setIntervalSec] = (0, import_react21.useState)("1");
3720
3854
  const handleVideoSelect = (item) => {
3721
3855
  const mediaId = item.frames[0]?.mediaId;
3722
3856
  if (!mediaId) return;
@@ -3726,7 +3860,7 @@ var LabFrameExtractor = ({
3726
3860
  setVideoReady(false);
3727
3861
  cancelledRef.current = false;
3728
3862
  };
3729
- const captureAt = (0, import_react22.useCallback)(
3863
+ const captureAt = (0, import_react21.useCallback)(
3730
3864
  (t, label) => new Promise((resolve) => {
3731
3865
  const video = videoRef.current;
3732
3866
  const canvas = canvasRef.current;
@@ -3796,10 +3930,10 @@ var LabFrameExtractor = ({
3796
3930
  frames: [labFrame]
3797
3931
  });
3798
3932
  };
3799
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 12, padding: 12, height: "100%", overflow: "auto" }, children: [
3800
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: [
3801
- videoItems.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: { fontSize: 11, color: "#666", fontStyle: "italic" }, children: "No video items available" }),
3802
- videoItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3933
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 12, padding: 12, height: "100%", overflow: "auto" }, children: [
3934
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: [
3935
+ videoItems.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: { fontSize: 11, color: "#666", fontStyle: "italic" }, children: "No video items available" }),
3936
+ videoItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3803
3937
  "button",
3804
3938
  {
3805
3939
  onClick: () => handleVideoSelect(item),
@@ -3817,7 +3951,7 @@ var LabFrameExtractor = ({
3817
3951
  item.id
3818
3952
  ))
3819
3953
  ] }),
3820
- videoSrc && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3954
+ videoSrc && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3821
3955
  "video",
3822
3956
  {
3823
3957
  ref: videoRef,
@@ -3828,9 +3962,9 @@ var LabFrameExtractor = ({
3828
3962
  style: { width: "100%", maxHeight: 280, background: "#000", borderRadius: 6, display: "block" }
3829
3963
  }
3830
3964
  ),
3831
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("canvas", { ref: canvasRef, style: { display: "none" } }),
3832
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", gap: 6, alignItems: "center" }, children: [
3833
- ["start", "current", "end"].map((mode) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3965
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("canvas", { ref: canvasRef, style: { display: "none" } }),
3966
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", gap: 6, alignItems: "center" }, children: [
3967
+ ["start", "current", "end"].map((mode) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3834
3968
  "button",
3835
3969
  {
3836
3970
  disabled: !videoReady,
@@ -3849,21 +3983,21 @@ var LabFrameExtractor = ({
3849
3983
  },
3850
3984
  mode
3851
3985
  )),
3852
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: { fontSize: 11, color: "#aaa" }, children: "every" }),
3853
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3986
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: { fontSize: 11, color: "#aaa" }, children: "every" }),
3987
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3854
3988
  "select",
3855
3989
  {
3856
3990
  value: intervalSec,
3857
3991
  onChange: (e) => setIntervalSec(e.target.value),
3858
3992
  disabled: !videoReady || isExtracting,
3859
3993
  style: { fontSize: 11, background: "#111", border: "1px solid #333", color: "#fff", borderRadius: 4, padding: "2px 4px" },
3860
- children: INTERVAL_OPTIONS.map((v) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("option", { value: v, children: [
3994
+ children: INTERVAL_OPTIONS.map((v) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("option", { value: v, children: [
3861
3995
  v,
3862
3996
  "s"
3863
3997
  ] }, v))
3864
3998
  }
3865
3999
  ),
3866
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4000
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3867
4001
  "button",
3868
4002
  {
3869
4003
  disabled: !videoReady,
@@ -3884,8 +4018,8 @@ var LabFrameExtractor = ({
3884
4018
  }
3885
4019
  )
3886
4020
  ] }),
3887
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", gap: 8, overflowX: "auto", paddingBottom: 4 }, children: [
3888
- frames.map((frame) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
4021
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", gap: 8, overflowX: "auto", paddingBottom: 4 }, children: [
4022
+ frames.map((frame) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
3889
4023
  "div",
3890
4024
  {
3891
4025
  style: {
@@ -3897,10 +4031,10 @@ var LabFrameExtractor = ({
3897
4031
  background: "rgba(255,255,255,0.03)"
3898
4032
  },
3899
4033
  children: [
3900
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("img", { src: frame.dataUrl, style: { width: "100%", aspectRatio: "16/9", objectFit: "cover", display: "block" }, alt: frame.label }),
3901
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { fontSize: 9, color: "#888", textAlign: "center", padding: "2px 4px", fontFamily: "monospace" }, children: frame.label }),
3902
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", gap: 2, padding: "0 4px 4px", justifyContent: "center" }, children: [
3903
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4034
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("img", { src: frame.dataUrl, style: { width: "100%", aspectRatio: "16/9", objectFit: "cover", display: "block" }, alt: frame.label }),
4035
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { fontSize: 9, color: "#888", textAlign: "center", padding: "2px 4px", fontFamily: "monospace" }, children: frame.label }),
4036
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", gap: 2, padding: "0 4px 4px", justifyContent: "center" }, children: [
4037
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3904
4038
  "button",
3905
4039
  {
3906
4040
  onClick: () => useFrame(frame),
@@ -3917,7 +4051,7 @@ var LabFrameExtractor = ({
3917
4051
  children: "Use"
3918
4052
  }
3919
4053
  ),
3920
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4054
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3921
4055
  "button",
3922
4056
  {
3923
4057
  onClick: () => setFrames((prev) => prev.filter((f) => f.id !== frame.id)),
@@ -3938,13 +4072,13 @@ var LabFrameExtractor = ({
3938
4072
  },
3939
4073
  frame.id
3940
4074
  )),
3941
- frames.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: { fontSize: 11, color: "#444", fontStyle: "italic", padding: "16px 0" }, children: isExtracting ? "Extracting frames\u2026" : "No frames yet" })
4075
+ frames.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: { fontSize: 11, color: "#444", fontStyle: "italic", padding: "16px 0" }, children: isExtracting ? "Extracting frames\u2026" : "No frames yet" })
3942
4076
  ] })
3943
4077
  ] });
3944
4078
  };
3945
4079
 
3946
4080
  // src/components/labs/LabsTab.tsx
3947
- var import_jsx_runtime19 = require("react/jsx-runtime");
4081
+ var import_jsx_runtime20 = require("react/jsx-runtime");
3948
4082
  var BASE_TABS = [
3949
4083
  { key: "remix", label: "Remix", icon: "auto_fix_high" },
3950
4084
  { key: "blend", label: "Blend", icon: "merge" },
@@ -3953,28 +4087,28 @@ var BASE_TABS = [
3953
4087
  ];
3954
4088
  var FRAMES_TAB = { key: "frames", label: "Frames", icon: "crop_original" };
3955
4089
  var LabsTab = ({ services, onResult, videoItems, resolveVideoUrl }) => {
3956
- const [activeTab, setActiveTab] = (0, import_react23.useState)("remix");
4090
+ const [activeTab, setActiveTab] = (0, import_react22.useState)("remix");
3957
4091
  const showFrames = !!(videoItems && resolveVideoUrl);
3958
4092
  const tabs = showFrames ? [...BASE_TABS, FRAMES_TAB] : BASE_TABS;
3959
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col h-full overflow-hidden", children: [
3960
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex border-b border-white/5 shrink-0", children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
4093
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-col h-full overflow-hidden", children: [
4094
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex border-b border-white/5 shrink-0", children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
3961
4095
  "button",
3962
4096
  {
3963
4097
  onClick: () => setActiveTab(tab.key),
3964
4098
  className: `flex-1 flex items-center justify-center gap-1 h-10 text-[9px] font-bold uppercase tracking-wide transition-colors ${activeTab === tab.key ? "text-white border-b-2 border-white" : "text-white/30 hover:text-white/60"}`,
3965
4099
  children: [
3966
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: tab.icon }),
4100
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: tab.icon }),
3967
4101
  tab.label
3968
4102
  ]
3969
4103
  },
3970
4104
  tab.key
3971
4105
  )) }),
3972
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex-1 overflow-hidden", children: [
3973
- activeTab === "remix" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(LabRemix, { services, onResult }),
3974
- activeTab === "blend" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(LabBlend, { services, onResult }),
3975
- activeTab === "compare" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(LabCompare, { services, onResult }),
3976
- activeTab === "loop" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(LabLoop, { services, onResult }),
3977
- activeTab === "frames" && showFrames && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
4106
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex-1 overflow-hidden", children: [
4107
+ activeTab === "remix" && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LabRemix, { services, onResult }),
4108
+ activeTab === "blend" && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LabBlend, { services, onResult }),
4109
+ activeTab === "compare" && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LabCompare, { services, onResult }),
4110
+ activeTab === "loop" && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LabLoop, { services, onResult }),
4111
+ activeTab === "frames" && showFrames && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3978
4112
  LabFrameExtractor,
3979
4113
  {
3980
4114
  videoItems,
@@ -3987,19 +4121,19 @@ var LabsTab = ({ services, onResult, videoItems, resolveVideoUrl }) => {
3987
4121
  };
3988
4122
 
3989
4123
  // src/components/TagManagerPanel.tsx
3990
- var import_react24 = require("react");
3991
- var import_jsx_runtime20 = require("react/jsx-runtime");
4124
+ var import_react23 = require("react");
4125
+ var import_jsx_runtime21 = require("react/jsx-runtime");
3992
4126
  function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete, onTagReorder, onTagMove }) {
3993
4127
  const categories = Object.keys(workspaceTags.by_category).filter(
3994
4128
  (cat) => (workspaceTags.by_category[cat] || []).some((t) => !t.is_deleted)
3995
4129
  );
3996
- const [selectedCategory, setSelectedCategory] = (0, import_react24.useState)(categories[0] || "");
4130
+ const [selectedCategory, setSelectedCategory] = (0, import_react23.useState)(categories[0] || "");
3997
4131
  const effectiveCategory = categories.includes(selectedCategory) ? selectedCategory : categories[0] || "";
3998
- const [editingLabel, setEditingLabel] = (0, import_react24.useState)(null);
3999
- const [editState, setEditState] = (0, import_react24.useState)({ label: "", value: "" });
4000
- const [newTag, setNewTag] = (0, import_react24.useState)({ label: "", value: "" });
4001
- const [movingLabel, setMovingLabel] = (0, import_react24.useState)(null);
4002
- const [moveTarget, setMoveTarget] = (0, import_react24.useState)("");
4132
+ const [editingLabel, setEditingLabel] = (0, import_react23.useState)(null);
4133
+ const [editState, setEditState] = (0, import_react23.useState)({ label: "", value: "" });
4134
+ const [newTag, setNewTag] = (0, import_react23.useState)({ label: "", value: "" });
4135
+ const [movingLabel, setMovingLabel] = (0, import_react23.useState)(null);
4136
+ const [moveTarget, setMoveTarget] = (0, import_react23.useState)("");
4003
4137
  const tags = (workspaceTags.by_category[effectiveCategory] || []).filter((t) => !t.is_deleted);
4004
4138
  const otherCategories = categories.filter((c) => c !== effectiveCategory);
4005
4139
  const startEdit = (tag) => {
@@ -4042,10 +4176,10 @@ function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete,
4042
4176
  if (!confirm(`Tag "${tag.label}" l\xF6schen?`)) return;
4043
4177
  onTagDelete(tag.label, effectiveCategory);
4044
4178
  };
4045
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-col h-full overflow-hidden", children: [
4046
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "px-3 py-2 border-b border-white/5 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-[10px] font-bold uppercase tracking-widest text-white/40", children: "Tag Manager" }) }),
4047
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "px-3 py-2 shrink-0 overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex gap-1.5 flex-nowrap", children: [
4048
- categories.map((cat) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
4179
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col h-full overflow-hidden", children: [
4180
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "px-3 py-2 border-b border-white/5 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[10px] font-bold uppercase tracking-widest text-white/40", children: "Tag Manager" }) }),
4181
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "px-3 py-2 shrink-0 overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex gap-1.5 flex-nowrap", children: [
4182
+ categories.map((cat) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4049
4183
  "button",
4050
4184
  {
4051
4185
  onClick: () => {
@@ -4057,17 +4191,17 @@ function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete,
4057
4191
  children: [
4058
4192
  cat,
4059
4193
  " ",
4060
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ml-1 opacity-50", children: (workspaceTags.by_category[cat] || []).filter((t) => !t.is_deleted).length })
4194
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ml-1 opacity-50", children: (workspaceTags.by_category[cat] || []).filter((t) => !t.is_deleted).length })
4061
4195
  ]
4062
4196
  },
4063
4197
  cat
4064
4198
  )),
4065
- categories.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-[10px] text-white/20", children: "Erst Workspace importieren" })
4199
+ categories.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[10px] text-white/20", children: "Erst Workspace importieren" })
4066
4200
  ] }) }),
4067
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex-1 overflow-y-auto dark-scrollbar px-3 pb-2 space-y-1", children: [
4068
- tags.map((tag, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { children: [
4069
- editingLabel === tag.label ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "bg-white/5 border border-blue-600/40 rounded-lg p-2.5 space-y-1.5", children: [
4070
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4201
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex-1 overflow-y-auto dark-scrollbar px-3 pb-2 space-y-1", children: [
4202
+ tags.map((tag, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
4203
+ editingLabel === tag.label ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "bg-white/5 border border-blue-600/40 rounded-lg p-2.5 space-y-1.5", children: [
4204
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4071
4205
  "input",
4072
4206
  {
4073
4207
  value: editState.label,
@@ -4078,7 +4212,7 @@ function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete,
4078
4212
  onKeyDown: (e) => e.key === "Enter" && saveEdit(tag.label)
4079
4213
  }
4080
4214
  ),
4081
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4215
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4082
4216
  "textarea",
4083
4217
  {
4084
4218
  value: editState.value,
@@ -4088,24 +4222,24 @@ function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete,
4088
4222
  placeholder: "Prompt-Wert (leer = Label)"
4089
4223
  }
4090
4224
  ),
4091
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex gap-1.5 justify-end", children: [
4092
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { onClick: () => saveEdit(tag.label), className: "px-2.5 py-1 bg-blue-700 hover:bg-blue-600 text-white text-[10px] font-bold rounded transition", children: "SPEICHERN" }),
4093
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { onClick: () => setEditingLabel(null), className: "px-2.5 py-1 bg-white/5 hover:bg-white/10 text-white/50 text-[10px] font-bold rounded transition", children: "ABBRUCH" })
4225
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex gap-1.5 justify-end", children: [
4226
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => saveEdit(tag.label), className: "px-2.5 py-1 bg-blue-700 hover:bg-blue-600 text-white text-[10px] font-bold rounded transition", children: "SPEICHERN" }),
4227
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => setEditingLabel(null), className: "px-2.5 py-1 bg-white/5 hover:bg-white/10 text-white/50 text-[10px] font-bold rounded transition", children: "ABBRUCH" })
4094
4228
  ] })
4095
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "group flex items-center gap-1.5 bg-white/3 hover:bg-white/6 border border-white/5 rounded-lg px-2 py-1.5 transition", children: [
4096
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-col gap-0 shrink-0", children: [
4097
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { onClick: () => handleMoveUp(i), disabled: i === 0, className: "text-white/20 hover:text-white/60 disabled:opacity-10 transition leading-none", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "arrow_drop_up" }) }),
4098
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { onClick: () => handleMoveDown(i), disabled: i === tags.length - 1, className: "text-white/20 hover:text-white/60 disabled:opacity-10 transition leading-none", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "arrow_drop_down" }) })
4229
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "group flex items-center gap-1.5 bg-white/3 hover:bg-white/6 border border-white/5 rounded-lg px-2 py-1.5 transition", children: [
4230
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col gap-0 shrink-0", children: [
4231
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => handleMoveUp(i), disabled: i === 0, className: "text-white/20 hover:text-white/60 disabled:opacity-10 transition leading-none", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "arrow_drop_up" }) }),
4232
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => handleMoveDown(i), disabled: i === tags.length - 1, className: "text-white/20 hover:text-white/60 disabled:opacity-10 transition leading-none", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "arrow_drop_down" }) })
4099
4233
  ] }),
4100
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex-1 min-w-0", children: [
4101
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "text-[12px] text-white/80 font-medium truncate", children: tag.label }),
4102
- tag.value && tag.value !== tag.label && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "text-[10px] text-white/30 truncate", children: [
4234
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex-1 min-w-0", children: [
4235
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-[12px] text-white/80 font-medium truncate", children: tag.label }),
4236
+ tag.value && tag.value !== tag.label && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "text-[10px] text-white/30 truncate", children: [
4103
4237
  tag.value.slice(0, 60),
4104
4238
  tag.value.length > 60 ? "\u2026" : ""
4105
4239
  ] })
4106
4240
  ] }),
4107
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex gap-1 opacity-0 group-hover:opacity-100 transition shrink-0", children: [
4108
- otherCategories.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4241
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex gap-1 opacity-0 group-hover:opacity-100 transition shrink-0", children: [
4242
+ otherCategories.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4109
4243
  "button",
4110
4244
  {
4111
4245
  onClick: () => {
@@ -4115,29 +4249,29 @@ function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete,
4115
4249
  },
4116
4250
  className: "p-1 rounded text-white/30 hover:text-purple-400 transition",
4117
4251
  title: "Kategorie wechseln",
4118
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "drive_file_move" })
4252
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "drive_file_move" })
4119
4253
  }
4120
4254
  ),
4121
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { onClick: () => startEdit(tag), className: "p-1 rounded text-white/30 hover:text-blue-400 transition", title: "Bearbeiten", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "edit" }) }),
4122
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { onClick: () => handleDelete(tag), className: "p-1 rounded text-white/30 hover:text-red-400 transition", title: "L\xF6schen", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "delete" }) })
4255
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => startEdit(tag), className: "p-1 rounded text-white/30 hover:text-blue-400 transition", title: "Bearbeiten", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "edit" }) }),
4256
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => handleDelete(tag), className: "p-1 rounded text-white/30 hover:text-red-400 transition", title: "L\xF6schen", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "delete" }) })
4123
4257
  ] })
4124
4258
  ] }),
4125
- movingLabel === tag.label && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "mt-1 bg-purple-900/20 border border-purple-700/30 rounded-lg p-2.5 space-y-1.5", children: [
4126
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "text-[9px] font-bold uppercase tracking-widest text-purple-400/70", children: "Verschieben nach Kategorie" }),
4127
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
4259
+ movingLabel === tag.label && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-1 bg-purple-900/20 border border-purple-700/30 rounded-lg p-2.5 space-y-1.5", children: [
4260
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-[9px] font-bold uppercase tracking-widest text-purple-400/70", children: "Verschieben nach Kategorie" }),
4261
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4128
4262
  "select",
4129
4263
  {
4130
4264
  value: moveTarget,
4131
4265
  onChange: (e) => setMoveTarget(e.target.value),
4132
4266
  className: "w-full bg-black/40 border border-white/10 rounded px-2 py-1 text-[11px] text-white/70 outline-none",
4133
4267
  children: [
4134
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("option", { value: "", children: "\u2014 Kategorie w\xE4hlen \u2014" }),
4135
- otherCategories.map((cat) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("option", { value: cat, children: cat }, cat))
4268
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: "", children: "\u2014 Kategorie w\xE4hlen \u2014" }),
4269
+ otherCategories.map((cat) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: cat, children: cat }, cat))
4136
4270
  ]
4137
4271
  }
4138
4272
  ),
4139
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex gap-1.5 justify-end", children: [
4140
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4273
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex gap-1.5 justify-end", children: [
4274
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4141
4275
  "button",
4142
4276
  {
4143
4277
  onClick: () => handleMove(tag),
@@ -4146,19 +4280,19 @@ function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete,
4146
4280
  children: "VERSCHIEBEN"
4147
4281
  }
4148
4282
  ),
4149
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { onClick: () => setMovingLabel(null), className: "px-2.5 py-1 bg-white/5 hover:bg-white/10 text-white/50 text-[10px] font-bold rounded transition", children: "ABBRUCH" })
4283
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: () => setMovingLabel(null), className: "px-2.5 py-1 bg-white/5 hover:bg-white/10 text-white/50 text-[10px] font-bold rounded transition", children: "ABBRUCH" })
4150
4284
  ] })
4151
4285
  ] })
4152
4286
  ] }, `${effectiveCategory}-${i}`)),
4153
- tags.length === 0 && effectiveCategory && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "text-center text-[11px] text-white/20 py-6", children: "Keine Tags in dieser Kategorie." })
4287
+ tags.length === 0 && effectiveCategory && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-center text-[11px] text-white/20 py-6", children: "Keine Tags in dieser Kategorie." })
4154
4288
  ] }),
4155
- effectiveCategory && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "px-3 py-2 border-t border-white/5 shrink-0 space-y-1.5", children: [
4156
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "text-[9px] font-bold uppercase tracking-widest text-white/30", children: [
4289
+ effectiveCategory && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "px-3 py-2 border-t border-white/5 shrink-0 space-y-1.5", children: [
4290
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "text-[9px] font-bold uppercase tracking-widest text-white/30", children: [
4157
4291
  "Neuer Tag in \u201E",
4158
4292
  effectiveCategory,
4159
4293
  '"'
4160
4294
  ] }),
4161
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4295
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4162
4296
  "input",
4163
4297
  {
4164
4298
  value: newTag.label,
@@ -4168,7 +4302,7 @@ function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete,
4168
4302
  className: "w-full bg-black/40 border border-white/10 rounded px-2 py-1.5 text-[12px] text-white outline-none focus:border-white/20"
4169
4303
  }
4170
4304
  ),
4171
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4305
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4172
4306
  "textarea",
4173
4307
  {
4174
4308
  value: newTag.value,
@@ -4178,14 +4312,14 @@ function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete,
4178
4312
  className: "w-full bg-black/40 border border-white/10 rounded px-2 py-1 text-[11px] text-white/60 outline-none focus:border-white/20 resize-none"
4179
4313
  }
4180
4314
  ),
4181
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
4315
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4182
4316
  "button",
4183
4317
  {
4184
4318
  onClick: handleCreate,
4185
4319
  disabled: !newTag.label.trim(),
4186
4320
  className: "w-full py-1.5 bg-white/5 border border-white/10 text-white/60 text-[10px] font-bold rounded hover:bg-white/10 hover:text-white transition disabled:opacity-30 flex items-center justify-center gap-1.5",
4187
4321
  children: [
4188
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "add" }),
4322
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "add" }),
4189
4323
  "TAG ERSTELLEN"
4190
4324
  ]
4191
4325
  }
@@ -4195,8 +4329,8 @@ function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete,
4195
4329
  }
4196
4330
 
4197
4331
  // src/components/HFTestTab.tsx
4198
- var import_react25 = require("react");
4199
- var import_jsx_runtime21 = require("react/jsx-runtime");
4332
+ var import_react24 = require("react");
4333
+ var import_jsx_runtime22 = require("react/jsx-runtime");
4200
4334
  var HF_BASE2 = "https://huggingface.co";
4201
4335
  var HF_REPO2 = "RolandSch/fa-app-state";
4202
4336
  var TEST_DIR = "test";
@@ -4388,8 +4522,8 @@ function tryFmt(s) {
4388
4522
  }
4389
4523
  }
4390
4524
  function CopyBtn({ text }) {
4391
- const [done, setDone] = (0, import_react25.useState)(false);
4392
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4525
+ const [done, setDone] = (0, import_react24.useState)(false);
4526
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
4393
4527
  "button",
4394
4528
  {
4395
4529
  onClick: () => {
@@ -4400,7 +4534,7 @@ function CopyBtn({ text }) {
4400
4534
  },
4401
4535
  style: { background: "none", border: "1px solid rgba(255,255,255,0.15)", borderRadius: 5, color: done ? "#4ade80" : "rgba(255,255,255,0.45)", fontSize: 10, padding: "3px 8px", cursor: "pointer", fontFamily: "inherit", display: "flex", alignItems: "center", gap: 3 },
4402
4536
  children: [
4403
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: done ? "check" : "content_copy" }),
4537
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: done ? "check" : "content_copy" }),
4404
4538
  done ? "Kopiert" : "Copy"
4405
4539
  ]
4406
4540
  }
@@ -4408,35 +4542,35 @@ function CopyBtn({ text }) {
4408
4542
  }
4409
4543
  function StepView({ step }) {
4410
4544
  const isSpecial = step.method === "-" || step.method === "import()" || step.method === "import()+call";
4411
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: 6, background: "rgba(0,0,0,0.3)", borderRadius: 7, padding: "7px 9px", border: `1px solid ${step.ok === false ? "rgba(248,113,113,0.2)" : "rgba(255,255,255,0.05)"}` }, children: [
4412
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 4 }, children: [
4413
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { style: { fontSize: 11, fontWeight: 700, color: step.ok === false ? "#f87171" : "#4ade80" }, children: step.ok === false ? "\u2717" : "\u2713" }),
4414
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { style: { fontSize: 11, fontWeight: 600, color: "rgba(255,255,255,0.7)", flex: 1 }, children: step.label }),
4415
- step.durationMs !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { style: { fontSize: 10, color: "rgba(255,255,255,0.3)" }, children: [
4545
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: 6, background: "rgba(0,0,0,0.3)", borderRadius: 7, padding: "7px 9px", border: `1px solid ${step.ok === false ? "rgba(248,113,113,0.2)" : "rgba(255,255,255,0.05)"}` }, children: [
4546
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 4 }, children: [
4547
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { fontSize: 11, fontWeight: 700, color: step.ok === false ? "#f87171" : "#4ade80" }, children: step.ok === false ? "\u2717" : "\u2713" }),
4548
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { fontSize: 11, fontWeight: 600, color: "rgba(255,255,255,0.7)", flex: 1 }, children: step.label }),
4549
+ step.durationMs !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { style: { fontSize: 10, color: "rgba(255,255,255,0.3)" }, children: [
4416
4550
  step.durationMs,
4417
4551
  "ms"
4418
4552
  ] }),
4419
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CopyBtn, { text: JSON.stringify(step, null, 2) })
4553
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CopyBtn, { text: JSON.stringify(step, null, 2) })
4420
4554
  ] }),
4421
- !isSpecial && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: 5 }, children: [
4422
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { fontSize: 10, color: "rgba(255,255,255,0.25)", marginBottom: 2 }, children: [
4555
+ !isSpecial && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: 5 }, children: [
4556
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { fontSize: 10, color: "rgba(255,255,255,0.25)", marginBottom: 2 }, children: [
4423
4557
  "\u2192 ",
4424
4558
  step.method,
4425
4559
  " ",
4426
4560
  step.url
4427
4561
  ] }),
4428
- Object.keys(step.reqHeaders).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { style: { fontSize: 9, color: "rgba(255,255,255,0.35)", margin: "2px 0", padding: "3px 5px", background: "rgba(255,255,255,0.03)", borderRadius: 3, whiteSpace: "pre-wrap", wordBreak: "break-all", maxHeight: 60, overflow: "auto" }, children: Object.entries(step.reqHeaders).map(([k, v]) => `${k}: ${v}`).join("\n") }),
4429
- step.reqBody && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { style: { fontSize: 9, color: "rgba(255,255,255,0.35)", margin: "2px 0", padding: "3px 5px", background: "rgba(255,255,255,0.03)", borderRadius: 3, whiteSpace: "pre-wrap", wordBreak: "break-all", maxHeight: 80, overflow: "auto" }, children: step.reqBody })
4562
+ Object.keys(step.reqHeaders).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("pre", { style: { fontSize: 9, color: "rgba(255,255,255,0.35)", margin: "2px 0", padding: "3px 5px", background: "rgba(255,255,255,0.03)", borderRadius: 3, whiteSpace: "pre-wrap", wordBreak: "break-all", maxHeight: 60, overflow: "auto" }, children: Object.entries(step.reqHeaders).map(([k, v]) => `${k}: ${v}`).join("\n") }),
4563
+ step.reqBody && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("pre", { style: { fontSize: 9, color: "rgba(255,255,255,0.35)", margin: "2px 0", padding: "3px 5px", background: "rgba(255,255,255,0.03)", borderRadius: 3, whiteSpace: "pre-wrap", wordBreak: "break-all", maxHeight: 80, overflow: "auto" }, children: step.reqBody })
4430
4564
  ] }),
4431
- step.error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { style: { fontSize: 11, color: "#f87171", margin: 0, padding: "3px 5px", background: "rgba(248,113,113,0.05)", borderRadius: 3, whiteSpace: "pre-wrap", wordBreak: "break-all" }, children: step.error }),
4432
- !step.error && (step.resStatus !== void 0 || step.resBody) && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
4433
- step.resStatus !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { fontSize: 11, fontWeight: 700, color: (step.resStatus || 0) < 300 ? "#4ade80" : "#f87171", marginBottom: 3 }, children: [
4565
+ step.error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("pre", { style: { fontSize: 11, color: "#f87171", margin: 0, padding: "3px 5px", background: "rgba(248,113,113,0.05)", borderRadius: 3, whiteSpace: "pre-wrap", wordBreak: "break-all" }, children: step.error }),
4566
+ !step.error && (step.resStatus !== void 0 || step.resBody) && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
4567
+ step.resStatus !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { fontSize: 11, fontWeight: 700, color: (step.resStatus || 0) < 300 ? "#4ade80" : "#f87171", marginBottom: 3 }, children: [
4434
4568
  "\u2190 ",
4435
4569
  step.resStatus,
4436
4570
  " ",
4437
4571
  step.resStatusText
4438
4572
  ] }),
4439
- step.resBody && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { style: { fontSize: 9, color: "rgba(255,255,255,0.55)", margin: 0, padding: "3px 5px", background: "rgba(255,255,255,0.03)", borderRadius: 3, whiteSpace: "pre-wrap", wordBreak: "break-all", maxHeight: 180, overflow: "auto" }, children: tryFmt(step.resBody) })
4573
+ step.resBody && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("pre", { style: { fontSize: 9, color: "rgba(255,255,255,0.55)", margin: 0, padding: "3px 5px", background: "rgba(255,255,255,0.03)", borderRadius: 3, whiteSpace: "pre-wrap", wordBreak: "break-all", maxHeight: 180, overflow: "auto" }, children: tryFmt(step.resBody) })
4440
4574
  ] })
4441
4575
  ] });
4442
4576
  }
@@ -4452,15 +4586,15 @@ function TestCard({
4452
4586
  onToggle
4453
4587
  }) {
4454
4588
  const hasResult = state && state.status !== "idle";
4455
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: 8, background: "rgba(255,255,255,0.03)", borderRadius: 10, border: `1px solid ${state?.status === "ok" ? "rgba(74,222,128,0.15)" : state?.status === "error" ? "rgba(248,113,113,0.15)" : "rgba(255,255,255,0.07)"}`, overflow: "hidden" }, children: [
4456
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, padding: "9px 10px" }, children: [
4457
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18, color: state?.status === "ok" ? "#4ade80" : state?.status === "error" ? "#f87171" : state?.status === "running" ? "#60a5fa" : "rgba(255,255,255,0.35)", flexShrink: 0 }, children: state?.status === "ok" ? "check_circle" : state?.status === "error" ? "error" : state?.status === "running" ? "hourglass_top" : icon }),
4458
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
4459
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { fontSize: 13, fontWeight: 700, color: "#fff" }, children: label }),
4460
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { fontSize: 10, color: "rgba(255,255,255,0.3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: desc })
4589
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: 8, background: "rgba(255,255,255,0.03)", borderRadius: 10, border: `1px solid ${state?.status === "ok" ? "rgba(74,222,128,0.15)" : state?.status === "error" ? "rgba(248,113,113,0.15)" : "rgba(255,255,255,0.07)"}`, overflow: "hidden" }, children: [
4590
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, padding: "9px 10px" }, children: [
4591
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18, color: state?.status === "ok" ? "#4ade80" : state?.status === "error" ? "#f87171" : state?.status === "running" ? "#60a5fa" : "rgba(255,255,255,0.35)", flexShrink: 0 }, children: state?.status === "ok" ? "check_circle" : state?.status === "error" ? "error" : state?.status === "running" ? "hourglass_top" : icon }),
4592
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
4593
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { fontSize: 13, fontWeight: 700, color: "#fff" }, children: label }),
4594
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { fontSize: 10, color: "rgba(255,255,255,0.3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: desc })
4461
4595
  ] }),
4462
- hasResult && state?.status !== "running" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: onToggle, style: { background: "none", border: "none", color: "rgba(255,255,255,0.3)", cursor: "pointer", padding: 2, lineHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: expanded ? "expand_less" : "expand_more" }) }),
4463
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4596
+ hasResult && state?.status !== "running" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { onClick: onToggle, style: { background: "none", border: "none", color: "rgba(255,255,255,0.3)", cursor: "pointer", padding: 2, lineHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: expanded ? "expand_less" : "expand_more" }) }),
4597
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4464
4598
  "button",
4465
4599
  {
4466
4600
  onClick: onRun,
@@ -4470,20 +4604,20 @@ function TestCard({
4470
4604
  }
4471
4605
  )
4472
4606
  ] }),
4473
- hasResult && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { borderTop: "1px solid rgba(255,255,255,0.05)" }, children: [
4474
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { padding: "4px 10px 5px", display: "flex", alignItems: "center", gap: 8 }, children: [
4475
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { style: { fontSize: 11, fontWeight: 700, color: state.status === "ok" ? "#4ade80" : "#f87171" }, children: state.status === "ok" ? "\u2713 OK" : state.status === "running" ? "\u2026" : "\u2717 Fehler" }),
4476
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { style: { fontSize: 10, color: "rgba(255,255,255,0.3)" }, children: [
4607
+ hasResult && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { borderTop: "1px solid rgba(255,255,255,0.05)" }, children: [
4608
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { padding: "4px 10px 5px", display: "flex", alignItems: "center", gap: 8 }, children: [
4609
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { fontSize: 11, fontWeight: 700, color: state.status === "ok" ? "#4ade80" : "#f87171" }, children: state.status === "ok" ? "\u2713 OK" : state.status === "running" ? "\u2026" : "\u2717 Fehler" }),
4610
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { style: { fontSize: 10, color: "rgba(255,255,255,0.3)" }, children: [
4477
4611
  state.totalMs,
4478
4612
  "ms \xB7 ",
4479
4613
  state.steps.length,
4480
4614
  " Step",
4481
4615
  state.steps.length !== 1 ? "s" : ""
4482
4616
  ] }),
4483
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { flex: 1 } }),
4484
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CopyBtn, { text: JSON.stringify(state, null, 2) })
4617
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { flex: 1 } }),
4618
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CopyBtn, { text: JSON.stringify(state, null, 2) })
4485
4619
  ] }),
4486
- expanded && state.steps.map((step, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { padding: "0 10px 4px" }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StepView, { step }) }, i))
4620
+ expanded && state.steps.map((step, i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { padding: "0 10px 4px" }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StepView, { step }) }, i))
4487
4621
  ] })
4488
4622
  ] });
4489
4623
  }
@@ -4495,10 +4629,10 @@ var EVENT_TYPE_COLORS = {
4495
4629
  };
4496
4630
  function EventMonitor({ events, confirmedEventKeys, galleryItems, imageUploadStatus }) {
4497
4631
  if (!events.length) {
4498
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { padding: "12px 14px", fontSize: 12, color: "rgba(255,255,255,0.3)", fontStyle: "italic" }, children: "Noch keine Events geladen." });
4632
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { padding: "12px 14px", fontSize: 12, color: "rgba(255,255,255,0.3)", fontStyle: "italic" }, children: "Noch keine Events geladen." });
4499
4633
  }
4500
4634
  const sorted = [...events].sort((a, b) => b.ts - a.ts).slice(0, 30);
4501
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { padding: "6px 8px 4px" }, children: [
4635
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { padding: "6px 8px 4px" }, children: [
4502
4636
  sorted.map((e, i) => {
4503
4637
  const eKey = `${e.ts}_${e.clientId}`;
4504
4638
  const isConfirmed = confirmedEventKeys.has(eKey);
@@ -4511,47 +4645,47 @@ function EventMonitor({ events, confirmedEventKeys, galleryItems, imageUploadSta
4511
4645
  const uploadStatus = imgId ? imageUploadStatus.get(imgId) : void 0;
4512
4646
  const payloadStr = JSON.stringify(e.payload ?? {});
4513
4647
  const payloadPreview = payloadStr.length > 70 ? payloadStr.slice(0, 70) + "\u2026" : payloadStr;
4514
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", gap: 7, alignItems: "flex-start", padding: "6px 2px", borderBottom: "1px solid rgba(255,255,255,0.05)" }, children: [
4515
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { width: 36, height: 36, flexShrink: 0, borderRadius: 4, overflow: "hidden", background: "rgba(255,255,255,0.05)", display: "flex", alignItems: "center", justifyContent: "center" }, children: isImageEvent ? galleryItem?.base64 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("img", { src: galleryItem.base64, style: { width: "100%", height: "100%", objectFit: "cover" } }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18, color: "rgba(255,255,255,0.2)" }, children: "image" }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16, color: "rgba(255,255,255,0.15)" }, children: e.type === "tag_upserted" ? "label" : e.type === "metadata_updated" ? "edit_note" : "data_object" }) }),
4516
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
4517
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 3 }, children: [
4518
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { style: { fontSize: 11, fontWeight: 700, color: typeColor }, children: e.type }),
4519
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { style: { fontSize: 9, color: "rgba(255,255,255,0.25)", fontVariantNumeric: "tabular-nums" }, children: timeStr }),
4520
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { flex: 1 } }),
4521
- isConfirmed ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { style: { fontSize: 9, fontWeight: 700, color: "#4ade80", display: "flex", alignItems: "center", gap: 2 }, children: [
4522
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "check_circle" }),
4648
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", gap: 7, alignItems: "flex-start", padding: "6px 2px", borderBottom: "1px solid rgba(255,255,255,0.05)" }, children: [
4649
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { width: 36, height: 36, flexShrink: 0, borderRadius: 4, overflow: "hidden", background: "rgba(255,255,255,0.05)", display: "flex", alignItems: "center", justifyContent: "center" }, children: isImageEvent ? galleryItem?.base64 ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("img", { src: galleryItem.base64, style: { width: "100%", height: "100%", objectFit: "cover" } }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18, color: "rgba(255,255,255,0.2)" }, children: "image" }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16, color: "rgba(255,255,255,0.15)" }, children: e.type === "tag_upserted" ? "label" : e.type === "metadata_updated" ? "edit_note" : "data_object" }) }),
4650
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
4651
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 3 }, children: [
4652
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { fontSize: 11, fontWeight: 700, color: typeColor }, children: e.type }),
4653
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { fontSize: 9, color: "rgba(255,255,255,0.25)", fontVariantNumeric: "tabular-nums" }, children: timeStr }),
4654
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { flex: 1 } }),
4655
+ isConfirmed ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { style: { fontSize: 9, fontWeight: 700, color: "#4ade80", display: "flex", alignItems: "center", gap: 2 }, children: [
4656
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "check_circle" }),
4523
4657
  "HF"
4524
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { style: { fontSize: 9, fontWeight: 700, color: "#fbbf24", display: "flex", alignItems: "center", gap: 2 }, children: [
4525
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "schedule" }),
4658
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { style: { fontSize: 9, fontWeight: 700, color: "#fbbf24", display: "flex", alignItems: "center", gap: 2 }, children: [
4659
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "schedule" }),
4526
4660
  "lokal"
4527
4661
  ] })
4528
4662
  ] }),
4529
- isImageEvent && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 3, flexWrap: "wrap" }, children: [
4530
- uploadStatus === "done" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { style: { fontSize: 9, color: "#4ade80", display: "flex", alignItems: "center", gap: 2 }, children: [
4531
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "cloud_done" }),
4663
+ isImageEvent && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 3, flexWrap: "wrap" }, children: [
4664
+ uploadStatus === "done" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { style: { fontSize: 9, color: "#4ade80", display: "flex", alignItems: "center", gap: 2 }, children: [
4665
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "cloud_done" }),
4532
4666
  "Upload \u2713"
4533
4667
  ] }),
4534
- uploadStatus === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { style: { fontSize: 9, color: "#60a5fa", display: "flex", alignItems: "center", gap: 2 }, children: [
4535
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "cloud_upload" }),
4668
+ uploadStatus === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { style: { fontSize: 9, color: "#60a5fa", display: "flex", alignItems: "center", gap: 2 }, children: [
4669
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "cloud_upload" }),
4536
4670
  "l\xE4dt hoch\u2026"
4537
4671
  ] }),
4538
- uploadStatus === "failed" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { style: { fontSize: 9, color: "#f87171", display: "flex", alignItems: "center", gap: 2 }, children: [
4539
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "cloud_off" }),
4672
+ uploadStatus === "failed" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { style: { fontSize: 9, color: "#f87171", display: "flex", alignItems: "center", gap: 2 }, children: [
4673
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "cloud_off" }),
4540
4674
  "Upload fehlgeschlagen"
4541
4675
  ] }),
4542
- galleryItem?.base64 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { style: { fontSize: 9, color: "#4ade80", display: "flex", alignItems: "center", gap: 2 }, children: [
4543
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "photo" }),
4676
+ galleryItem?.base64 ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { style: { fontSize: 9, color: "#4ade80", display: "flex", alignItems: "center", gap: 2 }, children: [
4677
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "photo" }),
4544
4678
  uploadStatus ? "lokal" : "von HF geladen"
4545
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { style: { fontSize: 9, color: "#f87171", display: "flex", alignItems: "center", gap: 2 }, children: [
4546
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "broken_image" }),
4679
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { style: { fontSize: 9, color: "#f87171", display: "flex", alignItems: "center", gap: 2 }, children: [
4680
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "broken_image" }),
4547
4681
  uploadStatus === "failed" ? "Binary nicht auf HF" : "wird geladen\u2026"
4548
4682
  ] })
4549
4683
  ] }),
4550
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { fontSize: 9, color: "rgba(255,255,255,0.25)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: payloadPreview })
4684
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { fontSize: 9, color: "rgba(255,255,255,0.25)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: payloadPreview })
4551
4685
  ] })
4552
4686
  ] }, `${eKey}_${i}`);
4553
4687
  }),
4554
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { padding: "6px 0 2px", fontSize: 9, color: "rgba(255,255,255,0.2)", textAlign: "right" }, children: [
4688
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { padding: "6px 0 2px", fontSize: 9, color: "rgba(255,255,255,0.2)", textAlign: "right" }, children: [
4555
4689
  events.length,
4556
4690
  " Events gesamt \xB7 ",
4557
4691
  [...confirmedEventKeys].length,
@@ -4560,9 +4694,9 @@ function EventMonitor({ events, confirmedEventKeys, galleryItems, imageUploadSta
4560
4694
  ] });
4561
4695
  }
4562
4696
  function HFTestTab({ token, namespace, galleryItems, allEvents = [], confirmedEventKeys = /* @__PURE__ */ new Set(), imageUploadStatus = /* @__PURE__ */ new Map(), missingImages = [] }) {
4563
- const [selected, setSelected] = (0, import_react25.useState)(null);
4564
- const [results, setResults] = (0, import_react25.useState)({});
4565
- const [expanded, setExpanded] = (0, import_react25.useState)({});
4697
+ const [selected, setSelected] = (0, import_react24.useState)(null);
4698
+ const [results, setResults] = (0, import_react24.useState)({});
4699
+ const [expanded, setExpanded] = (0, import_react24.useState)({});
4566
4700
  const withResults = galleryItems.filter((g) => g.base64 && g.status === "done");
4567
4701
  const setRunning = (id) => setResults((r) => ({ ...r, [id]: { status: "running", steps: [], totalMs: 0 } }));
4568
4702
  const setDone = (id, steps, t0) => {
@@ -4610,15 +4744,15 @@ function HFTestTab({ token, namespace, galleryItems, allEvents = [], confirmedEv
4610
4744
  { id: "img-hub", label: "Upload hub lib", icon: "package_2", desc: "uploadFile() via @huggingface/hub" },
4611
4745
  { id: "img-cdn", label: "Upload CDN lib", icon: "language", desc: "uploadFile() via esm.sh hub lib" }
4612
4746
  ];
4613
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", flexDirection: "column", height: "100%", overflowY: "auto", padding: "12px 10px 80px", boxSizing: "border-box", fontFamily: "inherit" }, children: [
4614
- noToken && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { marginBottom: 10, padding: "8px 12px", background: "rgba(248,113,113,0.08)", borderRadius: 8, border: "1px solid rgba(248,113,113,0.2)", fontSize: 12, color: "#f87171" }, children: "Kein HF-Token geladen \u2014 bitte zuerst Token im Sync-Tab eingeben." }),
4615
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { marginBottom: 12 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4747
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", flexDirection: "column", height: "100%", overflowY: "auto", padding: "12px 10px 80px", boxSizing: "border-box", fontFamily: "inherit" }, children: [
4748
+ noToken && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { marginBottom: 10, padding: "8px 12px", background: "rgba(248,113,113,0.08)", borderRadius: 8, border: "1px solid rgba(248,113,113,0.2)", fontSize: 12, color: "#f87171" }, children: "Kein HF-Token geladen \u2014 bitte zuerst Token im Sync-Tab eingeben." }),
4749
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { marginBottom: 12 }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4616
4750
  CollapsibleCard,
4617
4751
  {
4618
4752
  title: "Event Monitor",
4619
- icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "bolt" }),
4753
+ icon: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "bolt" }),
4620
4754
  defaultOpen: true,
4621
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4755
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4622
4756
  EventMonitor,
4623
4757
  {
4624
4758
  events: allEvents,
@@ -4629,52 +4763,52 @@ function HFTestTab({ token, namespace, galleryItems, allEvents = [], confirmedEv
4629
4763
  )
4630
4764
  }
4631
4765
  ) }),
4632
- missingImages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { marginBottom: 12 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4766
+ missingImages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { marginBottom: 12 }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4633
4767
  CollapsibleCard,
4634
4768
  {
4635
4769
  title: `Fehlende Bilder auf HF (${missingImages.length})`,
4636
- icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "broken_image" }),
4770
+ icon: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "broken_image" }),
4637
4771
  defaultOpen: false,
4638
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { padding: "8px 10px 4px" }, children: [
4639
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { fontSize: 11, color: "rgba(255,255,255,0.4)", marginBottom: 8 }, children: "Metadata-Eintr\xE4ge ohne Bild auf HuggingFace \u2014 Orphaned entries." }),
4640
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", gap: 8, marginBottom: 8, fontSize: 11, color: "rgba(255,255,255,0.5)" }, children: [
4641
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { children: [
4772
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { padding: "8px 10px 4px" }, children: [
4773
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { fontSize: 11, color: "rgba(255,255,255,0.4)", marginBottom: 8 }, children: "Metadata-Eintr\xE4ge ohne Bild auf HuggingFace \u2014 Orphaned entries." }),
4774
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", gap: 8, marginBottom: 8, fontSize: 11, color: "rgba(255,255,255,0.5)" }, children: [
4775
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { children: [
4642
4776
  "UUID (Flow-App): ",
4643
4777
  missingImages.filter((e) => !e.filename).length
4644
4778
  ] }),
4645
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "\xB7" }),
4646
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { children: [
4779
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: "\xB7" }),
4780
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { children: [
4647
4781
  "Filename (Server-Upload): ",
4648
4782
  missingImages.filter((e) => !!e.filename).length
4649
4783
  ] })
4650
4784
  ] }),
4651
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { maxHeight: 300, overflowY: "auto", fontFamily: "monospace", fontSize: 10 }, children: missingImages.map((e) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { padding: "3px 0", borderBottom: "1px solid rgba(255,255,255,0.04)", color: "rgba(255,255,255,0.5)", display: "flex", gap: 8 }, children: [
4652
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { style: { color: e.filename ? "#fb923c" : "#60a5fa", minWidth: 60 }, children: e.filename ? "filename" : "uuid" }),
4653
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { style: { flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: e.filename ?? e.id }),
4654
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { style: { color: "rgba(255,255,255,0.3)" }, children: new Date(e.timestamp).toLocaleDateString("de") })
4785
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { maxHeight: 300, overflowY: "auto", fontFamily: "monospace", fontSize: 10 }, children: missingImages.map((e) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { padding: "3px 0", borderBottom: "1px solid rgba(255,255,255,0.04)", color: "rgba(255,255,255,0.5)", display: "flex", gap: 8 }, children: [
4786
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { color: e.filename ? "#fb923c" : "#60a5fa", minWidth: 60 }, children: e.filename ? "filename" : "uuid" }),
4787
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: e.filename ?? e.id }),
4788
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { color: "rgba(255,255,255,0.3)" }, children: new Date(e.timestamp).toLocaleDateString("de") })
4655
4789
  ] }, e.id)) })
4656
4790
  ] })
4657
4791
  }
4658
4792
  ) }),
4659
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4793
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4660
4794
  CollapsibleCard,
4661
4795
  {
4662
4796
  title: "Upload Tests",
4663
- icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "science" }),
4797
+ icon: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "science" }),
4664
4798
  defaultOpen: false,
4665
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { padding: "10px 10px 4px" }, children: [
4666
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: 14 }, children: [
4667
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { fontSize: 10, fontWeight: 700, color: "rgba(255,255,255,0.3)", textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 8 }, children: [
4799
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { padding: "10px 10px 4px" }, children: [
4800
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: 14 }, children: [
4801
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { fontSize: 10, fontWeight: 700, color: "rgba(255,255,255,0.3)", textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 8 }, children: [
4668
4802
  "Bild ausw\xE4hlen (",
4669
4803
  withResults.length,
4670
4804
  " verf\xFCgbar)"
4671
4805
  ] }),
4672
- withResults.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { fontSize: 12, color: "rgba(255,255,255,0.3)", fontStyle: "italic" }, children: "Noch keine Bilder in der Galerie. Generiere zuerst ein Bild oder lade von HF." }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 6 }, children: withResults.slice(0, 12).map((g) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4806
+ withResults.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { fontSize: 12, color: "rgba(255,255,255,0.3)", fontStyle: "italic" }, children: "Noch keine Bilder in der Galerie. Generiere zuerst ein Bild oder lade von HF." }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 6 }, children: withResults.slice(0, 12).map((g) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4673
4807
  "button",
4674
4808
  {
4675
4809
  onClick: () => setSelected(g),
4676
4810
  style: { padding: 0, border: `2px solid ${selected?.id === g.id ? "#0284c7" : "transparent"}`, borderRadius: 6, cursor: "pointer", overflow: "hidden", background: "none", lineHeight: 0 },
4677
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4811
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4678
4812
  "img",
4679
4813
  {
4680
4814
  src: g.base64,
@@ -4685,38 +4819,38 @@ function HFTestTab({ token, namespace, galleryItems, allEvents = [], confirmedEv
4685
4819
  },
4686
4820
  g.id
4687
4821
  )) }),
4688
- selected && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginTop: 10, display: "flex", gap: 10, alignItems: "flex-start" }, children: [
4689
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4822
+ selected && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginTop: 10, display: "flex", gap: 10, alignItems: "flex-start" }, children: [
4823
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4690
4824
  "img",
4691
4825
  {
4692
4826
  src: selected.base64,
4693
4827
  style: { width: 80, height: 80, objectFit: "cover", borderRadius: 8, border: "1px solid rgba(255,255,255,0.1)", flexShrink: 0 }
4694
4828
  }
4695
4829
  ),
4696
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
4697
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { fontSize: 11, fontWeight: 700, color: "rgba(255,255,255,0.7)", marginBottom: 2 }, children: "Ausgew\xE4hlt" }),
4698
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { fontSize: 10, color: "rgba(255,255,255,0.3)", wordBreak: "break-all" }, children: [
4830
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
4831
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { fontSize: 11, fontWeight: 700, color: "rgba(255,255,255,0.7)", marginBottom: 2 }, children: "Ausgew\xE4hlt" }),
4832
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { fontSize: 10, color: "rgba(255,255,255,0.3)", wordBreak: "break-all" }, children: [
4699
4833
  "ID: ",
4700
4834
  selected.id
4701
4835
  ] }),
4702
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { fontSize: 10, color: "rgba(255,255,255,0.3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", marginTop: 2 }, children: [
4836
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { fontSize: 10, color: "rgba(255,255,255,0.3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", marginTop: 2 }, children: [
4703
4837
  "Ziel: test/",
4704
4838
  selected.id,
4705
4839
  ".jpg"
4706
4840
  ] }),
4707
- selected.prompt && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { fontSize: 10, color: "rgba(255,255,255,0.25)", marginTop: 2, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: selected.prompt })
4841
+ selected.prompt && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { fontSize: 10, color: "rgba(255,255,255,0.25)", marginTop: 2, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: selected.prompt })
4708
4842
  ] })
4709
4843
  ] })
4710
4844
  ] }),
4711
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: 14 }, children: [
4712
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { fontSize: 10, fontWeight: 700, color: "rgba(255,255,255,0.3)", textTransform: "uppercase", letterSpacing: "0.1em", marginBottom: 8, borderBottom: "1px solid rgba(255,255,255,0.06)", paddingBottom: 4 }, children: [
4845
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: 14 }, children: [
4846
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { fontSize: 10, fontWeight: 700, color: "rgba(255,255,255,0.3)", textTransform: "uppercase", letterSpacing: "0.1em", marginBottom: 8, borderBottom: "1px solid rgba(255,255,255,0.06)", paddingBottom: 4 }, children: [
4713
4847
  "Bild hochladen \u2192 test/",
4714
4848
  "{",
4715
4849
  "id",
4716
4850
  "}",
4717
4851
  ".jpg"
4718
4852
  ] }),
4719
- imgTests.map((t) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4853
+ imgTests.map((t) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4720
4854
  TestCard,
4721
4855
  {
4722
4856
  id: t.id,
@@ -4732,13 +4866,13 @@ function HFTestTab({ token, namespace, galleryItems, allEvents = [], confirmedEv
4732
4866
  t.id
4733
4867
  ))
4734
4868
  ] }),
4735
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { marginBottom: 4 }, children: [
4736
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { fontSize: 10, fontWeight: 700, color: "rgba(255,255,255,0.3)", textTransform: "uppercase", letterSpacing: "0.1em", marginBottom: 8, borderBottom: "1px solid rgba(255,255,255,0.06)", paddingBottom: 4 }, children: [
4869
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { marginBottom: 4 }, children: [
4870
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { fontSize: 10, fontWeight: 700, color: "rgba(255,255,255,0.3)", textTransform: "uppercase", letterSpacing: "0.1em", marginBottom: 8, borderBottom: "1px solid rgba(255,255,255,0.06)", paddingBottom: 4 }, children: [
4737
4871
  "Event schreiben \u2192 ",
4738
4872
  namespace || "(kein namespace)",
4739
4873
  "test/events/"
4740
4874
  ] }),
4741
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4875
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4742
4876
  TestCard,
4743
4877
  {
4744
4878
  id: "event",
@@ -4760,10 +4894,10 @@ function HFTestTab({ token, namespace, galleryItems, allEvents = [], confirmedEv
4760
4894
  }
4761
4895
 
4762
4896
  // src/components/ServerTab.tsx
4763
- var import_react26 = require("react");
4764
- var import_jsx_runtime22 = require("react/jsx-runtime");
4897
+ var import_react25 = require("react");
4898
+ var import_jsx_runtime23 = require("react/jsx-runtime");
4765
4899
  function StarRating({ rating = 0 }) {
4766
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex gap-[2px]", children: [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: `material-symbols-outlined text-[12px] ${i <= rating ? "text-yellow-400" : "text-white/15"}`, children: "star" }, i)) });
4900
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex gap-[2px]", children: [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: `material-symbols-outlined text-[12px] ${i <= rating ? "text-yellow-400" : "text-white/15"}`, children: "star" }, i)) });
4767
4901
  }
4768
4902
  async function serverGet(baseUrl, path) {
4769
4903
  const url = `${baseUrl.replace(/\/$/, "")}${path}`;
@@ -4773,21 +4907,21 @@ async function serverGet(baseUrl, path) {
4773
4907
  return json && typeof json === "object" && "data" in json ? json.data : json;
4774
4908
  }
4775
4909
  function ServerTab({ serverBaseUrl }) {
4776
- const [step, setStep] = (0, import_react26.useState)("user");
4777
- const [users, setUsers] = (0, import_react26.useState)([]);
4778
- const [usersLoading, setUsersLoading] = (0, import_react26.useState)(false);
4779
- const [usersError, setUsersError] = (0, import_react26.useState)(null);
4780
- const [selectedUser, setSelectedUser] = (0, import_react26.useState)(null);
4781
- const [contexts, setContexts] = (0, import_react26.useState)([]);
4782
- const [contextsLoading, setContextsLoading] = (0, import_react26.useState)(false);
4783
- const [selectedContext, setSelectedContext] = (0, import_react26.useState)(null);
4784
- const [tags, setTags] = (0, import_react26.useState)([]);
4785
- const [items, setItems] = (0, import_react26.useState)([]);
4786
- const [libLoading, setLibLoading] = (0, import_react26.useState)(false);
4787
- const [libError, setLibError] = (0, import_react26.useState)(null);
4788
- const [activeTag, setActiveTag] = (0, import_react26.useState)(null);
4789
- const [preview, setPreview] = (0, import_react26.useState)(null);
4790
- (0, import_react26.useEffect)(() => {
4910
+ const [step, setStep] = (0, import_react25.useState)("user");
4911
+ const [users, setUsers] = (0, import_react25.useState)([]);
4912
+ const [usersLoading, setUsersLoading] = (0, import_react25.useState)(false);
4913
+ const [usersError, setUsersError] = (0, import_react25.useState)(null);
4914
+ const [selectedUser, setSelectedUser] = (0, import_react25.useState)(null);
4915
+ const [contexts, setContexts] = (0, import_react25.useState)([]);
4916
+ const [contextsLoading, setContextsLoading] = (0, import_react25.useState)(false);
4917
+ const [selectedContext, setSelectedContext] = (0, import_react25.useState)(null);
4918
+ const [tags, setTags] = (0, import_react25.useState)([]);
4919
+ const [items, setItems] = (0, import_react25.useState)([]);
4920
+ const [libLoading, setLibLoading] = (0, import_react25.useState)(false);
4921
+ const [libError, setLibError] = (0, import_react25.useState)(null);
4922
+ const [activeTag, setActiveTag] = (0, import_react25.useState)(null);
4923
+ const [preview, setPreview] = (0, import_react25.useState)(null);
4924
+ (0, import_react25.useEffect)(() => {
4791
4925
  if (!serverBaseUrl) return;
4792
4926
  setUsersLoading(true);
4793
4927
  setUsersError(null);
@@ -4841,54 +4975,54 @@ function ServerTab({ serverBaseUrl }) {
4841
4975
  };
4842
4976
  const filteredItems = activeTag ? items.filter((item) => item.tags?.some((t) => t.l === activeTag)) : items;
4843
4977
  if (!serverBaseUrl) return null;
4844
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-col h-full min-h-0", children: [
4845
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-white/8", children: [
4846
- step !== "user" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { onClick: reset, className: "text-white/40 hover:text-white transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined text-[18px]", children: "arrow_back" }) }),
4847
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: "text-[11px] font-medium text-white/40 tracking-wide flex-1", children: [
4978
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col h-full min-h-0", children: [
4979
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-white/8", children: [
4980
+ step !== "user" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: reset, className: "text-white/40 hover:text-white transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[18px]", children: "arrow_back" }) }),
4981
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { className: "text-[11px] font-medium text-white/40 tracking-wide flex-1", children: [
4848
4982
  step === "user" && "Server Browser",
4849
4983
  step === "context" && `${selectedUser?.username} \u2014 Kontext w\xE4hlen`,
4850
4984
  step === "library" && `${selectedUser?.username} / ${selectedContext?.label || selectedContext?.name || selectedContext?.id}`
4851
4985
  ] })
4852
4986
  ] }),
4853
- step === "user" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-col flex-1 min-h-0 overflow-y-auto p-3 gap-2", children: [
4854
- usersLoading && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-white/30 text-[11px] text-center py-4", children: "Lade User\u2026" }),
4855
- usersError && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-red-400 text-[11px] text-center py-4", children: usersError }),
4856
- !usersLoading && users.map((u) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
4987
+ step === "user" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col flex-1 min-h-0 overflow-y-auto p-3 gap-2", children: [
4988
+ usersLoading && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-white/30 text-[11px] text-center py-4", children: "Lade User\u2026" }),
4989
+ usersError && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-red-400 text-[11px] text-center py-4", children: usersError }),
4990
+ !usersLoading && users.map((u) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
4857
4991
  "button",
4858
4992
  {
4859
4993
  onClick: () => selectUser(u),
4860
4994
  className: "flex items-center gap-3 px-3 py-2.5 rounded-xl border border-white/8 hover:border-white/20 hover:bg-white/5 transition-all text-left",
4861
4995
  children: [
4862
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined text-[20px] text-white/40", children: "person" }),
4863
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-col flex-1 min-w-0", children: [
4864
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-[12px] font-medium text-white", children: u.username }),
4865
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-[10px] text-white/30", children: u.id })
4996
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px] text-white/40", children: "person" }),
4997
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col flex-1 min-w-0", children: [
4998
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[12px] font-medium text-white", children: u.username }),
4999
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[10px] text-white/30", children: u.id })
4866
5000
  ] }),
4867
- contextsLoading && selectedUser?.id === u.id ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined text-[16px] text-white/30 animate-spin", children: "progress_activity" }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined text-[16px] text-white/20", children: "chevron_right" })
5001
+ contextsLoading && selectedUser?.id === u.id ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[16px] text-white/30 animate-spin", children: "progress_activity" }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[16px] text-white/20", children: "chevron_right" })
4868
5002
  ]
4869
5003
  },
4870
5004
  u.id
4871
5005
  ))
4872
5006
  ] }),
4873
- step === "context" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex flex-col flex-1 min-h-0 overflow-y-auto p-3 gap-2", children: contexts.map((ctx) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
5007
+ step === "context" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex flex-col flex-1 min-h-0 overflow-y-auto p-3 gap-2", children: contexts.map((ctx) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
4874
5008
  "button",
4875
5009
  {
4876
5010
  onClick: () => loadLibrary(selectedUser, ctx),
4877
5011
  className: "flex items-center gap-3 px-3 py-2.5 rounded-xl border border-white/8 hover:border-white/20 hover:bg-white/5 transition-all text-left",
4878
5012
  children: [
4879
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined text-[20px] text-white/40", children: "folder" }),
4880
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-col flex-1 min-w-0", children: [
4881
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-[12px] font-medium text-white", children: ctx.label || ctx.name || ctx.id }),
4882
- ctx.description && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-[10px] text-white/30 truncate", children: ctx.description })
5013
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px] text-white/40", children: "folder" }),
5014
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col flex-1 min-w-0", children: [
5015
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[12px] font-medium text-white", children: ctx.label || ctx.name || ctx.id }),
5016
+ ctx.description && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[10px] text-white/30 truncate", children: ctx.description })
4883
5017
  ] }),
4884
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined text-[16px] text-white/20", children: "chevron_right" })
5018
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[16px] text-white/20", children: "chevron_right" })
4885
5019
  ]
4886
5020
  },
4887
5021
  ctx.id
4888
5022
  )) }),
4889
- step === "library" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-col flex-1 min-h-0", children: [
4890
- tags.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex gap-1.5 px-3 py-2 overflow-x-auto border-b border-white/8", style: { scrollbarWidth: "none" }, children: [
4891
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5023
+ step === "library" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col flex-1 min-h-0", children: [
5024
+ tags.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex gap-1.5 px-3 py-2 overflow-x-auto border-b border-white/8", style: { scrollbarWidth: "none" }, children: [
5025
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4892
5026
  "button",
4893
5027
  {
4894
5028
  onClick: () => setActiveTag(null),
@@ -4896,7 +5030,7 @@ function ServerTab({ serverBaseUrl }) {
4896
5030
  children: "Alle"
4897
5031
  }
4898
5032
  ),
4899
- tags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5033
+ tags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4900
5034
  "button",
4901
5035
  {
4902
5036
  onClick: () => setActiveTag(activeTag === t.label ? null : t.label),
@@ -4906,22 +5040,22 @@ function ServerTab({ serverBaseUrl }) {
4906
5040
  t.id
4907
5041
  ))
4908
5042
  ] }),
4909
- libLoading && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-white/30 text-[11px] text-center py-8", children: "Lade Library\u2026" }),
4910
- libError && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-red-400 text-[11px] text-center py-8", children: libError }),
4911
- !libLoading && !libError && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex-1 min-h-0 overflow-y-auto p-3 grid grid-cols-2 gap-2 content-start", children: [
4912
- filteredItems.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "col-span-2 text-white/30 text-[11px] text-center py-8", children: "Keine Eintr\xE4ge." }),
5043
+ libLoading && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-white/30 text-[11px] text-center py-8", children: "Lade Library\u2026" }),
5044
+ libError && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-red-400 text-[11px] text-center py-8", children: libError }),
5045
+ !libLoading && !libError && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex-1 min-h-0 overflow-y-auto p-3 grid grid-cols-2 gap-2 content-start", children: [
5046
+ filteredItems.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "col-span-2 text-white/30 text-[11px] text-center py-8", children: "Keine Eintr\xE4ge." }),
4913
5047
  filteredItems.map((item, i) => {
4914
5048
  const imgUrl = item.images?.[0]?.url;
4915
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
5049
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
4916
5050
  "button",
4917
5051
  {
4918
5052
  onClick: () => imgUrl && setPreview(imgUrl),
4919
5053
  className: "flex flex-col rounded-xl overflow-hidden border border-white/8 hover:border-white/25 transition-all bg-white/3 text-left",
4920
5054
  children: [
4921
- imgUrl ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("img", { src: imgUrl, alt: "", className: "w-full aspect-square object-cover bg-white/5" }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "w-full aspect-square bg-white/5 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined text-[24px] text-white/15", children: "image" }) }),
4922
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "p-1.5 flex flex-col gap-0.5", children: [
4923
- item.title && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-[10px] font-medium text-white/70 truncate", children: item.title }),
4924
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StarRating, { rating: item.rating })
5055
+ imgUrl ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src: imgUrl, alt: "", className: "w-full aspect-square object-cover bg-white/5" }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-full aspect-square bg-white/5 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[24px] text-white/15", children: "image" }) }),
5056
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "p-1.5 flex flex-col gap-0.5", children: [
5057
+ item.title && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[10px] font-medium text-white/70 truncate", children: item.title }),
5058
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(StarRating, { rating: item.rating })
4925
5059
  ] })
4926
5060
  ]
4927
5061
  },
@@ -4930,17 +5064,17 @@ function ServerTab({ serverBaseUrl }) {
4930
5064
  })
4931
5065
  ] })
4932
5066
  ] }),
4933
- preview && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "absolute inset-0 z-50 bg-black/90 flex items-center justify-center", onClick: () => setPreview(null), children: [
4934
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("img", { src: preview, alt: "", className: "max-w-full max-h-full object-contain" }),
4935
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { className: "absolute top-3 right-3 text-white/60 hover:text-white", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "material-symbols-outlined text-[24px]", children: "close" }) })
5067
+ preview && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "absolute inset-0 z-50 bg-black/90 flex items-center justify-center", onClick: () => setPreview(null), children: [
5068
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src: preview, alt: "", className: "max-w-full max-h-full object-contain" }),
5069
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { className: "absolute top-3 right-3 text-white/60 hover:text-white", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[24px]", children: "close" }) })
4936
5070
  ] })
4937
5071
  ] });
4938
5072
  }
4939
5073
 
4940
5074
  // src/components/AvatarArchitectApp.tsx
4941
- var import_jsx_runtime23 = require("react/jsx-runtime");
5075
+ var import_jsx_runtime24 = require("react/jsx-runtime");
4942
5076
  function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onSelectMedia, buildInfo, initialHfToken, hfNamespace, allowDevNamespace, serverBaseUrl, onFetchServerProjects, onServerSave, onServerLoad, onServerDelete }) {
4943
- (0, import_react27.useEffect)(() => {
5077
+ (0, import_react26.useEffect)(() => {
4944
5078
  const id = "flow-styles";
4945
5079
  if (!document.getElementById(id)) {
4946
5080
  const style = document.createElement("style");
@@ -4949,19 +5083,19 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4949
5083
  document.head.appendChild(style);
4950
5084
  }
4951
5085
  }, []);
4952
- const [showStart, setShowStart] = (0, import_react27.useState)(true);
4953
- const [layoutChoice, setLayoutChoice] = (0, import_react27.useState)(() => {
5086
+ const [showStart, setShowStart] = (0, import_react26.useState)(true);
5087
+ const [layoutChoice, setLayoutChoice] = (0, import_react26.useState)(() => {
4954
5088
  try {
4955
5089
  return localStorage.getItem("aa-layout") || null;
4956
5090
  } catch {
4957
5091
  return null;
4958
5092
  }
4959
5093
  });
4960
- const [projectLoaded, setProjectLoaded] = (0, import_react27.useState)(false);
4961
- const [hfToken, setHfToken] = (0, import_react27.useState)(initialHfToken || "");
4962
- const [hfTokenInput, setHfTokenInput] = (0, import_react27.useState)(initialHfToken || "");
4963
- const [isLoadingFromHF, setIsLoadingFromHF] = (0, import_react27.useState)(false);
4964
- const [hfNamespaceLocal, setHfNamespaceLocal] = (0, import_react27.useState)(() => {
5094
+ const [projectLoaded, setProjectLoaded] = (0, import_react26.useState)(false);
5095
+ const [hfToken, setHfToken] = (0, import_react26.useState)(initialHfToken || "");
5096
+ const [hfTokenInput, setHfTokenInput] = (0, import_react26.useState)(initialHfToken || "");
5097
+ const [isLoadingFromHF, setIsLoadingFromHF] = (0, import_react26.useState)(false);
5098
+ const [hfNamespaceLocal, setHfNamespaceLocal] = (0, import_react26.useState)(() => {
4965
5099
  const KNOWN = ["app.art-by-rolands.de/", "dev-app.art-by-rolands.de/"];
4966
5100
  const DEFAULT = "app.art-by-rolands.de/";
4967
5101
  try {
@@ -4973,8 +5107,8 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4973
5107
  return DEFAULT;
4974
5108
  }
4975
5109
  });
4976
- const [hfNamespaceFromServer, setHfNamespaceFromServer] = (0, import_react27.useState)(null);
4977
- (0, import_react27.useEffect)(() => {
5110
+ const [hfNamespaceFromServer, setHfNamespaceFromServer] = (0, import_react26.useState)(null);
5111
+ (0, import_react26.useEffect)(() => {
4978
5112
  if (hfNamespace !== void 0) return;
4979
5113
  const backendUrl = typeof window !== "undefined" ? window.BACKEND_URL || window.location.origin : null;
4980
5114
  if (!backendUrl) return;
@@ -4996,36 +5130,36 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4996
5130
  refresh: refreshHF,
4997
5131
  hasStateZip
4998
5132
  } = useHFState(hfToken, effectiveNamespace);
4999
- const [imageUploadStatus, setImageUploadStatus] = (0, import_react27.useState)(/* @__PURE__ */ new Map());
5000
- const [bootstrapLog, setBootstrapLog] = (0, import_react27.useState)([]);
5001
- const [isBootstrapping, setIsBootstrapping] = (0, import_react27.useState)(false);
5002
- const [hfMissingImages, setHfMissingImages] = (0, import_react27.useState)([]);
5003
- const syncTopSlot = /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
5004
- localOnlyCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { background: "rgba(234,179,8,0.15)", border: "1px solid rgba(234,179,8,0.3)", padding: "4px 10px", fontSize: 11, color: "#fbbf24", borderRadius: 4, marginBottom: 4 }, children: [
5133
+ const [imageUploadStatus, setImageUploadStatus] = (0, import_react26.useState)(/* @__PURE__ */ new Map());
5134
+ const [bootstrapLog, setBootstrapLog] = (0, import_react26.useState)([]);
5135
+ const [isBootstrapping, setIsBootstrapping] = (0, import_react26.useState)(false);
5136
+ const [hfMissingImages, setHfMissingImages] = (0, import_react26.useState)([]);
5137
+ const syncTopSlot = /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
5138
+ localOnlyCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { background: "rgba(234,179,8,0.15)", border: "1px solid rgba(234,179,8,0.3)", padding: "4px 10px", fontSize: 11, color: "#fbbf24", borderRadius: 4, marginBottom: 4 }, children: [
5005
5139
  "\u26A0 ",
5006
5140
  localOnlyCount,
5007
5141
  " lokale Event",
5008
5142
  localOnlyCount > 1 ? "s" : "",
5009
5143
  " noch nicht auf HF best\xE4tigt"
5010
5144
  ] }),
5011
- pendingBufferCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { background: "linear-gradient(90deg,#f59e0b,#ef4444)", padding: "4px 10px", fontSize: 11, color: "#fff", borderRadius: 4, marginBottom: 4 }, children: [
5145
+ pendingBufferCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { background: "linear-gradient(90deg,#f59e0b,#ef4444)", padding: "4px 10px", fontSize: 11, color: "#fff", borderRadius: 4, marginBottom: 4 }, children: [
5012
5146
  pendingBufferCount,
5013
5147
  " \xC4nderung",
5014
5148
  pendingBufferCount > 1 ? "en" : "",
5015
5149
  " lokal \u2014 bei Flow-Reload verloren wenn nicht synchronisiert"
5016
5150
  ] }),
5017
- eventCount > 100 && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { background: "#dc2626", color: "#fff", padding: "5px 10px", borderRadius: 4, marginBottom: 4, fontWeight: 600, fontSize: 11 }, children: [
5151
+ eventCount > 100 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { background: "#dc2626", color: "#fff", padding: "5px 10px", borderRadius: 4, marginBottom: 4, fontWeight: 600, fontSize: 11 }, children: [
5018
5152
  "\u26A0 ",
5019
5153
  eventCount,
5020
5154
  " Events nicht konsolidiert \u2014 Konsolidierung dringend empfohlen"
5021
5155
  ] }),
5022
- eventCount > 50 && eventCount <= 100 && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { background: "#44403c", color: "#a8a29e", padding: "4px 10px", borderRadius: 4, marginBottom: 4, fontSize: 11 }, children: [
5156
+ eventCount > 50 && eventCount <= 100 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { background: "#44403c", color: "#a8a29e", padding: "4px 10px", borderRadius: 4, marginBottom: 4, fontSize: 11 }, children: [
5023
5157
  eventCount,
5024
5158
  " Events seit letzter Konsolidierung \u2014 Konsolidierung empfohlen"
5025
5159
  ] }),
5026
- hfToken && !hasStateZip && !isHfRefreshing && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { background: "#1c1917", border: "1px solid #44403c", borderRadius: 6, padding: "10px 12px" }, children: [
5027
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { fontSize: 12, color: "#a8a29e", marginBottom: 6 }, children: effectiveNamespace ? `Kein State-Snapshot in HF (${effectiveNamespace}) \u2014 aus Legacy-Daten (tags.json + metadata.json) migrieren?` : "Namespace wird geladen\u2026" }),
5028
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5160
+ hfToken && !hasStateZip && !isHfRefreshing && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { background: "#1c1917", border: "1px solid #44403c", borderRadius: 6, padding: "10px 12px" }, children: [
5161
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { fontSize: 12, color: "#a8a29e", marginBottom: 6 }, children: effectiveNamespace ? `Kein State-Snapshot in HF (${effectiveNamespace}) \u2014 aus Legacy-Daten (tags.json + metadata.json) migrieren?` : "Namespace wird geladen\u2026" }),
5162
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5029
5163
  "button",
5030
5164
  {
5031
5165
  disabled: isBootstrapping || !effectiveNamespace,
@@ -5046,10 +5180,10 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5046
5180
  children: isBootstrapping ? "Migriere\u2026" : "Legacy-Migration starten"
5047
5181
  }
5048
5182
  ),
5049
- bootstrapLog.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { marginTop: 6, fontFamily: "monospace", fontSize: 10, color: "#78716c", lineHeight: 1.6 }, children: bootstrapLog.map((l, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { children: l }, i)) })
5183
+ bootstrapLog.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { marginTop: 6, fontFamily: "monospace", fontSize: 10, color: "#78716c", lineHeight: 1.6 }, children: bootstrapLog.map((l, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { children: l }, i)) })
5050
5184
  ] })
5051
5185
  ] });
5052
- const wsInputRef = (0, import_react27.useRef)(null);
5186
+ const wsInputRef = (0, import_react26.useRef)(null);
5053
5187
  const startApp = (choice) => {
5054
5188
  try {
5055
5189
  localStorage.setItem("aa-layout", choice);
@@ -5058,16 +5192,37 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5058
5192
  setLayoutChoice(choice);
5059
5193
  setShowStart(false);
5060
5194
  };
5061
- const [nodes, setNodes] = (0, import_react27.useState)([{ id: "1", type: "custom", position: { x: 0, y: 0 }, data: { label: "Fine Art Project", placeholder: "Name..." } }]);
5062
- const [edges, setEdges] = (0, import_react27.useState)([]);
5063
- const [history, setHistory] = (0, import_react27.useState)([]);
5064
- const [galleryItems, setGalleryItems] = (0, import_react27.useState)([]);
5065
- const galleryItemsRef = (0, import_react27.useRef)([]);
5066
- (0, import_react27.useEffect)(() => {
5195
+ const [nodes, setNodes] = (0, import_react26.useState)([{ id: "1", type: "custom", position: { x: 0, y: 0 }, data: { label: "Fine Art Project", placeholder: "Name..." } }]);
5196
+ const [edges, setEdges] = (0, import_react26.useState)([]);
5197
+ const [history, setHistory] = (0, import_react26.useState)([]);
5198
+ const [galleryItems, setGalleryItems] = (0, import_react26.useState)([]);
5199
+ const galleryItemsRef = (0, import_react26.useRef)([]);
5200
+ (0, import_react26.useEffect)(() => {
5067
5201
  galleryItemsRef.current = galleryItems;
5068
5202
  }, [galleryItems]);
5069
- const hfImageNotFoundRef = (0, import_react27.useRef)(/* @__PURE__ */ new Map());
5070
- (0, import_react27.useEffect)(() => {
5203
+ const hfImageNotFoundRef = (0, import_react26.useRef)(/* @__PURE__ */ new Map());
5204
+ const [galleryVisibleCount, setGalleryVisibleCount] = (0, import_react26.useState)(20);
5205
+ const [historyVisibleCount, setHistoryVisibleCount] = (0, import_react26.useState)(20);
5206
+ const loadThumbnailsForEntries = (0, import_react26.useCallback)(async (entries) => {
5207
+ for (const entry of entries) {
5208
+ if (galleryItemsRef.current.find((g) => g.id === entry.id)?.base64) continue;
5209
+ if (hfImageNotFoundRef.current.has(entry.id)) continue;
5210
+ try {
5211
+ const b64 = await hfLoadImageAsBase64(entry.id, hfToken, effectiveNamespace, entry.filename, void 0, entry.mimeType, entry.hasThumb);
5212
+ if (!b64) {
5213
+ hfImageNotFoundRef.current.set(entry.id, Date.now());
5214
+ setHfMissingImages((prev) => prev.find((e) => e.id === entry.id) ? prev : [...prev, { id: entry.id, filename: entry.filename, mimeType: entry.mimeType ?? "image/jpeg", timestamp: entry.timestamp ?? 0 }]);
5215
+ continue;
5216
+ }
5217
+ const prefix = `data:${entry.mimeType || "image/jpeg"};base64,`;
5218
+ setGalleryItems((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
5219
+ setHistory((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
5220
+ } catch {
5221
+ hfImageNotFoundRef.current.set(entry.id, Date.now());
5222
+ }
5223
+ }
5224
+ }, [hfToken, effectiveNamespace]);
5225
+ (0, import_react26.useEffect)(() => {
5071
5226
  if (!hfState) return;
5072
5227
  if (hfState.tags?.by_category) setWorkspaceTags(hfState.tags);
5073
5228
  const hfIds = new Set(hfState.metadata.map((m) => m.id));
@@ -5093,90 +5248,97 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5093
5248
  const merged = skeletons.map((s) => prev.find((g) => g.id === s.id) ?? s);
5094
5249
  return [...localOnly, ...merged].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
5095
5250
  });
5096
- const sortedEntries = [...hfState.metadata].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
5097
- const galleryRepIds = new Set(groupByPrompt(skeletons).slice(0, 20).map((g) => g.representative.id));
5098
- const historyIds = new Set(sortedEntries.slice(0, 20).map((e) => e.id));
5099
- const initialIds = /* @__PURE__ */ new Set([...galleryRepIds, ...historyIds]);
5100
- const toLoad = sortedEntries.filter((e) => initialIds.has(e.id));
5101
- (async () => {
5102
- for (const entry of toLoad) {
5103
- if (galleryItemsRef.current.find((g) => g.id === entry.id)?.base64) continue;
5104
- if (hfImageNotFoundRef.current.has(entry.id)) continue;
5105
- try {
5106
- const b64 = await hfLoadImageAsBase64(entry.id, hfToken, effectiveNamespace, entry.filename, void 0, entry.mimeType, entry.hasThumb);
5107
- if (!b64) {
5108
- hfImageNotFoundRef.current.set(entry.id, Date.now());
5109
- setHfMissingImages((prev) => {
5110
- if (prev.find((e) => e.id === entry.id)) return prev;
5111
- return [...prev, { id: entry.id, filename: entry.filename, mimeType: entry.mimeType, timestamp: entry.timestamp }];
5112
- });
5113
- continue;
5114
- }
5115
- const prefix = `data:${entry.mimeType || "image/jpeg"};base64,`;
5116
- setGalleryItems((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
5117
- setHistory((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
5118
- } catch {
5119
- hfImageNotFoundRef.current.set(entry.id, Date.now());
5120
- }
5121
- }
5122
- })();
5123
5251
  }, [hfState]);
5124
- const [activePrompt, setActivePrompt] = (0, import_react27.useState)("");
5125
- const [isSynthesizing, setIsSynthesizing] = (0, import_react27.useState)(false);
5126
- const [activeGenerationsCount, setActiveGenerationsCount] = (0, import_react27.useState)(0);
5127
- const [currentResult, setCurrentResult] = (0, import_react27.useState)(null);
5128
- const [focusedNodeId, setFocusedNodeId] = (0, import_react27.useState)(null);
5129
- const [leftTab, setLeftTab] = (0, import_react27.useState)("prompt");
5130
- const [promptFeedback, setPromptFeedback] = (0, import_react27.useState)(null);
5131
- const [lastPromptPayload, setLastPromptPayload] = (0, import_react27.useState)(null);
5132
- const [isPromptTabGenerating, setIsPromptTabGenerating] = (0, import_react27.useState)(false);
5133
- const [activeTab, setActiveTab] = (0, import_react27.useState)("history");
5134
- const [mobileTab, setMobileTab] = (0, import_react27.useState)("stage");
5135
- const [middlePanel, setMiddlePanel] = (0, import_react27.useState)("stage");
5136
- const [recentLabItems, setRecentLabItems] = (0, import_react27.useState)([]);
5137
- const [aspectRatio, setAspectRatio] = (0, import_react27.useState)("1:1");
5138
- const [selectedModel, setSelectedModel] = (0, import_react27.useState)("\u{1F34C} Nano Banana Pro");
5139
- const [seed, setSeed] = (0, import_react27.useState)(Math.floor(Math.random() * 1e6));
5140
- const [seedMode, setSeedMode] = (0, import_react27.useState)("random");
5141
- const [isLeftCollapsed, setIsLeftCollapsed] = (0, import_react27.useState)(false);
5142
- const [isRightCollapsed, setIsRightCollapsed] = (0, import_react27.useState)(false);
5143
- const [leftPanelWidth, setLeftPanelWidth] = (0, import_react27.useState)(() => {
5252
+ (0, import_react26.useEffect)(() => {
5253
+ if (!hfState) return;
5254
+ const sortedMeta = [...hfState.metadata].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
5255
+ const skeletons = sortedMeta.map((m) => ({ id: m.id, prompt: m.prompt, timestamp: m.timestamp, status: "done", nodeId: m.id, tags: m.tags || [] }));
5256
+ const repIds = new Set(groupByPrompt(skeletons).slice(0, galleryVisibleCount).map((g) => g.representative.id));
5257
+ loadThumbnailsForEntries(sortedMeta.filter((e) => repIds.has(e.id)));
5258
+ }, [hfState, galleryVisibleCount, loadThumbnailsForEntries]);
5259
+ (0, import_react26.useEffect)(() => {
5260
+ if (!hfState) return;
5261
+ const sortedMeta = [...hfState.metadata].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
5262
+ loadThumbnailsForEntries(sortedMeta.slice(0, historyVisibleCount));
5263
+ }, [hfState, historyVisibleCount, loadThumbnailsForEntries]);
5264
+ const [activePrompt, setActivePrompt] = (0, import_react26.useState)("");
5265
+ const [isSynthesizing, setIsSynthesizing] = (0, import_react26.useState)(false);
5266
+ const [activeGenerationsCount, setActiveGenerationsCount] = (0, import_react26.useState)(0);
5267
+ const [currentResult, setCurrentResult] = (0, import_react26.useState)(null);
5268
+ const [focusedNodeId, setFocusedNodeId] = (0, import_react26.useState)(null);
5269
+ const [leftTab, setLeftTab] = (0, import_react26.useState)("prompt");
5270
+ const [promptFeedback, setPromptFeedback] = (0, import_react26.useState)(null);
5271
+ const [lastPromptPayload, setLastPromptPayload] = (0, import_react26.useState)(null);
5272
+ const [isPromptTabGenerating, setIsPromptTabGenerating] = (0, import_react26.useState)(false);
5273
+ const [activeTab, setActiveTab] = (0, import_react26.useState)("history");
5274
+ const [mobileTab, setMobileTab] = (0, import_react26.useState)("stage");
5275
+ const [middlePanel, setMiddlePanel] = (0, import_react26.useState)("stage");
5276
+ const [recentLabItems, setRecentLabItems] = (0, import_react26.useState)([]);
5277
+ const [aspectRatio, setAspectRatio] = (0, import_react26.useState)("1:1");
5278
+ const [selectedModel, setSelectedModel] = (0, import_react26.useState)("\u{1F34C} Nano Banana Pro");
5279
+ const [seed, setSeed] = (0, import_react26.useState)(Math.floor(Math.random() * 1e6));
5280
+ const [seedMode, setSeedMode] = (0, import_react26.useState)("random");
5281
+ const [imageCount, setImageCount] = (0, import_react26.useState)(() => {
5282
+ try {
5283
+ const v = parseInt(localStorage.getItem("aa-image-count") || "", 10);
5284
+ return v >= 1 && v <= 8 ? v : 4;
5285
+ } catch {
5286
+ return 4;
5287
+ }
5288
+ });
5289
+ const updateImageCount = (val) => {
5290
+ const n = Math.max(1, Math.min(8, parseInt(val, 10) || 4));
5291
+ setImageCount(n);
5292
+ try {
5293
+ localStorage.setItem("aa-image-count", String(n));
5294
+ } catch {
5295
+ }
5296
+ };
5297
+ const imageCountOptions = [
5298
+ { label: "1 Bild", value: "1" },
5299
+ { label: "2 Bilder", value: "2" },
5300
+ { label: "4 Bilder", value: "4" },
5301
+ { label: "8 Bilder", value: "8" }
5302
+ ];
5303
+ const [isLeftCollapsed, setIsLeftCollapsed] = (0, import_react26.useState)(false);
5304
+ const [isRightCollapsed, setIsRightCollapsed] = (0, import_react26.useState)(false);
5305
+ const [leftPanelWidth, setLeftPanelWidth] = (0, import_react26.useState)(() => {
5144
5306
  try {
5145
5307
  return parseInt(localStorage.getItem("aa-left-width") || "260", 10);
5146
5308
  } catch {
5147
5309
  return 260;
5148
5310
  }
5149
5311
  });
5150
- const [rightPanelWidth, setRightPanelWidth] = (0, import_react27.useState)(() => {
5312
+ const [rightPanelWidth, setRightPanelWidth] = (0, import_react26.useState)(() => {
5151
5313
  try {
5152
5314
  return parseInt(localStorage.getItem("aa-right-width") || "320", 10);
5153
5315
  } catch {
5154
5316
  return 320;
5155
5317
  }
5156
5318
  });
5157
- const [isPromptCollapsed, setIsPromptCollapsed] = (0, import_react27.useState)(false);
5158
- const [projectActionState, setProjectActionState] = (0, import_react27.useState)("idle");
5159
- const syncServerDataRef = (0, import_react27.useRef)(null);
5160
- const [workspaceTags, setWorkspaceTags] = (0, import_react27.useState)(null);
5161
- const [serverProjects, setServerProjects] = (0, import_react27.useState)([]);
5162
- const [isLoadingFromServer, setIsLoadingFromServer] = (0, import_react27.useState)(false);
5163
- const [highContrast, setHighContrast] = (0, import_react27.useState)(() => {
5319
+ const [isPromptCollapsed, setIsPromptCollapsed] = (0, import_react26.useState)(false);
5320
+ const [projectActionState, setProjectActionState] = (0, import_react26.useState)("idle");
5321
+ const syncServerDataRef = (0, import_react26.useRef)(null);
5322
+ const [workspaceTags, setWorkspaceTags] = (0, import_react26.useState)(null);
5323
+ const [serverProjects, setServerProjects] = (0, import_react26.useState)([]);
5324
+ const [isLoadingFromServer, setIsLoadingFromServer] = (0, import_react26.useState)(false);
5325
+ const [highContrast, setHighContrast] = (0, import_react26.useState)(() => {
5164
5326
  try {
5165
5327
  return localStorage.getItem("aa-contrast") === "high";
5166
5328
  } catch {
5167
5329
  return false;
5168
5330
  }
5169
5331
  });
5170
- const [activeReferenceId, setActiveReferenceId] = (0, import_react27.useState)(null);
5171
- const [activeReferenceThumbnail, setActiveReferenceThumbnail] = (0, import_react27.useState)(null);
5172
- const [isScanningImage, setIsScanningImage] = (0, import_react27.useState)(false);
5173
- const [touchStartX, setTouchStartX] = (0, import_react27.useState)(null);
5174
- const [isFullscreen, setIsFullscreen] = (0, import_react27.useState)(false);
5175
- const [zoomScale, setZoomScale] = (0, import_react27.useState)(1);
5176
- const [zoomOffset, setZoomOffset] = (0, import_react27.useState)({ x: 0, y: 0 });
5177
- const lastPinchDist = (0, import_react27.useRef)(null);
5178
- const lastTapTime = (0, import_react27.useRef)(0);
5179
- const dragStart = (0, import_react27.useRef)(null);
5332
+ const [activeReferenceId, setActiveReferenceId] = (0, import_react26.useState)(null);
5333
+ const [activeReferenceThumbnail, setActiveReferenceThumbnail] = (0, import_react26.useState)(null);
5334
+ const [isScanningImage, setIsScanningImage] = (0, import_react26.useState)(false);
5335
+ const [touchStartX, setTouchStartX] = (0, import_react26.useState)(null);
5336
+ const [isFullscreen, setIsFullscreen] = (0, import_react26.useState)(false);
5337
+ const [zoomScale, setZoomScale] = (0, import_react26.useState)(1);
5338
+ const [zoomOffset, setZoomOffset] = (0, import_react26.useState)({ x: 0, y: 0 });
5339
+ const lastPinchDist = (0, import_react26.useRef)(null);
5340
+ const lastTapTime = (0, import_react26.useRef)(0);
5341
+ const dragStart = (0, import_react26.useRef)(null);
5180
5342
  const openFullscreen = () => {
5181
5343
  setIsFullscreen(true);
5182
5344
  setZoomScale(1);
@@ -5239,7 +5401,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5239
5401
  setActiveReferenceId(null);
5240
5402
  setActiveReferenceThumbnail(null);
5241
5403
  };
5242
- const labServices = (0, import_react27.useMemo)(() => {
5404
+ const labServices = (0, import_react26.useMemo)(() => {
5243
5405
  const available = groupGenerationsToLabItems([...galleryItems, ...history]);
5244
5406
  return {
5245
5407
  availableItems: available,
@@ -5319,17 +5481,17 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5319
5481
  setIsScanningImage(false);
5320
5482
  }
5321
5483
  };
5322
- const currentIndex = (0, import_react27.useMemo)(() => history.findIndex((h) => h.id === currentResult?.id), [history, currentResult]);
5323
- const goToPrev = (0, import_react27.useCallback)(() => {
5484
+ const currentIndex = (0, import_react26.useMemo)(() => history.findIndex((h) => h.id === currentResult?.id), [history, currentResult]);
5485
+ const goToPrev = (0, import_react26.useCallback)(() => {
5324
5486
  if (currentIndex > 0) setCurrentResult(history[currentIndex - 1]);
5325
5487
  }, [currentIndex, history]);
5326
- const goToNext = (0, import_react27.useCallback)(() => {
5488
+ const goToNext = (0, import_react26.useCallback)(() => {
5327
5489
  if (currentIndex < history.length - 1) setCurrentResult(history[currentIndex + 1]);
5328
5490
  }, [currentIndex, history]);
5329
- const handleGallerySelect = (0, import_react27.useCallback)((g) => {
5491
+ const handleGallerySelect = (0, import_react26.useCallback)((g) => {
5330
5492
  setCurrentResult(g);
5331
5493
  setMobileTab("stage");
5332
- if (g.filename && hfToken && !g.fullBase64) {
5494
+ if (g.hasThumb && g.filename && hfToken && !g.fullBase64) {
5333
5495
  hfLoadImageAsBase64(g.id, hfToken, effectiveNamespace, g.filename, void 0, g.mimeType, false).then((b64) => {
5334
5496
  if (!b64) return;
5335
5497
  const full = `data:${g.mimeType || "image/jpeg"};base64,${b64}`;
@@ -5339,7 +5501,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5339
5501
  });
5340
5502
  }
5341
5503
  }, [hfToken, effectiveNamespace]);
5342
- const handleTitleSet = (0, import_react27.useCallback)((id) => {
5504
+ const handleTitleSet = (0, import_react26.useCallback)((id) => {
5343
5505
  const ts = Date.now();
5344
5506
  setGalleryItems((prev) => prev.map((g) => g.id === id ? { ...g, titleTs: ts } : g));
5345
5507
  setHistory((prev) => prev.map((g) => g.id === id ? { ...g, titleTs: ts } : g));
@@ -5348,13 +5510,13 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5348
5510
  });
5349
5511
  }
5350
5512
  }, [hfToken, effectiveNamespace, hfWriteEvent]);
5351
- const currentGroup = (0, import_react27.useMemo)(() => {
5513
+ const currentGroup = (0, import_react26.useMemo)(() => {
5352
5514
  if (!currentResult?.prompt) return [];
5353
5515
  const groups = groupByPrompt(galleryItems.filter((g) => g.status === "done" && !!g.base64));
5354
5516
  const group = groups.find((gr) => gr.prompt === currentResult.prompt);
5355
5517
  return group ? group.items : [];
5356
5518
  }, [galleryItems, currentResult?.prompt]);
5357
- (0, import_react27.useEffect)(() => {
5519
+ (0, import_react26.useEffect)(() => {
5358
5520
  if (!currentResult?.prompt || !hfToken || !effectiveNamespace || !hfState) return;
5359
5521
  const siblings = galleryItemsRef.current.filter(
5360
5522
  (g) => g.prompt === currentResult.prompt && !g.base64 && !hfImageNotFoundRef.current.has(g.id)
@@ -5380,9 +5542,20 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5380
5542
  })();
5381
5543
  }, [currentResult?.id, currentResult?.prompt]);
5382
5544
  const hcStyle = highContrast ? { filter: "brightness(1.6) contrast(1.05)" } : void 0;
5383
- const isGenerating = activeGenerationsCount > 0;
5545
+ const runningBadge = activeGenerationsCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5546
+ "div",
5547
+ {
5548
+ className: "flex items-center gap-1 rounded-full bg-sky-500/15 border border-sky-400/30 px-2 shrink-0",
5549
+ style: { height: 24 },
5550
+ title: `${activeGenerationsCount} Generierung${activeGenerationsCount === 1 ? "" : "en"} l\xE4uft gerade`,
5551
+ children: [
5552
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-sky-300", style: { fontSize: 14, lineHeight: 1 }, children: "autorenew" }),
5553
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[11px] font-bold text-sky-300 tabular-nums", children: activeGenerationsCount })
5554
+ ]
5555
+ }
5556
+ ) : null;
5384
5557
  useKeyboardNavigation(history, currentResult, setCurrentResult);
5385
- const getSubtreeFormat = (0, import_react27.useCallback)((nodeId, depth = 0) => {
5558
+ const getSubtreeFormat = (0, import_react26.useCallback)((nodeId, depth = 0) => {
5386
5559
  const node = nodes.find((n) => n.id === nodeId);
5387
5560
  if (!node) return "";
5388
5561
  const childrenIds = edges.filter((e) => e.source === nodeId).map((e) => e.target);
@@ -5390,7 +5563,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5390
5563
  return `${indent}- ${node.data.label || "(unbenannt)"}
5391
5564
  ` + childrenIds.map((id) => getSubtreeFormat(id, depth + 1)).join("");
5392
5565
  }, [nodes, edges]);
5393
- const activePath = (0, import_react27.useMemo)(() => {
5566
+ const activePath = (0, import_react26.useMemo)(() => {
5394
5567
  if (!focusedNodeId) return /* @__PURE__ */ new Set();
5395
5568
  const path = /* @__PURE__ */ new Set([focusedNodeId]);
5396
5569
  let currId = focusedNodeId;
@@ -5453,6 +5626,15 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5453
5626
  setActiveGenerationsCount((prev) => Math.max(0, prev - 1));
5454
5627
  }
5455
5628
  };
5629
+ const handleGenerateBatch = (customPrompt, useReferenceId, overrideNodeId, options = { silent: false }) => {
5630
+ const count = Math.max(1, Math.min(8, imageCount));
5631
+ return Promise.all(
5632
+ Array.from(
5633
+ { length: count },
5634
+ (_, i) => handleGenerateImage(customPrompt, useReferenceId, overrideNodeId, { silent: options.silent || i > 0 })
5635
+ )
5636
+ );
5637
+ };
5456
5638
  const handleSynthesizePrompt = async (nodeId, autoGenerate = false) => {
5457
5639
  setIsSynthesizing(true);
5458
5640
  try {
@@ -5739,7 +5921,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5739
5921
  setTimeout(() => setProjectActionState("idle"), 4e3);
5740
5922
  }
5741
5923
  };
5742
- (0, import_react27.useEffect)(() => {
5924
+ (0, import_react26.useEffect)(() => {
5743
5925
  if (activeTab === "setup" || activeTab === "sync") fetchServerProjects();
5744
5926
  }, [activeTab]);
5745
5927
  const mergeWorkspaceTags = (local, remote) => {
@@ -5764,7 +5946,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5764
5946
  if (isFullscreen && currentResult?.base64) {
5765
5947
  const fsRaw = currentResult.fullBase64 || currentResult.base64;
5766
5948
  const fsBase64 = fsRaw.startsWith("data:") ? fsRaw : `data:image/png;base64,${fsRaw}`;
5767
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
5949
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5768
5950
  "div",
5769
5951
  {
5770
5952
  className: "fixed inset-0 bg-black z-50 flex items-center justify-center overflow-hidden touch-none",
@@ -5772,7 +5954,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5772
5954
  onTouchMove: handleFsTouchMove,
5773
5955
  onTouchEnd: handleFsTouchEnd,
5774
5956
  children: [
5775
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5957
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5776
5958
  "img",
5777
5959
  {
5778
5960
  src: fsBase64,
@@ -5789,77 +5971,77 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5789
5971
  }
5790
5972
  }
5791
5973
  ),
5792
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: closeFullscreen, className: "absolute top-4 right-4 w-10 h-10 flex items-center justify-center rounded-full bg-black/70 border border-white/20 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: "close" }) }),
5793
- zoomScale > 1 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => {
5974
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: closeFullscreen, className: "absolute top-4 right-4 w-10 h-10 flex items-center justify-center rounded-full bg-black/70 border border-white/20 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: "close" }) }),
5975
+ zoomScale > 1 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => {
5794
5976
  setZoomScale(1);
5795
5977
  setZoomOffset({ x: 0, y: 0 });
5796
- }, className: "absolute top-4 left-4 w-10 h-10 flex items-center justify-center rounded-full bg-black/70 border border-white/20 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "zoom_out_map" }) }),
5797
- history.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
5798
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => {
5978
+ }, className: "absolute top-4 left-4 w-10 h-10 flex items-center justify-center rounded-full bg-black/70 border border-white/20 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "zoom_out_map" }) }),
5979
+ history.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
5980
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => {
5799
5981
  if (currentIndex > 0) setCurrentResult(history[currentIndex - 1]);
5800
- }, disabled: currentIndex <= 0, className: "absolute left-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_left" }) }),
5801
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => {
5982
+ }, disabled: currentIndex <= 0, className: "absolute left-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_left" }) }),
5983
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => {
5802
5984
  if (currentIndex < history.length - 1) setCurrentResult(history[currentIndex + 1]);
5803
- }, disabled: currentIndex >= history.length - 1, className: "absolute right-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_right" }) }),
5804
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "absolute bottom-6 left-1/2 -translate-x-1/2 bg-black/60 rounded-full px-3 py-0.5 text-[10px] text-white/40 font-mono", children: [
5985
+ }, disabled: currentIndex >= history.length - 1, className: "absolute right-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_right" }) }),
5986
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "absolute bottom-6 left-1/2 -translate-x-1/2 bg-black/60 rounded-full px-3 py-0.5 text-[10px] text-white/40 font-mono", children: [
5805
5987
  currentIndex + 1,
5806
5988
  " / ",
5807
5989
  history.length
5808
5990
  ] })
5809
5991
  ] }),
5810
- zoomScale === 1 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "absolute bottom-6 right-4 text-[9px] text-white/20 font-mono", children: "Pinch zum Zoomen \xB7 Doppeltipp 2.5\xD7" })
5992
+ zoomScale === 1 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute bottom-6 right-4 text-[9px] text-white/20 font-mono", children: "Pinch zum Zoomen \xB7 Doppeltipp 2.5\xD7" })
5811
5993
  ]
5812
5994
  }
5813
5995
  );
5814
5996
  }
5815
5997
  if (showStart) {
5816
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "fixed inset-0 bg-[#0e0e0e] flex flex-col items-center justify-center p-6", style: { gap: 28, ...hcStyle }, children: [
5817
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { ref: wsInputRef, type: "file", accept: ".zip", className: "hidden", onChange: (e) => {
5998
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "fixed inset-0 bg-[#0e0e0e] flex flex-col items-center justify-center p-6", style: { gap: 28, ...hcStyle }, children: [
5999
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { ref: wsInputRef, type: "file", accept: ".zip", className: "hidden", onChange: (e) => {
5818
6000
  const f = e.target.files?.[0];
5819
6001
  if (f) handleProjectImport(f);
5820
6002
  e.target.value = "";
5821
6003
  } }),
5822
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center gap-1", children: [
5823
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-white/15 text-[44px]", children: "palette" }),
5824
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-white/25 text-[10px] font-bold uppercase tracking-[0.25em]", children: "Avatar Architect" }),
5825
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { className: "text-white text-[13px] font-mono", children: [
6004
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col items-center gap-1", children: [
6005
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-white/15 text-[44px]", children: "palette" }),
6006
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-white/25 text-[10px] font-bold uppercase tracking-[0.25em]", children: "Avatar Architect" }),
6007
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "text-white text-[13px] font-mono", children: [
5826
6008
  "v",
5827
6009
  LIB_VERSION
5828
6010
  ] })
5829
6011
  ] }),
5830
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
6012
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5831
6013
  "button",
5832
6014
  {
5833
6015
  onClick: toggleContrast,
5834
6016
  className: "flex items-center gap-3 px-5 py-3 rounded-2xl border transition-colors",
5835
6017
  style: { borderColor: highContrast ? "rgba(255,255,255,0.3)" : "rgba(255,255,255,0.08)", background: highContrast ? "rgba(255,255,255,0.08)" : "transparent" },
5836
6018
  children: [
5837
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[22px]", style: { color: highContrast ? "#fff" : "rgba(255,255,255,0.35)" }, children: highContrast ? "light_mode" : "dark_mode" }),
5838
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-start", children: [
5839
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[13px] font-bold", style: { color: highContrast ? "#fff" : "rgba(255,255,255,0.5)" }, children: highContrast ? "Hoher Kontrast" : "Normaler Kontrast" }),
5840
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[10px]", style: { color: "rgba(255,255,255,0.25)" }, children: "Tippen zum Umschalten" })
6019
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[22px]", style: { color: highContrast ? "#fff" : "rgba(255,255,255,0.35)" }, children: highContrast ? "light_mode" : "dark_mode" }),
6020
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col items-start", children: [
6021
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[13px] font-bold", style: { color: highContrast ? "#fff" : "rgba(255,255,255,0.5)" }, children: highContrast ? "Hoher Kontrast" : "Normaler Kontrast" }),
6022
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[10px]", style: { color: "rgba(255,255,255,0.25)" }, children: "Tippen zum Umschalten" })
5841
6023
  ] })
5842
6024
  ]
5843
6025
  }
5844
6026
  ),
5845
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
5846
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
6027
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
6028
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5847
6029
  "button",
5848
6030
  {
5849
6031
  onClick: () => wsInputRef.current?.click(),
5850
6032
  className: "w-full flex items-center justify-center gap-3 rounded-2xl font-bold text-[14px] uppercase tracking-wide text-white active:scale-95 transition-transform",
5851
6033
  style: { height: 56, background: projectLoaded ? "#16a34a" : "#0284c7" },
5852
6034
  children: [
5853
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: projectLoaded ? "check_circle" : "folder_zip" }),
6035
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: projectLoaded ? "check_circle" : "folder_zip" }),
5854
6036
  projectLoaded ? "Projekt geladen \u2713" : "Projekt laden (.zip)"
5855
6037
  ]
5856
6038
  }
5857
6039
  ),
5858
- !projectLoaded && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-white/20 text-[10px] text-center", children: "Baum, Bilder und Einstellungen wiederherstellen" })
6040
+ !projectLoaded && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-white/20 text-[10px] text-center", children: "Baum, Bilder und Einstellungen wiederherstellen" })
5859
6041
  ] }),
5860
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
5861
- !initialHfToken && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex gap-2 w-full", children: [
5862
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6042
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
6043
+ !initialHfToken && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-2 w-full", children: [
6044
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5863
6045
  "input",
5864
6046
  {
5865
6047
  type: "password",
@@ -5875,7 +6057,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5875
6057
  style: { height: 44, background: "rgba(255,255,255,0.05)", border: "1px solid rgba(255,255,255,0.1)", color: "rgba(255,255,255,0.7)" }
5876
6058
  }
5877
6059
  ),
5878
- hfTokenInput.trim() && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6060
+ hfTokenInput.trim() && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5879
6061
  "button",
5880
6062
  {
5881
6063
  type: "button",
@@ -5886,9 +6068,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5886
6068
  }
5887
6069
  )
5888
6070
  ] }),
5889
- !hfNamespace && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-3 w-full", children: [
5890
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-white/25 text-[10px] uppercase tracking-widest font-bold flex-shrink-0", children: "State:" }),
5891
- ["app.art-by-rolands.de/", "dev-app.art-by-rolands.de/"].map((ns, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6071
+ !hfNamespace && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-3 w-full", children: [
6072
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-white/25 text-[10px] uppercase tracking-widest font-bold flex-shrink-0", children: "State:" }),
6073
+ ["app.art-by-rolands.de/", "dev-app.art-by-rolands.de/"].map((ns, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5892
6074
  "button",
5893
6075
  {
5894
6076
  onClick: () => {
@@ -5908,7 +6090,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5908
6090
  ns
5909
6091
  ))
5910
6092
  ] }),
5911
- hfToken && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
6093
+ hfToken && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5912
6094
  "button",
5913
6095
  {
5914
6096
  disabled: isLoadingFromHF,
@@ -5930,15 +6112,15 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5930
6112
  className: "w-full flex items-center justify-center gap-3 rounded-2xl font-bold text-[14px] uppercase tracking-wide text-white active:scale-95 transition-transform disabled:opacity-50",
5931
6113
  style: { height: 56, background: "#f59e0b" },
5932
6114
  children: [
5933
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: `material-symbols-outlined text-[22px]${isLoadingFromHF ? " animate-spin" : ""}`, children: isLoadingFromHF ? "sync" : "cloud_download" }),
6115
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: `material-symbols-outlined text-[22px]${isLoadingFromHF ? " animate-spin" : ""}`, children: isLoadingFromHF ? "sync" : "cloud_download" }),
5934
6116
  isLoadingFromHF ? "Laden\u2026" : "Von HF laden"
5935
6117
  ]
5936
6118
  }
5937
6119
  ),
5938
- hfToken && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-white/20 text-[10px] text-center", children: "Letzten Stand von Hugging Face laden" })
6120
+ hfToken && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-white/20 text-[10px] text-center", children: "Letzten Stand von Hugging Face laden" })
5939
6121
  ] }),
5940
- onFetchServerProjects && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
5941
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
6122
+ onFetchServerProjects && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
6123
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5942
6124
  "button",
5943
6125
  {
5944
6126
  disabled: isLoadingFromServer,
@@ -5959,35 +6141,35 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5959
6141
  className: "w-full flex items-center justify-center gap-3 rounded-2xl font-bold text-[14px] uppercase tracking-wide text-white active:scale-95 transition-transform disabled:opacity-50",
5960
6142
  style: { height: 56, background: "#7c3aed" },
5961
6143
  children: [
5962
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: `material-symbols-outlined text-[22px]${isLoadingFromServer ? " animate-spin" : ""}`, children: isLoadingFromServer ? "sync" : "cloud_download" }),
6144
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: `material-symbols-outlined text-[22px]${isLoadingFromServer ? " animate-spin" : ""}`, children: isLoadingFromServer ? "sync" : "cloud_download" }),
5963
6145
  isLoadingFromServer ? "Laden\u2026" : "Vom Server laden"
5964
6146
  ]
5965
6147
  }
5966
6148
  ),
5967
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-white/20 text-[10px] text-center", children: "Letzten Stand vom Server wiederherstellen" })
6149
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-white/20 text-[10px] text-center", children: "Letzten Stand vom Server wiederherstellen" })
5968
6150
  ] }),
5969
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
5970
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-white/25 text-[10px] uppercase tracking-widest font-bold", children: "Layout w\xE4hlen & starten" }),
5971
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "grid grid-cols-2 gap-2 w-full", children: [
6151
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col items-center gap-2 w-full max-w-[280px]", children: [
6152
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-white/25 text-[10px] uppercase tracking-widest font-bold", children: "Layout w\xE4hlen & starten" }),
6153
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "grid grid-cols-2 gap-2 w-full", children: [
5972
6154
  { id: "mobile", icon: "smartphone", label: "Mobile" },
5973
6155
  { id: "mobile-desktop", icon: "phonelink", label: "Mobile+" },
5974
6156
  { id: "desktop", icon: "desktop_windows", label: "Desktop" },
5975
6157
  { id: "tablet-landscape", icon: "tablet", label: "Landscape" }
5976
- ].map((opt) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
6158
+ ].map((opt) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5977
6159
  "button",
5978
6160
  {
5979
6161
  onClick: () => startApp(opt.id),
5980
6162
  className: "flex flex-col items-center gap-2 py-4 rounded-2xl border transition-colors",
5981
6163
  style: { borderColor: layoutChoice === opt.id ? "rgba(255,255,255,0.35)" : "rgba(255,255,255,0.08)", background: layoutChoice === opt.id ? "rgba(255,255,255,0.07)" : "transparent" },
5982
6164
  children: [
5983
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[24px]", style: { color: layoutChoice === opt.id ? "#fff" : "rgba(255,255,255,0.4)" }, children: opt.icon }),
5984
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[11px] font-bold", style: { color: layoutChoice === opt.id ? "#fff" : "rgba(255,255,255,0.4)" }, children: opt.label })
6165
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[24px]", style: { color: layoutChoice === opt.id ? "#fff" : "rgba(255,255,255,0.4)" }, children: opt.icon }),
6166
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[11px] font-bold", style: { color: layoutChoice === opt.id ? "#fff" : "rgba(255,255,255,0.4)" }, children: opt.label })
5985
6167
  ]
5986
6168
  },
5987
6169
  opt.id
5988
6170
  )) }),
5989
- layoutChoice === "mobile-desktop" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-white/20 text-[9px] text-center", children: "Mobil-Layout skaliert f\xFCr Desktop-Modus" }),
5990
- layoutChoice === "tablet-landscape" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-white/20 text-[9px] text-center", children: "2-Spalten-Layout f\xFCr Landscape-Tablet im Desktop-Mode" })
6171
+ layoutChoice === "mobile-desktop" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-white/20 text-[9px] text-center", children: "Mobil-Layout skaliert f\xFCr Desktop-Modus" }),
6172
+ layoutChoice === "tablet-landscape" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-white/20 text-[9px] text-center", children: "2-Spalten-Layout f\xFCr Landscape-Tablet im Desktop-Mode" })
5991
6173
  ] })
5992
6174
  ] });
5993
6175
  }
@@ -5996,22 +6178,22 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5996
6178
  const mdScale = mdMode ? window.innerWidth / 430 : 1;
5997
6179
  const mdW = mdMode ? 430 : void 0;
5998
6180
  const mdH = mdMode ? Math.ceil(window.innerHeight / mdScale) : void 0;
5999
- const mobileRoot = /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col bg-[#0e0e0e] text-white overflow-hidden", style: {
6181
+ const mobileRoot = /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col bg-[#0e0e0e] text-white overflow-hidden", style: {
6000
6182
  width: mdMode ? mdW : "100vw",
6001
6183
  height: mdMode ? mdH : "100dvh",
6002
6184
  transform: mdMode ? `scale(${mdScale})` : void 0,
6003
6185
  transformOrigin: mdMode ? "top left" : void 0,
6004
6186
  ...hcStyle || {}
6005
6187
  }, children: [
6006
- mobileTab === "labs" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex flex-col flex-1 min-h-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(LabsTab, { services: labServices, onResult: (item) => {
6188
+ mobileTab === "labs" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex flex-col flex-1 min-h-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LabsTab, { services: labServices, onResult: (item) => {
6007
6189
  const frame = item.frames[0];
6008
6190
  if (frame?.base64) {
6009
6191
  setCurrentResult(frameToGeneration(frame, item));
6010
6192
  setMobileTab("stage");
6011
6193
  }
6012
6194
  } }) }),
6013
- mobileTab === "server" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex flex-col flex-1 min-h-0 relative", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ServerTab, { serverBaseUrl }) }),
6014
- mobileTab === "tags" && workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex flex-col flex-1 min-h-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6195
+ mobileTab === "server" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex flex-col flex-1 min-h-0 relative", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ServerTab, { serverBaseUrl }) }),
6196
+ mobileTab === "tags" && workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex flex-col flex-1 min-h-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6015
6197
  TagManagerPanel,
6016
6198
  {
6017
6199
  workspaceTags,
@@ -6022,21 +6204,23 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6022
6204
  onTagMove: handleTagMove
6023
6205
  }
6024
6206
  ) }),
6025
- mobileTab === "stage" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col flex-1 min-h-0", children: [
6026
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2 px-3 border-b border-white/5 bg-black/30 shrink-0", style: { height: 52 }, children: [
6027
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CompactDropdown, { value: aspectRatio, onChange: setAspectRatio, options: [{ label: "1:1", value: "1:1" }, { label: "16:9", value: "16:9" }, { label: "9:16", value: "9:16" }] }),
6028
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] }),
6029
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1" }),
6030
- activeReferenceThumbnail ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-1 rounded-lg border border-white/20 bg-white/5 overflow-hidden mr-2", style: { height: 28 }, children: [
6031
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src: activeReferenceThumbnail, className: "h-full aspect-square object-cover" }),
6032
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[10px] text-white/60 font-bold uppercase tracking-wide px-1", children: "Ref" }),
6033
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: clearReference, className: "w-6 h-full flex items-center justify-center text-white/30 active:text-white/80 transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "close" }) })
6034
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: handleSelectReference, className: "text-white/20 active:text-white/60 transition-colors mr-2", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "add_photo_alternate" }) }),
6035
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: toggleContrast, className: "text-white/20 active:text-white/60 transition-colors mr-2", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: highContrast ? "light_mode" : "dark_mode" }) }),
6036
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => setShowStart(true), className: "text-white/20 active:text-white/60 transition-colors mr-1", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "desktop_windows" }) })
6207
+ mobileTab === "stage" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col flex-1 min-h-0", children: [
6208
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-2 px-3 border-b border-white/5 bg-black/30 shrink-0", style: { height: 52 }, children: [
6209
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CompactDropdown, { value: aspectRatio, onChange: setAspectRatio, options: [{ label: "1:1", value: "1:1" }, { label: "16:9", value: "16:9" }, { label: "9:16", value: "9:16" }] }),
6210
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] }),
6211
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions }),
6212
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex-1" }),
6213
+ runningBadge,
6214
+ activeReferenceThumbnail ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-1 rounded-lg border border-white/20 bg-white/5 overflow-hidden mr-2", style: { height: 28 }, children: [
6215
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("img", { src: activeReferenceThumbnail, className: "h-full aspect-square object-cover" }),
6216
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[10px] text-white/60 font-bold uppercase tracking-wide px-1", children: "Ref" }),
6217
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: clearReference, className: "w-6 h-full flex items-center justify-center text-white/30 active:text-white/80 transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "close" }) })
6218
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: handleSelectReference, className: "text-white/20 active:text-white/60 transition-colors mr-2", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "add_photo_alternate" }) }),
6219
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: toggleContrast, className: "text-white/20 active:text-white/60 transition-colors mr-2", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: highContrast ? "light_mode" : "dark_mode" }) }),
6220
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => setShowStart(true), className: "text-white/20 active:text-white/60 transition-colors mr-1", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "desktop_windows" }) })
6037
6221
  ] }),
6038
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "px-3 pt-3 pb-2 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `relative rounded-xl border transition-all ${isSynthesizing ? "prompt-loading" : "bg-white/5 border-white/10"}`, children: [
6039
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6222
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "px-3 pt-3 pb-2 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: `relative rounded-xl border transition-all ${isSynthesizing ? "prompt-loading" : "bg-white/5 border-white/10"}`, children: [
6223
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6040
6224
  "textarea",
6041
6225
  {
6042
6226
  value: activePrompt,
@@ -6046,26 +6230,23 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6046
6230
  placeholder: "Prompt eingeben..."
6047
6231
  }
6048
6232
  ),
6049
- activePrompt && !isSynthesizing && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => setActivePrompt(""), className: "absolute top-2 right-2 w-8 h-8 flex items-center justify-center text-white/20 active:text-white transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[18px]", children: "close" }) })
6233
+ activePrompt && !isSynthesizing && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => setActivePrompt(""), className: "absolute top-2 right-2 w-8 h-8 flex items-center justify-center text-white/20 active:text-white transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[18px]", children: "close" }) })
6050
6234
  ] }) }),
6051
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "px-3 pb-3 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6235
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "px-3 pb-3 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
6052
6236
  "button",
6053
6237
  {
6054
- onClick: () => handleGenerateImage(),
6055
- disabled: !activePrompt.trim() || isGenerating,
6238
+ onClick: () => handleGenerateBatch(),
6239
+ disabled: !activePrompt.trim(),
6056
6240
  className: "w-full flex items-center justify-center gap-2 rounded-xl font-bold text-[14px] uppercase tracking-wide transition-all disabled:opacity-30 active:scale-95",
6057
- style: { height: 48, background: activePrompt.trim() && !isGenerating ? "#0284c7" : void 0, border: "1px solid rgba(255,255,255,0.1)" },
6058
- children: isGenerating ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
6059
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-4 h-4 border-t-2 border-white rounded-full animate-spin" }),
6060
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Generiere..." })
6061
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
6062
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "bolt" }),
6063
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Generieren" })
6064
- ] })
6241
+ style: { height: 48, background: activePrompt.trim() ? "#0284c7" : void 0, border: "1px solid rgba(255,255,255,0.1)" },
6242
+ children: [
6243
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "bolt" }),
6244
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Generieren" })
6245
+ ]
6065
6246
  }
6066
6247
  ) }),
6067
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex-1 min-h-0 px-3 pb-3 flex flex-col", children: [
6068
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
6248
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 min-h-0 px-3 pb-3 flex flex-col", children: [
6249
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
6069
6250
  "div",
6070
6251
  {
6071
6252
  className: "w-full rounded-2xl border border-white/5 bg-black/40 relative overflow-hidden flex items-center justify-center",
@@ -6079,25 +6260,25 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6079
6260
  setTouchStartX(null);
6080
6261
  },
6081
6262
  children: [
6082
- currentResult?.status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center gap-3", children: [
6083
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-10 h-10 border-t-2 border-white rounded-full animate-spin" }),
6084
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[11px] text-white/40 uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
6263
+ currentResult?.status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col items-center gap-3 opacity-40", children: [
6264
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[40px]", children: "hourglass_top" }),
6265
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[11px] uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
6085
6266
  ] }),
6086
- currentResult?.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "p-6 text-center flex flex-col items-center gap-3", children: [
6087
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-red-400 text-[36px]", children: "warning" }),
6088
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-white/50 text-[13px]", children: currentResult.error?.message }),
6089
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => handleGenerateImage(currentResult.prompt), className: "px-4 py-2 rounded-lg border border-white/20 text-[13px] text-white/70 active:bg-white/10", children: "Erneut versuchen" })
6267
+ currentResult?.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "p-6 text-center flex flex-col items-center gap-3", children: [
6268
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-red-400 text-[36px]", children: "warning" }),
6269
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-white/50 text-[13px]", children: currentResult.error?.message }),
6270
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => handleGenerateImage(currentResult.prompt), className: "px-4 py-2 rounded-lg border border-white/20 text-[13px] text-white/70 active:bg-white/10", children: "Erneut versuchen" })
6090
6271
  ] }),
6091
- currentResult?.status === "done" && currentResult.base64 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src: currentResult.fullBase64 || currentResult.base64, className: "w-full h-full object-contain" }),
6092
- !currentResult && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center gap-2 opacity-10", children: [
6093
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[64px]", children: "palette" }),
6094
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[11px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
6272
+ currentResult?.status === "done" && currentResult.base64 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("img", { src: currentResult.fullBase64 || currentResult.base64, className: "w-full h-full object-contain" }),
6273
+ !currentResult && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col items-center gap-2 opacity-10", children: [
6274
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[64px]", children: "palette" }),
6275
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[11px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
6095
6276
  ] }),
6096
- currentResult?.status === "done" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: openFullscreen, className: "absolute top-2 right-2 w-8 h-8 flex items-center justify-center rounded-full bg-black/60 border border-white/10 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[18px]", children: "fullscreen" }) }),
6097
- history.length > 1 && currentResult && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
6098
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: goToPrev, disabled: currentIndex <= 0, className: "absolute left-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0 transition-opacity", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_left" }) }),
6099
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: goToNext, disabled: currentIndex >= history.length - 1, className: "absolute right-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0 transition-opacity", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_right" }) }),
6100
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "absolute bottom-2 left-1/2 -translate-x-1/2 bg-black/60 rounded-full px-3 py-0.5 text-[10px] text-white/40 font-mono", children: [
6277
+ currentResult?.status === "done" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: openFullscreen, className: "absolute top-2 right-2 w-8 h-8 flex items-center justify-center rounded-full bg-black/60 border border-white/10 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[18px]", children: "fullscreen" }) }),
6278
+ history.length > 1 && currentResult && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
6279
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: goToPrev, disabled: currentIndex <= 0, className: "absolute left-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0 transition-opacity", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_left" }) }),
6280
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: goToNext, disabled: currentIndex >= history.length - 1, className: "absolute right-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0 transition-opacity", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[22px]", children: "chevron_right" }) }),
6281
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "absolute bottom-2 left-1/2 -translate-x-1/2 bg-black/60 rounded-full px-3 py-0.5 text-[10px] text-white/40 font-mono", children: [
6101
6282
  currentIndex + 1,
6102
6283
  " / ",
6103
6284
  history.length
@@ -6106,8 +6287,8 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6106
6287
  ]
6107
6288
  }
6108
6289
  ),
6109
- currentResult?.status === "done" && currentGroup.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "mt-2 flex gap-1.5 overflow-x-auto pb-1", style: { scrollbarWidth: "none" }, children: currentGroup.map((item) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { position: "relative", flexShrink: 0 }, children: [
6110
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6290
+ currentResult?.status === "done" && currentGroup.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "mt-2 flex gap-1.5 overflow-x-auto pb-1", style: { scrollbarWidth: "none" }, children: currentGroup.map((item) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { position: "relative", flexShrink: 0 }, children: [
6291
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6111
6292
  "div",
6112
6293
  {
6113
6294
  onClick: () => handleGallerySelect(item),
@@ -6120,10 +6301,10 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6120
6301
  border: item.id === currentResult.id ? "2px solid rgba(255,255,255,0.8)" : "2px solid rgba(255,255,255,0.15)",
6121
6302
  opacity: item.id === currentResult.id ? 1 : 0.55
6122
6303
  },
6123
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src: item.base64, style: { width: "100%", height: "100%", objectFit: "cover" }, alt: "" })
6304
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("img", { src: item.base64, style: { width: "100%", height: "100%", objectFit: "cover" }, alt: "" })
6124
6305
  }
6125
6306
  ),
6126
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6307
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6127
6308
  "button",
6128
6309
  {
6129
6310
  onClick: (e) => {
@@ -6145,34 +6326,34 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6145
6326
  alignItems: "center",
6146
6327
  justifyContent: "center"
6147
6328
  },
6148
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 9, color: item.titleTs ? "#fff" : "rgba(255,255,255,0.5)", lineHeight: 1 }, children: "star" })
6329
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 9, color: item.titleTs ? "#fff" : "rgba(255,255,255,0.5)", lineHeight: 1 }, children: "star" })
6149
6330
  }
6150
6331
  )
6151
6332
  ] }, item.id)) }),
6152
- currentResult?.status === "done" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex gap-2 mt-3", children: [
6153
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => setActivePrompt(currentResult.prompt || ""), className: "flex-1 flex items-center justify-center gap-1.5 rounded-xl border border-white/10 bg-white/5 active:bg-white/10 transition-colors", style: { height: 44 }, children: [
6154
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[18px] text-white/60", children: "replay" }),
6155
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[12px] text-white/60", children: "Prompt" })
6333
+ currentResult?.status === "done" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-2 mt-3", children: [
6334
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("button", { onClick: () => setActivePrompt(currentResult.prompt || ""), className: "flex-1 flex items-center justify-center gap-1.5 rounded-xl border border-white/10 bg-white/5 active:bg-white/10 transition-colors", style: { height: 44 }, children: [
6335
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[18px] text-white/60", children: "replay" }),
6336
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[12px] text-white/60", children: "Prompt" })
6156
6337
  ] }),
6157
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => handleGenerateImage(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), className: "flex-1 flex items-center justify-center gap-1.5 rounded-xl bg-white/10 active:bg-white/15 transition-colors", style: { height: 44 }, children: [
6158
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[18px] text-white/80", children: "auto_fix_high" }),
6159
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[12px] text-white/80 font-bold", children: "Referenz" })
6338
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("button", { onClick: () => handleGenerateBatch(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), className: "flex-1 flex items-center justify-center gap-1.5 rounded-xl bg-white/10 active:bg-white/15 transition-colors", style: { height: 44 }, children: [
6339
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[18px] text-white/80", children: "auto_fix_high" }),
6340
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[12px] text-white/80 font-bold", children: "Referenz" })
6160
6341
  ] }),
6161
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: handleDownloadSingle, className: "flex-1 flex items-center justify-center gap-1.5 rounded-xl border border-white/10 bg-white/5 active:bg-white/10 transition-colors", style: { height: 44 }, children: [
6162
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[18px] text-white/60", children: "download" }),
6163
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[12px] text-white/60", children: "Laden" })
6342
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("button", { onClick: handleDownloadSingle, className: "flex-1 flex items-center justify-center gap-1.5 rounded-xl border border-white/10 bg-white/5 active:bg-white/10 transition-colors", style: { height: 44 }, children: [
6343
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[18px] text-white/60", children: "download" }),
6344
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[12px] text-white/60", children: "Laden" })
6164
6345
  ] })
6165
6346
  ] })
6166
6347
  ] })
6167
6348
  ] }),
6168
- mobileTab === "browse" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col flex-1 min-h-0", children: [
6169
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex border-b border-white/5 shrink-0", style: { height: 52 }, children: [
6170
- ["history", "gallery", "inspect"].map((tab) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => setActiveTab(tab), className: `flex-1 flex items-center justify-center gap-1.5 transition-colors text-[11px] font-bold uppercase tracking-wide ${activeTab === tab ? "text-white border-b-2 border-white" : "text-white/30"}`, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: tab === "history" ? "history" : tab === "gallery" ? "photo_library" : "info" }) }, tab)),
6171
- hfToken && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => refreshHF(), disabled: isHfRefreshing, className: "w-12 flex items-center justify-center text-white/20 active:text-white transition-colors disabled:opacity-30", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: `material-symbols-outlined text-[20px]${isHfRefreshing ? " animate-spin" : ""}`, children: "sync" }) })
6349
+ mobileTab === "browse" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col flex-1 min-h-0", children: [
6350
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex border-b border-white/5 shrink-0", style: { height: 52 }, children: [
6351
+ ["history", "gallery", "inspect"].map((tab) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => setActiveTab(tab), className: `flex-1 flex items-center justify-center gap-1.5 transition-colors text-[11px] font-bold uppercase tracking-wide ${activeTab === tab ? "text-white border-b-2 border-white" : "text-white/30"}`, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: tab === "history" ? "history" : tab === "gallery" ? "photo_library" : "info" }) }, tab)),
6352
+ hfToken && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => refreshHF(), disabled: isHfRefreshing, className: "w-12 flex items-center justify-center text-white/20 active:text-white transition-colors disabled:opacity-30", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: `material-symbols-outlined text-[20px]${isHfRefreshing ? " animate-spin" : ""}`, children: "sync" }) })
6172
6353
  ] }),
6173
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex-1 overflow-hidden relative", children: [
6174
- activeTab === "history" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)) }),
6175
- activeTab === "gallery" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6354
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 overflow-hidden relative", children: [
6355
+ activeTab === "history" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }),
6356
+ activeTab === "gallery" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6176
6357
  MediaLibrary,
6177
6358
  {
6178
6359
  items: galleryItems,
@@ -6184,49 +6365,51 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6184
6365
  onDelete: (id) => setGalleryItems((g) => g.filter((x) => x.id !== id)),
6185
6366
  onSelect: handleGallerySelect,
6186
6367
  onGenerateReference: (item) => {
6187
- handleGenerateImage(item.prompt || activePrompt, item.mediaId, void 0, { silent: true });
6368
+ handleGenerateBatch(item.prompt || activePrompt, item.mediaId, void 0, { silent: true });
6188
6369
  setMobileTab("stage");
6189
- }
6370
+ },
6371
+ visibleCount: galleryVisibleCount,
6372
+ onLoadMore: () => setGalleryVisibleCount((c) => c + 20)
6190
6373
  }
6191
6374
  ),
6192
- activeTab === "inspect" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(InspectPanel, { currentResult, history, onSelect: (g) => {
6375
+ activeTab === "inspect" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(InspectPanel, { currentResult, history, onSelect: (g) => {
6193
6376
  setCurrentResult(g);
6194
6377
  } })
6195
6378
  ] })
6196
6379
  ] }),
6197
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: mobileTab === "tools" ? "flex" : "none" }, className: "flex flex-col flex-1 min-h-0", children: [
6198
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex border-b border-white/5 shrink-0", style: { height: 52 }, children: [
6199
- workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => {
6380
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: mobileTab === "tools" ? "flex" : "none" }, className: "flex flex-col flex-1 min-h-0", children: [
6381
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex border-b border-white/5 shrink-0", style: { height: 52 }, children: [
6382
+ workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("button", { onClick: () => {
6200
6383
  setLeftTab("prompt");
6201
6384
  if (activeTab === "setup" || activeTab === "sync") setActiveTab("history");
6202
6385
  }, className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${leftTab === "prompt" && activeTab !== "setup" && activeTab !== "sync" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
6203
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "auto_fix_high" }),
6386
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "auto_fix_high" }),
6204
6387
  "Prompt"
6205
6388
  ] }),
6206
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => {
6389
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("button", { onClick: () => {
6207
6390
  setLeftTab("hierarchy");
6208
6391
  if (activeTab === "setup" || activeTab === "sync") setActiveTab("history");
6209
6392
  }, className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${leftTab === "hierarchy" && activeTab !== "setup" && activeTab !== "sync" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
6210
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "account_tree" }),
6393
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "account_tree" }),
6211
6394
  "Hierarchie"
6212
6395
  ] }),
6213
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => setActiveTab("setup"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "setup" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
6214
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "settings" }),
6396
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("button", { onClick: () => setActiveTab("setup"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "setup" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
6397
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "settings" }),
6215
6398
  "Setup"
6216
6399
  ] }),
6217
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => setActiveTab("sync"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "sync" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
6218
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "cloud_sync" }),
6400
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("button", { onClick: () => setActiveTab("sync"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "sync" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
6401
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "cloud_sync" }),
6219
6402
  "Sync"
6220
6403
  ] }),
6221
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => setActiveTab("hftest"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "hftest" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
6222
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "biotech" }),
6404
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("button", { onClick: () => setActiveTab("hftest"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "hftest" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: [
6405
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "biotech" }),
6223
6406
  "HF"
6224
6407
  ] }),
6225
- serverBaseUrl && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => setActiveTab("server"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "server" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "storage" }) }),
6226
- workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => setActiveTab("tags"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "tags" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "label" }) })
6408
+ serverBaseUrl && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => setActiveTab("server"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "server" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "storage" }) }),
6409
+ workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => setActiveTab("tags"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "tags" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "label" }) })
6227
6410
  ] }),
6228
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex-1 overflow-hidden relative", children: [
6229
- leftTab === "hierarchy" && activeTab !== "setup" && activeTab !== "sync" && activeTab !== "hftest" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "absolute inset-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6411
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 overflow-hidden relative", children: [
6412
+ leftTab === "hierarchy" && activeTab !== "setup" && activeTab !== "sync" && activeTab !== "hftest" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute inset-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6230
6413
  ListView,
6231
6414
  {
6232
6415
  nodes,
@@ -6257,12 +6440,12 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6257
6440
  isGeneratingNodeId: (id) => isSynthesizing && focusedNodeId === id
6258
6441
  }
6259
6442
  ) }),
6260
- workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { display: leftTab === "prompt" && activeTab !== "setup" && activeTab !== "sync" && activeTab !== "hftest" ? "flex" : "none" }, className: "absolute inset-0 flex-col", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PromptTab, { workspaceTags, onGenerate: handlePromptTabGenerate, isGenerating: isPromptTabGenerating, feedback: promptFeedback, promptResult: activePrompt || null, lastPayload: lastPromptPayload, onGenerateImage: (prompt) => {
6261
- handleGenerateImage(prompt);
6443
+ workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { display: leftTab === "prompt" && activeTab !== "setup" && activeTab !== "sync" && activeTab !== "hftest" ? "flex" : "none" }, className: "absolute inset-0 flex-col", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PromptTab, { workspaceTags, onGenerate: handlePromptTabGenerate, isGenerating: isPromptTabGenerating, feedback: promptFeedback, promptResult: activePrompt || null, lastPayload: lastPromptPayload, onGenerateImage: (prompt) => {
6444
+ handleGenerateBatch(prompt);
6262
6445
  setMobileTab("stage");
6263
6446
  }, onTagCreate: handleTagCreate, onTagUpdate: handleTagUpdate, onTagDelete: handleTagDelete, onScanImage: handleScanImage, isScanning: isScanningImage }) }),
6264
- activeTab === "setup" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SetupPanel, { onWorkspaceImport: handleWorkspaceImport, buildInfo }),
6265
- activeTab === "sync" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6447
+ activeTab === "setup" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SetupPanel, { onWorkspaceImport: handleWorkspaceImport, buildInfo }),
6448
+ activeTab === "sync" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6266
6449
  ProjectSyncTab,
6267
6450
  {
6268
6451
  topSlot: syncTopSlot,
@@ -6286,7 +6469,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6286
6469
  onHfInitialSync: hfToken ? handleHfInitialSync : void 0
6287
6470
  }
6288
6471
  ),
6289
- activeTab === "tags" && workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6472
+ activeTab === "tags" && workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6290
6473
  TagManagerPanel,
6291
6474
  {
6292
6475
  workspaceTags,
@@ -6297,7 +6480,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6297
6480
  onTagMove: handleTagMove
6298
6481
  }
6299
6482
  ),
6300
- activeTab === "hftest" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "absolute inset-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6483
+ activeTab === "hftest" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute inset-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6301
6484
  HFTestTab,
6302
6485
  {
6303
6486
  token: hfToken,
@@ -6309,23 +6492,23 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6309
6492
  missingImages: hfMissingImages
6310
6493
  }
6311
6494
  ) }),
6312
- activeTab === "server" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "absolute inset-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ServerTab, { serverBaseUrl }) })
6495
+ activeTab === "server" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute inset-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ServerTab, { serverBaseUrl }) })
6313
6496
  ] })
6314
6497
  ] }),
6315
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex border-t border-white/10 bg-black shrink-0", style: { height: 56, paddingBottom: "env(safe-area-inset-bottom, 0px)" }, children: [
6498
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex border-t border-white/10 bg-black shrink-0", style: { height: 56, paddingBottom: "env(safe-area-inset-bottom, 0px)" }, children: [
6316
6499
  { id: "tools", icon: "auto_fix_high", label: "Prompt" },
6317
6500
  { id: "stage", icon: "palette", label: "Stage" },
6318
6501
  { id: "labs", icon: "science", label: "Labs" },
6319
6502
  ...workspaceTags ? [{ id: "tags", icon: "label", label: "Tags" }] : [],
6320
6503
  { id: "browse", icon: "photo_library", label: "Galerie" },
6321
6504
  ...serverBaseUrl ? [{ id: "server", icon: "storage", label: "Server" }] : []
6322
- ].map((tab) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => setMobileTab(tab.id), className: `flex-1 flex flex-col items-center justify-center gap-0.5 transition-colors ${mobileTab === tab.id ? "text-white" : "text-white/30"}`, children: [
6323
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[24px]", children: tab.icon }),
6324
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[10px] font-bold uppercase tracking-wide", children: tab.label })
6505
+ ].map((tab) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("button", { onClick: () => setMobileTab(tab.id), className: `flex-1 flex flex-col items-center justify-center gap-0.5 transition-colors ${mobileTab === tab.id ? "text-white" : "text-white/30"}`, children: [
6506
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[24px]", children: tab.icon }),
6507
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[10px] font-bold uppercase tracking-wide", children: tab.label })
6325
6508
  ] }, tab.id)) })
6326
6509
  ] });
6327
6510
  if (mdMode) {
6328
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { position: "fixed", inset: 0, overflow: "hidden", background: "#0e0e0e" }, children: mobileRoot });
6511
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { position: "fixed", inset: 0, overflow: "hidden", background: "#0e0e0e" }, children: mobileRoot });
6329
6512
  }
6330
6513
  return mobileRoot;
6331
6514
  }
@@ -6333,17 +6516,19 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6333
6516
  const tlScale = Math.min(window.innerWidth / 920, window.innerHeight / 520);
6334
6517
  const tlW = 920;
6335
6518
  const tlH = 520;
6336
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { position: "fixed", inset: 0, background: "#0e0e0e", display: "flex", alignItems: "center", justifyContent: "center", overflow: "hidden", ...hcStyle || {} }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { width: tlW, height: tlH, transform: `scale(${tlScale})`, transformOrigin: "center center", display: "flex", flexDirection: "row", color: "#fff", overflow: "hidden", borderRadius: 0 }, children: [
6337
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { width: 320, height: tlH, display: "flex", flexDirection: "column", borderRight: "1px solid rgba(255,255,255,0.05)", background: "#000", flexShrink: 0 }, children: [
6338
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { height: 52, borderBottom: "1px solid rgba(255,255,255,0.05)", display: "flex", alignItems: "center", gap: 8, padding: "0 12px", flexShrink: 0 }, children: [
6339
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CompactDropdown, { value: aspectRatio, onChange: setAspectRatio, options: [{ label: "1:1", value: "1:1" }, { label: "16:9", value: "16:9" }, { label: "9:16", value: "9:16" }] }),
6340
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] }),
6341
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { flex: 1 } }),
6342
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: toggleContrast, style: { color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 4, lineHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: highContrast ? "light_mode" : "dark_mode" }) }),
6343
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => setShowStart(true), style: { color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 4, lineHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "apps" }) })
6519
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { position: "fixed", inset: 0, background: "#0e0e0e", display: "flex", alignItems: "center", justifyContent: "center", overflow: "hidden", ...hcStyle || {} }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { width: tlW, height: tlH, transform: `scale(${tlScale})`, transformOrigin: "center center", display: "flex", flexDirection: "row", color: "#fff", overflow: "hidden", borderRadius: 0 }, children: [
6520
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { width: 320, height: tlH, display: "flex", flexDirection: "column", borderRight: "1px solid rgba(255,255,255,0.05)", background: "#000", flexShrink: 0 }, children: [
6521
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { height: 52, borderBottom: "1px solid rgba(255,255,255,0.05)", display: "flex", alignItems: "center", gap: 8, padding: "0 12px", flexShrink: 0 }, children: [
6522
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CompactDropdown, { value: aspectRatio, onChange: setAspectRatio, options: [{ label: "1:1", value: "1:1" }, { label: "16:9", value: "16:9" }, { label: "9:16", value: "9:16" }] }),
6523
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] }),
6524
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions }),
6525
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1 } }),
6526
+ runningBadge,
6527
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: toggleContrast, style: { color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 4, lineHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: highContrast ? "light_mode" : "dark_mode" }) }),
6528
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => setShowStart(true), style: { color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 4, lineHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "apps" }) })
6344
6529
  ] }),
6345
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { padding: "12px 12px 8px", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { position: "relative", borderRadius: 12, border: `1px solid ${isSynthesizing ? "rgba(255,255,255,0.2)" : "rgba(255,255,255,0.1)"}`, background: "rgba(255,255,255,0.05)" }, children: [
6346
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6530
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { padding: "12px 12px 8px", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { position: "relative", borderRadius: 12, border: `1px solid ${isSynthesizing ? "rgba(255,255,255,0.2)" : "rgba(255,255,255,0.1)"}`, background: "rgba(255,255,255,0.05)" }, children: [
6531
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6347
6532
  "textarea",
6348
6533
  {
6349
6534
  value: activePrompt,
@@ -6352,27 +6537,24 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6352
6537
  placeholder: "Prompt eingeben..."
6353
6538
  }
6354
6539
  ),
6355
- activePrompt && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => setActivePrompt(""), style: { position: "absolute", top: 6, right: 6, width: 22, height: 22, display: "flex", alignItems: "center", justifyContent: "center", color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 15 }, children: "close" }) })
6540
+ activePrompt && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => setActivePrompt(""), style: { position: "absolute", top: 6, right: 6, width: 22, height: 22, display: "flex", alignItems: "center", justifyContent: "center", color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 15 }, children: "close" }) })
6356
6541
  ] }) }),
6357
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { padding: "0 12px 10px", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6542
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { padding: "0 12px 10px", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
6358
6543
  "button",
6359
6544
  {
6360
- onClick: () => handleGenerateImage(),
6361
- disabled: !activePrompt.trim() || isGenerating,
6362
- style: { width: "100%", height: 42, display: "flex", alignItems: "center", justifyContent: "center", gap: 8, borderRadius: 10, fontWeight: "bold", fontSize: 13, textTransform: "uppercase", letterSpacing: "0.05em", border: "1px solid rgba(255,255,255,0.1)", background: activePrompt.trim() && !isGenerating ? "#0284c7" : "transparent", color: "#fff", cursor: activePrompt.trim() && !isGenerating ? "pointer" : "default", opacity: !activePrompt.trim() || isGenerating ? 0.3 : 1, fontFamily: "inherit", transition: "background 0.2s" },
6363
- children: isGenerating ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
6364
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { width: 14, height: 14, borderTop: "2px solid #fff", borderRadius: "50%", animation: "spin 1s linear infinite" } }),
6365
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Generiere..." })
6366
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
6367
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "bolt" }),
6368
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Generieren" })
6369
- ] })
6545
+ onClick: () => handleGenerateBatch(),
6546
+ disabled: !activePrompt.trim(),
6547
+ style: { width: "100%", height: 42, display: "flex", alignItems: "center", justifyContent: "center", gap: 8, borderRadius: 10, fontWeight: "bold", fontSize: 13, textTransform: "uppercase", letterSpacing: "0.05em", border: "1px solid rgba(255,255,255,0.1)", background: activePrompt.trim() ? "#0284c7" : "transparent", color: "#fff", cursor: activePrompt.trim() ? "pointer" : "default", opacity: !activePrompt.trim() ? 0.3 : 1, fontFamily: "inherit", transition: "background 0.2s" },
6548
+ children: [
6549
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "bolt" }),
6550
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Generieren" })
6551
+ ]
6370
6552
  }
6371
6553
  ) }),
6372
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { flex: 1, overflow: "hidden", position: "relative" }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)) }) })
6554
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflow: "hidden", position: "relative" }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }) })
6373
6555
  ] }),
6374
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { flex: 1, height: tlH, display: "flex", flexDirection: "column", background: "#0b0b0b" }, children: [
6375
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6556
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { flex: 1, height: tlH, display: "flex", flexDirection: "column", background: "#0b0b0b" }, children: [
6557
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6376
6558
  "div",
6377
6559
  {
6378
6560
  style: { flex: 1, padding: 16, display: "flex", alignItems: "center", justifyContent: "center", position: "relative" },
@@ -6384,26 +6566,26 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6384
6566
  else if (dx > 50) goToPrev();
6385
6567
  setTouchStartX(null);
6386
6568
  },
6387
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { height: "100%", width: "100%", borderRadius: 20, border: "1px solid rgba(255,255,255,0.05)", background: "rgba(0,0,0,0.4)", position: "relative", overflow: "hidden", display: "flex", alignItems: "center", justifyContent: "center" }, children: [
6388
- currentResult?.status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }, children: [
6389
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { width: 36, height: 36, borderTop: "2px solid #fff", borderRadius: "50%", animation: "spin 1s linear infinite" } }),
6390
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { style: { fontSize: 10, color: "rgba(255,255,255,0.4)", textTransform: "uppercase", fontWeight: "bold", letterSpacing: "0.15em" }, children: "Erstelle Bild..." })
6569
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { height: "100%", width: "100%", borderRadius: 20, border: "1px solid rgba(255,255,255,0.05)", background: "rgba(0,0,0,0.4)", position: "relative", overflow: "hidden", display: "flex", alignItems: "center", justifyContent: "center" }, children: [
6570
+ currentResult?.status === "processing" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 12, opacity: 0.4 }, children: [
6571
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 36 }, children: "hourglass_top" }),
6572
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontSize: 10, color: "rgba(255,255,255,0.6)", textTransform: "uppercase", fontWeight: "bold", letterSpacing: "0.15em" }, children: "Erstelle Bild..." })
6391
6573
  ] }),
6392
- currentResult?.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { padding: 24, textAlign: "center", display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }, children: [
6393
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 32, color: "#f87171" }, children: "warning" }),
6394
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { style: { fontSize: 11, color: "rgba(255,255,255,0.5)", margin: 0 }, children: currentResult.error?.message }),
6395
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => handleGenerateImage(currentResult.prompt), style: { padding: "8px 16px", borderRadius: 8, border: "1px solid rgba(255,255,255,0.2)", fontSize: 11, color: "rgba(255,255,255,0.7)", background: "none", cursor: "pointer", fontFamily: "inherit" }, children: "Erneut versuchen" })
6574
+ currentResult?.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { padding: 24, textAlign: "center", display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }, children: [
6575
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 32, color: "#f87171" }, children: "warning" }),
6576
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { style: { fontSize: 11, color: "rgba(255,255,255,0.5)", margin: 0 }, children: currentResult.error?.message }),
6577
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => handleGenerateImage(currentResult.prompt), style: { padding: "8px 16px", borderRadius: 8, border: "1px solid rgba(255,255,255,0.2)", fontSize: 11, color: "rgba(255,255,255,0.7)", background: "none", cursor: "pointer", fontFamily: "inherit" }, children: "Erneut versuchen" })
6396
6578
  ] }),
6397
- currentResult?.status === "done" && currentResult.base64 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src: currentResult.fullBase64 || currentResult.base64, style: { maxWidth: "100%", maxHeight: "100%", objectFit: "contain" } }),
6398
- !currentResult && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 8, opacity: 0.1 }, children: [
6399
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 64 }, children: "palette" }),
6400
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { style: { fontSize: 11, fontWeight: "bold", textTransform: "uppercase", letterSpacing: "0.2em" }, children: "Avatar Architect" })
6579
+ currentResult?.status === "done" && currentResult.base64 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("img", { src: currentResult.fullBase64 || currentResult.base64, style: { maxWidth: "100%", maxHeight: "100%", objectFit: "contain" } }),
6580
+ !currentResult && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 8, opacity: 0.1 }, children: [
6581
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 64 }, children: "palette" }),
6582
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontSize: 11, fontWeight: "bold", textTransform: "uppercase", letterSpacing: "0.2em" }, children: "Avatar Architect" })
6401
6583
  ] }),
6402
- currentResult?.status === "done" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: openFullscreen, style: { position: "absolute", top: 8, right: 8, width: 32, height: 32, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff" }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "fullscreen" }) }),
6403
- history.length > 1 && currentResult && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
6404
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: goToPrev, disabled: currentIndex <= 0, style: { position: "absolute", left: 8, top: "50%", transform: "translateY(-50%)", width: 36, height: 36, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff", opacity: currentIndex <= 0 ? 0 : 1, transition: "opacity 0.2s" }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 20 }, children: "chevron_left" }) }),
6405
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: goToNext, disabled: currentIndex >= history.length - 1, style: { position: "absolute", right: 8, top: "50%", transform: "translateY(-50%)", width: 36, height: 36, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff", opacity: currentIndex >= history.length - 1 ? 0 : 1, transition: "opacity 0.2s" }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 20 }, children: "chevron_right" }) }),
6406
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { position: "absolute", bottom: 8, left: "50%", transform: "translateX(-50%)", background: "rgba(0,0,0,0.6)", borderRadius: 999, padding: "2px 12px", fontSize: 10, color: "rgba(255,255,255,0.4)", fontFamily: "monospace" }, children: [
6584
+ currentResult?.status === "done" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: openFullscreen, style: { position: "absolute", top: 8, right: 8, width: 32, height: 32, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff" }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "fullscreen" }) }),
6585
+ history.length > 1 && currentResult && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
6586
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: goToPrev, disabled: currentIndex <= 0, style: { position: "absolute", left: 8, top: "50%", transform: "translateY(-50%)", width: 36, height: 36, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff", opacity: currentIndex <= 0 ? 0 : 1, transition: "opacity 0.2s" }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 20 }, children: "chevron_left" }) }),
6587
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: goToNext, disabled: currentIndex >= history.length - 1, style: { position: "absolute", right: 8, top: "50%", transform: "translateY(-50%)", width: 36, height: 36, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff", opacity: currentIndex >= history.length - 1 ? 0 : 1, transition: "opacity 0.2s" }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 20 }, children: "chevron_right" }) }),
6588
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { position: "absolute", bottom: 8, left: "50%", transform: "translateX(-50%)", background: "rgba(0,0,0,0.6)", borderRadius: 999, padding: "2px 12px", fontSize: 10, color: "rgba(255,255,255,0.4)", fontFamily: "monospace" }, children: [
6407
6589
  currentIndex + 1,
6408
6590
  " / ",
6409
6591
  history.length
@@ -6412,42 +6594,42 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6412
6594
  ] })
6413
6595
  }
6414
6596
  ),
6415
- currentResult?.status === "done" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { padding: "0 16px 16px", display: "flex", gap: 8, flexShrink: 0 }, children: [
6416
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => setActivePrompt(currentResult.prompt || ""), style: { flex: 1, height: 40, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, borderRadius: 10, border: "1px solid rgba(255,255,255,0.1)", background: "rgba(255,255,255,0.05)", color: "rgba(255,255,255,0.6)", fontSize: 11, cursor: "pointer", fontFamily: "inherit" }, children: [
6417
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "replay" }),
6418
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Prompt" })
6597
+ currentResult?.status === "done" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { padding: "0 16px 16px", display: "flex", gap: 8, flexShrink: 0 }, children: [
6598
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("button", { onClick: () => setActivePrompt(currentResult.prompt || ""), style: { flex: 1, height: 40, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, borderRadius: 10, border: "1px solid rgba(255,255,255,0.1)", background: "rgba(255,255,255,0.05)", color: "rgba(255,255,255,0.6)", fontSize: 11, cursor: "pointer", fontFamily: "inherit" }, children: [
6599
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "replay" }),
6600
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Prompt" })
6419
6601
  ] }),
6420
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => handleGenerateImage(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), style: { flex: 1, height: 40, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, borderRadius: 10, border: "none", background: "rgba(255,255,255,0.1)", color: "rgba(255,255,255,0.8)", fontSize: 11, fontWeight: "bold", cursor: "pointer", fontFamily: "inherit" }, children: [
6421
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "auto_fix_high" }),
6422
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Referenz" })
6602
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("button", { onClick: () => handleGenerateBatch(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), style: { flex: 1, height: 40, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, borderRadius: 10, border: "none", background: "rgba(255,255,255,0.1)", color: "rgba(255,255,255,0.8)", fontSize: 11, fontWeight: "bold", cursor: "pointer", fontFamily: "inherit" }, children: [
6603
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "auto_fix_high" }),
6604
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Referenz" })
6423
6605
  ] }),
6424
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: handleDownloadSingle, style: { flex: 1, height: 40, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, borderRadius: 10, border: "1px solid rgba(255,255,255,0.1)", background: "rgba(255,255,255,0.05)", color: "rgba(255,255,255,0.6)", fontSize: 11, cursor: "pointer", fontFamily: "inherit" }, children: [
6425
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "download" }),
6426
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Laden" })
6606
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("button", { onClick: handleDownloadSingle, style: { flex: 1, height: 40, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, borderRadius: 10, border: "1px solid rgba(255,255,255,0.1)", background: "rgba(255,255,255,0.05)", color: "rgba(255,255,255,0.6)", fontSize: 11, cursor: "pointer", fontFamily: "inherit" }, children: [
6607
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "download" }),
6608
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Laden" })
6427
6609
  ] })
6428
6610
  ] })
6429
6611
  ] })
6430
6612
  ] }) });
6431
6613
  }
6432
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex h-screen w-screen bg-[#0e0e0e] text-white overflow-hidden", style: hcStyle, children: [
6433
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "absolute top-2 right-2 z-50", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => setShowStart(true), className: "text-white/10 hover:text-white/30 transition-colors text-[10px]", children: "\u21C4" }) }),
6434
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col border-r border-white/5 overflow-hidden relative bg-black/10 shrink-0", style: { width: isLeftCollapsed ? 48 : leftPanelWidth, transition: "none" }, children: [
6435
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "h-14 border-b border-white/5 flex items-center justify-between shrink-0 px-1", children: [
6436
- !isLeftCollapsed && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-1 gap-1", children: [
6437
- workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => setLeftTab("prompt"), className: `flex-1 flex items-center justify-center gap-1 h-8 rounded-lg text-[8px] font-bold uppercase tracking-wide transition-colors ${leftTab === "prompt" ? "bg-white/10 text-white" : "text-white/30 hover:text-white/60"}`, children: [
6438
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "auto_fix_high" }),
6614
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex h-screen w-screen bg-[#0e0e0e] text-white overflow-hidden", style: hcStyle, children: [
6615
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute top-2 right-2 z-50", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => setShowStart(true), className: "text-white/10 hover:text-white/30 transition-colors text-[10px]", children: "\u21C4" }) }),
6616
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col border-r border-white/5 overflow-hidden relative bg-black/10 shrink-0", style: { width: isLeftCollapsed ? 48 : leftPanelWidth, transition: "none" }, children: [
6617
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "h-14 border-b border-white/5 flex items-center justify-between shrink-0 px-1", children: [
6618
+ !isLeftCollapsed && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-1 gap-1", children: [
6619
+ workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("button", { onClick: () => setLeftTab("prompt"), className: `flex-1 flex items-center justify-center gap-1 h-8 rounded-lg text-[8px] font-bold uppercase tracking-wide transition-colors ${leftTab === "prompt" ? "bg-white/10 text-white" : "text-white/30 hover:text-white/60"}`, children: [
6620
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "auto_fix_high" }),
6439
6621
  "Prompt"
6440
6622
  ] }),
6441
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: () => setLeftTab("hierarchy"), className: `flex-1 flex items-center justify-center gap-1 h-8 rounded-lg text-[8px] font-bold uppercase tracking-wide transition-colors ${leftTab === "hierarchy" ? "bg-white/10 text-white" : "text-white/30 hover:text-white/60"}`, children: [
6442
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "account_tree" }),
6623
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("button", { onClick: () => setLeftTab("hierarchy"), className: `flex-1 flex items-center justify-center gap-1 h-8 rounded-lg text-[8px] font-bold uppercase tracking-wide transition-colors ${leftTab === "hierarchy" ? "bg-white/10 text-white" : "text-white/30 hover:text-white/60"}`, children: [
6624
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "account_tree" }),
6443
6625
  "Hierarchie"
6444
6626
  ] }),
6445
- workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => setActiveTab("tags"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "tags" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "label" }) })
6627
+ workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => setActiveTab("tags"), className: `flex-1 flex items-center justify-center gap-1.5 text-[11px] font-bold uppercase tracking-wide transition-colors ${activeTab === "tags" ? "text-white border-b-2 border-white" : "text-white/30"}`, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "label" }) })
6446
6628
  ] }),
6447
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => setIsLeftCollapsed(!isLeftCollapsed), className: "material-symbols-outlined text-[18px] text-white/40 hover:text-white transition-all w-10 flex items-center justify-center", children: isLeftCollapsed ? "chevron_right" : "chevron_left" })
6629
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => setIsLeftCollapsed(!isLeftCollapsed), className: "material-symbols-outlined text-[18px] text-white/40 hover:text-white transition-all w-10 flex items-center justify-center", children: isLeftCollapsed ? "chevron_right" : "chevron_left" })
6448
6630
  ] }),
6449
- !isLeftCollapsed && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex-1 overflow-hidden relative", children: [
6450
- activeTab === "tags" && workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6631
+ !isLeftCollapsed && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 overflow-hidden relative", children: [
6632
+ activeTab === "tags" && workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6451
6633
  TagManagerPanel,
6452
6634
  {
6453
6635
  workspaceTags,
@@ -6458,11 +6640,11 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6458
6640
  onTagMove: handleTagMove
6459
6641
  }
6460
6642
  ),
6461
- activeTab === "tags" && !workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex items-center justify-center h-full p-8 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { children: [
6462
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[40px] text-white/10 block mb-3", children: "label_off" }),
6463
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[11px] text-white/20", children: "Erst Workspace importieren um Tags zu verwalten." })
6643
+ activeTab === "tags" && !workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex items-center justify-center h-full p-8 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { children: [
6644
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[40px] text-white/10 block mb-3", children: "label_off" }),
6645
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-[11px] text-white/20", children: "Erst Workspace importieren um Tags zu verwalten." })
6464
6646
  ] }) }),
6465
- leftTab === "hierarchy" && activeTab !== "tags" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "absolute inset-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6647
+ leftTab === "hierarchy" && activeTab !== "tags" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute inset-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6466
6648
  ListView,
6467
6649
  {
6468
6650
  nodes,
@@ -6487,18 +6669,19 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6487
6669
  isGeneratingNodeId: (id) => isSynthesizing && focusedNodeId === id
6488
6670
  }
6489
6671
  ) }),
6490
- leftTab === "prompt" && workspaceTags && activeTab !== "tags" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PromptTab, { workspaceTags, onGenerate: handlePromptTabGenerate, isGenerating: isPromptTabGenerating, feedback: promptFeedback, promptResult: activePrompt || null, lastPayload: lastPromptPayload, onGenerateImage: (prompt) => handleGenerateImage(prompt), onTagCreate: handleTagCreate, onTagUpdate: handleTagUpdate, onTagDelete: handleTagDelete, onScanImage: handleScanImage, isScanning: isScanningImage })
6672
+ leftTab === "prompt" && workspaceTags && activeTab !== "tags" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PromptTab, { workspaceTags, onGenerate: handlePromptTabGenerate, isGenerating: isPromptTabGenerating, feedback: promptFeedback, promptResult: activePrompt || null, lastPayload: lastPromptPayload, onGenerateImage: (prompt) => handleGenerateBatch(prompt), onTagCreate: handleTagCreate, onTagUpdate: handleTagUpdate, onTagDelete: handleTagDelete, onScanImage: handleScanImage, isScanning: isScanningImage })
6491
6673
  ] })
6492
6674
  ] }),
6493
- !isLeftCollapsed && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { onMouseDown: startLeftResize, className: "w-1 shrink-0 cursor-col-resize hover:bg-white/20 active:bg-white/30 transition-colors", style: { background: "transparent" } }),
6494
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex-1 flex flex-col bg-[#0b0b0b] overflow-hidden", children: [
6495
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "h-14 border-b border-white/5 flex items-center px-4 gap-2 justify-between shrink-0 bg-black/20", children: [
6496
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-1.5", children: [
6497
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CompactDropdown, { value: aspectRatio, onChange: setAspectRatio, options: [{ label: "1:1", value: "1:1" }, { label: "16:9", value: "16:9" }, { label: "9:16", value: "9:16" }] }),
6498
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] })
6675
+ !isLeftCollapsed && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { onMouseDown: startLeftResize, className: "w-1 shrink-0 cursor-col-resize hover:bg-white/20 active:bg-white/30 transition-colors", style: { background: "transparent" } }),
6676
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 flex flex-col bg-[#0b0b0b] overflow-hidden", children: [
6677
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "h-14 border-b border-white/5 flex items-center px-4 gap-2 justify-between shrink-0 bg-black/20", children: [
6678
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-1.5", children: [
6679
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CompactDropdown, { value: aspectRatio, onChange: setAspectRatio, options: [{ label: "1:1", value: "1:1" }, { label: "16:9", value: "16:9" }, { label: "9:16", value: "9:16" }] }),
6680
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] }),
6681
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions })
6499
6682
  ] }),
6500
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-1 mx-auto", children: [
6501
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6683
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-1 mx-auto", children: [
6684
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6502
6685
  "button",
6503
6686
  {
6504
6687
  onClick: () => setMiddlePanel("stage"),
@@ -6506,7 +6689,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6506
6689
  children: "Stage"
6507
6690
  }
6508
6691
  ),
6509
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6692
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6510
6693
  "button",
6511
6694
  {
6512
6695
  onClick: () => setMiddlePanel("labs"),
@@ -6515,57 +6698,52 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6515
6698
  }
6516
6699
  )
6517
6700
  ] }),
6518
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2", children: [
6519
- activeReferenceThumbnail ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-1 rounded-lg border border-white/20 bg-white/5 overflow-hidden", style: { height: 28 }, children: [
6520
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src: activeReferenceThumbnail, className: "h-full aspect-square object-cover" }),
6521
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[10px] text-white/60 font-bold uppercase tracking-wide px-1", children: "Ref" }),
6522
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: clearReference, className: "w-6 h-full flex items-center justify-center text-white/30 hover:text-white/80 transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "close" }) })
6523
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { onClick: handleSelectReference, className: "flex items-center gap-1 h-7 px-2 rounded-lg border border-white/10 text-white/30 hover:text-white/60 hover:border-white/20 transition-colors text-[10px] font-bold uppercase tracking-wide", children: [
6524
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "add_photo_alternate" }),
6525
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Ref" })
6701
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-2", children: [
6702
+ activeReferenceThumbnail ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-1 rounded-lg border border-white/20 bg-white/5 overflow-hidden", style: { height: 28 }, children: [
6703
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("img", { src: activeReferenceThumbnail, className: "h-full aspect-square object-cover" }),
6704
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[10px] text-white/60 font-bold uppercase tracking-wide px-1", children: "Ref" }),
6705
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: clearReference, className: "w-6 h-full flex items-center justify-center text-white/30 hover:text-white/80 transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "close" }) })
6706
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("button", { onClick: handleSelectReference, className: "flex items-center gap-1 h-7 px-2 rounded-lg border border-white/10 text-white/30 hover:text-white/60 hover:border-white/20 transition-colors text-[10px] font-bold uppercase tracking-wide", children: [
6707
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "add_photo_alternate" }),
6708
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Ref" })
6526
6709
  ] }),
6527
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => setIsPromptCollapsed(!isPromptCollapsed), className: "text-white/40 hover:text-white transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", children: isPromptCollapsed ? "expand_more" : "expand_less" }) }),
6528
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PillButton, { variant: "solid", icon: "bolt", loading: isGenerating, disabled: !activePrompt.trim(), onClick: () => handleGenerateImage(), children: "Generieren" })
6710
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => setIsPromptCollapsed(!isPromptCollapsed), className: "text-white/40 hover:text-white transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", children: isPromptCollapsed ? "expand_more" : "expand_less" }) }),
6711
+ runningBadge,
6712
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PillButton, { variant: "solid", icon: "bolt", disabled: !activePrompt.trim(), onClick: () => handleGenerateBatch(), children: "Generieren" })
6529
6713
  ] })
6530
6714
  ] }),
6531
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex-1 flex flex-col overflow-hidden relative", children: [
6532
- !isPromptCollapsed && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "px-6 py-4 border-b border-white/5 bg-black/10 overflow-hidden shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `relative min-h-[60px] p-4 rounded-2xl border transition-all ${isSynthesizing ? "prompt-loading" : "bg-white/5 border-white/10"}`, children: [
6533
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("textarea", { value: activePrompt, onChange: (e) => setActivePrompt(e.target.value), className: "w-full bg-transparent border-none outline-none text-[12px] leading-relaxed text-white/80 resize-none h-20 dark-scrollbar", placeholder: "W\xE4hle einen Knoten oder tippe einen Prompt..." }),
6534
- activePrompt && !isSynthesizing && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => setActivePrompt(""), className: "absolute top-2 right-2 w-6 h-6 rounded-full bg-white/5 hover:bg-white/10 flex items-center justify-center transition-colors text-white/20 hover:text-white", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "close" }) })
6715
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 flex flex-col overflow-hidden relative", children: [
6716
+ !isPromptCollapsed && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "px-6 py-4 border-b border-white/5 bg-black/10 overflow-hidden shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: `relative min-h-[60px] p-4 rounded-2xl border transition-all ${isSynthesizing ? "prompt-loading" : "bg-white/5 border-white/10"}`, children: [
6717
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("textarea", { value: activePrompt, onChange: (e) => setActivePrompt(e.target.value), className: "w-full bg-transparent border-none outline-none text-[12px] leading-relaxed text-white/80 resize-none h-20 dark-scrollbar", placeholder: "W\xE4hle einen Knoten oder tippe einen Prompt..." }),
6718
+ activePrompt && !isSynthesizing && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => setActivePrompt(""), className: "absolute top-2 right-2 w-6 h-6 rounded-full bg-white/5 hover:bg-white/10 flex items-center justify-center transition-colors text-white/20 hover:text-white", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "close" }) })
6535
6719
  ] }) }),
6536
- middlePanel === "labs" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(LabsTab, { services: labServices, onResult: (item) => {
6720
+ middlePanel === "labs" ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LabsTab, { services: labServices, onResult: (item) => {
6537
6721
  const frame = item.frames[0];
6538
6722
  if (frame?.base64) setCurrentResult(frameToGeneration(frame, item));
6539
- } }) }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex-1 overflow-hidden flex flex-col", children: [
6540
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 p-6 overflow-hidden flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "h-full w-full max-w-4xl aspect-square rounded-3xl border border-white/5 bg-black/40 relative overflow-hidden flex items-center justify-center group shadow-2xl", children: [
6541
- isGenerating && currentResult?.status === "done" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "absolute top-6 right-6 z-30 bg-black/60 backdrop-blur-md px-4 py-2 rounded-full border border-white/10 flex items-center gap-3", children: [
6542
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-3 h-3 border-t-2 border-white rounded-full animate-spin" }),
6543
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[10px] text-white/60 uppercase font-bold tracking-widest", children: "Neue Referenz..." })
6723
+ } }) }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 overflow-hidden flex flex-col", children: [
6724
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex-1 p-6 overflow-hidden flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "h-full w-full max-w-4xl aspect-square rounded-3xl border border-white/5 bg-black/40 relative overflow-hidden flex items-center justify-center group shadow-2xl", children: currentResult ? currentResult.status === "processing" ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col items-center gap-4 opacity-40", children: [
6725
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[40px]", children: "hourglass_top" }),
6726
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[10px] uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
6727
+ ] }) : currentResult.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "p-10 text-center flex flex-col items-center gap-5 max-w-md", children: [
6728
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "w-16 h-16 rounded-full bg-red-500/10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-red-500 text-[32px]", children: "warning" }) }),
6729
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col gap-2", children: [
6730
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h3", { className: "text-[11px] font-bold uppercase tracking-widest text-red-400", children: "Generierungsfehler" }),
6731
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-white/60 text-[12px] leading-relaxed", children: currentResult.error?.message })
6544
6732
  ] }),
6545
- currentResult ? currentResult.status === "processing" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center gap-4", children: [
6546
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-10 h-10 border-t-2 border-white rounded-full animate-spin" }),
6547
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[10px] text-white/40 uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
6548
- ] }) : currentResult.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "p-10 text-center flex flex-col items-center gap-5 max-w-md", children: [
6549
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-16 h-16 rounded-full bg-red-500/10 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-red-500 text-[32px]", children: "warning" }) }),
6550
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col gap-2", children: [
6551
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { className: "text-[11px] font-bold uppercase tracking-widest text-red-400", children: "Generierungsfehler" }),
6552
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-white/60 text-[12px] leading-relaxed", children: currentResult.error?.message })
6553
- ] }),
6554
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PillButton, { variant: "outline", icon: "refresh", onClick: () => handleGenerateImage(currentResult.prompt), children: "Erneut versuchen" })
6555
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "h-full w-full relative flex items-center justify-center", children: [
6556
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src: currentResult.fullBase64 || currentResult.base64, className: "max-h-full max-w-full object-contain rounded-xl shadow-2xl" }),
6557
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "absolute bottom-6 flex gap-2 opacity-0 group-hover:opacity-100 transition-all translate-y-4 group-hover:translate-y-0 z-20", children: [
6558
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PillButton, { variant: "outline", icon: "replay", onClick: () => setActivePrompt(currentResult.prompt || ""), children: "Prompt" }),
6559
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PillButton, { variant: "solid", icon: "auto_fix_high", onClick: () => handleGenerateImage(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), children: "Referenz" }),
6560
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PillButton, { variant: "outline", icon: "download", onClick: handleDownloadSingle, children: "Speichern" })
6561
- ] })
6562
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center gap-2 opacity-10", children: [
6563
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[100px]", children: "palette" }),
6564
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[12px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
6733
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PillButton, { variant: "outline", icon: "refresh", onClick: () => handleGenerateImage(currentResult.prompt), children: "Erneut versuchen" })
6734
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "h-full w-full relative flex items-center justify-center", children: [
6735
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("img", { src: currentResult.fullBase64 || currentResult.base64, className: "max-h-full max-w-full object-contain rounded-xl shadow-2xl" }),
6736
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "absolute bottom-6 flex gap-2 opacity-0 group-hover:opacity-100 transition-all translate-y-4 group-hover:translate-y-0 z-20", children: [
6737
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PillButton, { variant: "outline", icon: "replay", onClick: () => setActivePrompt(currentResult.prompt || ""), children: "Prompt" }),
6738
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PillButton, { variant: "solid", icon: "auto_fix_high", onClick: () => handleGenerateBatch(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), children: "Referenz" }),
6739
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PillButton, { variant: "outline", icon: "download", onClick: handleDownloadSingle, children: "Speichern" })
6565
6740
  ] })
6566
- ] }) }),
6567
- currentResult?.status === "done" && currentGroup.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "px-6 pb-4 shrink-0 flex gap-2 overflow-x-auto", style: { scrollbarWidth: "none" }, children: currentGroup.map((item) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { position: "relative", flexShrink: 0 }, children: [
6568
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6741
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col items-center gap-2 opacity-10", children: [
6742
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[100px]", children: "palette" }),
6743
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[12px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
6744
+ ] }) }) }),
6745
+ currentResult?.status === "done" && currentGroup.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "px-6 pb-4 shrink-0 flex gap-2 overflow-x-auto", style: { scrollbarWidth: "none" }, children: currentGroup.map((item) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { position: "relative", flexShrink: 0 }, children: [
6746
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6569
6747
  "div",
6570
6748
  {
6571
6749
  onClick: () => handleGallerySelect(item),
@@ -6580,10 +6758,10 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6580
6758
  transition: "opacity 0.15s, border-color 0.15s"
6581
6759
  },
6582
6760
  className: "hover:opacity-80",
6583
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("img", { src: item.base64, style: { width: "100%", height: "100%", objectFit: "cover" }, alt: "" })
6761
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("img", { src: item.base64, style: { width: "100%", height: "100%", objectFit: "cover" }, alt: "" })
6584
6762
  }
6585
6763
  ),
6586
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6764
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6587
6765
  "button",
6588
6766
  {
6589
6767
  onClick: (e) => {
@@ -6606,31 +6784,31 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6606
6784
  alignItems: "center",
6607
6785
  justifyContent: "center"
6608
6786
  },
6609
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 10, color: item.titleTs ? "#fff" : "rgba(255,255,255,0.5)", lineHeight: 1 }, children: "star" })
6787
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 10, color: item.titleTs ? "#fff" : "rgba(255,255,255,0.5)", lineHeight: 1 }, children: "star" })
6610
6788
  }
6611
6789
  )
6612
6790
  ] }, item.id)) })
6613
6791
  ] })
6614
6792
  ] })
6615
6793
  ] }),
6616
- !isRightCollapsed && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { onMouseDown: startRightResize, className: "w-1 shrink-0 cursor-col-resize hover:bg-white/20 active:bg-white/30 transition-colors", style: { background: "transparent" } }),
6617
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col border-l border-white/5 bg-[#0e0e0e] shrink-0", style: { width: isRightCollapsed ? 60 : rightPanelWidth, transition: "none" }, children: [
6618
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex border-b border-white/5 h-14 shrink-0 overflow-hidden", children: [
6619
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-1", children: [
6620
- ["history", "gallery", "inspect", "setup", "sync", "tags"].map((tab) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => {
6794
+ !isRightCollapsed && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { onMouseDown: startRightResize, className: "w-1 shrink-0 cursor-col-resize hover:bg-white/20 active:bg-white/30 transition-colors", style: { background: "transparent" } }),
6795
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col border-l border-white/5 bg-[#0e0e0e] shrink-0", style: { width: isRightCollapsed ? 60 : rightPanelWidth, transition: "none" }, children: [
6796
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex border-b border-white/5 h-14 shrink-0 overflow-hidden", children: [
6797
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-1", children: [
6798
+ ["history", "gallery", "inspect", "setup", "sync", "tags"].map((tab) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => {
6621
6799
  setActiveTab(tab);
6622
6800
  setIsRightCollapsed(false);
6623
- }, className: `flex-1 flex items-center justify-center relative transition-colors ${activeTab === tab ? "text-white" : "text-white/20"}`, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: tab === "history" ? "history" : tab === "gallery" ? "photo_library" : tab === "inspect" ? "info" : tab === "setup" ? "settings" : tab === "sync" ? "cloud_sync" : "label" }) }, tab)),
6624
- serverBaseUrl && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => {
6801
+ }, className: `flex-1 flex items-center justify-center relative transition-colors ${activeTab === tab ? "text-white" : "text-white/20"}`, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: tab === "history" ? "history" : tab === "gallery" ? "photo_library" : tab === "inspect" ? "info" : tab === "setup" ? "settings" : tab === "sync" ? "cloud_sync" : "label" }) }, tab)),
6802
+ serverBaseUrl && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => {
6625
6803
  setActiveTab("server");
6626
6804
  setIsRightCollapsed(false);
6627
- }, className: `w-10 flex items-center justify-center relative transition-colors ${activeTab === "server" ? "text-white" : "text-white/20"}`, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "storage" }) })
6805
+ }, className: `w-10 flex items-center justify-center relative transition-colors ${activeTab === "server" ? "text-white" : "text-white/20"}`, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[20px]", children: "storage" }) })
6628
6806
  ] }),
6629
- hfToken && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => refreshHF(), disabled: isHfRefreshing, className: "w-10 flex items-center justify-center text-white/20 hover:text-white/60 transition-colors disabled:opacity-30", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: `material-symbols-outlined text-[18px]${isHfRefreshing ? " animate-spin" : ""}`, children: "sync" }) }),
6630
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { onClick: () => setIsRightCollapsed(!isRightCollapsed), className: "w-10 flex items-center justify-center text-white/20 hover:text-white", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[18px]", children: isRightCollapsed ? "chevron_left" : "chevron_right" }) })
6807
+ hfToken && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => refreshHF(), disabled: isHfRefreshing, className: "w-10 flex items-center justify-center text-white/20 hover:text-white/60 transition-colors disabled:opacity-30", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: `material-symbols-outlined text-[18px]${isHfRefreshing ? " animate-spin" : ""}`, children: "sync" }) }),
6808
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { onClick: () => setIsRightCollapsed(!isRightCollapsed), className: "w-10 flex items-center justify-center text-white/20 hover:text-white", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[18px]", children: isRightCollapsed ? "chevron_left" : "chevron_right" }) })
6631
6809
  ] }),
6632
- !isRightCollapsed && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex-1 overflow-hidden relative", children: [
6633
- activeTab === "tags" && workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6810
+ !isRightCollapsed && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex-1 overflow-hidden relative", children: [
6811
+ activeTab === "tags" && workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6634
6812
  TagManagerPanel,
6635
6813
  {
6636
6814
  workspaceTags,
@@ -6641,12 +6819,12 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6641
6819
  onTagMove: handleTagMove
6642
6820
  }
6643
6821
  ),
6644
- activeTab === "tags" && !workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex items-center justify-center h-full p-8 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { children: [
6645
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "material-symbols-outlined text-[40px] text-white/10 block mb-3", children: "label_off" }),
6646
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[11px] text-white/20", children: "Erst Workspace importieren um Tags zu verwalten." })
6822
+ activeTab === "tags" && !workspaceTags && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex items-center justify-center h-full p-8 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { children: [
6823
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "material-symbols-outlined text-[40px] text-white/10 block mb-3", children: "label_off" }),
6824
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-[11px] text-white/20", children: "Erst Workspace importieren um Tags zu verwalten." })
6647
6825
  ] }) }),
6648
- activeTab === "history" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)) }),
6649
- activeTab === "gallery" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6826
+ activeTab === "history" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }),
6827
+ activeTab === "gallery" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6650
6828
  MediaLibrary,
6651
6829
  {
6652
6830
  items: galleryItems,
@@ -6657,12 +6835,14 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6657
6835
  },
6658
6836
  onDelete: (id) => setGalleryItems((g) => g.filter((x) => x.id !== id)),
6659
6837
  onSelect: handleGallerySelect,
6660
- onGenerateReference: (item) => handleGenerateImage(item.prompt || activePrompt, item.mediaId, void 0, { silent: true })
6838
+ onGenerateReference: (item) => handleGenerateBatch(item.prompt || activePrompt, item.mediaId, void 0, { silent: true }),
6839
+ visibleCount: galleryVisibleCount,
6840
+ onLoadMore: () => setGalleryVisibleCount((c) => c + 20)
6661
6841
  }
6662
6842
  ),
6663
- activeTab === "inspect" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(InspectPanel, { currentResult, history, onSelect: setCurrentResult }),
6664
- activeTab === "setup" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SetupPanel, { onWorkspaceImport: handleWorkspaceImport, buildInfo }),
6665
- activeTab === "sync" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6843
+ activeTab === "inspect" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(InspectPanel, { currentResult, history, onSelect: setCurrentResult }),
6844
+ activeTab === "setup" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SetupPanel, { onWorkspaceImport: handleWorkspaceImport, buildInfo }),
6845
+ activeTab === "sync" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6666
6846
  ProjectSyncTab,
6667
6847
  {
6668
6848
  topSlot: syncTopSlot,
@@ -6686,15 +6866,15 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6686
6866
  onHfInitialSync: hfToken ? handleHfInitialSync : void 0
6687
6867
  }
6688
6868
  ),
6689
- activeTab === "server" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ServerTab, { serverBaseUrl })
6869
+ activeTab === "server" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ServerTab, { serverBaseUrl })
6690
6870
  ] })
6691
6871
  ] })
6692
6872
  ] });
6693
6873
  }
6694
6874
 
6695
6875
  // src/components/FaApp.tsx
6696
- var import_react28 = require("react");
6697
- var import_jsx_runtime24 = require("react/jsx-runtime");
6876
+ var import_react27 = require("react");
6877
+ var import_jsx_runtime25 = require("react/jsx-runtime");
6698
6878
  function FaApp({
6699
6879
  onGenerateImage,
6700
6880
  onGeneratePrompt,
@@ -6713,8 +6893,8 @@ function FaApp({
6713
6893
  onServerDelete,
6714
6894
  buildInfo
6715
6895
  }) {
6716
- const [hfNamespace, setHfNamespace] = (0, import_react28.useState)(void 0);
6717
- (0, import_react28.useEffect)(() => {
6896
+ const [hfNamespace, setHfNamespace] = (0, import_react27.useState)(void 0);
6897
+ (0, import_react27.useEffect)(() => {
6718
6898
  if (!serverBaseUrl) return;
6719
6899
  fetch(`${serverBaseUrl}/api/status`).then((r) => r.json()).then((d) => {
6720
6900
  if (typeof d.hfNamespace === "string") setHfNamespace(d.hfNamespace);
@@ -6725,7 +6905,7 @@ function FaApp({
6725
6905
  const result = await onGeneratePrompt(text, options);
6726
6906
  return result.text;
6727
6907
  };
6728
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6908
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6729
6909
  AvatarArchitectApp,
6730
6910
  {
6731
6911
  onGenerateImage,
@@ -6748,7 +6928,7 @@ function FaApp({
6748
6928
  // src/index.ts
6749
6929
  init_hfStateService();
6750
6930
  init_hfStateService();
6751
- var LIB_VERSION = "2.0.57";
6931
+ var LIB_VERSION = "2.0.62";
6752
6932
  // Annotate the CommonJS export names for ESM import in node:
6753
6933
  0 && (module.exports = {
6754
6934
  AvatarArchitectApp,