[gnome-code-assistance] [backends/css] New css backend



commit aa70ac4a9e66a3f5c0262fb448c200872162a9db
Author: Jesse van den Kieboom <jessevdk gmail com>
Date:   Wed Nov 13 19:52:29 2013 +0100

    [backends/css] New css backend

 backends/Makefile.am                               |    4 +
 backends/css/Makefile.am                           |   18 +
 backends/css/app.rb                                |   67 +
 backends/css/css.in                                |    6 +
 backends/css/deps.mf                               |  393 +++
 backends/css/gems/sass-3.2.12/.yardopts            |   11 +
 backends/css/gems/sass-3.2.12/CONTRIBUTING         |    3 +
 backends/css/gems/sass-3.2.12/MIT-LICENSE          |   20 +
 backends/css/gems/sass-3.2.12/README.md            |  201 ++
 backends/css/gems/sass-3.2.12/REVISION             |    1 +
 backends/css/gems/sass-3.2.12/Rakefile             |  347 +++
 backends/css/gems/sass-3.2.12/VERSION              |    1 +
 backends/css/gems/sass-3.2.12/VERSION_DATE         |    1 +
 backends/css/gems/sass-3.2.12/VERSION_NAME         |    1 +
 backends/css/gems/sass-3.2.12/bin/sass             |    9 +
 backends/css/gems/sass-3.2.12/bin/sass-convert     |    8 +
 backends/css/gems/sass-3.2.12/bin/scss             |    9 +
 .../css/gems/sass-3.2.12/extra/update_watch.rb     |   13 +
 backends/css/gems/sass-3.2.12/init.rb              |   18 +
 backends/css/gems/sass-3.2.12/lib/sass.rb          |   95 +
 .../css/gems/sass-3.2.12/lib/sass/cache_stores.rb  |   15 +
 .../gems/sass-3.2.12/lib/sass/cache_stores/base.rb |   88 +
 .../sass-3.2.12/lib/sass/cache_stores/chain.rb     |   33 +
 .../lib/sass/cache_stores/filesystem.rb            |   60 +
 .../sass-3.2.12/lib/sass/cache_stores/memory.rb    |   47 +
 .../gems/sass-3.2.12/lib/sass/cache_stores/null.rb |   25 +
 .../css/gems/sass-3.2.12/lib/sass/callbacks.rb     |   66 +
 backends/css/gems/sass-3.2.12/lib/sass/css.rb      |  409 +++
 backends/css/gems/sass-3.2.12/lib/sass/engine.rb   |  928 ++++++
 .../css/gems/sass-3.2.12/lib/sass/environment.rb   |  101 +
 backends/css/gems/sass-3.2.12/lib/sass/error.rb    |  201 ++
 backends/css/gems/sass-3.2.12/lib/sass/exec.rb     |  707 +++++
 .../css/gems/sass-3.2.12/lib/sass/importers.rb     |   22 +
 .../gems/sass-3.2.12/lib/sass/importers/base.rb    |  139 +
 .../sass-3.2.12/lib/sass/importers/filesystem.rb   |  190 ++
 backends/css/gems/sass-3.2.12/lib/sass/logger.rb   |   15 +
 .../css/gems/sass-3.2.12/lib/sass/logger/base.rb   |   32 +
 .../gems/sass-3.2.12/lib/sass/logger/log_level.rb  |   49 +
 backends/css/gems/sass-3.2.12/lib/sass/media.rb    |  213 ++
 backends/css/gems/sass-3.2.12/lib/sass/plugin.rb   |  132 +
 .../gems/sass-3.2.12/lib/sass/plugin/compiler.rb   |  406 +++
 .../sass-3.2.12/lib/sass/plugin/configuration.rb   |  123 +
 .../gems/sass-3.2.12/lib/sass/plugin/generic.rb    |   15 +
 .../css/gems/sass-3.2.12/lib/sass/plugin/merb.rb   |   48 +
 .../css/gems/sass-3.2.12/lib/sass/plugin/rack.rb   |   60 +
 .../css/gems/sass-3.2.12/lib/sass/plugin/rails.rb  |   47 +
 .../lib/sass/plugin/staleness_checker.rb           |  199 ++
 backends/css/gems/sass-3.2.12/lib/sass/railtie.rb  |    9 +
 backends/css/gems/sass-3.2.12/lib/sass/repl.rb     |   57 +
 backends/css/gems/sass-3.2.12/lib/sass/root.rb     |    7 +
 backends/css/gems/sass-3.2.12/lib/sass/script.rb   |   39 +
 .../gems/sass-3.2.12/lib/sass/script/arg_list.rb   |   52 +
 .../css/gems/sass-3.2.12/lib/sass/script/bool.rb   |   18 +
 .../css/gems/sass-3.2.12/lib/sass/script/color.rb  |  606 ++++
 .../gems/sass-3.2.12/lib/sass/script/css_lexer.rb  |   29 +
 .../gems/sass-3.2.12/lib/sass/script/css_parser.rb |   31 +
 .../gems/sass-3.2.12/lib/sass/script/funcall.rb    |  237 ++
 .../gems/sass-3.2.12/lib/sass/script/functions.rb  | 1543 ++++++++++
 .../sass-3.2.12/lib/sass/script/interpolation.rb   |   79 +
 .../css/gems/sass-3.2.12/lib/sass/script/lexer.rb  |  348 +++
 .../css/gems/sass-3.2.12/lib/sass/script/list.rb   |   85 +
 .../gems/sass-3.2.12/lib/sass/script/literal.rb    |  221 ++
 .../css/gems/sass-3.2.12/lib/sass/script/node.rb   |   99 +
 .../css/gems/sass-3.2.12/lib/sass/script/null.rb   |   37 +
 .../css/gems/sass-3.2.12/lib/sass/script/number.rb |  453 +++
 .../gems/sass-3.2.12/lib/sass/script/operation.rb  |  110 +
 .../css/gems/sass-3.2.12/lib/sass/script/parser.rb |  495 +++
 .../css/gems/sass-3.2.12/lib/sass/script/string.rb |   51 +
 .../lib/sass/script/string_interpolation.rb        |  103 +
 .../sass-3.2.12/lib/sass/script/unary_operation.rb |   69 +
 .../gems/sass-3.2.12/lib/sass/script/variable.rb   |   58 +
 backends/css/gems/sass-3.2.12/lib/sass/scss.rb     |   16 +
 .../gems/sass-3.2.12/lib/sass/scss/css_parser.rb   |   36 +
 .../css/gems/sass-3.2.12/lib/sass/scss/parser.rb   | 1179 +++++++
 backends/css/gems/sass-3.2.12/lib/sass/scss/rx.rb  |  133 +
 .../gems/sass-3.2.12/lib/sass/scss/script_lexer.rb |   15 +
 .../sass-3.2.12/lib/sass/scss/script_parser.rb     |   25 +
 .../sass-3.2.12/lib/sass/scss/static_parser.rb     |   54 +
 backends/css/gems/sass-3.2.12/lib/sass/selector.rb |  452 +++
 .../lib/sass/selector/abstract_sequence.rb         |   94 +
 .../lib/sass/selector/comma_sequence.rb            |   92 +
 .../gems/sass-3.2.12/lib/sass/selector/sequence.rb |  507 +++
 .../gems/sass-3.2.12/lib/sass/selector/simple.rb   |  119 +
 .../lib/sass/selector/simple_sequence.rb           |  212 ++
 backends/css/gems/sass-3.2.12/lib/sass/shared.rb   |   76 +
 backends/css/gems/sass-3.2.12/lib/sass/supports.rb |  229 ++
 .../gems/sass-3.2.12/lib/sass/tree/charset_node.rb |   22 +
 .../gems/sass-3.2.12/lib/sass/tree/comment_node.rb |   82 +
 .../gems/sass-3.2.12/lib/sass/tree/content_node.rb |    9 +
 .../sass-3.2.12/lib/sass/tree/css_import_node.rb   |   60 +
 .../gems/sass-3.2.12/lib/sass/tree/debug_node.rb   |   18 +
 .../sass-3.2.12/lib/sass/tree/directive_node.rb    |   42 +
 .../gems/sass-3.2.12/lib/sass/tree/each_node.rb    |   24 +
 .../gems/sass-3.2.12/lib/sass/tree/extend_node.rb  |   36 +
 .../css/gems/sass-3.2.12/lib/sass/tree/for_node.rb |   36 +
 .../sass-3.2.12/lib/sass/tree/function_node.rb     |   34 +
 .../css/gems/sass-3.2.12/lib/sass/tree/if_node.rb  |   52 +
 .../gems/sass-3.2.12/lib/sass/tree/import_node.rb  |   75 +
 .../gems/sass-3.2.12/lib/sass/tree/media_node.rb   |   58 +
 .../sass-3.2.12/lib/sass/tree/mixin_def_node.rb    |   38 +
 .../gems/sass-3.2.12/lib/sass/tree/mixin_node.rb   |   39 +
 .../css/gems/sass-3.2.12/lib/sass/tree/node.rb     |  196 ++
 .../gems/sass-3.2.12/lib/sass/tree/prop_node.rb    |  152 +
 .../gems/sass-3.2.12/lib/sass/tree/return_node.rb  |   18 +
 .../gems/sass-3.2.12/lib/sass/tree/root_node.rb    |   28 +
 .../gems/sass-3.2.12/lib/sass/tree/rule_node.rb    |  132 +
 .../sass-3.2.12/lib/sass/tree/supports_node.rb     |   51 +
 .../gems/sass-3.2.12/lib/sass/tree/trace_node.rb   |   32 +
 .../sass-3.2.12/lib/sass/tree/variable_node.rb     |   30 +
 .../sass-3.2.12/lib/sass/tree/visitors/base.rb     |   75 +
 .../lib/sass/tree/visitors/check_nesting.rb        |  147 +
 .../sass-3.2.12/lib/sass/tree/visitors/convert.rb  |  316 ++
 .../sass-3.2.12/lib/sass/tree/visitors/cssize.rb   |  229 ++
 .../lib/sass/tree/visitors/deep_copy.rb            |  102 +
 .../sass-3.2.12/lib/sass/tree/visitors/extend.rb   |   68 +
 .../sass-3.2.12/lib/sass/tree/visitors/perform.rb  |  446 +++
 .../lib/sass/tree/visitors/set_options.rb          |  125 +
 .../sass-3.2.12/lib/sass/tree/visitors/to_css.rb   |  228 ++
 .../gems/sass-3.2.12/lib/sass/tree/warn_node.rb    |   18 +
 .../gems/sass-3.2.12/lib/sass/tree/while_node.rb   |   18 +
 backends/css/gems/sass-3.2.12/lib/sass/util.rb     |  930 ++++++
 .../lib/sass/util/multibyte_string_scanner.rb      |  155 +
 .../gems/sass-3.2.12/lib/sass/util/subset_map.rb   |  109 +
 .../css/gems/sass-3.2.12/lib/sass/util/test.rb     |   10 +
 backends/css/gems/sass-3.2.12/lib/sass/version.rb  |  126 +
 backends/css/gems/sass-3.2.12/rails/init.rb        |    1 +
 backends/css/gems/sass-3.2.12/test/Gemfile         |    3 +
 backends/css/gems/sass-3.2.12/test/Gemfile.lock    |   10 +
 .../css/gems/sass-3.2.12/test/sass/cache_test.rb   |   89 +
 .../gems/sass-3.2.12/test/sass/callbacks_test.rb   |   61 +
 .../gems/sass-3.2.12/test/sass/conversion_test.rb  | 1760 +++++++++++
 .../gems/sass-3.2.12/test/sass/css2sass_test.rb    |  439 +++
 .../gems/sass-3.2.12/test/sass/data/hsl-rgb.txt    |  319 ++
 .../css/gems/sass-3.2.12/test/sass/engine_test.rb  | 3243 ++++++++++++++++++++
 .../css/gems/sass-3.2.12/test/sass/exec_test.rb    |   86 +
 .../css/gems/sass-3.2.12/test/sass/extend_test.rb  | 1482 +++++++++
 .../test_staleness_check_across_importers.css      |    1 +
 .../test_staleness_check_across_importers.scss     |    1 +
 .../gems/sass-3.2.12/test/sass/functions_test.rb   | 1139 +++++++
 .../gems/sass-3.2.12/test/sass/importer_test.rb    |  192 ++
 .../css/gems/sass-3.2.12/test/sass/logger_test.rb  |   58 +
 .../gems/sass-3.2.12/test/sass/mock_importer.rb    |   49 +
 .../sass-3.2.12/test/sass/more_results/more1.css   |    9 +
 .../sass/more_results/more1_with_line_comments.css |   26 +
 .../test/sass/more_results/more_import.css         |   29 +
 .../test/sass/more_templates/_more_partial.sass    |    2 +
 .../test/sass/more_templates/more1.sass            |   23 +
 .../test/sass/more_templates/more_import.sass      |   11 +
 .../css/gems/sass-3.2.12/test/sass/plugin_test.rb  |  550 ++++
 .../css/gems/sass-3.2.12/test/sass/results/alt.css |    4 +
 .../gems/sass-3.2.12/test/sass/results/basic.css   |    9 +
 .../test/sass/results/cached_import_option.css     |    3 +
 .../gems/sass-3.2.12/test/sass/results/compact.css |    5 +
 .../gems/sass-3.2.12/test/sass/results/complex.css |   86 +
 .../sass-3.2.12/test/sass/results/compressed.css   |    1 +
 .../sass-3.2.12/test/sass/results/expanded.css     |   19 +
 .../sass-3.2.12/test/sass/results/filename_fn.css  |    3 +
 .../css/gems/sass-3.2.12/test/sass/results/if.css  |    3 +
 .../gems/sass-3.2.12/test/sass/results/import.css  |   31 +
 .../test/sass/results/import_charset.css           |    5 +
 .../test/sass/results/import_charset_1_8.css       |    5 +
 .../test/sass/results/import_charset_ibm866.css    |    5 +
 .../test/sass/results/import_content.css           |    1 +
 .../sass-3.2.12/test/sass/results/line_numbers.css |   49 +
 .../gems/sass-3.2.12/test/sass/results/mixins.css  |   95 +
 .../sass-3.2.12/test/sass/results/multiline.css    |   24 +
 .../gems/sass-3.2.12/test/sass/results/nested.css  |   22 +
 .../gems/sass-3.2.12/test/sass/results/options.css |    1 +
 .../sass-3.2.12/test/sass/results/parent_ref.css   |   13 +
 .../gems/sass-3.2.12/test/sass/results/script.css  |   16 +
 .../sass-3.2.12/test/sass/results/scss_import.css  |   31 +
 .../test/sass/results/scss_importee.css            |    2 +
 .../results/subdir/nested_subdir/nested_subdir.css |    1 +
 .../test/sass/results/subdir/subdir.css            |    3 +
 .../gems/sass-3.2.12/test/sass/results/units.css   |   11 +
 .../test/sass/script_conversion_test.rb            |  299 ++
 .../css/gems/sass-3.2.12/test/sass/script_test.rb  |  591 ++++
 .../gems/sass-3.2.12/test/sass/scss/css_test.rb    | 1093 +++++++
 .../css/gems/sass-3.2.12/test/sass/scss/rx_test.rb |  156 +
 .../gems/sass-3.2.12/test/sass/scss/scss_test.rb   | 2043 ++++++++++++
 .../gems/sass-3.2.12/test/sass/scss/test_helper.rb |   37 +
 .../templates/_cached_import_option_partial.scss   |    1 +
 .../test/sass/templates/_double_import_loop2.sass  |    1 +
 .../test/sass/templates/_filename_fn_import.scss   |   11 +
 .../sass/templates/_imported_charset_ibm866.sass   |    4 +
 .../sass/templates/_imported_charset_utf8.sass     |    4 +
 .../test/sass/templates/_imported_content.sass     |    3 +
 .../sass-3.2.12/test/sass/templates/_partial.sass  |    2 +
 .../templates/_same_name_different_partiality.scss |    1 +
 .../gems/sass-3.2.12/test/sass/templates/alt.sass  |   16 +
 .../sass-3.2.12/test/sass/templates/basic.sass     |   23 +
 .../sass-3.2.12/test/sass/templates/bork1.sass     |    2 +
 .../sass-3.2.12/test/sass/templates/bork2.sass     |    2 +
 .../sass-3.2.12/test/sass/templates/bork3.sass     |    2 +
 .../sass-3.2.12/test/sass/templates/bork4.sass     |    2 +
 .../sass-3.2.12/test/sass/templates/bork5.sass     |    3 +
 .../test/sass/templates/cached_import_option.scss  |    3 +
 .../sass-3.2.12/test/sass/templates/compact.sass   |   17 +
 .../sass-3.2.12/test/sass/templates/complex.sass   |  305 ++
 .../test/sass/templates/compressed.sass            |   15 +
 .../test/sass/templates/double_import_loop1.sass   |    1 +
 .../sass-3.2.12/test/sass/templates/expanded.sass  |   17 +
 .../test/sass/templates/filename_fn.scss           |   18 +
 .../gems/sass-3.2.12/test/sass/templates/if.sass   |   11 +
 .../sass-3.2.12/test/sass/templates/import.sass    |   12 +
 .../test/sass/templates/import_charset.sass        |    9 +
 .../test/sass/templates/import_charset_1_8.sass    |    6 +
 .../test/sass/templates/import_charset_ibm866.sass |   11 +
 .../test/sass/templates/import_content.sass        |    4 +
 .../sass-3.2.12/test/sass/templates/importee.less  |    2 +
 .../sass-3.2.12/test/sass/templates/importee.sass  |   19 +
 .../test/sass/templates/line_numbers.sass          |   13 +
 .../test/sass/templates/mixin_bork.sass            |    5 +
 .../sass-3.2.12/test/sass/templates/mixins.sass    |   76 +
 .../sass-3.2.12/test/sass/templates/multiline.sass |   20 +
 .../sass-3.2.12/test/sass/templates/nested.sass    |   25 +
 .../test/sass/templates/nested_bork1.sass          |    2 +
 .../test/sass/templates/nested_bork2.sass          |    2 +
 .../test/sass/templates/nested_bork3.sass          |    2 +
 .../test/sass/templates/nested_bork4.sass          |    2 +
 .../test/sass/templates/nested_import.sass         |    2 +
 .../test/sass/templates/nested_mixin_bork.sass     |    6 +
 .../sass-3.2.12/test/sass/templates/options.sass   |    2 +
 .../test/sass/templates/parent_ref.sass            |   25 +
 .../sass/templates/same_name_different_ext.sass    |    2 +
 .../sass/templates/same_name_different_ext.scss    |    1 +
 .../templates/same_name_different_partiality.scss  |    1 +
 .../sass-3.2.12/test/sass/templates/script.sass    |  101 +
 .../test/sass/templates/scss_import.scss           |   11 +
 .../test/sass/templates/scss_importee.scss         |    1 +
 .../test/sass/templates/single_import_loop.sass    |    1 +
 .../subdir/nested_subdir/_nested_partial.sass      |    2 +
 .../subdir/nested_subdir/nested_subdir.sass        |    3 +
 .../test/sass/templates/subdir/subdir.sass         |    6 +
 .../sass-3.2.12/test/sass/templates/units.sass     |   11 +
 .../gems/sass-3.2.12/test/sass/templates/warn.sass |    3 +
 .../test/sass/templates/warn_imported.sass         |    4 +
 .../css/gems/sass-3.2.12/test/sass/test_helper.rb  |    8 +
 .../sass/util/multibyte_string_scanner_test.rb     |  147 +
 .../sass-3.2.12/test/sass/util/subset_map_test.rb  |   91 +
 .../css/gems/sass-3.2.12/test/sass/util_test.rb    |  361 +++
 backends/css/gems/sass-3.2.12/test/test_helper.rb  |   80 +
 .../gems/sass-3.2.12/vendor/listen/CHANGELOG.md    |  228 ++
 .../gems/sass-3.2.12/vendor/listen/CONTRIBUTING.md |   38 +
 .../css/gems/sass-3.2.12/vendor/listen/Gemfile     |   30 +
 .../css/gems/sass-3.2.12/vendor/listen/Guardfile   |    8 +
 .../css/gems/sass-3.2.12/vendor/listen/LICENSE     |   20 +
 .../css/gems/sass-3.2.12/vendor/listen/README.md   |  315 ++
 .../css/gems/sass-3.2.12/vendor/listen/Rakefile    |   47 +
 .../css/gems/sass-3.2.12/vendor/listen/Vagrantfile |   96 +
 .../gems/sass-3.2.12/vendor/listen/lib/listen.rb   |   40 +
 .../vendor/listen/lib/listen/adapter.rb            |  214 ++
 .../vendor/listen/lib/listen/adapters/bsd.rb       |  112 +
 .../vendor/listen/lib/listen/adapters/darwin.rb    |   85 +
 .../vendor/listen/lib/listen/adapters/linux.rb     |  113 +
 .../vendor/listen/lib/listen/adapters/polling.rb   |   67 +
 .../vendor/listen/lib/listen/adapters/windows.rb   |   87 +
 .../vendor/listen/lib/listen/dependency_manager.rb |  126 +
 .../vendor/listen/lib/listen/directory_record.rb   |  371 +++
 .../vendor/listen/lib/listen/listener.rb           |  225 ++
 .../vendor/listen/lib/listen/multi_listener.rb     |  143 +
 .../vendor/listen/lib/listen/turnstile.rb          |   28 +
 .../vendor/listen/lib/listen/version.rb            |    3 +
 .../gems/sass-3.2.12/vendor/listen/listen.gemspec  |   22 +
 .../vendor/listen/spec/listen/adapter_spec.rb      |  183 ++
 .../vendor/listen/spec/listen/adapters/bsd_spec.rb |   36 +
 .../listen/spec/listen/adapters/darwin_spec.rb     |   37 +
 .../listen/spec/listen/adapters/linux_spec.rb      |   47 +
 .../listen/spec/listen/adapters/polling_spec.rb    |   68 +
 .../listen/spec/listen/adapters/windows_spec.rb    |   30 +
 .../listen/spec/listen/dependency_manager_spec.rb  |  107 +
 .../listen/spec/listen/directory_record_spec.rb    | 1225 ++++++++
 .../vendor/listen/spec/listen/listener_spec.rb     |  169 +
 .../listen/spec/listen/multi_listener_spec.rb      |  174 ++
 .../vendor/listen/spec/listen/turnstile_spec.rb    |   56 +
 .../sass-3.2.12/vendor/listen/spec/listen_spec.rb  |   73 +
 .../sass-3.2.12/vendor/listen/spec/spec_helper.rb  |   21 +
 .../vendor/listen/spec/support/adapter_helper.rb   |  629 ++++
 .../listen/spec/support/directory_record_helper.rb |   55 +
 .../vendor/listen/spec/support/fixtures_helper.rb  |   29 +
 .../vendor/listen/spec/support/listeners_helper.rb |  156 +
 .../vendor/listen/spec/support/platform_helper.rb  |   15 +
 backends/css/mkdeps.py                             |   25 +
 .../css/org.gnome.CodeAssist.v1.css.service.in     |    3 +
 configure.ac                                       |   46 +
 285 files changed, 39432 insertions(+), 0 deletions(-)
---
diff --git a/backends/Makefile.am b/backends/Makefile.am
index 5130d20..7fd7626 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -42,4 +42,8 @@ if BACKENDS_SH_ENABLE
 include backends/sh/Makefile.am
 endif
 
+if BACKENDS_CSS_ENABLE
+include backends/css/Makefile.am
+endif
+
 GITIGNOREDEPS += backends/Makefile.am
diff --git a/backends/css/Makefile.am b/backends/css/Makefile.am
new file mode 100644
index 0000000..c0d3ce9
--- /dev/null
+++ b/backends/css/Makefile.am
@@ -0,0 +1,18 @@
+cssbackenddir = $(GCA_RBBACKENDS_DIR)/css
+cssbackend_DATA =                              \
+       backends/css/app.rb
+
+cssbackendexecdir = $(GCA_BACKENDS_EXEC_DIR)
+cssbackendexec_SCRIPTS = \
+       backends/css/css
+
+cssbackendservicedir = $(datadir)/dbus-1/services
+cssbackendservice_DATA = \
+       backends/css/org.gnome.CodeAssist.v1.css.service
+
+if RUBY_SASS
+else
+include backends/css/deps.mf
+endif
+
+GITIGNOREDEPS += backends/css/Makefile.am
diff --git a/backends/css/app.rb b/backends/css/app.rb
new file mode 100644
index 0000000..86747dc
--- /dev/null
+++ b/backends/css/app.rb
@@ -0,0 +1,67 @@
+# gnome code assistance ruby backend
+# Copyright (C) 2013  Jesse van den Kieboom <jessevdk gnome org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+require 'gnome/codeassistance/transport'
+
+oursass = File.join(File.dirname(__FILE__), 'gems', 'sass-3.2.12', 'init.rb')
+
+if FileTest.exist?(oursass)
+    require oursass
+else
+    require 'sass'
+end
+
+
+module Gnome::CodeAssistance
+    module Css
+        class Service < Service
+            @@language = 'css'
+
+            def parse(doc, options)
+                doc.diagnostics = []
+
+                f = File.new(doc.data_path, 'r')
+
+                begin
+                    parser = Sass::SCSS::CssParser.new(f.read(), doc.path)
+                    parser.parse()
+                rescue Sass::SyntaxError => e
+                    doc.diagnostics = [make_diagnostic(e)]
+                end
+
+                f.close
+            end
+
+            def make_diagnostic(e)
+                loc = SourceLocation.new(e.sass_line, 0)
+                Diagnostic.new(Diagnostic::Severity::ERROR, [], [loc.to_range], e.to_s)
+            end
+        end
+
+        class Document < Document
+            include Services::Diagnostics
+        end
+
+        class Application
+            def self.run()
+                Transport.new(Service, Document).run()
+            end
+        end
+    end
+end
+
+# ex:ts=4:et:
diff --git a/backends/css/css.in b/backends/css/css.in
new file mode 100644
index 0000000..5d79a29
--- /dev/null
+++ b/backends/css/css.in
@@ -0,0 +1,6 @@
+#!/usr/bin/env @RUBY_BASE@
+
+$:.unshift('@GCA_RBBACKENDS_ROOT_EX@')
+
+require 'gnome/codeassistance/css/app'
+Gnome::CodeAssistance::Css::Application.run()
diff --git a/backends/css/deps.mf b/backends/css/deps.mf
new file mode 100644
index 0000000..255e6e8
--- /dev/null
+++ b/backends/css/deps.mf
@@ -0,0 +1,393 @@
+csssass_gems_sass_3_2_12_lib_sass_scriptdir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/lib/sass/script
+csssass_gems_sass_3_2_12_lib_sass_script_DATA = \
+       backends/css/gems/sass-3.2.12/lib/sass/script/arg_list.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/bool.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/color.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/css_lexer.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/css_parser.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/funcall.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/functions.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/interpolation.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/lexer.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/list.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/literal.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/null.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/number.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/operation.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/parser.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/string.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/string_interpolation.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/unary_operation.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script/variable.rb
+
+csssass_gems_sass_3_2_12_test_sass_more_templatesdir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/test/sass/more_templates
+csssass_gems_sass_3_2_12_test_sass_more_templates_DATA = \
+       backends/css/gems/sass-3.2.12/test/sass/more_templates/_more_partial.sass \
+       backends/css/gems/sass-3.2.12/test/sass/more_templates/more1.sass \
+       backends/css/gems/sass-3.2.12/test/sass/more_templates/more_import.sass
+
+csssass_gems_sass_3_2_12_lib_sass_plugindir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/lib/sass/plugin
+csssass_gems_sass_3_2_12_lib_sass_plugin_DATA = \
+       backends/css/gems/sass-3.2.12/lib/sass/plugin/compiler.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/plugin/configuration.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/plugin/generic.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/plugin/merb.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/plugin/rack.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/plugin/rails.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/plugin/staleness_checker.rb
+
+csssass_gems_sass_3_2_12_test_sass_templates_subdirdir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/test/sass/templates/subdir
+csssass_gems_sass_3_2_12_test_sass_templates_subdir_DATA = \
+       backends/css/gems/sass-3.2.12/test/sass/templates/subdir/subdir.sass
+
+csssass_gems_sass_3_2_12_testdir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/test
+csssass_gems_sass_3_2_12_test_DATA = \
+       backends/css/gems/sass-3.2.12/test/Gemfile \
+       backends/css/gems/sass-3.2.12/test/Gemfile.lock \
+       backends/css/gems/sass-3.2.12/test/test_helper.rb
+
+csssass_gems_sass_3_2_12_test_sass_scssdir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/test/sass/scss
+csssass_gems_sass_3_2_12_test_sass_scss_DATA = \
+       backends/css/gems/sass-3.2.12/test/sass/scss/css_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/scss/rx_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/scss/scss_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/scss/test_helper.rb
+
+csssass_gems_sass_3_2_12dir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12
+csssass_gems_sass_3_2_12_DATA = \
+       backends/css/gems/sass-3.2.12/.yardopts \
+       backends/css/gems/sass-3.2.12/CONTRIBUTING \
+       backends/css/gems/sass-3.2.12/MIT-LICENSE \
+       backends/css/gems/sass-3.2.12/README.md \
+       backends/css/gems/sass-3.2.12/REVISION \
+       backends/css/gems/sass-3.2.12/Rakefile \
+       backends/css/gems/sass-3.2.12/VERSION \
+       backends/css/gems/sass-3.2.12/VERSION_DATE \
+       backends/css/gems/sass-3.2.12/VERSION_NAME \
+       backends/css/gems/sass-3.2.12/init.rb
+
+csssass_gems_sass_3_2_12_lib_sass_loggerdir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/lib/sass/logger
+csssass_gems_sass_3_2_12_lib_sass_logger_DATA = \
+       backends/css/gems/sass-3.2.12/lib/sass/logger/base.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/logger/log_level.rb
+
+csssass_gems_sass_3_2_12_bindir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/bin
+csssass_gems_sass_3_2_12_bin_DATA = \
+       backends/css/gems/sass-3.2.12/bin/sass \
+       backends/css/gems/sass-3.2.12/bin/sass-convert \
+       backends/css/gems/sass-3.2.12/bin/scss
+
+csssass_gems_sass_3_2_12_vendor_listen_spec_listendir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/vendor/listen/spec/listen
+csssass_gems_sass_3_2_12_vendor_listen_spec_listen_DATA = \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapter_spec.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/dependency_manager_spec.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/directory_record_spec.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/listener_spec.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/multi_listener_spec.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/turnstile_spec.rb
+
+csssass_gems_sass_3_2_12_vendor_listen_libdir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/vendor/listen/lib
+csssass_gems_sass_3_2_12_vendor_listen_lib_DATA = \
+       backends/css/gems/sass-3.2.12/vendor/listen/lib/listen.rb
+
+csssass_gems_sass_3_2_12_lib_sass_cache_storesdir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/lib/sass/cache_stores
+csssass_gems_sass_3_2_12_lib_sass_cache_stores_DATA = \
+       backends/css/gems/sass-3.2.12/lib/sass/cache_stores/base.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/cache_stores/chain.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/cache_stores/filesystem.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/cache_stores/memory.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/cache_stores/null.rb
+
+csssass_gems_sass_3_2_12_vendor_listen_lib_listendir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/vendor/listen/lib/listen
+csssass_gems_sass_3_2_12_vendor_listen_lib_listen_DATA = \
+       backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapter.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/dependency_manager.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/directory_record.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/listener.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/multi_listener.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/turnstile.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/version.rb
+
+csssass_gems_sass_3_2_12_vendor_listen_specdir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/vendor/listen/spec
+csssass_gems_sass_3_2_12_vendor_listen_spec_DATA = \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/listen_spec.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/spec_helper.rb
+
+csssass_gems_sass_3_2_12_lib_sassdir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/lib/sass
+csssass_gems_sass_3_2_12_lib_sass_DATA = \
+       backends/css/gems/sass-3.2.12/lib/sass/cache_stores.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/callbacks.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/css.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/engine.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/environment.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/error.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/exec.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/importers.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/logger.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/media.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/plugin.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/railtie.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/repl.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/root.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/script.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/scss.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/selector.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/shared.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/supports.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/util.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/version.rb
+
+csssass_gems_sass_3_2_12_extradir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/extra
+csssass_gems_sass_3_2_12_extra_DATA = \
+       backends/css/gems/sass-3.2.12/extra/update_watch.rb
+
+csssass_gems_sass_3_2_12_libdir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/lib
+csssass_gems_sass_3_2_12_lib_DATA = \
+       backends/css/gems/sass-3.2.12/lib/sass.rb
+
+csssass_gems_sass_3_2_12_vendor_listen_spec_supportdir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/vendor/listen/spec/support
+csssass_gems_sass_3_2_12_vendor_listen_spec_support_DATA = \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/support/adapter_helper.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/support/directory_record_helper.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/support/fixtures_helper.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/support/listeners_helper.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/support/platform_helper.rb
+
+csssass_gems_sass_3_2_12_test_sass_utildir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/test/sass/util
+csssass_gems_sass_3_2_12_test_sass_util_DATA = \
+       backends/css/gems/sass-3.2.12/test/sass/util/multibyte_string_scanner_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/util/subset_map_test.rb
+
+csssass_gems_sass_3_2_12_lib_sass_utildir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/lib/sass/util
+csssass_gems_sass_3_2_12_lib_sass_util_DATA = \
+       backends/css/gems/sass-3.2.12/lib/sass/util/multibyte_string_scanner.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/util/subset_map.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/util/test.rb
+
+csssass_gems_sass_3_2_12_test_sass_results_subdirdir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/test/sass/results/subdir
+csssass_gems_sass_3_2_12_test_sass_results_subdir_DATA = \
+       backends/css/gems/sass-3.2.12/test/sass/results/subdir/subdir.css
+
+csssass_gems_sass_3_2_12_vendor_listen_spec_listen_adaptersdir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters
+csssass_gems_sass_3_2_12_vendor_listen_spec_listen_adapters_DATA = \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/bsd_spec.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/darwin_spec.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/linux_spec.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/polling_spec.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/windows_spec.rb
+
+csssass_gems_sass_3_2_12_lib_sass_tree_visitorsdir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/lib/sass/tree/visitors
+csssass_gems_sass_3_2_12_lib_sass_tree_visitors_DATA = \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/base.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/check_nesting.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/convert.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/cssize.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/deep_copy.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/extend.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/perform.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/set_options.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/to_css.rb
+
+csssass_gems_sass_3_2_12_vendor_listendir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/vendor/listen
+csssass_gems_sass_3_2_12_vendor_listen_DATA = \
+       backends/css/gems/sass-3.2.12/vendor/listen/CHANGELOG.md \
+       backends/css/gems/sass-3.2.12/vendor/listen/CONTRIBUTING.md \
+       backends/css/gems/sass-3.2.12/vendor/listen/Gemfile \
+       backends/css/gems/sass-3.2.12/vendor/listen/Guardfile \
+       backends/css/gems/sass-3.2.12/vendor/listen/LICENSE \
+       backends/css/gems/sass-3.2.12/vendor/listen/README.md \
+       backends/css/gems/sass-3.2.12/vendor/listen/Rakefile \
+       backends/css/gems/sass-3.2.12/vendor/listen/Vagrantfile \
+       backends/css/gems/sass-3.2.12/vendor/listen/listen.gemspec
+
+csssass_gems_sass_3_2_12_test_sass_resultsdir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/test/sass/results
+csssass_gems_sass_3_2_12_test_sass_results_DATA = \
+       backends/css/gems/sass-3.2.12/test/sass/results/alt.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/basic.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/cached_import_option.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/compact.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/complex.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/compressed.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/expanded.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/filename_fn.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/if.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/import.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/import_charset.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/import_charset_1_8.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/import_charset_ibm866.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/import_content.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/line_numbers.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/mixins.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/multiline.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/nested.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/options.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/parent_ref.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/script.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/scss_import.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/scss_importee.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/units.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/warn.css \
+       backends/css/gems/sass-3.2.12/test/sass/results/warn_imported.css
+
+csssass_gems_sass_3_2_12_vendor_listen_lib_listen_adaptersdir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters
+csssass_gems_sass_3_2_12_vendor_listen_lib_listen_adapters_DATA = \
+       backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/bsd.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/darwin.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/linux.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/polling.rb \
+       backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/windows.rb
+
+csssass_gems_sass_3_2_12_test_sass_results_subdir_nested_subdirdir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/test/sass/results/subdir/nested_subdir
+csssass_gems_sass_3_2_12_test_sass_results_subdir_nested_subdir_DATA = \
+       backends/css/gems/sass-3.2.12/test/sass/results/subdir/nested_subdir/nested_subdir.css
+
+csssass_gems_sass_3_2_12_lib_sass_importersdir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/lib/sass/importers
+csssass_gems_sass_3_2_12_lib_sass_importers_DATA = \
+       backends/css/gems/sass-3.2.12/lib/sass/importers/base.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/importers/filesystem.rb
+
+csssass_gems_sass_3_2_12_lib_sass_selectordir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/lib/sass/selector
+csssass_gems_sass_3_2_12_lib_sass_selector_DATA = \
+       backends/css/gems/sass-3.2.12/lib/sass/selector/abstract_sequence.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/selector/comma_sequence.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/selector/sequence.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/selector/simple.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/selector/simple_sequence.rb
+
+csssass_gems_sass_3_2_12_test_sass_templates_subdir_nested_subdirdir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/test/sass/templates/subdir/nested_subdir
+csssass_gems_sass_3_2_12_test_sass_templates_subdir_nested_subdir_DATA = \
+       backends/css/gems/sass-3.2.12/test/sass/templates/subdir/nested_subdir/_nested_partial.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/subdir/nested_subdir/nested_subdir.sass
+
+csssass_gems_sass_3_2_12_test_sass_templatesdir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/test/sass/templates
+csssass_gems_sass_3_2_12_test_sass_templates_DATA = \
+       backends/css/gems/sass-3.2.12/test/sass/templates/_cached_import_option_partial.scss \
+       backends/css/gems/sass-3.2.12/test/sass/templates/_double_import_loop2.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/_filename_fn_import.scss \
+       backends/css/gems/sass-3.2.12/test/sass/templates/_imported_charset_ibm866.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/_imported_charset_utf8.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/_imported_content.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/_partial.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/_same_name_different_partiality.scss \
+       backends/css/gems/sass-3.2.12/test/sass/templates/alt.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/basic.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/bork1.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/bork2.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/bork3.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/bork4.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/bork5.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/cached_import_option.scss \
+       backends/css/gems/sass-3.2.12/test/sass/templates/compact.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/complex.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/compressed.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/double_import_loop1.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/expanded.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/filename_fn.scss \
+       backends/css/gems/sass-3.2.12/test/sass/templates/if.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/import.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/import_charset.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/import_charset_1_8.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/import_charset_ibm866.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/import_content.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/importee.less \
+       backends/css/gems/sass-3.2.12/test/sass/templates/importee.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/line_numbers.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/mixin_bork.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/mixins.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/multiline.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/nested.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork1.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork2.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork3.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork4.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/nested_import.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/nested_mixin_bork.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/options.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/parent_ref.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/same_name_different_ext.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/same_name_different_ext.scss \
+       backends/css/gems/sass-3.2.12/test/sass/templates/same_name_different_partiality.scss \
+       backends/css/gems/sass-3.2.12/test/sass/templates/script.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/scss_import.scss \
+       backends/css/gems/sass-3.2.12/test/sass/templates/scss_importee.scss \
+       backends/css/gems/sass-3.2.12/test/sass/templates/single_import_loop.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/units.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/warn.sass \
+       backends/css/gems/sass-3.2.12/test/sass/templates/warn_imported.sass
+
+csssass_gems_sass_3_2_12_test_sass_datadir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/test/sass/data
+csssass_gems_sass_3_2_12_test_sass_data_DATA = \
+       backends/css/gems/sass-3.2.12/test/sass/data/hsl-rgb.txt
+
+csssass_gems_sass_3_2_12_railsdir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/rails
+csssass_gems_sass_3_2_12_rails_DATA = \
+       backends/css/gems/sass-3.2.12/rails/init.rb
+
+csssass_gems_sass_3_2_12_test_sassdir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/test/sass
+csssass_gems_sass_3_2_12_test_sass_DATA = \
+       backends/css/gems/sass-3.2.12/test/sass/cache_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/callbacks_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/conversion_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/css2sass_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/engine_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/exec_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/extend_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/functions_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/importer_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/logger_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/mock_importer.rb \
+       backends/css/gems/sass-3.2.12/test/sass/plugin_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/script_conversion_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/script_test.rb \
+       backends/css/gems/sass-3.2.12/test/sass/test_helper.rb \
+       backends/css/gems/sass-3.2.12/test/sass/util_test.rb
+
+csssass_gems_sass_3_2_12_lib_sass_treedir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/lib/sass/tree
+csssass_gems_sass_3_2_12_lib_sass_tree_DATA = \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/charset_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/comment_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/content_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/css_import_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/debug_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/directive_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/each_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/extend_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/for_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/function_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/if_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/import_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/media_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/mixin_def_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/mixin_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/prop_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/return_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/root_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/rule_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/supports_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/trace_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/variable_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/warn_node.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/tree/while_node.rb
+
+csssass_gems_sass_3_2_12_lib_sass_scssdir = $(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/lib/sass/scss
+csssass_gems_sass_3_2_12_lib_sass_scss_DATA = \
+       backends/css/gems/sass-3.2.12/lib/sass/scss/css_parser.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/scss/parser.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/scss/rx.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/scss/script_lexer.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/scss/script_parser.rb \
+       backends/css/gems/sass-3.2.12/lib/sass/scss/static_parser.rb
+
+csssass_gems_sass_3_2_12_test_sass_more_resultsdir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/test/sass/more_results
+csssass_gems_sass_3_2_12_test_sass_more_results_DATA = \
+       backends/css/gems/sass-3.2.12/test/sass/more_results/more1.css \
+       backends/css/gems/sass-3.2.12/test/sass/more_results/more1_with_line_comments.css \
+       backends/css/gems/sass-3.2.12/test/sass/more_results/more_import.css
+
+csssass_gems_sass_3_2_12_test_sass_fixturesdir = 
$(GCA_RBBACKENDS_DIR)/css/gems/sass-3.2.12/test/sass/fixtures
+csssass_gems_sass_3_2_12_test_sass_fixtures_DATA = \
+       backends/css/gems/sass-3.2.12/test/sass/fixtures/test_staleness_check_across_importers.css \
+       backends/css/gems/sass-3.2.12/test/sass/fixtures/test_staleness_check_across_importers.scss
+
diff --git a/backends/css/gems/sass-3.2.12/.yardopts b/backends/css/gems/sass-3.2.12/.yardopts
new file mode 100644
index 0000000..1d14215
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/.yardopts
@@ -0,0 +1,11 @@
+--readme          README.md
+--markup          markdown
+--markup-provider maruku
+--default-return  ""
+--title           "Sass Documentation"
+--query           'object.type != :classvariable'
+--query           'object.type != :constant || @api && @api.text == "public"'
+--hide-void-return
+--protected
+--no-private
+--no-highlight
diff --git a/backends/css/gems/sass-3.2.12/CONTRIBUTING b/backends/css/gems/sass-3.2.12/CONTRIBUTING
new file mode 100644
index 0000000..be466d3
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/CONTRIBUTING
@@ -0,0 +1,3 @@
+Contributions are welcomed. Please see the following sites for guidelines:
+
+  http://sass-lang.com/development.html#contributing
diff --git a/backends/css/gems/sass-3.2.12/MIT-LICENSE b/backends/css/gems/sass-3.2.12/MIT-LICENSE
new file mode 100644
index 0000000..6b739c9
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2006-2013 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/backends/css/gems/sass-3.2.12/README.md b/backends/css/gems/sass-3.2.12/README.md
new file mode 100644
index 0000000..ef80d18
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/README.md
@@ -0,0 +1,201 @@
+# Sass [![Gem Version](https://badge.fury.io/rb/sass.png)](http://badge.fury.io/rb/sass)
+
+**Sass makes CSS fun again**. Sass is an extension of CSS3,
+adding nested rules, variables, mixins, selector inheritance, and more.
+It's translated to well-formatted, standard CSS
+using the command line tool or a web-framework plugin.
+
+Sass has two syntaxes. The new main syntax (as of Sass 3)
+is known as "SCSS" (for "Sassy CSS"),
+and is a superset of CSS3's syntax.
+This means that every valid CSS3 stylesheet is valid SCSS as well.
+SCSS files use the extension `.scss`.
+
+The second, older syntax is known as the indented syntax (or just "Sass").
+Inspired by Haml's terseness, it's intended for people
+who prefer conciseness over similarity to CSS.
+Instead of brackets and semicolons,
+it uses the indentation of lines to specify blocks.
+Although no longer the primary syntax,
+the indented syntax will continue to be supported.
+Files in the indented syntax use the extension `.sass`.
+
+## Using
+
+Sass can be used from the command line
+or as part of a web framework.
+The first step is to install the gem:
+
+    gem install sass
+
+After you convert some CSS to Sass, you can run
+
+    sass style.scss
+
+to compile it back to CSS.
+For more information on these commands, check out
+
+    sass --help
+
+To install Sass in Rails 2,
+just add `config.gem "sass"` to `config/environment.rb`.
+In Rails 3, add `gem "sass"` to your Gemfile instead.
+`.sass` or `.scss` files should be placed in `public/stylesheets/sass`,
+where they'll be automatically compiled
+to corresponding CSS files in `public/stylesheets` when needed
+(the Sass template directory is customizable...
+see [the Sass reference](http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#template_location-option) 
for details).
+
+Sass can also be used with any Rack-enabled web framework.
+To do so, just add
+
+    require 'sass/plugin/rack'
+    use Sass::Plugin::Rack
+
+to `config.ru`.
+Then any Sass files in `public/stylesheets/sass`
+will be compiled into CSS files in `public/stylesheets` on every request.
+
+To use Sass programmatically,
+check out the [YARD documentation](http://sass-lang.com/docs/yardoc/).
+
+## Formatting
+
+Sass is an extension of CSS
+that adds power and elegance to the basic language.
+It allows you to use [variables][vars], [nested rules][nested],
+[mixins][mixins], [inline imports][imports],
+and more, all with a fully CSS-compatible syntax.
+Sass helps keep large stylesheets well-organized,
+and get small stylesheets up and running quickly,
+particularly with the help of
+[the Compass style library](http://compass-style.org).
+
+[vars]:    http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#variables_
+[nested]:  http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#nested_rules_
+[mixins]:  http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#mixins
+[imports]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#import
+
+Sass has two syntaxes.
+The one presented here, known as "SCSS" (for "Sassy CSS"),
+is fully CSS-compatible.
+The other (older) syntax, known as the indented syntax or just "Sass",
+is whitespace-sensitive and indentation-based.
+For more information, see the [reference documentation][syntax].
+
+[syntax]: http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#syntax
+
+To run the following examples and see the CSS they produce,
+put them in a file called `test.scss` and run `sass test.scss`.
+
+### Nesting
+
+Sass avoids repetition by nesting selectors within one another.
+The same thing works for properties.
+
+    table.hl {
+      margin: 2em 0;
+      td.ln { text-align: right; }
+    }
+
+    li {
+      font: {
+        family: serif;
+        weight: bold;
+        size: 1.2em;
+      }
+    }
+
+### Variables
+
+Use the same color all over the place?
+Need to do some math with height and width and text size?
+Sass supports variables, math operations, and many useful functions.
+
+    $blue: #3bbfce;
+    $margin: 16px;
+
+    .content_navigation {
+      border-color: $blue;
+      color: darken($blue, 10%);
+    }
+
+    .border {
+      padding: $margin / 2;
+      margin: $margin / 2;
+      border-color: $blue;
+    }
+
+### Mixins
+
+Even more powerful than variables,
+mixins allow you to re-use whole chunks of CSS,
+properties or selectors.
+You can even give them arguments. 
+
+    @mixin table-scaffolding {
+      th {
+        text-align: center;
+        font-weight: bold;
+      }
+      td, th { padding: 2px; }
+    }
+
+    @mixin left($dist) {
+      float: left;
+      margin-left: $dist;
+    }
+
+    #data {
+      @include left(10px);
+      @include table-scaffolding;
+    }
+
+A comprehensive list of features is available
+in the [Sass reference](http://beta.sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html).
+
+## Executables
+
+The Sass gem includes several executables that are useful
+for dealing with Sass from the command line.
+
+### `sass`
+
+The `sass` executable transforms a source Sass file into CSS.
+See `sass --help` for further information and options.
+
+### `sass-convert`
+
+The `sass-convert` executable converts between CSS, Sass, and SCSS.
+When converting from CSS to Sass or SCSS,
+nesting is applied where appropriate.
+See `sass-convert --help` for further information and options.
+
+## Authors
+
+Sass was envisioned by [Hampton Catlin](http://www.hamptoncatlin.com)
+(@hcatlin). However, Hampton doesn't even know his way around the code anymore
+and now occasionally consults on the language issues. Hampton lives in San
+Francisco, California and works as VP of Technology
+at [Moovweb](http://www.moovweb.com/).
+
+[Nathan Weizenbaum](http://nex-3.com) is the primary developer and architect of
+Sass. His hard work has kept the project alive by endlessly answering forum
+posts, fixing bugs, refactoring, finding speed improvements, writing
+documentation, implementing new features, and getting Hampton coffee (a fitting
+task for a boy-genius). Nathan lives in Seattle, Washington and works on
+[Dart](http://dartlang.org) application libraries at Google.
+
+[Chris Eppstein](http://acts-as-architect.blogspot.com) is a core contributor to
+Sass and the creator of Compass, the first Sass-based framework. Chris focuses
+on making Sass more powerful, easy to use, and on ways to speed its adoption
+through the web development community. Chris lives in San Jose, California with
+his wife and daughter. He is the Software Architect for
+[Caring.com](http://caring.com), a website devoted to the 34 Million caregivers
+whose parents are sick or elderly, that uses Haml and Sass.
+
+If you use this software, you must pay Hampton a compliment. And
+buy Nathan some jelly beans. Maybe pet a kitten. Yeah. Pet that kitty.
+
+Beyond that, the implementation is licensed under the MIT License.
+Okay, fine, I guess that means compliments aren't __required__.
diff --git a/backends/css/gems/sass-3.2.12/REVISION b/backends/css/gems/sass-3.2.12/REVISION
new file mode 100644
index 0000000..54798d6
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/REVISION
@@ -0,0 +1 @@
+(release)
diff --git a/backends/css/gems/sass-3.2.12/Rakefile b/backends/css/gems/sass-3.2.12/Rakefile
new file mode 100644
index 0000000..b9440c9
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/Rakefile
@@ -0,0 +1,347 @@
+# ----- Utility Functions -----
+
+def scope(path)
+  File.join(File.dirname(__FILE__), path)
+end
+
+# ----- Default: Testing ------
+
+task :default => :test
+
+require 'rake/testtask'
+
+Rake::TestTask.new do |t|
+  t.libs << 'test'
+  test_files = FileList[scope('test/**/*_test.rb')]
+  test_files.exclude(scope('test/rails/*'))
+  test_files.exclude(scope('test/plugins/*'))
+  t.test_files = test_files
+  t.verbose = true
+end
+
+# ----- Packaging -----
+
+# Don't use Rake::GemPackageTast because we want prerequisites to run
+# before we load the gemspec.
+desc "Build all the packages."
+task :package => [:revision_file, :date_file, :submodules, :permissions] do
+  version = get_version
+  File.open(scope('VERSION'), 'w') {|f| f.puts(version)}
+  load scope('sass.gemspec')
+  Gem::Builder.new(SASS_GEMSPEC).build
+  sh %{git checkout VERSION}
+
+  pkg = "#{SASS_GEMSPEC.name}-#{SASS_GEMSPEC.version}"
+  mkdir_p "pkg"
+  verbose(true) {mv "#{pkg}.gem", "pkg/#{pkg}.gem"}
+
+  sh %{rm -f pkg/#{pkg}.tar.gz}
+  verbose(false) {SASS_GEMSPEC.files.each {|f| sh %{tar rf pkg/#{pkg}.tar #{f}}}}
+  sh %{gzip pkg/#{pkg}.tar}
+end
+
+task :permissions do
+  sh %{chmod -R a+rx bin}
+  sh %{chmod -R a+r .}
+  require 'shellwords'
+  Dir.glob('test/**/*_test.rb') do |file|
+    next if file =~ %r{^test/haml/spec/}
+    sh %{chmod a+rx #{file}}
+  end
+end
+
+task :revision_file do
+  require scope('lib/sass')
+
+  release = Rake.application.top_level_tasks.include?('release') || File.exist?(scope('EDGE_GEM_VERSION'))
+  if Sass.version[:rev] && !release
+    File.open(scope('REVISION'), 'w') { |f| f.puts Sass.version[:rev] }
+  elsif release
+    File.open(scope('REVISION'), 'w') { |f| f.puts "(release)" }
+  else
+    File.open(scope('REVISION'), 'w') { |f| f.puts "(unknown)" }
+  end
+end
+
+task :date_file do
+  File.open(scope('VERSION_DATE'), 'w') do |f|
+    f.puts Time.now.utc.strftime('%d %B %Y %T %Z')
+  end
+end
+
+# We also need to get rid of this file after packaging.
+at_exit do
+  File.delete(scope('REVISION')) rescue nil
+  File.delete(scope('VERSION_DATE')) rescue nil
+end
+
+desc "Install Sass as a gem. Use SUDO=1 to install with sudo."
+task :install => [:package] do
+  gem  = RUBY_PLATFORM =~ /java/  ? 'jgem' : 'gem' 
+  sh %{#{'sudo ' if ENV["SUDO"]}#{gem} install --no-ri pkg/sass-#{get_version}}
+end
+
+desc "Release a new Sass package to Rubyforge."
+task :release => [:check_release, :package] do
+  name = File.read(scope("VERSION_NAME")).strip
+  version = File.read(scope("VERSION")).strip
+  sh %{rubyforge add_release sass sass "#{name} (v#{version})" pkg/sass-#{version}.gem}
+  sh %{rubyforge add_file    sass sass "#{name} (v#{version})" pkg/sass-#{version}.tar.gz}
+  sh %{gem push pkg/sass-#{version}.gem}
+end
+
+# Ensures that the VERSION file has been updated for a new release.
+task :check_release do
+  version = File.read(scope("VERSION")).strip
+  raise "There have been changes since current version (#{version})" if changed_since?(version)
+  raise "VERSION_NAME must not be 'Bleeding Edge'" if File.read(scope("VERSION_NAME")) == "Bleeding Edge"
+end
+
+# Reads a password from the command line.
+#
+# @param name [String] The prompt to use to read the password
+def read_password(prompt)
+  require 'readline'
+  system "stty -echo"
+  Readline.readline("#{prompt}: ").strip
+ensure
+  system "stty echo"
+  puts
+end
+
+# Returns whether or not the repository, or specific files,
+# has/have changed since a given revision.
+#
+# @param rev [String] The revision to check against
+# @param files [Array<String>] The files to check.
+#   If this is empty, checks the entire repository
+def changed_since?(rev, *files)
+  IO.popen("git diff --exit-code #{rev} #{files.join(' ')}") {}
+  return !$?.success?
+end
+
+task :submodules do
+  if File.exist?(File.dirname(__FILE__) + "/.git")
+    sh %{git submodule sync}
+    sh %{git submodule update --init}
+  elsif !File.exist?(File.dirname(__FILE__) + "/vendor/listen/lib")
+    warn <<WARN
+WARNING: vendor/listen doesn't exist, and this isn't a git repository so
+I can't get it automatically!
+WARN
+  end
+end
+
+task :release_edge do
+  ensure_git_cleanup do
+    puts "#{'=' * 50} Running rake release_edge"
+
+    sh %{git checkout master}
+    sh %{git reset --hard origin/master}
+    sh %{rake package}
+    version = get_version
+    sh %{rubyforge add_release sass sass "Bleeding Edge (v#{version})" pkg/sass-#{version}.gem}
+    sh %{gem push pkg/sass-#{version}.gem}
+  end
+end
+
+# Get the version string. If this is being installed from Git,
+# this includes the proper prerelease version.
+def get_version
+  written_version = File.read(scope('VERSION').strip)
+  return written_version unless File.exist?(scope('.git'))
+
+  # Get the current master branch version
+  version = written_version.split('.')
+  version.map! {|n| n =~ /^[0-9]+$/ ? n.to_i : n}
+  return written_version unless version.size == 5 && version[3] == "alpha" # prerelease
+
+  return written_version if (commit_count = `git log --pretty=oneline HEAD ^stable | wc -l`).empty?
+  version[4] = commit_count.strip
+  version.join('.')
+end
+
+task :watch_for_update do
+  sh %{ruby extra/update_watch.rb}
+end
+
+# ----- Documentation -----
+
+task :rdoc do
+  puts '=' * 100, <<END, '=' * 100
+Sass uses the YARD documentation system (http://github.com/lsegal/yard).
+Install the yard gem and then run "rake doc".
+END
+end
+
+begin
+  require 'yard'
+
+  namespace :doc do
+    task :sass do
+      require scope('lib/sass')
+      Dir[scope("yard/default/**/*.sass")].each do |sass|
+        File.open(sass.gsub(/sass$/, 'css'), 'w') do |f|
+          f.write(Sass::Engine.new(File.read(sass)).render)
+        end
+      end
+    end
+
+    desc "List all undocumented methods and classes."
+    task :undocumented do
+      opts = ENV["YARD_OPTS"] || ""
+      ENV["YARD_OPTS"] = opts.dup + <<OPTS
+ --list --query "
+  object.docstring.blank? &&
+  !(object.type == :method && object.is_alias?)"
+OPTS
+      Rake::Task['yard'].execute
+    end
+  end
+
+  YARD::Rake::YardocTask.new do |t|
+    t.files = FileList.new(scope('lib/**/*.rb')) do |list|
+      list.exclude('lib/sass/plugin/merb.rb')
+      list.exclude('lib/sass/plugin/rails.rb')
+    end.to_a
+    t.options << '--incremental' if Rake.application.top_level_tasks.include?('redoc')
+    t.options += FileList.new(scope('yard/*.rb')).to_a.map {|f| ['-e', f]}.flatten
+    files = FileList.new(scope('doc-src/*')).to_a.sort_by {|s| s.size} + %w[MIT-LICENSE VERSION]
+    t.options << '--files' << files.join(',')
+    t.options << '--template-path' << scope('yard')
+    t.options << '--title' << ENV["YARD_TITLE"] if ENV["YARD_TITLE"]
+
+    t.before = lambda do
+      if ENV["YARD_OPTS"]
+        require 'shellwords'
+        t.options.concat(Shellwords.shellwords(ENV["YARD_OPTS"]))
+      end
+    end
+  end
+  Rake::Task['yard'].prerequisites.insert(0, 'doc:sass')
+  Rake::Task['yard'].instance_variable_set('@comment', nil)
+
+  desc "Generate Documentation"
+  task :doc => :yard
+  task :redoc => :yard
+rescue LoadError
+  desc "Generate Documentation"
+  task :doc => :rdoc
+  task :yard => :rdoc
+end
+
+task :pages do
+  ensure_git_cleanup do
+    puts "#{'=' * 50} Running rake pages"
+    sh %{git checkout sass-pages}
+    sh %{git reset --hard origin/sass-pages}
+
+    Dir.chdir("/var/www/sass-pages") do
+      sh %{git fetch origin}
+
+      sh %{git checkout stable}
+      sh %{git reset --hard origin/stable}
+
+      sh %{git checkout sass-pages}
+      sh %{git reset --hard origin/sass-pages}
+      sh %{rake build --trace}
+      sh %{mkdir -p tmp}
+      sh %{touch tmp/restart.txt}
+    end
+  end
+end
+
+# ----- Coverage -----
+
+begin
+  require 'rcov/rcovtask'
+
+  Rcov::RcovTask.new do |t|
+    t.test_files = FileList[scope('test/**/*_test.rb')]
+    t.rcov_opts << '-x' << '"^\/"'
+    if ENV['NON_NATIVE']
+      t.rcov_opts << "--no-rcovrt"
+    end
+    t.verbose = true
+  end
+rescue LoadError; end
+
+# ----- Profiling -----
+
+begin
+  require 'ruby-prof'
+
+  desc <<END
+Run a profile of sass.
+  TIMES=n sets the number of runs. Defaults to 1000.
+  FILE=str sets the file to profile. Defaults to 'complex'.
+  OUTPUT=str sets the ruby-prof output format.
+    Can be Flat, CallInfo, or Graph. Defaults to Flat. Defaults to Flat.
+END
+  task :profile do
+    times  = (ENV['TIMES'] || '1000').to_i
+    file   = ENV['FILE']
+
+    require 'lib/sass'
+
+    file = File.read(scope("test/sass/templates/#{file || 'complex'}.sass"))
+    result = RubyProf.profile { times.times { Sass::Engine.new(file).render } }
+
+    RubyProf.const_get("#{(ENV['OUTPUT'] || 'Flat').capitalize}Printer").new(result).print 
+  end
+rescue LoadError; end
+
+# ----- Handling Updates -----
+
+def email_on_error
+  yield
+rescue Exception => e
+  IO.popen("sendmail nex342 gmail com", "w") do |sm|
+    sm << "From: nex3 nex-3 com\n" <<
+      "To: nex342 gmail com\n" <<
+      "Subject: Exception when running rake #{Rake.application.top_level_tasks.join(', ')}\n" <<
+      e.message << "\n\n" <<
+      e.backtrace.join("\n")
+  end
+ensure
+  raise e if e
+end
+
+def ensure_git_cleanup
+  email_on_error {yield}
+ensure
+  sh %{git reset --hard HEAD}
+  sh %{git clean -xdf}
+  sh %{git checkout master}
+end
+
+task :handle_update do
+  email_on_error do
+    unless ENV["REF"] =~ %r{^refs/heads/(master|stable|sass-pages)$}
+      puts "#{'=' * 20} Ignoring rake handle_update REF=#{ENV["REF"].inspect}"
+      next
+    end
+    branch = $1
+
+    puts
+    puts
+    puts '=' * 150
+    puts "Running rake handle_update REF=#{ENV["REF"].inspect}"
+
+    sh %{git fetch origin}
+    sh %{git checkout stable}
+    sh %{git reset --hard origin/stable}
+    sh %{git checkout master}
+    sh %{git reset --hard origin/master}
+
+    case branch
+    when "master"
+      sh %{rake release_edge --trace}
+    when "stable", "sass-pages"
+      sh %{rake pages --trace}
+    end
+
+    puts 'Done running handle_update'
+    puts '=' * 150
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/VERSION b/backends/css/gems/sass-3.2.12/VERSION
new file mode 100644
index 0000000..275e51e
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/VERSION
@@ -0,0 +1 @@
+3.2.12
diff --git a/backends/css/gems/sass-3.2.12/VERSION_DATE b/backends/css/gems/sass-3.2.12/VERSION_DATE
new file mode 100644
index 0000000..81d9ff3
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/VERSION_DATE
@@ -0,0 +1 @@
+05 October 2013 01:29:11 UTC
diff --git a/backends/css/gems/sass-3.2.12/VERSION_NAME b/backends/css/gems/sass-3.2.12/VERSION_NAME
new file mode 100644
index 0000000..b0c8d03
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/VERSION_NAME
@@ -0,0 +1 @@
+Media Mark
diff --git a/backends/css/gems/sass-3.2.12/bin/sass b/backends/css/gems/sass-3.2.12/bin/sass
new file mode 100755
index 0000000..0e5279d
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/bin/sass
@@ -0,0 +1,9 @@
+#!/usr/bin/env ruby
+# The command line Sass parser.
+
+THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
+require File.dirname(THIS_FILE) + '/../lib/sass'
+require 'sass/exec'
+
+opts = Sass::Exec::Sass.new(ARGV)
+opts.parse!
diff --git a/backends/css/gems/sass-3.2.12/bin/sass-convert b/backends/css/gems/sass-3.2.12/bin/sass-convert
new file mode 100755
index 0000000..10f67d7
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/bin/sass-convert
@@ -0,0 +1,8 @@
+#!/usr/bin/env ruby
+
+THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
+require File.dirname(THIS_FILE) + '/../lib/sass'
+require 'sass/exec'
+
+opts = Sass::Exec::SassConvert.new(ARGV)
+opts.parse!
diff --git a/backends/css/gems/sass-3.2.12/bin/scss b/backends/css/gems/sass-3.2.12/bin/scss
new file mode 100755
index 0000000..5d4d4ae
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/bin/scss
@@ -0,0 +1,9 @@
+#!/usr/bin/env ruby
+# The command line Sass parser.
+
+THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
+require File.dirname(THIS_FILE) + '/../lib/sass'
+require 'sass/exec'
+
+opts = Sass::Exec::Scss.new(ARGV)
+opts.parse!
diff --git a/backends/css/gems/sass-3.2.12/extra/update_watch.rb 
b/backends/css/gems/sass-3.2.12/extra/update_watch.rb
new file mode 100644
index 0000000..73489a1
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/extra/update_watch.rb
@@ -0,0 +1,13 @@
+require 'rubygems'
+require 'sinatra'
+require 'json'
+set :port, 3124
+set :environment, :production
+enable :lock
+Dir.chdir(File.dirname(__FILE__) + "/..")
+
+post "/" do
+  puts "Recieved payload!"
+  puts "Rev: #{`git name-rev HEAD`.strip}"
+  system %{rake handle_update --trace REF=#{JSON.parse(params["payload"])["ref"].inspect}}
+end
diff --git a/backends/css/gems/sass-3.2.12/init.rb b/backends/css/gems/sass-3.2.12/init.rb
new file mode 100644
index 0000000..5a3bceb
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/init.rb
@@ -0,0 +1,18 @@
+begin
+  require File.join(File.dirname(__FILE__), 'lib', 'sass') # From here
+rescue LoadError
+  begin
+    require 'sass' # From gem
+  rescue LoadError => e
+    # gems:install may be run to install Haml with the skeleton plugin
+    # but not the gem itself installed.
+    # Don't die if this is the case.
+    raise e unless defined?(Rake) &&
+      (Rake.application.top_level_tasks.include?('gems') ||
+        Rake.application.top_level_tasks.include?('gems:install'))
+  end
+end
+
+# Load Sass.
+# Sass may be undefined if we're running gems:install.
+require 'sass/plugin' if defined?(Sass)
diff --git a/backends/css/gems/sass-3.2.12/lib/sass.rb b/backends/css/gems/sass-3.2.12/lib/sass.rb
new file mode 100644
index 0000000..63af120
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass.rb
@@ -0,0 +1,95 @@
+dir = File.dirname(__FILE__)
+$LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir)
+
+# This is necessary to set so that the Haml code that tries to load Sass
+# knows that Sass is indeed loading,
+# even if there's some crazy autoload stuff going on.
+SASS_BEGUN_TO_LOAD = true unless defined?(SASS_BEGUN_TO_LOAD)
+
+require 'sass/version'
+
+# The module that contains everything Sass-related:
+#
+# * {Sass::Engine} is the class used to render Sass/SCSS within Ruby code.
+# * {Sass::Plugin} is interfaces with web frameworks (Rails and Merb in particular).
+# * {Sass::SyntaxError} is raised when Sass encounters an error.
+# * {Sass::CSS} handles conversion of CSS to Sass.
+#
+# Also see the {file:SASS_REFERENCE.md full Sass reference}.
+module Sass
+  # The global load paths for Sass files. This is meant for plugins and
+  # libraries to register the paths to their Sass stylesheets to that they may
+  # be ` imported`  This load path is used by every instance of [Sass::Engine].
+  # They are lower-precedence than any load paths passed in via the
+  # {file:SASS_REFERENCE.md#load_paths-option `:load_paths` option}.
+  #
+  # If the `SASS_PATH` environment variable is set,
+  # the initial value of `load_paths` will be initialized based on that.
+  # The variable should be a colon-separated list of path names
+  # (semicolon-separated on Windows).
+  #
+  # Note that files on the global load path are never compiled to CSS
+  # themselves, even if they aren't partials. They exist only to be imported.
+  #
+  # @example
+  #   Sass.load_paths << File.dirname(__FILE__ + '/sass')
+  # @return [Array<String, Pathname, Sass::Importers::Base>]
+  def self.load_paths
+    @load_paths ||= ENV['SASS_PATH'] ?
+      ENV['SASS_PATH'].split(Sass::Util.windows? ? ';' : ':') : []
+  end
+
+  # Compile a Sass or SCSS string to CSS.
+  # Defaults to SCSS.
+  #
+  # @param contents [String] The contents of the Sass file.
+  # @param options [{Symbol => Object}] An options hash;
+  #   see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
+  # @raise [Sass::SyntaxError] if there's an error in the document
+  # @raise [Encoding::UndefinedConversionError] if the source encoding
+  #   cannot be converted to UTF-8
+  # @raise [ArgumentError] if the document uses an unknown encoding with ` charset`
+  def self.compile(contents, options = {})
+    options[:syntax] ||= :scss
+    Engine.new(contents, options).to_css
+  end
+
+  # Compile a file on disk to CSS.
+  #
+  # @param filename [String] The path to the Sass, SCSS, or CSS file on disk.
+  # @param options [{Symbol => Object}] An options hash;
+  #   see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
+  # @raise [Sass::SyntaxError] if there's an error in the document
+  # @raise [Encoding::UndefinedConversionError] if the source encoding
+  #   cannot be converted to UTF-8
+  # @raise [ArgumentError] if the document uses an unknown encoding with ` charset`
+  #
+  # @overload compile_file(filename, options = {})
+  #   Return the compiled CSS rather than writing it to a file.
+  #
+  #   @return [String] The compiled CSS.
+  #
+  # @overload compile_file(filename, css_filename, options = {})
+  #   Write the compiled CSS to a file.
+  #
+  #   @param css_filename [String] The location to which to write the compiled CSS.
+  def self.compile_file(filename, *args)
+    options = args.last.is_a?(Hash) ? args.pop : {}
+    css_filename = args.shift
+    result = Sass::Engine.for_file(filename, options).render
+    if css_filename
+      options[:css_filename] ||= css_filename
+      open(css_filename,"w") {|css_file| css_file.write(result)}
+      nil
+    else
+      result
+    end
+  end
+end
+
+require 'sass/logger'
+require 'sass/util'
+
+require 'sass/engine'
+require 'sass/plugin' if defined?(Merb::Plugins)
+require 'sass/railtie'
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/cache_stores.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/cache_stores.rb
new file mode 100644
index 0000000..62259b3
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/cache_stores.rb
@@ -0,0 +1,15 @@
+require 'stringio'
+
+module Sass
+  # Sass cache stores are in charge of storing cached information,
+  # especially parse trees for Sass documents.
+  #
+  # User-created importers must inherit from {CacheStores::Base}.
+  module CacheStores
+  end
+end
+
+require 'sass/cache_stores/base'
+require 'sass/cache_stores/filesystem'
+require 'sass/cache_stores/memory'
+require 'sass/cache_stores/chain'
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/cache_stores/base.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/cache_stores/base.rb
new file mode 100644
index 0000000..25e6472
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/cache_stores/base.rb
@@ -0,0 +1,88 @@
+module Sass
+  module CacheStores
+    # An abstract base class for backends for the Sass cache.
+    # Any key-value store can act as such a backend;
+    # it just needs to implement the
+    # \{#_store} and \{#_retrieve} methods.
+    #
+    # To use a cache store with Sass,
+    # use the {file:SASS_REFERENCE.md#cache_store-option `:cache_store` option}.
+    #
+    # @abstract
+    class Base
+      # Store cached contents for later retrieval
+      # Must be implemented by all CacheStore subclasses
+      #
+      # Note: cache contents contain binary data.
+      #
+      # @param key [String] The key to store the contents under
+      # @param version [String] The current sass version.
+      #                Cached contents must not be retrieved across different versions of sass.
+      # @param sha [String] The sha of the sass source.
+      #                Cached contents must not be retrieved if the sha has changed.
+      # @param contents [String] The contents to store.
+      def _store(key, version, sha, contents)
+        raise "#{self.class} must implement #_store."
+      end
+
+      # Retrieved cached contents.
+      # Must be implemented by all subclasses.
+      # 
+      # Note: if the key exists but the sha or version have changed,
+      # then the key may be deleted by the cache store, if it wants to do so.
+      #
+      # @param key [String] The key to retrieve
+      # @param version [String] The current sass version.
+      #                Cached contents must not be retrieved across different versions of sass.
+      # @param sha [String] The sha of the sass source.
+      #                Cached contents must not be retrieved if the sha has changed.
+      # @return [String] The contents that were previously stored.
+      # @return [NilClass] when the cache key is not found or the version or sha have changed.
+      def _retrieve(key, version, sha)
+        raise "#{self.class} must implement #_retrieve."
+      end
+
+      # Store a {Sass::Tree::RootNode}.
+      #
+      # @param key [String] The key to store it under.
+      # @param sha [String] The checksum for the contents that are being stored.
+      # @param obj [Object] The object to cache.
+      def store(key, sha, root)
+        _store(key, Sass::VERSION, sha, Marshal.dump(root))
+      rescue TypeError, LoadError => e
+        Sass::Util.sass_warn "Warning. Error encountered while saving cache #{path_to(key)}: #{e}"
+        nil
+      end
+
+      # Retrieve a {Sass::Tree::RootNode}.
+      #
+      # @param key [String] The key the root element was stored under.
+      # @param sha [String] The checksum of the root element's content.
+      # @return [Object] The cached object.
+      def retrieve(key, sha)
+        contents = _retrieve(key, Sass::VERSION, sha)
+        Marshal.load(contents) if contents
+      rescue EOFError, TypeError, ArgumentError, LoadError => e
+        Sass::Util.sass_warn "Warning. Error encountered while reading cache #{path_to(key)}: #{e}"
+        nil
+      end
+
+      # Return the key for the sass file.
+      #
+      # The `(sass_dirname, sass_basename)` pair
+      # should uniquely identify the Sass document,
+      # but otherwise there are no restrictions on their content.
+      #
+      # @param sass_dirname [String]
+      #   The fully-expanded location of the Sass file.
+      #   This corresponds to the directory name on a filesystem.
+      # @param sass_basename [String] The name of the Sass file that is being referenced.
+      #   This corresponds to the basename on a filesystem.
+      def key(sass_dirname, sass_basename)
+        dir = Digest::SHA1.hexdigest(sass_dirname)
+        filename = "#{sass_basename}c"
+        "#{dir}/#{filename}"
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/cache_stores/chain.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/cache_stores/chain.rb
new file mode 100644
index 0000000..d67086f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/cache_stores/chain.rb
@@ -0,0 +1,33 @@
+module Sass
+  module CacheStores
+    # A meta-cache that chains multiple caches together.
+    # Specifically:
+    #
+    # * All `#store`s are passed to all caches.
+    # * `#retrieve`s are passed to each cache until one has a hit.
+    # * When one cache has a hit, the value is `#store`d in all earlier caches.
+    class Chain < Base
+      # Create a new cache chaining the given caches.
+      #
+      # @param caches [Array<Sass::CacheStores::Base>] The caches to chain.
+      def initialize(*caches)
+        @caches = caches
+      end
+
+      # @see Base#store
+      def store(key, sha, obj)
+        @caches.each {|c| c.store(key, sha, obj)}
+      end
+
+      # @see Base#retrieve
+      def retrieve(key, sha)
+        @caches.each_with_index do |c, i|
+          next unless obj = c.retrieve(key, sha)
+          @caches[0...i].each {|prev| prev.store(key, sha, obj)}
+          return obj
+        end
+        nil
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/cache_stores/filesystem.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/cache_stores/filesystem.rb
new file mode 100644
index 0000000..221ec4a
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/cache_stores/filesystem.rb
@@ -0,0 +1,60 @@
+require 'fileutils'
+
+module Sass
+  module CacheStores
+    # A backend for the Sass cache using the filesystem.
+    class Filesystem < Base
+      # The directory where the cached files will be stored.
+      #
+      # @return [String]
+      attr_accessor :cache_location
+
+      # @param cache_location [String] see \{#cache\_location}
+      def initialize(cache_location)
+        @cache_location = cache_location
+      end
+
+      # @see Base#\_retrieve
+      def _retrieve(key, version, sha)
+        return unless File.readable?(path_to(key))
+        File.open(path_to(key), "rb") do |f|
+          if f.readline("\n").strip == version && f.readline("\n").strip == sha
+            return f.read
+          end
+        end
+        File.unlink path_to(key)
+        nil
+      rescue EOFError, TypeError, ArgumentError => e
+        Sass::Util.sass_warn "Warning. Error encountered while reading cache #{path_to(key)}: #{e}"
+      end
+
+      # @see Base#\_store
+      def _store(key, version, sha, contents)
+        # return unless File.writable?(File.dirname(@cache_location))
+        # return if File.exists?(@cache_location) && !File.writable?(@cache_location)
+        compiled_filename = path_to(key)
+        # return if File.exists?(File.dirname(compiled_filename)) && 
!File.writable?(File.dirname(compiled_filename))
+        # return if File.exists?(compiled_filename) && !File.writable?(compiled_filename)
+        FileUtils.mkdir_p(File.dirname(compiled_filename))
+        Sass::Util.atomic_create_and_write_file(compiled_filename) do |f|
+          f.puts(version)
+          f.puts(sha)
+          f.write(contents)
+        end
+      rescue Errno::EACCES
+        #pass
+      end
+
+      private
+
+      # Returns the path to a file for the given key.
+      #
+      # @param key [String]
+      # @return [String] The path to the cache file.
+      def path_to(key)
+        key = key.gsub(/[<>:\\|?*%]/) {|c| "%%%03d" % Sass::Util.ord(c)}
+        File.join(cache_location, key)
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/cache_stores/memory.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/cache_stores/memory.rb
new file mode 100644
index 0000000..65dcf68
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/cache_stores/memory.rb
@@ -0,0 +1,47 @@
+module Sass
+  module CacheStores
+    # A backend for the Sass cache using in-process memory.
+    class Memory < Base
+      # Since the {Memory} store is stored in the Sass tree's options hash,
+      # when the options get serialized as part of serializing the tree,
+      # you get crazy exponential growth in the size of the cached objects
+      # unless you don't dump the cache.
+      #
+      # @private
+      def _dump(depth)
+        ""
+      end
+
+      # If we deserialize this class, just make a new empty one.
+      #
+      # @private
+      def self._load(repr)
+        Memory.new
+      end
+
+      # Create a new, empty cache store.
+      def initialize
+        @contents = {}
+      end
+
+      # @see Base#retrieve
+      def retrieve(key, sha)
+        if @contents.has_key?(key)
+          return unless @contents[key][:sha] == sha
+          obj = @contents[key][:obj]
+          obj.respond_to?(:deep_copy) ? obj.deep_copy : obj.dup
+        end
+      end
+
+      # @see Base#store
+      def store(key, sha, obj)
+        @contents[key] = {:sha => sha, :obj => obj}
+      end
+      
+      # Destructively clear the cache.
+      def reset!
+        @contents = {}
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/cache_stores/null.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/cache_stores/null.rb
new file mode 100644
index 0000000..3bf56ca
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/cache_stores/null.rb
@@ -0,0 +1,25 @@
+module Sass
+  module CacheStores
+    # Doesn't store anything, but records what things it should have stored.
+    # This doesn't currently have any use except for testing and debugging.
+    #
+    # @private
+    class Null < Base
+      def initialize
+        @keys = {}
+      end
+
+      def _retrieve(key, version, sha)
+        nil
+      end
+      
+      def _store(key, version, sha, contents)
+        @keys[key] = true
+      end
+      
+      def was_set?(key)
+        @keys[key]
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/callbacks.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/callbacks.rb
new file mode 100644
index 0000000..f58b1ba
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/callbacks.rb
@@ -0,0 +1,66 @@
+module Sass
+  # A lightweight infrastructure for defining and running callbacks.
+  # Callbacks are defined using \{#define\_callback\} at the class level,
+  # and called using `run_#{name}` at the instance level.
+  #
+  # Clients can add callbacks by calling the generated `on_#{name}` method,
+  # and passing in a block that's run when the callback is activated.
+  #
+  # @example Define a callback
+  #   class Munger
+  #     extend Sass::Callbacks
+  #     define_callback :string_munged
+  #
+  #     def munge(str)
+  #       res = str.gsub(/[a-z]/, '\1\1')
+  #       run_string_munged str, res
+  #       res
+  #     end
+  #   end
+  #
+  # @example Use a callback
+  #   m = Munger.new
+  #   m.on_string_munged {|str, res| puts "#{str} was munged into #{res}!"}
+  #   m.munge "bar" #=> bar was munged into bbaarr!
+  module Callbacks
+    # Automatically includes {InstanceMethods}
+    # when something extends this module.
+    #
+    # @param base [Module]
+    def self.extended(base)
+      base.send(:include, InstanceMethods)
+    end
+    protected
+
+    module InstanceMethods
+      # Removes all callbacks registered against this object.
+      def clear_callbacks!
+        @_sass_callbacks = {}
+      end
+    end
+
+    # Define a callback with the given name.
+    # This will define an `on_#{name}` method
+    # that registers a block,
+    # and a `run_#{name}` method that runs that block
+    # (optionall with some arguments).
+    #
+    # @param name [Symbol] The name of the callback
+    # @return [void]
+    def define_callback(name)
+      class_eval <<RUBY, __FILE__, __LINE__ + 1
+def on_#{name}(&block)
+  @_sass_callbacks ||= {}
+  (@_sass_callbacks[#{name.inspect}] ||= []) << block
+end
+
+def run_#{name}(*args)
+  return unless @_sass_callbacks
+  return unless @_sass_callbacks[#{name.inspect}]
+  @_sass_callbacks[#{name.inspect}].each {|c| c[*args]}
+end
+private :run_#{name}
+RUBY
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/css.rb b/backends/css/gems/sass-3.2.12/lib/sass/css.rb
new file mode 100644
index 0000000..fa5532f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/css.rb
@@ -0,0 +1,409 @@
+require File.dirname(__FILE__) + '/../sass'
+require 'sass/tree/node'
+require 'sass/scss/css_parser'
+
+module Sass
+  # This class converts CSS documents into Sass or SCSS templates.
+  # It works by parsing the CSS document into a {Sass::Tree} structure,
+  # and then applying various transformations to the structure
+  # to produce more concise and idiomatic Sass/SCSS.
+  #
+  # Example usage:
+  #
+  #     Sass::CSS.new("p { color: blue }").render(:sass) #=> "p\n  color: blue"
+  #     Sass::CSS.new("p { color: blue }").render(:scss) #=> "p {\n  color: blue; }"
+  class CSS
+    # @param template [String] The CSS stylesheet.
+    #   This stylesheet can be encoded using any encoding
+    #   that can be converted to Unicode.
+    #   If the stylesheet contains an ` charset` declaration,
+    #   that overrides the Ruby encoding
+    #   (see {file:SASS_REFERENCE.md#encodings the encoding documentation})
+    # @option options :old [Boolean] (false)
+    #     Whether or not to output old property syntax
+    #     (`:color blue` as opposed to `color: blue`).
+    #     This is only meaningful when generating Sass code,
+    #     rather than SCSS.
+    # @option options :indent [String] ("  ")
+    #     The string to use for indenting each line. Defaults to two spaces.
+    def initialize(template, options = {})
+      if template.is_a? IO
+        template = template.read
+      end
+
+      @options = options.dup
+      # Backwards compatibility
+      @options[:old] = true if @options[:alternate] == false
+      @template = template
+    end
+
+    # Converts the CSS template into Sass or SCSS code.
+    #
+    # @param fmt [Symbol] `:sass` or `:scss`, designating the format to return.
+    # @return [String] The resulting Sass or SCSS code
+    # @raise [Sass::SyntaxError] if there's an error parsing the CSS template
+    def render(fmt = :sass)
+      check_encoding!
+      build_tree.send("to_#{fmt}", @options).strip + "\n"
+    rescue Sass::SyntaxError => err
+      err.modify_backtrace(:filename => @options[:filename] || '(css)')
+      raise err
+    end
+
+    # Returns the original encoding of the document,
+    # or `nil` under Ruby 1.8.
+    #
+    # @return [Encoding, nil]
+    # @raise [Encoding::UndefinedConversionError] if the source encoding
+    #   cannot be converted to UTF-8
+    # @raise [ArgumentError] if the document uses an unknown encoding with ` charset`
+    def source_encoding
+      check_encoding!
+      @original_encoding
+    end
+
+    private
+
+    def check_encoding!
+      return if @checked_encoding
+      @checked_encoding = true
+      @template, @original_encoding = Sass::Util.check_sass_encoding(@template) do |msg, line|
+        raise Sass::SyntaxError.new(msg, :line => line)
+      end
+    end
+
+    # Parses the CSS template and applies various transformations
+    #
+    # @return [Tree::Node] The root node of the parsed tree
+    def build_tree
+      root = Sass::SCSS::CssParser.new(@template, @options[:filename]).parse
+      parse_selectors    root
+      expand_commas      root
+      nest_seqs          root
+      parent_ref_rules   root
+      flatten_rules      root
+      bubble_subject     root
+      fold_commas        root
+      dump_selectors     root
+      root
+    end
+
+    # Parse all the selectors in the document and assign them to
+    # {Sass::Tree::RuleNode#parsed_rules}.
+    #
+    # @param root [Tree::Node] The parent node
+    def parse_selectors(root)
+      root.children.each do |child|
+        next parse_selectors(child) if child.is_a?(Tree::DirectiveNode)
+        next unless child.is_a?(Tree::RuleNode)
+        parser = Sass::SCSS::CssParser.new(child.rule.first, child.filename, child.line)
+        child.parsed_rules = parser.parse_selector
+      end
+    end
+
+    # Transform
+    #
+    #     foo, bar, baz
+    #       color: blue
+    #
+    # into
+    #
+    #     foo
+    #       color: blue
+    #     bar
+    #       color: blue
+    #     baz
+    #       color: blue
+    #
+    # @param root [Tree::Node] The parent node
+    def expand_commas(root)
+      root.children.map! do |child|
+        # child.parsed_rules.members.size > 1 iff the rule contains a comma
+        unless child.is_a?(Tree::RuleNode) && child.parsed_rules.members.size > 1
+          expand_commas(child) if child.is_a?(Tree::DirectiveNode)
+          next child
+        end
+        child.parsed_rules.members.map do |seq|
+          node = Tree::RuleNode.new([])
+          node.parsed_rules = make_cseq(seq)
+          node.children = child.children
+          node
+        end
+      end
+      root.children.flatten!
+    end
+
+    # Make rules use nesting so that
+    #
+    #     foo
+    #       color: green
+    #     foo bar
+    #       color: red
+    #     foo baz
+    #       color: blue
+    #
+    # becomes
+    #
+    #     foo
+    #       color: green
+    #       bar
+    #         color: red
+    #       baz
+    #         color: blue
+    #
+    # @param root [Tree::Node] The parent node
+    def nest_seqs(root)
+      current_rule = nil
+      root.children.map! do |child|
+        unless child.is_a?(Tree::RuleNode)
+          nest_seqs(child) if child.is_a?(Tree::DirectiveNode)
+          next child
+        end
+
+        seq = first_seq(child)
+        seq.members.reject! {|sseq| sseq == "\n"}
+        first, rest = seq.members.first, seq.members[1..-1]
+
+        if current_rule.nil? || first_sseq(current_rule) != first
+          current_rule = Tree::RuleNode.new([])
+          current_rule.parsed_rules = make_seq(first)
+        end
+
+        unless rest.empty?
+          child.parsed_rules = make_seq(*rest)
+          current_rule << child
+        else
+          current_rule.children += child.children
+        end
+
+        current_rule
+      end
+      root.children.compact!
+      root.children.uniq!
+
+      root.children.each {|v| nest_seqs(v)}
+    end
+
+    # Make rules use parent refs so that
+    #
+    #     foo
+    #       color: green
+    #     foo.bar
+    #       color: blue
+    #
+    # becomes
+    #
+    #     foo
+    #       color: green
+    #       &.bar
+    #         color: blue
+    #
+    # @param root [Tree::Node] The parent node
+    def parent_ref_rules(root)
+      current_rule = nil
+      root.children.map! do |child|
+        unless child.is_a?(Tree::RuleNode)
+          parent_ref_rules(child) if child.is_a?(Tree::DirectiveNode)
+          next child
+        end
+
+        sseq = first_sseq(child)
+        next child unless sseq.is_a?(Sass::Selector::SimpleSequence)
+
+        firsts, rest = [sseq.members.first], sseq.members[1..-1]
+        firsts.push rest.shift if firsts.first.is_a?(Sass::Selector::Parent)
+
+        last_simple_subject = rest.empty? && sseq.subject?
+        if current_rule.nil? || first_sseq(current_rule).members != firsts ||
+            !!first_sseq(current_rule).subject? != !!last_simple_subject
+          current_rule = Tree::RuleNode.new([])
+          current_rule.parsed_rules = make_sseq(last_simple_subject, *firsts)
+        end
+
+        unless rest.empty?
+          rest.unshift Sass::Selector::Parent.new
+          child.parsed_rules = make_sseq(sseq.subject?, *rest)
+          current_rule << child
+        else
+          current_rule.children += child.children
+        end
+
+        current_rule
+      end
+      root.children.compact!
+      root.children.uniq!
+
+      root.children.each {|v| parent_ref_rules(v)}
+    end
+
+    # Flatten rules so that
+    #
+    #     foo
+    #       bar
+    #         color: red
+    #
+    # becomes
+    #
+    #     foo bar
+    #       color: red
+    #
+    # and
+    #
+    #     foo
+    #       &.bar
+    #         color: blue
+    #
+    # becomes
+    #
+    #     foo.bar
+    #       color: blue
+    #
+    # @param root [Tree::Node] The parent node
+    def flatten_rules(root)
+      root.children.each do |child|
+        case child
+        when Tree::RuleNode
+          flatten_rule(child)
+        when Tree::DirectiveNode
+          flatten_rules(child)
+        end
+      end
+    end
+
+    # Flattens a single rule.
+    #
+    # @param rule [Tree::RuleNode] The candidate for flattening
+    # @see #flatten_rules
+    def flatten_rule(rule)
+      while rule.children.size == 1 && rule.children.first.is_a?(Tree::RuleNode)
+        child = rule.children.first
+
+        if first_simple_sel(child).is_a?(Sass::Selector::Parent)
+          rule.parsed_rules = child.parsed_rules.resolve_parent_refs(rule.parsed_rules)
+        else
+          rule.parsed_rules = make_seq(*(first_seq(rule).members + first_seq(child).members))
+        end
+
+        rule.children = child.children
+      end
+
+      flatten_rules(rule)
+    end
+
+    def bubble_subject(root)
+      root.children.each do |child|
+        bubble_subject(child) if child.is_a?(Tree::RuleNode) || child.is_a?(Tree::DirectiveNode)
+        next unless child.is_a?(Tree::RuleNode)
+        next unless child.children.all? do |c|
+          next unless c.is_a?(Tree::RuleNode)
+          first_simple_sel(c).is_a?(Sass::Selector::Parent) && first_sseq(c).subject?
+        end
+        first_sseq(child).subject = true
+        child.children.each {|c| first_sseq(c).subject = false}
+      end
+    end
+
+    # Transform
+    #
+    #     foo
+    #       bar
+    #         color: blue
+    #       baz
+    #         color: blue
+    #
+    # into
+    #
+    #     foo
+    #       bar, baz
+    #         color: blue
+    #
+    # @param rule [Tree::RuleNode] The candidate for flattening
+    def fold_commas(root)
+      prev_rule = nil
+      root.children.map! do |child|
+        unless child.is_a?(Tree::RuleNode)
+          fold_commas(child) if child.is_a?(Tree::DirectiveNode)
+          next child
+        end
+
+        if prev_rule && prev_rule.children == child.children
+          prev_rule.parsed_rules.members << first_seq(child)
+          next nil
+        end
+
+        fold_commas(child)
+        prev_rule = child
+        child
+      end
+      root.children.compact!
+    end
+
+    # Dump all the parsed {Sass::Tree::RuleNode} selectors to strings.
+    #
+    # @param root [Tree::Node] The parent node
+    def dump_selectors(root)
+      root.children.each do |child|
+        next dump_selectors(child) if child.is_a?(Tree::DirectiveNode)
+        next unless child.is_a?(Tree::RuleNode)
+        child.rule = [child.parsed_rules.to_s]
+        dump_selectors(child)
+      end
+    end
+
+    # Create a {Sass::Selector::CommaSequence}.
+    #
+    # @param seqs [Array<Sass::Selector::Sequence>]
+    # @return [Sass::Selector::CommaSequence]
+    def make_cseq(*seqs)
+      Sass::Selector::CommaSequence.new(seqs)
+    end
+
+    # Create a {Sass::Selector::CommaSequence} containing only a single
+    # {Sass::Selector::Sequence}.
+    #
+    # @param sseqs [Array<Sass::Selector::Sequence, String>]
+    # @return [Sass::Selector::CommaSequence]
+    def make_seq(*sseqs)
+      make_cseq(Sass::Selector::Sequence.new(sseqs))
+    end
+
+    # Create a {Sass::Selector::CommaSequence} containing only a single
+    # {Sass::Selector::Sequence} which in turn contains only a single
+    # {Sass::Selector::SimpleSequence}.
+    #
+    # @param subject [Boolean] Whether this is a subject selector
+    # @param sseqs [Array<Sass::Selector::Sequence, String>]
+    # @return [Sass::Selector::CommaSequence]
+    def make_sseq(subject, *sseqs)
+      make_seq(Sass::Selector::SimpleSequence.new(sseqs, subject))
+    end
+
+    # Return the first {Sass::Selector::Sequence} in a {Sass::Tree::RuleNode}.
+    #
+    # @param rule [Sass::Tree::RuleNode]
+    # @return [Sass::Selector::Sequence]
+    def first_seq(rule)
+      rule.parsed_rules.members.first
+    end
+
+    # Return the first {Sass::Selector::SimpleSequence} in a
+    # {Sass::Tree::RuleNode}.
+    #
+    # @param rule [Sass::Tree::RuleNode]
+    # @return [Sass::Selector::SimpleSequence, String]
+    def first_sseq(rule)
+      first_seq(rule).members.first
+    end
+
+    # Return the first {Sass::Selector::Simple} in a {Sass::Tree::RuleNode},
+    # unless the rule begins with a combinator.
+    #
+    # @param rule [Sass::Tree::RuleNode]
+    # @return [Sass::Selector::Simple?]
+    def first_simple_sel(rule)
+      sseq = first_sseq(rule)
+      return unless sseq.is_a?(Sass::Selector::SimpleSequence)
+      sseq.members.first
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/engine.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/engine.rb
new file mode 100644
index 0000000..5e87407
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/engine.rb
@@ -0,0 +1,928 @@
+require 'set'
+require 'digest/sha1'
+require 'sass/cache_stores'
+require 'sass/tree/node'
+require 'sass/tree/root_node'
+require 'sass/tree/rule_node'
+require 'sass/tree/comment_node'
+require 'sass/tree/prop_node'
+require 'sass/tree/directive_node'
+require 'sass/tree/media_node'
+require 'sass/tree/supports_node'
+require 'sass/tree/css_import_node'
+require 'sass/tree/variable_node'
+require 'sass/tree/mixin_def_node'
+require 'sass/tree/mixin_node'
+require 'sass/tree/trace_node'
+require 'sass/tree/content_node'
+require 'sass/tree/function_node'
+require 'sass/tree/return_node'
+require 'sass/tree/extend_node'
+require 'sass/tree/if_node'
+require 'sass/tree/while_node'
+require 'sass/tree/for_node'
+require 'sass/tree/each_node'
+require 'sass/tree/debug_node'
+require 'sass/tree/warn_node'
+require 'sass/tree/import_node'
+require 'sass/tree/charset_node'
+require 'sass/tree/visitors/base'
+require 'sass/tree/visitors/perform'
+require 'sass/tree/visitors/cssize'
+require 'sass/tree/visitors/extend'
+require 'sass/tree/visitors/convert'
+require 'sass/tree/visitors/to_css'
+require 'sass/tree/visitors/deep_copy'
+require 'sass/tree/visitors/set_options'
+require 'sass/tree/visitors/check_nesting'
+require 'sass/selector'
+require 'sass/environment'
+require 'sass/script'
+require 'sass/scss'
+require 'sass/error'
+require 'sass/importers'
+require 'sass/shared'
+require 'sass/media'
+require 'sass/supports'
+
+module Sass
+
+  # A Sass mixin or function.
+  #
+  # `name`: `String`
+  # : The name of the mixin/function.
+  #
+  # `args`: `Array<(Script::Node, Script::Node)>`
+  # : The arguments for the mixin/function.
+  #   Each element is a tuple containing the variable node of the argument
+  #   and the parse tree for the default value of the argument.
+  #
+  # `splat`: `Script::Node?`
+  # : The variable node of the splat argument for this callable, or null.
+  #
+  # `environment`: {Sass::Environment}
+  # : The environment in which the mixin/function was defined.
+  #   This is captured so that the mixin/function can have access
+  #   to local variables defined in its scope.
+  #
+  # `tree`: `Array<Tree::Node>`
+  # : The parse tree for the mixin/function.
+  #
+  # `has_content`: `Boolean`
+  # : Whether the callable accepts a content block.
+  #
+  # `type`: `String`
+  # : The user-friendly name of the type of the callable.
+  Callable = Struct.new(:name, :args, :splat, :environment, :tree, :has_content, :type)
+
+  # This class handles the parsing and compilation of the Sass template.
+  # Example usage:
+  #
+  #     template = File.load('stylesheets/sassy.sass')
+  #     sass_engine = Sass::Engine.new(template)
+  #     output = sass_engine.render
+  #     puts output
+  class Engine
+    include Sass::Util
+
+    # A line of Sass code.
+    #
+    # `text`: `String`
+    # : The text in the line, without any whitespace at the beginning or end.
+    #
+    # `tabs`: `Fixnum`
+    # : The level of indentation of the line.
+    #
+    # `index`: `Fixnum`
+    # : The line number in the original document.
+    #
+    # `offset`: `Fixnum`
+    # : The number of bytes in on the line that the text begins.
+    #   This ends up being the number of bytes of leading whitespace.
+    #
+    # `filename`: `String`
+    # : The name of the file in which this line appeared.
+    #
+    # `children`: `Array<Line>`
+    # : The lines nested below this one.
+    #
+    # `comment_tab_str`: `String?`
+    # : The prefix indentation for this comment, if it is a comment.
+    class Line < Struct.new(:text, :tabs, :index, :offset, :filename, :children, :comment_tab_str)
+      def comment?
+        text[0] == COMMENT_CHAR && (text[1] == SASS_COMMENT_CHAR || text[1] == CSS_COMMENT_CHAR)
+      end
+    end
+
+    # The character that begins a CSS property.
+    PROPERTY_CHAR  = ?:
+
+    # The character that designates the beginning of a comment,
+    # either Sass or CSS.
+    COMMENT_CHAR = ?/
+
+    # The character that follows the general COMMENT_CHAR and designates a Sass comment,
+    # which is not output as a CSS comment.
+    SASS_COMMENT_CHAR = ?/
+
+    # The character that indicates that a comment allows interpolation
+    # and should be preserved even in `:compressed` mode.
+    SASS_LOUD_COMMENT_CHAR = ?!
+
+    # The character that follows the general COMMENT_CHAR and designates a CSS comment,
+    # which is embedded in the CSS document.
+    CSS_COMMENT_CHAR = ?*
+
+    # The character used to denote a compiler directive.
+    DIRECTIVE_CHAR = ?@
+
+    # Designates a non-parsed rule.
+    ESCAPE_CHAR    = ?\\
+
+    # Designates block as mixin definition rather than CSS rules to output
+    MIXIN_DEFINITION_CHAR = ?=
+
+    # Includes named mixin declared using MIXIN_DEFINITION_CHAR
+    MIXIN_INCLUDE_CHAR    = ?+
+
+    # The regex that matches and extracts data from
+    # properties of the form `:name prop`.
+    PROPERTY_OLD = /^:([^\s=:"]+)\s*(?:\s+|$)(.*)/
+
+    # The default options for Sass::Engine.
+    # @api public
+    DEFAULT_OPTIONS = {
+      :style => :nested,
+      :load_paths => ['.'],
+      :cache => true,
+      :cache_location => './.sass-cache',
+      :syntax => :sass,
+      :filesystem_importer => Sass::Importers::Filesystem
+    }.freeze
+
+    # Converts a Sass options hash into a standard form, filling in
+    # default values and resolving aliases.
+    #
+    # @param options [{Symbol => Object}] The options hash;
+    #   see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
+    # @return [{Symbol => Object}] The normalized options hash.
+    # @private
+    def self.normalize_options(options)
+      options = DEFAULT_OPTIONS.merge(options.reject {|k, v| v.nil?})
+
+      # If the `:filename` option is passed in without an importer,
+      # assume it's using the default filesystem importer.
+      options[:importer] ||= options[:filesystem_importer].new(".") if options[:filename]
+
+      # Tracks the original filename of the top-level Sass file
+      options[:original_filename] ||= options[:filename]
+
+      options[:cache_store] ||= Sass::CacheStores::Chain.new(
+        Sass::CacheStores::Memory.new, Sass::CacheStores::Filesystem.new(options[:cache_location]))
+      # Support both, because the docs said one and the other actually worked
+      # for quite a long time.
+      options[:line_comments] ||= options[:line_numbers]
+
+      options[:load_paths] = (options[:load_paths] + Sass.load_paths).map do |p|
+        next p unless p.is_a?(String) || (defined?(Pathname) && p.is_a?(Pathname))
+        options[:filesystem_importer].new(p.to_s)
+      end
+
+      # Backwards compatibility
+      options[:property_syntax] ||= options[:attribute_syntax]
+      case options[:property_syntax]
+      when :alternate; options[:property_syntax] = :new
+      when :normal; options[:property_syntax] = :old
+      end
+
+      options
+    end
+
+    # Returns the {Sass::Engine} for the given file.
+    # This is preferable to Sass::Engine.new when reading from a file
+    # because it properly sets up the Engine's metadata,
+    # enables parse-tree caching,
+    # and infers the syntax from the filename.
+    #
+    # @param filename [String] The path to the Sass or SCSS file
+    # @param options [{Symbol => Object}] The options hash;
+    #   See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
+    # @return [Sass::Engine] The Engine for the given Sass or SCSS file.
+    # @raise [Sass::SyntaxError] if there's an error in the document.
+    def self.for_file(filename, options)
+      had_syntax = options[:syntax]
+
+      if had_syntax
+        # Use what was explicitly specificed
+      elsif filename =~ /\.scss$/
+        options.merge!(:syntax => :scss)
+      elsif filename =~ /\.sass$/
+        options.merge!(:syntax => :sass)
+      end
+
+      Sass::Engine.new(File.read(filename), options.merge(:filename => filename))
+    end
+
+    # The options for the Sass engine.
+    # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
+    #
+    # @return [{Symbol => Object}]
+    attr_reader :options
+
+    # Creates a new Engine. Note that Engine should only be used directly
+    # when compiling in-memory Sass code.
+    # If you're compiling a single Sass file from the filesystem,
+    # use \{Sass::Engine.for\_file}.
+    # If you're compiling multiple files from the filesystem,
+    # use {Sass::Plugin}.
+    #
+    # @param template [String] The Sass template.
+    #   This template can be encoded using any encoding
+    #   that can be converted to Unicode.
+    #   If the template contains an ` charset` declaration,
+    #   that overrides the Ruby encoding
+    #   (see {file:SASS_REFERENCE.md#encodings the encoding documentation})
+    # @param options [{Symbol => Object}] An options hash.
+    #   See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
+    # @see {Sass::Engine.for_file}
+    # @see {Sass::Plugin}
+    def initialize(template, options={})
+      @options = self.class.normalize_options(options)
+      @template = template
+    end
+
+    # Render the template to CSS.
+    #
+    # @return [String] The CSS
+    # @raise [Sass::SyntaxError] if there's an error in the document
+    # @raise [Encoding::UndefinedConversionError] if the source encoding
+    #   cannot be converted to UTF-8
+    # @raise [ArgumentError] if the document uses an unknown encoding with ` charset`
+    def render
+      return _render unless @options[:quiet]
+      Sass::Util.silence_sass_warnings {_render}
+    end
+    alias_method :to_css, :render
+
+    # Parses the document into its parse tree. Memoized.
+    #
+    # @return [Sass::Tree::Node] The root of the parse tree.
+    # @raise [Sass::SyntaxError] if there's an error in the document
+    def to_tree
+      @tree ||= @options[:quiet] ?
+        Sass::Util.silence_sass_warnings {_to_tree} :
+        _to_tree
+    end
+
+    # Returns the original encoding of the document,
+    # or `nil` under Ruby 1.8.
+    #
+    # @return [Encoding, nil]
+    # @raise [Encoding::UndefinedConversionError] if the source encoding
+    #   cannot be converted to UTF-8
+    # @raise [ArgumentError] if the document uses an unknown encoding with ` charset`
+    def source_encoding
+      check_encoding!
+      @original_encoding
+    end
+
+    # Gets a set of all the documents
+    # that are (transitive) dependencies of this document,
+    # not including the document itself.
+    #
+    # @return [[Sass::Engine]] The dependency documents.
+    def dependencies
+      _dependencies(Set.new, engines = Set.new)
+      Sass::Util.array_minus(engines, [self])
+    end
+
+    # Helper for \{#dependencies}.
+    #
+    # @private
+    def _dependencies(seen, engines)
+      return if seen.include?(key = [ options[:filename], @options[:importer]])
+      seen << key
+      engines << self
+      to_tree.grep(Tree::ImportNode) do |n|
+        next if n.css_import?
+        n.imported_file._dependencies(seen, engines)
+      end
+    end
+
+    private
+
+    def _render
+      rendered = _to_tree.render
+      return rendered if ruby1_8?
+      begin
+        # Try to convert the result to the original encoding,
+        # but if that doesn't work fall back on UTF-8
+        rendered = rendered.encode(source_encoding)
+      rescue EncodingError
+      end
+      rendered.gsub(Regexp.new('\A charset "(.*?)"'.encode(source_encoding)),
+        "@charset \"#{source_encoding.name}\"".encode(source_encoding))
+    end
+
+    def _to_tree
+      if (@options[:cache] || @options[:read_cache]) &&
+          @options[:filename] && @options[:importer]
+        key = sassc_key
+        sha = Digest::SHA1.hexdigest(@template)
+
+        if root = @options[:cache_store].retrieve(key, sha)
+          root.options = @options
+          return root
+        end
+      end
+
+      check_encoding!
+
+      if @options[:syntax] == :scss
+        root = Sass::SCSS::Parser.new(@template, @options[:filename]).parse
+      else
+        root = Tree::RootNode.new(@template)
+        append_children(root, tree(tabulate(@template)).first, true)
+      end
+
+      root.options = @options
+      if @options[:cache] && key && sha
+        begin
+          old_options = root.options
+          root.options = {}
+          @options[:cache_store].store(key, sha, root)
+        ensure
+          root.options = old_options
+        end
+      end
+      root
+    rescue SyntaxError => e
+      e.modify_backtrace(:filename => @options[:filename], :line => @line)
+      e.sass_template = @template
+      raise e
+    end
+
+    def sassc_key
+      @options[:cache_store].key(* options[:importer].key(@options[:filename], @options))
+    end
+
+    def check_encoding!
+      return if @checked_encoding
+      @checked_encoding = true
+      @template, @original_encoding = check_sass_encoding(@template) do |msg, line|
+        raise Sass::SyntaxError.new(msg, :line => line)
+      end
+    end
+
+    def tabulate(string)
+      tab_str = nil
+      comment_tab_str = nil
+      first = true
+      lines = []
+      string.gsub(/\r\n|\r|\n/, "\n").scan(/^[^\n]*?$/).each_with_index do |line, index|
+        index += (@options[:line] || 1)
+        if line.strip.empty?
+          lines.last.text << "\n" if lines.last && lines.last.comment?
+          next
+        end
+
+        line_tab_str = line[/^\s*/]
+        unless line_tab_str.empty?
+          if tab_str.nil?
+            comment_tab_str ||= line_tab_str
+            next if try_comment(line, lines.last, "", comment_tab_str, index)
+            comment_tab_str = nil
+          end
+
+          tab_str ||= line_tab_str
+
+          raise SyntaxError.new("Indenting at the beginning of the document is illegal.",
+            :line => index) if first
+
+          raise SyntaxError.new("Indentation can't use both tabs and spaces.",
+            :line => index) if tab_str.include?(?\s) && tab_str.include?(?\t)
+        end
+        first &&= !tab_str.nil?
+        if tab_str.nil?
+          lines << Line.new(line.strip, 0, index, 0, @options[:filename], [])
+          next
+        end
+
+        comment_tab_str ||= line_tab_str
+        if try_comment(line, lines.last, tab_str * lines.last.tabs, comment_tab_str, index)
+          next
+        else
+          comment_tab_str = nil
+        end
+
+        line_tabs = line_tab_str.scan(tab_str).size
+        if tab_str * line_tabs != line_tab_str
+          message = <<END.strip.gsub("\n", ' ')
+Inconsistent indentation: #{Sass::Shared.human_indentation line_tab_str, true} used for indentation,
+but the rest of the document was indented using #{Sass::Shared.human_indentation tab_str}.
+END
+          raise SyntaxError.new(message, :line => index)
+        end
+
+        lines << Line.new(line.strip, line_tabs, index, tab_str.size, @options[:filename], [])
+      end
+      lines
+    end
+
+    def try_comment(line, last, tab_str, comment_tab_str, index)
+      return unless last && last.comment?
+      # Nested comment stuff must be at least one whitespace char deeper
+      # than the normal indentation
+      return unless line =~ /^#{tab_str}\s/
+      unless line =~ /^(?:#{comment_tab_str})(.*)$/
+        raise SyntaxError.new(<<MSG.strip.gsub("\n", " "), :line => index)
+Inconsistent indentation:
+previous line was indented by #{Sass::Shared.human_indentation comment_tab_str},
+but this line was indented by #{Sass::Shared.human_indentation line[/^\s*/]}.
+MSG
+      end
+
+      last.comment_tab_str ||= comment_tab_str
+      last.text << "\n" << line
+      true
+    end
+
+    def tree(arr, i = 0)
+      return [], i if arr[i].nil?
+
+      base = arr[i].tabs
+      nodes = []
+      while (line = arr[i]) && line.tabs >= base
+        if line.tabs > base
+          raise SyntaxError.new("The line was indented #{line.tabs - base} levels deeper than the previous 
line.",
+            :line => line.index) if line.tabs > base + 1
+
+          nodes.last.children, i = tree(arr, i)
+        else
+          nodes << line
+          i += 1
+        end
+      end
+      return nodes, i
+    end
+
+    def build_tree(parent, line, root = false)
+      @line = line.index
+      node_or_nodes = parse_line(parent, line, root)
+
+      Array(node_or_nodes).each do |node|
+        # Node is a symbol if it's non-outputting, like a variable assignment
+        next unless node.is_a? Tree::Node
+
+        node.line = line.index
+        node.filename = line.filename
+
+        append_children(node, line.children, false)
+      end
+
+      node_or_nodes
+    end
+
+    def append_children(parent, children, root)
+      continued_rule = nil
+      continued_comment = nil
+      children.each do |line|
+        child = build_tree(parent, line, root)
+
+        if child.is_a?(Tree::RuleNode)
+          if child.continued? && child.children.empty?
+            if continued_rule
+              continued_rule.add_rules child
+            else
+              continued_rule = child
+            end
+            next
+          elsif continued_rule
+            continued_rule.add_rules child
+            continued_rule.children = child.children
+            continued_rule, child = nil, continued_rule
+          end
+        elsif continued_rule
+          continued_rule = nil
+        end
+
+        if child.is_a?(Tree::CommentNode) && child.type == :silent
+          if continued_comment &&
+              child.line == continued_comment.line +
+              continued_comment.lines + 1
+            continued_comment.value += ["\n"] + child.value
+            next
+          end
+
+          continued_comment = child
+        end
+
+        check_for_no_children(child)
+        validate_and_append_child(parent, child, line, root)
+      end
+
+      parent
+    end
+
+    def validate_and_append_child(parent, child, line, root)
+      case child
+      when Array
+        child.each {|c| validate_and_append_child(parent, c, line, root)}
+      when Tree::Node
+        parent << child
+      end
+    end
+
+    def check_for_no_children(node)
+      return unless node.is_a?(Tree::RuleNode) && node.children.empty?
+      Sass::Util.sass_warn(<<WARNING.strip)
+WARNING on line #{node.line}#{" of #{node.filename}" if node.filename}:
+This selector doesn't have any properties and will not be rendered.
+WARNING
+    end
+
+    def parse_line(parent, line, root)
+      case line.text[0]
+      when PROPERTY_CHAR
+        if line.text[1] == PROPERTY_CHAR ||
+            (@options[:property_syntax] == :new &&
+             line.text =~ PROPERTY_OLD && $2.empty?)
+          # Support CSS3-style pseudo-elements,
+          # which begin with ::,
+          # as well as pseudo-classes
+          # if we're using the new property syntax
+          Tree::RuleNode.new(parse_interp(line.text))
+        else
+          name, value = line.text.scan(PROPERTY_OLD)[0]
+          raise SyntaxError.new("Invalid property: \"#{line.text}\".",
+            :line => @line) if name.nil? || value.nil?
+          parse_property(name, parse_interp(name), value, :old, line)
+        end
+      when ?$
+        parse_variable(line)
+      when COMMENT_CHAR
+        parse_comment(line)
+      when DIRECTIVE_CHAR
+        parse_directive(parent, line, root)
+      when ESCAPE_CHAR
+        Tree::RuleNode.new(parse_interp(line.text[1..-1]))
+      when MIXIN_DEFINITION_CHAR
+        parse_mixin_definition(line)
+      when MIXIN_INCLUDE_CHAR
+        if line.text[1].nil? || line.text[1] == ?\s
+          Tree::RuleNode.new(parse_interp(line.text))
+        else
+          parse_mixin_include(line, root)
+        end
+      else
+        parse_property_or_rule(line)
+      end
+    end
+
+    def parse_property_or_rule(line)
+      scanner = Sass::Util::MultibyteStringScanner.new(line.text)
+      hack_char = scanner.scan(/[:\*\.]|\#(?!\{)/)
+      parser = Sass::SCSS::Parser.new(scanner, @options[:filename], @line)
+
+      unless res = parser.parse_interp_ident
+        return Tree::RuleNode.new(parse_interp(line.text))
+      end
+      res.unshift(hack_char) if hack_char
+      if comment = scanner.scan(Sass::SCSS::RX::COMMENT)
+        res << comment
+      end
+
+      name = line.text[0...scanner.pos]
+      if scanner.scan(/\s*:(?:\s|$)/)
+        parse_property(name, res, scanner.rest, :new, line)
+      else
+        res.pop if comment
+        Tree::RuleNode.new(res + parse_interp(scanner.rest))
+      end
+    end
+
+    def parse_property(name, parsed_name, value, prop, line)
+      if value.strip.empty?
+        expr = Sass::Script::String.new("")
+      else
+        expr = parse_script(value, :offset => line.offset + line.text.index(value))
+      end
+      node = Tree::PropNode.new(parse_interp(name), expr, prop)
+      if value.strip.empty? && line.children.empty?
+        raise SyntaxError.new(
+          "Invalid property: \"#{node.declaration}\" (no value)." +
+          node.pseudo_class_selector_message)
+      end
+
+      node
+    end
+
+    def parse_variable(line)
+      name, value, default = line.text.scan(Script::MATCH)[0]
+      raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath variable declarations.",
+        :line => @line + 1) unless line.children.empty?
+      raise SyntaxError.new("Invalid variable: \"#{line.text}\".",
+        :line => @line) unless name && value
+
+      expr = parse_script(value, :offset => line.offset + line.text.index(value))
+
+      Tree::VariableNode.new(name, expr, default)
+    end
+
+    def parse_comment(line)
+      if line.text[1] == CSS_COMMENT_CHAR || line.text[1] == SASS_COMMENT_CHAR
+        silent = line.text[1] == SASS_COMMENT_CHAR
+        loud = !silent && line.text[2] == SASS_LOUD_COMMENT_CHAR
+        if silent
+          value = [line.text]
+        else
+          value = self.class.parse_interp(line.text, line.index, line.offset, :filename => @filename)
+        end
+        value = with_extracted_values(value) do |str|
+          str = str.gsub(/^#{line.comment_tab_str}/m, '')[2..-1] # get rid of // or /*
+          format_comment_text(str, silent)
+        end
+        type = if silent then :silent elsif loud then :loud else :normal end
+        Tree::CommentNode.new(value, type)
+      else
+        Tree::RuleNode.new(parse_interp(line.text))
+      end
+    end
+
+    def parse_directive(parent, line, root)
+      directive, whitespace, value = line.text[1..-1].split(/(\s+)/, 2)
+      offset = directive.size + whitespace.size + 1 if whitespace
+
+      # If value begins with url( or ",
+      # it's a CSS @import rule and we don't want to touch it.
+      case directive
+      when 'import'
+        parse_import(line, value, offset)
+      when 'mixin'
+        parse_mixin_definition(line)
+      when 'content'
+        parse_content_directive(line)
+      when 'include'
+        parse_mixin_include(line, root)
+      when 'function'
+        parse_function(line, root)
+      when 'for'
+        parse_for(line, root, value)
+      when 'each'
+        parse_each(line, root, value)
+      when 'else'
+        parse_else(parent, line, value)
+      when 'while'
+        raise SyntaxError.new("Invalid while directive '@while': expected expression.") unless value
+        Tree::WhileNode.new(parse_script(value, :offset => offset))
+      when 'if'
+        raise SyntaxError.new("Invalid if directive '@if': expected expression.") unless value
+        Tree::IfNode.new(parse_script(value, :offset => offset))
+      when 'debug'
+        raise SyntaxError.new("Invalid debug directive '@debug': expected expression.") unless value
+        raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath debug directives.",
+          :line => @line + 1) unless line.children.empty?
+        offset = line.offset + line.text.index(value).to_i
+        Tree::DebugNode.new(parse_script(value, :offset => offset))
+      when 'extend'
+        raise SyntaxError.new("Invalid extend directive '@extend': expected expression.") unless value
+        raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath extend directives.",
+          :line => @line + 1) unless line.children.empty?
+        optional = !!value.gsub!(/\s+#{Sass::SCSS::RX::OPTIONAL}$/, '')
+        offset = line.offset + line.text.index(value).to_i
+        Tree::ExtendNode.new(parse_interp(value, offset), optional)
+      when 'warn'
+        raise SyntaxError.new("Invalid warn directive '@warn': expected expression.") unless value
+        raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath warn directives.",
+          :line => @line + 1) unless line.children.empty?
+        offset = line.offset + line.text.index(value).to_i
+        Tree::WarnNode.new(parse_script(value, :offset => offset))
+      when 'return'
+        raise SyntaxError.new("Invalid @return: expected expression.") unless value
+        raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath return directives.",
+          :line => @line + 1) unless line.children.empty?
+        offset = line.offset + line.text.index(value).to_i
+        Tree::ReturnNode.new(parse_script(value, :offset => offset))
+      when 'charset'
+        name = value && value[/\A(["'])(.*)\1\Z/, 2] #"
+        raise SyntaxError.new("Invalid charset directive '@charset': expected string.") unless name
+        raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath charset directives.",
+          :line => @line + 1) unless line.children.empty?
+        Tree::CharsetNode.new(name)
+      when 'media'
+        parser = Sass::SCSS::Parser.new(value, @options[:filename], @line)
+        Tree::MediaNode.new(parser.parse_media_query_list.to_a)
+      else
+        unprefixed_directive = directive.gsub(/^-[a-z0-9]+-/i, '')
+        if unprefixed_directive == 'supports'
+          parser = Sass::SCSS::Parser.new(value, @options[:filename], @line)
+          return Tree::SupportsNode.new(directive, parser.parse_supports_condition)
+        end
+
+        Tree::DirectiveNode.new(
+          value.nil? ? ["@#{directive}"] : ["@#{directive} "] + parse_interp(value, offset))
+      end
+    end
+
+    def parse_for(line, root, text)
+      var, from_expr, to_name, to_expr = text.scan(/^([^\s]+)\s+from\s+(.+)\s+(to|through)\s+(.+)$/).first
+
+      if var.nil? # scan failed, try to figure out why for error message
+        if text !~ /^[^\s]+/
+          expected = "variable name"
+        elsif text !~ /^[^\s]+\s+from\s+.+/
+          expected = "'from <expr>'"
+        else
+          expected = "'to <expr>' or 'through <expr>'"
+        end
+        raise SyntaxError.new("Invalid for directive '@for #{text}': expected #{expected}.")
+      end
+      raise SyntaxError.new("Invalid variable \"#{var}\".") unless var =~ Script::VALIDATE
+
+      var = var[1..-1]
+      parsed_from = parse_script(from_expr, :offset => line.offset + line.text.index(from_expr))
+      parsed_to = parse_script(to_expr, :offset => line.offset + line.text.index(to_expr))
+      Tree::ForNode.new(var, parsed_from, parsed_to, to_name == 'to')
+    end
+
+    def parse_each(line, root, text)
+      var, list_expr = text.scan(/^([^\s]+)\s+in\s+(.+)$/).first
+
+      if var.nil? # scan failed, try to figure out why for error message
+        if text !~ /^[^\s]+/
+          expected = "variable name"
+        elsif text !~ /^[^\s]+\s+from\s+.+/
+          expected = "'in <expr>'"
+        end
+        raise SyntaxError.new("Invalid for directive '@each #{text}': expected #{expected}.")
+      end
+      raise SyntaxError.new("Invalid variable \"#{var}\".") unless var =~ Script::VALIDATE
+
+      var = var[1..-1]
+      parsed_list = parse_script(list_expr, :offset => line.offset + line.text.index(list_expr))
+      Tree::EachNode.new(var, parsed_list)
+    end
+
+    def parse_else(parent, line, text)
+      previous = parent.children.last
+      raise SyntaxError.new("@else must come after @if.") unless previous.is_a?(Tree::IfNode)
+
+      if text
+        if text !~ /^if\s+(.+)/
+          raise SyntaxError.new("Invalid else directive '@else #{text}': expected 'if <expr>'.")
+        end
+        expr = parse_script($1, :offset => line.offset + line.text.index($1))
+      end
+
+      node = Tree::IfNode.new(expr)
+      append_children(node, line.children, false)
+      previous.add_else node
+      nil
+    end
+
+    def parse_import(line, value, offset)
+      raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath import directives.",
+        :line => @line + 1) unless line.children.empty?
+
+      scanner = Sass::Util::MultibyteStringScanner.new(value)
+      values = []
+
+      loop do
+        unless node = parse_import_arg(scanner, offset + scanner.pos)
+          raise SyntaxError.new("Invalid @import: expected file to import, was #{scanner.rest.inspect}",
+            :line => @line)
+        end
+        values << node
+        break unless scanner.scan(/,\s*/)
+      end
+
+      if scanner.scan(/;/)
+        raise SyntaxError.new("Invalid @import: expected end of line, was \";\".",
+          :line => @line)
+      end
+
+      return values
+    end
+
+    def parse_import_arg(scanner, offset)
+      return if scanner.eos?
+
+      if scanner.match?(/url\(/i)
+        script_parser = Sass::Script::Parser.new(scanner, @line, offset, @options)
+        str = script_parser.parse_string
+        media_parser = Sass::SCSS::Parser.new(scanner, @options[:filename], @line)
+        media = media_parser.parse_media_query_list
+        return Tree::CssImportNode.new(str, media.to_a)
+      end
+
+      unless str = scanner.scan(Sass::SCSS::RX::STRING)
+        return Tree::ImportNode.new(scanner.scan(/[^,;]+/))
+      end
+
+      val = scanner[1] || scanner[2]
+      scanner.scan(/\s*/)
+      if !scanner.match?(/[,;]|$/)
+        media_parser = Sass::SCSS::Parser.new(scanner, @options[:filename], @line)
+        media = media_parser.parse_media_query_list
+        Tree::CssImportNode.new(str || uri, media.to_a)
+      elsif val =~ /^(https?:)?\/\//
+        Tree::CssImportNode.new("url(#{val})")
+      else
+        Tree::ImportNode.new(val)
+      end
+    end
+
+    MIXIN_DEF_RE = /^(?:=|@mixin)\s*(#{Sass::SCSS::RX::IDENT})(.*)$/
+    def parse_mixin_definition(line)
+      name, arg_string = line.text.scan(MIXIN_DEF_RE).first
+      raise SyntaxError.new("Invalid mixin \"#{line.text[1..-1]}\".") if name.nil?
+
+      offset = line.offset + line.text.size - arg_string.size
+      args, splat = Script::Parser.new(arg_string.strip, @line, offset, @options).
+        parse_mixin_definition_arglist
+      Tree::MixinDefNode.new(name, args, splat)
+    end
+
+    CONTENT_RE = /^ content\s*(.+)?$/
+    def parse_content_directive(line)
+      trailing = line.text.scan(CONTENT_RE).first.first
+      raise SyntaxError.new("Invalid content directive. Trailing characters found: \"#{trailing}\".") unless 
trailing.nil?
+      raise SyntaxError.new("Illegal nesting: Nothing may be nested beneath @content directives.",
+        :line => line.index + 1) unless line.children.empty?
+      Tree::ContentNode.new
+    end
+
+    MIXIN_INCLUDE_RE = /^(?:\+|@include)\s*(#{Sass::SCSS::RX::IDENT})(.*)$/
+    def parse_mixin_include(line, root)
+      name, arg_string = line.text.scan(MIXIN_INCLUDE_RE).first
+      raise SyntaxError.new("Invalid mixin include \"#{line.text}\".") if name.nil?
+
+      offset = line.offset + line.text.size - arg_string.size
+      args, keywords, splat = Script::Parser.new(arg_string.strip, @line, offset, @options).
+        parse_mixin_include_arglist
+      Tree::MixinNode.new(name, args, keywords, splat)
+    end
+
+    FUNCTION_RE = /^ function\s*(#{Sass::SCSS::RX::IDENT})(.*)$/
+    def parse_function(line, root)
+      name, arg_string = line.text.scan(FUNCTION_RE).first
+      raise SyntaxError.new("Invalid function definition \"#{line.text}\".") if name.nil?
+
+      offset = line.offset + line.text.size - arg_string.size
+      args, splat = Script::Parser.new(arg_string.strip, @line, offset, @options).
+        parse_function_definition_arglist
+      Tree::FunctionNode.new(name, args, splat)
+    end
+
+    def parse_script(script, options = {})
+      line = options[:line] || @line
+      offset = options[:offset] || 0
+      Script.parse(script, line, offset, @options)
+    end
+
+    def format_comment_text(text, silent)
+      content = text.split("\n")
+
+      if content.first && content.first.strip.empty?
+        removed_first = true
+        content.shift
+      end
+
+      return silent ? "//" : "/* */" if content.empty?
+      content.last.gsub!(%r{ ?\*/ *$}, '')
+      content.map! {|l| l.gsub!(/^\*( ?)/, '\1') || (l.empty? ? "" : " ") + l}
+      content.first.gsub!(/^ /, '') unless removed_first
+      if silent
+        "//" + content.join("\n//")
+      else
+        # The #gsub fixes the case of a trailing */
+        "/*" + content.join("\n *").gsub(/ \*\Z/, '') + " */"
+      end
+    end
+
+    def parse_interp(text, offset = 0)
+      self.class.parse_interp(text, @line, offset, :filename => @filename)
+    end
+
+    # It's important that this have strings (at least)
+    # at the beginning, the end, and between each Script::Node.
+    #
+    # @private
+    def self.parse_interp(text, line, offset, options)
+      res = []
+      rest = Sass::Shared.handle_interpolation text do |scan|
+        escapes = scan[2].size
+        res << scan.matched[0...-2 - escapes]
+        if escapes % 2 == 1
+          res << "\\" * (escapes - 1) << '#{'
+        else
+          res << "\\" * [0, escapes - 1].max
+          res << Script::Parser.new(
+            scan, line, offset + scan.pos - scan.matched_size, options).
+            parse_interpolated
+        end
+      end
+      res << rest
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/environment.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/environment.rb
new file mode 100644
index 0000000..ec1800c
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/environment.rb
@@ -0,0 +1,101 @@
+require 'set'
+
+module Sass
+  # The lexical environment for SassScript.
+  # This keeps track of variable, mixin, and function definitions.
+  #
+  # A new environment is created for each level of Sass nesting.
+  # This allows variables to be lexically scoped.
+  # The new environment refers to the environment in the upper scope,
+  # so it has access to variables defined in enclosing scopes,
+  # but new variables are defined locally.
+  #
+  # Environment also keeps track of the {Engine} options
+  # so that they can be made available to {Sass::Script::Functions}.
+  class Environment
+    # The enclosing environment,
+    # or nil if this is the global environment.
+    #
+    # @return [Environment]
+    attr_reader :parent
+    attr_reader :options
+    attr_writer :caller
+    attr_writer :content
+
+    # @param options [{Symbol => Object}] The options hash. See
+    #   {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
+    # @param parent [Environment] See \{#parent}
+    def initialize(parent = nil, options = nil)
+      @parent = parent
+      @options = options || (parent && parent.options) || {}
+    end
+
+    # The environment of the caller of this environment's mixin or function.
+    # @return {Environment?}
+    def caller
+      @caller || (@parent && @parent.caller)
+    end
+
+    # The content passed to this environmnet. This is naturally only set
+    # for mixin body environments with content passed in.
+    # @return {Environment?}
+    def content
+      @content || (@parent && @parent.content)
+    end
+
+    private
+
+    class << self
+      private
+      UNDERSCORE, DASH = '_', '-'
+
+      # Note: when updating this,
+      # update sass/yard/inherited_hash.rb as well.
+      def inherited_hash(name)
+        class_eval <<RUBY, __FILE__, __LINE__ + 1
+          def #{name}(name)
+            _#{name}(name.tr(UNDERSCORE, DASH))
+          end
+
+          def _#{name}(name)
+            (@#{name}s && @#{name}s[name]) || @parent && @parent._#{name}(name)
+          end
+          protected :_#{name}
+
+          def set_#{name}(name, value)
+            name = name.tr(UNDERSCORE, DASH)
+            @#{name}s[name] = value unless try_set_#{name}(name, value)
+          end
+
+          def try_set_#{name}(name, value)
+            @#{name}s ||= {}
+            if @#{name}s.include?(name)
+              @#{name}s[name] = value
+              true
+            elsif @parent
+              @parent.try_set_#{name}(name, value)
+            else
+              false
+            end
+          end
+          protected :try_set_#{name}
+
+          def set_local_#{name}(name, value)
+            @#{name}s ||= {}
+            @#{name}s[name.tr(UNDERSCORE, DASH)] = value
+          end
+RUBY
+      end
+    end
+
+    # variable
+    # Script::Literal
+    inherited_hash :var
+    # mixin
+    # Sass::Callable
+    inherited_hash :mixin
+    # function
+    # Sass::Callable
+    inherited_hash :function
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/error.rb b/backends/css/gems/sass-3.2.12/lib/sass/error.rb
new file mode 100644
index 0000000..c72bfe6
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/error.rb
@@ -0,0 +1,201 @@
+module Sass
+  # An exception class that keeps track of
+  # the line of the Sass template it was raised on
+  # and the Sass file that was being parsed (if applicable).
+  #
+  # All Sass errors are raised as {Sass::SyntaxError}s.
+  #
+  # When dealing with SyntaxErrors,
+  # it's important to provide filename and line number information.
+  # This will be used in various error reports to users, including backtraces;
+  # see \{#sass\_backtrace} for details.
+  #
+  # Some of this information is usually provided as part of the constructor.
+  # New backtrace entries can be added with \{#add\_backtrace},
+  # which is called when an exception is raised between files (e.g. with ` import`).
+  #
+  # Often, a chunk of code will all have similar backtrace information -
+  # the same filename or even line.
+  # It may also be useful to have a default line number set.
+  # In those situations, the default values can be used
+  # by omitting the information on the original exception,
+  # and then calling \{#modify\_backtrace} in a wrapper `rescue`.
+  # When doing this, be sure that all exceptions ultimately end up
+  # with the information filled in.
+  class SyntaxError < StandardError
+    # The backtrace of the error within Sass files.
+    # This is an array of hashes containing information for a single entry.
+    # The hashes have the following keys:
+    #
+    # `:filename`
+    # : The name of the file in which the exception was raised,
+    #   or `nil` if no filename is available.
+    #
+    # `:mixin`
+    # : The name of the mixin in which the exception was raised,
+    #   or `nil` if it wasn't raised in a mixin.
+    #
+    # `:line`
+    # : The line of the file on which the error occurred. Never nil.
+    #
+    # This information is also included in standard backtrace format
+    # in the output of \{#backtrace}.
+    #
+    # @return [Aray<{Symbol => Object>}]
+    attr_accessor :sass_backtrace
+
+    # The text of the template where this error was raised.
+    #
+    # @return [String]
+    attr_accessor :sass_template
+
+    # @param msg [String] The error message
+    # @param attrs [{Symbol => Object}] The information in the backtrace entry.
+    #   See \{#sass\_backtrace}
+    def initialize(msg, attrs = {})
+      @message = msg
+      @sass_backtrace = []
+      add_backtrace(attrs)
+    end
+
+    # The name of the file in which the exception was raised.
+    # This could be `nil` if no filename is available.
+    #
+    # @return [String, nil]
+    def sass_filename
+      sass_backtrace.first[:filename]
+    end
+
+    # The name of the mixin in which the error occurred.
+    # This could be `nil` if the error occurred outside a mixin.
+    #
+    # @return [Fixnum]
+    def sass_mixin
+      sass_backtrace.first[:mixin]
+    end
+
+    # The line of the Sass template on which the error occurred.
+    #
+    # @return [Fixnum]
+    def sass_line
+      sass_backtrace.first[:line]
+    end
+
+    # Adds an entry to the exception's Sass backtrace.
+    #
+    # @param attrs [{Symbol => Object}] The information in the backtrace entry.
+    #   See \{#sass\_backtrace}
+    def add_backtrace(attrs)
+      sass_backtrace << attrs.reject {|k, v| v.nil?}
+    end
+
+    # Modify the top Sass backtrace entries
+    # (that is, the most deeply nested ones)
+    # to have the given attributes.
+    #
+    # Specifically, this goes through the backtrace entries
+    # from most deeply nested to least,
+    # setting the given attributes for each entry.
+    # If an entry already has one of the given attributes set,
+    # the pre-existing attribute takes precedence
+    # and is not used for less deeply-nested entries
+    # (even if they don't have that attribute set).
+    #
+    # @param attrs [{Symbol => Object}] The information to add to the backtrace entry.
+    #   See \{#sass\_backtrace}
+    def modify_backtrace(attrs)
+      attrs = attrs.reject {|k, v| v.nil?}
+      # Move backwards through the backtrace
+      (0...sass_backtrace.size).to_a.reverse.each do |i|
+        entry = sass_backtrace[i]
+        sass_backtrace[i] = attrs.merge(entry)
+        attrs.reject! {|k, v| entry.include?(k)}
+        break if attrs.empty?
+      end
+    end
+
+    # @return [String] The error message
+    def to_s
+      @message
+    end
+
+    # Returns the standard exception backtrace,
+    # including the Sass backtrace.
+    #
+    # @return [Array<String>]
+    def backtrace
+      return nil if super.nil?
+      return super if sass_backtrace.all? {|h| h.empty?}
+      sass_backtrace.map do |h|
+        "#{h[:filename] || "(sass)"}:#{h[:line]}" +
+          (h[:mixin] ? ":in `#{h[:mixin]}'" : "")
+      end + super
+    end
+
+    # Returns a string representation of the Sass backtrace.
+    #
+    # @param default_filename [String] The filename to use for unknown files
+    # @see #sass_backtrace
+    # @return [String]
+    def sass_backtrace_str(default_filename = "an unknown file")
+      lines = self.message.split("\n")
+      msg = lines[0] + lines[1..-1].
+        map {|l| "\n" + (" " * "Syntax error: ".size) + l}.join
+      "Syntax error: #{msg}" +
+        Sass::Util.enum_with_index(sass_backtrace).map do |entry, i|
+        "\n        #{i == 0 ? "on" : "from"} line #{entry[:line]}" +
+          " of #{entry[:filename] || default_filename}" +
+          (entry[:mixin] ? ", in `#{entry[:mixin]}'" : "")
+      end.join
+    end
+
+    class << self
+      # Returns an error report for an exception in CSS format.
+      #
+      # @param e [Exception]
+      # @param options [{Symbol => Object}] The options passed to {Sass::Engine#initialize}
+      # @return [String] The error report
+      # @raise [Exception] `e`, if the
+      #   {file:SASS_REFERENCE.md#full_exception-option `:full_exception`} option
+      #   is set to false.
+      def exception_to_css(e, options)
+        raise e unless options[:full_exception]
+
+        header = header_string(e, options)
+
+        <<END
+/*
+#{header.gsub("*/", "*\\/")}
+
+Backtrace:\n#{e.backtrace.join("\n").gsub("*/", "*\\/")}
+*/
+body:before {
+  white-space: pre;
+  font-family: monospace;
+  content: "#{header.gsub('"', '\"').gsub("\n", '\\A ')}"; }
+END
+      end
+
+      private
+
+      def header_string(e, options)
+        unless e.is_a?(Sass::SyntaxError) && e.sass_line && e.sass_template
+          return "#{e.class}: #{e.message}"
+        end
+
+        line_offset = options[:line] || 1
+        line_num = e.sass_line + 1 - line_offset
+        min = [line_num - 6, 0].max
+        section = e.sass_template.rstrip.split("\n")[min ... line_num + 5]
+        return e.sass_backtrace_str if section.nil? || section.empty?
+
+        e.sass_backtrace_str + "\n\n" + Sass::Util.enum_with_index(section).
+          map {|line, i| "#{line_offset + min + i}: #{line}"}.join("\n")
+      end
+    end
+  end
+
+  # The class for Sass errors that are raised due to invalid unit conversions
+  # in SassScript.
+  class UnitConversionError < SyntaxError; end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/exec.rb b/backends/css/gems/sass-3.2.12/lib/sass/exec.rb
new file mode 100644
index 0000000..5096ecb
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/exec.rb
@@ -0,0 +1,707 @@
+require 'optparse'
+require 'fileutils'
+
+module Sass
+  # This module handles the various Sass executables (`sass` and `sass-convert`).
+  module Exec
+    # An abstract class that encapsulates the executable code for all three executables.
+    class Generic
+      # @param args [Array<String>] The command-line arguments
+      def initialize(args)
+        @args = args
+        @options = {}
+      end
+
+      # Parses the command-line arguments and runs the executable.
+      # Calls `Kernel#exit` at the end, so it never returns.
+      #
+      # @see #parse
+      def parse!
+        begin
+          parse
+        rescue Exception => e
+          raise e if @options[:trace] || e.is_a?(SystemExit)
+
+          $stderr.print "#{e.class}: " unless e.class == RuntimeError
+          $stderr.puts "#{e.message}"
+          $stderr.puts "  Use --trace for backtrace."
+          exit 1
+        end
+        exit 0
+      end
+
+      # Parses the command-line arguments and runs the executable.
+      # This does not handle exceptions or exit the program.
+      #
+      # @see #parse!
+      def parse
+        @opts = OptionParser.new(&method(:set_opts))
+        @opts.parse!(@args)
+
+        process_result
+
+        @options
+      end
+
+      # @return [String] A description of the executable
+      def to_s
+        @opts.to_s
+      end
+
+      protected
+
+      # Finds the line of the source template
+      # on which an exception was raised.
+      #
+      # @param exception [Exception] The exception
+      # @return [String] The line number
+      def get_line(exception)
+        # SyntaxErrors have weird line reporting
+        # when there's trailing whitespace
+        return (exception.message.scan(/:(\d+)/).first || ["??"]).first if exception.is_a?(::SyntaxError)
+        (exception.backtrace[0].scan(/:(\d+)/).first || ["??"]).first
+      end
+
+      # Tells optparse how to parse the arguments
+      # available for all executables.
+      #
+      # This is meant to be overridden by subclasses
+      # so they can add their own options.
+      #
+      # @param opts [OptionParser]
+      def set_opts(opts)
+        opts.on('-s', '--stdin', :NONE, 'Read input from standard input instead of an input file') do
+          @options[:input] = $stdin
+        end
+
+        opts.on('--trace', :NONE, 'Show a full traceback on error') do
+          @options[:trace] = true
+        end
+
+        opts.on('--unix-newlines', 'Use Unix-style newlines in written files.') do
+          @options[:unix_newlines] = true if ::Sass::Util.windows?
+        end
+
+        opts.on_tail("-?", "-h", "--help", "Show this message") do
+          puts opts
+          exit
+        end
+
+        opts.on_tail("-v", "--version", "Print version") do
+          puts("Sass #{::Sass.version[:string]}")
+          exit
+        end
+      end
+
+      # Processes the options set by the command-line arguments.
+      # In particular, sets ` options[:input]` and ` options[:output]`
+      # to appropriate IO streams.
+      #
+      # This is meant to be overridden by subclasses
+      # so they can run their respective programs.
+      def process_result
+        input, output = @options[:input], @options[:output]
+        args = @args.dup
+        input ||=
+          begin
+            filename = args.shift
+            @options[:filename] = filename
+            open_file(filename) || $stdin
+          end
+        output ||= args.shift || $stdout
+
+        @options[:input], @options[:output] = input, output
+      end
+
+      COLORS = { :red => 31, :green => 32, :yellow => 33 }
+
+      # Prints a status message about performing the given action,
+      # colored using the given color (via terminal escapes) if possible.
+      #
+      # @param name [#to_s] A short name for the action being performed.
+      #   Shouldn't be longer than 11 characters.
+      # @param color [Symbol] The name of the color to use for this action.
+      #   Can be `:red`, `:green`, or `:yellow`.
+      def puts_action(name, color, arg)
+        return if @options[:for_engine][:quiet]
+        printf color(color, "%11s %s\n"), name, arg
+        STDOUT.flush
+      end
+
+      # Same as \{Kernel.puts}, but doesn't print anything if the `--quiet` option is set.
+      #
+      # @param args [Array] Passed on to \{Kernel.puts}
+      def puts(*args)
+        return if @options[:for_engine][:quiet]
+        Kernel.puts(*args)
+      end
+
+      # Wraps the given string in terminal escapes
+      # causing it to have the given color.
+      # If terminal esapes aren't supported on this platform,
+      # just returns the string instead.
+      #
+      # @param color [Symbol] The name of the color to use.
+      #   Can be `:red`, `:green`, or `:yellow`.
+      # @param str [String] The string to wrap in the given color.
+      # @return [String] The wrapped string.
+      def color(color, str)
+        raise "[BUG] Unrecognized color #{color}" unless COLORS[color]
+
+        # Almost any real Unix terminal will support color,
+        # so we just filter for Windows terms (which don't set TERM)
+        # and not-real terminals, which aren't ttys.
+        return str if ENV["TERM"].nil? || ENV["TERM"].empty? || !STDOUT.tty?
+        return "\e[#{COLORS[color]}m#{str}\e[0m"
+      end
+
+      def write_output(text, destination)
+        if destination.is_a?(String)
+          open_file(destination, 'w') {|file| file.write(text)}
+        else
+          destination.write(text)
+        end
+      end
+
+      private
+
+      def open_file(filename, flag = 'r')
+        return if filename.nil?
+        flag = 'wb' if @options[:unix_newlines] && flag == 'w'
+        file = File.open(filename, flag)
+        return file unless block_given?
+        yield file
+        file.close
+      end
+
+      def handle_load_error(err)
+        dep = err.message[/^no such file to load -- (.*)/, 1]
+        raise err if @options[:trace] || dep.nil? || dep.empty?
+        $stderr.puts <<MESSAGE
+Required dependency #{dep} not found!
+    Run "gem install #{dep}" to get it.
+  Use --trace for backtrace.
+MESSAGE
+        exit 1
+      end
+    end
+
+    # The `sass` executable.
+    class Sass < Generic
+      attr_reader :default_syntax
+
+      # @param args [Array<String>] The command-line arguments
+      def initialize(args)
+        super
+        @options[:for_engine] = {
+          :load_paths => ['.'] + (ENV['SASSPATH'] || '').split(File::PATH_SEPARATOR)
+        }
+        @default_syntax = :sass
+      end
+
+      protected
+
+      # Tells optparse how to parse the arguments.
+      #
+      # @param opts [OptionParser]
+      def set_opts(opts)
+        super
+
+        opts.banner = <<END
+Usage: #{default_syntax} [options] [INPUT] [OUTPUT]
+
+Description:
+  Converts SCSS or Sass files to CSS.
+
+Options:
+END
+
+        if @default_syntax == :sass
+          opts.on('--scss',
+                  'Use the CSS-superset SCSS syntax.') do
+            @options[:for_engine][:syntax] = :scss
+          end
+        else
+          opts.on('--sass',
+                  'Use the Indented syntax.') do
+            @options[:for_engine][:syntax] = :sass
+          end
+        end
+        opts.on('--watch', 'Watch files or directories for changes.',
+                           'The location of the generated CSS can be set using a colon:',
+                           "  #{ default_syntax} --watch input #{ default_syntax}:output.css",
+                           "  #{ default_syntax} --watch input-dir:output-dir") do
+          @options[:watch] = true
+        end
+        opts.on('--update', 'Compile files or directories to CSS.',
+                            'Locations are set like --watch.') do
+          @options[:update] = true
+        end
+        opts.on('--stop-on-error', 'If a file fails to compile, exit immediately.',
+                                   'Only meaningful for --watch and --update.') do
+          @options[:stop_on_error] = true
+        end
+        opts.on('--poll', 'Check for file changes manually, rather than relying on the OS.',
+                          'Only meaningful for --watch.') do
+          @options[:poll] = true
+        end
+        opts.on('-f', '--force', 'Recompile all Sass files, even if the CSS file is newer.',
+                                 'Only meaningful for --update.') do
+          @options[:force] = true
+        end
+        opts.on('-c', '--check', "Just check syntax, don't evaluate.") do
+          require 'stringio'
+          @options[:check_syntax] = true
+          @options[:output] = StringIO.new
+        end
+        opts.on('-t', '--style NAME',
+                'Output style. Can be nested (default), compact, compressed, or expanded.') do |name|
+          @options[:for_engine][:style] = name.to_sym
+        end
+        opts.on('--precision NUMBER_OF_DIGITS', Integer,
+                'How many digits of precision to use when outputting decimal numbers. Defaults to 3.') do 
|precision|
+          ::Sass::Script::Number.precision = precision
+        end
+        opts.on('-q', '--quiet', 'Silence warnings and status messages during compilation.') do
+          @options[:for_engine][:quiet] = true
+        end
+        opts.on('--compass', 'Make Compass imports available and load project configuration.') do
+          @options[:compass] = true
+        end
+        opts.on('-g', '--debug-info',
+                'Emit extra information in the generated CSS that can be used by the FireSass Firebug 
plugin.') do
+          @options[:for_engine][:debug_info] = true
+        end
+        opts.on('-l', '--line-numbers', '--line-comments',
+                'Emit comments in the generated CSS indicating the corresponding source line.') do
+          @options[:for_engine][:line_numbers] = true
+        end
+        opts.on('-i', '--interactive',
+                'Run an interactive SassScript shell.') do
+          @options[:interactive] = true
+        end
+        opts.on('-I', '--load-path PATH', 'Add a sass import path.') do |path|
+          @options[:for_engine][:load_paths] << path
+        end
+        opts.on('-r', '--require LIB', 'Require a Ruby library before running Sass.') do |lib|
+          require lib
+        end
+        opts.on('--cache-location PATH', 'The path to put cached Sass files. Defaults to .sass-cache.') do 
|loc|
+          @options[:for_engine][:cache_location] = loc
+        end
+        opts.on('-C', '--no-cache', "Don't cache to sassc files.") do
+          @options[:for_engine][:cache] = false
+        end
+
+        encoding_desc = if ::Sass::Util.ruby1_8?
+          'Does not work in ruby 1.8.'
+        else
+          'Specify the default encoding for Sass files.'
+        end
+        opts.on('-E encoding', encoding_desc) do |encoding|
+          if ::Sass::Util.ruby1_8?
+            $stderr.puts "Specifying the encoding is not supported in ruby 1.8."
+            exit 1
+          else
+            Encoding.default_external = encoding
+          end
+        end
+      end
+
+      # Processes the options set by the command-line arguments,
+      # and runs the Sass compiler appropriately.
+      def process_result
+        require 'sass'
+
+        if ! options[:update] && ! options[:watch] &&
+            @args.first && colon_path?(@args.first)
+          if @args.size == 1
+            @args = split_colon_path(@args.first)
+          else
+            @options[:update] = true
+          end
+        end
+        load_compass if @options[:compass]
+        return interactive if @options[:interactive]
+        return watch_or_update if @options[:watch] || @options[:update]
+        super
+        @options[:for_engine][:filename] = @options[:filename]
+        @options[:for_engine][:css_filename] = @options[:output] if @options[:output].is_a?(String)
+
+        begin
+          input = @options[:input]
+          output = @options[:output]
+
+          @options[:for_engine][:syntax] ||= :scss if input.is_a?(File) && input.path =~ /\.scss$/
+          @options[:for_engine][:syntax] ||= @default_syntax
+          engine =
+            if input.is_a?(File) && ! options[:check_syntax]
+              ::Sass::Engine.for_file(input.path, @options[:for_engine])
+            else
+              # We don't need to do any special handling of @options[:check_syntax] here,
+              # because the Sass syntax checking happens alongside evaluation
+              # and evaluation doesn't actually evaluate any code anyway.
+              ::Sass::Engine.new(input.read(), @options[:for_engine])
+            end
+
+          input.close() if input.is_a?(File)
+
+          write_output(engine.render, output)
+        rescue ::Sass::SyntaxError => e
+          raise e if @options[:trace]
+          raise e.sass_backtrace_str("standard input")
+        end
+      end
+
+      private
+
+      def load_compass
+        begin
+          require 'compass'
+        rescue LoadError
+          require 'rubygems'
+          begin
+            require 'compass'
+          rescue LoadError
+            puts "ERROR: Cannot load compass."
+            exit 1
+          end
+        end
+        Compass.add_project_configuration
+        Compass.configuration.project_path ||= Dir.pwd
+        @options[:for_engine][:load_paths] += Compass.configuration.sass_load_paths
+      end
+
+      def interactive
+        require 'sass/repl'
+        ::Sass::Repl.new(@options).run
+      end
+
+      def watch_or_update
+        require 'sass/plugin'
+        ::Sass::Plugin.options.merge! @options[:for_engine]
+        ::Sass::Plugin.options[:unix_newlines] = @options[:unix_newlines]
+        ::Sass::Plugin.options[:poll] = @options[:poll]
+
+        if @options[:force]
+          raise "The --force flag may only be used with --update." unless @options[:update]
+          ::Sass::Plugin.options[:always_update] = true
+        end
+
+        raise <<MSG if @args.empty?
+What files should I watch? Did you mean something like:
+    #{ default_syntax} --watch input #{ default_syntax}:output.css
+    #{ default_syntax} --watch input-dir:output-dir
+MSG
+
+        if !colon_path?(@args[0]) && probably_dest_dir?(@args[1])
+          flag = @options[:update] ? "--update" : "--watch"
+          err =
+            if !File.exist?(@args[1])
+              "doesn't exist"
+            elsif @args[1] =~ /\.css$/
+              "is a CSS file"
+            end
+          raise <<MSG if err
+File #{ args[1]} #{err}.
+    Did you mean: #{ default_syntax} #{flag} #{ args[0]}:#{ args[1]}
+MSG
+        end
+
+        dirs, files = @args.map {|name| split_colon_path(name)}.
+          partition {|i, _| File.directory? i}
+        files.map! {|from, to| [from, to || from.gsub(/\.[^.]*?$/, '.css')]}
+        dirs.map! {|from, to| [from, to || from]}
+        ::Sass::Plugin.options[:template_location] = dirs
+
+        ::Sass::Plugin.on_updated_stylesheet do |_, css|
+          if File.exists? css
+            puts_action :overwrite, :yellow, css
+          else
+            puts_action :create, :green, css
+          end
+        end
+
+        had_error = false
+        ::Sass::Plugin.on_creating_directory {|dirname| puts_action :directory, :green, dirname}
+        ::Sass::Plugin.on_deleting_css {|filename| puts_action :delete, :yellow, filename}
+        ::Sass::Plugin.on_compilation_error do |error, _, _|
+          if error.is_a?(SystemCallError) && ! options[:stop_on_error]
+            had_error = true
+            puts_action :error, :red, error.message
+            STDOUT.flush
+            next
+          end
+
+          raise error unless error.is_a?(::Sass::SyntaxError) && ! options[:stop_on_error]
+          had_error = true
+          puts_action :error, :red, "#{error.sass_filename} (Line #{error.sass_line}: #{error.message})"
+          STDOUT.flush
+        end
+
+        if @options[:update]
+          ::Sass::Plugin.update_stylesheets(files)
+          exit 1 if had_error
+          return
+        end
+
+        puts ">>> Sass is watching for changes. Press Ctrl-C to stop."
+
+        ::Sass::Plugin.on_template_modified do |template|
+          puts ">>> Change detected to: #{template}"
+          STDOUT.flush
+        end
+        ::Sass::Plugin.on_template_created do |template|
+          puts ">>> New template detected: #{template}"
+          STDOUT.flush
+        end
+        ::Sass::Plugin.on_template_deleted do |template|
+          puts ">>> Deleted template detected: #{template}"
+          STDOUT.flush
+        end
+
+        ::Sass::Plugin.watch(files)
+      end
+
+      def colon_path?(path)
+        !split_colon_path(path)[1].nil?
+      end
+
+      def split_colon_path(path)
+        one, two = path.split(':', 2)
+        if one && two && ::Sass::Util.windows? &&
+            one =~ /\A[A-Za-z]\Z/ && two =~ /\A[\/\\]/
+          # If we're on Windows and we were passed a drive letter path,
+          # don't split on that colon.
+          one2, two = two.split(':', 2)
+          one = one + ':' + one2
+        end
+        return one, two
+      end
+
+      # Whether path is likely to be meant as the destination
+      # in a source:dest pair.
+      def probably_dest_dir?(path)
+        return false unless path
+        return false if colon_path?(path)
+        return ::Sass::Util.glob(File.join(path, "*.s[ca]ss")).empty?
+      end
+    end
+
+    class Scss < Sass
+      # @param args [Array<String>] The command-line arguments
+      def initialize(args)
+        super
+        @default_syntax = :scss
+      end
+    end
+
+    # The `sass-convert` executable.
+    class SassConvert < Generic
+      # @param args [Array<String>] The command-line arguments
+      def initialize(args)
+        super
+        require 'sass'
+        @options[:for_tree] = {}
+        @options[:for_engine] = {:cache => false, :read_cache => true}
+      end
+
+      # Tells optparse how to parse the arguments.
+      #
+      # @param opts [OptionParser]
+      def set_opts(opts)
+        opts.banner = <<END
+Usage: sass-convert [options] [INPUT] [OUTPUT]
+
+Description:
+  Converts between CSS, Sass, and SCSS files.
+  E.g. converts from SCSS to Sass,
+  or converts from CSS to SCSS (adding appropriate nesting).
+
+Options:
+END
+
+        opts.on('-F', '--from FORMAT',
+          'The format to convert from. Can be css, scss, sass.',
+          'By default, this is inferred from the input filename.',
+          'If there is none, defaults to css.') do |name|
+          @options[:from] = name.downcase.to_sym
+          raise "sass-convert no longer supports LessCSS." if @options[:from] == :less
+          unless [:css, :scss, :sass].include?(@options[:from])
+            raise "Unknown format for sass-convert --from: #{name}"
+          end
+        end
+
+        opts.on('-T', '--to FORMAT',
+          'The format to convert to. Can be scss or sass.',
+          'By default, this is inferred from the output filename.',
+          'If there is none, defaults to sass.') do |name|
+          @options[:to] = name.downcase.to_sym
+          unless [:scss, :sass].include?(@options[:to])
+            raise "Unknown format for sass-convert --to: #{name}"
+          end
+        end
+
+        opts.on('-R', '--recursive',
+          'Convert all the files in a directory. Requires --from and --to.') do
+          @options[:recursive] = true
+        end
+
+        opts.on('-i', '--in-place',
+          'Convert a file to its own syntax.',
+          'This can be used to update some deprecated syntax.') do
+          @options[:in_place] = true
+        end
+
+        opts.on('--dasherize', 'Convert underscores to dashes') do
+          @options[:for_tree][:dasherize] = true
+        end
+
+        opts.on('--indent NUM',
+          'How many spaces to use for each level of indentation. Defaults to 2.',
+          '"t" means use hard tabs.') do |indent|
+
+          if indent == 't'
+            @options[:for_tree][:indent] = "\t"
+          else
+            @options[:for_tree][:indent] = " " * indent.to_i
+          end
+        end
+
+        opts.on('--old', 'Output the old-style ":prop val" property syntax.',
+                         'Only meaningful when generating Sass.') do
+          @options[:for_tree][:old] = true
+        end
+
+        opts.on('-C', '--no-cache', "Don't cache to sassc files.") do
+          @options[:for_engine][:read_cache] = false
+        end
+
+        unless ::Sass::Util.ruby1_8?
+          opts.on('-E encoding', 'Specify the default encoding for Sass and CSS files.') do |encoding|
+            Encoding.default_external = encoding
+          end
+        end
+
+        super
+      end
+
+      # Processes the options set by the command-line arguments,
+      # and runs the CSS compiler appropriately.
+      def process_result
+        require 'sass'
+
+        if @options[:recursive]
+          process_directory
+          return
+        end
+
+        super
+        input = @options[:input]
+        raise "Error: '#{input.path}' is a directory (did you mean to use --recursive?)" if 
File.directory?(input)
+        output = @options[:output]
+        output = input if @options[:in_place]
+        process_file(input, output)
+      end
+
+      private
+
+      def process_directory
+        unless input = @options[:input] = @args.shift
+          raise "Error: directory required when using --recursive."
+        end
+
+        output = @options[:output] = @args.shift
+        raise "Error: --from required when using --recursive." unless @options[:from]
+        raise "Error: --to required when using --recursive." unless @options[:to]
+        raise "Error: '#{ options[:input]}' is not a directory" unless File.directory?(@options[:input])
+        if @options[:output] && File.exists?(@options[:output]) && !File.directory?(@options[:output])
+          raise "Error: '#{ options[:output]}' is not a directory"
+        end
+        @options[:output] ||= @options[:input]
+
+        if @options[:to] == @options[:from] && ! options[:in_place]
+          fmt = @options[:from]
+          raise "Error: converting from #{fmt} to #{fmt} without --in-place"
+        end
+
+        ext = @options[:from]
+        ::Sass::Util.glob("#{ options[:input]}/**/*.#{ext}") do |f|
+          output =
+            if @options[:in_place]
+              f
+            elsif @options[:output]
+              output_name = f.gsub(/\.(c|sa|sc|le)ss$/, " #{ options[:to]}")
+              output_name[0    options[:input].size] = @options[:output]
+              output_name
+            else
+              f.gsub(/\.(c|sa|sc|le)ss$/, " #{ options[:to]}")
+            end
+
+          unless File.directory?(File.dirname(output))
+            puts_action :directory, :green, File.dirname(output)
+            FileUtils.mkdir_p(File.dirname(output))
+          end
+          puts_action :convert, :green, f
+          if File.exists?(output)
+            puts_action :overwrite, :yellow, output
+          else
+            puts_action :create, :green, output
+          end
+
+          input = open_file(f)
+          process_file(input, output)
+        end
+      end
+
+      def process_file(input, output)
+        if input.is_a?(File)
+          @options[:from] ||=
+            case input.path
+            when /\.scss$/; :scss
+            when /\.sass$/; :sass
+            when /\.less$/; raise "sass-convert no longer supports LessCSS."
+            when /\.css$/; :css
+            end
+        elsif @options[:in_place]
+          raise "Error: the --in-place option requires a filename."
+        end
+
+        if output.is_a?(File)
+          @options[:to] ||=
+            case output.path
+            when /\.scss$/; :scss
+            when /\.sass$/; :sass
+            end
+        end
+
+        @options[:from] ||= :css
+        @options[:to] ||= :sass
+        @options[:for_engine][:syntax] = @options[:from]
+
+        out =
+          ::Sass::Util.silence_sass_warnings do
+            if @options[:from] == :css
+              require 'sass/css'
+              ::Sass::CSS.new(input.read, @options[:for_tree]).render(@options[:to])
+            else
+              if input.is_a?(File)
+                ::Sass::Engine.for_file(input.path, @options[:for_engine])
+              else
+                ::Sass::Engine.new(input.read, @options[:for_engine])
+              end.to_tree.send("to_#{ options[:to]}", @options[:for_tree])
+            end
+          end
+
+        output = input.path if @options[:in_place]
+        write_output(out, output)
+      rescue ::Sass::SyntaxError => e
+        raise e if @options[:trace]
+        file = " of #{e.sass_filename}" if e.sass_filename
+        raise "Error on line #{e.sass_line}#{file}: #{e.message}\n  Use --trace for backtrace"
+      rescue LoadError => err
+        handle_load_error(err)
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/importers.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/importers.rb
new file mode 100644
index 0000000..1561a2d
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/importers.rb
@@ -0,0 +1,22 @@
+module Sass
+  # Sass importers are in charge of taking paths passed to ` import`
+  # and finding the appropriate Sass code for those paths.
+  # By default, this code is always loaded from the filesystem,
+  # but importers could be added to load from a database or over HTTP.
+  #
+  # Each importer is in charge of a single load path
+  # (or whatever the corresponding notion is for the backend).
+  # Importers can be placed in the {file:SASS_REFERENCE.md#load_paths-option `:load_paths` array}
+  # alongside normal filesystem paths.
+  #
+  # When resolving an ` import`, Sass will go through the load paths
+  # looking for an importer that successfully imports the path.
+  # Once one is found, the imported file is used.
+  #
+  # User-created importers must inherit from {Importers::Base}.
+  module Importers
+  end
+end
+
+require 'sass/importers/base'
+require 'sass/importers/filesystem'
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/importers/base.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/importers/base.rb
new file mode 100644
index 0000000..e18ebbd
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/importers/base.rb
@@ -0,0 +1,139 @@
+module Sass
+  module Importers
+    # The abstract base class for Sass importers.
+    # All importers should inherit from this.
+    #
+    # At the most basic level, an importer is given a string
+    # and must return a {Sass::Engine} containing some Sass code.
+    # This string can be interpreted however the importer wants;
+    # however, subclasses are encouraged to use the URI format
+    # for pathnames.
+    #
+    # Importers that have some notion of "relative imports"
+    # should take a single load path in their constructor,
+    # and interpret paths as relative to that.
+    # They should also implement the \{#find\_relative} method.
+    #
+    # Importers should be serializable via `Marshal.dump`.
+    # In addition to the standard `_dump` and `_load` methods,
+    # importers can define `_before_dump`, `_after_dump`, `_around_dump`,
+    # and `_after_load` methods as per {Sass::Util#dump} and {Sass::Util#load}.
+    #
+    # @abstract
+    class Base
+
+      # Find a Sass file relative to another file.
+      # Importers without a notion of "relative paths"
+      # should just return nil here.
+      #
+      # If the importer does have a notion of "relative paths",
+      # it should ignore its load path during this method.
+      #
+      # See \{#find} for important information on how this method should behave.
+      #
+      # The `:filename` option passed to the returned {Sass::Engine}
+      # should be of a format that could be passed to \{#find}.
+      #
+      # @param uri [String] The URI to import. This is not necessarily relative,
+      #   but this method should only return true if it is.
+      # @param base [String] The base filename. If `uri` is relative,
+      #   it should be interpreted as relative to `base`.
+      #   `base` is guaranteed to be in a format importable by this importer.
+      # @param options [{Symbol => Object}] Options for the Sass file
+      #   containing the ` import` that's currently being resolved.
+      # @return [Sass::Engine, nil] An Engine containing the imported file,
+      #   or nil if it couldn't be found or was in the wrong format.
+      def find_relative(uri, base, options)
+        Sass::Util.abstract(self)
+      end
+
+      # Find a Sass file, if it exists.
+      #
+      # This is the primary entry point of the Importer.
+      # It corresponds directly to an ` import` statement in Sass.
+      # It should do three basic things:
+      #
+      # * Determine if the URI is in this importer's format.
+      #   If not, return nil.
+      # * Determine if the file indicated by the URI actually exists and is readable.
+      #   If not, return nil.
+      # * Read the file and place the contents in a {Sass::Engine}.
+      #   Return that engine.
+      #
+      # If this importer's format allows for file extensions,
+      # it should treat them the same way as the default {Filesystem} importer.
+      # If the URI explicitly has a `.sass` or `.scss` filename,
+      # the importer should look for that exact file
+      # and import it as the syntax indicated.
+      # If it doesn't exist, the importer should return nil.
+      #
+      # If the URI doesn't have either of these extensions,
+      # the importer should look for files with the extensions.
+      # If no such files exist, it should return nil.
+      #
+      # The {Sass::Engine} to be returned should be passed `options`,
+      # with a few modifications. `:syntax` should be set appropriately,
+      # `:filename` should be set to `uri`,
+      # and `:importer` should be set to this importer.
+      #
+      # @param uri [String] The URI to import.
+      # @param options [{Symbol => Object}] Options for the Sass file
+      #   containing the ` import` that's currently being resolved.
+      #   This is safe for subclasses to modify destructively.
+      #   Callers should only pass in a value they don't mind being destructively modified.
+      # @return [Sass::Engine, nil] An Engine containing the imported file,
+      #   or nil if it couldn't be found or was in the wrong format.
+      def find(uri, options)
+        Sass::Util.abstract(self)
+      end
+
+      # Returns the time the given Sass file was last modified.
+      #
+      # If the given file has been deleted or the time can't be accessed
+      # for some other reason, this should return nil.
+      #
+      # @param uri [String] The URI of the file to check.
+      #   Comes from a `:filename` option set on an engine returned by this importer.
+      # @param options [{Symbol => Objet}] Options for the Sass file
+      #   containing the ` import` currently being checked.
+      # @return [Time, nil]
+      def mtime(uri, options)
+        Sass::Util.abstract(self)
+      end
+
+      # Get the cache key pair for the given Sass URI.
+      # The URI need not be checked for validity.
+      #
+      # The only strict requirement is that the returned pair of strings
+      # uniquely identify the file at the given URI.
+      # However, the first component generally corresponds roughly to the directory,
+      # and the second to the basename, of the URI.
+      #
+      # Note that keys must be unique *across importers*.
+      # Thus it's probably a good idea to include the importer name
+      # at the beginning of the first component.
+      #
+      # @param uri [String] A URI known to be valid for this importer.
+      # @param options [{Symbol => Object}] Options for the Sass file
+      #   containing the ` import` currently being checked.
+      # @return [(String, String)] The key pair which uniquely identifies
+      #   the file at the given URI.
+      def key(uri, options)
+        Sass::Util.abstract(self)
+      end
+
+      # A string representation of the importer.
+      # Should be overridden by subclasses.
+      #
+      # This is used to help debugging,
+      # and should usually just show the load path encapsulated by this importer.
+      #
+      # @return [String]
+      def to_s
+        Sass::Util.abstract(self)
+      end
+    end
+  end
+end
+
+      
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/importers/filesystem.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/importers/filesystem.rb
new file mode 100644
index 0000000..516b90f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/importers/filesystem.rb
@@ -0,0 +1,190 @@
+require 'pathname'
+require 'set'
+
+module Sass
+  module Importers
+    # The default importer, used for any strings found in the load path.
+    # Simply loads Sass files from the filesystem using the default logic.
+    class Filesystem < Base
+
+      attr_accessor :root
+
+      # Creates a new filesystem importer that imports files relative to a given path.
+      #
+      # @param root [String] The root path.
+      #   This importer will import files relative to this path.
+      def initialize(root)
+        @root = File.expand_path(root)
+        @same_name_warnings = Set.new
+      end
+
+      # @see Base#find_relative
+      def find_relative(name, base, options)
+        _find(File.dirname(base), name, options)
+      end
+
+      # @see Base#find
+      def find(name, options)
+        _find(@root, name, options)
+      end
+
+      # @see Base#mtime
+      def mtime(name, options)
+        file, _ = Sass::Util.destructure(find_real_file(@root, name, options))
+        File.mtime(file) if file
+      rescue Errno::ENOENT
+        nil
+      end
+
+      # @see Base#key
+      def key(name, options)
+        [self.class.name + ":" + File.dirname(File.expand_path(name)),
+          File.basename(name)]
+      end
+
+      # @see Base#to_s
+      def to_s
+        @root
+      end
+
+      def hash
+        @root.hash
+      end
+
+      def eql?(other)
+        root.eql?(other.root)
+      end
+
+      protected
+
+      # If a full uri is passed, this removes the root from it
+      # otherwise returns the name unchanged
+      def remove_root(name)
+        if name.index(@root + "/") == 0
+          name[(@root.length + 1)..-1]
+        else
+          name
+        end
+      end
+
+      # A hash from file extensions to the syntaxes for those extensions.
+      # The syntaxes must be `:sass` or `:scss`.
+      #
+      # This can be overridden by subclasses that want normal filesystem importing
+      # with unusual extensions.
+      #
+      # @return [{String => Symbol}]
+      def extensions
+        {'sass' => :sass, 'scss' => :scss}
+      end
+
+      # Given an ` import`ed path, returns an array of possible
+      # on-disk filenames and their corresponding syntaxes for that path.
+      #
+      # @param name [String] The filename.
+      # @return [Array(String, Symbol)] An array of pairs.
+      #   The first element of each pair is a filename to look for;
+      #   the second element is the syntax that file would be in (`:sass` or `:scss`).
+      def possible_files(name)
+        name = escape_glob_characters(name)
+        dirname, basename, extname = split(name)
+        sorted_exts = extensions.sort
+        syntax = extensions[extname]
+
+        if syntax
+          ret = [["#{dirname}/{_,}#{basename}.#{extensions.invert[syntax]}", syntax]]
+        else
+          ret = sorted_exts.map {|ext, syn| ["#{dirname}/{_,}#{basename}.#{ext}", syn]}
+        end
+
+        # JRuby chokes when trying to import files from JARs when the path starts with './'.
+        ret.map {|f, s| [f.sub(%r{^\./}, ''), s]}
+      end
+
+      def escape_glob_characters(name)
+        name.gsub(/[\*\[\]\{\}\?]/) do |char|
+          "\\#{char}"
+        end
+      end
+
+      REDUNDANT_DIRECTORY = %r{#{Regexp.escape(File::SEPARATOR)}\.#{Regexp.escape(File::SEPARATOR)}}
+      # Given a base directory and an ` import`ed name,
+      # finds an existant file that matches the name.
+      #
+      # @param dir [String] The directory relative to which to search.
+      # @param name [String] The filename to search for.
+      # @return [(String, Symbol)] A filename-syntax pair.
+      def find_real_file(dir, name, options)
+        # on windows 'dir' can be in native File::ALT_SEPARATOR form
+        dir = dir.gsub(File::ALT_SEPARATOR, File::SEPARATOR) unless File::ALT_SEPARATOR.nil?
+
+        found = possible_files(remove_root(name)).map do |f, s|
+          path = (dir == "." || Pathname.new(f).absolute?) ? f : "#{dir}/#{f}"
+          Dir[path].map do |full_path|
+            full_path.gsub!(REDUNDANT_DIRECTORY, File::SEPARATOR)
+            [full_path, s]
+          end
+        end
+        found = Sass::Util.flatten(found, 1)
+        return if found.empty?
+
+        if found.size > 1 && ! same_name_warnings include?(found.first.first)
+          found.each {|(f, _)| @same_name_warnings << f}
+          relative_to = Pathname.new(dir)
+          if options[:_line]
+            # If _line exists, we're here due to an actual import in an
+            # import_node and we want to print a warning for a user writing an
+            # ambiguous import.
+            candidates = found.map {|(f, _)| "    " + 
Pathname.new(f).relative_path_from(relative_to).to_s}.join("\n")
+            Sass::Util.sass_warn <<WARNING
+WARNING: On line #{options[:_line]}#{" of #{options[:filename]}" if options[:filename]}:
+  It's not clear which file to import for '@import "#{name}"'.
+  Candidates:
+#{candidates}
+  For now I'll choose #{File.basename found.first.first}.
+  This will be an error in future versions of Sass.
+WARNING
+          else
+            # Otherwise, we're here via StalenessChecker, and we want to print a
+            # warning for a user running `sass --watch` with two ambiguous files.
+            candidates = found.map {|(f, _)| "    " + File.basename(f)}.join("\n")
+            Sass::Util.sass_warn <<WARNING
+WARNING: In #{File.dirname(name)}:
+  There are multiple files that match the name "#{File.basename(name)}":
+#{candidates}
+WARNING
+          end
+        end
+        found.first
+      end
+
+      # Splits a filename into three parts, a directory part, a basename, and an extension
+      # Only the known extensions returned from the extensions method will be recognized as such.
+      def split(name)
+        extension = nil
+        dirname, basename = File.dirname(name), File.basename(name)
+        if basename =~ /^(.*)\.(#{extensions.keys.map{|e| Regexp.escape(e)}.join('|')})$/
+          basename = $1
+          extension = $2
+        end
+        [dirname, basename, extension]
+      end
+
+      private
+
+      def _find(dir, name, options)
+        full_filename, syntax = Sass::Util.destructure(find_real_file(dir, name, options))
+        return unless full_filename && File.readable?(full_filename)
+
+        options[:syntax] = syntax
+        options[:filename] = full_filename
+        options[:importer] = self
+        Sass::Engine.new(File.read(full_filename), options)
+      end
+
+      def join(base, path)
+        Pathname.new(base).join(path).to_s
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/logger.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/logger.rb
new file mode 100644
index 0000000..acc7437
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/logger.rb
@@ -0,0 +1,15 @@
+module Sass::Logger
+
+end
+
+require "sass/logger/log_level"
+require "sass/logger/base"
+
+module Sass
+
+  class << self
+    attr_accessor :logger
+  end
+
+  self.logger = Sass::Logger::Base.new
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/logger/base.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/logger/base.rb
new file mode 100644
index 0000000..c586c06
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/logger/base.rb
@@ -0,0 +1,32 @@
+require 'sass/logger/log_level'
+
+class Sass::Logger::Base
+  
+  include Sass::Logger::LogLevel
+
+  attr_accessor :log_level
+  attr_accessor :disabled
+
+  log_level :trace
+  log_level :debug
+  log_level :info
+  log_level :warn
+  log_level :error
+
+  def initialize(log_level = :debug)
+    self.log_level = log_level
+  end
+
+  def logging_level?(level)
+    !disabled && self.class.log_level?(level, log_level)
+  end
+
+  def log(level, message)
+    self._log(level, message) if logging_level?(level)
+  end
+
+  def _log(level, message)
+    Kernel::warn(message)
+  end
+
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/logger/log_level.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/logger/log_level.rb
new file mode 100644
index 0000000..c953bcf
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/logger/log_level.rb
@@ -0,0 +1,49 @@
+module Sass
+  module Logger
+    module LogLevel
+
+      def self.included(base)
+        base.extend(ClassMethods)
+      end
+      
+      module ClassMethods
+        def inherited(subclass)
+          subclass.log_levels = subclass.superclass.log_levels.dup
+        end
+
+        def log_levels
+          @log_levels ||= {}
+        end
+
+        def log_levels=(levels)
+          @log_levels = levels
+        end
+
+        def log_level?(level, min_level)
+          log_levels[level] >= log_levels[min_level]
+        end
+
+        def log_level(name, options = {})
+          if options[:prepend]
+            level = log_levels.values.min
+            level = level.nil? ? 0 : level - 1
+          else
+            level = log_levels.values.max
+            level = level.nil? ? 0 : level + 1
+          end
+          log_levels.update(name => level)
+          define_logger(name)
+        end
+
+        def define_logger(name, options = {})
+          class_eval <<-RUBY, __FILE__, __LINE__ + 1
+            def #{name}(message)
+              #{options.fetch(:to, :log)}(#{name.inspect}, message)
+            end
+          RUBY
+        end
+      end
+      
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/media.rb b/backends/css/gems/sass-3.2.12/lib/sass/media.rb
new file mode 100644
index 0000000..dba3aa3
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/media.rb
@@ -0,0 +1,213 @@
+# A namespace for the ` media` query parse tree.
+module Sass::Media
+  # A comma-separated list of queries.
+  #
+  #   media_query [ ',' S* media_query ]*
+  class QueryList
+    # The queries contained in this list.
+    #
+    # @return [Array<Query>]
+    attr_accessor :queries
+
+    # @param queries [Array<Query>] See \{#queries}
+    def initialize(queries)
+      @queries = queries
+    end
+
+    # Merges this query list with another. The returned query list
+    # queries for the intersection between the two inputs.
+    #
+    # Both query lists should be resolved.
+    #
+    # @param other [QueryList]
+    # @return [QueryList?] The merged list, or nil if there is no intersection.
+    def merge(other)
+      new_queries = queries.map {|q1| other.queries.map {|q2| q1.merge(q2)}}.flatten.compact
+      return if new_queries.empty?
+      QueryList.new(new_queries)
+    end
+
+    # Returns the CSS for the media query list.
+    #
+    # @return [String]
+    def to_css
+      queries.map {|q| q.to_css}.join(', ')
+    end
+
+    # Returns the Sass/SCSS code for the media query list.
+    #
+    # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize}).
+    # @return [String]
+    def to_src(options)
+      queries.map {|q| q.to_src(options)}.join(', ')
+    end
+
+    # Returns a representation of the query as an array of strings and
+    # potentially {Sass::Script::Node}s (if there's interpolation in it). When
+    # the interpolation is resolved and the strings are joined together, this
+    # will be the string representation of this query.
+    #
+    # @return [Array<String, Sass::Script::Node>]
+    def to_a
+      Sass::Util.intersperse(queries.map {|q| q.to_a}, ', ').flatten
+    end
+
+    # Returns a deep copy of this query list and all its children.
+    #
+    # @return [QueryList]
+    def deep_copy
+      QueryList.new(queries.map {|q| q.deep_copy})
+    end
+  end
+
+  # A single media query.
+  #
+  #   [ [ONLY | NOT]? S* media_type S* | expression ] [ AND S* expression ]*
+  class Query
+    # The modifier for the query.
+    #
+    # When parsed as Sass code, this contains strings and SassScript nodes. When
+    # parsed as CSS, it contains a single string (accessible via
+    # \{#resolved_modifier}).
+    #
+    # @return [Array<String, Sass::Script::Node>]
+    attr_accessor :modifier
+
+    # The type of the query (e.g. `"screen"` or `"print"`).
+    #
+    # When parsed as Sass code, this contains strings and SassScript nodes. When
+    # parsed as CSS, it contains a single string (accessible via
+    # \{#resolved_type}).
+    #
+    # @return [Array<String, Sass::Script::Node>]
+    attr_accessor :type
+
+    # The trailing expressions in the query.
+    #
+    # When parsed as Sass code, each expression contains strings and SassScript
+    # nodes. When parsed as CSS, each one contains a single string.
+    #
+    # @return [Array<Array<String, Sass::Script::Node>>]
+    attr_accessor :expressions
+
+    # @param modifier [Array<String, Sass::Script::Node>] See \{#modifier}
+    # @param type [Array<String, Sass::Script::Node>] See \{#type}
+    # @param expressions [Array<Array<String, Sass::Script::Node>>] See \{#expressions}
+    def initialize(modifier, type, expressions)
+      @modifier = modifier
+      @type = type
+      @expressions = expressions
+    end
+
+    # See \{#modifier}.
+    # @return [String]
+    def resolved_modifier
+      # modifier should contain only a single string
+      modifier.first || ''
+    end
+
+    # See \{#type}.
+    # @return [String]
+    def resolved_type
+      # type should contain only a single string
+      type.first || ''
+    end
+
+    # Merges this query with another. The returned query queries for
+    # the intersection between the two inputs.
+    #
+    # Both queries should be resolved.
+    #
+    # @param other [Query]
+    # @return [Query?] The merged query, or nil if there is no intersection.
+    def merge(other)
+      m1, t1 = resolved_modifier.downcase, resolved_type.downcase
+      m2, t2 = other.resolved_modifier.downcase, other.resolved_type.downcase
+      t1 = t2 if t1.empty?
+      t2 = t1 if t2.empty?
+      if ((m1 == 'not') ^ (m2 == 'not'))
+        return if t1 == t2
+        type = m1 == 'not' ? t2 : t1
+        mod = m1 == 'not' ? m2 : m1
+      elsif m1 == 'not' && m2 == 'not'
+        # CSS has no way of representing "neither screen nor print"
+        return unless t1 == t2
+        type = t1
+        mod = 'not'
+      elsif t1 != t2
+        return
+      else # t1 == t2, neither m1 nor m2 are "not"
+        type = t1
+        mod = m1.empty? ? m2 : m1
+      end
+      return Query.new([mod], [type], other.expressions + expressions)
+    end
+
+    # Returns the CSS for the media query.
+    #
+    # @return [String]
+    def to_css
+      css = ''
+      css << resolved_modifier
+      css << ' ' unless resolved_modifier.empty?
+      css << resolved_type
+      css << ' and ' unless resolved_type.empty? || expressions.empty?
+      css << expressions.map do |e|
+        # It's possible for there to be script nodes in Expressions even when
+        # we're converting to CSS in the case where we parsed the document as
+        # CSS originally (as in css_test.rb).
+        e.map {|c| c.is_a?(Sass::Script::Node) ? c.to_sass : c.to_s}.join
+      end.join(' and ')
+      css
+    end
+
+    # Returns the Sass/SCSS code for the media query.
+    #
+    # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize}).
+    # @return [String]
+    def to_src(options)
+      src = ''
+      src << Sass::Media._interp_to_src(modifier, options)
+      src << ' ' unless modifier.empty?
+      src << Sass::Media._interp_to_src(type, options)
+      src << ' and ' unless type.empty? || expressions.empty?
+      src << expressions.map do |e|
+        Sass::Media._interp_to_src(e, options)
+      end.join(' and ')
+      src
+    end
+
+    # @see \{MediaQuery#to\_a}
+    def to_a
+      res = []
+      res += modifier
+      res << ' ' unless modifier.empty?
+      res += type
+      res << ' and ' unless type.empty? || expressions.empty?
+      res += Sass::Util.intersperse(expressions, ' and ').flatten
+      res
+    end
+
+    # Returns a deep copy of this query and all its children.
+    #
+    # @return [Query]
+    def deep_copy
+      Query.new(
+        modifier.map {|c| c.is_a?(Sass::Script::Node) ? c.deep_copy : c},
+        type.map {|c| c.is_a?(Sass::Script::Node) ? c.deep_copy : c},
+        expressions.map {|e| e.map {|c| c.is_a?(Sass::Script::Node) ? c.deep_copy : c}})
+    end
+  end
+
+  # Converts an interpolation array to source.
+  #
+  # @param [Array<String, Sass::Script::Node>] The interpolation array to convert.
+  # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize}).
+  # @return [String]
+  def self._interp_to_src(interp, options)
+    interp.map do |r|
+      next r if r.is_a?(String)
+      "\#{#{r.to_sass(options)}}"
+    end.join
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/plugin.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/plugin.rb
new file mode 100644
index 0000000..0e037d8
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/plugin.rb
@@ -0,0 +1,132 @@
+require 'fileutils'
+
+require 'sass'
+require 'sass/plugin/compiler'
+
+module Sass
+  # This module provides a single interface to the compilation of Sass/SCSS files
+  # for an application. It provides global options and checks whether CSS files
+  # need to be updated.
+  #
+  # This module is used as the primary interface with Sass
+  # when it's used as a plugin for various frameworks.
+  # All Rack-enabled frameworks are supported out of the box.
+  # The plugin is {file:SASS_REFERENCE.md#rails_merb_plugin automatically activated for Rails and Merb}.
+  # Other frameworks must enable it explicitly; see {Sass::Plugin::Rack}.
+  #
+  # This module has a large set of callbacks available
+  # to allow users to run code (such as logging) when certain things happen.
+  # All callback methods are of the form `on_#{name}`,
+  # and they all take a block that's called when the given action occurs.
+  #
+  # Note that this class proxies almost all methods to its {Sass::Plugin::Compiler} instance.
+  # See \{#compiler}.
+  #
+  # @example Using a callback
+  #   Sass::Plugin.on_updating_stylesheet do |template, css|
+  #     puts "Compiling #{template} to #{css}"
+  #   end
+  #   Sass::Plugin.update_stylesheets
+  #     #=> Compiling app/sass/screen.scss to public/stylesheets/screen.css
+  #     #=> Compiling app/sass/print.scss to public/stylesheets/print.css
+  #     #=> Compiling app/sass/ie.scss to public/stylesheets/ie.css
+  # @see Sass::Plugin::Compiler
+  module Plugin
+    include Sass::Util
+    extend self
+
+    @checked_for_updates = false
+
+    # Whether or not Sass has **ever** checked if the stylesheets need to be updated
+    # (in this Ruby instance).
+    #
+    # @return [Boolean]
+    attr_accessor :checked_for_updates
+
+    # Same as \{#update\_stylesheets}, but respects \{#checked\_for\_updates}
+    # and the {file:SASS_REFERENCE.md#always_update-option `:always_update`}
+    # and {file:SASS_REFERENCE.md#always_check-option `:always_check`} options.
+    #
+    # @see #update_stylesheets
+    def check_for_updates
+      return unless !Sass::Plugin.checked_for_updates ||
+          Sass::Plugin.options[:always_update] || Sass::Plugin.options[:always_check]
+      update_stylesheets
+    end
+
+    # Returns the singleton compiler instance.
+    # This compiler has been pre-configured according
+    # to the plugin configuration.
+    #
+    # @return [Sass::Plugin::Compiler]
+    def compiler
+      @compiler ||= Compiler.new
+    end
+
+    # Updates out-of-date stylesheets.
+    #
+    # Checks each Sass/SCSS file in {file:SASS_REFERENCE.md#template_location-option `:template_location`}
+    # to see if it's been modified more recently than the corresponding CSS file
+    # in {file:SASS_REFERENCE.md#css_location-option `:css_location`}.
+    # If it has, it updates the CSS file.
+    #
+    # @param individual_files [Array<(String, String)>]
+    #   A list of files to check for updates
+    #   **in addition to those specified by the
+    #   {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
+    #   The first string in each pair is the location of the Sass/SCSS file,
+    #   the second is the location of the CSS file that it should be compiled to.
+    def update_stylesheets(individual_files = [])
+      return if options[:never_update]
+      compiler.update_stylesheets(individual_files)
+    end
+
+    # Updates all stylesheets, even those that aren't out-of-date.
+    # Ignores the cache.
+    #
+    # @param individual_files [Array<(String, String)>]
+    #   A list of files to check for updates
+    #   **in addition to those specified by the
+    #   {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
+    #   The first string in each pair is the location of the Sass/SCSS file,
+    #   the second is the location of the CSS file that it should be compiled to.
+    # @see #update_stylesheets
+    def force_update_stylesheets(individual_files = [])
+      Compiler.new(options.dup.merge(
+          :never_update => false,
+          :always_update => true,
+          :cache => false)).update_stylesheets(individual_files)
+    end
+
+    # All other method invocations are proxied to the \{#compiler}.
+    #
+    # @see #compiler
+    # @see Sass::Plugin::Compiler
+    def method_missing(method, *args, &block)
+      if compiler.respond_to?(method)
+        compiler.send(method, *args, &block)
+      else
+        super
+      end
+    end
+
+    # For parity with method_missing
+    def respond_to?(method)
+      super || compiler.respond_to?(method)
+    end
+
+    # There's a small speedup by not using method missing for frequently delegated methods.
+    def options
+      compiler.options
+    end
+
+  end
+end
+
+if defined?(ActionController)
+  require 'sass/plugin/rails'
+elsif defined?(Merb::Plugins)
+  require 'sass/plugin/merb'
+else
+  require 'sass/plugin/generic'
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/plugin/compiler.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/plugin/compiler.rb
new file mode 100644
index 0000000..feabe20
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/plugin/compiler.rb
@@ -0,0 +1,406 @@
+require 'fileutils'
+
+require 'sass'
+# XXX CE: is this still necessary now that we have the compiler class?
+require 'sass/callbacks'
+require 'sass/plugin/configuration'
+require 'sass/plugin/staleness_checker'
+
+module Sass::Plugin
+
+  # The Compiler class handles compilation of multiple files and/or directories,
+  # including checking which CSS files are out-of-date and need to be updated
+  # and calling Sass to perform the compilation on those files.
+  #
+  # {Sass::Plugin} uses this class to update stylesheets for a single application.
+  # Unlike {Sass::Plugin}, though, the Compiler class has no global state,
+  # and so multiple instances may be created and used independently.
+  #
+  # If you need to compile a Sass string into CSS,
+  # please see the {Sass::Engine} class.
+  #
+  # Unlike {Sass::Plugin}, this class doesn't keep track of
+  # whether or how many times a stylesheet should be updated.
+  # Therefore, the following `Sass::Plugin` options are ignored by the Compiler:
+  #
+  # * `:never_update`
+  # * `:always_check`
+  class Compiler
+    include Sass::Util
+    include Configuration
+    extend Sass::Callbacks
+
+    # Creates a new compiler.
+    #
+    # @param options [{Symbol => Object}]
+    #   See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
+    def initialize(options = {})
+      self.options.merge!(options)
+    end
+
+    # Register a callback to be run after stylesheets are mass-updated.
+    # This is run whenever \{#update\_stylesheets} is called,
+    # unless the \{file:SASS_REFERENCE.md#never_update-option `:never_update` option}
+    # is enabled.
+    #
+    # @yield [individual_files]
+    # @yieldparam individual_files [<(String, String)>]
+    #   Individual files to be updated, in addition to the directories
+    #   specified in the options.
+    #   The first element of each pair is the source file,
+    #   the second is the target CSS file.
+    define_callback :updating_stylesheets
+
+    # Register a callback to be run after a single stylesheet is updated.
+    # The callback is only run if the stylesheet is really updated;
+    # if the CSS file is fresh, this won't be run.
+    #
+    # Even if the \{file:SASS_REFERENCE.md#full_exception-option `:full_exception` option}
+    # is enabled, this callback won't be run
+    # when an exception CSS file is being written.
+    # To run an action for those files, use \{#on\_compilation\_error}.
+    #
+    # @yield [template, css]
+    # @yieldparam template [String]
+    #   The location of the Sass/SCSS file being updated.
+    # @yieldparam css [String]
+    #   The location of the CSS file being generated.
+    define_callback :updated_stylesheet
+
+    # Register a callback to be run before a single stylesheet is updated.
+    # The callback is only run if the stylesheet is guaranteed to be updated;
+    # if the CSS file is fresh, this won't be run.
+    #
+    # Even if the \{file:SASS_REFERENCE.md#full_exception-option `:full_exception` option}
+    # is enabled, this callback won't be run
+    # when an exception CSS file is being written.
+    # To run an action for those files, use \{#on\_compilation\_error}.
+    #
+    # @yield [template, css]
+    # @yieldparam template [String]
+    #   The location of the Sass/SCSS file being updated.
+    # @yieldparam css [String]
+    #   The location of the CSS file being generated.
+    define_callback :updating_stylesheet
+
+    def on_updating_stylesheet_with_deprecation_warning(&block)
+      Sass::Util.sass_warn("Sass::Compiler#on_updating_stylesheet callback is deprecated and will be removed 
in a future release. Use Sass::Compiler#on_updated_stylesheet instead, which is run after stylesheet 
compilation.")
+      on_updating_stylesheet_without_deprecation_warning(&block)
+    end
+    alias_method :on_updating_stylesheet_without_deprecation_warning, :on_updating_stylesheet
+    alias_method :on_updating_stylesheet, :on_updating_stylesheet_with_deprecation_warning
+
+    # Register a callback to be run when Sass decides not to update a stylesheet.
+    # In particular, the callback is run when Sass finds that
+    # the template file and none of its dependencies
+    # have been modified since the last compilation.
+    #
+    # Note that this is **not** run when the
+    # \{file:SASS_REFERENCE.md#never-update_option `:never_update` option} is set,
+    # nor when Sass decides not to compile a partial.
+    #
+    # @yield [template, css]
+    # @yieldparam template [String]
+    #   The location of the Sass/SCSS file not being updated.
+    # @yieldparam css [String]
+    #   The location of the CSS file not being generated.
+    define_callback :not_updating_stylesheet
+
+    # Register a callback to be run when there's an error
+    # compiling a Sass file.
+    # This could include not only errors in the Sass document,
+    # but also errors accessing the file at all.
+    #
+    # @yield [error, template, css]
+    # @yieldparam error [Exception] The exception that was raised.
+    # @yieldparam template [String]
+    #   The location of the Sass/SCSS file being updated.
+    # @yieldparam css [String]
+    #   The location of the CSS file being generated.
+    define_callback :compilation_error
+
+    # Register a callback to be run when Sass creates a directory
+    # into which to put CSS files.
+    #
+    # Note that even if multiple levels of directories need to be created,
+    # the callback may only be run once.
+    # For example, if "foo/" exists and "foo/bar/baz/" needs to be created,
+    # this may only be run for "foo/bar/baz/".
+    # This is not a guarantee, however;
+    # it may also be run for "foo/bar/".
+    #
+    # @yield [dirname]
+    # @yieldparam dirname [String]
+    #   The location of the directory that was created.
+    define_callback :creating_directory
+
+    # Register a callback to be run when Sass detects
+    # that a template has been modified.
+    # This is only run when using \{#watch}.
+    #
+    # @yield [template]
+    # @yieldparam template [String]
+    #   The location of the template that was modified.
+    define_callback :template_modified
+
+    # Register a callback to be run when Sass detects
+    # that a new template has been created.
+    # This is only run when using \{#watch}.
+    #
+    # @yield [template]
+    # @yieldparam template [String]
+    #   The location of the template that was created.
+    define_callback :template_created
+
+    # Register a callback to be run when Sass detects
+    # that a template has been deleted.
+    # This is only run when using \{#watch}.
+    #
+    # @yield [template]
+    # @yieldparam template [String]
+    #   The location of the template that was deleted.
+    define_callback :template_deleted
+
+    # Register a callback to be run when Sass deletes a CSS file.
+    # This happens when the corresponding Sass/SCSS file has been deleted.
+    #
+    # @yield [filename]
+    # @yieldparam filename [String]
+    #   The location of the CSS file that was deleted.
+    define_callback :deleting_css
+
+    # Updates out-of-date stylesheets.
+    #
+    # Checks each Sass/SCSS file in {file:SASS_REFERENCE.md#template_location-option `:template_location`}
+    # to see if it's been modified more recently than the corresponding CSS file
+    # in {file:SASS_REFERENCE.md#css_location-option `:css_location`}.
+    # If it has, it updates the CSS file.
+    #
+    # @param individual_files [Array<(String, String)>]
+    #   A list of files to check for updates
+    #   **in addition to those specified by the
+    #   {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
+    #   The first string in each pair is the location of the Sass/SCSS file,
+    #   the second is the location of the CSS file that it should be compiled to.
+    def update_stylesheets(individual_files = [])
+      individual_files = individual_files.dup
+      Sass::Plugin.checked_for_updates = true
+      staleness_checker = StalenessChecker.new(engine_options)
+
+      template_location_array.each do |template_location, css_location|
+        Sass::Util.glob(File.join(template_location, "**", "[^_]*.s[ca]ss")).sort.each do |file|
+          # Get the relative path to the file
+          name = file.sub(template_location.to_s.sub(/\/*$/, '/'), "")
+          css = css_filename(name, css_location)
+          individual_files << [file, css]
+        end
+      end
+
+      run_updating_stylesheets individual_files
+
+      individual_files.each do |file, css|
+        if options[:always_update] || staleness_checker.stylesheet_needs_update?(css, file)
+          update_stylesheet(file, css)
+        else
+          run_not_updating_stylesheet(file, css)
+        end
+      end
+    end
+
+    # Watches the template directory (or directories)
+    # and updates the CSS files whenever the related Sass/SCSS files change.
+    # `watch` never returns.
+    #
+    # Whenever a change is detected to a Sass/SCSS file in
+    # {file:SASS_REFERENCE.md#template_location-option `:template_location`},
+    # the corresponding CSS file in {file:SASS_REFERENCE.md#css_location-option `:css_location`}
+    # will be recompiled.
+    # The CSS files of any Sass/SCSS files that import the changed file will also be recompiled.
+    #
+    # Before the watching starts in earnest, `watch` calls \{#update\_stylesheets}.
+    #
+    # Note that `watch` uses the [Listen](http://github.com/guard/listen) library
+    # to monitor the filesystem for changes.
+    # Listen isn't loaded until `watch` is run.
+    # The version of Listen distributed with Sass is loaded by default,
+    # but if another version has already been loaded that will be used instead.
+    #
+    # @param individual_files [Array<(String, String)>]
+    #   A list of files to watch for updates
+    #   **in addition to those specified by the
+    #   {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
+    #   The first string in each pair is the location of the Sass/SCSS file,
+    #   the second is the location of the CSS file that it should be compiled to.
+    def watch(individual_files = [])
+      update_stylesheets(individual_files)
+
+      load_listen!
+
+      template_paths = template_locations # cache the locations
+      individual_files_hash = individual_files.inject({}) do |h, files|
+        parent = File.dirname(files.first)
+        (h[parent] ||= []) << files unless template_paths.include?(parent)
+        h
+      end
+      directories = template_paths + individual_files_hash.keys +
+        [{:relative_paths => true}]
+
+      # TODO: Keep better track of what depends on what
+      # so we don't have to run a global update every time anything changes.
+      listener = Listen::MultiListener.new(*directories) do |modified, added, removed|
+        modified.each do |f|
+          parent = File.dirname(f)
+          if files = individual_files_hash[parent]
+            next unless files.first == f
+          else
+            next unless f =~ /\.s[ac]ss$/
+          end
+          run_template_modified(f)
+        end
+
+        added.each do |f|
+          parent = File.dirname(f)
+          if files = individual_files_hash[parent]
+            next unless files.first == f
+          else
+            next unless f =~ /\.s[ac]ss$/
+          end
+          run_template_created(f)
+        end
+
+        removed.each do |f|
+          parent = File.dirname(f)
+          if files = individual_files_hash[parent]
+            next unless files.first == f
+            try_delete_css files[1]
+          else
+            next unless f =~ /\.s[ac]ss$/
+            try_delete_css f.gsub(/\.s[ac]ss$/, '.css')
+          end
+          run_template_deleted(f)
+        end
+
+        update_stylesheets(individual_files)
+      end
+
+      # The native windows listener is much slower than the polling
+      # option, according to 
https://github.com/nex3/sass/commit/a3031856b22bc834a5417dedecb038b7be9b9e3e#commitcomment-1295118
+      listener.force_polling(true) if @options[:poll] || Sass::Util.windows?
+
+      begin
+        listener.start
+      rescue Exception => e
+        raise e unless e.is_a?(Interrupt)
+      end
+    end
+
+    # Non-destructively modifies \{#options} so that default values are properly set,
+    # and returns the result.
+    #
+    # @param additional_options [{Symbol => Object}] An options hash with which to merge \{#options}
+    # @return [{Symbol => Object}] The modified options hash
+    def engine_options(additional_options = {})
+      opts = options.merge(additional_options)
+      opts[:load_paths] = load_paths(opts)
+      opts
+    end
+
+    # Compass expects this to exist
+    def stylesheet_needs_update?(css_file, template_file)
+      StalenessChecker.stylesheet_needs_update?(css_file, template_file)
+    end
+
+    private
+
+    def load_listen!
+      if defined?(gem)
+        begin
+          gem 'listen', '~> 0.7'
+          require 'listen'
+        rescue Gem::LoadError
+          dir = Sass::Util.scope("vendor/listen/lib")
+          $LOAD_PATH.unshift dir
+          begin
+            require 'listen'
+          rescue LoadError => e
+            e.message << "\n" <<
+              if File.exists?(scope(".git"))
+                'Run "git submodule update --init" to get the recommended version.'
+              else
+                'Run "gem install listen" to get it.'
+              end
+            raise e
+          end
+        end
+      else
+        begin
+          require 'listen'
+        rescue LoadError => e
+          dir = Sass::Util.scope("vendor/listen/lib")
+          if $LOAD_PATH.include?(dir)
+            raise e unless File.exists?(scope(".git"))
+            e.message << "\n" <<
+              'Run "git submodule update --init" to get the recommended version.'
+          else
+            $LOAD_PATH.unshift dir
+            retry
+          end
+        end
+      end
+    end
+
+    def update_stylesheet(filename, css)
+      dir = File.dirname(css)
+      unless File.exists?(dir)
+        run_creating_directory dir
+        FileUtils.mkdir_p dir
+      end
+
+      begin
+        File.read(filename) unless File.readable?(filename) # triggers an error for handling
+        engine_opts = engine_options(:css_filename => css, :filename => filename)
+        result = Sass::Engine.for_file(filename, engine_opts).render
+      rescue Exception => e
+        compilation_error_occured = true
+        run_compilation_error e, filename, css
+        result = Sass::SyntaxError.exception_to_css(e, options)
+      else
+        run_updating_stylesheet filename, css
+      end
+
+      write_file(css, result)
+      run_updated_stylesheet(filename, css) unless compilation_error_occured
+    end
+
+    def write_file(css, content)
+      flag = 'w'
+      flag = 'wb' if Sass::Util.windows? && options[:unix_newlines]
+      File.open(css, flag) do |file|
+        file.set_encoding(content.encoding) unless Sass::Util.ruby1_8?
+        file.print(content)
+      end
+    end
+
+    def try_delete_css(css)
+      return unless File.exists?(css)
+      run_deleting_css css
+      File.delete css
+    end
+
+    def load_paths(opts = options)
+      (opts[:load_paths] || []) + template_locations
+    end
+
+    def template_locations
+      template_location_array.to_a.map {|l| l.first}
+    end
+
+    def css_locations
+      template_location_array.to_a.map {|l| l.last}
+    end
+
+    def css_filename(name, path)
+      "#{path}/#{name}".gsub(/\.s[ac]ss$/, '.css')
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/plugin/configuration.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/plugin/configuration.rb
new file mode 100644
index 0000000..e6d65cd
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/plugin/configuration.rb
@@ -0,0 +1,123 @@
+# We keep configuration in its own self-contained file
+# so that we can load it independently in Rails 3,
+# where the full plugin stuff is lazy-loaded.
+
+module Sass
+  module Plugin
+    module Configuration
+
+      # Returns the default options for a {Sass::Plugin::Compiler}.
+      #
+      # @return [{Symbol => Object}]
+      def default_options
+        @default_options ||= {
+          :css_location       => './public/stylesheets',
+          :always_update      => false,
+          :always_check       => true,
+          :full_exception     => true,
+          :cache_location     => ".sass-cache"
+        }.freeze
+      end
+
+      # Resets the options and {Sass::Callbacks::InstanceMethods#clear_callbacks! clears all callbacks}.
+      def reset!
+        @options = nil
+        clear_callbacks!
+      end
+
+      # An options hash.
+      # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
+      #
+      # @return [{Symbol => Object}]
+      def options
+        @options ||= default_options.dup
+      end
+
+      # Sets the options hash.
+      # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
+      # See {Sass::Plugin::Configuration#reset!}
+      # @deprecated Instead, modify the options hash in-place.
+      # @param value [{Symbol => Object}] The options hash
+      def options=(value)
+        Sass::Util.sass_warn("Setting Sass::Plugin.options is deprecated " +
+                             "and will be removed in a future release.")
+        options.merge!(value)
+      end
+
+      # Adds a new template-location/css-location mapping.
+      # This means that Sass/SCSS files in `template_location`
+      # will be compiled to CSS files in `css_location`.
+      #
+      # This is preferred over manually manipulating the {file:SASS_REFERENCE.md#template_location-option 
`:template_location` option}
+      # since the option can be in multiple formats.
+      #
+      # Note that this method will change `options[:template_location]`
+      # to be in the Array format.
+      # This means that even if `options[:template_location]`
+      # had previously been a Hash or a String,
+      # it will now be an Array.
+      #
+      # @param template_location [String] The location where Sass/SCSS files will be.
+      # @param css_location [String] The location where compiled CSS files will go.
+      def add_template_location(template_location, css_location = options[:css_location])
+        normalize_template_location!
+        template_location_array << [template_location, css_location]
+      end
+
+      # Removes a template-location/css-location mapping.
+      # This means that Sass/SCSS files in `template_location`
+      # will no longer be compiled to CSS files in `css_location`.
+      #
+      # This is preferred over manually manipulating the {file:SASS_REFERENCE.md#template_location-option 
`:template_location` option}
+      # since the option can be in multiple formats.
+      #
+      # Note that this method will change `options[:template_location]`
+      # to be in the Array format.
+      # This means that even if `options[:template_location]`
+      # had previously been a Hash or a String,
+      # it will now be an Array.
+      #
+      # @param template_location [String]
+      #   The location where Sass/SCSS files were,
+      #   which is now going to be ignored.
+      # @param css_location [String]
+      #   The location where compiled CSS files went, but will no longer go.
+      # @return [Boolean]
+      #   Non-`nil` if the given mapping already existed and was removed,
+      #   or `nil` if nothing was changed.
+      def remove_template_location(template_location, css_location = options[:css_location])
+        normalize_template_location!
+        template_location_array.delete([template_location, css_location])
+      end
+
+      # Returns the template locations configured for Sass
+      # as an array of `[template_location, css_location]` pairs.
+      # See the {file:SASS_REFERENCE.md#template_location-option `:template_location` option}
+      # for details.
+      #
+      # @return [Array<(String, String)>]
+      #   An array of `[template_location, css_location]` pairs.
+      def template_location_array
+        old_template_location = options[:template_location]
+        normalize_template_location!
+        options[:template_location]
+      ensure
+        options[:template_location] = old_template_location
+      end
+
+      private
+
+      def normalize_template_location!
+        return if options[:template_location].is_a?(Array)
+        options[:template_location] =
+          case options[:template_location]
+          when nil
+            options[:css_location] ?
+              [[File.join(options[:css_location], 'sass'), options[:css_location]]] : []
+          when String; [[options[:template_location], options[:css_location]]]
+          else; options[:template_location].to_a
+          end
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/plugin/generic.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/plugin/generic.rb
new file mode 100644
index 0000000..3e82d2d
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/plugin/generic.rb
@@ -0,0 +1,15 @@
+# The reason some options are declared here rather than in sass/plugin/configuration.rb
+# is that otherwise they'd clobber the Rails-specific options.
+# Since Rails' options are lazy-loaded in Rails 3,
+# they're reverse-merged with the default options
+# so that user configuration is preserved.
+# This means that defaults that differ from Rails'
+# must be declared here.
+
+unless defined?(Sass::GENERIC_LOADED)
+  Sass::GENERIC_LOADED = true
+
+  Sass::Plugin.options.merge!(:css_location   => './public/stylesheets',
+                              :always_update  => false,
+                              :always_check   => true)
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/plugin/merb.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/plugin/merb.rb
new file mode 100644
index 0000000..f2b0a03
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/plugin/merb.rb
@@ -0,0 +1,48 @@
+unless defined?(Sass::MERB_LOADED)
+  Sass::MERB_LOADED = true
+
+  module Sass::Plugin::Configuration
+    # Different default options in a m envirionment.
+    def default_options
+      @default_options ||= begin
+        version = Merb::VERSION.split('.').map { |n| n.to_i }
+        if version[0] <= 0 && version[1] < 5
+          root = MERB_ROOT
+          env  = MERB_ENV
+        else
+          root = Merb.root.to_s
+          env  = Merb.environment
+        end
+
+        {
+          :always_update      => false,
+          :template_location => root + '/public/stylesheets/sass',
+          :css_location      => root + '/public/stylesheets',
+          :cache_location    => root + '/tmp/sass-cache',
+          :always_check      => env != "production",
+          :quiet             => env != "production",
+          :full_exception    => env != "production"
+        }.freeze
+      end
+    end
+  end
+
+  config = Merb::Plugins.config[:sass] || Merb::Plugins.config["sass"] || {}
+
+  if defined? config.symbolize_keys!
+    config.symbolize_keys!
+  end
+
+  Sass::Plugin.options.merge!(config)
+
+  require 'sass/plugin/rack'
+  class Sass::Plugin::MerbBootLoader < Merb::BootLoader
+    after Merb::BootLoader::RackUpApplication
+
+    def self.run
+      # Apparently there's no better way than this to add Sass
+      # to Merb's Rack stack.
+      Merb::Config[:app] = Sass::Plugin::Rack.new(Merb::Config[:app])
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/plugin/rack.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/plugin/rack.rb
new file mode 100644
index 0000000..1a93265
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/plugin/rack.rb
@@ -0,0 +1,60 @@
+module Sass
+  module Plugin
+    # Rack middleware for compiling Sass code.
+    #
+    # ## Activate
+    #
+    #     require 'sass/plugin/rack'
+    #     use Sass::Plugin::Rack
+    #
+    # ## Customize
+    #
+    #     Sass::Plugin.options.merge(
+    #       :cache_location => './tmp/sass-cache',
+    #       :never_update => environment != :production,
+    #       :full_exception => environment != :production)
+    #
+    # {file:SASS_REFERENCE.md#options See the Reference for more options}.
+    #
+    # ## Use
+    #
+    # Put your Sass files in `public/stylesheets/sass`.
+    # Your CSS will be generated in `public/stylesheets`,
+    # and regenerated every request if necessary.
+    # The locations and frequency {file:SASS_REFERENCE.md#options can be customized}.
+    # That's all there is to it!
+    class Rack
+      # The delay, in seconds, between update checks.
+      # Useful when many resources are requested for a single page.
+      # `nil` means no delay at all.
+      #
+      # @return [Float]
+      attr_accessor :dwell
+
+      # Initialize the middleware.
+      #
+      # @param app [#call] The Rack application
+      # @param dwell [Float] See \{#dwell}
+      def initialize(app, dwell = 1.0)
+        @app = app
+        @dwell = dwell
+        @check_after = Time.now.to_f
+      end
+
+      # Process a request, checking the Sass stylesheets for changes
+      # and updating them if necessary.
+      #
+      # @param env The Rack request environment
+      # @return [(#to_i, {String => String}, Object)] The Rack response
+      def call(env)
+        if @dwell.nil? || Time.now.to_f > @check_after
+          Sass::Plugin.check_for_updates
+          @check_after = Time.now.to_f + @dwell if @dwell
+        end
+        @app.call(env)
+      end
+    end
+  end
+end
+
+require 'sass/plugin'
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/plugin/rails.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/plugin/rails.rb
new file mode 100644
index 0000000..2ced021
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/plugin/rails.rb
@@ -0,0 +1,47 @@
+unless defined?(Sass::RAILS_LOADED)
+  Sass::RAILS_LOADED = true
+
+  module Sass::Plugin::Configuration
+    # Different default options in a rails envirionment.
+    def default_options
+      return @default_options if @default_options
+      opts = {
+        :quiet             => Sass::Util.rails_env != "production",
+        :full_exception    => Sass::Util.rails_env != "production",
+        :cache_location    => Sass::Util.rails_root + '/tmp/sass-cache'
+      }
+
+      opts.merge!(
+        :always_update     => false,
+        :template_location => Sass::Util.rails_root + '/public/stylesheets/sass',
+        :css_location      => Sass::Util.rails_root + '/public/stylesheets',
+        :always_check      => Sass::Util.rails_env == "development")
+
+      @default_options = opts.freeze
+    end
+  end
+
+  Sass::Plugin.options.reverse_merge!(Sass::Plugin.default_options)
+
+  # Rails 3.1 loads and handles Sass all on its own
+  if defined?(ActionController::Metal)
+    # 3.1 > Rails >= 3.0
+    require 'sass/plugin/rack'
+    Rails.configuration.middleware.use(Sass::Plugin::Rack)
+  elsif defined?(ActionController::Dispatcher) &&
+      defined?(ActionController::Dispatcher.middleware)
+    # Rails >= 2.3
+    require 'sass/plugin/rack'
+    ActionController::Dispatcher.middleware.use(Sass::Plugin::Rack)
+  else
+    module ActionController
+      class Base
+        alias_method :sass_old_process, :process
+        def process(*args)
+          Sass::Plugin.check_for_updates
+          sass_old_process(*args)
+        end
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/plugin/staleness_checker.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/plugin/staleness_checker.rb
new file mode 100644
index 0000000..74b1459
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/plugin/staleness_checker.rb
@@ -0,0 +1,199 @@
+require 'thread'
+
+module Sass
+  module Plugin
+    # The class handles `.s[ca]ss` file staleness checks via their mtime timestamps.
+    #
+    # To speed things up two level of caches are employed:
+    #
+    # * A class-level dependency cache which stores @import paths for each file.
+    #   This is a long-lived cache that is reused by every StalenessChecker instance.
+    # * Three short-lived instance-level caches, one for file mtimes,
+    #   one for whether a file is stale during this particular run.
+    #   and one for the parse tree for a file.
+    #   These are only used by a single StalenessChecker instance.
+    #
+    # Usage:
+    #
+    # * For a one-off staleness check of a single `.s[ca]ss` file,
+    #   the class-level {stylesheet_needs_update?} method
+    #   should be used.
+    # * For a series of staleness checks (e.g. checking all files for staleness)
+    #   a StalenessChecker instance should be created,
+    #   and the instance-level \{#stylesheet\_needs\_update?} method should be used.
+    #   the caches should make the whole process significantly faster.
+    #   *WARNING*: It is important not to retain the instance for too long,
+    #   as its instance-level caches are never explicitly expired.
+    class StalenessChecker
+      @dependencies_cache = {}
+      @dependency_cache_mutex = Mutex.new
+
+      class << self
+        # TODO: attach this to a compiler instance.
+        # @private
+        attr_accessor :dependencies_cache
+        attr_reader :dependency_cache_mutex
+      end
+
+      # Creates a new StalenessChecker
+      # for checking the staleness of several stylesheets at once.
+      #
+      # @param options [{Symbol => Object}]
+      #   See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
+      def initialize(options)
+        # URIs that are being actively checked for staleness. Protects against
+        # import loops.
+        @actively_checking = Set.new
+
+        # Entries in the following instance-level caches are never explicitly expired.
+        # Instead they are supposed to automaticaly go out of scope when a series of staleness checks
+        # (this instance of StalenessChecker was created for) is finished.
+        @mtimes, @dependencies_stale, @parse_trees = {}, {}, {}
+        @options = Sass::Engine.normalize_options(options)
+      end
+
+      # Returns whether or not a given CSS file is out of date
+      # and needs to be regenerated.
+      #
+      # @param css_file [String] The location of the CSS file to check.
+      # @param template_file [String] The location of the Sass or SCSS template
+      #   that is compiled to `css_file`.
+      # @return [Boolean] Whether the stylesheet needs to be updated.
+      def stylesheet_needs_update?(css_file, template_file, importer = nil)
+        template_file = File.expand_path(template_file)
+        begin
+          css_mtime = File.mtime(css_file)
+        rescue Errno::ENOENT
+          return true
+        end
+        stylesheet_modified_since?(template_file, css_mtime, importer)
+      end
+
+      # Returns whether a Sass or SCSS stylesheet has been modified since a given time.
+      #
+      # @param template_file [String] The location of the Sass or SCSS template.
+      # @param mtime [Fixnum] The modification time to check against.
+      # @param importer [Sass::Importers::Base] The importer used to locate the stylesheet.
+      #   Defaults to the filesystem importer.
+      # @return [Boolean] Whether the stylesheet has been modified.
+      def stylesheet_modified_since?(template_file, mtime, importer = nil)
+        importer ||= @options[:filesystem_importer].new(".")
+        dependency_updated?(mtime).call(template_file, importer)
+      end
+
+      # Returns whether or not a given CSS file is out of date
+      # and needs to be regenerated.
+      #
+      # The distinction between this method and the instance-level \{#stylesheet\_needs\_update?}
+      # is that the instance method preserves mtime and stale-dependency caches,
+      # so it's better to use when checking multiple stylesheets at once.
+      #
+      # @param css_file [String] The location of the CSS file to check.
+      # @param template_file [String] The location of the Sass or SCSS template
+      #   that is compiled to `css_file`.
+      # @return [Boolean] Whether the stylesheet needs to be updated.
+      def self.stylesheet_needs_update?(css_file, template_file, importer = nil)
+        new(Plugin.engine_options).stylesheet_needs_update?(css_file, template_file, importer)
+      end
+
+      # Returns whether a Sass or SCSS stylesheet has been modified since a given time.
+      #
+      # The distinction between this method and the instance-level \{#stylesheet\_modified\_since?}
+      # is that the instance method preserves mtime and stale-dependency caches,
+      # so it's better to use when checking multiple stylesheets at once.
+      #
+      # @param template_file [String] The location of the Sass or SCSS template.
+      # @param mtime [Fixnum] The modification time to check against.
+      # @param importer [Sass::Importers::Base] The importer used to locate the stylesheet.
+      #   Defaults to the filesystem importer.
+      # @return [Boolean] Whether the stylesheet has been modified.
+      def self.stylesheet_modified_since?(template_file, mtime, importer = nil)
+        new(Plugin.engine_options).stylesheet_modified_since?(template_file, mtime, importer)
+      end
+
+      private
+
+      def dependencies_stale?(uri, importer, css_mtime)
+        timestamps = @dependencies_stale[[uri, importer]] ||= {}
+        timestamps.each_pair do |checked_css_mtime, is_stale|
+          if checked_css_mtime <= css_mtime && !is_stale
+            return false
+          elsif checked_css_mtime > css_mtime && is_stale
+            return true
+          end
+        end
+        timestamps[css_mtime] = dependencies(uri, importer).any?(&dependency_updated?(css_mtime))
+      rescue Sass::SyntaxError
+        # If there's an error finding dependencies, default to recompiling.
+        true
+      end
+
+      def mtime(uri, importer)
+        @mtimes[[uri, importer]] ||=
+          begin
+            mtime = importer.mtime(uri, @options)
+            if mtime.nil?
+              with_dependency_cache {|cache| cache.delete([uri, importer])}
+              nil
+            else
+              mtime
+            end
+          end
+      end
+
+      def dependencies(uri, importer)
+        stored_mtime, dependencies =
+          with_dependency_cache {|cache| Sass::Util.destructure(cache[[uri, importer]])}
+
+        if !stored_mtime || stored_mtime < mtime(uri, importer)
+          dependencies = compute_dependencies(uri, importer)
+          with_dependency_cache do |cache|
+            cache[[uri, importer]] = [mtime(uri, importer), dependencies]
+          end
+        end
+
+        dependencies
+      end
+
+      def dependency_updated?(css_mtime)
+        Proc.new do |uri, importer|
+          next true if @actively_checking.include?(uri)
+          begin
+            @actively_checking << uri
+            sass_mtime = mtime(uri, importer)
+            !sass_mtime ||
+              sass_mtime > css_mtime ||
+              dependencies_stale?(uri, importer, css_mtime)
+          ensure
+            @actively_checking.delete uri
+          end
+        end
+      end
+
+      def compute_dependencies(uri, importer)
+        tree(uri, importer).grep(Tree::ImportNode) do |n|
+          next if n.css_import?
+          file = n.imported_file
+          key = [file.options[:filename], file.options[:importer]]
+          @parse_trees[key] = file.to_tree
+          key
+        end.compact
+      end
+
+      def tree(uri, importer)
+        @parse_trees[[uri, importer]] ||= importer.find(uri, @options).to_tree
+      end
+
+      # Get access to the global dependency cache in a threadsafe manner.
+      # Inside the block, no other thread can access the dependency cache.
+      #
+      # @yieldparam cache [Hash] The hash that is the global dependency cache
+      # @return The value returned by the block to which this method yields
+      def with_dependency_cache
+        StalenessChecker.dependency_cache_mutex.synchronize do
+          yield StalenessChecker.dependencies_cache
+        end
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/railtie.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/railtie.rb
new file mode 100644
index 0000000..a6c7535
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/railtie.rb
@@ -0,0 +1,9 @@
+# Rails 3.0.0.beta.2+, < 3.1
+if defined?(ActiveSupport) && Sass::Util.has?(:public_method, ActiveSupport, :on_load) &&
+    !Sass::Util.ap_geq?('3.1.0.beta')
+  require 'sass/plugin/configuration'
+  ActiveSupport.on_load(:before_configuration) do
+    require 'sass'
+    require 'sass/plugin'
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/repl.rb b/backends/css/gems/sass-3.2.12/lib/sass/repl.rb
new file mode 100644
index 0000000..7301de9
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/repl.rb
@@ -0,0 +1,57 @@
+require 'readline'
+
+module Sass
+  # Runs a SassScript read-eval-print loop.
+  # It presents a prompt on the terminal,
+  # reads in SassScript expressions,
+  # evaluates them,
+  # and prints the result.
+  class Repl
+    # @param options [{Symbol => Object}] An options hash.
+    def initialize(options = {})
+      @options = options
+    end
+
+    # Starts the read-eval-print loop.
+    def run
+      environment = Environment.new
+      @line = 0
+      loop do
+        @line += 1
+        unless text = Readline.readline('>> ')
+          puts
+          return
+        end
+
+        Readline::HISTORY << text
+        parse_input(environment, text)
+      end
+    end
+
+    private
+
+    def parse_input(environment, text)
+      case text
+      when Script::MATCH
+        name = $1
+        guarded = !!$3
+        val = Script::Parser.parse($2, @line, text.size - ($3 || '').size - $2.size)
+
+        unless guarded && environment.var(name)
+          environment.set_var(name, val.perform(environment))
+        end
+
+        p environment.var(name)
+      else
+        p Script::Parser.parse(text, @line, 0).perform(environment)
+      end
+    rescue Sass::SyntaxError => e
+      puts "SyntaxError: #{e.message}"
+      if @options[:trace]
+        e.backtrace.each do |e|
+          puts "\tfrom #{e}"
+        end
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/root.rb b/backends/css/gems/sass-3.2.12/lib/sass/root.rb
new file mode 100644
index 0000000..31e19c5
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/root.rb
@@ -0,0 +1,7 @@
+module Sass
+  # The root directory of the Sass source tree.
+  # This may be overridden by the package manager
+  # if the lib directory is separated from the main source tree.
+  # @api public
+  ROOT_DIR = File.expand_path(File.join(__FILE__, "../../.."))
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script.rb
new file mode 100644
index 0000000..44228b5
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script.rb
@@ -0,0 +1,39 @@
+require 'sass/script/node'
+require 'sass/script/variable'
+require 'sass/script/funcall'
+require 'sass/script/operation'
+require 'sass/script/literal'
+require 'sass/script/parser'
+
+module Sass
+  # SassScript is code that's embedded in Sass documents
+  # to allow for property values to be computed from variables.
+  #
+  # This module contains code that handles the parsing and evaluation of SassScript.
+  module Script
+    # The regular expression used to parse variables.
+    MATCH = /^\$(#{Sass::SCSS::RX::IDENT})\s*:\s*(.+?)(!(?i:default))?$/
+
+    # The regular expression used to validate variables without matching.
+    VALIDATE = /^\$#{Sass::SCSS::RX::IDENT}$/
+
+    # Parses a string of SassScript
+    #
+    # @param value [String] The SassScript
+    # @param line [Fixnum] The number of the line on which the SassScript appeared.
+    #   Used for error reporting
+    # @param offset [Fixnum] The number of characters in on `line` that the SassScript started.
+    #   Used for error reporting
+    # @param options [{Symbol => Object}] An options hash;
+    #   see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
+    # @return [Script::Node] The root node of the parse tree
+    def self.parse(value, line, offset, options = {})
+      Parser.parse(value, line, offset, options)
+    rescue Sass::SyntaxError => e
+      e.message << ": #{value.inspect}." if e.message == "SassScript error"
+      e.modify_backtrace(:line => line, :filename => options[:filename])
+      raise e
+    end
+
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/arg_list.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/arg_list.rb
new file mode 100644
index 0000000..e3e3e20
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/arg_list.rb
@@ -0,0 +1,52 @@
+module Sass::Script
+  # A SassScript object representing a variable argument list. This works just
+  # like a normal list, but can also contain keyword arguments.
+  #
+  # The keyword arguments attached to this list are unused except when this is
+  # passed as a glob argument to a function or mixin.
+  class ArgList < List
+    # Whether \{#keywords} has been accessed. If so, we assume that all keywords
+    # were valid for the function that created this ArgList.
+    #
+    # @return [Boolean]
+    attr_accessor :keywords_accessed
+
+    # Creates a new argument list.
+    #
+    # @param value [Array<Literal>] See \{List#value}.
+    # @param keywords [Hash<String, Literal>] See \{#keywords}
+    # @param separator [String] See \{List#separator}.
+    def initialize(value, keywords, separator)
+      super(value, separator)
+      @keywords = keywords
+    end
+
+    # The keyword arguments attached to this list.
+    #
+    # @return [Hash<String, Literal>]
+    def keywords
+      @keywords_accessed = true
+      @keywords
+    end
+
+    # @see Node#children
+    def children
+      super + @keywords.values
+    end
+
+    # @see Node#deep_copy
+    def deep_copy
+      node = super
+      node.instance_variable_set('@keywords',
+        Sass::Util.map_hash(@keywords) {|k, v| [k, v.deep_copy]})
+      node
+    end
+
+    protected
+
+    # @see Node#_perform
+    def _perform(environment)
+      self
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/bool.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/bool.rb
new file mode 100644
index 0000000..90fa39a
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/bool.rb
@@ -0,0 +1,18 @@
+require 'sass/script/literal'
+
+module Sass::Script
+  # A SassScript object representing a boolean (true or false) value.
+  class Bool < Literal
+    # The Ruby value of the boolean.
+    #
+    # @return [Boolean]
+    attr_reader :value
+    alias_method :to_bool, :value
+
+    # @return [String] "true" or "false"
+    def to_s(opts = {})
+      @value.to_s
+    end
+    alias_method :to_sass, :to_s
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/color.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/color.rb
new file mode 100644
index 0000000..70c125f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/color.rb
@@ -0,0 +1,606 @@
+require 'sass/script/literal'
+
+module Sass::Script
+  # A SassScript object representing a CSS color.
+  #
+  # A color may be represented internally as RGBA, HSLA, or both.
+  # It's originally represented as whatever its input is;
+  # if it's created with RGB values, it's represented as RGBA,
+  # and if it's created with HSL values, it's represented as HSLA.
+  # Once a property is accessed that requires the other representation --
+  # for example, \{#red} for an HSL color --
+  # that component is calculated and cached.
+  #
+  # The alpha channel of a color is independent of its RGB or HSL representation.
+  # It's always stored, as 1 if nothing else is specified.
+  # If only the alpha channel is modified using \{#with},
+  # the cached RGB and HSL values are retained.
+  class Color < Literal
+    class << self; include Sass::Util; end
+
+    # A hash from color names to `[red, green, blue]` value arrays.
+    COLOR_NAMES = map_vals({
+        'aliceblue' => 0xf0f8ff,
+        'antiquewhite' => 0xfaebd7,
+        'aqua' => 0x00ffff,
+        'aquamarine' => 0x7fffd4,
+        'azure' => 0xf0ffff,
+        'beige' => 0xf5f5dc,
+        'bisque' => 0xffe4c4,
+        'black' => 0x000000,
+        'blanchedalmond' => 0xffebcd,
+        'blue' => 0x0000ff,
+        'blueviolet' => 0x8a2be2,
+        'brown' => 0xa52a2a,
+        'burlywood' => 0xdeb887,
+        'cadetblue' => 0x5f9ea0,
+        'chartreuse' => 0x7fff00,
+        'chocolate' => 0xd2691e,
+        'coral' => 0xff7f50,
+        'cornflowerblue' => 0x6495ed,
+        'cornsilk' => 0xfff8dc,
+        'crimson' => 0xdc143c,
+        'cyan' => 0x00ffff,
+        'darkblue' => 0x00008b,
+        'darkcyan' => 0x008b8b,
+        'darkgoldenrod' => 0xb8860b,
+        'darkgray' => 0xa9a9a9,
+        'darkgrey' => 0xa9a9a9,
+        'darkgreen' => 0x006400,
+        'darkkhaki' => 0xbdb76b,
+        'darkmagenta' => 0x8b008b,
+        'darkolivegreen' => 0x556b2f,
+        'darkorange' => 0xff8c00,
+        'darkorchid' => 0x9932cc,
+        'darkred' => 0x8b0000,
+        'darksalmon' => 0xe9967a,
+        'darkseagreen' => 0x8fbc8f,
+        'darkslateblue' => 0x483d8b,
+        'darkslategray' => 0x2f4f4f,
+        'darkslategrey' => 0x2f4f4f,
+        'darkturquoise' => 0x00ced1,
+        'darkviolet' => 0x9400d3,
+        'deeppink' => 0xff1493,
+        'deepskyblue' => 0x00bfff,
+        'dimgray' => 0x696969,
+        'dimgrey' => 0x696969,
+        'dodgerblue' => 0x1e90ff,
+        'firebrick' => 0xb22222,
+        'floralwhite' => 0xfffaf0,
+        'forestgreen' => 0x228b22,
+        'fuchsia' => 0xff00ff,
+        'gainsboro' => 0xdcdcdc,
+        'ghostwhite' => 0xf8f8ff,
+        'gold' => 0xffd700,
+        'goldenrod' => 0xdaa520,
+        'gray' => 0x808080,
+        'green' => 0x008000,
+        'greenyellow' => 0xadff2f,
+        'honeydew' => 0xf0fff0,
+        'hotpink' => 0xff69b4,
+        'indianred' => 0xcd5c5c,
+        'indigo' => 0x4b0082,
+        'ivory' => 0xfffff0,
+        'khaki' => 0xf0e68c,
+        'lavender' => 0xe6e6fa,
+        'lavenderblush' => 0xfff0f5,
+        'lawngreen' => 0x7cfc00,
+        'lemonchiffon' => 0xfffacd,
+        'lightblue' => 0xadd8e6,
+        'lightcoral' => 0xf08080,
+        'lightcyan' => 0xe0ffff,
+        'lightgoldenrodyellow' => 0xfafad2,
+        'lightgreen' => 0x90ee90,
+        'lightgray' => 0xd3d3d3,
+        'lightgrey' => 0xd3d3d3,
+        'lightpink' => 0xffb6c1,
+        'lightsalmon' => 0xffa07a,
+        'lightseagreen' => 0x20b2aa,
+        'lightskyblue' => 0x87cefa,
+        'lightslategray' => 0x778899,
+        'lightslategrey' => 0x778899,
+        'lightsteelblue' => 0xb0c4de,
+        'lightyellow' => 0xffffe0,
+        'lime' => 0x00ff00,
+        'limegreen' => 0x32cd32,
+        'linen' => 0xfaf0e6,
+        'magenta' => 0xff00ff,
+        'maroon' => 0x800000,
+        'mediumaquamarine' => 0x66cdaa,
+        'mediumblue' => 0x0000cd,
+        'mediumorchid' => 0xba55d3,
+        'mediumpurple' => 0x9370db,
+        'mediumseagreen' => 0x3cb371,
+        'mediumslateblue' => 0x7b68ee,
+        'mediumspringgreen' => 0x00fa9a,
+        'mediumturquoise' => 0x48d1cc,
+        'mediumvioletred' => 0xc71585,
+        'midnightblue' => 0x191970,
+        'mintcream' => 0xf5fffa,
+        'mistyrose' => 0xffe4e1,
+        'moccasin' => 0xffe4b5,
+        'navajowhite' => 0xffdead,
+        'navy' => 0x000080,
+        'oldlace' => 0xfdf5e6,
+        'olive' => 0x808000,
+        'olivedrab' => 0x6b8e23,
+        'orange' => 0xffa500,
+        'orangered' => 0xff4500,
+        'orchid' => 0xda70d6,
+        'palegoldenrod' => 0xeee8aa,
+        'palegreen' => 0x98fb98,
+        'paleturquoise' => 0xafeeee,
+        'palevioletred' => 0xdb7093,
+        'papayawhip' => 0xffefd5,
+        'peachpuff' => 0xffdab9,
+        'peru' => 0xcd853f,
+        'pink' => 0xffc0cb,
+        'plum' => 0xdda0dd,
+        'powderblue' => 0xb0e0e6,
+        'purple' => 0x800080,
+        'red' => 0xff0000,
+        'rosybrown' => 0xbc8f8f,
+        'royalblue' => 0x4169e1,
+        'saddlebrown' => 0x8b4513,
+        'salmon' => 0xfa8072,
+        'sandybrown' => 0xf4a460,
+        'seagreen' => 0x2e8b57,
+        'seashell' => 0xfff5ee,
+        'sienna' => 0xa0522d,
+        'silver' => 0xc0c0c0,
+        'skyblue' => 0x87ceeb,
+        'slateblue' => 0x6a5acd,
+        'slategray' => 0x708090,
+        'slategrey' => 0x708090,
+        'snow' => 0xfffafa,
+        'springgreen' => 0x00ff7f,
+        'steelblue' => 0x4682b4,
+        'tan' => 0xd2b48c,
+        'teal' => 0x008080,
+        'thistle' => 0xd8bfd8,
+        'tomato' => 0xff6347,
+        'turquoise' => 0x40e0d0,
+        'violet' => 0xee82ee,
+        'wheat' => 0xf5deb3,
+        'white' => 0xffffff,
+        'whitesmoke' => 0xf5f5f5,
+        'yellow' => 0xffff00,
+        'yellowgreen' => 0x9acd32
+      }) {|color| (0..2).map {|n| color >> (n << 3) & 0xff}.reverse}
+
+    # A hash from `[red, green, blue]` value arrays to color names.
+    COLOR_NAMES_REVERSE = map_hash(hash_to_a(COLOR_NAMES)) {|k, v| [v, k]}
+
+    # Constructs an RGB or HSL color object,
+    # optionally with an alpha channel.
+    # 
+    # The RGB values must be between 0 and 255.
+    # The saturation and lightness values must be between 0 and 100.
+    # The alpha value must be between 0 and 1.
+    #
+    # @raise [Sass::SyntaxError] if any color value isn't in the specified range
+    #
+    # @overload initialize(attrs)
+    #   The attributes are specified as a hash.
+    #   This hash must contain either `:hue`, `:saturation`, and `:value` keys,
+    #   or `:red`, `:green`, and `:blue` keys.
+    #   It cannot contain both HSL and RGB keys.
+    #   It may also optionally contain an `:alpha` key.
+    #
+    #   @param attrs [{Symbol => Numeric}] A hash of color attributes to values
+    #   @raise [ArgumentError] if not enough attributes are specified,
+    #     or both RGB and HSL attributes are specified
+    #
+    # @overload initialize(rgba)
+    #   The attributes are specified as an array.
+    #   This overload only supports RGB or RGBA colors.
+    #
+    #   @param rgba [Array<Numeric>] A three- or four-element array
+    #     of the red, green, blue, and optionally alpha values (respectively)
+    #     of the color
+    #   @raise [ArgumentError] if not enough attributes are specified
+    def initialize(attrs, allow_both_rgb_and_hsl = false)
+      super(nil)
+
+      if attrs.is_a?(Array)
+        unless (3..4).include?(attrs.size)
+          raise ArgumentError.new("Color.new(array) expects a three- or four-element array")
+        end
+
+        red, green, blue = attrs[0...3].map {|c| c.to_i}
+        @attrs = {:red => red, :green => green, :blue => blue}
+        @attrs[:alpha] = attrs[3] ? attrs[3].to_f : 1
+      else
+        attrs = attrs.reject {|k, v| v.nil?}
+        hsl = [:hue, :saturation, :lightness] & attrs.keys
+        rgb = [:red, :green, :blue] & attrs.keys
+        if !allow_both_rgb_and_hsl && !hsl.empty? && !rgb.empty?
+          raise ArgumentError.new("Color.new(hash) may not have both HSL and RGB keys specified")
+        elsif hsl.empty? && rgb.empty?
+          raise ArgumentError.new("Color.new(hash) must have either HSL or RGB keys specified")
+        elsif !hsl.empty? && hsl.size != 3
+          raise ArgumentError.new("Color.new(hash) must have all three HSL values specified")
+        elsif !rgb.empty? && rgb.size != 3
+          raise ArgumentError.new("Color.new(hash) must have all three RGB values specified")
+        end
+
+        @attrs = attrs
+        @attrs[:hue] %= 360 if @attrs[:hue]
+        @attrs[:alpha] ||= 1
+      end
+
+      [:red, :green, :blue].each do |k|
+        next if @attrs[k].nil?
+        @attrs[k] = @attrs[k].to_i
+        Sass::Util.check_range("#{k.to_s.capitalize} value", 0..255, @attrs[k])
+      end
+
+      [:saturation, :lightness].each do |k|
+        next if @attrs[k].nil?
+        value = Number.new(@attrs[k], ['%']) # Get correct unit for error messages
+        @attrs[k] = Sass::Util.check_range("#{k.to_s.capitalize}", 0..100, value, '%')
+      end
+
+      @attrs[:alpha] = Sass::Util.check_range("Alpha channel", 0..1, @attrs[:alpha])
+    end
+
+    # The red component of the color.
+    #
+    # @return [Fixnum]
+    def red
+      hsl_to_rgb!
+      @attrs[:red]
+    end
+
+    # The green component of the color.
+    #
+    # @return [Fixnum]
+    def green
+      hsl_to_rgb!
+      @attrs[:green]
+    end
+
+    # The blue component of the color.
+    #
+    # @return [Fixnum]
+    def blue
+      hsl_to_rgb!
+      @attrs[:blue]
+    end
+
+    # The hue component of the color.
+    #
+    # @return [Numeric]
+    def hue
+      rgb_to_hsl!
+      @attrs[:hue]
+    end
+
+    # The saturation component of the color.
+    #
+    # @return [Numeric]
+    def saturation
+      rgb_to_hsl!
+      @attrs[:saturation]
+    end
+
+    # The lightness component of the color.
+    #
+    # @return [Numeric]
+    def lightness
+      rgb_to_hsl!
+      @attrs[:lightness]
+    end
+
+    # The alpha channel (opacity) of the color.
+    # This is 1 unless otherwise defined.
+    #
+    # @return [Fixnum]
+    def alpha
+      @attrs[:alpha]
+    end
+
+    # Returns whether this color object is translucent;
+    # that is, whether the alpha channel is non-1.
+    #
+    # @return [Boolean]
+    def alpha?
+      alpha < 1
+    end
+
+    # Returns the red, green, and blue components of the color.
+    #
+    # @return [Array<Fixnum>] A frozen three-element array of the red, green, and blue
+    #   values (respectively) of the color
+    def rgb
+      [red, green, blue].freeze
+    end
+
+    # Returns the hue, saturation, and lightness components of the color.
+    #
+    # @return [Array<Fixnum>] A frozen three-element array of the
+    #   hue, saturation, and lightness values (respectively) of the color
+    def hsl
+      [hue, saturation, lightness].freeze
+    end
+
+    # The SassScript `==` operation.
+    # **Note that this returns a {Sass::Script::Bool} object,
+    # not a Ruby boolean**.
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Bool] True if this literal is the same as the other,
+    #   false otherwise
+    def eq(other)
+      Sass::Script::Bool.new(
+        other.is_a?(Color) && rgb == other.rgb && alpha == other.alpha)
+    end
+
+    # Returns a copy of this color with one or more channels changed.
+    # RGB or HSL colors may be changed, but not both at once.
+    #
+    # For example:
+    #
+    #     Color.new([10, 20, 30]).with(:blue => 40)
+    #       #=> rgb(10, 40, 30)
+    #     Color.new([126, 126, 126]).with(:red => 0, :green => 255)
+    #       #=> rgb(0, 255, 126)
+    #     Color.new([255, 0, 127]).with(:saturation => 60)
+    #       #=> rgb(204, 51, 127)
+    #     Color.new([1, 2, 3]).with(:alpha => 0.4)
+    #       #=> rgba(1, 2, 3, 0.4)
+    #
+    # @param attrs [{Symbol => Numeric}]
+    #   A map of channel names (`:red`, `:green`, `:blue`,
+    #   `:hue`, `:saturation`, `:lightness`, or `:alpha`) to values
+    # @return [Color] The new Color object
+    # @raise [ArgumentError] if both RGB and HSL keys are specified
+    def with(attrs)
+      attrs = attrs.reject {|k, v| v.nil?}
+      hsl = !([:hue, :saturation, :lightness] & attrs.keys).empty?
+      rgb = !([:red, :green, :blue] & attrs.keys).empty?
+      if hsl && rgb
+        raise ArgumentError.new("Cannot specify HSL and RGB values for a color at the same time")
+      end
+
+      if hsl
+        [:hue, :saturation, :lightness].each {|k| attrs[k] ||= send(k)}
+      elsif rgb
+        [:red, :green, :blue].each {|k| attrs[k] ||= send(k)}
+      else
+        # If we're just changing the alpha channel,
+        # keep all the HSL/RGB stuff we've calculated
+        attrs = @attrs.merge(attrs)
+      end
+      attrs[:alpha] ||= alpha
+
+      Color.new(attrs, :allow_both_rgb_and_hsl)
+    end
+
+    # The SassScript `+` operation.
+    # Its functionality depends on the type of its argument:
+    #
+    # {Number}
+    # : Adds the number to each of the RGB color channels.
+    #
+    # {Color}
+    # : Adds each of the RGB color channels together.
+    #
+    # {Literal}
+    # : See {Literal#plus}.
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Color] The resulting color
+    # @raise [Sass::SyntaxError] if `other` is a number with units
+    def plus(other)
+      if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color)
+        piecewise(other, :+)
+      else
+        super
+      end
+    end
+
+    # The SassScript `-` operation.
+    # Its functionality depends on the type of its argument:
+    #
+    # {Number}
+    # : Subtracts the number from each of the RGB color channels.
+    #
+    # {Color}
+    # : Subtracts each of the other color's RGB color channels from this color's.
+    #
+    # {Literal}
+    # : See {Literal#minus}.
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Color] The resulting color
+    # @raise [Sass::SyntaxError] if `other` is a number with units
+    def minus(other)
+      if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color)
+        piecewise(other, :-)
+      else
+        super
+      end
+    end
+
+    # The SassScript `*` operation.
+    # Its functionality depends on the type of its argument:
+    #
+    # {Number}
+    # : Multiplies the number by each of the RGB color channels.
+    #
+    # {Color}
+    # : Multiplies each of the RGB color channels together.
+    #
+    # @param other [Number, Color] The right-hand side of the operator
+    # @return [Color] The resulting color
+    # @raise [Sass::SyntaxError] if `other` is a number with units
+    def times(other)
+      if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color)
+        piecewise(other, :*)
+      else
+        raise NoMethodError.new(nil, :times)
+      end
+    end
+
+    # The SassScript `/` operation.
+    # Its functionality depends on the type of its argument:
+    #
+    # {Number}
+    # : Divides each of the RGB color channels by the number.
+    #
+    # {Color}
+    # : Divides each of this color's RGB color channels by the other color's.
+    #
+    # {Literal}
+    # : See {Literal#div}.
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Color] The resulting color
+    # @raise [Sass::SyntaxError] if `other` is a number with units
+    def div(other)
+      if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color)
+        piecewise(other, :/)
+      else
+        super
+      end
+    end
+
+    # The SassScript `%` operation.
+    # Its functionality depends on the type of its argument:
+    #
+    # {Number}
+    # : Takes each of the RGB color channels module the number.
+    #
+    # {Color}
+    # : Takes each of this color's RGB color channels modulo the other color's.
+    #
+    # @param other [Number, Color] The right-hand side of the operator
+    # @return [Color] The resulting color
+    # @raise [Sass::SyntaxError] if `other` is a number with units
+    def mod(other)
+      if other.is_a?(Sass::Script::Number) || other.is_a?(Sass::Script::Color)
+        piecewise(other, :%)
+      else
+        raise NoMethodError.new(nil, :mod)
+      end
+    end
+
+    # Returns a string representation of the color.
+    # This is usually the color's hex value,
+    # but if the color has a name that's used instead.
+    #
+    # @return [String] The string representation
+    def to_s(opts = {})
+      return rgba_str if alpha?
+      return smallest if options[:style] == :compressed
+      return COLOR_NAMES_REVERSE[rgb] if COLOR_NAMES_REVERSE[rgb]
+      hex_str
+    end
+    alias_method :to_sass, :to_s
+
+    # Returns a string representation of the color.
+    #
+    # @return [String] The hex value
+    def inspect
+      alpha? ? rgba_str : hex_str
+    end
+
+    private
+
+    def smallest
+      small_hex_str = hex_str.gsub(/^#(.)\1(.)\2(.)\3$/, '#\1\2\3')
+      return small_hex_str unless (color = COLOR_NAMES_REVERSE[rgb]) &&
+        color.size <= small_hex_str.size
+      return color
+    end
+
+    def rgba_str
+      split = options[:style] == :compressed ? ',' : ', '
+      "rgba(#{rgb.join(split)}#{split}#{Number.round(alpha)})"
+    end
+
+    def hex_str
+      red, green, blue = rgb.map { |num| num.to_s(16).rjust(2, '0') }
+      "##{red}#{green}#{blue}"
+    end
+
+    def piecewise(other, operation)
+      other_num = other.is_a? Number
+      if other_num && !other.unitless?
+        raise Sass::SyntaxError.new("Cannot add a number with units (#{other}) to a color (#{self}).") 
+      end
+
+      result = []
+      for i in (0...3)
+        res = rgb[i].send(operation, other_num ? other.value : other.rgb[i])
+        result[i] = [ [res, 255].min, 0 ].max
+      end
+
+      if !other_num && other.alpha != alpha
+        raise Sass::SyntaxError.new("Alpha channels must be equal: #{self} #{operation} #{other}")
+      end
+
+      with(:red => result[0], :green => result[1], :blue => result[2])
+    end
+
+    def hsl_to_rgb!
+      return if @attrs[:red] && @attrs[:blue] && @attrs[:green]
+
+      h = @attrs[:hue] / 360.0
+      s = @attrs[:saturation] / 100.0
+      l = @attrs[:lightness] / 100.0
+
+      # Algorithm from the CSS3 spec: http://www.w3.org/TR/css3-color/#hsl-color.
+      m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s
+      m1 = l * 2 - m2
+      @attrs[:red], @attrs[:green], @attrs[:blue] = [
+        hue_to_rgb(m1, m2, h + 1.0/3),
+        hue_to_rgb(m1, m2, h),
+        hue_to_rgb(m1, m2, h - 1.0/3)
+      ].map {|c| (c * 0xff).round}
+    end
+
+    def hue_to_rgb(m1, m2, h)
+      h += 1 if h < 0
+      h -= 1 if h > 1
+      return m1 + (m2 - m1) * h * 6 if h * 6 < 1
+      return m2 if h * 2 < 1
+      return m1 + (m2 - m1) * (2.0/3 - h) * 6 if h * 3 < 2
+      return m1
+    end
+
+    def rgb_to_hsl!
+      return if @attrs[:hue] && @attrs[:saturation] && @attrs[:lightness]
+      r, g, b = [:red, :green, :blue].map {|k| @attrs[k] / 255.0}
+
+      # Algorithm from http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
+      max = [r, g, b].max
+      min = [r, g, b].min
+      d = max - min
+
+      h =
+        case max
+        when min; 0
+        when r; 60 * (g-b)/d
+        when g; 60 * (b-r)/d + 120
+        when b; 60 * (r-g)/d + 240
+        end
+
+      l = (max + min)/2.0
+
+      s =
+        if max == min
+          0
+        elsif l < 0.5
+          d/(2*l)
+        else
+          d/(2 - 2*l)
+        end
+
+      @attrs[:hue] = h % 360
+      @attrs[:saturation] = s * 100
+      @attrs[:lightness] = l * 100
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/css_lexer.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/css_lexer.rb
new file mode 100644
index 0000000..464fcf4
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/css_lexer.rb
@@ -0,0 +1,29 @@
+module Sass
+  module Script
+    # This is a subclass of {Lexer} for use in parsing plain CSS properties.
+    #
+    # @see Sass::SCSS::CssParser
+    class CssLexer < Lexer
+      private
+
+      def token
+        important || super
+      end
+
+      def string(re, *args)
+        if re == :uri
+          return unless uri = scan(URI)
+          return [:string, Script::String.new(uri)]
+        end
+
+        return unless scan(STRING)
+        [:string, Script::String.new((@scanner[1] || @scanner[2]).gsub(/\\(['"])/, '\1'), :string)]
+      end
+
+      def important
+        return unless s = scan(IMPORTANT)
+        [:raw, s]
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/css_parser.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/css_parser.rb
new file mode 100644
index 0000000..968b94b
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/css_parser.rb
@@ -0,0 +1,31 @@
+require 'sass/script'
+require 'sass/script/css_lexer'
+
+module Sass
+  module Script
+    # This is a subclass of {Parser} for use in parsing plain CSS properties.
+    #
+    # @see Sass::SCSS::CssParser
+    class CssParser < Parser
+      private
+
+      # @private
+      def lexer_class; CssLexer; end
+
+      # We need a production that only does /,
+      # since * and % aren't allowed in plain CSS
+      production :div, :unary_plus, :div
+
+      def string
+        return number unless tok = try_tok(:string)
+        return tok.value unless @lexer.peek && @lexer.peek.type == :begin_interpolation
+      end
+
+      # Short-circuit all the SassScript-only productions
+      alias_method :interpolation, :space
+      alias_method :or_expr, :div
+      alias_method :unary_div, :ident
+      alias_method :paren, :string
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/funcall.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/funcall.rb
new file mode 100644
index 0000000..bceea0a
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/funcall.rb
@@ -0,0 +1,237 @@
+require 'sass/script/functions'
+
+module Sass
+  module Script
+    # A SassScript parse node representing a function call.
+    #
+    # A function call either calls one of the functions in {Script::Functions},
+    # or if no function with the given name exists
+    # it returns a string representation of the function call.
+    class Funcall < Node
+      # The name of the function.
+      #
+      # @return [String]
+      attr_reader :name
+
+      # The arguments to the function.
+      #
+      # @return [Array<Script::Node>]
+      attr_reader :args
+
+      # The keyword arguments to the function.
+      #
+      # @return [{String => Script::Node}]
+      attr_reader :keywords
+
+      # The splat argument for this function, if one exists.
+      #
+      # @return [Script::Node?]
+      attr_accessor :splat
+
+      # @param name [String] See \{#name}
+      # @param args [Array<Script::Node>] See \{#args}
+      # @param splat [Script::Node] See \{#splat}
+      # @param keywords [{String => Script::Node}] See \{#keywords}
+      def initialize(name, args, keywords, splat)
+        @name = name
+        @args = args
+        @keywords = keywords
+        @splat = splat
+        super()
+      end
+
+      # @return [String] A string representation of the function call
+      def inspect
+        args = @args.map {|a| a.inspect}.join(', ')
+        keywords = Sass::Util.hash_to_a(@keywords).
+            map {|k, v| "$#{k}: #{v.inspect}"}.join(', ')
+        if self.splat
+          splat = (args.empty? && keywords.empty?) ? "" : ", "
+          splat = "#{splat}#{self.splat.inspect}..."
+        end
+        "#{name}(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords}#{splat})"
+      end
+
+      # @see Node#to_sass
+      def to_sass(opts = {})
+        arg_to_sass = lambda do |arg|
+          sass = arg.to_sass(opts)
+          sass = "(#{sass})" if arg.is_a?(Sass::Script::List) && arg.separator == :comma
+          sass
+        end
+
+        args = @args.map(&arg_to_sass).join(', ')
+        keywords = Sass::Util.hash_to_a(@keywords).
+          map {|k, v| "$#{dasherize(k, opts)}: #{arg_to_sass[v]}"}.join(', ')
+        if self.splat
+          splat = (args.empty? && keywords.empty?) ? "" : ", "
+          splat = "#{splat}#{arg_to_sass[self.splat]}..."
+        end
+        "#{dasherize(name, opts)}(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords}#{splat})"
+      end
+
+      # Returns the arguments to the function.
+      #
+      # @return [Array<Node>]
+      # @see Node#children
+      def children
+        res = @args + @keywords.values
+        res << @splat if @splat
+        res
+      end
+
+      # @see Node#deep_copy
+      def deep_copy
+        node = dup
+        node.instance_variable_set('@args', args.map {|a| a.deep_copy})
+        node.instance_variable_set('@keywords', Hash[keywords.map {|k, v| [k, v.deep_copy]}])
+        node
+      end
+
+      protected
+
+      # Evaluates the function call.
+      #
+      # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
+      # @return [Literal] The SassScript object that is the value of the function call
+      # @raise [Sass::SyntaxError] if the function call raises an ArgumentError
+      def _perform(environment)
+        args = @args.map {|a| a.perform(environment)}
+        splat = @splat.perform(environment) if @splat
+        if fn = environment.function(@name)
+          keywords = Sass::Util.map_hash(@keywords) {|k, v| [k, v.perform(environment)]}
+          return perform_sass_fn(fn, args, keywords, splat)
+        end
+
+        ruby_name = @name.tr('-', '_')
+        args = construct_ruby_args(ruby_name, args, splat, environment)
+
+        unless Functions.callable?(ruby_name)
+          opts(to_literal(args))
+        else
+          opts(Functions::EvaluationContext.new(environment.options).send(ruby_name, *args))
+        end
+      rescue ArgumentError => e
+        message = e.message
+
+        # If this is a legitimate Ruby-raised argument error, re-raise it.
+        # Otherwise, it's an error in the user's stylesheet, so wrap it.
+        if Sass::Util.rbx?
+          # Rubinius has a different error report string than vanilla Ruby. It
+          # also doesn't put the actual method for which the argument error was
+          # thrown in the backtrace, nor does it include `send`, so we look for
+          # `_perform`.
+          if e.message =~ /^method '([^']+)': given (\d+), expected (\d+)/
+            error_name, given, expected = $1, $2, $3
+            raise e if error_name != ruby_name || e.backtrace[0] !~ /:in `_perform'$/
+            message = "wrong number of arguments (#{given} for #{expected})"
+          end
+        elsif Sass::Util.jruby?
+          if Sass::Util.jruby1_6?
+            should_maybe_raise = e.message =~ /^wrong number of arguments \((\d+) for (\d+)\)/ &&
+              # The one case where JRuby does include the Ruby name of the function
+              # is manually-thrown ArgumentErrors, which are indistinguishable from
+              # legitimate ArgumentErrors. We treat both of these as
+              # Sass::SyntaxErrors even though it can hide Ruby errors.
+              e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
+          else
+            should_maybe_raise = e.message =~ /^wrong number of arguments calling `[^`]+` \((\d+) for 
(\d+)\)/
+            given, expected = $1, $2
+          end
+
+          if should_maybe_raise
+            # JRuby 1.7 includes __send__ before send and _perform.
+            trace = e.backtrace.dup
+            raise e if !Sass::Util.jruby1_6? && trace.shift !~ /:in `__send__'$/
+
+            # JRuby (as of 1.7.2) doesn't put the actual method
+            # for which the argument error was thrown in the backtrace, so we
+            # detect whether our send threw an argument error.
+            if !(trace[0] =~ /:in `send'$/ && trace[1] =~ /:in `_perform'$/)
+              raise e
+            elsif !Sass::Util.jruby1_6?
+              # JRuby 1.7 doesn't use standard formatting for its ArgumentErrors.
+              message = "wrong number of arguments (#{given} for #{expected})"
+            end
+          end
+        elsif e.message =~ /^wrong number of arguments \(\d+ for \d+\)/ &&
+            e.backtrace[0] !~ /:in `(block in )?#{ruby_name}'$/
+          raise e
+        end
+        raise Sass::SyntaxError.new("#{message} for `#{name}'")
+      end
+
+      # This method is factored out from `_perform` so that compass can override
+      # it with a cross-browser implementation for functions that require vendor prefixes
+      # in the generated css.
+      def to_literal(args)
+        Script::String.new("#{name}(#{args.join(', ')})")
+      end
+
+      private
+
+      def construct_ruby_args(name, args, splat, environment)
+        args += splat.to_a if splat
+
+        # If variable arguments were passed, there won't be any explicit keywords.
+        if splat.is_a?(Sass::Script::ArgList)
+          kwargs_size = splat.keywords.size
+          splat.keywords_accessed = false
+        else
+          kwargs_size = @keywords.size
+        end
+
+        unless signature = Functions.signature(name.to_sym, args.size, kwargs_size)
+          return args if @keywords.empty?
+          raise Sass::SyntaxError.new("Function #{name} doesn't support keyword arguments")
+        end
+        keywords = splat.is_a?(Sass::Script::ArgList) ? splat.keywords :
+          Sass::Util.map_hash(@keywords) {|k, v| [k, v.perform(environment)]}
+
+        # If the user passes more non-keyword args than the function expects,
+        # but it does expect keyword args, Ruby's arg handling won't raise an error.
+        # Since we don't want to make functions think about this,
+        # we'll handle it for them here.
+        if signature.var_kwargs && !signature.var_args && args.size > signature.args.size
+          raise Sass::SyntaxError.new(
+            "#{args[signature.args.size].inspect} is not a keyword argument for `#{name}'")
+        elsif keywords.empty?
+          return args 
+        end
+
+        args = args + signature.args[args.size..-1].map do |argname|
+          if keywords.has_key?(argname)
+            keywords.delete(argname)
+          else
+            raise Sass::SyntaxError.new("Function #{name} requires an argument named $#{argname}")
+          end
+        end
+
+        if keywords.size > 0
+          if signature.var_kwargs
+            args << keywords
+          else
+            argname = keywords.keys.sort.first
+            if signature.args.include?(argname)
+              raise Sass::SyntaxError.new("Function #{name} was passed argument $#{argname} both by position 
and by name")
+            else
+              raise Sass::SyntaxError.new("Function #{name} doesn't have an argument named $#{argname}")
+            end
+          end
+        end
+
+        args
+      end
+
+      def perform_sass_fn(function, args, keywords, splat)
+        Sass::Tree::Visitors::Perform.perform_arguments(function, args, keywords, splat) do |env|
+          val = catch :_sass_return do
+            function.tree.each {|c| Sass::Tree::Visitors::Perform.visit(c, env)}
+            raise Sass::SyntaxError.new("Function #{ name} finished without @return")
+          end
+          val
+        end
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/functions.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/functions.rb
new file mode 100644
index 0000000..b3b2458
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/functions.rb
@@ -0,0 +1,1543 @@
+module Sass::Script
+  # Methods in this module are accessible from the SassScript context.
+  # For example, you can write
+  #
+  #     $color: hsl(120deg, 100%, 50%)
+  #
+  # and it will call {Sass::Script::Functions#hsl}.
+  #
+  # The following functions are provided:
+  #
+  # *Note: These functions are described in more detail below.*
+  #
+  # ## RGB Functions
+  #
+  # \{#rgb rgb($red, $green, $blue)}
+  # : Creates a {Color} from red, green, and blue values.
+  #
+  # \{#rgba rgba($red, $green, $blue, $alpha)}
+  # : Creates a {Color} from red, green, blue, and alpha values.
+  #
+  # \{#red red($color)}
+  # : Gets the red component of a color.
+  #
+  # \{#green green($color)}
+  # : Gets the green component of a color.
+  #
+  # \{#blue blue($color)}
+  # : Gets the blue component of a color.
+  #
+  # \{#mix mix($color-1, $color-2, \[$weight\])}
+  # : Mixes two colors together.
+  #
+  # ## HSL Functions
+  #
+  # \{#hsl hsl($hue, $saturation, $lightness)}
+  # : Creates a {Color} from hue, saturation, and lightness values.
+  #
+  # \{#hsla hsla($hue, $saturation, $lightness, $alpha)}
+  # : Creates a {Color} from hue, saturation, lightness, and alpha
+  #   values.
+  #
+  # \{#hue hue($color)}
+  # : Gets the hue component of a color.
+  #
+  # \{#saturation saturation($color)}
+  # : Gets the saturation component of a color.
+  #
+  # \{#lightness lightness($color)}
+  # : Gets the lightness component of a color.
+  #
+  # \{#adjust_hue adjust-hue($color, $degrees)}
+  # : Changes the hue of a color.
+  #
+  # \{#lighten lighten($color, $amount)}
+  # : Makes a color lighter.
+  #
+  # \{#darken darken($color, $amount)}
+  # : Makes a color darker.
+  #
+  # \{#saturate saturate($color, $amount)}
+  # : Makes a color more saturated.
+  #
+  # \{#desaturate desaturate($color, $amount)}
+  # : Makes a color less saturated.
+  #
+  # \{#grayscale grayscale($color)}
+  # : Converts a color to grayscale.
+  #
+  # \{#complement complement($color)}
+  # : Returns the complement of a color.
+  #
+  # \{#invert invert($color)}
+  # : Returns the inverse of a color.
+  #
+  # ## Opacity Functions
+  #
+  # \{#alpha alpha($color)} / \{#opacity opacity($color)}
+  # : Gets the alpha component (opacity) of a color.
+  #
+  # \{#rgba rgba($color, $alpha)}
+  # : Changes the alpha component for a color.
+  #
+  # \{#opacify opacify($color, $amount)} / \{#fade_in fade-in($color, $amount)}
+  # : Makes a color more opaque.
+  #
+  # \{#transparentize transparentize($color, $amount)} / \{#fade_out fade-out($color, $amount)}
+  # : Makes a color more transparent.
+  #
+  # ## Other Color Functions
+  #
+  # \{#adjust_color adjust-color($color, \[$red\], \[$green\], \[$blue\], \[$hue\], \[$saturation\], 
\[$lightness\], \[$alpha\])}
+  # : Increases or decreases one or more components of a color.
+  #
+  # \{#scale_color scale-color($color, \[$red\], \[$green\], \[$blue\], \[$saturation\], \[$lightness\], 
\[$alpha\])}
+  # : Fluidly scales one or more properties of a color.
+  #
+  # \{#change_color change-color($color, \[$red\], \[$green\], \[$blue\], \[$hue\], \[$saturation\], 
\[$lightness\], \[$alpha\])}
+  # : Changes one or more properties of a color.
+  #
+  # \{#ie_hex_str ie-hex-str($color)}
+  # : Converts a color into the format understood by IE filters.
+  #
+  # ## String Functions
+  #
+  # \{#unquote unquote($string)}
+  # : Removes quotes from a string.
+  #
+  # \{#quote quote($string)}
+  # : Adds quotes to a string.
+  #
+  # ## Number Functions
+  #
+  # \{#percentage percentage($value)}
+  # : Converts a unitless number to a percentage.
+  #
+  # \{#round round($value)}
+  # : Rounds a number to the nearest whole number.
+  #
+  # \{#ceil ceil($value)}
+  # : Rounds a number up to the next whole number.
+  #
+  # \{#floor floor($value)}
+  # : Rounds a number down to the previous whole number.
+  #
+  # \{#abs abs($value)}
+  # : Returns the absolute value of a number.
+  #
+  # \{#min min($numbers...)\}
+  # : Finds the minimum of several numbers.
+  #
+  # \{#max max($numbers...)\}
+  # : Finds the maximum of several numbers.
+  #
+  # ## List Functions {#list-functions}
+  #
+  # \{#length length($list)}
+  # : Returns the length of a list.
+  #
+  # \{#nth nth($list, $n)}
+  # : Returns a specific item in a list.
+  #
+  # \{#join join($list1, $list2, \[$separator\])}
+  # : Joins together two lists into one.
+  #
+  # \{#append append($list1, $val, \[$separator\])}
+  # : Appends a single value onto the end of a list.
+  #
+  # \{#zip zip($lists...)}
+  # : Combines several lists into a single multidimensional list.
+  #
+  # \{#index index($list, $value)}
+  # : Returns the position of a value within a list.
+  #
+  # ## Introspection Functions
+  #
+  # \{#type_of type-of($value)}
+  # : Returns the type of a value.
+  #
+  # \{#unit unit($number)}
+  # : Returns the unit(s) associated with a number.
+  #
+  # \{#unitless unitless($number)}
+  # : Returns whether a number has units.
+  #
+  # \{#comparable comparable($number-1, $number-2)}
+  # : Returns whether two numbers can be added, subtracted, or compared.
+  #
+  # ## Miscellaneous Functions
+  #
+  # \{#if if($condition, $if-true, $if-false)}
+  # : Returns one of two values, depending on whether or not `$condition` is
+  #   true.
+  #
+  # ## Adding Custom Functions
+  #
+  # New Sass functions can be added by adding Ruby methods to this module.
+  # For example:
+  #
+  #     module Sass::Script::Functions
+  #       def reverse(string)
+  #         assert_type string, :String
+  #         Sass::Script::String.new(string.value.reverse)
+  #       end
+  #       declare :reverse, :args => [:string]
+  #     end
+  #
+  # Calling {declare} tells Sass the argument names for your function.
+  # If omitted, the function will still work, but will not be able to accept keyword arguments.
+  # {declare} can also allow your function to take arbitrary keyword arguments.
+  #
+  # There are a few things to keep in mind when modifying this module.
+  # First of all, the arguments passed are {Sass::Script::Literal} objects.
+  # Literal objects are also expected to be returned.
+  # This means that Ruby values must be unwrapped and wrapped.
+  #
+  # Most Literal objects support the {Sass::Script::Literal#value value} accessor
+  # for getting their Ruby values.
+  # Color objects, though, must be accessed using {Sass::Script::Color#rgb rgb},
+  # {Sass::Script::Color#red red}, {Sass::Script::Color#blue green}, or {Sass::Script::Color#blue blue}.
+  #
+  # Second, making Ruby functions accessible from Sass introduces the temptation
+  # to do things like database access within stylesheets.
+  # This is generally a bad idea;
+  # since Sass files are by default only compiled once,
+  # dynamic code is not a great fit.
+  #
+  # If you really, really need to compile Sass on each request,
+  # first make sure you have adequate caching set up.
+  # Then you can use {Sass::Engine} to render the code,
+  # using the {file:SASS_REFERENCE.md#custom-option `options` parameter}
+  # to pass in data that {EvaluationContext#options can be accessed}
+  # from your Sass functions.
+  #
+  # Within one of the functions in this module,
+  # methods of {EvaluationContext} can be used.
+  #
+  # ### Caveats
+  #
+  # When creating new {Literal} objects within functions,
+  # be aware that it's not safe to call {Literal#to_s #to_s}
+  # (or other methods that use the string representation)
+  # on those objects without first setting {Node#options= the #options attribute}.
+  module Functions
+    @signatures = {}
+
+    # A class representing a Sass function signature.
+    #
+    # @attr args [Array<Symbol>] The names of the arguments to the function.
+    # @attr var_args [Boolean] Whether the function takes a variable number of arguments.
+    # @attr var_kwargs [Boolean] Whether the function takes an arbitrary set of keyword arguments.
+    Signature = Struct.new(:args, :var_args, :var_kwargs)
+
+    # Declare a Sass signature for a Ruby-defined function.
+    # This includes the names of the arguments,
+    # whether the function takes a variable number of arguments,
+    # and whether the function takes an arbitrary set of keyword arguments.
+    #
+    # It's not necessary to declare a signature for a function.
+    # However, without a signature it won't support keyword arguments.
+    #
+    # A single function can have multiple signatures declared
+    # as long as each one takes a different number of arguments.
+    # It's also possible to declare multiple signatures
+    # that all take the same number of arguments,
+    # but none of them but the first will be used
+    # unless the user uses keyword arguments.
+    #
+    # @example
+    #   declare :rgba, [:hex, :alpha]
+    #   declare :rgba, [:red, :green, :blue, :alpha]
+    #   declare :accepts_anything, [], :var_args => true, :var_kwargs => true
+    #   declare :some_func, [:foo, :bar, :baz], :var_kwargs => true
+    #
+    # @param method_name [Symbol] The name of the method
+    #   whose signature is being declared.
+    # @param args [Array<Symbol>] The names of the arguments for the function signature.
+    # @option options :var_args [Boolean] (false)
+    #   Whether the function accepts a variable number of (unnamed) arguments
+    #   in addition to the named arguments.
+    # @option options :var_kwargs [Boolean] (false)
+    #   Whether the function accepts other keyword arguments
+    #   in addition to those in `:args`.
+    #   If this is true, the Ruby function will be passed a hash from strings
+    #   to {Sass::Script::Literal}s as the last argument.
+    #   In addition, if this is true and `:var_args` is not,
+    #   Sass will ensure that the last argument passed is a hash.
+    def self.declare(method_name, args, options = {})
+      @signatures[method_name] ||= []
+      @signatures[method_name] << Signature.new(
+        args.map {|s| s.to_s},
+        options[:var_args],
+        options[:var_kwargs])
+    end
+
+    # Determine the correct signature for the number of arguments
+    # passed in for a given function.
+    # If no signatures match, the first signature is returned for error messaging.
+    #
+    # @param method_name [Symbol] The name of the Ruby function to be called.
+    # @param arg_arity [Number] The number of unnamed arguments the function was passed.
+    # @param kwarg_arity [Number] The number of keyword arguments the function was passed.
+    #
+    # @return [{Symbol => Object}, nil]
+    #   The signature options for the matching signature,
+    #   or nil if no signatures are declared for this function. See {declare}.
+    def self.signature(method_name, arg_arity, kwarg_arity)
+      return unless @signatures[method_name]
+      @signatures[method_name].each do |signature|
+        return signature if signature.args.size == arg_arity + kwarg_arity
+        next unless signature.args.size < arg_arity + kwarg_arity
+
+        # We have enough args.
+        # Now we need to figure out which args are varargs
+        # and if the signature allows them.
+        t_arg_arity, t_kwarg_arity = arg_arity, kwarg_arity
+        if signature.args.size > t_arg_arity
+          # we transfer some kwargs arity to args arity
+          # if it does not have enough args -- assuming the names will work out.
+          t_kwarg_arity -= (signature.args.size - t_arg_arity)
+          t_arg_arity = signature.args.size
+        end
+
+        if (  t_arg_arity == signature.args.size ||   t_arg_arity > signature.args.size && 
signature.var_args  ) &&
+           (t_kwarg_arity == 0                   || t_kwarg_arity > 0                   && 
signature.var_kwargs)
+          return signature
+        end
+      end
+      @signatures[method_name].first
+    end
+
+    # The context in which methods in {Script::Functions} are evaluated.
+    # That means that all instance methods of {EvaluationContext}
+    # are available to use in functions.
+    class EvaluationContext
+      include Functions
+
+      # The options hash for the {Sass::Engine} that is processing the function call
+      #
+      # @return [{Symbol => Object}]
+      attr_reader :options
+
+      # @param options [{Symbol => Object}] See \{#options}
+      def initialize(options)
+        @options = options
+      end
+
+      # Asserts that the type of a given SassScript value
+      # is the expected type (designated by a symbol).
+      #
+      # Valid types are `:Bool`, `:Color`, `:Number`, and `:String`.
+      # Note that `:String` will match both double-quoted strings
+      # and unquoted identifiers.
+      #
+      # @example
+      #   assert_type value, :String
+      #   assert_type value, :Number
+      # @param value [Sass::Script::Literal] A SassScript value
+      # @param type [Symbol] The name of the type the value is expected to be
+      # @param name [String, Symbol, nil] The name of the argument.
+      def assert_type(value, type, name = nil)
+        return if value.is_a?(Sass::Script.const_get(type))
+        err = "#{value.inspect} is not a #{type.to_s.downcase}"
+        err = "$#{name.to_s.gsub('_', '-')}: " + err if name
+        raise ArgumentError.new(err)
+      end
+    end
+
+    class << self
+      # Returns whether user function with a given name exists.
+      #
+      # @param function_name [String]
+      # @return [Boolean]
+      alias_method :callable?, :public_method_defined?
+
+      private
+      def include(*args)
+        r = super
+        # We have to re-include ourselves into EvaluationContext to work around
+        # an icky Ruby restriction.
+        EvaluationContext.send :include, self
+        r
+      end
+    end
+
+    # Creates a {Color} object from red, green, and blue values.
+    #
+    # @see #rgba
+    # @overload rgb($red, $green, $blue)
+    # @param $red [Number] The amount of red in the color. Must be between 0 and
+    #   255 inclusive, or between `0%` and `100%` inclusive
+    # @param $green [Number] The amount of green in the color. Must be between 0
+    #   and 255 inclusive, or between `0%` and `100%` inclusive
+    # @param $blue [Number] The amount of blue in the color. Must be between 0
+    #   and 255 inclusive, or between `0%` and `100%` inclusive
+    # @return [Color]
+    # @raise [ArgumentError] if any parameter is the wrong type or out of bounds
+    def rgb(red, green, blue)
+      assert_type red, :Number, :red
+      assert_type green, :Number, :green
+      assert_type blue, :Number, :blue
+
+      Color.new([[red, :red], [green, :green], [blue, :blue]].map do |(c, name)|
+          v = c.value
+          if c.numerator_units == ["%"] && c.denominator_units.empty?
+            v = Sass::Util.check_range("$#{name}: Color value", 0..100, c, '%')
+            v * 255 / 100.0
+          else
+            Sass::Util.check_range("$#{name}: Color value", 0..255, c)
+          end
+        end)
+    end
+    declare :rgb, [:red, :green, :blue]
+
+    # Creates a {Color} from red, green, blue, and alpha values.
+    # @see #rgb
+    #
+    # @overload rgba($red, $green, $blue, $alpha)
+    #   @param $red [Number] The amount of red in the color. Must be between 0
+    #     and 255 inclusive
+    #   @param $green [Number] The amount of green in the color. Must be between
+    #     0 and 255 inclusive
+    #   @param $blue [Number] The amount of blue in the color. Must be between 0
+    #     and 255 inclusive
+    #   @param $alpha [Number] The opacity of the color. Must be between 0 and 1
+    #     inclusive
+    #   @return [Color]
+    #   @raise [ArgumentError] if any parameter is the wrong type or out of
+    #     bounds
+    #
+    # @overload rgba($color, $alpha)
+    #   Sets the opacity of an existing color.
+    #
+    #   @example
+    #     rgba(#102030, 0.5) => rgba(16, 32, 48, 0.5)
+    #     rgba(blue, 0.2)    => rgba(0, 0, 255, 0.2)
+    #
+    #   @param $color [Color] The color whose opacity will be changed.
+    #   @param $alpha [Number] The new opacity of the color. Must be between 0
+    #     and 1 inclusive
+    #   @return [Color]
+    #   @raise [ArgumentError] if `$alpha` is out of bounds or either parameter
+    #     is the wrong type
+    def rgba(*args)
+      case args.size
+      when 2
+        color, alpha = args
+
+        assert_type color, :Color, :color
+        assert_type alpha, :Number, :alpha
+
+        Sass::Util.check_range('Alpha channel', 0..1, alpha)
+        color.with(:alpha => alpha.value)
+      when 4
+        red, green, blue, alpha = args
+        rgba(rgb(red, green, blue), alpha)
+      else
+        raise ArgumentError.new("wrong number of arguments (#{args.size} for 4)")
+      end
+    end
+    declare :rgba, [:red, :green, :blue, :alpha]
+    declare :rgba, [:color, :alpha]
+
+    # Creates a {Color} from hue, saturation, and lightness values. Uses the
+    # algorithm from the [CSS3 spec][].
+    #
+    # [CSS3 spec]: http://www.w3.org/TR/css3-color/#hsl-color
+    #
+    # @see #hsla
+    # @overload hsl($hue, $saturation, $lightness)
+    # @param $hue [Number] The hue of the color. Should be between 0 and 360
+    #   degrees, inclusive
+    # @param $saturation [Number] The saturation of the color. Must be between
+    #   `0%` and `100%`, inclusive
+    # @param $lightness [Number] The lightness of the color. Must be between
+    #   `0%` and `100%`, inclusive
+    # @return [Color]
+    # @raise [ArgumentError] if `$saturation` or `$lightness` are out of bounds
+    #   or any parameter is the wrong type
+    def hsl(hue, saturation, lightness)
+      hsla(hue, saturation, lightness, Number.new(1))
+    end
+    declare :hsl, [:hue, :saturation, :lightness]
+
+    # Creates a {Color} from hue, saturation, lightness, and alpha
+    # values. Uses the algorithm from the [CSS3 spec][].
+    #
+    # [CSS3 spec]: http://www.w3.org/TR/css3-color/#hsl-color
+    #
+    # @see #hsl
+    # @overload hsla($hue, $saturation, $lightness, $alpha)
+    # @param $hue [Number] The hue of the color. Should be between 0 and 360
+    #   degrees, inclusive
+    # @param $saturation [Number] The saturation of the color. Must be between
+    #   `0%` and `100%`, inclusive
+    # @param $lightness [Number] The lightness of the color. Must be between
+    #   `0%` and `100%`, inclusive
+    # @param $alpha [Number] The opacity of the color. Must be between 0 and 1,
+    #   inclusive
+    # @return [Color]
+    # @raise [ArgumentError] if `$saturation`, `$lightness`, or `$alpha` are out
+    #   of bounds or any parameter is the wrong type
+    def hsla(hue, saturation, lightness, alpha)
+      assert_type hue, :Number, :hue
+      assert_type saturation, :Number, :saturation
+      assert_type lightness, :Number, :lightness
+      assert_type alpha, :Number, :alpha
+
+      Sass::Util.check_range('Alpha channel', 0..1, alpha)
+
+      h = hue.value
+      s = Sass::Util.check_range('Saturation', 0..100, saturation, '%')
+      l = Sass::Util.check_range('Lightness', 0..100, lightness, '%')
+
+      Color.new(:hue => h, :saturation => s, :lightness => l, :alpha => alpha.value)
+    end
+    declare :hsla, [:hue, :saturation, :lightness, :alpha]
+
+    # Gets the red component of a color. Calculated from HSL where necessary via
+    # [this algorithm][hsl-to-rgb].
+    #
+    # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
+    #
+    # @overload red($color)
+    # @param $color [Color]
+    # @return [Number] The red component, between 0 and 255 inclusive
+    # @raise [ArgumentError] if `$color` isn't a color
+    def red(color)
+      assert_type color, :Color, :color
+      Sass::Script::Number.new(color.red)
+    end
+    declare :red, [:color]
+
+    # Gets the green component of a color. Calculated from HSL where necessary
+    # via [this algorithm][hsl-to-rgb].
+    #
+    # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
+    #
+    # @overload green($color)
+    # @param $color [Color]
+    # @return [Number] The green component, between 0 and 255 inclusive
+    # @raise [ArgumentError] if `$color` isn't a color
+    def green(color)
+      assert_type color, :Color, :color
+      Sass::Script::Number.new(color.green)
+    end
+    declare :green, [:color]
+
+    # Gets the blue component of a color. Calculated from HSL where necessary
+    # via [this algorithm][hsl-to-rgb].
+    #
+    # [hsl-to-rgb]: http://www.w3.org/TR/css3-color/#hsl-color
+    #
+    # @overload blue($color)
+    # @param $color [Color]
+    # @return [Number] The blue component, between 0 and 255 inclusive
+    # @raise [ArgumentError] if `$color` isn't a color
+    def blue(color)
+      assert_type color, :Color, :color
+      Sass::Script::Number.new(color.blue)
+    end
+    declare :blue, [:color]
+
+    # Returns the hue component of a color. See [the CSS3 HSL
+    # specification][hsl]. Calculated from RGB where necessary via [this
+    # algorithm][rgb-to-hsl].
+    #
+    # [hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
+    # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
+    #
+    # @overload hue($color)
+    # @param $color [Color]
+    # @return [Number] The hue component, between 0deg and 360deg
+    # @raise [ArgumentError] if `$color` isn't a color
+    def hue(color)
+      assert_type color, :Color, :color
+      Sass::Script::Number.new(color.hue, ["deg"])
+    end
+    declare :hue, [:color]
+
+    # Returns the saturation component of a color. See [the CSS3 HSL
+    # specification][hsl]. Calculated from RGB where necessary via [this
+    # algorithm][rgb-to-hsl].
+    #
+    # [hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
+    # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
+    #
+    # @overload saturation($color)
+    # @param $color [Color]
+    # @return [Number] The saturation component, between 0% and 100%
+    # @raise [ArgumentError] if `$color` isn't a color
+    def saturation(color)
+      assert_type color, :Color, :color
+      Sass::Script::Number.new(color.saturation, ["%"])
+    end
+    declare :saturation, [:color]
+
+    # Returns the lightness component of a color. See [the CSS3 HSL
+    # specification][hsl]. Calculated from RGB where necessary via [this
+    # algorithm][rgb-to-hsl].
+    #
+    # [hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
+    # [rgb-to-hsl]: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
+    #
+    # @overload lightness($color)
+    # @param $color [Color]
+    # @return [Number] The lightness component, between 0% and 100%
+    # @raise [ArgumentError] if `$color` isn't a color
+    def lightness(color)
+      assert_type color, :Color, :color
+      Sass::Script::Number.new(color.lightness, ["%"])
+    end
+    declare :lightness, [:color]
+
+    # Returns the alpha component (opacity) of a color. This is 1 unless
+    # otherwise specified.
+    #
+    # This function also supports the proprietary Microsoft `alpha(opacity=20)`
+    # syntax as a special case.
+    #
+    # @overload alpha($color)
+    # @param $color [Color]
+    # @return [Number] The alpha component, between 0 and 1
+    # @raise [ArgumentError] if `$color` isn't a color
+    def alpha(*args)
+      if args.all? do |a|
+          a.is_a?(Sass::Script::String) && a.type == :identifier &&
+            a.value =~ /^[a-zA-Z]+\s*=/
+        end
+        # Support the proprietary MS alpha() function
+        return Sass::Script::String.new("alpha(#{args.map {|a| a.to_s}.join(", ")})")
+      end
+
+      raise ArgumentError.new("wrong number of arguments (#{args.size} for 1)") if args.size != 1
+
+      assert_type args.first, :Color, :color
+      Sass::Script::Number.new(args.first.alpha)
+    end
+    declare :alpha, [:color]
+
+    # Returns the alpha component (opacity) of a color. This is 1 unless
+    # otherwise specified.
+    #
+    # @overload opacity($color)
+    # @param $color [Color]
+    # @return [Number] The alpha component, between 0 and 1
+    # @raise [ArgumentError] if `$color` isn't a color
+    def opacity(color)
+      return Sass::Script::String.new("opacity(#{color})") if color.is_a?(Sass::Script::Number)
+      assert_type color, :Color, :color
+      Sass::Script::Number.new(color.alpha)
+    end
+    declare :opacity, [:color]
+
+    # Makes a color more opaque. Takes a color and a number between 0 and 1, and
+    # returns a color with the opacity increased by that amount.
+    #
+    # @see #transparentize
+    # @example
+    #   opacify(rgba(0, 0, 0, 0.5), 0.1) => rgba(0, 0, 0, 0.6)
+    #   opacify(rgba(0, 0, 17, 0.8), 0.2) => #001
+    # @overload opacify($color, $amount)
+    # @param $color [Color]
+    # @param $amount [Number] The amount to increase the opacity by, between 0
+    #   and 1
+    # @return [Color]
+    # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
+    #   is the wrong type
+    def opacify(color, amount)
+      _adjust(color, amount, :alpha, 0..1, :+)
+    end
+    declare :opacify, [:color, :amount]
+
+    alias_method :fade_in, :opacify
+    declare :fade_in, [:color, :amount]
+
+    # Makes a color more transparent. Takes a color and a number between 0 and
+    # 1, and returns a color with the opacity decreased by that amount.
+    #
+    # @see #opacify
+    # @example
+    #   transparentize(rgba(0, 0, 0, 0.5), 0.1) => rgba(0, 0, 0, 0.4)
+    #   transparentize(rgba(0, 0, 0, 0.8), 0.2) => rgba(0, 0, 0, 0.6)
+    # @overload transparentize($color, $amount)
+    # @param $color [Color]
+    # @param $amount [Number] The amount to decrease the opacity by, between 0
+    #   and 1
+    # @return [Color]
+    # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
+    #   is the wrong type
+    def transparentize(color, amount)
+      _adjust(color, amount, :alpha, 0..1, :-)
+    end
+    declare :transparentize, [:color, :amount]
+
+    alias_method :fade_out, :transparentize
+    declare :fade_out, [:color, :amount]
+
+    # Makes a color lighter. Takes a color and a number between `0%` and `100%`,
+    # and returns a color with the lightness increased by that amount.
+    #
+    # @see #darken
+    # @example
+    #   lighten(hsl(0, 0%, 0%), 30%) => hsl(0, 0, 30)
+    #   lighten(#800, 20%) => #e00
+    # @overload lighten($color, $amount)
+    # @param $color [Color]
+    # @param $amount [Number] The amount to increase the lightness by, between
+    #   `0%` and `100%`
+    # @return [Color]
+    # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
+    #   is the wrong type
+    def lighten(color, amount)
+      _adjust(color, amount, :lightness, 0..100, :+, "%")
+    end
+    declare :lighten, [:color, :amount]
+
+    # Makes a color darker. Takes a color and a number between 0% and 100%, and
+    # returns a color with the lightness decreased by that amount.
+    #
+    # @see #lighten
+    # @example
+    #   darken(hsl(25, 100%, 80%), 30%) => hsl(25, 100%, 50%)
+    #   darken(#800, 20%) => #200
+    # @overload darken($color, $amount)
+    # @param $color [Color]
+    # @param $amount [Number] The amount to dencrease the lightness by, between
+    #   `0%` and `100%`
+    # @return [Color]
+    # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
+    #   is the wrong type
+    def darken(color, amount)
+      _adjust(color, amount, :lightness, 0..100, :-, "%")
+    end
+    declare :darken, [:color, :amount]
+
+    # Makes a color more saturated. Takes a color and a number between 0% and
+    # 100%, and returns a color with the saturation increased by that amount.
+    #
+    # @see #desaturate
+    # @example
+    #   saturate(hsl(120, 30%, 90%), 20%) => hsl(120, 50%, 90%)
+    #   saturate(#855, 20%) => #9e3f3f
+    # @overload saturate($color, $amount)
+    # @param $color [Color]
+    # @param $amount [Number] The amount to increase the saturation by, between
+    #   `0%` and `100%`
+    # @return [Color]
+    # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
+    #   is the wrong type
+    def saturate(color, amount = nil)
+      # Support the filter effects definition of saturate.
+      # https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html
+      return Sass::Script::String.new("saturate(#{color})") if amount.nil?
+      _adjust(color, amount, :saturation, 0..100, :+, "%")
+    end
+    declare :saturate, [:color, :amount]
+    declare :saturate, [:amount]
+
+    # Makes a color less saturated. Takes a color and a number between 0% and
+    # 100%, and returns a color with the saturation decreased by that value.
+    #
+    # @see #saturate
+    # @example
+    #   desaturate(hsl(120, 30%, 90%), 20%) => hsl(120, 10%, 90%)
+    #   desaturate(#855, 20%) => #726b6b
+    # @overload desaturate($color, $amount)
+    # @param $color [Color]
+    # @param $amount [Number] The amount to decrease the saturation by, between
+    #   `0%` and `100%`
+    # @return [Color]
+    # @raise [ArgumentError] if `$amount` is out of bounds, or either parameter
+    #   is the wrong type
+    def desaturate(color, amount)
+      _adjust(color, amount, :saturation, 0..100, :-, "%")
+    end
+    declare :desaturate, [:color, :amount]
+
+    # Changes the hue of a color. Takes a color and a number of degrees (usually
+    # between `-360deg` and `360deg`), and returns a color with the hue rotated
+    # along the color wheel by that amount.
+    #
+    # @example
+    #   adjust-hue(hsl(120, 30%, 90%), 60deg) => hsl(180, 30%, 90%)
+    #   adjust-hue(hsl(120, 30%, 90%), 060deg) => hsl(60, 30%, 90%)
+    #   adjust-hue(#811, 45deg) => #886a11
+    # @overload adjust_hue($color, $degrees)
+    # @param $color [Color]
+    # @param $degrees [Number] The number of degrees to rotate the hue
+    # @return [Color]
+    # @raise [ArgumentError] if either parameter is the wrong type
+    def adjust_hue(color, degrees)
+      assert_type color, :Color, :color
+      assert_type degrees, :Number, :degrees
+      color.with(:hue => color.hue + degrees.value)
+    end
+    declare :adjust_hue, [:color, :degrees]
+
+    # Converts a color into the format understood by IE filters.
+    #
+    # @example
+    #   ie-hex-str(#abc) => #FFAABBCC
+    #   ie-hex-str(#3322BB) => #FF3322BB
+    #   ie-hex-str(rgba(0, 255, 0, 0.5)) => #8000FF00
+    # @overload ie_hex_str($color)
+    # @param $color [Color]
+    # @return [String] The IE-formatted string representation of the color
+    # @raise [ArgumentError] if `$color` isn't a color
+    def ie_hex_str(color)
+      assert_type color, :Color, :color
+      alpha = (color.alpha * 255).round.to_s(16).rjust(2, '0')
+      Sass::Script::String.new("##{alpha}#{color.send(:hex_str)[1..-1]}".upcase)
+    end
+    declare :ie_hex_str, [:color]
+
+    # Increases or decreases one or more properties of a color. This can change
+    # the red, green, blue, hue, saturation, value, and alpha properties. The
+    # properties are specified as keyword arguments, and are added to or
+    # subtracted from the color's current value for that property.
+    #
+    # All properties are optional. You can't specify both RGB properties
+    # (`$red`, `$green`, `$blue`) and HSL properties (`$hue`, `$saturation`,
+    # `$value`) at the same time.
+    #
+    # @example
+    #   adjust-color(#102030, $blue: 5) => #102035
+    #   adjust-color(#102030, $red: -5, $blue: 5) => #0b2035
+    #   adjust-color(hsl(25, 100%, 80%), $lightness: -30%, $alpha: -0.4) => hsla(25, 100%, 50%, 0.6)
+    # @overload adjust_color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], 
[$alpha])
+    # @param $color [Color]
+    # @param $red [Number] The adjustment to make on the red component, between
+    #   -255 and 255 inclusive
+    # @param $green [Number] The adjustment to make on the green component,
+    #   between -255 and 255 inclusive
+    # @param $blue [Number] The adjustment to make on the blue component, between
+    #   -255 and 255 inclusive
+    # @param $hue [Number] The adjustment to make on the hue component, in
+    #   degrees
+    # @param $saturation [Number] The adjustment to make on the saturation
+    #   component, between `-100%` and `100%` inclusive
+    # @param $lightness [Number] The adjustment to make on the lightness
+    #   component, between `-100%` and `100%` inclusive
+    # @param $alpha [Number] The adjustment to make on the alpha component,
+    #   between -1 and 1 inclusive
+    # @return [Color]
+    # @raise [ArgumentError] if any parameter is the wrong type or out-of
+    #   bounds, or if RGB properties and HSL properties are adjusted at the
+    #   same time
+    def adjust_color(color, kwargs)
+      assert_type color, :Color, :color
+      with = Sass::Util.map_hash({
+          "red" => [-255..255, ""],
+          "green" => [-255..255, ""],
+          "blue" => [-255..255, ""],
+          "hue" => nil,
+          "saturation" => [-100..100, "%"],
+          "lightness" => [-100..100, "%"],
+          "alpha" => [-1..1, ""]
+        }) do |name, (range, units)|
+
+        next unless val = kwargs.delete(name)
+        assert_type val, :Number, name
+        Sass::Util.check_range("$#{name}: Amount", range, val, units) if range
+        adjusted = color.send(name) + val.value
+        adjusted = [0, Sass::Util.restrict(adjusted, range)].max if range
+        [name.to_sym, adjusted]
+      end
+
+      unless kwargs.empty?
+        name, val = kwargs.to_a.first
+        raise ArgumentError.new("Unknown argument $#{name} (#{val})")
+      end
+
+      color.with(with)
+    end
+    declare :adjust_color, [:color], :var_kwargs => true
+
+    # Fluidly scales one or more properties of a color. Unlike
+    # \{#adjust_color adjust-color}, which changes a color's properties by fixed
+    # amounts, \{#scale_color scale-color} fluidly changes them based on how
+    # high or low they already are. That means that lightening an already-light
+    # color with \{#scale_color scale-color} won't change the lightness much,
+    # but lightening a dark color by the same amount will change it more
+    # dramatically. This has the benefit of making `scale-color($color, ...)`
+    # have a similar effect regardless of what `$color` is.
+    #
+    # For example, the lightness of a color can be anywhere between `0%` and
+    # `100%`. If `scale-color($color, $lightness: 40%)` is called, the resulting
+    # color's lightness will be 40% of the way between its original lightness
+    # and 100. If `scale-color($color, $lightness: -40%)` is called instead, the
+    # lightness will be 40% of the way between the original and 0.
+    #
+    # This can change the red, green, blue, saturation, value, and alpha
+    # properties. The properties are specified as keyword arguments. All
+    # arguments should be percentages between `0%` and `100%`.
+    #
+    # All properties are optional. You can't specify both RGB properties
+    # (`$red`, `$green`, `$blue`) and HSL properties (`$saturation`, `$value`)
+    # at the same time.
+    #
+    # @example
+    #   scale-color(hsl(120, 70%, 80%), $lightness: 50%) => hsl(120, 70%, 90%)
+    #   scale-color(rgb(200, 150%, 170%), $green: -40%, $blue: 70%) => rgb(200, 90, 229)
+    #   scale-color(hsl(200, 70%, 80%), $saturation: -90%, $alpha: -30%) => hsla(200, 7%, 80%, 0.7)
+    # @overload scale_color($color, [$red], [$green], [$blue], [$saturation], [$lightness], [$alpha])
+    # @param $color [Color]
+    # @param $red [Number]
+    # @param $green [Number]
+    # @param $blue [Number]
+    # @param $saturation [Number]
+    # @param $lightness [Number]
+    # @param $alpha [Number]
+    # @return [Color]
+    # @raise [ArgumentError] if any parameter is the wrong type or out-of
+    #   bounds, or if RGB properties and HSL properties are adjusted at the
+    #   same time
+    def scale_color(color, kwargs)
+      assert_type color, :Color, :color
+      with = Sass::Util.map_hash({
+          "red" => 255,
+          "green" => 255,
+          "blue" => 255,
+          "saturation" => 100,
+          "lightness" => 100,
+          "alpha" => 1
+        }) do |name, max|
+
+        next unless val = kwargs.delete(name)
+        assert_type val, :Number, name
+        if !(val.numerator_units == ['%'] && val.denominator_units.empty?)
+          raise ArgumentError.new("$#{name}: Amount #{val} must be a % (e.g. #{val.value}%)")
+        else
+          Sass::Util.check_range("$#{name}: Amount", -100..100, val, '%')
+        end
+
+        current = color.send(name)
+        scale = val.value/100.0
+        diff = scale > 0 ? max - current : current
+        [name.to_sym, current + diff*scale]
+      end
+
+      unless kwargs.empty?
+        name, val = kwargs.to_a.first
+        raise ArgumentError.new("Unknown argument $#{name} (#{val})")
+      end
+
+      color.with(with)
+    end
+    declare :scale_color, [:color], :var_kwargs => true
+
+    # Changes one or more properties of a color. This can change the red, green,
+    # blue, hue, saturation, value, and alpha properties. The properties are
+    # specified as keyword arguments, and replace the color's current value for
+    # that property.
+    #
+    # All properties are optional. You can't specify both RGB properties
+    # (`$red`, `$green`, `$blue`) and HSL properties (`$hue`, `$saturation`,
+    # `$value`) at the same time.
+    #
+    # @example
+    #   change-color(#102030, $blue: 5) => #102005
+    #   change-color(#102030, $red: 120, $blue: 5) => #782005
+    #   change-color(hsl(25, 100%, 80%), $lightness: 40%, $alpha: 0.8) => hsla(25, 100%, 40%, 0.8)
+    # @overload change_color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], 
[$alpha])
+    # @param $color [Color]
+    # @param $red [Number] The new red component for the color, within 0 and 255
+    #   inclusive
+    # @param $green [Number] The new green component for the color, within 0 and
+    #   255 inclusive
+    # @param $blue [Number] The new blue component for the color, within 0 and
+    #   255 inclusive
+    # @param $hue [Number] The new hue component for the color, in degrees
+    # @param $saturation [Number] The new saturation component for the color,
+    #   between `0%` and `100%` inclusive
+    # @param $lightness [Number] The new lightness component for the color,
+    #   within `0%` and `100%` inclusive
+    # @param $alpha [Number] The new alpha component for the color, within 0 and
+    #   1 inclusive
+    # @return [Color]
+    # @raise [ArgumentError] if any parameter is the wrong type or out-of
+    #   bounds, or if RGB properties and HSL properties are adjusted at the
+    #   same time
+    def change_color(color, kwargs)
+      assert_type color, :Color, :color
+      with = Sass::Util.map_hash(%w[red green blue hue saturation lightness alpha]) do |name, max|
+        next unless val = kwargs.delete(name)
+        assert_type val, :Number, name
+        [name.to_sym, val.value]
+      end
+
+      unless kwargs.empty?
+        name, val = kwargs.to_a.first
+        raise ArgumentError.new("Unknown argument $#{name} (#{val})")
+      end
+
+      color.with(with)
+    end
+    declare :change_color, [:color], :var_kwargs => true
+
+    # Mixes two colors together. Specifically, takes the average of each of the
+    # RGB components, optionally weighted by the given percentage. The opacity
+    # of the colors is also considered when weighting the components.
+    #
+    # The weight specifies the amount of the first color that should be included
+    # in the returned color. The default, `50%`, means that half the first color
+    # and half the second color should be used. `25%` means that a quarter of
+    # the first color and three quarters of the second color should be used.
+    #
+    # @example
+    #   mix(#f00, #00f) => #7f007f
+    #   mix(#f00, #00f, 25%) => #3f00bf
+    #   mix(rgba(255, 0, 0, 0.5), #00f) => rgba(63, 0, 191, 0.75)
+    # @overload mix($color-1, $color-2, $weight: 50%)
+    # @param $color-1 [Color]
+    # @param $color-2 [Color]
+    # @param $weight [Number] The relative weight of each color. Closer to `0%`
+    #   gives more weight to `$color`, closer to `100%` gives more weight to
+    #   `$color2`
+    # @return [Color]
+    # @raise [ArgumentError] if `$weight` is out of bounds or any parameter is
+    #   the wrong type
+    def mix(color_1, color_2, weight = Number.new(50))
+      assert_type color_1, :Color, :color_1
+      assert_type color_2, :Color, :color_2
+      assert_type weight, :Number, :weight
+
+      Sass::Util.check_range("Weight", 0..100, weight, '%')
+
+      # This algorithm factors in both the user-provided weight (w) and the
+      # difference between the alpha values of the two colors (a) to decide how
+      # to perform the weighted average of the two RGB values.
+      #
+      # It works by first normalizing both parameters to be within [-1, 1],
+      # where 1 indicates "only use color_1", -1 indicates "only use color_2", and
+      # all values in between indicated a proportionately weighted average.
+      #
+      # Once we have the normalized variables w and a, we apply the formula
+      # (w + a)/(1 + w*a) to get the combined weight (in [-1, 1]) of color_1.
+      # This formula has two especially nice properties:
+      #
+      #   * When either w or a are -1 or 1, the combined weight is also that number
+      #     (cases where w * a == -1 are undefined, and handled as a special case).
+      #
+      #   * When a is 0, the combined weight is w, and vice versa.
+      #
+      # Finally, the weight of color_1 is renormalized to be within [0, 1]
+      # and the weight of color_2 is given by 1 minus the weight of color_1.
+      p = (weight.value/100.0).to_f
+      w = p*2 - 1
+      a = color_1.alpha - color_2.alpha
+
+      w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0
+      w2 = 1 - w1
+
+      rgb = color_1.rgb.zip(color_2.rgb).map {|v1, v2| v1*w1 + v2*w2}
+      alpha = color_1.alpha*p + color_2.alpha*(1-p)
+      Color.new(rgb + [alpha])
+    end
+    declare :mix, [:color_1, :color_2]
+    declare :mix, [:color_1, :color_2, :weight]
+
+    # Converts a color to grayscale. This is identical to `desaturate(color,
+    # 100%)`.
+    #
+    # @see #desaturate
+    # @overload grayscale($color)
+    # @param $color [Color]
+    # @return [Color]
+    # @raise [ArgumentError] if `$color` isn't a color
+    def grayscale(color)
+      return Sass::Script::String.new("grayscale(#{color})") if color.is_a?(Sass::Script::Number)
+      desaturate color, Number.new(100)
+    end
+    declare :grayscale, [:color]
+
+    # Returns the complement of a color. This is identical to `adjust-hue(color,
+    # 180deg)`.
+    #
+    # @see #adjust_hue #adjust-hue
+    # @overload complement($color)
+    # @param $color [Color]
+    # @return [Color]
+    # @raise [ArgumentError] if `$color` isn't a color
+    def complement(color)
+      adjust_hue color, Number.new(180)
+    end
+    declare :complement, [:color]
+
+    # Returns the inverse (negative) of a color. The red, green, and blue values
+    # are inverted, while the opacity is left alone.
+    #
+    # @overload invert($color)
+    # @param $color [Color]
+    # @return [Color]
+    # @raise [ArgumentError] if `$color` isn't a color
+    def invert(color)
+      return Sass::Script::String.new("invert(#{color})") if color.is_a?(Sass::Script::Number)
+
+      assert_type color, :Color, :color
+      color.with(
+        :red => (255 - color.red),
+        :green => (255 - color.green),
+        :blue => (255 - color.blue))
+    end
+    declare :invert, [:color]
+
+    # Removes quotes from a string. If the string is already unquoted, this will
+    # return it unmodified.
+    #
+    # @see #quote
+    # @example
+    #   unquote("foo") => foo
+    #   unquote(foo) => foo
+    # @overload unquote($string)
+    # @param $string [String]
+    # @return [String]
+    # @raise [ArgumentError] if `$string` isn't a string
+    def unquote(string)
+      if string.is_a?(Sass::Script::String)
+        Sass::Script::String.new(string.value, :identifier)
+      else
+        string
+      end
+    end
+    declare :unquote, [:string]
+
+    # Add quotes to a string if the string isn't quoted,
+    # or returns the same string if it is.
+    #
+    # @see #unquote
+    # @example
+    #   quote("foo") => "foo"
+    #   quote(foo) => "foo"
+    # @overload quote($string)
+    # @param $string [String]
+    # @return [String]
+    # @raise [ArgumentError] if `$string` isn't a string
+    def quote(string)
+      assert_type string, :String, :string
+      Sass::Script::String.new(string.value, :string)
+    end
+    declare :quote, [:string]
+
+    # Returns the type of a value.
+    #
+    # @example
+    #   type-of(100px)  => number
+    #   type-of(asdf)   => string
+    #   type-of("asdf") => string
+    #   type-of(true)   => bool
+    #   type-of(#fff)   => color
+    #   type-of(blue)   => color
+    # @overload type_of($value)
+    # @param $value [Literal] The value to inspect
+    # @return [String] The unquoted string name of the value's type
+    def type_of(value)
+      Sass::Script::String.new(value.class.name.gsub(/Sass::Script::/,'').downcase)
+    end
+    declare :type_of, [:value]
+
+    # Returns the unit(s) associated with a number. Complex units are sorted in
+    # alphabetical order by numerator and denominator.
+    #
+    # @example
+    #   unit(100) => ""
+    #   unit(100px) => "px"
+    #   unit(3em) => "em"
+    #   unit(10px * 5em) => "em*px"
+    #   unit(10px * 5em / 30cm / 1rem) => "em*px/cm*rem"
+    # @overload unit($number)
+    # @param $number [Number]
+    # @return [String] The unit(s) of the number, as a quoted string
+    # @raise [ArgumentError] if `$number` isn't a number
+    def unit(number)
+      assert_type number, :Number, :number
+      Sass::Script::String.new(number.unit_str, :string)
+    end
+    declare :unit, [:number]
+
+    # Returns whether a number has units.
+    #
+    # @example
+    #   unitless(100) => true
+    #   unitless(100px) => false
+    # @overload unitless($number)
+    # @param $number [Number]
+    # @return [Bool]
+    # @raise [ArgumentError] if `$number` isn't a number
+    def unitless(number)
+      assert_type number, :Number, :number
+      Sass::Script::Bool.new(number.unitless?)
+    end
+    declare :unitless, [:number]
+
+    # Returns whether two numbers can added, subtracted, or compared.
+    #
+    # @example
+    #   comparable(2px, 1px) => true
+    #   comparable(100px, 3em) => false
+    #   comparable(10cm, 3mm) => true
+    # @overload comparable($number-1, $number-2)
+    # @param $number-1 [Number]
+    # @param $number-2 [Number]
+    # @return [Bool]
+    # @raise [ArgumentError] if either parameter is the wrong type
+    def comparable(number_1, number_2)
+      assert_type number_1, :Number, :number_1
+      assert_type number_2, :Number, :number_2
+      Sass::Script::Bool.new(number_1.comparable_to?(number_2))
+    end
+    declare :comparable, [:number_1, :number_2]
+
+    # Converts a unitless number to a percentage.
+    #
+    # @example
+    #   percentage(0.2) => 20%
+    #   percentage(100px / 50px) => 200%
+    # @overload percentage($value)
+    # @param $value [Number]
+    # @return [Number]
+    # @raise [ArgumentError] if `$value` isn't a unitless number
+    def percentage(value)
+      unless value.is_a?(Sass::Script::Number) && value.unitless?
+        raise ArgumentError.new("$value: #{value.inspect} is not a unitless number")
+      end
+      Sass::Script::Number.new(value.value * 100, ['%'])
+    end
+    declare :percentage, [:value]
+
+    # Rounds a number to the nearest whole number.
+    #
+    # @example
+    #   round(10.4px) => 10px
+    #   round(10.6px) => 11px
+    # @overload round($value)
+    # @param $value [Number]
+    # @return [Number]
+    # @raise [ArgumentError] if `$value` isn't a number
+    def round(value)
+      numeric_transformation(value) {|n| n.round}
+    end
+    declare :round, [:value]
+
+    # Rounds a number up to the next whole number.
+    #
+    # @example
+    #   ceil(10.4px) => 11px
+    #   ceil(10.6px) => 11px
+    # @overload ceil($value)
+    # @param $value [Number]
+    # @return [Number]
+    # @raise [ArgumentError] if `$value` isn't a number
+    def ceil(value)
+      numeric_transformation(value) {|n| n.ceil}
+    end
+    declare :ceil, [:value]
+
+    # Rounds a number down to the previous whole number.
+    #
+    # @example
+    #   floor(10.4px) => 10px
+    #   floor(10.6px) => 10px
+    # @overload floor($value)
+    # @param $value [Number]
+    # @return [Number]
+    # @raise [ArgumentError] if `$value` isn't a number
+    def floor(value)
+      numeric_transformation(value) {|n| n.floor}
+    end
+    declare :floor, [:value]
+
+    # Returns the absolute value of a number.
+    #
+    # @example
+    #   abs(10px) => 10px
+    #   abs(-10px) => 10px
+    # @overload abs($value)
+    # @param $value [Number]
+    # @return [Number]
+    # @raise [ArgumentError] if `$value` isn't a number
+    def abs(value)
+      numeric_transformation(value) {|n| n.abs}
+    end
+    declare :abs, [:value]
+
+    # Finds the minimum of several numbers. This function takes any number of
+    # arguments.
+    #
+    # @example
+    #   min(1px, 4px) => 1px
+    #   min(5em, 3em, 4em) => 3em
+    # @overload min($numbers...)
+    # @param $numbers [[Number]]
+    # @return [Number]
+    # @raise [ArgumentError] if any argument isn't a number, or if not all of
+    #   the arguments have comparable units
+    def min(*numbers)
+      numbers.each {|n| assert_type n, :Number}
+      numbers.inject {|min, num| min.lt(num).to_bool ? min : num}
+    end
+    declare :min, [], :var_args => :true
+
+    # Finds the maximum of several numbers. This function takes any number of
+    # arguments.
+    #
+    # @example
+    #   max(1px, 4px) => 4px
+    #   max(5em, 3em, 4em) => 5em
+    # @overload max($numbers...)
+    # @param $numbers [[Number]]
+    # @return [Number]
+    # @raise [ArgumentError] if any argument isn't a number, or if not all of
+    #   the arguments have comparable units
+    def max(*values)
+      values.each {|v| assert_type v, :Number}
+      values.inject {|max, val| max.gt(val).to_bool ? max : val}
+    end
+    declare :max, [], :var_args => :true
+
+    # Return the length of a list.
+    #
+    # @example
+    #   length(10px) => 1
+    #   length(10px 20px 30px) => 3
+    # @overload length($list)
+    # @param $list [Literal]
+    # @return [Number]
+    def length(list)
+      Sass::Script::Number.new(list.to_a.size)
+    end
+    declare :length, [:list]
+
+    # Gets the nth item in a list.
+    #
+    # Note that unlike some languages, the first item in a Sass list is number
+    # 1, the second number 2, and so forth.
+    #
+    # @example
+    #   nth(10px 20px 30px, 1) => 10px
+    #   nth((Helvetica, Arial, sans-serif), 3) => sans-serif
+    # @overload nth($list, $n)
+    # @param $list [Literal]
+    # @param $n [Number] The index of the item to get
+    # @return [Literal]
+    # @raise [ArgumentError] if `$n` isn't an integer between 1 and the length
+    #   of `$list`
+    def nth(list, n)
+      assert_type n, :Number, :n
+      if !n.int?
+        raise ArgumentError.new("List index #{n} must be an integer")
+      elsif n.to_i < 1
+        raise ArgumentError.new("List index #{n} must be greater than or equal to 1")
+      elsif list.to_a.size == 0
+        raise ArgumentError.new("List index is #{n} but list has no items")
+      elsif n.to_i > (size = list.to_a.size)
+        raise ArgumentError.new("List index is #{n} but list is only #{size} item#{'s' if size != 1} long")
+      end
+
+      list.to_a[n.to_i - 1]
+    end
+    declare :nth, [:list, :n]
+
+    # Joins together two lists into one.
+    #
+    # Unless `$separator` is passed, if one list is comma-separated and one is
+    # space-separated, the first parameter's separator is used for the resulting
+    # list. If both lists have fewer than two items, spaces are used for the
+    # resulting list.
+    #
+    # @example
+    #   join(10px 20px, 30px 40px) => 10px 20px 30px 40px
+    #   join((blue, red), (#abc, #def)) => blue, red, #abc, #def
+    #   join(10px, 20px) => 10px 20px
+    #   join(10px, 20px, comma) => 10px, 20px
+    #   join((blue, red), (#abc, #def), space) => blue red #abc #def
+    # @overload join($list1, $list2, $separator: auto)
+    # @param $list1 [Literal]
+    # @param $list2 [Literal]
+    # @param $separator [String] The list separator to use. If this is `comma`
+    #   or `space`, that separator will be used. If this is `auto` (the
+    #   default), the separator is determined as explained above.
+    # @return [List]
+    def join(list1, list2, separator = Sass::Script::String.new("auto"))
+      assert_type separator, :String, :separator
+      unless %w[auto space comma].include?(separator.value)
+        raise ArgumentError.new("Separator name must be space, comma, or auto")
+      end
+      sep1 = list1.separator if list1.is_a?(Sass::Script::List) && !list1.value.empty?
+      sep2 = list2.separator if list2.is_a?(Sass::Script::List) && !list2.value.empty?
+      Sass::Script::List.new(
+        list1.to_a + list2.to_a,
+        if separator.value == 'auto'
+          sep1 || sep2 || :space
+        else
+          separator.value.to_sym
+        end)
+    end
+    declare :join, [:list1, :list2]
+    declare :join, [:list1, :list2, :separator]
+
+    # Appends a single value onto the end of a list.
+    #
+    # Unless the `$separator` argument is passed, if the list had only one item,
+    # the resulting list will be space-separated.
+    #
+    # @example
+    #   append(10px 20px, 30px) => 10px 20px 30px
+    #   append((blue, red), green) => blue, red, green
+    #   append(10px 20px, 30px 40px) => 10px 20px (30px 40px)
+    #   append(10px, 20px, comma) => 10px, 20px
+    #   append((blue, red), green, space) => blue red green
+    # @overload append($list, $val, $separator: auto)
+    # @param $list [Literal]
+    # @param $val [Literal]
+    # @param $separator [String] The list separator to use. If this is `comma`
+    #   or `space`, that separator will be used. If this is `auto` (the
+    #   default), the separator is determined as explained above.
+    # @return [List]
+    def append(list, val, separator = Sass::Script::String.new("auto"))
+      assert_type separator, :String, :separator
+      unless %w[auto space comma].include?(separator.value)
+        raise ArgumentError.new("Separator name must be space, comma, or auto")
+      end
+      sep = list.separator if list.is_a?(Sass::Script::List)
+      Sass::Script::List.new(
+        list.to_a + [val],
+        if separator.value == 'auto'
+          sep || :space
+        else
+          separator.value.to_sym
+        end)
+    end
+    declare :append, [:list, :val]
+    declare :append, [:list, :val, :separator]
+
+    # Combines several lists into a single multidimensional list. The nth value
+    # of the resulting list is a space separated list of the source lists' nth
+    # values.
+    #
+    # The length of the resulting list is the length of the
+    # shortest list.
+    #
+    # @example
+    #   zip(1px 1px 3px, solid dashed solid, red green blue)
+    #   => 1px solid red, 1px dashed green, 3px solid blue
+    # @overload zip($lists...)
+    # @param $lists [[Literal]]
+    # @return [List]
+    def zip(*lists)
+      length = nil
+      values = []
+      lists.each do |list|
+        array = list.to_a
+        values << array.dup
+        length = length.nil? ? array.length : [length, array.length].min
+      end
+      values.each do |value|
+        value.slice!(length)
+      end
+      new_list_value = values.first.zip(*values[1..-1])
+      List.new(new_list_value.map{|list| List.new(list, :space)}, :comma)
+    end
+    declare :zip, [], :var_args => true
+
+
+    # Returns the position of a value within a list. If the value isn't found,
+    # returns false instead.
+    #
+    # Note that unlike some languages, the first item in a Sass list is number
+    # 1, the second number 2, and so forth.
+    #
+    # @example
+    #   index(1px solid red, solid) => 2
+    #   index(1px solid red, dashed) => false
+    # @overload index($list, $value)
+    # @param $list [Literal]
+    # @param $value [Literal]
+    # @return [Number, Bool] The 1-based index of `$value` in `$list`, or
+    #   `false`
+    def index(list, value)
+      index = list.to_a.index {|e| e.eq(value).to_bool }
+      if index
+        Number.new(index + 1)
+      else
+        Bool.new(false)
+      end
+    end
+    declare :index, [:list, :value]
+
+    # Returns one of two values, depending on whether or not `$condition` is
+    # true. Just like in ` if`, all values other than `false` and `null` are
+    # considered to be true.
+    #
+    # @example
+    #   if(true, 1px, 2px) => 1px
+    #   if(false, 1px, 2px) => 2px
+    # @overload if($condition, $if-true, $if-false)
+    # @param $condition [Literal] Whether the `$if-true` or `$if-false` will be
+    #   returned
+    # @param $if-true [Literal]
+    # @param $if-false [Literal]
+    # @return [Literal] `$if-true` or `$if-false`
+    def if(condition, if_true, if_false)
+      if condition.to_bool
+        if_true
+      else
+        if_false
+      end
+    end
+    declare :if, [:condition, :if_true, :if_false]
+
+    # This function only exists as a workaround for IE7's [`content: counter`
+    # bug][bug]. It works identically to any other plain-CSS function, except it
+    # avoids adding spaces between the argument commas.
+    #
+    # [bug]: http://jes.st/2013/ie7s-css-breaking-content-counter-bug/
+    #
+    # @example
+    #   counter(item, ".") => counter(item,".")
+    # @overload counter($args...)
+    # @return [String]
+    def counter(*args)
+      Sass::Script::String.new("counter(#{args.map {|a| a.to_s(options)}.join(',')})")
+    end
+    declare :counter, [], :var_args => true
+
+    # This function only exists as a workaround for IE7's [`content: counters`
+    # bug][bug]. It works identically to any other plain-CSS function, except it
+    # avoids adding spaces between the argument commas.
+    #
+    # [bug]: http://jes.st/2013/ie7s-css-breaking-content-counter-bug/
+    #
+    # @example
+    #   counters(item, ".") => counters(item,".")
+    # @overload counters($args...)
+    # @return [String]
+    def counters(*args)
+      Sass::Script::String.new("counters(#{args.map {|a| a.to_s(options)}.join(',')})")
+    end
+    declare :counters, [], :var_args => true
+
+    private
+
+    # This method implements the pattern of transforming a numeric value into
+    # another numeric value with the same units.
+    # It yields a number to a block to perform the operation and return a number
+    def numeric_transformation(value)
+      assert_type value, :Number, :value
+      Sass::Script::Number.new(yield(value.value), value.numerator_units, value.denominator_units)
+    end
+
+    def _adjust(color, amount, attr, range, op, units = "")
+      assert_type color, :Color, :color
+      assert_type amount, :Number, :amount
+      Sass::Util.check_range('Amount', range, amount, units)
+
+      # TODO: is it worth restricting here,
+      # or should we do so in the Color constructor itself,
+      # and allow clipping in rgb() et al?
+      color.with(attr => Sass::Util.restrict(
+          color.send(attr).send(op, amount.value), range))
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/interpolation.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/interpolation.rb
new file mode 100644
index 0000000..53902b1
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/interpolation.rb
@@ -0,0 +1,79 @@
+module Sass::Script
+  # A SassScript object representing `#{}` interpolation outside a string.
+  #
+  # @see StringInterpolation
+  class Interpolation < Node
+    # Interpolation in a property is of the form `before #{mid} after`.
+    #
+    # @param before [Node] The SassScript before the interpolation
+    # @param mid [Node] The SassScript within the interpolation
+    # @param after [Node] The SassScript after the interpolation
+    # @param wb [Boolean] Whether there was whitespace between `before` and `#{`
+    # @param wa [Boolean] Whether there was whitespace between `}` and `after`
+    # @param originally_text [Boolean]
+    #   Whether the original format of the interpolation was plain text,
+    #   not an interpolation.
+    #   This is used when converting back to SassScript.
+    def initialize(before, mid, after, wb, wa, originally_text = false)
+      @before = before
+      @mid = mid
+      @after = after
+      @whitespace_before = wb
+      @whitespace_after = wa
+      @originally_text = originally_text
+    end
+
+    # @return [String] A human-readable s-expression representation of the interpolation
+    def inspect
+      "(interpolation #{ before inspect} #{ mid inspect} #{ after inspect})"
+    end
+
+    # @see Node#to_sass
+    def to_sass(opts = {})
+      res = ""
+      res << @before.to_sass(opts) if @before
+      res << ' ' if @before && @whitespace_before
+      res << '#{' unless @originally_text
+      res << @mid.to_sass(opts)
+      res << '}' unless @originally_text
+      res << ' ' if @after && @whitespace_after
+      res << @after.to_sass(opts) if @after
+      res
+    end
+
+    # Returns the three components of the interpolation, `before`, `mid`, and `after`.
+    #
+    # @return [Array<Node>]
+    # @see #initialize
+    # @see Node#children
+    def children
+      [ before, @mid, @after].compact
+    end
+
+    # @see Node#deep_copy
+    def deep_copy
+      node = dup
+      node.instance_variable_set('@before', @before.deep_copy) if @before
+      node.instance_variable_set('@mid', @mid.deep_copy)
+      node.instance_variable_set('@after', @after.deep_copy) if @after
+      node
+    end
+
+    protected
+
+    # Evaluates the interpolation.
+    #
+    # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
+    # @return [Sass::Script::String] The SassScript string that is the value of the interpolation
+    def _perform(environment)
+      res = ""
+      res << @before.perform(environment).to_s if @before
+      res << " " if @before && @whitespace_before
+      val = @mid.perform(environment)
+      res << (val.is_a?(Sass::Script::String) ? val.value : val.to_s)
+      res << " " if @after && @whitespace_after
+      res << @after.perform(environment).to_s if @after
+      opts(Sass::Script::String.new(res))
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/lexer.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/lexer.rb
new file mode 100644
index 0000000..352c4a3
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/lexer.rb
@@ -0,0 +1,348 @@
+require 'sass/scss/rx'
+
+module Sass
+  module Script
+    # The lexical analyzer for SassScript.
+    # It takes a raw string and converts it to individual tokens
+    # that are easier to parse.
+    class Lexer
+      include Sass::SCSS::RX
+
+      # A struct containing information about an individual token.
+      #
+      # `type`: \[`Symbol`\]
+      # : The type of token.
+      #
+      # `value`: \[`Object`\]
+      # : The Ruby object corresponding to the value of the token.
+      #
+      # `line`: \[`Fixnum`\]
+      # : The line of the source file on which the token appears.
+      #
+      # `offset`: \[`Fixnum`\]
+      # : The number of bytes into the line the SassScript token appeared.
+      #
+      # `pos`: \[`Fixnum`\]
+      # : The scanner position at which the SassScript token appeared.
+      Token = Struct.new(:type, :value, :line, :offset, :pos)
+
+      # The line number of the lexer's current position.
+      #
+      # @return [Fixnum]
+      attr_reader :line
+
+      # The number of bytes into the current line
+      # of the lexer's current position.
+      #
+      # @return [Fixnum]
+      attr_reader :offset
+
+      # A hash from operator strings to the corresponding token types.
+      OPERATORS = {
+        '+' => :plus,
+        '-' => :minus,
+        '*' => :times,
+        '/' => :div,
+        '%' => :mod,
+        '=' => :single_eq,
+        ':' => :colon,
+        '(' => :lparen,
+        ')' => :rparen,
+        ',' => :comma,
+        'and' => :and,
+        'or' => :or,
+        'not' => :not,
+        '==' => :eq,
+        '!=' => :neq,
+        '>=' => :gte,
+        '<=' => :lte,
+        '>' => :gt,
+        '<' => :lt,
+        '#{' => :begin_interpolation,
+        '}' => :end_interpolation,
+        ';' => :semicolon,
+        '{' => :lcurly,
+        '...' => :splat,
+      }
+
+      OPERATORS_REVERSE = Sass::Util.map_hash(OPERATORS) {|k, v| [v, k]}
+
+      TOKEN_NAMES = Sass::Util.map_hash(OPERATORS_REVERSE) {|k, v| [k, v.inspect]}.merge({
+          :const => "variable (e.g. $foo)",
+          :ident => "identifier (e.g. middle)",
+          :bool => "boolean (e.g. true, false)",
+        })
+
+      # A list of operator strings ordered with longer names first
+      # so that `>` and `<` don't clobber `>=` and `<=`.
+      OP_NAMES = OPERATORS.keys.sort_by {|o| -o.size}
+
+      # A sub-list of {OP_NAMES} that only includes operators
+      # with identifier names.
+      IDENT_OP_NAMES = OP_NAMES.select {|k, v| k =~ /^\w+/}
+
+      # A hash of regular expressions that are used for tokenizing.
+      REGULAR_EXPRESSIONS = {
+        :whitespace => /\s+/,
+        :comment => COMMENT,
+        :single_line_comment => SINGLE_LINE_COMMENT,
+        :variable => /(\$)(#{IDENT})/,
+        :ident => /(#{IDENT})(\()?/,
+        :number => /(-)?(?:(\d*\.\d+)|(\d+))([a-zA-Z%]+)?/,
+        :color => HEXCOLOR,
+        :bool => /(true|false)\b/,
+        :null => /null\b/,
+        :ident_op => %r{(#{Regexp.union(*IDENT_OP_NAMES.map{|s| Regexp.new(Regexp.escape(s) + 
"(?!#{NMCHAR}|\Z)")})})},
+        :op => %r{(#{Regexp.union(*OP_NAMES)})},
+      }
+
+      class << self
+        private
+        def string_re(open, close)
+          /#{open}((?:\\.|\#(?!\{)|[^#{close}\\#])*)(#{close}|#\{)/
+        end
+      end
+
+      # A hash of regular expressions that are used for tokenizing strings.
+      #
+      # The key is a `[Symbol, Boolean]` pair.
+      # The symbol represents which style of quotation to use,
+      # while the boolean represents whether or not the string
+      # is following an interpolated segment.
+      STRING_REGULAR_EXPRESSIONS = {
+        [:double, false] => string_re('"', '"'),
+        [:single, false] => string_re("'", "'"),
+        [:double, true] => string_re('', '"'),
+        [:single, true] => string_re('', "'"),
+        [:uri, false] => /url\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/,
+        [:uri, true] => /(#{URLCHAR}*?)(#{W}\)|#\{)/,
+        # Defined in https://developer.mozilla.org/en/CSS/@-moz-document as a
+        # non-standard version of http://www.w3.org/TR/css3-conditional/
+        [:url_prefix, false] => /url-prefix\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/,
+        [:url_prefix, true] => /(#{URLCHAR}*?)(#{W}\)|#\{)/,
+        [:domain, false] => /domain\(#{W}(#{URLCHAR}*?)(#{W}\)|#\{)/,
+        [:domain, true] => /(#{URLCHAR}*?)(#{W}\)|#\{)/,
+      }
+
+      # @param str [String, StringScanner] The source text to lex
+      # @param line [Fixnum] The line on which the SassScript appears.
+      #   Used for error reporting
+      # @param offset [Fixnum] The number of characters in on which the SassScript appears.
+      #   Used for error reporting
+      # @param options [{Symbol => Object}] An options hash;
+      #   see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
+      def initialize(str, line, offset, options)
+        @scanner = str.is_a?(StringScanner) ? str : Sass::Util::MultibyteStringScanner.new(str)
+        @line = line
+        @offset = offset
+        @options = options
+        @interpolation_stack = []
+        @prev = nil
+      end
+
+      # Moves the lexer forward one token.
+      #
+      # @return [Token] The token that was moved past
+      def next
+        @tok ||= read_token
+        @tok, tok = nil, @tok
+        @prev = tok
+        return tok
+      end
+
+      # Returns whether or not there's whitespace before the next token.
+      #
+      # @return [Boolean]
+      def whitespace?(tok = @tok)
+        if tok
+          @scanner.string[0...tok.pos] =~ /\s\Z/
+        else
+          @scanner string[ scanner pos, 1] =~ /^\s/ ||
+            @scanner string[ scanner pos - 1, 1] =~ /\s\Z/
+        end
+      end
+
+      # Returns the next token without moving the lexer forward.
+      #
+      # @return [Token] The next token
+      def peek
+        @tok ||= read_token
+      end
+
+      # Rewinds the underlying StringScanner
+      # to before the token returned by \{#peek}.
+      def unpeek!
+        @scanner.pos = @tok.pos if @tok
+      end
+
+      # @return [Boolean] Whether or not there's more source text to lex.
+      def done?
+        whitespace unless after_interpolation? && @interpolation_stack.last
+        @scanner.eos? && @tok.nil?
+      end
+
+      # @return [Boolean] Whether or not the last token lexed was `:end_interpolation`.
+      def after_interpolation?
+        @prev && @prev.type == :end_interpolation
+      end
+
+      # Raise an error to the effect that `name` was expected in the input stream
+      # and wasn't found.
+      #
+      # This calls \{#unpeek!} to rewind the scanner to immediately after
+      # the last returned token.
+      #
+      # @param name [String] The name of the entity that was expected but not found
+      # @raise [Sass::SyntaxError]
+      def expected!(name)
+        unpeek!
+        Sass::SCSS::Parser.expected(@scanner, name, @line)
+      end
+
+      # Records all non-comment text the lexer consumes within the block
+      # and returns it as a string.
+      #
+      # @yield A block in which text is recorded
+      # @return [String]
+      def str
+        old_pos = @tok ? @tok.pos : @scanner.pos
+        yield
+        new_pos = @tok ? @tok.pos : @scanner.pos
+        @scanner.string[old_pos...new_pos]
+      end
+
+      private
+
+      def read_token
+        return if done?
+        return unless value = token
+        type, val, size = value
+        size ||= @scanner.matched_size
+
+        val.line = @line if val.is_a?(Script::Node)
+        Token.new(type, val, @line,
+          current_position - size, @scanner.pos - size)
+      end
+
+      def whitespace
+        nil while scan(REGULAR_EXPRESSIONS[:whitespace]) ||
+          scan(REGULAR_EXPRESSIONS[:comment]) ||
+          scan(REGULAR_EXPRESSIONS[:single_line_comment])
+      end
+
+      def token
+        if after_interpolation? && (interp_type = @interpolation_stack.pop)
+          return string(interp_type, true)
+        end
+
+        variable || string(:double, false) || string(:single, false) || number ||
+          color || bool || null || string(:uri, false) || raw(UNICODERANGE) ||
+          special_fun || special_val || ident_op || ident || op
+      end
+
+      def variable
+        _variable(REGULAR_EXPRESSIONS[:variable])
+      end
+
+      def _variable(rx)
+        return unless scan(rx)
+
+        [:const, @scanner[2]]
+      end
+
+      def ident
+        return unless scan(REGULAR_EXPRESSIONS[:ident])
+        [ scanner[2] ? :funcall : :ident, @scanner[1]]
+      end
+
+      def string(re, open)
+        return unless scan(STRING_REGULAR_EXPRESSIONS[[re, open]])
+        if @scanner[2] == '#{' #'
+          @scanner.pos -= 2 # Don't actually consume the #{
+          @interpolation_stack << re
+        end
+        str =
+          if re == :uri
+            Script::String.new("#{'url(' unless open}#{ scanner[1]}#{')' unless @scanner[2] == '#{'}")
+          else
+            Script::String.new(@scanner[1].gsub(/\\(['"]|\#\{)/, '\1'), :string)
+          end
+        [:string, str]
+      end
+
+      def number
+        return unless scan(REGULAR_EXPRESSIONS[:number])
+        value = @scanner[2] ? @scanner[2].to_f : @scanner[3].to_i
+        value = -value if @scanner[1]
+        [:number, Script::Number.new(value, Array(@scanner[4]))]
+      end
+
+      def color
+        return unless s = scan(REGULAR_EXPRESSIONS[:color])
+        raise Sass::SyntaxError.new(<<MESSAGE.rstrip) unless s.size == 4 || s.size == 7
+Colors must have either three or six digits: '#{s}'
+MESSAGE
+        value = s.scan(/^#(..?)(..?)(..?)$/).first.
+          map {|num| num.ljust(2, num).to_i(16)}
+        [:color, Script::Color.new(value)]
+      end
+
+      def bool
+        return unless s = scan(REGULAR_EXPRESSIONS[:bool])
+        [:bool, Script::Bool.new(s == 'true')]
+      end
+
+      def null
+        return unless scan(REGULAR_EXPRESSIONS[:null])
+        [:null, Script::Null.new]
+      end
+
+      def special_fun
+        return unless str1 = scan(/((-[\w-]+-)?(calc|element)|expression|progid:[a-z\.]*)\(/i)
+        str2, _ = Sass::Shared.balance(@scanner, ?(, ?), 1)
+        c = str2.count("\n")
+        old_line = @line
+        old_offset = @offset
+        @line += c
+        @offset = (c == 0 ? @offset + str2.size : str2[/\n(.*)/, 1].size)
+        [:special_fun,
+          Sass::Util.merge_adjacent_strings(
+            [str1] + Sass::Engine.parse_interp(str2, old_line, old_offset, @options)),
+          str1.size + str2.size]
+      end
+
+      def special_val
+        return unless scan(/!important/i)
+        [:string, Script::String.new("!important")]
+      end
+
+      def ident_op
+        return unless op = scan(REGULAR_EXPRESSIONS[:ident_op])
+        [OPERATORS[op]]
+      end
+
+      def op
+        return unless op = scan(REGULAR_EXPRESSIONS[:op])
+        @interpolation_stack << nil if op == :begin_interpolation
+        [OPERATORS[op]]
+      end
+
+      def raw(rx)
+        return unless val = scan(rx)
+        [:raw, val]
+      end
+
+      def scan(re)
+        return unless str = @scanner.scan(re)
+        c = str.count("\n")
+        @line += c
+        @offset = (c == 0 ? @offset + str.size : str[/\n(.*)/, 1].size)
+        str
+      end
+
+      def current_position
+        @offset + 1
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/list.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/list.rb
new file mode 100644
index 0000000..1f3dfd9
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/list.rb
@@ -0,0 +1,85 @@
+module Sass::Script
+  # A SassScript object representing a CSS list.
+  # This includes both comma-separated lists and space-separated lists.
+  class List < Literal
+    # The Ruby array containing the contents of the list.
+    #
+    # @return [Array<Literal>]
+    attr_reader :value
+    alias_method :children, :value
+    alias_method :to_a, :value
+
+    # The operator separating the values of the list.
+    # Either `:comma` or `:space`.
+    #
+    # @return [Symbol]
+    attr_reader :separator
+
+    # Creates a new list.
+    #
+    # @param value [Array<Literal>] See \{#value}
+    # @param separator [String] See \{#separator}
+    def initialize(value, separator)
+      super(value)
+      @separator = separator
+    end
+
+    # @see Node#deep_copy
+    def deep_copy
+      node = dup
+      node.instance_variable_set('@value', value.map {|c| c.deep_copy})
+      node
+    end
+
+    # @see Node#eq
+    def eq(other)
+      Sass::Script::Bool.new(
+        other.is_a?(List) && self.value == other.value &&
+        self.separator == other.separator)
+    end
+
+    # @see Node#to_s
+    def to_s(opts = {})
+      raise Sass::SyntaxError.new("() isn't a valid CSS value.") if value.empty?
+      return value.reject {|e| e.is_a?(Null) || e.is_a?(List) && e.value.empty?}.map {|e| 
e.to_s(opts)}.join(sep_str)
+    end
+
+    # @see Node#to_sass
+    def to_sass(opts = {})
+      return "()" if value.empty?
+      precedence = Sass::Script::Parser.precedence_of(separator)
+      value.reject {|e| e.is_a?(Null)}.map do |v|
+        if v.is_a?(List) && Sass::Script::Parser.precedence_of(v.separator) <= precedence ||
+            separator == :space && v.is_a?(UnaryOperation) && (v.operator == :minus || v.operator == :plus)
+          "(#{v.to_sass(opts)})"
+        else
+          v.to_sass(opts)
+        end
+      end.join(sep_str(nil))
+    end
+
+    # @see Node#inspect
+    def inspect
+      "(#{to_sass})"
+    end
+
+    protected
+
+    # @see Node#_perform
+    def _perform(environment)
+      list = Sass::Script::List.new(
+        value.map {|e| e.perform(environment)},
+        separator)
+      list.options = self.options
+      list
+    end
+
+    private
+
+    def sep_str(opts = self.options)
+      return ' ' if separator == :space
+      return ',' if opts && opts[:style] == :compressed
+      return ', '
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/literal.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/literal.rb
new file mode 100644
index 0000000..daef468
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/literal.rb
@@ -0,0 +1,221 @@
+module Sass::Script
+  # The abstract superclass for SassScript objects.
+  #
+  # Many of these methods, especially the ones that correspond to SassScript operations,
+  # are designed to be overridden by subclasses which may change the semantics somewhat.
+  # The operations listed here are just the defaults.
+  class Literal < Node
+    require 'sass/script/string'
+    require 'sass/script/number'
+    require 'sass/script/color'
+    require 'sass/script/bool'
+    require 'sass/script/null'
+    require 'sass/script/list'
+    require 'sass/script/arg_list'
+
+    # Returns the Ruby value of the literal.
+    # The type of this value varies based on the subclass.
+    #
+    # @return [Object]
+    attr_reader :value
+
+    # Creates a new literal.
+    #
+    # @param value [Object] The object for \{#value}
+    def initialize(value = nil)
+      @value = value
+      super()
+    end
+
+    # Returns an empty array.
+    #
+    # @return [Array<Node>] empty
+    # @see Node#children
+    def children
+      []
+    end
+
+    # @see Node#deep_copy
+    def deep_copy
+      dup
+    end
+
+    # Returns the options hash for this node.
+    #
+    # @return [{Symbol => Object}]
+    # @raise [Sass::SyntaxError] if the options hash hasn't been set.
+    #   This should only happen when the literal was created
+    #   outside of the parser and \{#to\_s} was called on it
+    def options
+      opts = super
+      return opts if opts
+      raise Sass::SyntaxError.new(<<MSG)
+The #options attribute is not set on this #{self.class}.
+  This error is probably occurring because #to_s was called
+  on this literal within a custom Sass function without first
+  setting the #option attribute.
+MSG
+    end
+
+    # The SassScript `==` operation.
+    # **Note that this returns a {Sass::Script::Bool} object,
+    # not a Ruby boolean**.
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Bool] True if this literal is the same as the other,
+    #   false otherwise
+    def eq(other)
+      Sass::Script::Bool.new(self.class == other.class && self.value == other.value)
+    end
+
+    # The SassScript `!=` operation.
+    # **Note that this returns a {Sass::Script::Bool} object,
+    # not a Ruby boolean**.
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Bool] False if this literal is the same as the other,
+    #   true otherwise
+    def neq(other)
+      Sass::Script::Bool.new(!eq(other).to_bool)
+    end
+
+    # The SassScript `==` operation.
+    # **Note that this returns a {Sass::Script::Bool} object,
+    # not a Ruby boolean**.
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Bool] True if this literal is the same as the other,
+    #   false otherwise
+    def unary_not
+      Sass::Script::Bool.new(!to_bool)
+    end
+
+    # The SassScript `=` operation
+    # (used for proprietary MS syntax like `alpha(opacity=20)`).
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Script::String] A string containing both literals
+    #   separated by `"="`
+    def single_eq(other)
+      Sass::Script::String.new("#{self.to_s}=#{other.to_s}")
+    end
+
+    # The SassScript `+` operation.
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Script::String] A string containing both literals
+    #   without any separation
+    def plus(other)
+      if other.is_a?(Sass::Script::String)
+        return Sass::Script::String.new(self.to_s + other.value, other.type)
+      end
+      Sass::Script::String.new(self.to_s + other.to_s)
+    end
+
+    # The SassScript `-` operation.
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Script::String] A string containing both literals
+    #   separated by `"-"`
+    def minus(other)
+      Sass::Script::String.new("#{self.to_s}-#{other.to_s}")
+    end
+
+    # The SassScript `/` operation.
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Script::String] A string containing both literals
+    #   separated by `"/"`
+    def div(other)
+      Sass::Script::String.new("#{self.to_s}/#{other.to_s}")
+    end
+
+    # The SassScript unary `+` operation (e.g. `+$a`).
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Script::String] A string containing the literal
+    #   preceded by `"+"`
+    def unary_plus
+      Sass::Script::String.new("+#{self.to_s}")
+    end
+
+    # The SassScript unary `-` operation (e.g. `-$a`).
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Script::String] A string containing the literal
+    #   preceded by `"-"`
+    def unary_minus
+      Sass::Script::String.new("-#{self.to_s}")
+    end
+
+    # The SassScript unary `/` operation (e.g. `/$a`).
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Script::String] A string containing the literal
+    #   preceded by `"/"`
+    def unary_div
+      Sass::Script::String.new("/#{self.to_s}")
+    end
+
+    # @return [String] A readable representation of the literal
+    def inspect
+      value.inspect
+    end
+
+    # @return [Boolean] `true` (the Ruby boolean value)
+    def to_bool
+      true
+    end
+
+    # Compares this object with another.
+    #
+    # @param other [Object] The object to compare with
+    # @return [Boolean] Whether or not this literal is equivalent to `other`
+    def ==(other)
+      eq(other).to_bool
+    end
+
+    # @return [Fixnum] The integer value of this literal
+    # @raise [Sass::SyntaxError] if this literal isn't an integer
+    def to_i
+      raise Sass::SyntaxError.new("#{self.inspect} is not an integer.")
+    end
+
+    # @raise [Sass::SyntaxError] if this literal isn't an integer
+    def assert_int!; to_i; end
+
+    # Returns the value of this literal as a list.
+    # Single literals are considered the same as single-element lists.
+    #
+    # @return [Array<Literal>] The of this literal as a list
+    def to_a
+      [self]
+    end
+
+    # Returns the string representation of this literal
+    # as it would be output to the CSS document.
+    #
+    # @return [String]
+    def to_s(opts = {})
+      raise Sass::SyntaxError.new("[BUG] All subclasses of Sass::Literal must implement #to_s.")
+    end
+    alias_method :to_sass, :to_s
+
+    # Returns whether or not this object is null.
+    #
+    # @return [Boolean] `false`
+    def null?
+      false
+    end
+
+    protected
+
+    # Evaluates the literal.
+    #
+    # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
+    # @return [Literal] This literal
+    def _perform(environment)
+      self
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/node.rb
new file mode 100644
index 0000000..bac6dd2
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/node.rb
@@ -0,0 +1,99 @@
+module Sass::Script
+  # The abstract superclass for SassScript parse tree nodes.
+  #
+  # Use \{#perform} to evaluate a parse tree.
+  class Node
+    # The options hash for this node.
+    #
+    # @return [{Symbol => Object}]
+    attr_reader :options
+
+    # The line of the document on which this node appeared.
+    #
+    # @return [Fixnum]
+    attr_accessor :line
+
+    # Sets the options hash for this node,
+    # as well as for all child nodes.
+    # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
+    #
+    # @param options [{Symbol => Object}] The options
+    def options=(options)
+      @options = options
+      children.each do |c|
+        if c.is_a? Hash
+          c.values.each {|v| v.options = options }
+        else
+          c.options = options
+        end
+      end
+    end
+
+    # Evaluates the node.
+    #
+    # \{#perform} shouldn't be overridden directly;
+    # instead, override \{#\_perform}.
+    #
+    # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
+    # @return [Literal] The SassScript object that is the value of the SassScript
+    def perform(environment)
+      _perform(environment)
+    rescue Sass::SyntaxError => e
+      e.modify_backtrace(:line => line)
+      raise e
+    end
+
+    # Returns all child nodes of this node.
+    #
+    # @return [Array<Node>]
+    def children
+      Sass::Util.abstract(self)
+    end
+
+    # Returns the text of this SassScript expression.
+    #
+    # @return [String]
+    def to_sass(opts = {})
+      Sass::Util.abstract(self)
+    end
+
+    # Returns a deep clone of this node.
+    # The child nodes are cloned, but options are not.
+    #
+    # @return [Node]
+    def deep_copy
+      Sass::Util.abstract(self)
+    end
+
+    protected
+
+    # Converts underscores to dashes if the :dasherize option is set.
+    def dasherize(s, opts)
+      if opts[:dasherize]
+        s.gsub(/_/,'-')
+      else
+        s
+      end
+    end
+
+    # Evaluates this node.
+    # Note that all {Literal} objects created within this method
+    # should have their \{#options} attribute set, probably via \{#opts}.
+    #
+    # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
+    # @return [Literal] The SassScript object that is the value of the SassScript
+    # @see #perform
+    def _perform(environment)
+      Sass::Util.abstract(self)
+    end
+
+    # Sets the \{#options} field on the given literal and returns it
+    #
+    # @param literal [Literal]
+    # @return [Literal]
+    def opts(literal)
+      literal.options = options
+      literal
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/null.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/null.rb
new file mode 100644
index 0000000..6f5b45f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/null.rb
@@ -0,0 +1,37 @@
+require 'sass/script/literal'
+
+module Sass::Script
+  # A SassScript object representing a null value.
+  class Null < Literal
+    # Creates a new null literal.
+    def initialize
+      super nil
+    end
+
+    # @return [Boolean] `false` (the Ruby boolean value)
+    def to_bool
+      false
+    end
+
+    # @return [Boolean] `true`
+    def null?
+      true
+    end
+
+    # @return [String] '' (An empty string)
+    def to_s(opts = {})
+      ''
+    end
+
+    def to_sass(opts = {})
+      'null'
+    end
+
+    # Returns a string representing a null value.
+    #
+    # @return [String]
+    def inspect
+      'null'
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/number.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/number.rb
new file mode 100644
index 0000000..1eac160
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/number.rb
@@ -0,0 +1,453 @@
+require 'sass/script/literal'
+
+module Sass::Script
+  # A SassScript object representing a number.
+  # SassScript numbers can have decimal values,
+  # and can also have units.
+  # For example, `12`, `1px`, and `10.45em`
+  # are all valid values.
+  #
+  # Numbers can also have more complex units, such as `1px*em/in`.
+  # These cannot be inputted directly in Sass code at the moment.
+  class Number < Literal
+    # The Ruby value of the number.
+    #
+    # @return [Numeric]
+    attr_reader :value
+
+    # A list of units in the numerator of the number.
+    # For example, `1px*em/in*cm` would return `["px", "em"]`
+    # @return [Array<String>] 
+    attr_reader :numerator_units
+
+    # A list of units in the denominator of the number.
+    # For example, `1px*em/in*cm` would return `["in", "cm"]`
+    # @return [Array<String>]
+    attr_reader :denominator_units
+
+    # The original representation of this number.
+    # For example, although the result of `1px/2px` is `0.5`,
+    # the value of `#original` is `"1px/2px"`.
+    #
+    # This is only non-nil when the original value should be used as the CSS value,
+    # as in `font: 1px/2px`.
+    #
+    # @return [Boolean, nil]
+    attr_accessor :original
+
+    def self.precision
+      @precision ||= 5
+    end
+
+    # Sets the number of digits of precision
+    # For example, if this is `3`,
+    # `3.1415926` will be printed as `3.142`.
+    def self.precision=(digits)
+      @precision = digits.round
+      @precision_factor = 10 0** precision
+    end
+
+    # the precision factor used in numeric output
+    # it is derived from the `precision` method.
+    def self.precision_factor
+      @precision_factor ||= 10.0**precision
+    end
+
+    # Handles the deprecation warning for the PRECISION constant
+    # This can be removed in 3.2.
+    def self.const_missing(const)
+      if const == :PRECISION
+        Sass::Util.sass_warn("Sass::Script::Number::PRECISION is deprecated and will be removed in a future 
release. Use Sass::Script::Number.precision_factor instead.")
+        const_set(:PRECISION, self.precision_factor)
+      else
+        super
+      end
+    end
+
+    # Used so we don't allocate two new arrays for each new number.
+    NO_UNITS  = []
+
+    # @param value [Numeric] The value of the number
+    # @param numerator_units [Array<String>] See \{#numerator\_units}
+    # @param denominator_units [Array<String>] See \{#denominator\_units}
+    def initialize(value, numerator_units = NO_UNITS, denominator_units = NO_UNITS)
+      super(value)
+      @numerator_units = numerator_units
+      @denominator_units = denominator_units
+      normalize!
+    end
+
+    # The SassScript `+` operation.
+    # Its functionality depends on the type of its argument:
+    #
+    # {Number}
+    # : Adds the two numbers together, converting units if possible.
+    #
+    # {Color}
+    # : Adds this number to each of the RGB color channels.
+    #
+    # {Literal}
+    # : See {Literal#plus}.
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Literal] The result of the operation
+    # @raise [Sass::UnitConversionError] if `other` is a number with incompatible units
+    def plus(other)
+      if other.is_a? Number
+        operate(other, :+)
+      elsif other.is_a?(Color)
+        other.plus(self)
+      else
+        super
+      end
+    end
+
+    # The SassScript binary `-` operation (e.g. `$a - $b`).
+    # Its functionality depends on the type of its argument:
+    #
+    # {Number}
+    # : Subtracts this number from the other, converting units if possible.
+    #
+    # {Literal}
+    # : See {Literal#minus}.
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Literal] The result of the operation
+    # @raise [Sass::UnitConversionError] if `other` is a number with incompatible units
+    def minus(other)
+      if other.is_a? Number
+        operate(other, :-)
+      else
+        super
+      end
+    end
+
+    # The SassScript unary `+` operation (e.g. `+$a`).
+    #
+    # @return [Number] The value of this number
+    def unary_plus
+      self
+    end
+
+    # The SassScript unary `-` operation (e.g. `-$a`).
+    #
+    # @return [Number] The negative value of this number
+    def unary_minus
+      Number.new(-value, @numerator_units, @denominator_units)
+    end
+
+    # The SassScript `*` operation.
+    # Its functionality depends on the type of its argument:
+    #
+    # {Number}
+    # : Multiplies the two numbers together, converting units appropriately.
+    #
+    # {Color}
+    # : Multiplies each of the RGB color channels by this number.
+    #
+    # @param other [Number, Color] The right-hand side of the operator
+    # @return [Number, Color] The result of the operation
+    # @raise [NoMethodError] if `other` is an invalid type
+    def times(other)
+      if other.is_a? Number
+        operate(other, :*)
+      elsif other.is_a? Color
+        other.times(self)
+      else
+        raise NoMethodError.new(nil, :times)
+      end
+    end
+
+    # The SassScript `/` operation.
+    # Its functionality depends on the type of its argument:
+    #
+    # {Number}
+    # : Divides this number by the other, converting units appropriately.
+    #
+    # {Literal}
+    # : See {Literal#div}.
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Literal] The result of the operation
+    def div(other)
+      if other.is_a? Number
+        res = operate(other, :/)
+        if self.original && other.original
+          res.original = "#{self.original}/#{other.original}"
+        end
+        res
+      else
+        super
+      end
+    end
+
+    # The SassScript `%` operation.
+    #
+    # @param other [Number] The right-hand side of the operator
+    # @return [Number] This number modulo the other
+    # @raise [NoMethodError] if `other` is an invalid type
+    # @raise [Sass::UnitConversionError] if `other` has any units
+    def mod(other)
+      if other.is_a?(Number)
+        unless other.unitless?
+          raise Sass::UnitConversionError.new("Cannot modulo by a number with units: #{other.inspect}.")
+        end
+        operate(other, :%)
+      else
+        raise NoMethodError.new(nil, :mod)
+      end
+    end
+
+    # The SassScript `==` operation.
+    #
+    # @param other [Literal] The right-hand side of the operator
+    # @return [Boolean] Whether this number is equal to the other object
+    def eq(other)
+      return Sass::Script::Bool.new(false) unless other.is_a?(Sass::Script::Number)
+      this = self
+      begin
+        if unitless?
+          this = this.coerce(other.numerator_units, other.denominator_units)
+        else
+          other = other.coerce(@numerator_units, @denominator_units)
+        end
+      rescue Sass::UnitConversionError
+        return Sass::Script::Bool.new(false)
+      end
+
+      Sass::Script::Bool.new(this.value == other.value)
+    end
+
+    # The SassScript `>` operation.
+    #
+    # @param other [Number] The right-hand side of the operator
+    # @return [Boolean] Whether this number is greater than the other
+    # @raise [NoMethodError] if `other` is an invalid type
+    def gt(other)
+      raise NoMethodError.new(nil, :gt) unless other.is_a?(Number)
+      operate(other, :>)
+    end
+
+    # The SassScript `>=` operation.
+    #
+    # @param other [Number] The right-hand side of the operator
+    # @return [Boolean] Whether this number is greater than or equal to the other
+    # @raise [NoMethodError] if `other` is an invalid type
+    def gte(other)
+      raise NoMethodError.new(nil, :gte) unless other.is_a?(Number)
+      operate(other, :>=)
+    end
+
+    # The SassScript `<` operation.
+    #
+    # @param other [Number] The right-hand side of the operator
+    # @return [Boolean] Whether this number is less than the other
+    # @raise [NoMethodError] if `other` is an invalid type
+    def lt(other)
+      raise NoMethodError.new(nil, :lt) unless other.is_a?(Number)
+      operate(other, :<)
+    end
+
+    # The SassScript `<=` operation.
+    #
+    # @param other [Number] The right-hand side of the operator
+    # @return [Boolean] Whether this number is less than or equal to the other
+    # @raise [NoMethodError] if `other` is an invalid type
+    def lte(other)
+      raise NoMethodError.new(nil, :lte) unless other.is_a?(Number)
+      operate(other, :<=)
+    end
+
+    # @return [String] The CSS representation of this number
+    # @raise [Sass::SyntaxError] if this number has units that can't be used in CSS
+    #   (e.g. `px*in`)
+    def to_s(opts = {})
+      return original if original
+      raise Sass::SyntaxError.new("#{inspect} isn't a valid CSS value.") unless legal_units?
+      inspect
+    end
+
+    # Returns a readable representation of this number.
+    #
+    # This representation is valid CSS (and valid SassScript)
+    # as long as there is only one unit.
+    #
+    # @return [String] The representation
+    def inspect(opts = {})
+      value = self.class.round(self.value)
+      unitless? ? value.to_s : "#{value}#{unit_str}"
+    end
+    alias_method :to_sass, :inspect
+
+    # @return [Fixnum] The integer value of the number
+    # @raise [Sass::SyntaxError] if the number isn't an integer
+    def to_i
+      super unless int?
+      return value
+    end
+
+    # @return [Boolean] Whether or not this number is an integer.
+    def int?
+      value % 1 == 0.0
+    end
+
+    # @return [Boolean] Whether or not this number has no units.
+    def unitless?
+      @numerator_units.empty? && @denominator_units.empty?
+    end
+
+    # @return [Boolean] Whether or not this number has units that can be represented in CSS
+    #   (that is, zero or one \{#numerator\_units}).
+    def legal_units?
+      (@numerator_units.empty? || @numerator_units.size == 1) && @denominator_units.empty?
+    end
+
+    # Returns this number converted to other units.
+    # The conversion takes into account the relationship between e.g. mm and cm,
+    # as well as between e.g. in and cm.
+    #
+    # If this number has no units, it will simply return itself
+    # with the given units.
+    #
+    # An incompatible coercion, e.g. between px and cm, will raise an error.
+    #
+    # @param num_units [Array<String>] The numerator units to coerce this number into.
+    #   See {\#numerator\_units}
+    # @param den_units [Array<String>] The denominator units to coerce this number into.
+    #   See {\#denominator\_units}
+    # @return [Number] The number with the new units
+    # @raise [Sass::UnitConversionError] if the given units are incompatible with the number's
+    #   current units
+    def coerce(num_units, den_units)
+      Number.new(if unitless?
+                   self.value
+                 else
+                   self.value * coercion_factor(@numerator_units, num_units) /
+                     coercion_factor(@denominator_units, den_units)
+                 end, num_units, den_units)
+    end
+
+    # @param other [Number] A number to decide if it can be compared with this number.
+    # @return [Boolean] Whether or not this number can be compared with the other.
+    def comparable_to?(other)
+      begin
+        operate(other, :+)
+        true
+      rescue Sass::UnitConversionError
+        false
+      end
+    end
+
+    # Returns a human readable representation of the units in this number.
+    # For complex units this takes the form of:
+    # numerator_unit1 * numerator_unit2 / denominator_unit1 * denominator_unit2
+    # @return [String] a string that represents the units in this number
+    def unit_str
+      rv = @numerator_units.sort.join("*")
+      if @denominator_units.any?
+        rv << "/"
+        rv << @denominator_units.sort.join("*")
+      end
+      rv
+    end
+
+    private
+
+    # @private
+    def self.round(num)
+      if num.is_a?(Float) && (num.infinite? || num.nan?)
+        num
+      elsif num % 1 == 0.0
+        num.to_i
+      else
+        ((num * self.precision_factor).round / self.precision_factor).to_f
+      end
+    end
+
+    OPERATIONS = [:+, :-, :<=, :<, :>, :>=]
+
+    def operate(other, operation)
+      this = self
+      if OPERATIONS.include?(operation)
+        if unitless?
+          this = this.coerce(other.numerator_units, other.denominator_units)
+        else
+          other = other.coerce(@numerator_units, @denominator_units)
+        end
+      end
+      # avoid integer division
+      value = (:/ == operation) ? this.value.to_f : this.value
+      result = value.send(operation, other.value)
+
+      if result.is_a?(Numeric)
+        Number.new(result, *compute_units(this, other, operation))
+      else # Boolean op
+        Bool.new(result)
+      end
+    end
+
+    def coercion_factor(from_units, to_units)
+      # get a list of unmatched units
+      from_units, to_units = sans_common_units(from_units, to_units)
+
+      if from_units.size != to_units.size || !convertable?(from_units | to_units)
+        raise Sass::UnitConversionError.new("Incompatible units: '#{from_units.join('*')}' and 
'#{to_units.join('*')}'.")
+      end
+
+      from_units.zip(to_units).inject(1) {|m,p| m * conversion_factor(p[0], p[1]) }
+    end
+
+    def compute_units(this, other, operation)
+      case operation
+      when :*
+        [this.numerator_units + other.numerator_units, this.denominator_units + other.denominator_units]
+      when :/
+        [this.numerator_units + other.denominator_units, this.denominator_units + other.numerator_units]
+      else  
+        [this.numerator_units, this.denominator_units]
+      end
+    end
+
+    def normalize!
+      return if unitless?
+      @numerator_units, @denominator_units = sans_common_units(@numerator_units, @denominator_units)
+
+      @denominator_units.each_with_index do |d, i|
+        if convertable?(d) && (u = @numerator_units.detect(&method(:convertable?)))
+          @value /= conversion_factor(d, u)
+          @denominator_units.delete_at(i)
+          @numerator_units.delete_at(@numerator_units.index(u))
+        end
+      end
+    end
+
+    # A hash of unit names to their index in the conversion table
+    CONVERTABLE_UNITS = {"in" => 0,        "cm" => 1,    "pc" => 2,    "mm" => 3,   "pt" => 4,  "px" => 5    
}
+    CONVERSION_TABLE = [[ 1,                2.54,         6,            25.4,        72        , 96          
], # in
+                        [ nil,              1,            2.36220473,   10,          28.3464567, 
37.795275591], # cm
+                        [ nil,              nil,          1,            4.23333333,  12        , 16          
], # pc
+                        [ nil,              nil,          nil,          1,           2.83464567, 
3.7795275591], # mm
+                        [ nil,              nil,          nil,          nil,         1         , 
1.3333333333], # pt
+                        [ nil,              nil,          nil,          nil,         nil       , 1           
]] # px
+
+    def conversion_factor(from_unit, to_unit)
+      res = CONVERSION_TABLE[CONVERTABLE_UNITS[from_unit]][CONVERTABLE_UNITS[to_unit]]
+      return 1.0 / conversion_factor(to_unit, from_unit) if res.nil?
+      res
+    end
+
+    def convertable?(units)
+      Array(units).all? {|u| CONVERTABLE_UNITS.include?(u)}
+    end
+
+    def sans_common_units(units1, units2)
+      units2 = units2.dup
+      # Can't just use -, because we want px*px to coerce properly to px*mm
+      return units1.map do |u|
+        next u unless j = units2.index(u)
+        units2.delete_at(j)
+        nil
+      end.compact, units2
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/operation.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/operation.rb
new file mode 100644
index 0000000..8827c26
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/operation.rb
@@ -0,0 +1,110 @@
+require 'set'
+require 'sass/script/string'
+require 'sass/script/number'
+require 'sass/script/color'
+require 'sass/script/functions'
+require 'sass/script/unary_operation'
+require 'sass/script/interpolation'
+require 'sass/script/string_interpolation'
+
+module Sass::Script
+  # A SassScript parse node representing a binary operation,
+  # such as `$a + $b` or `"foo" + 1`.
+  class Operation < Node
+    attr_reader :operand1
+    attr_reader :operand2
+    attr_reader :operator
+
+    # @param operand1 [Script::Node] The parse-tree node
+    #   for the right-hand side of the operator
+    # @param operand2 [Script::Node] The parse-tree node
+    #   for the left-hand side of the operator
+    # @param operator [Symbol] The operator to perform.
+    #   This should be one of the binary operator names in {Lexer::OPERATORS}
+    def initialize(operand1, operand2, operator)
+      @operand1 = operand1
+      @operand2 = operand2
+      @operator = operator
+      super()
+    end
+
+    # @return [String] A human-readable s-expression representation of the operation
+    def inspect
+      "(#{ operator inspect} #{ operand1 inspect} #{ operand2 inspect})"
+    end
+
+    # @see Node#to_sass
+    def to_sass(opts = {})
+      o1 = operand_to_sass @operand1, :left, opts
+      o2 = operand_to_sass @operand2, :right, opts
+      sep =
+        case @operator
+        when :comma; ", "
+        when :space; " "
+        else; " #{Lexer::OPERATORS_REVERSE[ operator]} "
+        end
+      "#{o1}#{sep}#{o2}"
+    end
+
+    # Returns the operands for this operation.
+    #
+    # @return [Array<Node>]
+    # @see Node#children
+    def children
+      [ operand1, @operand2]
+    end
+
+    # @see Node#deep_copy
+    def deep_copy
+      node = dup
+      node.instance_variable_set('@operand1', @operand1.deep_copy)
+      node.instance_variable_set('@operand2', @operand2.deep_copy)
+      node
+    end
+
+    protected
+
+    # Evaluates the operation.
+    #
+    # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
+    # @return [Literal] The SassScript object that is the value of the operation
+    # @raise [Sass::SyntaxError] if the operation is undefined for the operands
+    def _perform(environment)
+      literal1 = @operand1.perform(environment)
+
+      # Special-case :and and :or to support short-circuiting.
+      if @operator == :and
+        return literal1.to_bool ? @operand2.perform(environment) : literal1
+      elsif @operator == :or
+        return literal1.to_bool ? literal1 : @operand2.perform(environment)
+      end
+
+      literal2 = @operand2.perform(environment)
+
+      if (literal1.is_a?(Null) || literal2.is_a?(Null)) && @operator != :eq && @operator != :neq
+        raise Sass::SyntaxError.new("Invalid null operation: \"#{literal1.inspect} #{ operator} 
#{literal2.inspect}\".")
+      end
+
+      begin
+        opts(literal1.send(@operator, literal2))
+      rescue NoMethodError => e
+        raise e unless e.name.to_s == @operator.to_s
+        raise Sass::SyntaxError.new("Undefined operation: \"#{literal1} #{ operator} #{literal2}\".")
+      end
+    end
+
+    private
+
+    def operand_to_sass(op, side, opts)
+      return "(#{op.to_sass(opts)})" if op.is_a?(List)
+      return op.to_sass(opts) unless op.is_a?(Operation)
+
+      pred = Sass::Script::Parser.precedence_of(@operator)
+      sub_pred = Sass::Script::Parser.precedence_of(op.operator)
+      assoc = Sass::Script::Parser.associative?(@operator)
+      return "(#{op.to_sass(opts)})" if sub_pred < pred ||
+        (side == :right && sub_pred == pred && !assoc)
+      op.to_sass(opts)
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/parser.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/parser.rb
new file mode 100644
index 0000000..da3a7ef
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/parser.rb
@@ -0,0 +1,495 @@
+require 'sass/script/lexer'
+
+module Sass
+  module Script
+    # The parser for SassScript.
+    # It parses a string of code into a tree of {Script::Node}s.
+    class Parser
+      # The line number of the parser's current position.
+      #
+      # @return [Fixnum]
+      def line
+        @lexer.line
+      end
+
+      # @param str [String, StringScanner] The source text to parse
+      # @param line [Fixnum] The line on which the SassScript appears.
+      #   Used for error reporting
+      # @param offset [Fixnum] The number of characters in on which the SassScript appears.
+      #   Used for error reporting
+      # @param options [{Symbol => Object}] An options hash;
+      #   see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
+      def initialize(str, line, offset, options = {})
+        @options = options
+        @lexer = lexer_class.new(str, line, offset, options)
+      end
+
+      # Parses a SassScript expression within an interpolated segment (`#{}`).
+      # This means that it stops when it comes across an unmatched `}`,
+      # which signals the end of an interpolated segment,
+      # it returns rather than throwing an error.
+      #
+      # @return [Script::Node] The root node of the parse tree
+      # @raise [Sass::SyntaxError] if the expression isn't valid SassScript
+      def parse_interpolated
+        expr = assert_expr :expr
+        assert_tok :end_interpolation
+        expr.options = @options
+        expr
+      rescue Sass::SyntaxError => e
+        e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
+        raise e
+      end
+
+      # Parses a SassScript expression.
+      #
+      # @return [Script::Node] The root node of the parse tree
+      # @raise [Sass::SyntaxError] if the expression isn't valid SassScript
+      def parse
+        expr = assert_expr :expr
+        assert_done
+        expr.options = @options
+        expr
+      rescue Sass::SyntaxError => e
+        e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
+        raise e
+      end
+
+      # Parses a SassScript expression,
+      # ending it when it encounters one of the given identifier tokens.
+      #
+      # @param [#include?(String)] A set of strings that delimit the expression.
+      # @return [Script::Node] The root node of the parse tree
+      # @raise [Sass::SyntaxError] if the expression isn't valid SassScript
+      def parse_until(tokens)
+        @stop_at = tokens
+        expr = assert_expr :expr
+        assert_done
+        expr.options = @options
+        expr
+      rescue Sass::SyntaxError => e
+        e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
+        raise e
+      end
+
+      # Parses the argument list for a mixin include.
+      #
+      # @return [(Array<Script::Node>, {String => Script::Node}, Script::Node)]
+      #   The root nodes of the positional arguments, keyword arguments, and
+      #   splat argument. Keyword arguments are in a hash from names to values.
+      # @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
+      def parse_mixin_include_arglist
+        args, keywords = [], {}
+        if try_tok(:lparen)
+          args, keywords, splat = mixin_arglist || [[], {}]
+          assert_tok(:rparen)
+        end
+        assert_done
+
+        args.each {|a| a.options = @options}
+        keywords.each {|k, v| v.options = @options}
+        splat.options = @options if splat
+        return args, keywords, splat
+      rescue Sass::SyntaxError => e
+        e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
+        raise e
+      end
+
+      # Parses the argument list for a mixin definition.
+      #
+      # @return [(Array<Script::Node>, Script::Node)]
+      #   The root nodes of the arguments, and the splat argument.
+      # @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
+      def parse_mixin_definition_arglist
+        args, splat = defn_arglist!(false)
+        assert_done
+
+        args.each do |k, v|
+          k.options = @options
+          v.options = @options if v
+        end
+        splat.options = @options if splat
+        return args, splat
+      rescue Sass::SyntaxError => e
+        e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
+        raise e
+      end
+
+      # Parses the argument list for a function definition.
+      #
+      # @return [(Array<Script::Node>, Script::Node)]
+      #   The root nodes of the arguments, and the splat argument.
+      # @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
+      def parse_function_definition_arglist
+        args, splat = defn_arglist!(true)
+        assert_done
+
+        args.each do |k, v|
+          k.options = @options
+          v.options = @options if v
+        end
+        splat.options = @options if splat
+        return args, splat
+      rescue Sass::SyntaxError => e
+        e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
+        raise e
+      end
+
+      # Parse a single string value, possibly containing interpolation.
+      # Doesn't assert that the scanner is finished after parsing.
+      #
+      # @return [Script::Node] The root node of the parse tree.
+      # @raise [Sass::SyntaxError] if the string isn't valid SassScript
+      def parse_string
+        unless (peek = @lexer.peek) &&
+            (peek.type == :string ||
+            (peek.type == :funcall && peek.value.downcase == 'url'))
+          lexer.expected!("string")
+        end
+
+        expr = assert_expr :funcall
+        expr.options = @options
+        @lexer.unpeek!
+        expr
+      rescue Sass::SyntaxError => e
+        e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
+        raise e
+      end
+
+      # Parses a SassScript expression.
+      #
+      # @overload parse(str, line, offset, filename = nil)
+      # @return [Script::Node] The root node of the parse tree
+      # @see Parser#initialize
+      # @see Parser#parse
+      def self.parse(*args)
+        new(*args).parse
+      end
+
+      PRECEDENCE = [
+        :comma, :single_eq, :space, :or, :and,
+        [:eq, :neq],
+        [:gt, :gte, :lt, :lte],
+        [:plus, :minus],
+        [:times, :div, :mod],
+      ]
+
+      ASSOCIATIVE = [:plus, :times]
+
+      class << self
+        # Returns an integer representing the precedence
+        # of the given operator.
+        # A lower integer indicates a looser binding.
+        #
+        # @private
+        def precedence_of(op)
+          PRECEDENCE.each_with_index do |e, i|
+            return i if Array(e).include?(op)
+          end
+          raise "[BUG] Unknown operator #{op}"
+        end
+
+        # Returns whether or not the given operation is associative.
+        #
+        # @private
+        def associative?(op)
+          ASSOCIATIVE.include?(op)
+        end
+
+        private
+
+        # Defines a simple left-associative production.
+        # name is the name of the production,
+        # sub is the name of the production beneath it,
+        # and ops is a list of operators for this precedence level
+        def production(name, sub, *ops)
+          class_eval <<RUBY, __FILE__, __LINE__ + 1
+            def #{name}
+              interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect}) and return interp
+              return unless e = #{sub}
+              while tok = try_tok(#{ops.map {|o| o.inspect}.join(', ')})
+                if interp = try_op_before_interp(tok, e)
+                  return interp unless other_interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect}, 
interp)
+                  return other_interp
+                end
+
+                line = @lexer.line
+                e = Operation.new(e, assert_expr(#{sub.inspect}), tok.type)
+                e.line = line
+              end
+              e
+            end
+RUBY
+        end
+
+        def unary(op, sub)
+          class_eval <<RUBY, __FILE__, __LINE__ + 1
+            def unary_#{op}
+              return #{sub} unless tok = try_tok(:#{op})
+              interp = try_op_before_interp(tok) and return interp
+              line = @lexer.line 
+              op = UnaryOperation.new(assert_expr(:unary_#{op}), :#{op})
+              op.line = line
+              op
+            end
+RUBY
+        end
+      end
+
+      private
+
+      # @private
+      def lexer_class; Lexer; end
+
+      def expr
+        line = @lexer.line
+        return unless e = interpolation
+        list = node(List.new([e], :comma), line)
+        while tok = try_tok(:comma)
+          if interp = try_op_before_interp(tok, list)
+            return interp unless other_interp = try_ops_after_interp([:comma], :expr, interp)
+            return other_interp
+          end
+          list.value << assert_expr(:interpolation)
+        end
+        list.value.size == 1 ? list.value.first : list
+      end
+
+      production :equals, :interpolation, :single_eq
+
+      def try_op_before_interp(op, prev = nil)
+        return unless @lexer.peek && @lexer.peek.type == :begin_interpolation
+        wb = @lexer.whitespace?(op)
+        str = Script::String.new(Lexer::OPERATORS_REVERSE[op.type])
+        str.line = @lexer.line
+        interp = Script::Interpolation.new(prev, str, nil, wb, !:wa, :originally_text)
+        interp.line = @lexer.line
+        interpolation(interp)
+      end
+
+      def try_ops_after_interp(ops, name, prev = nil)
+        return unless @lexer.after_interpolation?
+        return unless op = try_tok(*ops)
+        interp = try_op_before_interp(op, prev) and return interp
+
+        wa = @lexer.whitespace?
+        str = Script::String.new(Lexer::OPERATORS_REVERSE[op.type])
+        str.line = @lexer.line
+        interp = Script::Interpolation.new(prev, str, assert_expr(name), !:wb, wa, :originally_text)
+        interp.line = @lexer.line
+        return interp
+      end
+
+      def interpolation(first = space)
+        e = first
+        while interp = try_tok(:begin_interpolation)
+          wb = @lexer.whitespace?(interp)
+          line = @lexer.line
+          mid = parse_interpolated
+          wa = @lexer.whitespace?
+          e = Script::Interpolation.new(e, mid, space, wb, wa)
+          e.line = line
+        end
+        e
+      end
+
+      def space
+        line = @lexer.line
+        return unless e = or_expr
+        arr = [e]
+        while e = or_expr
+          arr << e
+        end
+        arr.size == 1 ? arr.first : node(List.new(arr, :space), line)
+      end
+
+      production :or_expr, :and_expr, :or
+      production :and_expr, :eq_or_neq, :and
+      production :eq_or_neq, :relational, :eq, :neq
+      production :relational, :plus_or_minus, :gt, :gte, :lt, :lte
+      production :plus_or_minus, :times_div_or_mod, :plus, :minus
+      production :times_div_or_mod, :unary_plus, :times, :div, :mod
+
+      unary :plus, :unary_minus
+      unary :minus, :unary_div
+      unary :div, :unary_not # For strings, so /foo/bar works
+      unary :not, :ident
+
+      def ident
+        return funcall unless @lexer.peek && @lexer.peek.type == :ident
+        return if @stop_at && @stop_at.include?(@lexer.peek.value)
+
+        name = @lexer.next
+        if color = Color::COLOR_NAMES[name.value.downcase]
+          return node(Color.new(color))
+        end
+        node(Script::String.new(name.value, :identifier))
+      end
+
+      def funcall
+        return raw unless tok = try_tok(:funcall)
+        args, keywords, splat = fn_arglist || [[], {}]
+        assert_tok(:rparen)
+        node(Script::Funcall.new(tok.value, args, keywords, splat))
+      end
+
+      def defn_arglist!(must_have_parens)
+        if must_have_parens
+          assert_tok(:lparen)
+        else
+          return [], nil unless try_tok(:lparen)
+        end
+        return [], nil if try_tok(:rparen)
+
+        res = []
+        splat = nil
+        must_have_default = false
+        loop do
+          c = assert_tok(:const)
+          var = Script::Variable.new(c.value)
+          if try_tok(:colon)
+            val = assert_expr(:space)
+            must_have_default = true
+          elsif must_have_default
+            raise SyntaxError.new("Required argument #{var.inspect} must come before any optional 
arguments.")
+          elsif try_tok(:splat)
+            splat = var
+            break
+          end
+          res << [var, val]
+          break unless try_tok(:comma)
+        end
+        assert_tok(:rparen)
+        return res, splat
+      end
+
+      def fn_arglist
+        arglist(:equals, "function argument")
+      end
+
+      def mixin_arglist
+        arglist(:interpolation, "mixin argument")
+      end
+
+      def arglist(subexpr, description)
+        return unless e = send(subexpr)
+
+        args = []
+        keywords = {}
+        loop do
+          if @lexer.peek && @lexer.peek.type == :colon
+            name = e
+            @lexer.expected!("comma") unless name.is_a?(Variable)
+            assert_tok(:colon)
+            value = assert_expr(subexpr, description)
+
+            if keywords[name.underscored_name]
+              raise SyntaxError.new("Keyword argument \"#{name.to_sass}\" passed more than once")
+            end
+
+            keywords[name.underscored_name] = value
+          else
+            if !keywords.empty?
+              raise SyntaxError.new("Positional arguments must come before keyword arguments.")
+            end
+
+            return args, keywords, e if try_tok(:splat)
+            args << e
+          end
+
+          return args, keywords unless try_tok(:comma)
+          e = assert_expr(subexpr, description)
+        end
+      end
+
+      def raw
+        return special_fun unless tok = try_tok(:raw)
+        node(Script::String.new(tok.value))
+      end
+
+      def special_fun
+        return paren unless tok = try_tok(:special_fun)
+        first = node(Script::String.new(tok.value.first))
+        Sass::Util.enum_slice(tok.value[1..-1], 2).inject(first) do |l, (i, r)|
+          Script::Interpolation.new(
+            l, i, r && node(Script::String.new(r)),
+            false, false)
+        end
+      end
+
+      def paren
+        return variable unless try_tok(:lparen)
+        was_in_parens = @in_parens
+        @in_parens = true
+        line = @lexer.line
+        e = expr
+        assert_tok(:rparen)
+        return e || node(List.new([], :space), line)
+      ensure
+        @in_parens = was_in_parens
+      end
+
+      def variable
+        return string unless c = try_tok(:const)
+        node(Variable.new(*c.value))
+      end
+
+      def string
+        return number unless first = try_tok(:string)
+        return first.value unless try_tok(:begin_interpolation)
+        line = @lexer.line
+        mid = parse_interpolated
+        last = assert_expr(:string)
+        interp = StringInterpolation.new(first.value, mid, last)
+        interp.line = line
+        interp
+      end
+
+      def number
+        return literal unless tok = try_tok(:number)
+        num = tok.value
+        num.original = num.to_s unless @in_parens
+        num
+      end
+
+      def literal
+        (t = try_tok(:color, :bool, :null)) && (return t.value)
+      end
+
+      # It would be possible to have unified #assert and #try methods,
+      # but detecting the method/token difference turns out to be quite expensive.
+
+      EXPR_NAMES = {
+        :string => "string",
+        :default => "expression (e.g. 1px, bold)",
+        :mixin_arglist => "mixin argument",
+        :fn_arglist => "function argument",
+      }
+
+      def assert_expr(name, expected = nil)
+        (e = send(name)) && (return e)
+        @lexer.expected!(expected || EXPR_NAMES[name] || EXPR_NAMES[:default])
+      end
+
+      def assert_tok(*names)
+        (t = try_tok(*names)) && (return t)
+        @lexer.expected!(names.map {|tok| Lexer::TOKEN_NAMES[tok] || tok}.join(" or "))
+      end
+
+      def try_tok(*names)
+        peeked =  @lexer.peek
+        peeked && names.include?(peeked.type) && @lexer.next
+      end
+
+      def assert_done
+        return if @lexer.done?
+        @lexer.expected!(EXPR_NAMES[:default])
+      end
+
+      def node(node, line = @lexer.line)
+        node.line = line
+        node
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/string.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/string.rb
new file mode 100644
index 0000000..1048b86
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/string.rb
@@ -0,0 +1,51 @@
+require 'sass/script/literal'
+
+module Sass::Script
+  # A SassScript object representing a CSS string *or* a CSS identifier.
+  class String < Literal
+    # The Ruby value of the string.
+    #
+    # @return [String]
+    attr_reader :value
+
+    # Whether this is a CSS string or a CSS identifier.
+    # The difference is that strings are written with double-quotes,
+    # while identifiers aren't.
+    #
+    # @return [Symbol] `:string` or `:identifier`
+    attr_reader :type
+
+    # Creates a new string.
+    #
+    # @param value [String] See \{#value}
+    # @param type [Symbol] See \{#type}
+    def initialize(value, type = :identifier)
+      super(value)
+      @type = type
+    end
+
+    # @see Literal#plus
+    def plus(other)
+      other_str = other.is_a?(Sass::Script::String) ? other.value : other.to_s
+      Sass::Script::String.new(self.value + other_str, self.type)
+    end
+
+    # @see Node#to_s
+    def to_s(opts = {})
+      if @type == :identifier
+        return @value.gsub(/\n\s*/, " ")
+      end
+
+      return "\"#{value.gsub('"', "\\\"")}\"" if opts[:quote] == %q{"}
+      return "'#{value.gsub("'", "\\'")}'" if opts[:quote] == %q{'}
+      return "\"#{value}\"" unless value.include?('"')
+      return "'#{value}'" unless value.include?("'")
+      "\"#{value.gsub('"', "\\\"")}\"" #'
+    end
+
+    # @see Node#to_sass
+    def to_sass(opts = {})
+      to_s
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/string_interpolation.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/string_interpolation.rb
new file mode 100644
index 0000000..6baba12
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/string_interpolation.rb
@@ -0,0 +1,103 @@
+module Sass::Script
+  # A SassScript object representing `#{}` interpolation within a string.
+  #
+  # @see Interpolation
+  class StringInterpolation < Node
+    # Interpolation in a string is of the form `"before #{mid} after"`,
+    # where `before` and `after` may include more interpolation.
+    #
+    # @param before [Node] The string before the interpolation
+    # @param mid [Node] The SassScript within the interpolation
+    # @param after [Node] The string after the interpolation
+    def initialize(before, mid, after)
+      @before = before
+      @mid = mid
+      @after = after
+    end
+
+    # @return [String] A human-readable s-expression representation of the interpolation
+    def inspect
+      "(string_interpolation #{ before inspect} #{ mid inspect} #{ after inspect})"
+    end
+
+    # @see Node#to_sass
+    def to_sass(opts = {})
+      # We can get rid of all of this when we remove the deprecated :equals context
+      # XXX CE: It's gone now but I'm not sure what can be removed now.
+      before_unquote, before_quote_char, before_str = parse_str(@before.to_sass(opts))
+      after_unquote, after_quote_char, after_str = parse_str(@after.to_sass(opts))
+      unquote = before_unquote || after_unquote ||
+        (before_quote_char && !after_quote_char && !after_str.empty?) ||
+        (!before_quote_char && after_quote_char && !before_str.empty?)
+      quote_char =
+        if before_quote_char && after_quote_char && before_quote_char != after_quote_char
+          before_str.gsub!("\\'", "'")
+          before_str.gsub!('"', "\\\"")
+          after_str.gsub!("\\'", "'")
+          after_str.gsub!('"', "\\\"")
+          '"'
+        else
+          before_quote_char || after_quote_char
+        end
+
+      res = ""
+      res << 'unquote(' if unquote
+      res << quote_char if quote_char
+      res << before_str
+      res << '#{' << @mid.to_sass(opts) << '}'
+      res << after_str
+      res << quote_char if quote_char
+      res << ')' if unquote
+      res
+    end
+
+    # Returns the three components of the interpolation, `before`, `mid`, and `after`.
+    #
+    # @return [Array<Node>]
+    # @see #initialize
+    # @see Node#children
+    def children
+      [ before, @mid, @after].compact
+    end
+
+    # @see Node#deep_copy
+    def deep_copy
+      node = dup
+      node.instance_variable_set('@before', @before.deep_copy) if @before
+      node.instance_variable_set('@mid', @mid.deep_copy)
+      node.instance_variable_set('@after', @after.deep_copy) if @after
+      node
+    end
+
+    protected
+
+    # Evaluates the interpolation.
+    #
+    # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
+    # @return [Sass::Script::String] The SassScript string that is the value of the interpolation
+    def _perform(environment)
+      res = ""
+      before = @before.perform(environment)
+      res << before.value
+      mid = @mid.perform(environment)
+      res << (mid.is_a?(Sass::Script::String) ? mid.value : mid.to_s)
+      res << @after.perform(environment).value
+      opts(Sass::Script::String.new(res, before.type))
+    end
+
+    private
+
+    def parse_str(str)
+      case str
+      when /^unquote\((["'])(.*)\1\)$/
+        return true, $1, $2
+      when '""'
+        return false, nil, ""
+      when /^(["'])(.*)\1$/
+        return false, $1, $2
+      else
+        return false, nil, str
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/unary_operation.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/unary_operation.rb
new file mode 100644
index 0000000..efa78c7
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/unary_operation.rb
@@ -0,0 +1,69 @@
+module Sass::Script
+  # A SassScript parse node representing a unary operation,
+  # such as `-$b` or `not true`.
+  #
+  # Currently only `-`, `/`, and `not` are unary operators.
+  class UnaryOperation < Node
+    # @return [Symbol] The operation to perform
+    attr_reader :operator
+
+    # @return [Script::Node] The parse-tree node for the object of the operator
+    attr_reader :operand
+
+    # @param operand [Script::Node] See \{#operand}
+    # @param operator [Symbol] See \{#operator}
+    def initialize(operand, operator)
+      @operand = operand
+      @operator = operator
+      super()
+    end
+
+    # @return [String] A human-readable s-expression representation of the operation
+    def inspect
+      "(#{ operator inspect} #{ operand inspect})"
+    end
+
+    # @see Node#to_sass
+    def to_sass(opts = {})
+      operand = @operand.to_sass(opts)
+      if @operand.is_a?(Operation) ||
+          (@operator == :minus &&
+           (operand =~ Sass::SCSS::RX::IDENT) == 0)
+        operand = "(#{ operand to_sass(opts)})"
+      end
+      op = Lexer::OPERATORS_REVERSE[ operator]
+      op + (op =~ /[a-z]/ ? " " : "") + operand
+    end
+
+    # Returns the operand of the operation.
+    #
+    # @return [Array<Node>]
+    # @see Node#children
+    def children
+      [ operand]
+    end
+
+    # @see Node#deep_copy
+    def deep_copy
+      node = dup
+      node.instance_variable_set('@operand', @operand.deep_copy)
+      node
+    end
+
+    protected
+
+    # Evaluates the operation.
+    #
+    # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
+    # @return [Literal] The SassScript object that is the value of the operation
+    # @raise [Sass::SyntaxError] if the operation is undefined for the operand
+    def _perform(environment)
+      operator = "unary_#{ operator}"
+      literal = @operand.perform(environment)
+      literal.send(operator)
+    rescue NoMethodError => e
+      raise e unless e.name.to_s == operator.to_s
+      raise Sass::SyntaxError.new("Undefined unary operation: \"#{ operator} #{literal}\".")
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/script/variable.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/script/variable.rb
new file mode 100644
index 0000000..56ae9db
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/script/variable.rb
@@ -0,0 +1,58 @@
+module Sass
+  module Script
+    # A SassScript parse node representing a variable.
+    class Variable < Node
+      # The name of the variable.
+      #
+      # @return [String]
+      attr_reader :name
+
+      # The underscored name of the variable.
+      #
+      # @return [String]
+      attr_reader :underscored_name
+
+      # @param name [String] See \{#name}
+      def initialize(name)
+        @name = name
+        @underscored_name = name.gsub(/-/,"_")
+        super()
+      end
+
+      # @return [String] A string representation of the variable
+      def inspect(opts = {})
+        "$#{dasherize(name, opts)}"
+      end
+      alias_method :to_sass, :inspect
+
+      # Returns an empty array.
+      #
+      # @return [Array<Node>] empty
+      # @see Node#children
+      def children
+        []
+      end
+
+      # @see Node#deep_copy
+      def deep_copy
+        dup
+      end
+
+      protected
+
+      # Evaluates the variable.
+      #
+      # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
+      # @return [Literal] The SassScript object that is the value of the variable
+      # @raise [Sass::SyntaxError] if the variable is undefined
+      def _perform(environment)
+        raise SyntaxError.new("Undefined variable: \"$#{name}\".") unless val = environment.var(name)
+        if val.is_a?(Number)
+          val = val.dup
+          val.original = nil
+        end
+        return val
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/scss.rb b/backends/css/gems/sass-3.2.12/lib/sass/scss.rb
new file mode 100644
index 0000000..215fe95
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/scss.rb
@@ -0,0 +1,16 @@
+require 'sass/scss/rx'
+require 'sass/scss/script_lexer'
+require 'sass/scss/script_parser'
+require 'sass/scss/parser'
+require 'sass/scss/static_parser'
+require 'sass/scss/css_parser'
+
+module Sass
+  # SCSS is the CSS syntax for Sass.
+  # It parses into the same syntax tree as Sass,
+  # and generates the same sort of output CSS.
+  #
+  # This module contains code for the parsing of SCSS.
+  # The evaluation is handled by the broader {Sass} module.
+  module SCSS; end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/scss/css_parser.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/scss/css_parser.rb
new file mode 100644
index 0000000..4591324
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/scss/css_parser.rb
@@ -0,0 +1,36 @@
+require 'sass/script/css_parser'
+
+module Sass
+  module SCSS
+    # This is a subclass of {Parser} which only parses plain CSS.
+    # It doesn't support any Sass extensions, such as interpolation,
+    # parent references, nested selectors, and so forth.
+    # It does support all the same CSS hacks as the SCSS parser, though.
+    class CssParser < StaticParser
+      private
+
+      def placeholder_selector; nil; end
+      def parent_selector; nil; end
+      def interpolation; nil; end
+      def use_css_import?; true; end
+
+      def block_child(context)
+        case context
+        when :ruleset
+          declaration
+        when :stylesheet
+          directive || ruleset
+        when :directive
+          directive || declaration_or_ruleset
+        end
+      end
+
+      def nested_properties!(node, space)
+        expected('expression (e.g. 1px, bold)');
+      end
+
+      @sass_script_parser = Class.new(Sass::Script::CssParser)
+      @sass_script_parser.send(:include, ScriptParser)
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/scss/parser.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/scss/parser.rb
new file mode 100644
index 0000000..a790455
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/scss/parser.rb
@@ -0,0 +1,1179 @@
+require 'set'
+
+module Sass
+  module SCSS
+    # The parser for SCSS.
+    # It parses a string of code into a tree of {Sass::Tree::Node}s.
+    class Parser
+      # @param str [String, StringScanner] The source document to parse.
+      #   Note that `Parser` *won't* raise a nice error message if this isn't properly parsed;
+      #   for that, you should use the higher-level {Sass::Engine} or {Sass::CSS}.
+      # @param filename [String] The name of the file being parsed. Used for warnings.
+      # @param line [Fixnum] The line on which the source string appeared,
+      #   if it's part of another document.
+      def initialize(str, filename, line = 1)
+        @template = str
+        @filename = filename
+        @line = line
+        @strs = []
+      end
+
+      # Parses an SCSS document.
+      #
+      # @return [Sass::Tree::RootNode] The root node of the document tree
+      # @raise [Sass::SyntaxError] if there's a syntax error in the document
+      def parse
+        init_scanner!
+        root = stylesheet
+        expected("selector or at-rule") unless @scanner.eos?
+        root
+      end
+
+      # Parses an identifier with interpolation.
+      # Note that this won't assert that the identifier takes up the entire input string;
+      # it's meant to be used with `StringScanner`s as part of other parsers.
+      #
+      # @return [Array<String, Sass::Script::Node>, nil]
+      #   The interpolated identifier, or nil if none could be parsed
+      def parse_interp_ident
+        init_scanner!
+        interp_ident
+      end
+
+      # Parses a media query list.
+      #
+      # @return [Sass::Media::QueryList] The parsed query list
+      # @raise [Sass::SyntaxError] if there's a syntax error in the query list,
+      #   or if it doesn't take up the entire input string.
+      def parse_media_query_list
+        init_scanner!
+        ql = media_query_list
+        expected("media query list") unless @scanner.eos?
+        ql
+      end
+
+      # Parses a supports query condition.
+      #
+      # @return [Sass::Supports::Condition] The parsed condition
+      # @raise [Sass::SyntaxError] if there's a syntax error in the condition,
+      #   or if it doesn't take up the entire input string.
+      def parse_supports_condition
+        init_scanner!
+        condition = supports_condition
+        expected("supports condition") unless @scanner.eos?
+        condition
+      end
+
+      private
+
+      include Sass::SCSS::RX
+
+      def init_scanner!
+        @scanner =
+          if @template.is_a?(StringScanner)
+            @template
+          else
+            Sass::Util::MultibyteStringScanner.new(@template.gsub("\r", ""))
+          end
+      end
+
+      def stylesheet
+        node = node(Sass::Tree::RootNode.new(@scanner.string))
+        block_contents(node, :stylesheet) {s(node)}
+      end
+
+      def s(node)
+        while tok(S) || tok(CDC) || tok(CDO) || (c = tok(SINGLE_LINE_COMMENT)) || (c = tok(COMMENT))
+          next unless c
+          process_comment c, node
+          c = nil
+        end
+        true
+      end
+
+      def ss
+        nil while tok(S) || tok(SINGLE_LINE_COMMENT) || tok(COMMENT)
+        true
+      end
+
+      def ss_comments(node)
+        while tok(S) || (c = tok(SINGLE_LINE_COMMENT)) || (c = tok(COMMENT))
+          next unless c
+          process_comment c, node
+          c = nil
+        end
+
+        true
+      end
+
+      def whitespace
+        return unless tok(S) || tok(SINGLE_LINE_COMMENT) || tok(COMMENT)
+        ss
+      end
+
+      def process_comment(text, node)
+        silent = text =~ /^\/\//
+        loud = !silent && text =~ %r{^/[/*]!}
+        line = @line - text.count("\n")
+
+        if silent
+          value = [text.sub(/^\s*\/\//, '/*').gsub(/^\s*\/\//, ' *') + ' */']
+        else
+          value = Sass::Engine.parse_interp(text, line, @scanner.pos - text.size, :filename => @filename)
+          value.unshift(@scanner.
+            string[0    scanner pos] 
+            reverse[/.*?\*\/(.*?)($|\Z)/, 1].
+            reverse.gsub(/[^\s]/, ' '))
+        end
+
+        type = if silent then :silent elsif loud then :loud else :normal end
+        comment = Sass::Tree::CommentNode.new(value, type)
+        comment.line = line
+        node << comment
+      end
+
+      DIRECTIVES = Set[:mixin, :include, :function, :return, :debug, :warn, :for,
+        :each, :while, :if, :else, :extend, :import, :media, :charset, :content,
+        :_moz_document]
+
+      PREFIXED_DIRECTIVES = Set[:supports]
+
+      def directive
+        return unless tok(/@/)
+        name = tok!(IDENT)
+        ss
+
+        if dir = special_directive(name)
+          return dir
+        elsif dir = prefixed_directive(name)
+          return dir
+        end
+
+        # Most at-rules take expressions (e.g. @import),
+        # but some (e.g. @page) take selector-like arguments.
+        # Some take no arguments at all.
+        val = expr || selector
+        val = val ? ["@#{name} "] + Sass::Util.strip_string_array(val) : ["@#{name}"]
+        directive_body(val)
+      end
+
+      def directive_body(value)
+        node = node(Sass::Tree::DirectiveNode.new(value))
+
+        if tok(/\{/)
+          node.has_children = true
+          block_contents(node, :directive)
+          tok!(/\}/)
+        end
+
+        node
+      end
+
+      def special_directive(name)
+        sym = name.gsub('-', '_').to_sym
+        DIRECTIVES.include?(sym) && send("#{sym}_directive")
+      end
+
+      def prefixed_directive(name)
+        sym = name.gsub(/^-[a-z0-9]+-/i, '').gsub('-', '_').to_sym
+        PREFIXED_DIRECTIVES.include?(sym) && send("#{sym}_directive", name)
+      end
+
+      def mixin_directive
+        name = tok! IDENT
+        args, splat = sass_script(:parse_mixin_definition_arglist)
+        ss
+        block(node(Sass::Tree::MixinDefNode.new(name, args, splat)), :directive)
+      end
+
+      def include_directive
+        name = tok! IDENT
+        args, keywords, splat = sass_script(:parse_mixin_include_arglist)
+        ss
+        include_node = node(Sass::Tree::MixinNode.new(name, args, keywords, splat))
+        if tok?(/\{/)
+          include_node.has_children = true
+          block(include_node, :directive)
+        else
+          include_node
+        end
+      end
+
+      def content_directive
+        ss
+        node(Sass::Tree::ContentNode.new)
+      end
+
+      def function_directive
+        name = tok! IDENT
+        args, splat = sass_script(:parse_function_definition_arglist)
+        ss
+        block(node(Sass::Tree::FunctionNode.new(name, args, splat)), :function)
+      end
+
+      def return_directive
+        node(Sass::Tree::ReturnNode.new(sass_script(:parse)))
+      end
+
+      def debug_directive
+        node(Sass::Tree::DebugNode.new(sass_script(:parse)))
+      end
+
+      def warn_directive
+        node(Sass::Tree::WarnNode.new(sass_script(:parse)))
+      end
+
+      def for_directive
+        tok!(/\$/)
+        var = tok! IDENT
+        ss
+
+        tok!(/from/)
+        from = sass_script(:parse_until, Set["to", "through"])
+        ss
+
+        @expected = '"to" or "through"'
+        exclusive = (tok(/to/) || tok!(/through/)) == 'to'
+        to = sass_script(:parse)
+        ss
+
+        block(node(Sass::Tree::ForNode.new(var, from, to, exclusive)), :directive)
+      end
+
+      def each_directive
+        tok!(/\$/)
+        var = tok! IDENT
+        ss
+
+        tok!(/in/)
+        list = sass_script(:parse)
+        ss
+
+        block(node(Sass::Tree::EachNode.new(var, list)), :directive)
+      end
+
+      def while_directive
+        expr = sass_script(:parse)
+        ss
+        block(node(Sass::Tree::WhileNode.new(expr)), :directive)
+      end
+
+      def if_directive
+        expr = sass_script(:parse)
+        ss
+        node = block(node(Sass::Tree::IfNode.new(expr)), :directive)
+        pos = @scanner.pos
+        line = @line
+        ss
+
+        else_block(node) ||
+          begin
+            # Backtrack in case there are any comments we want to parse
+            @scanner.pos = pos
+            @line = line
+            node
+          end
+      end
+
+      def else_block(node)
+        return unless tok(/@else/)
+        ss
+        else_node = block(
+          Sass::Tree::IfNode.new((sass_script(:parse) if tok(/if/))),
+          :directive)
+        node.add_else(else_node)
+        pos = @scanner.pos
+        line = @line
+        ss
+
+        else_block(node) ||
+          begin
+            # Backtrack in case there are any comments we want to parse
+            @scanner.pos = pos
+            @line = line
+            node
+          end
+      end
+
+      def else_directive
+        err("Invalid CSS: @else must come after @if")
+      end
+
+      def extend_directive
+        selector = expr!(:selector_sequence)
+        optional = tok(OPTIONAL)
+        ss
+        node(Sass::Tree::ExtendNode.new(selector, !!optional))
+      end
+
+      def import_directive
+        values = []
+
+        loop do
+          values << expr!(:import_arg)
+          break if use_css_import?
+          break unless tok(/,/)
+          ss
+        end
+
+        return values
+      end
+
+      def import_arg
+        line = @line
+        return unless (str = tok(STRING)) || (uri = tok?(/url\(/i))
+        if uri
+          str = sass_script(:parse_string)
+          media = media_query_list
+          ss
+          return node(Tree::CssImportNode.new(str, media.to_a))
+        end
+
+        path = @scanner[1] || @scanner[2]
+        ss
+
+        media = media_query_list
+        if path =~ /^(https?:)?\/\// || media || use_css_import?
+          node = Sass::Tree::CssImportNode.new(str, media.to_a)
+        else
+          node = Sass::Tree::ImportNode.new(path.strip)
+        end
+        node.line = line
+        node
+      end
+
+      def use_css_import?; false; end
+
+      def media_directive
+        block(node(Sass::Tree::MediaNode.new(expr!(:media_query_list).to_a)), :directive)
+      end
+
+      # http://www.w3.org/TR/css3-mediaqueries/#syntax
+      def media_query_list
+        return unless query = media_query
+        queries = [query]
+
+        ss
+        while tok(/,/)
+          ss; queries << expr!(:media_query)
+        end
+        ss
+
+        Sass::Media::QueryList.new(queries)
+      end
+
+      def media_query
+        if ident1 = interp_ident
+          ss
+          ident2 = interp_ident
+          ss
+          if ident2 && ident2.length == 1 && ident2[0].is_a?(String) && ident2[0].downcase == 'and'
+            query = Sass::Media::Query.new([], ident1, [])
+          else
+            if ident2
+              query = Sass::Media::Query.new(ident1, ident2, [])
+            else
+              query = Sass::Media::Query.new([], ident1, [])
+            end
+            return query unless tok(/and/i)
+            ss
+          end
+        end
+
+        if query
+          expr = expr!(:media_expr)
+        else
+          return unless expr = media_expr
+        end
+        query ||= Sass::Media::Query.new([], [], [])
+        query.expressions << expr
+
+        ss
+        while tok(/and/i)
+          ss; query.expressions << expr!(:media_expr)
+        end
+
+        query
+      end
+
+      def media_expr
+        interp = interpolation and return interp
+        return unless tok(/\(/)
+        res = ['(']
+        ss
+        res << sass_script(:parse)
+
+        if tok(/:/)
+          res << ': '
+          ss
+          res << sass_script(:parse)
+        end
+        res << tok!(/\)/)
+        ss
+        res
+      end
+
+      def charset_directive
+        tok! STRING
+        name = @scanner[1] || @scanner[2]
+        ss
+        node(Sass::Tree::CharsetNode.new(name))
+      end
+
+      # The document directive is specified in
+      # http://www.w3.org/TR/css3-conditional/, but Gecko allows the
+      # `url-prefix` and `domain` functions to omit quotation marks, contrary to
+      # the standard.
+      #
+      # We could parse all document directives according to Mozilla's syntax,
+      # but if someone's using e.g. @-webkit-document we don't want them to
+      # think WebKit works sans quotes.
+      def _moz_document_directive
+        res = ["@-moz-document "]
+        loop do
+          res << str{ss} << expr!(:moz_document_function)
+          break unless c = tok(/,/)
+          res << c
+        end
+        directive_body(res.flatten)
+      end
+
+      def moz_document_function
+        return unless val = interp_uri || _interp_string(:url_prefix) ||
+          _interp_string(:domain) || function(!:allow_var) || interpolation
+        ss
+        val
+      end
+
+      # http://www.w3.org/TR/css3-conditional/
+      def supports_directive(name)
+        condition = expr!(:supports_condition)
+        node = node(Sass::Tree::SupportsNode.new(name, condition))
+
+        tok!(/\{/)
+        node.has_children = true
+        block_contents(node, :directive)
+        tok!(/\}/)
+
+        node
+      end
+
+      def supports_condition
+        supports_negation || supports_operator || supports_interpolation
+      end
+
+      def supports_negation
+        return unless tok(/not/i)
+        ss
+        Sass::Supports::Negation.new(expr!(:supports_condition_in_parens))
+      end
+
+      def supports_operator
+        return unless cond = supports_condition_in_parens
+        return cond unless op = tok(/and|or/i)
+        begin
+          ss
+          cond = Sass::Supports::Operator.new(
+            cond, expr!(:supports_condition_in_parens), op)
+        end while op = tok(/and|or/i)
+        cond
+      end
+
+      def supports_condition_in_parens
+        interp = supports_interpolation and return interp
+        return unless tok(/\(/); ss
+        if cond = supports_condition
+          tok!(/\)/); ss
+          cond
+        else
+          name = sass_script(:parse)
+          tok!(/:/); ss
+          value = sass_script(:parse)
+          tok!(/\)/); ss
+          Sass::Supports::Declaration.new(name, value)
+        end
+      end
+
+      def supports_declaration_condition
+        return unless tok(/\(/); ss
+        supports_declaration_body
+      end
+
+      def supports_interpolation
+        return unless interp = interpolation
+        ss
+        Sass::Supports::Interpolation.new(interp)
+      end
+
+      def variable
+        return unless tok(/\$/)
+        name = tok!(IDENT)
+        ss; tok!(/:/); ss
+
+        expr = sass_script(:parse)
+        guarded = tok(DEFAULT)
+        node(Sass::Tree::VariableNode.new(name, expr, guarded))
+      end
+
+      def operator
+        # Many of these operators (all except / and ,)
+        # are disallowed by the CSS spec,
+        # but they're included here for compatibility
+        # with some proprietary MS properties
+        str {ss if tok(/[\/,:.=]/)}
+      end
+
+      def ruleset
+        return unless rules = selector_sequence
+        block(node(Sass::Tree::RuleNode.new(rules.flatten.compact)), :ruleset)
+      end
+
+      def block(node, context)
+        node.has_children = true
+        tok!(/\{/)
+        block_contents(node, context)
+        tok!(/\}/)
+        node
+      end
+
+      # A block may contain declarations and/or rulesets
+      def block_contents(node, context)
+        block_given? ? yield : ss_comments(node)
+        node << (child = block_child(context))
+        while tok(/;/) || has_children?(child)
+          block_given? ? yield : ss_comments(node)
+          node << (child = block_child(context))
+        end
+        node
+      end
+
+      def block_child(context)
+        return variable || directive if context == :function
+        return variable || directive || ruleset if context == :stylesheet
+        variable || directive || declaration_or_ruleset
+      end
+
+      def has_children?(child_or_array)
+        return false unless child_or_array
+        return child_or_array.last.has_children if child_or_array.is_a?(Array)
+        return child_or_array.has_children
+      end
+
+      # This is a nasty hack, and the only place in the parser
+      # that requires a large amount of backtracking.
+      # The reason is that we can't figure out if certain strings
+      # are declarations or rulesets with fixed finite lookahead.
+      # For example, "foo:bar baz baz baz..." could be either a property
+      # or a selector.
+      #
+      # To handle this, we simply check if it works as a property
+      # (which is the most common case)
+      # and, if it doesn't, try it as a ruleset.
+      #
+      # We could eke some more efficiency out of this
+      # by handling some easy cases (first token isn't an identifier,
+      # no colon after the identifier, whitespace after the colon),
+      # but I'm not sure the gains would be worth the added complexity.
+      def declaration_or_ruleset
+        old_use_property_exception, @use_property_exception =
+          @use_property_exception, false
+        decl_err = catch_error do
+          decl = declaration
+          unless decl && decl.has_children
+            # We want an exception if it's not there,
+            # but we don't want to consume if it is
+            tok!(/[;}]/) unless tok?(/[;}]/)
+          end
+          return decl
+        end
+
+        ruleset_err = catch_error {return ruleset}
+        rethrow(@use_property_exception ? decl_err : ruleset_err)
+      ensure
+        @use_property_exception = old_use_property_exception
+      end
+
+      def selector_sequence
+        if sel = tok(STATIC_SELECTOR, true)
+          return [sel]
+        end
+
+        rules = []
+        return unless v = selector
+        rules.concat v
+
+        ws = ''
+        while tok(/,/)
+          ws << str {ss}
+          if v = selector
+            rules << ',' << ws
+            rules.concat v
+            ws = ''
+          end
+        end
+        rules
+      end
+
+      def selector
+        return unless sel = _selector
+        sel.to_a
+      end
+
+      def selector_comma_sequence
+        return unless sel = _selector
+        selectors = [sel]
+        ws = ''
+        while tok(/,/)
+          ws << str{ss}
+          if sel = _selector
+            selectors << sel
+            selectors[-1] = Selector::Sequence.new(["\n"] + selectors.last.members) if ws.include?("\n")
+            ws = ''
+          end
+        end
+        Selector::CommaSequence.new(selectors)
+      end
+
+      def _selector
+        # The combinator here allows the "> E" hack
+        return unless val = combinator || simple_selector_sequence
+        nl = str{ss}.include?("\n")
+        res = []
+        res << val
+        res << "\n" if nl
+
+        while val = combinator || simple_selector_sequence
+          res << val
+          res << "\n" if str{ss}.include?("\n")
+        end
+        Selector::Sequence.new(res.compact)
+      end
+
+      def combinator
+        tok(PLUS) || tok(GREATER) || tok(TILDE) || reference_combinator
+      end
+
+      def reference_combinator
+        return unless tok(/\//)
+        res = ['/']
+        ns, name = expr!(:qualified_name)
+        res << ns << '|' if ns
+        res << name << tok!(/\//)
+        res = res.flatten
+        res = res.join '' if res.all? {|e| e.is_a?(String)}
+        res
+      end
+
+      def simple_selector_sequence
+        # Returning expr by default allows for stuff like
+        # http://www.w3.org/TR/css3-animations/#keyframes-
+        return expr(!:allow_var) unless e = element_name || id_selector ||
+          class_selector || placeholder_selector || attrib || pseudo ||
+          parent_selector || interpolation_selector
+        res = [e]
+
+        # The tok(/\*/) allows the "E*" hack
+        while v = id_selector || class_selector || placeholder_selector || attrib ||
+            pseudo || interpolation_selector ||
+            (tok(/\*/) && Selector::Universal.new(nil))
+          res << v
+        end
+
+        pos = @scanner.pos
+        line = @line
+        if sel = str? {simple_selector_sequence}
+          @scanner.pos = pos
+          @line = line
+          begin
+            # If we see "*E", don't force a throw because this could be the
+            # "*prop: val" hack.
+            expected('"{"') if res.length == 1 && res[0].is_a?(Selector::Universal)
+            throw_error {expected('"{"')}
+          rescue Sass::SyntaxError => e
+            e.message << "\n\n\"#{sel}\" may only be used at the beginning of a compound selector."
+            raise e
+          end
+        end
+
+        Selector::SimpleSequence.new(res, tok(/!/))
+      end
+
+      def parent_selector
+        return unless tok(/&/)
+        Selector::Parent.new
+      end
+
+      def class_selector
+        return unless tok(/\./)
+        @expected = "class name"
+        Selector::Class.new(merge(expr!(:interp_ident)))
+      end
+
+      def id_selector
+        return unless tok(/#(?!\{)/)
+        @expected = "id name"
+        Selector::Id.new(merge(expr!(:interp_name)))
+      end
+
+      def placeholder_selector
+        return unless tok(/%/)
+        @expected = "placeholder name"
+        Selector::Placeholder.new(merge(expr!(:interp_ident)))
+      end
+
+      def element_name
+        ns, name = Sass::Util.destructure(qualified_name(:allow_star_name))
+        return unless ns || name
+
+        if name == '*'
+          Selector::Universal.new(merge(ns))
+        else
+          Selector::Element.new(merge(name), merge(ns))
+        end
+      end
+
+      def qualified_name(allow_star_name=false)
+        return unless name = interp_ident || tok(/\*/) || (tok?(/\|/) && "")
+        return nil, name unless tok(/\|/)
+
+        return name, expr!(:interp_ident) unless allow_star_name
+        @expected = "identifier or *"
+        return name, interp_ident || tok!(/\*/)
+      end
+
+      def interpolation_selector
+        return unless script = interpolation
+        Selector::Interpolation.new(script)
+      end
+
+      def attrib
+        return unless tok(/\[/)
+        ss
+        ns, name = attrib_name!
+        ss
+
+        if op = tok(/=/) ||
+            tok(INCLUDES) ||
+            tok(DASHMATCH) ||
+            tok(PREFIXMATCH) ||
+            tok(SUFFIXMATCH) ||
+            tok(SUBSTRINGMATCH)
+          @expected = "identifier or string"
+          ss
+          val = interp_ident || expr!(:interp_string)
+          ss
+        end
+        flags = interp_ident || interp_string
+        tok!(/\]/)
+
+        Selector::Attribute.new(merge(name), merge(ns), op, merge(val), merge(flags))
+      end
+
+      def attrib_name!
+        if name_or_ns = interp_ident
+          # E, E|E
+          if tok(/\|(?!=)/)
+            ns = name_or_ns
+            name = interp_ident
+          else
+            name = name_or_ns
+          end
+        else
+          # *|E or |E
+          ns = [tok(/\*/) || ""]
+          tok!(/\|/)
+          name = expr!(:interp_ident)
+        end
+        return ns, name
+      end
+
+      def pseudo
+        return unless s = tok(/::?/)
+        @expected = "pseudoclass or pseudoelement"
+        name = expr!(:interp_ident)
+        if tok(/\(/)
+          ss
+          arg = expr!(:pseudo_arg)
+          while tok(/,/)
+            arg << ',' << str{ss}
+            arg.concat expr!(:pseudo_arg)
+          end
+          tok!(/\)/)
+        end
+        Selector::Pseudo.new(s == ':' ? :class : :element, merge(name), merge(arg))
+      end
+
+      def pseudo_arg
+        # In the CSS spec, every pseudo-class/element either takes a pseudo
+        # expression or a selector comma sequence as an argument. However, we
+        # don't want to have to know which takes which, so we handle both at
+        # once.
+        #
+        # However, there are some ambiguities between the two. For instance, "n"
+        # could start a pseudo expression like "n+1", or it could start a
+        # selector like "n|m". In order to handle this, we must regrettably
+        # backtrack.
+        expr, sel = nil, nil
+        pseudo_err = catch_error do
+          expr = pseudo_expr
+          next if tok?(/[,)]/)
+          expr = nil
+          expected '")"'
+        end
+
+        return expr if expr
+        sel_err = catch_error {sel = selector}
+        return sel if sel
+        rethrow pseudo_err if pseudo_err
+        rethrow sel_err if sel_err
+        return
+      end
+
+      def pseudo_expr
+        return unless e = tok(PLUS) || tok(/[-*]/) || tok(NUMBER) ||
+          interp_string || tok(IDENT) || interpolation
+        res = [e, str{ss}]
+        while e = tok(PLUS) || tok(/[-*]/) || tok(NUMBER) ||
+            interp_string || tok(IDENT) || interpolation
+          res << e << str{ss}
+        end
+        res
+      end
+
+      def declaration
+        # This allows the "*prop: val", ":prop: val", and ".prop: val" hacks
+        if s = tok(/[:\*\.]|\#(?!\{)/)
+          @use_property_exception = s !~ /[\.\#]/
+          name = [s, str{ss}, *expr!(:interp_ident)]
+        else
+          return unless name = interp_ident
+          name = [name] if name.is_a?(String)
+        end
+        if comment = tok(COMMENT)
+          name << comment
+        end
+        ss
+
+        tok!(/:/)
+        space, value = value!
+        ss
+        require_block = tok?(/\{/)
+
+        node = node(Sass::Tree::PropNode.new(name.flatten.compact, value, :new))
+
+        return node unless require_block
+        nested_properties! node, space
+      end
+
+      def value!
+        space = !str {ss}.empty?
+        @use_property_exception ||= space || !tok?(IDENT)
+
+        return true, Sass::Script::String.new("") if tok?(/\{/)
+        # This is a bit of a dirty trick:
+        # if the value is completely static,
+        # we don't parse it at all, and instead return a plain old string
+        # containing the value.
+        # This results in a dramatic speed increase.
+        if val = tok(STATIC_VALUE, true)
+          return space, Sass::Script::String.new(val.strip)
+        end
+        return space, sass_script(:parse)
+      end
+
+      def nested_properties!(node, space)
+        err(<<MESSAGE) unless space
+Invalid CSS: a space is required between a property and its definition
+when it has other properties nested beneath it.
+MESSAGE
+
+        @use_property_exception = true
+        @expected = 'expression (e.g. 1px, bold) or "{"'
+        block(node, :property)
+      end
+
+      def expr(allow_var = true)
+        return unless t = term(allow_var)
+        res = [t, str{ss}]
+
+        while (o = operator) && (t = term(allow_var))
+          res << o << t << str{ss}
+        end
+
+        res.flatten
+      end
+
+      def term(allow_var)
+        if e = tok(NUMBER) ||
+            interp_uri ||
+            function(allow_var) ||
+            interp_string ||
+            tok(UNICODERANGE) ||
+            interp_ident ||
+            tok(HEXCOLOR) ||
+            (allow_var && var_expr)
+          return e
+        end
+
+        return unless op = tok(/[+-]/)
+        @expected = "number or function"
+        return [op, tok(NUMBER) || function(allow_var) ||
+          (allow_var && var_expr) || expr!(:interpolation)]
+      end
+
+      def function(allow_var)
+        return unless name = tok(FUNCTION)
+        if name == "expression(" || name == "calc("
+          str, _ = Sass::Shared.balance(@scanner, ?(, ?), 1)
+          [name, str]
+        else
+          [name, str{ss}, expr(allow_var), tok!(/\)/)]
+        end
+      end
+
+      def var_expr
+        return unless tok(/\$/)
+        line = @line
+        var = Sass::Script::Variable.new(tok!(IDENT))
+        var.line = line
+        var
+      end
+
+      def interpolation
+        return unless tok(INTERP_START)
+        sass_script(:parse_interpolated)
+      end
+
+      def interp_string
+        _interp_string(:double) || _interp_string(:single)
+      end
+
+      def interp_uri
+        _interp_string(:uri)
+      end
+
+      def _interp_string(type)
+        return unless start = tok(Sass::Script::Lexer::STRING_REGULAR_EXPRESSIONS[[type, false]])
+        res = [start]
+
+        mid_re = Sass::Script::Lexer::STRING_REGULAR_EXPRESSIONS[[type, true]]
+        # @scanner[2].empty? means we've started an interpolated section
+        while @scanner[2] == '#{'
+          @scanner.pos -= 2 # Don't consume the #{
+          res.last.slice!(-2..-1)
+          res << expr!(:interpolation) << tok(mid_re)
+        end
+        res
+      end
+
+      def interp_ident(start = IDENT)
+        return unless val = tok(start) || interpolation || tok(IDENT_HYPHEN_INTERP, true)
+        res = [val]
+        while val = tok(NAME) || interpolation
+          res << val
+        end
+        res
+      end
+
+      def interp_ident_or_var
+        (id = interp_ident) and return id
+        (var = var_expr) and return [var]
+      end
+
+      def interp_name
+        interp_ident NAME
+      end
+
+      def str
+        @strs.push ""
+        yield
+        @strs.last
+      ensure
+        @strs.pop
+      end
+
+      def str?
+        pos = @scanner.pos
+        line = @line
+        @strs.push ""
+        throw_error {yield} && @strs.last
+      rescue Sass::SyntaxError
+        @scanner.pos = pos
+        @line = line
+        nil
+      ensure
+        @strs.pop
+      end
+
+      def node(node)
+        node.line = @line
+        node
+      end
+
+      @sass_script_parser = Class.new(Sass::Script::Parser)
+      @sass_script_parser.send(:include, ScriptParser)
+      # @private
+      def self.sass_script_parser; @sass_script_parser; end
+
+      def sass_script(*args)
+        parser = self.class.sass_script_parser.new(@scanner, @line,
+          @scanner.pos - (@scanner string[0    scanner pos] rindex("\n") || 0))
+        result = parser.send(*args)
+        unless @strs.empty?
+          # Convert to CSS manually so that comments are ignored.
+          src = result.to_sass
+          @strs.each {|s| s << src}
+        end
+        @line = parser.line
+        result
+      rescue Sass::SyntaxError => e
+        throw(:_sass_parser_error, true) if @throw_error
+        raise e
+      end
+
+      def merge(arr)
+        arr && Sass::Util.merge_adjacent_strings([arr].flatten)
+      end
+
+      EXPR_NAMES = {
+        :media_query => "media query (e.g. print, screen, print and screen)",
+        :media_query_list => "media query (e.g. print, screen, print and screen)",
+        :media_expr => "media expression (e.g. (min-device-width: 800px))",
+        :pseudo_arg => "expression (e.g. fr, 2n+1)",
+        :interp_ident => "identifier",
+        :interp_name => "identifier",
+        :qualified_name => "identifier",
+        :expr => "expression (e.g. 1px, bold)",
+        :_selector => "selector",
+        :selector_comma_sequence => "selector",
+        :simple_selector_sequence => "selector",
+        :import_arg => "file to import (string or url())",
+        :moz_document_function => "matching function (e.g. url-prefix(), domain())",
+        :supports_condition => "@supports condition (e.g. (display: flexbox))",
+        :supports_condition_in_parens => "@supports condition (e.g. (display: flexbox))",
+      }
+
+      TOK_NAMES = Sass::Util.to_hash(
+        Sass::SCSS::RX.constants.map {|c| [Sass::SCSS::RX.const_get(c), c.downcase]}).
+        merge(IDENT => "identifier", /[;}]/ => '";"')
+
+      def tok?(rx)
+        @scanner.match?(rx)
+      end
+
+      def expr!(name)
+        (e = send(name)) && (return e)
+        expected(EXPR_NAMES[name] || name.to_s)
+      end
+
+      def tok!(rx)
+        (t = tok(rx)) && (return t)
+        name = TOK_NAMES[rx]
+
+        unless name
+          # Display basic regexps as plain old strings
+          string = rx.source.gsub(/\\(.)/, '\1')
+          name = rx.source == Regexp.escape(string) ? string.inspect : rx.inspect
+        end
+
+        expected(name)
+      end
+
+      def expected(name)
+        throw(:_sass_parser_error, true) if @throw_error
+        self.class.expected(@scanner, @expected || name, @line)
+      end
+
+      def err(msg)
+        throw(:_sass_parser_error, true) if @throw_error
+        raise Sass::SyntaxError.new(msg, :line => @line)
+      end
+
+      def throw_error
+        old_throw_error, @throw_error = @throw_error, false
+        yield
+      ensure
+        @throw_error = old_throw_error
+      end
+
+      def catch_error(&block)
+        old_throw_error, @throw_error = @throw_error, true
+        pos = @scanner.pos
+        line = @line
+        expected = @expected
+        if catch(:_sass_parser_error) {yield; false}
+          @scanner.pos = pos
+          @line = line
+          @expected = expected
+          {:pos => pos, :line => line, :expected => @expected, :block => block}
+        end
+      ensure
+        @throw_error = old_throw_error
+      end
+
+      def rethrow(err)
+        if @throw_error
+          throw :_sass_parser_error, err
+        else
+          @scanner = Sass::Util::MultibyteStringScanner.new(@scanner.string)
+          @scanner.pos = err[:pos]
+          @line = err[:line]
+          @expected = err[:expected]
+          err[:block].call
+        end
+      end
+
+      # @private
+      def self.expected(scanner, expected, line)
+        pos = scanner.pos
+
+        after = scanner.string[0...pos]
+        # Get rid of whitespace between pos and the last token,
+        # but only if there's a newline in there
+        after.gsub!(/\s*\n\s*$/, '')
+        # Also get rid of stuff before the last newline
+        after.gsub!(/.*\n/, '')
+        after = "..." + after[-15..-1] if after.size > 18
+
+        was = scanner.rest.dup
+        # Get rid of whitespace between pos and the next token,
+        # but only if there's a newline in there
+        was.gsub!(/^\s*\n\s*/, '')
+        # Also get rid of stuff after the next newline
+        was.gsub!(/\n.*/, '')
+        was = was[0...15] + "..." if was.size > 18
+
+        raise Sass::SyntaxError.new(
+          "Invalid CSS after \"#{after}\": expected #{expected}, was \"#{was}\"",
+          :line => line)
+      end
+
+      # Avoid allocating lots of new strings for `#tok`.
+      # This is important because `#tok` is called all the time.
+      NEWLINE = "\n"
+
+      def tok(rx, last_group_lookahead = false)
+        res = @scanner.scan(rx)
+        if res
+          # This fixes https://github.com/nex3/sass/issues/104, which affects
+          # Ruby 1.8.7 and REE. This fix is to replace the ?= zero-width
+          # positive lookahead operator in the Regexp (which matches without
+          # consuming the matched group), with a match that does consume the
+          # group, but then rewinds the scanner and removes the group from the
+          # end of the matched string. This fix makes the assumption that the
+          # matched group will always occur at the end of the match.
+          if last_group_lookahead && @scanner[-1]
+            @scanner.pos -= @scanner[-1].length
+            res.slice!(- scanner[-1] length  -1)
+          end
+          @line += res.count(NEWLINE)
+          @expected = nil
+          if ! strs empty? && rx != COMMENT && rx != SINGLE_LINE_COMMENT
+            @strs.each {|s| s << res}
+          end
+          res
+        end
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/scss/rx.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/scss/rx.rb
new file mode 100644
index 0000000..96eb2e1
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/scss/rx.rb
@@ -0,0 +1,133 @@
+module Sass
+  module SCSS
+    # A module containing regular expressions used
+    # for lexing tokens in an SCSS document.
+    # Most of these are taken from [the CSS3 spec](http://www.w3.org/TR/css3-syntax/#lexical),
+    # although some have been modified for various reasons.
+    module RX
+      # Takes a string and returns a CSS identifier
+      # that will have the value of the given string.
+      #
+      # @param str [String] The string to escape
+      # @return [String] The escaped string
+      def self.escape_ident(str)
+        return "" if str.empty?
+        return "\\#{str}" if str == '-' || str == '_'
+        out = ""
+        value = str.dup
+        out << value.slice!(0...1) if value =~ /^[-_]/
+        if value[0...1] =~ NMSTART
+          out << value.slice!(0...1)
+        else
+          out << escape_char(value.slice!(0...1))
+        end
+        out << value.gsub(/[^a-zA-Z0-9_-]/) {|c| escape_char c}
+        return out
+      end
+
+      # Escapes a single character for a CSS identifier.
+      #
+      # @param c [String] The character to escape. Should have length 1
+      # @return [String] The escaped character
+      # @private
+      def self.escape_char(c)
+        return "\\%06x" % Sass::Util.ord(c) unless c =~ /[ -\/:-~]/
+        return "\\#{c}"
+      end
+
+      # Creates a Regexp from a plain text string,
+      # escaping all significant characters.
+      #
+      # @param str [String] The text of the regexp
+      # @param flags [Fixnum] Flags for the created regular expression
+      # @return [Regexp]
+      # @private
+      def self.quote(str, flags = 0)
+        Regexp.new(Regexp.quote(str), flags)
+      end
+
+      H        = /[0-9a-fA-F]/
+      NL       = /\n|\r\n|\r|\f/
+      UNICODE  = /\\#{H}{1,6}[ \t\r\n\f]?/
+      s = if Sass::Util.ruby1_8?
+            '\200-\377'
+          elsif Sass::Util.macruby?
+            '\u0080-\uD7FF\uE000-\uFFFD\U00010000-\U0010FFFF'
+          else
+            '\u{80}-\u{D7FF}\u{E000}-\u{FFFD}\u{10000}-\u{10FFFF}'
+          end
+      NONASCII = /[#{s}]/
+      ESCAPE   = /#{UNICODE}|\\[ -~#{s}]/
+      NMSTART  = /[_a-zA-Z]|#{NONASCII}|#{ESCAPE}/
+      NMCHAR   = /[a-zA-Z0-9_-]|#{NONASCII}|#{ESCAPE}/
+      STRING1  = /\"((?:[^\n\r\f\\"]|\\#{NL}|#{ESCAPE})*)\"/
+      STRING2  = /\'((?:[^\n\r\f\\']|\\#{NL}|#{ESCAPE})*)\'/
+
+      IDENT    = /-?#{NMSTART}#{NMCHAR}*/
+      NAME     = /#{NMCHAR}+/
+      NUM      = /[0-9]+|[0-9]*\.[0-9]+/
+      STRING   = /#{STRING1}|#{STRING2}/
+      URLCHAR  = /[#%&*-~]|#{NONASCII}|#{ESCAPE}/
+      URL      = /(#{URLCHAR}*)/
+      W        = /[ \t\r\n\f]*/
+      VARIABLE = /(\$)(#{Sass::SCSS::RX::IDENT})/
+
+      # This is more liberal than the spec's definition,
+      # but that definition didn't work well with the greediness rules
+      RANGE    = /(?:#{H}|\?){1,6}/
+
+      ##
+
+      S = /[ \t\r\n\f]+/
+
+      COMMENT = /\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\//
+      SINGLE_LINE_COMMENT = /\/\/.*(\n[ \t]*\/\/.*)*/
+
+      CDO            = quote("<!--")
+      CDC            = quote("-->")
+      INCLUDES       = quote("~=")
+      DASHMATCH      = quote("|=")
+      PREFIXMATCH    = quote("^=")
+      SUFFIXMATCH    = quote("$=")
+      SUBSTRINGMATCH = quote("*=")
+
+      HASH = /##{NAME}/
+
+      IMPORTANT = /!#{W}important/i
+      DEFAULT = /!#{W}default/i
+
+      NUMBER = /#{NUM}(?:#{IDENT}|%)?/
+
+      URI = /url\(#{W}(?:#{STRING}|#{URL})#{W}\)/i
+      FUNCTION = /#{IDENT}\(/
+
+      UNICODERANGE = /u\+(?:#{H}{1,6}-#{H}{1,6}|#{RANGE})/i
+
+      # Defined in http://www.w3.org/TR/css3-selectors/#lex
+      PLUS = /#{W}\+/
+      GREATER = /#{W}>/
+      TILDE = /#{W}~/
+      NOT = quote(":not(", Regexp::IGNORECASE)
+
+      # Defined in https://developer.mozilla.org/en/CSS/@-moz-document as a
+      # non-standard version of http://www.w3.org/TR/css3-conditional/
+      URL_PREFIX = /url-prefix\(#{W}(?:#{STRING}|#{URL})#{W}\)/i
+      DOMAIN = /domain\(#{W}(?:#{STRING}|#{URL})#{W}\)/i
+
+      # Custom
+      HEXCOLOR = /\#[0-9a-fA-F]+/
+      INTERP_START = /#\{/
+      ANY = /:(-[-\w]+-)?any\(/i
+      OPTIONAL = /!#{W}optional/i
+
+      IDENT_HYPHEN_INTERP = /-(#\{)/
+      STRING1_NOINTERP = /\"((?:[^\n\r\f\\"#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\"/
+      STRING2_NOINTERP = /\'((?:[^\n\r\f\\'#]|#(?!\{)|\\#{NL}|#{ESCAPE})*)\'/
+      STRING_NOINTERP = /#{STRING1_NOINTERP}|#{STRING2_NOINTERP}/
+
+      STATIC_COMPONENT = /#{IDENT}|#{STRING_NOINTERP}|#{HEXCOLOR}|[+-]?#{NUMBER}|\!important/i
+      STATIC_VALUE = /#{STATIC_COMPONENT}(\s*[\s,\/]\s*#{STATIC_COMPONENT})*([;}])/i
+      STATIC_SELECTOR = /(#{NMCHAR}|[ \t]|[,>+*]|[:#.]#{NMSTART}){0,50}([{])/i
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/scss/script_lexer.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/scss/script_lexer.rb
new file mode 100644
index 0000000..777485f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/scss/script_lexer.rb
@@ -0,0 +1,15 @@
+module Sass
+  module SCSS
+    # A mixin for subclasses of {Sass::Script::Lexer}
+    # that makes them usable by {SCSS::Parser} to parse SassScript.
+    # In particular, the lexer doesn't support `!` for a variable prefix.
+    module ScriptLexer
+      private
+
+      def variable
+        return [:raw, "!important"] if scan(Sass::SCSS::RX::IMPORTANT)
+        _variable(Sass::SCSS::RX::VARIABLE)
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/scss/script_parser.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/scss/script_parser.rb
new file mode 100644
index 0000000..e5f64b2
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/scss/script_parser.rb
@@ -0,0 +1,25 @@
+module Sass
+  module SCSS
+    # A mixin for subclasses of {Sass::Script::Parser}
+    # that makes them usable by {SCSS::Parser} to parse SassScript.
+    # In particular, the parser won't raise an error
+    # when there's more content in the lexer once lexing is done.
+    # In addition, the parser doesn't support `!` for a variable prefix.
+    module ScriptParser
+      private
+
+      # @private
+      def lexer_class
+        klass = Class.new(super)
+        klass.send(:include, ScriptLexer)
+        klass
+      end
+
+      # Instead of raising an error when the parser is done,
+      # rewind the StringScanner so that it hasn't consumed the final token.
+      def assert_done
+        @lexer.unpeek!
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/scss/static_parser.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/scss/static_parser.rb
new file mode 100644
index 0000000..9d473cd
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/scss/static_parser.rb
@@ -0,0 +1,54 @@
+require 'sass/script/css_parser'
+
+module Sass
+  module SCSS
+    # A parser for a static SCSS tree.
+    # Parses with SCSS extensions, like nested rules and parent selectors,
+    # but without dynamic SassScript.
+    # This is useful for e.g. \{#parse\_selector parsing selectors}
+    # after resolving the interpolation.
+    class StaticParser < Parser
+      # Parses the text as a selector.
+      #
+      # @param filename [String, nil] The file in which the selector appears,
+      #   or nil if there is no such file.
+      #   Used for error reporting.
+      # @return [Selector::CommaSequence] The parsed selector
+      # @raise [Sass::SyntaxError] if there's a syntax error in the selector
+      def parse_selector
+        init_scanner!
+        seq = expr!(:selector_comma_sequence)
+        expected("selector") unless @scanner.eos?
+        seq.line = @line
+        seq.filename = @filename
+        seq
+      end
+
+      private
+
+      def moz_document_function
+        return unless val = tok(URI) || tok(URL_PREFIX) || tok(DOMAIN) ||
+          function(!:allow_var)
+        ss
+        [val]
+      end
+
+      def variable; nil; end
+      def script_value; nil; end
+      def interpolation; nil; end
+      def var_expr; nil; end
+      def interp_string; s = tok(STRING) and [s]; end
+      def interp_uri; s = tok(URI) and [s]; end
+      def interp_ident(ident = IDENT); s = tok(ident) and [s]; end
+      def use_css_import?; true; end
+
+      def special_directive(name)
+        return unless %w[media import charset -moz-document].include?(name)
+        super
+      end
+
+      @sass_script_parser = Class.new(Sass::Script::CssParser)
+      @sass_script_parser.send(:include, ScriptParser)
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/selector.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/selector.rb
new file mode 100644
index 0000000..9e4cfea
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/selector.rb
@@ -0,0 +1,452 @@
+require 'sass/selector/simple'
+require 'sass/selector/abstract_sequence'
+require 'sass/selector/comma_sequence'
+require 'sass/selector/sequence'
+require 'sass/selector/simple_sequence'
+
+module Sass
+  # A namespace for nodes in the parse tree for selectors.
+  #
+  # {CommaSequence} is the toplevel seelctor,
+  # representing a comma-separated sequence of {Sequence}s,
+  # such as `foo bar, baz bang`.
+  # {Sequence} is the next level,
+  # representing {SimpleSequence}s separated by combinators (e.g. descendant or child),
+  # such as `foo bar` or `foo > bar baz`.
+  # {SimpleSequence} is a sequence of selectors that all apply to a single element,
+  # such as `foo.bar[attr=val]`.
+  # Finally, {Simple} is the superclass of the simplest selectors,
+  # such as `.foo` or `#bar`.
+  module Selector
+    # The base used for calculating selector specificity. The spec says this
+    # should be "sufficiently high"; it's extremely unlikely that any single
+    # selector sequence will contain 1,000 simple selectors.
+    #
+    # @type [Fixnum]
+    SPECIFICITY_BASE = 1_000
+
+    # A parent-referencing selector (`&` in Sass).
+    # The function of this is to be replaced by the parent selector
+    # in the nested hierarchy.
+    class Parent < Simple
+      # @see Selector#to_a
+      def to_a
+        ["&"]
+      end
+
+      # Always raises an exception.
+      #
+      # @raise [Sass::SyntaxError] Parent selectors should be resolved before unification
+      # @see Selector#unify
+      def unify(sels)
+        raise Sass::SyntaxError.new("[BUG] Cannot unify parent selectors.")
+      end
+    end
+
+    # A class selector (e.g. `.foo`).
+    class Class < Simple
+      # The class name.
+      #
+      # @return [Array<String, Sass::Script::Node>]
+      attr_reader :name
+
+      # @param name [Array<String, Sass::Script::Node>] The class name
+      def initialize(name)
+        @name = name
+      end
+
+      # @see Selector#to_a
+      def to_a
+        [".", * name]
+      end
+
+      # @see AbstractSequence#specificity
+      def specificity
+        SPECIFICITY_BASE
+      end
+    end
+
+    # An id selector (e.g. `#foo`).
+    class Id < Simple
+      # The id name.
+      #
+      # @return [Array<String, Sass::Script::Node>]
+      attr_reader :name
+
+      # @param name [Array<String, Sass::Script::Node>] The id name
+      def initialize(name)
+        @name = name
+      end
+
+      # @see Selector#to_a
+      def to_a
+        ["#", * name]
+      end
+
+      # Returns `nil` if `sels` contains an {Id} selector
+      # with a different name than this one.
+      #
+      # @see Selector#unify
+      def unify(sels)
+        return if sels.any? {|sel2| sel2.is_a?(Id) && self.name != sel2.name}
+        super
+      end
+
+      # @see AbstractSequence#specificity
+      def specificity
+        SPECIFICITY_BASE**2
+      end
+    end
+
+    # A placeholder selector (e.g. `%foo`).
+    # This exists to be replaced via ` extend` 
+    # Rulesets using this selector will not be printed, but can be extended.
+    # Otherwise, this acts just like a class selector.
+    class Placeholder < Simple
+      # The placeholder name.
+      #
+      # @return [Array<String, Sass::Script::Node>]
+      attr_reader :name
+
+      # @param name [Array<String, Sass::Script::Node>] The placeholder name
+      def initialize(name)
+        @name = name
+      end
+
+      # @see Selector#to_a
+      def to_a
+        ["%", * name]
+      end
+
+      # @see AbstractSequence#specificity
+      def specificity
+        SPECIFICITY_BASE
+      end
+    end
+
+    # A universal selector (`*` in CSS).
+    class Universal < Simple
+      # The selector namespace.
+      # `nil` means the default namespace,
+      # `[""]` means no namespace,
+      # `["*"]` means any namespace.
+      #
+      # @return [Array<String, Sass::Script::Node>, nil]
+      attr_reader :namespace
+
+      # @param namespace [Array<String, Sass::Script::Node>, nil] See \{#namespace}
+      def initialize(namespace)
+        @namespace = namespace
+      end
+
+      # @see Selector#to_a
+      def to_a
+        @namespace ? @namespace + ["|*"] : ["*"]
+      end
+
+      # Unification of a universal selector is somewhat complicated,
+      # especially when a namespace is specified.
+      # If there is no namespace specified
+      # or any namespace is specified (namespace `"*"`),
+      # then `sel` is returned without change
+      # (unless it's empty, in which case `"*"` is required).
+      #
+      # If a namespace is specified
+      # but `sel` does not specify a namespace,
+      # then the given namespace is applied to `sel`,
+      # either by adding this {Universal} selector
+      # or applying this namespace to an existing {Element} selector.
+      #
+      # If both this selector *and* `sel` specify namespaces,
+      # those namespaces are unified via {Simple#unify_namespaces}
+      # and the unified namespace is used, if possible.
+      #
+      # @todo There are lots of cases that this documentation specifies;
+      #   make sure we thoroughly test **all of them**.
+      # @todo Keep track of whether a default namespace has been declared
+      #   and handle namespace-unspecified selectors accordingly.
+      # @todo If any branch of a CommaSequence ends up being just `"*"`,
+      #   then all other branches should be eliminated
+      #
+      # @see Selector#unify
+      def unify(sels)
+        name =
+          case sels.first
+          when Universal; :universal
+          when Element; sels.first.name
+          else
+            return [self] + sels unless namespace.nil? || namespace == ['*']
+            return sels unless sels.empty?
+            return [self]
+          end
+
+        ns, accept = unify_namespaces(namespace, sels.first.namespace)
+        return unless accept
+        [name == :universal ? Universal.new(ns) : Element.new(name, ns)] + sels[1..-1]
+      end
+
+      # @see AbstractSequence#specificity
+      def specificity
+        0
+      end
+    end
+
+    # An element selector (e.g. `h1`).
+    class Element < Simple
+      # The element name.
+      #
+      # @return [Array<String, Sass::Script::Node>]
+      attr_reader :name
+
+      # The selector namespace.
+      # `nil` means the default namespace,
+      # `[""]` means no namespace,
+      # `["*"]` means any namespace.
+      #
+      # @return [Array<String, Sass::Script::Node>, nil]
+      attr_reader :namespace
+
+      # @param name [Array<String, Sass::Script::Node>] The element name
+      # @param namespace [Array<String, Sass::Script::Node>, nil] See \{#namespace}
+      def initialize(name, namespace)
+        @name = name
+        @namespace = namespace
+      end
+
+      # @see Selector#to_a
+      def to_a
+        @namespace ? @namespace + ["|"] + @name : @name
+      end
+
+      # Unification of an element selector is somewhat complicated,
+      # especially when a namespace is specified.
+      # First, if `sel` contains another {Element} with a different \{#name},
+      # then the selectors can't be unified and `nil` is returned.
+      #
+      # Otherwise, if `sel` doesn't specify a namespace,
+      # or it specifies any namespace (via `"*"`),
+      # then it's returned with this element selector
+      # (e.g. `.foo` becomes `a.foo` or `svg|a.foo`).
+      # Similarly, if this selector doesn't specify a namespace,
+      # the namespace from `sel` is used.
+      #
+      # If both this selector *and* `sel` specify namespaces,
+      # those namespaces are unified via {Simple#unify_namespaces}
+      # and the unified namespace is used, if possible.
+      #
+      # @todo There are lots of cases that this documentation specifies;
+      #   make sure we thoroughly test **all of them**.
+      # @todo Keep track of whether a default namespace has been declared
+      #   and handle namespace-unspecified selectors accordingly.
+      #
+      # @see Selector#unify
+      def unify(sels)
+        case sels.first
+        when Universal;
+        when Element; return unless name == sels.first.name
+        else return [self] + sels
+        end
+
+        ns, accept = unify_namespaces(namespace, sels.first.namespace)
+        return unless accept
+        [Element.new(name, ns)] + sels[1..-1]
+      end
+
+      # @see AbstractSequence#specificity
+      def specificity
+        1
+      end
+    end
+
+    # Selector interpolation (`#{}` in Sass).
+    class Interpolation < Simple
+      # The script to run.
+      #
+      # @return [Sass::Script::Node]
+      attr_reader :script
+
+      # @param script [Sass::Script::Node] The script to run
+      def initialize(script)
+        @script = script
+      end
+
+      # @see Selector#to_a
+      def to_a
+        [ script]
+      end
+
+      # Always raises an exception.
+      #
+      # @raise [Sass::SyntaxError] Interpolation selectors should be resolved before unification
+      # @see Selector#unify
+      def unify(sels)
+        raise Sass::SyntaxError.new("[BUG] Cannot unify interpolation selectors.")
+      end
+    end
+
+    # An attribute selector (e.g. `[href^="http://"]`).
+    class Attribute < Simple
+      # The attribute name.
+      #
+      # @return [Array<String, Sass::Script::Node>]
+      attr_reader :name
+
+      # The attribute namespace.
+      # `nil` means the default namespace,
+      # `[""]` means no namespace,
+      # `["*"]` means any namespace.
+      #
+      # @return [Array<String, Sass::Script::Node>, nil]
+      attr_reader :namespace
+
+      # The matching operator, e.g. `"="` or `"^="`.
+      #
+      # @return [String]
+      attr_reader :operator
+
+      # The right-hand side of the operator.
+      #
+      # @return [Array<String, Sass::Script::Node>]
+      attr_reader :value
+
+      # Flags for the attribute selector (e.g. `i`).
+      #
+      # @return [Array<String, Sass::Script::Node>]
+      attr_reader :flags
+
+      # @param name [Array<String, Sass::Script::Node>] The attribute name
+      # @param namespace [Array<String, Sass::Script::Node>, nil] See \{#namespace}
+      # @param operator [String] The matching operator, e.g. `"="` or `"^="`
+      # @param value [Array<String, Sass::Script::Node>] See \{#value}
+      # @param value [Array<String, Sass::Script::Node>] See \{#flags}
+      def initialize(name, namespace, operator, value, flags)
+        @name = name
+        @namespace = namespace
+        @operator = operator
+        @value = value
+        @flags = flags
+      end
+
+      # @see Selector#to_a
+      def to_a
+        res = ["["]
+        res.concat(@namespace) << "|" if @namespace
+        res.concat @name
+        (res << @operator).concat @value if @value
+        (res << " ").concat @flags if @flags
+        res << "]"
+      end
+
+      # @see AbstractSequence#specificity
+      def specificity
+        SPECIFICITY_BASE
+      end
+    end
+
+    # A pseudoclass (e.g. `:visited`) or pseudoelement (e.g. `::first-line`) selector.
+    # It can have arguments (e.g. `:nth-child(2n+1)`).
+    class Pseudo < Simple
+      # Some psuedo-class-syntax selectors are actually considered
+      # pseudo-elements and must be treated differently. This is a list of such
+      # selectors
+      #
+      # @return [Array<String>]
+      ACTUALLY_ELEMENTS = %w[after before first-line first-letter]
+
+      # Like \{#type}, but returns the type of selector this looks like, rather
+      # than the type it is semantically. This only differs from type for
+      # selectors in \{ACTUALLY\_ELEMENTS}.
+      #
+      # @return [Symbol]
+      attr_reader :syntactic_type
+
+      # The name of the selector.
+      #
+      # @return [Array<String, Sass::Script::Node>]
+      attr_reader :name
+
+      # The argument to the selector,
+      # or `nil` if no argument was given.
+      #
+      # This may include SassScript nodes that will be run during resolution.
+      # Note that this should not include SassScript nodes
+      # after resolution has taken place.
+      #
+      # @return [Array<String, Sass::Script::Node>, nil]
+      attr_reader :arg
+
+      # @param type [Symbol] See \{#type}
+      # @param name [Array<String, Sass::Script::Node>] The name of the selector
+      # @param arg [nil, Array<String, Sass::Script::Node>] The argument to the selector,
+      #   or nil if no argument was given
+      def initialize(type, name, arg)
+        @syntactic_type = type
+        @name = name
+        @arg = arg
+      end
+
+      # The type of the selector. `:class` if this is a pseudoclass selector,
+      # `:element` if it's a pseudoelement.
+      #
+      # @return [Symbol]
+      def type
+        ACTUALLY_ELEMENTS.include?(name.first) ? :element : syntactic_type
+      end
+
+      # @see Selector#to_a
+      def to_a
+        res = [syntactic_type == :class ? ":" : "::"] + @name
+        (res << "(").concat(Sass::Util.strip_string_array(@arg)) << ")" if @arg
+        res
+      end
+
+      # Returns `nil` if this is a pseudoelement selector
+      # and `sels` contains a pseudoelement selector different than this one.
+      #
+      # @see Selector#unify
+      def unify(sels)
+        return if type == :element && sels.any? do |sel|
+          sel.is_a?(Pseudo) && sel.type == :element &&
+            (sel.name != self.name || sel.arg != self.arg)
+        end
+        super
+      end
+
+      # @see AbstractSequence#specificity
+      def specificity
+        type == :class ? SPECIFICITY_BASE : 1
+      end
+    end
+
+    # A pseudoclass selector whose argument is itself a selector
+    # (e.g. `:not(.foo)` or `:-moz-all(.foo, .bar)`).
+    class SelectorPseudoClass < Simple
+      # The name of the pseudoclass.
+      #
+      # @return [String]
+      attr_reader :name
+
+      # The selector argument.
+      #
+      # @return [Selector::Sequence]
+      attr_reader :selector
+
+      # @param [String] The name of the pseudoclass
+      # @param [Selector::CommaSequence] The selector argument
+      def initialize(name, selector)
+        @name = name
+        @selector = selector
+      end
+
+      # @see Selector#to_a
+      def to_a
+        [":", @name, "("] + @selector.to_a + [")"]
+      end
+
+      # @see AbstractSequence#specificity
+      def specificity
+        SPECIFICITY_BASE
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/selector/abstract_sequence.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/selector/abstract_sequence.rb
new file mode 100644
index 0000000..9b67800
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/selector/abstract_sequence.rb
@@ -0,0 +1,94 @@
+module Sass
+  module Selector
+    # The abstract parent class of the various selector sequence classes.
+    #
+    # All subclasses should implement a `members` method that returns an array
+    # of object that respond to `#line=` and `#filename=`, as well as a `to_a`
+    # method that returns an array of strings and script nodes.
+    class AbstractSequence
+      # The line of the Sass template on which this selector was declared.
+      #
+      # @return [Fixnum]
+      attr_reader :line
+
+      # The name of the file in which this selector was declared.
+      #
+      # @return [String, nil]
+      attr_reader :filename
+
+      # Sets the line of the Sass template on which this selector was declared.
+      # This also sets the line for all child selectors.
+      #
+      # @param line [Fixnum]
+      # @return [Fixnum]
+      def line=(line)
+        members.each {|m| m.line = line}
+        @line = line
+      end
+
+      # Sets the name of the file in which this selector was declared,
+      # or `nil` if it was not declared in a file (e.g. on stdin).
+      # This also sets the filename for all child selectors.
+      #
+      # @param filename [String, nil]
+      # @return [String, nil]
+      def filename=(filename)
+        members.each {|m| m.filename = filename}
+        @filename = filename
+      end
+
+      # Returns a hash code for this sequence.
+      #
+      # Subclasses should define `#_hash` rather than overriding this method,
+      # which automatically handles memoizing the result.
+      #
+      # @return [Fixnum]
+      def hash
+        @_hash ||= _hash
+      end
+
+      # Checks equality between this and another object.
+      #
+      # Subclasses should define `#_eql?` rather than overriding this method,
+      # which handles checking class equality and hash equality.
+      #
+      # @param other [Object] The object to test equality against
+      # @return [Boolean] Whether or not this is equal to `other`
+      def eql?(other)
+        other.class == self.class && other.hash == self.hash && _eql?(other)
+      end
+      alias_method :==, :eql?
+
+      # Whether or not this selector sequence contains a placeholder selector.
+      # Checks recursively.
+      def has_placeholder?
+        @has_placeholder ||=
+          members.any? {|m| m.is_a?(AbstractSequence) ? m.has_placeholder? : m.is_a?(Placeholder)}
+      end
+
+      # Converts the selector into a string. This is the standard selector
+      # string, along with any SassScript interpolation that may exist.
+      #
+      # @return [String]
+      def to_s
+        to_a.map {|e| e.is_a?(Sass::Script::Node) ? "\#{#{e.to_sass}}" : e}.join
+      end
+
+      # Returns the specificity of the selector as an integer. The base is given
+      # by {Sass::Selector::SPECIFICITY_BASE}.
+      #
+      # @return [Fixnum]
+      def specificity
+        _specificity(members)
+      end
+
+      protected
+
+      def _specificity(arr)
+        spec = 0
+        arr.map {|m| spec += m.is_a?(String) ? 0 : m.specificity}
+        spec
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/selector/comma_sequence.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/selector/comma_sequence.rb
new file mode 100644
index 0000000..0b70140
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/selector/comma_sequence.rb
@@ -0,0 +1,92 @@
+module Sass
+  module Selector
+    # A comma-separated sequence of selectors.
+    class CommaSequence < AbstractSequence
+      # The comma-separated selector sequences
+      # represented by this class.
+      #
+      # @return [Array<Sequence>]
+      attr_reader :members
+
+      # @param seqs [Array<Sequence>] See \{#members}
+      def initialize(seqs)
+        @members = seqs
+      end
+
+      # Resolves the {Parent} selectors within this selector
+      # by replacing them with the given parent selector,
+      # handling commas appropriately.
+      #
+      # @param super_cseq [CommaSequence] The parent selector
+      # @return [CommaSequence] This selector, with parent references resolved
+      # @raise [Sass::SyntaxError] If a parent selector is invalid
+      def resolve_parent_refs(super_cseq)
+        if super_cseq.nil?
+          if @members.any? do |sel|
+              sel.members.any? do |sel_or_op|
+                sel_or_op.is_a?(SimpleSequence) && sel_or_op.members.any? {|ssel| ssel.is_a?(Parent)}
+              end
+            end
+            raise Sass::SyntaxError.new("Base-level rules cannot contain the parent-selector-referencing 
character '&'.")
+          end
+          return self
+        end
+
+        CommaSequence.new(
+          super_cseq.members.map do |super_seq|
+            @members.map {|seq| seq.resolve_parent_refs(super_seq)}
+          end.flatten)
+      end
+
+      # Non-destrucively extends this selector with the extensions specified in a hash
+      # (which should come from {Sass::Tree::Visitors::Cssize}).
+      #
+      # @todo Link this to the reference documentation on ` extend`
+      #   when such a thing exists.
+      #
+      # @param extends [Sass::Util::SubsetMap{Selector::Simple =>
+      #                                       Sass::Tree::Visitors::Cssize::Extend}]
+      #   The extensions to perform on this selector
+      # @param parent_directives [Array<Sass::Tree::DirectiveNode>]
+      #   The directives containing this selector.
+      # @return [CommaSequence] A copy of this selector,
+      #   with extensions made according to `extends`
+      def do_extend(extends, parent_directives)
+        CommaSequence.new(members.map do |seq|
+            extended = seq.do_extend(extends, parent_directives)
+            # First Law of Extend: the result of extending a selector should
+            # always contain the base selector.
+            #
+            # See https://github.com/nex3/sass/issues/324.
+            extended.unshift seq unless seq.has_placeholder? || extended.include?(seq)
+            extended
+          end.flatten)
+      end
+
+      # Returns a string representation of the sequence.
+      # This is basically the selector string.
+      #
+      # @return [String]
+      def inspect
+        members.map {|m| m.inspect}.join(", ")
+      end
+
+      # @see Simple#to_a
+      def to_a
+        arr = Sass::Util.intersperse(@members.map {|m| m.to_a}, ", ").flatten
+        arr.delete("\n")
+        arr
+      end
+
+      private
+
+      def _hash
+        members.hash
+      end
+
+      def _eql?(other)
+        other.class == self.class && other.members.eql?(self.members)
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/selector/sequence.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/selector/sequence.rb
new file mode 100644
index 0000000..c172961
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/selector/sequence.rb
@@ -0,0 +1,507 @@
+module Sass
+  module Selector
+    # An operator-separated sequence of
+    # {SimpleSequence simple selector sequences}.
+    class Sequence < AbstractSequence
+      # Sets the line of the Sass template on which this selector was declared.
+      # This also sets the line for all child selectors.
+      #
+      # @param line [Fixnum]
+      # @return [Fixnum]
+      def line=(line)
+        members.each {|m| m.line = line if m.is_a?(SimpleSequence)}
+        line
+      end
+
+      # Sets the name of the file in which this selector was declared,
+      # or `nil` if it was not declared in a file (e.g. on stdin).
+      # This also sets the filename for all child selectors.
+      #
+      # @param filename [String, nil]
+      # @return [String, nil]
+      def filename=(filename)
+        members.each {|m| m.filename = filename if m.is_a?(SimpleSequence)}
+        filename
+      end
+
+      # The array of {SimpleSequence simple selector sequences}, operators, and
+      # newlines. The operators are strings such as `"+"` and `">"` representing
+      # the corresponding CSS operators, or interpolated SassScript. Newlines
+      # are also newline strings; these aren't semantically relevant, but they
+      # do affect formatting.
+      #
+      # @return [Array<SimpleSequence, String|Array<Sass::Tree::Node, String>>]
+      attr_reader :members
+
+      # @param seqs_and_ops [Array<SimpleSequence, String|Array<Sass::Tree::Node, String>>] See \{#members}
+      def initialize(seqs_and_ops)
+        @members = seqs_and_ops
+      end
+
+      # Resolves the {Parent} selectors within this selector
+      # by replacing them with the given parent selector,
+      # handling commas appropriately.
+      #
+      # @param super_seq [Sequence] The parent selector sequence
+      # @return [Sequence] This selector, with parent references resolved
+      # @raise [Sass::SyntaxError] If a parent selector is invalid
+      def resolve_parent_refs(super_seq)
+        members = @members.dup
+        nl = (members.first == "\n" && members.shift)
+        unless members.any? do |seq_or_op|
+            seq_or_op.is_a?(SimpleSequence) && seq_or_op.members.first.is_a?(Parent)
+          end
+          old_members, members = members, []
+          members << nl if nl
+          members << SimpleSequence.new([Parent.new], false)
+          members += old_members
+        end
+
+        Sequence.new(
+          members.map do |seq_or_op|
+            next seq_or_op unless seq_or_op.is_a?(SimpleSequence)
+            seq_or_op.resolve_parent_refs(super_seq)
+          end.flatten)
+      end
+
+      # Non-destructively extends this selector with the extensions specified in a hash
+      # (which should come from {Sass::Tree::Visitors::Cssize}).
+      #
+      # @overload def do_extend(extends, parent_directives)
+      # @param extends [Sass::Util::SubsetMap{Selector::Simple =>
+      #                                       Sass::Tree::Visitors::Cssize::Extend}]
+      #   The extensions to perform on this selector
+      # @param parent_directives [Array<Sass::Tree::DirectiveNode>]
+      #   The directives containing this selector.
+      # @return [Array<Sequence>] A list of selectors generated
+      #   by extending this selector with `extends`.
+      #   These correspond to a {CommaSequence}'s {CommaSequence#members members array}.
+      # @see CommaSequence#do_extend
+      def do_extend(extends, parent_directives, seen = Set.new)
+        extended_not_expanded = members.map do |sseq_or_op|
+          next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
+          extended = sseq_or_op.do_extend(extends, parent_directives, seen)
+          choices = extended.map {|seq| seq.members}
+          choices.unshift([sseq_or_op]) unless extended.any? {|seq| seq.superselector?(sseq_or_op)}
+          choices
+        end
+        weaves = Sass::Util.paths(extended_not_expanded).map {|path| weave(path)}
+        Sass::Util.flatten(trim(weaves), 1).map {|p| Sequence.new(p)}
+      end
+
+      # Returns whether or not this selector matches all elements
+      # that the given selector matches (as well as possibly more).
+      #
+      # @example
+      #   (.foo).superselector?(.foo.bar) #=> true
+      #   (.foo).superselector?(.bar) #=> false
+      #   (.bar .foo).superselector?(.foo) #=> false
+      # @param sseq [SimpleSequence]
+      # @return [Boolean]
+      def superselector?(sseq)
+        return false unless members.size == 1
+        members.last.superselector?(sseq)
+      end
+
+      # @see Simple#to_a
+      def to_a
+        ary = @members.map {|seq_or_op| seq_or_op.is_a?(SimpleSequence) ? seq_or_op.to_a : seq_or_op}
+        Sass::Util.intersperse(ary, " ").flatten.compact
+      end
+
+      # Returns a string representation of the sequence.
+      # This is basically the selector string.
+      #
+      # @return [String]
+      def inspect
+        members.map {|m| m.inspect}.join(" ")
+      end
+
+      # Add to the {SimpleSequence#sources} sets of the child simple sequences.
+      # This destructively modifies this sequence's members array, but not the
+      # child simple sequences.
+      #
+      # @param sources [Set<Sequence>]
+      def add_sources!(sources)
+        members.map! {|m| m.is_a?(SimpleSequence) ? m.with_more_sources(sources) : m}
+      end
+
+      private
+
+      # Conceptually, this expands "parenthesized selectors".
+      # That is, if we have `.A .B { extend .C}` and `.D .C {...}`,
+      # this conceptually expands into `.D .C, .D (.A .B)`,
+      # and this function translates `.D (.A .B)` into `.D .A .B, .A.D .B, .D .A .B`.
+      #
+      # @param path [Array<Array<SimpleSequence or String>>] A list of parenthesized selector groups.
+      # @return [Array<Array<SimpleSequence or String>>] A list of fully-expanded selectors.
+      def weave(path)
+        # This function works by moving through the selector path left-to-right,
+        # building all possible prefixes simultaneously. These prefixes are
+        # `befores`, while the remaining parenthesized suffixes is `afters`.
+        befores = [[]]
+        afters = path.dup
+
+        until afters.empty?
+          current = afters.shift.dup
+          last_current = [current.pop]
+          befores = Sass::Util.flatten(befores.map do |before|
+              next [] unless sub = subweave(before, current)
+              sub.map {|seqs| seqs + last_current}
+            end, 1)
+        end
+        return befores
+      end
+
+      # This interweaves two lists of selectors,
+      # returning all possible orderings of them (including using unification)
+      # that maintain the relative ordering of the input arrays.
+      #
+      # For example, given `.foo .bar` and `.baz .bang`,
+      # this would return `.foo .bar .baz .bang`, `.foo .bar.baz .bang`,
+      # `.foo .baz .bar .bang`, `.foo .baz .bar.bang`, `.foo .baz .bang .bar`,
+      # and so on until `.baz .bang .foo .bar`.
+      #
+      # Semantically, for selectors A and B, this returns all selectors `AB_i`
+      # such that the union over all i of elements matched by `AB_i X` is
+      # identical to the intersection of all elements matched by `A X` and all
+      # elements matched by `B X`. Some `AB_i` are elided to reduce the size of
+      # the output.
+      #
+      # @param seq1 [Array<SimpleSequence or String>]
+      # @param seq2 [Array<SimpleSequence or String>]
+      # @return [Array<Array<SimpleSequence or String>>]
+      def subweave(seq1, seq2)
+        return [seq2] if seq1.empty?
+        return [seq1] if seq2.empty?
+
+        seq1, seq2 = seq1.dup, seq2.dup
+        return unless init = merge_initial_ops(seq1, seq2)
+        return unless fin = merge_final_ops(seq1, seq2)
+        seq1 = group_selectors(seq1)
+        seq2 = group_selectors(seq2)
+        lcs = Sass::Util.lcs(seq2, seq1) do |s1, s2|
+          next s1 if s1 == s2
+          next unless s1.first.is_a?(SimpleSequence) && s2.first.is_a?(SimpleSequence)
+          next s2 if parent_superselector?(s1, s2)
+          next s1 if parent_superselector?(s2, s1)
+        end
+
+        diff = [[init]]
+        until lcs.empty?
+          diff << chunks(seq1, seq2) {|s| parent_superselector?(s.first, lcs.first)} << [lcs.shift]
+          seq1.shift
+          seq2.shift
+        end
+        diff << chunks(seq1, seq2) {|s| s.empty?}
+        diff += fin.map {|sel| sel.is_a?(Array) ? sel : [sel]}
+        diff.reject! {|c| c.empty?}
+
+        Sass::Util.paths(diff).map {|p| p.flatten}.reject {|p| path_has_two_subjects?(p)}
+      end
+
+      # Extracts initial selector combinators (`"+"`, `">"`, `"~"`, and `"\n"`)
+      # from two sequences and merges them together into a single array of
+      # selector combinators.
+      #
+      # @param seq1 [Array<SimpleSequence or String>]
+      # @param seq2 [Array<SimpleSequence or String>]
+      # @return [Array<String>, nil] If there are no operators in the merged
+      #   sequence, this will be the empty array. If the operators cannot be
+      #   merged, this will be nil.
+      def merge_initial_ops(seq1, seq2)
+        ops1, ops2 = [], []
+        ops1 << seq1.shift while seq1.first.is_a?(String)
+        ops2 << seq2.shift while seq2.first.is_a?(String)
+
+        newline = false
+        newline ||= !!ops1.shift if ops1.first == "\n"
+        newline ||= !!ops2.shift if ops2.first == "\n"
+
+        # If neither sequence is a subsequence of the other, they cannot be
+        # merged successfully
+        lcs = Sass::Util.lcs(ops1, ops2)
+        return unless lcs == ops1 || lcs == ops2
+        return (newline ? ["\n"] : []) + (ops1.size > ops2.size ? ops1 : ops2)
+      end
+
+      # Extracts final selector combinators (`"+"`, `">"`, `"~"`) and the
+      # selectors to which they apply from two sequences and merges them
+      # together into a single array.
+      #
+      # @param seq1 [Array<SimpleSequence or String>]
+      # @param seq2 [Array<SimpleSequence or String>]
+      # @return [Array<SimpleSequence or String or
+      #     Array<Array<SimpleSequence or String>>]
+      #   If there are no trailing combinators to be merged, this will be the
+      #   empty array. If the trailing combinators cannot be merged, this will
+      #   be nil. Otherwise, this will contained the merged selector. Array
+      #   elements are [Sass::Util#paths]-style options; conceptually, an "or"
+      #   of multiple selectors.
+      def merge_final_ops(seq1, seq2, res = [])
+        ops1, ops2 = [], []
+        ops1 << seq1.pop while seq1.last.is_a?(String)
+        ops2 << seq2.pop while seq2.last.is_a?(String)
+
+        # Not worth the headache of trying to preserve newlines here. The most
+        # important use of newlines is at the beginning of the selector to wrap
+        # across lines anyway.
+        ops1.reject! {|o| o == "\n"}
+        ops2.reject! {|o| o == "\n"}
+
+        return res if ops1.empty? && ops2.empty?
+        if ops1.size > 1 || ops2.size > 1
+          # If there are multiple operators, something hacky's going on. If one
+          # is a supersequence of the other, use that, otherwise give up.
+          lcs = Sass::Util.lcs(ops1, ops2)
+          return unless lcs == ops1 || lcs == ops2
+          res.unshift(*(ops1.size > ops2.size ? ops1 : ops2).reverse)
+          return res
+        end
+
+        # This code looks complicated, but it's actually just a bunch of special
+        # cases for interactions between different combinators.
+        op1, op2 = ops1.first, ops2.first
+        if op1 && op2
+          sel1 = seq1.pop
+          sel2 = seq2.pop
+          if op1 == '~' && op2 == '~'
+            if sel1.superselector?(sel2)
+              res.unshift sel2, '~'
+            elsif sel2.superselector?(sel1)
+              res.unshift sel1, '~'
+            else
+              merged = sel1.unify(sel2.members, sel2.subject?)
+              res.unshift [
+                [sel1, '~', sel2, '~'],
+                [sel2, '~', sel1, '~'],
+                ([merged, '~'] if merged)
+              ].compact
+            end
+          elsif (op1 == '~' && op2 == '+') || (op1 == '+' && op2 == '~')
+            if op1 == '~'
+              tilde_sel, plus_sel = sel1, sel2
+            else
+              tilde_sel, plus_sel = sel2, sel1
+            end
+
+            if tilde_sel.superselector?(plus_sel)
+              res.unshift plus_sel, '+'
+            else
+              merged = plus_sel.unify(tilde_sel.members, tilde_sel.subject?)
+              res.unshift [
+                [tilde_sel, '~', plus_sel, '+'],
+                ([merged, '+'] if merged)
+              ].compact
+            end
+          elsif op1 == '>' && %w[~ +].include?(op2)
+            res.unshift sel2, op2
+            seq1.push sel1, op1
+          elsif op2 == '>' && %w[~ +].include?(op1)
+            res.unshift sel1, op1
+            seq2.push sel2, op2
+          elsif op1 == op2
+            return unless merged = sel1.unify(sel2.members, sel2.subject?)
+            res.unshift merged, op1
+          else
+            # Unknown selector combinators can't be unified
+            return
+          end
+          return merge_final_ops(seq1, seq2, res)
+        elsif op1
+          seq2.pop if op1 == '>' && seq2.last && seq2.last.superselector?(seq1.last)
+          res.unshift seq1.pop, op1
+          return merge_final_ops(seq1, seq2, res)
+        else # op2
+          seq1.pop if op2 == '>' && seq1.last && seq1.last.superselector?(seq2.last)
+          res.unshift seq2.pop, op2
+          return merge_final_ops(seq1, seq2, res)
+        end
+      end
+
+      # Takes initial subsequences of `seq1` and `seq2` and returns all
+      # orderings of those subsequences. The initial subsequences are determined
+      # by a block.
+      #
+      # Destructively removes the initial subsequences of `seq1` and `seq2`.
+      #
+      # For example, given `(A B C | D E)` and `(1 2 | 3 4 5)` (with `|`
+      # denoting the boundary of the initial subsequence), this would return
+      # `[(A B C 1 2), (1 2 A B C)]`. The sequences would then be `(D E)` and
+      # `(3 4 5)`.
+      #
+      # @param seq1 [Array]
+      # @param seq2 [Array]
+      # @yield [a] Used to determine when to cut off the initial subsequences.
+      #   Called repeatedly for each sequence until it returns true.
+      # @yieldparam a [Array] A final subsequence of one input sequence after
+      #   cutting off some initial subsequence.
+      # @yieldreturn [Boolean] Whether or not to cut off the initial subsequence
+      #   here.
+      # @return [Array<Array>] All possible orderings of the initial subsequences.
+      def chunks(seq1, seq2)
+        chunk1 = []
+        chunk1 << seq1.shift until yield seq1
+        chunk2 = []
+        chunk2 << seq2.shift until yield seq2
+        return [] if chunk1.empty? && chunk2.empty?
+        return [chunk2] if chunk1.empty?
+        return [chunk1] if chunk2.empty?
+        [chunk1 + chunk2, chunk2 + chunk1]
+      end
+
+      # Groups a sequence into subsequences. The subsequences are determined by
+      # strings; adjacent non-string elements will be put into separate groups,
+      # but any element adjacent to a string will be grouped with that string.
+      #
+      # For example, `(A B "C" D E "F" G "H" "I" J)` will become `[(A) (B "C" D)
+      # (E "F" G "H" "I" J)]`.
+      #
+      # @param seq [Array]
+      # @return [Array<Array>]
+      def group_selectors(seq)
+        newseq = []
+        tail = seq.dup
+        until tail.empty?
+          head = []
+          begin
+            head << tail.shift
+          end while !tail.empty? && head.last.is_a?(String) || tail.first.is_a?(String)
+          newseq << head
+        end
+        return newseq
+      end
+
+      # Given two selector sequences, returns whether `seq1` is a
+      # superselector of `seq2`; that is, whether `seq1` matches every
+      # element `seq2` matches.
+      #
+      # @param seq1 [Array<SimpleSequence or String>]
+      # @param seq2 [Array<SimpleSequence or String>]
+      # @return [Boolean]
+      def _superselector?(seq1, seq2)
+        seq1 = seq1.reject {|e| e == "\n"}
+        seq2 = seq2.reject {|e| e == "\n"}
+        # Selectors with leading or trailing operators are neither
+        # superselectors nor subselectors.
+        return if seq1.last.is_a?(String) || seq2.last.is_a?(String) ||
+          seq1.first.is_a?(String) || seq2.first.is_a?(String)
+        # More complex selectors are never superselectors of less complex ones
+        return if seq1.size > seq2.size
+        return seq1.first.superselector?(seq2.last) if seq1.size == 1
+
+        _, si = Sass::Util.enum_with_index(seq2).find do |e, i|
+          return if i == seq2.size - 1
+          next if e.is_a?(String)
+          seq1.first.superselector?(e)
+        end
+        return unless si
+
+        if seq1[1].is_a?(String)
+          return unless seq2[si+1].is_a?(String)
+          # .foo ~ .bar is a superselector of .foo + .bar
+          return unless seq1[1] == "~" ? seq2[si+1] != ">" : seq1[1] == seq2[si+1]
+          return _superselector?(seq1[2..-1], seq2[si+2..-1])
+        elsif seq2[si+1].is_a?(String)
+          return unless seq2[si+1] == ">"
+          return _superselector?(seq1[1..-1], seq2[si+2..-1])
+        else
+          return _superselector?(seq1[1..-1], seq2[si+1..-1])
+        end
+      end
+
+      # Like \{#_superselector?}, but compares the selectors in the
+      # context of parent selectors, as though they shared an implicit
+      # base simple selector. For example, `B` is not normally a
+      # superselector of `B A`, since it doesn't match `A` elements.
+      # However, it is a parent superselector, since `B X` is a
+      # superselector of `B A X`.
+      #
+      # @param seq1 [Array<SimpleSequence or String>]
+      # @param seq2 [Array<SimpleSequence or String>]
+      # @return [Boolean]
+      def parent_superselector?(seq1, seq2)
+        base = Sass::Selector::SimpleSequence.new([Sass::Selector::Placeholder.new('<temp>')], false)
+        _superselector?(seq1 + [base], seq2 + [base])
+      end
+
+      # Removes redundant selectors from between multiple lists of
+      # selectors. This takes a list of lists of selector sequences;
+      # each individual list is assumed to have no redundancy within
+      # itself. A selector is only removed if it's redundant with a
+      # selector in another list.
+      #
+      # "Redundant" here means that one selector is a superselector of
+      # the other. The more specific selector is removed.
+      #
+      # @param seqses [Array<Array<Array<SimpleSequence or String>>>]
+      # @return [Array<Array<Array<SimpleSequence or String>>>]
+      def trim(seqses)
+        # Avoid truly horrific quadratic behavior. TODO: I think there
+        # may be a way to get perfect trimming without going quadratic.
+        return seqses if seqses.size > 100
+
+        # Keep the results in a separate array so we can be sure we aren't
+        # comparing against an already-trimmed selector. This ensures that two
+        # identical selectors don't mutually trim one another.
+        result = seqses.dup
+
+        # This is n^2 on the sequences, but only comparing between
+        # separate sequences should limit the quadratic behavior.
+        seqses.each_with_index do |seqs1, i|
+          result[i] = seqs1.reject do |seq1|
+            max_spec = _sources(seq1).map {|seq| seq.specificity}.max || 0
+            result.any? do |seqs2|
+              next if seqs1.equal?(seqs2)
+              # Second Law of Extend: the specificity of a generated selector
+              # should never be less than the specificity of the extending
+              # selector.
+              #
+              # See https://github.com/nex3/sass/issues/324.
+              seqs2.any? {|seq2| _specificity(seq2) >= max_spec && _superselector?(seq2, seq1)}
+            end
+          end
+        end
+        result
+      end
+
+      def _hash
+        members.reject {|m| m == "\n"}.hash
+      end
+
+      def _eql?(other)
+        other.members.reject {|m| m == "\n"}.eql?(self.members.reject {|m| m == "\n"})
+      end
+
+      private
+
+      def path_has_two_subjects?(path)
+        subject = false
+        path.each do |sseq_or_op|
+          next unless sseq_or_op.is_a?(SimpleSequence)
+          next unless sseq_or_op.subject?
+          return true if subject
+          subject = true
+        end
+        false
+      end
+
+      def _sources(seq)
+        s = Set.new
+        seq.map {|sseq_or_op| s.merge sseq_or_op.sources if sseq_or_op.is_a?(SimpleSequence)}
+        s
+      end
+
+      def extended_not_expanded_to_s(extended_not_expanded)
+        extended_not_expanded.map do |choices|
+          choices = choices.map do |sel|
+            next sel.first.to_s if sel.size == 1
+            "#{sel.join ' '}"
+          end
+          next choices.first if choices.size == 1 && !choices.include?(' ')
+          "(#{choices.join ', '})"
+        end.join ' '
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/selector/simple.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/selector/simple.rb
new file mode 100644
index 0000000..ab60005
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/selector/simple.rb
@@ -0,0 +1,119 @@
+module Sass
+  module Selector
+    # The abstract superclass for simple selectors
+    # (that is, those that don't compose multiple selectors).
+    class Simple
+      # The line of the Sass template on which this selector was declared.
+      #
+      # @return [Fixnum]
+      attr_accessor :line
+
+      # The name of the file in which this selector was declared,
+      # or `nil` if it was not declared in a file (e.g. on stdin).
+      #
+      # @return [String, nil]
+      attr_accessor :filename
+
+      # Returns a representation of the node
+      # as an array of strings and potentially {Sass::Script::Node}s
+      # (if there's interpolation in the selector).
+      # When the interpolation is resolved and the strings are joined together,
+      # this will be the string representation of this node.
+      #
+      # @return [Array<String, Sass::Script::Node>]
+      def to_a
+        Sass::Util.abstract(self)
+      end
+
+      # Returns a string representation of the node.
+      # This is basically the selector string.
+      #
+      # @return [String]
+      def inspect
+        to_a.map {|e| e.is_a?(Sass::Script::Node) ? "\#{#{e.to_sass}}" : e}.join
+      end
+
+      # @see \{#inspect}
+      # @return [String]
+      def to_s
+        inspect
+      end
+
+      # Returns a hash code for this selector object.
+      #
+      # By default, this is based on the value of \{#to\_a},
+      # so if that contains information irrelevant to the identity of the selector,
+      # this should be overridden.
+      #
+      # @return [Fixnum]
+      def hash
+        @_hash ||= to_a.hash
+      end
+
+      # Checks equality between this and another object.
+      #
+      # By default, this is based on the value of \{#to\_a},
+      # so if that contains information irrelevant to the identity of the selector,
+      # this should be overridden.
+      #
+      # @param other [Object] The object to test equality against
+      # @return [Boolean] Whether or not this is equal to `other`
+      def eql?(other)
+        other.class == self.class && other.hash == self.hash && other.to_a.eql?(to_a)
+      end
+      alias_method :==, :eql?
+
+      # Unifies this selector with a {SimpleSequence}'s {SimpleSequence#members members array},
+      # returning another `SimpleSequence` members array
+      # that matches both this selector and the input selector.
+      #
+      # By default, this just appends this selector to the end of the array
+      # (or returns the original array if this selector already exists in it).
+      #
+      # @param sels [Array<Simple>] A {SimpleSequence}'s {SimpleSequence#members members array}
+      # @return [Array<Simple>, nil] A {SimpleSequence} {SimpleSequence#members members array}
+      #   matching both `sels` and this selector,
+      #   or `nil` if this is impossible (e.g. unifying `#foo` and `#bar`)
+      # @raise [Sass::SyntaxError] If this selector cannot be unified.
+      #   This will only ever occur when a dynamic selector,
+      #   such as {Parent} or {Interpolation}, is used in unification.
+      #   Since these selectors should be resolved
+      #   by the time extension and unification happen,
+      #   this exception will only ever be raised as a result of programmer error
+      def unify(sels)
+        return sels if sels.any? {|sel2| eql?(sel2)}
+        sels_with_ix = Sass::Util.enum_with_index(sels)
+        _, i =
+          if self.is_a?(Pseudo) || self.is_a?(SelectorPseudoClass)
+            sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) && (sels.last.type == :element)}
+          else
+            sels_with_ix.find {|sel, _| sel.is_a?(Pseudo) || sel.is_a?(SelectorPseudoClass)}
+          end
+        return sels + [self] unless i
+        return sels[0...i] + [self] + sels[i..-1]
+      end
+
+      protected
+
+      # Unifies two namespaces,
+      # returning a namespace that works for both of them if possible.
+      #
+      # @param ns1 [String, nil] The first namespace.
+      #   `nil` means none specified, e.g. `foo`.
+      #   The empty string means no namespace specified, e.g. `|foo`.
+      #   `"*"` means any namespace is allowed, e.g. `*|foo`.
+      # @param ns2 [String, nil] The second namespace. See `ns1`.
+      # @return [Array(String or nil, Boolean)]
+      #   The first value is the unified namespace, or `nil` for no namespace.
+      #   The second value is whether or not a namespace that works for both inputs
+      #   could be found at all.
+      #   If the second value is `false`, the first should be ignored.
+      def unify_namespaces(ns1, ns2)
+        return nil, false unless ns1 == ns2 || ns1.nil? || ns1 == ['*'] || ns2.nil? || ns2 == ['*']
+        return ns2, true if ns1 == ['*']
+        return ns1, true if ns2 == ['*']
+        return ns1 || ns2, true
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/selector/simple_sequence.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/selector/simple_sequence.rb
new file mode 100644
index 0000000..a703e3f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/selector/simple_sequence.rb
@@ -0,0 +1,212 @@
+module Sass
+  module Selector
+    # A unseparated sequence of selectors
+    # that all apply to a single element.
+    # For example, `.foo#bar[attr=baz]` is a simple sequence
+    # of the selectors `.foo`, `#bar`, and `[attr=baz]`.
+    class SimpleSequence < AbstractSequence
+      # The array of individual selectors.
+      #
+      # @return [Array<Simple>]
+      attr_accessor :members
+
+      # The extending selectors that caused this selector sequence to be
+      # generated. For example:
+      #
+      #     a.foo { ... }
+      #     b.bar { extend a}
+      #     c.baz { extend b}
+      #
+      # The generated selector `b.foo.bar` has `{b.bar}` as its `sources` set,
+      # and the generated selector `c.foo.bar.baz` has `{b.bar, c.baz}` as its
+      # `sources` set.
+      #
+      # This is populated during the {#do_extend} process.
+      #
+      # @return {Set<Sequence>}
+      attr_accessor :sources
+
+      # @see \{#subject?}
+      attr_writer :subject
+
+      # Returns the element or universal selector in this sequence,
+      # if it exists.
+      #
+      # @return [Element, Universal, nil]
+      def base
+        @base ||= (members.first if members.first.is_a?(Element) || members.first.is_a?(Universal))
+      end
+
+      def pseudo_elements
+        @pseudo_elements ||= (members - [base]).
+          select {|sel| sel.is_a?(Pseudo) && sel.type == :element}
+      end
+
+      # Returns the non-base, non-pseudo-class selectors in this sequence.
+      #
+      # @return [Set<Simple>]
+      def rest
+        @rest ||= Set.new(members - [base] - pseudo_elements)
+      end
+
+      # Whether or not this compound selector is the subject of the parent
+      # selector; that is, whether it is prepended with `$` and represents the
+      # actual element that will be selected.
+      #
+      # @return [Boolean]
+      def subject?
+        @subject
+      end
+
+      # @param selectors [Array<Simple>] See \{#members}
+      # @param subject [Boolean] See \{#subject?}
+      # @param sources [Set<Sequence>]
+      def initialize(selectors, subject, sources = Set.new)
+        @members = selectors
+        @subject = subject
+        @sources = sources
+      end
+
+      # Resolves the {Parent} selectors within this selector
+      # by replacing them with the given parent selector,
+      # handling commas appropriately.
+      #
+      # @param super_seq [Sequence] The parent selector sequence
+      # @return [Array<SimpleSequence>] This selector, with parent references resolved.
+      #   This is an array because the parent selector is itself a {Sequence}
+      # @raise [Sass::SyntaxError] If a parent selector is invalid
+      def resolve_parent_refs(super_seq)
+        # Parent selector only appears as the first selector in the sequence
+        return [self] unless @members.first.is_a?(Parent)
+
+        return super_seq.members if @members.size == 1
+        unless super_seq.members.last.is_a?(SimpleSequence)
+          raise Sass::SyntaxError.new("Invalid parent selector: " + super_seq.to_a.join)
+        end
+
+        super_seq.members[0...-1] +
+          [SimpleSequence.new(super_seq.members.last.members + @members[1..-1], subject?)]
+      end
+
+      # Non-destrucively extends this selector with the extensions specified in a hash
+      # (which should come from {Sass::Tree::Visitors::Cssize}).
+      #
+      # @overload def do_extend(extends, parent_directives)
+      # @param extends [{Selector::Simple =>
+      #                  Sass::Tree::Visitors::Cssize::Extend}]
+      #   The extensions to perform on this selector
+      # @param parent_directives [Array<Sass::Tree::DirectiveNode>]
+      #   The directives containing this selector.
+      # @return [Array<Sequence>] A list of selectors generated
+      #   by extending this selector with `extends`.
+      # @see CommaSequence#do_extend
+      def do_extend(extends, parent_directives, seen = Set.new)
+        Sass::Util.group_by_to_a(extends.get(members.to_set)) {|ex, _| ex.extender}.map do |seq, group|
+          sels = group.map {|_, s| s}.flatten
+          # If A { extend B} and C {...},
+          # seq is A, sels is B, and self is C
+
+          self_without_sel = Sass::Util.array_minus(self.members, sels)
+          group.each {|e, _| e.result = :failed_to_unify unless e.result == :succeeded}
+          next unless unified = seq.members.last.unify(self_without_sel, subject?)
+          group.each {|e, _| e.result = :succeeded}
+          next if group.map {|e, _| check_directives_match!(e, parent_directives)}.none?
+          new_seq = Sequence.new(seq.members[0...-1] + [unified])
+          new_seq.add_sources!(sources + [seq])
+          [sels, new_seq]
+        end.compact.map do |sels, seq|
+          seen.include?(sels) ? [] : seq.do_extend(extends, parent_directives, seen + [sels])
+        end.flatten.uniq
+      end
+
+      # Unifies this selector with another {SimpleSequence}'s {SimpleSequence#members members array},
+      # returning another `SimpleSequence`
+      # that matches both this selector and the input selector.
+      #
+      # @param sels [Array<Simple>] A {SimpleSequence}'s {SimpleSequence#members members array}
+      # @param subject [Boolean] Whether the {SimpleSequence} being merged is a subject.
+      # @return [SimpleSequence, nil] A {SimpleSequence} matching both `sels` and this selector,
+      #   or `nil` if this is impossible (e.g. unifying `#foo` and `#bar`)
+      # @raise [Sass::SyntaxError] If this selector cannot be unified.
+      #   This will only ever occur when a dynamic selector,
+      #   such as {Parent} or {Interpolation}, is used in unification.
+      #   Since these selectors should be resolved
+      #   by the time extension and unification happen,
+      #   this exception will only ever be raised as a result of programmer error
+      def unify(sels, other_subject)
+        return unless sseq = members.inject(sels) do |member, sel|
+          return unless member
+          sel.unify(member)
+        end
+        SimpleSequence.new(sseq, other_subject || subject?)
+      end
+
+      # Returns whether or not this selector matches all elements
+      # that the given selector matches (as well as possibly more).
+      #
+      # @example
+      #   (.foo).superselector?(.foo.bar) #=> true
+      #   (.foo).superselector?(.bar) #=> false
+      # @param sseq [SimpleSequence]
+      # @return [Boolean]
+      def superselector?(sseq)
+        (base.nil? || base.eql?(sseq.base)) &&
+          pseudo_elements.eql?(sseq.pseudo_elements) &&
+          rest.subset?(sseq.rest)
+      end
+
+      # @see Simple#to_a
+      def to_a
+        res = @members.map {|sel| sel.to_a}.flatten
+        res << '!' if subject?
+        res
+      end
+
+      # Returns a string representation of the sequence.
+      # This is basically the selector string.
+      #
+      # @return [String]
+      def inspect
+        members.map {|m| m.inspect}.join
+      end
+
+      # Return a copy of this simple sequence with `sources` merged into the
+      # {#sources} set.
+      #
+      # @param sources [Set<Sequence>]
+      # @return [SimpleSequence]
+      def with_more_sources(sources)
+        sseq = dup
+        sseq.members = members.dup
+        sseq.sources = self.sources | sources
+        sseq
+      end
+
+      private
+
+      def check_directives_match!(extend, parent_directives)
+        dirs1 = extend.directives.map {|d| d.resolved_value}
+        dirs2 = parent_directives.map {|d| d.resolved_value}
+        return true if Sass::Util.subsequence?(dirs1, dirs2)
+
+        Sass::Util.sass_warn <<WARNING
+DEPRECATION WARNING on line #{extend.node.line}#{" of #{extend.node.filename}" if extend.node.filename}:
+  @extending an outer selector from within #{extend.directives.last.name} is deprecated.
+  You may only @extend selectors within the same directive.
+  This will be an error in Sass 3.3.
+  It can only work once @extend is supported natively in the browser.
+WARNING
+        return false
+      end
+
+      def _hash
+        [base, Sass::Util.set_hash(rest)].hash
+      end
+
+      def _eql?(other)
+        other.base.eql?(self.base) && other.pseudo_elements == pseudo_elements &&
+          Sass::Util.set_eql?(other.rest, self.rest) && other.subject? == self.subject?
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/shared.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/shared.rb
new file mode 100644
index 0000000..54bd9bd
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/shared.rb
@@ -0,0 +1,76 @@
+module Sass
+  # This module contains functionality that's shared between Haml and Sass.
+  module Shared
+    extend self
+
+    # Scans through a string looking for the interoplation-opening `#{`
+    # and, when it's found, yields the scanner to the calling code
+    # so it can handle it properly.
+    #
+    # The scanner will have any backslashes immediately in front of the `#{`
+    # as the second capture group (`scan[2]`),
+    # and the text prior to that as the first (`scan[1]`).
+    #
+    # @yieldparam scan [StringScanner] The scanner scanning through the string
+    # @return [String] The text remaining in the scanner after all `#{`s have been processed
+    def handle_interpolation(str)
+      scan = Sass::Util::MultibyteStringScanner.new(str)
+      yield scan while scan.scan(/(.*?)(\\*)\#\{/m)
+      scan.rest
+    end
+
+    # Moves a scanner through a balanced pair of characters.
+    # For example:
+    #
+    #     Foo (Bar (Baz bang) bop) (Bang (bop bip))
+    #     ^                       ^
+    #     from                    to
+    #
+    # @param scanner [StringScanner] The string scanner to move
+    # @param start [Character] The character opening the balanced pair.
+    #   A `Fixnum` in 1.8, a `String` in 1.9
+    # @param finish [Character] The character closing the balanced pair.
+    #   A `Fixnum` in 1.8, a `String` in 1.9
+    # @param count [Fixnum] The number of opening characters matched
+    #   before calling this method
+    # @return [(String, String)] The string matched within the balanced pair
+    #   and the rest of the string.
+    #   `["Foo (Bar (Baz bang) bop)", " (Bang (bop bip))"]` in the example above.
+    def balance(scanner, start, finish, count = 0)
+      str = ''
+      scanner = Sass::Util::MultibyteStringScanner.new(scanner) unless scanner.is_a? StringScanner
+      regexp = Regexp.new("(.*?)[\\#{start.chr}\\#{finish.chr}]", Regexp::MULTILINE)
+      while scanner.scan(regexp)
+        str << scanner.matched
+        count += 1 if scanner.matched[-1] == start
+        count -= 1 if scanner.matched[-1] == finish
+        return [str.strip, scanner.rest] if count == 0
+      end
+    end
+
+    # Formats a string for use in error messages about indentation.
+    #
+    # @param indentation [String] The string used for indentation
+    # @param was [Boolean] Whether or not to add `"was"` or `"were"`
+    #   (depending on how many characters were in `indentation`)
+    # @return [String] The name of the indentation (e.g. `"12 spaces"`, `"1 tab"`)
+    def human_indentation(indentation, was = false)
+      if !indentation.include?(?\t)
+        noun = 'space'
+      elsif !indentation.include?(?\s)
+        noun = 'tab'
+      else
+        return indentation.inspect + (was ? ' was' : '')
+      end
+
+      singular = indentation.length == 1
+      if was
+        was = singular ? ' was' : ' were'
+      else
+        was = ''
+      end
+
+      "#{indentation.length} #{noun}#{'s' unless singular}#{was}"
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/supports.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/supports.rb
new file mode 100644
index 0000000..7c14b29
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/supports.rb
@@ -0,0 +1,229 @@
+# A namespace for the ` supports` condition parse tree.
+module Sass::Supports
+  # The abstract superclass of all Supports conditions.
+  class Condition
+    # Runs the SassScript in the supports condition.
+    #
+    # @param env [Sass::Environment] The environment in which to run the script.
+    def perform(environment); Sass::Util.abstract(self); end
+
+    # Returns the CSS for this condition.
+    #
+    # @return [String]
+    def to_css; Sass::Util.abstract(self); end
+
+    # Returns the Sass/CSS code for this condition.
+    #
+    # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize}).
+    # @return [String]
+    def to_src(options); Sass::Util.abstract(self); end
+
+    # Returns a deep copy of this condition and all its children.
+    #
+    # @return [Condition]
+    def deep_copy; Sass::Util.abstract(self); end
+
+    # Sets the options hash for the script nodes in the supports condition.
+    #
+    # @param options [{Symbol => Object}] The options has to set.
+    def options=(options); Sass::Util.abstract(self); end
+  end
+
+  # An operator condition (e.g. `CONDITION1 and CONDITION2`).
+  class Operator < Condition
+    # The left-hand condition.
+    #
+    # @return [Sass::Supports::Condition]
+    attr_accessor :left
+
+    # The right-hand condition.
+    #
+    # @return [Sass::Supports::Condition]
+    attr_accessor :right
+
+    # The operator ("and" or "or").
+    #
+    # @return [String]
+    attr_accessor :op
+
+    def initialize(left, right, op)
+      @left = left
+      @right = right
+      @op = op
+    end
+
+    def perform(env)
+      @left.perform(env)
+      @right.perform(env)
+    end
+
+    def to_css
+      "#{left_parens @left.to_css} #{op} #{right_parens @right.to_css}"
+    end
+
+    def to_src(options)
+      "#{left_parens @left.to_src(options)} #{op} #{right_parens @right.to_src(options)}"
+    end
+
+    def deep_copy
+      copy = dup
+      copy.left = @left.deep_copy
+      copy.right = @right.deep_copy
+      copy
+    end
+
+    def options=(options)
+      @left.options = options
+      @right.options = options
+    end
+
+    private
+
+    def left_parens(str)
+      return "(#{str})" if @left.is_a?(Negation)
+      return str
+    end
+
+    def right_parens(str)
+      return "(#{str})" if @right.is_a?(Negation) || @right.is_a?(Operator)
+      return str
+    end
+  end
+
+  # A negation condition (`not CONDITION`).
+  class Negation < Condition
+    # The condition being negated.
+    #
+    # @return [Sass::Supports::Condition]
+    attr_accessor :condition
+
+    def initialize(condition)
+      @condition = condition
+    end
+
+    def perform(env)
+      @condition.perform(env)
+    end
+
+    def to_css
+      "not #{parens @condition.to_css}"
+    end
+
+    def to_src(options)
+      "not #{parens @condition.to_src(options)}"
+    end
+
+    def deep_copy
+      copy = dup
+      copy.condition = condition.deep_copy
+      copy
+    end
+
+    def options=(options)
+      condition.options = options
+    end
+
+    private
+
+    def parens(str)
+      return "(#{str})" if @condition.is_a?(Negation) || @condition.is_a?(Operator)
+      return str
+    end
+  end
+
+  # A declaration condition (e.g. `(feature: value)`).
+  class Declaration < Condition
+    # The feature name.
+    #
+    # @param [Sass::Script::Node]
+    attr_accessor :name
+
+    # The name of the feature after any SassScript has been resolved.
+    # Only set once \{Tree::Visitors::Perform} has been run.
+    #
+    # @return [String]
+    attr_accessor :resolved_name
+
+    # The feature value.
+    #
+    # @param [Sass::Script::Node]
+    attr_accessor :value
+
+    # The value of the feature after any SassScript has been resolved.
+    # Only set once \{Tree::Visitors::Perform} has been run.
+    #
+    # @return [String]
+    attr_accessor :resolved_value
+
+    def initialize(name, value)
+      @name = name
+      @value = value
+    end
+
+    def perform(env)
+      @resolved_name = name.perform(env)
+      @resolved_value = value.perform(env)
+    end
+
+    def to_css
+      "(#{ resolved_name}: #{ resolved_value})"
+    end
+
+    def to_src(options)
+      "(#{ name to_sass(options)}: #{ value to_sass(options)})"
+    end
+
+    def deep_copy
+      copy = dup
+      copy.name = @name.deep_copy
+      copy.value = @value.deep_copy
+      copy
+    end
+
+    def options=(options)
+      @name.options = options
+      @value.options = options
+    end
+  end
+
+  # An interpolation condition (e.g. `#{$var}`).
+  class Interpolation < Condition
+    # The SassScript expression in the interpolation.
+    #
+    # @param [Sass::Script::Node]
+    attr_accessor :value
+
+    # The value of the expression after it's been resolved.
+    # Only set once \{Tree::Visitors::Perform} has been run.
+    #
+    # @return [String]
+    attr_accessor :resolved_value
+
+    def initialize(value)
+      @value = value
+    end
+
+    def perform(env)
+      val = value.perform(env)
+      @resolved_value = val.is_a?(Sass::Script::String) ? val.value : val.to_s
+    end
+
+    def to_css
+      @resolved_value
+    end
+
+    def to_src(options)
+      "\#{#{ value to_sass(options)}}"
+    end
+
+    def deep_copy
+      copy = dup
+      copy.value = @value.deep_copy
+      copy
+    end
+
+    def options=(options)
+      @value.options = options
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/charset_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/charset_node.rb
new file mode 100644
index 0000000..65b6306
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/charset_node.rb
@@ -0,0 +1,22 @@
+module Sass::Tree
+  # A static node representing an unproccessed Sass ` charset` directive.
+  #
+  # @see Sass::Tree
+  class CharsetNode < Node
+    # The name of the charset.
+    #
+    # @return [String]
+    attr_accessor :name
+
+    # @param name [String] see \{#name}
+    def initialize(name)
+      @name = name
+      super()
+    end
+
+    # @see Node#invisible?
+    def invisible?
+      !Sass::Util.ruby1_8?
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/comment_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/comment_node.rb
new file mode 100644
index 0000000..ec38bbd
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/comment_node.rb
@@ -0,0 +1,82 @@
+require 'sass/tree/node'
+
+module Sass::Tree
+  # A static node representing a Sass comment (silent or loud).
+  #
+  # @see Sass::Tree
+  class CommentNode < Node
+    # The text of the comment, not including `/*` and `*/`.
+    # Interspersed with {Sass::Script::Node}s representing `#{}`-interpolation
+    # if this is a loud comment.
+    #
+    # @return [Array<String, Sass::Script::Node>]
+    attr_accessor :value
+
+    # The text of the comment
+    # after any interpolated SassScript has been resolved.
+    # Only set once \{Tree::Visitors::Perform} has been run.
+    #
+    # @return [String]
+    attr_accessor :resolved_value
+
+    # The type of the comment. `:silent` means it's never output to CSS,
+    # `:normal` means it's output in every compile mode except `:compressed`,
+    # and `:loud` means it's output even in `:compressed`.
+    #
+    # @return [Symbol]
+    attr_accessor :type
+
+    # @param value [Array<String, Sass::Script::Node>] See \{#value}
+    # @param type [Symbol] See \{#type}
+    def initialize(value, type)
+      @value = Sass::Util.with_extracted_values(value) {|str| normalize_indentation str}
+      @type = type
+      super()
+    end
+
+    # Compares the contents of two comments.
+    #
+    # @param other [Object] The object to compare with
+    # @return [Boolean] Whether or not this node and the other object
+    #   are the same
+    def ==(other)
+      self.class == other.class && value == other.value && type == other.type
+    end
+
+    # Returns `true` if this is a silent comment
+    # or the current style doesn't render comments.
+    #
+    # Comments starting with ! are never invisible (and the ! is removed from the output.)
+    #
+    # @return [Boolean]
+    def invisible?
+      case @type
+      when :loud; false
+      when :silent; true
+      else; style == :compressed
+      end
+    end
+
+    # Returns the number of lines in the comment.
+    #
+    # @return [Fixnum]
+    def lines
+      @value.inject(0) do |s, e|
+        next s + e.count("\n") if e.is_a?(String)
+        next s
+      end
+    end
+
+    private
+
+    def normalize_indentation(str)
+      ind = str.split("\n").inject(str[/^[ \t]*/].split("")) do |pre, line|
+        line[/^[ \t]*/].split("").zip(pre).inject([]) do |arr, (a, b)|
+          break arr if a != b
+          arr << a
+        end
+      end.join
+      str.gsub(/^#{ind}/, '')
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/content_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/content_node.rb
new file mode 100644
index 0000000..3f6528f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/content_node.rb
@@ -0,0 +1,9 @@
+module Sass
+  module Tree
+    # A node representing the placement within a mixin of the include statement's content.
+    #
+    # @see Sass::Tree
+    class ContentNode < Node
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/css_import_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/css_import_node.rb
new file mode 100644
index 0000000..7dbd25b
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/css_import_node.rb
@@ -0,0 +1,60 @@
+module Sass::Tree
+  # A node representing an ` import` rule that's importing plain CSS.
+  #
+  # @see Sass::Tree
+  class CssImportNode < DirectiveNode
+    # The URI being imported, either as a plain string or an interpolated
+    # script string.
+    #
+    # @return [String, Sass::Script::Node]
+    attr_accessor :uri
+
+    # The text of the URI being imported after any interpolated SassScript has
+    # been resolved. Only set once \{Tree::Visitors::Perform} has been run.
+    #
+    # @return [String]
+    attr_accessor :resolved_uri
+
+    # The media query for this rule, interspersed with {Sass::Script::Node}s
+    # representing `#{}`-interpolation. Any adjacent strings will be merged
+    # together.
+    #
+    # @return [Array<String, Sass::Script::Node>]
+    attr_accessor :query
+
+    # The media query for this rule, without any unresolved interpolation. It's
+    # only set once {Tree::Node#perform} has been called.
+    #
+    # @return [Sass::Media::QueryList]
+    attr_accessor :resolved_query
+
+    # @param uri [String, Sass::Script::Node] See \{#uri}
+    # @param query [Array<String, Sass::Script::Node>] See \{#query}
+    def initialize(uri, query = nil)
+      @uri = uri
+      @query = query
+      super('')
+    end
+
+    # @param uri [String] See \{#resolved_uri}
+    # @return [CssImportNode]
+    def self.resolved(uri)
+      node = new(uri)
+      node.resolved_uri = uri
+      node
+    end
+
+    # @see DirectiveNode#value
+    def value; raise NotImplementedError; end
+
+    # @see DirectiveNode#resolved_value
+    def resolved_value
+      @resolved_value ||=
+        begin
+          str = "@import #{resolved_uri}"
+          str << " #{resolved_query.to_css}" if resolved_query
+          str
+        end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/debug_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/debug_node.rb
new file mode 100644
index 0000000..e3c9fe2
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/debug_node.rb
@@ -0,0 +1,18 @@
+module Sass
+  module Tree
+    # A dynamic node representing a Sass ` debug` statement.
+    #
+    # @see Sass::Tree
+    class DebugNode < Node
+      # The expression to print.
+      # @return [Script::Node] 
+      attr_accessor :expr
+
+      # @param expr [Script::Node] The expression to print
+      def initialize(expr)
+        @expr = expr
+        super()
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/directive_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/directive_node.rb
new file mode 100644
index 0000000..8f73283
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/directive_node.rb
@@ -0,0 +1,42 @@
+module Sass::Tree
+  # A static node representing an unproccessed Sass ` `-directive 
+  # Directives known to Sass, like ` for` and ` debug`,
+  # are handled by their own nodes;
+  # only CSS directives like ` media` and ` font-face` become {DirectiveNode}s.
+  #
+  # ` import` and ` charset` are special cases;
+  # they become {ImportNode}s and {CharsetNode}s, respectively.
+  #
+  # @see Sass::Tree
+  class DirectiveNode < Node
+    # The text of the directive, ` ` and all, with interpolation included.
+    #
+    # @return [Array<String, Sass::Script::Node>]
+    attr_accessor :value
+
+    # The text of the directive after any interpolated SassScript has been resolved.
+    # Only set once \{Tree::Visitors::Perform} has been run.
+    #
+    # @return [String]
+    attr_accessor :resolved_value
+
+    # @param value [Array<String, Sass::Script::Node>] See \{#value}
+    def initialize(value)
+      @value = value
+      super()
+    end
+
+    # @param value [String] See \{#resolved_value}
+    # @return [DirectiveNode]
+    def self.resolved(value)
+      node = new([value])
+      node.resolved_value = value
+      node
+    end
+
+    # @return [String] The name of the directive, including ` ` 
+    def name
+      value.first.gsub(/ .*$/, '')
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/each_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/each_node.rb
new file mode 100644
index 0000000..5e3c071
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/each_node.rb
@@ -0,0 +1,24 @@
+require 'sass/tree/node'
+
+module Sass::Tree
+  # A dynamic node representing a Sass ` each` loop.
+  #
+  # @see Sass::Tree
+  class EachNode < Node
+    # The name of the loop variable.
+    # @return [String]
+    attr_reader :var
+
+    # The parse tree for the list.
+    # @param [Script::Node]
+    attr_accessor :list
+
+    # @param var [String] The name of the loop variable
+    # @param list [Script::Node] The parse tree for the list
+    def initialize(var, list)
+      @var = var
+      @list = list
+      super()
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/extend_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/extend_node.rb
new file mode 100644
index 0000000..fadc739
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/extend_node.rb
@@ -0,0 +1,36 @@
+require 'sass/tree/node'
+
+module Sass::Tree
+  # A static node reprenting an ` extend` directive.
+  #
+  # @see Sass::Tree
+  class ExtendNode < Node
+    # The parsed selector after interpolation has been resolved.
+    # Only set once {Tree::Visitors::Perform} has been run.
+    #
+    # @return [Selector::CommaSequence]
+    attr_accessor :resolved_selector
+
+    # The CSS selector to extend, interspersed with {Sass::Script::Node}s
+    # representing `#{}`-interpolation.
+    #
+    # @return [Array<String, Sass::Script::Node>]
+    attr_accessor :selector
+
+    # Whether the ` extend` is allowed to match no selectors or not.
+    #
+    # @return [Boolean]
+    def optional?; @optional; end
+
+    # @param selector [Array<String, Sass::Script::Node>]
+    #   The CSS selector to extend,
+    #   interspersed with {Sass::Script::Node}s
+    #   representing `#{}`-interpolation.
+    # @param optional [Boolean] See \{#optional}
+    def initialize(selector, optional)
+      @selector = selector
+      @optional = optional
+      super()
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/for_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/for_node.rb
new file mode 100644
index 0000000..9bb8d25
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/for_node.rb
@@ -0,0 +1,36 @@
+require 'sass/tree/node'
+
+module Sass::Tree
+  # A dynamic node representing a Sass ` for` loop.
+  #
+  # @see Sass::Tree
+  class ForNode < Node
+    # The name of the loop variable.
+    # @return [String]
+    attr_reader :var
+
+    # The parse tree for the initial expression.
+    # @return [Script::Node]
+    attr_accessor :from
+
+    # The parse tree for the final expression.
+    # @return [Script::Node]
+    attr_accessor :to
+
+    # Whether to include `to` in the loop or stop just before.
+    # @return [Boolean]
+    attr_reader :exclusive
+
+    # @param var [String] See \{#var}
+    # @param from [Script::Node] See \{#from}
+    # @param to [Script::Node] See \{#to}
+    # @param exclusive [Boolean] See \{#exclusive}
+    def initialize(var, from, to, exclusive)
+      @var = var
+      @from = from
+      @to = to
+      @exclusive = exclusive
+      super()
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/function_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/function_node.rb
new file mode 100644
index 0000000..d812c8f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/function_node.rb
@@ -0,0 +1,34 @@
+module Sass
+  module Tree
+    # A dynamic node representing a function definition.
+    #
+    # @see Sass::Tree
+    class FunctionNode < Node
+      # The name of the function.
+      # @return [String]
+      attr_reader :name
+
+      # The arguments to the function. Each element is a tuple
+      # containing the variable for argument and the parse tree for
+      # the default value of the argument
+      #
+      # @return [Array<Script::Node>]
+      attr_accessor :args
+
+      # The splat argument for this function, if one exists.
+      #
+      # @return [Script::Node?]
+      attr_accessor :splat
+
+      # @param name [String] The function name
+      # @param args [Array<(Script::Node, Script::Node)>] The arguments for the function.
+      # @param splat [Script::Node] See \{#splat}
+      def initialize(name, args, splat)
+        @name = name
+        @args = args
+        @splat = splat
+        super()
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/if_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/if_node.rb
new file mode 100644
index 0000000..a7b8906
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/if_node.rb
@@ -0,0 +1,52 @@
+require 'sass/tree/node'
+
+module Sass::Tree
+  # A dynamic node representing a Sass ` if` statement.
+  #
+  # {IfNode}s are a little odd, in that they also represent ` else` and ` else if`s.
+  # This is done as a linked list:
+  # each {IfNode} has a link (\{#else}) to the next {IfNode}.
+  #
+  # @see Sass::Tree
+  class IfNode < Node
+    # The conditional expression.
+    # If this is nil, this is an ` else` node, not an ` else if`.
+    #
+    # @return [Script::Expr]
+    attr_accessor :expr
+
+    # The next {IfNode} in the if-else list, or `nil`.
+    #
+    # @return [IfNode]
+    attr_accessor :else
+
+    # @param expr [Script::Expr] See \{#expr}
+    def initialize(expr)
+      @expr = expr
+      @last_else = self
+      super()
+    end
+
+    # Append an ` else` node to the end of the list.
+    #
+    # @param node [IfNode] The ` else` node to append
+    def add_else(node)
+      @last_else.else = node
+      @last_else = node
+    end
+
+    def _dump(f)
+      Marshal.dump([self.expr, self.else, self.children])
+    end
+
+    def self._load(data)
+      expr, else_, children = Marshal.load(data)
+      node = IfNode.new(expr)
+      node.else = else_
+      node.children = children
+      node.instance_variable_set('@last_else',
+        node.else ? node.else.instance_variable_get('@last_else') : node)
+      node
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/import_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/import_node.rb
new file mode 100644
index 0000000..557dd12
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/import_node.rb
@@ -0,0 +1,75 @@
+module Sass
+  module Tree
+    # A static node that wraps the {Sass::Tree} for an ` import`ed file.
+    # It doesn't have a functional purpose other than to add the ` import`ed file
+    # to the backtrace if an error occurs.
+    class ImportNode < RootNode
+      # The name of the imported file as it appears in the Sass document.
+      #
+      # @return [String]
+      attr_reader :imported_filename
+
+      # Sets the imported file.
+      attr_writer :imported_file
+
+      # @param imported_filename [String] The name of the imported file
+      def initialize(imported_filename)
+        @imported_filename = imported_filename
+        super(nil)
+      end
+
+      def invisible?; to_s.empty?; end
+
+      # Returns the imported file.
+      #
+      # @return [Sass::Engine]
+      # @raise [Sass::SyntaxError] If no file could be found to import.
+      def imported_file
+        @imported_file ||= import
+      end
+
+      # Returns whether or not this import should emit a CSS @import declaration
+      #
+      # @return [Boolean] Whether or not this is a simple CSS @import declaration.
+      def css_import?
+        if @imported_filename =~ /\.css$/
+          @imported_filename
+        elsif imported_file.is_a?(String) && imported_file =~ /\.css$/
+          imported_file
+        end
+      end
+
+      private
+
+      def import
+        paths = @options[:load_paths]
+
+        if @options[:importer]
+          f = @options[:importer].find_relative(
+            @imported_filename, @options[:filename], options_for_importer)
+          return f if f
+        end
+
+        paths.each do |p|
+          if f = p.find(@imported_filename, options_for_importer)
+            return f
+          end
+        end
+
+        message = "File to import not found or unreadable: #{ imported_filename} \n"
+        if paths.size == 1
+          message << "Load path: #{paths.first}"
+        else
+          message << "Load paths:\n  " << paths.join("\n  ")
+        end
+        raise SyntaxError.new(message)
+      rescue SyntaxError => e
+        raise SyntaxError.new(e.message, :line => self.line, :filename => @filename)
+      end
+
+      def options_for_importer
+        @options.merge(:_line => line)
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/media_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/media_node.rb
new file mode 100644
index 0000000..f3b74f4
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/media_node.rb
@@ -0,0 +1,58 @@
+module Sass::Tree
+  # A static node representing a ` media` rule.
+  # ` media` rules behave differently from other directives
+  # in that when they're nested within rules,
+  # they bubble up to top-level.
+  #
+  # @see Sass::Tree
+  class MediaNode < DirectiveNode
+    # TODO: parse and cache the query immediately if it has no dynamic elements
+
+    # The media query for this rule, interspersed with {Sass::Script::Node}s
+    # representing `#{}`-interpolation. Any adjacent strings will be merged
+    # together.
+    #
+    # @return [Array<String, Sass::Script::Node>]
+    attr_accessor :query
+
+    # The media query for this rule, without any unresolved interpolation. It's
+    # only set once {Tree::Node#perform} has been called.
+    #
+    # @return [Sass::Media::QueryList]
+    attr_accessor :resolved_query
+
+    # @see RuleNode#tabs
+    attr_accessor :tabs
+
+    # @see RuleNode#group_end
+    attr_accessor :group_end
+
+    # @param query [Array<String, Sass::Script::Node>] See \{#query}
+    def initialize(query)
+      @query = query
+      @tabs = 0
+      super('')
+    end
+
+    # @see DirectiveNode#value
+    def value; raise NotImplementedError; end
+
+    # @see DirectiveNode#name
+    def name; '@media'; end
+
+    # @see DirectiveNode#resolved_value
+    def resolved_value
+      @resolved_value ||= "@media #{resolved_query.to_css}"
+    end
+
+    # True when the directive has no visible children.
+    #
+    # @return [Boolean]
+    def invisible?
+      children.all? {|c| c.invisible?}
+    end
+
+    # @see Node#bubbles?
+    def bubbles?; true; end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/mixin_def_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/mixin_def_node.rb
new file mode 100644
index 0000000..9a08b59
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/mixin_def_node.rb
@@ -0,0 +1,38 @@
+module Sass
+  module Tree
+    # A dynamic node representing a mixin definition.
+    #
+    # @see Sass::Tree
+    class MixinDefNode < Node
+      # The mixin name.
+      # @return [String]
+      attr_reader :name
+
+      # The arguments for the mixin.
+      # Each element is a tuple containing the variable for argument
+      # and the parse tree for the default value of the argument.
+      #
+      # @return [Array<(Script::Node, Script::Node)>]
+      attr_accessor :args
+
+      # The splat argument for this mixin, if one exists.
+      #
+      # @return [Script::Node?]
+      attr_accessor :splat
+
+      # Whether the mixin uses ` content`  Set during the nesting check phase.
+      # @return [Boolean]
+      attr_accessor :has_content
+
+      # @param name [String] The mixin name
+      # @param args [Array<(Script::Node, Script::Node)>] See \{#args}
+      # @param splat [Script::Node] See \{#splat}
+      def initialize(name, args, splat)
+        @name = name
+        @args = args
+        @splat = splat
+        super()
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/mixin_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/mixin_node.rb
new file mode 100644
index 0000000..a34dca6
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/mixin_node.rb
@@ -0,0 +1,39 @@
+require 'sass/tree/node'
+
+module Sass::Tree
+  # A static node representing a mixin include.
+  # When in a static tree, the sole purpose is to wrap exceptions
+  # to add the mixin to the backtrace.
+  #
+  # @see Sass::Tree
+  class MixinNode < Node
+    # The name of the mixin.
+    # @return [String]
+    attr_reader :name
+
+    # The arguments to the mixin.
+    # @return [Array<Script::Node>]
+    attr_accessor :args
+
+    # A hash from keyword argument names to values.
+    # @return [{String => Script::Node}]
+    attr_accessor :keywords
+
+    # The splat argument for this mixin, if one exists.
+    #
+    # @return [Script::Node?]
+    attr_accessor :splat
+
+    # @param name [String] The name of the mixin
+    # @param args [Array<Script::Node>] See \{#args}
+    # @param splat [Script::Node] See \{#splat}
+    # @param keywords [{String => Script::Node}] See \{#keywords}
+    def initialize(name, args, keywords, splat)
+      @name = name
+      @args = args
+      @keywords = keywords
+      @splat = splat
+      super()
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/node.rb
new file mode 100644
index 0000000..d22f792
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/node.rb
@@ -0,0 +1,196 @@
+module Sass
+  # A namespace for nodes in the Sass parse tree.
+  #
+  # The Sass parse tree has three states: dynamic, static Sass, and static CSS.
+  #
+  # When it's first parsed, a Sass document is in the dynamic state.
+  # It has nodes for mixin definitions and ` for` loops and so forth,
+  # in addition to nodes for CSS rules and properties.
+  # Nodes that only appear in this state are called **dynamic nodes**.
+  #
+  # {Tree::Visitors::Perform} creates a static Sass tree, which is different.
+  # It still has nodes for CSS rules and properties
+  # but it doesn't have any dynamic-generation-related nodes.
+  # The nodes in this state are in the same structure as the Sass document:
+  # rules and properties are nested beneath one another.
+  # Nodes that can be in this state or in the dynamic state
+  # are called **static nodes**; nodes that can only be in this state
+  # are called **solely static nodes**.
+  #
+  # {Tree::Visitors::Cssize} is then used to create a static CSS tree.
+  # This is like a static Sass tree,
+  # but the structure exactly mirrors that of the generated CSS.
+  # Rules and properties can't be nested beneath one another in this state.
+  #
+  # Finally, {Tree::Visitors::ToCss} can be called on a static CSS tree
+  # to get the actual CSS code as a string.
+  module Tree
+    # The abstract superclass of all parse-tree nodes.
+    class Node
+      include Enumerable
+
+      # The child nodes of this node.
+      #
+      # @return [Array<Tree::Node>]
+      attr_accessor :children
+
+      # Whether or not this node has child nodes.
+      # This may be true even when \{#children} is empty,
+      # in which case this node has an empty block (e.g. `{}`).
+      #
+      # @return [Boolean]
+      attr_accessor :has_children
+
+      # The line of the document on which this node appeared.
+      #
+      # @return [Fixnum]
+      attr_accessor :line
+
+      # The name of the document on which this node appeared.
+      #
+      # @return [String]
+      attr_writer :filename
+
+      # The options hash for the node.
+      # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
+      #
+      # @return [{Symbol => Object}]
+      attr_reader :options
+
+      def initialize
+        @children = []
+      end
+
+      # Sets the options hash for the node and all its children.
+      #
+      # @param options [{Symbol => Object}] The options
+      # @see #options
+      def options=(options)
+        Sass::Tree::Visitors::SetOptions.visit(self, options)
+      end
+
+      # @private
+      def children=(children)
+        self.has_children ||= !children.empty?
+        @children = children
+      end
+
+      # The name of the document on which this node appeared.
+      #
+      # @return [String]
+      def filename
+        @filename || (@options && @options[:filename])
+      end
+
+      # Appends a child to the node.
+      #
+      # @param child [Tree::Node, Array<Tree::Node>] The child node or nodes
+      # @raise [Sass::SyntaxError] if `child` is invalid
+      def <<(child)
+        return if child.nil?
+        if child.is_a?(Array)
+          child.each {|c| self << c}
+        else
+          self.has_children = true
+          @children << child
+        end
+      end
+
+      # Compares this node and another object (only other {Tree::Node}s will be equal).
+      # This does a structural comparison;
+      # if the contents of the nodes and all the child nodes are equivalent,
+      # then the nodes are as well.
+      #
+      # Only static nodes need to override this.
+      #
+      # @param other [Object] The object to compare with
+      # @return [Boolean] Whether or not this node and the other object
+      #   are the same
+      # @see Sass::Tree
+      def ==(other)
+        self.class == other.class && other.children == children
+      end
+
+      # True if \{#to\_s} will return `nil`;
+      # that is, if the node shouldn't be rendered.
+      # Should only be called in a static tree.
+      #
+      # @return [Boolean]
+      def invisible?; false; end
+
+      # The output style. See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
+      #
+      # @return [Symbol]
+      def style
+        @options[:style]
+      end
+
+      # Computes the CSS corresponding to this static CSS tree.
+      #
+      # @return [String, nil] The resulting CSS
+      # @see Sass::Tree
+      def to_s
+        Sass::Tree::Visitors::ToCss.visit(self)
+      end
+
+      # Returns a representation of the node for debugging purposes.
+      #
+      # @return [String]
+      def inspect
+        return self.class.to_s unless has_children
+        "(#{self.class} #{children.map {|c| c.inspect}.join(' ')})"
+      end
+
+      # Iterates through each node in the tree rooted at this node
+      # in a pre-order walk.
+      #
+      # @yield node
+      # @yieldparam node [Node] a node in the tree
+      def each
+        yield self
+        children.each {|c| c.each {|n| yield n}}
+      end
+
+      # Converts a node to Sass code that will generate it.
+      #
+      # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize})
+      # @return [String] The Sass code corresponding to the node
+      def to_sass(options = {})
+        Sass::Tree::Visitors::Convert.visit(self, options, :sass)
+      end
+
+      # Converts a node to SCSS code that will generate it.
+      #
+      # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize})
+      # @return [String] The Sass code corresponding to the node
+      def to_scss(options = {})
+        Sass::Tree::Visitors::Convert.visit(self, options, :scss)
+      end
+
+      # Return a deep clone of this node.
+      # The child nodes are cloned, but options are not.
+      #
+      # @return [Node]
+      def deep_copy
+        Sass::Tree::Visitors::DeepCopy.visit(self)
+      end
+
+      # Whether or not this node bubbles up through RuleNodes.
+      #
+      # @return [Boolean]
+      def bubbles?
+        false
+      end
+
+      protected
+
+      # @see Sass::Shared.balance
+      # @raise [Sass::SyntaxError] if the brackets aren't balanced
+      def balance(*args)
+        res = Sass::Shared.balance(*args)
+        return res if res
+        raise Sass::SyntaxError.new("Unbalanced brackets.", :line => line)
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/prop_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/prop_node.rb
new file mode 100644
index 0000000..43461d7
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/prop_node.rb
@@ -0,0 +1,152 @@
+module Sass::Tree
+  # A static node reprenting a CSS property.
+  #
+  # @see Sass::Tree
+  class PropNode < Node
+    # The name of the property,
+    # interspersed with {Sass::Script::Node}s
+    # representing `#{}`-interpolation.
+    # Any adjacent strings will be merged together.
+    #
+    # @return [Array<String, Sass::Script::Node>]
+    attr_accessor :name
+
+    # The name of the property
+    # after any interpolated SassScript has been resolved.
+    # Only set once \{Tree::Visitors::Perform} has been run.
+    #
+    # @return [String]
+    attr_accessor :resolved_name
+
+    # The value of the property.
+    #
+    # @return [Sass::Script::Node]
+    attr_accessor :value
+
+    # The value of the property
+    # after any interpolated SassScript has been resolved.
+    # Only set once \{Tree::Visitors::Perform} has been run.
+    #
+    # @return [String]
+    attr_accessor :resolved_value
+
+    # How deep this property is indented
+    # relative to a normal property.
+    # This is only greater than 0 in the case that:
+    #
+    # * This node is in a CSS tree
+    # * The style is :nested
+    # * This is a child property of another property
+    # * The parent property has a value, and thus will be rendered
+    #
+    # @return [Fixnum]
+    attr_accessor :tabs
+
+    # @param name [Array<String, Sass::Script::Node>] See \{#name}
+    # @param value [Sass::Script::Node] See \{#value}
+    # @param prop_syntax [Symbol] `:new` if this property uses `a: b`-style syntax,
+    #   `:old` if it uses `:a b`-style syntax
+    def initialize(name, value, prop_syntax)
+      @name = Sass::Util.strip_string_array(
+        Sass::Util.merge_adjacent_strings(name))
+      @value = value
+      @tabs = 0
+      @prop_syntax = prop_syntax
+      super()
+    end
+
+    # Compares the names and values of two properties.
+    #
+    # @param other [Object] The object to compare with
+    # @return [Boolean] Whether or not this node and the other object
+    #   are the same
+    def ==(other)
+      self.class == other.class && name == other.name && value == other.value && super
+    end
+
+    # Returns a appropriate message indicating how to escape pseudo-class selectors.
+    # This only applies for old-style properties with no value,
+    # so returns the empty string if this is new-style.
+    #
+    # @return [String] The message
+    def pseudo_class_selector_message
+      return "" if @prop_syntax == :new || !value.is_a?(Sass::Script::String) || !value.value.empty?
+      "\nIf #{declaration.dump} should be a selector, use \"\\#{declaration}\" instead."
+    end
+
+    # Computes the Sass or SCSS code for the variable declaration.
+    # This is like \{#to\_scss} or \{#to\_sass},
+    # except it doesn't print any child properties or a trailing semicolon.
+    #
+    # @param opts [{Symbol => Object}] The options hash for the tree.
+    # @param fmt [Symbol] `:scss` or `:sass`.
+    def declaration(opts = {:old => @prop_syntax == :old}, fmt = :sass)
+      name = self.name.map {|n| n.is_a?(String) ? n : "\#{#{n.to_sass(opts)}}"}.join
+      if name[0] == ?:
+        raise Sass::SyntaxError.new("The \"#{name}: #{self.class.val_to_sass(value, opts)}\" hack is not 
allowed in the Sass indented syntax")
+      end
+
+      old = opts[:old] && fmt == :sass
+      initial = old ? ':' : ''
+      mid = old ? '' : ':'
+      "#{initial}#{name}#{mid} #{self.class.val_to_sass(value, opts)}".rstrip
+    end
+
+    # A property node is invisible if its value is empty.
+    #
+    # @return [Boolean]
+    def invisible?
+      resolved_value.empty?
+    end
+
+    private
+
+    def check!
+      if @options[:property_syntax] && @options[:property_syntax] != @prop_syntax
+        raise Sass::SyntaxError.new(
+          "Illegal property syntax: can't use #{ prop_syntax} syntax when :property_syntax => #{ 
options[:property_syntax].inspect} is set.")
+      end
+    end
+
+    class << self
+      # @private
+      def val_to_sass(value, opts)
+        val_to_sass_comma(value, opts).to_sass(opts)
+      end
+
+      private
+
+      def val_to_sass_comma(node, opts)
+        return node unless node.is_a?(Sass::Script::Operation)
+        return val_to_sass_concat(node, opts) unless node.operator == :comma
+
+        Sass::Script::Operation.new(
+          val_to_sass_concat(node.operand1, opts),
+          val_to_sass_comma(node.operand2, opts),
+          node.operator)
+      end
+
+      def val_to_sass_concat(node, opts)
+        return node unless node.is_a?(Sass::Script::Operation)
+        return val_to_sass_div(node, opts) unless node.operator == :space
+
+        Sass::Script::Operation.new(
+          val_to_sass_div(node.operand1, opts),
+          val_to_sass_concat(node.operand2, opts),
+          node.operator)
+      end
+
+      def val_to_sass_div(node, opts)
+        unless node.is_a?(Sass::Script::Operation) && node.operator == :div &&
+            node.operand1.is_a?(Sass::Script::Number) &&
+            node.operand2.is_a?(Sass::Script::Number) &&
+            (!node.operand1.original || !node.operand2.original)
+          return node
+        end
+
+        Sass::Script::String.new("(#{node.to_sass(opts)})")
+      end
+
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/return_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/return_node.rb
new file mode 100644
index 0000000..daff6bb
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/return_node.rb
@@ -0,0 +1,18 @@
+module Sass
+  module Tree
+    # A dynamic node representing returning from a function.
+    #
+    # @see Sass::Tree
+    class ReturnNode < Node
+      # The expression to return.
+      # @type [Script::Node]
+      attr_accessor :expr
+
+      # @param expr [Script::Node] The expression to return
+      def initialize(expr)
+        @expr = expr
+        super()
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/root_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/root_node.rb
new file mode 100644
index 0000000..9a04ad2
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/root_node.rb
@@ -0,0 +1,28 @@
+module Sass
+  module Tree
+    # A static node that is the root node of the Sass document.
+    class RootNode < Node
+      # The Sass template from which this node was created
+      #
+      # @param template [String]
+      attr_reader :template
+
+      # @param template [String] The Sass template from which this node was created
+      def initialize(template)
+        super()
+        @template = template
+      end
+
+      # Runs the dynamic Sass code *and* computes the CSS for the tree.
+      # @see #to_s
+      def render
+        Visitors::CheckNesting.visit(self)
+        result = Visitors::Perform.visit(self)
+        Visitors::CheckNesting.visit(result) # Check again to validate mixins
+        result, extends = Visitors::Cssize.visit(result)
+        Visitors::Extend.visit(result, extends)
+        result.to_s
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/rule_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/rule_node.rb
new file mode 100644
index 0000000..779e67c
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/rule_node.rb
@@ -0,0 +1,132 @@
+require 'pathname'
+require 'uri'
+
+module Sass::Tree
+  # A static node reprenting a CSS rule.
+  #
+  # @see Sass::Tree
+  class RuleNode < Node
+    # The character used to include the parent selector
+    PARENT = '&'
+
+    # The CSS selector for this rule,
+    # interspersed with {Sass::Script::Node}s
+    # representing `#{}`-interpolation.
+    # Any adjacent strings will be merged together.
+    #
+    # @return [Array<String, Sass::Script::Node>]
+    attr_accessor :rule
+
+    # The CSS selector for this rule,
+    # without any unresolved interpolation
+    # but with parent references still intact.
+    # It's only set once {Tree::Node#perform} has been called.
+    #
+    # @return [Selector::CommaSequence]
+    attr_accessor :parsed_rules
+
+    # The CSS selector for this rule,
+    # without any unresolved interpolation or parent references.
+    # It's only set once {Tree::Visitors::Cssize} has been run.
+    #
+    # @return [Selector::CommaSequence]
+    attr_accessor :resolved_rules
+
+    # How deep this rule is indented
+    # relative to a base-level rule.
+    # This is only greater than 0 in the case that:
+    #
+    # * This node is in a CSS tree
+    # * The style is :nested
+    # * This is a child rule of another rule
+    # * The parent rule has properties, and thus will be rendered
+    #
+    # @return [Fixnum]
+    attr_accessor :tabs
+
+    # Whether or not this rule is the last rule in a nested group.
+    # This is only set in a CSS tree.
+    #
+    # @return [Boolean]
+    attr_accessor :group_end
+
+    # The stack trace.
+    # This is only readable in a CSS tree as it is written during the perform step
+    # and only when the :trace_selectors option is set.
+    #
+    # @return [Array<String>]
+    attr_accessor :stack_trace
+
+    # @param rule [Array<String, Sass::Script::Node>]
+    #   The CSS rule. See \{#rule}
+    def initialize(rule)
+      merged = Sass::Util.merge_adjacent_strings(rule)
+      @rule = Sass::Util.strip_string_array(merged)
+      @tabs = 0
+      try_to_parse_non_interpolated_rules
+      super()
+    end
+
+    # If we've precached the parsed selector, set the line on it, too.
+    def line=(line)
+      @parsed_rules.line = line if @parsed_rules
+      super
+    end
+
+    # If we've precached the parsed selector, set the filename on it, too.
+    def filename=(filename)
+      @parsed_rules.filename = filename if @parsed_rules
+      super
+    end
+
+    # Compares the contents of two rules.
+    #
+    # @param other [Object] The object to compare with
+    # @return [Boolean] Whether or not this node and the other object
+    #   are the same
+    def ==(other)
+      self.class == other.class && rule == other.rule && super
+    end
+
+    # Adds another {RuleNode}'s rules to this one's.
+    #
+    # @param node [RuleNode] The other node
+    def add_rules(node)
+      @rule = Sass::Util.strip_string_array(
+        Sass::Util.merge_adjacent_strings(@rule + ["\n"] + node.rule))
+      try_to_parse_non_interpolated_rules
+    end
+
+    # @return [Boolean] Whether or not this rule is continued on the next line
+    def continued?
+      last = @rule.last
+      last.is_a?(String) && last[-1] == ?,
+    end
+
+    # A hash that will be associated with this rule in the CSS document
+    # if the {file:SASS_REFERENCE.md#debug_info-option `:debug_info` option} is enabled.
+    # This data is used by e.g. [the FireSass Firebug 
extension](https://addons.mozilla.org/en-US/firefox/addon/103988).
+    #
+    # @return [{#to_s => #to_s}]
+    def debug_info
+      {:filename => filename && ("file://" + URI.escape(File.expand_path(filename))),
+       :line => self.line}
+    end
+
+    # A rule node is invisible if it has only placeholder selectors.
+    def invisible?
+      resolved_rules.members.all? {|seq| seq.has_placeholder?}
+    end
+
+    private
+
+    def try_to_parse_non_interpolated_rules
+      if @rule.all? {|t| t.kind_of?(String)}
+        # We don't use real filename/line info because we don't have it yet.
+        # When we get it, we'll set it on the parsed rules if possible.
+        parser = Sass::SCSS::StaticParser.new(@rule.join.strip, '', 1)
+        @parsed_rules = parser.parse_selector rescue nil
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/supports_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/supports_node.rb
new file mode 100644
index 0000000..0dc8458
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/supports_node.rb
@@ -0,0 +1,51 @@
+module Sass::Tree
+  # A static node representing a ` supports` rule.
+  # ` supports` rules behave differently from other directives
+  # in that when they're nested within rules,
+  # they bubble up to top-level.
+  #
+  # @see Sass::Tree
+  class SupportsNode < DirectiveNode
+    # The name, which may include a browser prefix.
+    #
+    # @return [String]
+    attr_accessor :name
+
+    # The supports condition.
+    #
+    # @return [Sass::Supports::Condition]
+    attr_accessor :condition
+
+    # @see RuleNode#tabs
+    attr_accessor :tabs
+
+    # @see RuleNode#group_end
+    attr_accessor :group_end
+
+    # @param condition [Sass::Supports::Condition] See \{#condition}
+    def initialize(name, condition)
+      @name = name
+      @condition = condition
+      @tabs = 0
+      super('')
+    end
+
+    # @see DirectiveNode#value
+    def value; raise NotImplementedError; end
+
+    # @see DirectiveNode#resolved_value
+    def resolved_value
+      @resolved_value ||= "@#{name} #{condition.to_css}"
+    end
+
+    # True when the directive has no visible children.
+    #
+    # @return [Boolean]
+    def invisible?
+      children.all? {|c| c.invisible?}
+    end
+
+    # @see Node#bubbles?
+    def bubbles?; true; end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/trace_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/trace_node.rb
new file mode 100644
index 0000000..0000127
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/trace_node.rb
@@ -0,0 +1,32 @@
+require 'sass/tree/node'
+
+module Sass::Tree
+  # A solely static node left over after a mixin include or @content has been performed.
+  # Its sole purpose is to wrap exceptions to add to the backtrace.
+  #
+  # @see Sass::Tree
+  class TraceNode < Node
+    # The name of the trace entry to add.
+    # @return [String]
+    attr_reader :name
+
+    # @param name [String] The name of the trace entry to add.
+    def initialize(name)
+      @name = name
+      self.has_children = true
+      super()
+    end
+
+    # Initializes this node from an existing node.
+    # @param name [String] The name of the trace entry to add.
+    # @param mixin [Node] The node to copy information from.
+    # @return [TraceNode]
+    def self.from_node(name, node)
+      trace = new(name)
+      trace.line = node.line
+      trace.filename = node.filename
+      trace.options = node.options
+      trace
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/variable_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/variable_node.rb
new file mode 100644
index 0000000..0cb6ac6
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/variable_node.rb
@@ -0,0 +1,30 @@
+module Sass
+  module Tree
+    # A dynamic node representing a variable definition.
+    #
+    # @see Sass::Tree
+    class VariableNode < Node
+      # The name of the variable.
+      # @return [String]
+      attr_reader :name
+
+      # The parse tree for the variable value.
+      # @return [Script::Node]
+      attr_accessor :expr
+
+      # Whether this is a guarded variable assignment (`!default`).
+      # @return [Boolean]
+      attr_reader :guarded
+
+      # @param name [String] The name of the variable
+      # @param expr [Script::Node] See \{#expr}
+      # @param guarded [Boolean] See \{#guarded}
+      def initialize(name, expr, guarded)
+        @name = name
+        @expr = expr
+        @guarded = guarded
+        super()
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/base.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/base.rb
new file mode 100644
index 0000000..c104bad
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/base.rb
@@ -0,0 +1,75 @@
+# Visitors are used to traverse the Sass parse tree.
+# Visitors should extend {Visitors::Base},
+# which provides a small amount of scaffolding for traversal.
+module Sass::Tree::Visitors
+  # The abstract base class for Sass visitors.
+  # Visitors should extend this class,
+  # then implement `visit_*` methods for each node they care about
+  # (e.g. `visit_rule` for {RuleNode} or `visit_for` for {ForNode}).
+  # These methods take the node in question as argument.
+  # They may `yield` to visit the child nodes of the current node.
+  #
+  # *Note*: due to the unusual nature of {Sass::Tree::IfNode},
+  # special care must be taken to ensure that it is properly handled.
+  # In particular, there is no built-in scaffolding
+  # for dealing with the return value of ` else` nodes.
+  #
+  # @abstract
+  class Base
+    # Runs the visitor on a tree.
+    #
+    # @param root [Tree::Node] The root node of the Sass tree.
+    # @return [Object] The return value of \{#visit} for the root node.
+    def self.visit(root)
+      new.send(:visit, root)
+    end
+
+    protected
+
+    # Runs the visitor on the given node.
+    # This can be overridden by subclasses that need to do something for each node.
+    #
+    # @param node [Tree::Node] The node to visit.
+    # @return [Object] The return value of the `visit_*` method for this node.
+    def visit(node)
+      method = "visit_#{node_name node}"
+      if self.respond_to?(method, true)
+        self.send(method, node) {visit_children(node)}
+      else
+        visit_children(node)
+      end
+    end
+
+    # Visit the child nodes for a given node.
+    # This can be overridden by subclasses that need to do something
+    # with the child nodes' return values.
+    #
+    # This method is run when `visit_*` methods `yield`,
+    # and its return value is returned from the `yield`.
+    #
+    # @param parent [Tree::Node] The parent node of the children to visit.
+    # @return [Array<Object>] The return values of the `visit_*` methods for the children.
+    def visit_children(parent)
+      parent.children.map {|c| visit(c)}
+    end
+
+    NODE_NAME_RE = /.*::(.*?)Node$/
+
+    # Returns the name of a node as used in the `visit_*` method.
+    #
+    # @param [Tree::Node] node The node.
+    # @return [String] The name.
+    def node_name(node)
+      @@node_names ||= {}
+      @@node_names[node.class.name] ||= node.class.name.gsub(NODE_NAME_RE, '\\1').downcase
+    end
+
+    # `yield`s, then runs the visitor on the ` else` clause if the node has one.
+    # This exists to ensure that the contents of the ` else` clause get visited.
+    def visit_if(node)
+      yield
+      visit(node.else) if node.else
+      node
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/check_nesting.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/check_nesting.rb
new file mode 100644
index 0000000..a12ee46
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/check_nesting.rb
@@ -0,0 +1,147 @@
+# A visitor for checking that all nodes are properly nested.
+class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
+  protected
+
+  def initialize
+    @parents = []
+  end
+
+  def visit(node)
+    if error = @parent && (
+        try_send("invalid_#{node_name @parent}_child?", @parent, node) ||
+        try_send("invalid_#{node_name node}_parent?", @parent, node))
+      raise Sass::SyntaxError.new(error)
+    end
+    super
+  rescue Sass::SyntaxError => e
+    e.modify_backtrace(:filename => node.filename, :line => node.line)
+    raise e
+  end
+
+  CONTROL_NODES = [Sass::Tree::EachNode, Sass::Tree::ForNode, Sass::Tree::IfNode,
+    Sass::Tree::WhileNode, Sass::Tree::TraceNode]
+  SCRIPT_NODES = [Sass::Tree::ImportNode] + CONTROL_NODES
+  def visit_children(parent)
+    old_parent = @parent
+    @parent = parent unless is_any_of?(parent, SCRIPT_NODES) ||
+      (parent.bubbles? && !old_parent.is_a?(Sass::Tree::RootNode))
+    @parents.push parent
+    super
+  ensure
+    @parent = old_parent
+    @parents.pop
+  end
+
+  def visit_root(node)
+    yield
+  rescue Sass::SyntaxError => e
+    e.sass_template ||= node.template
+    raise e
+  end
+
+  def visit_import(node)
+    yield
+  rescue Sass::SyntaxError => e
+    e.modify_backtrace(:filename => node.children.first.filename)
+    e.add_backtrace(:filename => node.filename, :line => node.line)
+    raise e
+  end
+
+  def visit_mixindef(node)
+    @current_mixin_def, old_mixin_def = node, @current_mixin_def
+    yield
+  ensure
+    @current_mixin_def = old_mixin_def
+  end
+
+  def invalid_content_parent?(parent, child)
+    if @current_mixin_def
+      @current_mixin_def.has_content = true
+      nil
+    else
+      "@content may only be used within a mixin."
+    end
+  end
+
+  def invalid_charset_parent?(parent, child)
+    "@charset may only be used at the root of a document." unless parent.is_a?(Sass::Tree::RootNode)
+  end
+
+  VALID_EXTEND_PARENTS = [Sass::Tree::RuleNode, Sass::Tree::MixinDefNode, Sass::Tree::MixinNode]
+  def invalid_extend_parent?(parent, child)
+    unless is_any_of?(parent, VALID_EXTEND_PARENTS)
+      return "Extend directives may only be used within rules."
+    end
+  end
+
+  INVALID_IMPORT_PARENTS = CONTROL_NODES +
+    [Sass::Tree::MixinDefNode, Sass::Tree::MixinNode]
+  def invalid_import_parent?(parent, child)
+    unless (@parents.map {|p| p.class} & INVALID_IMPORT_PARENTS).empty?
+      return "Import directives may not be used within control directives or mixins."
+    end
+    return if parent.is_a?(Sass::Tree::RootNode)
+    return "CSS import directives may only be used at the root of a document." if child.css_import?
+  rescue Sass::SyntaxError => e
+    e.modify_backtrace(:filename => child.imported_file.options[:filename])
+    e.add_backtrace(:filename => child.filename, :line => child.line)
+    raise e
+  end
+
+  def invalid_mixindef_parent?(parent, child)
+    unless (@parents.map {|p| p.class} & INVALID_IMPORT_PARENTS).empty?
+      return "Mixins may not be defined within control directives or other mixins."
+    end
+  end
+
+  def invalid_function_parent?(parent, child)
+    unless (@parents.map {|p| p.class} & INVALID_IMPORT_PARENTS).empty?
+      return "Functions may not be defined within control directives or other mixins."
+    end
+  end
+
+  VALID_FUNCTION_CHILDREN = [
+    Sass::Tree::CommentNode,  Sass::Tree::DebugNode, Sass::Tree::ReturnNode,
+    Sass::Tree::VariableNode, Sass::Tree::WarnNode
+  ] + CONTROL_NODES
+  def invalid_function_child?(parent, child)
+    unless is_any_of?(child, VALID_FUNCTION_CHILDREN)
+      "Functions can only contain variable declarations and control directives."
+    end
+  end
+
+  VALID_PROP_CHILDREN = [Sass::Tree::CommentNode, Sass::Tree::PropNode, Sass::Tree::MixinNode] + 
CONTROL_NODES
+  def invalid_prop_child?(parent, child)
+    unless is_any_of?(child, VALID_PROP_CHILDREN)
+      "Illegal nesting: Only properties may be nested beneath properties."
+    end
+  end
+
+  VALID_PROP_PARENTS = [Sass::Tree::RuleNode, Sass::Tree::PropNode,
+                        Sass::Tree::MixinDefNode, Sass::Tree::DirectiveNode,
+                        Sass::Tree::MixinNode]
+  def invalid_prop_parent?(parent, child)
+    unless is_any_of?(parent, VALID_PROP_PARENTS)
+      "Properties are only allowed within rules, directives, mixin includes, or other properties." + 
child.pseudo_class_selector_message
+    end
+  end
+
+  def invalid_return_parent?(parent, child)
+    "@return may only be used within a function." unless parent.is_a?(Sass::Tree::FunctionNode)
+  end
+
+  private
+
+  def is_any_of?(val, classes)
+    for c in classes
+      return true if val.is_a?(c)
+    end
+    return false
+  end
+
+  def try_send(method, *args)
+    return unless respond_to?(method, true)
+    send(method, *args)
+  end
+end
+
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/convert.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/convert.rb
new file mode 100644
index 0000000..56c290f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/convert.rb
@@ -0,0 +1,316 @@
+# A visitor for converting a Sass tree into a source string.
+class Sass::Tree::Visitors::Convert < Sass::Tree::Visitors::Base
+  # Runs the visitor on a tree.
+  #
+  # @param root [Tree::Node] The root node of the Sass tree.
+  # @param options [{Symbol => Object}] An options hash (see {Sass::CSS#initialize}).
+  # @param format [Symbol] `:sass` or `:scss`.
+  # @return [String] The Sass or SCSS source for the tree.
+  def self.visit(root, options, format)
+    new(options, format).send(:visit, root)
+  end
+
+  protected
+
+  def initialize(options, format)
+    @options = options
+    @format = format
+    @tabs = 0
+    # 2 spaces by default
+    @tab_chars = @options[:indent] || "  "
+  end
+
+  def visit_children(parent)
+    @tabs += 1
+    return @format == :sass ? "\n" : " {}\n" if parent.children.empty?
+    (@format == :sass ? "\n" : " {\n") + super.join.rstrip + (@format == :sass ? "\n" : "\n#{ @tab_chars * 
(@tabs-1)}}\n")
+  ensure
+    @tabs -= 1
+  end
+
+  # Ensures proper spacing between top-level nodes.
+  def visit_root(node)
+    Sass::Util.enum_cons(node.children + [nil], 2).map do |child, nxt|
+      visit(child) +
+        if nxt &&
+            (child.is_a?(Sass::Tree::CommentNode) &&
+              child.line + child.lines + 1 == nxt.line) ||
+            (child.is_a?(Sass::Tree::ImportNode) && nxt.is_a?(Sass::Tree::ImportNode) &&
+              child.line + 1 == nxt.line) ||
+            (child.is_a?(Sass::Tree::VariableNode) && nxt.is_a?(Sass::Tree::VariableNode) &&
+              child.line + 1 == nxt.line)
+          ""
+        else
+          "\n"
+        end
+    end.join.rstrip + "\n"
+  end
+
+  def visit_charset(node)
+    "#{tab_str} charset \"#{node.name}\"#{semi}\n"
+  end
+
+  def visit_comment(node)
+    value = interp_to_src(node.value)
+    content = if @format == :sass
+      content = value.gsub(/\*\/$/, '').rstrip
+      if content =~ /\A[ \t]/
+        # Re-indent SCSS comments like this:
+        #     /* foo
+        #   bar
+        #       baz */
+        content.gsub!(/^/, '   ')
+        content.sub!(/\A([ \t]*)\/\*/, '/*\1')
+      end
+
+      content =
+        unless content.include?("\n")
+          content
+        else
+          content.gsub!(/\n( \*|\/\/)/, "\n  ")
+          spaces = content.scan(/\n( *)/).map {|s| s.first.size}.min
+          sep = node.type == :silent ? "\n//" : "\n *"
+          if spaces >= 2
+            content.gsub(/\n  /, sep)
+          else
+            content.gsub(/\n#{' ' * spaces}/, sep)
+          end
+        end
+
+      content.gsub!(/\A\/\*/, '//') if node.type == :silent
+      content.gsub!(/^/, tab_str)
+      content.rstrip + "\n"
+    else
+      spaces = (@tab_chars * [ tabs - value[/^ */].size, 0].max)
+      content = if node.type == :silent
+        value.gsub(/^[\/ ]\*/, '//').gsub(/ *\*\/$/, '')
+      else
+        value
+      end.gsub(/^/, spaces) + "\n"
+      content
+    end
+    content
+  end
+
+  def visit_debug(node)
+    "#{tab_str} debug #{node.expr.to_sass(@options)}#{semi}\n"
+  end
+
+  def visit_directive(node)
+    res = "#{tab_str}#{interp_to_src(node.value)}"
+    res.gsub!(/^ import \#\{(.*)\}([^}]*)$/, '@import \1\2');
+    return res + "#{semi}\n" unless node.has_children
+    res + yield + "\n"
+  end
+
+  def visit_each(node)
+    "#{tab_str} each $#{dasherize(node.var)} in #{node.list.to_sass(@options)}#{yield}"
+  end
+
+  def visit_extend(node)
+    "#{tab_str} extend #{selector_to_src(node.selector).lstrip}#{semi}#{" !optional" if node.optional?}\n"
+  end
+
+  def visit_for(node)
+    "#{tab_str} for $#{dasherize(node.var)} from #{node.from.to_sass(@options)} " +
+      "#{node.exclusive ? "to" : "through"} #{node.to.to_sass(@options)}#{yield}"
+  end
+
+  def visit_function(node)
+    args = node.args.map do |v, d|
+      d ? "#{v.to_sass(@options)}: #{d.to_sass(@options)}" : v.to_sass(@options)
+    end.join(", ")
+    if node.splat
+      args << ", " unless node.args.empty?
+      args << node.splat.to_sass(@options) << "..."
+    end
+
+    "#{tab_str} function #{dasherize(node.name)}(#{args})#{yield}"
+  end
+
+  def visit_if(node)
+    name =
+      if ! is_else; "if"
+      elsif node.expr; "else if"
+      else; "else"
+      end
+    @is_else = false
+    str = "#{tab_str} #{name}"
+    str << " #{node.expr.to_sass(@options)}" if node.expr
+    str << yield
+    @is_else = true
+    str << visit(node.else) if node.else
+    str
+  ensure
+    @is_else = false
+  end
+
+  def visit_import(node)
+    quote = @format == :scss ? '"' : ''
+    "#{tab_str} import #{quote}#{node.imported_filename}#{quote}#{semi}\n"
+  end
+
+  def visit_media(node)
+    "#{tab_str} media #{media_interp_to_src(node.query)}#{yield}"
+  end
+
+  def visit_supports(node)
+    "#{tab_str} #{node name} #{node.condition.to_src(@options)}#{yield}"
+  end
+
+  def visit_cssimport(node)
+    if node.uri.is_a?(Sass::Script::Node)
+      str = "#{tab_str} import #{node.uri.to_sass(@options)}"
+    else
+      str = "#{tab_str} import #{node.uri}"
+    end
+    str << " #{interp_to_src(node.query)}" unless node.query.empty?
+    "#{str}#{semi}\n"
+  end
+
+  def visit_mixindef(node)
+    args =
+      if node.args.empty? && node.splat.nil?
+        ""
+      else
+        str = '('
+        str << node.args.map do |v, d|
+          if d
+            "#{v.to_sass(@options)}: #{d.to_sass(@options)}"
+          else
+            v.to_sass(@options)
+          end
+        end.join(", ")
+
+        if node.splat
+          str << ", " unless node.args.empty?
+          str << node.splat.to_sass(@options) << '...'
+        end
+
+        str << ')'
+      end
+
+    "#{tab_str}#{ format == :sass ? '=' : '@mixin '}#{dasherize(node.name)}#{args}#{yield}"
+  end
+
+  def visit_mixin(node)
+    arg_to_sass = lambda do |arg|
+      sass = arg.to_sass(@options)
+      sass = "(#{sass})" if arg.is_a?(Sass::Script::List) && arg.separator == :comma
+      sass
+    end
+
+    unless node.args.empty? && node.keywords.empty? && node.splat.nil?
+      args = node.args.map(&arg_to_sass).join(", ")
+      keywords = Sass::Util.hash_to_a(node.keywords).
+        map {|k, v| "$#{dasherize(k)}: #{arg_to_sass[v]}"}.join(', ')
+      if node.splat
+        splat = (args.empty? && keywords.empty?) ? "" : ", "
+        splat = "#{splat}#{arg_to_sass[node.splat]}..."
+      end
+      arglist = "(#{args}#{', ' unless args.empty? || keywords.empty?}#{keywords}#{splat})"
+    end
+    "#{tab_str}#{ format == :sass ? '+' : '@include '}#{dasherize(node.name)}#{arglist}#{node.has_children ? 
yield : semi}\n"
+  end
+
+  def visit_content(node)
+    "#{tab_str} content#{semi}\n"
+  end
+
+  def visit_prop(node)
+    res = tab_str + node.declaration(@options, @format)
+    return res + semi + "\n" if node.children.empty?
+    res + yield.rstrip + semi + "\n"
+  end
+
+  def visit_return(node)
+    "#{tab_str} return #{node.expr.to_sass(@options)}#{semi}\n"
+  end
+
+  def visit_rule(node)
+    if @format == :sass
+      name = selector_to_sass(node.rule)
+      name = "\\" + name if name[0] == ?:
+      name.gsub(/^/, tab_str) + yield
+    elsif @format == :scss
+      name = selector_to_scss(node.rule)
+      res = name + yield
+      if node.children.last.is_a?(Sass::Tree::CommentNode) && node.children.last.type == :silent
+        res.slice!(-3..-1)
+        res << "\n" << tab_str << "}\n"
+      end
+      res
+    end
+  end
+
+  def visit_variable(node)
+    "#{tab_str}$#{dasherize(node.name)}: #{node.expr.to_sass(@options)}#{' !default' if 
node.guarded}#{semi}\n"
+  end
+
+  def visit_warn(node)
+    "#{tab_str} warn #{node.expr.to_sass(@options)}#{semi}\n"
+  end
+
+  def visit_while(node)
+    "#{tab_str} while #{node.expr.to_sass(@options)}#{yield}"
+  end
+
+  private
+
+  def interp_to_src(interp)
+    interp.map do |r|
+      next r if r.is_a?(String)
+      "\#{#{r.to_sass(@options)}}"
+    end.join
+  end
+
+  # Like interp_to_src, but removes the unnecessary `#{}` around the keys and
+  # values in media expressions.
+  def media_interp_to_src(interp)
+    Sass::Util.enum_with_index(interp).map do |r, i|
+      next r if r.is_a?(String)
+      before, after = interp[i-1], interp[i+1]
+      if before.is_a?(String) && after.is_a?(String) &&
+          ((before[-1] == ?( && after[0] == ?:) ||
+           (before =~ /:\s*/ && after[0] == ?)))
+        r.to_sass(@options)
+      else
+        "\#{#{r.to_sass(@options)}}"
+      end
+    end.join
+  end
+
+  def selector_to_src(sel)
+    @format == :sass ? selector_to_sass(sel) : selector_to_scss(sel)
+  end
+
+  def selector_to_sass(sel)
+    sel.map do |r|
+      if r.is_a?(String)
+        r.gsub(/(,)?([ \t]*)\n\s*/) {$1 ? "#{$1}#{$2}\n" : " "}
+      else
+        "\#{#{r.to_sass(@options)}}"
+      end
+    end.join
+  end
+
+  def selector_to_scss(sel)
+    interp_to_src(sel).gsub(/^[ \t]*/, tab_str).gsub(/[ \t]*$/, '')
+  end
+
+  def semi
+    @format == :sass ? "" : ";"
+  end
+
+  def tab_str
+    @tab_chars * @tabs
+  end
+
+  def dasherize(s)
+    if @options[:dasherize]
+      s.gsub('_', '-')
+    else
+      s
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/cssize.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/cssize.rb
new file mode 100644
index 0000000..3ac8e48
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/cssize.rb
@@ -0,0 +1,229 @@
+# A visitor for converting a static Sass tree into a static CSS tree.
+class Sass::Tree::Visitors::Cssize < Sass::Tree::Visitors::Base
+  # @param root [Tree::Node] The root node of the tree to visit.
+  # @return [(Tree::Node, Sass::Util::SubsetMap)] The resulting tree of static nodes
+  #   *and* the extensions defined for this tree
+  def self.visit(root); super; end
+
+  protected
+
+  # Returns the immediate parent of the current node.
+  # @return [Tree::Node]
+  attr_reader :parent
+
+  def initialize
+    @parent_directives = []
+    @extends = Sass::Util::SubsetMap.new
+  end
+
+  # If an exception is raised, this adds proper metadata to the backtrace.
+  def visit(node)
+    super(node)
+  rescue Sass::SyntaxError => e
+    e.modify_backtrace(:filename => node.filename, :line => node.line)
+    raise e
+  end
+
+  # Keeps track of the current parent node.
+  def visit_children(parent)
+    with_parent parent do
+      parent.children = super.flatten
+      parent
+    end
+  end
+
+  MERGEABLE_DIRECTIVES = [Sass::Tree::MediaNode]
+
+  # Runs a block of code with the current parent node
+  # replaced with the given node.
+  #
+  # @param parent [Tree::Node] The new parent for the duration of the block.
+  # @yield A block in which the parent is set to `parent`.
+  # @return [Object] The return value of the block.
+  def with_parent(parent)
+    if parent.is_a?(Sass::Tree::DirectiveNode)
+      if MERGEABLE_DIRECTIVES.any? {|klass| parent.is_a?(klass)}
+        old_parent_directive = @parent_directives.pop
+      end
+      @parent_directives.push parent
+    end
+
+    old_parent, @parent = @parent, parent
+    yield
+  ensure
+    @parent_directives.pop if parent.is_a?(Sass::Tree::DirectiveNode)
+    @parent_directives.push old_parent_directive if old_parent_directive
+    @parent = old_parent
+  end
+
+  # In Ruby 1.8, ensures that there's only one ` charset` directive
+  # and that it's at the top of the document.
+  #
+  # @return [(Tree::Node, Sass::Util::SubsetMap)] The resulting tree of static nodes
+  #   *and* the extensions defined for this tree
+  def visit_root(node)
+    yield
+
+    if parent.nil?
+      # In Ruby 1.9 we can make all @charset nodes invisible
+      # and infer the final @charset from the encoding of the final string.
+      if Sass::Util.ruby1_8?
+        charset = node.children.find {|c| c.is_a?(Sass::Tree::CharsetNode)}
+        node.children.reject! {|c| c.is_a?(Sass::Tree::CharsetNode)}
+        node.children.unshift charset if charset
+      end
+
+      imports = Sass::Util.extract!(node.children) do |c|
+        c.is_a?(Sass::Tree::DirectiveNode) && !c.is_a?(Sass::Tree::MediaNode) &&
+          c.resolved_value =~ /^ import /i
+      end
+      charset_and_index = Sass::Util.ruby1_8? &&
+        node.children.each_with_index.find {|c, _| c.is_a?(Sass::Tree::CharsetNode)}
+      if charset_and_index
+        index = charset_and_index.last
+        node.children = node.children[0..index] + imports + node.children[index+1..-1]
+      else
+        node.children = imports + node.children
+      end
+    end
+
+    return node, @extends
+  rescue Sass::SyntaxError => e
+    e.sass_template ||= node.template
+    raise e
+  end
+
+  # A simple struct wrapping up information about a single ` extend` instance. A
+  # single [ExtendNode] can have multiple Extends if either the parent node or
+  # the extended selector is a comma sequence.
+  #
+  # @attr extender [Sass::Selector::Sequence]
+  #   The selector of the CSS rule containing the ` extend` 
+  # @attr target [Array<Sass::Selector::Simple>] The selector being ` extend`ed 
+  # @attr node [Sass::Tree::ExtendNode] The node that produced this extend.
+  # @attr directives [Array<Sass::Tree::DirectiveNode>]
+  #   The directives containing the ` extend` 
+  # @attr result [Symbol]
+  #   The result of this extend. One of `:not_found` (the target doesn't exist
+  #   in the document), `:failed_to_unify` (the target exists but cannot be
+  #   unified with the extender), or `:succeeded`.
+  Extend = Struct.new(:extender, :target, :node, :directives, :result)
+
+  # Registers an extension in the ` extends` subset map.
+  def visit_extend(node)
+    node.resolved_selector.members.each do |seq|
+      if seq.members.size > 1
+        raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: can't extend nested selectors")
+      end
+
+      sseq = seq.members.first
+      if !sseq.is_a?(Sass::Selector::SimpleSequence)
+        raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: invalid selector")
+      elsif sseq.members.any? {|ss| ss.is_a?(Sass::Selector::Parent)}
+        raise Sass::SyntaxError.new("Can't extend #{seq.to_a.join}: can't extend parent selectors")
+      end
+
+      sel = sseq.members
+      parent.resolved_rules.members.each do |member|
+        if !member.members.last.is_a?(Sass::Selector::SimpleSequence)
+          raise Sass::SyntaxError.new("#{member} can't extend: invalid selector")
+        end
+
+        @extends[sel] = Extend.new(member, sel, node, @parent_directives.dup, :not_found)
+      end
+    end
+
+    []
+  end
+
+  # Modifies exception backtraces to include the imported file.
+  def visit_import(node)
+    # Don't use #visit_children to avoid adding the import node to the list of parents.
+    node.children.map {|c| visit(c)}.flatten
+  rescue Sass::SyntaxError => e
+    e.modify_backtrace(:filename => node.children.first.filename)
+    e.add_backtrace(:filename => node.filename, :line => node.line)
+    raise e
+  end
+
+  # Bubbles the ` media` directive up through RuleNodes
+  # and merges it with other ` media` directives.
+  def visit_media(node)
+    yield unless bubble(node)
+    media = node.children.select {|c| c.is_a?(Sass::Tree::MediaNode)}
+    node.children.reject! {|c| c.is_a?(Sass::Tree::MediaNode)}
+    media = media.select {|n| n.resolved_query = n.resolved_query.merge(node.resolved_query)}
+    (node.children.empty? ? [] : [node]) + media
+  end
+
+  # Bubbles the ` supports` directive up through RuleNodes.
+  def visit_supports(node)
+    yield unless bubble(node)
+    node
+  end
+
+  # Asserts that all the traced children are valid in their new location.
+  def visit_trace(node)
+    # Don't use #visit_children to avoid adding the trace node to the list of parents.
+    node.children.map {|c| visit(c)}.flatten
+  rescue Sass::SyntaxError => e
+    e.modify_backtrace(:mixin => node.name, :filename => node.filename, :line => node.line)
+    e.add_backtrace(:filename => node.filename, :line => node.line)
+    raise e
+  end
+
+  # Converts nested properties into flat properties
+  # and updates the indentation of the prop node based on the nesting level.
+  def visit_prop(node)
+    if parent.is_a?(Sass::Tree::PropNode)
+      node.resolved_name = "#{parent.resolved_name}-#{node.resolved_name}"
+      node.tabs = parent.tabs + (parent.resolved_value.empty? ? 0 : 1) if node.style == :nested
+    end
+
+    yield
+
+    result = node.children.dup
+    if !node.resolved_value.empty? || node.children.empty?
+      node.send(:check!)
+      result.unshift(node)
+    end
+
+    result
+  end
+
+  # Resolves parent references and nested selectors,
+  # and updates the indentation of the rule node based on the nesting level.
+  def visit_rule(node)
+    parent_resolved_rules = parent.is_a?(Sass::Tree::RuleNode) ? parent.resolved_rules : nil
+    # It's possible for resolved_rules to be set if we've duplicated this node during @media bubbling
+    node.resolved_rules ||= node.parsed_rules.resolve_parent_refs(parent_resolved_rules)
+
+    yield
+
+    rules = node.children.select {|c| c.is_a?(Sass::Tree::RuleNode) || c.bubbles?}
+    props = node.children.reject {|c| c.is_a?(Sass::Tree::RuleNode) || c.bubbles? || c.invisible?}
+
+    unless props.empty?
+      node.children = props
+      rules.each {|r| r.tabs += 1} if node.style == :nested
+      rules.unshift(node)
+    end
+
+    rules.last.group_end = true unless parent.is_a?(Sass::Tree::RuleNode) || rules.empty?
+
+    rules
+  end
+
+  private
+
+  def bubble(node)
+    return unless parent.is_a?(Sass::Tree::RuleNode)
+    new_rule = parent.dup
+    new_rule.children = node.children
+    node.children = with_parent(node) {Array(visit(new_rule))}
+    # If the last child is actually the end of the group,
+    # the parent's cssize will set it properly
+    node.children.last.group_end = false unless node.children.empty?
+    true
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/deep_copy.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/deep_copy.rb
new file mode 100644
index 0000000..2962e83
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/deep_copy.rb
@@ -0,0 +1,102 @@
+# A visitor for copying the full structure of a Sass tree.
+class Sass::Tree::Visitors::DeepCopy < Sass::Tree::Visitors::Base
+  protected
+
+  def visit(node)
+    super(node.dup)
+  end
+
+  def visit_children(parent)
+    parent.children = parent.children.map {|c| visit(c)}
+    parent
+  end
+
+  def visit_debug(node)
+    node.expr = node.expr.deep_copy
+    yield
+  end
+
+  def visit_each(node)
+    node.list = node.list.deep_copy
+    yield
+  end
+
+  def visit_extend(node)
+    node.selector = node.selector.map {|c| c.is_a?(Sass::Script::Node) ? c.deep_copy : c}
+    yield
+  end
+
+  def visit_for(node)
+    node.from = node.from.deep_copy
+    node.to = node.to.deep_copy
+    yield
+  end
+
+  def visit_function(node)
+    node.args = node.args.map {|k, v| [k.deep_copy, v && v.deep_copy]}
+    yield
+  end
+
+  def visit_if(node)
+    node.expr = node.expr.deep_copy if node.expr
+    node.else = visit(node.else) if node.else
+    yield
+  end
+
+  def visit_mixindef(node)
+    node.args = node.args.map {|k, v| [k.deep_copy, v && v.deep_copy]}
+    yield
+  end
+
+  def visit_mixin(node)
+    node.args = node.args.map {|a| a.deep_copy}
+    node.keywords = Hash[node.keywords.map {|k, v| [k, v.deep_copy]}]
+    yield
+  end
+
+  def visit_prop(node)
+    node.name = node.name.map {|c| c.is_a?(Sass::Script::Node) ? c.deep_copy : c}
+    node.value = node.value.deep_copy
+    yield
+  end
+
+  def visit_return(node)
+    node.expr = node.expr.deep_copy
+    yield
+  end
+
+  def visit_rule(node)
+    node.rule = node.rule.map {|c| c.is_a?(Sass::Script::Node) ? c.deep_copy : c}
+    yield
+  end
+
+  def visit_variable(node)
+    node.expr = node.expr.deep_copy
+    yield
+  end
+
+  def visit_warn(node)
+    node.expr = node.expr.deep_copy
+    yield
+  end
+
+  def visit_while(node)
+    node.expr = node.expr.deep_copy
+    yield
+  end
+
+  def visit_directive(node)
+    node.value = node.value.map {|c| c.is_a?(Sass::Script::Node) ? c.deep_copy : c}
+    yield
+  end
+
+  def visit_media(node)
+    node.query = node.query.map {|c| c.is_a?(Sass::Script::Node) ? c.deep_copy : c}
+    yield
+  end
+
+  def visit_supports(node)
+    node.condition = node.condition.deep_copy
+    yield
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/extend.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/extend.rb
new file mode 100644
index 0000000..9e8b62a
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/extend.rb
@@ -0,0 +1,68 @@
+# A visitor for performing selector inheritance on a static CSS tree.
+#
+# Destructively modifies the tree.
+class Sass::Tree::Visitors::Extend < Sass::Tree::Visitors::Base
+  # Performs the given extensions on the static CSS tree based in `root`, then
+  # validates that all extends matched some selector.
+  #
+  # @param root [Tree::Node] The root node of the tree to visit.
+  # @param extends [Sass::Util::SubsetMap{Selector::Simple =>
+  #                                       Sass::Tree::Visitors::Cssize::Extend}]
+  #   The extensions to perform on this tree.
+  # @return [Object] The return value of \{#visit} for the root node.
+  def self.visit(root, extends)
+    return if extends.empty?
+    new(extends).send(:visit, root)
+    check_extends_fired! extends
+  end
+
+  protected
+
+  def initialize(extends)
+    @parent_directives = []
+    @extends = extends
+  end
+
+  # If an exception is raised, this adds proper metadata to the backtrace.
+  def visit(node)
+    super(node)
+  rescue Sass::SyntaxError => e
+    e.modify_backtrace(:filename => node.filename, :line => node.line)
+    raise e
+  end
+
+  # Keeps track of the current parent directives.
+  def visit_children(parent)
+    @parent_directives.push parent if parent.is_a?(Sass::Tree::DirectiveNode)
+    super
+  ensure
+    @parent_directives.pop if parent.is_a?(Sass::Tree::DirectiveNode)
+  end
+
+  # Applies the extend to a single rule's selector.
+  def visit_rule(node)
+    node.resolved_rules = node.resolved_rules.do_extend(@extends, @parent_directives)
+  end
+
+  private
+
+  def self.check_extends_fired!(extends)
+    extends.each_value do |ex|
+      next if ex.result == :succeeded || ex.node.optional?
+      warn = "\"#{ex.extender}\" failed to @extend \"#{ex.target.join}\"."
+      reason =
+        if ex.result == :not_found
+          "The selector \"#{ex.target.join}\" was not found."
+        else
+          "No selectors matching \"#{ex.target.join}\" could be unified with \"#{ex.extender}\"."
+        end
+
+      Sass::Util.sass_warn <<WARN
+WARNING on line #{ex.node.line}#{" of #{ex.node.filename}" if ex.node.filename}: #{warn}
+  #{reason}
+  This will be an error in future releases of Sass.
+  Use "@extend #{ex.target.join} !optional" if the extend should be able to fail.
+WARN
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/perform.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/perform.rb
new file mode 100644
index 0000000..52960f3
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/perform.rb
@@ -0,0 +1,446 @@
+# A visitor for converting a dynamic Sass tree into a static Sass tree.
+class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
+  # @param root [Tree::Node] The root node of the tree to visit.
+  # @param environment [Sass::Environment] The lexical environment.
+  # @return [Tree::Node] The resulting tree of static nodes.
+  def self.visit(root, environment = Sass::Environment.new)
+    new(environment).send(:visit, root)
+  end
+
+  # @api private
+  def self.perform_arguments(callable, args, keywords, splat)
+    desc = "#{callable.type.capitalize} #{callable.name}"
+    downcase_desc = "#{callable.type} #{callable.name}"
+
+    begin
+      unless keywords.empty?
+        unknown_args = Sass::Util.array_minus(keywords.keys,
+          callable.args.map {|var| var.first.underscored_name})
+        if callable.splat && unknown_args.include?(callable.splat.underscored_name)
+          raise Sass::SyntaxError.new("Argument $#{callable.splat.name} of #{downcase_desc} cannot be used 
as a named argument.")
+        elsif unknown_args.any?
+          description = unknown_args.length > 1 ? 'the following arguments:' : 'an argument named'
+          raise Sass::SyntaxError.new("#{desc} doesn't have #{description} #{unknown_args.map {|name| 
"$#{name}"}.join ', '}.")
+        end
+      end
+    rescue Sass::SyntaxError => keyword_exception
+    end
+
+    # If there's no splat, raise the keyword exception immediately. The actual
+    # raising happens in the ensure clause at the end of this function.
+    return if keyword_exception && !callable.splat
+
+    if args.size > callable.args.size && !callable.splat
+      takes = callable.args.size
+      passed = args.size
+      raise Sass::SyntaxError.new(
+        "#{desc} takes #{takes} argument#{'s' unless takes == 1} " +
+        "but #{passed} #{passed == 1 ? 'was' : 'were'} passed.")
+    end
+
+    splat_sep = :comma
+    if splat
+      args += splat.to_a
+      splat_sep = splat.separator if splat.is_a?(Sass::Script::List)
+      # If the splat argument exists, there won't be any keywords passed in
+      # manually, so we can safely overwrite rather than merge here.
+      keywords = splat.keywords if splat.is_a?(Sass::Script::ArgList)
+    end
+
+    keywords = keywords.dup
+    env = Sass::Environment.new(callable.environment)
+    callable.args.zip(args[0...callable.args.length]) do |(var, default), value|
+      if value && keywords.include?(var.underscored_name)
+        raise Sass::SyntaxError.new("#{desc} was passed argument $#{var.name} both by position and by name.")
+      end
+
+      value ||= keywords.delete(var.underscored_name)
+      value ||= default && default.perform(env)
+      raise Sass::SyntaxError.new("#{desc} is missing argument #{var.inspect}.") unless value
+      env.set_local_var(var.name, value)
+    end
+
+    if callable.splat
+      rest = args[callable.args.length..-1]
+      arg_list = Sass::Script::ArgList.new(rest, keywords.dup, splat_sep)
+      arg_list.options = env.options
+      env.set_local_var(callable.splat.name, arg_list)
+    end
+
+    yield env
+  rescue Exception => e
+  ensure
+    # If there's a keyword exception, we don't want to throw it immediately,
+    # because the invalid keywords may be part of a glob argument that should be
+    # passed on to another function. So we only raise it if we reach the end of
+    # this function *and* the keywords attached to the argument list glob object
+    # haven't been accessed.
+    #
+    # The keyword exception takes precedence over any Sass errors, but not over
+    # non-Sass exceptions.
+    if keyword_exception &&
+        !(arg_list && arg_list.keywords_accessed) &&
+        (e.nil? || e.is_a?(Sass::SyntaxError))
+      raise keyword_exception
+    elsif e
+      raise e
+    end
+  end
+
+  protected
+
+  def initialize(env)
+    @environment = env
+    # Stack trace information, including mixin includes and imports.
+    @stack = []
+  end
+
+  # If an exception is raised, this adds proper metadata to the backtrace.
+  def visit(node)
+    super(node.dup)
+  rescue Sass::SyntaxError => e
+    e.modify_backtrace(:filename => node.filename, :line => node.line)
+    raise e
+  end
+
+  # Keeps track of the current environment.
+  def visit_children(parent)
+    with_environment Sass::Environment.new(@environment, parent.options) do
+      parent.children = super.flatten
+      parent
+    end
+  end
+
+  # Runs a block of code with the current environment replaced with the given one.
+  #
+  # @param env [Sass::Environment] The new environment for the duration of the block.
+  # @yield A block in which the environment is set to `env`.
+  # @return [Object] The return value of the block.
+  def with_environment(env)
+    old_env, @environment = @environment, env
+    yield
+  ensure
+    @environment = old_env
+  end
+
+  # Sets the options on the environment if this is the top-level root.
+  def visit_root(node)
+    yield
+  rescue Sass::SyntaxError => e
+    e.sass_template ||= node.template
+    raise e
+  end
+
+  # Removes this node from the tree if it's a silent comment.
+  def visit_comment(node)
+    return [] if node.invisible?
+    node.resolved_value = run_interp_no_strip(node.value)
+    node.resolved_value.gsub!(/\\([\\#])/, '\1')
+    node
+  end
+
+  # Prints the expression to STDERR.
+  def visit_debug(node)
+    res = node.expr.perform(@environment)
+    res = res.value if res.is_a?(Sass::Script::String)
+    if node.filename
+      Sass::Util.sass_warn "#{node.filename}:#{node.line} DEBUG: #{res}"
+    else
+      Sass::Util.sass_warn "Line #{node.line} DEBUG: #{res}"
+    end
+    []
+  end
+
+  # Runs the child nodes once for each value in the list.
+  def visit_each(node)
+    list = node.list.perform(@environment)
+
+    with_environment Sass::Environment.new(@environment) do
+      list.to_a.map do |v|
+        @environment.set_local_var(node.var, v)
+        node.children.map {|c| visit(c)}
+      end.flatten
+    end
+  end
+
+  # Runs SassScript interpolation in the selector,
+  # and then parses the result into a {Sass::Selector::CommaSequence}.
+  def visit_extend(node)
+    parser = Sass::SCSS::StaticParser.new(run_interp(node.selector), node.filename, node.line)
+    node.resolved_selector = parser.parse_selector
+    node
+  end
+
+  # Runs the child nodes once for each time through the loop, varying the variable each time.
+  def visit_for(node)
+    from = node.from.perform(@environment)
+    to = node.to.perform(@environment)
+    from.assert_int!
+    to.assert_int!
+
+    to = to.coerce(from.numerator_units, from.denominator_units)
+    range = Range.new(from.to_i, to.to_i, node.exclusive)
+
+    with_environment Sass::Environment.new(@environment) do
+      range.map do |i|
+        @environment.set_local_var(node.var,
+          Sass::Script::Number.new(i, from.numerator_units, from.denominator_units))
+        node.children.map {|c| visit(c)}
+      end.flatten
+    end
+  end
+
+  # Loads the function into the environment.
+  def visit_function(node)
+    env = Sass::Environment.new(@environment, node.options)
+    @environment.set_local_function(node.name,
+      Sass::Callable.new(node.name, node.args, node.splat, env, node.children, !:has_content, "function"))
+    []
+  end
+
+  # Runs the child nodes if the conditional expression is true;
+  # otherwise, tries the else nodes.
+  def visit_if(node)
+    if node.expr.nil? || node.expr.perform(@environment).to_bool
+      yield
+      node.children
+    elsif node.else
+      visit(node.else)
+    else
+      []
+    end
+  end
+
+  # Returns a static DirectiveNode if this is importing a CSS file,
+  # or parses and includes the imported Sass file.
+  def visit_import(node)
+    if path = node.css_import?
+      return Sass::Tree::CssImportNode.resolved("url(#{path})")
+    end
+    file = node.imported_file
+    handle_import_loop!(node) if @stack.any? {|e| e[:filename] == file.options[:filename]}
+
+    begin
+      @stack.push(:filename => node.filename, :line => node.line)
+      root = file.to_tree
+      Sass::Tree::Visitors::CheckNesting.visit(root)
+      node.children = root.children.map {|c| visit(c)}.flatten
+      node
+    rescue Sass::SyntaxError => e
+      e.modify_backtrace(:filename => node.imported_file.options[:filename])
+      e.add_backtrace(:filename => node.filename, :line => node.line)
+      raise e
+    end
+  ensure
+    @stack.pop unless path
+  end
+
+  # Loads a mixin into the environment.
+  def visit_mixindef(node)
+    env = Sass::Environment.new(@environment, node.options)
+    @environment.set_local_mixin(node.name,
+      Sass::Callable.new(node.name, node.args, node.splat, env, node.children, node.has_content, "mixin"))
+    []
+  end
+
+  # Runs a mixin.
+  def visit_mixin(node)
+    include_loop = true
+    handle_include_loop!(node) if @stack.any? {|e| e[:name] == node.name}
+    include_loop = false
+
+    @stack.push(:filename => node.filename, :line => node.line, :name => node.name)
+    raise Sass::SyntaxError.new("Undefined mixin '#{node.name}'.") unless mixin = 
@environment.mixin(node.name)
+
+    if node.children.any? && !mixin.has_content
+      raise Sass::SyntaxError.new(%Q{Mixin "#{node.name}" does not accept a content block.})
+    end
+
+    args = node.args.map {|a| a.perform(@environment)}
+    keywords = Sass::Util.map_hash(node.keywords) {|k, v| [k, v.perform(@environment)]}
+    splat = node.splat.perform(@environment) if node.splat
+
+    self.class.perform_arguments(mixin, args, keywords, splat) do |env|
+      env.caller = Sass::Environment.new(@environment)
+      env.content = node.children if node.has_children
+
+      trace_node = Sass::Tree::TraceNode.from_node(node.name, node)
+      with_environment(env) {trace_node.children = mixin.tree.map {|c| visit(c)}.flatten}
+      trace_node
+    end
+  rescue Sass::SyntaxError => e
+    unless include_loop
+      e.modify_backtrace(:mixin => node.name, :line => node.line)
+      e.add_backtrace(:line => node.line)
+    end
+    raise e
+  ensure
+    @stack.pop unless include_loop
+  end
+
+  def visit_content(node)
+    return [] unless content = @environment.content
+    @stack.push(:filename => node.filename, :line => node.line, :name => '@content')
+    trace_node = Sass::Tree::TraceNode.from_node('@content', node)
+    with_environment(@environment.caller) {trace_node.children = content.map {|c| visit(c.dup)}.flatten}
+    trace_node
+  rescue Sass::SyntaxError => e
+    e.modify_backtrace(:mixin => '@content', :line => node.line)
+    e.add_backtrace(:line => node.line)
+    raise e
+  ensure
+    @stack.pop if content
+  end
+
+  # Runs any SassScript that may be embedded in a property.
+  def visit_prop(node)
+    node.resolved_name = run_interp(node.name)
+    val = node.value.perform(@environment)
+    node.resolved_value = val.to_s
+    yield
+  end
+
+  # Returns the value of the expression.
+  def visit_return(node)
+    throw :_sass_return, node.expr.perform(@environment)
+  end
+
+  # Runs SassScript interpolation in the selector,
+  # and then parses the result into a {Sass::Selector::CommaSequence}.
+  def visit_rule(node)
+    rule = node.rule
+    rule = rule.map {|e| e.is_a?(String) && e != ' ' ? e.strip : e} if node.style == :compressed
+    parser = Sass::SCSS::StaticParser.new(run_interp(node.rule), node.filename, node.line)
+    node.parsed_rules ||= parser.parse_selector
+    if node.options[:trace_selectors]
+      @stack.push(:filename => node.filename, :line => node.line)
+      node.stack_trace = stack_trace
+      @stack.pop
+    end
+    yield
+  end
+
+  # Loads the new variable value into the environment.
+  def visit_variable(node)
+    var = @environment.var(node.name)
+    return [] if node.guarded && var && !var.null?
+    val = node.expr.perform(@environment)
+    @environment.set_var(node.name, val)
+    []
+  end
+
+  # Prints the expression to STDERR with a stylesheet trace.
+  def visit_warn(node)
+    @stack.push(:filename => node.filename, :line => node.line)
+    res = node.expr.perform(@environment)
+    res = res.value if res.is_a?(Sass::Script::String)
+    msg = "WARNING: #{res}\n         "
+    msg << stack_trace.join("\n         ") << "\n"
+    Sass::Util.sass_warn msg
+    []
+  ensure
+    @stack.pop
+  end
+
+  # Runs the child nodes until the continuation expression becomes false.
+  def visit_while(node)
+    children = []
+    with_environment Sass::Environment.new(@environment) do
+      children += node.children.map {|c| visit(c)} while node.expr.perform(@environment).to_bool
+    end
+    children.flatten
+  end
+
+  def visit_directive(node)
+    node.resolved_value = run_interp(node.value)
+    yield
+  end
+
+  def visit_media(node)
+    parser = Sass::SCSS::StaticParser.new(run_interp(node.query), node.filename, node.line)
+    node.resolved_query ||= parser.parse_media_query_list
+    yield
+  end
+
+  def visit_supports(node)
+    node.condition = node.condition.deep_copy
+    node.condition.perform(@environment)
+    yield
+  end
+
+  def visit_cssimport(node)
+    node.resolved_uri = run_interp([node.uri])
+    if node.query
+      parser = Sass::SCSS::StaticParser.new(run_interp(node.query), node.filename, node.line)
+      node.resolved_query ||= parser.parse_media_query_list
+    end
+    yield
+  end
+
+  private
+
+  def stack_trace
+    trace = []
+    stack = @stack.map {|e| e.dup}.reverse
+    stack.each_cons(2) {|(e1, e2)| e1[:caller] = e2[:name]; [e1, e2]}
+    stack.each_with_index do |entry, i|
+      msg = "#{i == 0 ? "on" : "from"} line #{entry[:line]}"
+      msg << " of #{entry[:filename] || "an unknown file"}"
+      msg << ", in `#{entry[:caller]}'" if entry[:caller]
+      trace << msg
+    end
+    trace
+  end
+
+  def run_interp_no_strip(text)
+    text.map do |r|
+      next r if r.is_a?(String)
+      val = r.perform(@environment)
+      # Interpolated strings should never render with quotes
+      next val.value if val.is_a?(Sass::Script::String)
+      val.to_s
+    end.join
+  end
+
+  def run_interp(text)
+    run_interp_no_strip(text).strip
+  end
+
+  def handle_include_loop!(node)
+    msg = "An @include loop has been found:"
+    content_count = 0
+    mixins = @stack.reverse.map {|s| s[:name]}.compact.select do |s|
+      if s == '@content'
+        content_count += 1
+        false
+      elsif content_count > 0
+        content_count -= 1
+        false
+      else
+        true
+      end
+    end
+
+    return unless mixins.include?(node.name)
+    raise Sass::SyntaxError.new("#{msg} #{node.name} includes itself") if mixins.size == 1
+
+    msg << "\n" << Sass::Util.enum_cons(mixins.reverse + [node.name], 2).map do |m1, m2|
+      "    #{m1} includes #{m2}"
+    end.join("\n")
+    raise Sass::SyntaxError.new(msg)
+  end
+
+  def handle_import_loop!(node)
+    msg = "An @import loop has been found:"
+    files = @stack.map {|s| s[:filename]}.compact
+    if node.filename == node.imported_file.options[:filename]
+      raise Sass::SyntaxError.new("#{msg} #{node.filename} imports itself")
+    end
+
+    files << node.filename << node.imported_file.options[:filename]
+    msg << "\n" << Sass::Util.enum_cons(files, 2).map do |m1, m2|
+      "    #{m1} imports #{m2}"
+    end.join("\n")
+    raise Sass::SyntaxError.new(msg)
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/set_options.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/set_options.rb
new file mode 100644
index 0000000..3cef777
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/set_options.rb
@@ -0,0 +1,125 @@
+# A visitor for setting options on the Sass tree
+class Sass::Tree::Visitors::SetOptions < Sass::Tree::Visitors::Base
+  # @param root [Tree::Node] The root node of the tree to visit.
+  # @param options [{Symbol => Object}] The options has to set.
+  def self.visit(root, options); new(options).send(:visit, root); end
+
+  protected
+
+  def initialize(options)
+    @options = options
+  end
+
+  def visit(node)
+    node.instance_variable_set('@options', @options)
+    super
+  end
+
+  def visit_debug(node)
+    node.expr.options = @options
+    yield
+  end
+
+  def visit_each(node)
+    node.list.options = @options
+    yield
+  end
+
+  def visit_extend(node)
+    node.selector.each {|c| c.options = @options if c.is_a?(Sass::Script::Node)}
+    yield
+  end
+
+  def visit_for(node)
+    node.from.options = @options
+    node.to.options = @options
+    yield
+  end
+
+  def visit_function(node)
+    node.args.each do |k, v|
+      k.options = @options
+      v.options = @options if v
+    end
+    yield
+  end
+
+  def visit_if(node)
+    node.expr.options = @options if node.expr
+    visit(node.else) if node.else
+    yield
+  end
+
+  def visit_import(node)
+    # We have no good way of propagating the new options through an Engine
+    # instance, so we just null it out. This also lets us avoid caching an
+    # imported Engine along with the importing source tree.
+    node.imported_file = nil
+    yield
+  end
+
+  def visit_mixindef(node)
+    node.args.each do |k, v|
+      k.options = @options
+      v.options = @options if v
+    end
+    yield
+  end
+
+  def visit_mixin(node)
+    node.args.each {|a| a.options = @options}
+    node.keywords.each {|k, v| v.options = @options}
+    yield
+  end
+
+  def visit_prop(node)
+    node.name.each {|c| c.options = @options if c.is_a?(Sass::Script::Node)}
+    node.value.options = @options
+    yield
+  end
+
+  def visit_return(node)
+    node.expr.options = @options
+    yield
+  end
+
+  def visit_rule(node)
+    node.rule.each {|c| c.options = @options if c.is_a?(Sass::Script::Node)}
+    yield
+  end
+
+  def visit_variable(node)
+    node.expr.options = @options
+    yield
+  end
+
+  def visit_warn(node)
+    node.expr.options = @options
+    yield
+  end
+
+  def visit_while(node)
+    node.expr.options = @options
+    yield
+  end
+
+  def visit_directive(node)
+    node.value.each {|c| c.options = @options if c.is_a?(Sass::Script::Node)}
+    yield
+  end
+
+  def visit_media(node)
+    node.query.each {|c| c.options = @options if c.is_a?(Sass::Script::Node)}
+    yield
+  end
+
+  def visit_cssimport(node)
+    node.query.each {|c| c.options = @options if c.is_a?(Sass::Script::Node)} if node.query
+    yield
+  end
+
+  def visit_supports(node)
+    node.condition.options = @options
+    yield
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/to_css.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/to_css.rb
new file mode 100644
index 0000000..9571d09
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/visitors/to_css.rb
@@ -0,0 +1,228 @@
+# A visitor for converting a Sass tree into CSS.
+class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
+  protected
+
+  def initialize
+    @tabs = 0
+  end
+
+  def visit(node)
+    super
+  rescue Sass::SyntaxError => e
+    e.modify_backtrace(:filename => node.filename, :line => node.line)
+    raise e
+  end
+
+  def with_tabs(tabs)
+    old_tabs, @tabs = @tabs, tabs
+    yield
+  ensure
+    @tabs = old_tabs
+  end
+
+  def visit_root(node)
+    result = String.new
+    node.children.each do |child|
+      next if child.invisible?
+      child_str = visit(child)
+      result << child_str + (node.style == :compressed ? '' : "\n")
+    end
+    result.rstrip!
+    return "" if result.empty?
+    result << "\n"
+    unless Sass::Util.ruby1_8? || result.ascii_only?
+      if node.children.first.is_a?(Sass::Tree::CharsetNode)
+        begin
+          encoding = node.children.first.name
+          # Default to big-endian encoding, because we have to decide somehow
+          encoding << 'BE' if encoding =~ /\Autf-(16|32)\Z/i
+          result = result.encode(Encoding.find(encoding))
+        rescue EncodingError
+        end
+      end
+
+      result = "@charset \"#{result.encoding.name}\";#{
+        node.style == :compressed ? '' : "\n"
+      }".encode(result.encoding) + result
+    end
+    result
+  rescue Sass::SyntaxError => e
+    e.sass_template ||= node.template
+    raise e
+  end
+
+  def visit_charset(node)
+    "@charset \"#{node.name}\";"
+  end 
+
+  def visit_comment(node)
+    return if node.invisible?
+    spaces = ('  ' * [ tabs - node.resolved_value[/^ */].size, 0].max)
+
+    content = node.resolved_value.gsub(/^/, spaces)
+    content.gsub!(%r{^(\s*)//(.*)$}) {|md| "#{$1}/*#{$2} */"} if node.type == :silent
+    content.gsub!(/\n +(\* *(?!\/))?/, ' ') if (node.style == :compact || node.style == :compressed) && 
node.type != :loud
+    content
+  end
+
+  def visit_directive(node)
+    was_in_directive = @in_directive
+    tab_str = '  ' * @tabs
+    return tab_str + node.resolved_value + ";" unless node.has_children
+    return tab_str + node.resolved_value + " {}" if node.children.empty?
+    @in_directive = @in_directive || !node.is_a?(Sass::Tree::MediaNode)
+    result = if node.style == :compressed
+               "#{node.resolved_value}{"
+             else
+               "#{tab_str}#{node.resolved_value} {" + (node.style == :compact ? ' ' : "\n")
+             end
+    was_prop = false
+    first = true
+    node.children.each do |child|
+      next if child.invisible?
+      if node.style == :compact
+        if child.is_a?(Sass::Tree::PropNode)
+          with_tabs(first || was_prop ? 0 : @tabs + 1) {result << visit(child) << ' '}
+        else
+          result[-1] = "\n" if was_prop
+          rendered = with_tabs(@tabs + 1) {visit(child).dup}
+          rendered = rendered.lstrip if first
+          result << rendered.rstrip + "\n"
+        end
+        was_prop = child.is_a?(Sass::Tree::PropNode)
+        first = false
+      elsif node.style == :compressed
+        result << (was_prop ? ";" : "") << with_tabs(0) {visit(child)}
+        was_prop = child.is_a?(Sass::Tree::PropNode)
+      else
+        result << with_tabs(@tabs + 1) {visit(child)} + "\n"
+      end
+    end
+    result.rstrip + if node.style == :compressed
+                      "}"
+                    else
+                      (node.style == :expanded ? "\n" : " ") + "}\n"
+                    end
+  ensure
+    @in_directive = was_in_directive
+  end
+
+  def visit_media(node)
+    str = with_tabs(@tabs + node.tabs) {visit_directive(node)}
+    str.gsub!(/\n\Z/, '') unless node.style == :compressed || node.group_end
+    str
+  end
+
+  def visit_supports(node)
+    visit_media(node)
+  end
+
+  def visit_cssimport(node)
+    visit_directive(node)
+  end
+
+  def visit_prop(node)
+    return if node.resolved_value.empty?
+    tab_str = '  ' * (@tabs + node.tabs)
+    if node.style == :compressed
+      "#{tab_str}#{node.resolved_name}:#{node.resolved_value}"
+    else
+      "#{tab_str}#{node.resolved_name}: #{node.resolved_value};"
+    end
+  end
+
+  def visit_rule(node)
+    with_tabs(@tabs + node.tabs) do
+      rule_separator = node.style == :compressed ? ',' : ', '
+      line_separator =
+        case node.style
+          when :nested, :expanded; "\n"
+          when :compressed; ""
+          else; " "
+        end
+      rule_indent = '  ' * @tabs
+      per_rule_indent, total_indent = [:nested, :expanded].include?(node.style) ? [rule_indent, ''] : ['', 
rule_indent]
+
+      joined_rules = node.resolved_rules.members.map do |seq|
+        next if seq.has_placeholder?
+        rule_part = seq.to_a.join
+        if node.style == :compressed
+          rule_part.gsub!(/([^,])\s*\n\s*/m, '\1 ')
+          rule_part.gsub!(/\s*([,+>])\s*/m, '\1')
+          rule_part.strip!
+        end
+        rule_part
+      end.compact.join(rule_separator)
+
+      joined_rules.sub!(/\A\s*/, per_rule_indent)
+      joined_rules.gsub!(/\s*\n\s*/, "#{line_separator}#{per_rule_indent}")
+      total_rule = total_indent << joined_rules
+
+      to_return = ''
+      old_spaces = '  ' * @tabs
+      if node.style != :compressed
+        if node.options[:debug_info] && ! in_directive
+          to_return << visit(debug_info_rule(node.debug_info, node.options)) << "\n"
+        elsif node.options[:trace_selectors]
+          to_return << "#{old_spaces}/* "
+          to_return << node.stack_trace.join("\n   #{old_spaces}")
+          to_return << " */\n"
+        elsif node.options[:line_comments]
+          to_return << "#{old_spaces}/* line #{node.line}"
+
+          if node.filename
+            relative_filename = if node.options[:css_filename]
+              begin
+                Pathname.new(node.filename).relative_path_from(
+                  Pathname.new(File.dirname(node.options[:css_filename]))).to_s
+              rescue ArgumentError
+                nil
+              end
+            end
+            relative_filename ||= node.filename
+            to_return << ", #{relative_filename}"
+          end
+
+          to_return << " */\n"
+        end
+      end
+
+      if node.style == :compact
+        properties = with_tabs(0) {node.children.map {|a| visit(a)}.join(' ')}
+        to_return << "#{total_rule} { #{properties} }#{"\n" if node.group_end}"
+      elsif node.style == :compressed
+        properties = with_tabs(0) {node.children.map {|a| visit(a)}.join(';')}
+        to_return << "#{total_rule}{#{properties}}"
+      else
+        properties = with_tabs(@tabs + 1) {node.children.map {|a| visit(a)}.join("\n")}
+        end_props = (node.style == :expanded ? "\n" + old_spaces : ' ')
+        to_return << "#{total_rule} {\n#{properties}#{end_props}}#{"\n" if node.group_end}"
+      end
+
+      to_return
+    end
+  end
+
+  private
+
+  def debug_info_rule(debug_info, options)
+    node = Sass::Tree::DirectiveNode.resolved("@media -sass-debug-info")
+    Sass::Util.hash_to_a(debug_info.map {|k, v| [k.to_s, v.to_s]}).each do |k, v|
+      rule = Sass::Tree::RuleNode.new([""])
+      rule.resolved_rules = Sass::Selector::CommaSequence.new(
+        [Sass::Selector::Sequence.new(
+            [Sass::Selector::SimpleSequence.new(
+                [Sass::Selector::Element.new(k.to_s.gsub(/[^\w-]/, "\\\\\\0"), nil)],
+                false)
+            ])
+        ])
+      prop = Sass::Tree::PropNode.new([""], Sass::Script::String.new(''), :new)
+      prop.resolved_name = "font-family"
+      prop.resolved_value = Sass::SCSS::RX.escape_ident(v.to_s)
+      rule << prop
+      node << rule
+    end
+    node.options = options.merge(:debug_info => false, :line_comments => false, :style => :compressed)
+    node
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/warn_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/warn_node.rb
new file mode 100644
index 0000000..a7d2e8f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/warn_node.rb
@@ -0,0 +1,18 @@
+module Sass
+  module Tree
+    # A dynamic node representing a Sass ` warn` statement.
+    #
+    # @see Sass::Tree
+    class WarnNode < Node
+      # The expression to print.
+      # @return [Script::Node]
+      attr_accessor :expr
+
+      # @param expr [Script::Node] The expression to print
+      def initialize(expr)
+        @expr = expr
+        super()
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/tree/while_node.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/tree/while_node.rb
new file mode 100644
index 0000000..31b2ec7
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/tree/while_node.rb
@@ -0,0 +1,18 @@
+require 'sass/tree/node'
+
+module Sass::Tree
+  # A dynamic node representing a Sass ` while` loop.
+  #
+  # @see Sass::Tree
+  class WhileNode < Node
+    # The parse tree for the continuation expression.
+    # @return [Script::Node]
+    attr_accessor :expr
+
+    # @param expr [Script::Node] See \{#expr}
+    def initialize(expr)
+      @expr = expr
+      super()
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/util.rb b/backends/css/gems/sass-3.2.12/lib/sass/util.rb
new file mode 100644
index 0000000..483bf83
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/util.rb
@@ -0,0 +1,930 @@
+require 'erb'
+require 'set'
+require 'enumerator'
+require 'stringio'
+require 'rbconfig'
+require 'thread'
+
+require 'sass/root'
+require 'sass/util/subset_map'
+
+module Sass
+  # A module containing various useful functions.
+  module Util
+    extend self
+
+    # An array of ints representing the Ruby version number.
+    # @api public
+    RUBY_VERSION = ::RUBY_VERSION.split(".").map {|s| s.to_i}
+
+    # The Ruby engine we're running under. Defaults to `"ruby"`
+    # if the top-level constant is undefined.
+    # @api public
+    RUBY_ENGINE = defined?(::RUBY_ENGINE) ? ::RUBY_ENGINE : "ruby"
+
+    # Returns the path of a file relative to the Sass root directory.
+    #
+    # @param file [String] The filename relative to the Sass root
+    # @return [String] The filename relative to the the working directory
+    def scope(file)
+      File.join(Sass::ROOT_DIR, file)
+    end
+
+    # Converts an array of `[key, value]` pairs to a hash.
+    #
+    # @example
+    #   to_hash([[:foo, "bar"], [:baz, "bang"]])
+    #     #=> {:foo => "bar", :baz => "bang"}
+    # @param arr [Array<(Object, Object)>] An array of pairs
+    # @return [Hash] A hash
+    def to_hash(arr)
+      Hash[arr.compact]
+    end
+
+    # Maps the keys in a hash according to a block.
+    #
+    # @example
+    #   map_keys({:foo => "bar", :baz => "bang"}) {|k| k.to_s}
+    #     #=> {"foo" => "bar", "baz" => "bang"}
+    # @param hash [Hash] The hash to map
+    # @yield [key] A block in which the keys are transformed
+    # @yieldparam key [Object] The key that should be mapped
+    # @yieldreturn [Object] The new value for the key
+    # @return [Hash] The mapped hash
+    # @see #map_vals
+    # @see #map_hash
+    def map_keys(hash)
+      to_hash(hash.map {|k, v| [yield(k), v]})
+    end
+
+    # Maps the values in a hash according to a block.
+    #
+    # @example
+    #   map_values({:foo => "bar", :baz => "bang"}) {|v| v.to_sym}
+    #     #=> {:foo => :bar, :baz => :bang}
+    # @param hash [Hash] The hash to map
+    # @yield [value] A block in which the values are transformed
+    # @yieldparam value [Object] The value that should be mapped
+    # @yieldreturn [Object] The new value for the value
+    # @return [Hash] The mapped hash
+    # @see #map_keys
+    # @see #map_hash
+    def map_vals(hash)
+      to_hash(hash.map {|k, v| [k, yield(v)]})
+    end
+
+    # Maps the key-value pairs of a hash according to a block.
+    #
+    # @example
+    #   map_hash({:foo => "bar", :baz => "bang"}) {|k, v| [k.to_s, v.to_sym]}
+    #     #=> {"foo" => :bar, "baz" => :bang}
+    # @param hash [Hash] The hash to map
+    # @yield [key, value] A block in which the key-value pairs are transformed
+    # @yieldparam [key] The hash key
+    # @yieldparam [value] The hash value
+    # @yieldreturn [(Object, Object)] The new value for the `[key, value]` pair
+    # @return [Hash] The mapped hash
+    # @see #map_keys
+    # @see #map_vals
+    def map_hash(hash)
+      # Using &block here completely hoses performance on 1.8.
+      to_hash(hash.map {|k, v| yield k, v})
+    end
+
+    # Computes the powerset of the given array.
+    # This is the set of all subsets of the array.
+    #
+    # @example
+    #   powerset([1, 2, 3]) #=>
+    #     Set[Set[], Set[1], Set[2], Set[3], Set[1, 2], Set[2, 3], Set[1, 3], Set[1, 2, 3]]
+    # @param arr [Enumerable]
+    # @return [Set<Set>] The subsets of `arr`
+    def powerset(arr)
+      arr.inject([Set.new].to_set) do |powerset, el|
+        new_powerset = Set.new
+        powerset.each do |subset|
+          new_powerset << subset
+          new_powerset << subset + [el]
+        end
+        new_powerset
+      end
+    end
+
+    # Restricts a number to falling within a given range.
+    # Returns the number if it falls within the range,
+    # or the closest value in the range if it doesn't.
+    #
+    # @param value [Numeric]
+    # @param range [Range<Numeric>]
+    # @return [Numeric]
+    def restrict(value, range)
+      [[value, range.first].max, range.last].min
+    end
+
+    # Concatenates all strings that are adjacent in an array,
+    # while leaving other elements as they are.
+    #
+    # @example
+    #   merge_adjacent_strings([1, "foo", "bar", 2, "baz"])
+    #     #=> [1, "foobar", 2, "baz"]
+    # @param arr [Array]
+    # @return [Array] The enumerable with strings merged
+    def merge_adjacent_strings(arr)
+      # Optimize for the common case of one element
+      return arr if arr.size < 2
+      arr.inject([]) do |a, e|
+        if e.is_a?(String)
+          if a.last.is_a?(String)
+            a.last << e
+          else
+            a << e.dup
+          end
+        else
+          a << e
+        end
+        a
+      end
+    end
+
+    # Intersperses a value in an enumerable, as would be done with `Array#join`
+    # but without concatenating the array together afterwards.
+    #
+    # @param enum [Enumerable]
+    # @param val
+    # @return [Array]
+    def intersperse(enum, val)
+      enum.inject([]) {|a, e| a << e << val}[0...-1]
+    end
+
+    # Substitutes a sub-array of one array with another sub-array.
+    #
+    # @param ary [Array] The array in which to make the substitution
+    # @param from [Array] The sequence of elements to replace with `to`
+    # @param to [Array] The sequence of elements to replace `from` with
+    def substitute(ary, from, to)
+      res = ary.dup
+      i = 0
+      while i < res.size
+        if res[i...i+from.size] == from
+          res[i...i+from.size] = to
+        end
+        i += 1
+      end
+      res
+    end
+
+    # Destructively strips whitespace from the beginning and end
+    # of the first and last elements, respectively,
+    # in the array (if those elements are strings).
+    #
+    # @param arr [Array]
+    # @return [Array] `arr`
+    def strip_string_array(arr)
+      arr.first.lstrip! if arr.first.is_a?(String)
+      arr.last.rstrip! if arr.last.is_a?(String)
+      arr
+    end
+
+    # Return an array of all possible paths through the given arrays.
+    #
+    # @param arrs [Array<Array>]
+    # @return [Array<Arrays>]
+    #
+    # @example
+    #   paths([[1, 2], [3, 4], [5]]) #=>
+    #     # [[1, 3, 5],
+    #     #  [2, 3, 5],
+    #     #  [1, 4, 5],
+    #     #  [2, 4, 5]]
+    def paths(arrs)
+      arrs.inject([[]]) do |paths, arr|
+        flatten(arr.map {|e| paths.map {|path| path + [e]}}, 1)
+      end
+    end
+
+    # Computes a single longest common subsequence for `x` and `y`.
+    # If there are more than one longest common subsequences,
+    # the one returned is that which starts first in `x`.
+    #
+    # @param x [Array]
+    # @param y [Array]
+    # @yield [a, b] An optional block to use in place of a check for equality
+    #   between elements of `x` and `y`.
+    # @yieldreturn [Object, nil] If the two values register as equal,
+    #   this will return the value to use in the LCS array.
+    # @return [Array] The LCS
+    def lcs(x, y, &block)
+      x = [nil, *x]
+      y = [nil, *y]
+      block ||= proc {|a, b| a == b && a}
+      lcs_backtrace(lcs_table(x, y, &block), x, y, x.size-1, y.size-1, &block)
+    end
+
+    # Converts a Hash to an Array. This is usually identical to `Hash#to_a`,
+    # with the following exceptions:
+    #
+    # * In Ruby 1.8, `Hash#to_a` is not deterministically ordered, but this is.
+    # * In Ruby 1.9 when running tests, this is ordered in the same way it would
+    #   be under Ruby 1.8 (sorted key order rather than insertion order).
+    #
+    # @param hash [Hash]
+    # @return [Array]
+    def hash_to_a(hash)
+      return hash.to_a unless ruby1_8? || defined?(Test::Unit)
+      return hash.sort_by {|k, v| k}
+    end
+
+    # Performs the equivalent of `enum.group_by.to_a`, but with a guaranteed
+    # order. Unlike [#hash_to_a], the resulting order isn't sorted key order;
+    # instead, it's the same order as `#group_by` has under Ruby 1.9 (key
+    # appearance order).
+    #
+    # @param enum [Enumerable]
+    # @return [Array<[Object, Array]>] An array of pairs.
+    def group_by_to_a(enum, &block)
+      return enum.group_by(&block).to_a unless ruby1_8?
+      order = {}
+      arr = []
+      enum.group_by do |e|
+        res = block[e]
+        unless order.include?(res)
+          order[res] = order.size
+        end
+        res
+      end.each do |key, vals|
+        arr[order[key]] = [key, vals]
+      end
+      arr
+    end
+
+    # Returns a sub-array of `minuend` containing only elements that are also in
+    # `subtrahend`. Ensures that the return value has the same order as
+    # `minuend`, even on Rubinius where that's not guaranteed by {Array#-}.
+    #
+    # @param minuend [Array]
+    # @param subtrahend [Array]
+    # @return [Array]
+    def array_minus(minuend, subtrahend)
+      return minuend - subtrahend unless rbx?
+      set = Set.new(minuend) - subtrahend
+      minuend.select {|e| set.include?(e)}
+    end
+
+    # Returns a string description of the character that caused an
+    # `Encoding::UndefinedConversionError`.
+    #
+    # @param [Encoding::UndefinedConversionError]
+    # @return [String]
+    def undefined_conversion_error_char(e)
+      # Rubinius (as of 2.0.0.rc1) pre-quotes the error character.
+      return e.error_char if rbx?
+      # JRuby (as of 1.7.2) doesn't have an error_char field on
+      # Encoding::UndefinedConversionError.
+      return e.error_char.dump unless jruby?
+      e.message[/^"[^"]+"/] #"
+    end
+
+    # Asserts that `value` falls within `range` (inclusive), leaving
+    # room for slight floating-point errors.
+    #
+    # @param name [String] The name of the value. Used in the error message.
+    # @param range [Range] The allowed range of values.
+    # @param value [Numeric, Sass::Script::Number] The value to check.
+    # @param unit [String] The unit of the value. Used in error reporting.
+    # @return [Numeric] `value` adjusted to fall within range, if it
+    #   was outside by a floating-point margin.
+    def check_range(name, range, value, unit='')
+      grace = (-0.00001..0.00001)
+      str = value.to_s
+      value = value.value if value.is_a?(Sass::Script::Number)
+      return value if range.include?(value)
+      return range.first if grace.include?(value - range.first)
+      return range.last if grace.include?(value - range.last)
+      raise ArgumentError.new(
+        "#{name} #{str} must be between #{range.first}#{unit} and #{range.last}#{unit}")
+    end
+
+    # Returns whether or not `seq1` is a subsequence of `seq2`. That is, whether
+    # or not `seq2` contains every element in `seq1` in the same order (and
+    # possibly more elements besides).
+    #
+    # @param seq1 [Array]
+    # @param seq2 [Array]
+    # @return [Boolean]
+    def subsequence?(seq1, seq2)
+      i = j = 0
+      loop do
+        return true if i == seq1.size
+        return false if j == seq2.size
+        i += 1 if seq1[i] == seq2[j]
+        j += 1
+      end
+    end
+
+    # Returns information about the caller of the previous method.
+    #
+    # @param entry [String] An entry in the `#caller` list, or a similarly formatted string
+    # @return [[String, Fixnum, (String, nil)]] An array containing the filename, line, and method name of 
the caller.
+    #   The method name may be nil
+    def caller_info(entry = nil)
+      # JRuby evaluates `caller` incorrectly when it's in an actual default argument.
+      entry ||= caller[1]
+      info = entry.scan(/^(.*?):(-?.*?)(?::.*`(.+)')?$/).first
+      info[1] = info[1].to_i
+      # This is added by Rubinius to designate a block, but we don't care about it.
+      info[2].sub!(/ \{\}\Z/, '') if info[2]
+      info
+    end
+
+    # Returns whether one version string represents a more recent version than another.
+    #
+    # @param v1 [String] A version string.
+    # @param v2 [String] Another version string.
+    # @return [Boolean]
+    def version_gt(v1, v2)
+      # Construct an array to make sure the shorter version is padded with nil
+      Array.new([v1.length, v2.length].max).zip(v1.split("."), v2.split(".")) do |_, p1, p2|
+        p1 ||= "0"
+        p2 ||= "0"
+        release1 = p1 =~ /^[0-9]+$/
+        release2 = p2 =~ /^[0-9]+$/
+        if release1 && release2
+          # Integer comparison if both are full releases
+          p1, p2 = p1.to_i, p2.to_i
+          next if p1 == p2
+          return p1 > p2
+        elsif !release1 && !release2
+          # String comparison if both are prereleases
+          next if p1 == p2
+          return p1 > p2
+        else
+          # If only one is a release, that one is newer
+          return release1
+        end
+      end
+    end
+
+    # Returns whether one version string represents the same or a more
+    # recent version than another.
+    #
+    # @param v1 [String] A version string.
+    # @param v2 [String] Another version string.
+    # @return [Boolean]
+    def version_geq(v1, v2)
+      version_gt(v1, v2) || !version_gt(v2, v1)
+    end
+
+    # Throws a NotImplementedError for an abstract method.
+    #
+    # @param obj [Object] `self`
+    # @raise [NotImplementedError]
+    def abstract(obj)
+      raise NotImplementedError.new("#{obj.class} must implement ##{caller_info[2]}")
+    end
+
+    # Silence all output to STDERR within a block.
+    #
+    # @yield A block in which no output will be printed to STDERR
+    def silence_warnings
+      the_real_stderr, $stderr = $stderr, StringIO.new
+      yield
+    ensure
+      $stderr = the_real_stderr
+    end
+
+    @@silence_warnings = false
+    # Silences all Sass warnings within a block.
+    #
+    # @yield A block in which no Sass warnings will be printed
+    def silence_sass_warnings
+      old_level, Sass.logger.log_level = Sass.logger.log_level, :error
+      yield
+    ensure
+      Sass.logger.log_level = old_level
+    end
+
+    # The same as `Kernel#warn`, but is silenced by \{#silence\_sass\_warnings}.
+    #
+    # @param msg [String]
+    def sass_warn(msg)
+      msg = msg + "\n" unless ruby1?
+      Sass.logger.warn(msg)
+    end
+
+    ## Cross Rails Version Compatibility
+
+    # Returns the root of the Rails application,
+    # if this is running in a Rails context.
+    # Returns `nil` if no such root is defined.
+    #
+    # @return [String, nil]
+    def rails_root
+      if defined?(::Rails.root)
+        return ::Rails.root.to_s if ::Rails.root
+        raise "ERROR: Rails.root is nil!"
+      end
+      return RAILS_ROOT.to_s if defined?(RAILS_ROOT)
+      return nil
+    end
+
+    # Returns the environment of the Rails application,
+    # if this is running in a Rails context.
+    # Returns `nil` if no such environment is defined.
+    #
+    # @return [String, nil]
+    def rails_env
+      return ::Rails.env.to_s if defined?(::Rails.env)
+      return RAILS_ENV.to_s if defined?(RAILS_ENV)
+      return nil
+    end
+
+    # Returns whether this environment is using ActionPack
+    # version 3.0.0 or greater.
+    #
+    # @return [Boolean]
+    def ap_geq_3?
+      ap_geq?("3.0.0.beta1")
+    end
+
+    # Returns whether this environment is using ActionPack
+    # of a version greater than or equal to that specified.
+    #
+    # @param version [String] The string version number to check against.
+    #   Should be greater than or equal to Rails 3,
+    #   because otherwise ActionPack::VERSION isn't autoloaded
+    # @return [Boolean]
+    def ap_geq?(version)
+      # The ActionPack module is always loaded automatically in Rails >= 3
+      return false unless defined?(ActionPack) && defined?(ActionPack::VERSION) &&
+        defined?(ActionPack::VERSION::STRING)
+
+      version_geq(ActionPack::VERSION::STRING, version)
+    end
+
+    # Returns an ActionView::Template* class.
+    # In pre-3.0 versions of Rails, most of these classes
+    # were of the form `ActionView::TemplateFoo`,
+    # while afterwards they were of the form `ActionView;:Template::Foo`.
+    #
+    # @param name [#to_s] The name of the class to get.
+    #   For example, `:Error` will return `ActionView::TemplateError`
+    #   or `ActionView::Template::Error`.
+    def av_template_class(name)
+      return ActionView.const_get("Template#{name}") if ActionView.const_defined?("Template#{name}")
+      return ActionView::Template.const_get(name.to_s)
+    end
+
+    ## Cross-OS Compatibility
+
+    # Whether or not this is running on Windows.
+    #
+    # @return [Boolean]
+    def windows?
+      RbConfig::CONFIG['host_os'] =~ /mswin|windows|mingw/i
+    end
+
+    # Whether or not this is running on IronRuby.
+    #
+    # @return [Boolean]
+    def ironruby?
+      RUBY_ENGINE == "ironruby"
+    end
+
+    # Whether or not this is running on Rubinius.
+    #
+    # @return [Boolean]
+    def rbx?
+      RUBY_ENGINE == "rbx"
+    end
+
+    # Whether or not this is running on JRuby.
+    #
+    # @return [Boolean]
+    def jruby?
+      RUBY_PLATFORM =~ /java/
+    end
+
+    # Returns an array of ints representing the JRuby version number.
+    #
+    # @return [Array<Fixnum>]
+    def jruby_version
+      $jruby_version ||= ::JRUBY_VERSION.split(".").map {|s| s.to_i}
+    end
+
+    # Like `Dir.glob`, but works with backslash-separated paths on Windows.
+    #
+    # @param path [String]
+    def glob(path, &block)
+      path = path.gsub('\\', '/') if windows?
+      Dir.glob(path, &block)
+    end
+
+    # Prepare a value for a destructuring assignment (e.g. `a, b =
+    # val`). This works around a performance bug when using
+    # ActiveSupport, and only needs to be called when `val` is likely
+    # to be `nil` reasonably often.
+    #
+    # See [this bug report](http://redmine.ruby-lang.org/issues/4917).
+    #
+    # @param val [Object]
+    # @return [Object]
+    def destructure(val)
+      val || []
+    end
+
+    ## Cross-Ruby-Version Compatibility
+
+    # Whether or not this is running under a Ruby version under 2.0.
+    #
+    # @return [Boolean]
+    def ruby1?
+      Sass::Util::RUBY_VERSION[0] <= 1
+    end
+
+    # Whether or not this is running under Ruby 1.8 or lower.
+    #
+    # Note that IronRuby counts as Ruby 1.8,
+    # because it doesn't support the Ruby 1.9 encoding API.
+    #
+    # @return [Boolean]
+    def ruby1_8?
+      # IronRuby says its version is 1.9, but doesn't support any of the encoding APIs.
+      # We have to fall back to 1.8 behavior.
+      ironruby? || (Sass::Util::RUBY_VERSION[0] == 1 && Sass::Util::RUBY_VERSION[1] < 9)
+    end
+
+    # Whether or not this is running under Ruby 1.8.6 or lower.
+    # Note that lower versions are not officially supported.
+    #
+    # @return [Boolean]
+    def ruby1_8_6?
+      ruby1_8? && Sass::Util::RUBY_VERSION[2] < 7
+    end
+
+    # Wehter or not this is running under JRuby 1.6 or lower.
+    def jruby1_6?
+      jruby? && jruby_version[0] == 1 && jruby_version[1] < 7
+    end
+
+    # Whether or not this is running under MacRuby.
+    #
+    # @return [Boolean]
+    def macruby?
+      RUBY_ENGINE == 'macruby'
+    end
+
+    # Checks that the encoding of a string is valid in Ruby 1.9
+    # and cleans up potential encoding gotchas like the UTF-8 BOM.
+    # If it's not, yields an error string describing the invalid character
+    # and the line on which it occurrs.
+    #
+    # @param str [String] The string of which to check the encoding
+    # @yield [msg] A block in which an encoding error can be raised.
+    #   Only yields if there is an encoding error
+    # @yieldparam msg [String] The error message to be raised
+    # @return [String] `str`, potentially with encoding gotchas like BOMs removed
+    def check_encoding(str)
+      if ruby1_8?
+        return str.gsub(/\A\xEF\xBB\xBF/, '') # Get rid of the UTF-8 BOM
+      elsif str.valid_encoding?
+        # Get rid of the Unicode BOM if possible
+        if str.encoding.name =~ /^UTF-(8|16|32)(BE|LE)?$/
+          return str.gsub(Regexp.new("\\A\uFEFF".encode(str.encoding.name)), '')
+        else
+          return str
+        end
+      end
+
+      encoding = str.encoding
+      newlines = Regexp.new("\r\n|\r|\n".encode(encoding).force_encoding("binary"))
+      str.force_encoding("binary").split(newlines).each_with_index do |line, i|
+        begin
+          line.encode(encoding)
+        rescue Encoding::UndefinedConversionError => e
+          yield <<MSG.rstrip, i + 1
+Invalid #{encoding.name} character #{undefined_conversion_error_char(e)}
+MSG
+        end
+      end
+      return str
+    end
+
+    # Like {\#check\_encoding}, but also checks for a ` charset` declaration
+    # at the beginning of the file and uses that encoding if it exists.
+    #
+    # The Sass encoding rules are simple.
+    # If a ` charset` declaration exists,
+    # we assume that that's the original encoding of the document.
+    # Otherwise, we use whatever encoding Ruby has.
+    # Then we convert that to UTF-8 to process internally.
+    # The UTF-8 end result is what's returned by this method.
+    #
+    # @param str [String] The string of which to check the encoding
+    # @yield [msg] A block in which an encoding error can be raised.
+    #   Only yields if there is an encoding error
+    # @yieldparam msg [String] The error message to be raised
+    # @return [(String, Encoding)] The original string encoded as UTF-8,
+    #   and the source encoding of the string (or `nil` under Ruby 1.8)
+    # @raise [Encoding::UndefinedConversionError] if the source encoding
+    #   cannot be converted to UTF-8
+    # @raise [ArgumentError] if the document uses an unknown encoding with ` charset`
+    def check_sass_encoding(str, &block)
+      return check_encoding(str, &block), nil if ruby1_8?
+      # We allow any printable ASCII characters but double quotes in the charset decl
+      bin = str.dup.force_encoding("BINARY")
+      encoding = Sass::Util::ENCODINGS_TO_CHECK.find do |enc|
+        re = Sass::Util::CHARSET_REGEXPS[enc]
+        re && bin =~ re
+      end
+      charset, bom = $1, $2
+      if charset
+        charset = charset.force_encoding(encoding).encode("UTF-8")
+        if endianness = encoding[/[BL]E$/]
+          begin
+            Encoding.find(charset + endianness)
+            charset << endianness
+          rescue ArgumentError # Encoding charset + endianness doesn't exist
+          end
+        end
+        str.force_encoding(charset)
+      elsif bom
+        str.force_encoding(encoding)
+      end
+
+      str = check_encoding(str, &block)
+      return str.encode("UTF-8"), str.encoding
+    end
+
+    unless ruby1_8?
+      # @private
+      def _enc(string, encoding)
+        string.encode(encoding).force_encoding("BINARY")
+      end
+
+      # We could automatically add in any non-ASCII-compatible encodings here,
+      # but there's not really a good way to do that
+      # without manually checking that each encoding
+      # encodes all ASCII characters properly,
+      # which takes long enough to affect the startup time of the CLI.
+      ENCODINGS_TO_CHECK = %w[UTF-8 UTF-16BE UTF-16LE UTF-32BE UTF-32LE]
+
+      CHARSET_REGEXPS = Hash.new do |h, e|
+        h[e] =
+          begin
+            # /\A(?:\uFEFF)? charset "(.*?)"|\A(\uFEFF)/
+            Regexp.new(/\A(?:#{_enc("\uFEFF", e)})?#{
+              _enc('@charset "', e)}(.*?)#{_enc('"', e)}|\A(#{
+              _enc("\uFEFF", e)})/)
+          rescue Encoding::ConverterNotFoundError => _
+            nil # JRuby on Java 5 doesn't support UTF-32
+          rescue
+            # /\A charset "(.*?)"/
+            Regexp.new(/\A#{_enc('@charset "', e)}(.*?)#{_enc('"', e)}/)
+          end
+      end
+    end
+
+    # Checks to see if a class has a given method.
+    # For example:
+    #
+    #     Sass::Util.has?(:public_instance_method, String, :gsub) #=> true
+    #
+    # Method collections like `Class#instance_methods`
+    # return strings in Ruby 1.8 and symbols in Ruby 1.9 and on,
+    # so this handles checking for them in a compatible way.
+    #
+    # @param attr [#to_s] The (singular) name of the method-collection method
+    #   (e.g. `:instance_methods`, `:private_methods`)
+    # @param klass [Module] The class to check the methods of which to check
+    # @param method [String, Symbol] The name of the method do check for
+    # @return [Boolean] Whether or not the given collection has the given method
+    def has?(attr, klass, method)
+      klass.send("#{attr}s").include?(ruby1_8? ? method.to_s : method.to_sym)
+    end
+
+    # A version of `Enumerable#enum_with_index` that works in Ruby 1.8 and 1.9.
+    #
+    # @param enum [Enumerable] The enumerable to get the enumerator for
+    # @return [Enumerator] The with-index enumerator
+    def enum_with_index(enum)
+      ruby1_8? ? enum.enum_with_index : enum.each_with_index
+    end
+
+    # A version of `Enumerable#enum_cons` that works in Ruby 1.8 and 1.9.
+    #
+    # @param enum [Enumerable] The enumerable to get the enumerator for
+    # @param n [Fixnum] The size of each cons
+    # @return [Enumerator] The consed enumerator
+    def enum_cons(enum, n)
+      ruby1_8? ? enum.enum_cons(n) : enum.each_cons(n)
+    end
+
+    # A version of `Enumerable#enum_slice` that works in Ruby 1.8 and 1.9.
+    #
+    # @param enum [Enumerable] The enumerable to get the enumerator for
+    # @param n [Fixnum] The size of each slice
+    # @return [Enumerator] The consed enumerator
+    def enum_slice(enum, n)
+      ruby1_8? ? enum.enum_slice(n) : enum.each_slice(n)
+    end
+
+    # Destructively removes all elements from an array that match a block, and
+    # returns the removed elements.
+    #
+    # @param array [Array] The array from which to remove elements.
+    # @yield [el] Called for each element.
+    # @yieldparam el [*] The element to test.
+    # @yieldreturn [Boolean] Whether or not to extract the element.
+    # @return [Array] The extracted elements.
+    def extract!(array)
+      out = []
+      array.reject! do |e|
+        next false unless yield e
+        out << e
+        true
+      end
+      out
+    end
+
+    # Returns the ASCII code of the given character.
+    #
+    # @param c [String] All characters but the first are ignored.
+    # @return [Fixnum] The ASCII code of `c`.
+    def ord(c)
+      ruby1_8? ? c[0] : c.ord
+    end
+
+    # Flattens the first `n` nested arrays in a cross-version manner.
+    #
+    # @param arr [Array] The array to flatten
+    # @param n [Fixnum] The number of levels to flatten
+    # @return [Array] The flattened array
+    def flatten(arr, n)
+      return arr.flatten(n) unless ruby1_8_6?
+      return arr if n == 0
+      arr.inject([]) {|res, e| e.is_a?(Array) ? res.concat(flatten(e, n - 1)) : res << e}
+    end
+
+    # Returns the hash code for a set in a cross-version manner.
+    # Aggravatingly, this is order-dependent in Ruby 1.8.6.
+    #
+    # @param set [Set]
+    # @return [Fixnum] The order-independent hashcode of `set`
+    def set_hash(set)
+      return set.hash unless ruby1_8_6?
+      set.map {|e| e.hash}.uniq.sort.hash
+    end
+
+    # Tests the hash-equality of two sets in a cross-version manner.
+    # Aggravatingly, this is order-dependent in Ruby 1.8.6.
+    #
+    # @param set1 [Set]
+    # @param set2 [Set]
+    # @return [Boolean] Whether or not the sets are hashcode equal
+    def set_eql?(set1, set2)
+      return set1.eql?(set2) unless ruby1_8_6?
+      set1.to_a.uniq.sort_by {|e| e.hash}.eql?(set2.to_a.uniq.sort_by {|e| e.hash})
+    end
+
+    # Like `Object#inspect`, but preserves non-ASCII characters rather than escaping them under Ruby 1.9.2.
+    # This is necessary so that the precompiled Haml template can be `#encode`d into ` options[:encoding]`
+    # before being evaluated.
+    #
+    # @param obj {Object}
+    # @return {String}
+    def inspect_obj(obj)
+      return obj.inspect unless version_geq(::RUBY_VERSION, "1.9.2")
+      return ':' + inspect_obj(obj.to_s) if obj.is_a?(Symbol)
+      return obj.inspect unless obj.is_a?(String)
+      '"' + obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]} + '"'
+    end
+
+    # Extracts the non-string vlaues from an array containing both strings and non-strings.
+    # These values are replaced with escape sequences.
+    # This can be undone using \{#inject\_values}.
+    #
+    # This is useful e.g. when we want to do string manipulation
+    # on an interpolated string.
+    #
+    # The precise format of the resulting string is not guaranteed.
+    # However, it is guaranteed that newlines and whitespace won't be affected.
+    #
+    # @param arr [Array] The array from which values are extracted.
+    # @return [(String, Array)] The resulting string, and an array of extracted values.
+    def extract_values(arr)
+      values = []
+      return arr.map do |e|
+        next e.gsub('{', '{{') if e.is_a?(String)
+        values << e
+        next "{#{values.count - 1}}"
+      end.join, values
+    end
+
+    # Undoes \{#extract\_values} by transforming a string with escape sequences
+    # into an array of strings and non-string values.
+    #
+    # @param str [String] The string with escape sequences.
+    # @param values [Array] The array of values to inject.
+    # @return [Array] The array of strings and values.
+    def inject_values(str, values)
+      return [str.gsub('{{', '{')] if values.empty?
+      # Add an extra { so that we process the tail end of the string
+      result = (str + '{{').scan(/(.*?)(?:(\{\{)|\{(\d+)\})/m).map do |(pre, esc, n)|
+        [pre, esc ? '{' : '', n ? values[n.to_i] : '']
+      end.flatten(1)
+      result[-2] = '' # Get rid of the extra {
+      merge_adjacent_strings(result).reject {|s| s == ''}
+    end
+
+    # Allows modifications to be performed on the string form
+    # of an array containing both strings and non-strings.
+    #
+    # @param arr [Array] The array from which values are extracted.
+    # @yield [str] A block in which string manipulation can be done to the array.
+    # @yieldparam str [String] The string form of `arr`.
+    # @yieldreturn [String] The modified string.
+    # @return [Array] The modified, interpolated array.
+    def with_extracted_values(arr)
+      str, vals = extract_values(arr)
+      str = yield str
+      inject_values(str, vals)
+    end
+
+    ## Static Method Stuff
+
+    # The context in which the ERB for \{#def\_static\_method} will be run.
+    class StaticConditionalContext
+      # @param set [#include?] The set of variables that are defined for this context.
+      def initialize(set)
+        @set = set
+      end
+
+      # Checks whether or not a variable is defined for this context.
+      #
+      # @param name [Symbol] The name of the variable
+      # @return [Boolean]
+      def method_missing(name, *args, &block)
+        super unless args.empty? && block.nil?
+        @set.include?(name)
+      end
+    end
+
+    # This creates a temp file and yields it for writing. When the
+    # write is complete, the file is moved into the desired location.
+    # The atomicity of this operation is provided by the filesystem's
+    # rename operation.
+    #
+    # @param filename [String] The file to write to.
+    # @yieldparam tmpfile [Tempfile] The temp file that can be written to.
+    # @return The value returned by the block.
+    def atomic_create_and_write_file(filename)
+      require 'tempfile'
+      tmpfile = Tempfile.new(File.basename(filename), File.dirname(filename))
+      tmp_path = tmpfile.path
+      tmpfile.binmode if tmpfile.respond_to?(:binmode)
+      result = yield tmpfile
+      File.rename tmpfile.path, filename
+      result
+    ensure
+      # close and remove the tempfile if it still exists,
+      # presumably due to an error during write
+      tmpfile.close if tmpfile
+      tmpfile.unlink if tmpfile
+    end
+
+    private
+
+    # Calculates the memoization table for the Least Common Subsequence algorithm.
+    # Algorithm from 
[Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Computing_the_length_of_the_LCS)
+    def lcs_table(x, y)
+      c = Array.new(x.size) {[]}
+      x.size.times {|i| c[i][0] = 0}
+      y.size.times {|j| c[0][j] = 0}
+      (1...x.size).each do |i|
+        (1...y.size).each do |j|
+          c[i][j] =
+            if yield x[i], y[j]
+              c[i-1][j-1] + 1
+            else
+              [c[i][j-1], c[i-1][j]].max
+            end
+        end
+      end
+      return c
+    end
+
+    # Computes a single longest common subsequence for arrays x and y.
+    # Algorithm from 
[Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS)
+    def lcs_backtrace(c, x, y, i, j, &block)
+      return [] if i == 0 || j == 0
+      if v = yield(x[i], y[j])
+        return lcs_backtrace(c, x, y, i-1, j-1, &block) << v
+      end
+
+      return lcs_backtrace(c, x, y, i, j-1, &block) if c[i][j-1] > c[i-1][j]
+      return lcs_backtrace(c, x, y, i-1, j, &block)
+    end
+  end
+end
+
+require 'sass/util/multibyte_string_scanner'
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/util/multibyte_string_scanner.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/util/multibyte_string_scanner.rb
new file mode 100644
index 0000000..7938f6c
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/util/multibyte_string_scanner.rb
@@ -0,0 +1,155 @@
+require 'strscan'
+
+if Sass::Util.ruby1_8?
+  Sass::Util::MultibyteStringScanner = StringScanner
+else
+  if Sass::Util.rbx?
+    # Rubinius's StringScanner class implements some of its methods in terms of
+    # others, which causes us to double-count bytes in some cases if we do
+    # straightforward inheritance. To work around this, we use a delegate class.
+    require 'delegate'
+    class Sass::Util::MultibyteStringScanner < DelegateClass(StringScanner)
+      def initialize(str)
+        super(StringScanner.new(str))
+        @mb_pos = 0
+        @mb_matched_size = nil
+        @mb_last_pos = nil
+      end
+
+      def is_a?(klass)
+        __getobj__.is_a?(klass) || super
+      end
+    end
+  else
+    class Sass::Util::MultibyteStringScanner < StringScanner
+      def initialize(str)
+        super
+        @mb_pos = 0
+        @mb_matched_size = nil
+        @mb_last_pos = nil
+      end
+    end
+  end
+
+  # A wrapper of the native StringScanner class that works correctly with
+  # multibyte character encodings. The native class deals only in bytes, not
+  # characters, for methods like [#pos] and [#matched_size]. This class deals
+  # only in characters, instead.
+  class Sass::Util::MultibyteStringScanner
+    def self.new(str)
+      return StringScanner.new(str) if str.ascii_only?
+      super
+    end
+
+    alias_method :byte_pos, :pos
+    alias_method :byte_matched_size, :matched_size
+
+    def check(pattern); _match super; end
+    def check_until(pattern); _matched super; end
+    def getch; _forward _match super; end
+    def match?(pattern); _size check(pattern); end
+    def matched_size; @mb_matched_size; end
+    def peek(len); string[ mb_pos, len]; end
+    alias_method :peep, :peek
+    def pos; @mb_pos; end
+    alias_method :pointer, :pos
+    def rest_size; rest.size; end
+    def scan(pattern); _forward _match super; end
+    def scan_until(pattern); _forward _matched super; end
+    def skip(pattern); _size scan(pattern); end
+    def skip_until(pattern); _matched _size scan_until(pattern); end
+
+    def get_byte
+      raise "MultibyteStringScanner doesn't support #get_byte."
+    end
+
+    def getbyte
+      raise "MultibyteStringScanner doesn't support #getbyte."
+    end
+
+    def pos=(n)
+      @mb_last_pos = nil
+
+      # We set position kind of a lot during parsing, so we want it to be as
+      # efficient as possible. This is complicated by the fact that UTF-8 is a
+      # variable-length encoding, so it's difficult to find the byte length that
+      # corresponds to a given character length.
+      #
+      # Our heuristic here is to try to count the fewest possible characters. So
+      # if the new position is close to the current one, just count the
+      # characters between the two; if the new position is closer to the
+      # beginning of the string, just count the characters from there.
+      if @mb_pos - n < @mb_pos / 2
+        # New position is close to old position
+        byte_delta = @mb_pos > n ? -string[n    mb_pos] bytesize : string[ mb_pos   n] bytesize
+        super(byte_pos + byte_delta)
+      else
+        # New position is close to BOS
+        super(string[0...n].bytesize)
+      end
+      @mb_pos = n
+    end
+
+    def reset
+      @mb_pos = 0
+      @mb_matched_size = nil
+      @mb_last_pos = nil
+      super
+    end
+
+    def scan_full(pattern, advance_pointer_p, return_string_p)
+      res = _match super(pattern, advance_pointer_p, true)
+      _forward res if advance_pointer_p
+      return res if return_string_p
+    end
+
+    def search_full(pattern, advance_pointer_p, return_string_p)
+      res = super(pattern, advance_pointer_p, true)
+      _forward res if advance_pointer_p
+      _matched((res if return_string_p))
+    end
+
+    def string=(str)
+      @mb_pos = 0
+      @mb_matched_size = nil
+      @mb_last_pos = nil
+      super
+    end
+
+    def terminate
+      @mb_pos = string.size
+      @mb_matched_size = nil
+      @mb_last_pos = nil
+      super
+    end
+    alias_method :clear, :terminate
+
+    def unscan
+      super
+      @mb_pos = @mb_last_pos
+      @mb_last_pos = @mb_matched_size = nil
+    end
+
+    private
+
+    def _size(str)
+      str && str.size
+    end
+
+    def _match(str)
+      @mb_matched_size = str && str.size
+      str
+    end
+
+    def _matched(res)
+      _match matched
+      res
+    end
+
+    def _forward(str)
+      @mb_last_pos = @mb_pos
+      @mb_pos += str.size if str
+      str
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/util/subset_map.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/util/subset_map.rb
new file mode 100644
index 0000000..b8076f5
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/util/subset_map.rb
@@ -0,0 +1,109 @@
+require 'set'
+
+module Sass
+  module Util
+    # A map from sets to values.
+    # A value is \{#\[]= set} by providing a set (the "set-set") and a value,
+    # which is then recorded as corresponding to that set.
+    # Values are \{#\[] accessed} by providing a set (the "get-set")
+    # and returning all values that correspond to set-sets
+    # that are subsets of the get-set.
+    #
+    # SubsetMap preserves the order of values as they're inserted.
+    #
+    # @example
+    #   ssm = SubsetMap.new
+    #   ssm[Set[1, 2]] = "Foo"
+    #   ssm[Set[2, 3]] = "Bar"
+    #   ssm[Set[1, 2, 3]] = "Baz"
+    #
+    #   ssm[Set[1, 2, 3]] #=> ["Foo", "Bar", "Baz"]
+    class SubsetMap
+      # Creates a new, empty SubsetMap.
+      def initialize
+        @hash = {}
+        @vals = []
+      end
+
+      # Whether or not this SubsetMap has any key-value pairs.
+      #
+      # @return [Boolean]
+      def empty?
+        @hash.empty?
+      end
+
+      # Associates a value with a set.
+      # When `set` or any of its supersets is accessed,
+      # `value` will be among the values returned.
+      #
+      # Note that if the same `set` is passed to this method multiple times,
+      # all given `value`s will be associated with that `set`.
+      #
+      # This runs in `O(n)` time, where `n` is the size of `set`.
+      #
+      # @param set [#to_set] The set to use as the map key. May not be empty.
+      # @param value [Object] The value to associate with `set`.
+      # @raise [ArgumentError] If `set` is empty.
+      def []=(set, value)
+        raise ArgumentError.new("SubsetMap keys may not be empty.") if set.empty?
+
+        index = @vals.size
+        @vals << value
+        set.each do |k|
+          @hash[k] ||= []
+          @hash[k] << [set, set.to_set, index]
+        end
+      end
+
+      # Returns all values associated with subsets of `set`.
+      #
+      # In the worst case, this runs in `O(m*max(n, log m))` time,
+      # where `n` is the size of `set`
+      # and `m` is the number of assocations in the map.
+      # However, unless many keys in the map overlap with `set`,
+      # `m` will typically be much smaller.
+      #
+      # @param set [Set] The set to use as the map key.
+      # @return [Array<(Object, #to_set)>] An array of pairs,
+      #   where the first value is the value associated with a subset of `set`,
+      #   and the second value is that subset of `set`
+      #   (or whatever `#to_set` object was used to set the value)
+      #   This array is in insertion order.
+      # @see #[]
+      def get(set)
+        res = set.map do |k|
+          next unless subsets = @hash[k]
+          subsets.map do |subenum, subset, index|
+            next unless subset.subset?(set)
+            [index, subenum]
+          end
+        end
+        res = Sass::Util.flatten(res, 1)
+        res.compact!
+        res.uniq!
+        res.sort!
+        res.map! {|i, s| [ vals[i], s]}
+        return res
+      end
+
+      # Same as \{#get}, but doesn't return the subsets of the argument
+      # for which values were found.
+      #
+      # @param set [Set] The set to use as the map key.
+      # @return [Array] The array of all values
+      #   associated with subsets of `set`, in insertion order.
+      # @see #get
+      def [](set)
+        get(set).map {|v, _| v}
+      end
+
+      # Iterates over each value in the subset map. Ignores keys completely. If
+      # multiple keys have the same value, this will return them multiple times.
+      #
+      # @yield [Object] Each value in the map.
+      def each_value
+        @vals.each {|v| yield v}
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/util/test.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/util/test.rb
new file mode 100644
index 0000000..b97842a
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/util/test.rb
@@ -0,0 +1,10 @@
+module Sass
+  module Util
+    module Test
+      def skip(msg = nil, bt = caller)
+        super if defined?(super)
+        return
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/lib/sass/version.rb 
b/backends/css/gems/sass-3.2.12/lib/sass/version.rb
new file mode 100644
index 0000000..4dcd587
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/lib/sass/version.rb
@@ -0,0 +1,126 @@
+require 'date'
+
+# This is necessary for loading Sass when Haml is required in Rails 3.
+# Once the split is complete, we can remove it.
+require File.dirname(__FILE__) + '/../sass'
+require 'sass/util'
+
+module Sass
+  # Handles Sass version-reporting.
+  # Sass not only reports the standard three version numbers,
+  # but its Git revision hash as well,
+  # if it was installed from Git.
+  module Version
+    include Sass::Util
+
+    # Returns a hash representing the version of Sass.
+    # The `:major`, `:minor`, and `:teeny` keys have their respective numbers as Fixnums.
+    # The `:name` key has the name of the version.
+    # The `:string` key contains a human-readable string representation of the version.
+    # The `:number` key is the major, minor, and teeny keys separated by periods.
+    # The `:date` key, which is not guaranteed to be defined, is the [DateTime] at which this release was 
cut.
+    # If Sass is checked out from Git, the `:rev` key will have the revision hash.
+    # For example:
+    #
+    #     {
+    #       :string => "2.1.0.9616393",
+    #       :rev    => "9616393b8924ef36639c7e82aa88a51a24d16949",
+    #       :number => "2.1.0",
+    #       :date   => DateTime.parse("Apr 30 13:52:01 2009 -0700"),
+    #       :major  => 2, :minor => 1, :teeny => 0
+    #     }
+    #
+    # If a prerelease version of Sass is being used,
+    # the `:string` and `:number` fields will reflect the full version
+    # (e.g. `"2.2.beta.1"`), and the `:teeny` field will be `-1`.
+    # A `:prerelease` key will contain the name of the prerelease (e.g. `"beta"`),
+    # and a `:prerelease_number` key will contain the rerelease number.
+    # For example:
+    #
+    #     {
+    #       :string => "3.0.beta.1",
+    #       :number => "3.0.beta.1",
+    #       :date   => DateTime.parse("Mar 31 00:38:04 2010 -0700"),
+    #       :major => 3, :minor => 0, :teeny => -1,
+    #       :prerelease => "beta",
+    #       :prerelease_number => 1
+    #     }
+    #
+    # @return [{Symbol => String/Fixnum}] The version hash
+    def version
+      return @@version if defined?(@@version)
+
+      numbers = File.read(scope('VERSION')).strip.split('.').
+        map {|n| n =~ /^[0-9]+$/ ? n.to_i : n}
+      name = File.read(scope('VERSION_NAME')).strip
+      @@version = {
+        :major => numbers[0],
+        :minor => numbers[1],
+        :teeny => numbers[2],
+        :name => name
+      }
+
+      if date = version_date
+        @@version[:date] = date
+      end
+
+      if numbers[3].is_a?(String)
+        @@version[:teeny] = -1
+        @@version[:prerelease] = numbers[3]
+        @@version[:prerelease_number] = numbers[4]
+      end
+
+      @@version[:number] = numbers.join('.')
+      @@version[:string] = @@version[:number].dup
+
+      if rev = revision_number
+        @@version[:rev] = rev
+        unless rev[0] == ?(
+          @@version[:string] << "." << rev[0...7]
+        end
+      end
+
+      @@version[:string] << " (#{name})"
+      @@version
+    end
+
+    private
+
+    def revision_number
+      if File.exists?(scope('REVISION'))
+        rev = File.read(scope('REVISION')).strip
+        return rev unless rev =~ /^([a-f0-9]+|\(.*\))$/ || rev == '(unknown)'
+      end
+
+      return unless File.exists?(scope('.git/HEAD'))
+      rev = File.read(scope('.git/HEAD')).strip
+      return rev unless rev =~ /^ref: (.*)$/
+
+      ref_name = $1
+      ref_file = scope(".git/#{ref_name}")
+      info_file = scope(".git/info/refs")
+      return File.read(ref_file).strip if File.exists?(ref_file)
+      return unless File.exists?(info_file)
+      File.open(info_file) do |f|
+        f.each do |l|
+          sha, ref = l.strip.split("\t", 2)
+          next unless ref == ref_name
+          return sha
+        end
+      end
+      return nil
+    end
+
+    def version_date
+      return unless File.exists?(scope('VERSION_DATE'))
+      return DateTime.parse(File.read(scope('VERSION_DATE')).strip)
+    end
+  end
+
+  extend Sass::Version
+
+  # A string representing the version of Sass.
+  # A more fine-grained representation is available from Sass.version.
+  # @api public
+  VERSION = version[:string] unless defined?(Sass::VERSION)
+end
diff --git a/backends/css/gems/sass-3.2.12/rails/init.rb b/backends/css/gems/sass-3.2.12/rails/init.rb
new file mode 100644
index 0000000..13d5baa
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/rails/init.rb
@@ -0,0 +1 @@
+Kernel.load File.join(File.dirname(__FILE__), '..', 'init.rb')
diff --git a/backends/css/gems/sass-3.2.12/test/Gemfile b/backends/css/gems/sass-3.2.12/test/Gemfile
new file mode 100644
index 0000000..eff8805
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/Gemfile
@@ -0,0 +1,3 @@
+source :gemcutter
+
+gem 'rake'
diff --git a/backends/css/gems/sass-3.2.12/test/Gemfile.lock b/backends/css/gems/sass-3.2.12/test/Gemfile.lock
new file mode 100644
index 0000000..ef36ebe
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/Gemfile.lock
@@ -0,0 +1,10 @@
+GEM
+  remote: http://rubygems.org/
+  specs:
+    rake (0.9.2)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  rake
diff --git a/backends/css/gems/sass-3.2.12/test/sass/cache_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/cache_test.rb
new file mode 100755
index 0000000..11cee69
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/cache_test.rb
@@ -0,0 +1,89 @@
+#!/usr/bin/env ruby
+require File.dirname(__FILE__) + '/../test_helper'
+require File.dirname(__FILE__) + '/test_helper'
+require 'sass/engine'
+
+class CacheTest < Test::Unit::TestCase
+  @@cache_dir = "tmp/file_cache"
+
+  def setup
+    FileUtils.mkdir_p @@cache_dir
+  end
+
+  def teardown
+    FileUtils.rm_rf @@cache_dir
+    clean_up_sassc
+  end
+
+  def test_file_cache_writes_a_file
+    file_store = Sass::CacheStores::Filesystem.new(@@cache_dir)
+    file_store.store("asdf/foo.scssc", "fakesha1", root_node)
+    assert File.exists?("#{@@cache_dir}/asdf/foo.scssc")
+  end
+
+  def test_file_cache_reads_a_file
+    file_store = Sass::CacheStores::Filesystem.new(@@cache_dir)
+    assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc")
+    file_store.store("asdf/foo.scssc", "fakesha1", root_node)
+    assert File.exists?("#{@@cache_dir}/asdf/foo.scssc")
+    assert_kind_of Sass::Tree::RootNode, file_store.retrieve("asdf/foo.scssc", "fakesha1")
+  end
+
+  def test_file_cache_miss_returns_nil
+    file_store = Sass::CacheStores::Filesystem.new(@@cache_dir)
+    assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc")
+    assert_nil file_store.retrieve("asdf/foo.scssc", "fakesha1")
+  end
+
+  def test_sha_change_invalidates_cache_and_cleans_up
+    file_store = Sass::CacheStores::Filesystem.new(@@cache_dir)
+    assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc")
+    file_store.store("asdf/foo.scssc", "fakesha1", root_node)
+    assert File.exists?("#{@@cache_dir}/asdf/foo.scssc")
+    assert_nil file_store.retrieve("asdf/foo.scssc", "differentsha1")
+    assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc")
+  end
+
+  def test_version_change_invalidates_cache_and_cleans_up
+    file_store = Sass::CacheStores::Filesystem.new(@@cache_dir)
+    assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc")
+    file_store.store("asdf/foo.scssc", "fakesha1", root_node)
+    assert File.exists?("#{@@cache_dir}/asdf/foo.scssc")
+    real_version = Sass::VERSION
+    begin
+      Sass::VERSION.replace("a different version")
+      assert_nil file_store.retrieve("asdf/foo.scssc", "fakesha1")
+      assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc")
+    ensure
+      Sass::VERSION.replace(real_version)
+    end
+  end
+
+  def test_arbitrary_objects_can_go_into_cache
+    cache = Sass::CacheStores::Memory.new
+    an_object = {:foo => :bar}
+    cache.store("an_object", "", an_object)
+    assert_equal an_object, cache.retrieve("an_object", "")
+  end
+
+  class Unmarshalable
+    def _dump(_)
+      raise 'Unmarshalable'
+    end
+  end
+
+  def test_cache_node_with_unmarshalable_option
+    engine = Sass::Engine.new("foo {a: b + c}",
+      :syntax => :scss, :object => Unmarshalable.new, :filename => 'file.scss',
+      :importer => Sass::Importers::Filesystem.new(absolutize('templates')))
+    engine.to_tree
+  end
+
+  private
+  def root_node
+    Sass::Engine.new(<<-SCSS, :syntax => :scss).to_tree
+      @mixin color($c) { color: $c}
+      div { @include color(red); }
+    SCSS
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/callbacks_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/callbacks_test.rb
new file mode 100755
index 0000000..b0a2081
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/callbacks_test.rb
@@ -0,0 +1,61 @@
+#!/usr/bin/env ruby
+require File.dirname(__FILE__) + '/../test_helper'
+require 'sass/callbacks'
+
+class CallerBack
+  extend Sass::Callbacks
+  define_callback :foo
+  define_callback :bar
+
+  def do_foo
+    run_foo
+  end
+
+  def do_bar
+    run_bar 12
+  end
+end
+
+module ClassLevelCallerBack
+  extend Sass::Callbacks
+  define_callback :foo
+  extend self
+
+  def do_foo
+    run_foo
+  end
+end
+
+class SassCallbacksTest < Test::Unit::TestCase
+  def test_simple_callback
+    cb = CallerBack.new
+    there = false
+    cb.on_foo {there = true}
+    cb.do_foo
+    assert there, "Expected callback to be called."
+  end
+
+  def test_multiple_callbacks
+    cb = CallerBack.new
+    str = ""
+    cb.on_foo {str += "first"}
+    cb.on_foo {str += " second"}
+    cb.do_foo
+    assert_equal "first second", str
+  end
+
+  def test_callback_with_arg
+    cb = CallerBack.new
+    val = nil
+    cb.on_bar {|a| val = a}
+    cb.do_bar
+    assert_equal 12, val
+  end
+
+  def test_class_level_callback
+    there = false
+    ClassLevelCallerBack.on_foo {there = true}
+    ClassLevelCallerBack.do_foo
+    assert there, "Expected callback to be called."
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/conversion_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/conversion_test.rb
new file mode 100755
index 0000000..c14a565
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/conversion_test.rb
@@ -0,0 +1,1760 @@
+#!/usr/bin/env ruby
+require File.dirname(__FILE__) + '/../test_helper'
+
+class ConversionTest < Test::Unit::TestCase
+  def test_basic
+    assert_renders <<SASS, <<SCSS
+foo bar
+  baz: bang
+  bip: bop
+SASS
+foo bar {
+  baz: bang;
+  bip: bop;
+}
+SCSS
+    assert_renders <<SASS, <<SCSS, :old => true
+foo bar
+  :baz bang
+  :bip bop
+SASS
+foo bar {
+  baz: bang;
+  bip: bop;
+}
+SCSS
+  end
+
+  def test_empty_selector
+    assert_renders "foo bar", "foo bar {}"
+  end
+
+  def test_empty_directive
+    assert_scss_to_sass "@media screen", "@media screen {}"
+    assert_scss_to_scss "@media screen {}"
+  end
+
+  def test_empty_control_directive
+    assert_renders "@if false", "@if false {}"
+  end
+
+  def test_nesting
+    assert_renders <<SASS, <<SCSS
+foo bar
+  baz bang
+    baz: bang
+    bip: bop
+  blat: boo
+SASS
+foo bar {
+  baz bang {
+    baz: bang;
+    bip: bop;
+  }
+  blat: boo;
+}
+SCSS
+  end
+
+  def test_nesting_with_parent_ref
+    assert_renders <<SASS, <<SCSS
+foo bar
+  &:hover
+    baz: bang
+SASS
+foo bar {
+  &:hover {
+    baz: bang;
+  }
+}
+SCSS
+  end
+
+  def test_selector_interpolation
+    assert_renders <<SASS, <<SCSS
+foo \#{$bar + "baz"}.bip
+  baz: bang
+
+foo /\#{$bar + "baz"}/ .bip
+  baz: bang
+SASS
+foo \#{$bar + "baz"}.bip {
+  baz: bang;
+}
+
+foo /\#{$bar + "baz"}/ .bip {
+  baz: bang;
+}
+SCSS
+  end
+
+  def test_multiline_selector_with_commas
+    assert_renders <<SASS, <<SCSS
+foo bar,
+baz bang
+  baz: bang
+SASS
+foo bar,
+baz bang {
+  baz: bang;
+}
+SCSS
+
+    assert_renders <<SASS, <<SCSS
+blat
+  foo bar,
+  baz bang
+    baz: bang
+SASS
+blat {
+  foo bar,
+  baz bang {
+    baz: bang;
+  }
+}
+SCSS
+  end
+
+  def test_multiline_selector_without_commas
+    assert_scss_to_sass <<SASS, <<SCSS
+foo bar baz bang
+  baz: bang
+SASS
+foo bar
+baz bang {
+  baz: bang;
+}
+SCSS
+
+    assert_scss_to_scss <<SCSS
+foo bar
+baz bang {
+  baz: bang;
+}
+SCSS
+  end
+
+  def test_escaped_selector
+    assert_renders <<SASS, <<SCSS
+foo bar
+  \\:hover
+    baz: bang
+SASS
+foo bar {
+  :hover {
+    baz: bang;
+  }
+}
+SCSS
+  end
+
+  def test_property_name_interpolation
+    assert_renders <<SASS, <<SCSS
+foo bar
+  baz\#{$bang}bip\#{$bop}: 12
+SASS
+foo bar {
+  baz\#{$bang}bip\#{$bop}: 12;
+}
+SCSS
+  end
+
+  def test_property_value_interpolation
+    assert_renders <<SASS, <<SCSS
+foo bar
+  baz: 12 \#{$bang} bip \#{"bop"} blat
+SASS
+foo bar {
+  baz: 12 \#{$bang} bip \#{"bop"} blat;
+}
+SCSS
+  end
+
+  def test_dynamic_properties
+    assert_renders <<SASS, <<SCSS
+foo bar
+  baz: 12 $bang "bip"
+SASS
+foo bar {
+  baz: 12 $bang "bip";
+}
+SCSS
+  end
+
+  def test_dynamic_properties_with_old
+    assert_renders <<SASS, <<SCSS, :old => true
+foo bar
+  :baz 12 $bang "bip"
+SASS
+foo bar {
+  baz: 12 $bang "bip";
+}
+SCSS
+  end
+
+  def test_multiline_properties
+    assert_scss_to_sass <<SASS, <<SCSS
+foo bar
+  baz: bip bam boon
+SASS
+foo bar {
+  baz:
+    bip
+  bam
+        boon;
+}
+SCSS
+
+    assert_scss_to_scss <<OUT, <<IN
+foo bar {
+  baz: bip bam boon;
+}
+OUT
+foo bar {
+  baz:
+    bip
+  bam
+        boon;
+}
+IN
+  end
+
+  def test_multiline_dynamic_properties
+    assert_scss_to_sass <<SASS, <<SCSS
+foo bar
+  baz: $bip "bam" 12px
+SASS
+foo bar {
+  baz:
+    $bip
+  "bam"
+        12px;
+}
+SCSS
+
+    assert_scss_to_scss <<OUT, <<IN
+foo bar {
+  baz: $bip "bam" 12px;
+}
+OUT
+foo bar {
+  baz:
+    $bip
+  "bam"
+        12px;
+}
+IN
+  end
+
+  def test_silent_comments
+    assert_renders <<SASS, <<SCSS
+// foo
+
+// bar
+
+// baz
+
+foo bar
+  a: b
+SASS
+// foo
+
+// bar
+
+// baz
+
+foo bar {
+  a: b;
+}
+SCSS
+
+    assert_renders <<SASS, <<SCSS
+// foo
+// bar
+//   baz
+// bang
+
+foo bar
+  a: b
+SASS
+// foo
+// bar
+//   baz
+// bang
+
+foo bar {
+  a: b;
+}
+SCSS
+
+    assert_sass_to_scss <<SCSS, <<SASS
+// foo
+// bar
+//   baz
+// bang
+
+foo bar {
+  a: b;
+}
+SCSS
+// foo
+// bar
+//   baz
+// bang
+
+foo bar
+  a: b
+SASS
+  end
+
+  def test_nested_silent_comments
+    assert_renders <<SASS, <<SCSS
+foo
+  bar: baz
+  // bip bop
+  // beep boop
+  bang: bizz
+  // bubble bubble
+  // toil trouble
+SASS
+foo {
+  bar: baz;
+  // bip bop
+  // beep boop
+  bang: bizz;
+  // bubble bubble
+  // toil trouble
+}
+SCSS
+
+    assert_sass_to_scss <<SCSS, <<SASS
+foo {
+  bar: baz;
+  // bip bop
+  // beep boop
+  //   bap blimp
+  bang: bizz;
+  // bubble bubble
+  // toil trouble
+  //    gorp
+}
+SCSS
+foo
+  bar: baz
+  // bip bop
+     beep boop
+       bap blimp
+  bang: bizz
+  // bubble bubble
+    toil trouble
+       gorp
+SASS
+  end
+
+  def test_loud_comments
+    assert_renders <<SASS, <<SCSS
+/* foo
+
+/* bar
+
+/* baz
+
+foo bar
+  a: b
+SASS
+/* foo */
+
+/* bar */
+
+/* baz */
+
+foo bar {
+  a: b;
+}
+SCSS
+
+    assert_scss_to_sass <<SASS, <<SCSS
+/* foo
+ * bar
+ *   baz
+ * bang
+
+foo bar
+  a: b
+SASS
+/* foo
+   bar
+     baz
+   bang */
+
+foo bar {
+  a: b;
+}
+SCSS
+
+    assert_scss_to_scss <<SCSS
+/* foo
+   bar
+     baz
+   bang */
+
+foo bar {
+  a: b;
+}
+SCSS
+
+    assert_renders <<SASS, <<SCSS
+/* foo
+ * bar
+ *   baz
+ * bang
+
+foo bar
+  a: b
+SASS
+/* foo
+ * bar
+ *   baz
+ * bang */
+
+foo bar {
+  a: b;
+}
+SCSS
+  end
+
+  def test_nested_loud_comments
+    assert_renders <<SASS, <<SCSS
+foo
+  bar: baz
+  /* bip bop
+   * beep boop
+  bang: bizz
+  /* bubble bubble
+   * toil trouble
+SASS
+foo {
+  bar: baz;
+  /* bip bop
+   * beep boop */
+  bang: bizz;
+  /* bubble bubble
+   * toil trouble */
+}
+SCSS
+
+    assert_sass_to_scss <<SCSS, <<SASS
+foo {
+  bar: baz;
+  /* bip bop
+   * beep boop
+   *   bap blimp */
+  bang: bizz;
+  /* bubble bubble
+   * toil trouble
+   *    gorp */
+}
+SCSS
+foo
+  bar: baz
+  /* bip bop
+     beep boop
+       bap blimp
+  bang: bizz
+  /* bubble bubble
+    toil trouble
+       gorp
+SASS
+  end
+
+  def test_loud_comments_with_weird_indentation
+    assert_scss_to_sass <<SASS, <<SCSS
+foo
+  /*      foo
+   * bar
+   *     baz
+  a: b
+SASS
+foo {
+  /* foo
+bar
+    baz */
+  a: b;
+}
+SCSS
+
+    assert_sass_to_scss <<SCSS, <<SASS
+foo {
+  /*      foo
+   * bar
+   *     baz */
+  a: b;
+}
+SCSS
+foo
+  /*      foo
+     bar
+         baz
+  a: b
+SASS
+  end
+
+  def test_immediately_preceding_comments
+    assert_renders <<SASS, <<SCSS
+/* Foo
+ * Bar
+ * Baz
+.foo#bar
+  a: b
+SASS
+/* Foo
+ * Bar
+ * Baz */
+.foo#bar {
+  a: b;
+}
+SCSS
+
+    assert_renders <<SASS, <<SCSS
+// Foo
+// Bar
+// Baz
+=foo
+  a: b
+SASS
+// Foo
+// Bar
+// Baz
+ mixin foo {
+  a: b;
+}
+SCSS
+  end
+
+  def test_debug
+    assert_renders <<SASS, <<SCSS
+foo
+  @debug 12px
+  bar: baz
+SASS
+foo {
+  @debug 12px;
+  bar: baz;
+}
+SCSS
+  end
+
+  def test_directive_without_children
+    assert_renders <<SASS, <<SCSS
+foo
+  @foo #bar "baz"
+  bar: baz
+SASS
+foo {
+  @foo #bar "baz";
+  bar: baz;
+}
+SCSS
+  end
+
+  def test_directive_with_prop_children
+    assert_renders <<SASS, <<SCSS
+foo
+  @foo #bar "baz"
+    a: b
+    c: d
+
+  bar: baz
+SASS
+foo {
+  @foo #bar "baz" {
+    a: b;
+    c: d;
+  }
+
+  bar: baz;
+}
+SCSS
+  end
+
+  def test_directive_with_rule_children
+    assert_renders <<SASS, <<SCSS
+foo
+  @foo #bar "baz"
+    #blat
+      a: b
+    .bang
+      c: d
+      e: f
+
+  bar: baz
+SASS
+foo {
+  @foo #bar "baz" {
+    #blat {
+      a: b;
+    }
+    .bang {
+      c: d;
+      e: f;
+    }
+  }
+
+  bar: baz;
+}
+SCSS
+  end
+
+  def test_directive_with_rule_and_prop_children
+    assert_renders <<SASS, <<SCSS
+foo
+  @foo #bar "baz"
+    g: h
+    #blat
+      a: b
+    .bang
+      c: d
+      e: f
+    i: j
+
+  bar: baz
+SASS
+foo {
+  @foo #bar "baz" {
+    g: h;
+    #blat {
+      a: b;
+    }
+    .bang {
+      c: d;
+      e: f;
+    }
+    i: j;
+  }
+
+  bar: baz;
+}
+SCSS
+  end
+
+  def test_charset
+    assert_renders <<SASS, <<SCSS
+ charset "utf-8"
+SASS
+ charset "utf-8";
+SCSS
+  end
+
+  def test_for
+    assert_renders <<SASS, <<SCSS
+foo
+  @for $a from $b to $c
+    a: b
+  @for $c from 1 to 16
+    d: e
+    f: g
+SASS
+foo {
+  @for $a from $b to $c {
+    a: b;
+  }
+  @for $c from 1 to 16 {
+    d: e;
+    f: g;
+  }
+}
+SCSS
+  end
+
+  def test_while
+    assert_renders <<SASS, <<SCSS
+foo
+  @while flaz($a + $b)
+    a: b
+  @while 1
+    d: e
+    f: g
+SASS
+foo {
+  @while flaz($a + $b) {
+    a: b;
+  }
+  @while 1 {
+    d: e;
+    f: g;
+  }
+}
+SCSS
+  end
+
+  def test_if
+    assert_renders <<SASS, <<SCSS
+foo
+  @if $foo or $bar
+    a: b
+  @if $baz
+    d: e
+  @else if $bang
+    f: g
+  @else
+    h: i
+SASS
+foo {
+  @if $foo or $bar {
+    a: b;
+  }
+  @if $baz {
+    d: e;
+  }
+  @else if $bang {
+    f: g;
+  }
+  @else {
+    h: i;
+  }
+}
+SCSS
+  end
+
+  def test_each
+    assert_renders <<SASS, <<SCSS
+a
+  @each $number in 1px 2px 3px 4px
+    b: $number
+
+c
+  @each $str in foo, bar, baz, bang
+    d: $str
+SASS
+a {
+  @each $number in 1px 2px 3px 4px {
+    b: $number;
+  }
+}
+
+c {
+  @each $str in foo, bar, baz, bang {
+    d: $str;
+  }
+}
+SCSS
+  end
+
+  def test_import
+    assert_renders <<SASS, <<SCSS
+ import foo
+
+ import url(bar.css)
+
+foo
+  bar: baz
+SASS
+ import "foo";
+
+ import url(bar.css);
+
+foo {
+  bar: baz;
+}
+SCSS
+
+    assert_renders <<SASS, <<SCSS
+ import foo.css
+
+ import url(bar.css)
+
+foo
+  bar: baz
+SASS
+ import "foo.css";
+
+ import url(bar.css);
+
+foo {
+  bar: baz;
+}
+SCSS
+  end
+
+  def test_import_as_directive_in_sass
+    assert_equal "@import foo.css\n", to_sass('@import "foo.css"')
+  end
+
+  def test_import_as_directive_in_scss
+    assert_renders <<SASS, <<SCSS
+ import "foo.css" print
+SASS
+ import "foo.css" print;
+SCSS
+
+    assert_renders <<SASS, <<SCSS
+ import url(foo.css) screen, print
+SASS
+ import url(foo.css) screen, print;
+SCSS
+  end
+
+  def test_adjacent_imports
+    assert_renders <<SASS, <<SCSS
+ import foo.sass
+ import bar.scss
+ import baz
+SASS
+ import "foo.sass";
+ import "bar.scss";
+ import "baz";
+SCSS
+  end
+
+  def test_non_adjacent_imports
+    assert_renders <<SASS, <<SCSS
+ import foo.sass
+
+ import bar.scss
+
+ import baz
+SASS
+ import "foo.sass";
+
+ import "bar.scss";
+
+ import "baz";
+SCSS
+  end
+
+  def test_import_with_interpolation
+    assert_renders <<SASS, <<SCSS
+$family: unquote("Droid+Sans")
+
+ import url("http://fonts.googleapis.com/css?family=\#{$family}";)
+SASS
+$family: unquote("Droid+Sans");
+
+ import url("http://fonts.googleapis.com/css?family=\#{$family}";);
+SCSS
+  end
+
+  def test_extend
+    assert_renders <<SASS, <<SCSS
+.foo
+  @extend .bar
+  @extend .baz:bang
+SASS
+.foo {
+  @extend .bar;
+  @extend .baz:bang;
+}
+SCSS
+  end
+
+  def test_comma_extendee
+    assert_renders <<SASS, <<SCSS
+.baz
+  @extend .foo, .bar
+SASS
+.baz {
+  @extend .foo, .bar;
+}
+SCSS
+  end
+
+  def test_argless_mixin_definition
+    assert_renders <<SASS, <<SCSS
+=foo-bar
+  baz
+    a: b
+SASS
+ mixin foo-bar {
+  baz {
+    a: b;
+  }
+}
+SCSS
+
+    assert_scss_to_sass <<SASS, <<SCSS
+=foo-bar
+  baz
+    a: b
+SASS
+ mixin foo-bar() {
+  baz {
+    a: b;
+  }
+}
+SCSS
+
+    assert_sass_to_scss <<SCSS, <<SASS
+ mixin foo-bar {
+  baz {
+    a: b;
+  }
+}
+SCSS
+=foo-bar()
+  baz
+    a: b
+SASS
+  end
+
+  def test_mixin_definition_without_defaults
+    assert_renders <<SASS, <<SCSS
+=foo-bar($baz, $bang)
+  baz
+    a: $baz $bang
+SASS
+ mixin foo-bar($baz, $bang) {
+  baz {
+    a: $baz $bang;
+  }
+}
+SCSS
+  end
+
+  def test_mixin_definition_with_defaults
+    assert_renders <<SASS, <<SCSS
+=foo-bar($baz, $bang: 12px)
+  baz
+    a: $baz $bang
+SASS
+ mixin foo-bar($baz, $bang: 12px) {
+  baz {
+    a: $baz $bang;
+  }
+}
+SCSS
+
+    assert_sass_to_scss <<SCSS, <<SASS
+ mixin foo-bar($baz, $bang: foo) {
+  baz {
+    a: $baz $bang;
+  }
+}
+SCSS
+=foo-bar($baz, $bang: foo)
+  baz
+    a: $baz $bang
+SASS
+  end
+
+  def test_argless_mixin_include
+    assert_renders <<SASS, <<SCSS
+foo
+  +foo-bar
+  a: blip
+SASS
+foo {
+  @include foo-bar;
+  a: blip;
+}
+SCSS
+  end
+
+  def test_mixin_include
+    assert_renders <<SASS, <<SCSS
+foo
+  +foo-bar(12px, "blaz")
+  a: blip
+SASS
+foo {
+  @include foo-bar(12px, "blaz");
+  a: blip;
+}
+SCSS
+  end
+
+  def test_mixin_include_with_keyword_args
+    assert_renders <<SASS, <<SCSS
+foo
+  +foo-bar(12px, "blaz", $blip: blap, $bloop: blop)
+  +foo-bar($blip: blap, $bloop: blop)
+  a: blip
+SASS
+foo {
+  @include foo-bar(12px, "blaz", $blip: blap, $bloop: blop);
+  @include foo-bar($blip: blap, $bloop: blop);
+  a: blip;
+}
+SCSS
+  end
+
+  def test_argless_function_definition
+    assert_renders <<SASS, <<SCSS
+ function foo()
+  $var: 1 + 1
+  @return $var
+SASS
+ function foo() {
+  $var: 1 + 1;
+  @return $var;
+}
+SCSS
+  end
+
+  def test_function_definition_without_defaults
+    assert_renders <<SASS, <<SCSS
+ function foo($var1, $var2)
+  @if $var1
+    @return $var1 + $var2
+SASS
+ function foo($var1, $var2) {
+  @if $var1 {
+    @return $var1 + $var2;
+  }
+}
+SCSS
+  end
+
+  def test_function_definition_with_defaults
+    assert_renders <<SASS, <<SCSS
+ function foo($var1, $var2: foo)
+  @if $var1
+    @return $var1 + $var2
+SASS
+ function foo($var1, $var2: foo) {
+  @if $var1 {
+    @return $var1 + $var2;
+  }
+}
+SCSS
+  end
+
+  def test_variable_definition
+    assert_renders <<SASS, <<SCSS
+$var1: 12px + 15px
+
+foo
+  $var2: flaz(#abcdef)
+  val: $var1 $var2
+SASS
+$var1: 12px + 15px;
+
+foo {
+  $var2: flaz(#abcdef);
+  val: $var1 $var2;
+}
+SCSS
+  end
+
+  def test_guarded_variable_definition
+    assert_renders <<SASS, <<SCSS
+$var1: 12px + 15px !default
+
+foo
+  $var2: flaz(#abcdef) !default
+  val: $var1 $var2
+SASS
+$var1: 12px + 15px !default;
+
+foo {
+  $var2: flaz(#abcdef) !default;
+  val: $var1 $var2;
+}
+SCSS
+  end
+
+  def test_multiple_variable_definitions
+    assert_renders <<SASS, <<SCSS
+$var1: foo
+$var2: bar
+$var3: baz
+
+$var4: bip
+$var5: bap
+SASS
+$var1: foo;
+$var2: bar;
+$var3: baz;
+
+$var4: bip;
+$var5: bap;
+SCSS
+  end
+
+  def test_division_asserted_with_parens
+    assert_renders <<SASS, <<SCSS
+foo
+  a: (1px / 2px)
+SASS
+foo {
+  a: (1px / 2px);
+}
+SCSS
+  end
+
+  def test_division_not_asserted_when_unnecessary
+    assert_renders <<SASS, <<SCSS
+$var: 1px / 2px
+
+foo
+  a: $var
+SASS
+$var: 1px / 2px;
+
+foo {
+  a: $var;
+}
+SCSS
+
+    assert_renders <<SASS, <<SCSS
+$var: 1px
+
+foo
+  a: $var / 2px
+SASS
+$var: 1px;
+
+foo {
+  a: $var / 2px;
+}
+SCSS
+
+    assert_renders <<SASS, <<SCSS
+foo
+  a: 1 + 1px / 2px
+SASS
+foo {
+  a: 1 + 1px / 2px;
+}
+SCSS
+  end
+
+  def test_literal_slash
+    assert_renders <<SASS, <<SCSS
+foo
+  a: 1px / 2px
+SASS
+foo {
+  a: 1px / 2px;
+}
+SCSS
+  end
+
+  def test_directive_with_interpolation
+    assert_renders <<SASS, <<SCSS
+$baz: 12
+
+ foo bar\#{$baz} qux
+  a: b
+SASS
+$baz: 12;
+
+ foo bar\#{$baz} qux {
+  a: b;
+}
+SCSS
+  end
+
+  def test_media_with_interpolation
+    assert_renders <<SASS, <<SCSS
+$baz: 12
+
+ media bar\#{$baz}
+  a: b
+SASS
+$baz: 12;
+
+ media bar\#{$baz} {
+  a: b;
+}
+SCSS
+  end
+
+  def test_media_with_expressions
+    assert_sass_to_scss <<SCSS, <<SASS
+$media1: screen;
+$media2: print;
+$var: -webkit-min-device-pixel-ratio;
+$val: 20;
+
+ media \#{$media1} and ($var + "-foo": $val + 5), only \#{$media2} {
+  a: b;
+}
+SCSS
+$media1: screen
+$media2: print
+$var: -webkit-min-device-pixel-ratio
+$val: 20
+
+ media \#{$media1} and ($var + "-foo": $val + 5), only \#{$media2}
+  a: b
+SASS
+
+    assert_scss_to_sass <<SASS, <<SCSS
+$media1: screen
+$media2: print
+$var: -webkit-min-device-pixel-ratio
+$val: 20
+
+ media \#{$media1} and ($var + "-foo": $val + 5), only \#{$media2}
+  a: b
+SASS
+$media1: screen;
+$media2: print;
+$var: -webkit-min-device-pixel-ratio;
+$val: 20;
+
+ media \#{$media1} and ($var + "-foo": $val + 5), only \#{$media2} {
+  a: b;
+}
+SCSS
+  end
+
+  def test_supports_with_expressions
+    assert_renders <<SASS, <<SCSS
+$query: "(feature1: val)"
+$feature: feature2
+$val: val
+
+ supports \#{$query} and ($feature: $val) or (not ($feature + 3: $val + 4))
+  foo
+    a: b
+SASS
+$query: "(feature1: val)";
+$feature: feature2;
+$val: val;
+
+ supports \#{$query} and ($feature: $val) or (not ($feature + 3: $val + 4)) {
+  foo {
+    a: b;
+  }
+}
+SCSS
+  end
+
+  # Hacks
+
+  def test_declaration_hacks
+    assert_renders <<SASS, <<SCSS
+foo
+  _name: val
+  *name: val
+  #name: val
+  .name: val
+  name/**/: val
+  name/*\\**/: val
+  name: val
+SASS
+foo {
+  _name: val;
+  *name: val;
+  #name: val;
+  .name: val;
+  name/**/: val;
+  name/*\\**/: val;
+  name: val;
+}
+SCSS
+  end
+
+  def test_old_declaration_hacks
+    assert_renders <<SASS, <<SCSS, :old => true
+foo
+  :_name val
+  :*name val
+  :#name val
+  :.name val
+  :name val
+SASS
+foo {
+  _name: val;
+  *name: val;
+  #name: val;
+  .name: val;
+  name: val;
+}
+SCSS
+  end
+
+  def test_selector_hacks
+    assert_selector_renders = lambda do |s|
+      assert_renders <<SASS, <<SCSS
+#{s}
+  a: b
+SASS
+#{s} {
+  a: b;
+}
+SCSS
+    end
+
+    assert_selector_renders['> E']
+    assert_selector_renders['+ E']
+    assert_selector_renders['~ E']
+    assert_selector_renders['> > E']
+
+    assert_selector_renders['E*']
+    assert_selector_renders['E*.foo']
+    assert_selector_renders['E*:hover']
+  end
+
+  def test_disallowed_colon_hack
+    assert_raise_message(Sass::SyntaxError, 'The ":name: val" hack is not allowed in the Sass indented 
syntax') do
+      to_sass("foo {:name: val;}", :syntax => :scss)
+    end
+  end
+
+  def test_nested_properties
+    assert_renders <<SASS, <<SCSS
+div
+  before: before
+  background:
+    color: blue
+    repeat: no-repeat
+  after: after
+SASS
+div {
+  before: before;
+  background: {
+    color: blue;
+    repeat: no-repeat;
+  };
+  after: after;
+}
+
+SCSS
+  end
+
+  def test_dasherize
+    assert_sass_to_scss(<<SCSS, <<SASS, :dasherize => true)
+ mixin under-scored-mixin($under-scored-arg: $under-scored-default) {
+  bar: $under-scored-arg;
+}
+
+div {
+  foo: under-scored-fn($under-scored-var + "before\#{$another-under-scored-var}after");
+  @include under-scored-mixin($passed-arg);
+  selector-\#{$under-scored-interp}: bold;
+}
+
+ if $under-scored {
+  @for $for-var from $from-var to $to-var {
+    @while $while-var == true {
+      $while-var: false;
+    }
+  }
+}
+SCSS
+=under_scored_mixin($under_scored_arg: $under_scored_default)
+  bar: $under_scored_arg
+div
+  foo: under_scored_fn($under_scored_var + "before\#{$another_under_scored_var}after")
+  +under_scored_mixin($passed_arg)
+  selector-\#{$under_scored_interp}: bold
+ if $under_scored
+  @for $for_var from $from_var to $to_var
+    @while $while_var == true
+      $while_var : false
+SASS
+  end
+
+   def test_loud_comment_conversion
+    assert_renders(<<SASS, <<SCSS)
+/*! \#{"interpolated"}
+SASS
+/*! \#{"interpolated"} */
+SCSS
+  end
+
+  def test_content_conversion
+    assert_renders(<<SASS, <<SCSS)
+$color: blue
+
+=context($class, $color: red)
+  .\#{$class}
+    background-color: $color
+    @content
+    border-color: $color
+
++context(parent)
+  +context(child, $color: yellow)
+    color: $color
+SASS
+$color: blue;
+
+ mixin context($class, $color: red) {
+  .\#{$class} {
+    background-color: $color;
+    @content;
+    border-color: $color;
+  }
+}
+
+ include context(parent) {
+  @include context(child, $color: yellow) {
+    color: $color;
+  }
+}
+SCSS
+
+  end
+
+  def test_empty_content
+    assert_scss_to_scss(<<SCSS)
+ mixin foo {
+  @content;
+}
+
+ include foo {}
+SCSS
+  end
+
+  def test_placeholder_conversion
+    assert_renders(<<SASS, <<SCSS)
+#content a%foo.bar
+  color: blue
+SASS
+#content a%foo.bar {
+  color: blue;
+}
+SCSS
+  end
+
+  def test_reference_selector
+    assert_renders(<<SASS, <<SCSS)
+foo /bar|baz/ bang
+  a: b
+SASS
+foo /bar|baz/ bang {
+  a: b;
+}
+SCSS
+  end
+
+  def test_subject
+    assert_renders(<<SASS, <<SCSS)
+foo bar! baz
+  a: b
+SASS
+foo bar! baz {
+  a: b;
+}
+SCSS
+  end
+
+  def test_placeholder_interoplation_conversion
+    assert_renders(<<SASS, <<SCSS)
+$foo: foo
+
+%\#{$foo}
+  color: blue
+
+.bar
+  @extend %foo
+SASS
+$foo: foo;
+
+%\#{$foo} {
+  color: blue;
+}
+
+.bar {
+  @extend %foo;
+}
+SCSS
+  end
+
+  def test_indent
+    assert_renders <<SASS, <<SCSS, :indent => "    "
+foo bar
+    baz bang
+        baz: bang
+        bip: bop
+    blat: boo
+SASS
+foo bar {
+    baz bang {
+        baz: bang;
+        bip: bop;
+    }
+    blat: boo;
+}
+SCSS
+
+    assert_renders <<SASS, <<SCSS, :indent => "\t"
+foo bar
+       baz bang
+               baz: bang
+               bip: bop
+       blat: boo
+SASS
+foo bar {
+       baz bang {
+               baz: bang;
+               bip: bop;
+       }
+       blat: boo;
+}
+SCSS
+
+    assert_sass_to_scss <<SCSS, <<SASS, :indent => "    "
+foo bar {
+    baz bang {
+        baz: bang;
+        bip: bop;
+    }
+    blat: boo;
+}
+SCSS
+foo bar
+  baz bang
+    baz: bang
+    bip: bop
+  blat: boo
+SASS
+
+    assert_sass_to_scss <<SCSS, <<SASS, :indent => "\t"
+foo bar {
+       baz bang {
+               baz: bang;
+               bip: bop;
+       }
+       blat: boo;
+}
+SCSS
+foo bar
+  baz bang
+    baz: bang
+    bip: bop
+  blat: boo
+SASS
+
+    assert_scss_to_sass <<SASS, <<SCSS, :indent => "    "
+foo bar
+    baz bang
+        baz: bang
+        bip: bop
+    blat: boo
+SASS
+foo bar {
+  baz bang {
+    baz: bang;
+    bip: bop;
+  }
+  blat: boo;
+}
+SCSS
+
+    assert_scss_to_sass <<SASS, <<SCSS, :indent => "\t"
+foo bar
+       baz bang
+               baz: bang
+               bip: bop
+       blat: boo
+SASS
+foo bar {
+  baz bang {
+    baz: bang;
+    bip: bop;
+  }
+  blat: boo;
+}
+SCSS
+  end
+
+  def test_extend_with_optional
+    assert_scss_to_sass <<SASS, <<SCSS
+foo
+  @extend .bar !optional
+SASS
+foo {
+  @extend .bar !optional;
+}
+SCSS
+  end
+
+  def test_mixin_var_args
+    assert_scss_to_sass <<SASS, <<SCSS
+=foo($args...)
+  a: b
+
+=bar($a, $args...)
+  a: b
+
+.foo
+  +foo($list...)
+  +bar(1, $list...)
+SASS
+ mixin foo($args...) {
+  a: b;
+}
+
+ mixin bar($a, $args...) {
+  a: b;
+}
+
+.foo {
+  @include foo($list...);
+  @include bar(1, $list...);
+}
+SCSS
+  end
+
+  def test_function_var_args
+    assert_scss_to_sass <<SASS, <<SCSS
+ function foo($args...)
+  @return foo
+
+ function bar($a, $args...)
+  @return bar
+
+.foo
+  a: foo($list...)
+  b: bar(1, $list...)
+SASS
+ function foo($args...) {
+  @return foo;
+}
+
+ function bar($a, $args...) {
+  @return bar;
+}
+
+.foo {
+  a: foo($list...);
+  b: bar(1, $list...);
+}
+SCSS
+  end
+
+  ## Regression Tests
+
+  def test_list_in_args
+    assert_renders(<<SASS, <<SCSS)
++mixin((a, b, c))
+
++mixin($arg: (a, b, c))
+
++mixin(a, b, (c, d, e)...)
+SASS
+ include mixin((a, b, c));
+
+ include mixin($arg: (a, b, c));
+
+ include mixin(a, b, (c, d, e)...);
+SCSS
+  end
+
+  def test_media_query_with_expr
+    assert_scss_to_sass <<SASS, <<SCSS
+ media foo and (bar: baz)
+  a: b
+SASS
+ media foo and (bar: baz) {
+  a: b; }
+SCSS
+  end
+
+  def test_nested_if_statements
+    assert_renders(<<SASS, <<SCSS)
+ if $foo
+  one
+    a: b
+ else
+  @if $bar
+    two
+      a: b
+  @else
+    three
+      a: b
+SASS
+ if $foo {
+  one {
+    a: b;
+  }
+}
+ else {
+  @if $bar {
+    two {
+      a: b;
+    }
+  }
+  @else {
+    three {
+      a: b;
+    }
+  }
+}
+SCSS
+  end
+
+  def test_comment_indentation
+    assert_renders(<<SASS, <<SCSS, :indent => '    ')
+foo
+    // bar
+    /* baz
+    a: b
+SASS
+foo {
+    // bar
+    /* baz */
+    a: b;
+}
+SCSS
+  end
+
+  def test_ambiguous_negation
+    assert_renders(<<SASS, <<SCSS, :indent => '    ')
+foo
+    ok: -$foo
+    comma: 10px, -$foo
+    needs-parens: 10px (-$foo)
+    no-parens: a 50px + 60px b
+SASS
+foo {
+    ok: -$foo;
+    comma: 10px, -$foo;
+    needs-parens: 10px (-$foo);
+    no-parens: a 50px + 60px b;
+}
+SCSS
+  end
+
+  private
+
+  def assert_sass_to_sass(sass, options = {})
+    assert_equal(sass.rstrip, to_sass(sass, options).rstrip,
+      "Expected Sass to transform to itself")
+  end
+
+  def assert_scss_to_sass(sass, scss, options = {})
+    assert_equal(sass.rstrip, to_sass(scss, options.merge(:syntax => :scss)).rstrip,
+      "Expected SCSS to transform to Sass")
+  end
+
+  def assert_scss_to_scss(scss, in_scss = nil, options = nil)
+    if in_scss.is_a?(Hash)
+      options = in_scss
+      in_scss = nil
+    end
+
+    in_scss ||= scss
+    options ||= {}
+
+    assert_equal(scss.rstrip, to_scss(in_scss, options.merge(:syntax => :scss)).rstrip,
+      "Expected SCSS to transform to #{scss == in_scss ? 'itself' : 'SCSS'}")
+  end
+
+  def assert_sass_to_scss(scss, sass, options = {})
+    assert_equal(scss.rstrip, to_scss(sass, options).rstrip,
+      "Expected Sass to transform to SCSS")
+  end
+
+  def assert_renders(sass, scss, options = {})
+    assert_sass_to_sass(sass, options)
+    assert_scss_to_sass(sass, scss, options)
+    assert_scss_to_scss(scss, options)
+    assert_sass_to_scss(scss, sass, options)
+  end
+
+  def to_sass(scss, options = {})
+    Sass::Util.silence_sass_warnings do
+      Sass::Engine.new(scss, options).to_tree.to_sass(options)
+    end
+  end
+
+  def to_scss(sass, options = {})
+    Sass::Util.silence_sass_warnings do
+      Sass::Engine.new(sass, options).to_tree.to_scss(options)
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/css2sass_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/css2sass_test.rb
new file mode 100755
index 0000000..b018f27
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/css2sass_test.rb
@@ -0,0 +1,439 @@
+#!/usr/bin/env ruby
+require 'test/unit'
+require File.dirname(__FILE__) + '/../test_helper'
+require 'sass/css'
+
+class CSS2SassTest < Test::Unit::TestCase
+  def test_basic
+    css = <<CSS
+h1 {
+  color: red;
+}
+CSS
+    assert_equal(<<SASS, css2sass(css))
+h1
+  color: red
+SASS
+    assert_equal(<<SASS, css2sass(css, :old => true))
+h1
+  :color red
+SASS
+  end
+
+  def test_nesting
+    assert_equal(<<SASS, css2sass(<<CSS))
+li
+  display: none
+  a
+    text-decoration: none
+    span
+      color: yellow
+    &:hover
+      text-decoration: underline
+SASS
+li {
+  display: none;
+}
+
+li a {
+  text-decoration: none;
+}
+
+li a span {
+  color: yellow;
+}
+
+li a:hover {
+  text-decoration: underline;
+}
+CSS
+  end
+
+  def test_no_nesting_around_rules
+    assert_equal(<<SASS, css2sass(<<CSS))
+div .warning
+  color: #d21a19
+
+span .debug
+  cursor: crosshair
+
+div .debug
+  cursor: default
+SASS
+div .warning {
+  color: #d21a19; }
+span .debug { 
+  cursor: crosshair;}
+div .debug {
+  cursor: default; }
+CSS
+  end
+
+  def test_comments_multiline
+    css = <<CSS
+/* comment */
+elephant.rawr {
+  rampages: excessively;
+}
+
+/* actual multiline
+  comment */
+span.turkey {
+  isdinner: true;
+}
+
+.turducken {
+  /* Sounds funny
+     doesn't it */
+  chimera: not_really;
+}
+
+#overhere {
+  bored: sorta; /* it's for a good
+  cause */
+  better_than: thread_pools;
+}
+
+#one_more {
+  finally: srsly;
+} /* just a line here */
+CSS
+    sass = <<SASS
+/* comment
+
+elephant.rawr
+  rampages: excessively
+
+/* actual multiline
+ *comment
+
+span.turkey
+  isdinner: true
+
+.turducken
+  /* Sounds funny
+   * doesn't it
+  chimera: not_really
+
+#overhere
+  bored: sorta
+  /*                  it's for a good
+   * cause
+  better_than: thread_pools
+
+#one_more
+  finally: srsly
+
+/* just a line here
+SASS
+    assert_equal(sass, css2sass(css))
+  end
+
+  def test_fold_commas
+    assert_equal(<<SASS, css2sass(<<CSS))
+li
+  .one, .two
+    color: red
+SASS
+li .one {
+  color: red;
+}
+li .two {
+  color: red;
+}
+CSS
+
+    assert_equal(<<SASS, css2sass(<<CSS))
+.one
+  color: green
+
+.two
+  color: green
+  color: red
+
+.three
+  color: red
+SASS
+.one, .two {
+  color: green;
+}
+
+.two, .three {
+  color: red;
+}
+CSS
+  end
+
+  def test_bad_formatting
+    assert_equal(<<SASS, css2sass(<<CSS))
+hello
+  parent: true
+  there
+    parent: false
+  who
+    hoo: false
+  why
+    y: true
+  when
+    wen: nao
+
+down_here
+  yeah: true
+SASS
+hello {
+  parent: true;
+}
+
+hello  there {
+  parent: false;
+}
+hello who  {
+  hoo: false;
+}
+hello why {
+   y: true;
+}
+hello when {
+  wen:  nao;
+}
+
+
+
+down_here { yeah: true; }
+CSS
+  end
+
+  def test_comments_in_selectors
+    assert_equal(<<SASS, css2sass(<<CSS))
+.js
+  #location-navigation-form .form-submit, #business-listing-form .form-submit, #detailTabs ul, 
#detailsEnhanced #addTags, #locationSearchList, #moreHoods
+    display: none
+
+#navListLeft
+  display: none
+SASS
+.js #location-navigation-form .form-submit,
+.js #business-listing-form .form-submit,
+.js #detailTabs ul,
+/* .js #addReview, */
+/* .js #addTags, */
+.js #detailsEnhanced #addTags,
+.js #locationSearchList,
+.js #moreHoods,
+#navListLeft
+  { display: none; }
+CSS
+  end
+
+  def test_pseudo_classes_are_escaped
+    assert_equal(<<SASS, css2sass(<<CSS))
+\\:focus
+  a: b
+  \\:foo
+    bar: baz
+SASS
+:focus {a: b;}
+:focus :foo {bar: baz;}
+CSS
+  end
+
+  def test_subject
+    assert_equal(<<SASS, css2sass(<<CSS))
+.foo
+  .bar!
+    .baz
+      a: b
+    .bip
+      c: d
+  .bar .bonk
+    e: f
+
+.flip!
+  &.bar
+    a: b
+  &.baz
+    c: d
+SASS
+.foo .bar! .baz {a: b;}
+.foo .bar! .bip {c: d;}
+.foo .bar .bonk {e: f;}
+
+.flip.bar! {a: b;}
+.flip.baz! {c: d;}
+CSS
+  end
+
+  # Regressions
+
+  def test_nesting_within_media
+    assert_equal(<<SASS, css2sass(<<CSS))
+ media all
+  .next .vevent
+    padding-left: 0
+    padding-right: 0
+SASS
+ media all {
+  .next .vevent {
+    padding-left: 0;
+    padding-right: 0; } }
+CSS
+  end
+
+  def test_multiline_selector_within_media_and_with_child_selector
+    assert_equal(<<SASS, css2sass(<<CSS))
+ media all
+  foo bar, baz
+    padding-left: 0
+    padding-right: 0
+SASS
+ media all {
+  foo bar,
+  baz {
+    padding-left: 0;
+    padding-right: 0; } }
+CSS
+  end
+
+  def test_double_comma
+    assert_equal(<<SASS, css2sass(<<CSS))
+foo, bar
+  a: b
+SASS
+foo, , bar { a: b }
+CSS
+  end
+
+  def test_selector_splitting
+    assert_equal(<<SASS, css2sass(<<CSS))
+.foo >
+  .bar
+    a: b
+  .baz
+    c: d
+SASS
+.foo>.bar {a: b}
+.foo>.baz {c: d}
+CSS
+
+    assert_equal(<<SASS, css2sass(<<CSS))
+.foo
+  &::bar
+    a: b
+  &::baz
+    c: d
+SASS
+.foo::bar {a: b}
+.foo::baz {c: d}
+CSS
+  end
+
+  def test_triple_nesting
+    assert_equal(<<SASS, css2sass(<<CSS))
+.foo .bar .baz
+  a: b
+SASS
+.foo .bar .baz {a: b}
+CSS
+
+    assert_equal(<<SASS, css2sass(<<CSS))
+.bar > .baz
+  c: d
+SASS
+.bar > .baz {c: d}
+CSS
+  end
+
+  # Error reporting
+
+  def test_error_reporting
+    css2sass("foo")
+    assert(false, "Expected exception")
+  rescue Sass::SyntaxError => err
+    assert_equal(1, err.sass_line)
+    assert_equal('Invalid CSS after "foo": expected "{", was ""', err.message)
+  end
+
+  def test_error_reporting_in_line
+    css2sass("foo\nbar }\nbaz")
+    assert(false, "Expected exception")
+  rescue Sass::SyntaxError => err
+    assert_equal(2, err.sass_line)
+    assert_equal('Invalid CSS after "bar ": expected "{", was "}"', err.message)
+  end
+
+  def test_error_truncate_after
+    css2sass("#{"a" * 16}foo")
+    assert(false, "Expected exception")
+  rescue Sass::SyntaxError => err
+    assert_equal(1, err.sass_line)
+    assert_equal('Invalid CSS after "...aaaaaaaaaaaafoo": expected "{", was ""', err.message)
+  end
+
+  def test_error_truncate_was
+    css2sass("foo }foo#{"a" * 15}")
+    assert(false, "Expected exception")
+  rescue Sass::SyntaxError => err
+    assert_equal(1, err.sass_line)
+    assert_equal('Invalid CSS after "foo ": expected "{", was "}fooaaaaaaaaaaa..."', err.message)
+  end
+
+  def test_error_doesnt_truncate_after_when_elipsis_would_add_length
+    css2sass("#{"a" * 15}foo")
+    assert(false, "Expected exception")
+  rescue Sass::SyntaxError => err
+    assert_equal(1, err.sass_line)
+    assert_equal('Invalid CSS after "aaaaaaaaaaaaaaafoo": expected "{", was ""', err.message)
+  end
+
+  def test_error_doesnt_truncate_was_when_elipsis_would_add_length
+    css2sass("foo }foo#{"a" * 14}")
+    assert(false, "Expected exception")
+  rescue Sass::SyntaxError => err
+    assert_equal(1, err.sass_line)
+    assert_equal('Invalid CSS after "foo ": expected "{", was "}fooaaaaaaaaaaaaaa"', err.message)
+  end
+
+  def test_error_gets_rid_of_trailing_newline_for_after
+    css2sass("foo  \n  ")
+    assert(false, "Expected exception")
+  rescue Sass::SyntaxError => err
+    assert_equal(2, err.sass_line)
+    assert_equal('Invalid CSS after "foo": expected "{", was ""', err.message)
+  end
+
+  def test_error_gets_rid_of_trailing_newline_for_was
+    css2sass("foo \n  }foo")
+    assert(false, "Expected exception")
+  rescue Sass::SyntaxError => err
+    assert_equal(2, err.sass_line)
+    assert_equal('Invalid CSS after "foo": expected "{", was "}foo"', err.message)
+  end
+
+  # Encodings
+
+  unless Sass::Util.ruby1_8?
+    def test_encoding_error
+      css2sass("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
+      assert(false, "Expected exception")
+    rescue Sass::SyntaxError => e
+      assert_equal(3, e.sass_line)
+      assert_equal('Invalid UTF-8 character "\xFE"', e.message)
+    end
+
+    def test_ascii_incompatible_encoding_error
+      template = "foo\nbar\nb_z".encode("utf-16le")
+      template[9] = "\xFE".force_encoding("utf-16le")
+      css2sass(template)
+      assert(false, "Expected exception")
+    rescue Sass::SyntaxError => e
+      assert_equal(3, e.sass_line)
+      assert_equal('Invalid UTF-16LE character "\xFE"', e.message)
+    end
+  end
+
+  private
+
+  def css2sass(string, opts={})
+    Sass::CSS.new(string, opts).render
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/data/hsl-rgb.txt 
b/backends/css/gems/sass-3.2.12/test/sass/data/hsl-rgb.txt
new file mode 100644
index 0000000..2e9e470
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/data/hsl-rgb.txt
@@ -0,0 +1,319 @@
+hsl(0, 100%, 50%)
+hsl(60, 100%, 50%)
+hsl(120, 100%, 50%)
+hsl(180, 100%, 50%)
+hsl(240, 100%, 50%)
+hsl(300, 100%, 50%)
+====
+rgb(255, 0, 0)
+rgb(255, 255, 0)
+rgb(0, 255, 0)
+rgb(0, 255, 255)
+rgb(0, 0, 255)
+rgb(255, 0, 255)
+
+hsl(-360, 100%, 50%)
+hsl(-300, 100%, 50%)
+hsl(-240, 100%, 50%)
+hsl(-180, 100%, 50%)
+hsl(-120, 100%, 50%)
+hsl(-60, 100%, 50%)
+====
+rgb(255, 0, 0)
+rgb(255, 255, 0)
+rgb(0, 255, 0)
+rgb(0, 255, 255)
+rgb(0, 0, 255)
+rgb(255, 0, 255)
+
+hsl(360, 100%, 50%)
+hsl(420, 100%, 50%)
+hsl(480, 100%, 50%)
+hsl(540, 100%, 50%)
+hsl(600, 100%, 50%)
+hsl(660, 100%, 50%)
+====
+rgb(255, 0, 0)
+rgb(255, 255, 0)
+rgb(0, 255, 0)
+rgb(0, 255, 255)
+rgb(0, 0, 255)
+rgb(255, 0, 255)
+
+hsl(6120, 100%, 50%)
+hsl(-9660, 100%, 50%)
+hsl(99840, 100%, 50%)
+hsl(-900, 100%, 50%)
+hsl(-104880, 100%, 50%)
+hsl(2820, 100%, 50%)
+====
+rgb(255, 0, 0)
+rgb(255, 255, 0)
+rgb(0, 255, 0)
+rgb(0, 255, 255)
+rgb(0, 0, 255)
+rgb(255, 0, 255)
+
+hsl(0, 100%, 50%)
+hsl(12, 100%, 50%)
+hsl(24, 100%, 50%)
+hsl(36, 100%, 50%)
+hsl(48, 100%, 50%)
+hsl(60, 100%, 50%)
+hsl(72, 100%, 50%)
+hsl(84, 100%, 50%)
+hsl(96, 100%, 50%)
+hsl(108, 100%, 50%)
+hsl(120, 100%, 50%)
+====
+rgb(255, 0, 0)
+rgb(255, 51, 0)
+rgb(255, 102, 0)
+rgb(255, 153, 0)
+rgb(255, 204, 0)
+rgb(255, 255, 0)
+rgb(204, 255, 0)
+rgb(153, 255, 0)
+rgb(102, 255, 0)
+rgb(51, 255, 0)
+rgb(0, 255, 0)
+
+hsl(120, 100%, 50%)
+hsl(132, 100%, 50%)
+hsl(144, 100%, 50%)
+hsl(156, 100%, 50%)
+hsl(168, 100%, 50%)
+hsl(180, 100%, 50%)
+hsl(192, 100%, 50%)
+hsl(204, 100%, 50%)
+hsl(216, 100%, 50%)
+hsl(228, 100%, 50%)
+hsl(240, 100%, 50%)
+====
+rgb(0, 255, 0)
+rgb(0, 255, 51)
+rgb(0, 255, 102)
+rgb(0, 255, 153)
+rgb(0, 255, 204)
+rgb(0, 255, 255)
+rgb(0, 204, 255)
+rgb(0, 153, 255)
+rgb(0, 102, 255)
+rgb(0, 51, 255)
+rgb(0, 0, 255)
+
+hsl(240, 100%, 50%)
+hsl(252, 100%, 50%)
+hsl(264, 100%, 50%)
+hsl(276, 100%, 50%)
+hsl(288, 100%, 50%)
+hsl(300, 100%, 50%)
+hsl(312, 100%, 50%)
+hsl(324, 100%, 50%)
+hsl(336, 100%, 50%)
+hsl(348, 100%, 50%)
+hsl(360, 100%, 50%)
+====
+rgb(0, 0, 255)
+rgb(51, 0, 255)
+rgb(102, 0, 255)
+rgb(153, 0, 255)
+rgb(204, 0, 255)
+rgb(255, 0, 255)
+rgb(255, 0, 204)
+rgb(255, 0, 153)
+rgb(255, 0, 102)
+rgb(255, 0, 51)
+rgb(255, 0, 0)
+
+hsl(0, 20%, 50%)
+hsl(0, 60%, 50%)
+hsl(0, 100%, 50%)
+====
+rgb(153, 102, 102)
+rgb(204, 51, 51)
+rgb(255, 0, 0)
+
+hsl(60, 20%, 50%)
+hsl(60, 60%, 50%)
+hsl(60, 100%, 50%)
+====
+rgb(153, 153, 102)
+rgb(204, 204, 51)
+rgb(255, 255, 0)
+
+hsl(120, 20%, 50%)
+hsl(120, 60%, 50%)
+hsl(120, 100%, 50%)
+====
+rgb(102, 153, 102)
+rgb(51, 204, 51)
+rgb(0, 255, 0)
+
+hsl(180, 20%, 50%)
+hsl(180, 60%, 50%)
+hsl(180, 100%, 50%)
+====
+rgb(102, 153, 153)
+rgb(51, 204, 204)
+rgb(0, 255, 255)
+
+hsl(240, 20%, 50%)
+hsl(240, 60%, 50%)
+hsl(240, 100%, 50%)
+====
+rgb(102, 102, 153)
+rgb(51, 51, 204)
+rgb(0, 0, 255)
+
+hsl(300, 20%, 50%)
+hsl(300, 60%, 50%)
+hsl(300, 100%, 50%)
+====
+rgb(153, 102, 153)
+rgb(204, 51, 204)
+rgb(255, 0, 255)
+
+hsl(0, 100%, 0%)
+hsl(0, 100%, 10%)
+hsl(0, 100%, 20%)
+hsl(0, 100%, 30%)
+hsl(0, 100%, 40%)
+hsl(0, 100%, 50%)
+hsl(0, 100%, 60%)
+hsl(0, 100%, 70%)
+hsl(0, 100%, 80%)
+hsl(0, 100%, 90%)
+hsl(0, 100%, 100%)
+====
+rgb(0, 0, 0)
+rgb(51, 0, 0)
+rgb(102, 0, 0)
+rgb(153, 0, 0)
+rgb(204, 0, 0)
+rgb(255, 0, 0)
+rgb(255, 51, 51)
+rgb(255, 102, 102)
+rgb(255, 153, 153)
+rgb(255, 204, 204)
+rgb(255, 255, 255)
+
+hsl(60, 100%, 0%)
+hsl(60, 100%, 10%)
+hsl(60, 100%, 20%)
+hsl(60, 100%, 30%)
+hsl(60, 100%, 40%)
+hsl(60, 100%, 50%)
+hsl(60, 100%, 60%)
+hsl(60, 100%, 70%)
+hsl(60, 100%, 80%)
+hsl(60, 100%, 90%)
+hsl(60, 100%, 100%)
+====
+rgb(0, 0, 0)
+rgb(51, 51, 0)
+rgb(102, 102, 0)
+rgb(153, 153, 0)
+rgb(204, 204, 0)
+rgb(255, 255, 0)
+rgb(255, 255, 51)
+rgb(255, 255, 102)
+rgb(255, 255, 153)
+rgb(255, 255, 204)
+rgb(255, 255, 255)
+
+hsl(120, 100%, 0%)
+hsl(120, 100%, 10%)
+hsl(120, 100%, 20%)
+hsl(120, 100%, 30%)
+hsl(120, 100%, 40%)
+hsl(120, 100%, 50%)
+hsl(120, 100%, 60%)
+hsl(120, 100%, 70%)
+hsl(120, 100%, 80%)
+hsl(120, 100%, 90%)
+hsl(120, 100%, 100%)
+====
+rgb(0, 0, 0)
+rgb(0, 51, 0)
+rgb(0, 102, 0)
+rgb(0, 153, 0)
+rgb(0, 204, 0)
+rgb(0, 255, 0)
+rgb(51, 255, 51)
+rgb(102, 255, 102)
+rgb(153, 255, 153)
+rgb(204, 255, 204)
+rgb(255, 255, 255)
+
+hsl(180, 100%, 0%)
+hsl(180, 100%, 10%)
+hsl(180, 100%, 20%)
+hsl(180, 100%, 30%)
+hsl(180, 100%, 40%)
+hsl(180, 100%, 50%)
+hsl(180, 100%, 60%)
+hsl(180, 100%, 70%)
+hsl(180, 100%, 80%)
+hsl(180, 100%, 90%)
+hsl(180, 100%, 100%)
+====
+rgb(0, 0, 0)
+rgb(0, 51, 51)
+rgb(0, 102, 102)
+rgb(0, 153, 153)
+rgb(0, 204, 204)
+rgb(0, 255, 255)
+rgb(51, 255, 255)
+rgb(102, 255, 255)
+rgb(153, 255, 255)
+rgb(204, 255, 255)
+rgb(255, 255, 255)
+
+hsl(240, 100%, 0%)
+hsl(240, 100%, 10%)
+hsl(240, 100%, 20%)
+hsl(240, 100%, 30%)
+hsl(240, 100%, 40%)
+hsl(240, 100%, 50%)
+hsl(240, 100%, 60%)
+hsl(240, 100%, 70%)
+hsl(240, 100%, 80%)
+hsl(240, 100%, 90%)
+hsl(240, 100%, 100%)
+====
+rgb(0, 0, 0)
+rgb(0, 0, 51)
+rgb(0, 0, 102)
+rgb(0, 0, 153)
+rgb(0, 0, 204)
+rgb(0, 0, 255)
+rgb(51, 51, 255)
+rgb(102, 102, 255)
+rgb(153, 153, 255)
+rgb(204, 204, 255)
+rgb(255, 255, 255)
+
+hsl(300, 100%, 0%)
+hsl(300, 100%, 10%)
+hsl(300, 100%, 20%)
+hsl(300, 100%, 30%)
+hsl(300, 100%, 40%)
+hsl(300, 100%, 50%)
+hsl(300, 100%, 60%)
+hsl(300, 100%, 70%)
+hsl(300, 100%, 80%)
+hsl(300, 100%, 90%)
+hsl(300, 100%, 100%)
+====
+rgb(0, 0, 0)
+rgb(51, 0, 51)
+rgb(102, 0, 102)
+rgb(153, 0, 153)
+rgb(204, 0, 204)
+rgb(255, 0, 255)
+rgb(255, 51, 255)
+rgb(255, 102, 255)
+rgb(255, 153, 255)
+rgb(255, 204, 255)
+rgb(255, 255, 255)
diff --git a/backends/css/gems/sass-3.2.12/test/sass/engine_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/engine_test.rb
new file mode 100755
index 0000000..a325167
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/engine_test.rb
@@ -0,0 +1,3243 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+require File.dirname(__FILE__) + '/../test_helper'
+require File.dirname(__FILE__) + '/test_helper'
+require 'sass/engine'
+require 'stringio'
+require 'mock_importer'
+require 'pathname'
+
+module Sass::Script::Functions::UserFunctions
+  def option(name)
+    Sass::Script::String.new(@options[name.value.to_sym].to_s)
+  end
+end
+
+class SassEngineTest < Test::Unit::TestCase
+  FAKE_FILE_NAME = __FILE__.gsub(/rb$/,"sass")
+  # A map of erroneous Sass documents to the error messages they should produce.
+  # The error messages may be arrays;
+  # if so, the second element should be the line number that should be reported for the error.
+  # If this isn't provided, the tests will assume the line number should be the last line of the document.
+  EXCEPTION_MAP = {
+    "$a: 1 + " => 'Invalid CSS after "1 +": expected expression (e.g. 1px, bold), was ""',
+    "$a: 1 + 2 +" => 'Invalid CSS after "1 + 2 +": expected expression (e.g. 1px, bold), was ""',
+    "$a: 1 + 2 + %" => 'Invalid CSS after "1 + 2 + ": expected expression (e.g. 1px, bold), was "%"',
+    "$a: foo(\"bar\"" => 'Invalid CSS after "foo("bar"": expected ")", was ""',
+    "$a: 1 }" => 'Invalid CSS after "1 ": expected expression (e.g. 1px, bold), was "}"',
+    "$a: 1 }foo\"" => 'Invalid CSS after "1 ": expected expression (e.g. 1px, bold), was "}foo""',
+    ":" => 'Invalid property: ":".',
+    ": a" => 'Invalid property: ": a".',
+    "a\n  :b" => <<MSG,
+Invalid property: ":b" (no value).
+If ":b" should be a selector, use "\\:b" instead.
+MSG
+    "a\n  b:" => 'Invalid property: "b:" (no value).',
+    "a\n  :b: c" => 'Invalid property: ":b: c".',
+    "a\n  :b:c d" => 'Invalid property: ":b:c d".',
+    "a\n  :b c;" => 'Invalid CSS after "c": expected expression (e.g. 1px, bold), was ";"',
+    "a\n  b: c;" => 'Invalid CSS after "c": expected expression (e.g. 1px, bold), was ";"',
+    ".foo ^bar\n  a: b" => ['Invalid CSS after ".foo ": expected selector, was "^bar"', 1],
+    "a\n  @extend .foo ^bar" => 'Invalid CSS after ".foo ": expected selector, was "^bar"',
+    "a\n  @extend .foo .bar" => "Can't extend .foo .bar: can't extend nested selectors",
+    "a\n  @extend >" => "Can't extend >: invalid selector",
+    "a\n  @extend &.foo" => "Can't extend &.foo: can't extend parent selectors",
+    "a: b" => 'Properties are only allowed within rules, directives, mixin includes, or other properties.',
+    ":a b" => 'Properties are only allowed within rules, directives, mixin includes, or other properties.',
+    "$" => 'Invalid variable: "$".',
+    "$a" => 'Invalid variable: "$a".',
+    "$ a" => 'Invalid variable: "$ a".',
+    "$a b" => 'Invalid variable: "$a b".',
+    "$a: 1b + 2c" => "Incompatible units: 'c' and 'b'.",
+    "$a: 1b < 2c" => "Incompatible units: 'c' and 'b'.",
+    "$a: 1b > 2c" => "Incompatible units: 'c' and 'b'.",
+    "$a: 1b <= 2c" => "Incompatible units: 'c' and 'b'.",
+    "$a: 1b >= 2c" => "Incompatible units: 'c' and 'b'.",
+    "a\n  b: 1b * 2c" => "2b*c isn't a valid CSS value.",
+    "a\n  b: 1b % 2c" => "Cannot modulo by a number with units: 2c.",
+    "$a: 2px + #ccc" => "Cannot add a number with units (2px) to a color (#cccccc).",
+    "$a: #ccc + 2px" => "Cannot add a number with units (2px) to a color (#cccccc).",
+    "& a\n  :b c" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 1],
+    "a\n  :b\n    c" => "Illegal nesting: Only properties may be nested beneath properties.",
+    "$a: b\n  :c d\n" => "Illegal nesting: Nothing may be nested beneath variable declarations.",
+    "$a: b\n  :c d\n" => "Illegal nesting: Nothing may be nested beneath variable declarations.",
+    "@import templates/basic\n  foo" => "Illegal nesting: Nothing may be nested beneath import directives.",
+    "foo\n  @import foo.css" => "CSS import directives may only be used at the root of a document.",
+    "@if true\n  @import foo" => "Import directives may not be used within control directives or mixins.",
+    "@if true\n  .foo\n    @import foo" => "Import directives may not be used within control directives or 
mixins.",
+    "@mixin foo\n  @import foo" => "Import directives may not be used within control directives or mixins.",
+    "@mixin foo\n  .foo\n    @import foo" => "Import directives may not be used within control directives or 
mixins.",
+    "@import foo;" => "Invalid @import: expected end of line, was \";\".",
+    '$foo: "bar" "baz" !' => %Q{Invalid CSS after ""bar" "baz" ": expected expression (e.g. 1px, bold), was 
"!"},
+    '$foo: "bar" "baz" $' => %Q{Invalid CSS after ""bar" "baz" ": expected expression (e.g. 1px, bold), was 
"$"}, #'
+    "=foo\n  :color red\n.bar\n  +bang" => "Undefined mixin 'bang'.",
+    "=foo\n  :color red\n.bar\n  +bang_bop" => "Undefined mixin 'bang_bop'.",
+    "=foo\n  :color red\n.bar\n  +bang-bop" => "Undefined mixin 'bang-bop'.",
+    ".foo\n  =foo\n    :color red\n.bar\n  +foo" => "Undefined mixin 'foo'.",
+    "    a\n  b: c" => ["Indenting at the beginning of the document is illegal.", 1],
+    " \n   \n\t\n  a\n  b: c" => ["Indenting at the beginning of the document is illegal.", 4],
+    "a\n  b: c\n b: c" => ["Inconsistent indentation: 1 space was used for indentation, but the rest of the 
document was indented using 2 spaces.", 3],
+    "a\n  b: c\na\n b: c" => ["Inconsistent indentation: 1 space was used for indentation, but the rest of 
the document was indented using 2 spaces.", 4],
+    "a\n\t\tb: c\n\tb: c" => ["Inconsistent indentation: 1 tab was used for indentation, but the rest of the 
document was indented using 2 tabs.", 3],
+    "a\n  b: c\n   b: c" => ["Inconsistent indentation: 3 spaces were used for indentation, but the rest of 
the document was indented using 2 spaces.", 3],
+    "a\n  b: c\n  a\n   d: e" => ["Inconsistent indentation: 3 spaces were used for indentation, but the 
rest of the document was indented using 2 spaces.", 4],
+    "a\n  b: c\na\n    d: e" => ["The line was indented 2 levels deeper than the previous line.", 4],
+    "a\n  b: c\n  a\n        d: e" => ["The line was indented 3 levels deeper than the previous line.", 4],
+    "a\n \tb: c" => ["Indentation can't use both tabs and spaces.", 2],
+    "=a(" => 'Invalid CSS after "(": expected variable (e.g. $foo), was ""',
+    "=a(b)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was "b)"',
+    "=a(,)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was ",)"',
+    "=a($)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was "$)"',
+    "=a($foo bar)" => 'Invalid CSS after "($foo ": expected ")", was "bar)"',
+    "=foo\n  bar: baz\n+foo" => ["Properties are only allowed within rules, directives, mixin includes, or 
other properties.", 2],
+    "a-\#{$b\n  c: d" => ['Invalid CSS after "a-#{$b": expected "}", was ""', 1],
+    "=a($b: 1, $c)" => "Required argument $c must come before any optional arguments.",
+    "=a($b: 1)\n  a: $b\ndiv\n  +a(1,2)" => "Mixin a takes 1 argument but 2 were passed.",
+    "=a($b: 1)\n  a: $b\ndiv\n  +a(1,$c: 3)" => "Mixin a doesn't have an argument named $c.",
+    "=a($b)\n  a: $b\ndiv\n  +a" => "Mixin a is missing argument $b.",
+    "@function foo()\n  1 + 2" => "Functions can only contain variable declarations and control directives.",
+    "@function foo()\n  foo: bar" => "Functions can only contain variable declarations and control 
directives.",
+    "@function foo()\n  foo: bar\n  @return 3" => ["Functions can only contain variable declarations and 
control directives.", 2],
+    "@function foo\n  @return 1" => ['Invalid CSS after "": expected "(", was ""', 1],
+    "@function foo(\n  @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was ""', 1],
+    "@function foo(b)\n  @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was "b)"', 1],
+    "@function foo(,)\n  @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was ",)"', 1],
+    "@function foo($)\n  @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was "$)"', 1],
+    "@function foo()\n  @return" => 'Invalid @return: expected expression.',
+    "@function foo()\n  @return 1\n    $var: val" => 'Illegal nesting: Nothing may be nested beneath return 
directives.',
+    "@function foo($a)\n  @return 1\na\n  b: foo()" => 'Function foo is missing argument $a.',
+    "@function foo()\n  @return 1\na\n  b: foo(2)" => 'Function foo takes 0 arguments but 1 was passed.',
+    "@function foo()\n  @return 1\na\n  b: foo($a: 1)" => "Function foo doesn't have an argument named $a.",
+    "@function foo()\n  @return 1\na\n  b: foo($a: 1, $b: 2)" => "Function foo doesn't have the following 
arguments: $a, $b.",
+    "@return 1" => '@return may only be used within a function.',
+    "@if true\n  @return 1" => '@return may only be used within a function.',
+    "@mixin foo\n  @return 1\n include foo" => ['@return may only be used within a function.', 2],
+    "@else\n  a\n    b: c" => ["@else must come after @if.", 1],
+    "@if false\n else foo" => "Invalid else directive '@else foo': expected 'if <expr>'.",
+    "@if false\n else if " => "Invalid else directive '@else if': expected 'if <expr>'.",
+    "a\n  $b: 12\nc\n  d: $b" => 'Undefined variable: "$b".',
+    "=foo\n  $b: 12\nc\n  +foo\n  d: $b" => 'Undefined variable: "$b".',
+    "c\n  d: $b-foo" => 'Undefined variable: "$b-foo".',
+    "c\n  d: $b_foo" => 'Undefined variable: "$b_foo".',
+    '@for $a from "foo" to 1' => '"foo" is not an integer.',
+    '@for $a from 1 to "2"' => '"2" is not an integer.',
+    '@for $a from 1 to "foo"' => '"foo" is not an integer.',
+    '@for $a from 1 to 1.232323' => '1.23232 is not an integer.',
+    '@for $a from 1px to 3em' => "Incompatible units: 'em' and 'px'.",
+    '@if' => "Invalid if directive '@if': expected expression.",
+    '@while' => "Invalid while directive '@while': expected expression.",
+    '@debug' => "Invalid debug directive '@debug': expected expression.",
+    %Q{ debug "a message"\n  "nested message"} => "Illegal nesting: Nothing may be nested beneath debug 
directives.",
+    '@warn' => "Invalid warn directive '@warn': expected expression.",
+    %Q{ warn "a message"\n  "nested message"} => "Illegal nesting: Nothing may be nested beneath warn 
directives.",
+    "/* foo\n    bar\n  baz" => "Inconsistent indentation: previous line was indented by 4 spaces, but this 
line was indented by 2 spaces.",
+    '+foo(1 + 1: 2)' => 'Invalid CSS after "(1 + 1": expected comma, was ": 2)"',
+    '+foo($var: )' => 'Invalid CSS after "($var: ": expected mixin argument, was ")"',
+    '+foo($var: a, $var: b)' => 'Keyword argument "$var" passed more than once',
+    '+foo($var-var: a, $var_var: b)' => 'Keyword argument "$var_var" passed more than once',
+    '+foo($var_var: a, $var-var: b)' => 'Keyword argument "$var-var" passed more than once',
+    "a\n  b: foo(1 + 1: 2)" => 'Invalid CSS after "foo(1 + 1": expected comma, was ": 2)"',
+    "a\n  b: foo($var: )" => 'Invalid CSS after "foo($var: ": expected function argument, was ")"',
+    "a\n  b: foo($var: a, $var: b)" => 'Keyword argument "$var" passed more than once',
+    "a\n  b: foo($var-var: a, $var_var: b)" => 'Keyword argument "$var_var" passed more than once',
+    "a\n  b: foo($var_var: a, $var-var: b)" => 'Keyword argument "$var-var" passed more than once',
+    "@if foo\n  @extend .bar" => ["Extend directives may only be used within rules.", 2],
+    "$var: true\n while $var\n  @extend .bar\n  $var: false" => ["Extend directives may only be used within 
rules.", 3],
+    "@for $i from 0 to 1\n  @extend .bar" => ["Extend directives may only be used within rules.", 2],
+    "@mixin foo\n  @extend  bar\n include foo" => ["Extend directives may only be used within rules.", 2],
+    "foo\n  &a\n    b: c" => ["Invalid CSS after \"&\": expected \"{\", was \"a\"\n\n\"a\" may only be used 
at the beginning of a compound selector.", 2],
+    "foo\n  &1\n    b: c" => ["Invalid CSS after \"&\": expected \"{\", was \"1\"\n\n\"1\" may only be used 
at the beginning of a compound selector.", 2],
+    "foo %\n  a: b" => ['Invalid CSS after "foo %": expected placeholder name, was ""', 1],
+    "=foo\n  @content error" => "Invalid content directive. Trailing characters found: \"error\".",
+    "=foo\n  @content\n    b: c" => "Illegal nesting: Nothing may be nested beneath @content directives.",
+    "@content" => '@content may only be used within a mixin.',
+    "=simple\n  .simple\n    color: red\n+simple\n  color: blue" => ['Mixin "simple" does not accept a 
content block.', 4],
+    "@import \"foo\" // bar" => "Invalid CSS after \"\"foo\" \": expected media query list, was \"// bar\"",
+
+    # Regression tests
+    "a\n  b:\n    c\n    d" => ["Illegal nesting: Only properties may be nested beneath properties.", 3],
+    "& foo\n  bar: baz\n  blat: bang" => ["Base-level rules cannot contain the parent-selector-referencing 
character '&'.", 1],
+    "a\n  b: c\n& foo\n  bar: baz\n  blat: bang" => ["Base-level rules cannot contain the 
parent-selector-referencing character '&'.", 3],
+  }
+
+  def teardown
+    clean_up_sassc
+  end
+
+  def test_basic_render
+    renders_correctly "basic", { :style => :compact }
+  end
+
+  def test_empty_render
+    assert_equal "", render("")
+  end
+
+  def test_multiple_calls_to_render
+    sass = Sass::Engine.new("a\n  b: c")
+    assert_equal sass.render, sass.render
+  end
+
+  def test_alternate_styles
+    renders_correctly "expanded", { :style => :expanded }
+    renders_correctly "compact", { :style => :compact }
+    renders_correctly "nested", { :style => :nested }
+    renders_correctly "compressed", { :style => :compressed }
+  end
+
+  def test_compile
+    assert_equal "div { hello: world; }\n", Sass.compile("$who: world\ndiv\n  hello: $who", :syntax => 
:sass, :style => :compact)
+    assert_equal "div { hello: world; }\n", Sass.compile("$who: world; div { hello: $who }", :style => 
:compact)
+  end
+
+  def test_compile_file
+    FileUtils.mkdir_p(absolutize("tmp"))
+    open(absolutize("tmp/test_compile_file.sass"), "w") {|f| f.write("$who: world\ndiv\n  hello: $who")}
+    open(absolutize("tmp/test_compile_file.scss"), "w") {|f| f.write("$who: world; div { hello: $who }")}
+    assert_equal "div { hello: world; }\n", Sass.compile_file(absolutize("tmp/test_compile_file.sass"), 
:style => :compact)
+    assert_equal "div { hello: world; }\n", Sass.compile_file(absolutize("tmp/test_compile_file.scss"), 
:style => :compact)
+  ensure
+    FileUtils.rm_rf(absolutize("tmp"))
+  end
+
+  def test_compile_file_to_css_file
+    FileUtils.mkdir_p(absolutize("tmp"))
+    open(absolutize("tmp/test_compile_file.sass"), "w") {|f| f.write("$who: world\ndiv\n  hello: $who")}
+    open(absolutize("tmp/test_compile_file.scss"), "w") {|f| f.write("$who: world; div { hello: $who }")}
+    Sass.compile_file(absolutize("tmp/test_compile_file.sass"), 
absolutize("tmp/test_compile_file_sass.css"), :style => :compact)
+    Sass.compile_file(absolutize("tmp/test_compile_file.scss"), 
absolutize("tmp/test_compile_file_scss.css"), :style => :compact)
+    assert_equal "div { hello: world; }\n", File.read(absolutize("tmp/test_compile_file_sass.css"))
+    assert_equal "div { hello: world; }\n", File.read(absolutize("tmp/test_compile_file_scss.css"))
+  ensure
+    FileUtils.rm_rf(absolutize("tmp"))
+  end
+  
+  def test_flexible_tabulation
+    assert_equal("p {\n  a: b; }\n  p q {\n    c: d; }\n",
+                 render("p\n a: b\n q\n  c: d\n"))
+    assert_equal("p {\n  a: b; }\n  p q {\n    c: d; }\n",
+                 render("p\n\ta: b\n\tq\n\t\tc: d\n"))
+  end
+
+  def test_import_same_name_different_ext
+    assert_warning <<WARNING do
+WARNING: On line 1 of test_import_same_name_different_ext_inline.sass:
+  It's not clear which file to import for '@import "same_name_different_ext"'.
+  Candidates:
+    same_name_different_ext.sass
+    same_name_different_ext.scss
+  For now I'll choose same_name_different_ext.sass.
+  This will be an error in future versions of Sass.
+WARNING
+      options = {:load_paths => [File.dirname(__FILE__) + '/templates/']}
+      munge_filename options
+      result = Sass::Engine.new("@import 'same_name_different_ext'", options).render
+      assert_equal(<<CSS, result)
+.foo {
+  ext: sass; }
+CSS
+    end
+  end
+
+  def test_import_same_name_different_partiality
+    assert_warning <<WARNING do
+WARNING: On line 1 of test_import_same_name_different_partiality_inline.sass:
+  It's not clear which file to import for '@import "same_name_different_partiality"'.
+  Candidates:
+    _same_name_different_partiality.scss
+    same_name_different_partiality.scss
+  For now I'll choose _same_name_different_partiality.scss.
+  This will be an error in future versions of Sass.
+WARNING
+      options = {:load_paths => [File.dirname(__FILE__) + '/templates/']}
+      munge_filename options
+      result = Sass::Engine.new("@import 'same_name_different_partiality'", options).render
+      assert_equal(<<CSS, result)
+.foo {
+  partial: yes; }
+CSS
+    end
+  end
+
+  EXCEPTION_MAP.each do |key, value|
+    define_method("test_exception (#{key.inspect})") do
+      line = 10
+      begin
+        silence_warnings {Sass::Engine.new(key, :filename => FAKE_FILE_NAME, :line => line).render}
+      rescue Sass::SyntaxError => err
+        value = [value] unless value.is_a?(Array)
+
+        assert_equal(value.first.rstrip, err.message, "Line: #{key}")
+        assert_equal(FAKE_FILE_NAME, err.sass_filename)
+        assert_equal((value[1] || key.split("\n").length) + line - 1, err.sass_line, "Line: #{key}")
+        assert_match(/#{Regexp.escape(FAKE_FILE_NAME)}:[0-9]+/, err.backtrace[0], "Line: #{key}")
+      else
+        assert(false, "Exception not raised for\n#{key}")
+      end
+    end
+  end
+
+  def test_exception_line
+    to_render = <<SASS
+rule
+  :prop val
+  // comment!
+
+  :broken
+SASS
+    begin
+      Sass::Engine.new(to_render).render
+    rescue Sass::SyntaxError => err
+      assert_equal(5, err.sass_line)
+    else
+      assert(false, "Exception not raised for '#{to_render}'!")
+    end
+  end
+
+  def test_exception_location
+    to_render = <<SASS
+rule
+  :prop val
+  // comment!
+
+  :broken
+SASS
+    begin
+      Sass::Engine.new(to_render, :filename => FAKE_FILE_NAME, :line => (__LINE__-7)).render
+    rescue Sass::SyntaxError => err
+      assert_equal(FAKE_FILE_NAME, err.sass_filename)
+      assert_equal((__LINE__-6), err.sass_line)
+    else
+      assert(false, "Exception not raised for '#{to_render}'!")
+    end
+  end
+
+  def test_imported_exception
+    [1, 2, 3, 4].each do |i|
+      begin
+        Sass::Engine.new("@import bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
+      rescue Sass::SyntaxError => err
+        assert_equal(2, err.sass_line)
+        assert_match(/(\/|^)bork#{i}\.sass$/, err.sass_filename)
+
+        assert_hash_has(err.sass_backtrace.first,
+          :filename => err.sass_filename, :line => err.sass_line)
+
+        assert_nil(err.sass_backtrace[1][:filename])
+        assert_equal(1, err.sass_backtrace[1][:line])
+
+        assert_match(/(\/|^)bork#{i}\.sass:2$/, err.backtrace.first)
+        assert_equal("(sass):1", err.backtrace[1])
+      else
+        assert(false, "Exception not raised for imported template: bork#{i}")
+      end
+    end
+  end
+
+  def test_double_imported_exception
+    [1, 2, 3, 4].each do |i|
+      begin
+        Sass::Engine.new("@import nested_bork#{i}", :load_paths => [File.dirname(__FILE__) + 
'/templates/']).render
+      rescue Sass::SyntaxError => err
+        assert_equal(2, err.sass_line)
+        assert_match(/(\/|^)bork#{i}\.sass$/, err.sass_filename)
+
+        assert_hash_has(err.sass_backtrace.first,
+          :filename => err.sass_filename, :line => err.sass_line)
+
+        assert_match(/(\/|^)nested_bork#{i}\.sass$/, err.sass_backtrace[1][:filename])
+        assert_equal(2, err.sass_backtrace[1][:line])
+
+        assert_nil(err.sass_backtrace[2][:filename])
+        assert_equal(1, err.sass_backtrace[2][:line])
+
+        assert_match(/(\/|^)bork#{i}\.sass:2$/, err.backtrace.first)
+        assert_match(/(\/|^)nested_bork#{i}\.sass:2$/, err.backtrace[1])
+        assert_equal("(sass):1", err.backtrace[2])
+      else
+        assert(false, "Exception not raised for imported template: bork#{i}")
+      end
+    end
+  end
+
+  def test_selector_tracing
+    actual_css = render(<<-SCSS, :syntax => :scss, :trace_selectors => true)
+      @mixin mixed {
+        .mixed { color: red; }
+      }
+      .context {
+        @include mixed;
+      }
+    SCSS
+    assert_equal(<<CSS,actual_css)
+/* on line 2 of test_selector_tracing_inline.scss, in `mixed'
+   from line 5 of test_selector_tracing_inline.scss */
+.context .mixed {
+  color: red; }
+CSS
+  end
+
+  def test_mixin_exception
+    render(<<SASS)
+=error-mixin($a)
+  color: $a * 1em * 1px
+
+=outer-mixin($a)
+  +error-mixin($a)
+
+.error
+  +outer-mixin(12)
+SASS
+    assert(false, "Exception not raised")
+  rescue Sass::SyntaxError => err
+    assert_equal(2, err.sass_line)
+    assert_equal(filename_for_test, err.sass_filename)
+    assert_equal("error-mixin", err.sass_mixin)
+
+    assert_hash_has(err.sass_backtrace.first, :line => err.sass_line,
+      :filename => err.sass_filename, :mixin => err.sass_mixin)
+    assert_hash_has(err.sass_backtrace[1], :line => 5,
+      :filename => filename_for_test, :mixin => "outer-mixin")
+    assert_hash_has(err.sass_backtrace[2], :line => 8,
+      :filename => filename_for_test, :mixin => nil)
+
+    assert_equal("#{filename_for_test}:2:in `error-mixin'", err.backtrace.first)
+    assert_equal("#{filename_for_test}:5:in `outer-mixin'", err.backtrace[1])
+    assert_equal("#{filename_for_test}:8", err.backtrace[2])
+  end
+
+  def test_mixin_callsite_exception
+    render(<<SASS)
+=one-arg-mixin($a)
+  color: $a
+
+=outer-mixin($a)
+  +one-arg-mixin($a, 12)
+
+.error
+  +outer-mixin(12)
+SASS
+    assert(false, "Exception not raised")
+  rescue Sass::SyntaxError => err
+    assert_hash_has(err.sass_backtrace.first, :line => 5,
+      :filename => filename_for_test, :mixin => "one-arg-mixin")
+    assert_hash_has(err.sass_backtrace[1], :line => 5,
+      :filename => filename_for_test, :mixin => "outer-mixin")
+    assert_hash_has(err.sass_backtrace[2], :line => 8,
+      :filename => filename_for_test, :mixin => nil)
+  end
+
+  def test_mixin_exception_cssize
+    render(<<SASS)
+=parent-ref-mixin
+  & foo
+    a: b
+
+=outer-mixin
+  +parent-ref-mixin
+
++outer-mixin
+SASS
+    assert(false, "Exception not raised")
+  rescue Sass::SyntaxError => err
+    assert_hash_has(err.sass_backtrace.first, :line => 2,
+      :filename => filename_for_test, :mixin => "parent-ref-mixin")
+    assert_hash_has(err.sass_backtrace[1], :line => 6,
+      :filename => filename_for_test, :mixin => "outer-mixin")
+    assert_hash_has(err.sass_backtrace[2], :line => 8,
+      :filename => filename_for_test, :mixin => nil)
+  end
+
+  def test_mixin_and_import_exception
+    Sass::Engine.new("@import nested_mixin_bork", :load_paths => [File.dirname(__FILE__) + 
'/templates/']).render
+    assert(false, "Exception not raised")
+  rescue Sass::SyntaxError => err
+    assert_match(/(\/|^)nested_mixin_bork\.sass$/, err.sass_backtrace.first[:filename])
+    assert_hash_has(err.sass_backtrace.first, :mixin => "error-mixin", :line => 4)
+
+    assert_match(/(\/|^)mixin_bork\.sass$/, err.sass_backtrace[1][:filename])
+    assert_hash_has(err.sass_backtrace[1], :mixin => "outer-mixin", :line => 2)
+
+    assert_match(/(\/|^)mixin_bork\.sass$/, err.sass_backtrace[2][:filename])
+    assert_hash_has(err.sass_backtrace[2], :mixin => nil, :line => 5)
+
+    assert_match(/(\/|^)nested_mixin_bork\.sass$/, err.sass_backtrace[3][:filename])
+    assert_hash_has(err.sass_backtrace[3], :mixin => nil, :line => 6)
+
+    assert_hash_has(err.sass_backtrace[4], :filename => nil, :mixin => nil, :line => 1)
+  end
+
+  def test_basic_mixin_loop_exception
+    render <<SASS
+ mixin foo
+  @include foo
+ include foo
+SASS
+    assert(false, "Exception not raised")
+  rescue Sass::SyntaxError => err
+    assert_equal("An @include loop has been found: foo includes itself", err.message)
+    assert_hash_has(err.sass_backtrace[0], :mixin => "foo", :line => 2)
+  end
+
+  def test_double_mixin_loop_exception
+    render <<SASS
+ mixin foo
+  @include bar
+ mixin bar
+  @include foo
+ include foo
+SASS
+    assert(false, "Exception not raised")
+  rescue Sass::SyntaxError => err
+    assert_equal(<<MESSAGE.rstrip, err.message)
+An @include loop has been found:
+    foo includes bar
+    bar includes foo
+MESSAGE
+    assert_hash_has(err.sass_backtrace[0], :mixin => "bar", :line => 4)
+    assert_hash_has(err.sass_backtrace[1], :mixin => "foo", :line => 2)
+  end
+
+  def test_deep_mixin_loop_exception
+    render <<SASS
+ mixin foo
+  @include bar
+
+ mixin bar
+  @include baz
+
+ mixin baz
+  @include foo
+
+ include foo
+SASS
+    assert(false, "Exception not raised")
+  rescue Sass::SyntaxError => err
+    assert_equal(<<MESSAGE.rstrip, err.message)
+An @include loop has been found:
+    foo includes bar
+    bar includes baz
+    baz includes foo
+MESSAGE
+    assert_hash_has(err.sass_backtrace[0], :mixin => "baz", :line => 8)
+    assert_hash_has(err.sass_backtrace[1], :mixin => "bar", :line => 5)
+    assert_hash_has(err.sass_backtrace[2], :mixin => "foo", :line => 2)
+  end
+
+  def test_mixin_loop_with_content
+    render <<SASS
+=foo
+  @content
+=bar
+  +foo
+    +bar
++bar
+SASS
+    assert(false, "Exception not raised")
+  rescue Sass::SyntaxError => err
+    assert_equal("An @include loop has been found: bar includes itself", err.message)
+    assert_hash_has(err.sass_backtrace[0], :mixin => "@content", :line => 5)
+  end
+
+  def test_basic_import_loop_exception
+    import = filename_for_test
+    importer = MockImporter.new
+    importer.add_import(import, "@import '#{import}'")
+
+    engine = Sass::Engine.new("@import '#{import}'", :filename => import,
+      :load_paths => [importer])
+
+    assert_raise_message(Sass::SyntaxError, <<ERR.rstrip) {engine.render}
+An @import loop has been found: #{import} imports itself
+ERR
+  end
+
+  def test_double_import_loop_exception
+    importer = MockImporter.new
+    importer.add_import("foo", "@import 'bar'")
+    importer.add_import("bar", "@import 'foo'")
+
+    engine = Sass::Engine.new('@import "foo"', :filename => filename_for_test,
+      :load_paths => [importer], :importer => importer)
+
+    assert_raise_message(Sass::SyntaxError, <<ERR.rstrip) {engine.render}
+An @import loop has been found:
+    #{filename_for_test} imports foo
+    foo imports bar
+    bar imports foo
+ERR
+  end
+
+  def test_deep_import_loop_exception
+    importer = MockImporter.new
+    importer.add_import("foo", "@import 'bar'")
+    importer.add_import("bar", "@import 'baz'")
+    importer.add_import("baz", "@import 'foo'")
+
+    engine = Sass::Engine.new('@import "foo"', :filename => filename_for_test,
+      :load_paths => [importer], :importer => importer)
+
+    assert_raise_message(Sass::SyntaxError, <<ERR.rstrip) {engine.render}
+An @import loop has been found:
+    #{filename_for_test} imports foo
+    foo imports bar
+    bar imports baz
+    baz imports foo
+ERR
+  end
+
+  def test_exception_css_with_offset
+    opts = {:full_exception => true, :line => 362}
+    render(("a\n  b: c\n" * 10) + "d\n  e:\n" + ("f\n  g: h\n" * 10), opts)
+  rescue Sass::SyntaxError => e
+    assert_equal(<<CSS, Sass::SyntaxError.exception_to_css(e, opts).split("\n")[0..15].join("\n"))
+/*
+Syntax error: Invalid property: "e:" (no value).
+        on line 383 of test_exception_css_with_offset_inline.sass
+
+378: a
+379:   b: c
+380: a
+381:   b: c
+382: d
+383:   e:
+384: f
+385:   g: h
+386: f
+387:   g: h
+388: f
+CSS
+  else
+    assert(false, "Exception not raised for test_exception_css_with_offset")
+  end
+
+  def test_exception_css_with_mixins
+    opts = {:full_exception => true}
+    render(<<SASS, opts)
+=error-mixin($a)
+  color: $a * 1em * 1px
+
+=outer-mixin($a)
+  +error-mixin($a)
+
+.error
+  +outer-mixin(12)
+SASS
+  rescue Sass::SyntaxError => e
+    assert_equal(<<CSS, Sass::SyntaxError.exception_to_css(e, opts).split("\n")[0..13].join("\n"))
+/*
+Syntax error: 12em*px isn't a valid CSS value.
+        on line 2 of test_exception_css_with_mixins_inline.sass, in `error-mixin'
+        from line 5 of test_exception_css_with_mixins_inline.sass, in `outer-mixin'
+        from line 8 of test_exception_css_with_mixins_inline.sass
+
+1: =error-mixin($a)
+2:   color: $a * 1em * 1px
+3: 
+4: =outer-mixin($a)
+5:   +error-mixin($a)
+6: 
+7: .error
+CSS
+  else
+    assert(false, "Exception not raised")
+  end
+
+  def test_cssize_exception_css
+    opts = {:full_exception => true}
+    render(<<SASS, opts)
+.filler
+  stuff: "stuff!"
+
+a: b
+
+.more.filler
+  a: b
+SASS
+  rescue Sass::SyntaxError => e
+    assert_equal(<<CSS, Sass::SyntaxError.exception_to_css(e, opts).split("\n")[0..11].join("\n"))
+/*
+Syntax error: Properties are only allowed within rules, directives, mixin includes, or other properties.
+        on line 4 of test_cssize_exception_css_inline.sass
+
+1: .filler
+2:   stuff: "stuff!"
+3: 
+4: a: b
+5: 
+6: .more.filler
+7:   a: b
+CSS
+  else
+    assert(false, "Exception not raised")
+  end
+
+  def test_css_import
+    assert_equal("@import url(./fonts.css);\n", render("@import \"./fonts.css\""))
+  end
+
+  def test_http_import
+    assert_equal("@import url(http://fonts.googleapis.com/css?family=Droid+Sans);\n",
+      render("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\"";))
+  end
+
+  def test_protocol_relative_import
+    assert_equal("@import url(//fonts.googleapis.com/css?family=Droid+Sans);\n",
+      render("@import \"//fonts.googleapis.com/css?family=Droid+Sans\""))
+  end
+
+  def test_import_with_interpolation
+    assert_equal(<<CSS, render(<<SASS))
+ import url("http://fonts.googleapis.com/css?family=Droid+Sans";);
+CSS
+$family: unquote("Droid+Sans")
+ import url("http://fonts.googleapis.com/css?family=\#{$family}";)
+SASS
+  end
+
+  def test_import_with_dynamic_media_query
+    assert_equal(<<CSS, render(<<SASS))
+ import "foo" print and (-webkit-min-device-pixel-ratio-foo: 25);
+CSS
+$media: print
+$key: -webkit-min-device-pixel-ratio
+$value: 20
+ import "foo" \#{$media} and ($key + "-foo": $value + 5)
+SASS
+  end
+
+  def test_url_import
+    assert_equal("@import url(fonts.sass);\n", render("@import url(fonts.sass)"))
+  end
+
+  def test_sass_import
+    sassc_file = sassc_path("importee")
+    assert !File.exists?(sassc_file)
+    renders_correctly "import", { :style => :compact, :load_paths => [File.dirname(__FILE__) + "/templates"] 
}
+    assert File.exists?(sassc_file)
+  end
+
+  def test_sass_pathname_import
+    sassc_file = sassc_path("importee")
+    assert !File.exists?(sassc_file)
+    renders_correctly("import",
+      :style => :compact,
+      :load_paths => [Pathname.new(File.dirname(__FILE__) + "/templates")])
+    assert File.exists?(sassc_file)
+  end
+
+  def test_import_from_global_load_paths
+    importer = MockImporter.new
+    importer.add_import("imported", "div{color:red}")
+    Sass.load_paths << importer
+
+    assert_equal "div {\n  color: red; }\n", Sass::Engine.new('@import "imported"', :importer => 
importer).render
+  ensure
+    Sass.load_paths.clear
+  end
+
+  def test_nonexistent_import
+    assert_raise_message(Sass::SyntaxError, <<ERR.rstrip) do
+File to import not found or unreadable: nonexistent.sass.
+Load path: #{Dir.pwd}
+ERR
+      render("@import nonexistent.sass")
+    end
+  end
+
+  def test_nonexistent_extensionless_import
+    assert_raise_message(Sass::SyntaxError, <<ERR.rstrip) do
+File to import not found or unreadable: nonexistent.
+Load path: #{Dir.pwd}
+ERR
+      render("@import nonexistent")
+    end
+  end
+
+  def test_no_cache
+    assert !File.exists?(sassc_path("importee"))
+    renders_correctly("import", {
+        :style => :compact, :cache => false,
+        :load_paths => [File.dirname(__FILE__) + "/templates"],
+      })
+    assert !File.exists?(sassc_path("importee"))
+  end
+
+  def test_import_in_rule
+    assert_equal(<<CSS, render(<<SASS, :load_paths => [File.dirname(__FILE__) + '/templates/']))
+.foo #foo {
+  background-color: #bbaaff; }
+
+.bar {
+  a: b; }
+  .bar #foo {
+    background-color: #bbaaff; }
+CSS
+.foo
+  @import partial
+
+.bar
+  a: b
+  @import partial
+SASS
+  end
+
+  def test_units
+    renders_correctly "units"
+  end
+
+  def test_default_function
+    assert_equal(<<CSS, render(<<SASS))
+foo {
+  bar: url("foo.png"); }
+CSS
+foo
+  bar: url("foo.png")
+SASS
+    assert_equal("foo {\n  bar: url(); }\n", render("foo\n  bar: url()\n"));
+  end
+
+  def test_string_minus
+    assert_equal("foo {\n  bar: baz-boom-bat; }\n", render(%Q{foo\n  bar: baz-boom-bat}))
+    assert_equal("foo {\n  bar: -baz-boom; }\n", render(%Q{foo\n  bar: -baz-boom}))
+  end
+
+  def test_string_div
+    assert_equal("foo {\n  bar: baz/boom/bat; }\n", render(%Q{foo\n  bar: baz/boom/bat}))
+    assert_equal("foo {\n  bar: /baz/boom; }\n", render(%Q{foo\n  bar: /baz/boom}))
+  end
+
+  def test_basic_multiline_selector
+    assert_equal("#foo #bar,\n#baz #boom {\n  foo: bar; }\n",
+                 render("#foo #bar,\n#baz #boom\n  :foo bar"))
+    assert_equal("#foo #bar,\n#foo #baz {\n  foo: bar; }\n",
+                 render("#foo\n  #bar,\n  #baz\n    :foo bar"))
+    assert_equal("#foo,\n#bar {\n  foo: bar; }\n  #foo #baz,\n  #bar #baz {\n    foo: bar; }\n",
+                 render("#foo,\n#bar\n  :foo bar\n  #baz\n    :foo bar"))
+    assert_equal("#foo #bar, #baz #boom { foo: bar; }\n",
+                 render("#foo #bar,\n#baz #boom\n  :foo bar", :style => :compact))
+                 
+    assert_equal("#foo #bar,#baz #boom{foo:bar}\n",
+                 render("#foo #bar,\n#baz #boom\n  :foo bar", :style => :compressed))
+
+    assert_equal("#foo #bar,\n#baz #boom {\n  foo: bar; }\n",
+                 render("#foo #bar,,\n,#baz #boom,\n  :foo bar"))
+
+    assert_equal("#bip #bop {\n  foo: bar; }\n",
+                 render("#bip #bop,, ,\n  :foo bar"))
+  end
+
+  def test_complex_multiline_selector
+    renders_correctly "multiline"
+  end
+
+  def test_colon_only
+    begin
+      render("a\n  b: c", :property_syntax => :old)
+    rescue Sass::SyntaxError => e
+      assert_equal("Illegal property syntax: can't use new syntax when :property_syntax => :old is set.",
+                   e.message)
+      assert_equal(2, e.sass_line)
+    else
+      assert(false, "SyntaxError not raised for :property_syntax => :old")
+    end
+
+    begin
+      render("a\n  :b c", :property_syntax => :new)
+      assert_equal(2, e.sass_line)
+    rescue Sass::SyntaxError => e
+      assert_equal("Illegal property syntax: can't use old syntax when :property_syntax => :new is set.",
+                   e.message)
+    else
+      assert(false, "SyntaxError not raised for :property_syntax => :new")
+    end
+  end
+
+  def test_pseudo_elements
+    assert_equal(<<CSS, render(<<SASS))
+::first-line {
+  size: 10em; }
+CSS
+::first-line
+  size: 10em
+SASS
+  end
+
+  def test_directive
+    assert_equal("@a b;\n", render("@a b"))
+
+    assert_equal("@a {\n  b: c; }\n", render("@a\n  :b c"))
+    assert_equal("@a { b: c; }\n", render("@a\n  :b c", :style => :compact))
+    assert_equal("@a {\n  b: c;\n}\n", render("@a\n  :b c", :style => :expanded))
+    assert_equal("@a{b:c}\n", render("@a\n  :b c", :style => :compressed))
+
+    assert_equal("@a {\n  b: c;\n  d: e; }\n",
+                 render("@a\n  :b c\n  :d e"))
+    assert_equal("@a { b: c; d: e; }\n",
+                 render("@a\n  :b c\n  :d e", :style => :compact))
+    assert_equal("@a {\n  b: c;\n  d: e;\n}\n",
+                 render("@a\n  :b c\n  :d e", :style => :expanded))
+    assert_equal("@a{b:c;d:e}\n",
+                 render("@a\n  :b c\n  :d e", :style => :compressed))
+
+    assert_equal("@a {\n  #b {\n    c: d; } }\n",
+                 render("@a\n  #b\n    :c d"))
+    assert_equal("@a { #b { c: d; } }\n",
+                 render("@a\n  #b\n    :c d", :style => :compact))
+    assert_equal("@a {\n  #b {\n    c: d;\n  }\n}\n",
+                 render("@a\n  #b\n    :c d", :style => :expanded))
+    assert_equal("@a{#b{c:d}}\n",
+                 render("@a\n  #b\n    :c d", :style => :compressed))
+
+    assert_equal("@a {\n  #b {\n    a: b; }\n    #b #c {\n      d: e; } }\n",
+                 render("@a\n  #b\n    :a b\n    #c\n      :d e"))
+    assert_equal("@a { #b { a: b; }\n  #b #c { d: e; } }\n",
+                 render("@a\n  #b\n    :a b\n    #c\n      :d e", :style => :compact))
+    assert_equal("@a {\n  #b {\n    a: b;\n  }\n  #b #c {\n    d: e;\n  }\n}\n",
+                 render("@a\n  #b\n    :a b\n    #c\n      :d e", :style => :expanded))
+    assert_equal("@a{#b{a:b}#b #c{d:e}}\n",
+                 render("@a\n  #b\n    :a b\n    #c\n      :d e", :style => :compressed))
+                 
+    assert_equal("@a {\n  #foo,\n  #bar {\n    b: c; } }\n",
+                 render("@a\n  #foo, \n  #bar\n    :b c"))
+    assert_equal("@a { #foo, #bar { b: c; } }\n",
+                 render("@a\n  #foo, \n  #bar\n    :b c", :style => :compact))
+    assert_equal("@a {\n  #foo,\n  #bar {\n    b: c;\n  }\n}\n",
+                 render("@a\n  #foo, \n  #bar\n    :b c", :style => :expanded))
+    assert_equal("@a{#foo,#bar{b:c}}\n",
+                 render("@a\n  #foo, \n  #bar\n    :b c", :style => :compressed))
+
+    to_render = <<END
+ a
+  :b c
+  #d
+    :e f
+  :g h
+END
+    rendered = <<END
+ a { b: c;
+  #d { e: f; }
+  g: h; }
+END
+    assert_equal(rendered, render(to_render, :style => :compact))
+    
+    assert_equal("@a{b:c;#d{e:f}g:h}\n", render(to_render, :style => :compressed))
+  end
+
+  def test_property_hacks
+    assert_equal(<<CSS, render(<<SASS))
+foo {
+  _name: val;
+  *name: val;
+  #name: val;
+  .name: val;
+  name/**/: val;
+  name/*\\**/: val;
+  name: val; }
+CSS
+foo
+  _name: val
+  *name: val
+  #name: val
+  .name: val
+  name/**/: val
+  name/*\\**/: val
+  name: val
+SASS
+  end
+
+  def test_properties_with_space_after_colon
+    assert_equal <<CSS, render(<<SASS)
+foo {
+  bar: baz;
+  bizz: bap; }
+CSS
+foo
+  bar : baz
+  bizz : bap
+SASS
+  end
+
+  def test_line_annotations
+    assert_equal(<<CSS, render(<<SASS, :line_comments => true, :style => :compact))
+/* line 2, test_line_annotations_inline.sass */
+foo bar { foo: bar; }
+/* line 5, test_line_annotations_inline.sass */
+foo baz { blip: blop; }
+
+/* line 9, test_line_annotations_inline.sass */
+floodle { flop: blop; }
+
+/* line 18, test_line_annotations_inline.sass */
+bup { mix: on; }
+/* line 15, test_line_annotations_inline.sass */
+bup mixin { moop: mup; }
+
+/* line 22, test_line_annotations_inline.sass */
+bip hop, skip hop { a: b; }
+CSS
+foo
+  bar
+    foo: bar
+
+  baz
+    blip: blop
+
+
+floodle
+
+  flop: blop
+
+=mxn
+  mix: on
+  mixin
+    moop: mup
+
+bup
+  +mxn
+
+bip, skip
+  hop
+    a: b
+SASS
+  end
+
+  def test_line_annotations_with_filename
+    renders_correctly "line_numbers", :line_comments => true, :load_paths => [File.dirname(__FILE__) + 
"/templates"]
+  end
+
+  def test_debug_info
+    esc_file_name = Sass::SCSS::RX.escape_ident(Sass::Util.scope("test_debug_info_inline.sass"))
+
+    assert_equal(<<CSS, render(<<SASS, :debug_info => true, :style => :compact))
+ media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000032}}
+foo bar { foo: bar; }
+ media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000035}}
+foo baz { blip: blop; }
+
+ media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000039}}
+floodle { flop: blop; }
+
+ media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\0000318}}
+bup { mix: on; }
+ media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\0000315}}
+bup mixin { moop: mup; }
+
+ media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\0000322}}
+bip hop, skip hop { a: b; }
+CSS
+foo
+  bar
+    foo: bar
+
+  baz
+    blip: blop
+
+
+floodle
+
+  flop: blop
+
+=mxn
+  mix: on
+  mixin
+    moop: mup
+
+bup
+  +mxn
+
+bip, skip
+  hop
+    a: b
+SASS
+  end
+
+  def test_debug_info_without_filename
+    assert_equal(<<CSS, Sass::Engine.new(<<SASS, :debug_info => true).render)
+ media -sass-debug-info{filename{}line{font-family:\\000031}}
+foo {
+  a: b; }
+CSS
+foo
+  a: b
+SASS
+  end
+
+  def test_debug_info_with_compressed
+    assert_equal(<<CSS, render(<<SASS, :debug_info => true, :style => :compressed))
+foo{a:b}
+CSS
+foo
+  a: b
+SASS
+  end
+
+  def test_debug_info_with_line_annotations
+    esc_file_name = 
Sass::SCSS::RX.escape_ident(Sass::Util.scope("test_debug_info_with_line_annotations_inline.sass"))
+
+    assert_equal(<<CSS, render(<<SASS, :debug_info => true, :line_comments => true))
+ media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000031}}
+foo {
+  a: b; }
+CSS
+foo
+  a: b
+SASS
+  end
+
+  def test_debug_info_in_keyframes
+    assert_equal(<<CSS, render(<<SASS, :debug_info => true))
+ -webkit-keyframes warm {
+  from {
+    color: black; }
+
+  to {
+    color: red; } }
+CSS
+ -webkit-keyframes warm
+  from
+    color: black
+  to
+    color: red
+SASS
+  end
+
+  def test_empty_first_line
+    assert_equal("#a {\n  b: c; }\n", render("#a\n\n  b: c"))
+  end
+
+  def test_escaped_rule
+    assert_equal(":focus {\n  a: b; }\n", render("\\:focus\n  a: b"))
+    assert_equal("a {\n  b: c; }\n  a :focus {\n    d: e; }\n", render("\\a\n  b: c\n  \\:focus\n    d: e"))
+  end
+
+  def test_cr_newline
+    assert_equal("foo {\n  a: b;\n  c: d;\n  e: f; }\n", render("foo\r  a: b\r\n  c: d\n\r  e: f"))
+  end
+
+  def test_property_with_content_and_nested_props
+    assert_equal(<<CSS, render(<<SASS))
+foo {
+  a: b;
+    a-c: d;
+      a-c-e: f; }
+CSS
+foo
+  a: b
+    c: d
+      e: f
+SASS
+
+    assert_equal(<<CSS, render(<<SASS))
+foo {
+  a: b;
+    a-c-e: f; }
+CSS
+foo
+  a: b
+    c:
+      e: f
+SASS
+  end
+
+  def test_guarded_assign
+    assert_equal("foo {\n  a: b; }\n", render(%Q{$foo: b\n$foo: c !default\nfoo\n  a: $foo}))
+    assert_equal("foo {\n  a: b; }\n", render(%Q{$foo: b !default\nfoo\n  a: $foo}))
+    assert_equal("foo {\n  a: b; }\n", render(%Q{$foo: null\n$foo: b !default\nfoo\n  a: $foo}))
+  end
+  
+  def test_mixins
+    renders_correctly "mixins", { :style => :expanded }
+  end
+
+  def test_directive_style_mixins
+    assert_equal <<CSS, render(<<SASS)
+bar {
+  prop: baz; }
+CSS
+ mixin foo($arg)
+  prop: $arg
+
+bar
+  @include foo(baz)
+SASS
+  end
+
+  def test_mixins_dont_interfere_with_sibling_combinator
+    assert_equal("foo + bar {\n  a: b; }\nfoo + baz {\n  c: d; }\n",
+                 render("foo\n  +\n    bar\n      a: b\n    baz\n      c: d"))
+  end
+
+  def test_mixin_args
+    assert_equal("blat {\n  baz: hi; }\n", render(<<SASS))
+=foo($bar)
+  baz: $bar
+blat
+  +foo(hi)
+SASS
+    assert_equal("blat {\n  baz: 3; }\n", render(<<SASS))
+=foo($a, $b)
+  baz: $a + $b
+blat
+  +foo(1, 2)
+SASS
+    assert_equal("blat {\n  baz: 4;\n  baz: 3;\n  baz: 5;\n  bang: 3; }\n", render(<<SASS))
+=foo($c: (6 + 4) / 2)
+  baz: $c
+$c: 3
+blat
+  +foo($c + 1)
+  +foo(($c + 3)/2)
+  +foo
+  bang: $c
+SASS
+  end
+
+  def test_default_values_for_mixin_arguments
+    assert_equal("white {\n  color: white; }\n\nblack {\n  color: black; }\n", render(<<SASS))
+=foo($a: #FFF)
+  :color $a
+white
+  +foo
+black
+  +foo(#000)
+SASS
+    assert_equal(<<CSS, render(<<SASS))
+one {
+  color: white;
+  padding: 1px;
+  margin: 4px; }
+
+two {
+  color: white;
+  padding: 2px;
+  margin: 5px; }
+
+three {
+  color: white;
+  padding: 2px;
+  margin: 3px; }
+CSS
+$a: 5px
+=foo($a, $b: 1px, $c: 3px + $b)
+  :color $a
+  :padding $b
+  :margin $c
+one
+  +foo(#fff)
+two
+  +foo(#fff, 2px)
+three
+  +foo(#fff, 2px, 3px)
+SASS
+    assert_equal(<<CSS, render(<<SASS))
+one {
+  color: white;
+  padding: 1px;
+  margin: 4px; }
+
+two {
+  color: white;
+  padding: 2px;
+  margin: 5px; }
+
+three {
+  color: white;
+  padding: 2px;
+  margin: 3px; }
+CSS
+$a: 5px
+=foo($a, $b: 1px, $c: null)
+  $c: 3px + $b !default
+  color: $a
+  padding: $b
+  margin: $c
+one
+  +foo(#fff)
+two
+  +foo(#fff, 2px)
+three
+  +foo(#fff, 2px, 3px)
+SASS
+  end
+
+  def test_hyphen_underscore_insensitive_mixins
+    assert_equal(<<CSS, render(<<SASS))
+a {
+  b: 12;
+  c: foo; }
+CSS
+=mixin-hyphen
+  b: 12
+
+=mixin_under
+  c: foo
+
+a
+  +mixin_hyphen
+  +mixin-under
+SASS
+  end
+
+  def test_css_identifier_mixin
+    assert_equal(<<CSS, render(<<SASS))
+a {
+  foo: 12; }
+CSS
+=\\{foo\\(12\\)($a)
+  foo: $a
+
+a
+  +\\{foo\\(12\\)(12)
+SASS
+  end
+
+  def test_basic_function
+    assert_equal(<<CSS, render(<<SASS))
+bar {
+  a: 3; }
+CSS
+ function foo()
+  @return 1 + 2
+
+bar
+  a: foo()
+SASS
+  end
+
+  def test_function_args
+    assert_equal(<<CSS, render(<<SASS))
+bar {
+  a: 3; }
+CSS
+ function plus($var1, $var2)
+  @return $var1 + $var2
+
+bar
+  a: plus(1, 2)
+SASS
+  end
+
+  def test_function_arg_default
+    assert_equal(<<CSS, render(<<SASS))
+bar {
+  a: 3; }
+CSS
+ function plus($var1, $var2: 2)
+  @return $var1 + $var2
+
+bar
+  a: plus(1)
+SASS
+  end
+
+  def test_function_arg_keyword
+    assert_equal(<<CSS, render(<<SASS))
+bar {
+  a: 1bar; }
+CSS
+ function plus($var1: 1, $var2: 2)
+  @return $var1 + $var2
+
+bar
+  a: plus($var2: bar)
+SASS
+  end
+
+  def test_function_with_missing_argument
+    render(<<SASS)
+ function plus($var1, $var2)
+  @return $var1 + $var2
+
+bar
+  a: plus($var2: bar)
+SASS
+    flunk("Expected exception")
+  rescue Sass::SyntaxError => e
+    assert_equal("Function plus is missing argument $var1.", e.message)
+  end
+
+  def test_function_with_extra_argument
+    render(<<SASS)
+ function plus($var1, $var2)
+  @return $var1 + $var2
+
+bar
+  a: plus($var1: foo, $var2: bar, $var3: baz)
+SASS
+    flunk("Expected exception")
+  rescue Sass::SyntaxError => e
+    assert_equal("Function plus doesn't have an argument named $var3.", e.message)
+  end
+
+  def test_function_with_positional_and_keyword_argument
+    render(<<SASS)
+ function plus($var1, $var2)
+  @return $var1 + $var2
+
+bar
+  a: plus(foo, bar, $var2: baz)
+SASS
+    flunk("Expected exception")
+  rescue Sass::SyntaxError => e
+    assert_equal("Function plus was passed argument $var2 both by position and by name.", e.message)
+  end
+
+  def test_function_with_keyword_before_positional_argument
+    render(<<SASS)
+ function plus($var1, $var2)
+  @return $var1 + $var2
+
+bar
+  a: plus($var2: foo, bar)
+SASS
+    flunk("Expected exception")
+  rescue Sass::SyntaxError => e
+    assert_equal("Positional arguments must come before keyword arguments.", e.message)
+  end
+
+  def test_function_with_if
+    assert_equal(<<CSS, render(<<SASS))
+bar {
+  a: foo;
+  b: bar; }
+CSS
+ function my-if($cond, $val1, $val2)
+  @if $cond
+    @return $val1
+  @else
+    @return $val2
+
+bar
+  a: my-if(true, foo, bar)
+  b: my-if(false, foo, bar)
+SASS
+  end
+
+  def test_function_with_var
+    assert_equal(<<CSS, render(<<SASS))
+bar {
+  a: 1; }
+CSS
+ function foo($val1, $val2)
+  $intermediate: $val1 + $val2
+  @return $intermediate/3
+
+bar
+  a: foo(1, 2)
+SASS
+  end
+
+  def test_control_directive_in_nested_property
+    assert_equal(<<CSS, render(<<SASS))
+foo {
+  a-b: c; }
+CSS
+foo
+  a:
+    @if true
+      b: c
+SASS
+  end
+
+  def test_interpolation
+    assert_equal("a-1 {\n  b-2-3: c-3; }\n", render(<<SASS))
+$a: 1
+$b: 2
+$c: 3
+a-\#{$a}
+  b-\#{$b}-\#{$c}: c-\#{$a + $b}
+SASS
+  end
+
+  def test_complex_property_interpolation
+    assert_equal(<<CSS, render(<<SASS))
+a-1 {
+  b-2 3-fizzap18: c-3; }
+CSS
+$a: 1
+$b: 2
+$c: 3
+a-\#{$a}
+  b-\#{$b $c}-\#{fizzap + ($c + 15)}: c-\#{$a + $b}
+SASS
+  end
+
+  def test_if_directive
+    assert_equal("a {\n  b: 1; }\n", render(<<SASS))
+$var: true
+a
+  @if $var
+    b: 1
+  @if not $var
+    b: 2
+SASS
+
+    assert_equal("a {\n  b: 2; }\n", render(<<SASS))
+$var: null
+a
+  @if $var
+    b: 1
+  @if not $var
+    b: 2
+SASS
+  end
+
+  def test_for
+    assert_equal(<<CSS, render(<<SASS))
+a-0 {
+  two-i: 0; }
+
+a-1 {
+  two-i: 2; }
+
+a-2 {
+  two-i: 4; }
+
+a-3 {
+  two-i: 6; }
+
+b-1 {
+  j-1: 0; }
+
+b-2 {
+  j-1: 1; }
+
+b-3 {
+  j-1: 2; }
+
+b-4 {
+  j-1: 3; }
+CSS
+$a: 3
+ for $i from 0 to $a + 1
+  a-\#{$i}
+    two-i: 2 * $i
+
+ for $j from 1 through 4
+  b-\#{$j}
+    j-1: $j - 1
+SASS
+  end
+
+  def test_while
+    assert_equal(<<CSS, render(<<SASS))
+a-5 {
+  blooble: gloop; }
+
+a-4 {
+  blooble: gloop; }
+
+a-3 {
+  blooble: gloop; }
+
+a-2 {
+  blooble: gloop; }
+
+a-1 {
+  blooble: gloop; }
+CSS
+$a: 5
+ while $a != 0
+  a-\#{$a}
+    blooble: gloop
+  $a: $a - 1
+SASS
+  end
+
+  def test_else
+    assert_equal(<<CSS, render(<<SASS))
+a {
+  t1: t;
+  t2: t;
+  t3: t;
+  t4: t; }
+CSS
+a
+  @if true
+    t1: t
+  @else
+    f1: f
+
+  @if false
+    f2: f
+  @else
+    t2: t
+
+  @if false
+    f3: f1
+  @else if 1 + 1 == 3
+    f3: f2
+  @else
+    t3: t
+
+  @if false
+    f4: f1
+  @else if 1 + 1 == 2
+    t4: t
+  @else
+    f4: f2
+
+  @if false
+    f5: f1
+  @else if false
+    f5: f2
+SASS
+  end
+
+  def test_each
+    assert_equal(<<CSS, render(<<SASS))
+a {
+  b: 1px;
+  b: 2px;
+  b: 3px;
+  b: 4px;
+  c: foo;
+  c: bar;
+  c: baz;
+  c: bang;
+  d: blue; }
+CSS
+a
+  @each $number in 1px 2px 3px 4px
+    b: $number
+  @each $str in foo, bar, baz, bang
+    c: $str
+  @each $single in blue
+    d: $single
+SASS
+  end
+
+  def test_variable_reassignment
+    assert_equal(<<CSS, render(<<SASS))
+a {
+  b: 1;
+  c: 2; }
+CSS
+$a: 1
+a
+  b: $a
+  $a: 2
+  c: $a
+SASS
+  end
+
+  def test_variable_scope
+    assert_equal(<<CSS, render(<<SASS))
+a {
+  b-1: c;
+  b-2: c;
+  d: 12; }
+
+b {
+  d: 17; }
+CSS
+$i: 12
+a
+  @for $i from 1 through 2
+    b-\#{$i}: c
+  d: $i
+
+=foo
+  $i: 17
+
+b
+  +foo
+  d: $i
+SASS
+  end
+
+  def test_hyphen_underscore_insensitive_variables
+    assert_equal(<<CSS, render(<<SASS))
+a {
+  b: c; }
+
+d {
+  e: 13;
+  f: foobar; }
+CSS
+$var-hyphen: 12
+$var_under: foo
+
+a
+  $var_hyphen: 1 + $var_hyphen
+  $var-under: $var-under + bar
+  b: c
+
+d
+  e: $var-hyphen
+  f: $var_under
+SASS
+  end
+
+  def test_css_identifier_variable
+    assert_equal(<<CSS, render(<<SASS))
+a {
+  b: 12; }
+CSS
+$\\{foo\\(12\\): 12
+
+a
+  b: $\\{foo\\(12\\)
+SASS
+  end
+
+  def test_important
+    assert_equal(<<CSS, render(<<SASS))
+a {
+  b: 12px !important; }
+CSS
+$foo: 12px
+a
+  b: $foo !important
+SASS
+  end
+
+  def test_argument_error
+    assert_raise(Sass::SyntaxError) { render("a\n  b: hsl(1)") }
+  end
+
+  def test_comments_at_the_top_of_a_document
+    render(<<SASS)
+//
+  This is a comment that
+  continues to the second line.
+foo
+  bar: baz
+SASS
+  end
+
+  def test_loud_comments_containing_a_comment_close
+    actual_css = render(<<SASS)
+/*
+  This is a comment that
+  continues to the second line. */
+foo
+  bar: baz
+SASS
+assert_equal(<<CSS, actual_css)
+/* This is a comment that
+ * continues to the second line. */
+foo {
+  bar: baz; }
+CSS
+  end
+
+  def test_loud_comments_with_starred_lines
+    assert_equal(<<CSS, render(<<SASS))
+/* This is a comment that
+ * continues to the second line.
+ * And even to the third! */
+CSS
+/* This is a comment that
+ * continues to the second line.
+ * And even to the third!
+SASS
+  end
+
+  def test_loud_comments_with_no_space_after_starred_lines
+    assert_equal(<<CSS, render(<<SASS))
+/*bip bop
+ *beep boop
+ *bap blimp */
+CSS
+/*bip bop
+ *beep boop
+ *bap blimp
+SASS
+  end
+
+  def test_comment_indentation_at_beginning_of_doc
+    assert_equal <<CSS, render(<<SASS)
+/* foo
+ * bar
+ *   baz */
+foo {
+  a: b; }
+CSS
+/* foo
+   bar
+     baz
+foo
+  a: b
+SASS
+  end
+
+  def test_unusual_comment_indentation
+    assert_equal <<CSS, render(<<SASS)
+foo {
+  /* foo
+   * bar
+   *   baz */ }
+CSS
+foo
+  /* foo
+     bar
+       baz
+SASS
+  end
+
+  def test_loud_comment_with_close
+    assert_equal <<CSS, render(<<SASS)
+foo {
+  /* foo
+   * bar */ }
+CSS
+foo
+  /* foo
+     bar */
+SASS
+  end
+
+  def test_loud_comment_with_separate_line_close
+    assert_equal <<CSS, render(<<SASS)
+foo {
+  /* foo
+   * bar
+   */ }
+CSS
+foo
+  /* foo
+   * bar
+   */
+SASS
+  end
+
+  def test_loud_comment_in_compressed_mode
+    assert_equal <<CSS, render(<<SASS, :style => :compressed)
+foo{color:blue;/*! foo
+ * bar
+ */}
+CSS
+foo
+  color: blue
+  /*! foo
+   * bar
+   */
+SASS
+  end
+
+  def test_loud_comment_is_evaluated
+    assert_equal <<CSS, render(<<SASS)
+/*!
+ * Hue: 327.21649deg */
+CSS
+/*!
+  Hue: \#{hue(#f836a0)}
+SASS
+  end
+
+  def test_attribute_selector_with_spaces
+    assert_equal(<<CSS, render(<<SASS))
+a b[foo=bar] {
+  c: d; }
+CSS
+a
+  b[foo = bar]
+    c: d
+SASS
+  end
+
+  def test_quoted_colon
+    assert_equal(<<CSS, render(<<SASS))
+a b[foo="bar: baz"] {
+  c: d; }
+CSS
+a
+  b[foo="bar: baz"]
+    c: d
+SASS
+  end
+
+  def test_quoted_comma
+    assert_equal(<<CSS, render(<<SASS))
+a b[foo="bar, baz"] {
+  c: d; }
+CSS
+a
+  b[foo="bar, baz"]
+    c: d
+SASS
+  end
+
+  def test_quoted_ampersand
+    assert_equal(<<CSS, render(<<SASS))
+a b[foo="bar & baz"] {
+  c: d; }
+CSS
+a
+  b[foo="bar & baz"]
+    c: d
+SASS
+  end
+
+  def test_empty_selector_warning
+    assert_warning(<<END) {render("foo bar")}
+WARNING on line 1 of test_empty_selector_warning_inline.sass:
+This selector doesn't have any properties and will not be rendered.
+END
+  end
+
+  def test_nonprinting_empty_property
+    assert_equal(<<CSS, render(<<SASS))
+a {
+  c: "";
+  e: f; }
+CSS
+$null-value: null
+$empty-string: ''
+$empty-list: (null)
+a
+  b: $null-value
+  c: $empty-string
+  d: $empty-list
+  e: f
+
+g
+  h: null
+SASS
+  end
+
+  def test_root_level_pseudo_class_with_new_properties
+    assert_equal(<<CSS, render(<<SASS, :property_syntax => :new))
+:focus {
+  outline: 0; }
+CSS
+:focus
+  outline: 0
+SASS
+  end
+
+  def test_pseudo_class_with_new_properties
+    assert_equal(<<CSS, render(<<SASS, :property_syntax => :new))
+p :focus {
+  outline: 0; }
+CSS
+p
+  :focus
+    outline: 0
+SASS
+  end
+
+  def test_nil_option
+    assert_equal(<<CSS, render(<<SASS, :format => nil))
+foo {
+  a: b; }
+CSS
+foo
+  a: b
+SASS
+  end
+
+  def test_interpolation_in_raw_functions
+    assert_equal(<<CSS, render(<<SASS))
+foo {
+  filter: progid:Microsoft.foo.bar.Baz(flip=foobar, bang=#00ff00cc); }
+CSS
+foo
+  filter: progid:Microsoft.foo.bar.Baz(flip=\#{foo + bar}, bang=#00ff00cc)
+SASS
+  end
+
+  # SassScript string behavior
+
+  def test_plus_preserves_quotedness
+    assert_equal(<<CSS, render(<<SASS))
+foo {
+  a: "foo1";
+  b: "1foo";
+  c: foo1;
+  d: 1foo;
+  e: "foobar";
+  f: foobar; }
+CSS
+foo
+  a: "foo" + 1
+  b: 1 + "foo"
+  c: foo + 1
+  d: 1 + foo
+  e: "foo" + bar
+  f: foo + "bar"
+SASS
+  end
+
+  def test_colon_properties_preserve_quotedness
+    assert_equal(<<CSS, render(<<SASS))
+foo {
+  a: "foo";
+  b: bar;
+  c: "foo" bar;
+  d: foo, "bar"; }
+CSS
+foo
+  a: "foo"
+  b: bar
+  c: "foo" bar
+  d: foo, "bar"
+SASS
+  end
+
+  def test_colon_variables_preserve_quotedness
+    assert_equal(<<CSS, render(<<SASS))
+foo {
+  a: "foo";
+  b: bar; }
+CSS
+$a: "foo"
+$b: bar
+
+foo
+  a: $a
+  b: $b
+SASS
+  end
+
+  def test_colon_args_preserve_quotedness
+    assert_equal(<<CSS, render(<<SASS))
+foo {
+  a: "foo";
+  b: bar;
+  c: "foo" bar;
+  d: foo, "bar"; }
+CSS
+=foo($a: "foo", $b: bar, $c: "foo" bar, $d: (foo, "bar"))
+  foo
+    a: $a
+    b: $b
+    c: $c
+    d: $d
+
++foo
+SASS
+  end
+
+  def test_interpolation_unquotes_strings
+    assert_equal(<<CSS, render(<<SASS))
+.foo-bar {
+  a: b; }
+CSS
+.foo-\#{"bar"}
+  a: b
+SASS
+
+    assert_equal(<<CSS, render(<<SASS))
+.foo {
+  a: b c; }
+CSS
+.foo
+  a: b \#{"c"}
+SASS
+  end
+
+  def test_interpolation_unquotes_strings_in_vars
+    assert_equal(<<CSS, render(<<SASS))
+.foo-bar {
+  a: b; }
+CSS
+$var: "bar"
+
+.foo-\#{$var}
+  a: b
+SASS
+  end
+
+  def test_interpolation_doesnt_deep_unquote_strings
+    assert_equal(<<CSS, render(<<SASS))
+.foo {
+  a: "bar" "baz"; }
+CSS
+.foo
+  a: \#{"bar" "baz"}
+SASS
+  end
+
+  def test_warn_directive
+  expected_warning = <<EXPECTATION
+WARNING: this is a warning
+         on line 4 of test_warn_directive_inline.sass
+
+WARNING: this is a mixin warning
+         on line 2 of test_warn_directive_inline.sass, in `foo'
+         from line 7 of test_warn_directive_inline.sass
+EXPECTATION
+    assert_warning expected_warning do
+      assert_equal <<CSS, render(<<SASS)
+bar {
+  c: d; }
+CSS
+=foo
+  @warn "this is a mixin warning"
+
+ warn "this is a warning"
+bar
+  c: d
+  +foo
+SASS
+    end
+  end
+
+  def test_warn_directive_when_quiet
+    assert_warning "" do
+      assert_equal <<CSS, render(<<SASS, :quiet => true)
+CSS
+ warn "this is a warning"
+SASS
+    end
+  end
+
+  def test_warn_with_imports
+    expected_warning = <<WARN
+WARNING: In the main file
+         on line 1 of #{File.dirname(__FILE__)}/templates/warn.sass
+
+WARNING: Imported
+         on line 1 of #{File.dirname(__FILE__)}/templates/warn_imported.sass
+         from line 2 of #{File.dirname(__FILE__)}/templates/warn.sass
+
+WARNING: In an imported mixin
+         on line 4 of #{File.dirname(__FILE__)}/templates/warn_imported.sass, in `emits-a-warning'
+         from line 3 of #{File.dirname(__FILE__)}/templates/warn.sass
+WARN
+    assert_warning expected_warning do
+      renders_correctly "warn", :style => :compact, :load_paths => [File.dirname(__FILE__) + "/templates"]
+    end
+  end
+
+  def test_media_bubbling
+    assert_equal <<CSS, render(<<SASS)
+.foo {
+  a: b; }
+  @media bar {
+    .foo {
+      c: d; } }
+  .foo .baz {
+    e: f; }
+    @media bip {
+      .foo .baz {
+        g: h; } }
+
+.other {
+  i: j; }
+CSS
+.foo
+  a: b
+  @media bar
+    c: d
+  .baz
+    e: f
+    @media bip
+      g: h
+
+.other
+  i: j
+SASS
+
+    assert_equal <<CSS, render(<<SASS, :style => :compact)
+.foo { a: b; }
+ media bar { .foo { c: d; } }
+.foo .baz { e: f; }
+ media bip { .foo .baz { g: h; } }
+
+.other { i: j; }
+CSS
+.foo
+  a: b
+  @media bar
+    c: d
+  .baz
+    e: f
+    @media bip
+      g: h
+
+.other
+  i: j
+SASS
+
+    assert_equal <<CSS, render(<<SASS, :style => :expanded)
+.foo {
+  a: b;
+}
+ media bar {
+  .foo {
+    c: d;
+  }
+}
+.foo .baz {
+  e: f;
+}
+ media bip {
+  .foo .baz {
+    g: h;
+  }
+}
+
+.other {
+  i: j;
+}
+CSS
+.foo
+  a: b
+  @media bar
+    c: d
+  .baz
+    e: f
+    @media bip
+      g: h
+
+.other
+  i: j
+SASS
+  end
+
+  def test_double_media_bubbling
+    assert_equal <<CSS, render(<<SASS)
+ media bar and (a: b) {
+  .foo {
+    c: d; } }
+CSS
+ media bar
+  @media (a: b)
+    .foo
+      c: d
+SASS
+
+    assert_equal <<CSS, render(<<SASS)
+ media bar {
+  .foo {
+    a: b; } }
+  @media bar and (a: b) {
+    .foo {
+      c: d; } }
+CSS
+.foo
+  @media bar
+    a: b
+    @media (a: b)
+      c: d
+SASS
+  end
+
+  def test_double_media_bubbling_with_commas
+    assert_equal <<CSS, render(<<SASS)
+ media (a: b) and (e: f), (c: d) and (e: f), (a: b) and (g: h), (c: d) and (g: h) {
+  .foo {
+    c: d; } }
+CSS
+ media (a: b), (c: d)
+  @media (e: f), (g: h)
+    .foo
+      c: d
+SASS
+  end
+
+  def test_rule_media_rule_bubbling
+    assert_equal <<CSS, render(<<SASS)
+ media bar {
+  .foo {
+    a: b;
+    e: f; }
+    .foo .baz {
+      c: d; } }
+CSS
+.foo
+  @media bar
+    a: b
+    .baz
+      c: d
+    e: f
+SASS
+  end
+
+  def test_nested_media_around_properties
+    assert_equal <<CSS, render(<<SASS)
+.outside {
+  color: red;
+  background: blue; }
+  @media print {
+    .outside {
+      color: black; } }
+    @media print and (a: b) {
+      .outside .inside {
+        border: 1px solid black; } }
+  .outside .middle {
+    display: block; }
+CSS
+.outside
+  color: red
+  @media print
+    color: black
+    .inside
+      @media (a: b)
+        border: 1px solid black
+  background: blue
+  .middle
+    display: block
+SASS
+  end
+
+  def test_media_with_parent_references
+    sass_str = <<SASS
+.outside
+  @media print
+    &.inside
+      border: 1px solid black
+SASS
+    css_str = <<CSS
+ media print {
+  .outside.inside {
+    border: 1px solid black; } }
+CSS
+    assert_equal css_str, render(sass_str)
+  end
+
+  def test_eliminated_media_bubbling
+    assert_equal <<CSS, render(<<SASS)
+ media screen {
+  a: b; }
+CSS
+ media screen
+  a: b
+  @media print
+    c: d
+SASS
+
+    assert_equal <<CSS, render(<<SASS)
+ media not print {
+  a: b; }
+CSS
+ media not print
+  a: b
+  @media print
+    c: d
+SASS
+
+    assert_equal <<CSS, render(<<SASS)
+ media not print {
+  a: b; }
+CSS
+ media not print
+  a: b
+  @media not screen
+    c: d
+SASS
+  end
+
+  def test_non_eliminated_media_bubbling
+    assert_equal <<CSS, render(<<SASS)
+ media screen {
+  a: b; }
+ media screen and (a: b) {
+  c: d; }
+CSS
+ media screen
+  a: b
+  @media screen and (a: b)
+    c: d
+SASS
+
+    assert_equal <<CSS, render(<<SASS)
+ media not print {
+  a: b; }
+ media screen {
+  c: d; }
+CSS
+ media not print
+  a: b
+  @media screen
+    c: d
+SASS
+
+    assert_equal <<CSS, render(<<SASS)
+ media only screen {
+  a: b; }
+ media only screen and (a: b) {
+  c: d; }
+CSS
+ media only screen
+  a: b
+  @media screen and (a: b)
+    c: d
+SASS
+  end
+
+  def test_directive_interpolation
+    assert_equal <<CSS, render(<<SASS)
+ foo bar12 qux {
+  a: b; }
+CSS
+$baz: 12
+ foo bar\#{$baz} qux
+  a: b
+SASS
+  end
+
+  def test_media_interpolation
+    assert_equal <<CSS, render(<<SASS)
+ media bar12 {
+  a: b; }
+CSS
+$baz: 12
+ media bar\#{$baz}
+  a: b
+SASS
+  end
+
+  def test_variables_in_media
+    assert_equal <<CSS, render(<<SASS)
+ media screen and (-webkit-min-device-pixel-ratio-foo: 25), only print {
+  a: b; }
+CSS
+$media1: screen
+$media2: print
+$var: -webkit-min-device-pixel-ratio
+$val: 20
+ media \#{$media1} and ($var + "-foo": $val + 5), only \#{$media2}
+  a: b
+SASS
+  end
+
+  # Regression tests
+
+  def test_parent_mixin_in_content_nested
+    assert_equal(<<CSS, render(<<SASS))
+a {
+  b: c; }
+CSS
+=foo
+  @content
+
+=bar
+  +foo
+    +foo
+      a
+        b: c
+
++bar
+SASS
+  end
+
+  def test_supports_bubbles
+    assert_equal <<CSS, render(<<SASS)
+parent {
+  background: orange; }
+  @supports (perspective: 10px) or (-moz-perspective: 10px) {
+    parent child {
+      background: blue; } }
+CSS
+parent
+  background: orange
+  @supports (perspective: 10px) or (-moz-perspective: 10px)
+    child
+      background: blue
+SASS
+  end
+
+  def test_line_numbers_with_dos_line_endings
+    assert_equal <<CSS, render(<<SASS, :line_comments => true)
+/* line 5, test_line_numbers_with_dos_line_endings_inline.sass */
+.foo {
+  a: b; }
+CSS
+\r
+\r
+\r
+\r
+.foo
+  a: b
+SASS
+  end
+
+  def test_variable_in_media_in_mixin
+    assert_equal <<CSS, render(<<SASS)
+ media screen and (min-width: 10px) {
+  body {
+    background: red; } }
+ media screen and (min-width: 20px) {
+  body {
+    background: blue; } }
+CSS
+ mixin respond-to($width)
+  @media screen and (min-width: $width)
+    @content
+
+body
+  @include respond-to(10px)
+    background: red
+  @include respond-to(20px)
+    background: blue
+SASS
+  end
+
+  def test_tricky_mixin_loop_exception
+    render <<SASS
+ mixin foo($a)
+  @if $a
+    @include foo(false)
+    @include foo(true)
+  @else
+    a: b
+
+a
+  @include foo(true)
+SASS
+    assert(false, "Exception not raised")
+  rescue Sass::SyntaxError => err
+    assert_equal("An @include loop has been found: foo includes itself", err.message)
+    assert_hash_has(err.sass_backtrace[0], :mixin => "foo", :line => 3)
+  end
+
+  def test_interpolated_comment_in_mixin
+    assert_equal <<CSS, render(<<SASS)
+/*! color: red */
+.foo {
+  color: red; }
+
+/*! color: blue */
+.foo {
+  color: blue; }
+
+/*! color: green */
+.foo {
+  color: green; }
+CSS
+=foo($var)
+  /*! color: \#{$var}
+  .foo
+    color: $var
+
++foo(red)
++foo(blue)
++foo(green)
+SASS
+  end
+
+  def test_parens_in_mixins
+    assert_equal(<<CSS, render(<<SASS))
+.foo {
+  color: #01ff7f;
+  background-color: #000102; }
+CSS
+=foo($c1, $c2: rgb(0, 1, 2))
+  color: $c1
+  background-color: $c2
+
+.foo
+  +foo(rgb(1,255,127))
+SASS
+  end
+
+  def test_comment_beneath_prop
+    assert_equal(<<RESULT, render(<<SOURCE))
+.box {
+  border-style: solid; }
+RESULT
+.box
+  :border
+    //:color black
+    :style solid
+SOURCE
+
+    assert_equal(<<RESULT, render(<<SOURCE))
+.box {
+  /* :color black */
+  border-style: solid; }
+RESULT
+.box
+  :border
+    /* :color black
+    :style solid
+SOURCE
+
+    assert_equal(<<RESULT, render(<<SOURCE, :style => :compressed))
+.box{border-style:solid}
+RESULT
+.box
+  :border
+    /*:color black
+    :style solid
+SOURCE
+  end
+
+  def test_compressed_comment_beneath_directive
+    assert_equal(<<RESULT, render(<<SOURCE, :style => :compressed))
+ foo{a:b}
+RESULT
+ foo
+  a: b
+  /*b: c
+SOURCE
+  end
+
+  def test_comment_with_crazy_indentation
+    assert_equal(<<CSS, render(<<SASS))
+/* This is a loud comment:
+ *          Where the indentation is wonky. */
+.comment {
+  width: 1px; }
+CSS
+/*
+  This is a loud comment:
+           Where the indentation is wonky.
+//
+  This is a silent comment:
+           Where the indentation is wonky.
+.comment
+  width: 1px
+SASS
+  end
+
+  def test_plus_with_space
+    assert_equal(<<CSS, render(<<SASS))
+a + b {
+  color: green; }
+CSS
+a
+  + b
+    color: green
+SASS
+  end
+
+  def test_empty_line_comment
+    assert_equal(<<CSS, render(<<SASS))
+/* Foo
+ *
+ * Bar */
+CSS
+/*
+  Foo
+
+  Bar
+SASS
+  end
+
+  def test_empty_comment
+    assert_equal(<<CSS, render(<<SASS))
+/* */
+a {
+  /* */
+  b: c; }
+CSS
+/*
+a
+  /*
+  b: c
+SASS
+  end
+
+  def test_options_available_in_environment
+    assert_equal(<<CSS, render(<<SASS))
+a {
+  b: nested; }
+CSS
+a
+  b: option("style")
+SASS
+  end
+
+  def test_mixin_no_arg_error
+    assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "($bar,": expected variable (e.g. $foo), was 
")"') do
+      render(<<SASS)
+=foo($bar,)
+  bip: bap
+SASS
+    end
+  end
+
+  def test_import_with_commas_in_url
+    assert_equal <<CSS, render(<<SASS)
+ import url(foo.css?bar,baz);
+CSS
+ import url(foo.css?bar,baz)
+SASS
+  end
+
+  def test_silent_comment_in_prop_val_after_important
+    assert_equal(<<CSS, render(<<SASS))
+.advanced {
+  display: none !important; }
+CSS
+.advanced
+  display: none !important // yeah, yeah. it's not really a style anyway.
+SASS
+  end
+
+  def test_mixin_with_keyword_args
+    assert_equal <<CSS, render(<<SASS)
+.mixed {
+  required: foo;
+  arg1: default-val1;
+  arg2: non-default-val2; }
+CSS
+=a-mixin($required, $arg1: default-val1, $arg2: default-val2)
+  required: $required
+  arg1: $arg1
+  arg2: $arg2
+.mixed
+  +a-mixin(foo, $arg2: non-default-val2)
+SASS
+  end
+
+  def test_mixin_with_keyword_arg_variable_value
+    assert_equal <<CSS, render(<<SASS)
+.mixed {
+  required: foo;
+  arg1: default-val1;
+  arg2: a-value; }
+CSS
+=a-mixin($required, $arg1: default-val1, $arg2: default-val2)
+  required: $required
+  arg1: $arg1
+  arg2: $arg2
+.mixed
+  $a-value: a-value
+  +a-mixin(foo, $arg2: $a-value)
+SASS
+  end
+
+  def test_mixin_keyword_args_handle_variable_underscore_dash_equivalence
+    assert_equal <<CSS, render(<<SASS)
+.mixed {
+  required: foo;
+  arg1: non-default-val1;
+  arg2: non-default-val2; }
+CSS
+=a-mixin($required, $arg-1: default-val1, $arg_2: default-val2)
+  required: $required
+  arg1: $arg_1
+  arg2: $arg-2
+.mixed
+  +a-mixin(foo, $arg-2: non-default-val2, $arg_1: non-default-val1)
+SASS
+  end
+
+  def test_passing_required_args_as_a_keyword_arg
+    assert_equal <<CSS, render(<<SASS)
+.mixed {
+  required: foo;
+  arg1: default-val1;
+  arg2: default-val2; }
+CSS
+=a-mixin($required, $arg1: default-val1, $arg2: default-val2)
+  required: $required
+  arg1: $arg1
+  arg2: $arg2
+.mixed
+  +a-mixin($required: foo)
+SASS
+  end
+
+  def test_passing_all_as_keyword_args_in_opposite_order
+    assert_equal <<CSS, render(<<SASS)
+.mixed {
+  required: foo;
+  arg1: non-default-val1;
+  arg2: non-default-val2; }
+CSS
+=a-mixin($required, $arg1: default-val1, $arg2: default-val2)
+  required: $required
+  arg1: $arg1
+  arg2: $arg2
+.mixed
+  +a-mixin($arg2: non-default-val2, $arg1: non-default-val1, $required: foo)
+SASS
+  end
+
+  def test_function_output_with_comma
+    assert_equal <<CSS, render(<<SASS)
+foo {
+  a: b(c), d(e); }
+CSS
+foo
+  a: b(c), d(e)
+SASS
+  end
+
+  def test_interpolation_with_comma
+    assert_equal <<CSS, render(<<SASS)
+foo {
+  a: foo, bar; }
+CSS
+$foo: foo
+foo
+  a: \#{$foo}, bar
+SASS
+  end
+
+  def test_string_interpolation_with_comma
+    assert_equal <<CSS, render(<<SASS)
+foo {
+  a: "bip foo bap", bar; }
+CSS
+$foo: foo
+foo
+  a: "bip \#{$foo} bap", bar
+SASS
+  end
+
+  def test_unknown_directive
+    assert_equal <<CSS, render(<<SASS)
+ baz {
+  c: d; }
+CSS
+ baz
+  c: d
+SASS
+  end
+
+  def test_loud_comment_interpolations_can_be_escaped
+    assert_equal <<CSS, render(<<SASS)
+/* \#{foo} */
+CSS
+/* \\\#{foo}
+SASS
+    assert_equal <<CSS, render(<<SASS)
+/*! \#{foo} */
+CSS
+/*! \\\#{foo}
+SASS
+  end
+
+  def test_selector_compression
+    assert_equal <<CSS, render(<<SASS, :style => :compressed)
+a>b,c+d,:-moz-any(e,f,g){h:i}
+CSS
+a > b, c + d, :-moz-any(e, f, g)
+  h: i
+SASS
+  end
+
+  def test_comment_like_selector
+    assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "/": expected identifier, was " foo"') 
{render(<<SASS)}
+/ foo
+  a: b
+SASS
+  end
+
+  def test_nested_empty_directive
+    assert_equal <<CSS, render(<<SASS)
+ media screen {
+  .foo {
+    a: b; }
+
+  @unknown-directive; }
+CSS
+ media screen
+  .foo
+    a: b
+
+  @unknown-directive
+SASS
+  end
+
+  # Encodings
+
+  unless Sass::Util.ruby1_8?
+    def test_encoding_error
+      render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
+      assert(false, "Expected exception")
+    rescue Sass::SyntaxError => e
+      assert_equal(3, e.sass_line)
+      assert_equal('Invalid UTF-8 character "\xFE"', e.message)
+    end
+
+    def test_ascii_incompatible_encoding_error
+      template = "foo\nbar\nb_z".encode("utf-16le")
+      template[9] = "\xFE".force_encoding("utf-16le")
+      render(template)
+      assert(false, "Expected exception")
+    rescue Sass::SyntaxError => e
+      assert_equal(3, e.sass_line)
+      assert_equal('Invalid UTF-16LE character "\xFE"', e.message)
+    end
+
+    def test_same_charset_as_encoding
+      assert_renders_encoded(<<CSS, <<SASS)
+ charset "UTF-8";
+fóó {
+  a: b; }
+CSS
+ charset "utf-8"
+fóó
+  a: b
+SASS
+    end
+
+    def test_different_charset_than_encoding
+      assert_renders_encoded(<<CSS.force_encoding("IBM866"), <<SASS)
+ charset "IBM866";
+fóó {
+  a: b; }
+CSS
+ charset "ibm866"
+fóó
+  a: b
+SASS
+    end
+
+    def test_different_encoding_than_system
+      assert_renders_encoded(<<CSS.encode("IBM866"), <<SASS.encode("IBM866"))
+ charset "IBM866";
+тАЬ {
+  a: b; }
+CSS
+тАЬ
+  a: b
+SASS
+    end
+
+    def test_multibyte_charset
+      assert_renders_encoded(<<CSS.encode("UTF-16LE"), <<SASS.encode("UTF-16LE").force_encoding("UTF-8"))
+ charset "UTF-16LE";
+fóó {
+  a: b; }
+CSS
+ charset "utf-16le"
+fóó
+  a: b
+SASS
+    end
+
+    def test_multibyte_charset_without_endian_specifier
+      assert_renders_encoded(<<CSS.encode("UTF-32BE"), <<SASS.encode("UTF-32BE").force_encoding("UTF-8"))
+ charset "UTF-32BE";
+fóó {
+  a: b; }
+CSS
+ charset "utf-32"
+fóó
+  a: b
+SASS
+    end
+
+    def test_utf8_bom
+      assert_renders_encoded(<<CSS, <<SASS.force_encoding("BINARY"))
+ charset "UTF-8";
+fóó {
+  a: b; }
+CSS
+\uFEFFfóó
+  a: b
+SASS
+    end
+
+    def test_utf16le_bom
+      assert_renders_encoded(<<CSS.encode("UTF-16LE"), <<SASS.encode("UTF-16LE").force_encoding("BINARY"))
+ charset "UTF-16LE";
+fóó {
+  a: b; }
+CSS
+\uFEFFfóó
+  a: b
+SASS
+    end
+
+    def test_utf32be_bom
+      assert_renders_encoded(<<CSS.encode("UTF-32BE"), <<SASS.encode("UTF-32BE").force_encoding("BINARY"))
+ charset "UTF-32BE";
+fóó {
+  a: b; }
+CSS
+\uFEFFfóó
+  a: b
+SASS
+    end
+
+    # Encoding Regression Test
+
+    def test_multibyte_prop_name
+      assert_equal(<<CSS, render(<<SASS))
+ charset "UTF-8";
+#bar {
+  cölor: blue; }
+CSS
+#bar
+  cölor: blue
+SASS
+    end
+
+    def test_multibyte_and_interpolation
+      assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))
+#bar {
+  background: a 0%; }
+CSS
+#bar {
+  // 
+  background: \#{a} 0%;
+}
+SCSS
+    end
+  end
+
+  def test_original_filename_set
+    importer = MockImporter.new
+    importer.add_import("imported", "div{color:red}")
+
+    original_filename = filename_for_test
+    engine = Sass::Engine.new('@import "imported"; div{color:blue}',
+      :filename => original_filename, :load_paths => [importer], :syntax => :scss, :importer => importer)
+    engine.render
+
+    assert_equal original_filename, engine.options[:original_filename]
+    assert_equal original_filename, importer.engine("imported").options[:original_filename]
+  end
+
+  def test_deprecated_PRECISION
+    assert_warning(<<END) {assert_equal 100_000.0, Sass::Script::Number::PRECISION}
+Sass::Script::Number::PRECISION is deprecated and will be removed in a future release. Use 
Sass::Script::Number.precision_factor instead.
+END
+  end
+
+  def test_changing_precision
+    old_precision = Sass::Script::Number.precision
+    begin
+      Sass::Script::Number.precision = 8
+      assert_equal <<CSS, render(<<SASS)
+div {
+  maximum: 1.00000001;
+  too-much: 1.0; }
+CSS
+div
+  maximum : 1.00000001
+  too-much: 1.000000001
+SASS
+    ensure
+      Sass::Script::Number.precision = old_precision
+    end
+  end
+
+  def test_content
+    assert_equal <<CSS, render(<<SASS)
+.children {
+  background-color: red;
+  color: blue;
+  border-color: red; }
+CSS
+$color: blue
+=context($class, $color: red)
+  .\#{$class}
+    background-color: $color
+    @content
+    border-color: $color
++context(children)
+  color: $color
+SASS
+  end
+
+  def test_selector_in_content
+    assert_equal <<CSS, render(<<SASS)
+.parent {
+  background-color: red;
+  border-color: red; }
+  .parent .children {
+    color: blue; }
+CSS
+$color: blue
+=context($class, $color: red)
+  .\#{$class}
+    background-color: $color
+    @content
+    border-color: $color
++context(parent)
+  .children
+    color: $color
+SASS
+  end
+
+  def test_using_parent_mixin_in_content
+    assert_equal <<CSS, render(<<SASS)
+.parent {
+  before-color: red;
+  after-color: red; }
+  .parent .sibling {
+    before-color: yellow;
+    after-color: yellow; }
+    .parent .sibling .child {
+      before-color: green;
+      color: blue;
+      after-color: green; }
+CSS
+$color: blue
+=context($class, $color: red)
+  .\#{$class}
+    before-color: $color
+    @content
+    after-color: $color
++context(parent)
+  +context(sibling, $color: yellow)
+    +context(child, $color: green)
+      color: $color
+SASS
+  end
+
+  def test_content_more_than_once
+    assert_equal <<CSS, render(<<SASS)
+.once {
+  color: blue; }
+
+.twice {
+  color: blue; }
+CSS
+$color: blue
+=context($class, $color: red)
+  .once
+    @content
+  .twice
+    @content
++context(parent)
+  color: $color
+SASS
+  end
+
+  def test_content_with_variable
+    assert_equal <<CSS, render(<<SASS)
+.foo {
+  a: 1px; }
+CSS
+=foo
+  .foo
+    @content
++foo
+  $a: 1px
+  a: $a
+SASS
+  end
+
+  def test_nested_content_blocks
+    assert_equal <<CSS, render(<<SASS)
+.foo {
+  a: foo; }
+  .foo .bar {
+    a: bar; }
+    .foo .bar .baz {
+      a: baz; }
+      .foo .bar .baz .outside {
+        a: outside;
+        color: red; }
+CSS
+$a: outside
+=baz($a: baz)
+  .baz
+    a: $a
+    @content
+=bar($a: bar)
+  .bar
+    a: $a
+    +baz
+      @content
+=foo($a: foo)
+  .foo
+    a: $a
+    +bar
+      @content
++foo
+  .outside
+    a: $a
+    color: red
+SASS
+  end
+
+  def test_content_not_seen_through_mixin
+    assert_equal <<CSS, render(<<SASS)
+a foo {
+  mixin: foo;
+  a: b; }
+  a foo bar {
+    mixin: bar; }
+CSS
+=foo
+  foo
+    mixin: foo
+    @content
+    +bar
+=bar
+  bar
+    mixin: bar
+    @content
+a
+  +foo
+    a: b
+SASS
+  end
+
+  def test_content_backtrace_for_perform
+    render(<<SASS)
+=foo
+  @content
+
+a
+  +foo
+    b: 1em + 2px
+SASS
+    assert(false, "Expected exception")
+  rescue Sass::SyntaxError => e
+    assert_equal([
+        {:mixin => '@content', :line => 6, :filename => 'test_content_backtrace_for_perform_inline.sass'},
+        {:mixin => 'foo', :line => 2, :filename => 'test_content_backtrace_for_perform_inline.sass'},
+        {:line => 5, :filename => 'test_content_backtrace_for_perform_inline.sass'},
+      ], e.sass_backtrace)
+  end
+
+  def test_content_backtrace_for_cssize
+    render(<<SASS)
+=foo
+  @content
+
+a
+  +foo
+    @extend foo bar baz
+SASS
+    assert(false, "Expected exception")
+  rescue Sass::SyntaxError => e
+    assert_equal([
+        {:mixin => '@content', :line => 6, :filename => 'test_content_backtrace_for_cssize_inline.sass'},
+        {:mixin => 'foo', :line => 2, :filename => 'test_content_backtrace_for_cssize_inline.sass'},
+        {:line => 5, :filename => 'test_content_backtrace_for_cssize_inline.sass'},
+      ], e.sass_backtrace)
+  end
+
+  private
+
+  def assert_hash_has(hash, expected)
+    expected.each {|k, v| assert_equal(v, hash[k])}
+  end
+
+  def assert_renders_encoded(css, sass)
+    result = render(sass)
+    assert_equal css.encoding, result.encoding
+    assert_equal css, result
+  end
+
+  def render(sass, options = {})
+    munge_filename options
+    options[:importer] ||= MockImporter.new
+    Sass::Engine.new(sass, options).render
+  end
+
+  def renders_correctly(name, options={})
+    sass_file  = load_file(name, "sass")
+    css_file   = load_file(name, "css")
+    options[:filename] ||= filename(name, "sass")
+    options[:syntax] ||= :sass
+    options[:css_filename] ||= filename(name, "css")
+    css_result = Sass::Engine.new(sass_file, options).render
+    assert_equal css_file, css_result
+  end
+
+  def load_file(name, type = "sass")
+    @result = ''
+    File.new(filename(name, type)).each_line { |l| @result += l }
+    @result
+  end
+
+  def filename(name, type)
+    File.dirname(__FILE__) + "/#{type == 'sass' ? 'templates' : 'results'}/#{name}.#{type}"
+  end
+
+  def sassc_path(template)
+    sassc_path = File.join(File.dirname(__FILE__) + "/templates/#{template}.sass")
+    engine = Sass::Engine.new("", :filename => sassc_path,
+      :importer => Sass::Importers::Filesystem.new("."))
+    key = engine.send(:sassc_key)
+    File.join(engine.options[:cache_location], key)
+  end
+end
+ 
diff --git a/backends/css/gems/sass-3.2.12/test/sass/exec_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/exec_test.rb
new file mode 100755
index 0000000..1f3e113
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/exec_test.rb
@@ -0,0 +1,86 @@
+#!/usr/bin/env ruby
+require File.dirname(__FILE__) + '/../test_helper'
+require 'sass/util/test'
+require 'tmpdir'
+
+class ExecTest < Test::Unit::TestCase
+  include Sass::Util::Test
+
+  def setup
+    @dir = Dir.mktmpdir
+  end
+
+  def teardown
+    FileUtils.rm_rf(@dir)
+    clean_up_sassc
+  end
+
+  def test_scss_t_expanded
+    src = get_path("src.scss")
+    dest = get_path("dest.css")
+    write(src, ".ruleset { margin: 0 }")
+    assert(exec(*%w[scss -t expanded --unix-newlines].push(src, dest)))
+    assert_equal(".ruleset {\n  margin: 0;\n}\n", read(dest))
+  end
+
+  def test_sass_convert_T_sass
+    src = get_path("src.scss")
+    dest = get_path("dest.css")
+    write(src, ".ruleset { margin: 0 }")
+    assert(exec(*%w[sass-convert -T sass --unix-newlines].push(src, dest)))
+    assert_equal(".ruleset\n  margin: 0\n", read(dest))
+  end
+
+  def test_sass_convert_T_sass_in_place
+    src = get_path("src.scss")
+    write(src, ".ruleset { margin: 0 }")
+    assert(exec(*%w[sass-convert -T sass --in-place --unix-newlines].push(src)))
+    assert_equal(".ruleset\n  margin: 0\n", read(src))
+  end
+
+  def test_scss_t_expanded_no_unix_newlines
+    return skip "Can be run on Windows only" unless Sass::Util.windows?
+    src = get_path("src.scss")
+    dest = get_path("dest.css")
+    write(src, ".ruleset { margin: 0 }")
+    assert(exec(*%w[scss -t expanded].push(src, dest)))
+    assert_equal(".ruleset {\r\n  margin: 0;\r\n}\r\n", read(dest))
+  end
+
+  def test_sass_convert_T_sass_no_unix_newlines
+    return skip "Can be run on Windows only" unless Sass::Util.windows?
+    src = get_path("src.scss")
+    dest = get_path("dest.sass")
+    write(src, ".ruleset { margin: 0 }")
+    assert(exec(*%w[sass-convert -T sass].push(src, dest)))
+    assert_equal(".ruleset\r\n  margin: 0\r\n", read(dest))
+  end
+
+  def test_sass_convert_T_sass_in_place_no_unix_newlines
+    return skip "Can be run on Windows only" unless Sass::Util.windows?
+    src = get_path("src.scss")
+    write(src, ".ruleset { margin: 0 }")
+    assert(exec(*%w[sass-convert -T sass --in-place].push(src)))
+    assert_equal(".ruleset\r\n  margin: 0\r\n", read(src))
+  end
+
+  private
+
+  def get_path(name)
+    File.join(@dir, name)
+  end
+
+  def read(file)
+    open(file, 'rb') {|f| f.read}
+  end
+
+  def write(file, content)
+    open(file, 'wb') {|f| f.write(content)}
+  end
+
+  def exec(script, *args)
+    script = File.dirname(__FILE__) + '/../../bin/' + script
+    ruby = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'] + 
RbConfig::CONFIG['EXEEXT'])
+    system(ruby, script, *args)
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/extend_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/extend_test.rb
new file mode 100755
index 0000000..fb24ce9
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/extend_test.rb
@@ -0,0 +1,1482 @@
+#!/usr/bin/env ruby
+require File.dirname(__FILE__) + '/../test_helper'
+
+class ExtendTest < Test::Unit::TestCase
+  def test_basic
+    assert_equal <<CSS, render(<<SCSS)
+.foo, .bar {
+  a: b; }
+CSS
+.foo {a: b}
+.bar { extend .foo}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+.foo, .bar {
+  a: b; }
+CSS
+.bar { extend .foo}
+.foo {a: b}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+.foo, .bar {
+  a: b; }
+
+.bar {
+  c: d; }
+CSS
+.foo {a: b}
+.bar {c: d; @extend .foo}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+.foo, .bar {
+  a: b; }
+
+.bar {
+  c: d; }
+CSS
+.foo {a: b}
+.bar { extend .foo; c: d}
+SCSS
+  end
+
+  def test_indented_syntax
+    assert_equal <<CSS, render(<<SASS, :syntax => :sass)
+.foo, .bar {
+  a: b; }
+CSS
+.foo
+  a: b
+.bar
+  @extend .foo
+SASS
+
+    assert_equal <<CSS, render(<<SASS, :syntax => :sass)
+.foo, .bar {
+  a: b; }
+CSS
+.foo
+  a: b
+.bar
+  @extend \#{".foo"}
+SASS
+  end
+
+  def test_multiple_targets
+    assert_equal <<CSS, render(<<SCSS)
+.foo, .bar {
+  a: b; }
+
+.blip .foo, .blip .bar {
+  c: d; }
+CSS
+.foo {a: b}
+.bar { extend .foo}
+.blip .foo {c: d}
+SCSS
+  end
+
+  def test_multiple_extendees
+    assert_equal <<CSS, render(<<SCSS)
+.foo, .baz {
+  a: b; }
+
+.bar, .baz {
+  c: d; }
+CSS
+.foo {a: b}
+.bar {c: d}
+.baz { extend .foo; @extend .bar}
+SCSS
+  end
+
+  def test_multiple_extends_with_single_extender_and_single_target
+    assert_extends('.foo .bar', '.baz { extend .foo; @extend .bar}',
+      '.foo .bar, .baz .bar, .foo .baz, .baz .baz')
+    assert_extends '.foo.bar', '.baz { extend .foo; @extend .bar}', '.foo.bar, .baz'
+  end
+
+  def test_multiple_extends_with_multiple_extenders_and_single_target
+    assert_equal <<CSS, render(<<SCSS)
+.foo .bar, .baz .bar, .foo .bang, .baz .bang {
+  a: b; }
+CSS
+.foo .bar {a: b}
+.baz { extend .foo}
+.bang { extend .bar}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+.foo.bar, .bar.baz, .baz.bang, .foo.bang {
+  a: b; }
+CSS
+.foo.bar {a: b}
+.baz { extend .foo}
+.bang { extend .bar}
+SCSS
+  end
+
+  def test_chained_extends
+    assert_equal <<CSS, render(<<SCSS)
+.foo, .bar, .baz, .bip {
+  a: b; }
+CSS
+.foo {a: b}
+.bar { extend .foo}
+.baz { extend .bar}
+.bip { extend .bar}
+SCSS
+  end
+
+  def test_dynamic_extendee
+    assert_extends '.foo', '.bar { extend #{".foo"}}', '.foo, .bar'
+    assert_extends('[baz^="blip12px"]', '.bar { extend [baz^="blip#{12px}"]}',
+      '[baz^="blip12px"], .bar')
+  end
+
+  def test_nested_target
+    assert_extends '.foo .bar', '.baz { extend .bar}', '.foo .bar, .foo .baz'
+  end
+
+  def test_target_with_child
+    assert_extends '.foo .bar', '.baz { extend .foo}', '.foo .bar, .baz .bar'
+  end
+
+  def test_class_unification
+    assert_unification '.foo.bar', '.baz { extend .foo}', '.foo.bar, .bar.baz' 
+    assert_unification '.foo.baz', '.baz { extend .foo}', '.baz' 
+  end
+
+  def test_id_unification
+    assert_unification '.foo.bar', '#baz { extend .foo}', '.foo.bar, .bar#baz'
+    assert_unification '.foo#baz', '#baz { extend .foo}', '#baz'
+
+    assert_extend_doesnt_match('#bar', '.foo', :failed_to_unify, 2) do
+      assert_unification '.foo#baz', '#bar { extend .foo}', '.foo#baz'
+    end
+  end
+
+  def test_universal_unification_with_simple_target
+    assert_unification '.foo', '* { extend .foo}', '.foo, *'
+    assert_unification '.foo', '*|* { extend .foo}', '.foo, *|*'
+    assert_unification '.foo.bar', '* { extend .foo}', '.bar'
+    assert_unification '.foo.bar', '*|* { extend .foo}', '.bar'
+    assert_unification '.foo.bar', 'ns|* { extend .foo}', '.foo.bar, ns|*.bar'
+  end
+
+  def test_universal_unification_with_namespaceless_universal_target
+    assert_unification '*.foo', '* { extend .foo}', '*'
+    assert_unification '*.foo', '*|* { extend .foo}', '*'
+    assert_unification '*|*.foo', '* { extend .foo}', '*|*.foo, *'
+    assert_unification '*|*.foo', '*|* { extend .foo}', '*|*'
+    assert_unification '*.foo', 'ns|* { extend .foo}', '*.foo, ns|*'
+    assert_unification '*|*.foo', 'ns|* { extend .foo}', '*|*.foo, ns|*'
+  end
+
+  def test_universal_unification_with_namespaced_universal_target
+    assert_unification 'ns|*.foo', '* { extend .foo}', 'ns|*'
+    assert_unification 'ns|*.foo', '*|* { extend .foo}', 'ns|*'
+
+    assert_extend_doesnt_match('ns2|*', '.foo', :failed_to_unify, 2) do
+      assert_unification 'ns1|*.foo', 'ns2|* { extend .foo}', 'ns1|*.foo'
+    end
+
+    assert_unification 'ns|*.foo', 'ns|* { extend .foo}', 'ns|*'
+  end
+
+  def test_universal_unification_with_namespaceless_element_target
+    assert_unification 'a.foo', '* { extend .foo}', 'a'
+    assert_unification 'a.foo', '*|* { extend .foo}', 'a'
+    assert_unification '*|a.foo', '* { extend .foo}', '*|a.foo, a'
+    assert_unification '*|a.foo', '*|* { extend .foo}', '*|a'
+    assert_unification 'a.foo', 'ns|* { extend .foo}', 'a.foo, ns|a'
+    assert_unification '*|a.foo', 'ns|* { extend .foo}', '*|a.foo, ns|a'
+  end
+
+  def test_universal_unification_with_namespaced_element_target
+    assert_unification 'ns|a.foo', '* { extend .foo}', 'ns|a'
+    assert_unification 'ns|a.foo', '*|* { extend .foo}', 'ns|a'
+
+    assert_extend_doesnt_match('ns2|*', '.foo', :failed_to_unify, 2) do
+      assert_unification 'ns1|a.foo', 'ns2|* { extend .foo}', 'ns1|a.foo'
+    end
+
+    assert_unification 'ns|a.foo', 'ns|* { extend .foo}', 'ns|a'
+  end
+
+  def test_element_unification_with_simple_target
+    assert_unification '.foo', 'a { extend .foo}', '.foo, a'
+    assert_unification '.foo.bar', 'a { extend .foo}', '.foo.bar, a.bar'
+    assert_unification '.foo.bar', '*|a { extend .foo}', '.foo.bar, *|a.bar'
+    assert_unification '.foo.bar', 'ns|a { extend .foo}', '.foo.bar, ns|a.bar'
+  end
+
+  def test_element_unification_with_namespaceless_universal_target
+    assert_unification '*.foo', 'a { extend .foo}', '*.foo, a'
+    assert_unification '*.foo', '*|a { extend .foo}', '*.foo, a'
+    assert_unification '*|*.foo', 'a { extend .foo}', '*|*.foo, a'
+    assert_unification '*|*.foo', '*|a { extend .foo}', '*|*.foo, *|a'
+    assert_unification '*.foo', 'ns|a { extend .foo}', '*.foo, ns|a'
+    assert_unification '*|*.foo', 'ns|a { extend .foo}', '*|*.foo, ns|a'
+  end
+
+  def test_element_unification_with_namespaced_universal_target
+    assert_unification 'ns|*.foo', 'a { extend .foo}', 'ns|*.foo, ns|a'
+    assert_unification 'ns|*.foo', '*|a { extend .foo}', 'ns|*.foo, ns|a'
+
+    assert_extend_doesnt_match('ns2|a', '.foo', :failed_to_unify, 2) do
+      assert_unification 'ns1|*.foo', 'ns2|a { extend .foo}', 'ns1|*.foo'
+    end
+
+    assert_unification 'ns|*.foo', 'ns|a { extend .foo}', 'ns|*.foo, ns|a'
+  end
+
+  def test_element_unification_with_namespaceless_element_target
+    assert_unification 'a.foo', 'a { extend .foo}', 'a'
+    assert_unification 'a.foo', '*|a { extend .foo}', 'a'
+    assert_unification '*|a.foo', 'a { extend .foo}', '*|a.foo, a'
+    assert_unification '*|a.foo', '*|a { extend .foo}', '*|a'
+    assert_unification 'a.foo', 'ns|a { extend .foo}', 'a.foo, ns|a'
+    assert_unification '*|a.foo', 'ns|a { extend .foo}', '*|a.foo, ns|a'
+
+    assert_extend_doesnt_match('h1', '.foo', :failed_to_unify, 2) do
+      assert_unification 'a.foo', 'h1 { extend .foo}', 'a.foo'
+    end
+  end
+
+  def test_element_unification_with_namespaced_element_target
+    assert_unification 'ns|a.foo', 'a { extend .foo}', 'ns|a'
+    assert_unification 'ns|a.foo', '*|a { extend .foo}', 'ns|a'
+
+    assert_extend_doesnt_match('ns2|a', '.foo', :failed_to_unify, 2) do
+      assert_unification 'ns1|a.foo', 'ns2|a { extend .foo}', 'ns1|a.foo'
+    end
+
+    assert_unification 'ns|a.foo', 'ns|a { extend .foo}', 'ns|a'
+  end
+
+  def test_attribute_unification
+    assert_unification '[foo=bar].baz', '[foo=baz] { extend .baz}', '[foo=bar].baz, [foo=bar][foo=baz]'
+    assert_unification '[foo=bar].baz', '[foo^=bar] { extend .baz}', '[foo=bar].baz, [foo=bar][foo^=bar]'
+    assert_unification '[foo=bar].baz', '[foot=bar] { extend .baz}', '[foo=bar].baz, [foo=bar][foot=bar]'
+    assert_unification '[foo=bar].baz', '[ns|foo=bar] { extend .baz}', '[foo=bar].baz, [foo=bar][ns|foo=bar]'
+    assert_unification '%-a [foo=bar].bar', '[foo=bar] { extend .bar}', '-a [foo=bar]'
+  end
+
+  def test_pseudo_unification
+    assert_unification ':foo.baz', ':foo(2n+1) { extend .baz}', ':foo.baz, :foo:foo(2n+1)'
+    assert_unification ':foo.baz', '::foo { extend .baz}', ':foo.baz, :foo::foo'
+
+    assert_extend_doesnt_match('::bar', '.baz', :failed_to_unify, 2) do
+      assert_unification '::foo.baz', '::bar { extend .baz}', '::foo.baz'
+    end
+
+    assert_extend_doesnt_match('::foo(2n+1)', '.baz', :failed_to_unify, 2) do
+      assert_unification '::foo.baz', '::foo(2n+1) { extend .baz}', '::foo.baz'
+    end
+
+    assert_unification '::foo.baz', '::foo { extend .baz}', '::foo'
+    assert_unification '::foo(2n+1).baz', '::foo(2n+1) { extend .baz}', '::foo(2n+1)'
+    assert_unification ':foo.baz', ':bar { extend .baz}', ':foo.baz, :foo:bar'
+    assert_unification '.baz:foo', ':after { extend .baz}', '.baz:foo, :foo:after'
+    assert_unification '.baz:after', ':foo { extend .baz}', '.baz:after, :foo:after'
+    assert_unification ':foo.baz', ':foo { extend .baz}', ':foo'
+  end
+
+  def test_pseudoelement_remains_at_end_of_selector
+    assert_extends '.foo::bar', '.baz { extend .foo}', '.foo::bar, .baz::bar'
+    assert_extends 'a.foo::bar', '.baz { extend .foo}', 'a.foo::bar, a.baz::bar'
+  end
+
+  def test_pseudoclass_remains_at_end_of_selector
+    assert_extends '.foo:bar', '.baz { extend .foo}', '.foo:bar, .baz:bar'
+    assert_extends 'a.foo:bar', '.baz { extend .foo}', 'a.foo:bar, a.baz:bar'
+  end
+
+  def test_not_remains_at_end_of_selector
+    assert_extends '.foo:not(.bar)', '.baz { extend .foo}', '.foo:not(.bar), .baz:not(.bar)'
+  end
+
+  def test_pseudoelement_goes_lefter_than_pseudoclass
+    assert_extends '.foo::bar', '.baz:bang { extend .foo}', '.foo::bar, .baz:bang::bar'
+    assert_extends '.foo:bar', '.baz::bang { extend .foo}', '.foo:bar, .baz:bar::bang'
+  end
+
+  def test_pseudoelement_goes_lefter_than_not
+    assert_extends '.foo::bar', '.baz:not(.bang) { extend .foo}', '.foo::bar, .baz:not(.bang)::bar'
+    assert_extends '.foo:not(.bang)', '.baz::bar { extend .foo}', '.foo:not(.bang), .baz:not(.bang)::bar'
+  end
+
+  def test_negation_unification
+    assert_unification ':not(.foo).baz', ':not(.bar) { extend .baz}', ':not(.foo).baz, :not(.foo):not(.bar)'
+    assert_unification ':not(.foo).baz', ':not(.foo) { extend .baz}', ':not(.foo)'
+    assert_unification ':not([a=b]).baz', ':not([a = b]) { extend .baz}', ':not([a=b])'
+  end
+
+  def test_comma_extendee
+    assert_equal <<CSS, render(<<SCSS)
+.foo, .baz {
+  a: b; }
+
+.bar, .baz {
+  c: d; }
+CSS
+.foo {a: b}
+.bar {c: d}
+.baz { extend .foo, .bar}
+SCSS
+  end
+
+  def test_redundant_selector_elimination
+    assert_equal <<CSS, render(<<SCSS)
+.foo.bar, .x, .y {
+  a: b; }
+CSS
+.foo.bar {a: b}
+.x { extend .foo, .bar}
+.y { extend .foo, .bar}
+SCSS
+  end
+
+  ## Long Extendees
+
+  def test_long_extendee
+    assert_extends '.foo.bar', '.baz { extend .foo.bar}', '.foo.bar, .baz'
+  end
+
+  def test_long_extendee_requires_all_selectors
+    assert_extend_doesnt_match('.baz', '.foo.bar', :not_found, 2) do
+      assert_extends '.foo', '.baz { extend .foo.bar}', '.foo'
+    end
+  end
+
+  def test_long_extendee_matches_supersets
+    assert_extends '.foo.bar.bap', '.baz { extend .foo.bar}', '.foo.bar.bap, .bap.baz'
+  end
+
+  def test_long_extendee_runs_unification
+    assert_extends 'ns|*.foo.bar', 'a.baz { extend .foo.bar}', 'ns|*.foo.bar, ns|a.baz'
+  end
+
+  ## Long Extenders
+
+  def test_long_extender
+    assert_extends '.foo.bar', '.baz.bang { extend .foo}', '.foo.bar, .bar.baz.bang'
+  end
+
+  def test_long_extender_runs_unification
+    assert_extends 'ns|*.foo.bar', 'a.baz { extend .foo}', 'ns|*.foo.bar, ns|a.bar.baz'
+  end
+
+  def test_long_extender_aborts_unification
+    assert_extend_doesnt_match('h1.baz', '.foo', :failed_to_unify, 2) do
+      assert_extends 'a.foo#bar', 'h1.baz { extend .foo}', 'a.foo#bar'
+    end
+
+    assert_extend_doesnt_match('.bang#baz', '.foo', :failed_to_unify, 2) do
+      assert_extends 'a.foo#bar', '.bang#baz { extend .foo}', 'a.foo#bar'
+    end
+  end
+
+  ## Nested Extenders
+
+  def test_nested_extender
+    assert_extends '.foo', 'foo bar { extend .foo}', '.foo, foo bar'
+  end
+
+  def test_nested_extender_runs_unification
+    assert_extends '.foo.bar', 'foo bar { extend .foo}', '.foo.bar, foo bar.bar'
+  end
+
+  def test_nested_extender_aborts_unification
+    assert_extend_doesnt_match('foo bar', '.foo', :failed_to_unify, 2) do
+      assert_extends 'baz.foo', 'foo bar { extend .foo}', 'baz.foo'
+    end
+  end
+
+  def test_nested_extender_alternates_parents
+    assert_extends('.baz .bip .foo', 'foo .grank bar { extend .foo}',
+      '.baz .bip .foo, .baz .bip foo .grank bar, foo .grank .baz .bip bar')
+  end
+
+  def test_nested_extender_unifies_identical_parents
+    assert_extends('.baz .bip .foo', '.baz .bip bar { extend .foo}',
+      '.baz .bip .foo, .baz .bip bar')
+  end
+
+  def test_nested_extender_unifies_common_substring
+    assert_extends('.baz .bip .bap .bink .foo', '.brat .bip .bap bar { extend .foo}',
+      '.baz .bip .bap .bink .foo, .baz .brat .bip .bap .bink bar, .brat .baz .bip .bap .bink bar')
+  end
+
+  def test_nested_extender_unifies_common_subseq
+    assert_extends('.a .x .b .y .foo', '.a .n .b .m bar { extend .foo}',
+      '.a .x .b .y .foo, .a .x .n .b .y .m bar, .a .n .x .b .y .m bar, .a .x .n .b .m .y bar, .a .n .x .b .m 
.y bar')
+  end
+
+  def test_nested_extender_chooses_first_subseq
+    assert_extends('.a .b .c .d .foo', '.c .d .a .b .bar { extend .foo}',
+      '.a .b .c .d .foo, .a .b .c .d .a .b .bar')
+  end
+
+  def test_nested_extender_counts_extended_subselectors
+    assert_extends('.a .bip.bop .foo', '.b .bip .bar { extend .foo}',
+      '.a .bip.bop .foo, .a .b .bip.bop .bar, .b .a .bip.bop .bar')
+  end
+
+  def test_nested_extender_counts_extended_superselectors
+    assert_extends('.a .bip .foo', '.b .bip.bop .bar { extend .foo}',
+      '.a .bip .foo, .a .b .bip.bop .bar, .b .a .bip.bop .bar')
+  end
+
+  def test_nested_extender_with_child_selector
+    assert_extends '.baz .foo', 'foo > bar { extend .foo}', '.baz .foo, .baz foo > bar'
+  end
+
+  def test_nested_extender_finds_common_selectors_around_child_selector
+    assert_extends 'a > b c .c1', 'a c .c2 { extend .c1}', 'a > b c .c1, a > b c .c2'
+    assert_extends 'a > b c .c1', 'b c .c2 { extend .c1}', 'a > b c .c1, a > b c .c2'
+  end
+
+  def test_nested_extender_doesnt_find_common_selectors_around_adjacent_sibling_selector
+    assert_extends 'a + b c .c1', 'a c .c2 { extend .c1}', 'a + b c .c1, a + b a c .c2, a a + b c .c2'
+    assert_extends 'a + b c .c1', 'a b .c2 { extend .c1}', 'a + b c .c1, a a + b c .c2'
+    assert_extends 'a + b c .c1', 'b c .c2 { extend .c1}', 'a + b c .c1, a + b c .c2'
+  end
+
+  def test_nested_extender_doesnt_find_common_selectors_around_sibling_selector
+    assert_extends 'a ~ b c .c1', 'a c .c2 { extend .c1}', 'a ~ b c .c1, a ~ b a c .c2, a a ~ b c .c2'
+    assert_extends 'a ~ b c .c1', 'a b .c2 { extend .c1}', 'a ~ b c .c1, a a ~ b c .c2'
+    assert_extends 'a ~ b c .c1', 'b c .c2 { extend .c1}', 'a ~ b c .c1, a ~ b c .c2'
+  end
+
+  def test_nested_extender_doesnt_find_common_selectors_around_reference_selector
+    assert_extends 'a /for/ b c .c1', 'a c .c2 { extend .c1}', 'a /for/ b c .c1, a /for/ b a c .c2, a a 
/for/ b c .c2'
+    assert_extends 'a /for/ b c .c1', 'a b .c2 { extend .c1}', 'a /for/ b c .c1, a a /for/ b c .c2'
+    assert_extends 'a /for/ b c .c1', 'b c .c2 { extend .c1}', 'a /for/ b c .c1, a /for/ b c .c2'
+  end
+
+  def test_nested_extender_with_early_child_selectors_doesnt_subseq_them
+    assert_extends('.bip > .bap .foo', '.grip > .bap .bar { extend .foo}',
+      '.bip > .bap .foo, .bip > .bap .grip > .bap .bar, .grip > .bap .bip > .bap .bar')
+    assert_extends('.bap > .bip .foo', '.bap > .grip .bar { extend .foo}',
+      '.bap > .bip .foo, .bap > .bip .bap > .grip .bar, .bap > .grip .bap > .bip .bar')
+  end
+
+  def test_nested_extender_with_child_selector_unifies
+    assert_extends '.baz.foo', 'foo > bar { extend .foo}', '.baz.foo, foo > bar.baz'
+
+    assert_equal <<CSS, render(<<SCSS)
+.baz > .foo, .baz > .bar {
+  a: b; }
+CSS
+.baz > {
+  .foo {a: b}
+  .bar { extend .foo}
+}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+.foo .bar, .foo > .baz {
+  a: b; }
+CSS
+.foo {
+  .bar {a: b}
+  > .baz { extend .bar}
+}
+SCSS
+  end
+
+  def test_another_nested_extender_with_early_child_selectors_doesnt_subseq_them
+    assert_equal <<CSS, render(<<SCSS)
+.foo .bar, .foo .bip > .baz {
+  a: b; }
+CSS
+.foo {
+  .bar {a: b}
+  .bip > .baz { extend .bar}
+}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+.foo .bip .bar, .foo .bip .foo > .baz {
+  a: b; }
+CSS
+.foo {
+  .bip .bar {a: b}
+  > .baz { extend .bar}
+}
+SCSS
+
+    assert_extends '.foo > .bar', '.bip + .baz { extend .bar}', '.foo > .bar, .foo > .bip + .baz'
+    assert_extends '.foo + .bar', '.bip > .baz { extend .bar}', '.foo + .bar, .bip > .foo + .baz'
+    assert_extends '.foo > .bar', '.bip > .baz { extend .bar}', '.foo > .bar, .bip.foo > .baz'
+  end
+
+  def test_nested_extender_with_trailing_child_selector
+    assert_raise(Sass::SyntaxError, "bar > can't extend: invalid selector") do
+      render("bar > { extend .baz}")
+    end
+  end
+
+  def test_nested_extender_with_sibling_selector
+    assert_extends '.baz .foo', 'foo + bar { extend .foo}', '.baz .foo, .baz foo + bar'
+  end
+
+  def test_nested_extender_with_hacky_selector
+    assert_extends('.baz .foo', 'foo + > > + bar { extend .foo}',
+      '.baz .foo, .baz foo + > > + bar, foo .baz + > > + bar')
+    assert_extends '.baz .foo', '> > bar { extend .foo}', '.baz .foo, > > .baz bar'
+  end
+
+  def test_nested_extender_merges_with_same_selector
+    assert_equal <<CSS, render(<<SCSS)
+.foo .bar, .foo .baz {
+  a: b; }
+CSS
+.foo {
+  .bar {a: b}
+  .baz { extend .bar} }
+SCSS
+  end
+
+  def test_nested_extender_with_child_selector_merges_with_same_selector
+    assert_extends('.foo > .bar .baz', '.foo > .bar .bang { extend .baz}',
+      '.foo > .bar .baz, .foo > .bar .bang')
+  end
+
+  # Combinator Unification
+
+  def test_combinator_unification_for_hacky_combinators
+    assert_extends '.a > + x', '.b y { extend x}', '.a > + x, .a .b > + y, .b .a > + y'
+    assert_extends '.a x', '.b > + y { extend x}', '.a x, .a .b > + y, .b .a > + y'
+    assert_extends '.a > + x', '.b > + y { extend x}', '.a > + x, .a .b > + y, .b .a > + y'
+    assert_extends '.a ~ > + x', '.b > + y { extend x}', '.a ~ > + x, .a .b ~ > + y, .b .a ~ > + y'
+    assert_extends '.a + > x', '.b > + y { extend x}', '.a + > x'
+    assert_extends '.a + > x', '.b > + y { extend x}', '.a + > x'
+    assert_extends '.a ~ > + .b > x', '.c > + .d > y { extend x}', '.a ~ > + .b > x, .a .c ~ > + .d.b > y, 
.c .a ~ > + .d.b > y'
+  end
+
+  def test_combinator_unification_double_tilde
+    assert_extends '.a.b ~ x', '.a ~ y { extend x}', '.a.b ~ x, .a.b ~ y'
+    assert_extends '.a ~ x', '.a.b ~ y { extend x}', '.a ~ x, .a.b ~ y'
+    assert_extends '.a ~ x', '.b ~ y { extend x}', '.a ~ x, .a ~ .b ~ y, .b ~ .a ~ y, .b.a ~ y'
+    assert_extends 'a.a ~ x', 'b.b ~ y { extend x}', 'a.a ~ x, a.a ~ b.b ~ y, b.b ~ a.a ~ y'
+  end
+
+  def test_combinator_unification_tilde_plus
+    assert_extends '.a.b + x', '.a ~ y { extend x}', '.a.b + x, .a.b + y'
+    assert_extends '.a + x', '.a.b ~ y { extend x}', '.a + x, .a.b ~ .a + y, .a.b + y'
+    assert_extends '.a + x', '.b ~ y { extend x}', '.a + x, .b ~ .a + y, .b.a + y'
+    assert_extends 'a.a + x', 'b.b ~ y { extend x}', 'a.a + x, b.b ~ a.a + y'
+    assert_extends '.a.b ~ x', '.a + y { extend x}', '.a.b ~ x, .a.b ~ .a + y, .a.b + y'
+    assert_extends '.a ~ x', '.a.b + y { extend x}', '.a ~ x, .a.b + y'
+    assert_extends '.a ~ x', '.b + y { extend x}', '.a ~ x, .a ~ .b + y, .a.b + y'
+    assert_extends 'a.a ~ x', 'b.b + y { extend x}', 'a.a ~ x, a.a ~ b.b + y'
+  end
+
+  def test_combinator_unification_angle_sibling
+    assert_extends '.a > x', '.b ~ y { extend x}', '.a > x, .a > .b ~ y'
+    assert_extends '.a > x', '.b + y { extend x}', '.a > x, .a > .b + y'
+    assert_extends '.a ~ x', '.b > y { extend x}', '.a ~ x, .b > .a ~ y'
+    assert_extends '.a + x', '.b > y { extend x}', '.a + x, .b > .a + y'
+  end
+
+  def test_combinator_unification_double_angle
+    assert_extends '.a.b > x', '.b > y { extend x}', '.a.b > x, .b.a > y'
+    assert_extends '.a > x', '.a.b > y { extend x}', '.a > x, .a.b > y'
+    assert_extends '.a > x', '.b > y { extend x}', '.a > x, .b.a > y'
+    assert_extends 'a.a > x', 'b.b > y { extend x}', 'a.a > x'
+  end
+
+  def test_combinator_unification_double_plus
+    assert_extends '.a.b + x', '.b + y { extend x}', '.a.b + x, .b.a + y'
+    assert_extends '.a + x', '.a.b + y { extend x}', '.a + x, .a.b + y'
+    assert_extends '.a + x', '.b + y { extend x}', '.a + x, .b.a + y'
+    assert_extends 'a.a + x', 'b.b + y { extend x}', 'a.a + x'
+  end
+
+  def test_combinator_unification_angle_space
+    assert_extends '.a.b > x', '.a y { extend x}', '.a.b > x, .a.b > y'
+    assert_extends '.a > x', '.a.b y { extend x}', '.a > x, .a.b .a > y'
+    assert_extends '.a > x', '.b y { extend x}', '.a > x, .b .a > y'
+    assert_extends '.a.b x', '.a > y { extend x}', '.a.b x, .a.b .a > y'
+    assert_extends '.a x', '.a.b > y { extend x}', '.a x, .a.b > y'
+    assert_extends '.a x', '.b > y { extend x}', '.a x, .a .b > y'
+  end
+
+  def test_combinator_unification_plus_space
+    assert_extends '.a.b + x', '.a y { extend x}', '.a.b + x, .a .a.b + y'
+    assert_extends '.a + x', '.a.b y { extend x}', '.a + x, .a.b .a + y'
+    assert_extends '.a + x', '.b y { extend x}', '.a + x, .b .a + y'
+    assert_extends '.a.b x', '.a + y { extend x}', '.a.b x, .a.b .a + y'
+    assert_extends '.a x', '.a.b + y { extend x}', '.a x, .a .a.b + y'
+    assert_extends '.a x', '.b + y { extend x}', '.a x, .a .b + y'
+  end
+
+  def test_combinator_unification_nested
+    assert_extends '.a > .b + x', '.c > .d + y { extend x}', '.a > .b + x, .c.a > .d.b + y'
+    assert_extends '.a > .b + x', '.c > y { extend x}', '.a > .b + x, .c.a > .b + y'
+  end
+
+  def test_combinator_unification_with_newlines
+    assert_equal <<CSS, render(<<SCSS)
+.a >
+.b
++ x, .c.a > .d.b + y {
+  a: b; }
+CSS
+.a >
+.b
++ x {a: b}
+.c
+> .d +
+y { extend x}
+SCSS
+  end
+
+  # Loops
+
+  def test_extend_self_loop
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: b; }
+CSS
+.foo {a: b; @extend .foo}
+SCSS
+  end
+
+  def test_basic_extend_loop
+    assert_equal <<CSS, render(<<SCSS)
+.bar, .foo {
+  a: b; }
+
+.foo, .bar {
+  c: d; }
+CSS
+.foo {a: b; @extend .bar}
+.bar {c: d; @extend .foo}
+SCSS
+  end
+
+  def test_three_level_extend_loop
+    assert_equal <<CSS, render(<<SCSS)
+.baz, .bar, .foo {
+  a: b; }
+
+.foo, .baz, .bar {
+  c: d; }
+
+.bar, .foo, .baz {
+  e: f; }
+CSS
+.foo {a: b; @extend .bar}
+.bar {c: d; @extend .baz}
+.baz {e: f; @extend .foo}
+SCSS
+  end
+
+  def test_nested_extend_loop
+    assert_equal <<CSS, render(<<SCSS)
+.bar, .bar .foo {
+  a: b; }
+  .bar .foo {
+    c: d; }
+CSS
+.bar {
+  a: b;
+  .foo {c: d; @extend .bar}
+}
+SCSS
+  end
+
+  def test_multiple_extender_merges_with_superset_selector
+    assert_equal <<CSS, render(<<SCSS)
+a.bar.baz, a.foo {
+  a: b; }
+CSS
+.foo { extend .bar; @extend .baz}
+a.bar.baz {a: b}
+SCSS
+  end
+
+  def test_control_flow_if
+    assert_equal <<CSS, render(<<SCSS)
+.true, .also-true {
+  color: green; }
+
+.false, .also-false {
+  color: red; }
+CSS
+.true  { color: green; }
+.false { color: red;   }
+.also-true {
+  @if true { @extend .true;  }
+  @else    { @extend .false; }
+}
+.also-false {
+  @if false { @extend .true;  }
+  @else     { @extend .false; }
+}
+SCSS
+  end
+
+  def test_control_flow_for
+    assert_equal <<CSS, render(<<SCSS)
+.base-0, .added {
+  color: green; }
+
+.base-1, .added {
+  display: block; }
+
+.base-2, .added {
+  border: 1px solid blue; }
+CSS
+.base-0  { color: green; }
+.base-1  { display: block; }
+.base-2  { border: 1px solid blue; }
+.added {
+  @for $i from 0 to 3 {
+    @extend .base-\#{$i};
+  }
+}
+SCSS
+  end
+
+  def test_control_flow_while
+    assert_equal <<CSS, render(<<SCSS)
+.base-0, .added {
+  color: green; }
+
+.base-1, .added {
+  display: block; }
+
+.base-2, .added {
+  border: 1px solid blue; }
+CSS
+.base-0  { color: green; }
+.base-1  { display: block; }
+.base-2  { border: 1px solid blue; }
+.added {
+  $i : 0;
+  @while $i < 3 {
+    @extend .base-\#{$i};
+    $i : $i + 1;
+  }
+}
+SCSS
+  end
+
+  def test_basic_placeholder_selector
+    assert_extends '%foo', '.bar { extend %foo}', '.bar'
+  end
+
+  def test_unused_placeholder_selector
+    assert_equal <<CSS, render(<<SCSS)
+.baz {
+  color: blue; }
+CSS
+%foo {color: blue}
+%bar {color: red}
+.baz { extend %foo}
+SCSS
+  end
+
+  def test_placeholder_descendant_selector
+    assert_extends '#context %foo a', '.bar { extend %foo}', '#context .bar a'
+  end
+
+  def test_semi_placeholder_selector
+    assert_equal <<CSS, render(<<SCSS)
+.bar .baz {
+  color: blue; }
+CSS
+#context %foo, .bar .baz {color: blue}
+SCSS
+  end
+
+  def test_placeholder_selector_with_multiple_extenders
+    assert_equal <<CSS, render(<<SCSS)
+.bar, .baz {
+  color: blue; }
+CSS
+%foo {color: blue}
+.bar { extend %foo}
+.baz { extend %foo}
+SCSS
+  end
+
+  def test_placeholder_selector_as_modifier
+    assert_extend_doesnt_match('div', '%foo', :failed_to_unify, 3) do
+      assert_equal <<CSS, render(<<SCSS)
+a.baz.bar {
+  color: blue; }
+CSS
+a%foo.baz {color: blue}
+.bar { extend %foo}
+div { extend %foo}
+SCSS
+    end
+  end
+
+  def test_placeholder_interpolation
+    assert_equal <<CSS, render(<<SCSS)
+.bar {
+  color: blue; }
+CSS
+$foo: foo;
+
+%\#{$foo} {color: blue}
+.bar { extend %foo}
+SCSS
+  end
+
+  def test_media_in_placeholder_selector
+    assert_equal <<CSS, render(<<SCSS)
+.baz {
+  c: d; }
+CSS
+%foo {bar { media screen {a: b}}}
+.baz {c: d}
+SCSS
+  end
+
+  def test_extend_out_of_media
+    assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
+DEPRECATION WARNING on line 3 of test_extend_out_of_media_inline.scss:
+  @extending an outer selector from within @media is deprecated.
+  You may only @extend selectors within the same directive.
+  This will be an error in Sass 3.3.
+  It can only work once @extend is supported natively in the browser.
+WARN
+.foo {
+  a: b; }
+CSS
+.foo {a: b}
+ media screen {
+  .bar { extend .foo}
+}
+SCSS
+  end
+
+  def test_extend_out_of_unknown_directive
+    assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
+DEPRECATION WARNING on line 3 of test_extend_out_of_unknown_directive_inline.scss:
+  @extending an outer selector from within @flooblehoof is deprecated.
+  You may only @extend selectors within the same directive.
+  This will be an error in Sass 3.3.
+  It can only work once @extend is supported natively in the browser.
+WARN
+.foo {
+  a: b; }
+
+ flooblehoof {}
+CSS
+.foo {a: b}
+ flooblehoof {
+  .bar { extend .foo}
+}
+SCSS
+  end
+
+  def test_extend_out_of_nested_directives
+    assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
+DEPRECATION WARNING on line 4 of test_extend_out_of_nested_directives_inline.scss:
+  @extending an outer selector from within @flooblehoof is deprecated.
+  You may only @extend selectors within the same directive.
+  This will be an error in Sass 3.3.
+  It can only work once @extend is supported natively in the browser.
+WARN
+ media screen {
+  .foo {
+    a: b; }
+
+  @flooblehoof {} }
+CSS
+ media screen {
+  .foo {a: b}
+  @flooblehoof {
+    .bar { extend .foo}
+  }
+}
+SCSS
+  end
+
+  def test_extend_within_media
+    assert_equal(<<CSS, render(<<SCSS))
+ media screen {
+  .foo, .bar {
+    a: b; } }
+CSS
+ media screen {
+  .foo {a: b}
+  .bar { extend .foo}
+}
+SCSS
+  end
+
+  def test_extend_within_unknown_directive
+    assert_equal(<<CSS, render(<<SCSS))
+ flooblehoof {
+  .foo, .bar {
+    a: b; } }
+CSS
+ flooblehoof {
+  .foo {a: b}
+  .bar { extend .foo}
+}
+SCSS
+  end
+
+  def test_extend_within_nested_directives
+    assert_equal(<<CSS, render(<<SCSS))
+ media screen {
+  @flooblehoof {
+    .foo, .bar {
+      a: b; } } }
+CSS
+ media screen {
+  @flooblehoof {
+    .foo {a: b}
+    .bar { extend .foo}
+  }
+}
+SCSS
+  end
+
+  def test_extend_within_disparate_media
+    assert_equal(<<CSS, render(<<SCSS))
+ media screen {
+  .foo, .bar {
+    a: b; } }
+CSS
+ media screen {.foo {a: b}}
+ media screen {.bar { extend .foo}}
+SCSS
+  end
+
+  def test_extend_within_disparate_unknown_directive
+    assert_equal(<<CSS, render(<<SCSS))
+ flooblehoof {
+  .foo, .bar {
+    a: b; } }
+
+ flooblehoof {}
+CSS
+ flooblehoof {.foo {a: b}}
+ flooblehoof {.bar { extend .foo}}
+SCSS
+  end
+
+  def test_extend_within_disparate_nested_directives
+    assert_equal(<<CSS, render(<<SCSS))
+ media screen {
+  @flooblehoof {
+    .foo, .bar {
+      a: b; } } }
+ media screen {
+  @flooblehoof {} }
+CSS
+ media screen { flooblehoof {.foo {a: b}}}
+ media screen { flooblehoof {.bar { extend .foo}}}
+SCSS
+  end
+
+  def test_extend_within_and_without_media
+    assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
+DEPRECATION WARNING on line 4 of test_extend_within_and_without_media_inline.scss:
+  @extending an outer selector from within @media is deprecated.
+  You may only @extend selectors within the same directive.
+  This will be an error in Sass 3.3.
+  It can only work once @extend is supported natively in the browser.
+WARN
+.foo {
+  a: b; }
+
+ media screen {
+  .foo, .bar {
+    c: d; } }
+CSS
+.foo {a: b}
+ media screen {
+  .foo {c: d}
+  .bar { extend .foo}
+}
+SCSS
+  end
+
+  def test_extend_within_and_without_unknown_directive
+    assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
+DEPRECATION WARNING on line 4 of test_extend_within_and_without_unknown_directive_inline.scss:
+  @extending an outer selector from within @flooblehoof is deprecated.
+  You may only @extend selectors within the same directive.
+  This will be an error in Sass 3.3.
+  It can only work once @extend is supported natively in the browser.
+WARN
+.foo {
+  a: b; }
+
+ flooblehoof {
+  .foo, .bar {
+    c: d; } }
+CSS
+.foo {a: b}
+ flooblehoof {
+  .foo {c: d}
+  .bar { extend .foo}
+}
+SCSS
+  end
+
+  def test_extend_within_and_without_nested_directives
+    assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
+DEPRECATION WARNING on line 5 of test_extend_within_and_without_nested_directives_inline.scss:
+  @extending an outer selector from within @flooblehoof is deprecated.
+  You may only @extend selectors within the same directive.
+  This will be an error in Sass 3.3.
+  It can only work once @extend is supported natively in the browser.
+WARN
+ media screen {
+  .foo {
+    a: b; }
+
+  @flooblehoof {
+    .foo, .bar {
+      c: d; } } }
+CSS
+ media screen {
+  .foo {a: b}
+  @flooblehoof {
+    .foo {c: d}
+    .bar { extend .foo}
+  }
+}
+SCSS
+  end
+
+  def test_extend_with_subject_transfers_subject_to_extender
+    assert_equal(<<CSS, render(<<SCSS))
+foo bar! baz, foo .bip .bap! baz, .bip foo .bap! baz {
+  a: b; }
+CSS
+foo bar! baz {a: b}
+.bip .bap { extend bar}
+SCSS
+
+    assert_equal(<<CSS, render(<<SCSS))
+foo.x bar.y! baz.z, foo.x .bip bar.bap! baz.z, .bip foo.x bar.bap! baz.z {
+  a: b; }
+CSS
+foo.x bar.y! baz.z {a: b}
+.bip .bap { extend .y}
+SCSS
+  end
+
+  def test_extend_with_subject_retains_subject_on_target
+    assert_equal(<<CSS, render(<<SCSS))
+.foo! .bar, .foo! .bip .bap, .bip .foo! .bap {
+  a: b; }
+CSS
+.foo! .bar {a: b}
+.bip .bap { extend .bar}
+SCSS
+  end
+
+  def test_extend_with_subject_transfers_subject_to_target
+    assert_equal(<<CSS, render(<<SCSS))
+a.foo .bar, .bip a.bap! .bar {
+  a: b; }
+CSS
+a.foo .bar {a: b}
+.bip .bap! { extend .foo}
+SCSS
+  end
+
+  def test_extend_with_subject_retains_subject_on_extender
+    assert_equal(<<CSS, render(<<SCSS))
+.foo .bar, .foo .bip! .bap, .bip! .foo .bap {
+  a: b; }
+CSS
+.foo .bar {a: b}
+.bip! .bap { extend .bar}
+SCSS
+  end
+
+  def test_extend_with_subject_fails_with_conflicting_subject
+    assert_equal(<<CSS, render(<<SCSS))
+x! .bar {
+  a: b; }
+CSS
+x! .bar {a: b}
+y! .bap { extend .bar}
+SCSS
+end
+
+  def test_extend_warns_when_extendee_doesnt_exist
+    assert_warning(<<WARN) {assert_equal("", render(<<SCSS))}
+WARNING on line 1 of test_extend_warns_when_extendee_doesnt_exist_inline.scss: ".foo" failed to @extend 
".bar".
+  The selector ".bar" was not found.
+  This will be an error in future releases of Sass.
+  Use "@extend .bar !optional" if the extend should be able to fail.
+WARN
+.foo { extend .bar}
+SCSS
+  end
+
+  def test_extend_warns_when_extension_fails
+    assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SCSS))}
+WARNING on line 2 of test_extend_warns_when_extension_fails_inline.scss: "b.foo" failed to @extend ".bar".
+  No selectors matching ".bar" could be unified with "b.foo".
+  This will be an error in future releases of Sass.
+  Use "@extend .bar !optional" if the extend should be able to fail.
+WARN
+a.bar {
+  a: b; }
+CSS
+a.bar {a: b}
+b.foo { extend .bar}
+SCSS
+  end
+
+  def test_extend_does_not_warn_when_one_extension_fails_but_others_dont
+    assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
+a.bar {
+  a: b; }
+
+.bar, b.foo {
+  c: d; }
+CSS
+a.bar {a: b}
+.bar {c: d}
+b.foo { extend .bar}
+SCSS
+  end
+
+  def test_optional_extend_does_not_warn_when_extendee_doesnt_exist
+    assert_no_warning {assert_equal("", render(<<SCSS))}
+.foo { extend .bar !optional}
+SCSS
+  end
+
+  def test_optional_extend_does_not_warn_when_extension_fails
+    assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
+a.bar {
+  a: b; }
+CSS
+a.bar {a: b}
+b.foo { extend .bar !optional}
+SCSS
+  end
+
+  # Regression Tests
+
+  def test_pseudo_element_superselector
+    # Pseudo-elements shouldn't be removed in superselector calculations.
+    assert_equal <<CSS, render(<<SCSS)
+a#bar, a#bar::fblthp {
+  a: b; }
+CSS
+%x#bar {a: b} // Add an id to make the results have high specificity
+%y, %y::fblthp { extend %x}
+a { extend %y}
+SCSS
+
+    # Pseudo-classes can be removed when the second law allows.
+    assert_equal <<CSS, render(<<SCSS)
+a#bar {
+  a: b; }
+CSS
+%x#bar {a: b}
+%y, %y:fblthp { extend %x}
+a { extend %y}
+SCSS
+
+    # A few pseudo-elements can be written as pseudo-elements for historical
+    # reasons. See http://www.w3.org/TR/selectors4/#pseudo-elements.
+    %w[first-line first-letter before after].each do |pseudo|
+      assert_equal <<CSS, render(<<SCSS)
+a#bar, a#bar:#{pseudo} {
+  a: b; }
+CSS
+%x#bar {a: b}
+%y, %y:#{pseudo} { extend %x}
+a { extend %y}
+SCSS
+    end
+  end
+
+  def test_multiple_source_redundancy_elimination
+    assert_equal <<CSS, render(<<SCSS)
+.test-case, .test-case:active {
+  color: red; }
+
+.test-case:hover {
+  color: green; }
+CSS
+%default-color {color: red}
+%alt-color {color: green}
+
+%default-style {
+  @extend %default-color;
+  &:hover { extend %alt-color}
+  &:active { extend %default-color}
+}
+
+.test-case { extend %default-style}
+SCSS
+  end
+
+  def test_nested_sibling_extend
+    assert_equal <<CSS, render(<<SCSS)
+.parent .bar, .parent .foo {
+  width: 2000px; }
+CSS
+.foo { extend .bar}
+
+.parent {
+  .bar {
+    width: 2000px;
+  }
+  .foo {
+    @extend .bar
+  }
+}
+SCSS
+  end
+
+  def test_parent_and_sibling_extend
+    assert_equal <<CSS, render(<<SCSS)
+.parent1 .parent2 .child1.child2, .parent2 .parent1 .child1.child2 {
+  c: d; }
+CSS
+%foo %bar%baz {c: d}
+
+.parent1 {
+  @extend %foo;
+  .child1 { extend %bar}
+}
+
+.parent2 {
+  @extend %foo;
+  .child2 { extend %baz}
+}
+SCSS
+  end
+
+  def test_nested_extend_specificity
+    assert_equal <<CSS, render(<<SCSS)
+a :b, a :b:c {
+  a: b; }
+CSS
+%foo {a: b}
+
+a {
+  :b { extend %foo}
+  :b:c { extend %foo}
+}
+SCSS
+  end
+
+  def test_nested_double_extend_optimization
+    assert_equal <<CSS, render(<<SCSS)
+.parent1 .child {
+  a: b; }
+CSS
+%foo %bar {
+  a: b;
+}
+
+.parent1 {
+  @extend %foo;
+
+  .child {
+    @extend %bar;
+  }
+}
+
+.parent2 {
+  @extend %foo;
+}
+SCSS
+  end
+
+  def test_extend_in_double_nested_media_query
+    assert_equal <<CSS, render(<<SCSS)
+ media all and (orientation: landscape) {
+  .bar {
+    color: blue; } }
+CSS
+ media all {
+  @media (orientation: landscape) {
+    %foo {color: blue}
+    .bar { extend %foo}
+  }
+}
+SCSS
+  end
+
+  def test_partially_failed_extend
+    assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
+.rc, test {
+  color: white; }
+
+.prices span.pill span.rc {
+  color: red; }
+CSS
+test { @extend .rc; }
+.rc {color: white;}
+.prices span.pill span.rc {color: red;}
+SCSS
+  end
+
+  def test_newline_near_combinator
+    assert_equal <<CSS, render(<<SCSS)
+.a +
+.b x, .a +
+.b .c y, .c .a +
+.b y {
+  a: b; }
+CSS
+.a +
+.b x {a: b}
+.c y { extend x}
+SCSS
+  end
+
+  def test_duplicated_selector_with_newlines
+    assert_equal(<<CSS, render(<<SCSS))
+.example-1-1,
+.example-1-2,
+.my-page-1 .my-module-1-1,
+.example-1-3 {
+  a: b; }
+CSS
+.example-1-1,
+.example-1-2,
+.example-1-3 {
+  a: b;
+}
+
+.my-page-1 .my-module-1-1 { extend .example-1-2}
+SCSS
+  end
+
+  def test_nested_selector_with_child_selector_hack_extendee
+    assert_extends '> .foo', 'foo bar { extend .foo}', '> .foo, > foo bar'
+  end
+
+  def test_nested_selector_with_child_selector_hack_extender
+    assert_extends '.foo .bar', '> foo bar { extend .bar}', '.foo .bar, > .foo foo bar, > foo .foo bar'
+  end
+
+  def test_nested_selector_with_child_selector_hack_extender_and_extendee
+    assert_extends '> .foo', '> foo bar { extend .foo}', '> .foo, > foo bar'
+  end
+
+  def test_nested_selector_with_child_selector_hack_extender_and_sibling_selector_extendee
+    assert_extends '~ .foo', '> foo bar { extend .foo}', '~ .foo'
+  end
+
+  def test_nested_selector_with_child_selector_hack_extender_and_extendee_and_newline
+    assert_equal <<CSS, render(<<SCSS)
+> .foo, > flip,
+> foo bar {
+  a: b; }
+CSS
+> .foo {a: b}
+flip,
+> foo bar { extend .foo}
+SCSS
+  end
+
+  def test_extended_parent_and_child_redundancy_elimination
+    assert_equal <<CSS, render(<<SCSS)
+a b, d b, a c, d c {
+  a: b; }
+CSS
+a {
+  b {a: b}
+  c { extend b}
+}
+d { extend a}
+SCSS
+  end
+
+  def test_extend_redundancy_elimination_when_it_would_reduce_specificity
+    assert_extends 'a', 'a.foo { extend a}', 'a, a.foo'
+  end
+
+  def test_extend_redundancy_elimination_when_it_would_preserve_specificity
+    assert_extends '.bar a', 'a.foo { extend a}', '.bar a'
+  end
+
+  def test_extend_redundancy_elimination_never_eliminates_base_selector
+    assert_extends 'a.foo', '.foo { extend a}', 'a.foo, .foo'
+  end
+
+  def test_extend_cross_branch_redundancy_elimination
+    assert_equal <<CSS, render(<<SCSS)
+.a .c .d, .b .c .a .d {
+  a: b; }
+CSS
+%x .c %y {a: b}
+.a, .b { extend %x}
+.a .d { extend %y}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+.e .a .c .d, .a .c .e .d, .e .b .c .a .d, .b .c .a .e .d {
+  a: b; }
+CSS
+.e %z {a: b}
+%x .c %y { extend %z}
+.a, .b { extend %x}
+.a .d { extend %y}
+SCSS
+  end
+
+  private
+
+  def assert_extend_doesnt_match(extender, target, reason, line, syntax = :scss)
+    warn = "\"#{extender}\" failed to @extend \"#{target}\"."
+    reason = 
+      if reason == :not_found
+        "The selector \"#{target}\" was not found."
+      else
+        "No selectors matching \"#{target}\" could be unified with \"#{extender}\"."
+      end
+
+    assert_warning(<<WARNING) {yield}
+WARNING on line #{line} of #{filename_for_test syntax}: #{warn}
+  #{reason}
+  This will be an error in future releases of Sass.
+  Use "@extend #{target} !optional" if the extend should be able to fail.
+WARNING
+  end
+
+  def assert_unification(selector, extension, unified)
+    # Do some trickery so the first law of extend doesn't get in our way.
+    assert_extends(
+      "%-a #{selector}",
+      extension + " -a { extend %-a}",
+      unified.split(', ').map {|s| "-a #{s}"}.join(', '))
+  end
+
+  def assert_extends(selector, extension, result)
+    assert_equal <<CSS, render(<<SCSS)
+#{result} {
+  a: b; }
+CSS
+#{selector} {a: b}
+#{extension}
+SCSS
+  end
+
+  def render(sass, options = {})
+    options = {:syntax => :scss}.merge(options)
+    munge_filename options
+    Sass::Engine.new(sass, options).render
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/fixtures/test_staleness_check_across_importers.css 
b/backends/css/gems/sass-3.2.12/test/sass/fixtures/test_staleness_check_across_importers.css
new file mode 100644
index 0000000..77b6225
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/fixtures/test_staleness_check_across_importers.css
@@ -0,0 +1 @@
+.pear { color: green; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/fixtures/test_staleness_check_across_importers.scss 
b/backends/css/gems/sass-3.2.12/test/sass/fixtures/test_staleness_check_across_importers.scss
new file mode 100644
index 0000000..1468ac9
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/fixtures/test_staleness_check_across_importers.scss
@@ -0,0 +1 @@
+ import "apple";
diff --git a/backends/css/gems/sass-3.2.12/test/sass/functions_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/functions_test.rb
new file mode 100755
index 0000000..7498f7a
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/functions_test.rb
@@ -0,0 +1,1139 @@
+#!/usr/bin/env ruby
+require 'test/unit'
+require File.dirname(__FILE__) + '/../test_helper'
+require 'sass/script'
+
+module Sass::Script::Functions
+  def no_kw_args
+    Sass::Script::String.new("no-kw-args")
+  end
+
+  def only_var_args(*args)
+    Sass::Script::String.new("only-var-args("+args.map{|a| a.plus(Sass::Script::Number.new(1)).to_s 
}.join(", ")+")")
+  end
+  declare :only_var_args, [], :var_args => true
+
+  def only_kw_args(kwargs)
+    Sass::Script::String.new("only-kw-args(" + kwargs.keys.map {|a| a.to_s}.sort.join(", ") + ")")
+  end
+  declare :only_kw_args, [], :var_kwargs => true
+end
+
+module Sass::Script::Functions::UserFunctions
+  def call_options_on_new_literal
+    str = Sass::Script::String.new("foo")
+    str.options[:foo]
+    str
+  end
+
+  def user_defined
+    Sass::Script::String.new("I'm a user-defined string!")
+  end
+
+  def _preceding_underscore
+    Sass::Script::String.new("I'm another user-defined string!")
+  end
+end
+
+module Sass::Script::Functions
+  include Sass::Script::Functions::UserFunctions
+end
+
+class SassFunctionTest < Test::Unit::TestCase
+  # Tests taken from:
+  #   http://www.w3.org/Style/CSS/Test/CSS3/Color/20070927/html4/t040204-hsl-h-rotating-b.htm
+  #   http://www.w3.org/Style/CSS/Test/CSS3/Color/20070927/html4/t040204-hsl-values-b.htm
+  File.read(File.dirname(__FILE__) + "/data/hsl-rgb.txt").split("\n\n").each do |chunk|
+    hsls, rgbs = chunk.strip.split("====")
+    hsls.strip.split("\n").zip(rgbs.strip.split("\n")) do |hsl, rgb|
+      hsl_method = "test_hsl: #{hsl} = #{rgb}"
+      unless method_defined?(hsl_method)
+        define_method(hsl_method) do
+          assert_equal(evaluate(rgb), evaluate(hsl))
+        end
+      end
+
+      rgb_to_hsl_method = "test_rgb_to_hsl: #{rgb} = #{hsl}"
+      unless method_defined?(rgb_to_hsl_method)
+        define_method(rgb_to_hsl_method) do
+          rgb_color = perform(rgb)
+          hsl_color = perform(hsl)
+
+          white = hsl_color.lightness == 100
+          black = hsl_color.lightness == 0
+          grayscale = white || black || hsl_color.saturation == 0
+
+          assert_in_delta(hsl_color.hue, rgb_color.hue, 0.0001,
+            "Hues should be equal") unless grayscale
+          assert_in_delta(hsl_color.saturation, rgb_color.saturation, 0.0001,
+            "Saturations should be equal") unless white || black
+          assert_in_delta(hsl_color.lightness, rgb_color.lightness, 0.0001,
+            "Lightnesses should be equal")
+        end
+      end
+    end
+  end
+
+  def test_hsl_kwargs
+    assert_equal "#33cccc", evaluate("hsl($hue: 180, $saturation: 60%, $lightness: 50%)")
+  end
+
+  def test_hsl_checks_bounds
+    assert_error_message("Saturation -114 must be between 0% and 100% for `hsl'", "hsl(10, -114, 12)");
+    assert_error_message("Lightness 256% must be between 0% and 100% for `hsl'", "hsl(10, 10, 256%)");
+  end
+
+  def test_hsl_checks_types
+    assert_error_message("$hue: \"foo\" is not a number for `hsl'", "hsl(\"foo\", 10, 12)");
+    assert_error_message("$saturation: \"foo\" is not a number for `hsl'", "hsl(10, \"foo\", 12)");
+    assert_error_message("$lightness: \"foo\" is not a number for `hsl'", "hsl(10, 10, \"foo\")");
+  end
+
+  def test_hsla
+    assert_equal "rgba(51, 204, 204, 0.4)", evaluate("hsla(180, 60%, 50%, 0.4)")
+    assert_equal "#33cccc", evaluate("hsla(180, 60%, 50%, 1)")
+    assert_equal "rgba(51, 204, 204, 0)", evaluate("hsla(180, 60%, 50%, 0)")
+    assert_equal "rgba(51, 204, 204, 0.4)", evaluate("hsla($hue: 180, $saturation: 60%, $lightness: 50%, 
$alpha: 0.4)")
+  end
+
+  def test_hsla_checks_bounds
+    assert_error_message("Saturation -114 must be between 0% and 100% for `hsla'", "hsla(10, -114, 12, 1)");
+    assert_error_message("Lightness 256% must be between 0% and 100% for `hsla'", "hsla(10, 10, 256%, 0)");
+    assert_error_message("Alpha channel -0.1 must be between 0 and 1 for `hsla'", "hsla(10, 10, 10, -0.1)");
+    assert_error_message("Alpha channel 1.1 must be between 0 and 1 for `hsla'", "hsla(10, 10, 10, 1.1)");
+  end
+
+  def test_hsla_checks_types
+    assert_error_message("$hue: \"foo\" is not a number for `hsla'", "hsla(\"foo\", 10, 12, 0.3)");
+    assert_error_message("$saturation: \"foo\" is not a number for `hsla'", "hsla(10, \"foo\", 12, 0)");
+    assert_error_message("$lightness: \"foo\" is not a number for `hsla'", "hsla(10, 10, \"foo\", 1)");
+    assert_error_message("$alpha: \"foo\" is not a number for `hsla'", "hsla(10, 10, 10, \"foo\")");
+  end
+
+  def test_percentage
+    assert_equal("50%",  evaluate("percentage(.5)"))
+    assert_equal("100%", evaluate("percentage(1)"))
+    assert_equal("25%",  evaluate("percentage(25px / 100px)"))
+    assert_equal("50%",  evaluate("percentage($value: 0.5)"))
+  end
+
+  def test_percentage_checks_types
+    assert_error_message("$value: 25px is not a unitless number for `percentage'", "percentage(25px)")
+    assert_error_message("$value: #cccccc is not a unitless number for `percentage'", "percentage(#ccc)")
+    assert_error_message("$value: \"string\" is not a unitless number for `percentage'", 
%Q{percentage("string")})
+  end
+
+  def test_round
+    assert_equal("5",   evaluate("round(4.8)"))
+    assert_equal("5px", evaluate("round(4.8px)"))
+    assert_equal("5px", evaluate("round(5.49px)"))
+    assert_equal("5px", evaluate("round($value: 5.49px)"))
+
+    assert_error_message("$value: #cccccc is not a number for `round'", "round(#ccc)")
+  end
+
+  def test_floor
+    assert_equal("4",   evaluate("floor(4.8)"))
+    assert_equal("4px", evaluate("floor(4.8px)"))
+    assert_equal("4px", evaluate("floor($value: 4.8px)"))
+
+    assert_error_message("$value: \"foo\" is not a number for `floor'", "floor(\"foo\")")
+  end
+
+  def test_ceil
+    assert_equal("5",   evaluate("ceil(4.1)"))
+    assert_equal("5px", evaluate("ceil(4.8px)"))
+    assert_equal("5px", evaluate("ceil($value: 4.8px)"))
+
+    assert_error_message("$value: \"a\" is not a number for `ceil'", "ceil(\"a\")")
+  end
+
+  def test_abs
+    assert_equal("5",   evaluate("abs(-5)"))
+    assert_equal("5px", evaluate("abs(-5px)"))
+    assert_equal("5",   evaluate("abs(5)"))
+    assert_equal("5px", evaluate("abs(5px)"))
+    assert_equal("5px", evaluate("abs($value: 5px)"))
+
+    assert_error_message("$value: #aaaaaa is not a number for `abs'", "abs(#aaa)")
+  end
+
+  def test_min
+    #assert_equal("1", evaluate("min(1, 2, 3)"))
+    assert_equal("1", evaluate("min(3px, 2px, 1)"))
+    assert_equal("4em", evaluate("min(4em)"))
+    assert_equal("10cm", evaluate("min(10cm, 6in)"))
+
+    assert_error_message("#aaaaaa is not a number for `min'", "min(#aaa)")
+    assert_error_message("Incompatible units: 'px' and 'em'.", "min(3em, 4em, 1px)")
+  end
+
+  def test_max
+    assert_equal("3", evaluate("max(1, 2, 3)"))
+    assert_equal("3", evaluate("max(3, 2px, 1px)"))
+    assert_equal("4em", evaluate("max(4em)"))
+    assert_equal("6in", evaluate("max(10cm, 6in)"))
+
+    assert_error_message("#aaaaaa is not a number for `max'", "max(#aaa)")
+    assert_error_message("Incompatible units: 'px' and 'em'.", "max(3em, 4em, 1px)")
+  end
+
+  def test_rgb
+    assert_equal("#123456", evaluate("rgb(18, 52, 86)"))
+    assert_equal("#beaded", evaluate("rgb(190, 173, 237)"))
+    assert_equal("springgreen", evaluate("rgb(0, 255, 127)"))
+    assert_equal("springgreen", evaluate("rgb($red: 0, $green: 255, $blue: 127)"))
+  end
+
+  def test_rgb_percent
+    assert_equal("#123456", evaluate("rgb(7.1%, 20.4%, 34%)"))
+    assert_equal("#beaded", evaluate("rgb(74.7%, 173, 93%)"))
+    assert_equal("#beaded", evaluate("rgb(190, 68%, 237)"))
+    assert_equal("springgreen", evaluate("rgb(0%, 100%, 50%)"))
+  end
+
+  def test_rgb_tests_bounds
+    assert_error_message("$red: Color value 256 must be between 0 and 255 for `rgb'",
+      "rgb(256, 1, 1)")
+    assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgb'",
+      "rgb(1, 256, 1)")
+    assert_error_message("$blue: Color value 256 must be between 0 and 255 for `rgb'",
+      "rgb(1, 1, 256)")
+    assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgb'",
+      "rgb(1, 256, 257)")
+    assert_error_message("$red: Color value -1 must be between 0 and 255 for `rgb'",
+      "rgb(-1, 1, 1)")
+  end
+
+  def test_rgb_test_percent_bounds
+    assert_error_message("$red: Color value 100.1% must be between 0% and 100% for `rgb'",
+      "rgb(100.1%, 0, 0)")
+    assert_error_message("$green: Color value -0.1% must be between 0% and 100% for `rgb'",
+      "rgb(0, -0.1%, 0)")
+    assert_error_message("$blue: Color value 101% must be between 0% and 100% for `rgb'",
+      "rgb(0, 0, 101%)")
+  end
+
+  def test_rgb_tests_types
+    assert_error_message("$red: \"foo\" is not a number for `rgb'", "rgb(\"foo\", 10, 12)");
+    assert_error_message("$green: \"foo\" is not a number for `rgb'", "rgb(10, \"foo\", 12)");
+    assert_error_message("$blue: \"foo\" is not a number for `rgb'", "rgb(10, 10, \"foo\")");
+  end
+
+  def test_rgba
+    assert_equal("rgba(18, 52, 86, 0.5)", evaluate("rgba(18, 52, 86, 0.5)"))
+    assert_equal("#beaded", evaluate("rgba(190, 173, 237, 1)"))
+    assert_equal("rgba(0, 255, 127, 0)", evaluate("rgba(0, 255, 127, 0)"))
+    assert_equal("rgba(0, 255, 127, 0)", evaluate("rgba($red: 0, $green: 255, $blue: 127, $alpha: 0)"))
+  end
+
+  def test_rgba_tests_bounds
+    assert_error_message("$red: Color value 256 must be between 0 and 255 for `rgba'",
+      "rgba(256, 1, 1, 0.3)")
+    assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgba'",
+      "rgba(1, 256, 1, 0.3)")
+    assert_error_message("$blue: Color value 256 must be between 0 and 255 for `rgba'",
+      "rgba(1, 1, 256, 0.3)")
+    assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgba'",
+      "rgba(1, 256, 257, 0.3)")
+    assert_error_message("$red: Color value -1 must be between 0 and 255 for `rgba'",
+      "rgba(-1, 1, 1, 0.3)")
+    assert_error_message("Alpha channel -0.2 must be between 0 and 1 for `rgba'",
+      "rgba(1, 1, 1, -0.2)")
+    assert_error_message("Alpha channel 1.2 must be between 0 and 1 for `rgba'",
+      "rgba(1, 1, 1, 1.2)")
+  end
+
+  def test_rgba_tests_types
+    assert_error_message("$red: \"foo\" is not a number for `rgba'", "rgba(\"foo\", 10, 12, 0.2)");
+    assert_error_message("$green: \"foo\" is not a number for `rgba'", "rgba(10, \"foo\", 12, 0.1)");
+    assert_error_message("$blue: \"foo\" is not a number for `rgba'", "rgba(10, 10, \"foo\", 0)");
+    assert_error_message("$alpha: \"foo\" is not a number for `rgba'", "rgba(10, 10, 10, \"foo\")");
+  end
+
+  def test_rgba_with_color
+    assert_equal "rgba(16, 32, 48, 0.5)", evaluate("rgba(#102030, 0.5)")
+    assert_equal "rgba(0, 0, 255, 0.5)", evaluate("rgba(blue, 0.5)")
+    assert_equal "rgba(0, 0, 255, 0.5)", evaluate("rgba($color: blue, $alpha: 0.5)")
+  end
+
+  def test_rgba_with_color_tests_types
+    assert_error_message("$color: \"foo\" is not a color for `rgba'", "rgba(\"foo\", 0.2)");
+    assert_error_message("$alpha: \"foo\" is not a number for `rgba'", "rgba(blue, \"foo\")");
+  end
+
+  def test_rgba_tests_num_args
+    assert_error_message("wrong number of arguments (0 for 4) for `rgba'", "rgba()");
+    assert_error_message("wrong number of arguments (1 for 4) for `rgba'", "rgba(blue)");
+    assert_error_message("wrong number of arguments (3 for 4) for `rgba'", "rgba(1, 2, 3)");
+    assert_error_message("wrong number of arguments (5 for 4) for `rgba'", "rgba(1, 2, 3, 0.4, 5)");
+  end
+
+  def test_red
+    assert_equal("18", evaluate("red(#123456)"))
+    assert_equal("18", evaluate("red($color: #123456)"))
+  end
+
+  def test_red_exception
+    assert_error_message("$color: 12 is not a color for `red'", "red(12)")
+  end
+
+  def test_green
+    assert_equal("52", evaluate("green(#123456)"))
+    assert_equal("52", evaluate("green($color: #123456)"))
+  end
+
+  def test_green_exception
+    assert_error_message("$color: 12 is not a color for `green'", "green(12)")
+  end
+
+  def test_blue
+    assert_equal("86", evaluate("blue(#123456)"))
+    assert_equal("86", evaluate("blue($color: #123456)"))
+  end
+
+  def test_blue_exception
+    assert_error_message("$color: 12 is not a color for `blue'", "blue(12)")
+  end
+
+  def test_hue
+    assert_equal("18deg", evaluate("hue(hsl(18, 50%, 20%))"))
+    assert_equal("18deg", evaluate("hue($color: hsl(18, 50%, 20%))"))
+  end
+
+  def test_hue_exception
+    assert_error_message("$color: 12 is not a color for `hue'", "hue(12)")
+  end
+
+  def test_saturation
+    assert_equal("52%", evaluate("saturation(hsl(20, 52%, 20%))"))
+    assert_equal("52%", evaluate("saturation(hsl(20, 52, 20%))"))
+    assert_equal("52%", evaluate("saturation($color: hsl(20, 52, 20%))"))
+  end
+
+  def test_saturation_exception
+    assert_error_message("$color: 12 is not a color for `saturation'", "saturation(12)")
+  end
+
+  def test_lightness
+    assert_equal("86%", evaluate("lightness(hsl(120, 50%, 86%))"))
+    assert_equal("86%", evaluate("lightness(hsl(120, 50%, 86))"))
+    assert_equal("86%", evaluate("lightness($color: hsl(120, 50%, 86))"))
+  end
+
+  def test_lightness_exception
+    assert_error_message("$color: 12 is not a color for `lightness'", "lightness(12)")
+  end
+
+  def test_alpha
+    assert_equal("1", evaluate("alpha(#123456)"))
+    assert_equal("0.34", evaluate("alpha(rgba(0, 1, 2, 0.34))"))
+    assert_equal("0", evaluate("alpha(hsla(0, 1, 2, 0))"))
+    assert_equal("0", evaluate("alpha($color: hsla(0, 1, 2, 0))"))
+  end
+
+  def test_alpha_exception
+    assert_error_message("$color: 12 is not a color for `alpha'", "alpha(12)")
+  end
+
+  def test_opacity
+    assert_equal("1", evaluate("opacity(#123456)"))
+    assert_equal("0.34", evaluate("opacity(rgba(0, 1, 2, 0.34))"))
+    assert_equal("0", evaluate("opacity(hsla(0, 1, 2, 0))"))
+    assert_equal("0", evaluate("opacity($color: hsla(0, 1, 2, 0))"))
+    assert_equal("opacity(20%)", evaluate("opacity(20%)"))
+  end
+
+  def test_opacity_exception
+    assert_error_message("$color: \"foo\" is not a color for `opacity'", "opacity(foo)")
+  end
+
+  def test_opacify
+    assert_equal("rgba(0, 0, 0, 0.75)", evaluate("opacify(rgba(0, 0, 0, 0.5), 0.25)"))
+    assert_equal("rgba(0, 0, 0, 0.3)", evaluate("opacify(rgba(0, 0, 0, 0.2), 0.1)"))
+    assert_equal("rgba(0, 0, 0, 0.7)", evaluate("fade-in(rgba(0, 0, 0, 0.2), 0.5px)"))
+    assert_equal("black", evaluate("fade_in(rgba(0, 0, 0, 0.2), 0.8)"))
+    assert_equal("black", evaluate("opacify(rgba(0, 0, 0, 0.2), 1)"))
+    assert_equal("rgba(0, 0, 0, 0.2)", evaluate("opacify(rgba(0, 0, 0, 0.2), 0%)"))
+    assert_equal("rgba(0, 0, 0, 0.2)", evaluate("opacify($color: rgba(0, 0, 0, 0.2), $amount: 0%)"))
+    assert_equal("rgba(0, 0, 0, 0.2)", evaluate("fade-in($color: rgba(0, 0, 0, 0.2), $amount: 0%)"))
+  end
+
+  def test_opacify_tests_bounds
+    assert_error_message("Amount -0.001 must be between 0 and 1 for `opacify'",
+      "opacify(rgba(0, 0, 0, 0.2), -0.001)")
+    assert_error_message("Amount 1.001 must be between 0 and 1 for `opacify'",
+      "opacify(rgba(0, 0, 0, 0.2), 1.001)")
+  end
+
+  def test_opacify_tests_types
+    assert_error_message("$color: \"foo\" is not a color for `opacify'", "opacify(\"foo\", 10%)")
+    assert_error_message("$amount: \"foo\" is not a number for `opacify'", "opacify(#fff, \"foo\")")
+  end
+
+  def test_transparentize
+    assert_equal("rgba(0, 0, 0, 0.3)", evaluate("transparentize(rgba(0, 0, 0, 0.5), 0.2)"))
+    assert_equal("rgba(0, 0, 0, 0.1)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 0.1)"))
+    assert_equal("rgba(0, 0, 0, 0.2)", evaluate("fade-out(rgba(0, 0, 0, 0.5), 0.3px)"))
+    assert_equal("rgba(0, 0, 0, 0)", evaluate("fade_out(rgba(0, 0, 0, 0.2), 0.2)"))
+    assert_equal("rgba(0, 0, 0, 0)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 1)"))
+    assert_equal("rgba(0, 0, 0, 0.2)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 0)"))
+    assert_equal("rgba(0, 0, 0, 0.2)", evaluate("transparentize($color: rgba(0, 0, 0, 0.2), $amount: 0)"))
+    assert_equal("rgba(0, 0, 0, 0.2)", evaluate("fade-out($color: rgba(0, 0, 0, 0.2), $amount: 0)"))
+  end
+
+  def test_transparentize_tests_bounds
+    assert_error_message("Amount -0.001 must be between 0 and 1 for `transparentize'",
+      "transparentize(rgba(0, 0, 0, 0.2), -0.001)")
+    assert_error_message("Amount 1.001 must be between 0 and 1 for `transparentize'",
+      "transparentize(rgba(0, 0, 0, 0.2), 1.001)")
+  end
+
+  def test_transparentize_tests_types
+    assert_error_message("$color: \"foo\" is not a color for `transparentize'", "transparentize(\"foo\", 
10%)")
+    assert_error_message("$amount: \"foo\" is not a number for `transparentize'", "transparentize(#fff, 
\"foo\")")
+  end
+
+  def test_lighten
+    assert_equal("#4d4d4d", evaluate("lighten(hsl(0, 0, 0), 30%)"))
+    assert_equal("#ee0000", evaluate("lighten(#800, 20%)"))
+    assert_equal("white", evaluate("lighten(#fff, 20%)"))
+    assert_equal("white", evaluate("lighten(#800, 100%)"))
+    assert_equal("#880000", evaluate("lighten(#800, 0%)"))
+    assert_equal("rgba(238, 0, 0, 0.5)", evaluate("lighten(rgba(136, 0, 0, 0.5), 20%)"))
+    assert_equal("rgba(238, 0, 0, 0.5)", evaluate("lighten($color: rgba(136, 0, 0, 0.5), $amount: 20%)"))
+  end
+
+  def test_lighten_tests_bounds
+    assert_error_message("Amount -0.001 must be between 0% and 100% for `lighten'",
+      "lighten(#123, -0.001)")
+    assert_error_message("Amount 100.001 must be between 0% and 100% for `lighten'",
+      "lighten(#123, 100.001)")
+  end
+
+  def test_lighten_tests_types
+    assert_error_message("$color: \"foo\" is not a color for `lighten'", "lighten(\"foo\", 10%)")
+    assert_error_message("$amount: \"foo\" is not a number for `lighten'", "lighten(#fff, \"foo\")")
+  end
+
+  def test_darken
+    assert_equal("#ff6a00", evaluate("darken(hsl(25, 100, 80), 30%)"))
+    assert_equal("#220000", evaluate("darken(#800, 20%)"))
+    assert_equal("black", evaluate("darken(#000, 20%)"))
+    assert_equal("black", evaluate("darken(#800, 100%)"))
+    assert_equal("#880000", evaluate("darken(#800, 0%)"))
+    assert_equal("rgba(34, 0, 0, 0.5)", evaluate("darken(rgba(136, 0, 0, 0.5), 20%)"))
+    assert_equal("rgba(34, 0, 0, 0.5)", evaluate("darken($color: rgba(136, 0, 0, 0.5), $amount: 20%)"))
+  end
+
+  def test_darken_tests_bounds
+    assert_error_message("Amount -0.001 must be between 0% and 100% for `darken'",
+      "darken(#123, -0.001)")
+    assert_error_message("Amount 100.001 must be between 0% and 100% for `darken'",
+      "darken(#123, 100.001)")
+  end
+
+  def test_darken_tests_types
+    assert_error_message("$color: \"foo\" is not a color for `darken'", "darken(\"foo\", 10%)")
+    assert_error_message("$amount: \"foo\" is not a number for `darken'", "darken(#fff, \"foo\")")
+  end
+
+  def test_saturate
+    assert_equal("#d9f2d9", evaluate("saturate(hsl(120, 30, 90), 20%)"))
+    assert_equal("#9e3f3f", evaluate("saturate(#855, 20%)"))
+    assert_equal("black", evaluate("saturate(#000, 20%)"))
+    assert_equal("white", evaluate("saturate(#fff, 20%)"))
+    assert_equal("#33ff33", evaluate("saturate(#8a8, 100%)"))
+    assert_equal("#88aa88", evaluate("saturate(#8a8, 0%)"))
+    assert_equal("rgba(158, 63, 63, 0.5)", evaluate("saturate(rgba(136, 85, 85, 0.5), 20%)"))
+    assert_equal("rgba(158, 63, 63, 0.5)", evaluate("saturate($color: rgba(136, 85, 85, 0.5), $amount: 
20%)"))
+    assert_equal("saturate(50%)", evaluate("saturate(50%)"))
+  end
+
+  def test_saturate_tests_bounds
+    assert_error_message("Amount -0.001 must be between 0% and 100% for `saturate'",
+      "saturate(#123, -0.001)")
+    assert_error_message("Amount 100.001 must be between 0% and 100% for `saturate'",
+      "saturate(#123, 100.001)")
+  end
+
+  def test_saturate_tests_types
+    assert_error_message("$color: \"foo\" is not a color for `saturate'", "saturate(\"foo\", 10%)")
+    assert_error_message("$amount: \"foo\" is not a number for `saturate'", "saturate(#fff, \"foo\")")
+  end
+
+  def test_desaturate
+    assert_equal("#e3e8e3", evaluate("desaturate(hsl(120, 30, 90), 20%)"))
+    assert_equal("#726b6b", evaluate("desaturate(#855, 20%)"))
+    assert_equal("black", evaluate("desaturate(#000, 20%)"))
+    assert_equal("white", evaluate("desaturate(#fff, 20%)"))
+    assert_equal("#999999", evaluate("desaturate(#8a8, 100%)"))
+    assert_equal("#88aa88", evaluate("desaturate(#8a8, 0%)"))
+    assert_equal("rgba(114, 107, 107, 0.5)", evaluate("desaturate(rgba(136, 85, 85, 0.5), 20%)"))
+    assert_equal("rgba(114, 107, 107, 0.5)", evaluate("desaturate($color: rgba(136, 85, 85, 0.5), $amount: 
20%)"))
+  end
+
+  def test_desaturate_tests_bounds
+    assert_error_message("Amount -0.001 must be between 0% and 100% for `desaturate'",
+      "desaturate(#123, -0.001)")
+    assert_error_message("Amount 100.001 must be between 0% and 100% for `desaturate'",
+      "desaturate(#123, 100.001)")
+  end
+
+  def test_desaturate_tests_types
+    assert_error_message("$color: \"foo\" is not a color for `desaturate'", "desaturate(\"foo\", 10%)")
+    assert_error_message("$amount: \"foo\" is not a number for `desaturate'", "desaturate(#fff, \"foo\")")
+  end
+
+  def test_adjust_hue
+    assert_equal("#deeded", evaluate("adjust-hue(hsl(120, 30, 90), 60deg)"))
+    assert_equal("#ededde", evaluate("adjust-hue(hsl(120, 30, 90), -60deg)"))
+    assert_equal("#886a11", evaluate("adjust-hue(#811, 45deg)"))
+    assert_equal("black", evaluate("adjust-hue(#000, 45deg)"))
+    assert_equal("white", evaluate("adjust-hue(#fff, 45deg)"))
+    assert_equal("#88aa88", evaluate("adjust-hue(#8a8, 360deg)"))
+    assert_equal("#88aa88", evaluate("adjust-hue(#8a8, 0deg)"))
+    assert_equal("rgba(136, 106, 17, 0.5)", evaluate("adjust-hue(rgba(136, 17, 17, 0.5), 45deg)"))
+    assert_equal("rgba(136, 106, 17, 0.5)", evaluate("adjust-hue($color: rgba(136, 17, 17, 0.5), $degrees: 
45deg)"))
+  end
+
+  def test_adjust_hue_tests_types
+    assert_error_message("$color: \"foo\" is not a color for `adjust-hue'", "adjust-hue(\"foo\", 10%)")
+    assert_error_message("$degrees: \"foo\" is not a number for `adjust-hue'", "adjust-hue(#fff, \"foo\")")
+  end
+
+  def test_adjust_color
+    # HSL
+    assert_equal(evaluate("hsl(180, 30, 90)"),
+      evaluate("adjust-color(hsl(120, 30, 90), $hue: 60deg)"))
+    assert_equal(evaluate("hsl(120, 50, 90)"),
+      evaluate("adjust-color(hsl(120, 30, 90), $saturation: 20%)"))
+    assert_equal(evaluate("hsl(120, 30, 60)"),
+      evaluate("adjust-color(hsl(120, 30, 90), $lightness: -30%)"))
+    # RGB
+    assert_equal(evaluate("rgb(15, 20, 30)"),
+      evaluate("adjust-color(rgb(10, 20, 30), $red: 5)"))
+    assert_equal(evaluate("rgb(10, 15, 30)"),
+      evaluate("adjust-color(rgb(10, 20, 30), $green: -5)"))
+    assert_equal(evaluate("rgb(10, 20, 40)"),
+      evaluate("adjust-color(rgb(10, 20, 30), $blue: 10)"))
+    # Alpha
+    assert_equal(evaluate("hsla(120, 30, 90, 0.65)"),
+      evaluate("adjust-color(hsl(120, 30, 90), $alpha: -0.35)"))
+    assert_equal(evaluate("rgba(10, 20, 30, 0.9)"),
+      evaluate("adjust-color(rgba(10, 20, 30, 0.4), $alpha: 0.5)"))
+
+    # HSL composability
+    assert_equal(evaluate("hsl(180, 20, 90)"),
+      evaluate("adjust-color(hsl(120, 30, 90), $hue: 60deg, $saturation: -10%)"))
+    assert_equal(evaluate("hsl(180, 20, 95)"),
+      evaluate("adjust-color(hsl(120, 30, 90), $hue: 60deg, $saturation: -10%, $lightness: 5%)"))
+    assert_equal(evaluate("hsla(120, 20, 95, 0.3)"),
+      evaluate("adjust-color(hsl(120, 30, 90), $saturation: -10%, $lightness: 5%, $alpha: -0.7)"))
+
+    # RGB composability
+    assert_equal(evaluate("rgb(15, 20, 29)"),
+      evaluate("adjust-color(rgb(10, 20, 30), $red: 5, $blue: -1)"))
+    assert_equal(evaluate("rgb(15, 45, 29)"),
+      evaluate("adjust-color(rgb(10, 20, 30), $red: 5, $green: 25, $blue: -1)"))
+    assert_equal(evaluate("rgba(10, 25, 29, 0.7)"),
+      evaluate("adjust-color(rgb(10, 20, 30), $green: 5, $blue: -1, $alpha: -0.3)"))
+
+    # HSL range restriction
+    assert_equal(evaluate("hsl(120, 30, 90)"),
+      evaluate("adjust-color(hsl(120, 30, 90), $hue: 720deg)"))
+    assert_equal(evaluate("hsl(120, 0, 90)"),
+      evaluate("adjust-color(hsl(120, 30, 90), $saturation: -90%)"))
+    assert_equal(evaluate("hsl(120, 30, 100)"),
+      evaluate("adjust-color(hsl(120, 30, 90), $lightness: 30%)"))
+
+    # RGB range restriction
+    assert_equal(evaluate("rgb(255, 20, 30)"),
+      evaluate("adjust-color(rgb(10, 20, 30), $red: 250)"))
+    assert_equal(evaluate("rgb(10, 0, 30)"),
+      evaluate("adjust-color(rgb(10, 20, 30), $green: -30)"))
+    assert_equal(evaluate("rgb(10, 20, 0)"),
+      evaluate("adjust-color(rgb(10, 20, 30), $blue: -40)"))
+  end
+
+  def test_adjust_color_tests_types
+    assert_error_message("$color: \"foo\" is not a color for `adjust-color'", "adjust-color(foo, $hue: 10)")
+    # HSL
+    assert_error_message("$hue: \"foo\" is not a number for `adjust-color'",
+      "adjust-color(blue, $hue: foo)")
+    assert_error_message("$saturation: \"foo\" is not a number for `adjust-color'",
+      "adjust-color(blue, $saturation: foo)")
+    assert_error_message("$lightness: \"foo\" is not a number for `adjust-color'",
+      "adjust-color(blue, $lightness: foo)")
+    # RGB
+    assert_error_message("$red: \"foo\" is not a number for `adjust-color'",
+      "adjust-color(blue, $red: foo)")
+    assert_error_message("$green: \"foo\" is not a number for `adjust-color'",
+      "adjust-color(blue, $green: foo)")
+    assert_error_message("$blue: \"foo\" is not a number for `adjust-color'",
+      "adjust-color(blue, $blue: foo)")
+    # Alpha
+    assert_error_message("$alpha: \"foo\" is not a number for `adjust-color'",
+      "adjust-color(blue, $alpha: foo)")
+  end
+
+  def test_adjust_color_tests_arg_range
+    # HSL
+    assert_error_message("$saturation: Amount 101% must be between -100% and 100% for `adjust-color'",
+      "adjust-color(blue, $saturation: 101%)")
+    assert_error_message("$saturation: Amount -101% must be between -100% and 100% for `adjust-color'",
+      "adjust-color(blue, $saturation: -101%)")
+    assert_error_message("$lightness: Amount 101% must be between -100% and 100% for `adjust-color'",
+      "adjust-color(blue, $lightness: 101%)")
+    assert_error_message("$lightness: Amount -101% must be between -100% and 100% for `adjust-color'",
+      "adjust-color(blue, $lightness: -101%)")
+    # RGB
+    assert_error_message("$red: Amount 256 must be between -255 and 255 for `adjust-color'",
+      "adjust-color(blue, $red: 256)")
+    assert_error_message("$red: Amount -256 must be between -255 and 255 for `adjust-color'",
+      "adjust-color(blue, $red: -256)")
+    assert_error_message("$green: Amount 256 must be between -255 and 255 for `adjust-color'",
+      "adjust-color(blue, $green: 256)")
+    assert_error_message("$green: Amount -256 must be between -255 and 255 for `adjust-color'",
+      "adjust-color(blue, $green: -256)")
+    assert_error_message("$blue: Amount 256 must be between -255 and 255 for `adjust-color'",
+      "adjust-color(blue, $blue: 256)")
+    assert_error_message("$blue: Amount -256 must be between -255 and 255 for `adjust-color'",
+      "adjust-color(blue, $blue: -256)")
+    # Alpha
+    assert_error_message("$alpha: Amount 1.1 must be between -1 and 1 for `adjust-color'",
+      "adjust-color(blue, $alpha: 1.1)")
+    assert_error_message("$alpha: Amount -1.1 must be between -1 and 1 for `adjust-color'",
+      "adjust-color(blue, $alpha: -1.1)")
+  end
+
+  def test_adjust_color_argument_errors
+    assert_error_message("Unknown argument $hoo (260deg) for `adjust-color'",
+      "adjust-color(blue, $hoo: 260deg)")
+    assert_error_message("Cannot specify HSL and RGB values for a color at the same time for `adjust-color'",
+      "adjust-color(blue, $hue: 120deg, $red: 10)");
+    assert_error_message("10px is not a keyword argument for `adjust_color'",
+      "adjust-color(blue, 10px)")
+    assert_error_message("10px is not a keyword argument for `adjust_color'",
+      "adjust-color(blue, 10px, 20px)")
+    assert_error_message("10px is not a keyword argument for `adjust_color'",
+      "adjust-color(blue, 10px, $hue: 180deg)")
+  end
+
+  def test_scale_color
+    # HSL
+    assert_equal(evaluate("hsl(120, 51, 90)"),
+      evaluate("scale-color(hsl(120, 30, 90), $saturation: 30%)"))
+    assert_equal(evaluate("hsl(120, 30, 76.5)"),
+      evaluate("scale-color(hsl(120, 30, 90), $lightness: -15%)"))
+    # RGB
+    assert_equal(evaluate("rgb(157, 20, 30)"),
+      evaluate("scale-color(rgb(10, 20, 30), $red: 60%)"))
+    assert_equal(evaluate("rgb(10, 38.8, 30)"),
+      evaluate("scale-color(rgb(10, 20, 30), $green: 8%)"))
+    assert_equal(evaluate("rgb(10, 20, 20)"),
+      evaluate("scale-color(rgb(10, 20, 30), $blue: -(1/3)*100%)"))
+    # Alpha
+    assert_equal(evaluate("hsla(120, 30, 90, 0.86)"),
+      evaluate("scale-color(hsl(120, 30, 90), $alpha: -14%)"))
+    assert_equal(evaluate("rgba(10, 20, 30, 0.82)"),
+      evaluate("scale-color(rgba(10, 20, 30, 0.8), $alpha: 10%)"))
+
+    # HSL composability
+    assert_equal(evaluate("hsl(120, 51, 76.5)"),
+      evaluate("scale-color(hsl(120, 30, 90), $saturation: 30%, $lightness: -15%)"))
+    assert_equal(evaluate("hsla(120, 51, 90, 0.2)"),
+      evaluate("scale-color(hsl(120, 30, 90), $saturation: 30%, $alpha: -80%)"))
+
+    # RGB composability
+    assert_equal(evaluate("rgb(157, 38.8, 30)"),
+      evaluate("scale-color(rgb(10, 20, 30), $red: 60%, $green: 8%)"))
+    assert_equal(evaluate("rgb(157, 38.8, 20)"),
+      evaluate("scale-color(rgb(10, 20, 30), $red: 60%, $green: 8%, $blue: -(1/3)*100%)"))
+    assert_equal(evaluate("rgba(10, 38.8, 20, 0.55)"),
+      evaluate("scale-color(rgba(10, 20, 30, 0.5), $green: 8%, $blue: -(1/3)*100%, $alpha: 10%)"))
+
+    # Extremes
+    assert_equal(evaluate("hsl(120, 100, 90)"),
+      evaluate("scale-color(hsl(120, 30, 90), $saturation: 100%)"))
+    assert_equal(evaluate("hsl(120, 30, 90)"),
+      evaluate("scale-color(hsl(120, 30, 90), $saturation: 0%)"))
+    assert_equal(evaluate("hsl(120, 0, 90)"),
+      evaluate("scale-color(hsl(120, 30, 90), $saturation: -100%)"))
+  end
+
+  def test_scale_color_tests_types
+    assert_error_message("$color: \"foo\" is not a color for `scale-color'", "scale-color(foo, $red: 10%)")
+    # HSL
+    assert_error_message("$saturation: \"foo\" is not a number for `scale-color'",
+      "scale-color(blue, $saturation: foo)")
+    assert_error_message("$lightness: \"foo\" is not a number for `scale-color'",
+      "scale-color(blue, $lightness: foo)")
+    # RGB
+    assert_error_message("$red: \"foo\" is not a number for `scale-color'",
+      "scale-color(blue, $red: foo)")
+    assert_error_message("$green: \"foo\" is not a number for `scale-color'",
+      "scale-color(blue, $green: foo)")
+    assert_error_message("$blue: \"foo\" is not a number for `scale-color'",
+      "scale-color(blue, $blue: foo)")
+    # Alpha
+    assert_error_message("$alpha: \"foo\" is not a number for `scale-color'",
+      "scale-color(blue, $alpha: foo)")
+  end
+
+  def test_scale_color_argument_errors
+    # Range
+    assert_error_message("$saturation: Amount 101% must be between -100% and 100% for `scale-color'",
+      "scale-color(blue, $saturation: 101%)")
+    assert_error_message("$red: Amount -101% must be between -100% and 100% for `scale-color'",
+      "scale-color(blue, $red: -101%)")
+    assert_error_message("$alpha: Amount -101% must be between -100% and 100% for `scale-color'",
+      "scale-color(blue, $alpha: -101%)")
+
+    # Unit
+    assert_error_message("$saturation: Amount 80 must be a % (e.g. 80%) for `scale-color'",
+      "scale-color(blue, $saturation: 80)")
+    assert_error_message("$alpha: Amount 0.5 must be a % (e.g. 0.5%) for `scale-color'",
+      "scale-color(blue, $alpha: 0.5)")
+
+    # Unknown argument
+    assert_error_message("Unknown argument $hue (80%) for `scale-color'", "scale-color(blue, $hue: 80%)")
+
+    # Non-keyword arg
+    assert_error_message("10px is not a keyword argument for `scale_color'", "scale-color(blue, 10px)")
+
+    # HSL/RGB
+    assert_error_message("Cannot specify HSL and RGB values for a color at the same time for `scale-color'",
+      "scale-color(blue, $lightness: 10%, $red: 20%)");
+  end
+
+  def test_change_color
+    # HSL
+    assert_equal(evaluate("hsl(195, 30, 90)"),
+      evaluate("change-color(hsl(120, 30, 90), $hue: 195deg)"))
+    assert_equal(evaluate("hsl(120, 50, 90)"),
+      evaluate("change-color(hsl(120, 30, 90), $saturation: 50%)"))
+    assert_equal(evaluate("hsl(120, 30, 40)"),
+      evaluate("change-color(hsl(120, 30, 90), $lightness: 40%)"))
+    # RGB
+    assert_equal(evaluate("rgb(123, 20, 30)"),
+      evaluate("change-color(rgb(10, 20, 30), $red: 123)"))
+    assert_equal(evaluate("rgb(10, 234, 30)"),
+      evaluate("change-color(rgb(10, 20, 30), $green: 234)"))
+    assert_equal(evaluate("rgb(10, 20, 198)"),
+      evaluate("change-color(rgb(10, 20, 30), $blue: 198)"))
+    # Alpha
+    assert_equal(evaluate("rgba(10, 20, 30, 0.76)"),
+      evaluate("change-color(rgb(10, 20, 30), $alpha: 0.76)"))
+
+    # HSL composability
+    assert_equal(evaluate("hsl(56, 30, 47)"),
+      evaluate("change-color(hsl(120, 30, 90), $hue: 56deg, $lightness: 47%)"))
+    assert_equal(evaluate("hsla(56, 30, 47, 0.9)"),
+      evaluate("change-color(hsl(120, 30, 90), $hue: 56deg, $lightness: 47%, $alpha: 0.9)"))
+  end
+
+  def test_change_color_tests_types
+    assert_error_message("$color: \"foo\" is not a color for `change-color'", "change-color(foo, $red: 10%)")
+    # HSL
+    assert_error_message("$saturation: \"foo\" is not a number for `change-color'",
+      "change-color(blue, $saturation: foo)")
+    assert_error_message("$lightness: \"foo\" is not a number for `change-color'",
+      "change-color(blue, $lightness: foo)")
+    # RGB
+    assert_error_message("$red: \"foo\" is not a number for `change-color'", "change-color(blue, $red: foo)")
+    assert_error_message("$green: \"foo\" is not a number for `change-color'", "change-color(blue, $green: 
foo)")
+    assert_error_message("$blue: \"foo\" is not a number for `change-color'", "change-color(blue, $blue: 
foo)")
+    # Alpha
+    assert_error_message("$alpha: \"foo\" is not a number for `change-color'", "change-color(blue, $alpha: 
foo)")
+  end
+
+  def test_change_color_argument_errors
+    # Range
+    assert_error_message("Saturation 101% must be between 0% and 100% for `change-color'",
+      "change-color(blue, $saturation: 101%)")
+    assert_error_message("Lightness 101% must be between 0% and 100% for `change-color'",
+      "change-color(blue, $lightness: 101%)")
+    assert_error_message("Red value -1 must be between 0 and 255 for `change-color'",
+      "change-color(blue, $red: -1)")
+    assert_error_message("Green value 256 must be between 0 and 255 for `change-color'",
+      "change-color(blue, $green: 256)")
+    assert_error_message("Blue value 500 must be between 0 and 255 for `change-color'",
+      "change-color(blue, $blue: 500)")
+
+    # Unknown argument
+    assert_error_message("Unknown argument $hoo (80%) for `change-color'", "change-color(blue, $hoo: 80%)")
+
+    # Non-keyword arg
+    assert_error_message("10px is not a keyword argument for `change_color'", "change-color(blue, 10px)")
+
+    # HSL/RGB
+    assert_error_message("Cannot specify HSL and RGB values for a color at the same time for `change-color'",
+      "change-color(blue, $lightness: 10%, $red: 120)");
+  end
+
+  def test_ie_hex_str
+    assert_equal("#FFAA11CC", evaluate('ie-hex-str(#aa11cc)'))
+    assert_equal("#FFAA11CC", evaluate('ie-hex-str(#a1c)'))
+    assert_equal("#FFAA11CC", evaluate('ie-hex-str(#A1c)'))
+    assert_equal("#80FF0000", evaluate('ie-hex-str(rgba(255, 0, 0, 0.5))'))
+  end
+
+  def test_mix
+    assert_equal("#7f007f", evaluate("mix(#f00, #00f)"))
+    assert_equal("#7f7f7f", evaluate("mix(#f00, #0ff)"))
+    assert_equal("#7f9055", evaluate("mix(#f70, #0aa)"))
+    assert_equal("#3f00bf", evaluate("mix(#f00, #00f, 25%)"))
+    assert_equal("rgba(63, 0, 191, 0.75)", evaluate("mix(rgba(255, 0, 0, 0.5), #00f)"))
+    assert_equal("red", evaluate("mix(#f00, #00f, 100%)"))
+    assert_equal("blue", evaluate("mix(#f00, #00f, 0%)"))
+    assert_equal("rgba(255, 0, 0, 0.5)", evaluate("mix(#f00, transparentize(#00f, 1))"))
+    assert_equal("rgba(0, 0, 255, 0.5)", evaluate("mix(transparentize(#f00, 1), #00f)"))
+    assert_equal("red", evaluate("mix(#f00, transparentize(#00f, 1), 100%)"))
+    assert_equal("blue", evaluate("mix(transparentize(#f00, 1), #00f, 0%)"))
+    assert_equal("rgba(0, 0, 255, 0)", evaluate("mix(#f00, transparentize(#00f, 1), 0%)"))
+    assert_equal("rgba(255, 0, 0, 0)", evaluate("mix(transparentize(#f00, 1), #00f, 100%)"))
+    assert_equal("rgba(255, 0, 0, 0)", evaluate("mix($color-1: transparentize(#f00, 1), $color-2: #00f, 
$weight: 100%)"))
+  end
+
+  def test_mix_tests_types
+    assert_error_message("$color-1: \"foo\" is not a color for `mix'", "mix(\"foo\", #f00, 10%)")
+    assert_error_message("$color-2: \"foo\" is not a color for `mix'", "mix(#f00, \"foo\", 10%)")
+    assert_error_message("$weight: \"foo\" is not a number for `mix'", "mix(#f00, #baf, \"foo\")")
+  end
+
+  def test_mix_tests_bounds
+    assert_error_message("Weight -0.001 must be between 0% and 100% for `mix'",
+      "mix(#123, #456, -0.001)")
+    assert_error_message("Weight 100.001 must be between 0% and 100% for `mix'",
+      "mix(#123, #456, 100.001)")
+  end
+
+  def test_grayscale
+    assert_equal("#bbbbbb", evaluate("grayscale(#abc)"))
+    assert_equal("gray", evaluate("grayscale(#f00)"))
+    assert_equal("gray", evaluate("grayscale(#00f)"))
+    assert_equal("white", evaluate("grayscale(white)"))
+    assert_equal("black", evaluate("grayscale(black)"))
+    assert_equal("black", evaluate("grayscale($color: black)"))
+
+    assert_equal("grayscale(2)", evaluate("grayscale(2)"))
+    assert_equal("grayscale(-5px)", evaluate("grayscale(-5px)"))
+  end
+
+  def tets_grayscale_tests_types
+    assert_error_message("$color: \"foo\" is not a color for `grayscale'", "grayscale(\"foo\")")
+  end
+
+  def test_complement
+    assert_equal("#ccbbaa", evaluate("complement(#abc)"))
+    assert_equal("cyan", evaluate("complement(red)"))
+    assert_equal("red", evaluate("complement(cyan)"))
+    assert_equal("white", evaluate("complement(white)"))
+    assert_equal("black", evaluate("complement(black)"))
+    assert_equal("black", evaluate("complement($color: black)"))
+  end
+
+  def tets_complement_tests_types
+    assert_error_message("$color: \"foo\" is not a color for `complement'", "complement(\"foo\")")
+  end
+
+  def test_invert
+    assert_equal("#112233", evaluate("invert(#edc)"))
+    assert_equal("rgba(245, 235, 225, 0.5)", evaluate("invert(rgba(10, 20, 30, 0.5))"))
+    assert_equal("invert(20%)", evaluate("invert(20%)"))
+  end
+
+  def test_invert_tests_types
+    assert_error_message("$color: \"foo\" is not a color for `invert'", "invert(\"foo\")")
+  end
+
+  def test_unquote
+    assert_equal('foo', evaluate('unquote("foo")'))
+    assert_equal('foo', evaluate('unquote(foo)'))
+    assert_equal('foo', evaluate('unquote($string: foo)'))
+  end
+
+  def test_quote
+    assert_equal('"foo"', evaluate('quote(foo)'))
+    assert_equal('"foo"', evaluate('quote("foo")'))
+    assert_equal('"foo"', evaluate('quote($string: "foo")'))
+  end
+
+  def test_quote_tests_type
+    assert_error_message("$string: #ff0000 is not a string for `quote'", "quote(#f00)")
+  end
+
+  def test_user_defined_function
+    assert_equal("I'm a user-defined string!", evaluate("user_defined()"))
+  end
+
+  def test_user_defined_function_with_preceding_underscore
+    assert_equal("I'm another user-defined string!", evaluate("_preceding_underscore()"))
+    assert_equal("I'm another user-defined string!", evaluate("-preceding-underscore()"))
+  end
+
+  def test_options_on_new_literals_fails
+    assert_error_message(<<MSG, "call-options-on-new-literal()")
+The #options attribute is not set on this Sass::Script::String.
+  This error is probably occurring because #to_s was called
+  on this literal within a custom Sass function without first
+  setting the #option attribute.
+MSG
+  end
+
+  def test_type_of
+    assert_equal("string", evaluate("type-of(\"asdf\")"))
+    assert_equal("string", evaluate("type-of(asdf)"))
+    assert_equal("number", evaluate("type-of(1px)"))
+    assert_equal("bool", evaluate("type-of(true)"))
+    assert_equal("color", evaluate("type-of(#fff)"))
+    assert_equal("color", evaluate("type-of($value: #fff)"))
+    assert_equal("null", evaluate("type-of(null)"))
+  end
+
+  def test_unit
+    assert_equal(%Q{""}, evaluate("unit(100)"))
+    assert_equal(%Q{"px"}, evaluate("unit(100px)"))
+    assert_equal(%Q{"em*px"}, evaluate("unit(10px * 5em)"))
+    assert_equal(%Q{"em*px"}, evaluate("unit(5em * 10px)"))
+    assert_equal(%Q{"em/rem"}, evaluate("unit(10px * 5em / 30cm / 1rem)"))
+    assert_equal(%Q{"em*vh/cm*rem"}, evaluate("unit(10vh * 5em / 30cm / 1rem)"))
+    assert_equal(%Q{"px"}, evaluate("unit($number: 100px)"))
+    assert_error_message("$number: #ff0000 is not a number for `unit'", "unit(#f00)")
+  end
+
+  def test_unitless
+    assert_equal(%Q{true}, evaluate("unitless(100)"))
+    assert_equal(%Q{false}, evaluate("unitless(100px)"))
+    assert_equal(%Q{false}, evaluate("unitless($number: 100px)"))
+    assert_error_message("$number: #ff0000 is not a number for `unitless'", "unitless(#f00)")
+  end
+
+  def test_comparable
+    assert_equal(%Q{true}, evaluate("comparable(2px, 1px)"))
+    assert_equal(%Q{true}, evaluate("comparable(10cm, 3mm)"))
+    assert_equal(%Q{false}, evaluate("comparable(100px, 3em)"))
+    assert_equal(%Q{false}, evaluate("comparable($number-1: 100px, $number-2: 3em)"))
+    assert_error_message("$number-1: #ff0000 is not a number for `comparable'", "comparable(#f00, 1px)")
+    assert_error_message("$number-2: #ff0000 is not a number for `comparable'", "comparable(1px, #f00)")
+  end
+
+  def test_length
+    assert_equal("5", evaluate("length(1 2 3 4 5)"))
+    assert_equal("4", evaluate("length((foo, bar, baz, bip))"))
+    assert_equal("3", evaluate("length((foo, bar, baz bip))"))
+    assert_equal("3", evaluate("length((foo, bar, (baz, bip)))"))
+    assert_equal("1", evaluate("length(#f00)"))
+    assert_equal("0", evaluate("length(())"))
+    assert_equal("4", evaluate("length(1 2 () 3)"))
+  end
+
+  def test_nth
+    assert_equal("1", evaluate("nth(1 2 3, 1)"))
+    assert_equal("2", evaluate("nth(1 2 3, 2)"))
+    assert_equal("3", evaluate("nth((1, 2, 3), 3)"))
+    assert_equal("foo", evaluate("nth(foo, 1)"))
+    assert_equal("bar baz", evaluate("nth(foo (bar baz) bang, 2)"))
+    assert_error_message("List index 0 must be greater than or equal to 1 for `nth'", "nth(foo, 0)")
+    assert_error_message("List index -10 must be greater than or equal to 1 for `nth'", "nth(foo, -10)")
+    assert_error_message("List index 1.5 must be an integer for `nth'", "nth(foo, 1.5)")
+    assert_error_message("List index is 5 but list is only 4 items long for `nth'", "nth(1 2 3 4, 5)")
+    assert_error_message("List index is 2 but list is only 1 item long for `nth'", "nth(foo, 2)")
+    assert_error_message("List index is 1 but list has no items for `nth'", "nth((), 1)")
+    assert_error_message("$n: \"foo\" is not a number for `nth'", "nth(1 2 3, foo)")
+  end
+
+  def test_join
+    assert_equal("1 2 3", evaluate("join(1 2, 3)"))
+    assert_equal("1 2 3", evaluate("join(1, 2 3)"))
+    assert_equal("1 2 3 4", evaluate("join(1 2, 3 4)"))
+    assert_equal("true", evaluate("(1 2 3 4) == join(1 2, 3 4)"))
+    assert_equal("false", evaluate("(1 2 (3 4)) == join(1 2, 3 4)"))
+    assert_equal("1, 2, 3", evaluate("join((1, 2), 3)"))
+    assert_equal("1, 2, 3", evaluate("join(1, (2, 3))"))
+    assert_equal("1, 2, 3, 4", evaluate("join((1, 2), (3, 4))"))
+    assert_equal("true", evaluate("(1, 2, 3, 4) == join((1, 2), (3, 4))"))
+    assert_equal("false", evaluate("(1, 2, (3, 4)) == join((1, 2), (3, 4))"))
+
+    assert_equal("1 2", evaluate("join(1, 2)"))
+    assert_equal("1 2 3 4", evaluate("join(1 2, (3, 4))"))
+    assert_equal("1, 2, 3, 4", evaluate("join((1, 2), 3 4)"))
+
+    assert_equal("1 2", evaluate("join(1, 2, auto)"))
+    assert_equal("1, 2, 3, 4", evaluate("join(1 2, 3 4, comma)"))
+    assert_equal("1 2 3 4", evaluate("join((1, 2), (3, 4), space)"))
+    assert_equal("1, 2", evaluate("join(1, 2, comma)"))
+
+    assert_equal("1 2", evaluate("join(1 2, ())"))
+    assert_equal("1, 2", evaluate("join((1, 2), ())"))
+    assert_equal("true", evaluate("(1 2) == join(1 2, ())"))
+    assert_equal("true", evaluate("(1, 2) == join((1, 2), ())"))
+    assert_equal("false", evaluate("(1 2 ()) == join(1 2, ())"))
+    assert_equal("false", evaluate("(1, 2, ()) == join((1, 2), ())"))
+
+    assert_equal("1 2", evaluate("join((), 1 2)"))
+    assert_equal("1, 2", evaluate("join((), (1, 2))"))
+    assert_equal("true", evaluate("(1 2) == join((), 1 2)"))
+    assert_equal("true", evaluate("(1, 2) == join((), (1, 2))"))
+    assert_equal("false", evaluate("(1 2 ()) == join((), 1 2)"))
+    assert_equal("false", evaluate("(1, 2, ()) == join((), (1, 2))"))
+
+    assert_error_message("Separator name must be space, comma, or auto for `join'", "join(1, 2, baboon)")
+    assert_error_message("$separator: 12 is not a string for `join'", "join(1, 2, 12)")
+  end
+
+  def test_append
+    assert_equal("1 2 3", evaluate("append(1 2, 3)"))
+    assert_equal("1 2 3 4", evaluate("append(1 2, 3 4)"))
+    assert_equal("false", evaluate("(1 2 3 4) == append(1 2, 3 4)"))
+    assert_equal("true", evaluate("(1 2 (3 4)) == append(1 2, 3 4)"))
+    assert_equal("1, 2, 3", evaluate("append((1, 2), 3)"))
+    assert_equal("1, 2, 3, 4", evaluate("append((1, 2), (3, 4))"))
+    assert_equal("false", evaluate("(1, 2, 3, 4) == append((1, 2), (3, 4))"))
+    assert_equal("true", evaluate("(1, 2, (3, 4)) == append((1, 2), (3, 4))"))
+
+    assert_equal("1 2", evaluate("append(1, 2)"))
+    assert_equal("1 2 3, 4", evaluate("append(1 2, (3, 4))"))
+    assert_equal("true", evaluate("(1 2 (3, 4)) == append(1 2, (3, 4))"))
+    assert_equal("1, 2, 3 4", evaluate("append((1, 2), 3 4)"))
+    assert_equal("true", evaluate("(1, 2, 3 4) == append((1, 2), 3 4)"))
+
+    assert_equal("1 2", evaluate("append(1, 2, auto)"))
+    assert_equal("1, 2, 3 4", evaluate("append(1 2, 3 4, comma)"))
+    assert_equal("1 2 3, 4", evaluate("append((1, 2), (3, 4), space)"))
+    assert_equal("1, 2", evaluate("append(1, 2, comma)"))
+
+    assert_equal("1 2", evaluate("append(1 2, ())"))
+    assert_equal("1, 2", evaluate("append((1, 2), ())"))
+    assert_equal("true", evaluate("(1 2 ()) == append(1 2, ())"))
+    assert_equal("true", evaluate("(1, 2, ()) == append((1, 2), ())"))
+
+    assert_equal("1 2", evaluate("append((), 1 2)"))
+    assert_equal("1, 2", evaluate("append((), (1, 2))"))
+    assert_equal("false", evaluate("(1 2) == append((), 1 2)"))
+    assert_equal("true", evaluate("(1 2) == nth(append((), 1 2), 1)"))
+
+    assert_error_message("Separator name must be space, comma, or auto for `append'", "append(1, 2, baboon)")
+    assert_error_message("$separator: 12 is not a string for `append'", "append(1, 2, 12)")
+  end
+
+  def test_zip
+    assert_equal("1 3 5, 2 4 6", evaluate("zip(1 2, 3 4, 5 6)"))
+    assert_equal("1 4 7, 2 5 8", evaluate("zip(1 2 3, 4 5 6, 7 8)"))
+    assert_equal("1 2 3", evaluate("zip(1, 2, 3)"))
+  end
+
+  def test_index
+    assert_equal("1", evaluate("index(1px solid blue, 1px)"))
+    assert_equal("2", evaluate("index(1px solid blue, solid)"))
+    assert_equal("3", evaluate("index(1px solid blue, #00f)"))
+    assert_equal("1", evaluate("index(1px, 1px)"))
+    assert_equal("false", evaluate("index(1px solid blue, 1em)"))
+    assert_equal("false", evaluate("index(1px solid blue, notfound)"))
+    assert_equal("false", evaluate("index(1px, #00f)"))
+  end
+
+  def test_if
+    assert_equal("1px", evaluate("if(true, 1px, 2px)"))
+    assert_equal("2px", evaluate("if(false, 1px, 2px)"))
+    assert_equal("2px", evaluate("if(null, 1px, 2px)"))
+  end
+
+  def test_counter
+    assert_equal("counter(foo)", evaluate("counter(foo)"))
+    assert_equal('counter(item,".")', evaluate('counter(item, ".")'))
+    assert_equal('counter(item,".")', evaluate('counter(item,".")'))
+  end
+
+  def test_counters
+    assert_equal("counters(foo)", evaluate("counters(foo)"))
+    assert_equal('counters(item,".")', evaluate('counters(item, ".")'))
+    assert_equal('counters(item,".")', evaluate('counters(item,".")'))
+  end
+
+  def test_keyword_args_rgb
+    assert_equal(%Q{white}, evaluate("rgb($red: 255, $green: 255, $blue: 255)"))
+  end
+
+  def test_keyword_args_rgba
+    assert_equal(%Q{rgba(255, 255, 255, 0.5)}, evaluate("rgba($red: 255, $green: 255, $blue: 255, $alpha: 
0.5)"))
+    assert_equal(%Q{rgba(255, 255, 255, 0.5)}, evaluate("rgba($color: #fff, $alpha: 0.5)"))
+  end
+
+  def test_keyword_args_rgba_with_extra_args
+    evaluate("rgba($red: 255, $green: 255, $blue: 255, $alpha: 0.5, $extra: error)")
+    flunk("Expected exception")
+  rescue Sass::SyntaxError => e
+    assert_equal("Function rgba doesn't have an argument named $extra", e.message)
+  end
+
+  def test_keyword_args_must_have_signature
+    evaluate("no-kw-args($fake: value)")
+    flunk("Expected exception")
+  rescue Sass::SyntaxError => e
+    assert_equal("Function no_kw_args doesn't support keyword arguments", e.message)
+  end
+
+  def test_keyword_args_with_missing_argument
+    evaluate("rgb($red: 255, $green: 255)")
+    flunk("Expected exception")
+  rescue Sass::SyntaxError => e
+    assert_equal("Function rgb requires an argument named $blue", e.message)
+  end
+
+  def test_keyword_args_with_extra_argument
+    evaluate("rgb($red: 255, $green: 255, $blue: 255, $purple: 255)")
+    flunk("Expected exception")
+  rescue Sass::SyntaxError => e
+    assert_equal("Function rgb doesn't have an argument named $purple", e.message)
+  end
+
+  def test_keyword_args_with_positional_and_keyword_argument
+    evaluate("rgb(255, 255, 255, $red: 255)")
+    flunk("Expected exception")
+  rescue Sass::SyntaxError => e
+    assert_equal("Function rgb was passed argument $red both by position and by name", e.message)
+  end
+
+  def test_keyword_args_with_keyword_before_positional_argument
+    evaluate("rgb($red: 255, 255, 255)")
+    flunk("Expected exception")
+  rescue Sass::SyntaxError => e
+    assert_equal("Positional arguments must come before keyword arguments.", e.message)
+  end
+
+  def test_only_var_args
+    assert_equal "only-var-args(2px, 3px, 4px)", evaluate("only-var-args(1px, 2px, 3px)")
+  end
+
+  def test_only_kw_args
+    assert_equal "only-kw-args(a, b, c)", evaluate("only-kw-args($a: 1, $b: 2, $c: 3)")
+  end
+
+  ## Regression Tests
+
+  def test_saturation_bounds
+    assert_equal "#fbfdff", evaluate("hsl(hue(#fbfdff), saturation(#fbfdff), lightness(#fbfdff))")
+  end
+
+  private
+
+  def evaluate(value)
+    result = perform(value)
+    assert_kind_of Sass::Script::Literal, result
+    return result.to_s
+  end
+
+  def perform(value)
+    Sass::Script::Parser.parse(value, 0, 0).perform(Sass::Environment.new)
+  end
+
+  def assert_error_message(message, value)
+    evaluate(value)
+    flunk("Error message expected but not raised: #{message}")
+  rescue Sass::SyntaxError => e
+    assert_equal(message, e.message)
+  end
+
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/importer_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/importer_test.rb
new file mode 100755
index 0000000..bdf63e1
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/importer_test.rb
@@ -0,0 +1,192 @@
+#!/usr/bin/env ruby
+require File.dirname(__FILE__) + '/../test_helper'
+require File.dirname(__FILE__) + '/test_helper'
+
+require 'sass/plugin'
+
+class ImporterTest < Test::Unit::TestCase
+  
+  class FruitImporter < Sass::Importers::Base
+    def find(name, context = nil)
+      if name =~ %r{fruits/(\w+)(\.s[ac]ss)?}
+        fruit = $1
+        color = case $1
+        when "apple"
+          "red"
+        when "orange"
+          "orange"
+        else
+          "blue"
+        end
+        contents = %Q{
+          $#{fruit}-color: #{color} !default;
+          @mixin #{fruit} {
+            color: $#{fruit}-color;
+          }
+        }
+        Sass::Engine.new(contents, :filename => name, :syntax => :scss, :importer => self)
+      end
+    end
+
+    def key(name, context)
+      [self.class.name, name]
+    end
+  end
+
+  # This class proves that you can override the extension scheme for importers
+  class ReversedExtImporter < Sass::Importers::Filesystem
+    def extensions
+      {"sscs" => :scss, "ssas" => :sass}
+    end
+  end
+
+  # This importer maps one import to another import
+  # based on the mappings passed to importer's constructor.
+  class IndirectImporter < Sass::Importers::Base
+    def initialize(mappings, mtimes)
+      @mappings = mappings
+      @mtimes = mtimes
+    end
+    def find_relative(uri, base, options)
+      nil
+    end
+    def find(name, options)
+      if @mappings.has_key?(name)
+        Sass::Engine.new(
+          %Q[ import "#{ mappings[name]}";],
+          options.merge(
+            :filename => name,
+            :syntax => :scss,
+            :importer => self
+          )
+        )
+      end
+    end
+    def mtime(uri, options)
+      @mtimes.fetch(uri, @mtimes.has_key?(uri) ? Time.now : nil)
+    end
+    def key(uri, options)
+      [self.class.name, uri]
+    end
+    def to_s
+      "IndirectImporter(#{ mappings keys join(", ")})"
+    end
+  end
+
+  # This importer maps the import to single class
+  # based on the mappings passed to importer's constructor.
+  class ClassImporter < Sass::Importers::Base
+    def initialize(mappings, mtimes)
+      @mappings = mappings
+      @mtimes = mtimes
+    end
+    def find_relative(uri, base, options)
+      nil
+    end
+    def find(name, options)
+      if @mappings.has_key?(name)
+        Sass::Engine.new(
+          %Q[ #{name}{#{ mappings[name]}}],
+          options.merge(
+            :filename => name,
+            :syntax => :scss,
+            :importer => self
+          )
+        )
+      end
+    end
+    def mtime(uri, options)
+      @mtimes.fetch(uri, @mtimes.has_key?(uri) ? Time.now : nil)
+    end
+    def key(uri, options)
+      [self.class.name, uri]
+    end
+    def to_s
+      "ClassImporter(#{ mappings keys join(", ")})"
+    end
+  end
+
+  def test_can_resolve_generated_imports
+    scss_file = %Q{
+      $pear-color: green;
+      @import "fruits/apple"; @import "fruits/orange"; @import "fruits/pear";
+      .apple { @include apple; }
+      .orange { @include orange; }
+      .pear { @include pear; }
+    }
+    css_file = <<CSS
+.apple { color: red; }
+
+.orange { color: orange; }
+
+.pear { color: green; }
+CSS
+    options = {:style => :compact, :load_paths => [FruitImporter.new], :syntax => :scss}
+    assert_equal css_file, Sass::Engine.new(scss_file, options).render
+  end
+
+  def test_extension_overrides
+    FileUtils.mkdir_p(absolutize("tmp"))
+    open(absolutize("tmp/foo.ssas"), "w") {|f| f.write(".foo\n  reversed: true\n")}
+    open(absolutize("tmp/bar.sscs"), "w") {|f| f.write(".bar {reversed: true}\n")}
+    scss_file = %Q{
+      @import "foo", "bar";
+      @import "foo.ssas", "bar.sscs";
+    }
+    css_file = <<CSS
+.foo { reversed: true; }
+
+.bar { reversed: true; }
+
+.foo { reversed: true; }
+
+.bar { reversed: true; }
+CSS
+    options = {:style => :compact, :load_paths => [ReversedExtImporter.new(absolutize("tmp"))], :syntax => 
:scss}
+    assert_equal css_file, Sass::Engine.new(scss_file, options).render
+  ensure
+    FileUtils.rm_rf(absolutize("tmp"))
+  end
+
+  def test_staleness_check_across_importers
+    file_system_importer = Sass::Importers::Filesystem.new(fixture_dir)
+    # Make sure the first import is older
+    indirect_importer = IndirectImporter.new({"apple" => "pear"}, {"apple" => Time.now - 1})
+    # Make css file is newer so the dependencies are the only way for the css file to be out of date.
+    FileUtils.touch(fixture_file("test_staleness_check_across_importers.css"))
+    # Make sure the first import is older
+    class_importer = ClassImporter.new({"pear" => %Q{color: green;}}, {"pear" => Time.now + 1})
+
+    options = {
+      :style => :compact,
+      :filename => fixture_file("test_staleness_check_across_importers.scss"),
+      :importer => file_system_importer,
+      :load_paths => [file_system_importer, indirect_importer, class_importer],
+      :syntax => :scss
+    }
+
+    assert_equal File.read(fixture_file("test_staleness_check_across_importers.css")),
+                 Sass::Engine.new(File.read(fixture_file("test_staleness_check_across_importers.scss")), 
options).render
+
+    checker = Sass::Plugin::StalenessChecker.new(options)
+
+    assert checker.stylesheet_needs_update?(
+      fixture_file("test_staleness_check_across_importers.css"),
+      fixture_file("test_staleness_check_across_importers.scss"),
+      file_system_importer
+    )
+  end
+
+  def fixture_dir
+    File.join(File.dirname(__FILE__), "fixtures")
+  end
+
+  def fixture_file(path)
+    File.join(fixture_dir, path)
+  end
+
+  def test_absolute_files_across_template_locations
+    importer = Sass::Importers::Filesystem.new(absolutize 'templates')
+    assert_not_nil importer.mtime(absolutize('more_templates/more1.sass'), {})
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/logger_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/logger_test.rb
new file mode 100755
index 0000000..7e0811d
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/logger_test.rb
@@ -0,0 +1,58 @@
+#!/usr/bin/env ruby
+require File.dirname(__FILE__) + '/../test_helper'
+require 'pathname'
+
+class LoggerTest < Test::Unit::TestCase
+
+  class InterceptedLogger < Sass::Logger::Base
+
+    attr_accessor :messages
+
+    def initialize(*args)
+      super
+      self.messages = []
+    end
+
+    def reset!
+      self.messages = []
+    end
+
+    def _log(*args)
+      messages << [args]
+    end
+
+  end
+
+  def test_global_sass_logger_instance_exists
+    assert Sass.logger.respond_to?(:warn)
+  end
+
+  def test_log_level_orders
+    logged_levels = {
+      :trace => [ [], [:trace, :debug, :info, :warn, :error]],
+      :debug => [ [:trace],   [:debug, :info, :warn, :error]],
+      :info  => [ [:trace, :debug],   [:info, :warn, :error]],
+      :warn  => [ [:trace, :debug, :info],   [:warn, :error]],
+      :error => [ [:trace, :debug, :info, :warn],   [:error]]
+    }
+    logged_levels.each do |level, (should_not_be_logged, should_be_logged)|
+      logger = Sass::Logger::Base.new(level)
+      should_not_be_logged.each do |should_level|
+        assert !logger.logging_level?(should_level)
+      end
+      should_be_logged.each do |should_level|
+        assert logger.logging_level?(should_level)
+      end
+    end
+  end
+
+  def test_logging_can_be_disabled
+    logger = InterceptedLogger.new
+    logger.error("message #1")
+    assert_equal 1, logger.messages.size
+    logger.reset!
+    logger.disabled = true
+    logger.error("message #2")
+    assert_equal 0, logger.messages.size
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/mock_importer.rb 
b/backends/css/gems/sass-3.2.12/test/sass/mock_importer.rb
new file mode 100644
index 0000000..312476d
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/mock_importer.rb
@@ -0,0 +1,49 @@
+class MockImporter < Sass::Importers::Base
+  def initialize(name = "mock")
+    @name = name
+    @imports = Hash.new({})
+  end
+
+  def find_relative(uri, base, options)
+    nil
+  end
+
+  def find(uri, options)
+    contents = @imports[uri][:contents]
+    return unless contents
+    options[:syntax] = @imports[uri][:syntax]
+    options[:filename] = uri
+    options[:importer] = self
+    @imports[uri][:engine] = Sass::Engine.new(contents, options)
+  end
+
+  def mtime(uri, options)
+    @imports[uri][:mtime]
+  end
+
+  def key(uri, options)
+    ["mock", uri]
+  end
+
+  def to_s
+    @name
+  end
+
+  # Methods for testing
+
+  def add_import(uri, contents, syntax = :scss, mtime = Time.now - 10)
+    @imports[uri] = {
+      :contents => contents,
+      :mtime => mtime,
+      :syntax => syntax
+    }
+  end
+
+  def touch(uri)
+    @imports[uri][:mtime] = Time.now
+  end
+
+  def engine(uri)
+    @imports[uri][:engine]
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/more_results/more1.css 
b/backends/css/gems/sass-3.2.12/test/sass/more_results/more1.css
new file mode 100644
index 0000000..b0d1182
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/more_results/more1.css
@@ -0,0 +1,9 @@
+body { font: Arial; background: blue; }
+
+#page { width: 700px; height: 100; }
+#page #header { height: 300px; }
+#page #header h1 { font-size: 50px; color: blue; }
+
+#content.user.show #container.top #column.left { width: 100px; }
+#content.user.show #container.top #column.right { width: 600px; }
+#content.user.show #container.bottom { background: brown; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/more_results/more1_with_line_comments.css 
b/backends/css/gems/sass-3.2.12/test/sass/more_results/more1_with_line_comments.css
new file mode 100644
index 0000000..f31dbca
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/more_results/more1_with_line_comments.css
@@ -0,0 +1,26 @@
+/* line 3, ../more_templates/more1.sass */
+body {
+  font: Arial;
+  background: blue; }
+
+/* line 7, ../more_templates/more1.sass */
+#page {
+  width: 700px;
+  height: 100; }
+  /* line 10, ../more_templates/more1.sass */
+  #page #header {
+    height: 300px; }
+    /* line 12, ../more_templates/more1.sass */
+    #page #header h1 {
+      font-size: 50px;
+      color: blue; }
+
+/* line 18, ../more_templates/more1.sass */
+#content.user.show #container.top #column.left {
+  width: 100px; }
+/* line 20, ../more_templates/more1.sass */
+#content.user.show #container.top #column.right {
+  width: 600px; }
+/* line 22, ../more_templates/more1.sass */
+#content.user.show #container.bottom {
+  background: brown; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/more_results/more_import.css 
b/backends/css/gems/sass-3.2.12/test/sass/more_results/more_import.css
new file mode 100644
index 0000000..7f4d5a7
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/more_results/more_import.css
@@ -0,0 +1,29 @@
+ import url(basic.css);
+ import url(../results/complex.css);
+imported { otherconst: hello; myconst: goodbye; pre-mixin: here; }
+
+body { font: Arial; background: blue; }
+
+#page { width: 700px; height: 100; }
+#page #header { height: 300px; }
+#page #header h1 { font-size: 50px; color: blue; }
+
+#content.user.show #container.top #column.left { width: 100px; }
+#content.user.show #container.top #column.right { width: 600px; }
+#content.user.show #container.bottom { background: brown; }
+
+midrule { inthe: middle; }
+
+body { font: Arial; background: blue; }
+
+#page { width: 700px; height: 100; }
+#page #header { height: 300px; }
+#page #header h1 { font-size: 50px; color: blue; }
+
+#content.user.show #container.top #column.left { width: 100px; }
+#content.user.show #container.top #column.right { width: 600px; }
+#content.user.show #container.bottom { background: brown; }
+
+#foo { background-color: #bbaaff; }
+
+nonimported { myconst: hello; otherconst: goodbye; post-mixin: here; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/more_templates/_more_partial.sass 
b/backends/css/gems/sass-3.2.12/test/sass/more_templates/_more_partial.sass
new file mode 100644
index 0000000..bef627d
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/more_templates/_more_partial.sass
@@ -0,0 +1,2 @@
+#foo
+  :background-color #baf
diff --git a/backends/css/gems/sass-3.2.12/test/sass/more_templates/more1.sass 
b/backends/css/gems/sass-3.2.12/test/sass/more_templates/more1.sass
new file mode 100644
index 0000000..71117bf
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/more_templates/more1.sass
@@ -0,0 +1,23 @@
+
+
+body  
+  :font Arial
+  :background blue
+
+#page
+  :width 700px
+  :height 100
+  #header
+    :height 300px
+    h1
+      :font-size 50px
+      :color     blue
+
+#content.user.show
+  #container.top
+    #column.left
+      :width 100px
+    #column.right
+      :width 600px
+  #container.bottom
+    :background brown
\ No newline at end of file
diff --git a/backends/css/gems/sass-3.2.12/test/sass/more_templates/more_import.sass 
b/backends/css/gems/sass-3.2.12/test/sass/more_templates/more_import.sass
new file mode 100644
index 0000000..8bb8430
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/more_templates/more_import.sass
@@ -0,0 +1,11 @@
+$preconst: hello
+
+=premixin
+  pre-mixin: here
+
+ import importee, basic, basic.css, ../results/complex.css, more_partial
+
+nonimported
+  :myconst $preconst
+  :otherconst $postconst
+  +postmixin
diff --git a/backends/css/gems/sass-3.2.12/test/sass/plugin_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/plugin_test.rb
new file mode 100755
index 0000000..14e9c86
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/plugin_test.rb
@@ -0,0 +1,550 @@
+#!/usr/bin/env ruby
+require File.dirname(__FILE__) + '/../test_helper'
+require File.dirname(__FILE__) + '/test_helper'
+require 'sass/plugin'
+require 'fileutils'
+
+module Sass::Script::Functions
+  def filename
+    filename = options[:filename].gsub(%r{.*((/[^/]+){4})}, '\1')
+    Sass::Script::String.new(filename)
+  end
+
+  def whatever
+    custom = options[:custom]
+    whatever = custom && custom[:whatever]
+    Sass::Script::String.new(whatever || "incorrect")
+  end
+end
+
+class SassPluginTest < Test::Unit::TestCase
+  @@templates = %w{
+    complex script parent_ref import scss_import alt
+    subdir/subdir subdir/nested_subdir/nested_subdir
+    options import_content filename_fn
+  }
+  @@templates += %w[import_charset import_charset_ibm866] unless Sass::Util.ruby1_8?
+  @@templates << 'import_charset_1_8' if Sass::Util.ruby1_8?
+
+  @@cache_store = Sass::CacheStores::Memory.new
+
+  def setup
+    FileUtils.mkdir_p tempfile_loc
+    FileUtils.mkdir_p tempfile_loc(nil,"more_")
+    set_plugin_opts
+    check_for_updates!
+    reset_mtimes
+  end
+
+  def teardown
+    clean_up_sassc
+    Sass::Plugin.reset!
+    FileUtils.rm_r tempfile_loc
+    FileUtils.rm_r tempfile_loc(nil,"more_")
+  end
+
+  @@templates.each do |name|
+    define_method("test_template_renders_correctly (#{name})") do
+      assert_renders_correctly(name)
+    end
+  end
+
+  def test_no_update
+    File.delete(tempfile_loc('basic'))
+    assert_needs_update 'basic'
+    check_for_updates!
+    assert_stylesheet_updated 'basic'
+  end
+
+  def test_update_needed_when_modified
+    touch 'basic'
+    assert_needs_update 'basic'
+    check_for_updates!
+    assert_stylesheet_updated 'basic'
+  end
+
+  def test_update_needed_when_dependency_modified
+    touch 'basic'
+    assert_needs_update 'import'
+    check_for_updates!
+    assert_stylesheet_updated 'basic'
+    assert_stylesheet_updated 'import'
+  end
+
+  def test_update_needed_when_scss_dependency_modified
+    touch 'scss_importee'
+    assert_needs_update 'import'
+    check_for_updates!
+    assert_stylesheet_updated 'scss_importee'
+    assert_stylesheet_updated 'import'
+  end
+
+  def test_scss_update_needed_when_dependency_modified
+    touch 'basic'
+    assert_needs_update 'scss_import'
+    check_for_updates!
+    assert_stylesheet_updated 'basic'
+    assert_stylesheet_updated 'scss_import'
+  end
+
+  def test_update_needed_when_nested_import_dependency_modified
+    touch 'basic'
+    assert_needs_update 'nested_import'
+    check_for_updates!
+    assert_stylesheet_updated 'basic'
+    assert_stylesheet_updated 'scss_import'
+  end
+
+  def test_no_updates_when_always_check_and_always_update_both_false
+    Sass::Plugin.options[:always_update] = false
+    Sass::Plugin.options[:always_check] = false
+
+    touch 'basic'
+    assert_needs_update 'basic'
+    check_for_updates!
+
+    # Check it's still stale
+    assert_needs_update 'basic'
+  end
+
+  def test_full_exception_handling
+    File.delete(tempfile_loc('bork1'))
+    check_for_updates!
+    File.open(tempfile_loc('bork1')) do |file|
+      assert_equal(<<CSS.strip, file.read.split("\n")[0...6].join("\n"))
+/*
+Syntax error: Undefined variable: "$bork".
+        on line 2 of #{template_loc('bork1')}
+
+1: bork
+2:   :bork $bork
+CSS
+    end
+    File.delete(tempfile_loc('bork1'))
+  end
+
+  def test_full_exception_with_block_comment
+    File.delete(tempfile_loc('bork5'))
+    check_for_updates!
+    File.open(tempfile_loc('bork5')) do |file|
+      assert_equal(<<CSS.strip, file.read.split("\n")[0...7].join("\n"))
+/*
+Syntax error: Undefined variable: "$bork".
+        on line 3 of #{template_loc('bork5')}
+
+1: bork
+2:   /* foo *\\/
+3:   :bork $bork
+CSS
+    end
+    File.delete(tempfile_loc('bork1'))
+  end
+
+  def test_single_level_import_loop
+    File.delete(tempfile_loc('single_import_loop'))
+    check_for_updates!
+    File.open(tempfile_loc('single_import_loop')) do |file|
+      assert_equal(<<CSS.strip, file.read.split("\n")[0...2].join("\n"))
+/*
+Syntax error: An @import loop has been found: #{template_loc('single_import_loop')} imports itself
+CSS
+    end
+  end
+
+  def test_double_level_import_loop
+    File.delete(tempfile_loc('double_import_loop1'))
+    check_for_updates!
+    File.open(tempfile_loc('double_import_loop1')) do |file|
+      assert_equal(<<CSS.strip, file.read.split("\n")[0...4].join("\n"))
+/*
+Syntax error: An @import loop has been found:
+                  #{template_loc('double_import_loop1')} imports #{template_loc('_double_import_loop2')}
+                  #{template_loc('_double_import_loop2')} imports #{template_loc('double_import_loop1')}
+CSS
+    end
+  end
+
+  def test_nonfull_exception_handling
+    old_full_exception = Sass::Plugin.options[:full_exception]
+    Sass::Plugin.options[:full_exception] = false
+
+    File.delete(tempfile_loc('bork1'))
+    assert_raise(Sass::SyntaxError) {check_for_updates!}
+  ensure
+    Sass::Plugin.options[:full_exception] = old_full_exception
+  end
+
+  def test_two_template_directories
+    set_plugin_opts :template_location => {
+      template_loc => tempfile_loc,
+      template_loc(nil,'more_') => tempfile_loc(nil,'more_')
+    }
+    check_for_updates!
+    ['more1', 'more_import'].each { |name| assert_renders_correctly(name, :prefix => 'more_') }
+  end
+
+  def test_two_template_directories_with_line_annotations
+    set_plugin_opts :line_comments => true,
+                    :style => :nested,
+                    :template_location => {
+                      template_loc => tempfile_loc,
+                      template_loc(nil,'more_') => tempfile_loc(nil,'more_')
+                    }
+    check_for_updates!
+    assert_renders_correctly('more1_with_line_comments', 'more1', :prefix => 'more_')
+  end
+
+  def test_doesnt_render_partials
+    assert !File.exists?(tempfile_loc('_partial'))
+  end
+
+  def test_template_location_array
+    assert_equal [[template_loc, tempfile_loc]], Sass::Plugin.template_location_array
+  end
+
+  def test_add_template_location
+    Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_"))
+    assert_equal(
+      [[template_loc, tempfile_loc], [template_loc(nil, "more_"), tempfile_loc(nil, "more_")]],
+      Sass::Plugin.template_location_array)
+
+    touch 'more1', 'more_'
+    touch 'basic'
+    assert_needs_update "more1", "more_"
+    assert_needs_update "basic"
+    check_for_updates!
+    assert_doesnt_need_update "more1", "more_"
+    assert_doesnt_need_update "basic"
+  end
+
+  def test_remove_template_location
+    Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_"))
+    Sass::Plugin.remove_template_location(template_loc, tempfile_loc)
+    assert_equal(
+      [[template_loc(nil, "more_"), tempfile_loc(nil, "more_")]],
+      Sass::Plugin.template_location_array)
+
+    touch 'more1', 'more_'
+    touch 'basic'
+    assert_needs_update "more1", "more_"
+    assert_needs_update "basic"
+    check_for_updates!
+    assert_doesnt_need_update "more1", "more_"
+    assert_needs_update "basic"
+  end
+
+  def test_import_same_name
+    assert_warning <<WARNING do
+WARNING: In #{template_loc}:
+  There are multiple files that match the name "same_name_different_partiality.scss":
+    _same_name_different_partiality.scss
+    same_name_different_partiality.scss
+WARNING
+      touch "_same_name_different_partiality"
+      assert_needs_update "same_name_different_partiality"
+    end
+  end
+
+  # Callbacks
+
+  def test_updating_stylesheets_callback
+    # Should run even when there's nothing to update
+    Sass::Plugin.options[:template_location] = nil
+    assert_callback :updating_stylesheets, []
+  end
+
+  def test_updating_stylesheets_callback_with_never_update
+    Sass::Plugin.options[:never_update] = true
+    assert_no_callback :updating_stylesheets
+  end
+
+  def test_updated_stylesheet_callback_for_updated_template
+    Sass::Plugin.options[:always_update] = false
+    touch 'basic'
+    assert_no_callback :updated_stylesheet, template_loc("complex"), tempfile_loc("complex") do
+      assert_callbacks(
+        [:updated_stylesheet, template_loc("basic"), tempfile_loc("basic")],
+        [:updated_stylesheet, template_loc("import"), tempfile_loc("import")])
+    end
+  end
+
+  def test_updated_stylesheet_callback_for_fresh_template
+    Sass::Plugin.options[:always_update] = false
+    assert_no_callback :updated_stylesheet
+  end
+
+  def test_updated_stylesheet_callback_for_error_template
+    Sass::Plugin.options[:always_update] = false
+    touch 'bork1'
+    assert_no_callback :updated_stylesheet
+  end
+
+  def test_not_updating_stylesheet_callback_for_fresh_template
+    Sass::Plugin.options[:always_update] = false
+    assert_callback :not_updating_stylesheet, template_loc("basic"), tempfile_loc("basic")
+  end
+
+  def test_not_updating_stylesheet_callback_for_updated_template
+    Sass::Plugin.options[:always_update] = false
+    assert_callback :not_updating_stylesheet, template_loc("complex"), tempfile_loc("complex") do
+      assert_no_callbacks(
+        [:updated_stylesheet, template_loc("basic"), tempfile_loc("basic")],
+        [:updated_stylesheet, template_loc("import"), tempfile_loc("import")])
+    end
+  end
+
+  def test_not_updating_stylesheet_callback_with_never_update
+    Sass::Plugin.options[:never_update] = true
+    assert_no_callback :not_updating_stylesheet
+  end
+
+  def test_not_updating_stylesheet_callback_for_partial
+    Sass::Plugin.options[:always_update] = false
+    assert_no_callback :not_updating_stylesheet, template_loc("_partial"), tempfile_loc("_partial")
+  end
+
+  def test_not_updating_stylesheet_callback_for_error
+    Sass::Plugin.options[:always_update] = false
+    touch 'bork1'
+    assert_no_callback :not_updating_stylesheet, template_loc("bork1"), tempfile_loc("bork1")
+  end
+
+  def test_compilation_error_callback
+    Sass::Plugin.options[:always_update] = false
+    touch 'bork1'
+    assert_callback(:compilation_error,
+      lambda {|e| e.message == 'Undefined variable: "$bork".'},
+      template_loc("bork1"), tempfile_loc("bork1"))
+  end
+
+  def test_compilation_error_callback_for_file_access
+    Sass::Plugin.options[:always_update] = false
+    assert_callback(:compilation_error,
+      lambda {|e| e.is_a?(Errno::ENOENT)},
+      template_loc("nonexistent"), tempfile_loc("nonexistent")) do
+      Sass::Plugin.update_stylesheets([[template_loc("nonexistent"), tempfile_loc("nonexistent")]])
+    end
+  end
+
+  def test_creating_directory_callback
+    Sass::Plugin.options[:always_update] = false
+    dir = File.join(tempfile_loc, "subdir", "nested_subdir")
+    FileUtils.rm_r dir
+    assert_callback :creating_directory, dir
+  end
+
+  ## Regression
+
+  def test_cached_dependencies_update
+    FileUtils.mv(template_loc("basic"), template_loc("basic", "more_"))
+    set_plugin_opts :load_paths => [template_loc(nil, "more_")]
+
+    touch 'basic', 'more_'
+    assert_needs_update "import"
+    check_for_updates!
+    assert_renders_correctly("import")
+  ensure
+    FileUtils.mv(template_loc("basic", "more_"), template_loc("basic"))
+  end
+
+  def test_cached_relative_import
+    old_always_update = Sass::Plugin.options[:always_update]
+    Sass::Plugin.options[:always_update] = true
+    check_for_updates!
+    assert_renders_correctly('subdir/subdir')
+  ensure
+    Sass::Plugin.options[:always_update] = old_always_update
+  end
+
+  def test_cached_if
+    set_plugin_opts :cache_store => Sass::CacheStores::Filesystem.new(tempfile_loc + '/cache')
+    check_for_updates!
+    assert_renders_correctly 'if'
+    check_for_updates!
+    assert_renders_correctly 'if'
+  ensure
+    set_plugin_opts
+  end
+
+  def test_cached_import_option
+    set_plugin_opts :custom => {:whatever => "correct"}
+    check_for_updates!
+    assert_renders_correctly "cached_import_option"
+
+    @@cache_store.reset!
+    set_plugin_opts :custom => nil, :always_update => false
+    check_for_updates!
+    assert_renders_correctly "cached_import_option"
+
+    set_plugin_opts :custom => {:whatever => "correct"}, :always_update => true
+    check_for_updates!
+    assert_renders_correctly "cached_import_option"
+  ensure
+    set_plugin_opts :custom => nil
+  end
+
+ private
+
+  def assert_renders_correctly(*arguments)
+    options = arguments.last.is_a?(Hash) ? arguments.pop : {}
+    prefix = options[:prefix]
+    result_name = arguments.shift
+    tempfile_name = arguments.shift || result_name
+
+    expected_str = File.read(result_loc(result_name, prefix))
+    actual_str = File.read(tempfile_loc(tempfile_name, prefix))
+    unless Sass::Util.ruby1_8?
+      expected_str = expected_str.force_encoding('IBM866') if result_name == 'import_charset_ibm866'
+      actual_str = actual_str.force_encoding('IBM866') if tempfile_name == 'import_charset_ibm866'
+    end
+    expected_lines = expected_str.split("\n")
+    actual_lines = actual_str.split("\n")
+
+    if actual_lines.first == "/*" && expected_lines.first != "/*"
+      assert(false, actual_lines[0..Sass::Util.enum_with_index(actual_lines).find {|l, i| l == 
"*/"}.last].join("\n"))
+    end
+
+    expected_lines.zip(actual_lines).each_with_index do |pair, line|
+      message = "template: #{result_name}\nline:     #{line + 1}"
+      assert_equal(pair.first, pair.last, message)
+    end
+    if expected_lines.size < actual_lines.size
+      assert(false, "#{actual_lines.size - expected_lines.size} Trailing lines found in 
#{tempfile_name}.css: #{actual_lines[expected_lines.size..-1].join('\n')}")
+    end
+  end
+
+  def assert_stylesheet_updated(name)
+    assert_doesnt_need_update name
+
+    # Make sure it isn't an exception
+    expected_lines = File.read(result_loc(name)).split("\n")
+    actual_lines = File.read(tempfile_loc(name)).split("\n")
+    if actual_lines.first == "/*" && expected_lines.first != "/*"
+      assert(false, actual_lines[0..actual_lines.enum_with_index.find {|l, i| l == "*/"}.last].join("\n"))
+    end
+  end
+
+  def assert_callback(name, *expected_args)
+    run = false
+    received_args = nil
+    Sass::Plugin.send("on_#{name}") do |*args|
+      received_args = args
+      run ||= expected_args.zip(received_args).all? do |ea, ra|
+        ea.respond_to?(:call) ? ea.call(ra) : ea == ra
+      end
+    end
+
+    if block_given?
+      Sass::Util.silence_sass_warnings {yield}
+    else
+      check_for_updates!
+    end
+
+    assert run, "Expected #{name} callback to be run with arguments:\n  #{expected_args.inspect}\nHowever, 
it got:\n  #{received_args.inspect}"
+  end
+
+  def assert_no_callback(name, *unexpected_args)
+    Sass::Plugin.send("on_#{name}") do |*a|
+      next unless unexpected_args.empty? || a == unexpected_args
+
+      msg = "Expected #{name} callback not to be run"
+      if !unexpected_args.empty?
+        msg << " with arguments #{unexpected_args.inspect}"
+      elsif !a.empty?
+        msg << ",\n  was run with arguments #{a.inspect}"
+      end
+
+      flunk msg
+    end
+
+    if block_given?
+      yield
+    else
+      check_for_updates!
+    end
+  end
+
+  def assert_callbacks(*args)
+    return check_for_updates! if args.empty?
+    assert_callback(*args.pop) {assert_callbacks(*args)}
+  end
+
+  def assert_no_callbacks(*args)
+    return check_for_updates! if args.empty?
+    assert_no_callback(*args.pop) {assert_no_callbacks(*args)}
+  end
+
+  def check_for_updates!
+    Sass::Util.silence_sass_warnings do
+      Sass::Plugin.check_for_updates
+    end
+  end
+
+  def assert_needs_update(*args)
+    assert(Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), template_loc(*args)),
+      "Expected #{template_loc(*args)} to need an update.")
+  end
+
+  def assert_doesnt_need_update(*args)
+    assert(!Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), 
template_loc(*args)),
+      "Expected #{template_loc(*args)} not to need an update.")
+  end
+
+  def touch(*args)
+    FileUtils.touch(template_loc(*args))
+  end
+
+  def reset_mtimes
+    Sass::Plugin::StalenessChecker.dependencies_cache = {}
+    atime = Time.now
+    mtime = Time.now - 5
+    Dir["{#{template_loc},#{tempfile_loc}}/**/*.{css,sass,scss}"].each {|f| File.utime(atime, mtime, f)}
+  end
+
+  def template_loc(name = nil, prefix = nil)
+    if name
+      scss = absolutize "#{prefix}templates/#{name}.scss"
+      File.exists?(scss) ? scss : absolutize("#{prefix}templates/#{name}.sass")
+    else
+      absolutize "#{prefix}templates"
+    end
+  end
+
+  def tempfile_loc(name = nil, prefix = nil)
+    if name
+      absolutize "#{prefix}tmp/#{name}.css"
+    else
+      absolutize "#{prefix}tmp"
+    end
+  end
+
+  def result_loc(name = nil, prefix = nil)
+    if name
+      absolutize "#{prefix}results/#{name}.css"
+    else
+      absolutize "#{prefix}results"
+    end
+  end
+
+  def set_plugin_opts(overrides = {})
+    Sass::Plugin.options.merge!(
+      :template_location => template_loc,
+      :css_location => tempfile_loc,
+      :style => :compact,
+      :always_update => true,
+      :never_update => false,
+      :full_exception => true,
+      :cache_store => @@cache_store
+    )
+    Sass::Plugin.options.merge!(overrides)
+  end
+end
+
+class Sass::Engine
+  alias_method :old_render, :render
+
+  def render
+    raise "bork bork bork!" if @template[0] == "{bork now!}"
+    old_render
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/alt.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/alt.css
new file mode 100644
index 0000000..8484343
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/alt.css
@@ -0,0 +1,4 @@
+h1 { float: left; width: 274px; height: 75px; margin: 0; background-repeat: no-repeat; background-image: 
none; }
+h1 a:hover, h1 a:visited { color: green; }
+h1 b:hover { color: red; background-color: green; }
+h1 const { nosp: 3; sp: 3; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/basic.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/basic.css
new file mode 100644
index 0000000..b0d1182
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/basic.css
@@ -0,0 +1,9 @@
+body { font: Arial; background: blue; }
+
+#page { width: 700px; height: 100; }
+#page #header { height: 300px; }
+#page #header h1 { font-size: 50px; color: blue; }
+
+#content.user.show #container.top #column.left { width: 100px; }
+#content.user.show #container.top #column.right { width: 600px; }
+#content.user.show #container.bottom { background: brown; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/cached_import_option.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/cached_import_option.css
new file mode 100644
index 0000000..331c0e7
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/cached_import_option.css
@@ -0,0 +1,3 @@
+partial { value: correct; }
+
+main { value: correct; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/compact.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/compact.css
new file mode 100644
index 0000000..3c33e8b
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/compact.css
@@ -0,0 +1,5 @@
+#main { width: 15em; color: blue; }
+#main p { border-style: dotted; /* Nested comment More nested stuff */ border-width: 2px; }
+#main .cool { width: 100px; }
+
+#left { font-size: 2em; font-weight: bold; float: left; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/complex.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/complex.css
new file mode 100644
index 0000000..9fcb03f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/complex.css
@@ -0,0 +1,86 @@
+body { margin: 0; font: 0.85em "Lucida Grande", "Trebuchet MS", Verdana, sans-serif; color: white; 
background: url(/images/global_bg.gif); }
+
+#page { width: 900px; margin: 0 auto; background: #440008; border-top-width: 5px; border-top-style: solid; 
border-top-color: #ff8500; }
+
+#header { height: 75px; padding: 0; }
+#header h1 { float: left; width: 274px; height: 75px; margin: 0; background-image: 
url(/images/global_logo.gif); /* Crazy nested comment */ background-repeat: no-repeat; text-indent: -9999px; }
+#header .status { float: right; padding-top: 0.5em; padding-left: 0.5em; padding-right: 0.5em; 
padding-bottom: 0; }
+#header .status p { float: left; margin-top: 0; margin-right: 0.5em; margin-bottom: 0; margin-left: 0; }
+#header .status ul { float: left; margin: 0; padding: 0; }
+#header .status li { list-style-type: none; display: inline; margin: 0 5px; }
+#header .status a:link, #header .status a:visited { color: #ff8500; text-decoration: none; }
+#header .status a:hover { text-decoration: underline; }
+#header .search { float: right; clear: right; margin: 12px 0 0 0; }
+#header .search form { margin: 0; }
+#header .search input { margin: 0 3px 0 0; padding: 2px; border: none; }
+
+#menu { clear: both; text-align: right; height: 20px; border-bottom: 5px solid #006b95; background: #00a4e4; 
}
+#menu .contests ul { margin: 0 5px 0 0; padding: 0; }
+#menu .contests ul li { list-style-type: none; margin: 0 5px; padding: 5px 5px 0 5px; display: inline; 
font-size: 1.1em; color: white; background: #00a4e4; }
+#menu .contests a:link, #menu .contests a:visited { color: white; text-decoration: none; font-weight: bold; }
+#menu .contests a:hover { text-decoration: underline; }
+
+#content { clear: both; }
+#content .container { clear: both; }
+#content .container .column { float: left; }
+#content .container .column .right { float: right; }
+#content a:link, #content a:visited { color: #93d700; text-decoration: none; }
+#content a:hover { text-decoration: underline; }
+
+#content p, #content div { width: 40em; }
+#content p li, #content p dt, #content p dd, #content div li, #content div dt, #content div dd { color: 
#ddffdd; background-color: #4792bb; }
+#content .container.video .column.left { width: 200px; }
+#content .container.video .column.left .box { margin-top: 10px; }
+#content .container.video .column.left .box p { margin: 0 1em auto 1em; }
+#content .container.video .column.left .box.participants img { float: left; margin: 0 1em auto 1em; border: 
1px solid #6e000d; border-style: solid; }
+#content .container.video .column.left .box.participants h2 { margin: 0 0 10px 0; padding: 0.5em; /* The 
background image is a gif! */ background: #6e000d url(/images/hdr_participant.gif) 2px 2px no-repeat; /* Okay 
check this out Multiline comments Wow dude I mean seriously, WOW */ text-indent: -9999px; border-top-width: 
5px; border-top-style: solid; border-top-color: #a20013; border-right-width: 1px; border-right-style: dotted; 
}
+#content .container.video .column.middle { width: 500px; }
+#content .container.video .column.right { width: 200px; }
+#content .container.video .column.right .box { margin-top: 0; }
+#content .container.video .column.right .box p { margin: 0 1em auto 1em; }
+#content .container.video .column p { margin-top: 0; }
+
+#content.contests .container.information .column.right .box { margin: 1em 0; }
+#content.contests .container.information .column.right .box.videos .thumbnail img { width: 200px; height: 
150px; margin-bottom: 5px; }
+#content.contests .container.information .column.right .box.videos a:link, #content.contests 
.container.information .column.right .box.videos a:visited { color: #93d700; text-decoration: none; }
+#content.contests .container.information .column.right .box.videos a:hover { text-decoration: underline; }
+#content.contests .container.information .column.right .box.votes a { display: block; width: 200px; height: 
60px; margin: 15px 0; background: url(/images/btn_votenow.gif) no-repeat; text-indent: -9999px; outline: 
none; border: none; }
+#content.contests .container.information .column.right .box.votes h2 { margin: 52px 0 10px 0; padding: 
0.5em; background: #6e000d url(/images/hdr_videostats.gif) 2px 2px no-repeat; text-indent: -9999px; 
border-top: 5px solid #a20013; }
+
+#content.contests .container.video .box.videos h2 { margin: 0; padding: 0.5em; background: #6e000d 
url(/images/hdr_newestclips.gif) 2px 2px no-repeat; text-indent: -9999px; border-top: 5px solid #a20013; }
+#content.contests .container.video .box.videos table { width: 100; }
+#content.contests .container.video .box.videos table td { padding: 1em; width: 25; vertical-align: top; }
+#content.contests .container.video .box.videos table td p { margin: 0 0 5px 0; }
+#content.contests .container.video .box.videos table td a:link, #content.contests .container.video 
.box.videos table td a:visited { color: #93d700; text-decoration: none; }
+#content.contests .container.video .box.videos table td a:hover { text-decoration: underline; }
+#content.contests .container.video .box.videos .thumbnail { float: left; }
+#content.contests .container.video .box.videos .thumbnail img { width: 80px; height: 60px; margin: 0 10px 0 
0; border: 1px solid #6e000d; }
+
+#content .container.comments .column { margin-top: 15px; }
+#content .container.comments .column.left { width: 600px; }
+#content .container.comments .column.left .box ol { margin: 0; padding: 0; }
+#content .container.comments .column.left .box li { list-style-type: none; padding: 10px; margin: 0 0 1em 0; 
background: #6e000d; border-top: 5px solid #a20013; }
+#content .container.comments .column.left .box li div { margin-bottom: 1em; }
+#content .container.comments .column.left .box li ul { text-align: right; }
+#content .container.comments .column.left .box li ul li { display: inline; border: none; padding: 0; }
+#content .container.comments .column.right { width: 290px; padding-left: 10px; }
+#content .container.comments .column.right h2 { margin: 0; padding: 0.5em; background: #6e000d 
url(/images/hdr_addcomment.gif) 2px 2px no-repeat; text-indent: -9999px; border-top: 5px solid #a20013; }
+#content .container.comments .column.right .box textarea { width: 290px; height: 100px; border: none; }
+
+#footer { margin-top: 10px; padding: 1.2em 1.5em; background: #ff8500; }
+#footer ul { margin: 0; padding: 0; list-style-type: none; }
+#footer ul li { display: inline; margin: 0 0.5em; color: #440008; }
+#footer ul.links { float: left; }
+#footer ul.links a:link, #footer ul.links a:visited { color: #440008; text-decoration: none; }
+#footer ul.links a:hover { text-decoration: underline; }
+#footer ul.copyright { float: right; }
+
+.clear { clear: both; }
+
+.centered { text-align: center; }
+
+img { border: none; }
+
+button.short { width: 60px; height: 22px; padding: 0 0 2px 0; color: white; border: none; background: 
url(/images/btn_short.gif) no-repeat; }
+
+table { border-collapse: collapse; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/compressed.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/compressed.css
new file mode 100644
index 0000000..7c62786
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/compressed.css
@@ -0,0 +1 @@
+#main{width:15em;color:blue}#main p{border-style:dotted;border-width:2px}#main 
.cool{width:100px}#left{font-size:2em;font-weight:bold;float:left}
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/expanded.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/expanded.css
new file mode 100644
index 0000000..b42e076
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/expanded.css
@@ -0,0 +1,19 @@
+#main {
+  width: 15em;
+  color: blue;
+}
+#main p {
+  border-style: dotted;
+  /* Nested comment
+   * More nested stuff */
+  border-width: 2px;
+}
+#main .cool {
+  width: 100px;
+}
+
+#left {
+  font-size: 2em;
+  font-weight: bold;
+  float: left;
+}
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/filename_fn.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/filename_fn.css
new file mode 100644
index 0000000..e55d9a7
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/filename_fn.css
@@ -0,0 +1,3 @@
+filename { imported: /test/sass/templates/_filename_fn_import.scss; }
+
+filename { local: /test/sass/templates/filename_fn.scss; local-mixin: /test/sass/templates/filename_fn.scss; 
local-function: /test/sass/templates/filename_fn.scss; imported-mixin: 
/test/sass/templates/_filename_fn_import.scss; imported-function: 
/test/sass/templates/_filename_fn_import.scss; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/if.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/if.css
new file mode 100644
index 0000000..31e8813
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/if.css
@@ -0,0 +1,3 @@
+a { branch: if; }
+
+b { branch: else; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/import.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/import.css
new file mode 100644
index 0000000..87ae3c8
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/import.css
@@ -0,0 +1,31 @@
+ import url(basic.css);
+ import url(../results/complex.css);
+imported { otherconst: hello; myconst: goodbye; pre-mixin: here; }
+
+body { font: Arial; background: blue; }
+
+#page { width: 700px; height: 100; }
+#page #header { height: 300px; }
+#page #header h1 { font-size: 50px; color: blue; }
+
+#content.user.show #container.top #column.left { width: 100px; }
+#content.user.show #container.top #column.right { width: 600px; }
+#content.user.show #container.bottom { background: brown; }
+
+midrule { inthe: middle; }
+
+scss { imported: yes; }
+
+body { font: Arial; background: blue; }
+
+#page { width: 700px; height: 100; }
+#page #header { height: 300px; }
+#page #header h1 { font-size: 50px; color: blue; }
+
+#content.user.show #container.top #column.left { width: 100px; }
+#content.user.show #container.top #column.right { width: 600px; }
+#content.user.show #container.bottom { background: brown; }
+
+#foo { background-color: #bbaaff; }
+
+nonimported { myconst: hello; otherconst: goodbye; post-mixin: here; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/import_charset.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/import_charset.css
new file mode 100644
index 0000000..d7184a3
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/import_charset.css
@@ -0,0 +1,5 @@
+ charset "UTF-8";
+ import url(foo.css);
+.foo { a: b; }
+
+.bar { a: щ; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/import_charset_1_8.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/import_charset_1_8.css
new file mode 100644
index 0000000..59cb744
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/import_charset_1_8.css
@@ -0,0 +1,5 @@
+ charset "IBM866";
+ import url(foo.css);
+.foo { a: b; }
+
+.bar { a: �; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/import_charset_ibm866.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/import_charset_ibm866.css
new file mode 100644
index 0000000..59cb744
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/import_charset_ibm866.css
@@ -0,0 +1,5 @@
+ charset "IBM866";
+ import url(foo.css);
+.foo { a: b; }
+
+.bar { a: �; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/import_content.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/import_content.css
new file mode 100644
index 0000000..c67e3f9
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/import_content.css
@@ -0,0 +1 @@
+a { b: c; }
\ No newline at end of file
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/line_numbers.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/line_numbers.css
new file mode 100644
index 0000000..3c657f9
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/line_numbers.css
@@ -0,0 +1,49 @@
+/* line 1, ../templates/line_numbers.sass */
+foo {
+  bar: baz; }
+
+/* line 6, ../templates/importee.sass */
+imported {
+  otherconst: 12;
+  myconst: goodbye; }
+  /* line 5, ../templates/line_numbers.sass */
+  imported squggle {
+    blat: bang; }
+
+/* line 3, ../templates/basic.sass */
+body {
+  font: Arial;
+  background: blue; }
+
+/* line 7, ../templates/basic.sass */
+#page {
+  width: 700px;
+  height: 100; }
+  /* line 10, ../templates/basic.sass */
+  #page #header {
+    height: 300px; }
+    /* line 12, ../templates/basic.sass */
+    #page #header h1 {
+      font-size: 50px;
+      color: blue; }
+
+/* line 18, ../templates/basic.sass */
+#content.user.show #container.top #column.left {
+  width: 100px; }
+/* line 20, ../templates/basic.sass */
+#content.user.show #container.top #column.right {
+  width: 600px; }
+/* line 22, ../templates/basic.sass */
+#content.user.show #container.bottom {
+  background: brown; }
+
+/* line 13, ../templates/importee.sass */
+midrule {
+  inthe: middle; }
+
+/* line 12, ../templates/line_numbers.sass */
+umph {
+  foo: bar; }
+  /* line 18, ../templates/importee.sass */
+  umph baz {
+    blat: bang; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/mixins.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/mixins.css
new file mode 100644
index 0000000..969d2a3
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/mixins.css
@@ -0,0 +1,95 @@
+#main {
+  width: 15em;
+  color: blue;
+}
+#main p {
+  border-top-width: 2px;
+  border-top-color: #ffcc00;
+  border-left-width: 1px;
+  border-left-color: black;
+  -moz-border-radius: 10px;
+  border-style: dotted;
+  border-width: 2px;
+}
+#main .cool {
+  width: 100px;
+}
+
+#left {
+  border-top-width: 2px;
+  border-top-color: #ffcc00;
+  border-left-width: 1px;
+  border-left-color: black;
+  -moz-border-radius: 10px;
+  font-size: 2em;
+  font-weight: bold;
+  float: left;
+}
+
+#right {
+  border-top-width: 2px;
+  border-top-color: #ffcc00;
+  border-left-width: 1px;
+  border-left-color: black;
+  -moz-border-radius: 10px;
+  color: red;
+  font-size: 20px;
+  float: right;
+}
+
+.bordered {
+  border-top-width: 2px;
+  border-top-color: #ffcc00;
+  border-left-width: 1px;
+  border-left-color: black;
+  -moz-border-radius: 10px;
+}
+
+.complex {
+  color: red;
+  font-size: 20px;
+  text-decoration: none;
+}
+.complex:after {
+  content: ".";
+  display: block;
+  height: 0;
+  clear: both;
+  visibility: hidden;
+}
+* html .complex {
+  height: 1px;
+  color: red;
+  font-size: 20px;
+}
+
+.more-complex {
+  color: red;
+  font-size: 20px;
+  text-decoration: none;
+  display: inline;
+  -webkit-nonsense-top-right: 1px;
+  -webkit-nonsense-bottom-left: 1px;
+}
+.more-complex:after {
+  content: ".";
+  display: block;
+  height: 0;
+  clear: both;
+  visibility: hidden;
+}
+* html .more-complex {
+  height: 1px;
+  color: red;
+  font-size: 20px;
+}
+.more-complex a:hover {
+  text-decoration: underline;
+  color: red;
+  font-size: 20px;
+  border-top-width: 2px;
+  border-top-color: #ffcc00;
+  border-left-width: 1px;
+  border-left-color: black;
+  -moz-border-radius: 10px;
+}
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/multiline.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/multiline.css
new file mode 100644
index 0000000..8fa9535
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/multiline.css
@@ -0,0 +1,24 @@
+#main,
+#header {
+  height: 50px; }
+  #main div,
+  #header div {
+    width: 100px; }
+    #main div a span,
+    #main div em span,
+    #header div a span,
+    #header div em span {
+      color: pink; }
+
+#one div.nested,
+#one span.nested,
+#one p.nested,
+#two div.nested,
+#two span.nested,
+#two p.nested,
+#three div.nested,
+#three span.nested,
+#three p.nested {
+  font-weight: bold;
+  border-color: red;
+  display: block; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/nested.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/nested.css
new file mode 100644
index 0000000..6200883
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/nested.css
@@ -0,0 +1,22 @@
+#main {
+  width: 15em;
+  color: blue; }
+  #main p {
+    border-style: dotted;
+    /* Nested comment
+     * More nested stuff */
+    border-width: 2px; }
+  #main .cool {
+    width: 100px; }
+
+#left {
+  font-size: 2em;
+  font-weight: bold;
+  float: left; }
+
+#right .header {
+  border-style: solid; }
+#right .body {
+  border-style: dotted; }
+#right .footer {
+  border-style: dashed; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/options.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/options.css
new file mode 100644
index 0000000..628f4c3
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/options.css
@@ -0,0 +1 @@
+foo { style: compact; }
\ No newline at end of file
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/parent_ref.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/parent_ref.css
new file mode 100644
index 0000000..4506709
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/parent_ref.css
@@ -0,0 +1,13 @@
+a { color: black; }
+a:hover { color: red; }
+
+p, div { width: 100em; }
+p foo, div foo { width: 10em; }
+p:hover, p bar, div:hover, div bar { height: 20em; }
+
+#cool { border-style: solid; border-width: 2em; }
+.ie7 #cool, .ie6 #cool { content: string("Totally not cool."); }
+.firefox #cool { content: string("Quite cool."); }
+
+.wow, .snazzy { font-family: fantasy; }
+.wow:hover, .wow:visited, .snazzy:hover, .snazzy:visited { font-weight: bold; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/script.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/script.css
new file mode 100644
index 0000000..570385c
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/script.css
@@ -0,0 +1,16 @@
+#main { content: Hello\!; qstr: 'Quo"ted"!'; hstr: Hyph-en\!; width: 30em; background-color: black; color: 
#ffffaa; short-color: #112233; named-color: olive; con: "foo" bar 9 hi there "boom"; con2: "noquo" quo; }
+#main #sidebar { background-color: #00ff98; num-normal: 10; num-dec: 10.2; num-dec0: 99; num-neg: -10; esc: 
10 \+12; many: 6; order: 7; complex: #4c9db1hi16; }
+
+#plus { num-num: 7; num-num-un: 25em; num-num-un2: 23em; num-num-neg: 9.87; num-str: 100px; num-col: 
#b7b7b7; num-perc: 31%; str-str: "hi\ there"; str-str2: "hi there"; str-col: "14em solid #112233"; str-num: 
"times: 13"; col-num: #ff7b9d; col-col: #5173ff; }
+
+#minus { num-num: 900; col-num: #f9f9f4; col-col: #000035; unary-num: -1; unary-const: 10; unary-paren: -11; 
unary-two: 12; unary-many: 12; unary-crazy: -15; }
+
+#times { num-num: 7; num-col: #7496b8; col-num: #092345; col-col: #243648; }
+
+#div { num-num: 3.33333; num-num2: 3.33333; col-num: #092345; col-col: #0b0d0f; comp: 1px; }
+
+#mod { num-num: 2; col-col: #0f0e05; col-num: #020001; }
+
+#const { escaped-quote: \$foo \!bar; default: Hello\! !important; }
+
+#regression { a: 4; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/scss_import.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/scss_import.css
new file mode 100644
index 0000000..87ae3c8
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/scss_import.css
@@ -0,0 +1,31 @@
+ import url(basic.css);
+ import url(../results/complex.css);
+imported { otherconst: hello; myconst: goodbye; pre-mixin: here; }
+
+body { font: Arial; background: blue; }
+
+#page { width: 700px; height: 100; }
+#page #header { height: 300px; }
+#page #header h1 { font-size: 50px; color: blue; }
+
+#content.user.show #container.top #column.left { width: 100px; }
+#content.user.show #container.top #column.right { width: 600px; }
+#content.user.show #container.bottom { background: brown; }
+
+midrule { inthe: middle; }
+
+scss { imported: yes; }
+
+body { font: Arial; background: blue; }
+
+#page { width: 700px; height: 100; }
+#page #header { height: 300px; }
+#page #header h1 { font-size: 50px; color: blue; }
+
+#content.user.show #container.top #column.left { width: 100px; }
+#content.user.show #container.top #column.right { width: 600px; }
+#content.user.show #container.bottom { background: brown; }
+
+#foo { background-color: #bbaaff; }
+
+nonimported { myconst: hello; otherconst: goodbye; post-mixin: here; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/scss_importee.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/scss_importee.css
new file mode 100644
index 0000000..c9fcf41
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/scss_importee.css
@@ -0,0 +1,2 @@
+scss {
+  imported: yes; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/subdir/nested_subdir/nested_subdir.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/subdir/nested_subdir/nested_subdir.css
new file mode 100644
index 0000000..7aadcfe
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/subdir/nested_subdir/nested_subdir.css
@@ -0,0 +1 @@
+#pi { width: 314px; }
\ No newline at end of file
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/subdir/subdir.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/subdir/subdir.css
new file mode 100644
index 0000000..e404728
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/subdir/subdir.css
@@ -0,0 +1,3 @@
+#nested { relative: true; }
+
+#subdir { font-size: 20px; font-weight: bold; }
\ No newline at end of file
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/units.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/units.css
new file mode 100644
index 0000000..affb36c
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/results/units.css
@@ -0,0 +1,11 @@
+b {
+  foo: 5px;
+  bar: 24px;
+  baz: 66.66667%;
+  many-units: 32em;
+  mm: 15mm;
+  pc: 2pc;
+  pt: -72pt;
+  inches: 2in;
+  more-inches: 3.5in;
+  mixed: 2.04167in; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/warn.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/warn.css
new file mode 100644
index 0000000..e69de29
diff --git a/backends/css/gems/sass-3.2.12/test/sass/results/warn_imported.css 
b/backends/css/gems/sass-3.2.12/test/sass/results/warn_imported.css
new file mode 100644
index 0000000..e69de29
diff --git a/backends/css/gems/sass-3.2.12/test/sass/script_conversion_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/script_conversion_test.rb
new file mode 100755
index 0000000..31538eb
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/script_conversion_test.rb
@@ -0,0 +1,299 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+require File.dirname(__FILE__) + '/../test_helper'
+require 'sass/engine'
+
+class SassScriptConversionTest < Test::Unit::TestCase
+  def test_bool
+    assert_renders "true"
+    assert_renders "false"
+  end
+
+  def test_color
+    assert_renders "#abcdef"
+    assert_renders "blue"
+    assert_renders "rgba(0, 1, 2, 0.2)"
+
+    assert_equal "#aabbcc", render("#abc")
+    assert_equal "blue", render("#0000ff")
+  end
+
+  def test_number
+    assert_renders "10"
+    assert_renders "10.35"
+    assert_renders "12px"
+    assert_renders "12.45px"
+
+    assert_equal "12.34568", render("12.345678901")
+  end
+
+  def test_string
+    assert_renders '"foo"'
+    assert_renders '"bar baz"'
+    assert_equal '"baz bang"', render("'baz bang'")
+  end
+
+  def test_string_quotes
+    assert_equal "'quote\"quote'", render('"quote\\"quote"')
+    assert_equal '"quote\'quote"', render("'quote\\'quote'")
+    assert_renders '"quote\'quote\\"quote"'
+    assert_equal '"quote\'quote\\"quote"', render("'quote\\'quote\"quote'")
+  end
+
+  def test_string_escapes
+    assert_renders '"foo\\\\bar"'
+  end
+
+  def test_funcall
+    assert_renders "foo(true, blue)"
+    assert_renders "hsla(20deg, 30%, 50%, 0.3)"
+    assert_renders "blam()"
+
+    assert_renders "-\xC3\xBFoo(12px)"
+    assert_renders "-foo(12px)"
+  end
+
+  def test_funcall_with_keyword_args
+    assert_renders "foo(arg1, arg2, $karg1: val, $karg2: val2)"
+    assert_renders "foo($karg1: val, $karg2: val2)"
+  end
+
+  def test_url
+    assert_renders "url(foo.gif)"
+    assert_renders "url($var)"
+    assert_renders "url(\#{$var}/flip.gif)"
+  end
+
+  def test_variable
+    assert_renders "$foo-bar"
+    assert_renders "$flaznicate"
+  end
+
+  def test_null
+    assert_renders "null"
+  end
+
+  def test_empty_list
+    assert_renders "()"
+  end
+
+  def test_list_in_args
+    assert_renders "foo((a, b, c))"
+    assert_renders "foo($arg: (a, b, c))"
+    assert_renders "foo(a, b, (a, b, c)...)"
+  end
+
+  def self.test_precedence(outer, inner)
+    op_outer = Sass::Script::Lexer::OPERATORS_REVERSE[outer]
+    op_inner = Sass::Script::Lexer::OPERATORS_REVERSE[inner]
+    class_eval <<RUBY
+      def test_precedence_#{outer}_#{inner} 
+        assert_renders "$foo #{op_outer} $bar #{op_inner} $baz"
+        assert_renders "$foo #{op_inner} $bar #{op_outer} $baz"
+
+        assert_renders "($foo #{op_outer} $bar) #{op_inner} $baz"
+        assert_renders "$foo #{op_inner} ($bar #{op_outer} $baz)"
+
+        assert_equal "$foo #{op_outer} $bar #{op_inner} $baz",
+          render("$foo #{op_outer} ($bar #{op_inner} $baz)")
+        assert_equal "$foo #{op_inner} $bar #{op_outer} $baz",
+          render("($foo #{op_inner} $bar) #{op_outer} $baz")
+      end
+RUBY
+  end
+
+  def self.assert_associative(op_name, sibling_name)
+    op = separator_for(op_name)
+    sibling = separator_for(sibling_name)
+    class_eval <<RUBY
+      def test_associative_#{op_name}_#{sibling_name} 
+        assert_renders "$foo#{op}$bar#{op}$baz"
+
+        assert_equal "$foo#{op}$bar#{op}$baz",
+          render("$foo#{op}($bar#{op}$baz)")
+        assert_equal "$foo#{op}$bar#{op}$baz",
+          render("($foo#{op}$bar)#{op}$baz")
+
+        assert_equal "$foo#{op}$bar#{sibling}$baz",
+          render("$foo#{op}($bar#{sibling}$baz)")
+        assert_equal "$foo#{sibling}$bar#{op}$baz",
+          render("($foo#{sibling}$bar)#{op}$baz")
+      end
+RUBY
+  end
+
+  def self.separator_for(op_name)
+    case op_name
+    when :comma; ", "
+    when :space; " "
+    else; " #{Sass::Script::Lexer::OPERATORS_REVERSE[op_name]} "
+    end
+  end
+
+  def self.assert_non_associative(op_name, sibling_name)
+    op = Sass::Script::Lexer::OPERATORS_REVERSE[op_name]
+    sibling = Sass::Script::Lexer::OPERATORS_REVERSE[sibling_name]
+    class_eval <<RUBY
+      def test_non_associative_#{op_name}_#{sibling_name} 
+        assert_renders "$foo #{op} $bar #{op} $baz"
+
+        assert_renders "$foo #{op} ($bar #{op} $baz)"
+        assert_equal "$foo #{op} $bar #{op} $baz",
+          render("($foo #{op} $bar) #{op} $baz")
+
+        assert_renders "$foo #{op} ($bar #{sibling} $baz)"
+        assert_equal "$foo #{sibling} $bar #{op} $baz",
+          render("($foo #{sibling} $bar) #{op} $baz")
+      end
+RUBY
+  end
+
+  test_precedence :or, :and
+  test_precedence :and, :eq
+  test_precedence :and, :neq
+  test_precedence :eq, :gt
+  test_precedence :eq, :gte
+  test_precedence :eq, :lt
+  test_precedence :eq, :lte
+  test_precedence :gt, :plus
+  test_precedence :gt, :minus
+  test_precedence :plus, :times
+  test_precedence :plus, :div
+  test_precedence :plus, :mod
+
+  assert_associative :plus, :minus
+  assert_associative :times, :div
+  assert_associative :times, :mod
+
+  assert_non_associative :minus, :plus
+  assert_non_associative :div, :times
+  assert_non_associative :mod, :times
+  assert_non_associative :gt, :gte
+  assert_non_associative :gte, :lt
+  assert_non_associative :lt, :lte
+  assert_non_associative :lte, :gt
+
+  def test_comma_precedence
+    assert_renders "$foo, $bar, $baz"
+
+    assert_renders "$foo ($bar, $baz)"
+    assert_renders "($foo, $bar) $baz"
+
+    assert_equal "$foo, $bar $baz", render("$foo, ($bar $baz)")
+    assert_equal "$foo $bar, $baz", render("($foo $bar), $baz")
+
+    assert_equal "$foo, ($bar, $baz)", render("$foo, ($bar, $baz)")
+    assert_equal "($foo, $bar), $baz", render("($foo, $bar), $baz")
+  end
+
+  def test_space_precedence
+    assert_renders "$foo $bar $baz"
+
+    assert_renders "$foo or ($bar $baz)"
+    assert_renders "($foo $bar) or $baz"
+
+    assert_equal "$foo $bar or $baz", render("$foo ($bar or $baz)")
+    assert_equal "$foo or $bar $baz", render("($foo or $bar) $baz")
+
+    assert_equal "$foo ($bar $baz)", render("$foo ($bar $baz)")
+    assert_equal "($foo $bar) $baz", render("($foo $bar) $baz")
+  end
+
+  def test_unary_op
+    assert_renders "-12px"
+    assert_renders '/"foo"'
+    assert_renders 'not true'
+
+    assert_renders "-(foo(12px))"
+    assert_renders "-(-foo(12px))"
+    assert_renders "-(_foo(12px))"
+    assert_renders "-(\xC3\xBFoo(12px))"
+    assert_renders "-(blue)"
+
+    assert_equal 'not true or false', render('(not true) or false')
+    assert_equal 'not (true or false)', render('not (true or false)')
+  end
+
+  def test_interpolation
+    assert_renders "$foo\#{$bar}$baz"
+    assert_renders "$foo\#{$bar} $baz"
+    assert_renders "$foo \#{$bar}$baz"
+    assert_renders "$foo \#{$bar} $baz"
+    assert_renders "$foo \#{$bar}\#{$bang} $baz"
+    assert_renders "$foo \#{$bar} \#{$bang} $baz"
+    assert_renders "\#{$bar}$baz"
+    assert_renders "$foo\#{$bar}"
+    assert_renders "\#{$bar}"
+  end
+
+  def test_interpolation_in_function
+    assert_renders 'flabnabbit(#{1 + "foo"})'
+    assert_renders 'flabnabbit($foo #{1 + "foo"}$baz)'
+    assert_renders 'flabnabbit($foo #{1 + "foo"}#{2 + "bar"} $baz)'
+  end
+
+  def test_interpolation_near_operators
+    assert_renders '#{1 + 2} , #{3 + 4}'
+    assert_renders '#{1 + 2}, #{3 + 4}'
+    assert_renders '#{1 + 2} ,#{3 + 4}'
+    assert_renders '#{1 + 2},#{3 + 4}'
+    assert_renders '#{1 + 2}, #{3 + 4}, #{5 + 6}'
+    assert_renders '3, #{3 + 4}, 11'
+
+    assert_renders '3 / #{3 + 4}'
+    assert_renders '3 /#{3 + 4}'
+    assert_renders '3/ #{3 + 4}'
+    assert_renders '3/#{3 + 4}'
+
+    assert_renders '#{1 + 2} * 7'
+    assert_renders '#{1 + 2}* 7'
+    assert_renders '#{1 + 2} *7'
+    assert_renders '#{1 + 2}*7'
+
+    assert_renders '-#{1 + 2}'
+    assert_renders '- #{1 + 2}'
+
+    assert_renders '5 + #{1 + 2} * #{3 + 4}'
+    assert_renders '5 +#{1 + 2} * #{3 + 4}'
+    assert_renders '5+#{1 + 2} * #{3 + 4}'
+    assert_renders '#{1 + 2} * #{3 + 4} + 5'
+    assert_renders '#{1 + 2} * #{3 + 4}+ 5'
+    assert_renders '#{1 + 2} * #{3 + 4}+5'
+
+    assert_equal '5 / #{1 + 2} + #{3 + 4}', render('5 / (#{1 + 2} + #{3 + 4})')
+    assert_equal '5 / #{1 + 2} + #{3 + 4}', render('5 /(#{1 + 2} + #{3 + 4})')
+    assert_equal '5 / #{1 + 2} + #{3 + 4}', render('5 /( #{1 + 2} + #{3 + 4} )')
+    assert_equal '#{1 + 2} + #{3 + 4} / 5', render('(#{1 + 2} + #{3 + 4}) / 5')
+    assert_equal '#{1 + 2} + #{3 + 4} / 5', render('(#{1 + 2} + #{3 + 4})/ 5')
+    assert_equal '#{1 + 2} + #{3 + 4} / 5', render('( #{1 + 2} + #{3 + 4} )/ 5')
+
+    assert_renders '#{1 + 2} + 2 + 3'
+    assert_renders '#{1 + 2} +2 + 3'
+  end
+
+  def test_string_interpolation
+    assert_renders '"foo#{$bar}baz"'
+    assert_renders '"foo #{$bar}baz"'
+    assert_renders '"foo#{$bar} baz"'
+    assert_renders '"foo #{$bar} baz"'
+    assert_renders '"foo #{$bar}#{$bang} baz"'
+    assert_renders '"foo #{$bar} #{$bang} baz"'
+    assert_renders '"#{$bar}baz"'
+    assert_renders '"foo#{$bar}"'
+    assert_equal '#{$bar}', render('"#{$bar}"')
+
+    assert_equal '"foo#{$bar}baz"', render("'foo\#{$bar}baz'")
+  end
+
+  private
+
+  def assert_renders(script, options = {})
+    assert_equal(script, render(script, options))
+  end
+
+  def render(script, options = {})
+    munge_filename(options)
+    node = Sass::Script.parse(script, 1, 0, options)
+    node.to_sass
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/script_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/script_test.rb
new file mode 100755
index 0000000..0730b90
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/script_test.rb
@@ -0,0 +1,591 @@
+#!/usr/bin/env ruby
+require File.dirname(__FILE__) + '/../test_helper'
+require 'sass/engine'
+
+module Sass::Script::Functions::UserFunctions
+  def assert_options(val)
+    val.options[:foo]
+    Sass::Script::String.new("Options defined!")
+  end
+
+  def arg_error
+    assert_options
+  end
+end
+
+module Sass::Script::Functions
+  include Sass::Script::Functions::UserFunctions
+end
+
+class SassScriptTest < Test::Unit::TestCase
+  include Sass::Script
+
+  def test_color_checks_input
+    assert_raise_message(ArgumentError, "Blue value -1 must be between 0 and 255") {Color.new([1, 2, -1])}
+    assert_raise_message(ArgumentError, "Red value 256 must be between 0 and 255") {Color.new([256, 2, 3])}
+  end
+
+  def test_color_checks_rgba_input
+    assert_raise_message(ArgumentError, "Alpha channel 1.1 must be between 0 and 1") {Color.new([1, 2, 3, 
1.1])}
+    assert_raise_message(ArgumentError, "Alpha channel -0.1 must be between 0 and 1") {Color.new([1, 2, 3, 
-0.1])}
+  end
+
+  def test_string_escapes
+    assert_equal "'", resolve("\"'\"")
+    assert_equal '"', resolve("\"\\\"\"")
+    assert_equal "\\\\", resolve("\"\\\\\"")
+    assert_equal "\\02fa", resolve("\"\\02fa\"")
+
+    assert_equal "'", resolve("'\\''")
+    assert_equal '"', resolve("'\"'")
+    assert_equal "\\\\", resolve("'\\\\'")
+    assert_equal "\\02fa", resolve("'\\02fa'")
+  end
+
+  def test_color_names
+    assert_equal "white", resolve("white")
+    assert_equal "white", resolve("#ffffff")
+    assert_equal "#fffffe", resolve("white - #000001")
+  end
+
+  def test_rgba_color_literals
+    assert_equal Sass::Script::Color.new([1, 2, 3, 0.75]), eval("rgba(1, 2, 3, 0.75)")
+    assert_equal "rgba(1, 2, 3, 0.75)", resolve("rgba(1, 2, 3, 0.75)")
+
+    assert_equal Sass::Script::Color.new([1, 2, 3, 0]), eval("rgba(1, 2, 3, 0)")
+    assert_equal "rgba(1, 2, 3, 0)", resolve("rgba(1, 2, 3, 0)")
+
+    assert_equal Sass::Script::Color.new([1, 2, 3]), eval("rgba(1, 2, 3, 1)")
+    assert_equal Sass::Script::Color.new([1, 2, 3, 1]), eval("rgba(1, 2, 3, 1)")
+    assert_equal "#010203", resolve("rgba(1, 2, 3, 1)")
+    assert_equal "white", resolve("rgba(255, 255, 255, 1)")
+  end
+
+  def test_rgba_color_math
+    assert_equal "rgba(50, 50, 100, 0.35)", resolve("rgba(1, 1, 2, 0.35) * rgba(50, 50, 50, 0.35)")
+    assert_equal "rgba(52, 52, 52, 0.25)", resolve("rgba(2, 2, 2, 0.25) + rgba(50, 50, 50, 0.25)")
+
+    assert_raise_message(Sass::SyntaxError, "Alpha channels must be equal: rgba(1, 2, 3, 0.15) + rgba(50, 
50, 50, 0.75)") do
+      resolve("rgba(1, 2, 3, 0.15) + rgba(50, 50, 50, 0.75)")
+    end
+    assert_raise_message(Sass::SyntaxError, "Alpha channels must be equal: #123456 * rgba(50, 50, 50, 
0.75)") do
+      resolve("#123456 * rgba(50, 50, 50, 0.75)")
+    end
+    assert_raise_message(Sass::SyntaxError, "Alpha channels must be equal: rgba(50, 50, 50, 0.75) / 
#123456") do
+      resolve("rgba(50, 50, 50, 0.75) / #123456")
+    end
+  end
+
+  def test_rgba_number_math
+    assert_equal "rgba(49, 49, 49, 0.75)", resolve("rgba(50, 50, 50, 0.75) - 1")
+    assert_equal "rgba(100, 100, 100, 0.75)", resolve("rgba(50, 50, 50, 0.75) * 2")
+  end
+
+  def test_rgba_rounding
+    assert_equal "rgba(10, 1, 0, 0.12346)", resolve("rgba(10.0, 1.23456789, 0.0, 0.1234567)")
+  end
+
+  def test_compressed_colors
+    assert_equal "#123456", resolve("#123456", :style => :compressed)
+    assert_equal "rgba(1,2,3,0.5)", resolve("rgba(1, 2, 3, 0.5)", :style => :compressed)
+    assert_equal "#123", resolve("#112233", :style => :compressed)
+    assert_equal "#000", resolve("black", :style => :compressed)
+    assert_equal "red", resolve("#f00", :style => :compressed)
+    assert_equal "blue", resolve("#00f", :style => :compressed)
+    assert_equal "navy", resolve("#000080", :style => :compressed)
+    assert_equal "navy #fff", resolve("#000080 white", :style => :compressed)
+    assert_equal "This color is #fff", resolve('"This color is #{ white }"', :style => :compressed)
+  end
+
+  def test_compressed_comma
+    # assert_equal "foo,bar,baz", resolve("foo, bar, baz", :style => :compressed)
+    # assert_equal "foo,#baf,baz", resolve("foo, #baf, baz", :style => :compressed)
+    assert_equal "foo,#baf,red", resolve("foo, #baf, #f00", :style => :compressed)
+  end
+
+  def test_implicit_strings
+    assert_equal Sass::Script::String.new("foo"), eval("foo")
+    assert_equal Sass::Script::String.new("foo/bar"), eval("foo/bar")
+  end
+
+  def test_basic_interpolation
+    assert_equal "foo3bar", resolve("foo\#{1 + 2}bar")
+    assert_equal "foo3 bar", resolve("foo\#{1 + 2} bar")
+    assert_equal "foo 3bar", resolve("foo \#{1 + 2}bar")
+    assert_equal "foo 3 bar", resolve("foo \#{1 + 2} bar")
+    assert_equal "foo 35 bar", resolve("foo \#{1 + 2}\#{2 + 3} bar")
+    assert_equal "foo 3 5 bar", resolve("foo \#{1 + 2} \#{2 + 3} bar")
+    assert_equal "3bar", resolve("\#{1 + 2}bar")
+    assert_equal "foo3", resolve("foo\#{1 + 2}")
+    assert_equal "3", resolve("\#{1 + 2}")
+  end
+
+  def test_interpolation_in_function
+    assert_equal 'flabnabbit(1foo)', resolve('flabnabbit(#{1 + "foo"})')
+    assert_equal 'flabnabbit(foo 1foobaz)', resolve('flabnabbit(foo #{1 + "foo"}baz)')
+    assert_equal('flabnabbit(foo 1foo2bar baz)',
+      resolve('flabnabbit(foo #{1 + "foo"}#{2 + "bar"} baz)'))
+  end
+
+  def test_interpolation_near_operators
+    assert_equal '3 , 7', resolve('#{1 + 2} , #{3 + 4}')
+    assert_equal '3, 7', resolve('#{1 + 2}, #{3 + 4}')
+    assert_equal '3 ,7', resolve('#{1 + 2} ,#{3 + 4}')
+    assert_equal '3,7', resolve('#{1 + 2},#{3 + 4}')
+    assert_equal '3, 7, 11', resolve('#{1 + 2}, #{3 + 4}, #{5 + 6}')
+    assert_equal '3, 7, 11', resolve('3, #{3 + 4}, 11')
+    assert_equal '3, 7, 11', resolve('3, 7, #{5 + 6}')
+
+    assert_equal '3 / 7', resolve('3 / #{3 + 4}')
+    assert_equal '3 /7', resolve('3 /#{3 + 4}')
+    assert_equal '3/ 7', resolve('3/ #{3 + 4}')
+    assert_equal '3/7', resolve('3/#{3 + 4}')
+
+    assert_equal '3 * 7', resolve('#{1 + 2} * 7')
+    assert_equal '3* 7', resolve('#{1 + 2}* 7')
+    assert_equal '3 *7', resolve('#{1 + 2} *7')
+    assert_equal '3*7', resolve('#{1 + 2}*7')
+
+    assert_equal '-3', resolve('-#{1 + 2}')
+    assert_equal '- 3', resolve('- #{1 + 2}')
+
+    assert_equal '5 + 3 * 7', resolve('5 + #{1 + 2} * #{3 + 4}')
+    assert_equal '5 +3 * 7', resolve('5 +#{1 + 2} * #{3 + 4}')
+    assert_equal '5+3 * 7', resolve('5+#{1 + 2} * #{3 + 4}')
+    assert_equal '3 * 7 + 5', resolve('#{1 + 2} * #{3 + 4} + 5')
+    assert_equal '3 * 7+ 5', resolve('#{1 + 2} * #{3 + 4}+ 5')
+    assert_equal '3 * 7+5', resolve('#{1 + 2} * #{3 + 4}+5')
+
+    assert_equal '5/3 + 7', resolve('5 / (#{1 + 2} + #{3 + 4})')
+    assert_equal '5/3 + 7', resolve('5 /(#{1 + 2} + #{3 + 4})')
+    assert_equal '5/3 + 7', resolve('5 /( #{1 + 2} + #{3 + 4} )')
+    assert_equal '3 + 7/5', resolve('(#{1 + 2} + #{3 + 4}) / 5')
+    assert_equal '3 + 7/5', resolve('(#{1 + 2} + #{3 + 4})/ 5')
+    assert_equal '3 + 7/5', resolve('( #{1 + 2} + #{3 + 4} )/ 5')
+
+    assert_equal '3 + 5', resolve('#{1 + 2} + 2 + 3')
+    assert_equal '3 +5', resolve('#{1 + 2} +2 + 3')
+  end
+
+  def test_string_interpolation
+    assert_equal "foo bar, baz bang", resolve('"foo #{"bar"}, #{"baz"} bang"')
+    assert_equal "foo bar baz bang", resolve('"foo #{"#{"ba" + "r"} baz"} bang"')
+    assert_equal 'foo #{bar baz} bang', resolve('"foo \#{#{"ba" + "r"} baz} bang"')
+    assert_equal 'foo #{baz bang', resolve('"foo #{"\#{" + "baz"} bang"')
+    assert_equal "foo2bar", resolve('\'foo#{1 + 1}bar\'')
+    assert_equal "foo2bar", resolve('"foo#{1 + 1}bar"')
+    assert_equal "foo1bar5baz4bang", resolve('\'foo#{1 + "bar#{2 + 3}baz" + 4}bang\'')
+  end
+
+  def test_rule_interpolation
+    assert_equal(<<CSS, render(<<SASS))
+foo bar baz bang {
+  a: b; }
+CSS
+foo \#{"\#{"ba" + "r"} baz"} bang
+  a: b
+SASS
+    assert_equal(<<CSS, render(<<SASS))
+foo [bar="\#{bar baz}"] bang {
+  a: b; }
+CSS
+foo [bar="\\\#{\#{"ba" + "r"} baz}"] bang
+  a: b
+SASS
+    assert_equal(<<CSS, render(<<SASS))
+foo [bar="\#{baz"] bang {
+  a: b; }
+CSS
+foo [bar="\#{"\\\#{" + "baz"}"] bang
+  a: b
+SASS
+  end
+
+  def test_inaccessible_functions
+    assert_equal "send(to_s)", resolve("send(to_s)", :line => 2)
+    assert_equal "public_instance_methods()", resolve("public_instance_methods()")
+  end
+
+  def test_adding_functions_directly_to_functions_module
+    assert !Functions.callable?('nonexistant')
+    Functions.class_eval { def nonexistant; end }
+    assert Functions.callable?('nonexistant')
+    Functions.send :remove_method, :nonexistant
+  end
+
+  def test_default_functions
+    assert_equal "url(12)", resolve("url(12)")
+    assert_equal 'blam("foo")', resolve('blam("foo")')
+  end
+
+  def test_function_results_have_options
+    assert_equal "Options defined!", resolve("assert_options(abs(1))")
+    assert_equal "Options defined!", resolve("assert_options(round(1.2))")
+  end
+
+  def test_funcall_requires_no_whitespace_before_lparen
+    assert_equal "no-repeat 15px", resolve("no-repeat (7px + 8px)")
+    assert_equal "no-repeat(15px)", resolve("no-repeat(7px + 8px)")
+  end
+
+  def test_dynamic_url
+    assert_equal "url(foo-bar)", resolve("url($foo)", {}, env('foo' => Sass::Script::String.new("foo-bar")))
+    assert_equal "url(foo-bar baz)", resolve("url($foo $bar)", {}, env('foo' => 
Sass::Script::String.new("foo-bar"), 'bar' => Sass::Script::String.new("baz")))
+    assert_equal "url(foo baz)", resolve("url(foo $bar)", {}, env('bar' => Sass::Script::String.new("baz")))
+    assert_equal "url(foo bar)", resolve("url(foo    bar)")
+  end
+
+  def test_url_with_interpolation
+    assert_equal "url(http://sass-lang.com/images/foo-bar)", 
resolve("url(http://sass-lang.com/images/\#{foo-bar})")
+    assert_equal 'url("http://sass-lang.com/images/foo-bar";)', 
resolve("url('http://sass-lang.com/images/\#{foo-bar}')")
+    assert_equal 'url("http://sass-lang.com/images/foo-bar";)', 
resolve('url("http://sass-lang.com/images/#{foo-bar}";)')
+    assert_unquoted "url(http://sass-lang.com/images/\#{foo-bar})"
+  end
+
+  def test_hyphenated_variables
+    assert_equal("a-b", resolve("$a-b", {}, env("a-b" => Sass::Script::String.new("a-b"))))
+  end
+
+  def test_ruby_equality
+    assert_equal eval('"foo"'), eval('"foo"')
+    assert_equal eval('1'), eval('1.0')
+    assert_equal eval('1 2 3.0'), eval('1 2 3')
+    assert_equal eval('1, 2, 3.0'), eval('1, 2, 3')
+    assert_equal eval('(1 2), (3, 4), (5 6)'), eval('(1 2), (3, 4), (5 6)')
+    assert_not_equal eval('1, 2, 3'), eval('1 2 3')
+    assert_not_equal eval('1'), eval('"1"')
+  end
+
+  def test_booleans
+    assert_equal "true", resolve("true")
+    assert_equal "false", resolve("false")
+  end
+
+  def test_null
+    assert_equal "", resolve("null")
+  end
+
+  def test_boolean_ops
+    assert_equal "true", resolve("true and true")
+    assert_equal "true", resolve("false or true")
+    assert_equal "true", resolve("true or false")
+    assert_equal "true", resolve("true or true")
+    assert_equal "false", resolve("false or false")
+    assert_equal "false", resolve("false and true")
+    assert_equal "false", resolve("true and false")
+    assert_equal "false", resolve("false and false")
+
+    assert_equal "true", resolve("not false")
+    assert_equal "false", resolve("not true")
+    assert_equal "true", resolve("not not true")
+
+    assert_equal "1", resolve("false or 1")
+    assert_equal "false", resolve("false and 1")
+    assert_equal "2", resolve("2 or 3")
+    assert_equal "3", resolve("2 and 3")
+
+    assert_equal "true", resolve("null or true")
+    assert_equal "true", resolve("true or null")
+    assert_equal "", resolve("null or null")
+    assert_equal "", resolve("null and true")
+    assert_equal "", resolve("true and null")
+    assert_equal "", resolve("null and null")
+
+    assert_equal "true", resolve("not null")
+
+    assert_equal "1", resolve("null or 1")
+    assert_equal "", resolve("null and 1")
+  end
+
+  def test_arithmetic_ops
+    assert_equal "2", resolve("1 + 1")
+    assert_equal "0", resolve("1 - 1")
+    assert_equal "8", resolve("2 * 4")
+    assert_equal "0.5", resolve("(2 / 4)")
+    assert_equal "2", resolve("(4 / 2)")
+
+    assert_equal "-1", resolve("-1")
+  end
+
+  def test_string_ops
+    assert_equal '"foo" "bar"', resolve('"foo" "bar"')
+    assert_equal "true 1", resolve('true 1')
+    assert_equal '"foo", "bar"', resolve("'foo' , 'bar'")
+    assert_equal "true, 1", resolve('true , 1')
+    assert_equal "foobar", resolve('"foo" + "bar"')
+    assert_equal "true1", resolve('true + 1')
+    assert_equal '"foo"-"bar"', resolve("'foo' - 'bar'")
+    assert_equal "true-1", resolve('true - 1')
+    assert_equal '"foo"/"bar"', resolve('"foo" / "bar"')
+    assert_equal "true/1", resolve('true / 1')
+
+    assert_equal '-"bar"', resolve("- 'bar'")
+    assert_equal "-true", resolve('- true')
+    assert_equal '/"bar"', resolve('/ "bar"')
+    assert_equal "/true", resolve('/ true')
+  end
+
+  def test_relational_ops
+    assert_equal "false", resolve("1 > 2")
+    assert_equal "false", resolve("2 > 2")
+    assert_equal "true", resolve("3 > 2")
+    assert_equal "false", resolve("1 >= 2")
+    assert_equal "true", resolve("2 >= 2")
+    assert_equal "true", resolve("3 >= 2")
+    assert_equal "true", resolve("1 < 2")
+    assert_equal "false", resolve("2 < 2")
+    assert_equal "false", resolve("3 < 2")
+    assert_equal "true", resolve("1 <= 2")
+    assert_equal "true", resolve("2 <= 2")
+    assert_equal "false", resolve("3 <= 2")
+  end
+
+  def test_null_ops
+    assert_raise_message(Sass::SyntaxError,
+      'Invalid null operation: "null plus 1".') {eval("null + 1")}
+    assert_raise_message(Sass::SyntaxError,
+      'Invalid null operation: "null minus 1".') {eval("null - 1")}
+    assert_raise_message(Sass::SyntaxError,
+      'Invalid null operation: "null times 1".') {eval("null * 1")}
+    assert_raise_message(Sass::SyntaxError,
+      'Invalid null operation: "null div 1".') {eval("null / 1")}
+    assert_raise_message(Sass::SyntaxError,
+      'Invalid null operation: "null mod 1".') {eval("null % 1")}
+    assert_raise_message(Sass::SyntaxError,
+      'Invalid null operation: "1 plus null".') {eval("1 + null")}
+    assert_raise_message(Sass::SyntaxError,
+      'Invalid null operation: "1 minus null".') {eval("1 - null")}
+    assert_raise_message(Sass::SyntaxError,
+      'Invalid null operation: "1 times null".') {eval("1 * null")}
+    assert_raise_message(Sass::SyntaxError,
+      'Invalid null operation: "1 div null".') {eval("1 / null")}
+    assert_raise_message(Sass::SyntaxError,
+      'Invalid null operation: "1 mod null".') {eval("1 % null")}
+    assert_raise_message(Sass::SyntaxError,
+      'Invalid null operation: "1 gt null".') {eval("1 > null")}
+    assert_raise_message(Sass::SyntaxError,
+      'Invalid null operation: "null lt 1".') {eval("null < 1")}
+    assert_raise_message(Sass::SyntaxError,
+      'Invalid null operation: "null plus null".') {eval("null + null")}
+    assert_raise_message(Sass::SyntaxError,
+      'Invalid null operation: ""foo" plus null".') {eval("foo + null")}
+  end
+
+  def test_equals
+    assert_equal("true", resolve('"foo" == $foo', {},
+        env("foo" => Sass::Script::String.new("foo"))))
+    assert_equal "true", resolve("1 == 1.0")
+    assert_equal "true", resolve("false != true")
+    assert_equal "false", resolve("1em == 1px")
+    assert_equal "false", resolve("12 != 12")
+    assert_equal "true", resolve("(foo bar baz) == (foo bar baz)")
+    assert_equal "true", resolve("(foo, bar, baz) == (foo, bar, baz)")
+    assert_equal "true", resolve('((1 2), (3, 4), (5 6)) == ((1 2), (3, 4), (5 6))')
+    assert_equal "true", resolve('((1 2), (3 4)) == (1 2, 3 4)')
+    assert_equal "false", resolve('((1 2) 3) == (1 2 3)')
+    assert_equal "false", resolve('(1 (2 3)) == (1 2 3)')
+    assert_equal "false", resolve('((1, 2) (3, 4)) == (1, 2 3, 4)')
+    assert_equal "false", resolve('(1 2 3) == (1, 2, 3)')
+
+    assert_equal "true", resolve('null == null')
+    assert_equal "false", resolve('"null" == null')
+    assert_equal "false", resolve('0 == null')
+    assert_equal "false", resolve('() == null')
+
+    assert_equal "false", resolve('null != null')
+    assert_equal "true", resolve('"null" != null')
+    assert_equal "true", resolve('0 != null')
+    assert_equal "true", resolve('() != null')
+  end
+
+  def test_operation_precedence
+    assert_equal "false true", resolve("true and false false or true")
+    assert_equal "true", resolve("false and true or true and true")
+    assert_equal "true", resolve("1 == 2 or 3 == 3")
+    assert_equal "true", resolve("1 < 2 == 3 >= 3")
+    assert_equal "true", resolve("1 + 3 > 4 - 2")
+    assert_equal "11", resolve("1 + 2 * 3 + 4")
+  end
+
+  def test_functions
+    assert_equal "#80ff80", resolve("hsl(120, 100%, 75%)")
+    assert_equal "#81ff81", resolve("hsl(120, 100%, 75%) + #010001")
+  end
+
+  def test_operator_unit_conversion
+    assert_equal "1.1cm", resolve("1cm + 1mm")
+    assert_equal "2in", resolve("1in + 96px")
+    assert_equal "true", resolve("2mm < 1cm")
+    assert_equal "true", resolve("10mm == 1cm")
+    assert_equal "true", resolve("1 == 1cm")
+    assert_equal "true", resolve("1.1cm == 11mm")
+  end
+
+  def test_operations_have_options
+    assert_equal "Options defined!", resolve("assert_options(1 + 1)")
+    assert_equal "Options defined!", resolve("assert_options('bar' + 'baz')")
+  end
+
+  def test_slash_compiles_literally_when_left_alone
+    assert_equal "1px/2px", resolve("1px/2px")
+    assert_equal "1px/2px/3px/4px", resolve("1px/2px/3px/4px")
+
+    assert_equal "1px/2px redpx bluepx", resolve("1px/2px redpx bluepx")
+    assert_equal "foo 1px/2px/3px bar", resolve("foo 1px/2px/3px bar")
+  end
+
+  def test_slash_divides_with_parens
+    assert_equal "0.5", resolve("(1px/2px)")
+    assert_equal "0.5", resolve("(1px)/2px")
+    assert_equal "0.5", resolve("1px/(2px)")
+  end
+
+  def test_slash_divides_with_other_arithmetic
+    assert_equal "0.5px", resolve("1px*1px/2px")
+    assert_equal "0.5px", resolve("1px/2px*1px")
+    assert_equal "0.5", resolve("0+1px/2px")
+    assert_equal "0.5", resolve("1px/2px+0")
+  end
+
+  def test_slash_divides_with_variable
+    assert_equal "0.5", resolve("$var/2px", {}, env("var" => eval("1px")))
+    assert_equal "0.5", resolve("1px/$var", {}, env("var" => eval("2px")))
+    assert_equal "0.5", resolve("$var", {}, env("var" => eval("1px/2px")))
+  end
+
+  def test_colors_with_wrong_number_of_digits
+    assert_raise_message(Sass::SyntaxError,
+      "Colors must have either three or six digits: '#0'") {eval("#0")}
+    assert_raise_message(Sass::SyntaxError,
+      "Colors must have either three or six digits: '#12'") {eval("#12")}
+    assert_raise_message(Sass::SyntaxError,
+      "Colors must have either three or six digits: '#abcd'") {eval("#abcd")}
+    assert_raise_message(Sass::SyntaxError,
+      "Colors must have either three or six digits: '#abcdE'") {eval("#abcdE")}
+    assert_raise_message(Sass::SyntaxError,
+      "Colors must have either three or six digits: '#abcdEFA'") {eval("#abcdEFA")}
+  end
+
+  def test_case_insensitive_color_names
+    assert_equal "blue", resolve("BLUE")
+    assert_equal "red", resolve("rEd")
+    assert_equal "#7f4000", resolve("mix(GrEeN, ReD)")
+  end
+
+  def test_empty_list
+    assert_equal "1 2 3", resolve("1 2 () 3")
+    assert_equal "1 2 3", resolve("1 2 3 ()")
+    assert_equal "1 2 3", resolve("() 1 2 3")
+    assert_raise_message(Sass::SyntaxError, "() isn't a valid CSS value.") {resolve("()")}
+    assert_raise_message(Sass::SyntaxError, "() isn't a valid CSS value.") {resolve("nth(append((), ()), 
1)")}
+  end
+
+  def test_list_with_nulls
+    assert_equal "1, 2, 3", resolve("1, 2, null, 3")
+    assert_equal "1 2 3", resolve("1 2 null 3")
+    assert_equal "1, 2, 3", resolve("1, 2, 3, null")
+    assert_equal "1 2 3", resolve("1 2 3 null")
+    assert_equal "1, 2, 3", resolve("null, 1, 2, 3")
+    assert_equal "1 2 3", resolve("null 1 2 3")
+  end
+
+  def test_deep_argument_error_not_unwrapped
+    # JRuby (as of 1.6.7.2) offers no way of distinguishing between
+    # argument errors caused by programming errors in a function and
+    # argument errors explicitly thrown within that function.
+    return if RUBY_PLATFORM =~ /java/
+
+    # Don't validate the message; it's different on Rubinius.
+    assert_raise(ArgumentError) {resolve("arg-error()")}
+  end
+
+  def test_shallow_argument_error_unwrapped
+    assert_raise_message(Sass::SyntaxError, "wrong number of arguments (1 for 0) for `arg-error'") 
{resolve("arg-error(1)")}
+  end
+
+  def test_boolean_ops_short_circuit
+    assert_equal "false", resolve("$ie and $ie <= 7", {}, env('ie' => Sass::Script::Bool.new(false)))
+    assert_equal "true", resolve("$ie or $undef", {}, env('ie' => Sass::Script::Bool.new(true)))
+  end
+
+  # Regression Tests
+
+  def test_funcall_has_higher_precedence_than_color_name
+    assert_equal "teal(12)", resolve("teal(12)")
+    assert_equal "tealbang(12)", resolve("tealbang(12)")
+    assert_equal "teal-bang(12)", resolve("teal-bang(12)")
+    assert_equal "teal\\+bang(12)", resolve("teal\\+bang(12)")
+  end
+
+  def test_interpolation_after_hash
+    assert_equal "#2", resolve('"##{1 + 1}"')
+  end
+
+  def test_misplaced_comma_in_funcall
+    assert_raise_message(Sass::SyntaxError,
+      'Invalid CSS after "foo(bar, ": expected function argument, was ")"') {eval('foo(bar, )')}
+  end
+
+  def test_color_prefixed_identifier
+    assert_equal "tealbang", resolve("tealbang")
+    assert_equal "teal-bang", resolve("teal-bang")
+  end
+
+  def test_op_prefixed_identifier
+    assert_equal "notbang", resolve("notbang")
+    assert_equal "not-bang", resolve("not-bang")
+    assert_equal "or-bang", resolve("or-bang")
+    assert_equal "and-bang", resolve("and-bang")
+  end
+
+  private
+
+  def resolve(str, opts = {}, environment = env)
+    munge_filename opts
+    val = eval(str, opts, environment)
+    assert_kind_of Sass::Script::Literal, val
+    val.is_a?(Sass::Script::String) ? val.value : val.to_s
+  end
+
+  def assert_unquoted(str, opts = {}, environment = env)
+    munge_filename opts
+    val = eval(str, opts, environment)
+    assert_kind_of Sass::Script::String, val
+    assert_equal :identifier, val.type
+  end
+
+  def assert_quoted(str, opts = {}, environment = env)
+    munge_filename opts
+    val = eval(str, opts, environment)
+    assert_kind_of Sass::Script::String, val
+    assert_equal :string, val.type
+  end
+
+  def eval(str, opts = {}, environment = env)
+    munge_filename opts
+    Sass::Script.parse(str, opts.delete(:line) || 1,
+      opts.delete(:offset) || 0, opts).
+      perform(Sass::Environment.new(environment, opts))
+  end
+
+  def render(sass, options = {})
+    munge_filename options
+    Sass::Engine.new(sass, options).render
+  end
+
+  def env(hash = {})
+    env = Sass::Environment.new
+    hash.each {|k, v| env.set_var(k, v)}
+    env
+  end
+
+  def test_number_printing
+    assert_equal "1", eval("1")
+    assert_equal "1", eval("1.0")
+    assert_equal "1.121", eval("1.1214")
+    assert_equal "1.122", eval("1.1215")
+    assert_equal "Infinity", eval("1.0/0.0")
+    assert_equal "-Infinity", eval("-1.0/0.0")
+    assert_equal "NaN", eval("0.0/0.0")
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/scss/css_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/scss/css_test.rb
new file mode 100755
index 0000000..79c43d9
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/scss/css_test.rb
@@ -0,0 +1,1093 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+require File.dirname(__FILE__) + '/test_helper'
+require 'sass/scss/css_parser'
+
+# These tests just test the parsing of CSS
+# (both standard and any hacks we intend to support).
+# Tests of SCSS-specific behavior go in scss_test.rb.
+class ScssCssTest < Test::Unit::TestCase
+  include ScssTestHelper
+
+  def test_basic_scss
+    assert_parses <<SCSS
+selector {
+  property: value;
+  property2: value; }
+SCSS
+
+    assert_equal <<CSS, render('sel{p:v}')
+sel {
+  p: v; }
+CSS
+  end
+
+  def test_empty_rule
+    assert_equal "", render("#foo .bar {}")
+    assert_equal "", render(<<SCSS)
+#foo .bar {
+}
+SCSS
+  end
+
+  def test_cdo_and_cdc_ignored_at_toplevel
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  bar: baz; }
+
+bar {
+  bar: baz; }
+
+baz {
+  bar: baz; }
+CSS
+foo {bar: baz}
+<!--
+bar {bar: baz}
+-->
+baz {bar: baz}
+SCSS
+  end
+
+  if Sass::Util.ruby1_8?
+    def test_unicode
+      assert_parses <<SCSS
+ charset "UTF-8";
+foo {
+  bar: föö bâr; }
+SCSS
+      assert_parses <<SCSS
+foo {
+  bar: föö bâr; }
+SCSS
+    end
+  else
+    def test_unicode
+      assert_parses <<SCSS
+ charset "UTF-8";
+foo {
+  bar: föö bâr; }
+SCSS
+      assert_equal <<CSS, render(<<SCSS)
+ charset "UTF-8";
+foo {
+  bar: föö bâr; }
+CSS
+foo {
+  bar: föö bâr; }
+SCSS
+    end
+  end
+
+  def test_invisible_comments
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: d; }
+CSS
+foo {a: /* b; c: */ d}
+SCSS
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: d; }
+CSS
+foo {a /*: b; c */: d}
+SCSS
+  end
+
+  def test_crazy_comments 
+    # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/t040109-c17-comments-00-b.xht
+    assert_equal <<CSS, render(<<SCSS)
+/* This is a CSS comment. */
+.one {
+  color: green; }
+
+/* Another comment */
+/* The following should not be used:
+.two {color: red;} */
+.three {
+  color: green;
+  /* color: red; */ }
+
+/**
+.four {color: red;} */
+.five {
+  color: green; }
+
+/**/
+.six {
+  color: green; }
+
+/*********/
+.seven {
+  color: green; }
+
+/* a comment **/
+.eight {
+  color: green; }
+CSS
+/* This is a CSS comment. */
+.one {color: green;} /* Another comment */
+/* The following should not be used:
+.two {color: red;} */
+.three {color: green; /* color: red; */}
+/**
+.four {color: red;} */
+.five {color: green;}
+/**/
+.six {color: green;}
+/*********/
+.seven {color: green;}
+/* a comment **/
+.eight {color: green;}
+SCSS
+  end
+
+  def test_rule_comments
+    assert_parses <<SCSS
+/* Foo */
+.foo {
+  a: b; }
+SCSS
+    assert_equal <<CSS, render(<<SCSS)
+/* Foo
+ * Bar */
+.foo {
+  a: b; }
+CSS
+/* Foo
+ * Bar */.foo {
+  a: b; }
+SCSS
+  end
+
+  def test_property_comments
+    assert_parses <<SCSS
+.foo {
+  /* Foo */
+  a: b; }
+SCSS
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  /* Foo
+   * Bar */
+  a: b; }
+CSS
+.foo {
+  /* Foo
+   * Bar */a: b; }
+SCSS
+  end
+
+  def test_selector_comments
+    assert_equal <<CSS, render(<<SCSS)
+.foo #bar:baz(bip) {
+  a: b; }
+CSS
+.foo /* .a #foo */ #bar:baz(/* bang )*/ bip) {
+  a: b; }
+SCSS
+  end
+
+  def test_lonely_comments
+    assert_parses <<SCSS
+/* Foo
+ * Bar */
+SCSS
+    assert_parses <<SCSS
+.foo {
+  /* Foo
+   * Bar */ }
+SCSS
+  end
+
+  def test_multiple_comments
+    assert_parses <<SCSS
+/* Foo
+ * Bar */
+/* Baz
+ * Bang */
+SCSS
+    assert_parses <<SCSS
+.foo {
+  /* Foo
+   * Bar */
+  /* Baz
+   * Bang */ }
+SCSS
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  /* Foo Bar */
+  /* Baz Bang */ }
+CSS
+.foo {
+  /* Foo Bar *//* Baz Bang */ }
+SCSS
+  end
+
+  def test_bizarrely_formatted_comments
+    assert_parses <<SCSS
+.foo {
+  /* Foo
+Bar
+  Baz */
+  a: b; }
+SCSS
+    assert_parses <<SCSS
+.foo {
+    /* Foo
+Bar
+  Baz */
+  a: b; }
+SCSS
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+   /* Foo
+Bar */
+  a: b; }
+CSS
+.foo {/* Foo
+   Bar */
+  a: b; }
+SCSS
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+    /* Foo
+ Bar
+Baz */
+  a: b; }
+CSS
+.foo {/* Foo
+   Bar
+  Baz */
+  a: b; }
+SCSS
+  end
+
+  ## Declarations
+
+  def test_vendor_properties
+    assert_parses <<SCSS
+foo {
+  -moz-foo-bar: blat;
+  -o-flat-blang: wibble; }
+SCSS
+  end
+
+  def test_empty_declarations
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  bar: baz; }
+CSS
+foo {;;;;
+  bar: baz;;;;
+  ;;}
+SCSS
+  end
+
+  def test_basic_property_types
+    assert_parses <<SCSS
+foo {
+  a: 2;
+  b: 2.3em;
+  c: 50%;
+  d: "fraz bran";
+  e: flanny-blanny-blan;
+  f: url(http://sass-lang.com);
+  g: U+ffa?;
+  h: #aabbcc; }
+SCSS
+  end
+
+  def test_functions
+    assert_parses <<SCSS
+foo {
+  a: foo-bar(12);
+  b: -foo-bar-baz(13, 14 15); }
+SCSS
+  end
+
+  def test_unary_minus
+    assert_parses <<SCSS
+foo {
+  a: -2;
+  b: -2.3em;
+  c: -50%;
+  d: -foo(bar baz); }
+SCSS
+  end
+
+  def test_operators
+    assert_parses <<SCSS
+foo {
+  a: foo bar baz;
+  b: foo, #aabbcc, -12;
+  c: 1px/2px/-3px;
+  d: foo bar, baz/bang; }
+SCSS
+  end
+
+  def test_important
+    assert_parses <<SCSS
+foo {
+  a: foo !important;
+  b: foo bar !important;
+  b: foo, bar !important; }
+SCSS
+  end
+
+  def test_initial_hyphen
+    assert_parses <<SCSS
+foo {
+  a: -moz-bar-baz;
+  b: foo -o-bar-baz; }
+SCSS
+  end
+
+  def test_ms_long_filter_syntax
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, 
endColorstr=#ff000000);
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, 
endColorstr=#ff000000); }
+CSS
+foo {
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, 
endColorstr=#ff000000);
+  filter:progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, 
endColorstr=#ff000000); }
+SCSS
+  end
+
+  def test_ms_short_filter_syntax
+    assert_parses <<SCSS
+foo {
+  filter: alpha(opacity=20);
+  filter: alpha(opacity=20, enabled=true);
+  filter: blaznicate(foo=bar, baz=bang bip, bart=#fa4600); }
+SCSS
+  end
+
+  def test_declaration_hacks
+    assert_parses <<SCSS
+foo {
+  _name: val;
+  *name: val;
+  :name: val;
+  .name: val;
+  #name: val;
+  name/**/: val;
+  name/*\\**/: val;
+  name: val; }
+SCSS
+  end
+
+  def test_trailing_hash_hack
+    assert_parses <<SCSS
+foo {
+  foo: bar;
+  #baz: bang;
+  #bip: bop; }
+SCSS
+  end
+
+  def test_zero_arg_functions
+    assert_parses <<SCSS
+foo {
+  a: foo();
+  b: bar baz-bang() bip; }
+SCSS
+  end
+
+  def test_expression_function
+    assert_parses <<SCSS
+foo {
+  a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); }
+SCSS
+  end
+
+  def test_calc_function
+    assert_parses <<SCSS
+foo {
+  a: 12px calc(100%/3 - 2*1em - 2*1px);
+  b: 12px -moz-calc(100%/3 - 2*1em - 2*1px);
+  b: 12px -webkit-calc(100%/3 - 2*1em - 2*1px);
+  b: 12px -foobar-calc(100%/3 - 2*1em - 2*1px); }
+SCSS
+  end
+
+  def test_element_function
+    assert_parses <<SCSS
+foo {
+  a: -moz-element(#foo);
+  b: -webkit-element(#foo);
+  b: -foobar-element(#foo); }
+SCSS
+  end
+
+  def test_unary_ops
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: -0.5em;
+  b: +0.5em;
+  c: -foo(12px);
+  d: +foo(12px); }
+CSS
+foo {
+  a: -0.5em;
+  b: +0.5em;
+  c: -foo(12px);
+  d: +foo(12px); }
+SCSS
+  end
+
+  def test_css_string_escapes
+    assert_parses <<SCSS
+foo {
+  a: "\\foo bar";
+  b: "foo\\ bar";
+  c: "\\2022 \\0020";
+  d: "foo\\\\bar";
+  e: "foo\\"'bar"; }
+SCSS
+  end
+
+  def test_css_ident_escapes
+    assert_parses <<SCSS
+foo {
+  a: \\foo bar;
+  b: foo\\ bar;
+  c: \\2022 \\0020;
+  d: foo\\\\bar;
+  e: foo\\"\\'bar; }
+SCSS
+  end
+
+  ## Directives
+
+  def test_namespace_directive
+    assert_parses '@namespace "http://www.w3.org/Profiles/xhtml1-strict";;'
+    assert_parses '@namespace url(http://www.w3.org/Profiles/xhtml1-strict);'
+    assert_parses '@namespace html url("http://www.w3.org/Profiles/xhtml1-strict";);'
+  end
+
+  def test_media_directive
+    assert_parses <<SCSS
+ media all {
+  rule1 {
+    prop: val; }
+
+  rule2 {
+    prop: val; } }
+SCSS
+    assert_parses <<SCSS
+ media screen, print {
+  rule1 {
+    prop: val; }
+
+  rule2 {
+    prop: val; } }
+SCSS
+  end
+
+  def test_media_directive_with_keywords
+    assert_parses <<SCSS
+ media screen and (-webkit-min-device-pixel-ratio: 0) {
+  a: b; }
+SCSS
+    assert_parses <<SCSS
+ media only screen, print and (foo: 0px) and (bar: flam(12px solid)) {
+  a: b; }
+SCSS
+  end
+
+  def test_import_directive
+    assert_parses '@import "foo.css";'
+    assert_parses "@import 'foo.css';"
+    assert_parses '@import url("foo.css");'
+    assert_parses "@import url('foo.css');"
+    assert_parses '@import url(foo.css);'
+  end
+
+  def test_import_directive_with_media
+    assert_parses '@import "foo.css" screen;'
+    assert_parses '@import "foo.css" screen, print;'
+    assert_parses '@import "foo.css" screen, print and (foo: 0);'
+    assert_parses '@import "foo.css" screen, only print, screen and (foo: 0);'
+  end
+
+  def test_page_directive
+    assert_parses <<SCSS
+ page {
+  prop1: val;
+  prop2: val; }
+SCSS
+    assert_parses <<SCSS
+ page flap {
+  prop1: val;
+  prop2: val; }
+SCSS
+    assert_parses <<SCSS
+ page :first {
+  prop1: val;
+  prop2: val; }
+SCSS
+    assert_parses <<SCSS
+ page flap:first {
+  prop1: val;
+  prop2: val; }
+SCSS
+  end
+
+  def test_blockless_directive_without_semicolon
+    assert_equal "@foo \"bar\";\n", render('@foo "bar"')
+  end
+
+  def test_directive_with_lots_of_whitespace
+    assert_equal "@foo \"bar\";\n", render('@foo    "bar"  ;')
+  end
+
+  def test_empty_blockless_directive
+    assert_parses "@foo;"
+  end
+
+  def test_multiple_blockless_directives
+    assert_parses <<SCSS
+ foo bar;
+ bar baz;
+SCSS
+  end
+
+  def test_empty_block_directive
+    assert_parses "@foo {}"
+    assert_equal "@foo {}\n", render(<<SCSS)
+ foo {
+}
+SCSS
+  end
+
+  def test_multiple_block_directives
+    assert_parses <<SCSS
+ foo bar {
+  a: b; }
+
+ bar baz {
+  c: d; }
+SCSS
+  end
+
+  def test_block_directive_with_rule_and_property
+    assert_parses <<SCSS
+ foo {
+  rule {
+    a: b; }
+
+  a: b; }
+SCSS
+  end
+
+  def test_block_directive_with_semicolon
+    assert_equal <<CSS, render(<<SCSS)
+ foo {
+  a: b; }
+
+ bar {
+  a: b; }
+CSS
+ foo {a:b};
+ bar {a:b};
+SCSS
+  end
+
+  def test_moz_document_directive
+    assert_equal <<CSS, render(<<SCSS)
+ -moz-document url(http://www.w3.org/),
+               url-prefix(http://www.w3.org/Style/),
+               domain(mozilla.org),
+               regexp("^https:.*") {
+  .foo {
+    a: b; } }
+CSS
+ -moz-document url(http://www.w3.org/),
+               url-prefix(http://www.w3.org/Style/),
+               domain(mozilla.org),
+               regexp("^https:.*") {
+  .foo {a: b}
+}
+SCSS
+  end
+
+  def test_supports
+    assert_equal <<CSS, render(<<SCSS)
+ supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) {
+  .foo {
+    a: b; } }
+ supports (a: b) {
+  .foo {
+    a: b; } }
+CSS
+ supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) {
+  .foo {
+    a: b;
+  }
+}
+
+ supports (a: b) {
+  .foo {
+    a: b;
+  }
+}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+ -prefix-supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) {
+  .foo {
+    a: b; } }
+CSS
+ -prefix-supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) {
+  .foo {
+    a: b;
+  }
+}
+SCSS
+  end
+
+  ## Selectors
+
+  # Taken from http://dev.w3.org/csswg/selectors4/#overview
+  def test_summarized_selectors
+    assert_selector_parses('*')
+    assert_selector_parses('E')
+    assert_selector_parses('E:not(s)')
+    assert_selector_parses('E:not(s1, s2)')
+    assert_selector_parses('E:matches(s1, s2)')
+    assert_selector_parses('E.warning')
+    assert_selector_parses('E#myid')
+    assert_selector_parses('E[foo]')
+    assert_selector_parses('E[foo="bar"]')
+    assert_selector_parses('E[foo="bar" i]')
+    assert_selector_parses('E[foo~="bar"]')
+    assert_selector_parses('E[foo^="bar"]')
+    assert_selector_parses('E[foo$="bar"]')
+    assert_selector_parses('E[foo*="bar"]')
+    assert_selector_parses('E[foo|="en"]')
+    assert_selector_parses('E:dir(ltr)')
+    assert_selector_parses('E:lang(fr)')
+    assert_selector_parses('E:lang(zh, *-hant)')
+    assert_selector_parses('E:any-link')
+    assert_selector_parses('E:link')
+    assert_selector_parses('E:visited')
+    assert_selector_parses('E:local-link')
+    assert_selector_parses('E:local-link(0)')
+    assert_selector_parses('E:target')
+    assert_selector_parses('E:scope')
+    assert_selector_parses('E:current')
+    assert_selector_parses('E:current(s)')
+    assert_selector_parses('E:past')
+    assert_selector_parses('E:future')
+    assert_selector_parses('E:active')
+    assert_selector_parses('E:hover')
+    assert_selector_parses('E:focus')
+    assert_selector_parses('E:enabled')
+    assert_selector_parses('E:disabled')
+    assert_selector_parses('E:checked')
+    assert_selector_parses('E:indeterminate')
+    assert_selector_parses('E:default')
+    assert_selector_parses('E:in-range')
+    assert_selector_parses('E:out-of-range')
+    assert_selector_parses('E:required')
+    assert_selector_parses('E:optional')
+    assert_selector_parses('E:read-only')
+    assert_selector_parses('E:read-write')
+    assert_selector_parses('E:root')
+    assert_selector_parses('E:empty')
+    assert_selector_parses('E:first-child')
+    assert_selector_parses('E:nth-child(n)')
+    assert_selector_parses('E:last-child')
+    assert_selector_parses('E:nth-last-child(n)')
+    assert_selector_parses('E:only-child')
+    assert_selector_parses('E:first-of-type')
+    assert_selector_parses('E:nth-of-type(n)')
+    assert_selector_parses('E:last-of-type')
+    assert_selector_parses('E:nth-last-of-type(n)')
+    assert_selector_parses('E:only-of-type')
+    assert_selector_parses('E:nth-match(n of selector)')
+    assert_selector_parses('E:nth-last-match(n of selector)')
+    assert_selector_parses('E:column(selector)')
+    assert_selector_parses('E:nth-column(n)')
+    assert_selector_parses('E:nth-last-column(n)')
+    assert_selector_parses('E F')
+    assert_selector_parses('E > F')
+    assert_selector_parses('E + F')
+    assert_selector_parses('E ~ F')
+    assert_selector_parses('E /foo/ F')
+    assert_selector_parses('E! > F')
+
+    assert_selector_parses('E /ns|foo/ F')
+    assert_selector_parses('E /*|foo/ F')
+  end
+
+  # Taken from http://dev.w3.org/csswg/selectors4/#overview, but without element
+  # names.
+  def test_more_summarized_selectors
+    assert_selector_parses(':not(s)')
+    assert_selector_parses(':not(s1, s2)')
+    assert_selector_parses(':matches(s1, s2)')
+    assert_selector_parses('.warning')
+    assert_selector_parses('#myid')
+    assert_selector_parses('[foo]')
+    assert_selector_parses('[foo="bar"]')
+    assert_selector_parses('[foo="bar" i]')
+    assert_selector_parses('[foo~="bar"]')
+    assert_selector_parses('[foo^="bar"]')
+    assert_selector_parses('[foo$="bar"]')
+    assert_selector_parses('[foo*="bar"]')
+    assert_selector_parses('[foo|="en"]')
+    assert_selector_parses(':dir(ltr)')
+    assert_selector_parses(':lang(fr)')
+    assert_selector_parses(':lang(zh, *-hant)')
+    assert_selector_parses(':any-link')
+    assert_selector_parses(':link')
+    assert_selector_parses(':visited')
+    assert_selector_parses(':local-link')
+    assert_selector_parses(':local-link(0)')
+    assert_selector_parses(':target')
+    assert_selector_parses(':scope')
+    assert_selector_parses(':current')
+    assert_selector_parses(':current(s)')
+    assert_selector_parses(':past')
+    assert_selector_parses(':future')
+    assert_selector_parses(':active')
+    assert_selector_parses(':hover')
+    assert_selector_parses(':focus')
+    assert_selector_parses(':enabled')
+    assert_selector_parses(':disabled')
+    assert_selector_parses(':checked')
+    assert_selector_parses(':indeterminate')
+    assert_selector_parses(':default')
+    assert_selector_parses(':in-range')
+    assert_selector_parses(':out-of-range')
+    assert_selector_parses(':required')
+    assert_selector_parses(':optional')
+    assert_selector_parses(':read-only')
+    assert_selector_parses(':read-write')
+    assert_selector_parses(':root')
+    assert_selector_parses(':empty')
+    assert_selector_parses(':first-child')
+    assert_selector_parses(':nth-child(n)')
+    assert_selector_parses(':last-child')
+    assert_selector_parses(':nth-last-child(n)')
+    assert_selector_parses(':only-child')
+    assert_selector_parses(':first-of-type')
+    assert_selector_parses(':nth-of-type(n)')
+    assert_selector_parses(':last-of-type')
+    assert_selector_parses(':nth-last-of-type(n)')
+    assert_selector_parses(':only-of-type')
+    assert_selector_parses(':nth-match(n of selector)')
+    assert_selector_parses(':nth-last-match(n of selector)')
+    assert_selector_parses(':column(selector)')
+    assert_selector_parses(':nth-column(n)')
+    assert_selector_parses(':nth-last-column(n)')
+  end
+
+  def test_attribute_selectors_with_identifiers
+    assert_selector_parses('[foo~=bar]')
+    assert_selector_parses('[foo^=bar]')
+    assert_selector_parses('[foo$=bar]')
+    assert_selector_parses('[foo*=bar]')
+    assert_selector_parses('[foo|=en]')
+  end
+
+  def test_nth_selectors
+    assert_selector_parses(':nth-child(-n)')
+    assert_selector_parses(':nth-child(+n)')
+
+    assert_selector_parses(':nth-child(even)')
+    assert_selector_parses(':nth-child(odd)')
+
+    assert_selector_parses(':nth-child(50)')
+    assert_selector_parses(':nth-child(-50)')
+    assert_selector_parses(':nth-child(+50)')
+
+    assert_selector_parses(':nth-child(2n+3)')
+    assert_selector_parses(':nth-child(2n-3)')
+    assert_selector_parses(':nth-child(+2n-3)')
+    assert_selector_parses(':nth-child(-2n+3)')
+    assert_selector_parses(':nth-child(-2n+ 3)')
+
+    assert_equal(<<CSS, render(<<SCSS))
+:nth-child(2n + 3) {
+  a: b; }
+CSS
+:nth-child( 2n + 3 ) {
+  a: b; }
+SCSS
+  end
+
+  def test_selectors_containing_selectors
+    assert_selector_can_contain_selectors(':not(<sel>)')
+    assert_selector_can_contain_selectors(':current(<sel>)')
+    assert_selector_can_contain_selectors(':nth-match(n of <sel>)')
+    assert_selector_can_contain_selectors(':nth-last-match(n of <sel>)')
+    assert_selector_can_contain_selectors(':column(<sel>)')
+    assert_selector_can_contain_selectors(':-moz-any(<sel>)')
+  end
+
+  def assert_selector_can_contain_selectors(sel)
+    try = lambda {|subsel| assert_selector_parses(sel.gsub('<sel>', subsel))}
+    
+    try['foo|bar']
+    try['*|bar']
+
+    try['foo|*']
+    try['*|*']
+
+    try['#blah']
+    try['.blah']
+
+    try['[foo]']
+    try['[foo^="bar"]']
+    try['[baz|foo~="bar"]']
+
+    try[':hover']
+    try[':nth-child(2n + 3)']
+
+    try['h1, h2, h3']
+    try['#foo, bar, [baz]']
+
+    # Not technically allowed for most selectors, but what the heck
+    try[':not(#foo)']
+    try['a#foo.bar']
+    try['#foo .bar > baz']
+  end
+
+  def test_namespaced_selectors
+    assert_selector_parses('foo|E')
+    assert_selector_parses('*|E')
+    assert_selector_parses('foo|*')
+    assert_selector_parses('*|*')
+  end
+
+  def test_namespaced_attribute_selectors
+    assert_selector_parses('[foo|bar=baz]')
+    assert_selector_parses('[*|bar=baz]')
+    assert_selector_parses('[foo|bar|=baz]')
+  end
+
+  def test_comma_selectors
+    assert_selector_parses('E, F')
+    assert_selector_parses('E F, G H')
+    assert_selector_parses('E > F, G > H')
+  end
+
+  def test_selectors_with_newlines
+    assert_selector_parses("E,\nF")
+    assert_selector_parses("E\nF")
+    assert_selector_parses("E, F\nG, H")
+  end
+
+  def test_expression_fallback_selectors
+    assert_selector_parses('0%')
+    assert_selector_parses('60%')
+    assert_selector_parses('100%')
+    assert_selector_parses('12px')
+    assert_selector_parses('"foo"')
+  end
+
+  def test_functional_pseudo_selectors
+    assert_selector_parses(':foo("bar")')
+    assert_selector_parses(':foo(bar)')
+    assert_selector_parses(':foo(12px)')
+    assert_selector_parses(':foo(+)')
+    assert_selector_parses(':foo(-)')
+    assert_selector_parses(':foo(+"bar")')
+    assert_selector_parses(':foo(-++--baz-"bar"12px)')
+  end
+
+  def test_selector_hacks
+    assert_selector_parses('> E')
+    assert_selector_parses('+ E')
+    assert_selector_parses('~ E')
+    assert_selector_parses('> > E')
+    assert_equal <<CSS, render(<<SCSS)
+> > E {
+  a: b; }
+CSS
+>> E {
+  a: b; }
+SCSS
+
+    assert_selector_parses('E*')
+    assert_selector_parses('E*.foo')
+    assert_selector_parses('E*:hover')
+  end
+
+  def test_spaceless_combo_selectors
+    assert_equal "E > F {\n  a: b; }\n", render("E>F { a: b;} ")
+    assert_equal "E ~ F {\n  a: b; }\n", render("E~F { a: b;} ")
+    assert_equal "E + F {\n  a: b; }\n", render("E+F { a: b;} ")
+  end
+
+  ## Errors
+
+  def test_invalid_directives
+    assert_not_parses("identifier", '@<err> import "foo";')
+    assert_not_parses("identifier", '@<err>12 "foo";')
+  end
+
+  def test_invalid_classes
+    assert_not_parses("class name", 'p.<err> foo {a: b}')
+    assert_not_parses("class name", 'p.<err>1foo {a: b}')
+  end
+
+  def test_invalid_ids
+    assert_not_parses("id name", 'p#<err> foo {a: b}')
+  end
+
+  def test_no_properties_at_toplevel
+    assert_not_parses('pseudoclass or pseudoelement', 'a:<err> b;')
+  end
+
+  def test_no_scss_directives
+    assert_parses('@import "foo.sass";')
+    assert_parses <<SCSS
+ mixin foo {
+  a: b; }
+SCSS
+  end
+
+  def test_no_variables
+    assert_not_parses("selector or at-rule", "<err>$var = 12;")
+    assert_not_parses('"}"', "foo { <err>!var = 12; }")
+  end
+
+  def test_no_parent_selectors
+    assert_not_parses('"{"', "foo <err>&.bar {a: b}")
+  end
+
+  def test_no_selector_interpolation
+    assert_not_parses('"{"', 'foo <err>#{"bar"}.baz {a: b}')
+  end
+
+  def test_no_prop_name_interpolation
+    assert_not_parses('":"', 'foo {a<err>#{"bar"}baz: b}')
+  end
+
+  def test_no_prop_val_interpolation
+    assert_not_parses('"}"', 'foo {a: b <err>#{"bar"} c}')
+  end
+
+  def test_no_string_interpolation
+    assert_parses <<SCSS
+foo {
+  a: "bang \#{1 +    " bar "} bip"; }
+SCSS
+  end
+
+  def test_no_sass_script_values
+    assert_not_parses('"}"', 'foo {a: b <err>* c}')
+  end
+
+  def test_no_nested_rules
+    assert_not_parses('":"', 'foo {bar <err>{a: b}}')
+    assert_not_parses('"}"', 'foo {<err>[bar=baz] {a: b}}')
+  end
+
+  def test_no_nested_properties
+    assert_not_parses('expression (e.g. 1px, bold)', 'foo {bar: <err>{a: b}}')
+    assert_not_parses('expression (e.g. 1px, bold)', 'foo {bar: bang <err>{a: b}}')
+  end
+
+  def test_no_nested_directives
+    assert_not_parses('"}"', 'foo {<err>@bar {a: b}}')
+  end
+
+  def test_error_with_windows_newlines
+    render <<SCSS
+foo {bar}\r
+baz {a: b}
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal 'Invalid CSS after "foo {bar": expected ":", was "}"', e.message
+    assert_equal 1, e.sass_line
+  end
+
+  ## Regressions
+
+  def test_double_space_string
+    assert_equal(<<CSS, render(<<SCSS))
+.a {
+  content: "  a"; }
+CSS
+.a {
+  content: "  a";
+}
+SCSS
+  end
+
+  def test_very_long_number_with_important_doesnt_take_forever
+    assert_equal(<<CSS, render(<<SCSS))
+.foo {
+  width: 97.916666666666666666666666666667% !important; }
+CSS
+.foo {
+  width: 97.916666666666666666666666666667% !important;
+}
+SCSS
+  end
+
+  def test_selector_without_closing_bracket
+    assert_not_parses('"]"', "foo[bar <err>{a: b}")
+  end
+
+  def test_closing_line_comment_end_with_compact_output
+    assert_equal(<<CSS, render(<<SCSS, :style => :compact))
+/* foo */
+bar { baz: bang; }
+CSS
+/*
+ * foo
+ */
+bar {baz: bang}
+SCSS
+  end
+
+  def test_single_line_comment_within_multiline_comment
+    assert_equal(<<CSS, render(<<SCSS))
+body {
+  /*
+  //comment here
+  */ }
+CSS
+body {
+  /*
+  //comment here
+  */
+}
+SCSS
+  end
+
+  def test_malformed_media
+    render <<SCSS
+ media {
+  margin: 0;
+}
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal 'Invalid CSS after "@media ": expected media query (e.g. print, screen, print and screen), 
was "{"', e.message
+    assert_equal 1, e.sass_line
+  end
+
+  private
+
+  def assert_selector_parses(selector)
+    assert_parses <<SCSS
+#{selector} {
+  a: b; }
+SCSS
+  end
+
+  def render(scss, options = {})
+    tree = Sass::SCSS::CssParser.new(scss, options[:filename]).parse
+    tree.options = Sass::Engine::DEFAULT_OPTIONS.merge(options)
+    tree.render
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/scss/rx_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/scss/rx_test.rb
new file mode 100755
index 0000000..e5cb59a
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/scss/rx_test.rb
@@ -0,0 +1,156 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+require File.dirname(__FILE__) + '/../../test_helper'
+require 'sass/engine'
+
+class ScssRxTest < Test::Unit::TestCase
+  include Sass::SCSS::RX
+
+  def test_identifiers
+    assert_match IDENT, "foo"
+    assert_match IDENT, "\xC3\xBFoo" # Initial char can be nonascii
+    assert_match IDENT, "\\123abcoo" # Initial char can be unicode escape
+    assert_match IDENT, "\\f oo" # Unicode escapes can be followed by whitespace
+    assert_match IDENT, "\\fa\too"
+    assert_match IDENT, "\\ff2\roo"
+    assert_match IDENT, "\\f13a\foo"
+    assert_match IDENT, "\\f13abcoo"
+    assert_match IDENT, "\\ oo" # Initial char can be a plain escape as well
+    assert_match IDENT, "\\~oo"
+    assert_match IDENT, "\\\\oo"
+    assert_match IDENT, "\\{oo"
+    assert_match IDENT, "\\\xC3\xBFoo"
+    assert_match IDENT, "-foo" # Can put a - before anything
+    assert_match IDENT, "-\xC3\xBFoo"
+    assert_match IDENT, "-\\f oo"
+    assert_match IDENT, "_foo" # Can put a _ before anything
+    assert_match IDENT, "_\xC3\xBFoo"
+    assert_match IDENT, "_\\f oo"
+
+    assert_match IDENT, "foo-bar"
+    assert_match IDENT, "f012-23"
+    assert_match IDENT, "foo_-_bar"
+    assert_match IDENT, "f012_23"
+
+    # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/escapes-003.xht
+    assert_match IDENT, "c\\lass"
+    # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/escapes-004.xht
+    assert_match IDENT, "c\\00006Cas\\000073"
+    # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-001.xht
+    assert_match IDENT, "IdE6n-3t0_6"
+    # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-006.xht
+    assert_match IDENT, "\\6000ident"
+    # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-007.xht
+    assert_match IDENT, "iden\\6000t\\6000"
+    # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-013.xht
+    assert_match IDENT, "\\-ident"
+  end
+
+  def test_underscores_in_identifiers
+    assert_match IDENT, "foo_bar"
+    assert_match IDENT, "_\xC3\xBFfoo"
+    assert_match IDENT, "__foo"
+    assert_match IDENT, "_1foo"
+    assert_match IDENT, "-_foo"
+    assert_match IDENT, "_-foo"
+  end
+
+  def test_invalid_identifiers
+    assert_no_match IDENT, ""
+    assert_no_match IDENT, "1foo"
+    assert_no_match IDENT, "-1foo"
+    assert_no_match IDENT, "--foo"
+    assert_no_match IDENT, "foo bar"
+    assert_no_match IDENT, "foo~bar"
+
+    # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/escapes-008.xht
+    assert_no_match IDENT, "c\\06C  ass"
+    assert_no_match IDENT, "back\\67\n round"
+  end
+
+  def test_double_quote_strings
+    assert_match STRING, '"foo bar"'
+    assert_match STRING, '"foo\\\nbar"'
+    assert_match STRING, "\"\\\"\""
+    assert_match STRING, '"\t !#$%&(-~()*+,-./0123456789~"'
+  end
+
+  def test_single_quote_strings
+    assert_match STRING, "'foo bar'"
+    assert_match STRING, "'foo\\\nbar'"
+    assert_match STRING, "'\\''"
+    assert_match STRING, "'\t !#\$%&(-~()*+,-./0123456789~'"
+  end
+
+  def test_invalid_strings
+    assert_no_match STRING, "\"foo\nbar\""
+    assert_no_match STRING, "\"foo\"bar\""
+    assert_no_match STRING, "'foo\nbar'"
+    assert_no_match STRING, "'foo'bar'"
+  end
+
+  def test_uri
+    assert_match URI, 'url("foo bar)")'
+    assert_match URI, "url('foo bar)')"
+    assert_match URI, 'url( "foo bar)" )'
+    assert_match URI, "url(#\\%&**+,-./0123456789~)"
+  end
+
+  def test_invalid_uri
+    assert_no_match URI, 'url(foo)bar)'
+  end
+
+  def test_unicode_range
+    assert_match UNICODERANGE, 'U+00-Ff'
+    assert_match UNICODERANGE, 'u+980-9FF'
+    assert_match UNICODERANGE, 'U+9aF??'
+    assert_match UNICODERANGE, 'U+??'
+  end
+
+  def test_escape_empty_ident
+    assert_equal "", Sass::SCSS::RX.escape_ident("")
+  end
+
+  def test_escape_just_prefix_ident
+    assert_equal "\\-", Sass::SCSS::RX.escape_ident("-")
+    assert_equal "\\_", Sass::SCSS::RX.escape_ident("_")
+  end
+
+  def test_escape_plain_ident
+    assert_equal "foo", Sass::SCSS::RX.escape_ident("foo")
+    assert_equal "foo-1bar", Sass::SCSS::RX.escape_ident("foo-1bar")
+    assert_equal "-foo-bar", Sass::SCSS::RX.escape_ident("-foo-bar")
+    assert_equal "f2oo_bar", Sass::SCSS::RX.escape_ident("f2oo_bar")
+    assert_equal "_foo_bar", Sass::SCSS::RX.escape_ident("_foo_bar")
+  end
+
+  def test_escape_initial_funky_ident
+    assert_equal "\\000035foo", Sass::SCSS::RX.escape_ident("5foo")
+    assert_equal "-\\000035foo", Sass::SCSS::RX.escape_ident("-5foo")
+    assert_equal "_\\000035foo", Sass::SCSS::RX.escape_ident("_5foo")
+
+    assert_equal "\\&foo", Sass::SCSS::RX.escape_ident("&foo")
+    assert_equal "-\\&foo", Sass::SCSS::RX.escape_ident("-&foo")
+
+    assert_equal "-\\ foo", Sass::SCSS::RX.escape_ident("- foo")
+  end
+
+  def test_escape_mid_funky_ident
+    assert_equal "foo\\&bar", Sass::SCSS::RX.escape_ident("foo&bar")
+    assert_equal "foo\\ \\ bar", Sass::SCSS::RX.escape_ident("foo  bar")
+    assert_equal "foo\\00007fbar", Sass::SCSS::RX.escape_ident("foo\177bar")
+  end
+
+  private
+
+  def assert_match(rx, str)
+    assert_not_nil(match = rx.match(str))
+    assert_equal str.size, match[0].size
+  end
+
+  def assert_no_match(rx, str)
+    match = rx.match(str)
+    assert_not_equal str.size, match && match[0].size
+  end
+
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/scss/scss_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/scss/scss_test.rb
new file mode 100755
index 0000000..4ef8203
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/scss/scss_test.rb
@@ -0,0 +1,2043 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+require File.dirname(__FILE__) + '/test_helper'
+
+class ScssTest < Test::Unit::TestCase
+  include ScssTestHelper
+
+  ## One-Line Comments
+
+  def test_one_line_comments
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  baz: bang; }
+CSS
+.foo {// bar: baz;}
+  baz: bang; //}
+}
+SCSS
+    assert_equal <<CSS, render(<<SCSS)
+.foo bar[val="//"] {
+  baz: bang; }
+CSS
+.foo bar[val="//"] {
+  baz: bang; //}
+}
+SCSS
+  end
+
+  ## Script
+
+  def test_variables
+    assert_equal <<CSS, render(<<SCSS)
+blat {
+  a: foo; }
+CSS
+$var: foo;
+
+blat {a: $var}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: 2;
+  b: 6; }
+CSS
+foo {
+  $var: 2;
+  $another-var: 4;
+  a: $var;
+  b: $var + $another-var;}
+SCSS
+  end
+
+  def test_unicode_variables
+    assert_equal <<CSS, render(<<SCSS)
+blat {
+  a: foo; }
+CSS
+$vär: foo;
+
+blat {a: $vär}
+SCSS
+  end
+
+  def test_guard_assign
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: 1; }
+CSS
+$var: 1;
+$var: 2 !default;
+
+foo {a: $var}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: 2; }
+CSS
+$var: 2 !default;
+
+foo {a: $var}
+SCSS
+  end
+
+  def test_sass_script
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: 3;
+  b: -1;
+  c: foobar;
+  d: 12px; }
+CSS
+foo {
+  a: 1 + 2;
+  b: 1 - 2;
+  c: foo + bar;
+  d: floor(12.3px); }
+SCSS
+  end
+
+  def test_debug_directive
+    assert_warning "test_debug_directive_inline.scss:2 DEBUG: hello world!" do
+      assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: b; }
+
+bar {
+  c: d; }
+CSS
+foo {a: b}
+ debug "hello world!";
+bar {c: d}
+SCSS
+    end
+  end
+
+  def test_warn_directive
+    expected_warning = <<EXPECTATION
+WARNING: this is a warning
+         on line 2 of test_warn_directive_inline.scss
+
+WARNING: this is a mixin
+         on line 1 of test_warn_directive_inline.scss, in `foo'
+         from line 3 of test_warn_directive_inline.scss
+EXPECTATION
+    assert_warning expected_warning do
+      assert_equal <<CSS, render(<<SCSS)
+bar {
+  c: d; }
+CSS
+ mixin foo { @warn "this is a mixin";}
+ warn "this is a warning";
+bar {c: d; @include foo;}
+SCSS
+    end
+  end
+
+  def test_for_directive
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: 1;
+  a: 2;
+  a: 3;
+  a: 4; }
+CSS
+.foo {
+  @for $var from 1 to 5 {a: $var;}
+}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: 1;
+  a: 2;
+  a: 3;
+  a: 4;
+  a: 5; }
+CSS
+.foo {
+  @for $var from 1 through 5 {a: $var;}
+}
+SCSS
+  end
+
+  def test_if_directive
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: b; }
+CSS
+ if "foo" == "foo" {foo {a: b}}
+ if "foo" != "foo" {bar {a: b}}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+bar {
+  a: b; }
+CSS
+ if "foo" != "foo" {foo {a: b}}
+ else if "foo" == "foo" {bar {a: b}}
+ else if true {baz {a: b}}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+bar {
+  a: b; }
+CSS
+ if "foo" != "foo" {foo {a: b}}
+ else {bar {a: b}}
+SCSS
+  end
+
+  def test_comment_after_if_directive
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: b;
+  /* This is a comment */
+  c: d; }
+CSS
+foo {
+  @if true {a: b}
+  /* This is a comment */
+  c: d }
+SCSS
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: b;
+  /* This is a comment */
+  c: d; }
+CSS
+foo {
+  @if true {a: b}
+  @else {x: y}
+  /* This is a comment */
+  c: d }
+SCSS
+  end
+
+  def test_while_directive
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: 1;
+  a: 2;
+  a: 3;
+  a: 4; }
+CSS
+$i: 1;
+
+.foo {
+  @while $i != 5 {
+    a: $i;
+    $i: $i + 1;
+  }
+}
+SCSS
+  end
+
+  def test_each_directive
+    assert_equal <<CSS, render(<<SCSS)
+a {
+  b: 1px;
+  b: 2px;
+  b: 3px;
+  b: 4px; }
+
+c {
+  d: foo;
+  d: bar;
+  d: baz;
+  d: bang; }
+CSS
+a {
+  @each $number in 1px 2px 3px 4px {
+    b: $number;
+  }
+}
+c {
+  @each $str in foo, bar, baz, bang {
+    d: $str;
+  }
+}
+SCSS
+  end
+
+  def test_css_import_directive
+    assert_equal "@import url(foo.css);\n", render('@import "foo.css";')
+    assert_equal "@import url(foo.css);\n", render("@import 'foo.css';")
+    assert_equal "@import url(\"foo.css\");\n", render('@import url("foo.css");')
+    assert_equal "@import url(\"foo.css\");\n", render('@import url("foo.css");')
+    assert_equal "@import url(foo.css);\n", render('@import url(foo.css);')
+  end
+
+  def test_media_import
+    assert_equal("@import \"./fonts.sass\" all;\n", render("@import \"./fonts.sass\" all;"))
+  end
+
+  def test_dynamic_media_import
+    assert_equal(<<CSS, render(<<SCSS))
+ import "foo" print and (-webkit-min-device-pixel-ratio-foo: 25);
+CSS
+$media: print;
+$key: -webkit-min-device-pixel-ratio;
+$value: 20;
+ import "foo" \#{$media} and ($key + "-foo": $value + 5);
+SCSS
+  end
+
+  def test_http_import
+    assert_equal("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\";\n";,
+      render("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\";";))
+  end
+
+  def test_protocol_relative_import
+    assert_equal("@import \"//fonts.googleapis.com/css?family=Droid+Sans\";\n",
+      render("@import \"//fonts.googleapis.com/css?family=Droid+Sans\";"))
+  end
+
+  def test_import_with_interpolation
+    assert_equal <<CSS, render(<<SCSS)
+ import url("http://fonts.googleapis.com/css?family=Droid+Sans";);
+CSS
+$family: unquote("Droid+Sans");
+ import url("http://fonts.googleapis.com/css?family=\#{$family}";);
+SCSS
+  end
+
+  def test_url_import
+    assert_equal("@import url(fonts.sass);\n", render("@import url(fonts.sass);"))
+  end
+
+  def test_block_comment_in_script
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: 1bar; }
+CSS
+foo {a: 1 + /* flang */ bar}
+SCSS
+  end
+
+  def test_line_comment_in_script
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: 1blang; }
+CSS
+foo {a: 1 + // flang }
+  blang }
+SCSS
+  end
+
+  ## Nested Rules
+
+  def test_nested_rules
+    assert_equal <<CSS, render(<<SCSS)
+foo bar {
+  a: b; }
+CSS
+foo {bar {a: b}}
+SCSS
+    assert_equal <<CSS, render(<<SCSS)
+foo bar {
+  a: b; }
+foo baz {
+  b: c; }
+CSS
+foo {
+  bar {a: b}
+  baz {b: c}}
+SCSS
+    assert_equal <<CSS, render(<<SCSS)
+foo bar baz {
+  a: b; }
+foo bang bip {
+  a: b; }
+CSS
+foo {
+  bar {baz {a: b}}
+  bang {bip {a: b}}}
+SCSS
+  end
+
+  def test_nested_rules_with_declarations
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: b; }
+  foo bar {
+    c: d; }
+CSS
+foo {
+  a: b;
+  bar {c: d}}
+SCSS
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: b; }
+  foo bar {
+    c: d; }
+CSS
+foo {
+  bar {c: d}
+  a: b}
+SCSS
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  ump: nump;
+  grump: clump; }
+  foo bar {
+    blat: bang;
+    habit: rabbit; }
+    foo bar baz {
+      a: b; }
+    foo bar bip {
+      c: d; }
+  foo bibble bap {
+    e: f; }
+CSS
+foo {
+  ump: nump;
+  grump: clump;
+  bar {
+    blat: bang;
+    habit: rabbit;
+    baz {a: b}
+    bip {c: d}}
+  bibble {
+    bap {e: f}}}
+SCSS
+  end
+
+  def test_nested_rules_with_fancy_selectors
+    assert_equal <<CSS, render(<<SCSS)
+foo .bar {
+  a: b; }
+foo :baz {
+  c: d; }
+foo bang:bop {
+  e: f; }
+CSS
+foo {
+  .bar {a: b}
+  :baz {c: d}
+  bang:bop {e: f}}
+SCSS
+  end
+
+  def test_almost_ambiguous_nested_rules_and_declarations
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  bar: baz bang bop biddle woo look at all these elems; }
+  foo bar:baz:bang:bop:biddle:woo:look:at:all:these:pseudoclasses {
+    a: b; }
+  foo bar:baz bang bop biddle woo look at all these elems {
+    a: b; }
+CSS
+foo {
+  bar:baz:bang:bop:biddle:woo:look:at:all:these:pseudoclasses {a: b};
+  bar:baz bang bop biddle woo look at all these elems {a: b};
+  bar:baz bang bop biddle woo look at all these elems; }
+SCSS
+  end
+
+  def test_newlines_in_selectors
+    assert_equal <<CSS, render(<<SCSS)
+foo
+bar {
+  a: b; }
+CSS
+foo
+bar {a: b}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+foo baz,
+foo bang,
+bar baz,
+bar bang {
+  a: b; }
+CSS
+foo,
+bar {
+  baz,
+  bang {a: b}}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+foo
+bar baz
+bang {
+  a: b; }
+foo
+bar bip bop {
+  c: d; }
+CSS
+foo
+bar {
+  baz
+  bang {a: b}
+
+  bip bop {c: d}}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+foo bang, foo bip
+bop, bar
+baz bang, bar
+baz bip
+bop {
+  a: b; }
+CSS
+foo, bar
+baz {
+  bang, bip
+  bop {a: b}}
+SCSS
+  end
+
+  def test_trailing_comma_in_selector
+    assert_equal <<CSS, render(<<SCSS)
+#foo #bar,
+#baz #boom {
+  a: b; }
+
+#bip #bop {
+  c: d; }
+CSS
+#foo #bar,,
+,#baz #boom, {a: b}
+
+#bip #bop, ,, {c: d}
+SCSS
+  end
+
+  def test_parent_selectors
+    assert_equal <<CSS, render(<<SCSS)
+foo:hover {
+  a: b; }
+bar foo.baz {
+  c: d; }
+CSS
+foo {
+  &:hover {a: b}
+  bar &.baz {c: d}}
+SCSS
+  end
+
+  def test_parent_selector_with_subject
+    assert_equal <<CSS, render(<<SCSS)
+bar foo.baz! .bip {
+  a: b; }
+
+bar foo bar.baz! .bip {
+  c: d; }
+CSS
+foo {
+  bar &.baz! .bip {a: b}}
+
+foo bar {
+  bar &.baz! .bip {c: d}}
+SCSS
+  end
+
+  ## Namespace Properties
+
+  def test_namespace_properties
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  bar: baz;
+  bang-bip: 1px;
+  bang-bop: bar; }
+CSS
+foo {
+  bar: baz;
+  bang: {
+    bip: 1px;
+    bop: bar;}}
+SCSS
+  end
+
+  def test_several_namespace_properties
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  bar: baz;
+  bang-bip: 1px;
+  bang-bop: bar;
+  buzz-fram: "foo";
+  buzz-frum: moo; }
+CSS
+foo {
+  bar: baz;
+  bang: {
+    bip: 1px;
+    bop: bar;}
+  buzz: {
+    fram: "foo";
+    frum: moo;
+  }
+}
+SCSS
+  end
+
+  def test_nested_namespace_properties
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  bar: baz;
+  bang-bip: 1px;
+  bang-bop: bar;
+  bang-blat-baf: bort; }
+CSS
+foo {
+  bar: baz;
+  bang: {
+    bip: 1px;
+    bop: bar;
+    blat:{baf:bort}}}
+SCSS
+  end
+
+  def test_namespace_properties_with_value
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  bar: baz;
+    bar-bip: bop;
+    bar-bing: bop; }
+CSS
+foo {
+  bar: baz {
+    bip: bop;
+    bing: bop; }}
+SCSS
+  end
+
+  def test_namespace_properties_with_script_value
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  bar: bazbang;
+    bar-bip: bop;
+    bar-bing: bop; }
+CSS
+foo {
+  bar: baz + bang {
+    bip: bop;
+    bing: bop; }}
+SCSS
+  end
+
+  def test_no_namespace_properties_without_space
+    assert_equal <<CSS, render(<<SCSS)
+foo bar:baz {
+  bip: bop; }
+CSS
+foo {
+  bar:baz {
+    bip: bop }}
+SCSS
+  end
+
+  def test_no_namespace_properties_without_space_even_when_its_unambiguous
+    render(<<SCSS)
+foo {
+  bar:1px {
+    bip: bop }}
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal <<MESSAGE, e.message
+Invalid CSS: a space is required between a property and its definition
+when it has other properties nested beneath it.
+MESSAGE
+    assert_equal 2, e.sass_line
+  end
+
+  ## Mixins
+
+  def test_basic_mixins
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: b; }
+CSS
+ mixin foo {
+  .foo {a: b}}
+
+ include foo;
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+bar {
+  c: d; }
+  bar .foo {
+    a: b; }
+CSS
+ mixin foo {
+  .foo {a: b}}
+
+bar {
+  @include foo;
+  c: d; }
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+bar {
+  a: b;
+  c: d; }
+CSS
+ mixin foo {a: b}
+
+bar {
+  @include foo;
+  c: d; }
+SCSS
+  end
+
+  def test_mixins_with_empty_args
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: b; }
+CSS
+ mixin foo() {a: b}
+
+.foo { include foo();}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: b; }
+CSS
+ mixin foo() {a: b}
+
+.foo { include foo;}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: b; }
+CSS
+ mixin foo {a: b}
+
+.foo { include foo();}
+SCSS
+  end
+
+  def test_mixins_with_args
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: bar; }
+CSS
+ mixin foo($a) {a: $a}
+
+.foo { include foo(bar)}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: bar;
+  b: 12px; }
+CSS
+ mixin foo($a, $b) {
+  a: $a;
+  b: $b; }
+
+.foo { include foo(bar, 12px)}
+SCSS
+  end
+
+  ## Functions
+
+  def test_basic_function
+    assert_equal(<<CSS, render(<<SASS))
+bar {
+  a: 3; }
+CSS
+ function foo() {
+  @return 1 + 2;
+}
+
+bar {
+  a: foo();
+}
+SASS
+  end
+
+  def test_function_args
+    assert_equal(<<CSS, render(<<SASS))
+bar {
+  a: 3; }
+CSS
+ function plus($var1, $var2) {
+  @return $var1 + $var2;
+}
+
+bar {
+  a: plus(1, 2);
+}
+SASS
+  end
+
+  ## Var Args
+
+  def test_mixin_var_args
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: 1;
+  b: 2, 3, 4; }
+CSS
+ mixin foo($a, $b...) {
+  a: $a;
+  b: $b;
+}
+
+.foo { include foo(1, 2, 3, 4)}
+SCSS
+  end
+
+  def test_mixin_empty_var_args
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: 1;
+  b: 0; }
+CSS
+ mixin foo($a, $b...) {
+  a: $a;
+  b: length($b);
+}
+
+.foo { include foo(1)}
+SCSS
+  end
+
+  def test_mixin_var_args_act_like_list
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: 3;
+  b: 3; }
+CSS
+ mixin foo($a, $b...) {
+  a: length($b);
+  b: nth($b, 2);
+}
+
+.foo { include foo(1, 2, 3, 4)}
+SCSS
+  end
+
+  def test_mixin_splat_args
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: 1;
+  b: 2;
+  c: 3;
+  d: 4; }
+CSS
+ mixin foo($a, $b, $c, $d) {
+  a: $a;
+  b: $b;
+  c: $c;
+  d: $d;
+}
+
+$list: 2, 3, 4;
+.foo { include foo(1, $list...)}
+SCSS
+  end
+
+  def test_mixin_splat_expression
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: 1;
+  b: 2;
+  c: 3;
+  d: 4; }
+CSS
+ mixin foo($a, $b, $c, $d) {
+  a: $a;
+  b: $b;
+  c: $c;
+  d: $d;
+}
+
+.foo { include foo(1, (2, 3, 4)...)}
+SCSS
+  end
+
+  def test_mixin_splat_args_with_var_args
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: 1;
+  b: 2, 3, 4; }
+CSS
+ mixin foo($a, $b...) {
+  a: $a;
+  b: $b;
+}
+
+$list: 2, 3, 4;
+.foo { include foo(1, $list...)}
+SCSS
+  end
+
+  def test_mixin_splat_args_with_var_args_and_normal_args
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: 1;
+  b: 2;
+  c: 3, 4; }
+CSS
+ mixin foo($a, $b, $c...) {
+  a: $a;
+  b: $b;
+  c: $c;
+}
+
+$list: 2, 3, 4;
+.foo { include foo(1, $list...)}
+SCSS
+  end
+
+  def test_mixin_splat_args_with_var_args_preserves_separator
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: 1;
+  b: 2 3 4 5; }
+CSS
+ mixin foo($a, $b...) {
+  a: $a;
+  b: $b;
+}
+
+$list: 3 4 5;
+.foo { include foo(1, 2, $list...)}
+SCSS
+  end
+
+  def test_mixin_var_and_splat_args_pass_through_keywords
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  a: 3;
+  b: 1;
+  c: 2; }
+CSS
+ mixin foo($a...) {
+  @include bar($a...);
+}
+
+ mixin bar($b, $c, $a) {
+  a: $a;
+  b: $b;
+  c: $c;
+}
+
+.foo { include foo(1, $c: 2, $a: 3)}
+SCSS
+  end
+
+  def test_mixin_var_args_with_keyword
+    assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") 
{render <<SCSS}
+ mixin foo($a, $b...) {
+  a: $a;
+  b: $b;
+}
+
+.foo { include foo($a: 1, 2, 3, 4)}
+SCSS
+  end
+
+  def test_mixin_keyword_for_var_arg
+    assert_raise_message(Sass::SyntaxError, "Argument $b of mixin foo cannot be used as a named argument.") 
{render <<SCSS}
+ mixin foo($a, $b...) {
+  a: $a;
+  b: $b;
+}
+
+.foo { include foo(1, $b: 2 3 4)}
+SCSS
+  end
+
+  def test_mixin_keyword_for_unknown_arg_with_var_args
+    assert_raise_message(Sass::SyntaxError, "Mixin foo doesn't have an argument named $c.") {render <<SCSS}
+ mixin foo($a, $b...) {
+  a: $a;
+  b: $b;
+}
+
+.foo { include foo(1, $c: 2 3 4)}
+SCSS
+  end
+
+  def test_function_var_args
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  val: "a: 1, b: 2, 3, 4"; }
+CSS
+ function foo($a, $b...) {
+  @return "a: \#{$a}, b: \#{$b}";
+}
+
+.foo {val: foo(1, 2, 3, 4)}
+SCSS
+  end
+
+  def test_function_empty_var_args
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  val: "a: 1, b: 0"; }
+CSS
+ function foo($a, $b...) {
+  @return "a: \#{$a}, b: \#{length($b)}";
+}
+
+.foo {val: foo(1)}
+SCSS
+  end
+
+  def test_function_var_args_act_like_list
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  val: "a: 3, b: 3"; }
+CSS
+ function foo($a, $b...) {
+  @return "a: \#{length($b)}, b: \#{nth($b, 2)}";
+}
+
+.foo {val: foo(1, 2, 3, 4)}
+SCSS
+  end
+
+  def test_function_splat_args
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  val: "a: 1, b: 2, c: 3, d: 4"; }
+CSS
+ function foo($a, $b, $c, $d) {
+  @return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}";
+}
+
+$list: 2, 3, 4;
+.foo {val: foo(1, $list...)}
+SCSS
+  end
+
+  def test_function_splat_expression
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  val: "a: 1, b: 2, c: 3, d: 4"; }
+CSS
+ function foo($a, $b, $c, $d) {
+  @return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}";
+}
+
+.foo {val: foo(1, (2, 3, 4)...)}
+SCSS
+  end
+
+  def test_function_splat_args_with_var_args
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  val: "a: 1, b: 2, 3, 4"; }
+CSS
+ function foo($a, $b...) {
+  @return "a: \#{$a}, b: \#{$b}";
+}
+
+$list: 2, 3, 4;
+.foo {val: foo(1, $list...)}
+SCSS
+  end
+
+  def test_function_splat_args_with_var_args_and_normal_args
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  val: "a: 1, b: 2, c: 3, 4"; }
+CSS
+ function foo($a, $b, $c...) {
+  @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
+}
+
+$list: 2, 3, 4;
+.foo {val: foo(1, $list...)}
+SCSS
+  end
+
+  def test_function_splat_args_with_var_args_preserves_separator
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  val: "a: 1, b: 2 3 4 5"; }
+CSS
+ function foo($a, $b...) {
+  @return "a: \#{$a}, b: \#{$b}";
+}
+
+$list: 3 4 5;
+.foo {val: foo(1, 2, $list...)}
+SCSS
+  end
+
+  def test_function_var_and_splat_args_pass_through_keywords
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  val: "a: 3, b: 1, c: 2"; }
+CSS
+ function foo($a...) {
+  @return bar($a...);
+}
+
+ function bar($b, $c, $a) {
+  @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
+}
+
+.foo {val: foo(1, $c: 2, $a: 3)}
+SCSS
+  end
+
+  def test_function_var_args_with_keyword
+    assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") 
{render <<SCSS}
+ function foo($a, $b...) {
+  @return "a: \#{$a}, b: $b";
+}
+
+.foo {val: foo($a: 1, 2, 3, 4)}
+SCSS
+  end
+
+  def test_function_keyword_for_var_arg
+    assert_raise_message(Sass::SyntaxError, "Argument $b of function foo cannot be used as a named 
argument.") {render <<SCSS}
+ function foo($a, $b...) {
+  @return "a: \#{$a}, b: \#{$b}";
+}
+
+.foo {val: foo(1, $b: 2 3 4)}
+SCSS
+  end
+
+  def test_function_keyword_for_unknown_arg_with_var_args
+    assert_raise_message(Sass::SyntaxError, "Function foo doesn't have an argument named $c.") {render 
<<SCSS}
+ function foo($a, $b...) {
+  @return "a: \#{$a}, b: \#{$b}";
+}
+
+.foo {val: foo(1, $c: 2 3 4)}
+SCSS
+  end
+
+  def test_function_var_args_passed_to_native
+    assert_equal <<CSS, render(<<SCSS)
+.foo {
+  val: #102035; }
+CSS
+ function foo($args...) {
+  @return adjust-color($args...);
+}
+
+.foo {val: foo(#102030, $blue: 5)}
+SCSS
+  end
+
+  ## Interpolation
+
+  def test_basic_selector_interpolation
+    assert_equal <<CSS, render(<<SCSS)
+foo 3 baz {
+  a: b; }
+CSS
+foo \#{1 + 2} baz {a: b}
+SCSS
+    assert_equal <<CSS, render(<<SCSS)
+foo.bar baz {
+  a: b; }
+CSS
+foo\#{".bar"} baz {a: b}
+SCSS
+    assert_equal <<CSS, render(<<SCSS)
+foo.bar baz {
+  a: b; }
+CSS
+\#{"foo"}.bar baz {a: b}
+SCSS
+  end
+
+  def test_selector_only_interpolation
+    assert_equal <<CSS, render(<<SCSS)
+foo bar {
+  a: b; }
+CSS
+\#{"foo" + " bar"} {a: b}
+SCSS
+  end
+
+  def test_selector_interpolation_before_element_name
+    assert_equal <<CSS, render(<<SCSS)
+foo barbaz {
+  a: b; }
+CSS
+\#{"foo" + " bar"}baz {a: b}
+SCSS
+  end
+
+  def test_selector_interpolation_in_string
+    assert_equal <<CSS, render(<<SCSS)
+foo[val="bar foo bar baz"] {
+  a: b; }
+CSS
+foo[val="bar \#{"foo" + " bar"} baz"] {a: b}
+SCSS
+  end
+
+  def test_selector_interpolation_in_pseudoclass
+    assert_equal <<CSS, render(<<SCSS)
+foo:nth-child(5n) {
+  a: b; }
+CSS
+foo:nth-child(\#{5 + "n"}) {a: b}
+SCSS
+  end
+
+  def test_selector_interpolation_at_class_begininng
+    assert_equal <<CSS, render(<<SCSS)
+.zzz {
+  a: b; }
+CSS
+$zzz: zzz;
+.\#{$zzz} { a: b; }
+SCSS
+  end
+
+  def test_selector_interpolation_at_id_begininng
+    assert_equal <<CSS, render(<<SCSS)
+#zzz {
+  a: b; }
+CSS
+$zzz: zzz;
+#\#{$zzz} { a: b; }
+SCSS
+  end
+
+  def test_selector_interpolation_at_pseudo_begininng
+    assert_equal <<CSS, render(<<SCSS)
+:zzz::zzz {
+  a: b; }
+CSS
+$zzz: zzz;
+:\#{$zzz}::\#{$zzz} { a: b; }
+SCSS
+  end
+
+  def test_selector_interpolation_at_attr_beginning
+    assert_equal <<CSS, render(<<SCSS)
+[zzz=foo] {
+  a: b; }
+CSS
+$zzz: zzz;
+[\#{$zzz}=foo] { a: b; }
+SCSS
+  end
+
+  def test_selector_interpolation_at_attr_end
+    assert_equal <<CSS, render(<<SCSS)
+[foo=zzz] {
+  a: b; }
+CSS
+$zzz: zzz;
+[foo=\#{$zzz}] { a: b; }
+SCSS
+  end
+
+  def test_selector_interpolation_at_dashes
+    assert_equal <<CSS, render(<<SCSS)
+div {
+  -foo-a-b-foo: foo; }
+CSS
+$a : a;
+$b : b;
+div { -foo-\#{$a}-\#{$b}-foo: foo }
+SCSS
+  end
+
+  def test_selector_interpolation_in_reference_combinator
+    assert_equal <<CSS, render(<<SCSS)
+.foo /a/ .bar /b|c/ .baz {
+  a: b; }
+CSS
+$a: a;
+$b: b;
+$c: c;
+.foo /\#{$a}/ .bar /\#{$b}|\#{$c}/ .baz {a: b}
+SCSS
+  end
+
+  def test_parent_selector_with_parent_and_subject
+    assert_equal <<CSS, render(<<SCSS)
+bar foo.baz! .bip {
+  c: d; }
+CSS
+$subject: "!";
+foo {
+  bar &.baz\#{$subject} .bip {c: d}}
+SCSS
+  end
+
+  def test_basic_prop_name_interpolation
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  barbazbang: blip; }
+CSS
+foo {bar\#{"baz" + "bang"}: blip}
+SCSS
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  bar3: blip; }
+CSS
+foo {bar\#{1 + 2}: blip}
+SCSS
+  end
+
+  def test_prop_name_only_interpolation
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  bazbang: blip; }
+CSS
+foo {\#{"baz" + "bang"}: blip}
+SCSS
+  end
+
+  def test_directive_interpolation
+    assert_equal <<CSS, render(<<SCSS)
+ foo bar12 qux {
+  a: b; }
+CSS
+$baz: 12;
+ foo bar\#{$baz} qux {a: b}
+SCSS
+  end
+
+  def test_media_interpolation
+    assert_equal <<CSS, render(<<SCSS)
+ media bar12 {
+  a: b; }
+CSS
+$baz: 12;
+ media bar\#{$baz} {a: b}
+SCSS
+  end
+
+  def test_script_in_media
+    assert_equal <<CSS, render(<<SCSS)
+ media screen and (-webkit-min-device-pixel-ratio: 20), only print {
+  a: b; }
+CSS
+$media1: screen;
+$media2: print;
+$var: -webkit-min-device-pixel-ratio;
+$val: 20;
+ media \#{$media1} and ($var: $val), only \#{$media2} {a: b}
+SCSS
+
+    assert_equal <<CSS, render(<<SCSS)
+ media screen and (-webkit-min-device-pixel-ratio: 13) {
+  a: b; }
+CSS
+$vals: 1 2 3;
+ media screen and (-webkit-min-device-pixel-ratio: 5 + 6 + nth($vals, 2)) {a: b}
+SCSS
+  end
+
+  def test_media_interpolation_with_reparse
+    assert_equal <<CSS, render(<<SCSS)
+ media screen and (max-width: 300px) {
+  a: b; }
+ media screen and (max-width: 300px) {
+  a: b; }
+ media screen and (max-width: 300px) {
+  a: b; }
+ media screen and (max-width: 300px), print and (max-width: 300px) {
+  a: b; }
+CSS
+$constraint: "(max-width: 300px)";
+$fragment: "nd \#{$constraint}";
+$comma: "een, pri";
+ media screen and \#{$constraint} {a: b}
+ media screen {
+  @media \#{$constraint} {a: b}
+}
+ media screen a\#{$fragment} {a: b}
+ media scr\#{$comma}nt {
+  @media \#{$constraint} {a: b}
+}
+SCSS
+  end
+
+  def test_moz_document_interpolation
+    assert_equal <<CSS, render(<<SCSS)
+ -moz-document url(http://sass-lang.com/),
+               url-prefix(http://sass-lang.com/docs),
+               domain(sass-lang.com),
+               domain("sass-lang.com") {
+  .foo {
+    a: b; } }
+CSS
+$domain: "sass-lang.com";
+ -moz-document url(http://\#{$domain}/),
+               url-prefix(http://\#{$domain}/docs),
+               domain(\#{$domain}),
+               \#{domain($domain)} {
+  .foo {a: b}
+}
+SCSS
+  end
+
+  def test_supports_with_expressions
+    assert_equal <<CSS, render(<<SCSS)
+ supports (feature1: val) and (feature2: val) or (not (feature23: val4)) {
+  foo {
+    a: b; } }
+CSS
+$query: "(feature1: val)";
+$feature: feature2;
+$val: val;
+ supports \#{$query} and ($feature: $val) or (not ($feature + 3: $val + 4)) {
+  foo {a: b}
+}
+SCSS
+  end
+
+  def test_supports_bubbling
+    assert_equal <<CSS, render(<<SCSS)
+ supports (foo: bar) {
+  a {
+    b: c; }
+    @supports (baz: bang) {
+      a {
+        d: e; } } }
+CSS
+a {
+  @supports (foo: bar) {
+    b: c;
+    @supports (baz: bang) {
+      d: e;
+    }
+  }
+}
+SCSS
+  end
+
+  def test_random_directive_interpolation
+    assert_equal <<CSS, render(<<SCSS)
+ foo url(http://sass-lang.com/),
+     domain("sass-lang.com"),
+     "foobarbaz",
+     foobarbaz {
+  .foo {
+    a: b; } }
+CSS
+$domain: "sass-lang.com";
+ foo url(http://\#{$domain}/),
+     \#{domain($domain)},
+     "foo\#{'ba' + 'r'}baz",
+     foo\#{'ba' + 'r'}baz {
+  .foo {a: b}
+}
+SCSS
+  end
+
+  def test_nested_mixin_def
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: b; }
+CSS
+foo {
+  @mixin bar {a: b}
+  @include bar; }
+SCSS
+  end
+
+  def test_nested_mixin_shadow
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  c: d; }
+
+baz {
+  a: b; }
+CSS
+ mixin bar {a: b}
+
+foo {
+  @mixin bar {c: d}
+  @include bar;
+}
+
+baz { include bar}
+SCSS
+  end
+
+  def test_nested_function_def
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: 1; }
+
+bar {
+  b: foo(); }
+CSS
+foo {
+  @function foo() { return 1}
+  a: foo(); }
+
+bar {b: foo()}
+SCSS
+  end
+
+  def test_nested_function_shadow
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: 2; }
+
+baz {
+  b: 1; }
+CSS
+ function foo() { return 1}
+
+foo {
+  @function foo() { return 2}
+  a: foo();
+}
+
+baz {b: foo()}
+SCSS
+  end
+
+  ## Errors
+
+  def test_nested_mixin_def_is_scoped
+    render <<SCSS
+foo {
+  @mixin bar {a: b}}
+bar { include bar}
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal "Undefined mixin 'bar'.", e.message
+    assert_equal 3, e.sass_line
+  end
+
+  def test_rules_beneath_properties
+    render <<SCSS
+foo {
+  bar: {
+    baz {
+      bang: bop }}}
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal 'Illegal nesting: Only properties may be nested beneath properties.', e.message
+    assert_equal 3, e.sass_line
+  end
+
+  def test_uses_property_exception_with_star_hack
+    render <<SCSS
+foo {
+  *bar:baz [fail]; }
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal 'Invalid CSS after "  *bar:baz ": expected ";", was "[fail]; }"', e.message
+    assert_equal 2, e.sass_line
+  end
+
+  def test_uses_property_exception_with_colon_hack
+    render <<SCSS
+foo {
+  :bar:baz [fail]; }
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal 'Invalid CSS after "  :bar:baz ": expected ";", was "[fail]; }"', e.message
+    assert_equal 2, e.sass_line
+  end
+
+  def test_uses_rule_exception_with_dot_hack
+    render <<SCSS
+foo {
+  .bar:baz <fail>; }
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal 'Invalid CSS after "  .bar:baz ": expected "{", was "<fail>; }"', e.message
+    assert_equal 2, e.sass_line
+  end
+
+  def test_uses_property_exception_with_space_after_name
+    render <<SCSS
+foo {
+  bar: baz [fail]; }
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal 'Invalid CSS after "  bar: baz ": expected ";", was "[fail]; }"', e.message
+    assert_equal 2, e.sass_line
+  end
+
+  def test_uses_property_exception_with_non_identifier_after_name
+    render <<SCSS
+foo {
+  bar:1px [fail]; }
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal 'Invalid CSS after "  bar:1px ": expected ";", was "[fail]; }"', e.message
+    assert_equal 2, e.sass_line
+  end
+
+  def test_uses_property_exception_when_followed_by_open_bracket
+    render <<SCSS
+foo {
+  bar:{baz: .fail} }
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal 'Invalid CSS after "  bar:{baz: ": expected expression (e.g. 1px, bold), was ".fail} }"', 
e.message
+    assert_equal 2, e.sass_line
+  end
+
+  def test_script_error
+    render <<SCSS
+foo {
+  bar: "baz" * * }
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal 'Invalid CSS after "  bar: "baz" * ": expected expression (e.g. 1px, bold), was "* }"', 
e.message
+    assert_equal 2, e.sass_line
+  end
+
+  def test_multiline_script_syntax_error
+    render <<SCSS
+foo {
+  bar:
+    "baz" * * }
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal 'Invalid CSS after "    "baz" * ": expected expression (e.g. 1px, bold), was "* }"', 
e.message
+    assert_equal 3, e.sass_line
+  end
+
+  def test_multiline_script_runtime_error
+    render <<SCSS
+foo {
+  bar: "baz" +
+    "bar" +
+    $bang }
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal "Undefined variable: \"$bang\".", e.message
+    assert_equal 4, e.sass_line
+  end
+
+  def test_post_multiline_script_runtime_error
+    render <<SCSS
+foo {
+  bar: "baz" +
+    "bar" +
+    "baz";
+  bip: $bop; }
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal "Undefined variable: \"$bop\".", e.message
+    assert_equal 5, e.sass_line
+  end
+
+  def test_multiline_property_runtime_error
+    render <<SCSS
+foo {
+  bar: baz
+    bar
+    \#{$bang} }
+SCSS
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal "Undefined variable: \"$bang\".", e.message
+    assert_equal 4, e.sass_line
+  end
+
+  def test_post_resolution_selector_error
+    render "\n\nfoo \#{\") bar\"} {a: b}"
+    assert(false, "Expected syntax error")
+  rescue Sass::SyntaxError => e
+    assert_equal 'Invalid CSS after "foo ": expected selector, was ") bar"', e.message
+    assert_equal 3, e.sass_line
+  end
+
+  def test_parent_in_mid_selector_error
+    assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
+Invalid CSS after "  .foo": expected "{", was "&.bar {a: b}"
+
+"&.bar" may only be used at the beginning of a compound selector.
+MESSAGE
+flim {
+  .foo&.bar {a: b}
+}
+SCSS
+  end
+
+  def test_parent_after_selector_error
+    assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
+Invalid CSS after "  .foo.bar": expected "{", was "& {a: b}"
+
+"&" may only be used at the beginning of a compound selector.
+MESSAGE
+flim {
+  .foo.bar& {a: b}
+}
+SCSS
+  end
+
+  def test_double_parent_selector_error
+    assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
+Invalid CSS after "  &": expected "{", was "& {a: b}"
+
+"&" may only be used at the beginning of a compound selector.
+MESSAGE
+flim {
+  && {a: b}
+}
+SCSS
+  end
+
+  def test_no_lonely_else
+    assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
+Invalid CSS: @else must come after @if
+MESSAGE
+ else {foo: bar}
+SCSS
+  end
+
+  # Regression
+
+  def test_loud_comment_in_compressed_mode
+    assert_equal(<<CSS, render(<<SCSS))
+/*! foo */
+CSS
+/*! foo */
+SCSS
+  end
+
+  def test_parsing_decimals_followed_by_comments_doesnt_take_forever
+    assert_equal(<<CSS, render(<<SCSS))
+.foo {
+  padding: 4.21053% 4.21053% 5.63158%; }
+CSS
+.foo {
+  padding: 4.21052631578947% 4.21052631578947% 5.631578947368421% /**/
+}
+SCSS
+  end
+
+  def test_parsing_many_numbers_doesnt_take_forever
+    values = ["80% 90%"] * 1000
+    assert_equal(<<CSS, render(<<SCSS))
+.foo {
+  padding: #{values.join(', ')}; }
+CSS
+.foo {
+  padding: #{values.join(', ')};
+}
+SCSS
+  end
+
+  def test_import_comments_in_imports
+    assert_equal(<<CSS, render(<<SCSS))
+ import url(foo.css);
+ import url(bar.css);
+ import url(baz.css);
+CSS
+ import "foo.css", // this is a comment
+        "bar.css", /* this is another comment */
+        "baz.css"; // this is a third comment
+SCSS
+  end
+
+  def test_reference_combinator_with_parent_ref
+    assert_equal <<CSS, render(<<SCSS)
+a /foo/ b {
+  c: d; }
+CSS
+a {& /foo/ b {c: d}}
+SCSS
+  end
+
+  def test_newline_selector_rendered_multiple_times
+    assert_equal <<CSS, render(<<SCSS)
+form input,
+form select {
+  color: white; }
+
+form input,
+form select {
+  color: white; }
+CSS
+ for $i from 1 through 2 {
+  form {
+    input,
+    select {
+      color: white;
+    }
+  }
+}
+SCSS
+  end
+
+  def test_prop_name_interpolation_after_hyphen
+    assert_equal <<CSS, render(<<SCSS)
+a {
+  -foo-bar: b; }
+CSS
+a { -\#{"foo"}-bar: b; }
+SCSS
+  end
+
+  def test_star_plus_and_parent
+    assert_equal <<CSS, render(<<SCSS)
+* + html foo {
+  a: b; }
+CSS
+foo {*+html & {a: b}}
+SCSS
+  end
+
+  def test_weird_added_space
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  bar: -moz-bip; }
+CSS
+$value : bip;
+
+foo {
+  bar: -moz-\#{$value};
+}
+SCSS
+  end
+
+  def test_interpolation_with_bracket_on_next_line
+    assert_equal <<CSS, render(<<SCSS)
+a.foo b {
+  color: red; }
+CSS
+a.\#{"foo"} b
+{color: red}
+SCSS
+  end
+
+  def test_extra_comma_in_mixin_arglist_error
+    assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
+Invalid CSS after "...clude foo(bar, ": expected mixin argument, was ");"
+MESSAGE
+ mixin foo($a1, $a2) {
+  baz: $a1 $a2;
+}
+
+.bar {
+  @include foo(bar, );
+}
+SCSS
+  end
+
+  def test_interpolation
+    assert_equal <<CSS, render(<<SCSS)
+ul li#foo a span.label {
+  foo: bar; }
+CSS
+$bar : "#foo";
+ul li\#{$bar} a span.label { foo: bar; }
+SCSS
+  end
+
+  def test_mixin_with_keyword_args
+    assert_equal <<CSS, render(<<SCSS)
+.mixed {
+  required: foo;
+  arg1: default-val1;
+  arg2: non-default-val2; }
+CSS
+ mixin a-mixin($required, $arg1: default-val1, $arg2: default-val2) {
+  required: $required;
+  arg1: $arg1;
+  arg2: $arg2;
+}
+.mixed { @include a-mixin(foo, $arg2: non-default-val2); }
+SCSS
+  end
+
+  def test_passing_required_args_as_a_keyword_arg
+    assert_equal <<CSS, render(<<SCSS)
+.mixed {
+  required: foo;
+  arg1: default-val1;
+  arg2: default-val2; }
+CSS
+ mixin a-mixin($required, $arg1: default-val1, $arg2: default-val2) {
+  required: $required;
+  arg1: $arg1;
+  arg2: $arg2; }
+.mixed { @include a-mixin($required: foo); }
+SCSS
+  end
+
+  def test_passing_all_as_keyword_args_in_opposite_order
+    assert_equal <<CSS, render(<<SCSS)
+.mixed {
+  required: foo;
+  arg1: non-default-val1;
+  arg2: non-default-val2; }
+CSS
+ mixin a-mixin($required, $arg1: default-val1, $arg2: default-val2) {
+  required: $required;
+  arg1: $arg1;
+  arg2: $arg2; }
+.mixed { @include a-mixin($arg2: non-default-val2, $arg1: non-default-val1, $required: foo); }
+SCSS
+  end
+
+  def test_keyword_args_in_functions
+    assert_equal <<CSS, render(<<SCSS)
+.keyed {
+  color: rgba(170, 119, 204, 0.4); }
+CSS
+.keyed { color: rgba($color: #a7c, $alpha: 0.4) }
+SCSS
+  end
+
+  def test_unknown_keyword_arg_raises_error
+    assert_raise_message(Sass::SyntaxError, "Mixin a doesn't have an argument named $c.") {render <<SCSS}
+ mixin a($b: 1) { a: $b; }
+div { @include a(1, $c: 3); }
+SCSS
+  end
+
+
+  def test_newlines_removed_from_selectors_when_compressed
+    assert_equal <<CSS, render(<<SCSS, :style => :compressed)
+z a,z b{display:block}
+CSS
+a
+, b {
+  z & {
+    display: block;
+  }
+}
+SCSS
+  end
+
+  def test_if_error_line
+    assert_raise_line(2) {render(<<SCSS)}
+ if true {foo: bar}
+}
+SCSS
+  end
+
+  def test_multiline_var
+    assert_equal <<CSS, render(<<SCSS)
+foo {
+  a: 3;
+  b: false;
+  c: a b c; }
+CSS
+foo {
+  $var1: 1 +
+    2;
+  $var2: true and
+    false;
+  $var3: a b
+    c;
+  a: $var1;
+  b: $var2;
+  c: $var3; }
+SCSS
+  end
+
+  def test_mixin_content
+    assert_equal <<CSS, render(<<SASS)
+.parent {
+  background-color: red;
+  border-color: red; }
+  .parent .child {
+    background-color: yellow;
+    color: blue;
+    border-color: yellow; }
+CSS
+$color: blue;
+ mixin context($class, $color: red) {
+  .\#{$class} {
+    background-color: $color;
+    @content;
+    border-color: $color;
+  }
+}
+ include context(parent) {
+  @include context(child, $color: yellow) {
+    color: $color;
+  }
+}
+SASS
+  end
+
+  def test_empty_content
+    assert_equal <<CSS, render(<<SCSS)
+a {
+  b: c; }
+CSS
+ mixin foo { @content }
+a { b: c; @include foo {} }
+SCSS
+  end
+
+  def test_options_passed_to_script
+    assert_equal <<CSS, render(<<SCSS, :style => :compressed)
+foo{color:#000}
+CSS
+foo {color: darken(black, 10%)}
+SCSS
+  end
+
+  # ref: https://github.com/nex3/sass/issues/104
+  def test_no_buffer_overflow
+    template = render <<SCSS
+.aaa {
+  background-color: white;
+}
+.aaa .aaa .aaa {
+  background-color: black;
+}   
+.bbb {
+  @extend .aaa;
+} 
+.xxx {
+  @extend .bbb;
+}
+.yyy {
+  @extend .bbb;
+}
+.zzz {
+  @extend .bbb;
+}
+SCSS
+    Sass::SCSS::Parser.new(template, "test.scss").parse
+  end
+
+  def test_extend_in_media_in_rule
+    assert_equal(<<CSS, render(<<SCSS))
+ media screen {
+  .foo {
+    a: b; } }
+CSS
+.foo {
+  @media screen {
+    @extend %bar;
+  }
+}
+
+ media screen {
+  %bar {
+    a: b;
+  }
+}
+SCSS
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/scss/test_helper.rb 
b/backends/css/gems/sass-3.2.12/test/sass/scss/test_helper.rb
new file mode 100644
index 0000000..11e177d
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/scss/test_helper.rb
@@ -0,0 +1,37 @@
+require File.dirname(__FILE__) + '/../../test_helper'
+require 'sass/engine'
+
+module ScssTestHelper
+  def assert_parses(scss)
+    assert_equal scss.rstrip, render(scss).rstrip
+  end
+
+  def assert_not_parses(expected, scss)
+    raise "Template must include <err> where an error is expected" unless scss.include?("<err>")
+
+    after, was = scss.split("<err>")
+    line = after.count("\n") + 1
+
+    after.gsub!(/\s*\n\s*$/, '')
+    after.gsub!(/.*\n/, '')
+    after = "..." + after[-15..-1] if after.size > 18
+
+    was.gsub!(/^\s*\n\s*/, '')
+    was.gsub!(/\n.*/, '')
+    was = was[0...15] + "..." if was.size > 18
+
+    to_render = scss.sub("<err>", "")
+    render(to_render)
+    assert(false, "Expected syntax error for:\n#{to_render}\n")
+  rescue Sass::SyntaxError => err
+    assert_equal("Invalid CSS after \"#{after}\": expected #{expected}, was \"#{was}\"",
+      err.message)
+    assert_equal line, err.sass_line
+  end
+
+  def render(scss, options = {})
+    options[:syntax] ||= :scss
+    munge_filename options
+    Sass::Engine.new(scss, options).render
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/_cached_import_option_partial.scss 
b/backends/css/gems/sass-3.2.12/test/sass/templates/_cached_import_option_partial.scss
new file mode 100644
index 0000000..e4f9d3c
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/_cached_import_option_partial.scss
@@ -0,0 +1 @@
+partial {value: whatever()}
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/_double_import_loop2.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/_double_import_loop2.sass
new file mode 100644
index 0000000..efa4eb5
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/_double_import_loop2.sass
@@ -0,0 +1 @@
+ import "double_import_loop1"
\ No newline at end of file
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/_filename_fn_import.scss 
b/backends/css/gems/sass-3.2.12/test/sass/templates/_filename_fn_import.scss
new file mode 100644
index 0000000..4a1eec4
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/_filename_fn_import.scss
@@ -0,0 +1,11 @@
+ mixin imported-mixin {
+  imported-mixin: filename();
+}
+
+ function imported-function() {
+  @return filename();
+}
+
+filename {
+  imported: filename();
+}
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/_imported_charset_ibm866.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/_imported_charset_ibm866.sass
new file mode 100644
index 0000000..b679317
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/_imported_charset_ibm866.sass
@@ -0,0 +1,4 @@
+ charset "IBM866"
+
+.bar
+  a: �
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/_imported_charset_utf8.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/_imported_charset_utf8.sass
new file mode 100644
index 0000000..cecdc5b
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/_imported_charset_utf8.sass
@@ -0,0 +1,4 @@
+ charset "UTF-8"
+
+.bar
+  a: щ
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/_imported_content.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/_imported_content.sass
new file mode 100644
index 0000000..65c4e33
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/_imported_content.sass
@@ -0,0 +1,3 @@
+ mixin foo
+  a
+    @content
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/_partial.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/_partial.sass
new file mode 100644
index 0000000..bef627d
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/_partial.sass
@@ -0,0 +1,2 @@
+#foo
+  :background-color #baf
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/_same_name_different_partiality.scss 
b/backends/css/gems/sass-3.2.12/test/sass/templates/_same_name_different_partiality.scss
new file mode 100644
index 0000000..a04e83a
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/_same_name_different_partiality.scss
@@ -0,0 +1 @@
+.foo {partial: yes}
\ No newline at end of file
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/alt.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/alt.sass
new file mode 100644
index 0000000..cbcb648
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/alt.sass
@@ -0,0 +1,16 @@
+h1
+  :float  left
+  :width  274px
+  height: 75px
+  margin: 0
+  background:
+    repeat: no-repeat
+    :image none
+  a:hover, a:visited
+    color: green
+  b:hover
+    color: red
+    :background-color green
+  const
+    nosp: 1 + 2
+    sp : 1 + 2
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/basic.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/basic.sass
new file mode 100644
index 0000000..5d4bf61
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/basic.sass
@@ -0,0 +1,23 @@
+
+
+body
+  :font Arial
+  :background blue
+
+#page
+  :width 700px
+  :height 100
+  #header
+    :height 300px
+    h1
+      :font-size 50px
+      :color     blue
+
+#content.user.show
+  #container.top
+    #column.left
+      :width 100px
+    #column.right
+      :width 600px
+  #container.bottom
+    :background brown
\ No newline at end of file
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/bork1.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/bork1.sass
new file mode 100644
index 0000000..70ba9db
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/bork1.sass
@@ -0,0 +1,2 @@
+bork
+  :bork $bork
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/bork2.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/bork2.sass
new file mode 100644
index 0000000..462afb5
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/bork2.sass
@@ -0,0 +1,2 @@
+bork
+  :bork: bork;
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/bork3.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/bork3.sass
new file mode 100644
index 0000000..9d0fb70
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/bork3.sass
@@ -0,0 +1,2 @@
+bork
+  bork:
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/bork4.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/bork4.sass
new file mode 100644
index 0000000..75610d9
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/bork4.sass
@@ -0,0 +1,2 @@
+
+bork: blah
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/bork5.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/bork5.sass
new file mode 100644
index 0000000..df156d7
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/bork5.sass
@@ -0,0 +1,3 @@
+bork
+  /* foo */
+  :bork $bork
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/cached_import_option.scss 
b/backends/css/gems/sass-3.2.12/test/sass/templates/cached_import_option.scss
new file mode 100644
index 0000000..3ade543
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/cached_import_option.scss
@@ -0,0 +1,3 @@
+ import "cached_import_option_partial";
+
+main {value: whatever()}
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/compact.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/compact.sass
new file mode 100644
index 0000000..e37f86e
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/compact.sass
@@ -0,0 +1,17 @@
+#main
+  :width 15em
+  :color #0000ff
+  p
+    :border
+      :style dotted
+      /* Nested comment
+        More nested stuff
+      :width 2px
+  .cool
+    :width 100px
+
+#left
+  :font
+    :size 2em
+    :weight bold
+  :float left
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/complex.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/complex.sass
new file mode 100644
index 0000000..e3c3301
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/complex.sass
@@ -0,0 +1,305 @@
+body
+  :margin 0
+  :font   0.85em "Lucida Grande", "Trebuchet MS", Verdana, sans-serif
+  :color #fff
+  :background url(/images/global_bg.gif)
+
+#page
+  :width      900px
+  :margin     0 auto
+  :background #440008
+  :border-top
+    :width 5px
+    :style solid
+    :color #ff8500
+
+#header
+  :height  75px
+  :padding 0
+  h1
+    :float  left
+    :width  274px
+    :height 75px
+    :margin 0
+    :background
+      :image url(/images/global_logo.gif)
+      /* Crazy nested comment
+      :repeat no-repeat
+    :text-indent -9999px
+  .status
+    :float   right
+    :padding
+      :top .5em
+      :left .5em
+      :right .5em
+      :bottom 0
+    p
+      :float  left
+      :margin
+        :top 0
+        :right 0.5em
+        :bottom 0
+        :left 0
+    ul
+      :float   left
+      :margin  0
+      :padding 0
+    li
+      :list-style-type none
+      :display inline
+      :margin 0 5px
+    a:link, a:visited
+      :color #ff8500
+      :text-decoration none
+    a:hover
+      :text-decoration underline
+  .search
+    :float  right
+    :clear  right
+    :margin 12px 0 0 0
+    form
+      :margin 0
+    input
+      :margin 0 3px 0 0
+      :padding 2px
+      :border none
+
+#menu 
+  :clear both
+  :text-align right
+  :height 20px
+  :border-bottom 5px solid #006b95
+  :background #00a4e4
+  .contests
+    ul
+      :margin 0 5px 0 0
+      :padding 0
+      li 
+        :list-style-type none
+        :margin 0 5px
+        :padding 5px 5px 0 5px
+        :display inline
+        :font-size 1.1em
+        // This comment is properly indented
+        :color #fff
+        :background #00a4e4
+    a:link, a:visited
+      :color #fff
+      :text-decoration none
+      :font-weight bold
+    a:hover
+      :text-decoration underline
+
+//General content information
+#content
+  :clear both
+  .container
+    :clear both
+    .column
+      :float left
+      .right
+        :float right
+  a:link, a:visited
+    :color #93d700
+    :text-decoration none
+  a:hover
+    :text-decoration underline
+
+// A hard tab:
+       
+
+#content
+  p, div
+    :width 40em
+    li, dt, dd
+      :color #ddffdd
+      :background-color #4792bb
+  .container.video
+    .column.left
+      :width 200px
+      .box
+        :margin-top 10px
+        p 
+          :margin 0 1em auto 1em
+      .box.participants 
+        img
+          :float  left
+          :margin 0 1em auto 1em
+          :border 1px solid #6e000d
+            :style solid
+        h2
+          :margin 0 0 10px 0
+          :padding 0.5em
+          /* The background image is a gif!
+          :background #6e000d url(/images/hdr_participant.gif) 2px 2px no-repeat
+          /* Okay check this out
+            Multiline comments
+            Wow dude
+            I mean seriously, WOW
+          :text-indent -9999px
+          // And also...
+            Multiline comments that don't output!
+            Snazzy, no?
+          :border
+            :top
+              :width 5px
+              :style solid
+              :color #a20013
+            :right
+              :width 1px
+              :style dotted
+    .column.middle
+      :width 500px
+    .column.right
+      :width 200px
+      .box
+        :margin-top 0
+        p
+          :margin 0 1em auto 1em
+    .column
+      p
+        :margin-top 0
+
+#content.contests
+  .container.information 
+    .column.right 
+      .box
+        :margin 1em 0
+      .box.videos
+        .thumbnail img 
+          :width         200px
+          :height        150px
+          :margin-bottom 5px
+        a:link, a:visited
+          :color #93d700
+          :text-decoration none
+        a:hover
+          :text-decoration underline
+      .box.votes 
+        a
+          :display block
+          :width  200px
+          :height 60px
+          :margin 15px 0
+          :background url(/images/btn_votenow.gif) no-repeat
+          :text-indent -9999px
+          :outline none
+          :border  none
+        h2
+          :margin  52px 0 10px 0
+          :padding 0.5em
+          :background #6e000d url(/images/hdr_videostats.gif) 2px 2px no-repeat
+          :text-indent -9999px
+          :border-top 5px solid #a20013
+
+#content.contests 
+  .container.video
+    .box.videos
+      h2
+        :margin  0
+        :padding 0.5em
+        :background #6e000d url(/images/hdr_newestclips.gif) 2px 2px no-repeat
+        :text-indent -9999px
+        :border-top 5px solid #a20013
+      table
+        :width 100
+        td 
+          :padding 1em
+          :width 25
+          :vertical-align top
+          p
+            :margin 0 0 5px 0
+          a:link, a:visited    
+            :color #93d700
+            :text-decoration none
+          a:hover
+            :text-decoration underline
+      .thumbnail
+        :float left
+        img
+          :width  80px
+          :height 60px
+          :margin 0 10px 0 0
+          :border 1px solid #6e000d
+
+#content 
+  .container.comments 
+    .column
+      :margin-top 15px
+    .column.left
+      :width 600px
+      .box 
+        ol
+          :margin  0
+          :padding 0
+        li
+          :list-style-type none
+          :padding 10px
+          :margin 0 0 1em 0
+          :background #6e000d
+          :border-top 5px solid #a20013
+          div
+            :margin-bottom 1em
+          ul
+            :text-align right
+            li
+              :display inline
+              :border none
+              :padding 0
+    .column.right
+      :width        290px
+      :padding-left 10px
+      h2
+        :margin 0
+        :padding 0.5em
+        :background #6e000d url(/images/hdr_addcomment.gif) 2px 2px no-repeat
+        :text-indent -9999px
+        :border-top 5px solid #a20013
+      .box
+        textarea
+          :width  290px
+          :height 100px
+          :border none
+
+#footer
+  :margin-top 10px
+  :padding    1.2em 1.5em
+  :background #ff8500
+  ul
+    :margin 0
+    :padding 0
+    :list-style-type none
+    li
+      :display inline
+      :margin  0 0.5em
+      :color   #440008
+  ul.links
+    :float left
+    a:link, a:visited
+      :color #440008
+      :text-decoration none
+    a:hover
+      :text-decoration underline
+  ul.copyright
+    :float right
+
+
+.clear 
+  :clear both
+
+.centered 
+  :text-align center
+
+img
+  :border none
+
+button.short 
+  :width   60px
+  :height  22px
+  :padding 0 0 2px 0
+  :color   #fff
+  :border  none
+  :background url(/images/btn_short.gif) no-repeat
+
+table
+  :border-collapse collapse
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/compressed.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/compressed.sass
new file mode 100644
index 0000000..675fea4
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/compressed.sass
@@ -0,0 +1,15 @@
+#main
+  :width 15em
+  :color #0000ff
+  p
+    :border
+      :style dotted
+      :width 2px
+  .cool
+    :width 100px
+
+#left
+  :font
+    :size 2em
+    :weight bold
+  :float left
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/double_import_loop1.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/double_import_loop1.sass
new file mode 100644
index 0000000..5477384
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/double_import_loop1.sass
@@ -0,0 +1 @@
+ import "double_import_loop2"
\ No newline at end of file
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/expanded.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/expanded.sass
new file mode 100644
index 0000000..e37f86e
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/expanded.sass
@@ -0,0 +1,17 @@
+#main
+  :width 15em
+  :color #0000ff
+  p
+    :border
+      :style dotted
+      /* Nested comment
+        More nested stuff
+      :width 2px
+  .cool
+    :width 100px
+
+#left
+  :font
+    :size 2em
+    :weight bold
+  :float left
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/filename_fn.scss 
b/backends/css/gems/sass-3.2.12/test/sass/templates/filename_fn.scss
new file mode 100644
index 0000000..e43d508
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/filename_fn.scss
@@ -0,0 +1,18 @@
+ import "filename_fn_import";
+
+ mixin local-mixin {
+  local-mixin: filename();
+}
+
+ function local-function() {
+  @return filename();
+}
+
+filename {
+  local: filename();
+  @include local-mixin;
+  local-function: local-function();
+
+  @include imported-mixin;
+  imported-function: imported-function();
+}
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/if.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/if.sass
new file mode 100644
index 0000000..787bff0
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/if.sass
@@ -0,0 +1,11 @@
+a
+  @if true
+    branch: if
+  @else
+    branch: else
+
+b
+  @if false
+    branch: if
+  @else
+    branch: else
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/import.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/import.sass
new file mode 100644
index 0000000..512e4a2
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/import.sass
@@ -0,0 +1,12 @@
+$preconst: hello
+
+=premixin
+  pre-mixin: here
+
+ import importee.sass, scss_importee, "basic.sass", basic.css, ../results/complex.css
+ import partial.sass
+
+nonimported
+  :myconst $preconst
+  :otherconst $postconst
+  +postmixin
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/import_charset.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/import_charset.sass
new file mode 100644
index 0000000..b85447c
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/import_charset.sass
@@ -0,0 +1,9 @@
+.foo
+  a: b
+
+ import "foo.css"
+
+// Even though the imported file is in IBM866,
+// since the root file is in UTF-8/ASCII
+// the output will end up being UTF-8.
+ import "imported_charset_ibm866"
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/import_charset_1_8.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/import_charset_1_8.sass
new file mode 100644
index 0000000..8a89b82
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/import_charset_1_8.sass
@@ -0,0 +1,6 @@
+.foo
+  a: b
+
+ import "foo.css"
+
+ import "imported_charset_ibm866"
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/import_charset_ibm866.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/import_charset_ibm866.sass
new file mode 100644
index 0000000..164e702
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/import_charset_ibm866.sass
@@ -0,0 +1,11 @@
+ charset "IBM866"
+
+.foo
+  a: b
+
+ import "foo.css"
+
+// Even though the imported file is in UTF-8,
+// since the root file is in IBM866
+// the output will end up being IBM866.
+ import "imported_charset_utf8"
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/import_content.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/import_content.sass
new file mode 100644
index 0000000..2ef8ad9
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/import_content.sass
@@ -0,0 +1,4 @@
+ import imported_content
+
+ include foo
+  b: c
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/importee.less 
b/backends/css/gems/sass-3.2.12/test/sass/templates/importee.less
new file mode 100644
index 0000000..ac03a0e
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/importee.less
@@ -0,0 +1,2 @@
+.foo    {a: b}
+.bar () {c: d}
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/importee.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/importee.sass
new file mode 100644
index 0000000..ddc8da8
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/importee.sass
@@ -0,0 +1,19 @@
+$postconst: goodbye
+
+=postmixin
+  post-mixin: here
+
+imported
+  :otherconst $preconst
+  :myconst $postconst
+  +premixin
+
+ import basic
+
+midrule
+  :inthe middle
+
+=crazymixin
+  foo: bar
+  baz
+    blat: bang
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/line_numbers.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/line_numbers.sass
new file mode 100644
index 0000000..2afc103
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/line_numbers.sass
@@ -0,0 +1,13 @@
+foo
+  bar: baz
+
+=premixin
+  squggle
+    blat: bang
+
+$preconst: 12
+
+ import importee
+
+umph
+  +crazymixin
\ No newline at end of file
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/mixin_bork.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/mixin_bork.sass
new file mode 100644
index 0000000..844acb9
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/mixin_bork.sass
@@ -0,0 +1,5 @@
+=outer-mixin
+  +error-mixin
+
+foo
+  +outer-mixin
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/mixins.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/mixins.sass
new file mode 100644
index 0000000..633a626
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/mixins.sass
@@ -0,0 +1,76 @@
+$yellow: #fc0
+
+=bordered
+  :border
+    :top
+      :width 2px
+      :color $yellow
+    :left
+      :width 1px
+      :color #000
+  -moz-border-radius: 10px
+
+=header-font
+  :color #f00
+  :font
+    :size 20px
+
+=compound
+  +header-font
+  +bordered
+
+=complex
+  +header-font
+  text:
+    decoration: none
+  &:after
+    content: "."
+    display: block
+    height: 0
+    clear: both
+    visibility: hidden
+  * html &
+    height: 1px
+    +header-font
+=deep
+  a:hover
+    :text-decoration underline
+    +compound
+
+
+#main
+  :width 15em
+  :color #0000ff
+  p
+    +bordered
+    :border
+      :style dotted
+      :width 2px
+  .cool
+    :width 100px
+
+#left
+  +bordered
+  :font
+    :size 2em
+    :weight bold
+  :float left
+
+#right
+  +bordered
+  +header-font
+  :float right
+
+.bordered
+  +bordered
+
+.complex
+  +complex
+
+.more-complex
+  +complex
+  +deep
+  display: inline
+  -webkit-nonsense:
+    top-right: 1px
+    bottom-left: 1px
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/multiline.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/multiline.sass
new file mode 100644
index 0000000..83140e9
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/multiline.sass
@@ -0,0 +1,20 @@
+#main,
+#header
+  height: 50px
+  div
+    width: 100px
+    a,
+    em
+      span
+        color: pink
+
+#one,
+#two,
+#three
+  div.nested,
+  span.nested,
+  p.nested
+    :font
+      :weight bold
+    :border-color red
+    :display block
\ No newline at end of file
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/nested.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/nested.sass
new file mode 100644
index 0000000..a9ee4e0
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/nested.sass
@@ -0,0 +1,25 @@
+#main
+  :width 15em
+  :color #0000ff
+  p
+    :border
+      :style dotted
+      /* Nested comment
+        More nested stuff
+      :width 2px
+  .cool
+    :width 100px
+
+#left
+  :font
+    :size 2em
+    :weight bold
+  :float left
+
+#right
+  .header
+    :border-style solid
+  .body
+    :border-style dotted
+  .footer
+    :border-style dashed
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork1.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork1.sass
new file mode 100644
index 0000000..638496e
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork1.sass
@@ -0,0 +1,2 @@
+
+ import bork1
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork2.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork2.sass
new file mode 100644
index 0000000..28b0bc8
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork2.sass
@@ -0,0 +1,2 @@
+
+ import bork2
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork3.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork3.sass
new file mode 100644
index 0000000..eeccd66
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork3.sass
@@ -0,0 +1,2 @@
+
+ import bork3
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork4.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork4.sass
new file mode 100644
index 0000000..173c947
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/nested_bork4.sass
@@ -0,0 +1,2 @@
+
+ import bork4
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/nested_import.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/nested_import.sass
new file mode 100644
index 0000000..24b48e5
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/nested_import.sass
@@ -0,0 +1,2 @@
+.foo
+  @import basic
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/nested_mixin_bork.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/nested_mixin_bork.sass
new file mode 100644
index 0000000..f79fdc7
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/nested_mixin_bork.sass
@@ -0,0 +1,6 @@
+
+
+=error-mixin
+  width: 1px * 1em
+
+ import mixin_bork
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/options.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/options.sass
new file mode 100644
index 0000000..7e9d3c4
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/options.sass
@@ -0,0 +1,2 @@
+foo
+  style: option("style")
\ No newline at end of file
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/parent_ref.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/parent_ref.sass
new file mode 100644
index 0000000..70cafb8
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/parent_ref.sass
@@ -0,0 +1,25 @@
+a
+  :color #000
+  &:hover
+    :color #f00
+
+p, div
+  :width 100em
+  & foo
+    :width 10em
+  &:hover, bar
+    :height 20em
+
+#cool
+  :border
+    :style solid
+    :width 2em
+  .ie7 &, .ie6 &
+    :content string("Totally not cool.")
+  .firefox &
+    :content string("Quite cool.")
+
+.wow, .snazzy
+  :font-family fantasy
+  &:hover, &:visited
+    :font-weight bold
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/same_name_different_ext.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/same_name_different_ext.sass
new file mode 100644
index 0000000..c00a8b5
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/same_name_different_ext.sass
@@ -0,0 +1,2 @@
+.foo
+  ext: sass
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/same_name_different_ext.scss 
b/backends/css/gems/sass-3.2.12/test/sass/templates/same_name_different_ext.scss
new file mode 100644
index 0000000..38090ce
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/same_name_different_ext.scss
@@ -0,0 +1 @@
+.foo {ext: scss}
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/same_name_different_partiality.scss 
b/backends/css/gems/sass-3.2.12/test/sass/templates/same_name_different_partiality.scss
new file mode 100644
index 0000000..8ba7d06
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/same_name_different_partiality.scss
@@ -0,0 +1 @@
+.foo {partial: no}
\ No newline at end of file
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/script.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/script.sass
new file mode 100644
index 0000000..3b3c85f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/script.sass
@@ -0,0 +1,101 @@
+$width: 10em + 20
+$color: #00ff98
+$main_text: #ffa
+$num: 10
+$dec: 10.2
+$dec_0: 99.0
+$neg: -10
+$esc: 10\+12
+$str: Hello\!
+$qstr: "Quo\"ted\"!"
+$hstr: Hyph-en\!
+$space: #{5 + 4} hi there
+$percent: 11%
+$complex: 1px/1em
+
+#main
+  :content $str
+  :qstr $qstr
+  :hstr $hstr
+  :width $width
+  :background-color #000
+  :color $main_text
+  :short-color #123
+  :named-color olive
+  :con "foo" bar ($space "boom")
+  :con2 "noquo" quo
+  #sidebar
+    :background-color $color
+    :num
+      :normal $num
+      :dec $dec
+      :dec0 $dec_0
+      :neg $neg
+    :esc $esc
+    :many 1 + 2 + 3
+    :order 1 + 2 * 3
+    :complex ((1 + 2) + 15)+#3a8b9f + (hi+(1 +1+ 2)*   4)
+
+#plus
+  :num
+    :num 5+2
+    :num-un 10em + 15em
+    :num-un2 10 + 13em
+    :num-neg 10 + -.13
+    :str 100 * 1px
+    :col 13 + #aaa
+    :perc $percent + 20%
+  :str
+    :str "hi" + "\ there"
+    :str2 "hi" + " there"
+    :col "14em solid " + #123
+    :num "times: " + 13
+  :col
+    :num #f02 + 123.5
+    :col #12A + #405162
+
+#minus
+  :num
+    :num 912 - 12
+  :col
+    :num #fffffa - 5.2
+    :col #abcdef - #fedcba
+  :unary
+    :num -1
+    :const -$neg
+    :paren -(5 + 6)
+    :two --12
+    :many --------12
+    :crazy -----(5 + ---$neg)
+
+#times
+  :num
+    :num 2 * 3.5
+    :col 2 * #3a4b5c
+  :col
+    :num #12468a * 0.5
+    :col #121212 * #020304
+    
+#div
+  :num
+    :num (10 / 3.0)
+    :num2 (10 / 3)
+  :col
+    :num #12468a / 2
+    :col #abcdef / #0f0f0f
+  :comp  $complex * 1em
+
+#mod
+  :num
+    :num 17 % 3
+  :col
+    :col #5f6e7d % #10200a
+    :num #aaabac % 3
+
+#const
+  :escaped
+    :quote \$foo \!bar
+  :default $str !important
+
+#regression
+  :a (3 + 2) - 1
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/scss_import.scss 
b/backends/css/gems/sass-3.2.12/test/sass/templates/scss_import.scss
new file mode 100644
index 0000000..f64d80b
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/scss_import.scss
@@ -0,0 +1,11 @@
+$preconst: hello;
+
+ mixin premixin {pre-mixin: here}
+
+ import "importee.sass", "scss_importee", "basic.sass", "basic.css", "../results/complex.css";
+ import "partial.sass";
+
+nonimported {
+  myconst: $preconst;
+  otherconst: $postconst;
+  @include postmixin; }
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/scss_importee.scss 
b/backends/css/gems/sass-3.2.12/test/sass/templates/scss_importee.scss
new file mode 100644
index 0000000..df49e68
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/scss_importee.scss
@@ -0,0 +1 @@
+scss {imported: yes}
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/single_import_loop.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/single_import_loop.sass
new file mode 100644
index 0000000..db50397
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/single_import_loop.sass
@@ -0,0 +1 @@
+ import "single_import_loop"
\ No newline at end of file
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/subdir/nested_subdir/_nested_partial.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/subdir/nested_subdir/_nested_partial.sass
new file mode 100644
index 0000000..04008f6
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/subdir/nested_subdir/_nested_partial.sass
@@ -0,0 +1,2 @@
+#nested
+  :relative true
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/subdir/nested_subdir/nested_subdir.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/subdir/nested_subdir/nested_subdir.sass
new file mode 100644
index 0000000..aae9eeb
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/subdir/nested_subdir/nested_subdir.sass
@@ -0,0 +1,3 @@
+#pi
+  :width 314px
+    
\ No newline at end of file
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/subdir/subdir.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/subdir/subdir.sass
new file mode 100644
index 0000000..8fff002
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/subdir/subdir.sass
@@ -0,0 +1,6 @@
+ import nested_subdir/nested_partial.sass
+
+#subdir
+  :font
+    :size 20px
+    :weight bold
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/units.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/units.sass
new file mode 100644
index 0000000..47b7744
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/units.sass
@@ -0,0 +1,11 @@
+b
+  :foo 0.5 * 10px
+  :bar 10zzz * 12px / 5zzz
+  :baz percentage(12.0px / 18px)
+  :many-units 10.0zzz / 3yyy * 12px / 5zzz * 3yyy / 3px * 4em
+  :mm 5mm + 1cm
+  :pc 1pc + 12pt
+  :pt 72pt - 2in
+  :inches 1in + 2.54cm
+  :more-inches 1in + ((72pt * 2in) + (36pt * 1in)) / 2.54cm
+  :mixed (1 + (1em * 6px / 3in)) * 4in / 2em
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/warn.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/warn.sass
new file mode 100644
index 0000000..514c44a
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/warn.sass
@@ -0,0 +1,3 @@
+ warn "In the main file"
+ import warn_imported.sass
++emits-a-warning
diff --git a/backends/css/gems/sass-3.2.12/test/sass/templates/warn_imported.sass 
b/backends/css/gems/sass-3.2.12/test/sass/templates/warn_imported.sass
new file mode 100644
index 0000000..493bd8a
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/templates/warn_imported.sass
@@ -0,0 +1,4 @@
+ warn "Imported"
+
+=emits-a-warning
+  @warn "In an imported mixin"
diff --git a/backends/css/gems/sass-3.2.12/test/sass/test_helper.rb 
b/backends/css/gems/sass-3.2.12/test/sass/test_helper.rb
new file mode 100644
index 0000000..919806e
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/test_helper.rb
@@ -0,0 +1,8 @@
+test_dir = File.dirname(__FILE__)
+$:.unshift test_dir unless $:.include?(test_dir)
+
+class Test::Unit::TestCase
+  def absolutize(file)
+    File.expand_path("#{File.dirname(__FILE__)}/#{file}")
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/util/multibyte_string_scanner_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/util/multibyte_string_scanner_test.rb
new file mode 100755
index 0000000..bc0db14
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/util/multibyte_string_scanner_test.rb
@@ -0,0 +1,147 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+require File.dirname(__FILE__) + '/../../test_helper'
+
+unless Sass::Util.ruby1_8?
+  class MultibyteStringScannerTest < Test::Unit::TestCase
+    def setup
+      @scanner = Sass::Util::MultibyteStringScanner.new("cölorfül")
+    end
+
+    def test_initial
+      assert_scanner_state 0, 0, nil, nil
+    end
+
+    def test_check
+      assert_equal 'cö', @scanner.check(/../)
+      assert_scanner_state 0, 0, 2, 3
+      assert_equal 0, @scanner.pos
+      assert_equal 0, @scanner.pos
+      assert_equal 2, @scanner.matched_size
+      assert_equal 3, @scanner.byte_matched_size
+    end
+
+    def test_check_until
+      assert_equal 'cölorfü', @scanner.check_until(/f./)
+      assert_scanner_state 0, 0, 2, 3
+    end
+
+    def test_getch
+      assert_equal 'c', @scanner.getch
+      assert_equal 'ö', @scanner.getch
+      assert_scanner_state 2, 3, 1, 2
+    end
+
+    def test_match?
+      assert_equal 2, @scanner.match?(/../)
+      assert_scanner_state 0, 0, 2, 3
+    end
+
+    def test_peek
+      assert_equal 'cö', @scanner.peek(2)
+      assert_scanner_state 0, 0, nil, nil
+    end
+
+    def test_rest_size
+      assert_equal 'cö', @scanner.scan(/../)
+      assert_equal 6, @scanner.rest_size
+    end
+
+    def test_scan
+      assert_equal 'cö', @scanner.scan(/../)
+      assert_scanner_state 2, 3, 2, 3
+    end
+
+    def test_scan_until
+      assert_equal 'cölorfü', @scanner.scan_until(/f./)
+      assert_scanner_state 7, 9, 2, 3
+    end
+
+    def test_skip
+      assert_equal 2, @scanner.skip(/../)
+      assert_scanner_state 2, 3, 2, 3
+    end
+
+    def test_skip_until
+      assert_equal 7, @scanner.skip_until(/f./)
+      assert_scanner_state 7, 9, 2, 3
+    end
+
+    def test_set_pos
+      @scanner.pos = 7
+      assert_scanner_state 7, 9, nil, nil
+      @scanner.pos = 6
+      assert_scanner_state 6, 7, nil, nil
+      @scanner.pos = 1
+      assert_scanner_state 1, 1, nil, nil
+    end
+
+    def test_reset
+      @scanner.scan(/../)
+      @scanner.reset
+      assert_scanner_state 0, 0, nil, nil
+    end
+
+    def test_scan_full
+      assert_equal 'cö', @scanner.scan_full(/../, true, true)
+      assert_scanner_state 2, 3, 2, 3
+
+      @scanner.reset
+      assert_equal 'cö', @scanner.scan_full(/../, false, true)
+      assert_scanner_state 0, 0, 2, 3
+
+      @scanner.reset
+      assert_nil @scanner.scan_full(/../, true, false)
+      assert_scanner_state 2, 3, 2, 3
+
+      @scanner.reset
+      assert_nil @scanner.scan_full(/../, false, false)
+      assert_scanner_state 0, 0, 2, 3
+    end
+
+    def test_search_full
+      assert_equal 'cölorfü', @scanner.search_full(/f./, true, true)
+      assert_scanner_state 7, 9, 2, 3
+
+      @scanner.reset
+      assert_equal 'cölorfü', @scanner.search_full(/f./, false, true)
+      assert_scanner_state 0, 0, 2, 3
+
+      @scanner.reset
+      assert_nil @scanner.search_full(/f./, true, false)
+      assert_scanner_state 7, 9, 2, 3
+
+      @scanner.reset
+      assert_nil @scanner.search_full(/f./, false, false)
+      assert_scanner_state 0, 0, 2, 3
+    end
+
+    def test_set_string
+      @scanner.scan(/../)
+      @scanner.string = 'föóbâr'
+      assert_scanner_state 0, 0, nil, nil
+    end
+
+    def test_terminate
+      @scanner.scan(/../)
+      @scanner.terminate
+      assert_scanner_state 8, 10, nil, nil
+    end
+
+    def test_unscan
+      @scanner.scan(/../)
+      @scanner.scan_until(/f./)
+      @scanner.unscan
+      assert_scanner_state 2, 3, nil, nil
+    end
+
+    private
+
+    def assert_scanner_state(pos, byte_pos, matched_size, byte_matched_size)
+      assert_equal pos, @scanner.pos, 'pos'
+      assert_equal byte_pos, @scanner.byte_pos, 'byte_pos'
+      assert_equal matched_size, @scanner.matched_size, 'matched_size'
+      assert_equal byte_matched_size, @scanner.byte_matched_size, 'byte_matched_size'
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/util/subset_map_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/util/subset_map_test.rb
new file mode 100755
index 0000000..b595394
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/util/subset_map_test.rb
@@ -0,0 +1,91 @@
+#!/usr/bin/env ruby
+require File.dirname(__FILE__) + '/../../test_helper'
+
+class SubsetMapTest < Test::Unit::TestCase
+  def setup
+    @ssm = Sass::Util::SubsetMap.new
+    @ssm[Set[1, 2]] = "Foo"
+    @ssm[Set["fizz", "fazz"]] = "Bar"
+
+    @ssm[Set[:foo, :bar]] = "Baz"
+    @ssm[Set[:foo, :bar, :baz]] = "Bang"
+
+    @ssm[Set[:bip, :bop, :blip]] = "Qux"
+    @ssm[Set[:bip, :bop]] = "Thram"
+  end
+
+  def test_equal_keys
+    assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2])
+    assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz"])
+  end
+
+  def test_subset_keys
+    assert_equal [["Foo", Set[1, 2]]], @ssm.get(Set[1, 2, "fuzz"])
+    assert_equal [["Bar", Set["fizz", "fazz"]]], @ssm.get(Set["fizz", "fazz", 3])
+  end
+
+  def test_superset_keys
+    assert_equal [], @ssm.get(Set[1])
+    assert_equal [], @ssm.get(Set[2])
+    assert_equal [], @ssm.get(Set["fizz"])
+    assert_equal [], @ssm.get(Set["fazz"])
+  end
+
+  def test_disjoint_keys
+    assert_equal [], @ssm.get(Set[3, 4])
+    assert_equal [], @ssm.get(Set["fuzz", "frizz"])
+    assert_equal [], @ssm.get(Set["gran", 15])
+  end
+
+  def test_semi_disjoint_keys
+    assert_equal [], @ssm.get(Set[2, 3])
+    assert_equal [], @ssm.get(Set["fizz", "fuzz"])
+    assert_equal [], @ssm.get(Set[1, "fazz"])
+  end
+
+  def test_empty_key_set
+    assert_raise(ArgumentError) { ssm[Set[]] = "Fail"}
+  end
+
+  def test_empty_key_get
+    assert_equal [], @ssm.get(Set[])
+  end
+
+  def test_multiple_subsets
+    assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, "fizz", "fazz"])
+    assert_equal [["Foo", Set[1, 2]], ["Bar", Set["fizz", "fazz"]]], @ssm.get(Set[1, 2, 3, "fizz", "fazz", 
"fuzz"])
+
+    assert_equal [["Baz", Set[:foo, :bar]]], @ssm.get(Set[:foo, :bar])
+    assert_equal [["Baz", Set[:foo, :bar]], ["Bang", Set[:foo, :bar, :baz]]], @ssm.get(Set[:foo, :bar, :baz])
+  end
+
+  def test_bracket_bracket
+    assert_equal ["Foo"], @ssm[Set[1, 2, "fuzz"]]
+    assert_equal ["Baz", "Bang"], @ssm[Set[:foo, :bar, :baz]]
+  end
+
+  def test_order_preserved
+    @ssm[Set[10, 11, 12]] = 1
+    @ssm[Set[10, 11]] = 2
+    @ssm[Set[11]] = 3
+    @ssm[Set[11, 12]] = 4
+    @ssm[Set[9, 10, 11, 12, 13]] = 5
+    @ssm[Set[10, 13]] = 6
+
+    assert_equal(
+      [[1, Set[10, 11, 12]], [2, Set[10, 11]], [3, Set[11]], [4, Set[11, 12]],
+        [5, Set[9, 10, 11, 12, 13]], [6, Set[10, 13]]],
+      @ssm.get(Set[9, 10, 11, 12, 13]))
+  end
+
+  def test_multiple_equal_values
+    @ssm[Set[11, 12]] = 1
+    @ssm[Set[12, 13]] = 2
+    @ssm[Set[13, 14]] = 1
+    @ssm[Set[14, 15]] = 1
+
+    assert_equal(
+      [[1, Set[11, 12]], [2, Set[12, 13]], [1, Set[13, 14]], [1, Set[14, 15]]],
+      @ssm.get(Set[11, 12, 13, 14, 15]))
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/sass/util_test.rb 
b/backends/css/gems/sass-3.2.12/test/sass/util_test.rb
new file mode 100755
index 0000000..dc176fc
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/sass/util_test.rb
@@ -0,0 +1,361 @@
+#!/usr/bin/env ruby
+require File.dirname(__FILE__) + '/../test_helper'
+require 'pathname'
+require 'tmpdir'
+
+class UtilTest < Test::Unit::TestCase
+  include Sass::Util
+
+  def test_scope
+    assert(File.exist?(scope("Rakefile")))
+  end
+
+  def test_to_hash
+    assert_equal({
+        :foo => 1,
+        :bar => 2,
+        :baz => 3
+      }, to_hash([[:foo, 1], [:bar, 2], [:baz, 3]]))
+  end
+
+  def test_map_keys
+    assert_equal({
+        "foo" => 1,
+        "bar" => 2,
+        "baz" => 3
+      }, map_keys({:foo => 1, :bar => 2, :baz => 3}) {|k| k.to_s})
+  end
+
+  def test_map_vals
+    assert_equal({
+        :foo => "1",
+        :bar => "2",
+        :baz => "3"
+      }, map_vals({:foo => 1, :bar => 2, :baz => 3}) {|k| k.to_s})
+  end
+
+  def test_map_hash
+    assert_equal({
+        "foo" => "1",
+        "bar" => "2",
+        "baz" => "3"
+      }, map_hash({:foo => 1, :bar => 2, :baz => 3}) {|k, v| [k.to_s, v.to_s]})
+  end
+
+  def test_powerset
+    return unless Set[Set[]] == Set[Set[]] # There's a bug in Ruby 1.8.6 that breaks nested set equality
+    assert_equal([[].to_set].to_set,
+      powerset([]))
+    assert_equal([[].to_set, [1].to_set].to_set,
+      powerset([1]))
+    assert_equal([[].to_set, [1].to_set, [2].to_set, [1, 2].to_set].to_set,
+      powerset([1, 2]))
+    assert_equal([[].to_set, [1].to_set, [2].to_set, [3].to_set,
+        [1, 2].to_set, [2, 3].to_set, [1, 3].to_set, [1, 2, 3].to_set].to_set,
+      powerset([1, 2, 3]))
+  end
+
+  def test_restrict
+    assert_equal(0.5, restrict(0.5, 0..1))
+    assert_equal(1, restrict(2, 0..1))
+    assert_equal(1.3, restrict(2, 0..1.3))
+    assert_equal(0, restrict(-1, 0..1))
+  end
+
+  def test_merge_adjacent_strings
+    assert_equal(["foo bar baz", :bang, "biz bop", 12],
+      merge_adjacent_strings(["foo ", "bar ", "baz", :bang, "biz", " bop", 12]))
+    str = "foo"
+    assert_equal(["foo foo foo", :bang, "foo foo", 12],
+      merge_adjacent_strings([str, " ", str, " ", str, :bang, str, " ", str, 12]))
+  end
+
+  def test_intersperse
+    assert_equal(["foo", " ", "bar", " ", "baz"],
+      intersperse(%w[foo bar baz], " "))
+    assert_equal([], intersperse([], " "))
+  end
+
+  def test_substitute
+    assert_equal(["foo", "bar", "baz", 3, 4],
+      substitute([1, 2, 3, 4], [1, 2], ["foo", "bar", "baz"]))
+    assert_equal([1, "foo", "bar", "baz", 4],
+      substitute([1, 2, 3, 4], [2, 3], ["foo", "bar", "baz"]))
+    assert_equal([1, 2, "foo", "bar", "baz"],
+      substitute([1, 2, 3, 4], [3, 4], ["foo", "bar", "baz"]))
+
+    assert_equal([1, "foo", "bar", "baz", 2, 3, 4],
+      substitute([1, 2, 2, 2, 3, 4], [2, 2], ["foo", "bar", "baz"]))
+  end
+
+  def test_strip_string_array
+    assert_equal(["foo ", " bar ", " baz"],
+      strip_string_array([" foo ", " bar ", " baz "]))
+    assert_equal([:foo, " bar ", " baz"],
+      strip_string_array([:foo, " bar ", " baz "]))
+    assert_equal(["foo ", " bar ", :baz],
+      strip_string_array([" foo ", " bar ", :baz]))
+  end
+
+  def test_paths
+    assert_equal([[1, 3, 5], [2, 3, 5], [1, 4, 5], [2, 4, 5]],
+      paths([[1, 2], [3, 4], [5]]))
+    assert_equal([[]], paths([]))
+    assert_equal([[1, 2, 3]], paths([[1], [2], [3]]))
+  end
+
+  def test_lcs
+    assert_equal([1, 2, 3], lcs([1, 2, 3], [1, 2, 3]))
+    assert_equal([], lcs([], [1, 2, 3]))
+    assert_equal([], lcs([1, 2, 3], []))
+    assert_equal([1, 2, 3], lcs([5, 1, 4, 2, 3, 17], [0, 0, 1, 2, 6, 3]))
+
+    assert_equal([1], lcs([1, 2, 3, 4], [4, 3, 2, 1]))
+    assert_equal([1, 2], lcs([1, 2, 3, 4], [3, 4, 1, 2]))
+  end
+
+  def test_lcs_with_block
+    assert_equal(["1", "2", "3"],
+      lcs([1, 4, 2, 5, 3], [1, 2, 3]) {|a, b| a == b && a.to_s})
+    assert_equal([-4, 2, 8],
+      lcs([-5, 3, 2, 8], [-4, 1, 8]) {|a, b| (a - b).abs <= 1 && [a, b].max})
+  end
+
+  def test_group_by_to_a
+    assert_equal([[1, [1, 3, 5, 7]], [0, [2, 4, 6, 8]]],
+      group_by_to_a(1..8) {|i| i % 2})
+    assert_equal([[1, [1, 4, 7, 10]], [2, [2, 5, 8, 11]], [0, [3, 6, 9, 12]]],
+      group_by_to_a(1..12) {|i| i % 3})
+  end
+
+  def test_subsequence
+    assert(subsequence?([1, 2, 3], [1, 2, 3]))
+    assert(subsequence?([1, 2, 3], [1, :a, 2, :b, 3]))
+    assert(subsequence?([1, 2, 3], [:a, 1, :b, :c, 2, :d, 3, :e, :f]))
+
+    assert(!subsequence?([1, 2, 3], [1, 2]))
+    assert(!subsequence?([1, 2, 3], [1, 3, 2]))
+    assert(!subsequence?([1, 2, 3], [3, 2, 1]))
+  end
+
+  def test_silence_warnings
+    old_stderr, $stderr = $stderr, StringIO.new
+    warn "Out"
+    assert_equal("Out\n", $stderr.string)
+    silence_warnings {warn "In"}
+    assert_equal("Out\n", $stderr.string)
+  ensure
+    $stderr = old_stderr
+  end
+
+  def test_sass_warn
+    assert_warning("Foo!") {sass_warn "Foo!"}
+  end
+
+  def test_silence_sass_warnings
+    old_stderr, $stderr = $stderr, StringIO.new
+    silence_sass_warnings {warn "Out"}
+    assert_equal("Out\n", $stderr.string)
+    silence_sass_warnings {sass_warn "In"}
+    assert_equal("Out\n", $stderr.string)
+  ensure
+    $stderr = old_stderr
+  end
+
+  def test_has
+    assert(has?(:instance_method, String, :chomp!))
+    assert(has?(:private_instance_method, Sass::Engine, :parse_interp))
+  end
+
+  def test_enum_with_index
+    assert_equal(%w[foo0 bar1 baz2],
+      enum_with_index(%w[foo bar baz]).map {|s, i| "#{s}#{i}"})
+  end
+
+  def test_enum_cons
+    assert_equal(%w[foobar barbaz],
+      enum_cons(%w[foo bar baz], 2).map {|s1, s2| "#{s1}#{s2}"})
+  end
+
+  def test_extract
+    arr = [1, 2, 3, 4, 5]
+    assert_equal([1, 3, 5], extract!(arr) {|e| e % 2 == 1})
+    assert_equal([2, 4], arr)
+  end
+
+  def test_ord
+    assert_equal(102, ord("f"))
+    assert_equal(98, ord("bar"))
+  end
+
+  def test_flatten
+    assert_equal([1, 2, 3], flatten([1, 2, 3], 0))
+    assert_equal([1, 2, 3], flatten([1, 2, 3], 1))
+    assert_equal([1, 2, 3], flatten([1, 2, 3], 2))
+
+    assert_equal([[1, 2], 3], flatten([[1, 2], 3], 0))
+    assert_equal([1, 2, 3], flatten([[1, 2], 3], 1))
+    assert_equal([1, 2, 3], flatten([[1, 2], 3], 2))
+
+    assert_equal([[[1], 2], [3], 4], flatten([[[1], 2], [3], 4], 0))
+    assert_equal([[1], 2, 3, 4], flatten([[[1], 2], [3], 4], 1))
+    assert_equal([1, 2, 3, 4], flatten([[[1], 2], [3], 4], 2))
+  end
+
+  def test_set_hash
+    assert(set_hash(Set[1, 2, 3]) == set_hash(Set[3, 2, 1]))
+    assert(set_hash(Set[1, 2, 3]) == set_hash(Set[1, 2, 3]))
+
+    s1 = Set[]
+    s1 << 1
+    s1 << 2
+    s1 << 3
+    s2 = Set[]
+    s2 << 3
+    s2 << 2
+    s2 << 1
+    assert(set_hash(s1) == set_hash(s2))
+  end
+
+  def test_set_eql
+    assert(set_eql?(Set[1, 2, 3], Set[3, 2, 1]))
+    assert(set_eql?(Set[1, 2, 3], Set[1, 2, 3]))
+
+    s1 = Set[]
+    s1 << 1
+    s1 << 2
+    s1 << 3
+    s2 = Set[]
+    s2 << 3
+    s2 << 2
+    s2 << 1
+    assert(set_eql?(s1, s2))
+  end
+
+  def test_extract_and_inject_values
+    test = lambda {|arr| assert_equal(arr, with_extracted_values(arr) {|str| str})}
+
+    test[['foo bar']]
+    test[['foo {12} bar']]
+    test[['foo {{12} bar']]
+    test[['foo {{1', 12, '2} bar']]
+    test[['foo 1', 2, '{3', 4, 5, 6, '{7}', 8]]
+    test[['foo 1', [2, 3, 4], ' bar']]
+    test[['foo ', 1, "\n bar\n", [2, 3, 4], "\n baz"]]
+  end
+
+  def nested_caller_info_fn
+    caller_info
+  end
+
+  def double_nested_caller_info_fn
+    nested_caller_info_fn
+  end
+
+  def test_caller_info
+    assert_equal(["/tmp/foo.rb", 12, "fizzle"], caller_info("/tmp/foo.rb:12: in `fizzle'"))
+    assert_equal(["/tmp/foo.rb", 12, nil], caller_info("/tmp/foo.rb:12"))
+    assert_equal(["(sass)", 12, "blah"], caller_info("(sass):12: in `blah'"))
+    assert_equal(["", 12, "boop"], caller_info(":12: in `boop'"))
+    assert_equal(["/tmp/foo.rb", -12, "fizzle"], caller_info("/tmp/foo.rb:-12: in `fizzle'"))
+    assert_equal(["/tmp/foo.rb", 12, "fizzle"], caller_info("/tmp/foo.rb:12: in `fizzle {}'"))
+
+    info = nested_caller_info_fn
+    assert_equal(__FILE__, info[0])
+    assert_equal("test_caller_info", info[2])
+
+    info = proc {nested_caller_info_fn}.call
+    assert_equal(__FILE__, info[0])
+    assert_match(/^(block in )?test_caller_info$/, info[2])
+
+    info = double_nested_caller_info_fn
+    assert_equal(__FILE__, info[0])
+    assert_equal("double_nested_caller_info_fn", info[2])
+
+    info = proc {double_nested_caller_info_fn}.call
+    assert_equal(__FILE__, info[0])
+    assert_equal("double_nested_caller_info_fn", info[2])
+  end
+
+  def test_version_gt
+    assert_version_gt("2.0.0", "1.0.0")
+    assert_version_gt("1.1.0", "1.0.0")
+    assert_version_gt("1.0.1", "1.0.0")
+    assert_version_gt("1.0.0", "1.0.0.rc")
+    assert_version_gt("1.0.0.1", "1.0.0.rc")
+    assert_version_gt("1.0.0.rc", "0.9.9")
+    assert_version_gt("1.0.0.beta", "1.0.0.alpha")
+
+    assert_version_eq("1.0.0", "1.0.0")
+    assert_version_eq("1.0.0", "1.0.0.0")
+  end
+
+  def assert_version_gt(v1, v2)
+    #assert(version_gt(v1, v2), "Expected #{v1} > #{v2}")
+    assert(!version_gt(v2, v1), "Expected #{v2} < #{v1}")
+  end
+
+  def assert_version_eq(v1, v2)
+    assert(!version_gt(v1, v2), "Expected #{v1} = #{v2}")
+    assert(!version_gt(v2, v1), "Expected #{v2} = #{v1}")
+  end
+
+  class FooBar
+    def foo
+      Sass::Util.abstract(self)
+    end
+  end
+
+  def test_abstract
+    assert_raise_message(NotImplementedError,
+      "UtilTest::FooBar must implement #foo") {FooBar.new.foo}
+  end
+
+  def test_atomic_writes
+    # when using normal writes, this test fails about 90% of the time.
+    filename = File.join(Dir.tmpdir, "test_atomic")
+    5.times do
+      writes_to_perform = %w(1 2 3 4 5 6 7 8 9).map {|i| "#{i}\n" * 100_000}
+      threads = writes_to_perform.map do |to_write|
+        Thread.new do
+          # To see this test fail with a normal write,
+          # change to the standard file open mechanism:
+          # open(filename, "w") do |f|
+          atomic_create_and_write_file(filename) do |f|
+            f.write(to_write)
+          end
+        end
+      end
+      loop do
+        contents = File.exist?(filename) ? File.read(filename) : nil
+        next if contents.nil? || contents.size == 0
+        unless writes_to_perform.include?(contents)
+          if contents.size != writes_to_perform.first.size
+            fail "Incomplete write detected: was #{contents.size} characters, " +
+                 "should have been #{writes_to_perform.first.size}"
+          else
+            fail "Corrupted read/write detected"
+          end
+        end
+        break if threads.all? {|t| !t.alive?}
+      end
+      threads.each {|t| t.join}
+    end
+  end
+
+  class FakeError < RuntimeError; end
+
+  def test_atomic_writes_handles_exceptions
+    filename = File.join(Dir.tmpdir, "test_atomic_exception")
+    FileUtils.rm_f(filename)
+    tmp_filename = nil
+    assert_raises FakeError do
+      atomic_create_and_write_file(filename) do |f|
+        tmp_filename = f.path
+        raise FakeError.new "Borken"
+      end
+    end
+    assert !File.exist?(filename)
+    assert !File.exist?(tmp_filename)
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/test/test_helper.rb 
b/backends/css/gems/sass-3.2.12/test/test_helper.rb
new file mode 100644
index 0000000..386fa58
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/test/test_helper.rb
@@ -0,0 +1,80 @@
+lib_dir = File.dirname(__FILE__) + '/../lib'
+
+require 'test/unit'
+require 'fileutils'
+$:.unshift lib_dir unless $:.include?(lib_dir)
+require 'sass'
+require 'mathn' if ENV['MATHN'] == 'true'
+
+Sass::RAILS_LOADED = true unless defined?(Sass::RAILS_LOADED)
+Encoding.default_external = 'UTF-8' if defined?(Encoding)
+
+module Sass::Script::Functions
+  def option(name)
+    Sass::Script::String.new(@options[name.value.to_sym].to_s)
+  end
+end
+
+class Test::Unit::TestCase
+  def munge_filename(opts = {})
+    return if opts.has_key?(:filename)
+    opts[:filename] = filename_for_test(opts[:syntax] || :sass)
+  end
+
+  def filename_for_test(syntax = :sass)
+    test_name = caller.
+      map {|c| Sass::Util.caller_info(c)[2]}.
+      compact.
+      map {|c| c.sub(/^(block|rescue) in /, '')}.
+      find {|c| c =~ /^test_/}
+    "#{test_name}_inline.#{syntax}"
+  end
+
+  def clean_up_sassc
+    path = File.dirname(__FILE__) + "/../.sass-cache"
+    FileUtils.rm_r(path) if File.exist?(path)
+  end
+
+  def assert_warning(message)
+    the_real_stderr, $stderr = $stderr, StringIO.new
+    yield
+
+    if message.is_a?(Regexp)
+      assert_match message, $stderr.string.strip
+    else
+      assert_equal message.strip, $stderr.string.strip
+    end
+  ensure
+    $stderr = the_real_stderr
+  end
+
+  def assert_no_warning
+    the_real_stderr, $stderr = $stderr, StringIO.new
+    yield
+
+    assert_equal '', $stderr.string
+  ensure
+    $stderr = the_real_stderr
+  end
+
+  def silence_warnings(&block)
+    Sass::Util.silence_warnings(&block)
+  end
+
+  def assert_raise_message(klass, message)
+    yield
+  rescue Exception => e
+    assert_instance_of(klass, e)
+    assert_equal(message, e.message)
+  else
+    flunk "Expected exception #{klass}, none raised"
+  end
+
+  def assert_raise_line(line)
+    yield
+  rescue Sass::SyntaxError => e
+    assert_equal(line, e.sass_line)
+  else
+    flunk "Expected exception on line #{line}, none raised"
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/CHANGELOG.md 
b/backends/css/gems/sass-3.2.12/vendor/listen/CHANGELOG.md
new file mode 100644
index 0000000..6efc036
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/CHANGELOG.md
@@ -0,0 +1,228 @@
+## 0.7.3 - February 24, 2013
+
+### Bug fix
+
+- [#88] Update wdm dependency. (fixed by [ mrbinky3000][])
+- [#78] Depend on latest rb-inotify. (fixed by [ mbj][])
+
+## 0.7.2 - January 11, 2013
+
+### Bug fix
+
+- [#76] Exception on filename which is not in UTF-8. (fixed by [ piotr-sokolowski][])
+
+## 0.7.1 - January 6, 2013
+
+### Bug fix
+
+- [#75] Default high precision off if the mtime call fails. (fixed by [ zanker][])
+
+## 0.7.0 - December 29, 2012
+
+### Bug fixes
+
+- [#73] Rescue Errno::EOPNOTSUPP on sha1_checksum generation. (fixed by [ thibaudgg][])
+
+### New feature
+
+- Add support for *BSD with rb-kqueue. ([ mat813][])
+
+## 0.6.0 - November 21, 2012
+
+### New feature
+
+- Add bang versions for filter and ignore listener methods. ([ tarsolya][])
+
+## 0.5.3 - October 3, 2012
+
+### Bug fixes
+
+- [#65] Fix ruby warning in adapter.rb. (fixed by [ vongruenigen][])
+- [#64] ENXIO raised when hashing UNIX domain socket file. (fixed by [ sunaku][])
+
+## 0.5.2 - Septemper 23, 2012
+
+### Bug fix
+
+- [#62] Fix double change callback with polling adapter. (fixed by [ thibaudgg][])
+
+## 0.5.1 - Septemper 18, 2012
+
+### Bug fix
+
+- [#61] Fix a synchronisation bug that caused constant fallback to polling. (fixed by [ Maher4Ever][])
+
+## 0.5.0 - Septemper 1, 2012
+
+### New features
+
+- Add a dependency manager to handle platform-specific gems. So there is no need anymore to install
+  extra gems which will never be used on the user system. ([ Maher4Ever][])
+- Add a manual reporting mode to the adapters. ([ Maher4Ever][])
+
+### Improvements
+
+- [#28] Enhance the speed of detecting changes on Windows by using the [WDM][] library. ([ Maher4Ever][])
+
+## 0.4.7 - June 27, 2012
+
+### Bug fixes
+
+- Increase latency to 0.25, to avoid useless polling fallback. (fixed by [ thibaudgg][])
+- Change watched inotify events, to avoid duplication callback. (fixed by [ thibaudgg][])
+- [#41](https://github.com/guard/listen/issues/41) Use lstat instead of stat when calculating mtime. (fixed 
by [ ebroder][])
+
+## 0.4.6 - June 20, 2012
+
+### Bug fix
+
+- [#39](https://github.com/guard/listen/issues/39) Fix digest race condition. (fixed by [ dkubb][])
+
+## 0.4.5 - June 13, 2012
+
+### Bug fix
+
+- [#39](https://github.com/guard/listen/issues/39) Rescue Errno::ENOENT when path inserted doesn't exist. 
(reported by [ textgoeshere][], fixed by [ thibaudgg][] and [ rymai][])
+
+## 0.4.4 - June 8, 2012
+
+### Bug fixes
+
+- ~~[#39](https://github.com/guard/listen/issues/39) Non-existing path insertion bug. (reported by [ 
textgoeshere][], fixed by [ thibaudgg][])~~
+- Fix relative path for directories containing special characters. (reported by [ napcs][], fixed by [ 
netzpirat][])
+
+## 0.4.3 - June 6, 2012
+
+### Bug fixes
+
+- [#24](https://github.com/guard/listen/issues/24) Fail gracefully when the inotify limit is not enough for 
Listen to function. (reported by [ daemonza][], fixed by [ Maher4Ever][])
+- [#32](https://github.com/guard/listen/issues/32) Fix a crash when trying to calculate the checksum of 
unreadable files. (reported by [ nex3][], fixed by [ Maher4Ever][])
+
+### Improvements
+
+- Add `#relative_paths` method to listeners. ([ Maher4Ever][])
+- Add `#started?` query-method to adapters. ([ Maher4Ever][])
+- Dynamically detect the mtime precision used on a system. ([ Maher4Ever][] with help from [ nex3][])
+
+## 0.4.2 - May 1, 2012
+
+### Bug fixes
+
+- [#21](https://github.com/guard/listen/issues/21) Issues when listening to changes in relative paths. 
(reported by [ akerbos][], fixed by [ Maher4Ever][])
+- [#27](https://github.com/guard/listen/issues/27) Wrong reports for files modifications. (reported by [ 
cobychapple][], fixed by [ Maher4Ever][])
+- Fix segmentation fault when profiling on Windows. ([ Maher4Ever][])
+- Fix redundant watchers on Windows. ([ Maher4Ever][])
+
+### Improvements
+
+- [#17](https://github.com/guard/listen/issues/17) Use regexp-patterns with the `ignore` method instead of 
supplying paths. (reported by [ fny][], added by [ Maher4Ever][])
+- Speed improvement when listening to changes in directories with ignored paths. ([ Maher4Ever][])
+- Added `.rbx` and `.svn` to ignored directories. ([ Maher4Ever][])
+
+## 0.4.1 - April 15, 2012
+
+### Bug fix
+
+- [#18](https://github.com/guard/listen/issues/18) Listener crashes when removing directories with nested 
paths. (reported by [ daemonza][], fixed by [ Maher4Ever][])
+
+## 0.4.0 - April 9, 2012
+
+### New features
+
+- Add `wait_for_callback` method to all adapters. ([ Maher4Ever][])
+- Add `Listen::MultiListener` class to listen to multiple directories at once. ([ Maher4Ever][])
+- Allow passing multiple directories to the `Listen.to` method. ([ Maher4Ever][])
+- Add `blocking` option to `Listen#start` which can be used to disable blocking the current thread upon 
starting. ([ Maher4Ever][])
+- Use absolute-paths in callbacks by default instead of relative-paths. ([ Maher4Ever][])
+- Add `relative_paths` option to `Listen::Listener` to retain the old functionality. ([ Maher4Ever][])
+
+### Improvements
+
+- Encapsulate thread spawning in the linux-adapter. ([ Maher4Ever][])
+- Encapsulate thread spawning in the darwin-adapter. ([ Maher4Ever][] with [ scottdavis][] help)
+- Encapsulate thread spawning in the windows-adapter. ([ Maher4Ever][])
+- Fix linux-adapter bug where Listen would report file-modification events on the parent-directory. ([ 
Maher4Ever][])
+
+### Change
+
+- Remove `wait_until_listening` as adapters doesn't need to run inside threads anymore ([ Maher4Ever][])
+
+## 0.3.3 - March 6, 2012
+
+### Improvement
+
+- Improve pause/unpause. ([ thibaudgg][])
+
+## 0.3.2 - March 4, 2012
+
+### New feature
+
+- Add pause/unpause listener's methods. ([ thibaudgg][])
+
+## 0.3.1 - February 22, 2012
+
+### Bug fix
+
+- [#9](https://github.com/guard/listen/issues/9) Ignore doesn't seem to work. (reported by [ markiz][], 
fixed by [ thibaudgg][])
+
+## 0.3.0 - February 21, 2012
+
+### New features
+
+- Add automatic fallback to polling if system adapter doesn't work (like a DropBox folder). ([ thibaudgg][])
+- Add latency and force_polling options. ([ Maher4Ever][])
+
+## 0.2.0 - February 13, 2012
+
+### New features
+
+- Add checksum comparaison support for detecting consecutive file modifications made during the same second. 
([ thibaudgg][])
+- Add rb-fchange support. ([ thibaudgg][])
+- Add rb-inotify support. ([ thibaudgg][] with [ Maher4Ever][] help)
+- Add rb-fsevent support. ([ thibaudgg][])
+- Add non-recursive diff with multiple directories support. ([ thibaudgg][])
+- Ignore .DS_Store by default. ([ thibaudgg][])
+
+## 0.1.0 - January 28, 2012
+
+- First version with only a polling adapter and basic features set (ignore & filter). ([ thibaudgg][])
+
+<!--- The following link definition list is generated by PimpMyChangelog --->
+[#9]: https://github.com/guard/listen/issues/9
+[#17]: https://github.com/guard/listen/issues/17
+[#18]: https://github.com/guard/listen/issues/18
+[#21]: https://github.com/guard/listen/issues/21
+[#24]: https://github.com/guard/listen/issues/24
+[#27]: https://github.com/guard/listen/issues/27
+[#28]: https://github.com/guard/listen/issues/28
+[#32]: https://github.com/guard/listen/issues/32
+[#41]: https://github.com/guard/listen/issues/41
+[#61]: https://github.com/guard/listen/issues/61
+[#62]: https://github.com/guard/listen/issues/62
+[#64]: https://github.com/guard/listen/issues/64
+[#65]: https://github.com/guard/listen/issues/65
+[#73]: https://github.com/guard/listen/issues/73
+[#75]: https://github.com/guard/listen/issues/75
+[#76]: https://github.com/guard/listen/issues/76
+[ Maher4Ever]: https://github.com/Maher4Ever
+[ dkubb]: https://github.com/dkubb
+[ ebroder]: https://github.com/ebroder
+[ akerbos]: https://github.com/akerbos
+[ cobychapple]: https://github.com/cobychapple
+[ daemonza]: https://github.com/daemonza
+[ fny]: https://github.com/fny
+[ markiz]: https://github.com/markiz
+[ mat813]: https://github.com/mat813
+[ napcs]: https://github.com/napcs
+[ netzpirat]: https://github.com/netzpirat
+[ nex3]: https://github.com/nex3
+[ piotr-sokolowski]: https://github.com/piotr-sokolowski
+[ rymai]: https://github.com/rymai
+[ scottdavis]: https://github.com/scottdavis
+[ sunaku]: https://github.com/sunaku
+[ textgoeshere]: https://github.com/textgoeshere
+[ thibaudgg]: https://github.com/thibaudgg
+[ tarsolya]: https://github.com/tarsolya
+[ vongruenigen]: https://github.com/vongruenigen
+[ zanker]: https://github.com/zanker
+[WDM]: https://github.com/Maher4Ever/wdm
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/CONTRIBUTING.md 
b/backends/css/gems/sass-3.2.12/vendor/listen/CONTRIBUTING.md
new file mode 100644
index 0000000..8db7f5b
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/CONTRIBUTING.md
@@ -0,0 +1,38 @@
+Contribute to Listen
+===================
+
+File an issue
+-------------
+
+You can report bugs and feature requests to [GitHub Issues](https://github.com/guard/listen/issues).
+
+**Please don't ask question in the issue tracker**, instead ask them in our
+[Google group](http://groups.google.com/group/guard-dev) or on `#guard` (irc.freenode.net).
+
+Try to figure out where the issue belongs to: Is it an issue with Listen itself or with Guard?
+
+When you file a bug, please try to follow these simple rules if applicable:
+
+* Make sure you run Listen with `bundle exec` first.
+* Add your `Guardfile` (if used) and `Gemfile` to the issue.
+* Make sure that the issue is reproducible with your description.
+
+**It's most likely that your bug gets resolved faster if you provide as much information as possible!**
+
+Development
+-----------
+
+* Documentation hosted at [RubyDoc](http://rubydoc.info/github/guard/listen/master/frames).
+* Source hosted at [GitHub](https://github.com/guard/listen).
+
+Pull requests are very welcome! Please try to follow these simple rules if applicable:
+
+* Please create a topic branch for every separate change you make.
+* Make sure your patches are well tested. All specs run with `rake spec` must pass.
+* Update the [Yard](http://yardoc.org/) documentation.
+* Update the [README](https://github.com/guard/listen/blob/master/README.md).
+* Update the [CHANGELOG](https://github.com/guard/listen/blob/master/CHANGELOG.md) for noteworthy changes.
+* Please **do not change** the version number.
+
+For questions please join us in our [Google group](http://groups.google.com/group/guard-dev) or on
+`#guard` (irc.freenode.net).
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/Gemfile 
b/backends/css/gems/sass-3.2.12/vendor/listen/Gemfile
new file mode 100644
index 0000000..e92d8ff
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/Gemfile
@@ -0,0 +1,30 @@
+require 'rbconfig'
+
+source :rubygems
+
+gemspec
+
+gem 'rake'
+
+gem 'rb-kqueue', '~> 0.2' if RbConfig::CONFIG['target_os'] =~ /freebsd/i
+gem 'rb-fsevent', '~> 0.9.1' if RbConfig::CONFIG['target_os'] =~ /darwin(1.+)?$/i
+gem 'rb-inotify', '~> 0.9.0' if RbConfig::CONFIG['target_os'] =~ /linux/i
+gem 'wdm',        '~> 0.0.3' if RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
+
+group :development do
+  platform :ruby do
+    gem 'coolline'
+  end
+
+  gem 'guard'
+  gem 'guard-rspec'
+  gem 'yard'
+  gem 'redcarpet'
+  gem 'pry'
+
+  gem 'vagrant'
+end
+
+group :test do
+  gem 'rspec'
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/Guardfile 
b/backends/css/gems/sass-3.2.12/vendor/listen/Guardfile
new file mode 100644
index 0000000..f5a4cd7
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/Guardfile
@@ -0,0 +1,8 @@
+guard :rspec, :all_on_start => false, :all_after_pass => false do
+  watch(%r{^spec/.+_spec\.rb$})
+  watch(%r{^lib/(.+)\.rb$})                { |m| "spec/#{m[1]}_spec.rb" }
+  watch('spec/support/adapter_helper.rb')  { "spec/listen/adapters" }
+  watch('spec/support/listener_helper.rb') { "spec/listen/listener_spec.rb" }
+  watch('spec/support/fixtures_helper.rb') { "spec" }
+  watch('spec/spec_helper.rb')             { "spec" }
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/LICENSE 
b/backends/css/gems/sass-3.2.12/vendor/listen/LICENSE
new file mode 100644
index 0000000..9c5c40f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2013 Thibaud Guillaume-Gentil
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/README.md 
b/backends/css/gems/sass-3.2.12/vendor/listen/README.md
new file mode 100644
index 0000000..6ce84a4
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/README.md
@@ -0,0 +1,315 @@
+# Listen [![Build 
Status](https://secure.travis-ci.org/guard/listen.png?branch=master)](http://travis-ci.org/guard/listen)
+
+The Listen gem listens to file modifications and notifies you about the changes.
+
+## Features
+
+* Works everywhere!
+* Supports watching multiple directories from a single listener.
+* OS-specific adapters for Mac OS X 10.6+, Linux, *BSD and Windows.
+* Automatic fallback to polling if OS-specific adapter doesn't work.
+* Detects file modification, addition and removal.
+* Checksum comparison for modifications made under the same second.
+* Allows supplying regexp-patterns to ignore and filter paths for better results.
+* Tested on all Ruby environments via [travis-ci](http://travis-ci.org/guard/listen).
+
+## Install
+
+``` bash
+gem install listen
+```
+
+## Usage
+
+There are **two ways** to use Listen:
+
+1. Call `Listen.to` with either a single directory or multiple directories, then define the `change` 
callback in a block.
+2. Create a `listener` object and use it in an (ARel style) chainable way.
+
+Feel free to give your feeback via [Listen issues](https://github.com/guard/listen/issues)
+
+### Block API
+
+``` ruby
+# Listen to a single directory.
+Listen.to('dir/path/to/listen', :filter => /\.rb$/, :ignore => %r{ignored/path/}) do |modified, added, 
removed|
+  # ...
+end
+
+# Listen to multiple directories.
+Listen.to('dir/to/awesome_app', 'dir/to/other_app', :filter => /\.rb$/, :latency => 0.1) do |modified, 
added, removed|
+  # ...
+end
+```
+
+### "Object" API
+
+``` ruby
+listener = Listen.to('dir/path/to/listen')
+listener = listener.ignore(%r{^ignored/path/})
+listener = listener.filter(/\.rb$/)
+listener = listener.latency(0.5)
+listener = listener.force_polling(true)
+listener = listener.polling_fallback_message(false)
+listener = listener.change(&callback)
+listener.start # blocks execution!
+```
+
+### Chainable
+
+``` ruby
+Listen.to('dir/path/to/listen')
+      .ignore(%r{^ignored/path/})
+      .filter(/\.rb$/)
+      .latency(0.5)
+      .force_polling(true)
+      .polling_fallback_message('custom message')
+      .change(&callback)
+      .start # blocks execution!
+```
+
+### Pause/Unpause
+
+Listener can also easily be paused/unpaused:
+
+``` ruby
+listener = Listen.to('dir/path/to/listen')
+listener.start(false) # non-blocking mode
+listener.pause   # stop listening to changes
+listener.paused? # => true
+listener.unpause
+listener.stop
+```
+
+## Listening to changes on multiple directories
+
+The Listen gem provides the `MultiListener` class to watch multiple directories and
+handle their changes from a single listener:
+
+```ruby
+listener = Listen::MultiListener.new('app/css', 'app/js')
+listener.latency(0.5)
+
+# Configure the listener to your needs...
+
+listener.start # blocks execution!
+````
+
+For an easier access, the `Listen.to` method can also be used to create a multi-listener:
+
+``` ruby
+listener = Listen.to('app/css', 'app/js')
+                 .ignore(%r{^vendor/}) # both js/vendor and css/vendor will be ignored
+                 .change(&assets_callback)
+
+listener.start # blocks execution!
+```
+
+## Changes callback
+
+Changes to the listened-to directories gets reported back to the user in a callback.
+The registered callback gets invoked, when there are changes, with **three** parameters:
+`modified_paths`, `added_paths` and `removed_paths` in that particular order.
+
+You can register a callback in two ways. The first way is by passing a block when calling
+the `Listen.to` method or when initializing a listener object:
+
+```ruby
+Listen.to('path/to/app') do |modified, added, removed|
+  # This block will be called when there are changes.
+end
+
+# or ...
+
+listener = Listen::Listener.new('path/to/app') do |modified, added, removed|
+  # This block will be called when there are changes.
+end
+
+```
+
+The second way to register a callback is be calling the `change` method on any
+listener passing it a block:
+
+```ruby
+# Create a callback
+callback = Proc.new do |modified, added, removed|
+  # This proc will be called when there are changes.
+end
+
+listener = Listen.to('dir')
+listener.change(&callback) # convert the callback to a block and register it
+
+listener.start # blocks execution
+```
+
+### Paths in callbacks
+
+Listeners invoke callbacks passing them absolute paths by default:
+
+```ruby
+# Assume someone changes the 'style.css' file in '/home/user/app/css' after creating
+# the listener.
+Listen.to('/home/user/app/css') do |modified, added, removed|
+  modified.inspect # => ['/home/user/app/css/style.css']
+end
+```
+
+#### Relative paths in callbacks
+
+When creating a listener for a **single** path (more specifically a `Listen::Listener` instance),
+you can pass `:relative_paths => true` as an option to get relative paths in
+your callback:
+
+```ruby
+# Assume someone changes the 'style.css' file in '/home/user/app/css' after creating
+# the listener.
+Listen.to('/home/user/app/css', :relative_paths => true) do |modified, added, removed|
+  modified.inspect # => ['style.css']
+end
+```
+
+Passing the `:relative_paths => true` option won't work when listeneing to multiple
+directories:
+
+```ruby
+# Assume someone changes the 'style.css' file in '/home/user/app/css' after creating
+# the listener.
+Listen.to('/home/user/app/css', '/home/user/app/js', :relative_paths => true) do |modified, added, removed|
+  modified.inspect # => ['/home/user/app/css/style.css']
+end
+```
+
+## Options
+
+These options can be set through `Listen.to` params or via methods (see the "Object" API)
+
+```ruby
+:filter => /\.rb$/, /\.coffee$/                # Filter files to listen to via a regexps list.
+                                               # default: none
+
+:ignore => %r{app/CMake/}, /\.pid$/            # Ignore a list of paths (root directory or sub-dir)
+                                               # default: See DEFAULT_IGNORED_DIRECTORIES and 
DEFAULT_IGNORED_EXTENSIONS in Listen::DirectoryRecord
+
+:latency => 0.5                                # Set the delay (**in seconds**) between checking for changes
+                                               # default: 0.25 sec (1.0 sec for polling)
+
+:relative_paths => true                        # Enable the use of relative paths in the callback.
+                                               # default: false
+
+:force_polling => true                         # Force the use of the polling adapter
+                                               # default: none
+
+:polling_fallback_message => 'custom message'  # Set a custom polling fallback message (or disable it with 
`false`)
+                                               # default: "WARNING: Listen fallen back to polling, learn 
more at https://github.com/guard/listen#fallback.";
+```
+
+### The patterns for filtering and ignoring paths
+
+Just like the unix convention of beginning absolute paths with the
+directory-separator (forward slash `/` in unix) and with no prefix for relative paths,
+Listen doesn't prefix relative paths (to the watched directory) with a directory-separator.
+
+Therefore make sure _NOT_ to prefix your regexp-patterns for filtering or ignoring paths
+with a directory-separator, otherwise they won't work as expected.
+
+As an example: to ignore the `build` directory in a C-project, use `%r{build/}`
+and not `%r{/build/}`.
+
+Use `#filter!` and `#ignore!` methods to overwrites default patterns.
+
+### Non-blocking listening to changes
+
+Starting a listener blocks the current thread by default. That means any code after the
+`start` call won't be run until the listener is stopped (which needs to be done from another thread).
+
+For advanced usage there is an option to disable this behavior and have the listener start working
+in the background without blocking. To enable non-blocking listening the `start` method of
+the listener (be it `Listener` or `MultiListener`) needs to be called with `false` as a parameter.
+
+Here is an example of using a listener in the non-blocking mode:
+
+```ruby
+listener = Listen.to('dir/path/to/listen')
+listener.start(false) # doesn't block execution
+
+# Code here will run immediately after starting the listener
+
+```
+
+**note**: Using the `Listen.to` helper-method with a callback-block will always
+block execution. See the "Block API" section for an example.
+
+## Listen adapters
+
+The Listen gem has a set of adapters to notify it when there are changes.
+There are 3 OS-specific adapters to support Mac, Linux, *BSD and Windows. These adapters are fast
+as they use some system-calls to implement the notifying function.
+
+There is also a polling adapter which is a cross-platform adapter and it will
+work on any system. This adapter is unfortunately slower than the rest of the adapters.
+
+The Listen gem will choose the best and working adapter for your machine automatically. If you
+want to force the use of the polling adapter, either use the `:force_polling` option
+while initializing the listener or call the `force_polling` method on your listener
+before starting it.
+
+## Polling fallback
+
+When a OS-specific adapter doesn't work the Listen gem automatically falls back to the polling adapter.
+Here are some things you could try to avoid the polling fallback:
+
+* [Update your Dropbox client](http://www.dropbox.com/downloading) (if used).
+* Increase latency. (Please [open an issue](https://github.com/guard/listen/issues/new) if you think that 
default is too low.)
+* Move or rename the listened folder.
+* Update/reboot your OS.
+
+If your application keeps using the polling-adapter and you can't figure out why, feel free to [open an 
issue](https://github.com/guard/listen/issues/new) (and be sure to give all the details).
+
+## Development [![Dependency 
Status](https://gemnasium.com/guard/listen.png?branch=master)](https://gemnasium.com/guard/listen)
+
+* Documentation hosted at [RubyDoc](http://rubydoc.info/github/guard/listen/master/frames).
+* Source hosted at [GitHub](https://github.com/guard/listen).
+
+Pull requests are very welcome! Please try to follow these simple rules if applicable:
+
+* Please create a topic branch for every separate change you make.
+* Make sure your patches are well tested. All specs run with `rake spec:portability` must pass.
+* Update the [Yard](http://yardoc.org/) documentation.
+* Update the README.
+* Update the CHANGELOG for noteworthy changes.
+* Please **do not change** the version number.
+
+For questions please join us in our [Google group](http://groups.google.com/group/guard-dev) or on
+`#guard` (irc.freenode.net).
+
+## Acknowledgment
+
+* [Michael Kessler (netzpirat)][] for having written the [initial 
specs](https://github.com/guard/listen/commit/1e457b13b1bb8a25d2240428ce5ed488bafbed1f).
+* [Travis Tilley (ttilley)][] for this awesome work on [fssm][] & [rb-fsevent][].
+* [Nathan Weizenbaum (nex3)][] for [rb-inotify][], a thorough inotify wrapper.
+* [Mathieu Arnold (mat813)][] for [rb-kqueue][], a simple kqueue wrapper.
+* [stereobooster][] for [rb-fchange][], windows support wouldn't exist without him.
+* [Yehuda Katz (wycats)][] for [vigilo][], that has been a great source of inspiration.
+
+## Authors
+
+* [Thibaud Guillaume-Gentil][] ([ thibaudgg](http://twitter.com/thibaudgg))
+* [Maher Sallam][] ([ mahersalam](http://twitter.com/mahersalam))
+
+## Contributors
+
+[https://github.com/guard/listen/contributors](https://github.com/guard/listen/contributors)
+
+[Thibaud Guillaume-Gentil]: https://github.com/thibaudgg
+[Maher Sallam]: https://github.com/Maher4Ever
+[Michael Kessler (netzpirat)]: https://github.com/netzpirat
+[Travis Tilley (ttilley)]: https://github.com/ttilley
+[fssm]: https://github.com/ttilley/fssm
+[rb-fsevent]: https://github.com/thibaudgg/rb-fsevent
+[Mathieu Arnold (mat813)]: https://github.com/mat813
+[Nathan Weizenbaum (nex3)]: https://github.com/nex3
+[rb-inotify]: https://github.com/nex3/rb-inotify
+[stereobooster]: https://github.com/stereobooster
+[rb-fchange]: https://github.com/stereobooster/rb-fchange
+[Yehuda Katz (wycats)]: https://github.com/wycats
+[vigilo]: https://github.com/wycats/vigilo
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/Rakefile 
b/backends/css/gems/sass-3.2.12/vendor/listen/Rakefile
new file mode 100644
index 0000000..f2ef7f5
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/Rakefile
@@ -0,0 +1,47 @@
+require 'bundler/gem_tasks'
+require 'rspec/core/rake_task'
+
+RSpec::Core::RakeTask.new(:spec)
+task :default => :spec
+
+require 'rbconfig'
+namespace(:spec) do
+  if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/i
+    desc "Run all specs on multiple ruby versions (requires pik)"
+    task(:portability) do
+      %w[187 192 161].each do |version|
+         system "cmd /c echo -----------#{version}------------ & " +
+           "pik use #{version} & " +
+           "bundle install & " +
+           "bundle exec rspec spec"
+      end
+    end
+  else
+    desc "Run all specs on multiple ruby versions (requires rvm)"
+    task(:portability) do
+      travis_config_file = File.expand_path("../.travis.yml", __FILE__)
+      begin
+        travis_options ||= YAML::load_file(travis_config_file)
+      rescue => ex
+        puts "Travis config file '#{travis_config_file}' could not be found: #{ex.message}"
+        return
+      end
+
+      travis_options['rvm'].each do |version|
+        system <<-BASH
+          bash -c 'source ~/.rvm/scripts/rvm;
+                   rvm #{version};
+                   ruby_version_string_size=`ruby -v | wc -m`
+                   echo;
+                   for ((c=1; c<$ruby_version_string_size; c++)); do echo -n "="; done
+                   echo;
+                   echo "`ruby -v`";
+                   for ((c=1; c<$ruby_version_string_size; c++)); do echo -n "="; done
+                   echo;
+                   RBXOPT="-Xrbc.db" bundle install;
+                   RBXOPT="-Xrbc.db" bundle exec rspec spec -f doc 2>&1;'
+        BASH
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/Vagrantfile 
b/backends/css/gems/sass-3.2.12/vendor/listen/Vagrantfile
new file mode 100644
index 0000000..ad1aa97
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/Vagrantfile
@@ -0,0 +1,96 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+Vagrant::Config.run do |config|
+  # All Vagrant configuration is done here. The most common configuration
+  # options are documented and commented below. For a complete reference,
+  # please see the online documentation at vagrantup.com.
+
+  # Every Vagrant virtual environment requires a box to build off of.
+  config.vm.box = "lucid32"
+
+  # The url from where the 'config.vm.box' box will be fetched if it
+  # doesn't already exist on the user's system.
+  # config.vm.box_url = "http://domain.com/path/to/above.box";
+
+  # Boot with a GUI so you can see the screen. (Default is headless)
+  # config.vm.boot_mode = :gui
+
+  # Assign this VM to a host-only network IP, allowing you to access it
+  # via the IP. Host-only networks can talk to the host machine as well as
+  # any other machines on the same network, but cannot be accessed (through this
+  # network interface) by any external networks.
+  # config.vm.network :hostonly, "33.33.33.10"
+
+  # Assign this VM to a bridged network, allowing you to connect directly to a
+  # network using the host's network device. This makes the VM appear as another
+  # physical device on your network.
+  # config.vm.network :bridged
+
+  # Forward a port from the guest to the host, which allows for outside
+  # computers to access the VM, whereas host only networking does not.
+  # config.vm.forward_port 80, 8080
+
+  # Share an additional folder to the guest VM. The first argument is
+  # an identifier, the second is the path on the guest to mount the
+  # folder, and the third is the path on the host to the actual folder.
+  # config.vm.share_folder "v-data", "/vagrant_data", "../data"
+
+  # Enable provisioning with Puppet stand alone.  Puppet manifests
+  # are contained in a directory path relative to this Vagrantfile.
+  # You will need to create the manifests directory and a manifest in
+  # the file lucid32.pp in the manifests_path directory.
+  #
+  # An example Puppet manifest to provision the message of the day:
+  #
+  # # group { "puppet":
+  # #   ensure => "present",
+  # # }
+  # #
+  # # File { owner => 0, group => 0, mode => 0644 }
+  # #
+  # # file { '/etc/motd':
+  # #   content => "Welcome to your Vagrant-built virtual machine!
+  # #               Managed by Puppet.\n"
+  # # }
+  #
+  # config.vm.provision :puppet do |puppet|
+  #   puppet.manifests_path = "manifests"
+  #   puppet.manifest_file  = "lucid32.pp"
+  # end
+
+  # Enable provisioning with chef solo, specifying a cookbooks path (relative
+  # to this Vagrantfile), and adding some recipes and/or roles.
+  #
+  # config.vm.provision :chef_solo do |chef|
+  #   chef.cookbooks_path = "cookbooks"
+  #   chef.add_recipe "mysql"
+  #   chef.add_role "web"
+  #
+  #   # You may also specify custom JSON attributes:
+  #   chef.json = { :mysql_password => "foo" }
+  # end
+
+  # Enable provisioning with chef server, specifying the chef server URL,
+  # and the path to the validation key (relative to this Vagrantfile).
+  #
+  # The Opscode Platform uses HTTPS. Substitute your organization for
+  # ORGNAME in the URL and validation key.
+  #
+  # If you have your own Chef Server, use the appropriate URL, which may be
+  # HTTP instead of HTTPS depending on your configuration. Also change the
+  # validation key to validation.pem.
+  #
+  # config.vm.provision :chef_client do |chef|
+  #   chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME";
+  #   chef.validation_key_path = "ORGNAME-validator.pem"
+  # end
+  #
+  # If you're using the Opscode platform, your validator client is
+  # ORGNAME-validator, replacing ORGNAME with your organization name.
+  #
+  # IF you have your own Chef Server, the default validation client name is
+  # chef-validator, unless you changed the configuration.
+  #
+  #   chef.validation_client_name = "ORGNAME-validator"
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen.rb
new file mode 100644
index 0000000..d29d527
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen.rb
@@ -0,0 +1,40 @@
+module Listen
+
+  autoload :Turnstile,         'listen/turnstile'
+  autoload :Listener,          'listen/listener'
+  autoload :MultiListener,     'listen/multi_listener'
+  autoload :DirectoryRecord,   'listen/directory_record'
+  autoload :DependencyManager, 'listen/dependency_manager'
+  autoload :Adapter,           'listen/adapter'
+
+  module Adapters
+    autoload :Darwin,  'listen/adapters/darwin'
+    autoload :Linux,   'listen/adapters/linux'
+    autoload :BSD,     'listen/adapters/bsd'
+    autoload :Windows, 'listen/adapters/windows'
+    autoload :Polling, 'listen/adapters/polling'
+  end
+
+  # Listens to filesystem modifications on a either single directory or multiple directories.
+  #
+  # @param (see Listen::Listener#new)
+  # @param (see Listen::MultiListener#new)
+  #
+  # @yield [modified, added, removed] the changed files
+  # @yieldparam [Array<String>] modified the list of modified files
+  # @yieldparam [Array<String>] added the list of added files
+  # @yieldparam [Array<String>] removed the list of removed files
+  #
+  # @return [Listen::Listener] the file listener if no block given
+  #
+  def self.to(*args, &block)
+    listener = if args.length == 1 || ! args[1].is_a?(String)
+      Listener.new(*args, &block)
+    else
+      MultiListener.new(*args, &block)
+    end
+
+    block ? listener.start : listener
+  end
+
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapter.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapter.rb
new file mode 100644
index 0000000..0a7811f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapter.rb
@@ -0,0 +1,214 @@
+require 'rbconfig'
+require 'thread'
+require 'set'
+require 'fileutils'
+
+module Listen
+  class Adapter
+    attr_accessor :directories, :latency, :paused
+
+    # The default delay between checking for changes.
+    DEFAULT_LATENCY = 0.25
+
+    # The default warning message when there is a missing dependency.
+    MISSING_DEPENDENCY_MESSAGE = <<-EOS.gsub(/^\s*/, '')
+      For a better performance, it's recommended that you satisfy the missing dependency.
+    EOS
+
+    # The default warning message when falling back to polling adapter.
+    POLLING_FALLBACK_MESSAGE = <<-EOS.gsub(/^\s*/, '')
+      Listen will be polling changes. Learn more at https://github.com/guard/listen#polling-fallback.
+    EOS
+
+    # Selects the appropriate adapter implementation for the
+    # current OS and initializes it.
+    #
+    # @param [String, Array<String>] directories the directories to watch
+    # @param [Hash] options the adapter options
+    # @option options [Boolean] force_polling to force polling or not
+    # @option options [String, Boolean] polling_fallback_message to change polling fallback message or 
remove it
+    # @option options [Float] latency the delay between checking for changes in seconds
+    #
+    # @yield [changed_dirs, options] callback Callback called when a change happens
+    # @yieldparam [Array<String>] changed_dirs the changed directories
+    # @yieldparam [Hash] options callback options (like :recursive => true)
+    #
+    # @return [Listen::Adapter] the chosen adapter
+    #
+    def self.select_and_initialize(directories, options = {}, &callback)
+      return Adapters::Polling.new(directories, options, &callback) if options.delete(:force_polling)
+
+      warning = ''
+
+      begin
+        if Adapters::Darwin.usable_and_works?(directories, options)
+          return Adapters::Darwin.new(directories, options, &callback)
+        elsif Adapters::Linux.usable_and_works?(directories, options)
+          return Adapters::Linux.new(directories, options, &callback)
+        elsif Adapters::BSD.usable_and_works?(directories, options)
+          return Adapters::BSD.new(directories, options, &callback)
+        elsif Adapters::Windows.usable_and_works?(directories, options)
+          return Adapters::Windows.new(directories, options, &callback)
+        end
+      rescue DependencyManager::Error => e
+        warning += e.message + "\n" + MISSING_DEPENDENCY_MESSAGE
+      end
+
+      unless options[:polling_fallback_message] == false
+        warning += options[:polling_fallback_message] || POLLING_FALLBACK_MESSAGE
+        Kernel.warn "[Listen warning]:\n" + warning.gsub(/^(.*)/, '  \1')
+      end
+
+      Adapters::Polling.new(directories, options, &callback)
+    end
+
+    # Initializes the adapter.
+    #
+    # @param [String, Array<String>] directories the directories to watch
+    # @param [Hash] options the adapter options
+    # @option options [Float] latency the delay between checking for changes in seconds
+    # @option options [Boolean] report_changes whether or not to automatically report changes (run the 
callback)
+    #
+    # @yield [changed_dirs, options] callback Callback called when a change happens
+    # @yieldparam [Array<String>] changed_dirs the changed directories
+    # @yieldparam [Hash] options callback options (like :recursive => true)
+    #
+    # @return [Listen::Adapter] the adapter
+    #
+    def initialize(directories, options = {}, &callback)
+      @directories  = Array(directories)
+      @callback     = callback
+      @paused       = false
+      @mutex        = Mutex.new
+      @changed_dirs = Set.new
+      @turnstile    = Turnstile.new
+      @latency    ||= DEFAULT_LATENCY
+      @latency      = options[:latency] if options[:latency]
+      @report_changes = options[:report_changes].nil? ? true : options[:report_changes]
+    end
+
+    # Starts the adapter.
+    #
+    # @param [Boolean] blocking whether or not to block the current thread after starting
+    #
+    def start(blocking = true)
+      @stop = false
+    end
+
+    # Stops the adapter.
+    #
+    def stop
+      @stop = true
+      @turnstile.signal # ensure no thread is blocked
+    end
+
+    # Returns whether the adapter is statred or not
+    #
+    # @return [Boolean] whether the adapter is started or not
+    #
+    def started?
+      @stop.nil? ? false : ! stop
+    end
+
+    # Blocks the main thread until the poll thread
+    # runs the callback.
+    #
+    def wait_for_callback
+      @turnstile.wait unless @paused
+    end
+
+    # Blocks the main thread until N changes are
+    # detected.
+    #
+    def wait_for_changes(goal = 0)
+      changes = 0
+
+      loop do
+        @mutex.synchronize { changes = @changed_dirs.size }
+
+        return if @paused || @stop
+        return if changes >= goal
+
+        sleep(@latency)
+      end
+    end
+
+    # Checks if the adapter is usable on the current OS.
+    #
+    # @return [Boolean] whether usable or not
+    #
+    def self.usable?
+      load_depenencies
+      dependencies_loaded?
+    end
+
+    # Checks if the adapter is usable and works on the current OS.
+    #
+    # @param [String, Array<String>] directories the directories to watch
+    # @param [Hash] options the adapter options
+    # @option options [Float] latency the delay between checking for changes in seconds
+    #
+    # @return [Boolean] whether usable and work or not
+    #
+    def self.usable_and_works?(directories, options = {})
+      usable? && Array(directories).all? { |d| works?(d, options) }
+    end
+
+    # Runs a tests to determine if the adapter can actually pick up
+    # changes in a given directory and returns the result.
+    #
+    # @note This test takes some time depending the adapter latency.
+    #
+    # @param [String, Pathname] directory the directory to watch
+    # @param [Hash] options the adapter options
+    # @option options [Float] latency the delay between checking for changes in seconds
+    #
+    # @return [Boolean] whether the adapter works or not
+    #
+    def self.works?(directory, options = {})
+      work = false
+      test_file = "#{directory}/.listen_test"
+      callback = lambda { |*| work = true }
+      adapter  = self.new(directory, options, &callback)
+      adapter.start(false)
+
+      FileUtils.touch(test_file)
+
+      t = Thread.new { sleep(adapter.latency * 5); adapter.stop }
+
+      adapter.wait_for_callback
+      work
+    ensure
+      Thread.kill(t) if t
+      FileUtils.rm(test_file) if File.exists?(test_file)
+      adapter.stop if adapter && adapter.started?
+    end
+
+    # Runs the callback and passes it the changes if there are any.
+    #
+    def report_changes
+      changed_dirs = nil
+
+      @mutex.synchronize do
+        return if @changed_dirs.empty?
+        changed_dirs = @changed_dirs.to_a
+        @changed_dirs.clear
+      end
+
+      @callback.call(changed_dirs, {})
+      @turnstile.signal
+    end
+
+    private
+
+    # Polls changed directories and reports them back
+    # when there are changes.
+    #
+    def poll_changed_dirs
+      until @stop
+        sleep(@latency)
+        report_changes
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/bsd.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/bsd.rb
new file mode 100644
index 0000000..8a8a6a9
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/bsd.rb
@@ -0,0 +1,112 @@
+module Listen
+  module Adapters
+
+    # Listener implementation for BSD's `kqueue`.
+    #
+    class BSD < Adapter
+      extend DependencyManager
+
+      # Declare the adapter's dependencies
+      dependency 'rb-kqueue', '~> 0.2'
+
+      # Watched kqueue events
+      #
+      # @see http://www.freebsd.org/cgi/man.cgi?query=kqueue
+      # @see https://github.com/nex3/rb-kqueue/blob/master/lib/rb-kqueue/queue.rb
+      #
+      EVENTS = [ :delete, :write, :extend, :attrib, :link, :rename, :revoke ]
+
+      # Initializes the Adapter. See {Listen::Adapter#initialize} for
+      # more info.
+      #
+      def initialize(directories, options = {}, &callback)
+        super
+        @kqueue = init_kqueue
+      end
+
+      # Starts the adapter.
+      #
+      # @param [Boolean] blocking whether or not to block the current thread after starting
+      #
+      def start(blocking = true)
+        @mutex.synchronize do
+          return if @stop == false
+          super
+        end
+
+        @kqueue_thread = Thread.new do
+          until @stop
+            @kqueue.poll
+            sleep(@latency)
+          end
+        end
+        @poll_thread   = Thread.new { poll_changed_dirs } if @report_changes
+
+        @kqueue_thread.join if blocking
+      end
+
+      # Stops the adapter.
+      #
+      def stop
+        @mutex.synchronize do
+          return if @stop == true
+          super
+        end
+
+        @kqueue.stop
+        Thread.kill(@kqueue_thread) if @kqueue_thread
+        @poll_thread.join if @poll_thread
+      end
+
+      # Checks if the adapter is usable on the current OS.
+      #
+      # @return [Boolean] whether usable or not
+      #
+      def self.usable?
+        return false unless RbConfig::CONFIG['target_os'] =~ /freebsd/i
+        super
+      end
+
+      private
+
+      # Initializes a kqueue Queue and adds a watcher for each files in
+      # the directories passed to the adapter.
+      #
+      # @return [INotify::Notifier] initialized kqueue
+      #
+      def init_kqueue
+        require 'find'
+
+        callback = lambda do |event|
+          path = event.watcher.path
+          @mutex.synchronize do
+            # kqueue watches everything, but Listen only needs the
+            # directory where stuffs happens.
+            @changed_dirs << (File.directory?(path) ? path : File.dirname(path))
+
+            # If it is a directory, and it has a write flag, it means a
+            # file has been added so find out which and deal with it.
+            # No need to check for removed file, kqueue will forget them
+            # when the vfs does..
+            if File.directory?(path) && !(event.flags & [:write]).empty?
+              queue = event.watcher.queue
+              Find.find(path) do |file|
+                unless queue.watchers.detect {|k,v| v.path == file.to_s}
+                  queue.watch_file(file, *EVENTS, &callback)
+                end
+              end
+            end
+          end
+        end
+
+        KQueue::Queue.new.tap do |queue|
+          @directories.each do |directory|
+            Find.find(directory) do |path|
+              queue.watch_file(path, *EVENTS, &callback)
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/darwin.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/darwin.rb
new file mode 100644
index 0000000..016cd3c
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/darwin.rb
@@ -0,0 +1,85 @@
+module Listen
+  module Adapters
+
+    # Adapter implementation for Mac OS X `FSEvents`.
+    #
+    class Darwin < Adapter
+      extend DependencyManager
+
+      # Declare the adapter's dependencies
+      dependency 'rb-fsevent', '~> 0.9'
+
+      LAST_SEPARATOR_REGEX = /\/$/
+
+      # Initializes the Adapter. See {Listen::Adapter#initialize} for more info.
+      #
+      def initialize(directories, options = {}, &callback)
+        super
+        @worker = init_worker
+      end
+
+      # Starts the adapter.
+      #
+      # @param [Boolean] blocking whether or not to block the current thread after starting
+      #
+      def start(blocking = true)
+        @mutex.synchronize do
+          return if @stop == false
+          super
+        end
+
+        @worker_thread = Thread.new { @worker.run }
+
+        # The FSEvent worker needs sometime to startup. Turnstiles can't
+        # be used to wait for it as it runs in a loop.
+        # TODO: Find a better way to block until the worker starts.
+        sleep 0.1
+
+        @poll_thread = Thread.new { poll_changed_dirs } if @report_changes
+        @worker_thread.join if blocking
+      end
+
+      # Stops the adapter.
+      #
+      def stop
+        @mutex.synchronize do
+          return if @stop == true
+          super
+        end
+
+        @worker.stop
+        @worker_thread.join if @worker_thread
+        @poll_thread.join if @poll_thread
+      end
+
+      # Checks if the adapter is usable on the current OS.
+      #
+      # @return [Boolean] whether usable or not
+      #
+      def self.usable?
+        return false unless RbConfig::CONFIG['target_os'] =~ /darwin(1.+)?$/i
+        super
+      end
+
+      private
+
+      # Initializes a FSEvent worker and adds a watcher for
+      # each directory passed to the adapter.
+      #
+      # @return [FSEvent] initialized worker
+      #
+      def init_worker
+        FSEvent.new.tap do |worker|
+          worker.watch(@directories.dup, :latency => @latency) do |changes|
+            next if @paused
+            @mutex.synchronize do
+              changes.each { |path| @changed_dirs << path.sub(LAST_SEPARATOR_REGEX, '') }
+            end
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/linux.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/linux.rb
new file mode 100644
index 0000000..f5beb97
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/linux.rb
@@ -0,0 +1,113 @@
+module Listen
+  module Adapters
+
+    # Listener implementation for Linux `inotify`.
+    #
+    class Linux < Adapter
+      extend DependencyManager
+
+      # Declare the adapter's dependencies
+      dependency 'rb-inotify', '~> 0.9'
+
+      # Watched inotify events
+      #
+      # @see http://www.tin.org/bin/man.cgi?section=7&topic=inotify
+      # @see https://github.com/nex3/rb-inotify/blob/master/lib/rb-inotify/notifier.rb#L99-L177
+      #
+      EVENTS = %w[recursive attrib create delete move close_write]
+
+      # The message to show when the limit of inotify watchers is not enough
+      #
+      INOTIFY_LIMIT_MESSAGE = <<-EOS.gsub(/^\s*/, '')
+        Listen error: unable to monitor directories for changes.
+
+        Please head to https://github.com/guard/listen/wiki/Increasing-the-amount-of-inotify-watchers
+        for information on how to solve this issue.
+      EOS
+
+      # Initializes the Adapter. See {Listen::Adapter#initialize} for more info.
+      #
+      def initialize(directories, options = {}, &callback)
+        super
+        @worker = init_worker
+      rescue Errno::ENOSPC
+        abort(INOTIFY_LIMIT_MESSAGE)
+      end
+
+      # Starts the adapter.
+      #
+      # @param [Boolean] blocking whether or not to block the current thread after starting
+      #
+      def start(blocking = true)
+        @mutex.synchronize do
+          return if @stop == false
+          super
+        end
+
+        @worker_thread = Thread.new { @worker.run }
+        @poll_thread   = Thread.new { poll_changed_dirs } if @report_changes
+
+        @worker_thread.join if blocking
+      end
+
+      # Stops the adapter.
+      #
+      def stop
+        @mutex.synchronize do
+          return if @stop == true
+          super
+        end
+
+        @worker.stop
+        Thread.kill(@worker_thread) if @worker_thread
+        @poll_thread.join if @poll_thread
+      end
+
+      # Checks if the adapter is usable on the current OS.
+      #
+      # @return [Boolean] whether usable or not
+      #
+      def self.usable?
+        return false unless RbConfig::CONFIG['target_os'] =~ /linux/i
+        super
+      end
+
+    private
+
+      # Initializes a INotify worker and adds a watcher for
+      # each directory passed to the adapter.
+      #
+      # @return [INotify::Notifier] initialized worker
+      #
+      def init_worker
+        callback = lambda do |event|
+          if @paused || (
+            # Event on root directory
+            event.name == ""
+          ) || (
+            # INotify reports changes to files inside directories as events
+            # on the directories themselves too.
+            #
+            # @see http://linux.die.net/man/7/inotify
+            event.flags.include?(:isdir) and event.flags & [:close, :modify] != []
+          )
+            # Skip all of these!
+            next
+          end
+
+          @mutex.synchronize do
+            @changed_dirs << File.dirname(event.absolute_name)
+          end
+        end
+
+        INotify::Notifier.new.tap do |worker|
+          @directories.each do |directory|
+            worker.watch(directory, *EVENTS.map(&:to_sym), &callback)
+          end
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/polling.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/polling.rb
new file mode 100644
index 0000000..4f494ab
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/polling.rb
@@ -0,0 +1,67 @@
+module Listen
+  module Adapters
+
+    # The default delay between checking for changes.
+    DEFAULT_POLLING_LATENCY = 1.0
+
+    # Polling Adapter that works cross-platform and
+    # has no dependencies. This is the adapter that
+    # uses the most CPU processing power and has higher
+    # file IO that the other implementations.
+    #
+    class Polling < Adapter
+      extend DependencyManager
+
+      # Initialize the Adapter. See {Listen::Adapter#initialize} for more info.
+      #
+      def initialize(directories, options = {}, &callback)
+        @latency ||= DEFAULT_POLLING_LATENCY
+        super
+      end
+
+      # Start the adapter.
+      #
+      # @param [Boolean] blocking whether or not to block the current thread after starting
+      #
+      def start(blocking = true)
+        @mutex.synchronize do
+          return if @stop == false
+          super
+        end
+
+        @poll_thread = Thread.new { poll }
+        @poll_thread.join if blocking
+      end
+
+      # Stop the adapter.
+      #
+      def stop
+        @mutex.synchronize do
+          return if @stop == true
+          super
+        end
+
+        @poll_thread.join
+      end
+
+    private
+
+      # Poll listener directory for file system changes.
+      #
+      def poll
+        until @stop
+          next if @paused
+
+          start = Time.now.to_f
+          @callback.call(@directories.dup, :recursive => true)
+          @turnstile.signal
+          nap_time = @latency - (Time.now.to_f - start)
+          sleep(nap_time) if nap_time > 0
+        end
+      rescue Interrupt
+      end
+
+    end
+
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/windows.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/windows.rb
new file mode 100644
index 0000000..228bfd7
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/adapters/windows.rb
@@ -0,0 +1,87 @@
+require 'set'
+
+module Listen
+  module Adapters
+
+    # Adapter implementation for Windows `wdm`.
+    #
+    class Windows < Adapter
+      extend DependencyManager
+
+      # Declare the adapter's dependencies
+      dependency 'wdm', '~> 0.1'
+
+      # Initializes the Adapter. See {Listen::Adapter#initialize} for more info.
+      #
+      def initialize(directories, options = {}, &callback)
+        super
+        @worker = init_worker
+      end
+
+      # Starts the adapter.
+      #
+      # @param [Boolean] blocking whether or not to block the current thread after starting
+      #
+      def start(blocking = true)
+        @mutex.synchronize do
+          return if @stop == false
+          super
+        end
+
+        @worker_thread = Thread.new { @worker.run! }
+
+        # Wait for the worker to start. This is needed to avoid a deadlock
+        # when stopping immediately after starting.
+        sleep 0.1
+
+        @poll_thread = Thread.new { poll_changed_dirs } if @report_changes
+
+        @worker_thread.join if blocking
+      end
+
+      # Stops the adapter.
+      #
+      def stop
+        @mutex.synchronize do
+          return if @stop == true
+          super
+        end
+
+        @worker.stop
+        @worker_thread.join if @worker_thread
+        @poll_thread.join if @poll_thread
+      end
+
+      # Checks if the adapter is usable on the current OS.
+      #
+      # @return [Boolean] whether usable or not
+      #
+      def self.usable?
+        return false unless RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
+        super
+      end
+
+    private
+
+      # Initializes a WDM monitor and adds a watcher for
+      # each directory passed to the adapter.
+      #
+      # @return [WDM::Monitor] initialized worker
+      #
+      def init_worker
+        callback = Proc.new do |change|
+          next if @paused
+          @mutex.synchronize do
+            @changed_dirs << File.dirname(change.path)
+          end
+        end
+
+        WDM::Monitor.new.tap do |worker|
+          @directories.each { |d| worker.watch_recursively(d, &callback) }
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/dependency_manager.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/dependency_manager.rb
new file mode 100644
index 0000000..d63a09d
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/dependency_manager.rb
@@ -0,0 +1,126 @@
+require 'set'
+
+module Listen
+
+  # The dependency-manager offers a simple DSL which allows
+  # classes to declare their gem dependencies and load them when
+  # needed.
+  # It raises a user-friendly exception when the dependencies
+  # can't be loaded which has the install command in the message.
+  #
+  module DependencyManager
+
+    GEM_LOAD_MESSAGE = <<-EOS.gsub(/^ {6}/, '')
+      Missing dependency '%s' (version '%s')!
+    EOS
+
+    GEM_INSTALL_COMMAND = <<-EOS.gsub(/^ {6}/, '')
+      Please run the following to satisfy the dependency:
+        gem install --version '%s' %s
+    EOS
+
+    BUNDLER_DECLARE_GEM = <<-EOS.gsub(/^ {6}/, '')
+      Please add the following to your Gemfile to satisfy the dependency:
+        gem '%s', '%s'
+    EOS
+
+    Dependency = Struct.new(:name, :version)
+
+    # The error raised when a dependency can't be loaded.
+    class Error < StandardError; end
+
+    # A list of all loaded dependencies in the dependency manager.
+    @_loaded_dependencies = Set.new
+
+    # class methods
+    class << self
+
+      # Initializes the extended class.
+      #
+      # @param [Class] the class for which some dependencies must be managed
+      #
+      def extended(base)
+        base.class_eval do
+          @_dependencies = Set.new
+        end
+      end
+
+      # Adds a loaded dependency to a list so that it doesn't have
+      # to be loaded again by another classes.
+      #
+      # @param [Dependency] dependency
+      #
+      def add_loaded(dependency)
+        @_loaded_dependencies << dependency
+      end
+
+      # Returns whether the dependency is alread loaded or not.
+      #
+      # @param [Dependency] dependency
+      # @return [Boolean]
+      #
+      def already_loaded?(dependency)
+        @_loaded_dependencies.include?(dependency)
+      end
+
+      # Clears the list of loaded dependencies.
+      #
+      def clear_loaded
+        @_loaded_dependencies.clear
+      end
+    end
+
+    # Registers a new dependency.
+    #
+    # @param [String] name the name of the gem
+    # @param [String] version the version of the gem
+    #
+    def dependency(name, version)
+      @_dependencies << Dependency.new(name, version)
+    end
+
+    # Loads the registered dependencies.
+    #
+    # @raise DependencyManager::Error if the dependency can't be loaded.
+    #
+    def load_depenencies
+      @_dependencies.each do |dependency|
+        begin
+          next if DependencyManager.already_loaded?(dependency)
+          gem(dependency.name, dependency.version)
+          require(dependency.name)
+          DependencyManager.add_loaded(dependency)
+          @_dependencies.delete(dependency)
+        rescue Gem::LoadError
+          args = [dependency.name, dependency.version]
+          command = if running_under_bundler?
+            BUNDLER_DECLARE_GEM % args
+          else
+            GEM_INSTALL_COMMAND % args.reverse
+          end
+          message = GEM_LOAD_MESSAGE % args
+
+          raise Error.new(message + command)
+        end
+      end
+    end
+
+    # Returns whether all the dependencies has been loaded or not.
+    #
+    # @return [Boolean]
+    #
+    def dependencies_loaded?
+      @_dependencies.empty?
+    end
+
+    private
+
+    # Returns whether we are running under bundler or not
+    #
+    # @return [Boolean]
+    #
+    def running_under_bundler?
+      !!(File.exists?('Gemfile') && ENV['BUNDLE_GEMFILE'])
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/directory_record.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/directory_record.rb
new file mode 100644
index 0000000..acfaa55
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/directory_record.rb
@@ -0,0 +1,371 @@
+require 'set'
+require 'find'
+require 'digest/sha1'
+
+module Listen
+
+  # The directory record stores information about
+  # a directory and keeps track of changes to
+  # the structure of its childs.
+  #
+  class DirectoryRecord
+    attr_reader :directory, :paths, :sha1_checksums
+
+    DEFAULT_IGNORED_DIRECTORIES = %w[.rbx .bundle .git .svn log tmp vendor]
+
+    DEFAULT_IGNORED_EXTENSIONS  = %w[.DS_Store]
+
+    # Defines the used precision based on the type of mtime returned by the
+    # system (whether its in milliseconds or just seconds)
+    #
+    begin
+      HIGH_PRECISION_SUPPORTED = File.mtime(__FILE__).to_f.to_s[-2..-1] != '.0'
+    rescue
+      HIGH_PRECISION_SUPPORTED = false
+    end
+
+    # Data structure used to save meta data about a path
+    #
+    MetaData = Struct.new(:type, :mtime)
+
+    # Class methods
+    #
+    class << self
+
+      # Creates the ignoring patterns from the default ignored
+      # directories and extensions. It memoizes the generated patterns
+      # to avoid unnecessary computation.
+      #
+      def generate_default_ignoring_patterns
+        @@default_ignoring_patterns ||= Array.new.tap do |default_patterns|
+          # Add directories
+          ignored_directories = DEFAULT_IGNORED_DIRECTORIES.map { |d| Regexp.escape(d) }
+          default_patterns << %r{^(?:#{ignored_directories.join('|')})/}
+
+          # Add extensions
+          ignored_extensions = DEFAULT_IGNORED_EXTENSIONS.map { |e| Regexp.escape(e) }
+          default_patterns << %r{(?:#{ignored_extensions.join('|')})$}
+        end
+      end
+    end
+
+    # Initializes a directory record.
+    #
+    # @option [String] directory the directory to keep track of
+    #
+    def initialize(directory)
+      raise ArgumentError, "The path '#{directory}' is not a directory!" unless File.directory?(directory)
+
+      @directory          = directory
+      @ignoring_patterns  = Set.new
+      @filtering_patterns = Set.new
+      @sha1_checksums     = Hash.new
+
+      @ignoring_patterns.merge(DirectoryRecord.generate_default_ignoring_patterns)
+    end
+
+    # Returns the ignoring patterns in the record
+    #
+    # @return [Array<Regexp>] the ignoring patterns
+    #
+    def ignoring_patterns
+      @ignoring_patterns.to_a
+    end
+
+    # Returns the filtering patterns used in the record to know
+    # which paths should be stored.
+    #
+    # @return [Array<Regexp>] the filtering patterns
+    #
+    def filtering_patterns
+      @filtering_patterns.to_a
+    end
+
+    # Adds ignoring patterns to the record.
+    #
+    # @example Ignore some paths
+    #   ignore %r{^ignored/path/}, /man/
+    #
+    # @param [Regexp] regexp a pattern for ignoring paths
+    #
+    def ignore(*regexps)
+      @ignoring_patterns.merge(regexps)
+    end
+
+    # Replaces ignoring patterns in the record.
+    #
+    # @example Ignore only these paths
+    #   ignore! %r{^ignored/path/}, /man/
+    #
+    # @param [Regexp] regexp a pattern for ignoring paths
+    #
+    def ignore!(*regexps)
+      @ignoring_patterns.replace(regexps)
+    end
+
+    # Adds filtering patterns to the listener.
+    #
+    # @example Filter some files
+    #   ignore /\.txt$/, /.*\.zip/
+    #
+    # @param [Regexp] regexp a pattern for filtering paths
+    #
+    def filter(*regexps)
+      @filtering_patterns.merge(regexps)
+    end
+
+    # Replaces filtering patterns in the listener.
+    #
+    # @example Filter only these files
+    #   ignore /\.txt$/, /.*\.zip/
+    #
+    # @param [Regexp] regexp a pattern for filtering paths
+    #
+    def filter!(*regexps)
+      @filtering_patterns.replace(regexps)
+    end
+
+    # Returns whether a path should be ignored or not.
+    #
+    # @param [String] path the path to test.
+    #
+    # @return [Boolean]
+    #
+    def ignored?(path)
+      path = relative_to_base(path)
+      @ignoring_patterns.any? { |pattern| pattern =~ path }
+    end
+
+    # Returns whether a path should be filtered or not.
+    #
+    # @param [String] path the path to test.
+    #
+    # @return [Boolean]
+    #
+    def filtered?(path)
+      # When no filtering patterns are set, ALL files are stored.
+      return true if @filtering_patterns.empty?
+
+      path = relative_to_base(path)
+      @filtering_patterns.any? { |pattern| pattern =~ path }
+    end
+
+    # Finds the paths that should be stored and adds them
+    # to the paths' hash.
+    #
+    def build
+      @paths = Hash.new { |h, k| h[k] = Hash.new }
+      important_paths { |path| insert_path(path) }
+    end
+
+    # Detects changes in the passed directories, updates
+    # the record with the new changes and returns the changes
+    #
+    # @param [Array] directories the list of directories scan for changes
+    # @param [Hash] options
+    # @option options [Boolean] recursive scan all sub-directories recursively
+    # @option options [Boolean] relative_paths whether or not to use relative paths for changes
+    #
+    # @return [Hash<Array>] the changes
+    #
+    def fetch_changes(directories, options = {})
+      @changes    = { :modified => [], :added => [], :removed => [] }
+      directories = directories.sort_by { |el| el.length }.reverse # diff sub-dir first
+
+      directories.each do |directory|
+        next unless directory[ directory] # Path is or inside directory
+        detect_modifications_and_removals(directory, options)
+        detect_additions(directory, options)
+      end
+
+      @changes
+    end
+
+    # Converts an absolute path to a path that's relative to the base directory.
+    #
+    # @param [String] path the path to convert
+    #
+    # @return [String] the relative path
+    #
+    def relative_to_base(path)
+      return nil unless path[ directory]
+      path = path.force_encoding("BINARY") if path.respond_to?(:force_encoding)
+      path.sub(%r{^#{Regexp.quote(@directory)}#{File::SEPARATOR}?}, '')
+    end
+
+    private
+
+    # Detects modifications and removals recursively in a directory.
+    #
+    # @note Modifications detection begins by checking the modification time (mtime)
+    #   of files and then by checking content changes (using SHA1-checksum)
+    #   when the mtime of files is not changed.
+    #
+    # @param [String] directory the path to analyze
+    # @param [Hash] options
+    # @option options [Boolean] recursive scan all sub-directories recursively
+    # @option options [Boolean] relative_paths whether or not to use relative paths for changes
+    #
+    def detect_modifications_and_removals(directory, options = {})
+      @paths[directory].each do |basename, meta_data|
+        path = File.join(directory, basename)
+
+        case meta_data.type
+        when 'Dir'
+          if File.directory?(path)
+            detect_modifications_and_removals(path, options) if options[:recursive]
+          else
+            detect_modifications_and_removals(path, { :recursive => true }.merge(options))
+            @paths[directory].delete(basename)
+            @paths.delete("#{directory}/#{basename}")
+          end
+        when 'File'
+          if File.exist?(path)
+            new_mtime = mtime_of(path)
+
+            # First check if we are in the same second (to update checksums)
+            # before checking the time difference
+            if (meta_data.mtime.to_i == new_mtime.to_i && content_modified?(path)) || meta_data.mtime < 
new_mtime
+              # Update the sha1 checksum of the file
+              insert_sha1_checksum(path)
+
+              # Update the meta data of the file
+              meta_data.mtime = new_mtime
+              @paths[directory][basename] = meta_data
+
+              @changes[:modified] << (options[:relative_paths] ? relative_to_base(path) : path)
+            end
+          else
+            @paths[directory].delete(basename)
+            @sha1_checksums.delete(path)
+            @changes[:removed] << (options[:relative_paths] ? relative_to_base(path) : path)
+          end
+        end
+      end
+    end
+
+    # Detects additions in a directory.
+    #
+    # @param [String] directory the path to analyze
+    # @param [Hash] options
+    # @option options [Boolean] recursive scan all sub-directories recursively
+    # @option options [Boolean] relative_paths whether or not to use relative paths for changes
+    #
+    def detect_additions(directory, options = {})
+      # Don't process removed directories
+      return unless File.exist?(directory)
+
+      Find.find(directory) do |path|
+        next if path == @directory
+
+        if File.directory?(path)
+          # Add a trailing slash to directories when checking if a directory is
+          # ignored to optimize finding them as Find.find doesn't.
+          if ignored?(path + File::SEPARATOR) || (directory != path && (!options[:recursive] && 
existing_path?(path)))
+            Find.prune # Don't look any further into this directory.
+          else
+            insert_path(path)
+          end
+        elsif !ignored?(path) && filtered?(path) && !existing_path?(path)
+          if File.file?(path)
+            @changes[:added] << (options[:relative_paths] ? relative_to_base(path) : path)
+            insert_path(path)
+          end
+        end
+      end
+    end
+
+    # Returns whether or not a file's content has been modified by
+    # comparing the SHA1-checksum to a stored one.
+    # Ensure that the SHA1-checksum is inserted to the sha1_checksums
+    # array for later comparaison if false.
+    #
+    # @param [String] path the file path
+    #
+    def content_modified?(path)
+      @sha1_checksum = sha1_checksum(path)
+      if @sha1_checksums[path] == @sha1_checksum || ! sha1_checksums key?(path)
+        insert_sha1_checksum(path)
+        false
+      else
+        true
+      end
+    end
+
+    # Inserts a SHA1-checksum path in @SHA1-checksums hash.
+    #
+    # @param [String] path the SHA1-checksum path to insert in @sha1_checksums.
+    #
+    def insert_sha1_checksum(path)
+      if @sha1_checksum ||= sha1_checksum(path)
+        @sha1_checksums[path] = @sha1_checksum
+        @sha1_checksum = nil
+      end
+    end
+
+    # Returns the SHA1-checksum for the file path.
+    #
+    # @param [String] path the file path
+    #
+    def sha1_checksum(path)
+      Digest::SHA1.file(path).to_s
+    rescue Errno::EACCES, Errno::ENOENT, Errno::ENXIO, Errno::EOPNOTSUPP
+      nil
+    end
+
+    # Traverses the base directory looking for paths that should
+    # be stored; thus paths that are filters or not ignored.
+    #
+    # @yield [path] an important path
+    #
+    def important_paths
+      Find.find(@directory) do |path|
+        next if path == @directory
+
+        if File.directory?(path)
+          # Add a trailing slash to directories when checking if a directory is
+          # ignored to optimize finding them as Find.find doesn't.
+          if ignored?(path + File::SEPARATOR)
+            Find.prune # Don't look any further into this directory.
+          else
+            yield(path)
+          end
+        elsif !ignored?(path) && filtered?(path)
+          yield(path)
+        end
+      end
+    end
+
+    # Inserts a path with its type (Dir or File) in paths hash.
+    #
+    # @param [String] path the path to insert in @paths.
+    #
+    def insert_path(path)
+      meta_data = MetaData.new
+      meta_data.type = File.directory?(path) ? 'Dir' : 'File'
+      meta_data.mtime = mtime_of(path) unless meta_data.type == 'Dir' # mtimes of dirs are not used yet
+      @paths[File.dirname(path)][File.basename(path)] = meta_data
+    rescue Errno::ENOENT
+    end
+
+    # Returns whether or not a path exists in the paths hash.
+    #
+    # @param [String] path the path to check
+    #
+    # @return [Boolean]
+    #
+    def existing_path?(path)
+      @paths[File.dirname(path)][File.basename(path)] != nil
+    end
+
+    # Returns the modification time of a file based on the precision defined by the system
+    #
+    # @param [String] file the file for which the mtime must be returned
+    #
+    # @return [Fixnum, Float] the mtime of the file
+    #
+    def mtime_of(file)
+      File.lstat(file).mtime.send(HIGH_PRECISION_SUPPORTED ? :to_f : :to_i)
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/listener.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/listener.rb
new file mode 100644
index 0000000..80ec227
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/listener.rb
@@ -0,0 +1,225 @@
+require 'pathname'
+
+module Listen
+  class Listener
+    attr_reader :directory, :directory_record, :adapter
+
+    # The default value for using relative paths in the callback.
+    DEFAULT_TO_RELATIVE_PATHS = false
+
+    # Initializes the directory listener.
+    #
+    # @param [String] directory the directory to listen to
+    # @param [Hash] options the listen options
+    # @option options [Regexp] ignore a pattern for ignoring paths
+    # @option options [Regexp] filter a pattern for filtering paths
+    # @option options [Float] latency the delay between checking for changes in seconds
+    # @option options [Boolean] relative_paths whether or not to use relative-paths in the callback
+    # @option options [Boolean] force_polling whether to force the polling adapter or not
+    # @option options [String, Boolean] polling_fallback_message to change polling fallback message or 
remove it
+    #
+    # @yield [modified, added, removed] the changed files
+    # @yieldparam [Array<String>] modified the list of modified files
+    # @yieldparam [Array<String>] added the list of added files
+    # @yieldparam [Array<String>] removed the list of removed files
+    #
+    def initialize(directory, options = {}, &block)
+      @block              = block
+      @directory          = Pathname.new(directory).realpath.to_s
+      @directory_record   = DirectoryRecord.new(@directory)
+      @use_relative_paths = DEFAULT_TO_RELATIVE_PATHS
+
+      @use_relative_paths = options.delete(:relative_paths) if options[:relative_paths]
+      @directory_record.ignore(*options.delete(:ignore))    if options[:ignore]
+      @directory_record.filter(*options.delete(:filter))    if options[:filter]
+
+      @adapter_options = options
+    end
+
+    # Starts the listener by initializing the adapter and building
+    # the directory record concurrently, then it starts the adapter to watch
+    # for changes.
+    #
+    # @param [Boolean] blocking whether or not to block the current thread after starting
+    #
+    def start(blocking = true)
+      t = Thread.new { @directory_record.build }
+      @adapter = initialize_adapter
+      t.join
+      @adapter.start(blocking)
+    end
+
+    # Stops the listener.
+    #
+    def stop
+      @adapter.stop
+    end
+
+    # Pauses the listener.
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def pause
+      @adapter.paused = true
+      self
+    end
+
+    # Unpauses the listener.
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def unpause
+      @directory_record.build
+      @adapter.paused = false
+      self
+    end
+
+    # Returns whether the listener is paused or not.
+    #
+    # @return [Boolean] adapter paused status
+    #
+    def paused?
+      !! adapter && @adapter.paused == true
+    end
+
+    # Adds ignoring patterns to the listener.
+    #
+    # @param (see Listen::DirectoryRecord#ignore)
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def ignore(*regexps)
+      @directory_record.ignore(*regexps)
+      self
+    end
+
+    # Replaces ignoring patterns in the listener.
+    #
+    # @param (see Listen::DirectoryRecord#ignore!)
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def ignore!(*regexps)
+      @directory_record.ignore!(*regexps)
+      self
+    end
+
+    # Adds filtering patterns to the listener.
+    #
+    # @param (see Listen::DirectoryRecord#filter)
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def filter(*regexps)
+      @directory_record.filter(*regexps)
+      self
+    end
+
+    # Replacing filtering patterns in the listener.
+    #
+    # @param (see Listen::DirectoryRecord#filter!)
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def filter!(*regexps)
+      @directory_record.filter!(*regexps)
+      self
+    end
+
+    # Sets the latency for the adapter. This is a helper method
+    # to simplify changing the latency directly from the listener.
+    #
+    # @example Wait 0.5 seconds each time before checking changes
+    #   latency 0.5
+    #
+    # @param [Float] seconds the amount of delay, in seconds
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def latency(seconds)
+      @adapter_options[:latency] = seconds
+      self
+    end
+
+    # Sets whether the use of the polling adapter
+    # should be forced or not.
+    #
+    # @example Forcing the use of the polling adapter
+    #   force_polling true
+    #
+    # @param [Boolean] value whether to force the polling adapter or not
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def force_polling(value)
+      @adapter_options[:force_polling] = value
+      self
+    end
+
+    # Sets whether the paths in the callback should be
+    # relative or absolute.
+    #
+    # @example Enabling relative paths in the callback
+    #   relative_paths true
+    #
+    # @param [Boolean] value whether to enable relative paths in the callback or not
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def relative_paths(value)
+      @use_relative_paths = value
+      self
+    end
+
+    # Defines a custom polling fallback message of disable it.
+    #
+    # @example Disabling the polling fallback message
+    #   polling_fallback_message false
+    #
+    # @param [String, Boolean] value to change polling fallback message or remove it
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def polling_fallback_message(value)
+      @adapter_options[:polling_fallback_message] = value
+      self
+    end
+
+    # Sets the callback that gets called on changes.
+    #
+    # @example Assign a callback to be called on changes
+    #   callback = lambda { |modified, added, removed| ... }
+    #   change &callback
+    #
+    # @param [Proc] block the callback proc
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def change(&block) # modified, added, removed
+      @block = block
+      self
+    end
+
+    # Runs the callback passing it the changes if there are any.
+    #
+    # @param (see Listen::DirectoryRecord#fetch_changes)
+    #
+    def on_change(directories, options = {})
+      changes = @directory_record.fetch_changes(directories, options.merge(
+        :relative_paths => @use_relative_paths
+      ))
+      unless changes.values.all? { |paths| paths.empty? }
+        @block.call(changes[:modified],changes[:added],changes[:removed])
+      end
+    end
+
+    private
+
+    # Initializes an adapter passing it the callback and adapters' options.
+    #
+    def initialize_adapter
+      callback = lambda { |changed_dirs, options| self.on_change(changed_dirs, options) }
+      Adapter.select_and_initialize(@directory, @adapter_options, &callback)
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/multi_listener.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/multi_listener.rb
new file mode 100644
index 0000000..4ff08ca
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/multi_listener.rb
@@ -0,0 +1,143 @@
+module Listen
+  class MultiListener < Listener
+    attr_reader :directories, :directories_records, :adapter
+
+    # Initializes the multiple directories listener.
+    #
+    # @param [String] directories the directories to listen to
+    # @param [Hash] options the listen options
+    # @option options [Regexp] ignore a pattern for ignoring paths
+    # @option options [Regexp] filter a pattern for filtering paths
+    # @option options [Float] latency the delay between checking for changes in seconds
+    # @option options [Boolean] force_polling whether to force the polling adapter or not
+    # @option options [String, Boolean] polling_fallback_message to change polling fallback message or 
remove it
+    #
+    # @yield [modified, added, removed] the changed files
+    # @yieldparam [Array<String>] modified the list of modified files
+    # @yieldparam [Array<String>] added the list of added files
+    # @yieldparam [Array<String>] removed the list of removed files
+    #
+    def initialize(*args, &block)
+      options     = args.last.is_a?(Hash) ? args.pop : {}
+      directories = args
+
+      @block               = block
+      @directories         = directories.map  { |d| Pathname.new(d).realpath.to_s }
+      @directories_records = @directories.map { |d| DirectoryRecord.new(d) }
+
+      ignore(*options.delete(:ignore)) if options[:ignore]
+      filter(*options.delete(:filter)) if options[:filter]
+
+      @adapter_options = options
+    end
+
+    # Starts the listener by initializing the adapter and building
+    # the directory record concurrently, then it starts the adapter to watch
+    # for changes.
+    #
+    # @param [Boolean] blocking whether or not to block the current thread after starting
+    #
+    def start(blocking = true)
+      t = Thread.new { @directories_records.each { |r| r.build } }
+      @adapter = initialize_adapter
+      t.join
+      @adapter.start(blocking)
+    end
+
+    # Unpauses the listener.
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def unpause
+      @directories_records.each { |r| r.build }
+      @adapter.paused = false
+      self
+    end
+
+    # Adds ignored paths to the listener.
+    #
+    # @param (see Listen::DirectoryRecord#ignore)
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def ignore(*paths)
+      @directories_records.each { |r| r.ignore(*paths) }
+      self
+    end
+
+    # Replaces ignored paths in the listener.
+    #
+    # @param (see Listen::DirectoryRecord#ignore!)
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def ignore!(*paths)
+      @directories_records.each { |r| r.ignore!(*paths) }
+      self
+    end
+
+    # Adds file filters to the listener.
+    #
+    # @param (see Listen::DirectoryRecord#filter)
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def filter(*regexps)
+      @directories_records.each { |r| r.filter(*regexps) }
+      self
+    end
+
+    # Replaces file filters in the listener.
+    #
+    # @param (see Listen::DirectoryRecord#filter!)
+    #
+    # @return [Listen::Listener] the listener
+    #
+    def filter!(*regexps)
+      @directories_records.each { |r| r.filter!(*regexps) }
+      self
+    end
+
+    # Runs the callback passing it the changes if there are any.
+    #
+    # @param (see Listen::DirectoryRecord#fetch_changes)
+    #
+    def on_change(directories_to_search, options = {})
+      changes = fetch_records_changes(directories_to_search, options)
+      unless changes.values.all? { |paths| paths.empty? }
+        @block.call(changes[:modified],changes[:added],changes[:removed])
+      end
+    end
+
+    private
+
+    # Initializes an adapter passing it the callback and adapters' options.
+    #
+    def initialize_adapter
+      callback = lambda { |changed_dirs, options| self.on_change(changed_dirs, options) }
+      Adapter.select_and_initialize(@directories, @adapter_options, &callback)
+    end
+
+    # Returns the sum of all the changes to the directories records
+    #
+    # @param (see Listen::DirectoryRecord#fetch_changes)
+    #
+    # @return [Hash] the changes
+    #
+    def fetch_records_changes(directories_to_search, options)
+      @directories_records.inject({}) do |h, r|
+        # directory records skips paths outside their range, so passing the
+        # whole `directories` array is not a problem.
+        record_changes = r.fetch_changes(directories_to_search, options.merge(:relative_paths => 
DEFAULT_TO_RELATIVE_PATHS))
+
+        if h.empty?
+          h.merge!(record_changes)
+        else
+          h.each { |k, v| h[k] += record_changes[k] }
+        end
+
+        h
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/turnstile.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/turnstile.rb
new file mode 100644
index 0000000..5e395d0
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/turnstile.rb
@@ -0,0 +1,28 @@
+module Listen
+  # Allows two threads to wait on eachother.
+  #
+  # @note Only two threads can be used with this Turnstile
+  #   because of the current implementation.
+  class Turnstile
+
+    # Initialize the turnstile.
+    #
+    def initialize
+      # Until ruby offers semahpores, only queues can be used
+      # to implement a turnstile.
+      @q = Queue.new
+    end
+
+    # Blocks the current thread until a signal is received.
+    #
+    def wait
+      @q.pop if @q.num_waiting == 0
+    end
+
+    # Unblocks the waiting thread if there is one.
+    #
+    def signal
+      @q.push :dummy if @q.num_waiting == 1
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/version.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/version.rb
new file mode 100644
index 0000000..3b23921
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/lib/listen/version.rb
@@ -0,0 +1,3 @@
+module Listen
+  VERSION = '0.7.3'
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/listen.gemspec 
b/backends/css/gems/sass-3.2.12/vendor/listen/listen.gemspec
new file mode 100644
index 0000000..e1d84ea
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/listen.gemspec
@@ -0,0 +1,22 @@
+# -*- encoding: utf-8 -*-
+$:.push File.expand_path('../lib', __FILE__)
+require 'listen/version'
+
+Gem::Specification.new do |s|
+  s.name        = 'listen'
+  s.version     = Listen::VERSION
+  s.platform    = Gem::Platform::RUBY
+  s.authors     = ['Thibaud Guillaume-Gentil', 'Maher Sallam']
+  s.email       = ['thibaud thibaud me', 'maher sallam me']
+  s.homepage    = 'https://github.com/guard/listen'
+  s.summary     = 'Listen to file modifications'
+  s.description = 'The Listen gem listens to file modifications and notifies you about the changes. Works 
everywhere!'
+
+  s.required_rubygems_version = '>= 1.3.6'
+  s.rubyforge_project = 'listen'
+
+  s.add_development_dependency 'bundler'
+
+  s.files        = Dir.glob('{lib}/**/*') + %w[CHANGELOG.md LICENSE README.md]
+  s.require_path = 'lib'
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapter_spec.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapter_spec.rb
new file mode 100644
index 0000000..8c7b19e
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapter_spec.rb
@@ -0,0 +1,183 @@
+require 'spec_helper'
+
+describe Listen::Adapter do
+  subject { described_class.new('dir') }
+
+  describe '#initialize' do
+    it 'sets the latency to the default one' do
+      subject.latency.should eq described_class::DEFAULT_LATENCY
+    end
+
+    it 'accepts a single directory to watch' do
+      described_class.new('dir').directories = %w{dir}
+    end
+
+    it 'accepts multiple directories to watch' do
+      described_class.new(%w{dir1 dir2}).directories.should eq %w{dir1 dir2}
+    end
+  end
+
+  describe ".select_and_initialize" do
+    before do
+      Listen::Adapters::Darwin.stub(:usable_and_works?) { false }
+      Listen::Adapters::Linux.stub(:usable_and_works?) { false }
+      Listen::Adapters::BSD.stub(:usable_and_works?) { false }
+      Listen::Adapters::Windows.stub(:usable_and_works?) { false }
+    end
+
+    context "with no specific adapter usable" do
+      it "returns Listen::Adapters::Polling instance" do
+        Kernel.stub(:warn)
+        Listen::Adapters::Polling.should_receive(:new).with('dir', {})
+        described_class.select_and_initialize('dir')
+      end
+
+      it 'warns with the default polling fallback message' do
+        Kernel.should_receive(:warn).with(/#{Listen::Adapter::POLLING_FALLBACK_MESSAGE}/)
+        described_class.select_and_initialize('dir')
+      end
+
+      context 'when the dependencies of an adapter are not satisfied' do
+        before do
+          Listen::Adapters::Darwin.stub(:usable_and_works?).and_raise(Listen::DependencyManager::Error)
+          Listen::Adapters::Linux.stub(:usable_and_works?).and_raise(Listen::DependencyManager::Error)
+          Listen::Adapters::BSD.stub(:usable_and_works?).and_raise(Listen::DependencyManager::Error)
+          Listen::Adapters::Windows.stub(:usable_and_works?).and_raise(Listen::DependencyManager::Error)
+        end
+
+        it 'invites the user to satisfy the dependencies of the adapter in the warning' do
+          Kernel.should_receive(:warn).with(/#{Listen::Adapter::MISSING_DEPENDENCY_MESSAGE}/)
+          described_class.select_and_initialize('dir')
+        end
+      end
+
+      context "with custom polling_fallback_message option" do
+        it "warns with the custom polling fallback message" do
+          Kernel.should_receive(:warn).with(/custom/)
+          described_class.select_and_initialize('dir', :polling_fallback_message => 'custom')
+        end
+      end
+
+      context "with polling_fallback_message to false" do
+        it "doesn't warn with a polling fallback message" do
+          Kernel.should_not_receive(:warn)
+          described_class.select_and_initialize('dir', :polling_fallback_message => false)
+        end
+      end
+    end
+
+    context "on Mac OX >= 10.6" do
+      before { Listen::Adapters::Darwin.stub(:usable_and_works?) { true } }
+
+      it "uses Listen::Adapters::Darwin" do
+        Listen::Adapters::Darwin.should_receive(:new).with('dir', {})
+        described_class.select_and_initialize('dir')
+      end
+
+      context 'when the use of the polling adapter is forced' do
+        it 'uses Listen::Adapters::Polling' do
+          Listen::Adapters::Polling.should_receive(:new).with('dir', {})
+          described_class.select_and_initialize('dir', :force_polling => true)
+        end
+      end
+    end
+
+    context "on Linux" do
+      before { Listen::Adapters::Linux.stub(:usable_and_works?) { true } }
+
+      it "uses Listen::Adapters::Linux" do
+        Listen::Adapters::Linux.should_receive(:new).with('dir', {})
+        described_class.select_and_initialize('dir')
+      end
+
+      context 'when the use of the polling adapter is forced' do
+        it 'uses Listen::Adapters::Polling' do
+          Listen::Adapters::Polling.should_receive(:new).with('dir', {})
+          described_class.select_and_initialize('dir', :force_polling => true)
+        end
+      end
+    end
+
+    context "on BSD" do
+      before { Listen::Adapters::BSD.stub(:usable_and_works?) { true } }
+
+      it "uses Listen::Adapters::BSD" do
+        Listen::Adapters::BSD.should_receive(:new).with('dir', {})
+        described_class.select_and_initialize('dir')
+      end
+
+      context 'when the use of the polling adapter is forced' do
+        it 'uses Listen::Adapters::Polling' do
+          Listen::Adapters::Polling.should_receive(:new).with('dir', {})
+          described_class.select_and_initialize('dir', :force_polling => true)
+        end
+      end
+    end
+
+    context "on Windows" do
+      before { Listen::Adapters::Windows.stub(:usable_and_works?) { true } }
+
+      it "uses Listen::Adapters::Windows" do
+        Listen::Adapters::Windows.should_receive(:new).with('dir', {})
+        described_class.select_and_initialize('dir')
+      end
+
+      context 'when the use of the polling adapter is forced' do
+        it 'uses Listen::Adapters::Polling' do
+          Listen::Adapters::Polling.should_receive(:new).with('dir', {})
+          described_class.select_and_initialize('dir', :force_polling => true)
+        end
+      end
+    end
+  end
+
+  [Listen::Adapters::Darwin, Listen::Adapters::Linux,
+   Listen::Adapters::BSD, Listen::Adapters::Windows].each do
+    |adapter_class|
+    if adapter_class.usable?
+      describe '.usable?' do
+        it 'checks the dependencies' do
+          adapter_class.should_receive(:load_depenencies)
+          adapter_class.should_receive(:dependencies_loaded?)
+          adapter_class.usable?
+        end
+      end
+
+      describe '.usable_and_works?' do
+        it 'checks if the adapter is usable' do
+          adapter_class.stub(:works?)
+          adapter_class.should_receive(:usable?)
+          adapter_class.usable_and_works?('dir')
+        end
+
+        context 'with one directory' do
+          it 'tests if that directory actually work' do
+            fixtures do |path|
+              adapter_class.should_receive(:works?).with(path, anything).and_return(true)
+              adapter_class.usable_and_works?(path)
+            end
+          end
+        end
+
+        context 'with multiple directories' do
+          it 'tests if each directory passed does actually work' do
+            fixtures(3) do |path1, path2, path3|
+              adapter_class.should_receive(:works?).exactly(3).times.with do |path, options|
+                [path1, path2, path3].include? path
+              end.and_return(true)
+              adapter_class.usable_and_works?([path1, path2, path3])
+            end
+          end
+        end
+      end
+
+      describe '.works?' do
+        it 'does work' do
+          fixtures do |path|
+            adapter_class.works?(path).should be_true
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/bsd_spec.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/bsd_spec.rb
new file mode 100644
index 0000000..ec02917
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/bsd_spec.rb
@@ -0,0 +1,36 @@
+require 'spec_helper'
+
+describe Listen::Adapters::BSD do
+  if bsd?
+    if Listen::Adapters::BSD.usable?
+      it "is usable on BSD" do
+        described_class.should be_usable
+      end
+
+      it_should_behave_like 'a filesystem adapter'
+      it_should_behave_like 'an adapter that call properly listener#on_change'
+    else
+      it "isn't usable on BSD with #{RbConfig::CONFIG['RUBY_INSTALL_NAME']}" do
+        described_class.should_not be_usable
+      end
+    end
+  end
+
+  if linux?
+    it "isn't usable on Linux" do
+      described_class.should_not be_usable
+    end
+  end
+
+  if mac?
+    it "isn't usable on Mac OS X" do
+      described_class.should_not be_usable
+    end
+  end
+
+  if windows?
+    it "isn't usable on Windows" do
+      described_class.should_not be_usable
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/darwin_spec.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/darwin_spec.rb
new file mode 100644
index 0000000..dabee67
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/darwin_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe Listen::Adapters::Darwin do
+  if mac?
+    if Listen::Adapters::Darwin.usable?
+      it "is usable on Mac OS X >= 10.6" do
+        described_class.should be_usable
+      end
+
+      it_should_behave_like 'a filesystem adapter'
+      it_should_behave_like 'an adapter that call properly listener#on_change'
+    else
+      it "isn't usable on Mac OS X with #{RbConfig::CONFIG['RUBY_INSTALL_NAME']}" do
+        described_class.should_not be_usable
+      end
+    end
+
+  end
+
+  if windows?
+    it "isn't usable on Windows" do
+      described_class.should_not be_usable
+    end
+  end
+
+  if linux?
+    it "isn't usable on Linux" do
+      described_class.should_not be_usable
+    end
+  end
+
+  if bsd?
+    it "isn't usable on BSD" do
+      described_class.should_not be_usable
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/linux_spec.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/linux_spec.rb
new file mode 100644
index 0000000..ff119aa
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/linux_spec.rb
@@ -0,0 +1,47 @@
+require 'spec_helper'
+
+describe Listen::Adapters::Linux do
+  if linux?
+    if Listen::Adapters::Linux.usable?
+      it "is usable on Linux" do
+        described_class.should be_usable
+      end
+
+      it_should_behave_like 'a filesystem adapter'
+      it_should_behave_like 'an adapter that call properly listener#on_change'
+
+      describe '#initialize' do
+        context 'when the inotify limit for watched files is not enough' do
+          before { INotify::Notifier.any_instance.should_receive(:watch).and_raise(Errno::ENOSPC) }
+
+          it 'fails gracefully' do
+            described_class.any_instance.should_receive(:abort).with(described_class::INOTIFY_LIMIT_MESSAGE)
+            described_class.new(File.dirname(__FILE__))
+          end
+        end
+      end
+    else
+      it "isn't usable on Linux with #{RbConfig::CONFIG['RUBY_INSTALL_NAME']}" do
+        described_class.should_not be_usable
+      end
+    end
+  end
+
+  if bsd?
+    it "isn't usable on BSD" do
+      described_class.should_not be_usable
+    end
+  end
+
+  if mac?
+    it "isn't usable on Mac OS X" do
+      described_class.should_not be_usable
+    end
+  end
+
+  if windows?
+    it "isn't usable on Windows" do
+      described_class.should_not be_usable
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/polling_spec.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/polling_spec.rb
new file mode 100644
index 0000000..d53b580
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/polling_spec.rb
@@ -0,0 +1,68 @@
+require 'spec_helper'
+
+describe Listen::Adapters::Polling do
+  subject { described_class.new('dir') }
+
+  it_should_behave_like 'a filesystem adapter'
+
+  describe '#initialize' do
+    it 'sets the latency to the default polling one' do
+      subject.latency.should eq Listen::Adapters::DEFAULT_POLLING_LATENCY
+    end
+  end
+
+  describe '#poll' do
+    let(:listener) { mock(Listen::Listener) }
+    let(:callback) { lambda { |changed_dirs, options| @called = true; listener.on_change(changed_dirs, 
options) } }
+
+    after { subject.stop }
+
+    context 'with one directory to watch' do
+      subject { Listen::Adapters::Polling.new('dir', {}, &callback) }
+
+      it 'calls listener.on_change' do
+        listener.should_receive(:on_change).at_least(1).times.with(['dir'], :recursive => true)
+        subject.start(false)
+        subject.wait_for_callback
+      end
+
+      it 'calls listener.on_change continuously' do
+        subject.latency = 0.001
+        listener.should_receive(:on_change).at_least(10).times.with(['dir'], :recursive => true)
+        subject.start(false)
+        10.times { subject.wait_for_callback }
+      end
+
+      it "doesn't call listener.on_change if paused" do
+        subject.paused = true
+        subject.start(false)
+        subject.wait_for_callback
+        @called.should be_nil
+      end
+    end
+
+    context 'with multiple directories to watch' do
+      subject { Listen::Adapters::Polling.new(%w{dir1 dir2}, {}, &callback) }
+
+      it 'calls listener.on_change' do
+        listener.should_receive(:on_change).at_least(1).times.with(%w{dir1 dir2}, :recursive => true)
+        subject.start(false)
+        subject.wait_for_callback
+      end
+
+      it 'calls listener.on_change continuously' do
+        subject.latency = 0.001
+        listener.should_receive(:on_change).at_least(10).times.with(%w{dir1 dir2}, :recursive => true)
+        subject.start(false)
+        10.times { subject.wait_for_callback }
+      end
+
+      it "doesn't call listener.on_change if paused" do
+        subject.paused = true
+        subject.start(false)
+        subject.wait_for_callback
+        @called.should be_nil
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/windows_spec.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/windows_spec.rb
new file mode 100644
index 0000000..b9cd969
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/adapters/windows_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe Listen::Adapters::Windows do
+  if windows? && Listen::Adapters::Windows.usable?
+    it "is usable on Windows" do
+      described_class.should be_usable
+    end
+
+    it_should_behave_like 'a filesystem adapter'
+    it_should_behave_like 'an adapter that call properly listener#on_change'
+  end
+
+  if mac?
+    it "isn't usable on Mac OS X" do
+      described_class.should_not be_usable
+    end
+  end
+
+  if bsd?
+    it "isn't usable on BSD" do
+      described_class.should_not be_usable
+    end
+  end
+
+  if linux?
+    it "isn't usable on Linux" do
+      described_class.should_not be_usable
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/dependency_manager_spec.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/dependency_manager_spec.rb
new file mode 100644
index 0000000..f1d3203
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/dependency_manager_spec.rb
@@ -0,0 +1,107 @@
+require 'spec_helper'
+
+describe Listen::DependencyManager do
+  let(:dependency) { Listen::DependencyManager::Dependency.new('listen', '~> 0.0.1') }
+
+  subject { Class.new { extend Listen::DependencyManager } }
+
+  before { described_class.clear_loaded }
+
+  describe '.add_loaded' do
+    it 'adds a dependency to the list of loaded dependencies' do
+      described_class.add_loaded dependency
+      described_class.already_loaded?(dependency).should be_true
+    end
+  end
+
+  describe '.already_loaded?' do
+    it 'returns false when a dependency is not in the list of loaded dependencies' do
+      described_class.already_loaded?(dependency).should be_false
+    end
+
+    it 'returns true when a dependency is in the list of loaded dependencies' do
+      described_class.add_loaded dependency
+      described_class.already_loaded?(dependency).should be_true
+    end
+  end
+
+  describe '.clear_loaded' do
+    it 'clears the whole list of loaded dependencies' do
+      described_class.add_loaded dependency
+      described_class.already_loaded?(dependency).should be_true
+      described_class.clear_loaded
+      described_class.already_loaded?(dependency).should be_false
+    end
+  end
+
+  describe '#dependency' do
+    it 'registers a new dependency for the managed class' do
+      subject.dependency 'listen', '~> 0.0.1'
+      subject.dependencies_loaded?.should be_false
+    end
+  end
+
+  describe '#load_depenencies' do
+    before { subject.dependency 'listen', '~> 0.0.1' }
+
+    context 'when dependencies can be loaded' do
+      before { subject.stub(:gem, :require) }
+
+      it 'loads all the registerd dependencies' do
+        subject.load_depenencies
+        subject.dependencies_loaded?.should be_true
+      end
+    end
+
+    context 'when dependencies can not be loaded' do
+      it 'raises an error' do
+        expect {
+          subject.load_depenencies
+        }.to raise_error(described_class::Error)
+      end
+
+      context 'when running under bundler' do
+        before { subject.should_receive(:running_under_bundler?).and_return(true) }
+
+        it 'includes the Gemfile declaration to satisfy the dependency' do
+          begin
+            subject.load_depenencies
+          rescue described_class::Error => e
+            e.message.should include("gem 'listen', '~> 0.0.1'")
+          end
+        end
+      end
+
+      context 'when not running under bundler' do
+        before { subject.should_receive(:running_under_bundler?).and_return(false) }
+
+        it 'includes the command to install the dependency' do
+          begin
+            subject.load_depenencies
+          rescue described_class::Error => e
+            e.message.should include("gem install --version '~> 0.0.1' listen")
+          end
+        end
+      end
+    end
+  end
+
+  describe '#dependencies_loaded?' do
+    it 'return false when dependencies are not loaded' do
+      subject.dependency 'listen', '~> 0.0.1'
+      subject.dependencies_loaded?.should be_false
+    end
+
+    it 'return true when dependencies are loaded' do
+      subject.stub(:gem, :require)
+
+      subject.dependency 'listen', '~> 0.0.1'
+      subject.load_depenencies
+      subject.dependencies_loaded?.should be_true
+    end
+
+    it 'return true when there are no dependencies to load' do
+      subject.dependencies_loaded?.should be_true
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/directory_record_spec.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/directory_record_spec.rb
new file mode 100644
index 0000000..d7a64b6
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/directory_record_spec.rb
@@ -0,0 +1,1225 @@
+# encoding: UTF-8
+require 'spec_helper'
+
+describe Listen::DirectoryRecord do
+  let(:base_directory) { File.dirname(__FILE__) }
+
+  subject { described_class.new(base_directory) }
+
+  describe '.generate_default_ignoring_patterns' do
+    it 'creates regexp patterns from the default ignored directories and extensions' do
+      described_class.generate_default_ignoring_patterns.should include(
+        %r{^(?:\.rbx|\.bundle|\.git|\.svn|log|tmp|vendor)/},
+        %r{(?:\.DS_Store)$}
+      )
+    end
+
+    it 'memoizes the generated results' do
+      described_class.generate_default_ignoring_patterns.should equal 
described_class.generate_default_ignoring_patterns
+    end
+  end
+
+  describe '#initialize' do
+    it 'sets the base directory' do
+      subject.directory.should eq base_directory
+    end
+
+    it 'sets the default ignoring patterns' do
+      subject.ignoring_patterns.should =~ described_class.generate_default_ignoring_patterns
+    end
+
+    it 'sets the default filtering patterns' do
+      subject.filtering_patterns.should eq []
+    end
+
+    it 'raises an error when the passed path does not exist' do
+      expect { described_class.new('no way I exist') }.to raise_error(ArgumentError)
+    end
+
+    it 'raises an error when the passed path is not a directory' do
+      expect { described_class.new(__FILE__) }.to raise_error(ArgumentError)
+    end
+  end
+
+  describe '#ignore' do
+    it 'adds the passed paths to the list of ignored paths in the record' do
+      subject.ignore(%r{^\.old/}, %r{\.pid$})
+      subject.ignoring_patterns.should include(%r{^\.old/}, %r{\.pid$})
+    end
+  end
+
+  describe '#ignore!' do
+    it 'replace the ignored paths in the record' do
+      subject.ignore!(%r{^\.old/}, %r{\.pid$})
+      subject.ignoring_patterns.should =~ [%r{^\.old/}, %r{\.pid$}]
+    end
+  end
+
+  describe '#filter' do
+    it 'adds the passed regexps to the list of filters that determine the stored paths' do
+      subject.filter(%r{\.(?:jpe?g|gif|png)}, %r{\.(?:mp3|ogg|a3c)})
+      subject.filtering_patterns.should include(%r{\.(?:jpe?g|gif|png)}, %r{\.(?:mp3|ogg|a3c)})
+    end
+  end
+
+  describe '#filter!' do
+    it 'replaces the passed regexps in the list of filters that determine the stored paths' do
+      subject.filter!(%r{\.(?:jpe?g|gif|png)}, %r{\.(?:mp3|ogg|a3c)})
+      subject.filtering_patterns.should =~ [%r{\.(?:mp3|ogg|a3c)}, %r{\.(?:jpe?g|gif|png)}]
+    end
+  end
+
+  describe '#ignored?' do
+    before { subject.stub(:relative_to_base) { |path| path } }
+
+    it 'tests paths relative to the base directory' do
+      subject.should_receive(:relative_to_base).with('file.txt')
+      subject.ignored?('file.txt')
+    end
+
+    it 'returns true when the passed path is a default ignored path' do
+      subject.ignored?('tmp/some_process.pid').should be_true
+      subject.ignored?('dir/.DS_Store').should be_true
+      subject.ignored?('.git/config').should be_true
+    end
+
+    it 'returns false when the passed path is not a default ignored path' do
+      subject.ignored?('nested/tmp/some_process.pid').should be_false
+      subject.ignored?('nested/.git').should be_false
+      subject.ignored?('dir/.DS_Store/file').should be_false
+      subject.ignored?('file.git').should be_false
+    end
+
+    it 'returns true when the passed path is ignored' do
+      subject.ignore(%r{\.pid$})
+      subject.ignored?('dir/some_process.pid').should be_true
+    end
+
+    it 'returns false when the passed path is not ignored' do
+      subject.ignore(%r{\.pid$})
+      subject.ignored?('dir/some_file.txt').should be_false
+    end
+  end
+
+  describe '#filtered?' do
+    before { subject.stub(:relative_to_base) { |path| path } }
+
+    context 'when no filtering patterns are set' do
+      it 'returns true for any path' do
+        subject.filtered?('file.txt').should be_true
+      end
+    end
+
+    context 'when filtering patterns are set' do
+      before { subject.filter(%r{\.(?:jpe?g|gif|png)}) }
+
+      it 'tests paths relative to the base directory' do
+        subject.should_receive(:relative_to_base).with('file.txt')
+        subject.filtered?('file.txt')
+      end
+
+      it 'returns true when the passed path is filtered' do
+        subject.filter(%r{\.(?:jpe?g|gif|png)})
+        subject.filtered?('dir/picture.jpeg').should be_true
+      end
+
+      it 'returns false when the passed path is not filtered' do
+        subject.filter(%r{\.(?:jpe?g|gif|png)})
+        subject.filtered?('dir/song.mp3').should be_false
+      end
+    end
+  end
+
+  describe '#build' do
+    it 'stores all files' do
+      fixtures do |path|
+        touch 'file.rb'
+        mkdir 'a_directory'
+        touch 'a_directory/file.txt'
+
+        record = described_class.new(path)
+        record.build
+
+        record.paths[path]['file.rb'].type.should eq 'File'
+        record.paths[path]['a_directory'].type.should eq 'Dir'
+        record.paths["#{path}/a_directory"]['file.txt'].type.should eq 'File'
+      end
+    end
+
+    context 'with ignored path set' do
+      it 'does not store ignored directory or its childs' do
+        fixtures do |path|
+          mkdir 'ignored_directory'
+          mkdir 'ignored_directory/child_directory'
+          touch 'ignored_directory/file.txt'
+
+          record = described_class.new(path)
+          record.ignore %r{^ignored_directory/}
+          record.build
+
+          record.paths[path]['/a_ignored_directory'].should be_nil
+          record.paths["#{path}/a_ignored_directory"]['child_directory'].should be_nil
+          record.paths["#{path}/a_ignored_directory"]['file.txt'].should be_nil
+        end
+      end
+
+      it 'does not store ignored files' do
+        fixtures do |path|
+          touch 'ignored_file.rb'
+
+          record = described_class.new(path)
+          record.ignore %r{^ignored_file.rb$}
+          record.build
+
+          record.paths[path]['ignored_file.rb'].should be_nil
+        end
+      end
+    end
+
+    context 'with filters set' do
+      it 'only stores filterd files' do
+        fixtures do |path|
+          touch 'file.rb'
+          touch 'file.zip'
+          mkdir 'a_directory'
+          touch 'a_directory/file.txt'
+          touch 'a_directory/file.rb'
+
+          record = described_class.new(path)
+          record.filter(/\.txt$/, /.*\.zip/)
+          record.build
+
+          record.paths[path]['file.rb'].should be_nil
+          record.paths[path]['file.zip'].type.should eq 'File'
+          record.paths[path]['a_directory'].type.should eq 'Dir'
+          record.paths["#{path}/a_directory"]['file.txt'].type.should eq 'File'
+          record.paths["#{path}/a_directory"]['file.rb'].should be_nil
+        end
+      end
+    end
+  end
+
+  describe '#relative_to_base' do
+    it 'removes the path of the base-directory from the passed path' do
+      path = 'dir/to/app/file.rb'
+      subject.relative_to_base(File.join(base_directory, path)).should eq path
+    end
+
+    it 'returns nil when the passed path is not inside the base-directory' do
+      subject.relative_to_base('/tmp/some_random_path').should be_nil
+    end
+
+    it 'works with non UTF-8 paths' do
+      path = "tmp/\xE4\xE4"
+      subject.relative_to_base(File.join(base_directory, path))
+    end
+
+    context 'when containing regexp characters in the base directory' do
+      before do
+        fixtures do |path|
+          mkdir 'a_directory$'
+          @dir = described_class.new(path + '/a_directory$')
+          @dir.build
+        end
+      end
+
+      it 'removes the path of the base-directory from the passed path' do
+        path = 'dir/to/app/file.rb'
+        @dir.relative_to_base(File.join(@dir.directory, path)).should eq path
+      end
+
+      it 'returns nil when the passed path is not inside the base-directory' do
+        @dir.relative_to_base('/tmp/some_random_path').should be_nil
+      end
+    end
+  end
+
+  describe '#fetch_changes' do
+    context 'with single file changes' do
+      context 'when a file is created' do
+        it 'detects the added file' do
+          fixtures do |path|
+            modified, added, removed = changes(path) do
+              touch 'new_file.rb'
+            end
+
+            added.should =~ %w(new_file.rb)
+            modified.should be_empty
+            removed.should be_empty
+          end
+        end
+
+        it 'stores the added file in the record' do
+          fixtures do |path|
+            changes(path) do
+              @record.paths.should be_empty
+
+              touch 'new_file.rb'
+            end
+
+            @record.paths[path]['new_file.rb'].should_not be_nil
+          end
+        end
+
+        context 'given a new created directory' do
+          it 'detects the added file' do
+            fixtures do |path|
+              modified, added, removed = changes(path) do
+                mkdir 'a_directory'
+                touch 'a_directory/new_file.rb'
+              end
+
+              added.should =~ %w(a_directory/new_file.rb)
+              modified.should be_empty
+              removed.should be_empty
+            end
+          end
+
+          it 'stores the added directory and file in the record' do
+            fixtures do |path|
+              changes(path) do
+                @record.paths.should be_empty
+
+                mkdir 'a_directory'
+                touch 'a_directory/new_file.rb'
+              end
+
+              @record.paths[path]['a_directory'].should_not be_nil
+              @record.paths["#{path}/a_directory"]['new_file.rb'].should_not be_nil
+            end
+          end
+        end
+
+        context 'given an existing directory' do
+          context 'with recursive option set to true' do
+            it 'detects the added file' do
+              fixtures do |path|
+                mkdir 'a_directory'
+
+                modified, added, removed = changes(path, :recursive => true) do
+                  touch 'a_directory/new_file.rb'
+                end
+
+                added.should =~ %w(a_directory/new_file.rb)
+                modified.should be_empty
+                removed.should be_empty
+              end
+            end
+
+            context 'with an ignored directory' do
+              it "doesn't detect the added file" do
+                fixtures do |path|
+                  mkdir 'ignored_directory'
+
+                  modified, added, removed = changes(path, :ignore => %r{^ignored_directory/}, :recursive => 
true) do
+                    touch 'ignored_directory/new_file.rb'
+                  end
+
+                  added.should be_empty
+                  modified.should be_empty
+                  removed.should be_empty
+                end
+              end
+
+              it "doesn't detect the added file when it's asked to fetch the changes of the ignored 
directory"do
+                fixtures do |path|
+                  mkdir 'ignored_directory'
+
+                  modified, added, removed = changes(path, :paths => ["#{path}/ignored_directory"], :ignore 
=> %r{^ignored_directory/}, :recursive => true) do
+                    touch 'ignored_directory/new_file.rb'
+                  end
+
+                  added.should be_empty
+                  modified.should be_empty
+                  removed.should be_empty
+                end
+              end
+            end
+          end
+
+          context 'with recursive option set to false' do
+            it "doesn't detect deeply-nested added files" do
+              fixtures do |path|
+                mkdir 'a_directory'
+
+                modified, added, removed = changes(path, :recursive => false) do
+                  touch 'a_directory/new_file.rb'
+                end
+
+                added.should be_empty
+                modified.should be_empty
+                removed.should be_empty
+              end
+            end
+          end
+        end
+
+        context 'given a directory with subdirectories' do
+          it 'detects the added file' do
+            fixtures do |path|
+              mkdir_p 'a_directory/subdirectory'
+
+              modified, added, removed = changes(path, :recursive => true) do
+                touch 'a_directory/subdirectory/new_file.rb'
+              end
+
+              added.should =~ %w(a_directory/subdirectory/new_file.rb)
+              modified.should be_empty
+              removed.should be_empty
+            end
+          end
+
+          context 'with an ignored directory' do
+            it "doesn't detect added files in neither the directory nor the subdirectory" do
+              fixtures do |path|
+                mkdir_p 'ignored_directory/subdirectory'
+
+                modified, added, removed = changes(path, :ignore => %r{^ignored_directory/}, :recursive => 
true) do
+                  touch 'ignored_directory/new_file.rb'
+                  touch 'ignored_directory/subdirectory/new_file.rb'
+                end
+
+                added.should be_empty
+                modified.should be_empty
+                removed.should be_empty
+              end
+            end
+          end
+        end
+      end
+
+      context 'when a file is modified' do
+        it 'detects the modified file' do
+          fixtures do |path|
+            touch 'existing_file.txt'
+
+            modified, added, removed = changes(path) do
+              sleep 1.5 # make a difference in the mtime of the file
+              touch 'existing_file.txt'
+            end
+
+            added.should be_empty
+            modified.should =~ %w(existing_file.txt)
+            removed.should be_empty
+          end
+        end
+
+        context 'during the same second at which we are checking for changes' do
+          before { ensure_same_second }
+
+          # The following test can only be run on systems that report
+          # modification times in milliseconds.
+          it 'always detects the modified file the first time', :if => 
described_class::HIGH_PRECISION_SUPPORTED do
+            fixtures do |path|
+              touch 'existing_file.txt'
+
+              modified, added, removed = changes(path) do
+                sleep 0.3 # make sure the mtime is changed a bit
+                touch 'existing_file.txt'
+              end
+
+              added.should be_empty
+              modified.should =~ %w(existing_file.txt)
+              removed.should be_empty
+            end
+          end
+
+          context 'when a file is created and then checked for modifications at the same second - #27' do
+            # This issue was the result of checking a file for content changes when
+            # the mtime and the checking time are the same. In this case there
+            # is no checksum saved, so the file was reported as being changed.
+            it ' does not report any changes' do
+              fixtures do |path|
+                touch 'a_file.rb'
+
+                modified, added, removed = changes(path)
+
+                added.should be_empty
+                modified.should be_empty
+                removed.should be_empty
+              end
+            end
+          end
+
+          it "doesn't detects the modified file the second time if the content haven't changed" do
+            fixtures do |path|
+              touch 'existing_file.txt'
+
+              changes(path) do
+                touch 'existing_file.txt'
+              end
+
+              modified, added, removed = changes(path, :use_last_record => true) do
+                touch 'existing_file.txt'
+              end
+
+              added.should be_empty
+              modified.should be_empty
+              removed.should be_empty
+            end
+          end
+
+          it 'detects the modified file the second time if the content have changed' do
+            fixtures do |path|
+              touch 'existing_file.txt'
+              # Set sha1 path checksum
+              changes(path) do
+                touch 'existing_file.txt'
+              end
+              small_time_difference
+
+              changes(path) do
+                touch 'existing_file.txt'
+              end
+
+              modified, added, removed = changes(path, :use_last_record => true) do
+                open('existing_file.txt', 'w') { |f| f.write('foo') }
+              end
+
+              added.should be_empty
+              modified.should =~ %w(existing_file.txt)
+              removed.should be_empty
+            end
+          end
+
+          it "doesn't detects the modified file the second time if just touched - #62" do
+            fixtures do |path|
+              touch 'existing_file.txt'
+              # Set sha1 path checksum
+              changes(path) do
+                touch 'existing_file.txt'
+              end
+              small_time_difference
+
+              changes(path, :use_last_record => true) do
+                open('existing_file.txt', 'w') { |f| f.write('foo') }
+              end
+
+              modified, added, removed = changes(path, :use_last_record => true) do
+                touch 'existing_file.txt'
+              end
+
+              added.should be_empty
+              modified.should be_empty
+              removed.should be_empty
+            end
+          end
+
+          it "adds the path in the paths checksums if just touched - #62" do
+            fixtures do |path|
+              touch 'existing_file.txt'
+              small_time_difference
+
+              changes(path) do
+                touch 'existing_file.txt'
+              end
+
+              @record.sha1_checksums["#{path}/existing_file.txt"].should_not be_nil
+            end
+          end
+
+        it "deletes the path from the paths checksums" do
+          fixtures do |path|
+            touch 'unnecessary.txt'
+
+            changes(path) do
+              @record.sha1_checksums["#{path}/unnecessary.txt"] = 'foo'
+
+              rm 'unnecessary.txt'
+            end
+
+            @record.sha1_checksums["#{path}/unnecessary.txt"].should be_nil
+          end
+        end
+
+
+        end
+
+        context 'given a hidden file' do
+          it 'detects the modified file' do
+            fixtures do |path|
+              touch '.hidden'
+
+              modified, added, removed = changes(path) do
+                small_time_difference
+                touch '.hidden'
+              end
+
+              added.should be_empty
+              modified.should =~ %w(.hidden)
+              removed.should be_empty
+            end
+          end
+        end
+
+        context 'given a file mode change' do
+          it 'does not detect the mode change' do
+            fixtures do |path|
+              touch 'run.rb'
+              sleep 1.5 # make a difference in the mtime of the file
+
+              modified, added, removed = changes(path) do
+                chmod 0777, 'run.rb'
+              end
+
+              added.should be_empty
+              modified.should be_empty
+              removed.should be_empty
+            end
+          end
+        end
+
+        context 'given an existing directory' do
+          context 'with recursive option set to true' do
+            it 'detects the modified file' do
+              fixtures do |path|
+                mkdir 'a_directory'
+                touch 'a_directory/existing_file.txt'
+
+                modified, added, removed = changes(path, :recursive => true) do
+                  small_time_difference
+                  touch 'a_directory/existing_file.txt'
+                end
+
+                added.should be_empty
+                modified.should =~ %w(a_directory/existing_file.txt)
+                removed.should be_empty
+              end
+            end
+          end
+
+          context 'with recursive option set to false' do
+            it "doesn't detects the modified file" do
+              fixtures do |path|
+                mkdir 'a_directory'
+                touch 'a_directory/existing_file.txt'
+
+                modified, added, removed = changes(path, :recursive => false) do
+                  small_time_difference
+                  touch 'a_directory/existing_file.txt'
+                end
+
+                added.should be_empty
+                modified.should be_empty
+                removed.should be_empty
+              end
+            end
+          end
+        end
+
+        context 'given a directory with subdirectories' do
+          it 'detects the modified file' do
+            fixtures do |path|
+              mkdir_p 'a_directory/subdirectory'
+              touch   'a_directory/subdirectory/existing_file.txt'
+
+              modified, added, removed = changes(path, :recursive => true) do
+                small_time_difference
+                touch 'a_directory/subdirectory/existing_file.txt'
+              end
+
+              added.should be_empty
+              modified.should =~ %w(a_directory/subdirectory/existing_file.txt)
+              removed.should be_empty
+            end
+          end
+
+          context 'with an ignored subdirectory' do
+            it "doesn't detect the modified files in neither the directory nor the subdirectory" do
+              fixtures do |path|
+                mkdir_p 'ignored_directory/subdirectory'
+                touch   'ignored_directory/existing_file.txt'
+                touch   'ignored_directory/subdirectory/existing_file.txt'
+
+                modified, added, removed = changes(path, :ignore => %r{^ignored_directory/}, :recursive => 
true) do
+                  touch 'ignored_directory/existing_file.txt'
+                  touch 'ignored_directory/subdirectory/existing_file.txt'
+                end
+
+                added.should be_empty
+                modified.should be_empty
+                removed.should be_empty
+              end
+            end
+          end
+        end
+      end
+
+      context 'when a file is moved' do
+        it 'detects the file movement' do
+          fixtures do |path|
+            touch 'move_me.txt'
+
+            modified, added, removed = changes(path) do
+              mv 'move_me.txt', 'new_name.txt'
+            end
+
+            added.should =~ %w(new_name.txt)
+            modified.should be_empty
+            removed.should =~ %w(move_me.txt)
+          end
+        end
+
+        context 'given an existing directory' do
+          context 'with recursive option set to true' do
+            it 'detects the file movement into the directory' do
+              fixtures do |path|
+                mkdir 'a_directory'
+                touch 'move_me.txt'
+
+                modified, added, removed = changes(path, :recursive => true) do
+                  mv 'move_me.txt', 'a_directory/move_me.txt'
+                end
+
+                added.should =~ %w(a_directory/move_me.txt)
+                modified.should be_empty
+                removed.should =~ %w(move_me.txt)
+              end
+            end
+
+            it 'detects a file movement out of the directory' do
+              fixtures do |path|
+                mkdir 'a_directory'
+                touch 'a_directory/move_me.txt'
+
+                modified, added, removed = changes(path, :recursive => true) do
+                  mv 'a_directory/move_me.txt', 'i_am_here.txt'
+                end
+
+                added.should =~ %w(i_am_here.txt)
+                modified.should be_empty
+                removed.should =~ %w(a_directory/move_me.txt)
+              end
+            end
+
+            it 'detects a file movement between two directories' do
+              fixtures do |path|
+                mkdir 'from_directory'
+                touch 'from_directory/move_me.txt'
+                mkdir 'to_directory'
+
+                modified, added, removed = changes(path, :recursive => true) do
+                  mv 'from_directory/move_me.txt', 'to_directory/move_me.txt'
+                end
+
+                added.should =~ %w(to_directory/move_me.txt)
+                modified.should be_empty
+                removed.should =~ %w(from_directory/move_me.txt)
+              end
+            end
+          end
+
+          context 'with recursive option set to false' do
+            it "doesn't detect the file movement into the directory" do
+              fixtures do |path|
+                mkdir 'a_directory'
+                touch 'move_me.txt'
+
+                modified, added, removed = changes(path, :recursive => false) do
+                  mv 'move_me.txt', 'a_directory/move_me.txt'
+                end
+
+                added.should be_empty
+                modified.should be_empty
+                removed.should =~ %w(move_me.txt)
+              end
+            end
+
+            it "doesn't detect a file movement out of the directory" do
+              fixtures do |path|
+                mkdir 'a_directory'
+                touch 'a_directory/move_me.txt'
+
+                modified, added, removed = changes(path, :recursive => false) do
+                  mv 'a_directory/move_me.txt', 'i_am_here.txt'
+                end
+
+                added.should =~ %w(i_am_here.txt)
+                modified.should be_empty
+                removed.should be_empty
+              end
+            end
+
+            it "doesn't detect a file movement between two directories" do
+              fixtures do |path|
+                mkdir 'from_directory'
+                touch 'from_directory/move_me.txt'
+                mkdir 'to_directory'
+
+                modified, added, removed = changes(path, :recursive => false) do
+                  mv 'from_directory/move_me.txt', 'to_directory/move_me.txt'
+                end
+
+                added.should be_empty
+                modified.should be_empty
+                removed.should be_empty
+              end
+            end
+
+            context 'given a directory with subdirectories' do
+              it 'detects a file movement between two subdirectories' do
+                fixtures do |path|
+                  mkdir_p 'a_directory/subdirectory'
+                  mkdir_p 'b_directory/subdirectory'
+                  touch   'a_directory/subdirectory/move_me.txt'
+
+                  modified, added, removed = changes(path, :recursive => true) do
+                    mv 'a_directory/subdirectory/move_me.txt', 'b_directory/subdirectory'
+                  end
+
+                  added.should =~ %w(b_directory/subdirectory/move_me.txt)
+                  modified.should be_empty
+                  removed.should =~ %w(a_directory/subdirectory/move_me.txt)
+                end
+              end
+
+              context 'with an ignored subdirectory' do
+                it "doesn't detect the file movement between subdirectories" do
+                  fixtures do |path|
+                    mkdir_p 'a_ignored_directory/subdirectory'
+                    mkdir_p 'b_ignored_directory/subdirectory'
+                    touch   'a_ignored_directory/subdirectory/move_me.txt'
+
+                    modified, added, removed = changes(path, :ignore => %r{^(?:a|b)_ignored_directory/}, 
:recursive => true) do
+                      mv 'a_ignored_directory/subdirectory/move_me.txt', 'b_ignored_directory/subdirectory'
+                    end
+
+                    added.should be_empty
+                    modified.should be_empty
+                    removed.should be_empty
+                  end
+                end
+              end
+            end
+
+            context 'with all paths passed as params' do
+              it 'detects the file movement into the directory' do
+                fixtures do |path|
+                  mkdir 'a_directory'
+                  touch 'move_me.txt'
+
+                  modified, added, removed = changes(path, :recursive => false, :paths => [path, 
"#{path}/a_directory"]) do
+                    mv 'move_me.txt', 'a_directory/move_me.txt'
+                  end
+
+                  added.should =~ %w(a_directory/move_me.txt)
+                  modified.should be_empty
+                  removed.should =~ %w(move_me.txt)
+                end
+              end
+
+              it 'detects a file moved outside of a directory' do
+                fixtures do |path|
+                  mkdir 'a_directory'
+                  touch 'a_directory/move_me.txt'
+
+                  modified, added, removed = changes(path, :recursive => false, :paths => [path, 
"#{path}/a_directory"]) do
+                    mv 'a_directory/move_me.txt', 'i_am_here.txt'
+                  end
+
+                  added.should =~ %w(i_am_here.txt)
+                  modified.should be_empty
+                  removed.should =~ %w(a_directory/move_me.txt)
+                end
+              end
+
+              it 'detects a file movement between two directories' do
+                fixtures do |path|
+                  mkdir 'from_directory'
+                  touch 'from_directory/move_me.txt'
+                  mkdir 'to_directory'
+
+                  modified, added, removed = changes(path, :recursive => false, :paths => [path, 
"#{path}/from_directory", "#{path}/to_directory"]) do
+                    mv 'from_directory/move_me.txt', 'to_directory/move_me.txt'
+                  end
+
+                  added.should =~ %w(to_directory/move_me.txt)
+                  modified.should be_empty
+                  removed.should =~ %w(from_directory/move_me.txt)
+                end
+              end
+            end
+          end
+        end
+      end
+
+      context 'when a file is deleted' do
+        it 'detects the file removal' do
+          fixtures do |path|
+            touch 'unnecessary.txt'
+
+            modified, added, removed = changes(path) do
+              rm 'unnecessary.txt'
+            end
+
+            added.should be_empty
+            modified.should be_empty
+            removed.should =~ %w(unnecessary.txt)
+          end
+        end
+
+        it "deletes the file from the record" do
+          fixtures do |path|
+            touch 'unnecessary.txt'
+
+            changes(path) do
+              @record.paths[path]['unnecessary.txt'].should_not be_nil
+
+              rm 'unnecessary.txt'
+            end
+
+            @record.paths[path]['unnecessary.txt'].should be_nil
+          end
+        end
+
+        it "deletes the path from the paths checksums" do
+          fixtures do |path|
+            touch 'unnecessary.txt'
+
+            changes(path) do
+              @record.sha1_checksums["#{path}/unnecessary.txt"] = 'foo'
+
+              rm 'unnecessary.txt'
+            end
+
+            @record.sha1_checksums["#{path}/unnecessary.txt"].should be_nil
+          end
+        end
+
+        context 'given an existing directory' do
+          context 'with recursive option set to true' do
+            it 'detects the file removal' do
+              fixtures do |path|
+                mkdir 'a_directory'
+                touch 'a_directory/do_not_use.rb'
+
+                modified, added, removed = changes(path, :recursive => true) do
+                  rm 'a_directory/do_not_use.rb'
+                end
+
+                added.should be_empty
+                modified.should be_empty
+                removed.should =~ %w(a_directory/do_not_use.rb)
+              end
+            end
+          end
+
+          context 'with recursive option set to false' do
+            it "doesn't detect the file removal" do
+              fixtures do |path|
+                mkdir 'a_directory'
+                touch 'a_directory/do_not_use.rb'
+
+                modified, added, removed = changes(path, :recursive => false) do
+                  rm 'a_directory/do_not_use.rb'
+                end
+
+                added.should be_empty
+                modified.should be_empty
+                removed.should be_empty
+              end
+            end
+          end
+        end
+
+        context 'given a directory with subdirectories' do
+          it 'detects the file removal in subdirectories' do
+            fixtures do |path|
+              mkdir_p 'a_directory/subdirectory'
+              touch   'a_directory/subdirectory/do_not_use.rb'
+
+              modified, added, removed = changes(path, :recursive => true) do
+                rm 'a_directory/subdirectory/do_not_use.rb'
+              end
+
+              added.should be_empty
+              modified.should be_empty
+              removed.should =~ %w(a_directory/subdirectory/do_not_use.rb)
+            end
+          end
+
+          context 'with an ignored subdirectory' do
+            it "doesn't detect files removals in neither the directory nor its subdirectories" do
+              fixtures do |path|
+                mkdir_p 'ignored_directory/subdirectory'
+                touch   'ignored_directory/do_not_use.rb'
+                touch   'ignored_directory/subdirectory/do_not_use.rb'
+
+                modified, added, removed = changes(path, :ignore => %r{^ignored_directory/}, :recursive => 
true) do
+                  rm 'ignored_directory/do_not_use.rb'
+                  rm 'ignored_directory/subdirectory/do_not_use.rb'
+                end
+
+                added.should be_empty
+                modified.should be_empty
+                removed.should be_empty
+              end
+            end
+          end
+        end
+      end
+    end
+
+    context 'multiple file operations' do
+      it 'detects the added files' do
+        fixtures do |path|
+          modified, added, removed = changes(path) do
+            touch 'a_file.rb'
+            touch 'b_file.rb'
+            mkdir 'a_directory'
+            touch 'a_directory/a_file.rb'
+            touch 'a_directory/b_file.rb'
+          end
+
+          added.should =~ %w(a_file.rb b_file.rb a_directory/a_file.rb a_directory/b_file.rb)
+          modified.should be_empty
+          removed.should be_empty
+        end
+      end
+
+      it 'detects the modified files' do
+        fixtures do |path|
+          touch 'a_file.rb'
+          touch 'b_file.rb'
+          mkdir 'a_directory'
+          touch 'a_directory/a_file.rb'
+          touch 'a_directory/b_file.rb'
+
+          small_time_difference
+
+          modified, added, removed = changes(path) do
+            touch 'b_file.rb'
+            touch 'a_directory/a_file.rb'
+          end
+
+          added.should be_empty
+          modified.should =~ %w(b_file.rb a_directory/a_file.rb)
+          removed.should be_empty
+        end
+      end
+
+      it 'detects the removed files' do
+        fixtures do |path|
+          touch 'a_file.rb'
+          touch 'b_file.rb'
+          mkdir 'a_directory'
+          touch 'a_directory/a_file.rb'
+          touch 'a_directory/b_file.rb'
+
+          modified, added, removed = changes(path) do
+            rm 'b_file.rb'
+            rm 'a_directory/a_file.rb'
+          end
+
+          added.should be_empty
+          modified.should be_empty
+          removed.should =~ %w(b_file.rb a_directory/a_file.rb)
+        end
+      end
+    end
+
+    context 'single directory operations' do
+      it 'detects a moved directory' do
+        fixtures do |path|
+          mkdir 'a_directory'
+          touch 'a_directory/a_file.rb'
+          touch 'a_directory/b_file.rb'
+
+          modified, added, removed = changes(path) do
+            mv 'a_directory', 'renamed'
+          end
+
+          added.should =~ %w(renamed/a_file.rb renamed/b_file.rb)
+          modified.should be_empty
+          removed.should =~ %w(a_directory/a_file.rb a_directory/b_file.rb)
+        end
+      end
+
+      it 'detects a removed directory' do
+        fixtures do |path|
+          mkdir 'a_directory'
+          touch 'a_directory/a_file.rb'
+          touch 'a_directory/b_file.rb'
+
+          modified, added, removed = changes(path) do
+            rm_rf 'a_directory'
+          end
+
+          added.should be_empty
+          modified.should be_empty
+          removed.should =~ %w(a_directory/a_file.rb a_directory/b_file.rb)
+        end
+      end
+
+      it "deletes the directory from the record" do
+        fixtures do |path|
+          mkdir 'a_directory'
+          touch 'a_directory/file.rb'
+
+          changes(path) do
+            @record.paths.should have(2).paths
+            @record.paths[path]['a_directory'].should_not be_nil
+            @record.paths["#{path}/a_directory"]['file.rb'].should_not be_nil
+
+            rm_rf 'a_directory'
+          end
+
+          @record.paths.should have(1).paths
+          @record.paths[path]['a_directory'].should be_nil
+          @record.paths["#{path}/a_directory"]['file.rb'].should be_nil
+        end
+      end
+
+      context 'with nested paths' do
+        it 'detects removals without crashing - #18' do
+          fixtures do |path|
+            mkdir_p 'a_directory/subdirectory'
+            touch   'a_directory/subdirectory/do_not_use.rb'
+
+            modified, added, removed = changes(path) do
+              rm_r 'a_directory'
+            end
+
+            added.should be_empty
+            modified.should be_empty
+            removed.should =~ %w(a_directory/subdirectory/do_not_use.rb)
+          end
+        end
+      end
+    end
+
+    context 'with a path outside the directory for which a record is made' do
+      it "skips that path and doesn't check for changes" do
+          fixtures do |path|
+            modified, added, removed = changes(path, :paths => ['some/where/outside']) do
+              @record.should_not_receive(:detect_additions)
+              @record.should_not_receive(:detect_modifications_and_removals)
+
+              touch 'new_file.rb'
+            end
+
+            added.should be_empty
+            modified.should be_empty
+            removed.should be_empty
+          end
+      end
+    end
+
+    context 'with the relative_paths option set to false' do
+      it 'returns full paths in the changes hash' do
+        fixtures do |path|
+          touch 'a_file.rb'
+          touch 'b_file.rb'
+
+          modified, added, removed = changes(path, :relative_paths => false) do
+            small_time_difference
+            rm    'a_file.rb'
+            touch 'b_file.rb'
+            touch 'c_file.rb'
+            mkdir 'a_directory'
+            touch 'a_directory/a_file.rb'
+          end
+
+          added.should =~ ["#{path}/c_file.rb", "#{path}/a_directory/a_file.rb"]
+          modified.should =~ ["#{path}/b_file.rb"]
+          removed.should =~ ["#{path}/a_file.rb"]
+        end
+      end
+    end
+
+    context 'within a directory containing unreadble paths - #32' do
+      it 'detects changes more than a second apart' do
+        fixtures do |path|
+          touch 'unreadable_file.txt'
+          chmod 000, 'unreadable_file.txt'
+
+          modified, added, removed = changes(path) do
+            sleep 1.1
+            touch 'unreadable_file.txt'
+          end
+
+          added.should be_empty
+          modified.should =~ %w(unreadable_file.txt)
+          removed.should be_empty
+        end
+      end
+
+      context 'with multiple changes within the same second' do
+        before { ensure_same_second }
+
+        it 'does not detect changes even if content changes', :unless => 
described_class::HIGH_PRECISION_SUPPORTED do
+          fixtures do |path|
+            touch 'unreadable_file.txt'
+
+            modified, added, removed = changes(path) do
+              open('unreadable_file.txt', 'w') { |f| f.write('foo') }
+              chmod 000, 'unreadable_file.txt'
+            end
+
+            added.should be_empty
+            modified.should be_empty
+            removed.should be_empty
+          end
+        end
+      end
+    end
+
+    context 'within a directory containing a removed file - #39' do
+      it 'does not raise an exception when hashing a removed file' do
+
+        # simulate a race condition where the file is removed after the
+        # change event is tracked, but before the hash is calculated
+        Digest::SHA1.should_receive(:file).twice.and_raise(Errno::ENOENT)
+
+        lambda {
+          fixtures do |path|
+            file = 'removed_file.txt'
+            touch file
+            changes(path) { touch file }
+          end
+        }.should_not raise_error(Errno::ENOENT)
+      end
+    end
+
+    context 'within a directory containing a unix domain socket file' do
+      it 'does not raise an exception when hashing a unix domain socket file' do
+        fixtures do |path|
+          require 'socket'
+          UNIXServer.new('unix_domain_socket.sock')
+          lambda { changes(path){} }.should_not raise_error(Errno::ENXIO)
+        end
+      end
+    end
+
+    context 'with symlinks', :unless => windows? do
+      it 'looks at symlinks not their targets' do
+        fixtures do |path|
+          touch 'target'
+          symlink 'target', 'symlink'
+
+          record = described_class.new(path)
+          record.build
+
+          sleep 1
+          touch 'target'
+
+          record.fetch_changes([path], :relative_paths => true)[:modified].should == ['target']
+        end
+      end
+
+      it 'handles broken symlinks' do
+        fixtures do |path|
+          symlink 'target', 'symlink'
+
+          record = described_class.new(path)
+          record.build
+
+          sleep 1
+          rm 'symlink'
+          symlink 'new-target', 'symlink'
+          record.fetch_changes([path], :relative_paths => true)
+        end
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/listener_spec.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/listener_spec.rb
new file mode 100644
index 0000000..cf82f1b
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/listener_spec.rb
@@ -0,0 +1,169 @@
+require 'spec_helper'
+
+describe Listen::Listener do
+  let(:adapter)           { mock(Listen::Adapter, :start => true).as_null_object }
+  let(:watched_directory) { File.dirname(__FILE__) }
+
+  subject { described_class.new(watched_directory) }
+
+  before do
+    Listen::Adapter.stub(:select_and_initialize) { adapter }
+    # Don't build a record of the files inside the base directory.
+    subject.directory_record.stub(:build)
+  end
+
+  it_should_behave_like 'a listener to changes on a file-system'
+
+  describe '#initialize' do
+    context 'with no options' do
+      it 'sets the directory' do
+        subject.directory.should eq watched_directory
+      end
+
+      it 'converts the passed path into an absolute path - #21' do
+        described_class.new(File.join(watched_directory, '..')).directory.should eq File.expand_path('..', 
watched_directory)
+      end
+
+      it 'sets the option for using relative paths in the callback to the default one' do
+        subject.instance_variable_get(:@use_relative_paths).should eq 
described_class::DEFAULT_TO_RELATIVE_PATHS
+      end
+    end
+
+    context 'with custom options' do
+      subject { described_class.new(watched_directory, :ignore => /\.ssh/, :filter => [/.*\.rb/,/.*\.md/],
+                                    :latency => 0.5, :force_polling => true, :relative_paths => true) }
+
+      it 'passes the custom ignored paths to the directory record' do
+        subject.directory_record.ignoring_patterns.should include /\.ssh/
+      end
+
+      it 'passes the custom filters to the directory record' do
+        subject.directory_record.filtering_patterns.should =~  [/.*\.rb/,/.*\.md/]
+      end
+
+      it 'sets the cutom option for using relative paths in the callback' do
+        subject.instance_variable_get(:@use_relative_paths).should be_true
+      end
+
+      it 'sets adapter_options' do
+        subject.instance_variable_get(:@adapter_options).should eq(:latency => 0.5, :force_polling => true)
+      end
+    end
+  end
+
+  describe '#start' do
+    it 'selects and initializes an adapter' do
+      Listen::Adapter.should_receive(:select_and_initialize).with(watched_directory, {}) { adapter }
+      subject.start
+    end
+
+    it 'builds the directory record' do
+      subject.directory_record.should_receive(:build)
+      subject.start
+    end
+  end
+
+  context 'with a started listener' do
+    before do
+      subject.stub(:initialize_adapter) { adapter }
+      subject.start
+    end
+
+    describe '#unpause' do
+      it 'rebuilds the directory record' do
+        subject.directory_record.should_receive(:build)
+        subject.unpause
+      end
+    end
+  end
+
+  describe '#ignore'do
+    it 'delegates the work to the directory record' do
+      subject.directory_record.should_receive(:ignore).with 'some_directory'
+      subject.ignore 'some_directory'
+    end
+  end
+
+  describe '#ignore!'do
+    it 'delegates the work to the directory record' do
+      subject.directory_record.should_receive(:ignore!).with 'some_directory'
+      subject.ignore! 'some_directory'
+    end
+  end
+
+  describe '#filter' do
+    it 'delegates the work to the directory record' do
+      subject.directory_record.should_receive(:filter).with /\.txt$/
+      subject.filter /\.txt$/
+    end
+  end
+
+  describe '#filter!' do
+    it 'delegates the work to the directory record' do
+      subject.directory_record.should_receive(:filter!).with /\.txt$/
+      subject.filter! /\.txt$/
+    end
+  end
+
+
+  describe '#on_change' do
+    let(:directories) { %w{dir1 dir2 dir3} }
+    let(:changes)     { {:modified => [], :added => [], :removed => []} }
+    let(:callback)    { Proc.new { @called = true } }
+
+    before do
+      @called = false
+      subject.directory_record.stub(:fetch_changes => changes)
+    end
+
+    it 'fetches the changes of the directory record' do
+      subject.directory_record.should_receive(:fetch_changes).with(
+        directories, hash_including(:relative_paths => described_class::DEFAULT_TO_RELATIVE_PATHS)
+      )
+      subject.on_change(directories)
+    end
+
+    context 'with relative paths option set to true' do
+      subject { described_class.new(watched_directory, :relative_paths => true) }
+
+      it 'fetches the changes of the directory record' do
+        subject.directory_record.should_receive(:fetch_changes).with(directories, 
hash_including(:relative_paths => true))
+        subject.on_change(directories)
+      end
+    end
+
+    context 'with no changes to report' do
+      if RUBY_VERSION[/^1.8/]
+        it 'does not run the callback' do
+            subject.change(&callback)
+            subject.on_change(directories)
+            @called.should be_false
+        end
+      else
+        it 'does not run the callback' do
+          callback.should_not_receive(:call)
+          subject.change(&callback)
+          subject.on_change(directories)
+        end
+      end
+    end
+
+    context 'with changes to report' do
+      let(:changes)     { {:modified => %w{path1}, :added => [], :removed => %w{path2}} }
+
+      if RUBY_VERSION[/^1.8/]
+        it 'runs the callback passing it the changes' do
+          subject.change(&callback)
+          subject.on_change(directories)
+          @called.should be_true
+        end
+      else
+        it 'runs the callback passing it the changes' do
+          callback.should_receive(:call).with(changes[:modified], changes[:added], changes[:removed])
+          subject.change(&callback)
+          subject.on_change(directories)
+        end
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/multi_listener_spec.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/multi_listener_spec.rb
new file mode 100644
index 0000000..32e1c89
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/multi_listener_spec.rb
@@ -0,0 +1,174 @@
+require 'spec_helper'
+
+describe Listen::MultiListener do
+  let(:adapter)             { mock(Listen::Adapter, :start => true).as_null_object }
+  let(:watched_directories) { [File.dirname(__FILE__), File.expand_path('../..', __FILE__)] }
+
+  subject { described_class.new(*watched_directories) }
+
+  before do
+    Listen::Adapter.stub(:select_and_initialize) { adapter }
+    # Don't build a record of the files inside the base directory.
+    Listen::DirectoryRecord.any_instance.stub(:build)
+  end
+
+  it_should_behave_like 'a listener to changes on a file-system'
+
+  describe '#initialize' do
+    context 'with no options' do
+      it 'sets the directories' do
+        subject.directories.should =~ watched_directories
+      end
+
+      it 'converts the passed paths into absolute paths - #21' do
+        paths = watched_directories.map { |d| File.join(d, '..') }
+        described_class.new(*paths).directories.should =~ watched_directories.map{ |d| 
File.expand_path('..', d) }
+      end
+    end
+
+    context 'with custom options' do
+      subject do
+        args = watched_directories << {:ignore => /\.ssh/, :filter => [/.*\.rb/,/.*\.md/], :latency => 0.5, 
:force_polling => true}
+        described_class.new(*args)
+      end
+
+      it 'passes the custom ignored paths to each directory record' do
+        subject.directories_records.each do |r|
+          r.ignoring_patterns.should include /\.ssh/
+        end
+      end
+
+      it 'passes the custom filters to each directory record' do
+        subject.directories_records.each do |r|
+          r.filtering_patterns.should =~  [/.*\.rb/,/.*\.md/]
+        end
+      end
+
+      it 'sets adapter_options' do
+        subject.instance_variable_get(:@adapter_options).should eq(:latency => 0.5, :force_polling => true)
+      end
+    end
+  end
+
+  describe '#start' do
+    it 'selects and initializes an adapter' do
+      Listen::Adapter.should_receive(:select_and_initialize).with(watched_directories, {}) { adapter }
+      subject.start
+    end
+
+    it 'builds all directories records' do
+      subject.directories_records.each do |r|
+        r.should_receive(:build)
+      end
+      subject.start
+    end
+  end
+
+  context 'with a started listener' do
+    before do
+      subject.stub(:initialize_adapter) { adapter }
+      subject.start
+    end
+
+    describe '#unpause' do
+      it 'rebuilds all directories records' do
+        subject.directories_records.each do |r|
+          r.should_receive(:build)
+        end
+        subject.unpause
+      end
+    end
+  end
+
+  describe '#ignore' do
+    it 'delegates the work to each directory record' do
+      subject.directories_records.each do |r|
+        r.should_receive(:ignore).with 'some_directory'
+      end
+      subject.ignore 'some_directory'
+    end
+  end
+
+  describe '#ignore!' do
+    it 'delegates the work to each directory record' do
+      subject.directories_records.each do |r|
+        r.should_receive(:ignore!).with 'some_directory'
+      end
+      subject.ignore! 'some_directory'
+    end
+  end
+
+  describe '#filter' do
+    it 'delegates the work to each directory record' do
+      subject.directories_records.each do |r|
+        r.should_receive(:filter).with /\.txt$/
+      end
+      subject.filter /\.txt$/
+    end
+  end
+
+  describe '#filter!' do
+    it 'delegates the work to each directory record' do
+      subject.directories_records.each do |r|
+        r.should_receive(:filter!).with /\.txt$/
+      end
+      subject.filter! /\.txt$/
+    end
+  end
+
+  describe '#on_change' do
+    let(:directories) { %w{dir1 dir2 dir3} }
+    let(:changes)     { {:modified => [], :added => [], :removed => []} }
+    let(:callback)    { Proc.new { @called = true } }
+
+    before do
+      @called = false
+      subject.stub(:fetch_records_changes => changes)
+    end
+
+    it 'fetches the changes of all directories records' do
+      subject.unstub(:fetch_records_changes)
+
+      subject.directories_records.each do |record|
+        record.should_receive(:fetch_changes).with(
+          directories, hash_including(:relative_paths => described_class::DEFAULT_TO_RELATIVE_PATHS)
+        ).and_return(changes)
+      end
+      subject.on_change(directories)
+    end
+
+    context 'with no changes to report' do
+      if RUBY_VERSION[/^1.8/]
+        it 'does not run the callback' do
+            subject.change(&callback)
+            subject.on_change(directories)
+            @called.should be_false
+        end
+      else
+        it 'does not run the callback' do
+          callback.should_not_receive(:call)
+          subject.change(&callback)
+          subject.on_change(directories)
+        end
+      end
+    end
+
+    context 'with changes to report' do
+      let(:changes)     { {:modified => %w{path1}, :added => [], :removed => %w{path2}} }
+
+      if RUBY_VERSION[/^1.8/]
+        it 'runs the callback passing it the changes' do
+          subject.change(&callback)
+          subject.on_change(directories)
+          @called.should be_true
+        end
+      else
+        it 'runs the callback passing it the changes' do
+          callback.should_receive(:call).with(changes[:modified], changes[:added], changes[:removed])
+          subject.change(&callback)
+          subject.on_change(directories)
+        end
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/turnstile_spec.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/turnstile_spec.rb
new file mode 100644
index 0000000..178a3b4
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen/turnstile_spec.rb
@@ -0,0 +1,56 @@
+require 'spec_helper'
+
+def run_in_two_threads(proc1, proc2)
+  t1 = Thread.new &proc1
+  sleep test_latency # t1 must run before t2
+  t2 = Thread.new { proc2.call; Thread.kill t1 }
+  t2.join(test_latency * 2)
+ensure
+  Thread.kill t1 if t1
+  Thread.kill t2 if t2
+end
+
+describe Listen::Turnstile do
+  before { @called = false }
+
+  describe '#wait' do
+    context 'without a signal' do
+      it 'blocks one thread indefinitely' do
+        run_in_two_threads lambda {
+          subject.wait
+          @called = true
+        }, lambda {
+          sleep test_latency
+        }
+        @called.should be_false
+      end
+    end
+
+    context 'with a signal' do
+      it 'blocks one thread until it recieves a signal from another thread' do
+        run_in_two_threads lambda {
+          subject.wait
+          @called = true
+        }, lambda {
+          subject.signal
+          sleep test_latency
+        }
+        @called.should be_true
+      end
+    end
+  end
+
+  describe '#signal' do
+    context 'without a wait-call before' do
+      it 'does nothing' do
+        run_in_two_threads lambda {
+          subject.signal
+          @called = true
+        }, lambda {
+          sleep test_latency
+        }
+        @called.should be_true
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen_spec.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen_spec.rb
new file mode 100644
index 0000000..9e35ecf
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/listen_spec.rb
@@ -0,0 +1,73 @@
+require 'spec_helper'
+
+describe Listen do
+  describe '#to' do
+    context 'with one path to listen to' do
+      let(:listener)       { mock(Listen::Listener) }
+      let(:listener_class) { Listen::Listener }
+
+      before { listener_class.stub(:new => listener) }
+
+      context 'without options' do
+        it 'creates an instance of Listner' do
+          listener_class.should_receive(:new).with('/path')
+          described_class.to('/path')
+        end
+      end
+
+      context 'with options' do
+        it 'creates an instance of Listner with the passed params' do
+          listener_class.should_receive(:new).with('/path', :filter => '**/*')
+          described_class.to('/path', :filter => '**/*')
+        end
+      end
+
+      context 'without a block' do
+        it 'returns the listener' do
+          described_class.to('/path', :filter => '**/*').should eq listener
+        end
+      end
+
+      context 'with a block' do
+        it 'starts the listner after creating it' do
+          listener.should_receive(:start)
+          described_class.to('/path', :filter => '**/*') { |modified, added, removed| }
+        end
+      end
+    end
+
+    context 'with multiple paths to listen to' do
+      let(:multi_listener)       { mock(Listen::MultiListener) }
+      let(:multi_listener_class) { Listen::MultiListener }
+
+      before { multi_listener_class.stub(:new => multi_listener) }
+
+      context 'without options' do
+        it 'creates an instance of MultiListner' do
+          multi_listener_class.should_receive(:new).with('path1', 'path2')
+          described_class.to('path1', 'path2')
+        end
+      end
+
+      context 'with options' do
+        it 'creates an instance of MultiListner with the passed params' do
+          multi_listener_class.should_receive(:new).with('path1', 'path2', :filter => '**/*')
+          described_class.to('path1', 'path2', :filter => '**/*')
+        end
+      end
+
+      context 'without a block' do
+        it 'returns a MultiListener instance created with the passed params' do
+          described_class.to('path1', 'path2', :filter => '**/*').should eq multi_listener
+        end
+      end
+
+      context 'with a block' do
+        it 'starts a MultiListener instance after creating it with the passed params' do
+          multi_listener.should_receive(:start)
+          described_class.to('path1', 'path2', :filter => '**/*') { |modified, added, removed| }
+        end
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/spec_helper.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/spec_helper.rb
new file mode 100644
index 0000000..853253e
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/spec_helper.rb
@@ -0,0 +1,21 @@
+require 'listen'
+
+Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
+
+# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+RSpec.configure do |config|
+  config.color_enabled = true
+  config.order = :random
+  config.filter_run :focus => true
+  config.treat_symbols_as_metadata_keys_with_true_values = true
+  config.run_all_when_everything_filtered = true
+  config.filter_run_excluding :broken => true
+  config.fail_fast = true
+end
+
+def test_latency
+  0.1
+end
+
+# Crash loud in tests!
+Thread.abort_on_exception = true
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/support/adapter_helper.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/support/adapter_helper.rb
new file mode 100644
index 0000000..9784749
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/support/adapter_helper.rb
@@ -0,0 +1,629 @@
+# Adapter watch
+#
+# @param [Listen::Listener] listener the adapter listener
+# @param [String] path the path to watch
+#
+def watch(listener, expected_changes, *paths)
+  callback = lambda { |changed_dirs, options| @called = true; listener.on_change(changed_dirs) }
+  @adapter = Listen::Adapter.select_and_initialize(paths, { :report_changes => false, :latency => 
test_latency }, &callback)
+
+  forced_stop = false
+  prevent_deadlock = Proc.new { sleep(10); puts "Forcing stop"; @adapter.stop; forced_stop = true }
+
+  @adapter.start(false)
+
+  yield
+
+  t = Thread.new(&prevent_deadlock)
+  @adapter.wait_for_changes(expected_changes)
+
+  unless forced_stop
+    Thread.kill(t)
+    @adapter.report_changes
+  end
+ensure
+  unless forced_stop
+    Thread.kill(t) if t
+    @adapter.stop
+  end
+end
+
+shared_examples_for 'a filesystem adapter' do
+  subject { described_class.new(File.dirname(__FILE__), &Proc.new {}) }
+
+  describe '#start' do
+    after { subject.stop }
+
+    context 'with the blocking param set to true' do
+      it 'blocks the current thread after starting the workers' do
+        @called = false
+        t = Thread.new { subject.start(true); @called = true }
+        sleep(test_latency * 3)
+        Thread.kill(t) if t
+        @called.should be_false
+      end
+    end
+
+    context 'with the blocking param set to false' do
+      it 'does not block the current thread after starting the workers' do
+        @called = false
+        t = Thread.new { subject.start(false); @called = true }
+        sleep(test_latency * 3)
+        Thread.kill(t) if t
+        @called.should be_true
+      end
+    end
+  end
+
+  describe '#started?' do
+    context 'with a new adapter' do
+      it 'returns false' do
+        subject.should_not be_started
+      end
+    end
+
+    context 'with a stopped adapter' do
+      before { subject.start(false); subject.stop }
+
+      it 'returns false' do
+        subject.should_not be_started
+      end
+    end
+
+    context 'with a started adapter' do
+      before { subject.start(false) }
+      after  { subject.stop }
+
+      it 'returns true' do
+        subject.should be_started
+      end
+    end
+  end
+end
+
+shared_examples_for 'an adapter that call properly listener#on_change' do |*args|
+  options = (args.first && args.first.is_a?(Hash)) ? args.first : {}
+  let(:listener) { mock(Listen::Listener) }
+  before { described_class.stub(:works?) { true } }
+
+  context 'single file operations' do
+    context 'when a file is created' do
+      it 'detects the added file' do
+        fixtures do |path|
+          listener.should_receive(:on_change).once.with do |array|
+            array.should include(path)
+          end
+
+          watch(listener, 1, path) do
+            touch 'new_file.rb'
+          end
+        end
+      end
+
+      context 'given a symlink', :unless => windows? do
+        it 'detects the added file' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include(path)
+            end
+
+            touch 'new_file.rb'
+
+            watch(listener, 1, path) do
+              ln_s 'new_file.rb', 'new_file_symlink.rb'
+            end
+          end
+        end
+      end
+
+      context 'given a new created directory' do
+        it 'detects the added file' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include(path, "#{path}/a_directory")
+            end
+
+            watch(listener, 2, path) do
+              mkdir 'a_directory'
+              # Needed for INotify, because of :recursive rb-inotify custom flag?
+              sleep 0.05
+              touch 'a_directory/new_file.rb'
+            end
+          end
+        end
+      end
+
+      context 'given an existing directory' do
+        it 'detects the added file' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include("#{path}/a_directory")
+            end
+
+            mkdir 'a_directory'
+
+            watch(listener, 1, path) do
+              touch 'a_directory/new_file.rb'
+            end
+          end
+        end
+      end
+
+      context 'given a directory with subdirectories' do
+        it 'detects the added file' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include("#{path}/a_directory/subdirectory")
+            end
+
+            mkdir_p 'a_directory/subdirectory'
+
+            watch(listener, 1, path) do
+              touch 'a_directory/subdirectory/new_file.rb'
+            end
+          end
+        end
+      end
+    end
+
+    context 'when a file is modified' do
+      it 'detects the modified file' do
+        fixtures do |path|
+          listener.should_receive(:on_change).once.with do |array|
+            array.should include(path)
+          end
+
+          touch 'existing_file.txt'
+
+          watch(listener, 1, path) do
+            touch 'existing_file.txt'
+          end
+        end
+      end
+
+      context 'given a symlink', :unless => windows? do
+        it 'detects the modified file' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include(path)
+            end
+
+            touch 'existing_file.rb'
+            ln_s  'existing_file.rb', 'existing_file_symlink.rb'
+
+            watch(listener, 1, path) do
+              touch 'existing_file.rb'
+            end
+          end
+        end
+      end
+
+      context 'given a hidden file' do
+        it 'detects the modified file' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include(path)
+            end
+
+            touch '.hidden'
+
+            watch(listener, 1, path) do
+              touch '.hidden'
+            end
+          end
+        end
+      end
+
+      context 'given a file mode change', :unless => windows? do
+        it 'does not detect the mode change' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include(path)
+            end
+
+            touch 'run.rb'
+
+            watch(listener, 1, path) do
+              chmod 0777, 'run.rb'
+            end
+          end
+        end
+      end
+
+      context 'given an existing directory' do
+        it 'detects the modified file' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include("#{path}/a_directory")
+            end
+
+            mkdir 'a_directory'
+            touch 'a_directory/existing_file.txt'
+
+            watch(listener, 1, path) do
+              touch 'a_directory/existing_file.txt'
+            end
+          end
+        end
+      end
+
+      context 'given a directory with subdirectories' do
+        it 'detects the modified file' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include("#{path}/a_directory/subdirectory")
+            end
+
+            mkdir_p 'a_directory/subdirectory'
+            touch   'a_directory/subdirectory/existing_file.txt'
+
+            watch(listener, 1, path) do
+              touch 'a_directory/subdirectory/new_file.rb'
+            end
+          end
+        end
+      end
+    end
+
+    context 'when a file is moved' do
+      it 'detects the file move' do
+        fixtures do |path|
+          listener.should_receive(:on_change).once.with do |array|
+            array.should include(path)
+          end
+
+          touch 'move_me.txt'
+
+          watch(listener, 1, path) do
+            mv 'move_me.txt', 'new_name.txt'
+          end
+        end
+      end
+
+      context 'given a symlink', :unless => windows? do
+        it 'detects the file move' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include(path)
+            end
+
+            touch 'move_me.rb'
+            ln_s  'move_me.rb', 'move_me_symlink.rb'
+
+            watch(listener, 1, path) do
+              mv 'move_me_symlink.rb', 'new_symlink.rb'
+            end
+          end
+        end
+      end
+
+      context 'given an existing directory' do
+        it 'detects the file move into the directory' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include(path, "#{path}/a_directory")
+            end
+
+            mkdir 'a_directory'
+            touch 'move_me.txt'
+
+            watch(listener, 2, path) do
+              mv 'move_me.txt', 'a_directory/move_me.txt'
+            end
+          end
+        end
+
+        it 'detects a file move out of the directory' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include(path, "#{path}/a_directory")
+            end
+
+            mkdir 'a_directory'
+            touch 'a_directory/move_me.txt'
+
+            watch(listener, 2, path) do
+              mv 'a_directory/move_me.txt', 'i_am_here.txt'
+            end
+          end
+        end
+
+        it 'detects a file move between two directories' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include("#{path}/from_directory", "#{path}/to_directory")
+            end
+
+            mkdir 'from_directory'
+            touch 'from_directory/move_me.txt'
+            mkdir 'to_directory'
+
+            watch(listener, 2, path) do
+              mv 'from_directory/move_me.txt', 'to_directory/move_me.txt'
+            end
+          end
+        end
+      end
+
+      context 'given a directory with subdirectories' do
+        it 'detects files movements between subdirectories' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include("#{path}/a_directory/subdirectory", "#{path}/b_directory/subdirectory")
+            end
+
+            mkdir_p 'a_directory/subdirectory'
+            mkdir_p 'b_directory/subdirectory'
+            touch   'a_directory/subdirectory/move_me.txt'
+
+            watch(listener, 2, path) do
+              mv 'a_directory/subdirectory/move_me.txt', 'b_directory/subdirectory'
+            end
+          end
+        end
+      end
+    end
+
+    context 'when a file is deleted' do
+      it 'detects the file removal' do
+        fixtures do |path|
+          listener.should_receive(:on_change).once.with do |array|
+            array.should include(path)
+          end
+
+          touch 'unnecessary.txt'
+
+          watch(listener, 1, path) do
+            rm 'unnecessary.txt'
+          end
+        end
+      end
+
+      context 'given a symlink', :unless => windows? do
+        it 'detects the file removal' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include(path)
+            end
+
+            touch 'unnecessary.rb'
+            ln_s  'unnecessary.rb', 'unnecessary_symlink.rb'
+
+            watch(listener, 1, path) do
+              rm 'unnecessary_symlink.rb'
+            end
+          end
+        end
+      end
+
+      context 'given an existing directory' do
+        it 'detects the file removal' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include("#{path}/a_directory")
+            end
+
+            mkdir 'a_directory'
+            touch 'a_directory/do_not_use.rb'
+
+            watch(listener, 1, path) do
+              rm 'a_directory/do_not_use.rb'
+            end
+          end
+        end
+      end
+
+      context 'given a directory with subdirectories' do
+        it 'detects the file removal' do
+          fixtures do |path|
+            listener.should_receive(:on_change).once.with do |array|
+              array.should include("#{path}/a_directory/subdirectory")
+            end
+
+            mkdir_p 'a_directory/subdirectory'
+            touch   'a_directory/subdirectory/do_not_use.rb'
+
+            watch(listener, 1, path) do
+              rm 'a_directory/subdirectory/do_not_use.rb'
+            end
+          end
+        end
+      end
+    end
+  end
+
+  context 'multiple file operations' do
+    it 'detects the added files' do
+      fixtures do |path|
+        listener.should_receive(:on_change).once.with do |array|
+          array.should include(path, "#{path}/a_directory")
+        end
+
+        watch(listener, 2, path) do
+          touch 'a_file.rb'
+          touch 'b_file.rb'
+          mkdir 'a_directory'
+          # Needed for INotify, because of :recursive rb-inotify custom flag?
+          # Also needed for the osx adapter
+          sleep 0.05
+          touch 'a_directory/a_file.rb'
+          touch 'a_directory/b_file.rb'
+        end
+      end
+    end
+
+    it 'detects the modified files' do
+      fixtures do |path|
+        listener.should_receive(:on_change).once.with do |array|
+          array.should include(path, "#{path}/a_directory")
+        end
+
+        touch 'a_file.rb'
+        touch 'b_file.rb'
+        mkdir 'a_directory'
+        touch 'a_directory/a_file.rb'
+        touch 'a_directory/b_file.rb'
+
+        watch(listener, 2, path) do
+          touch 'b_file.rb'
+          touch 'a_directory/a_file.rb'
+        end
+      end
+    end
+
+    it 'detects the removed files' do
+      fixtures do |path|
+        listener.should_receive(:on_change).once.with do |array|
+          array.should include(path, "#{path}/a_directory")
+        end
+
+        touch 'a_file.rb'
+        touch 'b_file.rb'
+        mkdir 'a_directory'
+        touch 'a_directory/a_file.rb'
+        touch 'a_directory/b_file.rb'
+
+        watch(listener, 2, path) do
+          rm 'b_file.rb'
+          rm 'a_directory/a_file.rb'
+        end
+      end
+    end
+  end
+
+  context 'single directory operations' do
+    it 'detects a moved directory' do
+      fixtures do |path|
+        listener.should_receive(:on_change).once.with do |array|
+          array.should include(path)
+        end
+
+        mkdir 'a_directory'
+        touch 'a_directory/a_file.rb'
+        touch 'a_directory/b_file.rb'
+
+        watch(listener, 1, path) do
+          mv 'a_directory', 'renamed'
+        end
+      end
+    end
+
+    it 'detects a removed directory' do
+      fixtures do |path|
+        listener.should_receive(:on_change).once.with do |array|
+          array.should include(path, "#{path}/a_directory")
+        end
+
+        mkdir 'a_directory'
+        touch 'a_directory/a_file.rb'
+        touch 'a_directory/b_file.rb'
+
+        watch(listener, 2, path) do
+          rm_rf 'a_directory'
+        end
+      end
+    end
+  end
+
+  context "paused adapter" do
+    context 'when a file is created' do
+      it "doesn't detects the added file" do
+        fixtures do |path|
+          watch(listener, 1, path) do # The expected changes param is set to one!
+            @adapter.paused = true
+            touch 'new_file.rb'
+          end
+          @called.should be_nil
+        end
+      end
+    end
+  end
+
+  context "when multiple directories are listened to" do
+    context 'when files are added to one of multiple directories' do
+      it 'detects added files' do
+        fixtures(2) do |path1, path2|
+          listener.should_receive(:on_change).once.with do |array|
+            array.should include(path2)
+          end
+
+          watch(listener, 1, path1, path2) do
+            touch "#{path2}/new_file.rb"
+          end
+        end
+      end
+    end
+
+    context 'when files are added to multiple directories' do
+      it 'detects added files' do
+        fixtures(2) do |path1, path2|
+          listener.should_receive(:on_change).once.with do |array|
+            array.should include(path1, path2)
+          end
+
+          watch(listener, 2, path1, path2) do
+            touch "#{path1}/new_file.rb"
+            touch "#{path2}/new_file.rb"
+          end
+        end
+      end
+    end
+
+    context 'given a new and an existing directory on multiple directories' do
+      it 'detects the added file' do
+        fixtures(2) do |path1, path2|
+          listener.should_receive(:on_change).once.with do |array|
+            array.should include(path2, "#{path1}/a_directory", "#{path2}/b_directory")
+          end
+
+          mkdir "#{path1}/a_directory"
+
+          watch(listener, 3, path1, path2) do
+            mkdir "#{path2}/b_directory"
+            # Needed for INotify
+            sleep 0.05
+            touch "#{path1}/a_directory/new_file.rb"
+            touch "#{path2}/b_directory/new_file.rb"
+          end
+        end
+      end
+    end
+
+    context 'when a file is moved between the multiple watched directories' do
+      it 'detects the movements of the file' do
+        fixtures(3) do |path1, path2, path3|
+          listener.should_receive(:on_change).once.with do |array|
+            array.should include("#{path1}/from_directory", path2, "#{path3}/to_directory")
+          end
+
+          mkdir "#{path1}/from_directory"
+          touch "#{path1}/from_directory/move_me.txt"
+          mkdir "#{path3}/to_directory"
+
+          watch(listener, 3, path1, path2, path3) do
+            mv "#{path1}/from_directory/move_me.txt", "#{path2}/move_me.txt"
+            mv "#{path2}/move_me.txt", "#{path3}/to_directory/move_me.txt"
+          end
+        end
+      end
+    end
+
+    context 'when files are deleted from the multiple watched directories' do
+      it 'detects the files removal' do
+        fixtures(2) do |path1, path2|
+          listener.should_receive(:on_change).once.with do |array|
+            array.should include(path1, path2)
+          end
+
+          touch "#{path1}/unnecessary.txt"
+          touch "#{path2}/unnecessary.txt"
+
+          watch(listener, 2, path1, path2) do
+            rm "#{path1}/unnecessary.txt"
+            rm "#{path2}/unnecessary.txt"
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/support/directory_record_helper.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/support/directory_record_helper.rb
new file mode 100644
index 0000000..404e81e
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/support/directory_record_helper.rb
@@ -0,0 +1,55 @@
+# Prepares a record for the test and fetches changes
+# afterwards.
+#
+# @param [String] root_path the path to watch
+# @param [Hash] options
+# @option options [Array<string>] :paths optional paths fetch changes for
+# @option options [Boolean] :use_last_record allow the use of an already
+#   created record, handy for ordered tests.
+#
+# @return [Array, Array, Array] the changes
+#
+def changes(root_path, options = {})
+  unless @record || options[:use_last_record]
+    @record = Listen::DirectoryRecord.new(root_path)
+    @record.filter(options.delete(:filter)) if options[:filter]
+    @record.ignore(options.delete(:ignore)) if options[:ignore]
+
+    # Build the record after adding the filtering and ignoring patterns
+    @record.build
+  end
+
+  yield if block_given?
+
+  paths = options.delete(:paths) || [root_path]
+  options[:recursive] = true if options[:recursive].nil?
+
+  changes = @record.fetch_changes(paths, {:relative_paths => true}.merge(options))
+
+  [changes[:modified], changes[:added], changes[:removed]]
+end
+
+# Generates a small time difference before performing a time sensitive
+# task (like comparing mtimes of files).
+#
+# @note Modification time for files only includes the milliseconds on Linux with MRI > 1.9.2,
+#   that's why we generate a difference that's greater than 1 second.
+#
+def small_time_difference
+  t = Time.now
+  diff = t.to_f - t.to_i
+
+  sleep( 1.5 - (diff < 0.5 ? diff : 0.4) )
+end
+
+# Ensures that the test runs at almost the same second at which
+# changes are being checked.
+#
+def ensure_same_second
+  t = Time.now
+  diff = t.to_f - t.to_i
+
+  if diff > 0.1 # We are not at the beginning of a second
+    sleep 1.1 - diff # 1.1 is used instead of 1 to account for the processing time (estimated at 0.1 sec)
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/support/fixtures_helper.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/support/fixtures_helper.rb
new file mode 100644
index 0000000..a885ac6
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/support/fixtures_helper.rb
@@ -0,0 +1,29 @@
+require 'tmpdir'
+
+include FileUtils
+
+# Prepares temporary fixture-directories and
+# cleans them afterwards.
+#
+# @param [Fixnum] number_of_directories the number of fixture-directories to make
+#
+# @yield [path1, path2, ...] the empty fixture-directories
+# @yieldparam [String] path the path to a fixture directory
+#
+def fixtures(number_of_directories = 1)
+  current_pwd = pwd
+  paths = 1.upto(number_of_directories).map do
+    File.expand_path(File.join(pwd, "spec/.fixtures/#{Time.now.to_f.to_s.sub('.', '') + rand(9999).to_s}"))
+  end
+
+  # Create the dirs
+  paths.each { |p| mkdir_p(p) }
+
+  cd(paths.first) if number_of_directories == 1
+
+  yield(*paths)
+
+ensure
+  cd current_pwd
+  paths.map { |p| rm_rf(p) if File.exists?(p) }
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/support/listeners_helper.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/support/listeners_helper.rb
new file mode 100644
index 0000000..2ff969b
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/support/listeners_helper.rb
@@ -0,0 +1,156 @@
+shared_examples_for 'a listener to changes on a file-system' do
+  describe '#start' do
+    before do
+      subject.stub(:initialize_adapter) { adapter }
+    end
+
+    it 'starts the adapter' do
+      adapter.should_receive(:start)
+      subject.start
+    end
+
+    context 'with the blocking param set to false' do
+      it 'passes the blocking param to the adapter' do
+        adapter.should_receive(:start).with(false)
+        subject.start(false)
+      end
+    end
+  end
+
+  context 'with a started listener' do
+    before do
+      subject.start
+    end
+
+    describe '#stop' do
+      it "stops adapter" do
+        adapter.should_receive(:stop)
+        subject.stop
+      end
+    end
+
+    describe '#pause' do
+      it 'sets adapter.paused to true' do
+        adapter.should_receive(:paused=).with(true)
+        subject.pause
+      end
+
+      it 'returns the same listener to allow chaining' do
+        subject.pause.should equal subject
+      end
+    end
+
+    describe '#unpause' do
+      it 'sets adapter.paused to false' do
+        adapter.should_receive(:paused=).with(false)
+        subject.unpause
+      end
+
+      it 'returns the same listener to allow chaining' do
+        subject.unpause.should equal subject
+      end
+    end
+
+    describe '#paused?' do
+      it 'returns false when there is no adapter' do
+        subject.instance_variable_set(:@adapter, nil)
+        subject.should_not be_paused
+      end
+
+      it 'returns true when adapter is paused' do
+        adapter.should_receive(:paused) { true }
+        subject.should be_paused
+      end
+
+      it 'returns false when adapter is not paused' do
+        adapter.should_receive(:paused) { false }
+        subject.should_not be_paused
+      end
+    end
+  end
+
+  describe '#change' do
+    it 'sets the callback block' do
+      callback = lambda { |modified, added, removed| }
+      subject.change(&callback)
+      subject.instance_variable_get(:@block).should eq callback
+    end
+
+    it 'returns the same listener to allow chaining' do
+      subject.change(&Proc.new{}).should equal subject
+    end
+  end
+
+  describe '#ignore' do
+    it 'returns the same listener to allow chaining' do
+      subject.ignore('some_directory').should equal subject
+    end
+  end
+
+  describe '#ignore!' do
+    it 'returns the same listener to allow chaining' do
+      subject.ignore!('some_directory').should equal subject
+    end
+  end
+
+  describe '#filter' do
+    it 'returns the same listener to allow chaining' do
+      subject.filter(/\.txt$/).should equal subject
+    end
+  end
+
+  describe '#filter!' do
+    it 'returns the same listener to allow chaining' do
+      subject.filter!(/\.txt$/).should equal subject
+    end
+  end
+
+  describe '#latency' do
+    it 'sets the latency to @adapter_options' do
+      subject.latency(0.7)
+      subject.instance_variable_get(:@adapter_options).should eq(:latency => 0.7)
+    end
+
+    it 'returns the same listener to allow chaining' do
+      subject.latency(0.7).should equal subject
+    end
+  end
+
+  describe '#force_polling' do
+    it 'sets force_polling to @adapter_options' do
+      subject.force_polling(false)
+      subject.instance_variable_get(:@adapter_options).should eq(:force_polling => false)
+    end
+
+    it 'returns the same listener to allow chaining' do
+      subject.force_polling(true).should equal subject
+    end
+  end
+
+  describe '#relative_paths' do
+    it 'sets the relative paths option for paths in the callback' do
+      subject.relative_paths(true)
+      subject.instance_variable_get(:@use_relative_paths).should be_true
+    end
+
+    it 'returns the same listener to allow chaining' do
+      subject.relative_paths(true).should equal subject
+    end
+  end
+
+  describe '#polling_fallback_message' do
+    it 'sets custom polling fallback message to @adapter_options' do
+      subject.polling_fallback_message('custom message')
+      subject.instance_variable_get(:@adapter_options).should eq(:polling_fallback_message => 'custom 
message')
+    end
+
+    it 'sets polling fallback message to false in @adapter_options' do
+      subject.polling_fallback_message(false)
+      subject.instance_variable_get(:@adapter_options).should eq(:polling_fallback_message => false)
+    end
+
+    it 'returns the same listener to allow chaining' do
+      subject.polling_fallback_message('custom message').should equal subject
+    end
+  end
+end
diff --git a/backends/css/gems/sass-3.2.12/vendor/listen/spec/support/platform_helper.rb 
b/backends/css/gems/sass-3.2.12/vendor/listen/spec/support/platform_helper.rb
new file mode 100644
index 0000000..480b21f
--- /dev/null
+++ b/backends/css/gems/sass-3.2.12/vendor/listen/spec/support/platform_helper.rb
@@ -0,0 +1,15 @@
+def mac?
+  RbConfig::CONFIG['target_os'] =~ /darwin/i
+end
+
+def linux?
+  RbConfig::CONFIG['target_os'] =~ /linux/i
+end
+
+def bsd?
+  RbConfig::CONFIG['target_os'] =~ /freebsd/i
+end
+
+def windows?
+  RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
+end
diff --git a/backends/css/mkdeps.py b/backends/css/mkdeps.py
new file mode 100644
index 0000000..a322791
--- /dev/null
+++ b/backends/css/mkdeps.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+
+import subprocess, os, re
+
+perdir = {}
+
+ret = subprocess.check_output(['git', 'ls-tree', 'HEAD', '--name-only', '-r', '--', 'gems']).splitlines()
+
+for r in ret:
+    dname = os.path.dirname(r)
+
+    if dname in perdir:
+        perdir[dname].append(r)
+    else:
+        perdir[dname] = [r]
+
+for dname in perdir:
+    vname = 'csssass_{0}'.format(re.sub('[/.-]', '_', dname))
+
+    print('{0}dir = $(GCA_RBBACKENDS_DIR)/css/{1}'.format(vname, dname))
+    print('{0}_DATA = \\'.format(vname))
+    print("\tbackends/css/{0}".format(" \\\n\tbackends/css/".join(perdir[dname])))
+    print('')
+
+# vi:ts=4:et
diff --git a/backends/css/org.gnome.CodeAssist.v1.css.service.in 
b/backends/css/org.gnome.CodeAssist.v1.css.service.in
new file mode 100644
index 0000000..e193079
--- /dev/null
+++ b/backends/css/org.gnome.CodeAssist.v1.css.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gnome.CodeAssist.v1.css
+Exec= backendexecdir@/css --transport dbus
diff --git a/configure.ac b/configure.ac
index cf9f57c..01d692a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -232,6 +232,49 @@ AM_CONDITIONAL(BACKENDS_RUBY_ENABLE, test "x$enable_ruby" = "xyes")
 
 
 dnl ================================================================
+dnl css backend configuration
+dnl ================================================================
+AC_ARG_ENABLE([css],
+              AS_HELP_STRING([--enable-css],[enable css backend]),
+              [enable_css=$enableval],
+              [enable_css=auto])
+
+AC_MSG_CHECKING([css backend])
+
+if test "x$enable_css" = "xauto"; then
+       if test "x$RUBY" = "x"; then
+               AC_MSG_RESULT([no (requires ruby 2.0)])
+               enable_css=no
+       else
+               AC_MSG_RESULT([yes])
+               enable_css=yes
+       fi
+elif test "x$enable_css" != "xno"; then
+       if test "x$RUBY" = "x"; then
+               AC_MSG_ERROR([no (requires ruby 2.0)])
+       else
+               AC_MSG_RESULT([yes])
+               enable_css=yes
+       fi
+else
+       AC_MSG_RESULT([no])
+fi
+
+ruby_sass=
+
+if test "x$enable_css" = "xyes"; then
+       $RUBY -rsass -e '' 2>/dev/null
+       if test $? -eq 0 ; then
+               ruby_sass=yes
+       fi
+fi
+
+color_enable_var("$enable_css", [enable_css_msg])
+
+AM_CONDITIONAL(BACKENDS_CSS_ENABLE, test "x$enable_css" = "xyes")
+AM_CONDITIONAL(RUBY_SASS, test "x$ruby_sass" = "xyes")
+
+dnl ================================================================
 dnl js support
 dnl ================================================================
 AC_PATH_PROG([GJS],[gjs])
@@ -498,6 +541,8 @@ backends/js/org.gnome.CodeAssist.v1.js.service
 backends/js/js
 backends/sh/org.gnome.CodeAssist.v1.sh.service
 backends/sh/sh
+backends/css/org.gnome.CodeAssist.v1.css.service
+backends/css/css
 ])
 
 AC_OUTPUT
@@ -520,5 +565,6 @@ Configuration:
                ruby:           $enable_ruby_msg
                javascript:     $enable_js_msg
                shell:          $enable_sh_msg
+               css:            $enable_css_msg
 "
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]