$grid-gutter-width: 16px;
$grid-columns: 12;
$grid-container: 'container';
$grid-row: 'row';
$grid-prefix: 'col';
$grid-sizes: (xs, sm, md, lg);
$grid-ratio-name: 'aspect';
$grid-ratio-inner-name: 'aspect__inner';
$grid-container-padding: (
  xs: 3.5%,
  sm: 7%
);
$grid-max-width--desktop: 1200px;
$grid-ratios: (
  (16, 9),
  (9, 16),
  (4, 3),
  (3, 4),
  (3, 2),
  (3, 1),
  (2, 3),
  (2, 1),
  (1, 2),
  (1, 1)
);

// 7% => 0.07
$_grid-padding-pct: map-get($grid-container-padding, "sm") / 100%;
// 0.07 => 0.14 => 0.86
$_grid-padding-value: 1 - $_grid-padding-pct * 2;

// Size of the window when the grid row has hit max-width.
$_viewport-at-max-grid-width: $grid-max-width--desktop / $_grid-padding-value;
$viewport-at-max-grid-width: round($_viewport-at-max-grid-width) + 0px;
$padding-at-max-grid-width: round($_viewport-at-max-grid-width * $_grid-padding-pct) + 0px;

@function get-column-selector($number, $breakpoint) {
  @return ".#{$grid-prefix}-#{$number}\\@#{$breakpoint}";
}

@function get-grid-breakpoint-selectors($breakpoint) {
  $selectors: ();
  @for $i from 1 through $grid-columns {
    $selectors: append($selectors, get-column-selector($i, $breakpoint), comma);
  }

  @return $selectors;
}

@function get-all-grid-breakpoint-selectors() {
  $selectors: ();
  @each $breakpoint in $grid-sizes {
    $selectors: append($selectors, get-grid-breakpoint-selectors($breakpoint), comma);
  }

  @return $selectors;
}


@mixin make-grid-columns() {
  $selectors: get-all-grid-breakpoint-selectors();

  #{$selectors} {
    position: relative;
    box-sizing: border-box;
    // Prevent columns from collapsing when empty
    min-height: 1px;
    // Inner gutter via padding
    padding-left:  ($grid-gutter-width / 2);
    padding-right: ($grid-gutter-width / 2);
  }
}


@mixin float-grid-columns($breakpoint) {
  $selectors: get-grid-breakpoint-selectors($breakpoint);

  #{$selectors} {
    float: left;
  }
}


@mixin grid-ratios($breakpoint: "") {
  // If there is a grid breakpoint class here, prepend a @.
  // e.g. "@sm" or "" when there isn't a class.
  @if $breakpoint != "" {
    $breakpoint: "\\@" + $breakpoint;
  }

  // Note @extend isn't used because it cannot be used within @media directives.
  @each $list in $grid-ratios {
    $top: nth($list, 1);
    $bottom: nth($list, 2);
    $name: "#{$top}x#{$bottom}";
    .#{$grid-ratio-name}--#{$name}#{$breakpoint} {
      padding-bottom: percentage($bottom / $top);
    }
  }

  // A `none` class (eg `aspect--none@xs`) which removes the aspect ratio
  .#{$grid-ratio-name}--none#{$breakpoint} {
    @include no-aspect();

    > .#{$grid-ratio-inner-name} {
      position: static;
    }
  }
}

@mixin calc-grid-column($index, $columns, $breakpoint, $type) {
  @if ($type == "width") and ($index > 0) {
    .#{$grid-prefix}-#{$index}\@#{$breakpoint} {
      width: percentage(($index / $columns));
    }
  }
  @if ($type == "push") and ($index > 0) {
    .#{$grid-prefix}-push-#{$index}\@#{$breakpoint} {
      left: percentage(($index / $columns));
    }
  }
  @if ($type == "push") and ($index == 0) {
    .#{$grid-prefix}-push-0\@#{$breakpoint} {
      left: auto;
    }
  }
  @if ($type == "pull") and ($index > 0) {
    .#{$grid-prefix}-pull-#{$index}\@#{$breakpoint} {
      right: percentage(($index / $columns));
    }
  }
  @if ($type == "pull") and ($index == 0) {
    .#{$grid-prefix}-pull-0\@#{$breakpoint} {
      right: auto;
    }
  }
  @if ($type == "offset") {
    .#{$grid-prefix}-offset-#{$index}\@#{$breakpoint} {
      margin-left: percentage(($index / $columns));
    }
  }
}

@mixin loop-grid-columns($columns, $breakpoint, $type) {
  @for $i from 0 through $columns {
    @include calc-grid-column($i, $columns, $breakpoint, $type);
  }
}

// Create grid for specific class
@mixin make-grid($breakpoint, $columns: $grid-columns) {
  @include float-grid-columns($breakpoint);
  @include grid-ratios($breakpoint);

  @include loop-grid-columns($columns, $breakpoint, "width");
  @include loop-grid-columns($columns, $breakpoint, "pull");
  @include loop-grid-columns($columns, $breakpoint, "push");
  @include loop-grid-columns($columns, $breakpoint, "offset");
}
