(function () {
  'use strict';

  const t = {
    bgPage: '#0f0f0f', bgCard: '#1a1a1a', bgCardAlt: '#141414', bgInput: '#111',
    bgHover: '#222', bgSunken: '#0a0a0a', bgOverlay: 'rgba(0,0,0,0.75)',
    border: '#2a2a2a', borderSubtle: '#1e1e1e',
    textPrimary: '#f5f5f5', textSecondary: '#aaaaaa', textMuted: '#666',
    textDisabled: '#444', accent: '#00ff00', accentText: '#000',
    error: '#ff4444',
  };

  const INTERPOLATION_MODES = ['linear', 'bezier', 'easeIn', 'easeOut', 'easeInOut', 'hold'];
  const INTERPOLATION_LABELS = { linear: 'Linear', bezier: 'Bezier', easeIn: 'Ease In', easeOut: 'Ease Out', easeInOut: 'Ease In/Out', hold: 'Hold' };
  const INTERPOLATION_SYMBOL = { linear: '◇', bezier: '◆', easeIn: '◁', easeOut: '▷', easeInOut: '◈', hold: '■' };
  const INTERPOLATION_COLOR = { linear: 'rgba(255,165,0,0.9)', bezier: 'rgba(180,100,255,0.9)', easeIn: 'rgba(80,180,255,0.9)', easeOut: 'rgba(80,255,180,0.9)', easeInOut: 'rgba(100,220,120,0.9)', hold: 'rgba(255,80,80,0.9)' };

  const IconMove = () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polyline points="5 9 2 12 5 15"/><polyline points="9 5 12 2 15 5"/><polyline points="15 19 12 22 9 19"/><polyline points="19 9 22 12 19 15"/><line x1="2" y1="12" x2="22" y2="12"/><line x1="12" y1="2" x2="12" y2="22"/></svg>;
  const IconScale = () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>;
  const IconRotateCw = () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg>;
  const IconEye = () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>;
  const IconPalette = () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="13.5" cy="6.5" r=".5"/><circle cx="17.5" cy="10.5" r=".5"/><circle cx="8.5" cy="7.5" r=".5"/><circle cx="6.5" cy="12.5" r=".5"/><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z"/></svg>;
  const IconVolume2 = () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"/></svg>;
  const IconAudioLines = () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M2 10v3"/><path d="M6 6v11"/><path d="M10 3v18"/><path d="M14 8v7"/><path d="M18 5v13"/><path d="M22 10v3"/></svg>;
  const IconMusic = () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M9 18V5l12-2v13"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="16" r="3"/></svg>;

  function formatTime(seconds) {
    if (!seconds || isNaN(seconds)) return '00:00.00';
    const mins = Math.floor(seconds / 60);
    const secs = Math.floor(seconds % 60);
    const ms = Math.floor((seconds % 1) * 100);
    return `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}.${String(ms).padStart(2, '0')}`;
  }

  function KeyframePanelReal() {
    const selectedClips = ['demo-clip-1'];
    const [clips, setClips] = React.useState([{
      id: 'demo-clip-1',
      name: 'Interview.mp4',
      startTime: 0,
      endTime: 5.0,
      type: 'video',
      hasAudio: true,
      volume: 1,
      audioProps: { pan: 0, pitch: 0 },
      clipTransform: { posX: 0, posY: 0, posZ: 0, rotX: 0, rotY: 0, rotZ: 0, scaleX: 1, scaleY: 1, scaleZ: 1, shearX: 0, shearY: 0, anchorX: 0.5, anchorY: 0.5 },
      keyframes: [],
      keyframedProps: [],
    }]);
    const [currentTime, setCurrentTime] = React.useState(1.5);
    const [selectedProperty, setSelectedProperty] = React.useState('position');
    const [scrubberValue, setScrubberValue] = React.useState(null);

    const updateClip = (id, patch) => setClips(prev => prev.map(c => c.id === id ? { ...c, ...patch } : c));

    const selectedClip = clips.find(c => selectedClips.includes(c.id));
    const clipHasAudio = selectedClip ? (selectedClip.type === 'audio' || selectedClip.hasAudio !== false) : false;

    const visualProperties = [
      { id: 'position', label: 'Position', Icon: IconMove },
      { id: 'scale', label: 'Scale', Icon: IconScale },
      { id: 'rotation', label: 'Rotation', Icon: IconRotateCw },
      { id: 'opacity', label: 'Opacity', Icon: IconEye },
      { id: 'color', label: 'Color', Icon: IconPalette },
      { id: 'posX', label: 'Pos X', Icon: IconMove },
      { id: 'posY', label: 'Pos Y', Icon: IconMove },
      { id: 'rotZ', label: 'Rot Z', Icon: IconRotateCw },
      { id: 'scaleX', label: 'Scale X', Icon: IconScale },
      { id: 'scaleY', label: 'Scale Y', Icon: IconScale },
    ];
    const audioProperties = [
      { id: 'volume', label: 'Volume', Icon: IconVolume2 },
      { id: 'pan', label: 'Pan', Icon: IconAudioLines },
      { id: 'pitch', label: 'Pitch', Icon: IconMusic },
    ];
    const keyframeProperties = clipHasAudio ? [...visualProperties, ...audioProperties] : visualProperties;

    const audioPropMeta = {
      volume: { min: 0, max: 2, step: 0.01, defaultValue: 1, unit: 'x' },
      pan: { min: -1, max: 1, step: 0.01, defaultValue: 0, unit: '' },
      pitch: { min: -12, max: 12, step: 0.5, defaultValue: 0, unit: ' st' },
    };
    const isAudioProperty = (prop) => prop in audioPropMeta;

    const getCurrentValue = (property) => {
      if (!selectedClip) return null;
      switch (property) {
        case 'position': return selectedClip.clipTransform ? { x: selectedClip.clipTransform.posX || 0, y: selectedClip.clipTransform.posY || 0 } : { x: 0, y: 0 };
        case 'scale': return { x: selectedClip.clipTransform?.scaleX ?? 1, y: selectedClip.clipTransform?.scaleY ?? 1 };
        case 'rotation': return selectedClip.clipTransform?.rotZ ?? 0;
        case 'opacity': return 100;
        case 'color': return { brightness: 0, contrast: 0, saturation: 0 };
        case 'volume': return selectedClip.volume ?? 1;
        case 'pan': return selectedClip.audioProps?.pan ?? 0;
        case 'pitch': return selectedClip.audioProps?.pitch ?? 0;
        case 'posX': return selectedClip.clipTransform?.posX ?? 0;
        case 'posY': return selectedClip.clipTransform?.posY ?? 0;
        case 'rotZ': return selectedClip.clipTransform?.rotZ ?? 0;
        case 'scaleX': return selectedClip.clipTransform?.scaleX ?? 1;
        case 'scaleY': return selectedClip.clipTransform?.scaleY ?? 1;
        default: return null;
      }
    };

    const addKeyframe = (property) => {
      if (!selectedClip) return;
      const value = scrubberValue !== null && isAudioProperty(property) ? scrubberValue : getCurrentValue(property);
      const keyframe = {
        id: 'kf-' + Date.now() + '-' + Math.random().toString(36).slice(2, 7),
        property,
        time: currentTime,
        value,
        interpolation: 'linear',
      };
      updateClip(selectedClip.id, {
        keyframes: [...(selectedClip.keyframes || []), keyframe],
        keyframedProps: [...new Set([...(selectedClip.keyframedProps || []), property])],
      });
    };

    const deleteKeyframe = (keyframeId) => {
      if (!selectedClip) return;
      updateClip(selectedClip.id, {
        keyframes: (selectedClip.keyframes || []).filter(kf => kf.id !== keyframeId),
      });
    };

    const setKeyframeInterpolation = (keyframeId, mode) => {
      if (!selectedClip) return;
      updateClip(selectedClip.id, {
        keyframes: (selectedClip.keyframes || []).map(kf => kf.id === keyframeId ? { ...kf, interpolation: mode } : kf),
      });
    };

    const setPropertyInterpolation = (property, mode) => {
      if (!selectedClip) return;
      updateClip(selectedClip.id, {
        keyframes: (selectedClip.keyframes || []).map(kf => kf.property === property ? { ...kf, interpolation: mode } : kf),
      });
    };

    const clipKeyframes = selectedClip?.keyframes || [];
    const propertyKeyframes = clipKeyframes.filter(kf => kf.property === selectedProperty);
    const clipStart = selectedClip?.startTime ?? 0;
    const clipEnd = selectedClip?.endTime ?? 5;
    const clipHasTimeBounds = Number.isFinite(clipStart) && Number.isFinite(clipEnd) && clipEnd > clipStart;
    const activeMeta = audioPropMeta[selectedProperty];
    const effectiveScrubberValue = scrubberValue !== null ? scrubberValue : (activeMeta ? getCurrentValue(selectedProperty) : null);

    const buildMiniGraphPoints = (kfs, meta, cStart, cEnd) => {
      if (!meta || kfs.length === 0) return null;
      const span = cEnd - cStart;
      if (span <= 0) return null;
      const sorted = [...kfs].sort((a, b) => a.time - b.time);
      const toY = (v) => { const frac = (v - meta.min) / (meta.max - meta.min); return (1 - Math.max(0, Math.min(1, frac))) * 56 + 2; };
      const toX = (time) => Math.max(0, Math.min(100, ((time - cStart) / span) * 100));
      return sorted.map(kf => `${toX(kf.time).toFixed(1)},${toY(Number(kf.value)).toFixed(1)}`).join(' ');
    };

    const handlePropertySelect = (propId) => {
      setSelectedProperty(propId);
      setScrubberValue(null);
    };

    return (
      <div style={{ padding: '15px', color: t.textPrimary, fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif' }}>
        <div style={{ marginBottom: '15px' }}>
          <h3 style={{ fontSize: '14px', fontWeight: '600', marginBottom: '10px', color: t.accent }}>
            Keyframe Animation
          </h3>
          {!selectedClip && (
            <div style={{ padding: '10px', backgroundColor: t.border, borderRadius: '4px', fontSize: '11px', color: t.textMuted }}>
              Select a clip to animate with keyframes
            </div>
          )}
        </div>

        {/* Current time scrubber */}
        <div style={{ marginBottom: '12px', padding: '8px 10px', background: t.bgInput, borderRadius: '4px', border: `1px solid ${t.border}`, display: 'flex', alignItems: 'center', gap: '10px' }}>
          <span style={{ fontSize: '11px', color: t.textMuted }}>Time:</span>
          <input type="range" min={0} max={5} step={0.05} value={currentTime} onChange={e => setCurrentTime(Number(e.target.value))} style={{ flex: 1, accentColor: '#00ff00' }} />
          <span style={{ fontSize: '11px', color: t.accent, fontFamily: 'monospace', minWidth: '55px' }}>{formatTime(currentTime)}</span>
        </div>

        {selectedClip && (
          <>
            <div style={{ marginBottom: '20px' }}>
              <div style={{ fontSize: '12px', fontWeight: '600', marginBottom: '10px', color: t.textSecondary }}>
                ANIMATE PROPERTY
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '8px' }}>
                {keyframeProperties.map(prop => (
                  <button
                    key={prop.id}
                    onClick={() => handlePropertySelect(prop.id)}
                    style={{
                      padding: '10px',
                      backgroundColor: selectedProperty === prop.id ? t.border : t.bgHover,
                      color: selectedProperty === prop.id ? t.accent : t.textMuted,
                      border: selectedProperty === prop.id ? `1px solid ${t.accent}` : `1px solid ${t.border}`,
                      borderRadius: '4px', cursor: 'pointer', fontSize: '11px', fontWeight: '600',
                      display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '5px',
                    }}
                  >
                    <prop.Icon /> {prop.label}
                  </button>
                ))}
              </div>
            </div>

            {activeMeta && (
              <div style={{ marginBottom: '16px', padding: '10px', backgroundColor: t.bgHover, borderRadius: '4px', border: `1px solid ${t.border}` }}>
                <div style={{ fontSize: '11px', fontWeight: '600', marginBottom: '8px', color: t.textMuted, textTransform: 'uppercase' }}>
                  {selectedProperty} value
                </div>
                <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
                  <input
                    type="range"
                    min={activeMeta.min}
                    max={activeMeta.max}
                    step={activeMeta.step}
                    value={effectiveScrubberValue ?? activeMeta.defaultValue}
                    onChange={(e) => setScrubberValue(Number(e.target.value))}
                    style={{ flex: 1, accentColor: '#00ff00' }}
                  />
                  <input
                    type="number"
                    min={activeMeta.min}
                    max={activeMeta.max}
                    step={activeMeta.step}
                    value={effectiveScrubberValue ?? activeMeta.defaultValue}
                    onChange={(e) => {
                      const v = Math.max(activeMeta.min, Math.min(activeMeta.max, Number(e.target.value)));
                      setScrubberValue(v);
                    }}
                    style={{ width: '56px', backgroundColor: t.bgCard, color: t.textPrimary, border: `1px solid ${t.border}`, borderRadius: '3px', padding: '3px 5px', fontSize: '11px', textAlign: 'right' }}
                  />
                  <span style={{ fontSize: '10px', color: t.textMuted, minWidth: '18px' }}>{activeMeta.unit}</span>
                </div>
                <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: '9px', color: t.textMuted, marginTop: '3px' }}>
                  <span>{activeMeta.min}{activeMeta.unit}</span>
                  <span>{activeMeta.max}{activeMeta.unit}</span>
                </div>
              </div>
            )}

            <div style={{ marginBottom: '20px' }}>
              <button
                onClick={() => addKeyframe(selectedProperty)}
                style={{
                  width: '100%', padding: '12px', backgroundColor: t.accent, color: t.bgSunken,
                  border: 'none', borderRadius: '4px', cursor: 'pointer', fontSize: '12px', fontWeight: '700', textTransform: 'uppercase',
                }}
              >
                ➕ Add Keyframe at {formatTime(currentTime)}
              </button>
            </div>

            <div style={{ marginBottom: '15px' }}>
              <div style={{ fontSize: '12px', fontWeight: '600', marginBottom: '10px', color: t.textSecondary, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <span>KEYFRAMES ({propertyKeyframes.length})</span>
                {propertyKeyframes.length > 0 && <span style={{ fontSize: '10px', color: t.textMuted }}>{selectedProperty.toUpperCase()}</span>}
              </div>

              {propertyKeyframes.length === 0 ? (
                <div style={{ padding: '20px', backgroundColor: t.bgHover, borderRadius: '4px', textAlign: 'center', color: t.textMuted, fontSize: '11px' }}>
                  No keyframes added yet.<br />Click "Add Keyframe" to start animating.
                </div>
              ) : (
                <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
                  {propertyKeyframes.sort((a, b) => a.time - b.time).map(keyframe => {
                    const mode = keyframe.interpolation || 'linear';
                    const modeColor = INTERPOLATION_COLOR[mode] || INTERPOLATION_COLOR.linear;
                    return (
                      <div key={keyframe.id} style={{ padding: '10px', backgroundColor: t.bgHover, borderRadius: '4px', border: `1px solid ${t.border}` }}>
                        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '6px' }}>
                          <div style={{ fontSize: '11px', fontWeight: '600' }}>{formatTime(keyframe.time)}</div>
                          <div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
                            <span style={{ fontSize: '10px', color: modeColor, fontWeight: '600' }}>
                              {INTERPOLATION_SYMBOL[mode]} {INTERPOLATION_LABELS[mode]}
                            </span>
                            <button onClick={() => deleteKeyframe(keyframe.id)} style={{ padding: '4px 8px', backgroundColor: '#ff4444', color: '#ffffff', border: 'none', borderRadius: '3px', cursor: 'pointer', fontSize: '10px', fontWeight: '600' }}>✕</button>
                          </div>
                        </div>
                        {activeMeta && (
                          <div style={{ fontSize: '10px', color: t.textSecondary, marginBottom: '6px' }}>
                            {Number(keyframe.value).toFixed(2)}{activeMeta.unit}
                          </div>
                        )}
                        <div style={{ display: 'flex', flexWrap: 'wrap', gap: '4px' }}>
                          {INTERPOLATION_MODES.map(m => (
                            <button
                              key={m}
                              onClick={() => setKeyframeInterpolation(keyframe.id, m)}
                              title={INTERPOLATION_LABELS[m]}
                              style={{
                                padding: '3px 6px',
                                backgroundColor: mode === m ? 'rgba(255,165,0,0.25)' : t.bgCard,
                                color: mode === m ? '#ffa500' : t.textMuted,
                                border: `1px solid ${mode === m ? '#ffa500' : t.border}`,
                                borderRadius: '3px', cursor: 'pointer', fontSize: '10px',
                              }}
                            >
                              {INTERPOLATION_SYMBOL[m]}
                            </button>
                          ))}
                        </div>
                      </div>
                    );
                  })}
                </div>
              )}
            </div>

            <div style={{ marginTop: '20px' }}>
              <div style={{ fontSize: '12px', fontWeight: '600', marginBottom: '10px', color: t.textSecondary }}>TIMELINE</div>
              {activeMeta ? (
                <svg width="100%" height="60" viewBox="0 0 100 60" preserveAspectRatio="none"
                  style={{ display: 'block', backgroundColor: t.bgHover, borderRadius: '4px' }}>
                  {(() => {
                    const refVal = activeMeta.min < 0 ? 0 : activeMeta.defaultValue;
                    const refY = (1 - (refVal - activeMeta.min) / (activeMeta.max - activeMeta.min)) * 56 + 2;
                    return <line x1="0" y1={refY} x2="100" y2={refY} stroke={t.border} strokeWidth="0.5" strokeDasharray="2,2" />;
                  })()}
                  {clipHasTimeBounds && (() => {
                    const pts = buildMiniGraphPoints(propertyKeyframes, activeMeta, clipStart, clipEnd);
                    return pts ? <polyline points={pts} fill="none" stroke="#00ff00" strokeWidth="1.5" vectorEffect="non-scaling-stroke" /> : null;
                  })()}
                  {clipHasTimeBounds && propertyKeyframes.map(kf => {
                    const span = (clipEnd - clipStart) || 1;
                    const x = Math.max(0, Math.min(100, ((kf.time - clipStart) / span) * 100));
                    const frac = (Number(kf.value) - activeMeta.min) / (activeMeta.max - activeMeta.min);
                    const y = (1 - Math.max(0, Math.min(1, frac))) * 56 + 2;
                    return <circle key={kf.id} cx={x} cy={y} r="2.5" fill={t.accent} stroke={t.bgSunken} strokeWidth="1" vectorEffect="non-scaling-stroke"><title>{formatTime(kf.time)}: {Number(kf.value).toFixed(2)}{activeMeta.unit}</title></circle>;
                  })}
                  {clipHasTimeBounds && (() => {
                    const span = (clipEnd - clipStart) || 1;
                    const x = Math.max(0, Math.min(100, ((currentTime - clipStart) / span) * 100));
                    return <line x1={x} y1="0" x2={x} y2="60" stroke="#ff0000" strokeWidth="0.8" />;
                  })()}
                </svg>
              ) : (
                <div style={{ height: '60px', backgroundColor: t.bgHover, borderRadius: '4px', position: 'relative', overflow: 'hidden' }}>
                  {clipHasTimeBounds && propertyKeyframes.map(keyframe => {
                    const span = (clipEnd - clipStart) || 1;
                    return (
                      <div
                        key={keyframe.id}
                        style={{
                          position: 'absolute',
                          left: `${Math.max(0, Math.min(100, ((keyframe.time - clipStart) / span) * 100))}%`,
                          top: '50%', transform: 'translateY(-50%)',
                          width: '8px', height: '8px', backgroundColor: t.accent,
                          borderRadius: '50%', border: `2px solid ${t.bgSunken}`,
                        }}
                        title={`Keyframe at ${formatTime(keyframe.time)}`}
                      />
                    );
                  })}
                  {clipHasTimeBounds && (() => {
                    const span = (clipEnd - clipStart) || 1;
                    const x = Math.max(0, Math.min(100, ((currentTime - clipStart) / span) * 100));
                    return <div style={{ position: 'absolute', left: `${x}%`, top: 0, bottom: 0, width: '2px', backgroundColor: '#ff0000' }} />;
                  })()}
                </div>
              )}
            </div>

            <div style={{ marginTop: '20px' }}>
              <div style={{ fontSize: '12px', fontWeight: '600', marginBottom: '6px', color: t.textSecondary }}>INTERPOLATION (APPLY TO ALL)</div>
              {propertyKeyframes.length === 0 && (
                <div style={{ fontSize: '10px', color: t.textMuted, marginBottom: '8px' }}>Add keyframes first to apply an interpolation mode.</div>
              )}
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '6px' }}>
                {INTERPOLATION_MODES.map(mode => (
                  <button
                    key={mode}
                    onClick={() => setPropertyInterpolation(selectedProperty, mode)}
                    disabled={propertyKeyframes.length === 0}
                    title={INTERPOLATION_LABELS[mode]}
                    style={{
                      padding: '6px 4px', backgroundColor: t.bgHover, color: t.textSecondary,
                      border: `1px solid ${t.border}`, borderRadius: '3px',
                      cursor: propertyKeyframes.length === 0 ? 'not-allowed' : 'pointer',
                      fontSize: '10px', fontWeight: '500', display: 'flex', flexDirection: 'column',
                      alignItems: 'center', gap: '2px', opacity: propertyKeyframes.length === 0 ? 0.4 : 1,
                    }}
                  >
                    <span style={{ fontSize: '13px' }}>{INTERPOLATION_SYMBOL[mode]}</span>
                    <span>{INTERPOLATION_LABELS[mode]}</span>
                  </button>
                ))}
              </div>
            </div>
          </>
        )}
      </div>
    );
  }

  window.KeyframePanelReal = KeyframePanelReal;
})();
