// @forward and @use
@forward "foo.scss";
@use "foo.scss";

@forward "bar.scss" as bar-*;
@use "bar.scss" as *;

@forward "baz.scss" with ($grey: #a4a4a4);
@use "baz.scss" with ($grey: #686868);

// Nested Rules

#main p {
  color: #00ff00;
  width: 97%;

  .redbox {
    background-color: #ff0000;
    color: #000000;
  }
}

#main {
  width: 97%;

  p, div {
    font-size: 2em;
    a { font-weight: bold; }
  }

  pre { font-size: 3em; }
}

// Referencing Parent Selectors: &

a {
  font-weight: bold;
  text-decoration: none;
  &:hover { text-decoration: underline; }
  body.firefox & { font-weight: normal; }
}

#main {
  color: black;
  a {
    font-weight: bold;
    &:hover { color: red; }
  }
}

#main {
  color: black;
  &-sidebar { border: 1px solid; }
}

// Nested Properties

.funky {
  font: {
    family: fantasy;
    size: 30em;
    weight: bold;
  }
}

.funky {
  font: 20px/24px fantasy {
    weight: bold;
  }
}

// Comments: /* */ and //

/* This comment is
 * several lines long.
 * since it uses the CSS comment syntax,
 * it will appear in the CSS output */
body { color: black; }

// These comments are only one line long each.
// They won't appear in the CSS output,
// since they use the single-line comment syntax.
a { color: green; }

$version: "1.2.3";
/* This CSS is generated by My Snazzy Framework version #{$version}. */

// Variables: $

$width: 5em;

#main {
  width: $width;
}

#main {
  $width: 5em !global;
  width: $width;
}

#sidebar {
  width: $width;
}

// Data Types: Strings

@mixin firefox-message($selector) {
  body.firefox #{$selector}:before {
    content: "Hi, Firefox users!";
  }
}

@include firefox-message(".header");

// Maps

$map: (key1: value1, key2: value2, key3: value3);

// Number Operations

p {
  font: 10px/8px;             // Plain CSS, no division
  $width: 1000px;
  width: $width/2;            // Uses a variable, does division
  width: round(1.5)/2;        // Uses a function, does division
  height: (500px/2);          // Uses parentheses, does division
  margin-left: 5px + 8px/2px; // Uses +, does division
  font: (italic bold 10px/8px); // In a list, parentheses don't count
}

p {
  $font-size: 12px;
  $line-height: 30px;
  font: #{$font-size}/#{$line-height};
}

// Color Operations

p {
  color: #010203 + #040506;
}

p {
  color: #010203 * 2;
}

p {
  color: rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75);
}

$translucent-red: rgba(255, 0, 0, 0.5);
p {
  color: opacify($translucent-red, 0.3);
  background-color: transparentize($translucent-red, 0.25);
}

// String Operations

p {
  cursor: e + -resize;
}

p:before {
  content: "Foo " + Bar;
  font-family: sans- + "serif";
}

p {
  margin: 3px + 4px auto;
}

p:before {
  content: "I ate #{5 + 10} pies!";
}

$value: null;
p:before {
  content: "I ate #{$value} pies!";
}

// Parentheses

p {
  width: 1em + (2em * 3);
}

// Functions

p {
  color: hsl(0, 100%, 50%);
}

// Keyword Arguments

p {
  color: hsl($hue: 0, $saturation: 100%, $lightness: 50%);
}

// Interpolation: #{}

$name: foo;
$attr: border;
p.#{$name} {
  #{$attr}-color: blue;
}

p {
  $font-size: 12px;
  $line-height: 30px;
  font: #{$font-size}/#{$line-height};
}

// & in SassScript

.foo.bar .baz.bang, .bip.qux {
  $selector: &;
}

@mixin does-parent-exist {
  @if & {
    &:hover {
      color: red;
    }
  } @else {
    a {
      color: red;
    }
  }
}

// Variable Defaults: !default

$content: "First content";
$content: "Second content?" !default;
$new_content: "First time reference" !default;

#main {
  content: $content;
  new-content: $new_content;
}

$content: null;
$content: "Non-null content" !default;

#main {
  content: $content;
}

// @import

@import "foo.scss";
@import "foo";

@import "foo.css";
@import "foo" screen;
@import "http://foo.com/bar";
@import url(foo);

@import "rounded-corners", "text-shadow";

$family: unquote("Droid+Sans");
@import url("http://fonts.googleapis.com/css?family=#{$family}");

// Partials

@import "colors";

// Nested @import

.example {
  color: red;
}

#main {
  @import "example";
}

// @media

.sidebar {
  width: 300px;
  @media screen and (orientation: landscape) {
    width: 500px;
  }
}

@media screen {
  .sidebar {
    @media (orientation: landscape) {
      width: 500px;
    }
  }
}

$media: screen;
$feature: -webkit-min-device-pixel-ratio;
$value: 1.5;

@media #{$media} and ($feature: $value) {
  .sidebar {
    width: 500px;
  }
}

// @extend

.error {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  @extend .error;
  border-width: 3px;
}

.error {
  border: 1px #f00;
  background-color: #fdd;
}
.error.intrusion {
  background-image: url("/image/hacked.png");
}
.seriousError {
  @extend .error;
  border-width: 3px;
}

// Extending Complex Selectors

.hoverlink {
  @extend a:hover;
}
a:hover {
  text-decoration: underline;
}

.hoverlink {
  @extend a:hover;
}
.comment a.user:hover {
  font-weight: bold;
}

// Multiple Extends

.error {
  border: 1px #f00;
  background-color: #fdd;
}
.attention {
  font-size: 3em;
  background-color: #ff0;
}
.seriousError {
  @extend .error;
  @extend .attention;
  border-width: 3px;
}

// Chaining Extends

.error {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  @extend .error;
  border-width: 3px;
}
.criticalError {
  @extend .seriousError;
  position: fixed;
  top: 10%;
  bottom: 10%;
  left: 10%;
  right: 10%;
}

// Selector Sequences

#fake-links .link {
  @extend a;
}

a {
  color: blue;
  &:hover {
    text-decoration: underline;
  }
}

// Merging Selector Sequences

#admin .tabbar a {
  font-weight: bold;
}
#demo .overview .fakelink {
  @extend a;
}

#admin .tabbar a {
  font-weight: bold;
}
#admin .overview .fakelink {
  @extend a;
}

// @extend-Only Selectors

#context a%extreme {
  color: blue;
  font-weight: bold;
  font-size: 2em;
}

.notice {
  @extend %extreme;
}

// The !optional Flag

a.important {
  @extend .notice !optional;
}

// @extend in Directives

@media print {
  .error {
    border: 1px #f00;
    background-color: #fdd;
  }
  .seriousError {
    @extend .error;
    border-width: 3px;
  }
}

// @at-root

.parent {
  @at-root .child {}
}

.parent {
  @at-root {
    .child1 {}
    .child2 {}
  }
  .step-child {}
}

@media print {
  .page {
    width: 8in;
    @at-root (without: media) {
      color: red;
    }
  }
}

// @debug

@debug 10em + 12em;

// @warn

@mixin adjust-location($x, $y) {
  @if unitless($x) {
    @warn "Assuming #{$x} to be in pixels";
    $x: 1px * $x;
  }
  @if unitless($y) {
    @warn "Assuming #{$y} to be in pixels";
    $y: 1px * $y;
  }
  position: relative; left: $x; top: $y;
}

// @error

@mixin adjust-location($x, $y) {
  @if unitless($x) {
    @error "$x may not be unitless, was #{$x}.":
  }
  @if unitless($y) {
    @error "$y may not be unitless, was #{$y}.";
  }
  position: relative; left: $x, top: $y;
}

// @if

p {
  @if 1 + 1 == 2 { border: 1px solid;  }
  @if 5 < 3      { border: 2px dotted; }
  @if null       { border: 3px double; }
}

$type: monster;
p {
  @if $type == ocean {
    color: blue;
  } @else if $type == matador {
    color: red;
  } @else if $type == monster {
    color: green;
  } @else {
    color: black;
  }
}

// @for

@for $i from 1 through 3 {
  .item-#{$1} { width: 2em * $i; }
}

@for $i from 1 to 3 {
  .item-#{$1} { width: 2em * $i; }
}

// @each

@each $animal in puma, sea-slug, egret, salamander {
  .#{$animal}-icon {
    background-image: url('/images/#{$animal}.png');
  }
}

@each $animal, $color, $cursor in (puma, black, default),
                                  (sea-slug, blue, pointer),
                                  (egret, white, move) {
  .#{$animal}-icon {
    background-image: url('/images/#{$animal}.png');
    border: 2px solid $color;
    cursor: $cursor;
  }
}

@each $header, $size in (h1: 2em, h2: 1.5em, h3: 1.2em) {
  #{$header} {
    font-size: $size;
  }
}

// @while

$i: 6;
@while $1 > 0 {
  .item-#{$i} { width: 2em * $i; }
  $i: $1 - 2;
}

// Defining a Mixin: @mixin

@mixin large-text {
  font: {
    family: Arial;
    size: 20px;
    weight: bold;
  }
  color: #ff0000;
}

@mixin clearfix {
  display: inline-block;
  &:after {
    content: ".";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
  }
  * html & { height: 1px }
}

// Including a Mixin: @include

.page-title {
  @include large-text;
  padding: 4px;
  margin-top: 10px;
}

@mixin silly-links {
  a {
    color: blue;
    background-color: red;
  }
}

@include silly-links;

@mixin compound {
  @include highlighted-background;
  @include header-text;
}

@mixin highlighted-background { background-color: #fc0; }
@mixin header-text { font-size: 20px; }

// Arguments

@mixin sexy-border($color, $width) {
  border: {
    color: $color;
    width: $width;
    style: dashed;
  }
}

p { @include sexy-border(blue, 1in); }

@mixin sexy-border($color, $width: 1in) {
  border: {
    color: $color;
    width: $width;
    style: dashed;
  }
}
p { @include sexy-border(blue); }
h1 { @include sexy-border(blue, 2in); }

// Keyword Arguments

p { @include sexy-border($color: blue); }
h1 { @include sexy-border($color: blue, $width: 2in); }

// Variable Arguments

@mixin box-shadows($shadows...) {
  -moz-box-shadow: $shadows;
  -webkit-box-shadow: $shadows;
  box-shadow: $shadows;
}

.shadows {
  @include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
}

@mixin colors($text, $background, $border) {
  color: $text;
  background-color: $background;
  border-color: $border;
}

$values: #ff0000, #00ff00, #0000ff;
.primary {
  @include colors($values...);
}

$value-map: (text: #00ff00, background: #0000ff, border: #ff0000);
.secondary {
  @include colors($value-map...);
}

@mixin wrapped-stylish-mixin($args...) {
  font-weight: bold;
  @include stylish-mixin($args...);
}

.stylish {
  // The $width argument will get passed on to "stylish-mixin" as a keyword
  @include wrapped-stylish-mixin(#00ff00, $width: 100px);
}

// Passing Content Blocks to a Mixin

@mixin apply-to-ie6-only {
  * html {
    @content;
  }
}
@include apply-to-ie6-only {
  #logo {
    background-image: url(/logo.gif);
  }
}

// Variable Scope and Content Blocks

$color: white;
@mixin colors($color: blue) {
  background-color: $color;
  @content;
  border-color: $color;
}
.colors {
  @include colors { color: $color; }
}

#sidebar {
  $sidebar-width: 300px;
  width: $sidebar-width;
  @include smartphone {
    width: $sidebar-width / 3;
  }
}

// Function Directives

$grid-width: 40px;
$gutter-width: 10px;

@function grid-width($n) {
  @return $n * $grid-width + ($n - 1) * $gutter-width;
}

#sidebar { width: grid-width(5); }
#sidebar { width: grid-width($n: 5); }

// Styles which were not highlighted correctly in the past

// TODO: todo should be highlighted, ticket #21
/* TODO: same here */

@import url(http://fonts.googleapis.com/css?family=Vollkorn);  // the // in the url shouldn't be highlighted as comment, ticket #24

.foo {
  color: green; // issue #3: a comment ending with {}
}

// Attribute selectors should get highlighted for parent references.
input {
    &[type="text"] { } // <-- This should look the same as...
}
input[type="text"] { } // <-- this.

$a: $b + $c; // issue #4: variables should be displayed with the same color

@include text-shadow; // issue #23, @include content block

@include breakpoint( $bp-default ) {
  display: inline-block;
}

.app-header { // issue #31, functions with hyphens not properly highlighted
  @include linear-gradient(gray-with-lightness(0.94), #FFF 90%);
  border-bottom: 1px solid gray-with-lightness(0.95);
}

.breadcrumb:before { // issue #20, string escaping rendering incorrectly for "\\"
  content: "\\";
}

@import "icons/*.png"; // issue #14, don't treat "/*" as the start of a comment

.foo { // issue #5, lines without {} colored incorrectly
  label.due input[type=text]
  {
    padding-right: 25px;
  }
}

.funky { // comments after nested properties should be recognized
  font: {
    family: fantasy; // a comment
    size: 30em;      /* another comment */
    weight: bold;
  }
}

.container { // issue #33, multiline comments are not recognized as comments
  /*height: auto !important;
  min-height: 100%;*/
  background: #fff;
}

.button { // issue #34, functions as params should be recognized as functions
  background-image: -webkit-linear-gradient(top, bottom, from(#933), to(#944));
}

.class { // issue #35 a) media block is not recognized
  @media screen and (min-width: em(480)) {
    a {
      @extend .clearfix;
    }
  }
}

.class { // issue #35 b) @extend & @include are not recognized inside media block
  @media screen and (min-width: em(480)) {
    @extend .clearfix;
    @include header-text;
  }
}

@media screen and (min-width: em(480)) {
  // issue #35 c) comment inside media block is not recognized
  a {
    @extend .clearfix;
  }
}

.foo { // issue #35 d) the two &:nth-child are not highlighted in the same way
  &:nth-child(3n) {
    @include bar(#000);
  }
  @media screen and (max-width: em(1024)) {
    &:nth-child(2n) {
      @include foobar;
    }
  }
}

.gradient { // issue #36, params are not consistently highlighted
  background-image: -webkit-gradient(linear, left top, left bottom, from(#444444), to(#999999));
  background-image:  -webkit-gradien(linear, left top, right bottom);
  background-image:              foo(linear, top left, bottom right);
  fake-attribute:                foo(linear, left top, right bottom);
  @include                       foo(linear, left top, left bottom, from(#444444), to(#999999));
  border:           -webkit-gradient(linear, left top, left bottom, from(#444444), to(#999999));

  background-image: -webkit-linear-gradient(top, #444444, #999999);
}

.button { // issue #37, only "border" is highlighted in Vim 7.3
  border-radius: 5px;
}

.ding { // issue #40, properties without space after them are not highlighted
  font-size:12px;
  color:red;
}

// issue #43
.rich {
  .figure[style*="float: left"] {} // <-- this should look the same as...
  .figure[style*="float:left"] {}  // <-- this
}

@font-face {  // issue #47 a) syntax within font-face block is not highlighted (plus this comment is not recognized as comment)
  $a: ('a', 'b');

  @each $b in $a {
  }

  @debug 10em + 12em;
  @warn "Warning";
  @error "Error";
}

@mixin generate-fontfaces($ffs-info) {  // issue #47 b) "@font-face" is not highlighted
  @font-face {
    $a: ('a', 'b');

    @each $b in $a {
    }
  }
}

@function grid-width($n) {  // issue #48: various elements are not highlighted inside @function (plus this comment is not recognized as comment)
  @debug 10em + 12em;
  @warn "Warning";
  @error "Error";

  @if unitless($n) {
  }

  $a: ('a', 'b');

  @each $b in $a {
  }

  @for $i from 1 through 3 {
  }

  @while $n > 0 {
  }
}

@function grid-width($n) {  // issue #49: @return and @debug are not highlighted if nested
  @if unitless($n) {
    @debug $n;
    @return $n;
  }
  @debug $n;
  @return $n;
}

// issue #50 a): not all null values are recognized
@mixin setup-animation($name: null, $count: null, $duration: null, $delay: null,
                       $function: null,
                       $direction: null, $fill: null, $visibility: null) {
}

// issue #50 b): null is not recognized as function parameter
@include setup-animation($name:   animation-value($part, "name"),
                         $count:  animation-value($part, "count", null));

// issue #50 c): function is not highlighted if nested
@function animation-value($n) {
  @if $n {
    @return safe-map-get($n);
  }
  @return safe-map-get($n);
}

// issue #52: ")" inside a string param is mistaken as the end of the function
@mixin filter($filter-type, $filter-amount) {
  -webkit-filter: $filter-type+unquote('(#{$filter-amount})');
  -moz-filter: $filter-type+unquote('(#{$filter-amount})');
  -ms-filter: $filter-type+unquote('(#{$filter-amount})');
  -o-filter: $filter-type+unquote('(#{$filter-amount})');
  filter: $filter-type+unquote('(#{$filter-amount})');
}

$x: fnA(fnB("b"), "a");
$x: fnA(fnB('b'), 'a');

// issue #53 a) function is not recognized when params are on multiple lines
$keyframe-info: map-merge($keyframe-info, (
  'offset-x': $x,
  'offset-y': $y,
));

$keyframe-info: map-merge($keyframe-info, ('offset-x': $x, 'offset-y': $y));

// issue #53 b) multiline map is not recognized
$m: (
  'offset-x': $x,
  'offset-y': $y,
);

// issue #53 c) boolean values are not recognized
$a: true;
$b: false;
$c: (key1: true, key2: false, key3: null);

// issue #53 d) classes inside pseudo-selectors are not recognized
html {
  &:not(.animate-once) {
  }
}

// issue #54 a) the highlighting of both ">" should be identical
html > body.contacts {
  .content > .panel-wrp {
  }
}

// issue #54 b) multiline selector is not recognized if there is a string interpolation
@mixin apply-page-contacts($ns, $colors) {
  html##{$ns} > body.contacts
  > .parts {
  }
}

// issue #56: variable inside media block is not highlighted correctly
@media #{small-only()} {
  $padding-horiz: 0.4rem;
}

// issue #57 a) comments inside multi-line map are not recognized
$breakpoints: (
  wp-adminbar-mobile: 783px,  // comment not highlighted
  desktop: 60em,              /* comment not highlighted */
);

// issue #57 b) comments inside multi-line list are not recognized
$list: "1",  /* comment not highlighted */
"2",         // comment not highlighted
"3";

// issue #59: list is mistaken as a map and the string value is not recognized as a string
$a: (
  "string"
);

// issue #60 a) first comment is not recognized
@mixin _setup-panel-title( // comment
  $colors
) {} // comment

// issue #60 b) indented comment containing a "{" is not recognized
@mixin m() {
// { comment
  // { another comment
  // yet another comment
}

// issue #65, cssBoxProp & cssDimensionProp are not recognized as mixin params
// i.e. "margin" and "width" are not highlighted in the example below
.container {
  @include test(margin, $marginDefault, auto);
  @include test(width, 18);
}

// function is not recognized in map
$m: (key: fn());

// map is not recognized as param
$m: fn((key: value));

// string with spaces is not recognized as map value
$m: (key: "string");
$m: (key: "string with spaces");

// boolean operators are not recognized
@if $a and $b {}
@if $a or $b {}
@if not $a {}

@function fn($a, $b, $c, $d) {
  @return $a or $b and $c and not $d;
}

// interpolation is not recognized
$a: oo;
$b: fn(f#{$a});

// comment is not recognized
a {
  /* a comment */
}

// multiple extends are not recognized
.class {
    @extend .classA, .classB, .classC;
}

// function with underscores is not recognized
$a: fn_with_underscores();

// interpolation is not recognized inside function
@function stringConcatCompassStyle($start,$last) {
    @return #{$start}-#{$last};
}

@function stringConcatCompassStyle($start,$last)
{
    @return #{$start}-#{$last};
}

@function fn($x) {
    @if $x {
        // string is not recognized
        @return "string";
    }

    @return "string";
}

// null and boolean values are not recognized as parameters
.foo {
    @include myMixin(20, null, true, false);
}

// interpolation is not recognized in pseudo-selector
$scope: 2;
div.element:nth-child(#{$scope}n) {}

// URL is not recognized
.foo {
  @include wallpaper(url(/images/logo.png));
}

// the exclamation mark of sticky comments should be highlighted
/*! sticky comment */
/* ! not a sticky comment */

// params are not recognized if there is whitespace between function name and params
@function test ($a, $b: $a/2) {
    @return $b;
}

// attributes not terminated by a semicolon should be recognized
a { color: red }
a { color: red;}

div {
  height: 10px;
}

div {
  a: 10px;
}

div {
  foo: 10px;
}

// issue #70: string is not recognized as string if it contains open bracket(s)
div {
  background-image   : url("{{ 'neat-background-product.png' | asset_url }}");
}
