docs: function (context, env) {
          var css = [],      // The CSS output
              rules = [],    // node.Rule instances
             _rules = [],    //
              rulesets = [], // node.Ruleset instances
              paths = [],    // Current selectors
              selector,      // The fully rendered selector
              debugInfo,     // Line number debugging
              rule;
  
          if (! this.root) {
              this.joinSelectors(paths, context, this.selectors);
          }
  
          // Compile rules and rulesets
          for (var i = 0; i < this.rules.length; i++) {
              rule = this.rules[i];
  
              if (rule.rules || (rule instanceof tree.Media)) {
                  rulesets.push(rule.toCSS(paths, env));
              } else if (rule instanceof tree.Directive) {
                  var cssValue = rule.toCSS(paths, env);
                  // Output only the first @charset definition as such - convert the others
                  // to comments in case debug is enabled
                  if (rule.name === "@charset") {
                      // Only output the debug info together with subsequent @charset definitions
                      // a comment (or @media statement) before the actual @charset directive would
                      // be considered illegal css as it has to be on the first line
                      if (env.charset) {
                          if (rule.debugInfo) {
                              rulesets.push(tree.debugInfo(env, rule));
                              rulesets.push(new tree.Comment("/* "+cssValue.replace(/\n/g, "")+" */\n").toCSS(env));
                          }
                          continue;
                      }
                      env.charset = true;
                  }
                  rulesets.push(cssValue);
              } else if (rule instanceof tree.Comment) {
                  if (!rule.silent) {
                      if (this.root) {
                          rulesets.push(rule.toCSS(env));
                      } else {
                          rules.push(rule.toCSS(env));
                      }
                  }
              } else {
                  if (rule.toCSS && !rule.variable) {
                      rules.push(rule.toCSS(env));
                  } else if (rule.value && !rule.variable) {
                      rules.push(rule.value.toString());
                  }
              }
          } 
  
          rulesets = rulesets.join('');
  
          // If this is the root node, we don't render
          // a selector, or {}.
          // Otherwise, only output if this ruleset has rules.
          if (this.root) {
              css.push(rules.join(env.compress ? '' : '\n'));
          } else {
              if (rules.length > 0) {
                  debugInfo = tree.debugInfo(env, this);
                  selector = paths.map(function (p) {
                      return p.map(function (s) {
                          return s.toCSS(env);
                      }).join('').trim();
                  }).join(env.compress ? ',' : ',\n');
  
                  // Remove duplicates
                  for (var i = rules.length - 1; i >= 0; i--) {
                      if (_rules.indexOf(rules[i]) === -1) {
                          _rules.unshift(rules[i]);
                      }
                  }
                  rules = _rules;
  
                  css.push(debugInfo + selector + 
                          (env.compress ? '{' : ' {\n  ') +
                          rules.join(env.compress ? '' : '\n  ') +
                          (env.compress ? '}' : '\n}\n'));
              }
          }
          css.push(rulesets);
  
          return css.join('')  + (env.compress ? '\n' : '');
      }