    /**
     * @private
     */
    Ext.define('Ext.fx.runner.Css', {
        extend: 'Ext.Evented',

        requires: [
            'Ext.fx.Animation'
        ],

        prefixedProperties: {
            'transform'                 : true,
            'transform-origin'          : true,
            'perspective'               : true,
            'transform-style'           : true,
            'transition'                : true,
            'transition-property'       : true,
            'transition-duration'       : true,
            'transition-timing-function': true,
            'transition-delay'          : true,
            'animation'                 : true,
            'animation-name'            : true,
            'animation-duration'        : true,
            'animation-iteration-count' : true,
            'animation-direction'       : true,
            'animation-timing-function' : true,
            'animation-delay'           : true
        },

        lengthProperties: {
            'top'                : true,
            'right'              : true,
            'bottom'             : true,
            'left'               : true,
            'width'              : true,
            'height'             : true,
            'max-height'         : true,
            'max-width'          : true,
            'min-height'         : true,
            'min-width'          : true,
            'margin-bottom'      : true,
            'margin-left'        : true,
            'margin-right'       : true,
            'margin-top'         : true,
            'padding-bottom'     : true,
            'padding-left'       : true,
            'padding-right'      : true,
            'padding-top'        : true,
            'border-bottom-width': true,
            'border-left-width'  : true,
            'border-right-width' : true,
            'border-spacing'     : true,
            'border-top-width'   : true,
            'border-width'       : true,
            'outline-width'      : true,
            'letter-spacing'     : true,
            'line-height'        : true,
            'text-indent'        : true,
            'word-spacing'       : true,
            'font-size'          : true,
            'translate'          : true,
            'translateX'         : true,
            'translateY'         : true,
            'translateZ'         : true,
            'translate3d'        : true
        },

        durationProperties: {
            'transition-duration'   : true,
            'transition-delay'      : true,
            'animation-duration'    : true,
            'animation-delay'       : true
        },

        angleProperties: {
            rotate     : true,
            rotateX    : true,
            rotateY    : true,
            rotateZ    : true,
            skew       : true,
            skewX      : true,
            skewY      : true
        },

        lengthUnitRegex: /([a-z%]*)$/,

        DEFAULT_UNIT_LENGTH: 'px',

        DEFAULT_UNIT_ANGLE: 'deg',

        DEFAULT_UNIT_DURATION: 'ms',

        formattedNameCache: {},

        constructor: function() {
            var supports3dTransform = Ext.feature.has.Css3dTransforms;

            if (supports3dTransform) {
                this.transformMethods = ['translateX', 'translateY', 'translateZ', 'rotate', 'rotateX', 'rotateY', 'rotateZ', 'skewX', 'skewY', 'scaleX', 'scaleY', 'scaleZ'];
            }
            else {
                this.transformMethods = ['translateX', 'translateY', 'rotate', 'skewX', 'skewY', 'scaleX', 'scaleY'];
            }

            this.vendorPrefix = Ext.browser.getStyleDashPrefix();

            this.ruleStylesCache = {};

            return this;
        },

        getStyleSheet: function() {
            var styleSheet = this.styleSheet,
                styleElement, styleSheets;

            if (!styleSheet) {
                styleElement = document.createElement('style');
                styleElement.type = 'text/css';

                (document.head || document.getElementsByTagName('head')[0]).appendChild(styleElement);

                styleSheets = document.styleSheets;

                this.styleSheet = styleSheet = styleSheets[styleSheets.length - 1];
            }

            return styleSheet;
        },

        applyRules: function(selectors) {
            var styleSheet = this.getStyleSheet(),
                ruleStylesCache = this.ruleStylesCache,
                rules = styleSheet.cssRules,
                selector, properties, ruleStyle,
                ruleStyleCache, rulesLength, name, value;

            for (selector in selectors) {
                properties = selectors[selector];

                ruleStyle = ruleStylesCache[selector];

                if (ruleStyle === undefined) {
                    rulesLength = rules.length;
                    styleSheet.insertRule(selector + '{}', rulesLength);
                    ruleStyle = ruleStylesCache[selector] = rules.item(rulesLength).style;
                }

                ruleStyleCache = ruleStyle.$cache;

                if (!ruleStyleCache) {
                    ruleStyleCache = ruleStyle.$cache = {};
                }

                for (name in properties) {
                    value = this.formatValue(properties[name], name);
                    name = this.formatName(name);

                    if (ruleStyleCache[name] !== value) {
                        ruleStyleCache[name] = value;
    //                    console.log(name + " " + value);

                        if (value === null) {
                            ruleStyle.removeProperty(name);
                        }
                        else {
                            ruleStyle.setProperty(name, value, 'important');
                        }
                    }
                }
            }

            return this;
        },

        applyStyles: function(styles) {
            var id, element, elementStyle, properties, name, value;

            for (id in styles) {
    //            console.log("-> ["+id+"]", "APPLY======================");
                element = document.getElementById(id);

                if (!element) {
                    return this;
                }

                elementStyle = element.style;

                properties = styles[id];

                for (name in properties) {
                    value = this.formatValue(properties[name], name);
                    name = this.formatName(name);

    //                console.log("->-> ["+id+"]", name, value);

                    if (value === null) {
                        elementStyle.removeProperty(name);
                    }
                    else {
                        elementStyle.setProperty(name, value, 'important');
                    }
                }
            }

            return this;
        },

        formatName: function(name) {
            var cache = this.formattedNameCache,
                formattedName = cache[name];

            if (!formattedName) {
                if (this.prefixedProperties[name]) {
                    formattedName = this.vendorPrefix + name;
                }
                else {
                    formattedName = name;
                }

                cache[name] = formattedName;
            }

            return formattedName;
        },

        formatValue: function(value, name) {
            var type = typeof value,
                lengthUnit = this.DEFAULT_UNIT_LENGTH,
                transformMethods,
                method, i, ln,
                transformValues, values, unit;

            if (type == 'string') {
                if (this.lengthProperties[name]) {
                    unit = value.match(this.lengthUnitRegex)[1];

                    if (unit.length > 0) {
                        //<debug error>
                        if (unit !== lengthUnit) {
                            Ext.Logger.error("Length unit: '" + unit + "' in value: '" + value + "' of property: '" + name + "' is not " +
                                "valid for animation. Only 'px' is allowed");
                        }
                        //</debug>
                    }
                    else {
                        return value + lengthUnit;
                    }
                }

                return value;
            }
            else if (type == 'number') {
                if (value == 0) {
                    return '0';
                }

                if (this.lengthProperties[name]) {
                    return value + lengthUnit;
                }

                if (this.angleProperties[name]) {
                    return value + this.DEFAULT_UNIT_ANGLE;
                }

                if (this.durationProperties[name]) {
                    return value + this.DEFAULT_UNIT_DURATION;
                }
            }
            else if (name === 'transform') {
                transformMethods = this.transformMethods;
                transformValues = [];

                for (i = 0,ln = transformMethods.length; i < ln; i++) {
                    method = transformMethods[i];

                    transformValues.push(method + '(' + this.formatValue(value[method], method) + ')');
                }

                return transformValues.join(' ');
            }
            else if (Ext.isArray(value)) {
                values = [];

                for (i = 0,ln = value.length; i < ln; i++) {
                    values.push(this.formatValue(value[i], name));
                }

                return (values.length > 0) ? values.join(', ') : 'none';
            }

            return value;
        }
    });