--- /dev/null
+@charset "UTF-8";
+
+/// Increments up or down a defined scale and returns an adjusted value. This
+/// helps establish consistent measurements and spacial relationships throughout
+/// your project. We provide a list of commonly used scales as
+/// [pre-defined variables][scales].
+///
+/// [scales]: https://github.com/thoughtbot/bourbon/blob/master/core/bourbon/helpers/_scales.scss
+///
+/// @argument {number (unitless)} $increment
+/// How many steps to increment up or down the scale.
+///
+/// @argument {number (with unit) | list} $value [1em]
+/// The base value the scale starts at. Can also be set globally using the
+/// `modular-scale-base` key in the Bourbon settings.
+///
+/// @argument {number (unitless)} $ratio [1.25]
+/// The ratio the scale is built on. Can also be set globally using the
+/// `modular-scale-ratio` key in the Bourbon settings.
+///
+/// @return {number (with unit)}
+///
+/// @example scss
+/// .element {
+/// font-size: modular-scale(2);
+/// }
+///
+/// // CSS Output
+/// .element {
+/// font-size: 1.5625em;
+/// }
+///
+/// @example scss
+/// .element {
+/// margin-right: modular-scale(3, 2em);
+/// }
+///
+/// // CSS Output
+/// .element {
+/// margin-right: 3.90625em;
+/// }
+///
+/// @example scss
+/// .element {
+/// font-size: modular-scale(3, 1em 1.6em, $major-seventh);
+/// }
+///
+/// // CSS Output
+/// .element {
+/// font-size: 3em;
+/// }
+///
+/// @example scss
+/// // Globally change the base ratio
+/// $bourbon: (
+/// "modular-scale-ratio": 1.2,
+/// );
+///
+/// .element {
+/// font-size: modular-scale(3);
+/// }
+///
+/// // CSS Output
+/// .element {
+/// font-size: 1.728em;
+/// }
+///
+/// @require {function} _fetch-bourbon-setting
+
+@function modular-scale(
+ $increment,
+ $value: _fetch-bourbon-setting("modular-scale-base"),
+ $ratio: _fetch-bourbon-setting("modular-scale-ratio")
+) {
+ $v1: nth($value, 1);
+ $v2: nth($value, length($value));
+ $value: $v1;
+
+ // scale $v2 to just above $v1
+ @while $v2 > $v1 {
+ $v2: ($v2 / $ratio); // will be off-by-1
+ }
+ @while $v2 < $v1 {
+ $v2: ($v2 * $ratio); // will fix off-by-1
+ }
+
+ // check AFTER scaling $v2 to prevent double-counting corner-case
+ $double-stranded: $v2 > $v1;
+
+ @if $increment > 0 {
+ @for $i from 1 through $increment {
+ @if $double-stranded and ($v1 * $ratio) > $v2 {
+ $value: $v2;
+ $v2: ($v2 * $ratio);
+ } @else {
+ $v1: ($v1 * $ratio);
+ $value: $v1;
+ }
+ }
+ }
+
+ @if $increment < 0 {
+ // adjust $v2 to just below $v1
+ @if $double-stranded {
+ $v2: ($v2 / $ratio);
+ }
+
+ @for $i from $increment through -1 {
+ @if $double-stranded and ($v1 / $ratio) < $v2 {
+ $value: $v2;
+ $v2: ($v2 / $ratio);
+ } @else {
+ $v1: ($v1 / $ratio);
+ $value: $v1;
+ }
+ }
+ }
+
+ @return $value;
+}