gil00pita
8/23/2016 - 1:30 PM

Sass Toolbox

Sass Toolbox

/* ==========================================================================
   # Sassy Validation
   https://github.com/iamskok/sassy-validation
   ========================================================================== */
@import "sassy-validation/sassy-validation";

/* ==========================================================================
   # Browsers Support
     Usage: @include prefixProperty(user-select, none);
   ========================================================================== */

$defaultWebkitSupport: true;
$defaultFirefoxSupport: true;
$defaultExplorerSupport: true;
$defaultOperaSupport: true;

@mixin prefixProperty($property, $value...) {
  -webkit-#{$property}: #{$value};
  -khtml-#{$property}: #{$value};
  -moz-#{$property}: #{$value};
  -ms-#{$property}: #{$value};
  -o-#{$property}: #{$value};
  #{$property}: #{$value};
}

@mixin prefixValue($property, $value...) {
  #{$property}: -webkit-#{$value};
  #{$property}: -khtml-#{$value};
  #{$property}: -moz-#{$value};
  #{$property}: -ms-#{$value};
  #{$property}: -o-#{$value};
  #{$property}: #{$value};
}

/* ==========================================================================
   # Opacity
     Usage: @include opacity(0.8);
   ========================================================================== */

@mixin opacity($opacity) {
  opacity: $opacity;
  -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=#{$opacity * 100});
  filter: alpha(opacity=$opacity * 100);
  zoom: 1;
}

/* ==========================================================================
   # Opacity
     Usage:
      *,
      *:after,
      *:before {
        @include box-sizing(border-box);
      }
   ========================================================================== */

@mixin box-sizing($box-model) {
  @include prefixProperty(box-sizing, $box-model);
}

/* ==========================================================================
   # no-select
     Usage: @include no-select;
   ========================================================================== */
@mixin no-select() {
  //make unselectable
  -webkit-touch-callout: none;
  @include prefixProperty(user-select, none);
}

@mixin user-select($value) {
  -webkit-touch-callout: $value;
  @include prefixProperty(user-select, $value);
}

/* ==========================================================================
   # Browsers Support
     https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html
     Usage:
     grayscale      ex: filter: grayscale(100%);
     sepia          ex: filter: sepia(100%);
     saturate       ex: filter: saturate(0%);
     hue-rotate     ex: filter: hue-rotate(45deg);
     invert         ex: filter: invert(100%);
     brightness     ex: filter: brightness(15%);
     contrast       ex: filter: contrast(200%);
     blur           ex: filter: blur(2px);
   ========================================================================== */

@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})');
}

/* ==========================================================================
   # Hyphens
     Usage:
   ========================================================================== */

@mixin hyphens() {
  @include prefixProperty(-webkit-hyphens, auto);
}

/* ==========================================================================
   # Typography
     Usage:
     font-face('gotham', '/fonts/gotham');            # Import font files
     better-font                                      # Better Font Rendering
     ligature                                         # Enable Ligatures
     font-size(16px)                                  # convert font size px to rem
   ========================================================================== */

@mixin font-face($font-name, $file-name, $weight: normal, $style: normal) {
  @font-face {
    font-family: quote($font-name);
    src: url('../' + $file-name + '.eot');
    src:
      url('../' + $file-name + '.eot?#iefix') format('embedded-opentype'),
      url('../' + $file-name + '.woff') format('woff'),
      url('../' + $file-name + '.ttf') format('truetype'),
      url('../' + $file-name + '.svg##{$font-name}') format('svg');
    font-weight: $weight;
    font-style: $style;
  }
}

@mixin better-font() {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  //vertical-align: middle;
}

@mixin ligature() {
  //-webkit-font-feature-settings: "liga";
  -moz-font-feature-settings: "liga=1";
  //-moz-font-feature-settings: "liga";
  -ms-font-feature-settings: "liga" 1;
  //-o-font-feature-settings: "liga";
  //font-feature-settings: "liga";
  @include prefixProperty(font-feature-settings, "liga");
}

@mixin font-size($size) {
  @if (validate($size, measure)) { //pixel fallback
    font-size: #{$size};
  }
  @else if (validate($size, number)) {
    font-size: #{$size}px;
  }
  @else {
    @warn "Invalid font-size Unit!";
  }

  font-size: rem($size);
}

/* ==========================================================================
   # Border Radius
     Usage:
     border-radius(3)
     border-radius-separate(2px, 6px, 8px, 4px)
   ========================================================================== */

@mixin border-radius($radius...) {
  @if length($radius) > 1 {
    $border-radius-values: ();
    $border-radius-REMvalues: ();
    $dontUseREM: false;

    @for $value from 1 through length($radius) {
      $nthValue: nth($radius, $value);

      @if (validate($nthValue, measure)) and not(validate($nthValue, number)) {
        $border-radius-values: append($border-radius-values, #{$nthValue});
        $border-radius-REMvalues: append($border-radius-REMvalues, rem($nthValue));
      }
  @else if (validate($nthValue, number)) {
        @if ($nthValue == 0) {
          $border-radius-values: append($border-radius-values, 0);
          $border-radius-REMvalues: append($border-radius-REMvalues, 0);
        }
  @else {
          $border-radius-values: append($border-radius-values, #{$nthValue}px);
          $border-radius-REMvalues: append($border-radius-REMvalues, rem($nthValue));
        }
        //@include prefixProperty(border-radius, rem($nthValue));
      }
  @else if (unit($nthValue) == "%") {
        $dontUseREM: true;
        @if ($nthValue == 0%) or ($nthValue == "0%") {
          $border-radius-values: append($border-radius-values, 0);
        }
  @else {
          $border-radius-values: append($border-radius-values, $nthValue);
        }
      }
  @else {
        @warn "border-radius: " + $value validate($nthValue, unit) + " Error with the rem conversion: unit measure is not valid!";
      }
    }

    @if ($dontUseREM) {
      @include prefixProperty(border-radius, $border-radius-values);
      @include prefixProperty(background-clip, padding-box); // keeps background from busting out of border
    }
  @else {
      @include prefixProperty(border-radius, $border-radius-values);
      @include prefixProperty(border-radius, $border-radius-REMvalues);
      @include prefixProperty(background-clip, padding-box); // keeps background from busting out of border
    }
  }
  @else if (length($radius) == 1) {
    $onlyOne: nth($radius, 1);

    @if (validate($onlyOne, measure)) and not(validate($onlyOne, number)) and not(unit(nth($radius, 1)) == "%") {
      @include prefixProperty(border-radius, #{$onlyOne});
      @include prefixProperty(border-radius, rem($onlyOne));
      @include prefixProperty(background-clip, padding-box); // keeps background from busting out of border
    }
  @else if (validate($onlyOne, number)) {
      @include prefixProperty(border-radius, #{$onlyOne}px);
      @include prefixProperty(border-radius, rem($onlyOne));
      @include prefixProperty(background-clip, padding-box); // keeps background from busting out of border
    }
  @else if (unit(nth($radius, 1)) == "%") {
      @include prefixProperty(border-radius, $onlyOne);
      @include prefixProperty(background-clip, padding-box); // keeps background from busting out of border
    }
  @else {
      @warn "border-radius: " $onlyOne validate($onlyOne, unit) "Error with the rem conversion: unit measure is not valid!";
    }
  }
  @else {
    @warn "border-radius: Error with the rem conversion: no items to convert!";
  }
}

@mixin border-radius-separate($top-left-radius:0, $top-right-radius:0, $bottom-right-radius:0, $bottom-left-radius:0) {
  @include border-radius($top-left-radius, $top-right-radius, $bottom-right-radius, $bottom-left-radius);
}

/* ==========================================================================
   # Box Shadow
     Usage: @include box-shadow(...)
   ========================================================================== */

@mixin box-shadow($args...) {
  @include prefixProperty(box-shadow, #{$args});
}

/* ==========================================================================
   # Text Shadow
     Usage: @include text-shadow(...)
   ========================================================================== */

@mixin text-shadow($args...) {
  @include prefixProperty(text-shadow, #{$args}, false, false, false, false);
}

/* ==========================================================================
  # Keyframes animation
    Usage:

  @include keyframes(slide-down) {
      0% { opacity: 1; }
      90% { opacity: 0; }
  }

  .element {
      width: 100px;
      height: 100px;
      background: black;
      @include animation('slide-down 5s 3');
  }
   ========================================================================== */

@mixin keyframes($animation-name) {
  @-webkit-keyframes #{$animation-name} {
    @content;
  }

  @-moz-keyframes #{$animation-name} {
    @content;
  }

  @-ms-keyframes #{$animation-name} {
    @content;
  }

  @-o-keyframes #{$animation-name} {
    @content;
  }

  @keyframes #{$animation-name} {
    @content;
  }
}

@mixin animation($arguments) {
  @include prefixProperty(animation, $arguments);
}

/* ==========================================================================
   # Material Animations
     Usage:
     @include material-animation-default();

   ========================================================================== */

@mixin material-animation-fast-out-slow-in($duration:0.2s) {
  transition-duration: $duration;
  transition-timing-function: $animation-curve-fast-out-slow-in;
}

@mixin material-animation-linear-out-slow-in($duration:0.2s) {
  transition-duration: $duration;
  transition-timing-function: $animation-curve-linear-out-slow-in;
}

@mixin material-animation-fast-out-linear-in($duration:0.2s) {
  transition-duration: $duration;
  transition-timing-function: $animation-curve-fast-out-linear-in;
}

@mixin material-animation-default($duration:0.2s) {
  transition-duration: $duration;
  transition-timing-function: $animation-curve-default;
}

/* ==========================================================================
   # Gradients
     Usage:
     @include linear-gradient(...)
     @include radial-gradient(...)

   ========================================================================== */

@mixin linear-gradient($args...) {
  @include prefixValue(background-image, linear-gradient(#{$args}));
}

@mixin radial-gradient($args...) {
  @include prefixValue(background-image, radial-gradient(#{$args}));
}

@mixin gradient-horizontal($start-color: #555, $end-color: #333, $start-percent: 0%, $end-percent: 100%) {
  background-image: -webkit-linear-gradient(to right, $start-color $start-percent, $end-color $end-percent); // Safari 5.1-6, Chrome 10+
  background-image: -o-linear-gradient(to right, $start-color $start-percent, $end-color $end-percent); // Opera 12
  background-image: linear-gradient(to right, $start-color $start-percent, $end-color $end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+
  background-repeat: repeat-x;
  filter: progid:dximagetransform.microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=1); // IE9 and down
}

@mixin gradient-vertical($start-color: #555, $end-color: #333, $start-percent: 0%, $end-percent: 100%) {
  background-image: -webkit-linear-gradient(to top, $start-color $start-percent, $end-color $end-percent); // Safari 5.1-6, Chrome 10+
  background-image: -o-linear-gradient(to top, $start-color $start-percent, $end-color $end-percent); // Opera 12
  background-image: linear-gradient(to bottom, $start-color $start-percent, $end-color $end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+
  background-repeat: repeat-x;
  filter: progid:dximagetransform.microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=0); // IE9 and down
}

@mixin gradient-directional($start-color: #555, $end-color: #333, $deg: 45deg) {
  background-repeat: repeat-x;
  background-image: -webkit-linear-gradient($deg, $start-color, $end-color); // Safari 5.1-6, Chrome 10+
  background-image: -o-linear-gradient($deg, $start-color, $end-color); // Opera 12
  background-image: linear-gradient($deg, $start-color, $end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+
}

@mixin gradient-horizontal-three-colors($start-color: #00b3ee, $mid-color: #7a43b6, $color-stop: 50%, $end-color: #c3325f) {
  background-image: -webkit-linear-gradient(to left, $start-color, $mid-color $color-stop, $end-color);
  background-image: -o-linear-gradient(to left, $start-color, $mid-color $color-stop, $end-color);
  background-image: linear-gradient(to left, $start-color, $mid-color $color-stop, $end-color);
  background-repeat: no-repeat;
  filter: progid:dximagetransform.microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=1); // IE9 and down, gets no color-stop at all for proper fallback
}

@mixin gradient-vertical-three-colors($start-color: #00b3ee, $mid-color: #7a43b6, $color-stop: 50%, $end-color: #c3325f) {
  background-image: -webkit-linear-gradient($start-color, $mid-color $color-stop, $end-color);
  background-image: -o-linear-gradient($start-color, $mid-color $color-stop, $end-color);
  background-image: linear-gradient($start-color, $mid-color $color-stop, $end-color);
  background-repeat: no-repeat;
  filter: progid:dximagetransform.microsoft.gradient(startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}', GradientType=0); // IE9 and down, gets no color-stop at all for proper fallback
}

@mixin gradient-radial($inner-color: #555, $outer-color: #333) {
  background-image: -webkit-radial-gradient(circle, $inner-color, $outer-color);
  background-image: radial-gradient(circle, $inner-color, $outer-color);
  background-repeat: no-repeat;
}

@mixin gradient-striped($color: rgba(255,255,255,0.15), $angle: 45deg) {
  background-image: -webkit-linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent);
  background-image: -o-linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent);
  background-image: linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent);
}

//http://tympanus.net/codrops/css_reference/repeating-radial-gradient/
@mixin repeating-radial-gradient($args...) {
  @include prefixValue(background-image, repeating-radial-gradient(#{$args}));
}

/* ==========================================================================
   # Transforms
     Usage:
     @include transform(...)                 # generic transform
     @include rotate(...)                    #
     @include scale(...)
     @include translate(...)
     @include skew(...)
     @include transform-origin(...)
   ========================================================================== */

@mixin transform($transforms...) {
  @include prefixValue(transform, $transforms);
}

@mixin rotate($deg) {
  @include transform(rotate(#{$deg}deg));
}

@mixin scale($scale) {
  @include transform(scale($scale));
}

@mixin translate($x: 0, $y: 0) {

  @if (is-percentage($x) AND $y==0) {
    @include transform(translate($x, 0));
  }
  @else if (is-percentage($y) AND $x==0) {
    @include transform(translate(0, $y));
  }
  @else if (is-percentage($x) AND is-percentage($y)) {
    @include transform(translate($x, $y));
  }
  @else if (is-int($x) AND is-int($y)) {
    @include transform(translate(#{$x}px, #{$y}px));
  }
}

@mixin skew($x: 0, $y: 0) {
  @include transform(skew(#{$x}deg, #{$y}deg));
}

@mixin transform-origin($origin) {
  -moz-transform-origin: $origin;
  -o-transform-origin: $origin;
  -ms-transform-origin: $origin;
  -webkit-transform-origin: $origin;
  transform-origin: $origin;
}

/* ==========================================================================
   # Positions
     Usage:
     @include position(absolute, $top: 10px, $left: 10px);
   ========================================================================== */

@mixin position($type, $top: null, $right: null, $bottom: null, $left: null) {
  position: $type;
  top: $top;
  right: $right;
  bottom: $bottom;
  left: $left;
}

/* ==========================================================================
   # Transition
     Usage:
        a {
			color: gray;
		    @include transition(color .3s ease);
		}
   ========================================================================== */

@mixin transition($args...) {
  @include prefixProperty(transition, #{$args});
}

@mixin transition-property($args...) {
  @include prefixProperty(transition-property, #{$args});
}

@mixin transition-duration($duration...) {
  @include prefixProperty(transition-duration, #{$duration});
}

@mixin transition-timing-function($timing...) {
  @include prefixProperty(transition-timing-function, #{$timing});
}

@mixin transition-delay($delay...) {
  @include prefixProperty(transition-delay, #{$delay});
}

/* ==========================================================================
   # Easing http://cubic-bezier.com/
     Usage:
     @include transition(top 500ms $easeInOutCubic);             # Cubic
     @include transition(top 500ms $easeInOut);                  # Circ
     @include transition(top 500ms $easeInOutExpo);              # Expo
     @include transition(top 500ms $easeInOutQuad);              # Quad
     @include transition(top 500ms $easeInOutQuart);             # Quart
     @include transition(top 500ms $easeInOutQuint);             # Quint
     @include transition(top 500ms $easeInOutSine);              # Sine
     @include transition(top 500ms $easeInOutBack);              # Back
     @include transition(top 500ms $easeInOutFast);              # Ease tFast
     @include transition(top 500ms $authenticMotion);            # Authentic Motion
   ========================================================================== */

$easeInCubic: cubic-bezier(0.55, 0.055, 0.675, 0.19);
$easeOutCubic: cubic-bezier(0.215, 0.61, 0.355, 1);
$easeInOutCubic: cubic-bezier(0.645, 0.045, 0.355, 1);

$easeInCirc: cubic-bezier(0.6, 0.04, 0.98, 0.335);
$easeOutCirc: cubic-bezier(0.075, 0.82, 0.165, 1);
$easeInOutCirc: cubic-bezier(0.785, 0.135, 0.15, 0.86);

$easeInExpo: cubic-bezier(0.95, 0.05, 0.795, 0.035);
$easeOutExpo: cubic-bezier(0.19, 1, 0.22, 1);
$easeInOutExpo: cubic-bezier(1, 0, 0, 1);

$easeInQuad: cubic-bezier(0.55, 0.085, 0.68, 0.53);
$easeOutQuad: cubic-bezier(0.25, 0.46, 0.45, 0.94);
$easeInOutQuad: cubic-bezier(0.455, 0.03, 0.515, 0.955);

$easeInQuart: cubic-bezier(0.895, 0.03, 0.685, 0.22);
$easeOutQuart: cubic-bezier(0.165, 0.84, 0.44, 1);
$easeInOutQuart: cubic-bezier(0.77, 0, 0.175, 1);

$easeInQuint: cubic-bezier(0.755, 0.05, 0.855, 0.06);
$easeOutQuint: cubic-bezier(0.23, 1, 0.32, 1);
$easeInOutQuint: cubic-bezier(0.86, 0, 0.07, 1);

$easeInSine: cubic-bezier(0.47, 0, 0.745, 0.715);
$easeOutSine: cubic-bezier(0.39, 0.575, 0.565, 1);
$easeInOutSine: cubic-bezier(0.445, 0.05, 0.55, 0.95);

$easeInBack: cubic-bezier(0.6, -0.28, 0.735, 0.045);
$easeOutBack: cubic-bezier(0.175, 0.885, 0.32, 1.275);
$easeInOutBack: cubic-bezier(0.68, -0.55, 0.265, 1.55);

$easeInOutFast: cubic-bezier(1, 0, 0, 1);

$authenticMotion: cubic-bezier(0.4, 0, 0.2, 1);

/* ==========================================================================
   # Flexbox Containers
     info:
      	 The 'flex' value causes an element to generate a block-level flex
		 container box.
		 The 'inline-flex' value causes an element to generate a inline-level
		 flex container box.
	 usage:
	 @extend %flexbox
	 @extend %inline-flex
   ========================================================================== */

@mixin flexbox {
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
}

@mixin inline-flex {
  display: -webkit-inline-flex;
  display: -moz-inline-box;
  display: -ms-inline-flexbox;
  display: inline-flex;
}

/* ==========================================================================
   # Flexbox Direction
     info:
      	 The 'flex-direction' property specifies how flex items are placed in
		 the flex container, by setting the direction of the flex container's
		 main axis. This determines the direction that flex items are laid out in.
	 usage:
	 @include flex-direction(row|row-reverse|column|column-reverse|initial|inherit)
	 @include flex-dir(row|row-reverse|column|column-reverse|initial|inherit)           # Shorter version
   ========================================================================== */

@mixin flex-direction($value: row) {
  @if $value == row-reverse {
    -webkit-box-direction: reverse;
    -webkit-box-orient: horizontal;
  }
  @else if $value == column {
    -webkit-box-direction: normal;
    -webkit-box-orient: vertical;
  }
  @else if $value == column-reverse {
    -webkit-box-direction: reverse;
    -webkit-box-orient: vertical;
  }
  @else {
    -webkit-box-direction: normal;
    -webkit-box-orient: horizontal;
  }

  -webkit-flex-direction: $value;
  -moz-flex-direction: $value;
  -ms-flex-direction: $value;
  flex-direction: $value;
}

@mixin flex-dir($args...) {
  @include flex-direction($args...);
}

/* ==========================================================================
   # Flexbox Wrap
     info:
		 The 'flex-wrap' property controls whether the flex container is single-line
		 or multi-line, and the direction of the cross-axis, which determines
		 the direction new lines are stacked in.
	 usage:
	 @include flex-wrap(nowrap | wrap | wrap-reverse)
   ========================================================================== */

@mixin flex-wrap($value: nowrap) {
  // No Webkit Box fallback.
  -webkit-flex-wrap: $value;
  -moz-flex-wrap: wrap;

  @if $value == nowrap {
    -ms-flex-wrap: none;
  }
  @else {
    -ms-flex-wrap: $value;
  }

  flex-wrap: $value;
}

/* ==========================================================================
   # Flexbox Flow
     info:
		 The 'flex-flow' property is a shorthand for setting the 'flex-direction'
		 and 'flex-wrap' properties, which together define the flex container's
		 main and cross axes.
	 usage:
	 @include flex-flow(flex-direction | flex-wrap)
   ========================================================================== */

@mixin flex-flow($values: (row nowrap)) {
  @include prefixProperty(flex-flow, $values);
}

/* ==========================================================================
   # Flexbox Order
     info:
		  The 'order' property controls the order in which flex items appear within
 		  their flex container, by assigning them to ordinal groups.
	 usage:
	 @include flex-order(1)
   ========================================================================== */

@mixin flex-order($int: 0) {
  -webkit-box-ordinal-group: $int + 1;
  @include prefixProperty(order, $int);
}

/* ==========================================================================
   # Flexbox Grow
     info:
		 The 'flex-grow' property sets the flex grow factor. Negative numbers
		 are invalid.
	 usage:
	 @include flex-grow(1)
   ========================================================================== */

@mixin flex-grow($int: 0) {
  -webkit-box-flex: $int;
  -ms-flex-positive: $int;
  @include prefixProperty(flex-grow, $int);
}

/* ==========================================================================
   # Flexbox Shrink
	  info:
		 The 'flex-shrink' property sets the flex shrink factor. Negative numbers
		 are invalid.
	 usage:
	 @include flex-shrink(1)
   ========================================================================== */

@mixin flex-shrink($int: 1) {
  -ms-flex-negative: $int;
  @include prefixProperty(flex-shrink, $int);
}

/* ==========================================================================
   # Flexbox Basis
     info:
		 The 'flex-basis' property sets the flex basis. Negative lengths are invalid.
	 usage:
	 @include flex-basis(auto)
   ========================================================================== */

@mixin flex-basis($value: auto) {
  @include prefixProperty(flex-basis, $value);

  -ms-flex-preferred-size: $value;
}

/* ==========================================================================
   # Flexbox "Flex" (shorthand)
     info:
		 The 'flex' property specifies the modules of a flexible length: the
		 flex grow factor and flex shrink factor, and the flex basis. When an
		 element is a flex item, 'flex' is consulted instead of the main size
		 property to determine the main size of the element. If an element is
		 not a flex item, 'flex' has no effect.
	 usage:
	 @include flex( none | flex-grow | flex-shrink | flex-basis)
   ========================================================================== */

@mixin flex($fg: 1, $fs: null, $fb: null) {
  // Set a variable to be used by box-flex properties
  $fg-boxflex: $fg;

  // Box-Flex only supports a flex-grow value so let's grab the
  // first item in the list and just return that.
  @if type-of($fg) == 'list' {
    $fg-boxflex: nth($fg, 1);
  }

  -webkit-box-flex: $fg-boxflex;
  -moz-box-flex: $fg-boxflex;
  @include prefixProperty(flex, $fg $fs $fb);
}

/* ==========================================================================
   # Flexbox Justify Content
     info:
		 The 'justify-content' property aligns flex items along the main axis
		 of the current line of the flex container. This is done after any flexible
		 lengths and any auto margins have been resolved. Typically it helps distribute
		 extra free space leftover when either all the flex items on a line are
		 inflexible, or are flexible but have reached their maximum size. It also
		 exerts some control over the alignment of items when they overflow the line.

		 Note: 'space-*' values not supported in older syntaxes.

	 usage:
	 @include justify-content(flex-start | flex-end | center | space-between | space-around)
   ========================================================================== */

@mixin justify-content($value: flex-start) {
  @if $value == flex-start {
    -webkit-box-pack: start;
    -ms-flex-pack: start;
  }
  @else if $value == flex-end {
    -webkit-box-pack: end;
    -ms-flex-pack: end;
  }
  @else if $value == space-between {
    -webkit-box-pack: justify;
    -ms-flex-pack: justify;
  }
  @else if $value == space-around {
    -ms-flex-pack: distribute;
  }
  @else {
    -webkit-box-pack: $value;
    -ms-flex-pack: $value;
  }

  //-webkit-justify-content: $value;
  //-moz-justify-content: $value;
  //justify-content: $value;
  @include prefixProperty(justify-content, $value);
}

// Shorter version:
@mixin flex-just($args...) {
  @include justify-content($args...);
}

/* ==========================================================================
   # Flexbox Align Items
     info:
		 Flex items can be aligned in the cross axis of the current line of the
		 flex container, similar to 'justify-content' but in the perpendicular
		 direction. 'align-items' sets the default alignment for all of the flex
		 container's items, including anonymous flex items. 'align-self' allows
		 this default alignment to be overridden for individual flex items. (For
		 anonymous flex items, 'align-self' always matches the value of 'align-items'
		 on their associated flex container.)

	 usage:
	 @include align-items(flex-start | flex-end | center | baseline | stretch)
   ========================================================================== */

@mixin align-items($value: stretch) {
  @if $value == flex-start {
    -webkit-box-align: start;
    -ms-flex-align: start;
  }
  @else if $value == flex-end {
    -webkit-box-align: end;
    -ms-flex-align: end;
  }
  @else {
    -webkit-box-align: $value;
    -ms-flex-align: $value;
  }

  //-webkit-align-items: $value;
  //-moz-align-items: $value;
  //align-items: $value;
  @include prefixProperty(align-items, $value);
}

/* ==========================================================================
   # Flexbox Align Self
     info:
		 Center the alignments for all the items of the flexible <div> element:
	 usage:
	 @include align-self(auto | flex-start | flex-end | center | baseline | stretch)
   ========================================================================== */

@mixin align-self($value: auto) {
  // No Webkit Box Fallback.
  //-webkit-align-self: $value;
  //-moz-align-self: $value;

  @if $value == flex-start {
    -ms-flex-item-align: start;
  }
  @else if $value == flex-end {
    -ms-flex-item-align: end;
  }
  @else {
    -ms-flex-item-align: $value;
  }

  //align-self: $value;
  @include prefixProperty(align-self, $value);
}

/* ==========================================================================
   # Flexbox Align Content
     info:
		 The 'align-content' property aligns a flex container's lines within the
		 flex container when there is extra space in the cross-axis, similar to
		 how 'justify-content' aligns individual items within the main-axis. Note,
		 this property has no effect when the flexbox has only a single line.
	 usage:
	 @include align-content(flex-start | flex-end | center | space-between | space-around | stretch)
   ========================================================================== */

@mixin align-content($value: stretch) {
  // No Webkit Box Fallback.
  //-webkit-align-content: $value;
  //-moz-align-content: $value;

  @if $value == flex-start {
    -ms-flex-line-pack: start;
  }
  @else if $value == flex-end {
    -ms-flex-line-pack: end;
  }
  @else {
    -ms-flex-line-pack: $value;
  }

  //align-content: $value;
  @include prefixProperty(align-content, $value);
}

/* ==========================================================================
   # Clearfix
	 usage:
	 @include clearfix
   ========================================================================== */

@mixin clearfix() {
  & {
    *zoom: 1;
  }

  &::before,
  &::after {
    content: "";
    display: table;
  }

  &::after {
    clear: both;
  }
}

/* ==========================================================================
   # Material Design Custom Shadow
	 usage:
	 @include customShadow(1)
   ========================================================================== */

$level: 1;

@mixin customShadow($level) {
  @include transition(box-shadow 0.3s ease-in-out);

  @if $level == 1 {
    @include box-shadow(0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24));
  }
  @else if $level == 2 {
    @include box-shadow(0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23));
  }
  @else if $level == 3 {
    @include box-shadow(0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23));
  }
  @else if $level == 4 {
    @include box-shadow(0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22));
  }
  @else if $level == 5 {
    @include box-shadow(0 19px 38px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.22));
  }
}

/* ==========================================================================
   # Material Shadow
	 usage:
	 @include focus-shadow()
   ========================================================================== */

@mixin focus-shadow() {
  @include box-shadow(0 0 8px rgba(0, 0, 0, 0.18), 0 8px 16px rgba(0, 0, 0, 0.36));
}

@mixin shadow-2dp() {
  @include box-shadow(0 2px 2px 0 rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0 3px 1px -2px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0 1px 5px 0 rgba(0, 0, 0, $shadow-ambient-shadow-opacity));
}

@mixin shadow-3dp() {
  @include box-shadow(0 3px 4px 0 rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0 3px 3px -2px rgba(0, 0, 0, $shadow-key-umbra-opacity), 0 1px 8px 0 rgba(0, 0, 0, $shadow-ambient-shadow-opacity));
}

@mixin shadow-4dp() {
  @include box-shadow(0 4px 5px 0 rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0 1px 10px 0 rgba(0, 0, 0, $shadow-ambient-shadow-opacity), 0 2px 4px -1px rgba(0, 0, 0, $shadow-key-umbra-opacity));
}

@mixin shadow-6dp() {
  @include box-shadow(0 6px 10px 0 rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0 1px 18px 0 rgba(0, 0, 0, $shadow-ambient-shadow-opacity), 0 3px 5px -1px rgba(0, 0, 0, $shadow-key-umbra-opacity));
}

@mixin shadow-8dp() {
  @include box-shadow(0 8px 10px 1px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0 3px 14px 2px rgba(0, 0, 0, $shadow-ambient-shadow-opacity), 0 5px 5px -3px rgba(0, 0, 0, $shadow-key-umbra-opacity));
}

@mixin shadow-16dp() {
  @include box-shadow(0 16px 24px 2px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0 6px 30px 5px rgba(0, 0, 0, $shadow-ambient-shadow-opacity), 0 8px 10px -5px rgba(0, 0, 0, $shadow-key-umbra-opacity));
}

@mixin shadow-24dp() {
  @include box-shadow(0 9px 46px 8px rgba(0, 0, 0, $shadow-key-penumbra-opacity), 0 11px 15px -7px rgba(0, 0, 0, $shadow-ambient-shadow-opacity), 0 24px 38px 3px rgba(0, 0, 0, $shadow-key-umbra-opacity));
}

/* ==========================================================================
   # Trucane
	 usage:
	 @include trucane
   ========================================================================== */

@mixin trucane() {
  white-space: nowrap;
  overflow: hidden;
  -ms-text-overflow: ellipsis;
  -o-text-overflow: ellipsis;
  text-overflow: ellipsis;
}
/* ==========================================================================
   A collection of functions for color adjustments
   Usage: adjust-lightness(#000, 20%) { }
   ========================================================================== */

// a genericized version of lighten/darken so that negative values can be used.
@function adjust-lightness($color, $amount) {
  //@debug $color;  @debug $amount;
  @return adjust-color($color, $lightness: $amount);
}

// Scales a color's lightness by some percentage.
// If the amount is negative, the color is scaled darker, if positive, it is scaled lighter.
// This will never return a pure light or dark color unless the amount is 100%.
@function lighten($color, $amount) {
  //@debug $color;@debug $amount;
  @return scale-color($color, $lightness: $amount);
}

// a genericized version of saturate/desaturate so that negative values can be used.
@function adjust-saturation($color, $amount) {
  //@debug $color;@debug $amount;
  @return adjust-color($color, $saturation: $amount);
}

// Scales a color's saturation by some percentage.
// If the amount is negative, the color is desaturated, if positive, it is saturated.
// This will never return a pure saturated or desaturated color unless the amount is 100%.
@function darken($color, $amount) {
  //@debug $color;@debug $amount;
  @return scale-color($color, $saturation: $amount);
}

@function shade($color, $percentage) {
  //@debug $color;@debug $percentage;
  @return mix(#000000, $color, $percentage);
}

@function tint($color, $percentage) {
  //@debug $color;@debug $percentage;
  @return mix(#ffffff, $color, $percentage);
}

/* ==========================================================================
   A collection of function for advanced type checking
   Usage: @if is-number(14px) { }
   ========================================================================== */

@function is-number($value) {
  @return type-of($value) == 'number';
}

@function is-int($value) {
  @return unitless($value);
}

@function is-time($value) {
  @return is-number($value) and index('ms' 's', unit($value)) != null;
}

@function is-duration($value) {
  @return is-time($value);
}

@function is-angle($value) {
  @return is-number($value) and index('deg' 'rad' 'grad' 'turn', unit($value)) != null;
}

@function is-frequency($value) {
  @return is-number($value) and index('Hz' 'kHz', unit($value)) != null;
}

@function is-integer($value) {
  @return is-number($value) and round($value) == $value;
}

@function is-relative-length($value) {
  @return is-number($value) and index('em' 'ex' 'ch' 'rem' 'vw' 'vh' 'vmin' 'vmax', unit($value)) != null;
}

@function is-absolute-length($value) {
  @return is-number($value) and index('cm' 'mm' 'in' 'px' 'pt' 'pc', unit($value)) != null;
}

@function is-percentage($value) {
  @return is-number($value) and unit($value) == '%';
}

@function is-length($value) {
  @return is-relative-length($value) or is-absolute-length($value);
}

@function is-resolution($value) {
  @return is-number($value) and index('dpi' 'dpcm' 'dppx', unit($value)) != null;
}

@function is-position($value) {
  @return is-length($value) or is-percentage($value) or index('top' 'right' 'bottom' 'left' 'center', $value) != null;
}

/* ==========================================================================
   Convert px to REM
   Usage: @include rem(14px)
   ========================================================================== */

/// Power function
/// @param {Number} $x
/// @param {Number} $n
/// @return {Number}
@function pow($x, $n) {
  $ret: 1;

  @if $n >= 0 {
    @for $i from 1 through $n {
      $ret: $ret * $x;
    }
  }
  @else {
    @for $i from $n to 0 {
      $ret: $ret / $x;
    }
  }

  @return $ret;
}

@function stripunits($value) {
  @return ($value) / ($value * 0 + 1);
}

@function num($input) {
  @if type-of($input) != number {
    @error 'Could not convert `#{$input}` - must be `type-of number`';
    @return null;
  }
  @return $input/($input*0+1);
}

@function pxToRem($size, $context: $base-font-size) {
  //@debug stripUnits($size) /$context * 1rem;
  @return stripunits($size) /$context * 1rem;
}

@function rem($sizes...) {
  $rems: ();
  @if length($sizes) > 1 {
    @for $value from 1 through length($sizes) {
      @if (unit(nth($sizes, $value )) == "%") {
        $rems: append($rems, nth($sizes, $value));
      }
      @else {
        $rems: append($rems, pxToRem(stripunits($value)));
      }
    }
    @return #{$rems};
  }
  @else if (length($sizes) == 1) {
    $onlyOne: nth($sizes, 1);

    @if ($onlyOne == 0) or ($onlyOne == "0px") or ($onlyOne == "0") {
      @return $onlyOne;
    }
    @else if (validate($onlyOne, measure)) {
      @return pxToRem($onlyOne);
    }
    @else if (validate($onlyOne, number)) {
      //@debug calculateRem($onlyOne);
      @return pxToRem($onlyOne);
    }
    @else {
      @warn "rem: " $onlyOne validate($onlyOne, unit) "Error with the rem conversion: unit measure is not valid!";
      @return $onlyOne;
    }
  }
  @else {
    @warn "rem: Error with the rem conversion: no items to convert!";
  }
}