


/* Vars */



// Modular Scale ratios
$golden:           1.618;
$minor-second:     1.067;
$major-second:     1.125;
$minor-third:      1.2;
$major-third:      1.25;
$perfect-fourth:   1.333;
$augmented-fourth: 1.414;
$perfect-fifth:    1.5;
$minor-sixth:      1.6;
$major-sixth:      1.667;
$minor-seventh:    1.778;
$major-seventh:    1.875;
$octave:           2;
$major-tenth:      2.5;
$major-eleventh:   2.667;
$major-twelfth:    3;
$double-octave:    4;

// Settings
$body-font-size: 	14px !default;
$body-line-height: 	$golden !default;
$scale-factor: 		$minor-third !default;
$ie8compatability: 	true !default;
$outputrems: 		true !default;



/* - - - - - - -  Utility Functions - - - - - - - - - */



// Sass exponent support
@function exponent($base, $exponent) {
	// reset value
	$value: $base;
	// positive intergers get multiplied
	@if ($exponent > 1) {
		@for $i from 2 through $exponent {
			$value : $value * $base;
		}
	}
	// negitive intergers get divided. A number divided by itself is 1
	@if ($exponent < 1) {
		@for $i from 0 through -$exponent {
			$value : $value / $base;
		}
	}
	// return the last value written
	@return ($value);
}
// strip units for rem calculations so that we don't run into errors in case people declare numerical values instead of ##px
@function stripUnits($value) {
	@return ($value) / ($value * 0 + 1);
}

// px to rem
@function calculateRem($size) {
	@return stripUnits($size) / stripUnits($body-font-size) * 1rem;
}

// resolve values to a multiple of our base
@function resolve($value: 0, $roundup: false) {
	$kb : ceil($body-font-size * $body-line-height);
	$newVal: $value % $kb;
	$r : 0;

	@if ($roundup == false) {
		$r: $value - $newVal;
	} @else if ($roundup == true) {
		$x : $kb - $newVal;
		$r : $value + $x;
	}

	@return $r;
}

// vertical rythm units for use in layouts and non-type elements, pass rem:true to return rem values
@function kunit($baselines: 1, $rem: false) {
	@if ($rem == true) {
		@return	calculateRem(ceil($body-font-size * $body-line-height) * $baselines);
	}

	@return	ceil($body-font-size * $body-line-height) * $baselines;
}



/* - - - - - - - - -  Utility Mixins  - - - - - - - - - -  */



// rem font and line height
@mixin pxType($fontSize, $lineHeight) {
	font-size: $fontSize;
	line-height: $lineHeight;
}

// rem font and line height
@mixin remType($fontSize, $lineHeight) {
	font-size: calculateRem($fontSize);
	line-height: calculateRem($lineHeight);
}

// margin top and bottom in px
@mixin pxMargin($mb: 0,$ma: 0) {
	margin-top: $mb;
	margin-bottom: $ma;
}

// margin top and bottom in rem
@mixin remMargin($mb: 0,$ma: 0) {
	margin-top: calculateRem($mb);
	margin-bottom: calculateRem($ma);
}




/* - - - - - - - - -  Public Mixins  - - - - - - - - - -  */




// output any attr as rem with IE support
@mixin krem($attr: "",$px: 0, $ie: $ie8compatability, $resolve: false, $roundup: false) {
	@if ($resolve == false) {
		@if ($ie == true) {
			#{$attr} : stripUnits($px) * 1px;
		}
		#{$attr} : calculateRem($px);

	} @else if ($resolve == true) {
		$newVal : resolve($px,$roundup);
		@if ($ie == true) {
			#{$attr} : stripUnits($newVal) * 1px;
		}
		#{$attr} : calculateRem($newVal);
	}

}

// html mixin
@mixin khtml($reduce:0px) {
	$kb : 		(ceil($body-font-size * $body-line-height)) - $reduce;
	$px : 			$body-font-size - $reduce;
	@include pxType($px, $kb);
}

// body mixin
@mixin kbody($reduce:0px) {
  $kb :  (ceil($body-font-size * $body-line-height)) - $reduce;
  $px :  $body-font-size - $reduce;
  $rkb : $kb+$reduce;
  $rpx : $px+$reduce;

  @if ($ie8compatability == true) {
    @include pxType($px, $kb);
  }
  @include remType($rpx, $rkb);
}

// type mixin
@mixin ktype($scale, $before: 0, $after: 0, $lineheightmod: 0, $offset: 0, $pull: 0, $push: 0, $ie: $ie8compatability) {

	// setup what we've got to work with
	$kb : 				ceil($body-font-size * $body-line-height);
	$new-font-size: 	$body-font-size;
	$new-line-height: 	$kb;
	$margin-before: 	$kb * $before;
	$margin-after: 		$kb * $after;
	$compat: 			$ie;

	// Set new vars
	@if ($scale != 0) {
		$new-font-size: 	ceil($body-font-size * exponent($scale-factor, $scale));
		$new-line-height: 	ceil($new-font-size / $kb) * $kb;

		// push and pull, to be deprecated, see below
		@if ($pull != 0) {
			$m: ($pull / 2);
			$new-line-height: $new-line-height - ($new-line-height*$m);
		} @else if ($push != 0) {
			$m: ($push / 2);
			$new-line-height: $new-line-height + ($new-line-height*$m);
		}
	}

	//lineheightmod to replace push and pull with a single value, easy declare eg. to bump up lineheight by one whole line (2 half lines) for an element ktype(0,1,1,2)
	@if ($lineheightmod < 0) {
		$m: ($lineheightmod / 2);
		$new-line-height: $new-line-height + ($kb*$m);
	} @else if ($lineheightmod > 0) {
		$m: ($lineheightmod / 2);
		$new-line-height: $new-line-height + ($kb*$m);
	}

	// offset
	@if ($offset != 0) {
		$new-line-height: $new-line-height - $offset;
	}

	// Output
	@include krem("font-size", $new-font-size, $compat);
	@include krem("line-height", $new-line-height, $compat);
	@include krem("margin-top", $margin-before, $compat);
	@include krem("margin-bottom", $margin-after, $compat);
}

// prefix : add padding before
@mixin kprefix($multiple, $margin:false) {
	$x : 		(ceil($body-font-size * $body-line-height)) * $multiple;
	@if ($margin == false) {
		@include krem("padding-top",$x);
	} @else {
		@include krem("margin-top",$x);
	}
}

// suffix : add padding after
@mixin ksuffix($multiple, $margin:false) {
	$x : 		(ceil($body-font-size * $body-line-height)) * $multiple;
	@if ($margin == false) {
		@include krem("padding-bottom",$x);
	} @else {
		@include krem("margin-bottom",$x);
	}
}


