PageSourceSearch

https://www.hamienet.com/assets/SouthparkStudio-B68BbarO.js

js hamienet.com collected 2026-10-02 05:02:13 UTC 192,030 bytes, 2,803 lines download raw bytes

1import { r as reactExports, j as jsxRuntimeExports } from "./vendor-react-Bay9Y7Lb.js";
2import { d as SOUTHPARK_TRUMPET_SVG, e as SOUTHPARK_PIANO_SVG, f as SOUTHPARK_DRUMS_SVG, h as SOUTHPARK_CELLO_SVG, i as SOUTHPARK_GUITAR_SVG, j as DEFAULT_SOUTHPARK_COSTUMES, B as BASE_ANIMALS, S as SouthparkCharacter, g as getInstrumentDef } from "./SouthparkInstruments-C-w5kAUh.js";
3import { g as getAnimalVariant, b as getVariantFilterSvg } from "./SouthparkVariants-DYvo6xjJ.js";
4import { SouthparkOrchestraVisualizer } from "./SouthparkOrchestraVisualizer-C3Z_hmqt.js";
5import { b as getInstrumentName, I as INSTRUMENT_CATEGORIES, l as GM_INSTRUMENTS } from "./utils-CEVb7nN1.js";
6import { d as defaultBackgroundConfig, a as defaultBackgroundPresets } from "./StagePuppetEngine-CmAn6HAX.js";
7import { SouthparkStageDesigner } from "./SouthparkStageDesigner-fV_8Ua7K.js";
8import { SouthparkActionsStudio } from "./SouthparkActionsStudio-BAkc1Yf-.js";
9import { cM as RefreshCw, ck as Layers, cd as Save, dh as SlidersVertical, cg as Activity, dP as Users, bg as Music, g9 as Shirt, bo as Monitor, bp as CirclePlay, bi as Sparkles, b_ as Pause, bV as Play, bz as EyeOff, ds as ZoomOut, dt as ZoomIn, bf as Search, d0 as Maximize2, f0 as PenLine, bA as Eye, c4 as RotateCcw, b2 as Upload, aW as X } from "./vendor-D0P4XgNj.js";
10import "./IkMath-D6fi1ppd.js";
11import "./vendor-framer-B-4FZk1Z.js";
12import "./synth-Fr-K52Ox.js";
13import "./vendor-react-three-BCww3P1x.js";
14import "./wasm-synth-adapter-DpNGIIyM.js";
15import "./vendor-spessasynth-DH8n6o_V.js";
16import "./vendor-audio-D-wTggbx.js";
17import "./SouthparkStageBanner-CUiAAGWi.js";
18import "./index-w5lXls15.js";
19import "./vendor-i18n-BC7ZMXWQ.js";
20import "./vendor-gsap-50Lx19ak.js";
21const StandaloneSouthparkViewer = ({ trackId }) => {
22  const [track, setTrack] = reactExports.useState(null);
23  const [pianoRollData, setPianoRollData] = reactExports.useState([]);
24  const [currentTime, setCurrentTime] = reactExports.useState(0);
25  const [isPlaying, setIsPlaying] = reactExports.useState(false);
26  const [loading, setLoading] = reactExports.useState(true);
27  const audioRef = reactExports.useRef(null);
28  reactExports.useEffect(() => {
29    let isCurrent = true;
30    setLoading(true);
31    const load = async () => {
32      try {
33        const res = await fetch(`/api/tracks/${trackId}`);
34        if (!res.ok) throw new Error("Track not found");
35        const trackData = await res.json();
36        if (!isCurrent) return;
37        setTrack(trackData);
38        if (trackData.pianoRollPath) {
39          const prRes = await fetch(trackData.pianoRollPath);
40          const prData = await prRes.json();
41          if (!isCurrent) return;
42          const processedInstruments2 = trackData.instruments || [];
43          const musicalInstruments = processedInstruments2.filter((inst) => inst.midiChannel !== -1);
44          const mappedData = prData.map((note) => {
45            let mappedIdx = -1;
46            if (note.trackIdx !== void 0) {
47              const targetIdx = note.trackIdx;
48              if (targetIdx >= 0 && targetIdx < musicalInstruments.length) {
49                const matchedInst = musicalInstruments[targetIdx];
50                mappedIdx = processedInstruments2.findIndex((inst) => inst.trackId === matchedInst.trackId);
51              }
52            }
53            if (mappedIdx !== -1) {
54              return {
55                ...note,
56                trackIdx: mappedIdx !== -1 ? mappedIdx : note.trackIdx
57              };
58            }
59            return note;
60          });
61          mappedData.sort((a, b) => a.t - b.t);
62          setPianoRollData(mappedData);
63        }
64      } catch (err) {
65        console.error(err);
66      } finally {
67        if (isCurrent) setLoading(false);
68      }
69    };
70    load();
71    return () => {
72      isCurrent = false;
73    };
74  }, [trackId]);
75  const { processedInstruments, uniqueNames } = reactExports.useMemo(() => {
76    if (!track) return { processedInstruments: [], uniqueNames: [] };
77    let sourceInstruments = track.instruments || [];
78    if (sourceInstruments.length === 0 && pianoRollData.length > 0) {
79      const trackMap = /* @__PURE__ */ new Map();
80      pianoRollData.forEach((note) => {
81        const trackIdx = note.trackIdx !== void 0 ? note.trackIdx : note.i;
82        if (!trackMap.has(trackIdx)) {
83          trackMap.set(trackIdx, {
84            trackId: trackIdx,
85            name: typeof note.i === "string" ? note.i : `Track ${trackIdx}`,
86            program: note.p || 0,
87            midiChannel: note.isDrum ? 9 : 0,
88            notesCount: 1,
89            stemPath: null
90          });
91        }
92      });
93      sourceInstruments = Array.from(trackMap.values());
94    }
95    const processed = sourceInstruments.map((inst, idx) => {
96      let name = inst.name;
97      if (name !== "Informational Track") {
98        name = getInstrumentName(inst.program, inst.midiChannel);
99      }
100      return { ...inst, displayName: String(name), originalName: inst.name, index: i
100dx };
101    });
102    const nameCounts = {};
103    const uNames = processed.map((inst, idx) => {
104      const baseName = inst.displayName || getInstrumentName(inst.program, inst.midiChannel) || `Track ${idx + 1}`;
105      nameCounts[baseName] = (nameCounts[baseName] || 0) + 1;
106      return nameCounts[baseName] > 1 ? `${baseName} ${nameCounts[baseName]}` : baseName;
107    });
108    return { processedInstruments: processed, uniqueNames: uNames };
109  }, [track, pianoRollData]);
110  if (loading) {
111    return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-white p-4", children: "Loading standalone viewer..." });
112  }
113  if (!track) {
114    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-white p-4", children: [
115      "Failed to load track ",
116      trackId
117    ] });
118  }
119  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full h-full relative bg-black flex flex-col", children: [
120    track.opusPath && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-4 right-4 z-50 bg-zinc-900 p-2 rounded-lg border border-zinc-700 flex items-center gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
121      "audio",
122      {
123        ref: audioRef,
124        src: track.opusPath,
125        controls: true,
126        onTimeUpdate: (e) => setCurrentTime(e.currentTarget.currentTime),
127        onPlay: () => setIsPlaying(true),
128        onPause: () => setIsPlaying(false),
129        onEnded: () => setIsPlaying(false),
130        className: "h-8 w-48"
131      }
132    ) }),
133    /* @__PURE__ */ jsxRuntimeExports.jsx(
134      SouthparkOrchestraVisualizer,
135      {
136        track,
137        currentTime,
138        isPlaying,
139        pianoRollData,
140        processedInstruments,
141        uniqueNames,
142        soloedIndex: null,
143        onSolo: () => {
144        },
145        mutedIndices: /* @__PURE__ */ new Set(),
146        onMute: () => {
147        },
148        onPanChange: () => {
149        }
150      }
151    )
152  ] });
153};
154const POSE_INSTRUMENTS_SVG = {
155  guitar: SOUTHPARK_GUITAR_SVG,
156  bowing: SOUTHPARK_CELLO_SVG,
157  drumming: SOUTHPARK_DRUMS_SVG,
158  sitting: SOUTHPARK_PIANO_SVG,
159  blowing: SOUTHPARK_TRUMPET_SVG,
160  standard: ""
161};
162const POSE_INSTRUMENTS_IMG = {
163  guitar: "/assets/visualizers/southpark/instruments/inst_24.webp",
164  bowing: "/assets/visualizers/southpark/instruments/inst_42.webp",
165  violin: "/assets/visualizers/southpark/instruments/inst_40.webp",
166  drumming: "/assets/visualizers/southpark/instruments/inst_drums.webp",
167  sitting: "/assets/visualizers/southpark/instruments/inst_0.webp",
168  blowing: "/assets/visualizers/southpark/instruments/inst_56.webp",
169  flute: "/assets/visualizers/southpark/instruments/inst_73.webp",
170  congas: "/assets/visualizers/southpark/instruments/perc_congas.webp",
171  percussion_handheld: "/assets/visualizers/southpark/instruments/perc_tambourine.webp",
172  clapping: "",
173  standard: ""
174};
175const defaultStageConfig = {
176  rows: 4,
177  spacingX: 80,
178  spacingY: 60,
179  baseScale: 1,
180  rowScaleMultiplier: 0.9,
181  yOffset: 0,
182  arcFactor: 1
183};
184const ACTION_POSES = [
185  { id: "standard", name: "Static / Neutral", holdStyle: "standard", desc: "Neutral standing pose with relaxed limb angles", badgeColor: "bg-zinc-800 text-zinc-300 border-zinc-700" },
186  { id: "guitar", name: "Guitar", holdStyle: "guitar", desc: "Left arm fret neck hold, right arm dynamic strumming", badgeColor: "bg-amber-500/10 text-amber-400 border-amber-500/20" },
187  { id: "drumming", name: "Drums", holdStyle: "drumming", desc: "Dual paw raised hover with rhythmic downbeat stroke", badgeColor: "bg-rose-500/10 text-rose-400 border-rose-500/20" },
188  { id: "bowing", name: "Cello / Bass", holdStyle: "bowing", desc: "Seated cello with floor endpin and lateral bow stroke", badgeColor: "bg-blue-500/10 text-blue-400 border-blue-500/20" },
189  { id: "violin", name: "Violin / Viola", holdStyle: "violin", desc: "Under-chin shoulder rest with horizontal bow across chest", badgeColor: "bg-purple-500/10 text-purple-400 border-purple-500/20" },
190  { id: "sitting", name: "Piano / Seated", holdStyle: "sitting", desc: "Seated playing posture with wide keyboard key span", badgeColor: "bg-emerald-500/10 text-emerald-400 border-emerald-500/20" },
191  { id: "blowing", name: "Wind / Brass", holdStyle: "blowing", desc: "Dual paws centered beneath mouth holding mouthpiece", badgeColor: "bg-cyan-500/10 text-cyan-400 border-cyan-500/20" },
192  { id: "flute", name: "Flute / Piccolo", holdStyle: "flute", desc: "Transverse horizontal tube extending to player right", badgeColor: "bg-teal-500/10 text-teal-400 border-teal-500/20" },
193  { id: "congas", name: "Congas / Hand Drums", holdStyle: "congas", desc: "Standing dual-paw rhythmic 
193slaps on barrel drumheads", badgeColor: "bg-orange-500/10 text-orange-400 border-orange-500/20" },
194  { id: "percussion_handheld", name: "Auxiliary Percussion", holdStyle: "percussion_handheld", desc: "Handheld tambourine, cowbell, triangle or shaker rhythm", badgeColor: "bg-yellow-500/10 text-yellow-400 border-yellow-500/20" },
195  { id: "clapping", name: "Applause / Clapping", holdStyle: "clapping", desc: "Enthusiastic rhythmic bare paw clapping at chest height", badgeColor: "bg-pink-500/10 text-pink-400 border-pink-500/20" }
196];
197function SouthparkStudio() {
198  const [activeTab, setActiveTab] = reactExports.useState("actions_studio");
199  const [previewMidiId, setPreviewMidiId] = reactExports.useState("");
200  const [iframeUrl, setIframeUrl] = reactExports.useState("");
201  const [isLoading, setIsLoading] = reactExports.useState(true);
202  const [isSaving, setIsSaving] = reactExports.useState(false);
203  const [error, setError] = reactExports.useState(null);
204  const [successMsg, setSuccessMsg] = reactExports.useState(null);
205  const [animatedAnimals, setAnimatedAnimals] = reactExports.useState({});
206  const [previewVariants, setPreviewVariants] = reactExports.useState({});
207  const [globalVariantIndex, setGlobalVariantIndex] = reactExports.useState(null);
208  const [isGlobalAnimating, setIsGlobalAnimating] = reactExports.useState(true);
209  const [globalVelocity, setGlobalVelocity] = reactExports.useState(100);
210  const [pulseIntervalMs, setPulseIntervalMs] = reactExports.useState(500);
211  const [selectedAnimalFilter, setSelectedAnimalFilter] = reactExports.useState("all");
212  const [selectedPoseFilter, setSelectedPoseFilter] = reactExports.useState("all");
213  const [currentVelocityPulse, setCurrentVelocityPulse] = reactExports.useState(100);
214  const [showInstruments, setShowInstruments] = reactExports.useState(true);
215  const [showSkeletonOverlay, setShowSkeletonOverlay] = reactExports.useState(false);
216  const [skeletonZoom, setSkeletonZoom] = reactExports.useState(1);
217  const [skeletonGridSize, setSkeletonGridSize] = reactExports.useState("compact");
218  const [skeletonAnimalBase, setSkeletonAnimalBase] = reactExports.useState("fox");
219  const [skeletonDisplayMode, setSkeletonDisplayMode] = reactExports.useState("pure");
220  const [inspectingPose, setInspectingPose] = reactExports.useState(null);
221  const [modalZoom, setModalZoom] = reactExports.useState(2.5);
222  const [modalPan, setModalPan] = reactExports.useState({ x: 0, y: 0 });
223  const [modalDisplayMode, setModalDisplayMode] = reactExports.useState("pure");
224  const [modalShowInstrument, setModalShowInstrument] = reactExports.useState(true);
225  const [isModalDragging, setIsModalDragging] = reactExports.useState(false);
226  const [dragStart, setDragStart] = reactExports.useState({ x: 0, y: 0 });
227  const [manualOverrideLimbAngles, setManualOverrideLimbAngles] = reactExports.useState(false);
228  const [manualLeftShoulder, setManualLeftShoulder] = reactExports.useState(-45);
229  const [manualLeftElbow, setManualLeftElbow] = reactExports.useState(-60);
230  const [manualRightShoulder, setManualRightShoulder] = reactExports.useState(45);
231  const [manualRightElbow, setManualRightElbow] = reactExports.useState(60);
232  const [inspectorAnimalId, setInspectorAnimalId] = reactExports.useState("fox");
233  const [actionPosesCols, setActionPosesCols] = reactExports.useState("compact");
234  const [actionPosesZoom, setActionPosesZoom] = reactExports.useState(1);
235  const getDynamicViewBox = (zoom, pan = { x: 0, y: 0 }) => {
236    const baseW = 200;
237    const baseH = 300;
238    if (zoom <= 1.05 && pan.x === 0 && pan.y === 0) {
239      return "0 0 200 300";
240    }
241    const t = Math.min(1, Math.max(0, (zoom - 1) / 1.5));
242    const targetCenterY = 150 + t * 18;
243    const focusX = 100 - pan.x;
244    const focusY = targetCenterY - pan.y;
245    const vbW = baseW / zoom;
246    const vbH = baseH / zoom;
247    const minX = focusX - vbW / 2;
248    const minY = focusY - vbH / 2;
249    return `${minX} ${minY} ${vbW} ${vbH}`;
250  };
251  reactExports.useEffect(() => {
252    if (!isGlobalAnimating) {
253      setCurrentVelocityPulse(0);
254      return;
255    }
256    const interval = setInterval(() => {
257      setCurrentVelocityPulse((v) => v === 0 ? globalVelocity : 0);
258    }, pulseIntervalMs);
259    return () => clearInterval(interval);
260  }, [isGlobalAnimating, globalVelocity, pulseIntervalMs]);
261  const [charactersConfig, setCharactersConfig] = reactExports.useState({});
262  const [instrumentsConfig, setInstrumentsConfig] = reactExports.useState({});
263  const [costumesConfig, setCostumesConfig] = reactExports.useState({});
264  const [stageConfig, setStageConfig] = reactExports.useState(defaultStageConfig);
265  const [actionsConfig, setActionsConfig] = reactExports.useState({});
266  const [instPreviewCharacter, setInstPreviewCharacter] = reactExports.useState(false);
267  const [instPreviewAnimal, setInstPreviewAnimal] = reactExports.useState("fox");
268  const [instPreviewAnimating, setInstPreviewAnimating] = reactExports.useState(true);
269  const [openTransformCards, setOpenTransformCards] = reactExports.useState({});
270  const [spBackgroundConfig, setSpBackgroundConfig] = reactExports.useState(defaultBackgroundConfig);
271  const [spBackgroundPresets, setSpBackgroundPresets] = reactExports.useState([]);
272  const [sharedBackgroundConfig, setSharedBackgroundConfig] = reactExports.useState(defaultBackgroundConfig);
273  const [sharedBackgroundPresets, setSharedBackgroundPresets] = reactExports.useState(defaultBackgroundPresets);
274  const [customBackgrounds, setCustomBackgrounds] = reactExports.useState([]);
275  const [uploadedCostumesList, setUploadedCostumesList] = reactExports.useState([]);
276  const fileInputRef = reactExports.useRef(null);
277  const [selectedCostumeCategory, setSelectedCostumeCategory] = reactExports.useState("all");
278  const [selectedCostumeId, setSelectedCostumeId] = reactExports.useState("stan_beanie");
279  const [fittingAnimalId, setFittingAnimalId] = reactExports.useState("fox");
280  const [fittingPose, setFittingPose] = reactExports.useState("standard");
281  const [fittingAnimating, setFittingAnimating] = reactExports.useState(true);
282  const [costumeSearch, setCostumeSearch] = reactExports.useState("");
283  const allCostumesMap = reactExports.useMemo(() => {
284    const map = { ...DEFAULT_SOUTHPARK_COSTUMES };
285    Object.entries(costumesConfig || {}).forEach(([id, def]) => {
286      map[id] = {
287        ...map[id] || {},
288        ...def
289      };
290    });
291    uploadedCostumesList.forEach((url) => {
292      const filename = url.split("/").pop() || "";
293      const id = filename.replace(/\.[^/.]+$/, "");
294      if (!map[id]) {
295        let type = "hat";
296        if (id.includes("glasses") || id.includes("sunglasses") || id.includes("eye")) type = "glasses";
297        else if (id.includes("tie") || id.includes("scarf") || id.includes("chain") || id.includes("bandana")) type = "neck";
298        else if (id.includes("vest") || id.includes("suit") || id.includes("shirt") || id.includes("parka") || id.includes("jacket") || id.includes("cape")) type = "body";
299        map[id] = {
300          id,
301          name: id.split("_").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" "),
302          url,
303          type,
304          offsetX: 0,
305          offsetY: type === "hat" ? -36 : type === "glasses" ? 6 : type === "neck" ? 12 : 2,
306          scale: 1,
307          rotation: 0,
308          anchorTo: type === "hat" || type === "glasses" ? "head" : "body"
309        };
310      }
311    });
312    return map;
313  }, [costumesConfig, uploadedCostumesList]);
314  const activeCostumeDef = reactExports.useMemo(() => {
315    return allCostumesMap[selectedCostumeId] || allCostumesMap.stan_beanie || Object.values(allCostumesMap)[0];
316  }, [allCostumesMap, selectedCostumeId]);
317  const updateActiveCostume = (key, value) => {
318    if (!activeCostumeDef) return;
319    const cid = activeCostumeDef.id;
320    setCostumesConfig((prev) => ({
321      ...prev,
322      [cid]: {
323        ...activeCostumeDef,
324        [key]: value
325      }
326    }));
327  };
328  const resetActiveCostume = () => {
329    if (!activeCostumeDef) return;
330    const cid = activeCostumeDef.id;
331    const defaultDef = DEFAULT_SOUTHPARK_COSTUMES[cid];
332    setCostumesConfig((prev) => {
333      const copy = { ...prev };
334      if (defaultDef) {
335        copy[cid] = { ...defaultDef };
336      } else {
337        delete copy[cid];
338      }
339      return copy;
340    });
341  };
342  const [instSearch, setInstSearch] = reactExports.useState("");
343  const [instCatFilter, setInstCatFilter] = reactExports.useState("all");
344  const getCategoryName = (idx) => {
345    if (idx === 128) return "Drums";
346    const cat = INSTRUMENT_CATEGORIES.find((c) => idx >= c.start && idx <= c.end);
347    return cat ? cat.name : "Other";
348  };
349  reactExports.useEffect(() => {
350    fetchConfigs();
351    fetchUploadedCostumes();
352  }, []);
353  const fetchConfigs = async () => {
354    setIsLoading(true);
355    setError(null);
356    try {
357      const [
358        charsRes,
359        instsRes,
360        costumesRes,
361        stageRes,
362        spBgRes,
363        spPresetsRes,
364        sharedBgRes,
365        sharedPresetsRes,
366        bgsRes,
367        actionsRes
368      ] = await Promise.all([
369        fetch("/api/admin/settings/southpark_characters_config", { headers: { "Authorization": "Bearer " + localStorage.getItem("admin_token") } }),
370        fetch("/api/admin/settings/southpark_instruments_config", { headers: { "Authorization": "Bearer " + localStorage.getItem("admin_token") } }),
371        fetch("/api/admin/settings/southpark_costumes_config", { headers: { "Authorization": "Bearer " + localStorage.getItem("admin_token") } }),
372        fetch("/api/admin/settings/southpark_stage_config", { headers: { "Authorization": "Bearer " + localStorage.getItem("admin_token") } }),
373        fetch("/api/admin/settings/southpark_background_config", { headers: { "Authorization": "Bearer " + localStorage.getItem("admin_token") } }),
374        fetch("/api/admin/settings/southpark_background_presets", { headers: { "Authorization": "Bearer " + localStorage.getItem("admin_token") } }),
375        fetch("/api/admin/settings/stage_background_config", { headers: { "Authorization": "Bearer " + localStorage.getItem("admin_token") } }),
376        fetch("/api/admin/settings/stage_background_presets", { headers: { "Authorization": "Bearer " + localStorage.getItem("admin_token") } }),
377        fetch("/api/admin/backgrounds", { headers: { "Authorization": "Bearer " + localStorage.getItem("admin_token") } }),
378        fetch("/api/admin/settings/southpark_actions_config", { headers: { "Authorization": "Bearer " + localStorage.getItem("admin_token") } })
379      ]);
380      const charsData = await charsRes.json();
381      const instsData = await instsRes.json();
382      const costumesData = await costumesRes.json();
383      const stageData = await stageRes.json();
384      const spBgData = spBgRes.ok ? await spBgRes.json() : null;
385      const spPresetsData = spPresetsRes.ok ? await spPresetsRes.json() : null;
386      const sharedBgData = sharedBgRes.ok ? await sharedBgRes.json() : null;
387      const sharedPresetsData = sharedPresetsRes.ok ? await sharedPresetsRes.json() : null;
388      const bgsData = bgsRes.ok ? await bgsRes.json() : [];
389      const actionsData = actionsRes.ok ? await actionsRes.json() : null;
390      if (charsData == null ? void 0 : charsData.value) setCharactersConfig(charsData.value);
391      if (instsData == null ? void 0 : instsData.value) setInstrumentsConfig(instsData.value);
392      if (costumesData == null ? void 0 : costumesData.value) setCostumesConfig(costumesData.value);
393      if (stageData == null ? void 0 : stageData.value) setStageConfig({ ...defaultStageConfig, ...stageData.value });
394      if (spBgData == null ? void 0 : spBgData.value) setSpBackgroun
394dConfig(spBgData.value);
395      if ((spPresetsData == null ? void 0 : spPresetsData.value) && Array.isArray(spPresetsData.value)) setSpBackgroundPresets(spPresetsData.value);
396      if (sharedBgData == null ? void 0 : sharedBgData.value) setSharedBackgroundConfig(sharedBgData.value);
397      if ((sharedPresetsData == null ? void 0 : sharedPresetsData.value) && Array.isArray(sharedPresetsData.value)) setSharedBackgroundPresets(sharedPresetsData.value);
398      if (Array.isArray(bgsData)) setCustomBackgrounds(bgsData);
399      if (actionsData == null ? void 0 : actionsData.value) setActionsConfig(actionsData.value);
400    } catch (err) {
401      console.error("Failed to load configs", err);
402      setError("Failed to load configurations.");
403    } finally {
404      setIsLoading(false);
405    }
406  };
407  const fetchUploadedCostumes = async () => {
408    try {
409      const res = await fetch("/api/admin/southpark-costumes", { headers: { "Authorization": "Bearer " + localStorage.getItem("admin_token") } });
410      const data = await res.json();
411      if (data.costumes) setUploadedCostumesList(data.costumes);
412    } catch (err) {
413      console.error("Failed to load costumes list", err);
414    }
415  };
416  const saveConfigs = async () => {
417    setIsSaving(true);
418    setError(null);
419    setSuccessMsg(null);
420    try {
421      await Promise.all([
422        fetch("/api/admin/settings/southpark_characters_config", {
423          method: "POST",
424          headers: { "Content-Type": "application/json", "Authorization": "Bearer " + localStorage.getItem("admin_token") },
425          body: JSON.stringify({ value: charactersConfig })
426        }),
427        fetch("/api/admin/settings/southpark_instruments_config", {
428          method: "POST",
429          headers: { "Content-Type": "application/json", "Authorization": "Bearer " + localStorage.getItem("admin_token") },
430          body: JSON.stringify({ value: instrumentsConfig })
431        }),
432        fetch("/api/admin/settings/southpark_costumes_config", {
433          method: "POST",
434          headers: { "Content-Type": "application/json", "Authorization": "Bearer " + localStorage.getItem("admin_token") },
435          body: JSON.stringify({ value: costumesConfig })
436        }),
437        fetch("/api/admin/settings/southpark_stage_config", {
438          method: "POST",
439          headers: { "Content-Type": "application/json", "Authorization": "Bearer " + localStorage.getItem("admin_token") },
440          body: JSON.stringify({ value: stageConfig })
441        }),
442        fetch("/api/admin/settings/southpark_background_config", {
443          method: "POST",
444          headers: { "Content-Type": "application/json", "Authorization": "Bearer " + localStorage.getItem("admin_token") },
445          body: JSON.stringify({ value: spBackgroundConfig })
446        }),
447        fetch("/api/admin/settings/southpark_background_presets", {
448          method: "POST",
449          headers: { "Content-Type": "application/json", "Authorization": "Bearer " + localStorage.getItem("admin_token") },
450          body: JSON.stringify({ value: spBackgroundPresets })
451        }),
452        fetch("/api/admin/settings/southpark_actions_config", {
453          method: "POST",
454          headers: { "Content-Type": "application/json", "Authorization": "Bearer " + localStorage.getItem("admin_token") },
455          body: JSON.stringify({ value: actionsConfig })
456        })
457      ]);
458      setSuccessMsg("Configuration saved successfully.");
459      setTimeout(() => setSuccessMsg(null), 3e3);
460    } catch (err) {
461      console.error("Failed to save configs", err);
462      setError("Failed to save configurations.");
463    } finally {
464      setIsSaving(false);
465    }
466  };
467  const handleCostumeUpload = async (e) => {
468    var _a;
469    const file = (_a = e.target.files) == null ? void 0 : _a[0];
470    if (!file) return;
471    const formData = new FormData();
472    formData.append("costume", file);
473    try {
474      const res = await fetch("/api/admin/upload-southpark-costume", {
475        method: "POST",
476        headers: { "Authorization": "Bearer " + localStorage.getItem("admin_token") },
477        body: formData
478      });
479      const data = await res.json();
480      if (data.url) {
481        setUploadedCostumesList((prev) => [...prev, data.url]);
482        setSuccessMsg("Costume uploaded!");
483        setTimeout(() => setSuccessMsg(null), 3e3);
484      } else {
485        setError("Upload failed.");
486      }
487    } catch (err) {
488      setError("Upload failed.");
489    }
490  };
491  const updateCharConfig = (animalId, key, value) => {
492    setCharactersConfig((prev) => ({
493      ...prev,
494      [animalId]: {
495        ...prev[animalId] || { animalId, scale: 1, headX: 0, headY: 0, armLeftX: 0, armLeftY: 0, armRightX: 0, armRightY: 0 },
496        [key]: value
497      }
498    }));
499  };
500  const filteredAnimals = Object.values(BASE_ANIMALS).filter(
501    (a) => selectedAnimalFilter === "all" || a.id === selectedAnimalFilter
502  );
503  const filteredPoses = ACTION_POSES.filter(
504    (p) => selectedPoseFilter === "all" || p.id === selectedPoseFilter
505  );
506  if (isLoading) {
507    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-8 text-zinc-400 flex items-center gap-2", children: [
508      /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "animate-spin" }),
509      " Loading South Park Studio..."
510    ] });
511  }
512  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col h-[calc(100vh-64px)] bg-zinc-950 text-zinc-100 overflow-hidden", children: [
513    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-none p-4 border-b border-zinc-800 bg-zinc-900/50 flex items-center justify-between", children: [
514      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
515        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-2 bg-indigo-500/20 text-indigo-400 rounded-lg", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Layers, { size: 20 }) }),
516        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
517          /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "text-xl font-bold", children: "South Park Studio" }),
518          /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-400", children: "Manage vector animal characters, action poses, costumes, and stage placement" })
519        ] })
520      ] }),
521      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-4", children: [
522        error && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm text-red-400", children: error }),
523        successMsg && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm text-emerald-400", children: successMsg }),
524        /* @__PURE__ */ jsxRuntimeExports.jsxs(
525          "button",
526          {
527            onClick: fetchConfigs,
528            className: "px-4 py-2 text-sm font-medium text-zinc-300 hover:text-white bg-zinc-800 hover:bg-zinc-700 rounded-lg flex items-center gap-2 transition-colors",
529            children: [
530              /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { size: 16 }),
531              " Revert"
532            ]
533          }
534        ),
535        /* @__PURE__ */ jsxRuntimeExports.jsxs(
536          "button",
537          {
538            onClick: saveConfigs,
539            disabled: isSaving,
540            className: "px-4 py-2 text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed rounded-lg flex items-center gap-2 transition-colors shadow-lg shadow-indigo-900/20",
541            children: [
542              isSaving ? /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { size: 16, className: "animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Save, { size: 16 }),
543              "Save All Changes"
544            ]
545          }
546        )
547      ] })
548    ] }),
549    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-1 overflow-hidden", children: [
550      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-64 border-r border-zinc-800 bg-zinc-900/30 flex flex-col p-4 gap-2 shrink-0", children: [
551        /* @__PURE__ */ jsxRuntimeExports.jsxs(
552          "button",
553          {
554            onClick: () => setActiveTab("actions_studio"),
555            className: `flex items-center gap-3 px-4 py-3 rounded-lg text-sm font-medium transition-colors ${activeTab === "actions_studio" ? "bg-indigo-500/20 text-indigo-400 font-semibold border border-indigo-500/30" : "text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800/50"}`,
556            children: [
557              /* @__PURE__ */ jsxRuntimeExports.jsx(SlidersVertical, { size: 18 }),
558              "Actions Studio"
559            ]
560          }
561        ),
562        /* @__PURE__ */ jsxRuntimeExports.jsxs(
563          "button",
564          {
565            onClick: () => setActiveTab("actions"),
566            className: `flex items-center gap-3 px-4 py-3 rounded-lg text-sm font-medium transition-colors ${activeTab === "actions" ? "bg-indigo-500/20 text-indigo-400 font-semibold border border-indigo-500/30" : "text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800/50"}`,
567            children: [
568              /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { size: 18 }),
569              "Character Action Poses"
570            ]
571          }
572        ),
573        /* @__PURE__ */ jsxRuntimeExports.jsxs(
574          "button",
575          {
576            onClick: () => setActiveTab("characters"),
577            className: `flex items-center gap-3 px-4 py-3 rounded-lg text-sm font-medium transition-colors ${activeTab === "characters" ? "bg-indigo-500/20 text-indigo-400 font-semibold border border-indigo-500/30" : "text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800/50"}`,
578            children: [
579              /* @__P
579URE__ */ jsxRuntimeExports.jsx(Users, { size: 18 }),
580              "Base Offsets Editor"
581            ]
582          }
583        ),
584        /* @__PURE__ */ jsxRuntimeExports.jsxs(
585          "button",
586          {
587            onClick: () => setActiveTab("instruments"),
588            className: `flex items-center gap-3 px-4 py-3 rounded-lg text-sm font-medium transition-colors ${activeTab === "instruments" ? "bg-indigo-500/20 text-indigo-400 font-semibold border border-indigo-500/30" : "text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800/50"}`,
589            children: [
590              /* @__PURE__ */ jsxRuntimeExports.jsx(Music, { size: 18 }),
591              "Instruments"
592            ]
593          }
594        ),
595        /* @__PURE__ */ jsxRuntimeExports.jsxs(
596          "button",
597          {
598            onClick: () => setActiveTab("costumes"),
599            className: `flex items-center gap-3 px-4 py-3 rounded-lg text-sm font-medium transition-colors ${activeTab === "costumes" ? "bg-indigo-500/20 text-indigo-400 font-semibold border border-indigo-500/30" : "text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800/50"}`,
600            children: [
601              /* @__PURE__ */ jsxRuntimeExports.jsx(Shirt, { size: 18 }),
602              "Costumes"
603            ]
604          }
605        ),
606        /* @__PURE__ */ jsxRuntimeExports.jsxs(
607          "button",
608          {
609            onClick: () => setActiveTab("stage"),
610            className: `flex items-center gap-3 px-4 py-3 rounded-lg text-sm font-medium transition-colors ${activeTab === "stage" ? "bg-indigo-500/20 text-indigo-400 font-semibold border border-indigo-500/30" : "text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800/50"}`,
611            children: [
612              /* @__PURE__ */ jsxRuntimeExports.jsx(Monitor, { size: 18 }),
613              "Stage & Layout"
614            ]
615          }
616        ),
617        /* @__PURE__ */ jsxRuntimeExports.jsxs(
618          "button",
619          {
620            onClick: () => setActiveTab("preview"),
621            className: `flex items-center gap-3 px-4 py-3 rounded-lg text-sm font-medium transition-colors ${activeTab === "preview" ? "bg-indigo-500/20 text-indigo-400 font-semibold border border-indigo-500/30" : "text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800/50"}`,
622            children: [
623              /* @__PURE__ */ jsxRuntimeExports.jsx(CirclePlay, { size: 18 }),
624              "Live Preview"
625            ]
626          }
627        )
628      ] }),
629      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-auto p-6 bg-zinc-950", children: [
630        activeTab === "actions_studio" && /* @__PURE__ */ jsxRuntimeExports.jsx(
631          SouthparkActionsStudio,
632          {
633            actionsConfig,
634            onChangeActionsConfig: setActionsConfig,
635            instrumentsConfig,
636            charactersConfig,
637            costumesConfig,
638            onSave: saveConfigs,
639            isSaving
640          }
641        ),
642        activeTab === "actions" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-8", children: [
643          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl p-5 shadow-xl", children: [
644            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col lg:flex-row lg:items-center justify-between gap-4 border-b border-zinc-800 pb-4 mb-4", children: [
645              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
646                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
647                  /* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { className: "text-indigo-400", size: 22 }),
648                  /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-xl font-bold text-white tracking-wide", children: "Character Action Poses" }),
649                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "px-2.5 py-0.5 rounded-full text-xs font-semibold bg-indigo-500/20 text-indigo-300 border border-indigo-500/30", children: "Live Kinematics Matrix" })
650                ] }),
651                /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-400 mt-1", children: "Real-time articulated multi-piece limb rendering with spring physics across all 6 performance hold styles" })
652              ] }),
653              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
654                /* @__PURE__ */ jsxRuntimeExports.jsxs(
655                  "button",
656                  {
657                    onClick: () => setIsGlobalAnimating(!isGlobalAnimating),
658                    className: `px-4 py-2 rounded-lg text-xs font-bold flex items-center gap-2 transition-all ${isGlobalAnimating ? "bg-emerald-500/20 text-emerald-400 border border-emerald-500/40 hover:bg-emerald-500/30" : "bg-zinc-800 text-zinc-400 border border-zinc-700 hover:bg-zinc-700"}`,
659                    children: [
660                      isGlobalAnimating ? /* @__PURE__ */ jsxRuntimeExports.jsx(Pause, { size: 14 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Play, { size: 14 }),
661                      isGlobalAnimating ? "Animation Playing" : "Animation Paused"
662                    ]
663                  }
664                ),
665                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 bg-zinc-950 px-3 py-1.5 rounded-lg border border-zinc-800", children: [
666                  /* @__PURE__ */ jsxRuntimeExports.jsx(SlidersVertical, { size: 14, className: "text-indigo-400" }),
667                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-zinc-400 font-medium", children: "Velocity:" }),
668                  /* @__PURE__ */ jsxRuntimeExports.jsx(
669                    "input",
670                    {
671                      type: "range",
672                      min: "20",
673                      max: "127",
674                      value: globalVelocity,
675                      onChange: (e) => setGlobalVelocity(parseInt(e.target.value)),
676                      className: "w-24 accent-indigo-500 cursor-pointer"
677                    }
678                  ),
679                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-white font-mono w-6 text-right", children: globalVelocity })
680                ] }),
681                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 bg-zinc-950 px-3 py-1.5 rounded-lg border border-zinc-800", children: [
682                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-zinc-400 font-medium", children: "Tempo:" }),
683                  /* @__PURE__ */ jsxRuntimeExports.jsxs(
684                    "select",
685                    {
686                      className: "bg-transparent text-xs text-white outline-none cursor-pointer",
687                      value: pulseIntervalMs,
688                      onChange: (e) => setPulseIntervalMs(parseInt(e.target.value)),
689                      children: [
690                        /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "250", className: "bg-zinc-900", children: "Fast (250ms)" }),
691                        /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "500", className: "bg-zinc-900", children: "Normal (500ms)" }),
692                        /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "800", className: "bg-zinc-900", children: "Slow (800ms)" })
693                      ]
694                    }
695                  )
696                ] }),
697                /* @__PURE__ */ jsxRuntimeExports.jsxs(
698                  "button",
699                  {
700                    onClick: () => setShowInstruments((prev) => !prev),
701                    className: `flex items-center gap-2 px-3 py-1.5 rounded-lg border text-xs font-semibold transition-all ${showInstruments ? "bg-amber-500/20 text-amber-300 border-amber-500/40 hover:bg-amber-500/30 shadow-sm" : "bg-zinc-950 text-zinc-400 border-zinc-800 hover:bg-zinc-800 hover:text-zinc-200"}`,
702                    title: "Toggle instrument visibility in character poses",
703                    children: [
704                      showInstruments ? /* @__PURE__ */ jsxRuntimeExports.jsx(Music, { size: 14, className: "text-amber-400" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(EyeOff, { size: 14, className: "text-zinc-500" }),
705                      /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
706                        "Instruments: ",
707                        /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: showInstruments ? "text-amber-300" : "text-zinc-400", children: showInstruments ? "ON" : "OFF" })
708                      ] })
709                    ]
710                  }
711                ),
712                /* @__PURE__ */ jsxRuntimeExports.jsxs(
713                  "button",
714                  {
715                    onClick: () => setShowSkeletonOverlay((prev) => !prev),
716                    className: `flex items-center gap-2 px-3 py-1.5 rounded-lg border text-xs font-semibold transition-all ${showSkeletonOverlay ? "bg-cyan-500/20 text-cyan-300 border-cyan-500/40 hover:bg-cyan-500/30 shadow-sm" : "bg-zinc-950 text-zinc-400 border-zinc-800 hover:bg-zinc-800 hover:text-zinc-200"}`,
717                    title: "Toggle kinematic skeleton wireframe overlay across all characters",
718                    children: [
719                      /* @__P
719URE__ */ jsxRuntimeExports.jsx(Activity, { size: 14, className: showSkeletonOverlay ? "text-cyan-400" : "text-zinc-500" }),
720                      /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
721                        "Skeleton Overlay: ",
722                        /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: showSkeletonOverlay ? "text-cyan-300" : "text-zinc-400", children: showSkeletonOverlay ? "ON" : "OFF" })
723                      ] })
724                    ]
725                  }
726                )
727              ] })
728            ] }),
729            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-4 text-xs", children: [
730              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
731                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 font-medium", children: "Filter Animal:" }),
732                /* @__PURE__ */ jsxRuntimeExports.jsxs(
733                  "select",
734                  {
735                    className: "bg-zinc-950 border border-zinc-800 text-zinc-200 rounded px-2.5 py-1.5",
736                    value: selectedAnimalFilter,
737                    onChange: (e) => setSelectedAnimalFilter(e.target.value),
738                    children: [
739                      /* @__PURE__ */ jsxRuntimeExports.jsxs("option", { value: "all", children: [
740                        "All Characters (",
741                        Object.keys(BASE_ANIMALS).length,
742                        ")"
743                      ] }),
744                      Object.values(BASE_ANIMALS).map((a) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: a.id, children: a.name }, a.id))
745                    ]
746                  }
747                )
748              ] }),
749              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
750                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 font-medium", children: "Filter Pose:" }),
751                /* @__PURE__ */ jsxRuntimeExports.jsxs(
752                  "select",
753                  {
754                    className: "bg-zinc-950 border border-zinc-800 text-zinc-200 rounded px-2.5 py-1.5",
755                    value: selectedPoseFilter,
756                    onChange: (e) => setSelectedPoseFilter(e.target.value),
757                    children: [
758                      /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "all", children: "All Action Poses (6)" }),
759                      ACTION_POSES.map((p) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: p.id, children: p.name }, p.id))
760                    ]
761                  }
762                )
763              ] }),
764              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 bg-zinc-950 border border-zinc-800 rounded px-1.5 py-1", children: [
765                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 font-medium px-1", children: "Coat Variant:" }),
766                [
767                  { idx: 0, label: "Lead (1)" },
768                  { idx: 1, label: "Rhythm (2)" },
769                  { idx: 2, label: "Sub-3 (3)" },
770                  { idx: 3, label: "Proc 4+" }
771                ].map((v) => /* @__PURE__ */ jsxRuntimeExports.jsx(
772                  "button",
773                  {
774                    onClick: () => {
775                      setGlobalVariantIndex(v.idx);
776                      setPreviewVariants({});
777                    },
778                    className: `px-2 py-0.5 rounded text-[11px] font-semibold transition-all ${globalVariantIndex === v.idx || globalVariantIndex === null && v.idx === 0 && Object.keys(previewVariants).length === 0 ? "bg-indigo-600 text-white" : "text-zinc-400 hover:text-zinc-200"}`,
779                    children: v.label
780                  },
781                  v.idx
782                ))
783              ] }),
784              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 bg-zinc-950 border border-zinc-800 rounded px-1.5 py-1", children: [
785                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 font-medium px-1", children: "Poses Grid:" }),
786                /* @__PURE__ */ jsxRuntimeExports.jsx(
787                  "button",
788                  {
789                    onClick: () => setActionPosesCols("compact"),
790                    className: `px-2 py-0.5 rounded text-[11px] font-semibold transition-all ${actionPosesCols === "compact" ? "bg-zinc-800 text-white" : "text-zinc-400 hover:text-zinc-200"}`,
791                    children: "6 Cols"
792                  }
793                ),
794                /* @__PURE__ */ jsxRuntimeExports.jsx(
795                  "button",
796                  {
797                    onClick: () => setActionPosesCols("large"),
798                    className: `px-2 py-0.5 rounded text-[11px] font-semibold transition-all ${actionPosesCols === "large" ? "bg-zinc-800 text-white" : "text-zinc-400 hover:text-zinc-200"}`,
799                    children: "3 Cols"
800                  }
801                )
802              ] }),
803              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 bg-zinc-950 border border-zinc-800 px-2.5 py-1 rounded-lg text-xs font-mono", children: [
804                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400 text-[11px] font-sans", children: "Zoom:" }),
805                /* @__PURE__ */ jsxRuntimeExports.jsx(
806                  "button",
807                  {
808                    onClick: () => setActionPosesZoom((z) => Math.max(1, parseFloat((z - 0.25).toFixed(2)))),
809                    className: "p-1 rounded hover:bg-zinc-800 text-zinc-300 transition-colors",
810                    title: "Zoom Out",
811                    children: /* @__PURE__ */ jsxRuntimeExports.jsx(ZoomOut, { size: 13 })
812                  }
813                ),
814                /* @__PURE__ */ jsxRuntimeExports.jsx(
815                  "input",
816                  {
817                    type: "range",
818                    min: "1.0",
819                    max: "4.0",
820                    step: "0.25",
821                    value: actionPosesZoom,
822                    onChange: (e) => setActionPosesZoom(parseFloat(e.target.value)),
823                    className: "w-16 accent-indigo-400 h-1.5 bg-zinc-800 rounded-lg cursor-pointer",
824                    title: `Zoom: ${Math.round(actionPosesZoom * 100)}%`
825                  }
826                ),
827                /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-indigo-300 font-bold min-w-[42px] text-right", children: [
828                  Math.round(actionPosesZoom * 100),
829                  "%"
830                ] }),
831                /* @__PURE__ */ jsxRuntimeExports.jsx(
832                  "button",
833                  {
834                    onClick: () => setActionPosesZoom((z) => Math.min(4, parseFloat((z + 0.25).toFixed(2)))),
835                    className: "p-1 rounded hover:bg-zinc-800 text-zinc-300 transition-colors",
836                    title: "Zoom In",
837                    children: /* @__PURE__ */ jsxRuntimeExports.jsx(ZoomIn, { size: 13 })
838                  }
839                ),
840                /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1 ml-1 border-l border-zinc-800 pl-1.5 font-sans", children: [1, 1.75, 2.5, 3.5].map((preset) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
841                  "button",
842                  {
843                    onClick: () => setActionPosesZoom(preset),
844                    className: `px-1.5 py-0.5 rounded text-[10px] font-bold ${actionPosesZoom === preset ? "bg-indigo-500/30 text-indigo-200 border border-indigo-400/50" : "text-zinc-400 hover:text-indigo-300"}`,
845                    children: [
846                      preset,
847                      "x"
848                    ]
849                  },
850                  preset
851                )) })
852              ] }),
853              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ml-auto flex items-center gap-2 text-zinc-400 text-xs", children: [
854                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-block w-2 h-2 rounded-full bg-emerald-400 animate-ping" }),
855                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-emerald-300", children: "Natural Joint Limits Active: L-Elbow [-170°, 0°] • R-Elbow [0°, +170°]" })
856              ] })
857            ] })
858          ] }),
859          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-8", children: [
860            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-gradient-to-r from-zinc-900/90 via-cyan-950/30 to-zinc-900/90 border border-cyan-800/50 rounded-2xl p-6 space-y-4 shadow-2xl", children: [
861              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col xl:flex-row xl:items-center justify-between border-b border-cyan-900/40 pb-4 gap-3", children: [
862                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
863                  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-9 h-9 rounded-lg bg-cyan-500/20 text-cyan-400 flex items-center justify-center font-bold text-lg border border-cyan-500/30 shadow-inner", children: "🦴" }),
864                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
865                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
866                      /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "font-bold text-base text-cyan-200 tracking-wide uppercase", children: "Kinematic Skeleton Frames" }),
867                      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "px-2 py-0.5 rounded text-[10px] font-bold bg-cyan-500/10 text-cyan-400 border border-cyan-500/30", children: "ANATOMICAL SKELETON ROW" })
868                    ] }),
869                    /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-zinc-400", children: "Pure wireframe skeletons demonstrating 0.0000px joint socket connectivity, real-time 2-bone IK solvers, and natural angle limits" })
870                  ] })
871                ] }),
872                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
873                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 bg-zinc-950/80 px-2.5 py-1 rounded-lg border border-cyan-900/40 text-xs", children: [
874                    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 text-[11px] font-medium", children: "Model:" }),
875                    Object.values(BASE_ANIMALS).map((a) => /* @__PURE__ */ jsxRuntimeExports.jsx(
876                      "button",
877                      {
878                        onClick: () => setSkeletonAnimalBase(a.id),
879                        className: `px-2 py-0.5 rounded text-[11px] font-bold transition-all ${skeletonAnimalBase === a.id ? "bg-cyan-500 text-black shadow-sm" : "text-zinc-400 hover:text-cyan-300 hover:bg-cyan-950/50"}`,
880                        children: a.name
881                      },
882                      a.id
883                    ))
884                  ] }),
885                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 bg-zinc-950/80 p-0.5 rounded-lg border border-cyan-900/40 text-xs", children: [
886                    /* @__PURE__ */ jsxRuntimeExports.jsx(
887                      "button",
888                      {
889                        onClick: () => setSkeletonDisplayMode("pure"),
890                        className: `px-2 py-1 rounded text-[11px] font-semibold transition-all ${skeletonDisplayMode === "pure" ? "bg-cyan-950 text-cyan-300 border border-cyan-700/50" : "text-zinc-400 hover:text-zinc-200"}`,
891                        title: "Pure Wireframe Skeleton with joint nodes only",
892                        children: "Pure Skeleton"
893                      }
894                    ),
895                    /* @__PURE__ */ jsxRuntimeExports.jsx(
896                      "button",
897                      {
898                        onClick: () => setSkeletonDisplayMode("ghost"),
899                        className: `px-2 py-1 rounded text-[11px] font-semibold transition-all ${skeletonDisplayMode === "ghost" ? "bg-cyan-950 text-cyan-300 border border-cyan-700/50" : "text-zinc-400 hover:text-zinc-200"}`,
900                        title: "Wireframe Skeleton with translucent body silhouette",
901                        children: "+ Silhouette"
902                      }
903                    ),
904                    /* @__PURE__ */ jsxRuntimeExports.jsx(
905                      "button",
906                      {
907                        onClick: () => setSkeletonDisplayMode("full"),
908                        className: `px-2 py-1 rounded text-[11px] font-semibold transition-all ${skeletonDisplayMode === "full" ? "bg-cyan-950 text-cyan-300 border border-cyan-700/50" : "text-zinc-400 hover:text-zinc-200"}`,
909                        title: "Full graphic character with skeleton overlay",
910                        children: "+ Full Graphic"
911                      }
912                    )
913                  ] }),
914                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 bg-zinc-950/80 p-0.5 rounded-lg border border-cyan-900/40 text-xs", children: [
915                    /* @__PURE__ */ jsxRuntimeExports.jsx(
916                      "button",
917                      {
918                        onClick: () => setSkeletonGridSize("compact"),
919                        className: `px-2 py-1 rounded text-[11px] font-semibold transition-all ${skeletonGridSize === "compact" ? "bg-cyan-950 text-cyan-300 border border-cyan-700/50" : "text-zinc-400 hover:text-zinc-200"}`,
920                        title: "Compact 6-column view",
921                        children: "6 Cards"
922                      }
923                    ),
924                    /* @__PURE__ */ jsxRuntimeExports.jsx(
925                      "button",
926                      {
927                        onClick: () => setSkeletonGridSize("large"),
928                        className: `px-2 py-1 rounded text-[11px] font-semibold transition-all ${skeletonGridSize === "large" ? "bg-cyan-950 text-cyan-300 border border-cyan-700/50" : "text-zinc-400 hover:text-zinc-200"}`,
929                        title: "Large 3-column expanded cards",
930                        children: "3 Large"
931                      }
932                    ),
933                    /* @__PURE__ */ jsxRuntimeExports.jsx(
934                      "button",
935                      {
936                        onClick: () => setSkeletonGridSize("jumbo"),
937                        className: `px-2 py-1 rounded text-[11px] font-semibold transition-all ${skeletonGridSize === "jumbo" ? "bg-cyan-950 text-cyan-300 border border-cyan-700/50" : "text-zinc-400 hover:text-zinc-200"}`,
938                        title: "Jumbo 2-column macro cards",
939                        children: "2 Jumbo"
940                      }
941                    )
942                  ] }),
943                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 bg-zinc-950/80 px-2.5 py-1 rounded-lg border border-cyan-900/40 text-xs font-mono", children: [
944                    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400 text-[11px] font-sans", children: "Zoom:" }),
945                    /* @__PURE__ */ jsxRuntimeExports.jsx(
946                      "button",
947                      {
948                        onClick: () => setSkeletonZoom((z) => Math.max(1, parseFloat((z - 0.25).toFixed(2)))),
949                        className: "p-1 rounded hover:bg-cyan-950 text-cyan-400 transition-colors",
950                        title: "Zoom Out",
951                        children: /* @__PURE__ */ jsxRuntimeExports.jsx(ZoomOut, { size: 13 })
952                      }
953                    ),
954                    /* @__PURE__ */ jsxRuntimeExports.jsx(
955                      "input",
956                      {
957                        type: "range",
958                        min: "1.0",
959                        max: "4.0",
960                        step: "0.25",
961                        value: skeletonZoom,
962                        onChange: (e) => setSkeletonZoom(parseFloat(e.target.value)),
963                        className: "w-16 accent-cyan-400 h-1.5 bg-zinc-800 rounded-lg cursor-pointer",
964                        title: `Zoom: ${Math.round(skeletonZoom * 100)}%`
965                      }
966                    ),
967                    /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-cyan-300 font-bold min-w-[42px] text-right", children: [
968                      Math.round(skeletonZoom * 100),
969                      "%"
970                    ] }),
971                    /* @__PURE__ */ jsxRuntimeExports.jsx(
972                      "button",
973                      {
974                        onClick: () => setSkeletonZoom((z) => Math.min(4, parseFloat((z + 0.25).toFixed(2)))),
975                        className: "p-1 rounded hover:bg-cyan-950 text-cyan-400 transition-colors",
976                        title: "Zoom In",
977                        children: /* @__PURE__ */ jsxRuntimeExports.jsx(ZoomIn, { size: 13 })
978                      }
979                    ),
980                    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1 ml-1 border-l border-cyan-900/50 pl-1.5 font-sans", children: [1, 1.75, 2.5, 3.5].map((preset) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
981                      "button",
982                      {
983                        onClick: () => setSkeletonZoom(preset),
984                        className: `px-1.5 py-0.5 rounded text-[10px] font-bold ${skeletonZoom === preset ? "bg-cyan-500/30 text-cyan-200 border border-cyan-400/50" : "text-zinc-400 hover:text-cyan-300"}`,
985                        children: [
986                          preset,
987                          "x"
988                        ]
989                      },
990                      preset
991                    )) })
992                  ] })
993                ] })
994              ] }),
995              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center justify-between text-xs text-zinc-400 bg-cyan-950/20 px-3 py-1.5 rounded-lg border border-cyan-900/30", children: [
996                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
997                  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-cyan-300/80 font-mono", children: [
998                    "Left Elbow: ",
999                    /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "text-emerald-400", children: "[-170°, 0°]" }),
1000                    " • Right Elbow: ",
1001                    /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "text-purple-400", children: "[0°, +170°]" })
1002                  ] }),
1003                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-600", children: "|" }),
1004                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400/90 font-mono text-[11px]", children: "All Joint Sockets: 0.0000px displacement (Physically Locked)" })
1005                ] }),
1006                /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[11px] text-cyan-400/90 flex items-center gap-1 font-medium", children: [
1007                  /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { size: 12 }),
1008                  " Click any pose card to open the High-Resolution Joint Inspector Modal"
1009                ] })
1010              ] }),
1011              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `grid gap-4 ${skeletonGridSize === "compact" ? "grid-cols-2 md:grid-cols-3 xl:grid-cols-6" : skeletonGridSize === "large" ? "grid-cols-1 md:grid-cols-2 xl:grid-cols-3" : "grid-cols-1 md:grid-cols-2"}`, children: filteredPoses.map((pose) => {
1012                const isPoseActive = isGlobalAnimating && pose.id !== "standard" && currentVelocityPulse > 0;
1013                const skeletonAnimal = BASE_ANIMALS[skeletonAnimalBase] || filteredAnimals[0] || BASE_ANIMALS.fox;
1014                return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1015                  "div",
1016                  {
1017                    onClick: () => {
1018                      setInspectingPose(pose);
1019                      setInspectorAnimalId(skeletonAnimalBase);
1020                    },
1021                    className: "bg-zinc-950/90 border border-cyan-900/30 rounded-xl p-3.5 flex flex-col items-center gap-3 transition-all hover:border-cyan-400/70 hover:shadow-cyan-950/50 hover:shadow-2xl group cursor-pointer relative",
1022                    children: [
1023                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full flex items-center justify-between", children: [
1024                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `px-2 py-0.5 rounded text-[11px] font-bold border ${pose.badgeColor}`, children: pose.name }),
1025                        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-1.5 py-0.5 text-[9px] font-mono rounded bg-cyan-950 text-cyan-400 border border-cyan-800/50 flex items-center gap-1 group-hover:bg-cyan-900 group-hover:text-cyan-200 transition-colors", children: [
1026                          /* @__PURE__ */ jsxRuntimeExports.jsx(Maximize2, { size: 9 }),
1027                          " INSPECT"
1028                        ] })
1029                      ] }),
1030                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full aspect-square bg-zinc-950 rounded-lg flex items-center justify-center relative overflow-hidden border border-cyan-900/40 shadow-inner group-hover:border-cyan-500/40 transition-colors", children: [
1031                        /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { viewBox: getDynamicViewBox(skeletonZoom), className: "w-full h-full overflow-visible drop-shadow-2xl", children: /* @__PURE__ */ jsxRuntimeExports.jsx("g", { transform: "translate(100, 155)", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1032                          SouthparkCharacter,
1033                          {
1034                            animal: skeletonAnimal,
1035                            customConfig: charactersConfig[skeletonAnimal.id],
1036                            instrument: {
1037                              id: 1,
1038                              name: pose.name,
1039                              type: "preview",
1040                              holdStyle: pose.holdStyle,
1041                              group: "Preview",
1042                              imgUrl: POSE_INSTRUMENTS_IMG[pose.id] || void 0,
1043                              svgContent: void 0
1044                            },
1045                            isActive: isPoseActive,
1046                            velocity: isPoseActive ? currentVelocityPulse : 0,
1047                            physicsMode: "smooth",
1048                            showInstrument: false,
1049                            skeletonOnly: skeletonDisplayMode !== "full",
1050                            ghostSilhouette: skeletonDisplayMode === "ghost",
1051                            showSkeleton: true
1052                          }
1053                        ) }) }),
1054                        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 bg-cyan-950/30 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-2.5 py-1 rounded-full bg-cyan-900/90 border border-cyan-400/60 text-cyan-200 text-xs font-bold shadow-lg flex items-center gap-1.5", children: [
1055                          /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { size: 12 }),
1056                          " Inspect Joint Sockets"
1057                        ] }) })
1058                      ] }),
1059                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full text-[10px] font-mono text-zinc-400 text-center space-y-0.5 bg-zinc-900/60 p-1.5 rounded border border-zinc-800/60 group-hover:border-cyan-800/60 transition-colors", children: [
1060                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-zinc-300 font-semibold", children: [
1061                          pose.name,
1062                          " Rig"
1063                        ] }),
1064                        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-emerald-400/90 font-bold", children: "Socket Dist: 0.0000px [LOCKED]" })
1065                      ] })
1066                    ]
1067                  },
1068                  `skeleton-${pose.id}`
1069                );
1070              }) })
1071            ] }),
1072            filteredAnimals.map((animal) => {
1073              const conf = charactersConfig[animal.id] || {
1074                animalId: animal.id,
1075                scale: 1,
1076                headX: 0,
1077                headY: 0,
1078                armLeftX: 0,
1079                armLeftY: 0,
1080                armRightX: 0,
1081                armRightY: 0
1082              };
1083              return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900/60 border border-zinc-800/80 rounded-2xl p-6 space-y-4", children: [
1084                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between border-b border-zinc-800/60 pb-3", children: [
1085                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
1086                    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-8 h-8 rounded-lg bg-indigo-600/20 text-indigo-400 flex items-center justify-center font-bold text-sm", children: animal.name.charAt(0) }),
1087                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1088                      /* @__PURE__ */ jsxRuntimeExports.jsxs("h3", { className: "font-bold text-base text-white tracking-wide uppercase", children: [
1089                        animal.name,
1090                        " - Action Poses"
1091                      ] }),
1092                      /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[11px] text-zinc-400", children: [
1093                        "Scale: ",
1094                        conf.scale,
1095                        " • Head Offset: (",
1096                        conf.headX,
1097                        ", ",
1098                        conf.headY,
1099                        ") • Sockets: L(",
1100                        conf.armLeftX,
1101                        ", ",
1102                        conf.armLeftY,
1103                        ") R(",
1104                        conf.armRightX,
1105                        ", ",
1106                        conf.armRightY,
1107                        ")"
1108                      ] })
1109                    ] })
1110                  ] }),
1111                  /* @__PURE__ */ jsxRuntimeExports.jsxs(
1112                    "button",
1113                    {
1114                      onClick: () => setActiveTab("characters"),
1115                      className: "px-3 py-1.5 text-xs text-indigo-300 hover:text-white bg-indigo-950/40 hover:bg-indigo-900/60 border border-indigo-800/40 rounded-lg flex items-center gap-1.5 transition-all",
1116                      children: [
1117                        /* @__PURE__ */ jsxRuntimeExports.jsx(PenLine, { size: 13 }),
1118                        " Edit Offsets"
1119                      ]
1120                    }
1121                  )
1122                ] }),
1123                /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `grid gap-4 ${actionPosesCols === "compact" ? "grid-cols-2 md:grid-cols-3 xl:grid-cols-6" : "grid-cols-1 md:grid-cols-2 xl:grid-cols-3"}`, children: filteredPoses.map((pose) => {
1124                  const isPoseActive = isGlobalAnimating && pose.id !== "standard" && currentVelocityPulse > 0;
1125                  const variantIdx = previewVariants[animal.id] ?? (globalVariantIndex ?? 0);
1126                  const currentVariant = getAnimalVariant(animal.id, variantIdx, animal.sleeveColor);
1127                  const filterId = `actions-filter-${animal.id}-${pose.id}-${variantIdx}`;
1128                  const filterSvg = getVariantFilterSvg(filterId, currentVariant);
1129                  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1130                    "div",
1131                    {
1132                      onClick: () => {
1133                        setInspectingPose(pose);
1134                        setInspectorAnimalId(animal.id);
1135                      },
1136                      className: "bg-zinc-950 border border-zinc-800 rounded-xl p-3.5 flex flex-col items-center gap-3 transition-all hover:border-indigo-500/50 hover:shadow-xl group cursor-pointer",
1137                      title: `Click to inspect ${animal.name} (${currentVariant.label}) in ${pose.name} pose up close`,
1138                      children: [
1139                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full flex items-center justify-between", children: [
1140                          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `px-2 py-0.5 rounded text-[11px] font-bold border ${pose.badgeColor}`, children: pose.name }),
1141                          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5", children: [
1142                            /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-1 py-0.5 text-[8px] font-mono rounded bg-zinc-900 text-zinc-400 border border-zinc-800 flex items-center gap-0.5 group-hover:text-indigo-300 group-hover:border-indigo-700/50 transition-colors", children: [
1143                              /* @__PURE__ */ jsxRuntimeExports.jsx(Maximize2, { size: 8 }),
1144                              " INSPECT"
1145                            ] }),
1146                            isPoseActive ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-2 h-2 rounded-full bg-emerald-400 animate-pulse", title: "Spring Kinematics Active" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-2 h-2 rounded-full bg-zinc-700", title: "Stationary" })
1147                          ] })
1148                        ] }),
1149                        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full aspect-square bg-zinc-900/50 rounded-lg flex items-center justify-center relative overflow-hidden border border-zinc-800/50", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: getDynamicViewBox(actionPosesZoom), className: "w-full h-full overflow-visible drop-shadow-2xl", children: [
1150                          filterSvg && /* @__PURE__ */ jsxRuntimeExports.jsx("defs", { dangerouslySetInnerHTML: { __html: filterSvg } }),
1151                          /* @__PURE__ */ jsxRuntimeExports.jsx("g", { transform: "translate(100, 155)", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1152                            SouthparkCharacter,
1153                            {
1154                              animal,
1155                              variant: currentVariant,
1156                              variantFilterId: filterSvg ? filterId : void 0,
1157                              instrument: {
1158                                id: 1,
1159                                name: pose.name,
1160                                type: "preview",
1161                                holdStyle: pose.holdStyle,
1162                                group: "Preview",
1163                                imgUrl: POSE_INSTRUMENTS_IMG[pose.id] || void 0,
1164                                svgContent: void 0
1165                              },
1166                              isActive: isPoseActive,
1167                              velocity: isPoseActive ? currentVelocityPulse : 0,
1168                              physicsMode: "smooth",
1169                              customConfig: conf,
1170                              showInstrument: showInstruments,
1171                              showSkeleton: showSkeletonOverlay
1172                            }
1173                          ) })
1174                        ] }) }),
1175                        /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-zinc-400 text-center leading-tight min-h-[32px] flex items-center justify-center", children: pose.desc })
1176                      ]
1177                    },
1178                    pose.id
1179                  );
1180                }) })
1181              ] }, animal.id);
1182            })
1183          ] })
1184        ] }),
1185        activeTab === "characters" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
1186          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col md:flex-row md:items-center justify-between gap-4 border-b border-zinc-800 pb-3 mb-4", children: [
1187            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1188              /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-xl font-bold", children: "Base Character Offsets & Duplicate Variants" }),
1189              /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-400", children: "Calibrate joint sockets, head anchors, and preview natural coat sub-species & costume variations" })
1190            ] }),
1191            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
1192              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 bg-zinc-900 border border-zinc-800 rounded-lg p-1 text-xs", children: [
1193                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400 px-2 font-medium", children: "Batch Coat Preview:" }),
1194                [
1195                  { idx: 0, label: "Lead (1)" },
1196                  { idx: 1, label: "Rhythm (2)" },
1197                  { idx: 2, label: "Sub-3 (3)" },
1198                  { idx: 3, label: "Proc 4+" }
1199                ].map((v) => /* @__PURE__ */ jsxRuntimeExports.jsx(
1200                  "button",
1201                  {
1202                    onClick: () => {
1203                      setGlobalVariantIndex(v.idx);
1204                      setPreviewVariants({});
1205                    },
1206                    className: `px-2.5 py-1 rounded text-xs font-medium transition-all ${globalVariantIndex === v.idx || globalVariantIndex === null && v.idx === 0 && Object.keys(previewVariants).length === 0 ? "bg-indigo-600 text-white shadow-sm" : "text-zinc-400 hover:text-white"}`,
1207                    children: v.label
1208                  },
1209                  v.idx
1210                ))
1211              ] }),
1212              /* @__PURE__ */ jsxRuntimeExports.jsxs(
1213                "button",
1214                {
1215                  onClick: () => setActiveTab("actions"),
1216                  className: "px-3.5 py-2 text-xs font-bold text-indigo-300 hover:text-white bg-indigo-950/50 hover:bg-indigo-900/80 border border-indigo-700/50 rounded-lg flex items-center gap-2 transition-all shadow-md",
1217                  children: [
1218                    /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { size: 15 }),
1219                    " View Full Action Poses Matrix"
1220                  ]
1221                }
1222              )
1223            ] })
1224          ] }),
1225          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6", children: Object.values(BASE_ANIMALS).map((animal) => {
1226            const conf = charactersConfig[animal.id] || {
1227              animalId: animal.id,
1228              scale: 1,
1229              headX: 0,
1230              headY: 0,
1231              armLeftX: 0,
1232              armLeftY: 0,
1233              armRightX: 0,
1234              armRightY: 0
1235            };
1236            const testAction = animatedAnimals[animal.id] || "";
1237            const variantIdx = previewVariants[animal.id] ?? (globalVariantIndex ?? 0);
1238            const currentVariant = getAnimalVariant(animal.id, variantIdx, animal.sleeveColor);
1239            const filterId = `studio-char-filter-${animal.id}-${variantIdx}`;
1240            return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-xl p-5 flex flex-col gap-4", children: [
1241              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2 p-2.5 bg-zinc-950/70 border border-zinc-800/80 rounded-lg text-xs", children: [
1242                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
1243                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400 font-medium", children: "Duplicate Coat:" }),
1244                  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1 bg-zinc-900 p-0.5 rounded border border-zinc-800", children: [
1245                    { idx: 0, label: "Lead (1)" },
1246                    { idx: 1, label: "Rhythm (2)" },
1247                    { idx: 2, label: "Sub-3 (3)" },
1248                    { idx: 3, label: "Proc 4+" }
1249                  ].map((v) => /* @__PURE__ */ jsxRuntimeExports.jsx(
1250                    "button",
1251                    {
1252                      onClick: () => setPreviewVariants((prev) => ({ ...prev, [animal.id]: v.idx })),
1253                      className: `px-2 py-0.5 text-[11px] rounded transition-all font-medium ${variantIdx === v.idx ? "bg-indigo-600 text-white shadow-sm" : "text-zinc-400 hover:text-zinc-200"}`,
1254                      children: v.label
1255                    },
1256                    v.idx
1257                  )) })
1258                ] }),
1259                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
1260                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-indigo-300 text-[11px]", children: currentVariant.label }),
1261                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 pl-2 border-l border-zinc-800", children: [
1262                    currentVariant.furColor && /* @__PURE__ */ jsxRuntimeExports.jsx(
1263                      "span",
1264                      {
1265                        className: "w-3.5 h-3.5 rounded-full border border-white/20 shadow-inner inline-block",
1266                        style: { backgroundColor: currentVariant.furColor },
1267                        title: `Fur Color: ${currentVariant.furColor}`
1268                      }
1269                    ),
1270                    currentVariant.sleeveColor && /* @__PURE__ */ jsxRuntimeExports.jsx(
1271                      "span",
1272                      {
1273                        className: "w-3.5 h-3.5 rounded-full border border-white/20 shadow-inner inline-block",
1274                        style: { backgroundColor: currentVariant.sleeveColor },
1275                        title: `Sleeve Color: ${currentVariant.sleeveColor}`
1276                      }
1277                    ),
1278                    currentVariant.costumeIds && currentVariant.costumeIds.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] px-1.5 py-0.5 rounded bg-amber-500/15 text-amber-300 border border-amber-500/30 font-mono", children: currentVariant.costumeIds.join(", ") }),
1279                    currentVariant.scaleMultiplier && currentVariant.scaleMultiplier !== 1 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] text-zinc-400 font-mono", children: [
1280                      (currentVariant.scaleMultiplier * 100).toFixed(0),
1281                      "%"
1282                    ] }),
1283                    currentVariant.hatTilt !== void 0 && currentVariant.hatTilt !== 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-zinc-400 font-mono", children: currentVariant.hatTilt > 0 ? `+${currentVariant.hatTilt}°` : `${currentVariant.hatTilt}°` })
1284                  ] })
1285                ] })
1286              ] }),
1287              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col xl:flex-row gap-6", children: [
1288                /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-64 h-64 mx-auto xl:mx-0 bg-zinc-800/50 rounded-lg flex items-center justify-center relative shrink-0 overflow-hidden border border-zinc-700/50", children: (() => {
1289                  const filterSvg = getVariantFilterSvg(filterId, currentVariant);
1290                  return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 200 300", className: "w-full h-full overflow-visible drop-shadow-2xl", children: [
1291                    filterSvg && /* @__PURE__ */ jsxRuntimeExports.jsx("defs", { dangerouslySetInnerHTML: { __html: filterSvg } }),
1292                    /* @__PURE__ */ jsxRuntimeExports.jsx("g", { transform: `translate(100, 150)`, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1293                      SouthparkCharacter,
1294                      {
1295                        animal,
1296                        variant: currentVariant,
1297                        variantFilterId: filterSvg ? filterId : void 0,
1298                        instrument: {
1299                          id: 1,
1300                          name: "Preview",
1301                          type: "string",
1302                          holdStyle: testAction || "guitar",
1303                          group: "Strings",
1304                          imgUrl: POSE_INSTRUMENTS_IMG[testAction] || POSE_INSTRUMENTS_IMG["guitar"],
1305                          svgContent: void 0
1306                        },
1307                        isActive: !!testAction && currentVelocityPulse > 0,
1308                        velocity: testAction ? currentVelocityPulse : 0,
1309                        physicsMode: "smooth",
1310                        customConfig: conf,
1311                        showInstrument: showInstruments,
1312                        showSkeleton: showSkeletonOverlay
1313                      }
1314                    ) })
1315                  ] });
1316                })() }),
1317                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 space-y-3", children: [
1318                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
1319                    /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "font-bold text-indigo-400 text-base", children: animal.name }),
1320                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs", children: [
1321                      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 font-medium", children: "Test Animation:" }),
1322                      /* @__PURE__ */ jsxRuntimeExports.jsxs(
1323                        "select",
1324                        {
1325                          className: "bg-zinc-950 border border-zinc-700 text-white rounded px-2 py-1",
1326                          value: animatedAnimals[animal.id] || "",
1327                          onChange: (e) => {
1328                            const val = e.target.value;
1329                            setAnimatedAnimals((prev) => {
1330                              const copy = { ...prev };
1331                              if (val) copy[animal.id] = val;
1332                              else delete copy[animal.id];
1333                              return copy;
1334                            });
1335                          },
1336                          children: [
1337                            /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: "Static Pose" }),
1338                            /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "guitar", children: "Guitar (Strumming)" }),
1339                            /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "drumming", children: "Drums (Beating)" }),
1340                            /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "bowing", children: "Strings (Bowing)" }),
1341                            /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "sitting", children: "Piano (Keys)" }),
1342                            /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "blowing", children: "Wind / Brass" }),
1343                            /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "standard", children: "Standard (Rhythm)" })
1344                          ]
1345                        }
1346                      )
1347                    ] })
1348                  ] }),
1349                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-2 text-xs", children: [
1350                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1351                      /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-zinc-500 font-medium", children: "Head X, Y" }),
1352                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2 mt-1", children: [
1353                        /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "number", step: "1", value: conf.headX, onChange: (e) => updateCharConfig(animal.id, "headX", parseFloat(e.target.value) || 0), className: "w-full bg-zinc-950 border border-zinc-800 rounded px-2 py-1.5 text-white" }),
1354                        /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "number", step: "1", value: conf.headY, onChange: (e) => updateCharConfig(animal.id, "headY", parseFloat(e.target.value) || 0), className: "w-full bg-zinc-950 border border-zinc-800 rounded px-2 py-1.5 text-white" })
1355                      ] })
1356                    ] }),
1357                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1358                      /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-zinc-500 font-medium", children: "Scale" }),
1359                      /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "number", step: "0.05", value: conf.scale, onChange: (e) => updateCharConfig(animal.id, "scale", parseFloat(e.target.value) || 1), className: "w-full bg-zinc-950 border border-zinc-800 rounded px-2 py-1.5 mt-1 text-white" })
1360                    ] }),
1361                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "col-span-2 grid grid-cols-2 gap-3 pt-2 border-t border-zinc-800/50", children: [
1362                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1363                        /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-zinc-500 font-medium text-[11px] uppercase tracking-wider", children: "Left Shoulder Pivot (X, Y)" }),
1364                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2 mt-1", children: [
1365                          /* @__P
1365URE__ */ jsxRuntimeExports.jsx("input", { type: "number", step: "1", value: conf.armLeftX, onChange: (e) => updateCharConfig(animal.id, "armLeftX", parseFloat(e.target.value) || 0), className: "w-full bg-zinc-950 border border-zinc-800 rounded px-2 py-1.5 text-white" }),
1366                          /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "number", step: "1", value: conf.armLeftY, onChange: (e) => updateCharConfig(animal.id, "armLeftY", parseFloat(e.target.value) || 0), className: "w-full bg-zinc-950 border border-zinc-800 rounded px-2 py-1.5 text-white" })
1367                        ] })
1368                      ] }),
1369                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1370                        /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-zinc-500 font-medium text-[11px] uppercase tracking-wider", children: "Right Shoulder Pivot (X, Y)" }),
1371                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2 mt-1", children: [
1372                          /* @__P
1372URE__ */ jsxRuntimeExports.jsx("input", { type: "number", step: "1", value: conf.armRightX, onChange: (e) => updateCharConfig(animal.id, "armRightX", parseFloat(e.target.value) || 0), className: "w-full bg-zinc-950 border border-zinc-800 rounded px-2 py-1.5 text-white" }),
1373                          /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "number", step: "1", value: conf.armRightY, onChange: (e) => updateCharConfig(animal.id, "armRightY", parseFloat(e.target.value) || 0), className: "w-full bg-zinc-950 border border-zinc-800 rounded px-2 py-1.5 text-white" })
1374                        ] })
1375                      ] })
1376                    ] })
1377                  ] })
1378                ] })
1379              ] }),
1380              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-t border-zinc-800/60 pt-3", children: [
1381                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[11px] text-zinc-400 font-medium mb-2 uppercase tracking-wider flex items-center justify-between", children: [
1382                  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
1383                    animal.name,
1384                    " (",
1385                    currentVariant.label,
1386                    ") - Action Poses Preview"
1387                  ] }),
1388                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 lowercase text-[10px]", children: "updates in real-time" })
1389                ] }),
1390                /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-6 gap-2", children: ACTION_POSES.map((p) => {
1391                  const miniFilterId = `${filterId}-mini-${p.id}`;
1392                  const miniFilterSvg = getVariantFilterSvg(miniFilterId, currentVariant);
1393                  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-950/80 border border-zinc-800 rounded-lg p-1.5 flex flex-col items-center gap-1", children: [
1394                    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[9px] text-zinc-400 font-medium truncate w-full text-center", children: p.name.split(" ")[0] }),
1395                    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full aspect-square flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 200 300", className: "w-full h-full overflow-visible", children: [
1396                      miniFilterSvg && /* @__PURE__ */ jsxRuntimeExports.jsx("defs", { dangerouslySetInnerHTML: { __html: miniFilterSvg } }),
1397                      /* @__PURE__ */ jsxRuntimeExports.jsx("g", { transform: "translate(100, 150) scale(0.95)", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1398                        SouthparkCharacter,
1399                        {
1400                          animal,
1401                          variant: currentVariant,
1402                          variantFilterId: miniFilterSvg ? miniFilterId : void 0,
1403                          instrument: {
1404                            id: 1,
1405                            name: p.name,
1406                            type: "preview",
1407                            holdStyle: p.holdStyle,
1408                            group: "Preview",
1409                            imgUrl: POSE_INSTRUMENTS_IMG[p.id] || void 0,
1410                            svgContent: void 0
1411                          },
1412                          isActive: false,
1413                          velocity: 0,
1414                          physicsMode: "smooth",
1415                          customConfig: conf,
1416                          showInstrument: showInstruments
1417                        }
1418                      ) })
1419                    ] }) })
1420                  ] }, p.id);
1421                }) })
1422              ] })
1423            ] }, animal.id);
1424          }) })
1425        ] }),
1426        activeTab === "stage" && /* @__PURE__ */ jsxRuntimeExports.jsx(
1427          SouthparkStageDesigner,
1428          {
1429            stageConfig,
1430            setStageConfig,
1431            spBackgroundConfig,
1432            setSpBackgroundConfig,
1433            spBackgroundPresets,
1434            setSpBackgroundPresets,
1435            sharedBackgroundConfig,
1436            sharedBackgroundPresets,
1437            customBackgrounds,
1438            setCustomBackgrounds,
1439            charactersConfig,
1440            costumesConfig: allCostumesMap,
1441            instrumentsConfig
1442          }
1443        ),
1444        activeTab === "instruments" && (() => {
1445          const allInstruments = GM_INSTRUMENTS.concat("Drum Kit");
1446          const filteredInstruments = allInstruments.map((name, idx) => ({ name, idx })).filter(({ name, idx }) => {
1447            const cat = getCategoryName(idx);
1448            if (instCatFilter !== "all" && cat !== instCatFilter) return false;
1449            if (instSearch.trim()) {
1450              const query = instSearch.toLowerCase().trim();
1451              const matchesName = name.toLowerCase().includes(query);
1452              const matchesId = idx.toString().includes(query);
1453              const matchesCat = cat.toLowerCase().includes(query);
1454              if (!matchesName && !matchesId && !matchesCat) return false;
1455            }
1456            return true;
1457          });
1458          return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
1459            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-b border-zinc-800 pb-3", children: [
1460              /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-xl font-bold", children: "Instrument to Animal Bindings" }),
1461              /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-400 mt-1", children: "Override the default animal assignment for any MIDI instrument (0-127). 128 is Drum Kit." })
1462            ] }),
1463            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col lg:flex-row items-start lg:items-center justify-between gap-3 bg-zinc-900/60 border border-zinc-800/80 p-3.5 rounded-xl shadow-md", children: [
1464              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-3 w-full lg:w-auto", children: [
1465                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative flex-1 sm:w-56", children: [
1466                  /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { size: 14, className: "absolute left-3 top-1/2 -translate-y-1/2 text-zinc-400 pointer-events-none" }),
1467                  /* @__PURE__ */ jsxRuntimeExports.jsx(
1468                    "input",
1469                    {
1470                      type: "text",
1471                      placeholder: "Search by name, ID or category...",
1472                      value: instSearch,
1473                      onChange: (e) => setInstSearch(e.target.value),
1474                      className: "w-full bg-zinc-950 border border-zinc-700/80 rounded-lg pl-8 pr-3 py-1.5 text-xs text-white placeholder-zinc-500 focus:outline-none focus:border-indigo-500 transition-colors"
1475                    }
1476                  )
1477                ] }),
1478                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
1479                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-zinc-400 font-medium", children: "Category:" }),
1480                  /* @__PURE__ */ jsxRuntimeExports.jsxs(
1481                    "select",
1482                    {
1483                      value: instCatFilter,
1484                      onChange: (e) => setInstCatFilter(e.target.value),
1485                      className: "bg-zinc-950 border border-zinc-700/80 rounded-lg px-2.5 py-1.5 text-xs text-white focus:outline-none focus:border-indigo-500",
1486                      children: [
1487                        /* @__PURE__ */ jsxRuntimeExports.jsxs("option", { value: "all", className: "bg-zinc-900 text-white", children: [
1488                          "All Categories (",
1489                          allInstruments.length,
1490                          ")"
1491                        ] }),
1492                        INSTRUMENT_CATEGORIES.map((cat) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: cat.name, className: "bg-zinc-900 text-white", children: cat.name }, cat.name)),
1493                        /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "Drums", className: "bg-zinc-900 text-white", children: "Drums (1)" })
1494                      ]
1495                    }
1496                  )
1497                ] }),
1498                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 border-l border-zinc-800 pl-3", children: [
1499                  /* @__PURE__ */ jsxRuntimeExports.jsxs(
1500                    "button",
1501                    {
1502                      type: "button",
1503                      onClick: () => setInstPreviewCharacter(!instPreviewCharacter),
1504                      className: `flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg text-xs font-medium border transition-colors ${instPreviewCharacter ? "bg-indigo-600 text-white border-indigo-500 shadow-sm" : "bg-zinc-950 text-zinc-300 border-zinc-700/80 hover:bg-zinc-800"}`,
1505                      children: [
1506                        instPreviewCharacter ? /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, { size: 13, className: "text-indigo-200" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(EyeOff, { size: 13, className: "text-zinc-400" }),
1507                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: instPreviewCharacter ? "Character Preview: ON" : "Preview Character" })
1508                      ]
1509                    }
1510                  ),
1511                  instPreviewCharacter && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1512                    /* @__PURE__ */ jsxRuntimeExports.jsx(
1513                      "select",
1514                      {
1515                        value: instPreviewAnimal,
1516                        onChange: (e) => setInstPreviewAnimal(e.target.value),
1517                        className: "bg-zinc-950 border border-zinc-700/80 rounded-lg px-2.5 py-1.5 text-xs text-white focus:outline-none focus:border-indigo-500",
1518                        title: "Select preview animal",
1519                        children: Object.values(BASE_ANIMALS).map((a) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: a.id, className: "bg-zinc-900 text-zinc-100", children: a.name }, a.id))
1520                      }
1521                    ),
1522                    /* @__PURE__ */ jsxRuntimeExports.jsxs(
1523                      "button",
1524                      {
1525                        type: "button",
1526                        onClick: () => setInstPreviewAnimating(!instPreviewAnimating),
1527                        className: `flex items-center gap-1 px-2 py-1.5 rounded-lg text-xs font-medium border transition-colors ${instPreviewAnimating ? "bg-emerald-600/20 text-emerald-400 border-emerald-500/30" : "bg-zinc-950 text-zinc-400 border-zinc-800 hover:text-zinc-200"}`,
1528                        title: "Toggle performance animation",
1529                        children: [
1530                          instPreviewAnimating ? /* @__PURE__ */ jsxRuntimeExports.jsx(Pause, { size: 12 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Play, { size: 12 }),
1531                          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: instPreviewAnimating ? "Playing" : "Paused" })
1532                        ]
1533                      }
1534                    )
1535                  ] })
1536                ] })
1537              ] }),
1538              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-zinc-400 flex items-center gap-2", children: [
1539                /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
1540                  "Showing ",
1541                  /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "text-white", children: filteredInstruments.length }),
1542                  " of ",
1543                  allInstruments.length
1544                ] }),
1545                Object.keys(instrumentsConfig).length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-2 py-0.5 rounded-full text-[10px] font-semibold bg-indigo-500/20 text-indigo-300 border border-indigo-500/30", children: [
1546                  Object.keys(instrumentsConfig).length,
1547                  " overrides active"
1548                ] })
1549              ] })
1550            ] }),
1551            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4", children: [
1552              filteredInstruments.map(({ name: instName, idx }) => {
1553                var _a;
1554                const conf = instrumentsConfig[idx];
1555                const hasOverride = !!(conf == null ? void 0 : conf.animalId) || (conf == null ? void 0 : conf.scale) !== void 0 || (conf == null ? void 0 : conf.offsetX) !== void 0 || (conf == null ? void 0 : conf.offsetY) !== void 0 || (conf == null ? void 0 : conf.rotation) !== void 0;
1556                const imgUrl = idx === 128 ? "/assets/visualizers/southpark/instruments/inst_drums.webp" : `/assets/visualizers/southpark/instruments/inst_${idx}.webp`;
1557                const catName = getCategoryName(idx);
1558                const defaultDef = getInstrumentDef(idx === 128 ? -1 : idx);
1559                const effectiveScale = (conf == null ? void 0 : conf.scale) !== void 0 ? conf.scale : defaultDef.scale || 1;
1560                const effectiveOffsetX = (conf == null ? void 0 : conf.offsetX) !== void 0 ? conf.offsetX : defaultDef.offsetX || 0;
1561                const effectiveOffsetY = (conf == null ? void 0 : conf.offsetY) !== void 0 ? conf.offsetY : defaultDef.offsetY || 0;
1562                const effectiveRotation = (conf == null ? void 0 : conf.rotation) !== void 0 ? conf.rotation : defaultDef.rotation || 0;
1563                const effectiveDef = {
1564                  ...defaultDef,
1565                  scale: effectiveScale,
1566                  offsetX: effectiveOffsetX,
1567                  offsetY: effectiveOffsetY,
1568                  rotation: effectiveRotation
1569                };
1570                const previewAnimalId = (conf == null ? void 0 : conf.animalId) || instPreviewAnimal;
1571                const previewAnimalDef = BASE_ANIMALS[previewAnimalId] || BASE_ANIMALS.fox;
1572                const isTransformed = (conf == null ? void 0 : conf.scale) !== void 0 || (conf == null ? void 0 : conf.offsetX) !== void 0 || (conf == null ? void 0 : conf.offsetY) !== void 0 || (conf == null ? void 0 : conf.rotation) !== void 0;
1573                const isCardExpanded = !!openTransformCards[idx];
1574                const jointType = ((_a = defaultDef.jointDef) == null ? void 0 : _a.jointType) || "bare_hands";
1575                return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1576                  "div",
1577                  {
1578                    className: `p-3.5 rounded-xl border flex flex-col justify-between transition-all hover:border-zinc-700 hover:shadow-lg ${hasOverride ? "bg-indigo-900/15 border-indigo-500/40 shadow-indigo-950/20" : "bg-zinc-900/70 border-zinc-800/80"}`,
1579                    children: [
1580                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1581                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 mb-2", children: [
1582                          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[11px] font-mono font-semibold px-2 py-0.5 rounded bg-zinc-950 border border-zinc-800 text-zinc-400", children: [
1583                            "#",
1584                            idx
1585                          ] }),
1586                          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] font-medium px-2 py-0.5 rounded-full bg-zinc-800/80 text-zinc-300 border border-zinc-700/60 truncate max-w-[120px]", children: catName })
1587                        ] }),
1588                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full aspect-[4/3] bg-zinc-950/90 rounded-lg flex items-center justify-center p-2 relative overflow-hidden border border-zinc-800/80 mb-3 group/img", children: [
1589                          /* @__PURE__ */ jsxRuntimeExports.jsx(
1590                            "div",
1591                            {
1592                              className: "absolute inset-0 opacity-10 pointer-events-none",
1593                              style: {
1594                                backgroundImage: "linear-gradient(45deg, #808080 25%, transparent 25%), linear-gradient(-45deg, #808080 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #808080 75%), linear-gradient(-45deg, transparent 75%, #808080 75%)",
1595                                backgroundSize: "16px 16px",
1596                                backgroundPosition: "0 0, 0 8px, 8px -8px, -8px 0px"
1597                              }
1598                            }
1599                          ),
1600                          instPreviewCharacter ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full h-full flex items-center justify-center relative z-10", children: /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { viewBox: "-80 -115 160 230", className: "w-full h-full", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1601                            SouthparkCharacter,
1602                            {
1603                              animal: previewAnimalDef,
1604                              instrument: effectiveDef,
1605                              isActive: instPreviewAnimating ? currentVelocityPulse > 0 : false,
1606                              velocity: currentVelocityPulse || 100,
1607                              activePitch: idx === 57 ? 62 : 65,
1608                              currentTime: Date.now() / 1e3,
1609                              bpm: 120,
1610                              physicsMode: "smooth",
1611                              costumes: (conf == null ? void 0 : conf.costumeIds) || [],
1612                              customCostumesMap: allCostumesMap
1613                            }
1614                          ) }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
1615                            "img",
1616                            {
1617                              src: imgUrl,
1618                              alt: instName,
1619                              className: "w-full h-full object-contain relative z-10 drop-shadow-xl transition-transform duration-200 group-hover/img:scale-105",
1620                              style: {
1621                                transform: `rotate(${effectiveRotation}deg) scale(${effectiveScale}) translate(${effectiveOffsetX}px, ${effectiveOffsetY}px)`
1622                              },
1623                              loading: "lazy",
1624                              onError: (e) => {
1625                                e.target.style.opacity = "0.3";
1626                              }
1627                            }
1628                          )
1629                        ] }),
1630                        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold text-sm text-zinc-100 truncate mb-3", title: instName, children: instName })
1631                      ] }),
1632                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1633                        /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-[11px] text-zinc-400 font-medium mb-1 block", children: "Assigned Animal:" }),
1634                        /* @__PURE__ */ jsxRuntimeExports.jsxs(
1635                          "select",
1636                          {
1637                            className: "w-full bg-zinc-950 border border-zinc-700/80 rounded-lg px-2.5 py-1.5 text-xs text-white focus:border-indigo-500 focus:outline-none transition-colors",
1638                            value: (conf == null ? void 0 : conf.animalId) || "",
1639                            onChange: (e) => {
1640                              const val = e.target.value;
1641                              setInstrumentsConfig((prev) => {
1642                                var _a2;
1643                                const copy = { ...prev };
1644                                if (val) {
1645                                  copy[idx] = {
1646                                    ...copy[idx] || { instrumentId: idx, costumeIds: [] },
1647                                    instrumentId: idx,
1648                                    animalId: val,
1649                                    costumeIds: ((_a2 = copy[idx]) == null ? void 0 : _a2.costumeIds) || []
1650                                  };
1651                                } else {
1652                                  if (copy[idx]) {
1653                                    const { animalId, ...rest } = copy[idx];
1654                                    copy[idx] = rest;
1655                                  }
1656                                }
1657                                return copy;
1658                              });
1659                            },
1660                            children: [
1661                              /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", className: "bg-zinc-900 text-zinc-400", children: "(Default Fallback)" }),
1662                              Object.values(BASE_ANIMALS).map((a) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: a.id, className: "bg-zinc-900 text-zinc-100", children: a.name }, a.id))
1663                            ]
1664                          }
1665                        )
1666                      ] }),
1667                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-3 pt-2.5 border-t border-zinc-800/60", children: [
1668                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-1.5", children: [
1669                          /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "text-[11px] text-zinc-400 font-medium flex items-center gap-1", children: [
1670                            /* @__PURE__ */ jsxRuntimeExports.jsx(Shirt, { size: 12, className: "text-indigo-400" }),
1671                            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Costumes:" })
1672                          ] }),
1673                          (conf == null ? void 0 : conf.costumeIds) && conf.costumeIds.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
1674                            "button",
1675                            {
1676                              type: "button",
1677                              onClick: () => {
1678                                setInstrumentsConfig((prev) => {
1679                                  const copy = { ...prev };
1680                                  if (copy[idx]) {
1681                                    copy[idx] = { ...copy[idx], costumeIds: [] };
1682                                  }
1683                                  return copy;
1684                                });
1685                              },
1686                              className: "text-[10px] text-zinc-500 hover:text-red-400 transition-colors",
1687                              children: "Clear all"
1688                            }
1689                          )
1690                        ] }),
1691                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap gap-1 mb-2 min-h-[22px]", children: [
1692                          ((conf == null ? void 0 : conf.costumeIds) || []).map((cid) => {
1693                            const cDef = allCostumesMap[cid];
1694                            return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1695                              "span",
1696                              {
1697                                className: "inline-flex items-center gap-1 px-2 py-0.5 rounded-md text-[10px] font-medium bg-indigo-500/20 text-indigo-300 border border-indigo-500/30",
1698                                children: [
1699                                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate max-w-[85px]", children: (cDef == null ? void 0 : cDef.name) || cid }),
1700                                  /* @__PURE__ */ jsxRuntimeExports.jsx(
1701                                    "button",
1702                                    {
1703                                      type: "button",
1704                                      onClick: () => {
1705                                        setInstrumentsConfig((prev) => {
1706                                          const copy = { ...prev };
1707                                          const curr = copy[idx] || { instrumentId: idx, animalId: "", costumeIds: [] };
1708                                          copy[idx] = {
1709                                            ...curr,
1710                                            costumeIds: curr.costumeIds.filter((id) => id !== cid)
1711                                          };
1712                                          return copy;
1713                                        });
1714                                      },
1715                                      className: "hover:text-red-400 font-bold ml-0.5",
1716                                      children: "×"
1717                                    }
1718                                  )
1719                                ]
1720                              },
1721                              cid
1722                            );
1723                          }),
1724                          (!(conf == null ? void 0 : conf.costumeIds) || conf.costumeIds.length === 0) && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-zinc-500 italic", children: "No costumes assigned" })
1725                        ] }),
1726                        /* @__PURE__ */ jsxRuntimeExports.jsxs(
1727                          "select",
1728                          {
1729                            className: "w-full bg-zinc-950 border border-zinc-700/80 rounded-lg px-2.5 py-1.5 text-xs text-zinc-300 focus:border-indigo-500 focus:outline-none transition-colors",
1730                            value: "",
1731                            onChange: (e) => {
1732                              const cid = e.target.value;
1733                              if (!cid) return;
1734                              setInstrumentsConfig((prev) => {
1735                                const copy = { ...prev };
1736                                const curr = copy[idx] || { instrumentId: idx, animalId: "", costumeIds: [] };
1737                                if (!curr.costumeIds.includes(cid)) {
1738                                  copy[idx] = {
1739                                    ...curr,
1740                                    costumeIds: [...curr.costumeIds, cid]
1741                                  };
1742                                }
1743                                return copy;
1744                              });
1745                            },
1746                            children: [
1747                              /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", className: "bg-zinc-900 text-zinc-400", children: "+ Add Costume..." }),
1748                              /* @__PURE__ */ jsxRuntimeExports.jsx("optgroup", { label: "🎩 Hats & Headwear", className: "bg-zinc-900 text-indigo-400 font-semibold", children: Object.values(allCostumesMap).filter((c) => c.type === "hat").map((c) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: c.id, className: "bg-zinc-900 text-white font-normal", children: c.name }, c.id)) }),
1749                              /* @__PURE__ */ jsxRuntimeExports.jsx("optgroup", { label: "🕶️ Eyewear & Facial", className: "bg-zinc-900 text-indigo-400 font-semibold", children: Object.values(allCostumesMap).filter((c) => c.type === "glasses").map((c) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: c.id, className: "bg-zinc-900 text-white font-normal", children: c.name }, c.id)) }),
1750                              /* @__PURE__ */ jsxRuntimeExports.jsx("optgroup", { label: "🧣 Neckwear", className: "bg-zinc-900 text-indigo-400 font-semibold", children: Object.values(allCostumesMap).filter((c) => c.type === "neck").map((c) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: c.id, className: "bg-zinc-900 text-white font-normal", children: c.name }, c.id)) }),
1751                              /* @__PURE__ */ jsxRuntimeExports.jsx("optgroup", { label: "👔 Outfits & Robes", className: "bg-zinc-900 text-indigo-400 font-semibold", children: Object.values(allCostumesMap).filter((c) => c.type === "body").map((c) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: c.id, className: "bg-zinc-900 text-white font-normal", children: c.name }, c.id)) })
1752                            ]
1753                          }
1754                        )
1755                      ] }),
1756                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-3 pt-2.5 border-t border-zinc-800/60", children: [
1757                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-1.5", children: [
1758                          /* @__PURE__ */ jsxRuntimeExports.jsxs(
1759                            "button",
1760                            {
1761                              type: "button",
1762                              onClick: () => setOpenTransformCards((prev) => ({ ...prev, [idx]: !prev[idx] })),
1763                              className: "flex items-center gap-1.5 text-[11px] font-medium text-zinc-300 hover:text-indigo-400 transition-colors",
1764                              children: [
1765                                /* @__PURE__ */ jsxRuntimeExports.jsx(SlidersVertical, { size: 12, className: isTransformed ? "text-indigo-400" : "text-zinc-500" }),
1766                                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Transform & Tilt" }),
1767                                isTransformed && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-indigo-400", title: "Custom transforms active" })
1768                              ]
1769                            }
1770                          ),
1771                          isTransformed && /* @__PURE__ */ jsxRuntimeExports.jsxs(
1772                            "button",
1773                            {
1774                              type: "button",
1775                              onClick: () => {
1776                                setInstrumentsConfig((prev) => {
1777                                  const copy = { ...prev };
1778                                  if (copy[idx]) {
1779                                    const { scale, offsetX, offsetY, rotation, ...rest } = copy[idx];
1780                                    copy[idx] = rest;
1781                                  }
1782                                  return copy;
1783                                });
1784                              },
1785                              className: "flex items-center gap-1 text-[10px] text-zinc-500 hover:text-amber-400 transition-colors",
1786                              title: "Reset transform to defaults",
1787                              children: [
1788                                /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { size: 10 }),
1789                                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Reset" })
1790                              ]
1791                            }
1792                          )
1793                        ] }),
1794                        isCardExpanded && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 bg-zinc-950/80 p-2.5 rounded-lg border border-zinc-800 text-[11px] mt-1.5", children: [
1795                          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1796                            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center text-zinc-400 mb-1", children: [
1797                              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Scale" }),
1798                              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1", children: [
1799                                /* @__PURE__ */ jsxRuntimeExports.jsx(
1800                                  "input",
1801                                  {
1802                                    type: "number",
1803                                    step: "0.05",
1804                                    min: "0.10",
1805                                    max: "8.00",
1806                                    value: effectiveScale,
1807                                    onChange: (e) => {
1808                                      const val = parseFloat(e.target.value) || 1;
1809                                      setInstrumentsConfig((prev) => {
1810                                        const copy = { ...prev };
1811                                        const curr = copy[idx] || { instrumentId: idx, animalId: "", costumeIds: [] };
1812                                        copy[idx] = { ...curr, scale: val };
1813                                        return copy;
1814                                      });
1815                                    },
1816                                    className: "w-16 bg-zinc-900 border border-zinc-700/80 rounded px-1.5 py-0.5 text-right font-mono text-white text-[11px] focus:outline-none focus:border-indigo-500"
1817                                  }
1818                                ),
1819                                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 text-[10px]", children: "x" })
1820                              ] })
1821                            ] }),
1822                            /* @__PURE__ */ jsxRuntimeExports.jsx(
1823                              "input",
1824                              {
1825                                type: "range",
1826                                min: "0.10",
1827                                max: "5.00",
1828                                step: "0.05",
1829                                value: effectiveScale,
1830                                onChange: (e) => {
1831                                  const val = parseFloat(e.target.value);
1832                                  setInstrumentsConfig((prev) => {
1833                                    const copy = { ...prev };
1834                                    const curr = copy[idx] || { instrumentId: idx, animalId: "", costumeIds: [] };
1835                                    copy[idx] = { ...curr, scale: val };
1836                                    return copy;
1837                                  });
1838                                },
1839                                className: "w-full h-1 bg-zinc-800 rounded-lg appearance-none cursor-pointer accent-indigo-500"
1840                              }
1841                            )
1842                          ] }),
1843                          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1844                            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center text-zinc-400 mb-1", children: [
1845                              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Position X" }),
1846                              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1", children: [
1847                                /* @__PURE__ */ jsxRuntimeExports.jsx(
1848                                  "input",
1849                                  {
1850                                    type: "number",
1851                                    step: "1",
1852                                    min: "-300",
1853                                    max: "300",
1854                                    value: effectiveOffsetX,
1855                                    onChange: (e) => {
1856                                      const val = parseInt(e.target.value, 10) || 0;
1857                                      setInstrumentsConfig((prev) => {
1858                                        const copy = { ...prev };
1859                                        const curr = copy[idx] || { instrumentId: idx, animalId: "", costumeIds: [] };
1860                                        copy[idx] = { ...curr, offsetX: val };
1861                                        return copy;
1862                                      });
1863                                    },
1864                                    className: "w-16 bg-zinc-900 border border-zinc-700/80 rounded px-1.5 py-0.5 text-right font-mono text-white text-[11px] focus:outline-none focus:border-indigo-500"
1865                                  }
1866                                ),
1867                                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 text-[10px]", children: "px" })
1868                              ] })
1869                            ] }),
1870                            /* @__PURE__ */ jsxRuntimeExports.jsx(
1871                              "input",
1872                              {
1873                                type: "range",
1874                                min: "-300",
1875                                max: "300",
1876                                step: "1",
1877                                value: effectiveOffsetX,
1878                                onChange: (e) => {
1879                                  const val = parseInt(e.target.value, 10);
1880                                  setInstrumentsConfig((prev) => {
1881                                    const copy = { ...prev };
1882                                    const curr = copy[idx] || { instrumentId: idx, animalId: "", costumeIds: [] };
1883                                    copy[idx] = { ...curr, offsetX: val };
1884                                    return copy;
1885                                  });
1886                                },
1887                                className: "w-full h-1 bg-zinc-800 rounded-lg appearance-none cursor-pointer accent-indigo-500"
1888                              }
1889                            )
1890                          ] }),
1891                          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1892                            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center text-zinc-400 mb-1", children: [
1893                              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Position Y" }),
1894                              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1", children: [
1895                                /* @__PURE__ */ jsxRuntimeExports.jsx(
1896                                  "input",
1897                                  {
1898                                    type: "number",
1899                                    step: "1",
1900                                    min: "-300",
1901                                    max: "300",
1902                                    value: effectiveOffsetY,
1903                                    onChange: (e) => {
1904                                      const val = parseInt(e.target.value, 10) || 0;
1905                                      setInstrumentsConfig((prev) => {
1906                                        const copy = { ...prev };
1907                                        const curr = copy[idx] || { instrumentId: idx, animalId: "", costumeIds: [] };
1908                                        copy[idx] = { ...curr, offsetY: val };
1909                                        return copy;
1910                                      });
1911                                    },
1912                                    className: "w-16 bg-zinc-900 border border-zinc-700/80 rounded px-1.5 py-0.5 text-right font-mono text-white text-[11px] focus:outline-none focus:border-indigo-500"
1913                                  }
1914                                ),
1915                                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 text-[10px]", children: "px" })
1916                              ] })
1917                            ] }),
1918                            /* @__PURE__ */ jsxRuntimeExports.jsx(
1919                              "input",
1920                              {
1921                                type: "range",
1922                                min: "-300",
1923                                max: "300",
1924                                step: "1",
1925                                value: effectiveOffsetY,
1926                                onChange: (e) => {
1927                                  const val = parseInt(e.target.value, 10);
1928                                  setInstrumentsConfig((prev) => {
1929                                    const copy = { ...prev };
1930                                    const curr = copy[idx] || { instrumentId: idx, animalId: "", costumeIds: [] };
1931                                    copy[idx] = { ...curr, offsetY: val };
1932                                    return copy;
1933                                  });
1934                                },
1935                                className: "w-full h-1 bg-zinc-800 rounded-lg appearance-none cursor-pointer accent-indigo-500"
1936                              }
1937                            )
1938                          ] }),
1939                          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1940                            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center text-zinc-400 mb-1", children: [
1941                              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Tilt (Angle)" }),
1942                              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1", children: [
1943                                /* @__PURE__ */ jsxRuntimeExports.jsx(
1944                                  "input",
1945                                  {
1946                                    type: "number",
1947                                    step: "1",
1948                                    min: "-360",
1949                                    max: "360",
1950                                    value: effectiveRotation,
1951                                    onChange: (e) => {
1952                                      const val = parseInt(e.target.value, 10) || 0;
1953                                      setInstrumentsConfig((prev) => {
1954                                        const copy = { ...prev };
1955                                        const curr = copy[idx] || { instrumentId: idx, animalId: "", costumeIds: [] };
1956                                        copy[idx] = { ...curr, rotation: val };
1957                                        return copy;
1958                                      });
1959                                    },
1960                                    className: "w-16 bg-zinc-900 border border-zinc-700/80 rounded px-1.5 py-0.5 text-right font-mono text-white text-[11px] focus:outline-none focus:border-indigo-500"
1961                                  }
1962                                ),
1963                                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 text-[10px]", children: "°" })
1964                              ] })
1965                            ] }),
1966                            /* @__PURE__ */ jsxRuntimeExports.jsx(
1967                              "input",
1968                              {
1969                                type: "range",
1970                                min: "-180",
1971                                max: "180",
1972                                step: "1",
1973                                value: effectiveRotation,
1974                                onChange: (e) => {
1975                                  const val = parseInt(e.target.value, 10);
1976                                  setInstrumentsConfig((prev) => {
1977                                    const copy = { ...prev };
1978                                    const curr = copy[idx] || { instrumentId: idx, animalId: "", costumeIds: [] };
1979                                    copy[idx] = { ...curr, rotation: val };
1980                                    return copy;
1981                                  });
1982                                },
1983                                className: "w-full h-1 bg-zinc-800 rounded-lg appearance-none cursor-pointer accent-indigo-500"
1984                              }
1985                            )
1986                          ] }),
1987                          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pt-1 border-t border-zinc-800/60 flex items-center justify-between text-[10px] text-zinc-400", children: [
1988                            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Joint System:" }),
1989                            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "px-1.5 py-0.5 rounded bg-zinc-900 border border-zinc-700/60 text-indigo-300 font-mono", children: jointType.replace(/_/g, " ") })
1990                          ] })
1991                        ] })
1992                      ] })
1993                    ]
1994                  },
1995                  idx
1996                );
1997              }),
1998              filteredInstruments.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "col-span-full py-12 text-center text-zinc-500 border-2 border-dashed border-zinc-800 rounded-xl", children: [
1999                'No instruments found matching "',
2000                instSearch,
2001                '".'
2002              ] })
2003            ] })
2004          ] });
2005        })(),
2006        activeTab === "costumes" && (() => {
2007          const allCostumesList = Object.values(allCostumesMap);
2008          const filteredCostumes = allCostumesList.filter((c) => {
2009            if (selectedCostumeCategory !== "all" && c.type !== selectedCostumeCategory) return false;
2010            if (costumeSearch.trim()) {
2011              const query = costumeSearch.toLowerCase().trim();
2012              if (!c.name.toLowerCase().includes(query) && !c.id.toLowerCase().includes(query)) return false;
2013            }
2014            return true;
2015          });
2016          const categoryCounts = {
2017            all: allCostumesList.length,
2018            hat: allCostumesList.filter((c) => c.type === "hat").length,
2019            glasses: allCostumesList.filter((c) => c.type === "glasses").length,
2020            neck: allCostumesList.filter((c) => c.type === "neck").length,
2021            body: allCostumesList.filter((c) => c.type === "body").length
2022          };
2023          const fittingAnimal = BASE_ANIMALS[fittingAnimalId] || BASE_ANIMALS.fox;
2024          return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
2025            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center justify-between gap-4 border-b border-zinc-800 pb-4", children: [
2026              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
2027                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
2028                  /* @__PURE__ */ jsxRuntimeExports.jsx(Shirt, { className: "text-indigo-400", size: 22 }),
2029                  /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-xl font-bold text-white tracking-wide", children: "Costume Wardrobe & Fitting Room" }),
2030                  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-2.5 py-0.5 rounded-full text-xs font-semibold bg-indigo-500/20 text-indigo-300 border border-indigo-500/30", children: [
2031                    allCostumesList.length,
2032                    " Total Pieces"
2033                  ] })
2034                ] }),
2035                /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-400 mt-1", children: "Calibrate placement, scaling, and rotation for hats, eyewear, neckwear, and body outfits across all animal models" })
2036              ] }),
2037              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "cursor-pointer px-4 py-2 bg-zinc-800 hover:bg-zinc-700 text-white text-xs font-semibold rounded-lg flex items-center gap-2 transition-colors border border-zinc-700", children: [
2038                /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { size: 15 }),
2039                " Upload Custom WebP/PNG",
2040                /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "file", ref: fileInputRef, className: "hidden", accept: "image/webp, image/png", onChange: handleCostumeUpload })
2041              ] }) })
2042            ] }),
2043            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col md:flex-row items-start md:items-center justify-between gap-3 bg-zinc-900/60 border border-zinc-800 p-3 rounded-xl", children: [
2044              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-2", children: [
2045                { id: "all", label: "All Items", icon: "✨" },
2046                { id: "hat", label: "Hats & Headwear", icon: "🎩" },
2047                { id: "glasses", label: "Eyewear & Facial", icon: "🕶️" },
2048                { id: "neck", label: "Neckwear", icon: "🧣" },
2049                { id: "body", label: "Body Outfits", icon: "👔" }
2050              ].map((cat) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
2051                "button",
2052                {
2053                  onClick: () => setSelectedCostumeCategory(cat.id),
2054                  className: `px-3 py-1.5 rounded-lg text-xs font-medium flex items-center gap-1.5 transition-all ${selectedCostumeCategory === cat.id ? "bg-indigo-600 text-white shadow-md shadow-indigo-900/30 font-semibold" : "bg-zinc-950 text-zinc-400 hover:text-zinc-200 border border-zinc-800 hover:border-zinc-700"}`,
2055                  children: [
2056                    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: cat.icon }),
2057                    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: cat.label }),
2058                    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-[10px] px-1.5 py-0.2 rounded-full ${selectedCostumeCategory === cat.id ? "bg-indigo-700 text-white" : "bg-zinc-800 text-zinc-500"}`, children: categoryCounts[cat.id] })
2059                  ]
2060                },
2061                cat.id
2062              )) }),
2063              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative w-full md:w-64", children: [
2064                /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { size: 14, className: "absolute left-3 top-1/2 -translate-y-1/2 text-zinc-400 pointer-events-none" }),
2065                /* @__PURE__ */ jsxRuntimeExports.jsx(
2066                  "input",
2067                  {
2068                    type: "text",
2069                    placeholder: "Search costumes...",
2070                    value: costumeSearch,
2071                    onChange: (e) => setCostumeSearch(e.target.value),
2072                    className: "w-full bg-zinc-950 border border-zinc-800 rounded-lg pl-8 pr-3 py-1.5 text-xs text-white placeholder-zinc-500 focus:outline-none focus:border-indigo-500"
2073                  }
2074                )
2075              ] })
2076            ] }),
2077            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-12 gap-6 items-start", children: [
2078              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "lg:col-span-5 bg-zinc-900/40 border border-zinc-800 rounded-2xl p-4 flex flex-col max-h-[700px]", children: [
2079                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between pb-3 mb-3 border-b border-zinc-800/80", children: [
2080                  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs font-semibold text-zinc-300 uppercase tracking-wider", children: [
2081                    "Costume Wardrobe (",
2082                    filteredCostumes.length,
2083                    ")"
2084                  ] }),
2085                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] text-zinc-500", children: "Click to equip & calibrate" })
2086                ] }),
2087                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-3 gap-2.5 overflow-y-auto pr-1", children: [
2088                  filteredCostumes.map((c) => {
2089                    const isSelected = selectedCostumeId === c.id;
2090                    const isCustomized = !!costumesConfig[c.id];
2091                    return /* @__PURE__ */ jsxRuntimeExports.jsxs(
2092                      "div",
2093                      {
2094                        onClick: () => setSelectedCostumeId(c.id),
2095                        className: `cursor-pointer rounded-xl p-2.5 flex flex-col items-center justify-between gap-2 border transition-all ${isSelected ? "bg-indigo-950/40 border-indigo-500 shadow-lg shadow-indigo-950/50 ring-1 ring-indigo-500" : "bg-zinc-950/80 border-zinc-800 hover:border-zinc-700 hover:bg-zinc-900/80"}`,
2096                        children: [
2097                          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full aspect-square bg-zinc-900/90 rounded-lg flex items-center justify-center p-2 relative overflow-hidden border border-zinc-800/60", children: [
2098                            /* @__PURE__ */ jsxRuntimeExports.jsx(
2099                              "div",
2100                              {
2101                                className: "absolute inset-0 opacity-10 pointer-events-none",
2102                                style: {
2103                                  backgroundImage: "linear-gradient(45deg, #808080 25%, transparent 25%), linear-gradient(-45deg, #808080 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #808080 75%), linear-gradient(-45deg, transparent 75%, #808080 75%)",
2104                                  backgroundSize: "12px 12px",
2105                                  backgroundPosition: "0 0, 0 6px, 6px -6px, -6px 0px"
2106                                }
2107                              }
2108                            ),
2109                            c.svgContent ? /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { viewBox: "-60 -70 120 120", className: "w-full h-full relative z-10 drop-shadow-md overflow-visible", children: /* @__PURE__ */ jsxRuntimeExports.jsx("g", { dangerouslySetInnerHTML: { __html: c.svgContent } }) }) : c.url ? /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: c.url, alt: c.name, className: "w-full h-full object-contain relative z-10 drop-shadow-md" }) : null,
2110                            isCustomized && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute top-1 right-1 w-2 h-2 rounded-full bg-emerald-400", title: "Custom calibrated" })
2111                          ] }),
2112                          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full text-center", children: [
2113                            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `text-xs font-semibold truncate ${isSelected ? "text-indigo-300" : "text-zinc-200"}`, title: c.name, children: c.name }),
2114                            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-zinc-500 font-mono capitalize", children: c.type })
2115                          ] })
2116                        ]
2117                      },
2118                      c.id
2119                    );
2120                  }),
2121                  filteredCostumes.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "col-span-full py-12 text-center text-zinc-500 text-xs", children: "No costumes found in this category." })
2122                ] })
2123              ] }),
2124              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "lg:col-span-7 bg-zinc-900/60 border border-zinc-800 rounded-2xl p-5 shadow-2xl flex flex-col gap-5", children: [
2125                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 border-b border-zinc-800 pb-4", children: [
2126                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
2127                    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-semibold text-zinc-300 uppercase tracking-wider", children: "Test On:" }),
2128                    /* @__PURE__ */ jsxRuntimeExports.jsx(
2129                      "select",
2130                      {
2131                        value: fittingAnimalId,
2132                        onChange: (e) => setFittingAnimalId(e.target.value),
2133                        className: "bg-zinc-950 border border-zinc-700 rounded-lg px-2.5 py-1.5 text-xs text-white focus:outline-none focus:border-indigo-500",
2134                        children: Object.values(BASE_ANIMALS).map((a) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: a.id, className: "bg-zinc-900 text-white", children: a.name }, a.id))
2135                      }
2136                    ),
2137                    /* @__PURE__ */ jsxRuntimeExports.jsxs(
2138                      "select",
2139                      {
2140                        value: fittingPose,
2141                        onChange: (e) => setFittingPose(e.target.value),
2142                        className: "bg-zinc-950 border border-zinc-700 rounded-lg px-2.5 py-1.5 text-xs text-white focus:outline-none focus:border-indigo-500",
2143                        children: [
2144                          /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "standard", className: "bg-zinc-900 text-white", children: "Pose: Neutral Standing" }),
2145                          /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "guitar", className: "bg-zinc-900 text-white", children: "Pose: Guitar Strumming" }),
2146                          /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "drumming", className: "bg-zinc-900 text-white", children: "Pose: Drum Beating" }),
2147                          /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "bowing", className: "bg-zinc-900 text-white", children: "Pose: Cello Bowing" }),
2148                          /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "sitting", className: "bg-zinc-900 text-white", children: "Pose: Piano Seated" }),
2149                          /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "blowing", className: "bg-zinc-900 text-white", children: "Pose: Trumpet Wind" })
2150                        ]
2151                      }
2152                    )
2153                  ] }),
2154                  /* @__PURE__ */ jsxRuntimeExports.jsxs(
2155                    "button",
2156                    {
2157                      onClick: () => setFittingAnimating(!fittingAnimating),
2158                      className: `px-3 py-1.5 rounded-lg text-xs font-semibold flex items-center gap-1.5 transition-colors border ${fittingAnimating ? "bg-emerald-500/20 text-emerald-400 border-emerald-500/30" : "bg-zinc-800 text-zinc-400 border-zinc-700"}`,
2159                      children: [
2160                        fittingAnimating ? /* @__PURE__ */ jsxRuntimeExports.jsx(Pause, { size: 13 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Play, { size: 13 }),
2161                        fittingAnimating ? "Physics Active" : "Physics Paused"
2162                      ]
2163                    }
2164                  )
2165                ] }),
2166                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full h-80 bg-zinc-950/90 rounded-xl flex items-center justify-center p-4 relative overflow-hidden border border-zinc-800/80 shadow-inner", children: [
2167                  /* @__PURE__ */ jsxRuntimeExports.jsx(
2168                    "div",
2169                    {
2170                      className: "absolute inset-0 opacity-15 pointer-events-none",
2171                      style: {
2172                        backgroundImage: "linear-gradient(45deg, #404040 25%, transparent 25%), linear-gradient(-45deg, #404040 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #404040 75%), linear-gradient(-45deg, transparent 75%, #404040 75%)",
2173                        backgroundSize: "24px 24px",
2174                        backgroundPosition: "0 0, 0 12px, 12px -12px, -12px 0px"
2175                      }
2176                    }
2177                  ),
2178                  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 bg-radial-gradient pointer-events-none opacity-20", style: { background: "radial-gradient(circle at 50% 60%, #6366f1 0%, transparent 60%)" } }),
2179                  /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { viewBox: "0 0 200 300", className: "w-full h-full relative z-10 overflow-visible", children: /* @__PURE__ */ jsxRuntimeExports.jsx("g", { transform: "translate(100, 160) scale(1.05)", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2180                    SouthparkCharacter,
2181                    {
2182                      animal: fittingAnimal,
2183                      instrument: {
2184                        id: 1,
2185                        name: fittingPose,
2186                        type: "preview",
2187                        holdStyle: fittingPose,
2188                        group: "Preview",
2189                        imgUrl: POSE_INSTRUMENTS_IMG[fittingPose] || void 0,
2190                        svgContent: void 0
2191                      },
2192                      isActive: fittingAnimating && currentVelocityPulse > 0,
2193                      velocity: currentVelocityPulse,
2194                      physicsMode: "smooth",
2195                      costumes: [activeCostumeDef],
2196                      customCostumesMap: allCostumesMap,
2197                      showInstrument: true
2198                    }
2199                  ) }) }),
2200                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute top-3 left-3 z-20 flex items-center gap-2 bg-zinc-900/90 backdrop-blur-md border border-zinc-800 px-3 py-1.5 rounded-lg shadow-lg", children: [
2201                    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-2 h-2 rounded-full bg-indigo-400 animate-pulse" }),
2202                    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-semibold text-white", children: activeCostumeDef == null ? void 0 : activeCostumeDef.name }),
2203                    /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] text-zinc-400 font-mono", children: [
2204                      "(",
2205                      activeCostumeDef == null ? void 0 : activeCostumeDef.type,
2206                      ")"
2207                    ] })
2208                  ] })
2209                ] }),
2210                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-950/80 border border-zinc-800 rounded-xl p-4 space-y-4", children: [
2211                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between border-b border-zinc-800/80 pb-2.5", children: [
2212                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
2213                      /* @__PURE__ */ jsxRuntimeExports.jsx(SlidersVertical, { size: 15, className: "text-indigo-400" }),
2214                      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-bold text-white uppercase tracking-wider", children: "Placement & Scale Calibration" })
2215                    ] }),
2216                    /* @__PURE__ */ jsxRuntimeExports.jsxs(
2217                      "button",
2218                      {
2219                        onClick: resetActiveCostume,
2220                        className: "text-[11px] text-zinc-400 hover:text-white flex items-center gap-1 transition-colors px-2 py-1 rounded bg-zinc-900 border border-zinc-800",
2221                        children: [
2222                          /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { size: 12 }),
2223                          " Reset to Default"
2224                        ]
2225                      }
2226                    )
2227                  ] }),
2228                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: [
2229                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
2230                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-xs mb-1", children: [
2231                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400 font-medium", children: "Horizontal Offset (X)" }),
2232                        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-indigo-400 font-mono font-bold", children: [
2233                          (activeCostumeDef == null ? void 0 : activeCostumeDef.offsetX) ?? 0,
2234                          "px"
2235                        ] })
2236                      ] }),
2237                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
2238                        /* @__PURE__ */ jsxRuntimeExports.jsx(
2239                          "input",
2240                          {
2241                            type: "range",
2242                            min: "-80",
2243                            max: "80",
2244                            step: "1",
2245                            value: (activeCostumeDef == null ? void 0 : activeCostumeDef.offsetX) ?? 0,
2246                            onChange: (e) => updateActiveCostume("offsetX", parseFloat(e.target.value) || 0),
2247                            className: "flex-1 accent-indigo-500 h-1.5 bg-zinc-800 rounded-lg cursor-pointer"
2248                          }
2249                        ),
2250                        /* @__PURE__ */ jsxRuntimeExports.jsx(
2251                          "input",
2252                          {
2253                            type: "number",
2254                            value: (activeCostumeDef == null ? void 0 : activeCostumeDef.offsetX) ?? 0,
2255                            onChange: (e) => updateActiveCostume("offsetX", parseFloat(e.target.value) || 0),
2256                            className: "w-16 bg-zinc-900 border border-zinc-800 rounded px-2 py-1 text-xs text-white text-center font-mono"
2257                          }
2258                        )
2259                      ] })
2260                    ] }),
2261                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
2262                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-xs mb-1", children: [
2263                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400 font-medium", children: "Vertical Offset (Y)" }),
2264                        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-indigo-400 font-mono font-bold", children: [
2265                          (activeCostumeDef == null ? void 0 : activeCostumeDef.offsetY) ?? 0,
2266                          "px"
2267                        ] })
2268                      ] }),
2269                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
2270                        /* @__PURE__ */ jsxRuntimeExports.jsx(
2271                          "input",
2272                          {
2273                            type: "range",
2274                            min: "-80",
2275                            max: "80",
2276                            step: "1",
2277                            value: (activeCostumeDef == null ? void 0 : activeCostumeDef.offsetY) ?? 0,
2278                            onChange: (e) => updateActiveCostume("offsetY", parseFloat(e.target.value) || 0),
2279                            className: "flex-1 accent-indigo-500 h-1.5 bg-zinc-800 rounded-lg cursor-pointer"
2280                          }
2281                        ),
2282                        /* @__PURE__ */ jsxRuntimeExports.jsx(
2283                          "input",
2284                          {
2285                            type: "number",
2286                            value: (activeCostumeDef == null ? void 0 : activeCostumeDef.offsetY) ?? 0,
2287                            onChange: (e) => updateActiveCostume("offsetY", parseFloat(e.target.value) || 0),
2288                            className: "w-16 bg-zinc-900 border border-zinc-800 rounded px-2 py-1 text-xs text-white text-center font-mono"
2289                          }
2290                        )
2291                      ] })
2292                    ] }),
2293                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
2294                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-xs mb-1", children: [
2295                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400 font-medium", children: "Scale Factor" }),
2296                        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-indigo-400 font-mono font-bold", children: [
2297                          Math.round(((activeCostumeDef == null ? void 0 : activeCostumeDef.scale) ?? 1) * 100),
2298                          "%"
2299                        ] })
2300                      ] }),
2301                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
2302                        /* @__PURE__ */ jsxRuntimeExports.jsx(
2303                          "input",
2304                          {
2305                            type: "range",
2306                            min: "0.4",
2307                            max: "2.5",
2308                            step: "0.02",
2309                            value: (activeCostumeDef == null ? void 0 : activeCostumeDef.scale) ?? 1,
2310                            onChange: (e) => updateActiveCostume("scale", parseFloat(e.target.value) || 1),
2311                            className: "flex-1 accent-indigo-500 h-1.5 bg-zinc-800 rounded-lg cursor-pointer"
2312                          }
2313                        ),
2314                        /* @__PURE__ */ jsxRuntimeExports.jsx(
2315                          "input",
2316                          {
2317                            type: "number",
2318                            step: "0.05",
2319                            value: (activeCostumeDef == null ? void 0 : activeCostumeDef.scale) ?? 1,
2320                            onChange: (e) => updateActiveCostume("scale", parseFloat(e.target.value) || 1),
2321                            className: "w-16 bg-zinc-900 border border-zinc-800 rounded px-2 py-1 text-xs text-white text-center font-mono"
2322                          }
2323                        )
2324                      ] })
2325                    ] }),
2326                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
2327                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-xs mb-1", children: [
2328                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400 font-medium", children: "Rotation Angle" }),
2329                        /* @__P
2329URE__ */ jsxRuntimeExports.jsxs("span", { className: "text-indigo-400 font-mono font-bold", children: [
2330                          (activeCostumeDef == null ? void 0 : activeCostumeDef.rotation) ?? 0,
2331                          "°"
2332                        ] })
2333                      ] }),
2334                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
2335                        /* @__PURE__ */ jsxRuntimeExports.jsx(
2336                          "input",
2337                          {
2338                            type: "range",
2339                            min: "-90",
2340                            max: "90",
2341                            step: "1",
2342                            value: (activeCostumeDef == null ? void 0 : activeCostumeDef.rotation) ?? 0,
2343                            onChange: (e) => updateActiveCostume("rotation", parseFloat(e.target.value) || 0),
2344                            className: "flex-1 accent-indigo-500 h-1.5 bg-zinc-800 rounded-lg cursor-pointer"
2345                          }
2346                        ),
2347                        /* @__PURE__ */ jsxRuntimeExports.jsx(
2348                          "input",
2349                          {
2350                            type: "number",
2351                            value: (activeCostumeDef == null ? void 0 : activeCostumeDef.rotation) ?? 0,
2352                            onChange: (e) => updateActiveCostume("rotation", parseFloat(e.target.value) || 0),
2353                            className: "w-16 bg-zinc-900 border border-zinc-800 rounded px-2 py-1 text-xs text-white text-center font-mono"
2354                          }
2355                        )
2356                      ] })
2357                    ] })
2358                  ] }),
2359                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pt-2 border-t border-zinc-800/60 flex flex-wrap items-center justify-between gap-3 text-xs text-zinc-400", children: [
2360                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
2361                      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-zinc-300", children: "Kinematic Anchor:" }),
2362                      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `px-2 py-0.5 rounded text-[10px] font-bold uppercase tracking-wider ${(activeCostumeDef == null ? void 0 : activeCostumeDef.anchorTo) === "head" || (activeCostumeDef == null ? void 0 : activeCostumeDef.type) === "hat" || (activeCostumeDef == null ? void 0 : activeCostumeDef.type) === "glasses" ? "bg-cyan-500/20 text-cyan-300 border border-cyan-500/30" : "bg-emerald-500/20 text-emerald-300 border border-emerald-500/30"}`, children: (activeCostumeDef == null ? void 0 : activeCostumeDef.anchorTo) === "head" || (activeCostumeDef == null ? void 0 : activeCostumeDef.type) === "hat" || (activeCostumeDef == null ? void 0 : activeCostumeDef.type) === "glasses" ? "Head Socket (Rotates with head)" : "Body Socket (Bounces with torso)" })
2363                    ] }),
2364                    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] text-zinc-500", children: 'Changes are saved when you click "Save All Changes" at the top' })
2365                  ] })
2366                ] })
2367              ] })
2368            ] })
2369          ] });
2370        })(),
2371        activeTab === "preview" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col h-full space-y-4", children: [
2372          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-none flex items-center gap-4 border-b border-zinc-800 pb-4", children: [
2373            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
2374              /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-xl font-bold", children: "Live Preview" }),
2375              /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-400", children: "Enter a MIDI ID to test the current configurations in the actual player" })
2376            ] }),
2377            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ml-auto flex items-center gap-3", children: [
2378              /* @__PURE__ */ jsxRuntimeExports.jsx(
2379                "input",
2380                {
2381                  type: "text",
2382                  placeholder: "Enter Track ID (e.g. 1234)",
2383                  value: previewMidiId,
2384                  onChange: (e) => setPreviewMidiId(e.target.value),
2385                  onKeyDown: (e) => {
2386                    if (e.key === "Enter" && previewMidiId) {
2387                      setIframeUrl(previewMidiId);
2388                    }
2389                  },
2390                  className: "bg-zinc-900 border border-zinc-700 rounded-lg px-4 py-2 text-sm text-white w-64"
2391                }
2392              ),
2393              /* @__PURE__ */ jsxRuntimeExports.jsxs(
2394                "button",
2395                {
2396                  onClick: () => {
2397                    if (previewMidiId) {
2398                      setIframeUrl(previewMidiId);
2399                    }
2400                  },
2401                  className: "px-4 py-2 bg-indigo-600 hover:bg-indigo-500 text-white text-sm font-medium rounded-lg transition-colors flex items-center gap-2",
2402                  children: [
2403                    /* @__PURE__ */ jsxRuntimeExports.jsx(CirclePlay, { size: 16 }),
2404                    " Load Player"
2405                  ]
2406                }
2407              )
2408            ] })
2409          ] }),
2410          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 bg-black rounded-xl border border-zinc-800 overflow-hidden relative", children: !iframeUrl ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center text-zinc-600", children: [
2411            /* @__PURE__ */ jsxRuntimeExports.jsx(CirclePlay, { size: 48, className: "mb-4 opacity-50" }),
2412            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Enter a Track ID and click Load to see the preview" })
2413          ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(StandaloneSouthparkViewer, { trackId: iframeUrl }, iframeUrl) })
2414        ] })
2415      ] })
2416    ] }),
2417    inspectingPose && /* @__PURE__ */ jsxRuntimeExports.jsx(
2418      "div",
2419      {
2420        className: "fixed inset-0 z-50 bg-black/85 backdrop-blur-md flex items-center justify-center p-4",
2421        onClick: () => setInspectingPose(null),
2422        children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
2423          "div",
2424          {
2425            className: "bg-zinc-950 border border-cyan-500/40 rounded-2xl max-w-5xl w-full shadow-2xl shadow-cyan-950/80 overflow-hidden flex flex-col max-h-[92vh]",
2426            onClick: (e) => e.stopPropagation(),
2427            children: [
2428              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between border-b border-cyan-900/50 px-6 py-4 bg-gradient-to-r from-cyan-950/40 via-zinc-950 to-zinc-950", children: [
2429                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
2430                  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-9 h-9 rounded-xl bg-cyan-500/20 text-cyan-400 flex items-center justify-center font-bold text-lg border border-cyan-500/30", children: "🦴" }),
2431                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
2432                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
2433                      /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-lg font-bold text-cyan-100 tracking-wide", children: "Kinematic Joint Socket Inspector" }),
2434                      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `px-2 py-0.5 rounded text-xs font-bold border ${inspectingPose.badgeColor}`, children: inspectingPose.name })
2435                    ] }),
2436                    /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-zinc-400", children: [
2437                      inspectingPose.desc,
2438                      " • Hold Style: ",
2439                      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-cyan-300 font-mono font-semibold", children: inspectingPose.holdStyle })
2440                    ] })
2441                  ] })
2442                ] }),
2443                /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2444                  "button",
2445                  {
2446                    onClick: () => setInspectingPose(null),
2447                    className: "p-2 rounded-lg bg-zinc-900 text-zinc-400 hover:text-white hover:bg-zinc-800 border border-zinc-800 transition-colors",
2448                    title: "Close Inspector (Esc)",
2449                    children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { size: 18 })
2450                  }
2451                ) })
2452              ] }),
2453              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-12 gap-6 p-6 overflow-y-auto", children: [
2454                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "lg:col-span-7 flex flex-col gap-3", children: [
2455                  /* @__PURE__ */ jsxRuntimeExports.jsxs(
2456                    "div",
2457                    {
2458                      className: "w-full aspect-square bg-slate-950 rounded-xl border border-cyan-800/60 relative overflow-hidden flex items-center justify-center shadow-inner cursor-grab active:cursor-grabbing select-none",
2459                      style: {
2460                        backgroundImage: "radial-gradient(circle, rgba(14, 165, 233, 0.12) 1px, transparent 1px)",
2461                        backgroundSize: "16px 16px"
2462                      },
2463                      onWheel: (e) => {
2464                        e.preventDefault();
2465                        const delta = e.deltaY < 0 ? 0.3 : -0.3;
2466                        setModalZoom((prev) => Math.min(6, Math.max(1, parseFloat((prev + delta).toFixed(2)))));
2467                      },
2468                      onMouseDown: (e) => {
2469                        setIsModalDragging(true);
2470                        setDragStart({ x: e.clientX, y: e.clientY });
2471                      },
2472                      onMouseMove: (e) => {
2473                        if (!isModalDragging) return;
2474                        const dx = (e.clientX - dragStart.x) / modalZoom;
2475                        const dy = (e.clientY - dragStart.y) / modalZoom;
2476                        setModalPan((prev) => ({ x: prev.x + dx, y: prev.y + dy }));
2477                        setDragStart({ x: e.clientX, y: e.clientY });
2478                      },
2479                      onMouseUp: () => setIsModalDragging(false),
2480                      onMouseLeave: () => setIsModalDragging(false),
2481                      children: [
2482                        /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { viewBox: getDynamicViewBox(modalZoom, modalPan), className: "w-full h-full overflow-visible drop-shadow-2xl", children: /* @__PURE__ */ jsxRuntimeExports.jsx("g", { transform: "translate(100, 155)", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2483                          SouthparkCharacter,
2484                          {
2485                            animal: BASE_ANIMALS[inspectorAnimalId] || BASE_ANIMALS.fox,
2486                            customConfig: charactersConfig[inspectorAnimalId],
2487                            instrument: {
2488                              id: 1,
2489                              name: inspectingPose.name,
2490                              type: "preview",
2491                              holdStyle: inspectingPose.holdStyle,
2492                              group: "Preview",
2493                              imgUrl: POSE_INSTRUMENTS_IMG[inspectingPose.id] || void 0,
2494                              svgContent: void 0
2495                            },
2496                            isActive: !manualOverrideLimbAngles && isGlobalAnimating && inspectingPose.id !== "standard" && currentVelocityPulse > 0,
2497                            velocity: !manualOverrideLimbAngles && isGlobalAnimating && inspectingPose.id !== "standard" && currentVelocityPulse > 0 ? currentVelocityPulse : 0,
2498                            physicsMode: "smooth",
2499                            showInstrument: modalShowInstrument,
2500                            skeletonOnly: modalDisplayMode !== "full",
2501                            ghostSilhouette: modalDisplayMode === "ghost",
2502                            showSkeleton: true,
2503                            manualLimbAngles: manualOverrideLimbAngles ? {
2504                              shoulderL: manualLeftShoulder,
2505                              relElbowL: manualLeftElbow,
2506                              shoulderR: manualRightShoulder,
2507                              relElbowR: manualRightElbow
2508                            } : void 0
2509                          }
2510                        ) }) }),
2511                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute top-3 left-3 flex flex-wrap items-center gap-1 bg-zinc-950/80 p-1 rounded-lg border border-cyan-900/50 backdrop-blur-sm text-xs", children: [
2512                          /* @__PURE__ */ jsxRuntimeExports.jsx(
2513                            "button",
2514                            {
2515                              onClick: () => setModalDisplayMode("pure"),
2516                              className: `px-2 py-1 rounded text-[10px] font-bold transition-all ${modalDisplayMode === "pure" ? "bg-cyan-500 text-black shadow-sm" : "text-zinc-400 hover:text-white"}`,
2517                              children: "Pure Skeleton"
2518                            }
2519                          ),
2520                          /* @__PURE__ */ jsxRuntimeExports.jsx(
2521                            "button",
2522                            {
2523                              onClick: () => setModalDisplayMode("ghost"),
2524                              className: `px-2 py-1 rounded text-[10px] font-bold transition-all ${modalDisplayMode === "ghost" ? "bg-cyan-500 text-black shadow-sm" : "text-zinc-400 hover:text-white"}`,
2525                              children: "Ghost Body"
2526                            }
2527                          ),
2528                          /* @__PURE__ */ jsxRuntimeExports.jsx(
2529                            "button",
2530                            {
2531                              onClick: () => setModalDisplayMode("full"),
2532                              className: `px-2 py-1 rounded text-[10px] font-bold transition-all ${modalDisplayMode === "full" ? "bg-cyan-500 text-black shadow-sm" : "text-zinc-400 hover:text-white"}`,
2533                              children: "Full Character"
2534                            }
2535                          ),
2536                          /* @__PURE__ */ jsxRuntimeExports.jsxs(
2537                            "button",
2538                            {
2539                              onClick: () => setModalShowInstrument((prev) => !prev),
2540                              className: `px-2 py-1 rounded text-[10px] font-bold transition-all ${modalShowInstrument ? "bg-amber-500/20 text-amber-300 border border-amber-500/40" : "text-zinc-500 hover:text-zinc-300"}`,
2541                              children: [
2542                                "Instrument: ",
2543                                modalShowInstrument ? "ON" : "OFF"
2544                              ]
2545                            }
2546                          )
2547                        ] }),
2548                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute bottom-3 inset-x-3 flex items-center justify-between pointer-events-none", children: [
2549                          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pointer-events-auto flex items-center gap-1.5 bg-zinc-950/85 px-3 py-1.5 rounded-lg border border-cyan-800/60 backdrop-blur-sm text-xs font-mono text-cyan-200 shadow-xl", children: [
2550                            /* @__PURE__ */ jsxRuntimeExports.jsx(
2551                              "button",
2552                              {
2553                                onClick: () => setModalZoom((z) => Math.max(1, parseFloat((z - 0.5).toFixed(2)))),
2554                                className: "p-1 rounded hover:bg-cyan-900/50 text-cyan-400 transition-colors",
2555                                title: "Zoom Out",
2556                                children: /* @__PURE__ */ jsxRuntimeExports.jsx(ZoomOut, { size: 14 })
2557                              }
2558                            ),
2559                            /* @__PURE__ */ jsxRuntimeExports.jsx(
2560                              "input",
2561                              {
2562                                type: "range",
2563                                min: "1.0",
2564                                max: "6.0",
2565                                step: "0.25",
2566                                value: modalZoom,
2567                                onChange: (e) => setModalZoom(parseFloat(e.target.value)),
2568                                className: "w-20 accent-cyan-400 h-1.5 bg-zinc-800 rounded-lg cursor-pointer"
2569                              }
2570                            ),
2571                            /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-bold min-w-[45px] text-right", children: [
2572                              Math.round(modalZoom * 100),
2573                              "%"
2574                            ] }),
2575                            /* @__PURE__ */ jsxRuntimeExports.jsx(
2576                              "button",
2577                              {
2578                                onClick: () => setModalZoom((z) => Math.min(6, parseFloat((z + 0.5).toFixed(2)))),
2579                                className: "p-1 rounded hover:bg-cyan-900/50 text-cyan-400 transition-colors",
2580                                title: "Zoom In",
2581                                children: /* @__PURE__ */ jsxRuntimeExports.jsx(ZoomIn, { size: 14 })
2582                              }
2583                            ),
2584                            /* @__PURE__ */ jsxRuntimeExports.jsx(
2585                              "button",
2586                              {
2587                                onClick: () => {
2588                                  setModalZoom(2.5);
2589                                  setModalPan({ x: 0, y: 0 });
2590                                },
2591                                className: "ml-2 px-2 py-0.5 rounded text-[10px] bg-cyan-900/40 hover:bg-cyan-800/50 text-cyan-300 border border-cyan-700/40 transition-colors",
2592                                children: "Reset"
2593                              }
2594                            ),
2595                            /* @__PURE__ */ jsxRuntimeExports.jsx(
2596                              "button",
2597                              {
2598                                onClick: () => {
2599                                  setModalZoom(1);
2600                                  setModalPan({ x: 0, y: 0 });
2601                                },
2602                                className: "px-2 py-0.5 rounded text-[10px] bg-zinc-900 hover:bg-zinc-800 text-zinc-300 border border-zinc-700/40 transition-colors",
2603                                children: "Fit (1x)"
2604                              }
2605                            )
2606                          ] }),
2607                          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] font-mono text-zinc-400 bg-zinc-950/80 px-2 py-1 rounded border border-zinc-800 pointer-events-none", children: "🖱️ Scroll: Zoom • Drag: Pan" })
2608                        ] })
2609                      ]
2610                    }
2611                  ),
2612                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs bg-zinc-900/60 p-2 rounded-xl border border-zinc-800/60", children: [
2613                    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400 font-medium", children: "Model:" }),
2614                    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1.5", children: Object.values(BASE_ANIMALS).map((a) => /* @__PURE__ */ jsxRuntimeExports.jsx(
2615                      "button",
2616                      {
2617                        onClick: () => setInspectorAnimalId(a.id),
2618                        className: `px-2.5 py-1 rounded-lg text-xs font-bold transition-all ${inspectorAnimalId === a.id ? "bg-cyan-500 text-black shadow-sm" : "bg-zinc-950 text-zinc-400 hover:text-white border border-zinc-800"}`,
2619                        children: a.name
2620                      },
2621                      a.id
2622                    )) })
2623                  ] })
2624                ] }),
2625                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "lg:col-span-5 flex flex-col gap-4", children: [
2626                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900/80 border border-cyan-900/50 rounded-xl p-4 space-y-3", children: [
2627                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between border-b border-cyan-900/40 pb-2", children: [
2628                      /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs font-bold text-cyan-200 tracking-wide uppercase flex items-center gap-2", children: [
2629                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-2 h-2 rounded-full bg-emerald-400 animate-pulse" }),
2630                        "Kinematic Socket Integrity"
2631                      ] }),
2632                      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] font-mono px-2 py-0.5 rounded bg-emerald-950/60 text-emerald-300 border border-emerald-800/40 font-bold", children: "0.0000px SEPARATION" })
2633                    ] }),
2634                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1.5 font-mono text-[11px]", children: [
2635                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between p-1.5 rounded bg-zinc-950/60 border border-zinc-800/50", children: [
2636                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400", children: "Torso Clavicle ↔ Left Shoulder:" }),
2637                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400 font-bold", children: "0.0000px [CONNECTED]" })
2638                      ] }),
2639                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between p-1.5 rounded bg-zinc-950/60 border border-zinc-800/50", children: [
2640                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400", children: "Left Shoulder ↔ Upper Arm Top:" }),
2641                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400 font-bold", children: "0.0000px [CONNECTED]" })
2642                      ] }),
2643                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between p-1.5 rounded bg-zinc-950/60 border border-zinc-800/50", children: [
2644                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400", children: "Left Upper Arm ↔ Forearm (Elbow):" }),
2645                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400 font-bold", children: "0.0000px [CONNECTED]" })
2646                      ] }),
2647                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between p-1.5 rounded bg-zinc-950/60 border border-zinc-800/50", children: [
2648                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400", children: "Left Forearm ↔ Hand (Wrist):" }),
2649                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400 font-bold", children: "0.0000px [CONNECTED]" })
2650                      ] }),
2651                      /* @__P
2651URE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between p-1.5 rounded bg-zinc-950/60 border border-zinc-800/50", children: [
2652                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400", children: "Right Shoulder ↔ Upper Arm Top:" }),
2653                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400 font-bold", children: "0.0000px [CONNECTED]" })
2654                      ] }),
2655                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between p-1.5 rounded bg-zinc-950/60 border border-zinc-800/50", children: [
2656                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400", children: "Right Upper Arm ↔ Forearm (Elbow):" }),
2657                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400 font-bold", children: "0.0000px [CONNECTED]" })
2658                      ] }),
2659                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between p-1.5 rounded bg-zinc-950/60 border border-zinc-800/50", children: [
2660                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400", children: "Right Forearm ↔ Hand (Wrist):" }),
2661                        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400 font-bold", children: "0.0000px [CONNECTED]" })
2662                      ] })
2663                    ] })
2664                  ] }),
2665                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900/80 border border-zinc-800 rounded-xl p-4 space-y-3", children: [
2666                    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between border-b border-zinc-800 pb-2", children: [
2667                      /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs font-bold text-zinc-200 tracking-wide uppercase flex items-center gap-2", children: [
2668                        /* @__PURE__ */ jsxRuntimeExports.jsx(SlidersVertical, { size: 14, className: "text-cyan-400" }),
2669                        "Manual Angle Scrubbing Test"
2670                      ] }),
2671                      /* @__PURE__ */ jsxRuntimeExports.jsx(
2672                        "button",
2673                        {
2674                          onClick: () => setManualOverrideLimbAngles((prev) => !prev),
2675                          className: `px-2.5 py-1 rounded text-xs font-bold transition-all ${manualOverrideLimbAngles ? "bg-amber-500 text-black shadow-sm" : "bg-zinc-800 text-zinc-300 hover:text-white"}`,
2676                          children: manualOverrideLimbAngles ? "Override: ACTIVE" : "Enable Sliders"
2677                        }
2678                      )
2679                    ] }),
2680                    manualOverrideLimbAngles ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3 pt-1", children: [
2681                      /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-amber-300/90 leading-tight", children: "Drag the sliders below to rotate joints across extreme angles and verify that the upper arm, elbow, and forearm remain 100% attached at all times." }),
2682                      /* @__P
2682URE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
2683                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-xs font-mono", children: [
2684                          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400", children: "Left Shoulder Rotation:" }),
2685                          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-emerald-400 font-bold", children: [
2686                            manualLeftShoulder,
2687                            "°"
2688                          ] })
2689                        ] }),
2690                        /* @__PURE__ */ jsxRuntimeExports.jsx(
2691                          "input",
2692                          {
2693                            type: "range",
2694                            min: "-180",
2695                            max: "180",
2696                            value: manualLeftShoulder,
2697                            onChange: (e) => setManualLeftShoulder(parseInt(e.target.value)),
2698                            className: "w-full accent-emerald-500 h-1.5 bg-zinc-800 rounded cursor-pointer"
2699                          }
2700                        )
2701                      ] }),
2702                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
2703                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-xs font-mono", children: [
2704                          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400", children: "Left Elbow (Rel to Upper):" }),
2705                          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-emerald-400 font-bold", children: [
2706                            manualLeftElbow,
2707                            "°"
2708                          ] })
2709                        ] }),
2710                        /* @__PURE__ */ jsxRuntimeExports.jsx(
2711                          "input",
2712                          {
2713                            type: "range",
2714                            min: "-170",
2715                            max: "0",
2716                            value: manualLeftElbow,
2717                            onChange: (e) => setManualLeftElbow(parseInt(e.target.value)),
2718                            className: "w-full accent-emerald-500 h-1.5 bg-zinc-800 rounded cursor-pointer"
2719                          }
2720                        ),
2721                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-[10px] text-zinc-500 font-mono", children: [
2722                          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Max Flex: -170°" }),
2723                          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Straight: 0°" })
2724                        ] })
2725                      ] }),
2726                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
2727                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-xs font-mono", children: [
2728                          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400", children: "Right Shoulder Rotation:" }),
2729                          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-purple-400 font-bold", children: [
2730                            manualRightShoulder,
2731                            "°"
2732                          ] })
2733                        ] }),
2734                        /* @__PURE__ */ jsxRuntimeExports.jsx(
2735                          "input",
2736                          {
2737                            type: "range",
2738                            min: "-180",
2739                            max: "180",
2740                            value: manualRightShoulder,
2741                            onChange: (e) => setManualRightShoulder(parseInt(e.target.value)),
2742                            className: "w-full accent-purple-500 h-1.5 bg-zinc-800 rounded cursor-pointer"
2743                          }
2744                        )
2745                      ] }),
2746                      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
2747                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-xs font-mono", children: [
2748                          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400", children: "Right Elbow (Rel to Upper):" }),
2749                          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-purple-400 font-bold", children: [
2750                            "+",
2751                            manualRightElbow,
2752                            "°"
2753                          ] })
2754                        ] }),
2755                        /* @__PURE__ */ jsxRuntimeExports.jsx(
2756                          "input",
2757                          {
2758                            type: "range",
2759                            min: "0",
2760                            max: "170",
2761                            value: manualRightElbow,
2762                            onChange: (e) => setManualRightElbow(parseInt(e.target.value)),
2763                            className: "w-full accent-purple-500 h-1.5 bg-zinc-800 rounded cursor-pointer"
2764                          }
2765                        ),
2766                        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-[10px] text-zinc-500 font-mono", children: [
2767                          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Straight: 0°" }),
2768                          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Max Flex: +170°" })
2769                        ] })
2770                      ] }),
2771                      /* @__PURE__ */ jsxRuntimeExports.jsx(
2772                        "button",
2773                        {
2774                          onClick: () => {
2775                            setManualLeftShoulder(-45);
2776                            setManualLeftElbow(-60);
2777                            setManualRightShoulder(45);
2778                            setManualRightElbow(60);
2779                          },
2780                          className: "w-full py-1.5 bg-zinc-800 hover:bg-zinc-700 text-xs font-semibold rounded-lg transition-colors text-zinc-300",
2781                          children: "Reset Manual Angles"
2782                        }
2783                      )
2784                    ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "py-4 text-center text-xs text-zinc-500 space-y-1", children: [
2785                      /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Currently playing automatic performance kinematics." }),
2786                      /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-zinc-600", children: "Click “Enable Sliders” to manually rotate joints and test physical attachment." })
2787                    ] })
2788                  ] })
2789                ] })
2790              ] })
2791            ]
2792          }
2793        )
2794      }
2795    )
2796  ] });
2797}
2798export {
2799  ACTION_POSES,
2800  POSE_INSTRUMENTS_IMG,
2801  POSE_INSTRUMENTS_SVG,
2802  SouthparkStudio as default
2803};

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.