docs: function () {
  
                  /*****************
                      Transforms
                  *****************/
  
                  /* Transforms are the subproperties contained by the CSS "transform" property. Transforms must undergo normalization
                     so that they can be referenced in a properties map by their individual names. */
                  /* Note: When transforms are "set", they are actually assigned to a per-element transformCache. When all transform
                     setting is complete complete, CSS.flushTransformCache() must be manually called to flush the values to the DOM.
                     Transform setting is batched in this way to improve performance: the transform style only needs to be updated
                     once when multiple transform subproperties are being animated simultaneously. */
                  /* Note: IE9 and Android Gingerbread have support for 2D -- but not 3D -- transforms. Since animating unsupported
                     transform properties results in the browser ignoring the *entire* transform string, we prevent these 3D values
                     from being normalized for these browsers so that tweening skips these properties altogether
                     (since it will ignore them as being unsupported by the browser.) */
                  if (!(IE <= 9) && !Velocity.State.isGingerbread) {
                      /* Note: Since the standalone CSS "perspective" property and the CSS transform "perspective" subproperty
                      share the same name, the latter is given a unique token within Velocity: "transformPerspective". */
                      CSS.Lists.transformsBase = CSS.Lists.transformsBase.concat(CSS.Lists.transforms3D);
                  }
  
                  for (var i = 0; i < CSS.Lists.transformsBase.length; i++) {
                      /* Wrap the dynamically generated normalization function in a new scope so that transformName's value is
                      paired with its respective function. (Otherwise, all functions would take the final for loop's transformName.) */
                      (function() {
                          var transformName = CSS.Lists.transformsBase[i];
  
                          CSS.Normalizations.registered[transformName] = function (type, element, propertyValue) {
                              switch (type) {
                                  /* The normalized property name is the parent "transform" property -- the property that is actually set in CSS. */
                                  case "name":
                                      return "transform";
                                  /* Transform values are cached onto a per-element transformCache object. */
                                  case "extract":
                                      /* If this transform has yet to be assigned a value, return its null value. */
                                      if (Data(element).transformCache[transformName] === undefined) {
                                          /* Scale CSS.Lists.transformsBase default to 1 whereas all other transform properties default to 0. */
                                          return /^scale/i.test(transformName) ? 1 : 0;
                                      /* When transform values are set, they are wrapped in parentheses as per the CSS spec.
                                         Thus, when extracting their values (for tween calculations), we strip off the parentheses. */
                                      } else {
                                          return Data(element).transformCache[transformName].replace(/[()]/g, "");
                                      }
                                  case "inject":
                                      var invalid = false;
  
                                      /* If an individual transform property contains an unsupported unit type, the browser ignores the *entire* transform property.
                                         Thus, protect users from themselves by skipping setting for transform values supplied with invalid unit types. */
                                      /* Switch on the base transform type; ignore the axis by removing the last letter from the transform's name. */
                                      switch (transformName.substr(0, transformName.length - 1)) {
                                          /* Whitelist unit types for each transform. */
                                          case "translate":
                                              invalid = !/(%|px|em|rem|vw|vh|\d)$/i.test(propertyValue);
                                              break;
                                          /* Since an axis-free "scale" property is supported as well, a little hack is used here to detect it by chopping off its last letter. */
                                          case "scal":
                                          case "scale":
                                              /* Chrome on Android has a bug in which scaled elements blur if their initial scale
                                                 value is below 1 (which can happen with forcefeeding). Thus, we detect a yet-unset scale property
                                                 and ensure that its first value is always 1. More info: http://stackoverflow.com/questions/10417890/css3-animations-with-transform-causes-blurred-elements-on-webkit/10417962#10417962 */
                                              if (Velocity.State.isAndroid && Data(element).transformCache[transformName] === undefined && propertyValue < 1) {
                                                  propertyValue = 1;
                                              }
  
                                              invalid = !/(\d)$/i.test(propertyValue);
                                              break;
                                          case "skew":
                                              invalid = !/(deg|\d)$/i.test(propertyValue);
                                              break;
                                          case "rotate":
                                              invalid = !/(deg|\d)$/i.test(propertyValue);
                                              break;
                                      }
  
                                      if (!invalid) {
                                          /* As per the CSS spec, wrap the value in parentheses. */
                                          Data(element).transformCache[transformName] = "(" + propertyValue + ")";
                                      }
  
                                      /* Although the value is set on the transformCache object, return the newly-updated value for the calling code to process as normal. */
                                      return Data(element).transformCache[transformName];
                              }
                          };
                      })();
                  }
  
                  /*************
                      Colors
                  *************/
  
                  /* Since Velocity only animates a single numeric value per property, color animation is achieved by hooking the individual RGBA components of CSS color properties.
                     Accordingly, color values must be normalized (e.g. "#ff0000", "red", and "rgb(255, 0, 0)" ==> "255 0 0 1") so that their components can be injected/extracted by CSS.Hooks logic. */
                  for (var i = 0; i < CSS.Lists.colors.length; i++) {
                      /* Wrap the dynamically generated normalization function in a new scope so that colorName's value is paired with its respective function.
                         (Otherwise, all functions would take the final for loop's colorName.) */
                      (function () {
                          var colorName = CSS.Lists.colors[i];
  
                          /* Note: In IE<=8, which support rgb but not rgba, color properties are reverted to rgb by stripping off the alpha component. */
                          CSS.Normalizations.registered[colorName] = function(type, element, propertyValue) {
                              switch (type) {
                                  case "name":
                                      return colorName;
                                  /* Convert all color values into the rgb format. (Old IE can return hex values and color names instead of rgb/rgba.) */
                                  case "extract":
                                      var extracted;
  
                                      /* If the color is already in its hookable form (e.g. "255 255 255 1") due to having been previously extracted, skip extraction. */
                                      if (CSS.RegEx.wrappedValueAlreadyExtracted.test(propertyValue)) {
                                          extracted = propertyValue;
                                      } else {
                                          var converted,
                                              colorNames = {
                                                  black: "rgb(0, 0, 0)",
                                                  blue: "rgb(0, 0, 255)",
                                                  gray: "rgb(128, 128, 128)",
                                                  green: "rgb(0, 128, 0)",
                                                  red: "rgb(255, 0, 0)",
                                                  white: "rgb(255, 255, 255)"
                                              };
  
                                          /* Convert color names to rgb. */
                                          if (/^[A-z]+$/i.test(propertyValue)) {
                                              if (colorNames[propertyValue] !== undefined) {
                                                  converted = colorNames[propertyValue]
                                              } else {
                                                  /* If an unmatched color name is provided, default to black. */
                                                  converted = colorNames.black;
                                              }
                                          /* Convert hex values to rgb. */
                                          } else if (CSS.RegEx.isHex.test(propertyValue)) {
                                              converted = "rgb(" + CSS.Values.hexToRgb(propertyValue).join(" ") + ")";
                                          /* If the provided color doesn't match any of the accepted color formats, default to black. */
                                          } else if (!(/^rgba?\(/i.test(propertyValue))) {
                                              converted = colorNames.black;
                                          }
  
                                          /* Remove the surrounding "rgb/rgba()" string then replace commas with spaces and strip
                                             repeated spaces (in case the value included spaces to begin with). */
                                          extracted = (converted || propertyValue).toString().match(CSS.RegEx.valueUnwrap)[1].replace(/,(\s+)?/g, " ");
                                      }
  
                                      /* So long as this isn't <=IE8, add a fourth (alpha) component if it's missing and default it to 1 (visible). */
                                      if (!(IE <= 8) && extracted.split(" ").length === 3) {
                                          extracted += " 1";
                                      }
  
                                      return extracted;
                                  case "inject":
                                      /* If this is IE<=8 and an alpha component exists, strip it off. */
                                      if (IE <= 8) {
                                          if (propertyValue.split(" ").length === 4) {
                                              propertyValue = propertyValue.split(/\s+/).slice(0, 3).join(" ");
                                          }
                                      /* Otherwise, add a fourth (alpha) component if it's missing and default it to 1 (visible). */
                                      } else if (propertyValue.split(" ").length === 3) {
                                          propertyValue += " 1";
                                      }
  
                                      /* Re-insert the browser-appropriate wrapper("rgb/rgba()"), insert commas, and strip off decimal units
                                         on all values but the fourth (R, G, and B only accept whole numbers). */
                                      return (IE <= 8 ? "rgb" : "rgba") + "(" + propertyValue.replace(/\s+/g, ",").replace(/\.(\d)+(?=,)/g, "") + ")";
                              }
                          };
                      })();
                  }
              }