PageSourceSearch

https://www.hamienet.com/assets/SouthparkActionsStudio-DE8P5dhV.js

js hamienet.com collected 2026-09-24 19:00:52 UTC 75,521 bytes, 1,303 lines download raw bytes

1import { r as reactExports, j as jsxRuntimeExports } from "./vendor-react-Bay9Y7Lb.js";
2import { P as PERCUSSION_INSTRUMENTS, g as getInstrumentDef, a as PROGRAM_SPECIFIC_ACTIONS, D as DEFAULT_HOLD_STYLE_ACTIONS, b as DEFAULT_IDLE_ACTIONS, S as SouthparkCharacter, B as BASE_ANIMALS } from "./SouthparkCharacter-BNwA9Wd0.js";
3import { I as INSTRUMENT_CATEGORIES, k as GM_INSTRUMENTS } from "./utils-BYCVoSTN.js";
4import { df as SlidersVertical, bg as Music, bL as Clock, cL as RefreshCw, cc as Save, bf as Search, c3 as RotateCcw, bi as Sparkles, ce as Plus, b5 as Trash2, bZ as Pause, bU as Play } from "./vendor-dVNaLJx_.js";
5import "./IkMath-D6fi1ppd.js";
6import "./vendor-framer-C8eEgkdL.js";
7import "./index-D0Bmh-UX.js";
8import "./vendor-i18n-R-bMoYp_.js";
9const TARGET_OPTIONS = [
10  { id: "targetL", label: "Left Arm (Target X/Y)", group: "Limbs" },
11  { id: "targetR", label: "Right Arm (Target X/Y)", group: "Limbs" },
12  { id: "wristTiltL", label: "Left Wrist Tilt (Deg)", group: "Limbs" },
13  { id: "wristTiltR", label: "Right Wrist Tilt (Deg)", group: "Limbs" },
14  { id: "bodyBounce", label: "Body Vertical Bounce (Y)", group: "Torso" },
15  { id: "bodySquash", label: "Body Squash/Stretch", group: "Torso" },
16  { id: "bodySwayX", label: "Body Lateral Sway (X)", group: "Torso" },
17  { id: "headTilt", label: "Head Rotation Tilt (Deg)", group: "Head & Mouth" },
18  { id: "headBobY", label: "Head Bob (Y)", group: "Head & Mouth" },
19  { id: "mouthOpen", label: "Mouth Open / Blow (0-1)", group: "Head & Mouth" },
20  { id: "instrumentRotation", label: "Instrument Tilt (Deg)", group: "Instrument" }
21];
22const SouthparkActionsStudio = ({
23  actionsConfig,
24  onChangeActionsConfig,
25  instrumentsConfig,
26  charactersConfig,
27  costumesConfig,
28  onSave,
29  isSaving
30}) => {
31  const [studioMode, setStudioMode] = reactExports.useState("playing");
32  const [selectedProgram, setSelectedProgram] = reactExports.useState(0);
33  const [searchQuery, setSearchQuery] = reactExports.useState("");
34  const [selectedCategory, setSelectedCategory] = reactExports.useState("all");
35  const [editScope, setEditScope] = reactExports.useState("holdStyle");
36  const [previewAnimal, setPreviewAnimal] = reactExports.useState("fox");
37  const [isSimulating, setIsSimulating] = reactExports.useState(true);
38  const [simVelocity, setSimVelocity] = reactExports.useState(100);
39  const [simPitch, setSimPitch] = reactExports.useState(60);
40  const [simBpm, setSimBpm] = reactExports.useState(120);
41  const [notePulsing, setNotePulsing] = reactExports.useState(true);
42  const [isNoteActive, setIsNoteActive] = reactExports.useState(true);
43  const [showSkeleton, setShowSkeleton] = reactExports.useState(false);
44  const [skeletonOnly, setSkeletonOnly] = reactExports.useState(false);
45  const [simTime, setSimTime] = reactExports.useState(0);
46  const [activeTestingIdleId, setActiveTestingIdleId] = reactExports.useState(null);
47  const percKits = reactExports.useMemo(() => {
48    return Object.entries(PERCUSSION_INSTRUMENTS).map(([key, def]) => ({
49      id: def.program,
50      name: `${def.name} (${key})`,
51      percRole: key,
52      isPercussion: true
53    }));
54  }, []);
55  const allInstruments = reactExports.useMemo(() => {
56    const gm = GM_INSTRUMENTS.map((name, idx) => ({
57      id: idx,
58      name: `${idx}: ${name}`,
59      percRole: void 0,
60      isPercussion: false
61    }));
62    return [...gm, ...percKits];
63  }, [percKits]);
64  const filteredInstruments = reactExports.useMemo(() => {
65    return allInstruments.filter((inst) => {
66      const matchesSearch = inst.name.toLowerCase().includes(searchQuery.toLowerCase()) || inst.id.toString().includes(searchQuery);
67      if (!matchesSearch) return false;
68      if (selectedCategory === "all") return true;
69      if (selectedCategory === "percussion") return inst.isPercussion;
70      if (inst.isPercussion) return false;
71      const cat = INSTRUMENT_CATEGORIES.find((c) => inst.id >= c.start && inst.id <= c.end);
72      return cat ? cat.name.toLowerCase().includes(selectedCategory.toLowerCase()) : false;
73    });
74  }, [allInstruments, searchQuery, selectedCategory]);
75  const selectedInstDef = reactExports.useMemo(() => {
76    return getInstrumentDef(selectedProgram, selectedProgram < 0);
77  }, [selectedProgram]);
78  const holdStyle = selectedInstDef.holdStyle || "standard";
79  const currentActions = reactExports.useMemo(() => {
80    var _a, _b;
81    if (editScope === "program") {
82      if ((_a = actionsConfig.programActions) == null ? void 0 : _a[selectedProgram]) {
83        return actionsConfig.programActions[selectedProgram];
84      }
85      if (PROGRAM_SPECIFIC_ACTIONS[selectedProgram]) {
86        return PROGRAM_SPECIFIC_ACTIONS[selectedProgram];
87      }
88    }
89    return ((_b = actionsConfig.holdStyleActions) == null ? void 0 : _b[holdStyle]) || DEFAULT_HOLD_STYLE_ACTIONS[holdStyle] || DEFAULT_HOLD_STYLE_ACTIONS.standard;
90  }, [editScope, selectedProgram, holdStyle, actionsConfig]);
91  const idleActionsList = reactExports.useMemo(() => {
92    return actionsConfig.idleActions || DEFAULT_IDLE_ACTIONS;
93  }, [actionsConfig.idleActions]);
94  reactExports.useEffect(() => {
95    if (!isSimulating) return;
96    let animationFrameId;
97    let lastTimestamp = performance.now();
98    const tick = (now) => {
99      const deltaSec = (now - lastTimestamp) / 1e3;
100      lastTimestamp = now;
101      setSimTime((prev) => prev + deltaSec);
102      if (notePulsing) {
103        const bps = simBpm / 60;
104        const beatPhase = (simTime + deltaSec) * bps * Math.PI * 2;
105        const stroke = Math.sin(beatPhase);
106        setIsNoteActive(stroke > -0.2);
107      }
108      animationFrameId = requestAnimationFrame(tick);
109    };
110    animationFrameId = requestAnimationFrame(tick);
111    return () => cancelAnimationFrame(animationFrameId);
112  }, [isSimulating, simTime, notePulsing, simBpm]);
113  const handleUpdateChannel = (actionIndex, channelIndex, updatedChannel) => {
114    const clonedActions = JSON.parse(JSON.stringify(currentActions));
115    if (!clonedActions[actionIndex]) return;
116    clonedActions[actionIndex].channels[channelIndex] = updatedChannel;
117    if (editScope === "program") {
118      onChangeActionsConfig({
119        ...actionsConfig,
120        programActions: {
121          ...actionsConfig.programActions || {},
122          [selectedProgram]: clonedActions
123        }
124      });
125    } else {
126      onChangeActionsConfig({
127        ...actionsConfig,
128        holdStyleActions: {
129          ...actionsConfig.holdStyleActions || {},
130          [holdStyle]: clonedActions
131        }
132      });
133    }
134  };
135  const handleAddChannel = (actionIndex) => {
136    const clonedActions = JSON.parse(JSON.stringify(currentActions));
137    if (!clonedActions[actionIndex]) return;
138    clonedActions[actionIndex].channels.push({
139      target: "targetR",
140      driver: "wave",
141      wave: {
142        waveform: "sine",
143        frequency: 2,
144        amplitude: 5,
145        amplitudeBase: 0,
146        phase: 0,
147        axis: "y",
148        activeOnly: true
149      }
150    });
151    if (editScope === "program") {
152      onChangeActionsConfig({
153        ...actionsConfig,
154        programActions: {
155          ...actionsConfig.programActions || {},
156          [selectedProgram]: clonedActions
157        }
158      });
159    } else {
160      onChangeActionsConfig({
161        ...actionsConfig,
162        holdStyleActions: {
163          ...actionsConfig.holdStyleActions || {},
164          [holdStyle]: clonedActions
165        }
166      });
167    }
168  };
169  const handleRemoveChannel = (actionIndex, channelIndex) => {
170    const clonedActions = JSON.parse(JSON.stringify(currentActions));
171    if (!clonedActions[actionIndex]) return;
172    clonedActions[actionIndex].channels.splice(channelIndex, 1);
173    if (editScope === "program") {
174      onChangeActionsConfig({
175        ...actionsConfig,
176        programActions: {
177          ...actionsConfig.programActions || {},
178          [selectedProgram]: clonedActions
179        }
180      });
181    } else {
182      onChangeActionsConfig({
183        ...actionsConfig,
184        holdStyleActions: {
185          ...actionsConfig.holdStyleActions || {},
186          [holdStyle]: clonedActions
187        }
188      });
189    }
190  };
191  const handleResetActionToDefault = () => {
192    if (editScope === "program") {
193      const next = { ...actionsConfig.programActions || {} };
194      delete next[selectedProgram];
195      onChangeActionsConfig({
196        ...actionsConfig,
197        programActions: next
198      });
199    } else {
200      const next = { ...actionsConfig.holdStyleActions || {} };
201      delete next[holdStyle];
202      onChangeActionsConfig({
203        ...actionsConfig,
204        holdStyleActions: next
205      });
206    }
207  };
208  const handleUpdateIdleSchedule = (idleId, field, val) => {
209    const nextList = idleActionsList.map((item) => {
210      if (item.id === idleId) {
211        return {
212          ...item,
213          idleSchedule: {
214            ...item.idleSchedule || { minIntervalMs: 1e4, maxIntervalMs: 3e4, durationMs: 2e3, blendInMs: 400, blendOutMs: 400 },
215            [field]: val
216          }
217        };
218      }
219      return item;
220    });
221    onChangeActionsConfig({
222      ...actionsConfig,
223      idleActions: nextList
224    });
225  };
226  const handleTestIdleAction = (idleId) => {
227    setActiveTestingIdleId(idleId);
228    setIsNoteActive(false);
229    setNotePulsing(false);
230    setTimeout(() => {
231      setActiveTestingIdleId(null);
232    }, 3500);
233  };
234  const handleResetAllIdleDefaults = () => {
235    onChangeActionsConfig({
236      ...actionsConfig,
237      idleActions: DEFAULT_IDLE_ACTIONS
238    });
239  };
240  const activeAnimalDef = BASE_ANIMALS[previewAnimal] || BASE_ANIMALS.fox;
241  const charConfig = charactersConfig[previewAnimal];
242  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
243    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl p-5 shadow-xl flex flex-col md:flex-row md:items-center justify-between gap-4", children: [
244      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
245        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-2.5 rounded-xl bg-indigo-500/10 text-indigo-400 border border-indigo-500/20", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SlidersVertical, { size: 22 }) }),
246        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
247          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
248            /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-xl font-bold text-white tracking-wide", children: "Actions & Kinematics Studio" }),
249            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "px-2.5 py-0.5 rounded-full text-xs font-semibold bg-emerald-500/20 text-emerald-300 border border-emerald-500/30", children: "Data-Driven Engine" })
250          ] }),
251          /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-400 mt-1", children: "Customize unique limb movements, note-pitch responsiveness, mouth blowing, and orchestra idle behaviors." })
252        ] })
253      ] }) }),
254      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
255        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center bg-zinc-950 p-1 rounded-xl border border-zinc-800", children: [
256          /* @__PURE__ */ jsxRuntimeExports.jsxs(
257            "button",
258            {
259              onClick: () => setStudioMode("playing"),
260              className: `flex items-center gap-2 px-4 py-2 rounded-lg text-xs font-semibold transition-all ${studioMode === "playing" ? "bg-indigo-600 text-white shadow-lg" : "text-zinc-400 hover:text-white"}`,
261              children: [
262                /* @__PURE__ */ jsxRuntimeExports.jsx(Music, { size: 14 }),
263                "Instrument Playing Actions"
264              ]
265            }
266          ),
267          /* @__PURE__ */ jsxRuntimeExports.jsxs(
268            "button",
269            {
270              onClick: () => setStudioMode("idle"),
271              className: `flex items-center gap-2 px-4 py-2 rounded-lg text-xs font-semibold transition-all ${studioMode === "idle" ? "bg-indigo-600 text-white shadow-lg" : "text-zinc-400 hover:text-white"}`,
272              children: [
273                /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { size: 14 }),
274                "Idle & Spare Actions"
275              ]
276            }
277          )
278        ] }),
279        onSave && /* @__PURE__ */ jsxRuntimeExports.jsxs(
280          "button",
281          {
282            onClick: onSave,
283            disabled: isSaving,
284            className: "flex items-center gap-2 px-4 py-2 bg-emerald-600 hover:bg-emerald-500 disabled:opacity-50 text-white font-semibold rounded-xl text-xs shadow-lg transition-all",
285            children: [
286              isSaving ? /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Save, { size: 14 }),
287              "Save All Actions"
288            ]
289          }
290        )
291      ] })
292    ] }),
293    studioMode === "playing" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 xl:grid-cols-12 gap-6", children: [
294      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "xl:col-span-7 space-y-6", children: [
295        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl p-5 shadow-lg space-y-4", children: [
296          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
297            /* @__PURE__ */ jsxRuntimeExports.jsxs("h3", { className: "text-sm font-bold text-white uppercase tracking-wider flex items-center gap-2", children: [
298              /* @__PURE__ */ jsxRuntimeExports.jsx(Music, { size: 16, className: "text-indigo-400" }),
299              "Select Instrument to Configure"
300            ] }),
301            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
302              "button",
303              {
304                onClick: () => setEditScope(editScope === "holdStyle" ? "program" : "holdStyle"),
305                className: `text-xs px-3 py-1 rounded-lg border font-medium transition-all ${editScope === "program" ? "bg-amber-500/20 text-amber-300 border-amber-500/40" : "bg-zinc-800 text-zinc-400 border-zinc-700 hover:text-white"}`,
306                children: editScope === "program" ? "⚡ Program Override Active" : "Hold Style Default"
307              }
308            ) })
309          ] }),
310          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row gap-3", children: [
311            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative flex-1", children: [
312              /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { className: "absolute left-3 top-2.5 text-zinc-500", size: 16 }),
313              /* @__PURE__ */ jsxRuntimeExports.jsx(
314                "input",
315                {
316                  type: "text",
317                  placeholder: "Search GM instrument name or number...",
318                  value: searchQuery,
319                  onChange: (e) => setSearchQuery(e.target.value),
320                  className: "w-full pl-9 pr-3 py-2 bg-zinc-950 border border-zinc-800 rounded-xl text-xs text-white placeholder-zinc-500 outline-none focus:border-indigo-500"
321                }
322              )
323            ] }),
324            /* @__PURE__ */ jsxRuntimeExports.jsxs(
325              "select",
326              {
327                value: selectedCategory,
328                onChange: (e) => setSelectedCategory(e.target.value),
329                className: "bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-xs text-zinc-300 outline-none focus:border-indigo-500",
330                children: [
331                  /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "all", children: "All Categories" }),
332                  /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "piano", children: "Piano & Keys" }),
333                  /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "guitar", children: "Guitars" }),
334                  /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "bass", children: "Basses" }),
335                  /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "strings", children: "Strings / Orchestral" }),
336                  /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "brass", children: "Brass" }),
337                  /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "reed", children: "Woodwinds / Reeds" }),
338                  /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "pipe", children: "Flutes / Pipes" }),
339                  /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "synth", children: "Synths & FX" }),
340                  /* @__P
340URE__ */ jsxRuntimeExports.jsx("option", { value: "ethnic", children: "Ethnic & World" }),
341                  /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "percussion", children: "Percussion Kits" })
342                ]
343              }
344            )
345          ] }),
346          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-2 overflow-x-auto pb-2 scrollbar-thin scrollbar-thumb-zinc-800", children: filteredInstruments.slice(0, 30).map((inst) => {
347            var _a;
348            const isSelected = inst.id === selectedProgram;
349            const hasCustomProgram = !!((_a = actionsConfig.programActions) == null ? void 0 : _a[inst.id]);
350            return /* @__PURE__ */ jsxRuntimeExports.jsxs(
351              "button",
352              {
353                onClick: () => setSelectedProgram(inst.id),
354                className: `shrink-0 px-3 py-2 rounded-xl text-left border transition-all ${isSelected ? "bg-indigo-600/30 text-white border-indigo-500 shadow-md" : "bg-zinc-950/70 text-zinc-400 border-zinc-800 hover:border-zinc-700 hover:text-zinc-200"}`,
355                children: [
356                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5", children: [
357                    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-mono font-bold text-zinc-400", children: inst.id }),
358                    hasCustomProgram && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-amber-400 animate-pulse", title: "Custom Override" })
359                  ] }),
360                  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs font-semibold truncate max-w-[140px] mt-0.5", children: inst.name.split(":")[1] || inst.name })
361                ]
362              },
363              inst.id
364            );
365          }) }),
366          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-950 border border-zinc-800/80 rounded-xl p-3 flex items-center justify-between", children: [
367            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
368              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-10 h-10 rounded-lg bg-zinc-900 border border-zinc-800 flex items-center justify-center text-lg font-bold text-indigo-400", children: selectedProgram < 0 ? "🥁" : selectedProgram }),
369              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
370                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm font-bold text-white flex items-center gap-2", children: [
371                  selectedInstDef.name,
372                  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-2 py-0.5 rounded-md text-[10px] font-semibold bg-indigo-500/20 text-indigo-300 border border-indigo-500/30", children: [
373                    "Hold: ",
374                    holdStyle
375                  ] })
376                ] }),
377                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[11px] text-zinc-400", children: [
378                  "Editing Scope: ",
379                  /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "text-zinc-200", children: editScope === "program" ? `Specific to Program ${selectedProgram}` : `All '${holdStyle}' Instruments` })
380                ] })
381              ] })
382            ] }),
383            /* @__PURE__ */ jsxRuntimeExports.jsxs(
384              "button",
385              {
386                onClick: handleResetActionToDefault,
387                className: "flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs text-zinc-400 hover:text-white bg-zinc-900 hover:bg-zinc-800 border border-zinc-800 transition-all",
388                title: "Reset this action to factory built-in defaults",
389                children: [
390                  /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { size: 12 }),
391                  "Reset to Defaults"
392                ]
393              }
394            )
395          ] })
396        ] }),
397        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-4", children: currentActions.map((action, actionIdx) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl p-5 shadow-lg space-y-4", children: [
398          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between border-b border-zinc-800 pb-3", children: [
399            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
400              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
401                /* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { size: 16, className: "text-amber-400" }),
402                /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-sm font-bold text-white tracking-wide", children: action.name }),
403                /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] font-mono px-2 py-0.5 rounded bg-zinc-800 text-zinc-400", children: [
404                  action.channels.length,
405                  " channels"
406                ] })
407              ] }),
408              /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-400 mt-0.5", children: "Active when instrument plays notes (velocity > 0)" })
409            ] }),
410            /* @__PURE__ */ jsxRuntimeExports.jsxs(
411              "button",
412              {
413                onClick: () => handleAddChannel(actionIdx),
414                className: "flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-indigo-500/20 text-indigo-300 hover:bg-indigo-500/30 border border-indigo-500/40 text-xs font-semibold transition-all",
415                children: [
416                  /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { size: 14 }),
417                  "Add Movement Channel"
418                ]
419              }
420            )
421          ] }),
422          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-3", children: action.channels.map((channel, chIdx) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-950 border border-zinc-800 rounded-xl p-4 space-y-3", children: [
423            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 border-b border-zinc-900 pb-2.5", children: [
424              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
425                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-5 h-5 rounded-full bg-zinc-800 text-zinc-400 text-[11px] font-bold flex items-center justify-center", children: chIdx + 1 }),
426                /* @__PURE__ */ jsxRuntimeExports.jsx(
427                  "select",
428                  {
429                    value: channel.target,
430                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
431                      ...channel,
432                      target: e.target.value
433                    }),
434                    className: "bg-zinc-900 border border-zinc-700 text-xs font-bold text-white px-2.5 py-1 rounded-lg outline-none",
435                    children: TARGET_OPTIONS.map((opt) => /* @__PURE__ */ jsxRuntimeExports.jsxs("option", { value: opt.id, className: "bg-zinc-900 text-white", children: [
436                      opt.group,
437                      ": ",
438                      opt.label
439                    ] }, opt.id))
440                  }
441                ),
442                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-600 text-xs", children: "→" }),
443                /* @__PURE__ */ jsxRuntimeExports.jsxs(
444                  "select",
445                  {
446                    value: channel.driver,
447                    onChange: (e) => {
448                      const newDriver = e.target.value;
449                      let updated = { ...channel, driver: newDriver };
450                      if (newDriver === "wave" && !updated.wave) {
451                        updated.wave = { waveform: "sine", frequency: 2, amplitude: 5, axis: "y", activeOnly: true };
452                      } else if (newDriver === "density_pulse" && !updated.densityPulse) {
453                        updated.densityPulse = { waveform: "sine", baseFrequency: 2, densityFactor: 0.15, amplitude: 6, axis: "y" };
454                      } else if (newDriver === "velocity_envelope" && !updated.velocityEnvelope) {
455                        updated.velocityEnvelope = { factor: 3, axis: "y" };
456                      } else if (newDriver === "articulation_switch" && !updated.articulationSwitch) {
457                        updated.articulationSwitch = { staccatoValue: -4, legatoValue: 3, sustainedValue: 0, axis: "y" };
458                      } else if (newDriver === "phrase_accent" && !updated.phraseAccent) {
459                        updated.phraseAccent = { impulse: 5, axis: "y" };
460                      } else if (newDriver === "polyphony_spread" && !updated.polyphonySpread) {
461                        updated.polyphonySpread = { spreadPerNote: 2, maxSpread: 8, axis: "x" };
462                      } else if (newDriver === "climax_boost" && !updated.climaxBoost) {
463                        updated.climaxBoost = { multiplier: 1.5, axis: "y" };
464                      } else if (newDriver === "pitch_map" && !updated.pitchMap) {
465                        updated.pitchMap = { midiLow: 36, midiHigh: 84, outputLow: -6, outputHigh: 6, axis: "y" };
466                      } else if (newDriver === "velocity_scale" && !updated.velocityScale) {
467                        updated.velocityScale = { factor: 3, axis: "y", activeOnly: true };
468                      }
469                      handleUpdateChannel(actionIdx, chIdx, updated);
470                    },
471                    className: "bg-zinc-900 border border-zinc-700 text-xs font-bold text-amber-300 px-2.5 py-1 rounded-lg outline-none",
472                    children: [
473                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "wave", children: "Wave (Oscillation / Stroke)" }),
474                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "density_pulse", children: "Density Pulse (Music Speed)" }),
475                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "velocity_envelope", children: "Velocity Envelope (Smooth Dynamics)" }),
476                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "articulation_switch", children: "Articulation Switch (Legato/Staccato)" }),
477                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "phrase_accent", children: "Phrase Accent (Attack Impulse)" }),
478                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "polyphony_spread", children: "Polyphony Spread (Chord Width)" }),
479                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "climax_boost", children: "Climax Boost (Tutti Surge)" }),
480                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "pitch_map", children: "Pitch Map (Fret / Slide / Keys)" }),
481                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "velocity_scale", children: "Velocity Scale (Impact)" }),
482                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "constant", children: "Constant Offset" })
483                    ]
484                  }
485                )
486              ] }),
487              /* @__PURE__ */ jsxRuntimeExports.jsx(
488                "button",
489                {
490                  onClick: () => handleRemoveChannel(actionIdx, chIdx),
491                  className: "text-zinc-500 hover:text-red-400 p-1 transition-colors",
492                  title: "Delete Channel",
493                  children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { size: 14 })
494                }
495              )
496            ] }),
497            channel.driver === "wave" && channel.wave && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-3 text-xs", children: [
498              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
499                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Waveform:" }),
500                /* @__PURE__ */ jsxRuntimeExports.jsxs(
501                  "select",
502                  {
503                    value: channel.wave.waveform,
504                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
505                      ...channel,
506                      wave: { ...channel.wave, waveform: e.target.value }
507                    }),
508                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none",
509                    children: [
510                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "sine", children: "Sine (Smooth)" }),
511                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "abs_sine", children: "Abs Sine (Bounce)" }),
512                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "triangle", children: "Triangle (Linear)" }),
513                      /* @__P
513URE__ */ jsxRuntimeExports.jsx("option", { value: "sawtooth", children: "Sawtooth (Ramp)" })
514                    ]
515                  }
516                )
517              ] }),
518              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
519                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-500 mb-1", children: [
520                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Beat Rate:" }),
521                  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono", children: [
522                    channel.wave.frequency,
523                    "x"
524                  ] })
525                ] }),
526                /* @__PURE__ */ jsxRuntimeExports.jsx(
527                  "input",
528                  {
529                    type: "range",
530                    min: "0.5",
531                    max: "8.0",
532                    step: "0.5",
533                    value: channel.wave.frequency,
534                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
535                      ...channel,
536                      wave: { ...channel.wave, frequency: parseFloat(e.target.value) }
537                    }),
538                    className: "w-full accent-indigo-500 cursor-pointer"
539                  }
540                )
541              ] }),
542              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
543                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-500 mb-1", children: [
544                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Amplitude:" }),
545                  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono", children: [
546                    channel.wave.amplitude,
547                    "px"
548                  ] })
549                ] }),
550                /* @__PURE__ */ jsxRuntimeExports.jsx(
551                  "input",
552                  {
553                    type: "range",
554                    min: "0",
555                    max: "30",
556                    step: "1",
557                    value: channel.wave.amplitude,
558                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
559                      ...channel,
560                      wave: { ...channel.wave, amplitude: parseFloat(e.target.value) }
561                    }),
562                    className: "w-full accent-indigo-500 cursor-pointer"
563                  }
564                )
565              ] }),
566              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
567                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Axis:" }),
568                /* @__PURE__ */ jsxRuntimeExports.jsxs(
569                  "select",
570                  {
571                    value: channel.wave.axis || "y",
572                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
573                      ...channel,
574                      wave: { ...channel.wave, axis: e.target.value }
575                    }),
576                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none",
577                    children: [
578                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "y", children: "Vertical (Y)" }),
579                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "x", children: "Horizontal (X)" }),
580                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "both", children: "Elliptical (Both X & Y)" })
581                    ]
582                  }
583                )
584              ] })
585            ] }),
586            channel.driver === "pitch_map" && channel.pitchMap && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-3 text-xs", children: [
587              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
588                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "MIDI Low (Pitch):" }),
589                /* @__PURE__ */ jsxRuntimeExports.jsx(
590                  "input",
591                  {
592                    type: "number",
593                    value: channel.pitchMap.midiLow,
594                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
595                      ...channel,
596                      pitchMap: { ...channel.pitchMap, midiLow: parseInt(e.target.value) }
597                    }),
598                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono"
599                  }
600                )
601              ] }),
602              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
603                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "MIDI High (Pitch):" }),
604                /* @__P
604URE__ */ jsxRuntimeExports.jsx(
605                  "input",
606                  {
607                    type: "number",
608                    value: channel.pitchMap.midiHigh,
609                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
610                      ...channel,
611                      pitchMap: { ...channel.pitchMap, midiHigh: parseInt(e.target.value) }
612                    }),
613                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono"
614                  }
615                )
616              ] }),
617              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
618                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Output Low (px/deg):" }),
619                /* @__PURE__ */ jsxRuntimeExports.jsx(
620                  "input",
621                  {
622                    type: "number",
623                    value: channel.pitchMap.outputLow,
624                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
625                      ...channel,
626                      pitchMap: { ...channel.pitchMap, outputLow: parseFloat(e.target.value) }
627                    }),
628                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono"
629                  }
630                )
631              ] }),
632              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
633                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Output High (px/deg):" }),
634                /* @__PURE__ */ jsxRuntimeExports.jsx(
635                  "input",
636                  {
637                    type: "number",
638                    value: channel.pitchMap.outputHigh,
639                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
640                      ...channel,
641                      pitchMap: { ...channel.pitchMap, outputHigh: parseFloat(e.target.value) }
642                    }),
643                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono"
644                  }
645                )
646              ] })
647            ] }),
648            channel.driver === "velocity_scale" && channel.velocityScale && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-4 text-xs", children: [
649              /* @__P
649URE__ */ jsxRuntimeExports.jsxs("div", { children: [
650                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-500 mb-1", children: [
651                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Velocity Impact Factor:" }),
652                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-white font-mono", children: channel.velocityScale.factor })
653                ] }),
654                /* @__PURE__ */ jsxRuntimeExports.jsx(
655                  "input",
656                  {
657                    type: "range",
658                    min: "-15",
659                    max: "15",
660                    step: "0.5",
661                    value: channel.velocityScale.factor,
662                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
663                      ...channel,
664                      velocityScale: { ...channel.velocityScale, factor: parseFloat(e.target.value) }
665                    }),
666                    className: "w-full accent-indigo-500 cursor-pointer"
667                  }
668                )
669              ] }),
670              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
671                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Axis:" }),
672                /* @__PURE__ */ jsxRuntimeExports.jsxs(
673                  "select",
674                  {
675                    value: channel.velocityScale.axis || "y",
676                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
677                      ...channel,
678                      velocityScale: { ...channel.velocityScale, axis: e.target.value }
679                    }),
680                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none",
681                    children: [
682                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "y", children: "Vertical (Y)" }),
683                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "x", children: "Horizontal (X)" })
684                    ]
685                  }
686                )
687              ] })
688            ] }),
689            channel.driver === "constant" && channel.constant && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-2 gap-4 text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
690              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Offset Value:" }),
691              /* @__PURE__ */ jsxRuntimeExports.jsx(
692                "input",
693                {
694                  type: "number",
695                  value: channel.constant.value,
696                  onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
697                    ...channel,
698                    constant: { ...channel.constant, value: parseFloat(e.target.value) }
699                  }),
700                  className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono"
701                }
702              )
703            ] }) }),
704            channel.driver === "density_pulse" && channel.densityPulse && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-3 text-xs", children: [
705              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
706                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Base Rate:" }),
707                /* @__PURE__ */ jsxRuntimeExports.jsx(
708                  "input",
709                  {
710                    type: "number",
711                    step: "0.5",
712                    value: channel.densityPulse.baseFrequency ?? 1,
713                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
714                      ...channel,
715                      densityPulse: { ...channel.densityPulse, baseFrequency: parseFloat(e.target.value) }
716                    }),
717                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono"
718                  }
719                )
720              ] }),
721              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
722                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Density Scaling Factor:" }),
723                /* @__PURE__ */ jsxRuntimeExports.jsx(
724                  "input",
725                  {
726                    type: "number",
727                    step: "0.05",
728                    value: channel.densityPulse.densityFactor ?? 0.15,
729                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
730                      ...channel,
731                      densityPulse: { ...channel.densityPulse, densityFactor: parseFloat(e.target.value) }
732                    }),
733                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono"
734                  }
735                )
736              ] }),
737              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
738                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Amplitude:" }),
739                /* @__PURE__ */ jsxRuntimeExports.jsx(
740                  "input",
741                  {
742                    type: "number",
743                    value: channel.densityPulse.amplitude,
744                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
745                      ...channel,
746                      densityPulse: { ...channel.densityPulse, amplitude: parseFloat(e.target.value) }
747                    }),
748                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono"
749                  }
750                )
751              ] }),
752              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
753                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Axis:" }),
754                /* @__P
754URE__ */ jsxRuntimeExports.jsxs(
755                  "select",
756                  {
757                    value: channel.densityPulse.axis || "y",
758                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
759                      ...channel,
760                      densityPulse: { ...channel.densityPulse, axis: e.target.value }
761                    }),
762                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none",
763                    children: [
764                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "y", children: "Vertical (Y)" }),
765                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "x", children: "Horizontal (X)" }),
766                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "both", children: "Both (X & Y)" })
767                    ]
768                  }
769                )
770              ] })
771            ] }),
772            channel.driver === "velocity_envelope" && channel.velocityEnvelope && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-4 text-xs", children: [
773              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
774                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Envelope Scale Factor:" }),
775                /* @__PURE__ */ jsxRuntimeExports.jsx(
776                  "input",
777                  {
778                    type: "number",
779                    step: "0.5",
780                    value: channel.velocityEnvelope.factor,
781                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
782                      ...channel,
783                      velocityEnvelope: { ...channel.velocityEnvelope, factor: parseFloat(e.target.value) }
784                    }),
785                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono"
786                  }
787                )
788              ] }),
789              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
790                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Axis:" }),
791                /* @__PURE__ */ jsxRuntimeExports.jsxs(
792                  "select",
793                  {
794                    value: channel.velocityEnvelope.axis || "y",
795                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
796                      ...channel,
797                      velocityEnvelope: { ...channel.velocityEnvelope, axis: e.target.value }
798                    }),
799                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none",
800                    children: [
801                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "y", children: "Vertical (Y)" }),
802                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "x", children: "Horizontal (X)" })
803                    ]
804                  }
805                )
806              ] })
807            ] }),
808            channel.driver === "articulation_switch" && channel.articulationSwitch && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-3 text-xs", children: [
809              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
810                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Legato Value:" }),
811                /* @__PURE__ */ jsxRuntimeExports.jsx(
812                  "input",
813                  {
814                    type: "number",
815                    value: channel.articulationSwitch.legatoValue ?? 0,
816                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
817                      ...channel,
818                      articulationSwitch: { ...channel.articulationSwitch, legatoValue: parseFloat(e.target.value) }
819                    }),
820                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono"
821                  }
822                )
823              ] }),
824              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
825                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Staccato Value:" }),
826                /* @__PURE__ */ jsxRuntimeExports.jsx(
827                  "input",
828                  {
829                    type: "number",
830                    value: channel.articulationSwitch.staccatoValue ?? 0,
831                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
832                      ...channel,
833                      articulationSwitch: { ...channel.articulationSwitch, staccatoValue: parseFloat(e.target.value) }
834                    }),
835                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono"
836                  }
837                )
838              ] }),
839              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
840                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Tremolo Value:" }),
841                /* @__PURE__ */ jsxRuntimeExports.jsx(
842                  "input",
843                  {
844                    type: "number",
845                    value: channel.articulationSwitch.tremoloValue ?? 0,
846                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
847                      ...channel,
848                      articulationSwitch: { ...channel.articulationSwitch, tremoloValue: parseFloat(e.target.value) }
849                    }),
850                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono"
851                  }
852                )
853              ] }),
854              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
855                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Axis:" }),
856                /* @__PURE__ */ jsxRuntimeExports.jsxs(
857                  "select",
858                  {
859                    value: channel.articulationSwitch.axis || "y",
860                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
861                      ...channel,
862                      articulationSwitch: { ...channel.articulationSwitch, axis: e.target.value }
863                    }),
864                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none",
865                    children: [
866                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "y", children: "Vertical (Y)" }),
867                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "x", children: "Horizontal (X)" })
868                    ]
869                  }
870                )
871              ] })
872            ] }),
873            channel.driver === "phrase_accent" && channel.phraseAccent && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-4 text-xs", children: [
874              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
875                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Attack Impulse:" }),
876                /* @__PURE__ */ jsxRuntimeExports.jsx(
877                  "input",
878                  {
879                    type: "number",
880                    value: channel.phraseAccent.impulse,
881                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
882                      ...channel,
883                      phraseAccent: { ...channel.phraseAccent, impulse: parseFloat(e.target.value) }
884                    }),
885                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono"
886                  }
887                )
888              ] }),
889              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
890                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Axis:" }),
891                /* @__P
891URE__ */ jsxRuntimeExports.jsxs(
892                  "select",
893                  {
894                    value: channel.phraseAccent.axis || "y",
895                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
896                      ...channel,
897                      phraseAccent: { ...channel.phraseAccent, axis: e.target.value }
898                    }),
899                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none",
900                    children: [
901                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "y", children: "Vertical (Y)" }),
902                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "x", children: "Horizontal (X)" })
903                    ]
904                  }
905                )
906              ] })
907            ] }),
908            channel.driver === "polyphony_spread" && channel.polyphonySpread && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-3 gap-3 text-xs", children: [
909              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
910                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Spread Per Note:" }),
911                /* @__PURE__ */ jsxRuntimeExports.jsx(
912                  "input",
913                  {
914                    type: "number",
915                    step: "0.5",
916                    value: channel.polyphonySpread.spreadPerNote,
917                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
918                      ...channel,
919                      polyphonySpread: { ...channel.polyphonySpread, spreadPerNote: parseFloat(e.target.value) }
920                    }),
921                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono"
922                  }
923                )
924              ] }),
925              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
926                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Max Spread:" }),
927                /* @__PURE__ */ jsxRuntimeExports.jsx(
928                  "input",
929                  {
930                    type: "number",
931                    value: channel.polyphonySpread.maxSpread ?? 10,
932                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
933                      ...channel,
934                      polyphonySpread: { ...channel.polyphonySpread, maxSpread: parseFloat(e.target.value) }
935                    }),
936                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono"
937                  }
938                )
939              ] }),
940              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
941                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Axis:" }),
942                /* @__PURE__ */ jsxRuntimeExports.jsxs(
943                  "select",
944                  {
945                    value: channel.polyphonySpread.axis || "x",
946                    onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
947                      ...channel,
948                      polyphonySpread: { ...channel.polyphonySpread, axis: e.target.value }
949                    }),
950                    className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none",
951                    children: [
952                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "x", children: "Horizontal (X)" }),
953                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "y", children: "Vertical (Y)" })
954                    ]
955                  }
956                )
957              ] })
958            ] }),
959            channel.driver === "climax_boost" && channel.climaxBoost && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-2 gap-4 text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
960              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Climax Multiplier:" }),
961              /* @__PURE__ */ jsxRuntimeExports.jsx(
962                "input",
963                {
964                  type: "number",
965                  step: "0.1",
966                  value: channel.climaxBoost.multiplier,
967                  onChange: (e) => handleUpdateChannel(actionIdx, chIdx, {
968                    ...channel,
969                    climaxBoost: { ...channel.climaxBoost, multiplier: parseFloat(e.target.value) }
970                  }),
971                  className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono"
972                }
973              )
974            ] }) })
975          ] }, chIdx)) })
976        ] }, action.id || actionIdx)) })
977      ] }),
978      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "xl:col-span-5 space-y-6", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl p-5 shadow-xl sticky top-6 space-y-5", children: [
979        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between border-b border-zinc-800 pb-3", children: [
980          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
981            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-2.5 h-2.5 rounded-full bg-emerald-400 animate-ping" }),
982            /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-bold text-white uppercase tracking-wider", children: "Live Action Simulator" })
983          ] }),
984          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
985            "button",
986            {
987              onClick: () => setIsSimulating(!isSimulating),
988              className: `px-3 py-1 rounded-lg text-xs font-semibold flex items-center gap-1.5 transition-all ${isSimulating ? "bg-emerald-500/20 text-emerald-300 border border-emerald-500/30" : "bg-zinc-800 text-zinc-400 border border-zinc-700"}`,
989              children: [
990                isSimulating ? /* @__PURE__ */ jsxRuntimeExports.jsx(Pause, { size: 12 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Play, { size: 12 }),
991                isSimulating ? "Playing" : "Paused"
992              ]
993            }
994          ) })
995        ] }),
996        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full h-80 bg-zinc-950 border border-zinc-800 rounded-2xl relative overflow-hidden flex items-center justify-center", children: [
997          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-x-0 bottom-0 h-28 bg-gradient-to-t from-black/80 to-transparent pointer-events-none" }),
998          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute w-40 h-8 rounded-full bg-black/60 blur-md bottom-12" }),
999          /* @__PURE__ */ jsxRuntimeExports.jsx(
1000            "svg",
1001            {
1002              viewBox: "-100 -120 200 240",
1003              className: "w-full h-full relative z-10",
1004              preserveAspectRatio: "xMidYMid meet",
1005              children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1006                SouthparkCharacter,
1007                {
1008                  animal: activeAnimalDef,
1009                  instrument: selectedInstDef,
1010                  isActive: isNoteActive,
1011                  velocity: isNoteActive ? simVelocity : 0,
1012                  activePitch: simPitch,
1013                  currentTime: simTime,
1014                  bpm: simBpm,
1015                  isPlaying: isSimulating,
1016                  physicsMode: "snappy",
1017                  showInstrument: true,
1018                  showSkeleton,
1019                  skeletonOnly,
1020                  customConfig: charConfig,
1021                  actionsConfig
1022                }
1023              )
1024            }
1025          ),
1026          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute top-3 left-3 px-2.5 py-1 rounded-lg text-[10px] font-bold border flex items-center gap-1.5 bg-zinc-900/90 backdrop-blur-sm", children: [
1027            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `w-2 h-2 rounded-full ${isNoteActive ? "bg-emerald-400" : "bg-zinc-600"}` }),
1028            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: isNoteActive ? "text-emerald-300" : "text-zinc-500", children: isNoteActive ? `NOTE ON (Vel ${simVelocity})` : "IDLE GAP" })
1029          ] }),
1030          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-3 right-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1031            "select",
1032            {
1033              value: previewAnimal,
1034              onChange: (e) => setPreviewAnimal(e.target.value),
1035              className: "bg-zinc-900/90 border border-zinc-700 text-[11px] font-bold text-white px-2.5 py-1 rounded-lg outline-none backdrop-blur-sm",
1036              children: Object.keys(BASE_ANIMALS).map((aId) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: aId, className: "bg-zinc-900 text-white", children: BASE_ANIMALS[aId].name }, aId))
1037            }
1038          ) })
1039        ] }),
1040        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4 bg-zinc-950 p-4 rounded-xl border border-zinc-800 text-xs", children: [
1041          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
1042            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-zinc-300", children: "Rhythmic Downbeat Pulse:" }),
1043            /* @__PURE__ */ jsxRuntimeExports.jsx(
1044              "button",
1045              {
1046                onClick: () => setNotePulsing(!notePulsing),
1047                className: `px-2.5 py-0.5 rounded text-[11px] font-bold border transition-all ${notePulsing ? "bg-emerald-500/20 text-emerald-300 border-emerald-500/40" : "bg-zinc-800 text-zinc-400 border-zinc-700"}`,
1048                children: notePulsing ? "Auto Tempo Pulsing" : "Manual Trigger"
1049              }
1050            )
1051          ] }),
1052          !notePulsing && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1053            "button",
1054            {
1055              onMouseDown: () => setIsNoteActive(true),
1056              onMouseUp: () => setIsNoteActive(false),
1057              onTouchStart: () => setIsNoteActive(true),
1058              onTouchEnd: () => setIsNoteActive(false),
1059              className: "flex-1 py-2 rounded-xl bg-indigo-600 hover:bg-indigo-500 active:scale-95 text-white font-bold text-xs shadow-md transition-all text-center",
1060              children: "Hold to Strike Note 🎵"
1061            }
1062          ) }),
1063          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1064            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-400 mb-1", children: [
1065              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "MIDI Pitch (Slides / Fret / Keys):" }),
1066              /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono font-bold", children: [
1067                simPitch,
1068                " (C",
1069                Math.floor(simPitch / 12) - 1,
1070                ")"
1071              ] })
1072            ] }),
1073            /* @__PURE__ */ jsxRuntimeExports.jsx(
1074              "input",
1075              {
1076                type: "range",
1077                min: "21",
1078                max: "108",
1079                value: simPitch,
1080                onChange: (e) => setSimPitch(parseInt(e.target.value)),
1081                className: "w-full accent-amber-500 cursor-pointer"
1082              }
1083            )
1084          ] }),
1085          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1086            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-400 mb-1", children: [
1087              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Velocity (Impact Energy):" }),
1088              /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono font-bold", children: [
1089                simVelocity,
1090                " / 127"
1091              ] })
1092            ] }),
1093            /* @__PURE__ */ jsxRuntimeExports.jsx(
1094              "input",
1095              {
1096                type: "range",
1097                min: "20",
1098                max: "127",
1099                value: simVelocity,
1100                onChange: (e) => setSimVelocity(parseInt(e.target.value)),
1101                className: "w-full accent-emerald-500 cursor-pointer"
1102              }
1103            )
1104          ] }),
1105          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1106            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-400 mb-1", children: [
1107              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "BPM (Tempo Speed):" }),
1108              /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono font-bold", children: [
1109                simBpm,
1110                " BPM"
1111              ] })
1112            ] }),
1113            /* @__PURE__ */ jsxRuntimeExports.jsx(
1114              "input",
1115              {
1116                type: "range",
1117                min: "60",
1118                max: "200",
1119                value: simBpm,
1120                onChange: (e) => setSimBpm(parseInt(e.target.value)),
1121                className: "w-full accent-indigo-500 cursor-pointer"
1122              }
1123            )
1124          ] }),
1125          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between pt-2 border-t border-zinc-900", children: [
1126            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400 font-medium", children: "Kinematic Wireframe:" }),
1127            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
1128              /* @__PURE__ */ jsxRuntimeExports.jsx(
1129                "button",
1130                {
1131                  onClick: () => setShowSkeleton(!showSkeleton),
1132                  className: `px-2 py-1 rounded text-[11px] font-semibold border ${showSkeleton ? "bg-indigo-500/20 text-indigo-300 border-indigo-500/40" : "bg-zinc-900 text-zinc-500 border-zinc-800"}`,
1133                  children: "Joint Overlay"
1134                }
1135              ),
1136              /* @__PURE__ */ jsxRuntimeExports.jsx(
1137                "button",
1138                {
1139                  onClick: () => setSkeletonOnly(!skeletonOnly),
1140                  className: `px-2 py-1 rounded text-[11px] font-semibold border ${skeletonOnly ? "bg-amber-500/20 text-amber-300 border-amber-500/40" : "bg-zinc-900 text-zinc-500 border-zinc-800"}`,
1141                  children: "Skeleton Only"
1142                }
1143              )
1144            ] })
1145          ] })
1146        ] })
1147      ] }) })
1148    ] }) : (
1149      /* IDLE & SPARE ACTIONS STUDIO */
1150      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
1151        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl p-5 shadow-lg flex flex-col md:flex-row md:items-center justify-between gap-4", children: [
1152          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1153            /* @__PURE__ */ jsxRuntimeExports.jsxs("h3", { className: "text-base font-bold text-white flex items-center gap-2", children: [
1154              /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { size: 18, className: "text-amber-400" }),
1155              "Orchestra Idle & Spare Actions Library"
1156            ] }),
1157            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-400 mt-1", children: "Characters randomly execute these natural micro-behaviors during rests and silent passages, bringing the stage to life." })
1158          ] }),
1159          /* @__PURE__ */ jsxRuntimeExports.jsxs(
1160            "button",
1161            {
1162              onClick: handleResetAllIdleDefaults,
1163              className: "flex items-center gap-1.5 px-3 py-1.5 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 text-xs font-semibold rounded-lg border border-zinc-700 transition-all",
1164              children: [
1165                /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { size: 14 }),
1166                "Reset All Idle Defaults"
1167              ]
1168            }
1169          )
1170        ] }),
1171        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6", children: idleActionsList.map((idle) => {
1172          const isTesting = activeTestingIdleId === idle.id;
1173          const sched = idle.idleSchedule || {
1174            minIntervalMs: 1e4,
1175            maxIntervalMs: 3e4,
1176            durationMs: 2e3,
1177            blendInMs: 400,
1178            blendOutMs: 400
1179          };
1180          return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1181            "div",
1182            {
1183              className: `bg-zinc-900 border rounded-2xl p-5 shadow-lg space-y-4 transition-all ${isTesting ? "border-amber-500/60 shadow-amber-500/10" : "border-zinc-800"}`,
1184              children: [
1185                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between border-b border-zinc-800 pb-3", children: [
1186                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1187                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
1188                      /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-sm font-bold text-white", children: idle.name }),
1189                      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] font-mono px-2 py-0.5 rounded bg-zinc-800 text-zinc-400", children: idle.id })
1190                    ] }),
1191                    /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[11px] text-zinc-500 mt-0.5", children: [
1192                      "Targets: ",
1193                      idle.channels.map((c) => c.target).join(", ")
1194                    ] })
1195                  ] }),
1196                  /* @__PURE__ */ jsxRuntimeExports.jsxs(
1197                    "button",
1198                    {
1199                      onClick: () => handleTestIdleAction(idle.id),
1200                      className: `px-3 py-1.5 rounded-xl text-xs font-bold flex items-center gap-1.5 transition-all ${isTesting ? "bg-amber-500 text-black shadow-lg animate-pulse" : "bg-indigo-600/30 text-indigo-300 hover:bg-indigo-600/50 border border-indigo-500/30"}`,
1201                      children: [
1202                        /* @__PURE__ */ jsxRuntimeExports.jsx(Play, { size: 12 }),
1203                        isTesting ? "Testing Now..." : "Test Action"
1204                      ]
1205                    }
1206                  )
1207                ] }),
1208                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3 text-xs bg-zinc-950 p-3.5 rounded-xl border border-zinc-800/80", children: [
1209                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1210                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-400 mb-1", children: [
1211                      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Duration:" }),
1212                      /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono font-bold", children: [
1213                        (sched.durationMs / 1e3).toFixed(1),
1214                        "s"
1215                      ] })
1216                    ] }),
1217                    /* @__PURE__ */ jsxRuntimeExports.jsx(
1218                      "input",
1219                      {
1220                        type: "range",
1221                        min: "500",
1222                        max: "6000",
1223                        step: "100",
1224                        value: sched.durationMs,
1225                        onChange: (e) => handleUpdateIdleSchedule(idle.id, "durationMs", parseInt(e.target.value)),
1226                        className: "w-full accent-indigo-500 cursor-pointer"
1227                      }
1228                    )
1229                  ] }),
1230                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
1231                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1232                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-500 mb-1", children: [
1233                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Min Interval:" }),
1234                        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono", children: [
1235                          Math.round(sched.minIntervalMs / 1e3),
1236                          "s"
1237                        ] })
1238                      ] }),
1239                      /* @__PURE__ */ jsxRuntimeExports.jsx(
1240                        "input",
1241                        {
1242                          type: "range",
1243                          min: "4000",
1244                          max: "40000",
1245                          step: "1000",
1246                          value: sched.minIntervalMs,
1247                          onChange: (e) => handleUpdateIdleSchedule(idle.id, "minIntervalMs", parseInt(e.target.value)),
1248                          className: "w-full accent-indigo-500 cursor-pointer"
1249                        }
1250                      )
1251                    ] }),
1252                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1253                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-500 mb-1", children: [
1254                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Max Interval:" }),
1255                        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono", children: [
1256                          Math.round(sched.maxIntervalMs / 1e3),
1257                          "s"
1258                        ] })
1259                      ] }),
1260                      /* @__PURE__ */ jsxRuntimeExports.jsx(
1261                        "input",
1262                        {
1263                          type: "range",
1264                          min: "8000",
1265                          max: "90000",
1266                          step: "1000",
1267                          value: sched.maxIntervalMs,
1268                          onChange: (e) => handleUpdateIdleSchedule(idle.id, "maxIntervalMs", parseInt(e.target.value)),
1269                          className: "w-full accent-indigo-500 cursor-pointer"
1270                        }
1271                      )
1272                    ] })
1273                  ] }),
1274                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-3 pt-1 border-t border-zinc-900", children: [
1275                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1276                      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-0.5", children: "Blend In:" }),
1277                      /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-zinc-300 font-mono text-[11px]", children: [
1278                        sched.blendInMs,
1279                        "ms"
1280                      ] })
1281                    ] }),
1282                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1283                      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-0.5", children: "Blend Out:" }),
1284                      /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-zinc-300 font-mono text-[11px]", children: [
1285                        sched.blendOutMs,
1286                        "ms"
1287                      ] })
1288                    ] })
1289                  ] })
1290                ] })
1291              ]
1292            },
1293            idle.id
1294          );
1295        }) })
1296      ] })
1297    )
1298  ] });
1299};
1300export {
1301  SouthparkActionsStudio,
1302  SouthparkActionsStudio as default
1303};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.