/* mixins
   ========================================================================== */

// units to rem
$font-size-base         : rem($font-size-base);

$baseline               : rem($baseline);

$font-size-h1           : rem($font-size-h1);
$font-size-h2           : rem($font-size-h2);
$font-size-h3           : rem($font-size-h3);
$font-size-h4           : rem($font-size-h4);
$font-size-h5           : rem($font-size-h5);
$font-size-h6           : rem($font-size-h6);

$container-width        : rem($container-width);

$label-font-size        : rem($label-font-size);

$field-height           : rem($field-height);
$field-padding-x        : rem($field-padding-x);
$field-font-size        : rem($field-font-size);

$btn-height             : rem($btn-height);
$btn-padding-x          : rem($btn-padding-x);
$btn-font-size          : rem($btn-font-size);

/* vertical rhythm
   ========================================================================== */

@mixin rhythm($font-size: $font-size-base, $rhythm: null, $minor: false, $unit-to: "rem") {
  @if $unit-to == "em" {
    font-size: em($font-size);
  } @else {
    font-size: rem($font-size);
  }

  @if $enable-rhythm or $rhythm {
    $custom: false;

    @if not $rhythm {
      $rhythm: $baseline;
    } @else {
      $custom: true;
    }
    line-height: line-height($font-size, $rhythm, $minor, $custom);
  }
}

// rhythm form
@mixin rhythm-form($font-size, $height, $padding-x, $field-fixed) {
  $font-size: rem($font-size);
  $height: rem($height);
  $line-height: line-height($font-size);
  $padding-x: em($padding-x, $font-size);
  $padding-y: em(($height - $font-size * $line-height) / 2, $font-size);

  @if $padding-y < 0 {
    $padding-y: 0;
  }

  @if $field-fixed {
    height: em($height, $font-size);
  }
  padding: $padding-y $padding-x;
  font-size: $font-size;
  line-height: $line-height;
}

// rhythm field
@mixin rhythm-field($font-size: $field-font-size, $height: $field-height, $padding-x: $field-padding-x) {
  @include rhythm-form($font-size, $height, $padding-x, true);
}

// rhythm check
@mixin rhythm-check($font-size: $label-font-size) {
  height: $font-size * line-height($font-size);
}

// rhythm label
@mixin rhythm-label($font-size: $label-font-size, $height: $field-height, $padding-x: 0) {
  @include rhythm-form($font-size, $height, $padding-x, false);
}

// rhythm btn
@mixin rhythm-btn($font-size: $btn-font-size, $height: $btn-height, $padding-x: $btn-padding-x) {
  @include rhythm-form($font-size, $height, $padding-x, false);
}

/* fonts
   ========================================================================== */

@mixin font($key, $minor: false, $unit-to: "rem") {
  @include rhythm(font-size($key), font-size($key, 2), $minor, $unit-to);
}

// responsive font
@mixin font-map($font-size, $minor, $unit-to) {
  @if type-of($font-size) == "list" {
    @include rhythm(nth($font-size, 1), nth($font-size, 2), $minor: $minor, $unit-to: $unit-to);
  } @else {
    @include rhythm($font-size, $minor: $minor, $unit-to: $unit-to);
  }
}

@mixin font-responsive($key, $minor: false, $unit-to: "rem") {
  @if map-has-key($responsive-font-sizes, $key) {
    $font-size: map-get($responsive-font-sizes, $key);

    @if type-of($font-size) == "map" {
      @each $font-size-key, $font-size-value in $font-size {
        @if $font-size-key == "default" {
          @include font-map($font-size-value, $minor, $unit-to);
        } @else {
          @media (max-width: bp($font-size-key)) {
            @include font-map($font-size-value, $minor, $unit-to);
          }
        }
      }
    } @else {
      @include font-map($font-size, $minor, $unit-to);
    }
  }
}

/* layouts
   ========================================================================== */

// container generator
@mixin container-generator($grid-offset-width) {
  $grid-offset-width: rem($grid-offset-width);

  .o-container {
    max-width: $container-width + $grid-offset-width * 2;
    padding-right: $grid-offset-width;
    padding-left: $grid-offset-width;
  }
}

@mixin container-width {
  @if $enable-custom-properties {
    .o-container {
      max-width: calc(var(--container-width) + var(--grid-offset-width) * 2);
      padding-right: var(--grid-offset-width);
      padding-left: var(--grid-offset-width);
    }
  } @else {
    @if type-of($grid-offset-width) == "map" {
      @each $grid-offset-width-key, $grid-offset-width-value in $grid-offset-width {
        @if $grid-offset-width-key == "default" {
          @include container-generator($grid-offset-width-value);
        } @else {
          @media (max-width: bp($grid-offset-width-key)) {
            @include container-generator($grid-offset-width-value);
          }
        }
      }
    } @else {
      @include container-generator($grid-offset-width);
    }
  }
}

// grid gutter generator
@mixin grid-gutter-generator($grid-gutter-width) {
  $grid-gutter-width: rem($grid-gutter-width);

  .o-grid {
    margin-bottom: -$grid-gutter-width;
    margin-left: -$grid-gutter-width;
  }

  .o-grid__col {
    padding-bottom: $grid-gutter-width;
    padding-left: $grid-gutter-width;
  }
}

@mixin grid-gutter-width {
  @if $enable-custom-properties {
    .o-grid {
      --grid-gutter-x: var(--grid-gutter-width);
      --grid-gutter-y: var(--grid-gutter-width);

      margin-bottom: calc(var(--grid-gutter-y) * -1);
      margin-left: calc(var(--grid-gutter-x) * -1);
    }

    .o-grid__col {
      padding-bottom: var(--grid-gutter-y);
      padding-left: var(--grid-gutter-x);
    }
  } @else {
    @if type-of($grid-gutter-width) == "map" {
      @each $grid-gutter-width-key, $grid-gutter-width-value in $grid-gutter-width {
        @if $grid-gutter-width-key == "default" {
          @include grid-gutter-generator($grid-gutter-width-value);
        } @else {
          @media (max-width: bp($grid-gutter-width-key)) {
            @include grid-gutter-generator($grid-gutter-width-value);
          }
        }
      }
    } @else {
      @include grid-gutter-generator($grid-gutter-width);
    }
  }
}

// grid columns generator
@mixin grid-columns($modifier: null) {
  @if $modifier {
    $modifier: "\\@#{$modifier}";
  }

  @for $i from 1 through $grid-columns {
    .o-grid--#{$i}#{$modifier} > .o-grid__col {
      width: calc(100% / #{$i});
    }

    .o-grid__col--#{$i}#{$modifier} {
      width: calc(#{$i} * 100% / #{$grid-columns});
    }

    .o-grid__col--offset-#{$i}#{$modifier} {
      margin-left: 100% * $i / $grid-columns;
    }
  }
}

/* utilities generator
   ========================================================================== */

// colors
@mixin colors($modifier: null) {
  @if $modifier {
    $modifier: "\\@#{$modifier}";
  }

  @each $color-name, $color-value in $colors {
    .u-color-#{$color-name}#{$modifier} {
      @if $enable-custom-properties {
        $color-value: var(--color-#{$color-name});
      }
      color: $color-value;
    }
  }
}

// font sizes
@mixin font-sizes($modifier: null) {
  @if $modifier {
    $modifier: "\\@#{$modifier}";
  }

  @each $font-size-name, $font-size-value in $font-sizes {
    .u-text-#{$font-size-name}#{$modifier} {
      @include rhythm(font-size($font-size-name), font-size($font-size-name, 2));
    }
  }
}

// font weights
@mixin font-weights($modifier: null) {
  @if $modifier {
    $modifier: "\\@#{$modifier}";
  }

  @each $font-weight-name, $font-weight-value in $font-weights {
    .u-text-#{$font-weight-name}#{$modifier} {
      font-weight: $font-weight-value;
    }
  }
}

// sizes
@mixin sizes($modifier: null) {
  @if $modifier {
    $modifier: "\\@#{$modifier}";
  }

  @each $size-name, $size-value in $sizes {
    .u-w-#{$size-name}#{$modifier} {
      width: $size-value;
    }
  }
}

// spacers
@mixin spacers($modifier: null) {
  @if $modifier {
    $modifier: "\\@#{$modifier}";
  }

  @each $spacer-name, $spacer-value in $spacers {
    $spacer-value: rem($spacer-value);

    .u-m-#{$spacer-name}#{$modifier} {
      margin: $spacer-value;
    }

    .u-mt-#{$spacer-name}#{$modifier} {
      margin-top: $spacer-value;
    }

    .u-mr-#{$spacer-name}#{$modifier} {
      margin-right: $spacer-value;
    }

    .u-mb-#{$spacer-name}#{$modifier} {
      margin-bottom: $spacer-value;
    }

    .u-ml-#{$spacer-name}#{$modifier} {
      margin-left: $spacer-value;
    }

    .u-p-#{$spacer-name}#{$modifier} {
      padding: $spacer-value;
    }

    .u-pt-#{$spacer-name}#{$modifier} {
      padding-top: $spacer-value;
    }

    .u-pr-#{$spacer-name}#{$modifier} {
      padding-right: $spacer-value;
    }

    .u-pb-#{$spacer-name}#{$modifier} {
      padding-bottom: $spacer-value;
    }

    .u-pl-#{$spacer-name}#{$modifier} {
      padding-left: $spacer-value;
    }
  }

  .u-p#{$modifier} {
    margin-top: spacer(md);

    &:first-child {
      margin-top: 0;
    }
  }

  .u-m-auto#{$modifier} {
    margin: auto;
  }

  .u-mt-auto#{$modifier} {
    margin-top: auto;
  }

  .u-mr-auto#{$modifier} {
    margin-right: auto;
  }

  .u-mb-auto#{$modifier} {
    margin-bottom: auto;
  }

  .u-ml-auto#{$modifier} {
    margin-left: auto;
  }

  .u-mx-auto#{$modifier} {
    margin-right: auto;
    margin-left: auto;
  }

  .u-my-auto#{$modifier} {
    margin-top: auto;
    margin-bottom: auto;
  }
}

// display
@mixin display($modifier: null) {
  @if $modifier {
    $modifier: "\\@#{$modifier}";
  }

  .u-block#{$modifier} {
    display: block;
  }

  .u-none#{$modifier} {
    display: none;
  }

  .u-inline#{$modifier} {
    display: inline;
  }

  .u-inline-block#{$modifier} {
    display: inline-block;
    vertical-align: top;
  }
}

// flex
@mixin flex($modifier: null) {
  @if $modifier {
    $modifier: "\\@#{$modifier}";
  }

  .u-flex#{$modifier} {
    display: flex;
  }

  .u-inline-flex#{$modifier} {
    display: inline-flex;
  }

  .u-flex-nowrap#{$modifier} {
    flex-wrap: nowrap;
  }

  .u-flex-wrap#{$modifier} {
    flex-wrap: wrap;
  }

  .u-flex-wrap-reverse#{$modifier} {
    flex-wrap: wrap-reverse;
  }

  .u-flex-row#{$modifier} {
    flex-direction: row;
  }

  .u-flex-row-reverse#{$modifier} {
    flex-direction: row-reverse;
  }

  .u-flex-column#{$modifier} {
    flex-direction: column;
  }

  .u-flex-column-reverse#{$modifier} {
    flex-direction: column-reverse;
  }

  .u-flex-main-start#{$modifier} {
    justify-content: flex-start;
  }

  .u-flex-main-end#{$modifier} {
    justify-content: flex-end;
  }

  .u-flex-main-center#{$modifier} {
    justify-content: center;
  }

  .u-flex-main-between#{$modifier} {
    justify-content: space-between;
  }

  .u-flex-main-around#{$modifier} {
    justify-content: space-around;
  }

  .u-flex-cross-start#{$modifier} {
    align-items: flex-start;
  }

  .u-flex-cross-end#{$modifier} {
    align-items: flex-end;
  }

  .u-flex-cross-center#{$modifier} {
    align-items: center;
  }

  .u-flex-cross-baseline#{$modifier} {
    align-items: baseline;
  }

  .u-flex-cross-stretch#{$modifier} {
    align-items: stretch;
  }

  .u-flex-self-start#{$modifier} {
    align-self: flex-start;
  }

  .u-flex-self-end#{$modifier} {
    align-self: flex-end;
  }

  .u-flex-self-center#{$modifier} {
    align-self: center;
  }

  .u-flex-self-baseline#{$modifier} {
    align-self: baseline;
  }

  .u-flex-self-stretch#{$modifier} {
    align-self: stretch;
  }

  .u-flex-item-fluid#{$modifier} {
    flex: 1;
  }

  .u-flex-item-auto#{$modifier} {
    flex: auto;
  }

  .u-flex-item-initial#{$modifier} {
    flex: initial;
  }

  .u-flex-item-none#{$modifier} {
    flex: none;
  }

  .u-flex-item-first#{$modifier} {
    order: -1;
  }

  .u-flex-item-medium#{$modifier} {
    order: 0;
  }

  .u-flex-item-last#{$modifier} {
    order: 1;
  }
}

// columns
@mixin columns($modifier: null) {
  @if $modifier {
    $modifier: "\\@#{$modifier}";
  }

  .u-col#{$modifier} {
    column-gap: $grid-gutter-width;
  }

  @for $i from 1 through $grid-columns {
    .u-col-#{$i}#{$modifier} {
      column-count: $i;
    }
  }

  .u-col-item#{$modifier} {
    break-inside: avoid;
  }
}

// float
@mixin float($modifier: null) {
  @if $modifier {
    $modifier: "\\@#{$modifier}";
  }

  .u-float-right#{$modifier} {
    float: right;
  }

  .u-float-left#{$modifier} {
    float: left;
  }

  .u-float-none#{$modifier} {
    float: none;
  }
}

// clearfix
@mixin clearfix($modifier: null) {
  @if $modifier {
    $modifier: "\\@#{$modifier}";
  }

  .u-clear#{$modifier} {
    clear: both;
  }

  .u-clearfix#{$modifier} {
    &::after {
      display: table;
      clear: both;
      border-collapse: collapse;
      content: "";
    }
  }

  .u-mod#{$modifier} {
    overflow: hidden;
  }
}

// text
@mixin text($modifier: null) {
  @if $modifier {
    $modifier: "\\@#{$modifier}";
  }

  .u-text-right#{$modifier} {
    text-align: right;
  }

  .u-text-center#{$modifier} {
    text-align: center;
  }

  .u-text-left#{$modifier} {
    text-align: left;
  }

  .u-text-lowercase#{$modifier} {
    text-transform: lowercase;
  }

  .u-text-uppercase#{$modifier} {
    text-transform: uppercase;
  }

  .u-text-capitalize#{$modifier} {
    text-transform: capitalize;
  }
}

// a11y
@mixin a11y($modifier: null) {
  @if $modifier {
    $modifier: "\\@#{$modifier}";
  }

  .u-visually-hidden#{$modifier} {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    white-space: nowrap;
    border: 0;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
  }
}

// unstyled
@mixin unstyled($modifier: null) {
  @if $modifier {
    $modifier: "\\@#{$modifier}";
  }

  .u-list-unstyled#{$modifier} {
    padding-left: 0;
    list-style: none;
  }

  .u-link-unstyled#{$modifier} {
    color: inherit;
    text-decoration: none;

    &:focus,
    &:hover,
    &:active {
      text-decoration: none;
    }
  }

  .u-btn-unstyled#{$modifier} {
    padding: 0;
    background: none;
    border: 0;
    cursor: pointer;
  }
}

/* responsive component generator
   ========================================================================== */

@mixin components($component, $bp-name) {
  @if $component == "grid-columns" {
    @include grid-columns($bp-name);
  }

  @if $component == "colors" {
    @include colors($bp-name);
  }

  @if $component == "font-sizes" {
    @include font-sizes($bp-name);
  }

  @if $component == "font-weights" {
    @include font-weights($bp-name);
  }

  @if $component == "sizes" {
    @include sizes($bp-name);
  }

  @if $component == "spacers" {
    @include spacers($bp-name);
  }

  @if $component == "display" {
    @include display($bp-name);
  }

  @if $component == "flex" {
    @include flex($bp-name);
  }

  @if $component == "columns" {
    @include columns($bp-name);
  }

  @if $component == "float" {
    @include float($bp-name);
  }

  @if $component == "clearfix" {
    @include clearfix($bp-name);
  }

  @if $component == "text" {
    @include text($bp-name);
  }

  @if $component == "a11y" {
    @include a11y($bp-name);
  }

  @if $component == "unstyled" {
    @include unstyled($bp-name);
  }
}

@mixin responsive($component) {
  $bp-name-sup: null;
  $bp-value-sup: null;
  $bp-context: 16px;

  @each $bp-name, $bp-value in $breakpoints {
    @if index($breakpoints, ($bp-name $bp-value)) == 1 {
      @media (min-width: $bp-value + em(1px, $bp-context)) {
        @include components($component, "#{$bp-name}-plus");
      }
    }

    @if index($breakpoints, ($bp-name $bp-value)) != 1 {
      @media (min-width: $bp-value + em(1px, $bp-context)) and (max-width: $bp-value-sup) {
        @include components($component, $bp-name-sup);
      }
    }

    @if index($breakpoints, ($bp-name $bp-value)) == length($breakpoints) {
      @media (max-width: $bp-value) {
        @include components($component, $bp-name);
      }
    }

    $bp-name-sup: $bp-name;
    $bp-value-sup: $bp-value;
  }
}
