<commit_before>// -----------------------------------------------------------------------------
// Copyright (c) 2016 <NAME> (https://github.com/NicolasGraph)
// Distributed under the MIT licence (https://opensource.org/licenses/MIT).
// -----------------------------------------------------------------------------
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// -----------------------------------------------------------------------------
// 1. Settings
// 2. CSS base
// 3. Variables
// 4. Mixins
// 4.1 bpt
// 4.1 this
// 4.2 children
// 5. Functions
// 5.1 this
// 5.2 spacing
// 5.3 spacing-val
// 5.4 position
// 5.5 bpts
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// 1. Settings
// -----------------------------------------------------------------------------

$settings: (
    "s": (                           // Each key is used as a bpt.
        "content-max-width" : 480px, // Max-width to optionally apply to containers.
        "vertical-spacing"  : 12px,  // Top and bottom margins/paddings.
        "horizontal-spacing": 8px    // Right and left margins/paddings.
    ),
    "m": (
        "device-min-width"  : 640px, // Media-query min-width.
        "content-max-width" : 800px,
        "vertical-spacing"  : 16px,
        "horizontal-spacing": 12px
    ),
    "l": (
        "device-min-width"  : 1024px,
        "content-max-width" : 1000px,
        "vertical-spacing"  : 24px,
        "horizontal-spacing": 16px
    ),
    "xl": (
        "device-min-width"  : 1440px,
        "content-max-width" : 1280px,
        "vertical-spacing"  : 32px,
        "horizontal-spacing": 24px
    )
);

// -----------------------------------------------------------------------------
// 2. CSS base
// -----------------------------------------------------------------------------

html { box-sizing: border-box; }

html * { box-sizing: inherit; }

// -----------------------------------------------------------------------------
// 3. Variables
// -----------------------------------------------------------------------------

$bpts: map-keys($settings);

// -----------------------------------------------------------------------------
// 4. Mixins
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// 4.1 bpt
// -----------------------------------------------------------------------------
// Generate a media-query.
// @param    $min             Breakpoint as a $settings key or a CSS value;
// @param    $max             Breakpoint as a $settings key or a CSS value.
// @see      @mixin this()
// -----------------------------------------------------------------------------
@mixin bpt($min: null, $max: null) {
    $media-query: null;

    @if $min {
        // If $min is a $settings key; get the related value if it exists.
        @if map-has-key($settings, $min) {
            $min-settings: map-get($settings, $min);
            @if map-has-key($min-settings, "device-min-width") {
                $min: map-get($min-settings, "device-min-width");
            } @else {
                $min: null;
            }
        }
        // Set the media-query min-width if defined.
        $media-query: if($min, "(min-width: #{$min})", null);
    }

    @if $max {
        // If $max is a $settings key; get the related val.
        @if map-has-key($settings, $max) {
            $max-settings: map-get($settings, $max);
            $max: map-get($max-settings, "device-min-width") - 1;
        }
        // Add or set the media-query max-width.
        @if $min {
            $media-query: $media-query " and (max-width: #{$max})";
        } @else {
            $media-query: "(max-width: #{$max})";
        }
    }

    // Generate the CSS media-query if it exists.
    @if $media-query {
        @media screen and #{$media-query} {
            @content;
        }
    } @else {
        @content;
    }
}

// -----------------------------------------------------------------------------
// 4.2 this
// -----------------------------------------------------------------------------
// Generate a responsive this.
// @param    $media    Breakpoint(s) used as media-query min-width and/or max-width;
// @param    $flow     "flex-row" or "flex-grid";
// @param    $width    Fraction/factor of the container width,
//                     "max-width" can also be used to generate a width of 100%
//                     following by a responsive max-width as provided in $settings.
// @param    $gutter   ;
// @param    $position "pull", "push", "center" or a fraction/factor of the container width;
// @param    $padding  ;
// -----------------------------------------------------------------------------
@mixin this($media: null, $flow: null, $width: null, $gutter: null, $position: null, $padding: null) {

    // List in use breakpoints from $media.
    $min-bpt: null;
    $max-bpt: null;

    @if $media {
        $min-bpt: if(nth($media, 1), nth($media, 1), null);
        $max-bpt: if(type-of($media) == list, nth($media, 2), null);
    }

    $bpts: bpts($min-bpt, $max-bpt);

    $css: ();
    $first: true;

    @each $bpt in $bpts {
        // Get CSS properties and their values.
        $bpt-css: this($bpt, $flow, $width, $gutter, $position, $padding);
        // Remove useless repeated values.
        @each $bpt-prop, $bpt-val in $bpt-css {
            @each $stored-bpt, $stored-css in $css {
                @if map-has-key($stored-css, $bpt-prop) {
                    @if map-get($stored-css, $bpt-prop) == $bpt-val {
                        $bpt-css: map-remove($bpt-css, $bpt-prop);
                    } @else {
                        $bpt-css: map-merge($bpt-css, ($bpt-prop: $bpt-val));
                    }
                }
            }
        }
        // Store CSS properties and their values.
        $css: map-merge($css, ($bpt: $bpt-css));
    }
    // Generate CSS.
    @each $stored-bpt, $stored-css in $css {
        @if $stored-bpt == nth($bpts, 1) {
        @include bpt($stored-bpt, nth($bpts, length($bpts))) {
            @each $prop, $val in map-get($css, $stored-bpt) {
                #{$prop}: $val;
            }
                @content;
            }
        } @else {
            @include bpt($stored-bpt) {
                @each $prop, $val in map-get($css, $stored-bpt) {
                    #{$prop}: $val;
                }
            }
        }
    }
}

@function this($media: null, $flow: null, $width: null, $gutter: null, $position: null, $padding: null) {

    // Set a map to store the generated css properties and their vals.
    $css : ();

    // Get the media-query related vals.
    // ---------------------------------
    $min-settings: null;
    $min-width: null;
    $max-width: null;

    @if $media {
        @if nth($media, 1) {
            $min-settings: map-get($settings, nth($media, 1));
        } @else {
            $min-settings: map-get($settings, "s");
        }
    } @else {
        $min-settings: map-get($settings, "s");
    }

    // Set the display and flex-wrap properties from $flow.
    // ----------------------------------------------------
    @if $flow {
        $css: map-merge($css, (display: flex));
        @if $flow == "flex-grid" {
            $css: map-merge($css, (flex-wrap: wrap));
        }
    }

    // Set the margins properties from $gutter and $position.
    // ------------------------------------------------------
    $spacing-x: map-get($min-settings, "horizontal-spacing");
    $spacing-y: map-get($min-settings, "vertical-spacing");

    $css-margins: null;
    $css-positions: null;

    @if $gutter {
        // Make $gutter a four thiss list.
        @if type-of($gutter) == list {
            @if length($gutter) == 2 {
                $gutter: nth($gutter, 1) nth($gutter, 2) nth($gutter, 1) nth($gutter, 2);
            }
        } @else {
            $gutter: $gutter $gutter $gutter $gutter;
        }
        // Get a map of CSS margins.
        $css-margins: spacing($spacing-y, $spacing-x, $gutter);
        $css-positions: $css-margins;
        @if $position {
            // Alterate margins width $position.
            $css-positions: position($css-positions, $position);
        }
        // Use the margin shorthand or store each side value.
        @if map-has-key($css-positions, "global") {
            $css: map-merge($css, (margin: map-get($css-positions, "global")));
        } @else {
            @each $side, $val in $css-positions {
                $css: map-merge($css, (margin-#{$side}: $val));
            }
        }
    }

    // Set the paddings properties from $padding.
    // ------------------------------------------
    @if $padding {
        $css-paddings: null;
        // Make $padding a four thiss list.
        @if type-of($padding) == list {
            @if length($padding) == 2 {
                $padding: nth($padding, 1) nth($padding, 2) nth($padding, 1) nth($padding, 2);
            }
        } @else {
            $padding: $padding $padding $padding $padding;
        }
        // Get a map of CSS paddings.
        $css-paddings: spacing($spacing-y, $spacing-x, $padding);
        // Use the padding shorthand or store each side value.
        @if map-has-key($css-paddings, "global") {
            $css: map-merge($css, (padding: map-get($css-paddings, "global")));
        } @else {
            @each $side, $val in $css-paddings {
                $css: map-merge($css, (padding-#{$side}: $val));
            }
        }
    }

    // Set the width and max-width properties from $width and $gutter.
    // ---------------------------------------------------------------
    @if $width {
        // Set the margin val to soustract from the width.
        $gutter-factor: null;
        @if $gutter {
            @if map-get($css-margins, "right") and map-get($css-margins, "right") != 0 {
                $gutter-factor: map-get($css-margins, "right");
            }
            @if map-get($css-margins, "left") and map-get($css-margins, "left") != 0 {
                @if $gutter-factor {
                    $gutter-factor: $gutter-factor + map-get($css-margins, "left");
                } @else {
                    $gutter-factor: map-get($css-margins, "left");
                }
            }
        }

        // Set the max-width val.
        // ----------------------
        $content-max-width: null;
        $val: null;
        @if $width == "max-width" {
            $val: 100%;
            $content-max-width: map-get($min-settings, "content-max-width");
        } @else {
            $val: $width * 100%;
        }

        $css: map-merge($css, (width: if($gutter-factor, calc(#{$val} - #{$gutter-factor}), #{$val})));
        $css: map-merge($css, (max-width: $content-max-width));
    }

    @return $css;
}

// -----------------------------------------------------------------------------
// 4.3 children
// -----------------------------------------------------------------------------
// Generate a media-query.
// @param    $min-width    A $settings key or a CSS min-width val;
// @param    …    A $settings key or a CSS max-width val;
// -----------------------------------------------------------------------------
@mixin children($media: null, $flow: null, $widths: null, $gutter: null, $position: null, $padding: null) {

    // Extract the repeat scheme.
    // --------------------------
    $repeat: null;
    $valid-widths: null;

    @each $width in $widths {
        @if type-of($width) == string {
            $repeat: $width;
        } @else {
            $valid-widths: if($valid-widths, append($valid-widths, $width), $width);
        }
    }
    $widths: $valid-widths;

    // Iterate over $widths.
    // ---------------------
    $thiss: length($widths);

    @for $this from 1 through $thiss {
        // Define the default targeted child.
        $child: #{$thiss}n+#{$this};
        @if $repeat == "no-repeat" {
            $child: #{$this};
        } @else if $repeat == "repeat-last" {
            $child: if($this != $thiss, #{$this}, n+#{$this});
        }

        > :nth-child(#{$child}) {
            @include this($media, $flow, nth($widths, $this), $gutter, $position, $padding) {
                @content;
            }
        }
    }
}

// -----------------------------------------------------------------------------
// 5. Functions
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// 5.1 spacing
// -----------------------------------------------------------------------------
// Return a map of spacing vals from the $spacing mixin argument
// to be used as margins and/or paddings.
// @param     $base-y   The default val for vertival spacings;
// @param     $base-x   The default val for horizontal spacings;
// @param     $val     Mixin argument;
// @return    $vals    Map of spacing vals:
//                         $vals: (
//                             "global": …, <- optional key for shorthand
//                             "top": …,
//                             "right": …,
//                             "bottom": …,
//                             "left": …
//                          );
// @see       _mixins.scss.
// -----------------------------------------------------------------------------
@function spacing($base-y, $base-x, $spacing: null) {

    // Shorten $spacing list if possible.
    // ----------------------------------
    @if type-of($spacing) == list {
        @if length($spacing) == 4 {
            @if nth($spacing, 1) == nth($spacing, 3) and nth($spacing, 2) == nth($spacing, 4)  {
                @if nth($spacing, 1) == nth($spacing, 2) {
                    $spacing: nth($spacing, 1);
                } @else {
                    $spacing: nth($spacing, 1) nth($spacing, 2);
                }
            }
        }
        @if length($spacing) == 2 {
            @if not nth($spacing, 1) or not nth($spacing, 2) {
            // A list of two vals can't be used as is if one of the val is false.
                $spacing: nth($spacing, 1) nth($spacing, 2) nth($spacing, 1) nth($spacing, 2);
            }
        }
    }

    $sides: "top", "right", "bottom", "left";
    $spacings: ();
    $new-spacings: ();

    // Iterate over $spacing vals.
    // ---------------------------
    @for $index from 1 through length($spacing) {
        $val: nth($spacing, $index);

        @if $val != false {

            // Get the CSS $spacing-val.
            $base: if($index == 1 or $index == 3, $base-y, $base-x);
            $spacing-val: spacing-val($base, $val);

            // Build the map.
            @if type-of($spacing) == list {

                @if length($spacing) == 2 {
                    $global: null;
                    @if not map-has-key($spacings, "global") {
                        // Set the first shorthand val…
                        $global: $spacing-val;
                    } @else {
                        // …or append the second shorthand val.
                        $global: map-get($spacings, "global");
                        @if $global == $spacing-val {
                            $global: $spacing-val;
                        } @else {
                            $global: $global $spacing-val;
                        }
                    }
                    $new-spacings: (
                        #{nth($sides, $index)}: $spacing-val,
                        #{nth($sides, $index + 2)}: $spacing-val,
                        "global": $global
                    );
                } @else {
                    $new-spacings: (
                        #{nth($sides, $index)}: $spacing-val
                    );
                }
                // Merge existing vals with new ones.
                $spacings: map-merge($spacings, $new-spacings);

            } @else {
                @each $side in $sides {
                    $base: if($side == "top" or $side == "bottom", $base-y, $base-x);
                    $val-y: spacing-val($base-y, $val);
                    $val-x: spacing-val($base-x, $val);
                    $global: if($val-y == $val-x, $val-y, $val-y $val-x);
                    $new-spacings: (
                        #{$side}: spacing-val($base, $val),
                        "global": $global
                    );
                    // Merge existing vals with new ones.
                    $spacings: map-merge($spacings, $new-spacings);
                }
            }
        }
    }

    @return $spacings;
}

// -----------------------------------------------------------------------------
// 5.2 spacing-val
// -----------------------------------------------------------------------------
// Return a css val from a $spacing mixin argument
// val to be used as a margin and/or padding value.
// @param     $base                  A CSS value used as a calculation base;
// @param     $val                   A $spacing value;
// @return    $spacing               A CSS margin/padding value.
// @see       @function spacing()
// -----------------------------------------------------------------------------
@function spacing-val($base: null, $val: null) {
    $spacing: null;

    @if $val == true {
        // Use the $base val.
        $spacing: $base;
    } @else if $val == "nested" {
        // Use $base as a negative val.
        $spacing: (-$base);
    } @else if type-of($val) == number and unitless($val) {
        // Use a factor to multiply the $base val.
        $spacing: if($val == 0, $val, $val * $base);
    } @else {
        // Ignore $base; use a custom spacing val.
        $spacing: $val;
    }

    @return $spacing;
}

// -----------------------------------------------------------------------------
// 5.3 position
// -----------------------------------------------------------------------------
// Atlterate margins depending of the $position value.
// @param     $spacings           Map returned by spacing(),
// @param     $position           Mixin argument
// @return    $spacings           Alterated map
// @see       @function this()
// -----------------------------------------------------------------------------
@function position($spacings, $position) {
    $position-side: null;
    $val: null;
    $new-spacings: null;

    @if type-of($position) == number {
    // $position is a number; use it to alterate the left margin.

        // Prepare $position to be added, or soustracted if negative.
        $operator: if($position == abs($position), "+", "-");
        $position: percentage(abs($position));
        $position-side: "left";
        $gutter: map-get($spacings, "left");

        @if $gutter and $gutter != 0 {
            $val: calc(#{$gutter} #{$operator} #{$position});
        } @else {
            $val: #{$operator}$position;
        }

    } @else {
    // $position is not a number; use 'auto' to push, pull or center.
        @if $position == "pull" {
            $position-side: "right";
        } @else if $position == "push" {
            $position-side: "left";
        } @else if $position == "center" {
            $position-side: "right" "left";
        }
        $val: auto;
    }

    @each $side in $position-side {
        $new-spacings: (#{$side}: #{$val});
        $spacings: map-remove($spacings, $side);
        $spacings: map-merge($spacings, $new-spacings);
    }

    @if map-has-key($spacings, "global") {
        // Remove the global spacing val(s).
        $global: map-get($spacings, "global");
        $spacings: map-remove($spacings, "global");
        @if $position == "center" {
            // Reset the global $spacings key using 'auto' for right and left margins.
            @if type-of($global) == list {
                $new-spacings: ("global": nth($global, 1) #{$val});
            } @else {
                $new-spacings: ("global": #{$val});
            }
            $spacings: map-merge($spacings, $new-spacings);
        }
    }

    @return $spacings;
}

// -----------------------------------------------------------------------------
// 5.4 bpts
// -----------------------------------------------------------------------------
// Get a list of breakpoints explicitly or implicitly set in the this mixin.
// @param     $from            $settings key used as the media-query min-width;
// @param     $to              $settings key used as the media-query max-width;
// @return    $missing-bpts    A list of breakpoints as $settings map keys.
// @see       @mixin this()
// -----------------------------------------------------------------------------
@function bpts($from: null, $to: null) {
    // Get the position of $from as a $settings key or start from the first one.
    $from-index: if($from, index($bpts, $from), 1);
    // Get the position of $to as a $settings key or stop at the last one.
    $to-index: if($to, index($bpts, $to) - 1, length($bpts));

    // List breakpoints from $from to $to.
    // -----------------------------------
    $missing-bpts: null;
    @if $to-index - $from-index >= 0 {
        @for $index from $from-index through $to-index {
            $bpt: nth($bpts, $index);
            @if $missing-bpts {
                $missing-bpts: append($missing-bpts, $bpt);
            } @else {
                $missing-bpts: $bpt;
            }
        }
    }

    @return $missing-bpts;
}<commit_msg>Backup<commit_after>// -----------------------------------------------------------------------------
// Copyright (c) 2016 <NAME> (https://github.com/NicolasGraph)
// Distributed under the MIT licence (https://opensource.org/licenses/MIT).
// -----------------------------------------------------------------------------
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// -----------------------------------------------------------------------------
// 1. Settings
// 2. CSS base
// 3. Variables
// 4. Mixins
// 4.1 bpt
// 4.1 this
// 4.2 children
// 5. Functions
// 5.1 this
// 5.2 spacing
// 5.3 spacing-val
// 5.4 position
// 5.5 bpts
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// 1. Settings
// -----------------------------------------------------------------------------

$settings: (
    "s": (                           // Each key is used as a custom breakpoint.
        "content-max-width" : 480px, // Max-width to optionally apply to containers.
        "vertical-spacing"  : 12px,  // Top and bottom margins/paddings.
        "horizontal-spacing": 8px    // Right and left margins/paddings.
    ),
    "m": (
        "device-min-width"  : 640px, // Media-query min-width.
        "content-max-width" : 800px,
        "vertical-spacing"  : 16px,
        "horizontal-spacing": 12px
    ),
    "l": (
        "device-min-width"  : 1024px,
        "content-max-width" : 1000px,
        "vertical-spacing"  : 24px,
        "horizontal-spacing": 16px
    ),
    "xl": (
        "device-min-width"  : 1440px,
        "content-max-width" : 1280px,
        "vertical-spacing"  : 32px,
        "horizontal-spacing": 24px
    )
);

// -----------------------------------------------------------------------------
// 2. CSS base
// -----------------------------------------------------------------------------

html { box-sizing: border-box; }

html * { box-sizing: inherit; }

// -----------------------------------------------------------------------------
// 3. Variables
// -----------------------------------------------------------------------------

$bpts: map-keys($settings);

// -----------------------------------------------------------------------------
// 4. Mixins
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// 4.1 bpt
// -----------------------------------------------------------------------------
// Generate a media-query.
// @param    $min             Breakpoint as a $settings key or a CSS value;
// @param    $max             Breakpoint as a $settings key or a CSS value.
// @see      @mixin this()
// -----------------------------------------------------------------------------
@mixin bpt($min: null, $max: null) {
    $media-query: null;

    @if $min {
        // If $min is a $settings key; get the related value if it exists.
        @if map-has-key($settings, $min) {
            $min-settings: map-get($settings, $min);
            @if map-has-key($min-settings, "device-min-width") {
                $min: map-get($min-settings, "device-min-width");
            } @else {
                $min: null;
            }
        }
        // Set the media-query min-width if defined.
        $media-query: if($min, "(min-width: #{$min})", false);
    }

    @if $max {
        // If $max is a $settings key; get the related value.
        @if map-has-key($settings, $max) {
            $max-settings: map-get($settings, $max);
            $max: map-get($max-settings, "device-min-width") - 1;
        }
        // Add or set the media-query max-width.
        @if $min {
            $media-query: $media-query " and (max-width: #{$max})";
        } @else {
            $media-query: "(max-width: #{$max})";
        }
    }

    // Generate the CSS media-query if it exists.
    // ------------------------------------------
    @if $media-query {
        @media screen and #{$media-query} {
            @content;
        }
    } @else {
        @content;
    }
}

// -----------------------------------------------------------------------------
// 4.2 this
// -----------------------------------------------------------------------------
// Generate a responsive this.
// @param    $media    Breakpoint(s) used as media-query min-width and/or max-width;
// @param    $flow     "flex-row" or "flex-grid";
// @param    $width    Fraction/factor of the container width,
//                     "max-width" can also be used to generate a width of 100%
//                     following by a responsive max-width as provided in $settings.
// @param    $gutter   ;
// @param    $position "pull", "push", "center" or a fraction/factor of the container width;
// @param    $padding  ;
// -----------------------------------------------------------------------------
@mixin this($media: null, $flow: null, $width: null, $gutter: null, $position: null, $padding: null) {

    // List breakpoints explicitly or implicitly set.
    // ----------------------------------------------
    $min-bpt: if(nth($media, 1), nth($media, 1), false);
    $max-bpt: if(type-of($media) == list, nth($media, 2), false);
    $bpts: bpts($min-bpt, $max-bpt);

    // Store each breakpoint CSS properties and values in a map.
    // ---------------------------------------------------------
    $css: ();
    @each $bpt in $bpts {
        $bpt-css: this($bpt, $flow, $width, $gutter, $position, $padding);
        // Remove useless repeated values through media-queries.
        // -----------------------------------------------------
        @each $bpt-prop, $bpt-val in $bpt-css {
            @each $stored-bpt, $stored-css in $css {
                @if map-has-key($stored-css, $bpt-prop) {
                    @if map-get($stored-css, $bpt-prop) == $bpt-val {
                        $bpt-css: map-remove($bpt-css, $bpt-prop);
                    } @else {
                        $bpt-css: map-merge($bpt-css, ($bpt-prop: $bpt-val));
                    }
                }
            }
        }
        $css: map-merge($css, ($bpt: $bpt-css));
    }

    // Generate CSS.
    // -------------
    @each $stored-bpt, $stored-css in $css {
        @if $stored-bpt == nth($bpts, 1) {
            @include bpt($stored-bpt, nth($bpts, length($bpts))) {
                @each $prop, $val in map-get($css, $stored-bpt) {
                    #{$prop}: $val;
                }
                @content;
            }
        } @else {
            @include bpt($stored-bpt) {
                @each $prop, $val in map-get($css, $stored-bpt) {
                    #{$prop}: $val;
                }
            }
        }
    }
}

@function this($media: null, $flow: null, $width: null, $gutter: null, $position: null, $padding: null) {

    // Set a map to store the generated css properties and their vals.
    $css : ();

    // Get the media-query related vals.
    // ---------------------------------
    $min-settings: null;
    $min-width: null;
    $max-width: null;

    @if $media {
        @if nth($media, 1) {
            $min-settings: map-get($settings, nth($media, 1));
        } @else {
            $min-settings: map-get($settings, "s");
        }
    } @else {
        $min-settings: map-get($settings, "s");
    }

    // Set the display and flex-wrap properties from $flow.
    // ----------------------------------------------------
    @if $flow {
        $css: map-merge($css, (display: flex));
        @if $flow == "flex-grid" {
            $css: map-merge($css, (flex-wrap: wrap));
        }
    }

    // Set the margins properties from $gutter and $position.
    // ------------------------------------------------------
    $spacing-x: map-get($min-settings, "horizontal-spacing");
    $spacing-y: map-get($min-settings, "vertical-spacing");

    $css-margins: null;
    $css-positions: null;

    @if $gutter {
        // Get a map of CSS margins.
        $css-margins: spacing($spacing-y, $spacing-x, $gutter);
        $css-positions: $css-margins;
        @if $position {
            // Alterate margins width $position.
            $css-positions: position($css-positions, $position);
        }
        // Use the margin shorthand or store each side value.
        @if map-has-key($css-positions, "global") {
            $css: map-merge($css, (margin: map-get($css-positions, "global")));
        } @else {
            @each $side, $val in $css-positions {
                $css: map-merge($css, (margin-#{$side}: $val));
            }
        }
    }

    // Set the paddings properties from $padding.
    // ------------------------------------------
    @if $padding {
        // Get a map of CSS paddings.
        $css-paddings: spacing($spacing-y, $spacing-x, $padding);
        // Use the padding shorthand or store each side value.
        @if map-has-key($css-paddings, "global") {
            $css: map-merge($css, (padding: map-get($css-paddings, "global")));
        } @else {
            @each $side, $val in $css-paddings {
                $css: map-merge($css, (padding-#{$side}: $val));
            }
        }
    }

    // Set the width and max-width properties from $width and $gutter.
    // ---------------------------------------------------------------
    @if $width {
        // Set the margin val to soustract from the width.
        $gutter-factor: null;
        @if $gutter {
            $margin-right: map-get($css-margins, "right");
            @if $margin-right and $margin-right != 0 {
                $gutter-factor: $margin-right;
            }
            $margin-left: map-get($css-margins, "left");
            @if $margin-left and $margin-left != 0 {
                @if $gutter-factor {
                    $gutter-factor: $gutter-factor + $margin-left;
                } @else {
                    $gutter-factor: $margin-left;
                }
            }
        }

        // Set the width and max-width values.
        // -----------------------------------
        $css-width: null;
        $css-max-width: null;
        @if $width == "max-width" {
            $css-width: 100%;
            $css-max-width: map-get($min-settings, "content-max-width");
            $css: map-merge($css, (max-width: $css-max-width));
        } @else {
            $css-width: $width * 100%;
        }

        @if $gutter-factor {
            $css-width: calc(#{$css-width} - #{$gutter-factor});
        }

        $css: map-merge($css, (width: #{$css-width}));
    }

    @return $css;
}

// -----------------------------------------------------------------------------
// 4.3 children
// -----------------------------------------------------------------------------
// Generate a media-query.
// @param    $min-width    A $settings key or a CSS min-width val;
// @param    …             A $settings key or a CSS max-width val;
// -----------------------------------------------------------------------------
@mixin children($media: null, $flow: null, $widths: null, $gutter: null, $position: null, $padding: null) {

    // Extract the repeat scheme.
    // --------------------------
    $repeat: null;
    $valid-widths: null;

    @each $width in $widths {
        @if type-of($width) == string {
            $repeat: $width;
        } @else {
            $valid-widths: if($valid-widths, append($valid-widths, $width), $width);
        }
    }
    $widths: $valid-widths;

    // Iterate over $widths to call $this mixin on defined children.
    // -------------------------------------------------------------
    $thiss: length($widths);

    @for $this from 1 through $thiss {
        // Define the default targeted child.
        $child: #{$thiss}n+#{$this};
        @if $repeat == "no-repeat" {
            $child: #{$this};
        } @else if $repeat == "repeat-last" {
            $child: if($this != $thiss, #{$this}, n+#{$this});
        }

        > :nth-child(#{$child}) {
            @include this($media, $flow, nth($widths, $this), $gutter, $position, $padding) {
                @content;
            }
        }
    }
}

// -----------------------------------------------------------------------------
// 5. Functions
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// 5.1 spacing
// -----------------------------------------------------------------------------
// Return a map of spacing vals from the $spacing mixin argument
// to be used as margins and/or paddings.
// @param     $base-y   The default val for vertival spacings;
// @param     $base-x   The default val for horizontal spacings;
// @param     $val     Mixin argument;
// @return    $vals    Map of spacing vals:
//                         $vals: (
//                             "global": …, <- optional key for shorthand
//                             "top": …,
//                             "right": …,
//                             "bottom": …,
//                             "left": …
//                          );
// @see       _mixins.scss.
// -----------------------------------------------------------------------------
@function spacing($base-y, $base-x, $spacing: null) {

    // Shorten $spacing list if possible.
    // ----------------------------------
    @if type-of($spacing) == list {
        @if length($spacing) == 4 {
            @if nth($spacing, 1) == nth($spacing, 3) and nth($spacing, 2) == nth($spacing, 4)  {
                @if nth($spacing, 1) == nth($spacing, 2) {
                    $spacing: nth($spacing, 1);
                } @else {
                    $spacing: nth($spacing, 1) nth($spacing, 2);
                }
            }
        }
        @if length($spacing) == 2 {
            @if not nth($spacing, 1) or not nth($spacing, 2) {
            // A list of two vals can't be used as is if one of the val is false.
                $spacing: nth($spacing, 1) nth($spacing, 2) nth($spacing, 1) nth($spacing, 2);
            }
        }
    }

    $sides: "top", "right", "bottom", "left";
    $spacings: ();
    $new-spacings: ();

    // Iterate over $spacing vals.
    // ---------------------------
    @for $i from 1 through length($spacing) {
        $val: nth($spacing, $i);

        @if $val != false {

            // Get the CSS $spacing-val.
            $base: if($i == 1 or $i == 3, $base-y, $base-x);
            $spacing-val: spacing-val($base, $val);

            // Build the map.
            @if type-of($spacing) == list {
                @if length($spacing) == 2 {
                    $global: null;
                    @if not map-has-key($spacings, "global") {
                        // Set the first shorthand val…
                        $global: $spacing-val;
                    } @else {
                        // …or append the second shorthand val.
                        $global: map-get($spacings, "global");
                        @if $global == $spacing-val {
                            $global: $spacing-val;
                        } @else {
                            $global: $global $spacing-val;
                        }
                    }
                    $new-spacings: (
                        #{nth($sides, $i)}: $spacing-val,
                        #{nth($sides, $i + 2)}: $spacing-val,
                        "global": $global
                    );
                } @else {
                    $new-spacings: (
                        #{nth($sides, $i)}: $spacing-val
                    );
                }
                // Merge existing vals with new ones.
                $spacings: map-merge($spacings, $new-spacings);
            } @else {
                @each $side in $sides {
                    $base: if($side == "top" or $side == "bottom", $base-y, $base-x);
                    $val-y: spacing-val($base-y, $val);
                    $val-x: spacing-val($base-x, $val);
                    $global: if($val-y == $val-x, $val-y, $val-y $val-x);
                    $new-spacings: (
                        #{$side}: spacing-val($base, $val),
                        "global": $global
                    );
                    // Merge existing vals with new ones.
                    $spacings: map-merge($spacings, $new-spacings);
                }
            }
        }
    }

    @return $spacings;
}

// -----------------------------------------------------------------------------
// 5.2 spacing-val
// -----------------------------------------------------------------------------
// Return a css val from a $spacing mixin argument
// val to be used as a margin and/or padding value.
// @param     $base                  A CSS value used as a calculation base;
// @param     $val                   A $spacing value;
// @return    $spacing               A CSS margin/padding value.
// @see       @function spacing()
// -----------------------------------------------------------------------------
@function spacing-val($base: null, $val: null) {
    $spacing: null;

    @if $val == true {
        // Use the $base val.
        $spacing: $base;
    } @else if $val == "nested" {
        // Use $base as a negative val.
        $spacing: (-$base);
    } @else if type-of($val) == number and unitless($val) {
        // Use a factor to multiply the $base val.
        $spacing: if($val == 0, $val, $val * $base);
    } @else {
        // Ignore $base; use a custom spacing val.
        $spacing: $val;
    }

    @return $spacing;
}

// -----------------------------------------------------------------------------
// 5.3 position
// -----------------------------------------------------------------------------
// Atlterate margins depending of the $position value.
// @param     $spacings           Map returned by spacing(),
// @param     $position           Mixin argument
// @return    $spacings           Alterated map
// @see       @function this()
// -----------------------------------------------------------------------------
@function position($margins, $position) {
    $side: null;
    $val: null;
    $new-margins: null;

    // $position is a number; use it to alterate the left margin,
    // else, use 'auto' to push, pull or center.
    // ----------------------------------------------------------
    @if type-of($position) == number {
        // Prepare $position to be added, or soustracted if negative.
        $operator: if($position == abs($position), "+", "-");
        $position: percentage(abs($position));
        $side: "left";
        $gutter: map-get($margins, "left");
        @if $gutter and $gutter != 0 {
            $val: calc(#{$gutter} #{$operator} #{$position});
        } @else {
            $val: #{$operator}$position;
        }
    } @else {
        @if $position == "pull" {
            $side: "right";
        } @else if $position == "push" {
            $side: "left";
        } @else if $position == "center" {
            $side: "right" "left";
        }
        $val: auto;
    }

    @each $s in $side {
        $new-margins: (#{$side}: #{$val});
        $margins: map-remove($margins, $side);
        $margins: map-merge($margins, $new-margins);
    }

    @if map-has-key($margins, "global") {
        // Remove the global margin value(s).
        $global: map-get($margins, "global");
        $margins: map-remove($margins, "global");
        @if $position == "center" {
            // Reset the global $spacings key using 'auto' for right and left margins.
            @if type-of($global) == list {
                $new-margins: ("global": nth($global, 1) #{$val});
            } @else {
                $new-margins: ("global": #{$val});
            }
            $margins: map-merge($margins, $new-margins);
        }
    }

    @return $margins;
}

// -----------------------------------------------------------------------------
// 5.4 bpts
// -----------------------------------------------------------------------------
// Get a list of breakpoints explicitly or implicitly set in the this mixin.
// @param     $from            $settings key used as the media-query min-width;
// @param     $to              $settings key used as the media-query max-width;
// @return    $bpts-set    A list of breakpoints as $settings map keys.
// @see       @mixin this()
// -----------------------------------------------------------------------------
@function bpts($from: null, $to: null) {
    // Get the position of $from as a $settings key or start from the first one.
    $from: if($from, index($bpts, $from), 1);
    // Get the position of $to as a $settings key or stop at the last one.
    $to: if($to, index($bpts, $to) - 1, length($bpts));

    // List breakpoints from $from to $to.
    // -----------------------------------
    $bpts-set: null;
    @if $to - $from >= 0 {
        @for $i from $from through $to {
            $bpt: nth($bpts, $i);
            @if $bpts-set {
                $bpts-set: append($bpts-set, $bpt);
            } @else {
                $bpts-set: $bpt;
            }
        }
    }

    @return $bpts-set;
}
{'fraction_non_alphanumeric': 0.28564865858140387, 'fraction_numerical': 0.006247703050349137, 'mean_word_length': 1.0644411778652378, 'pattern_counts': {'":': 34, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1300525', 'n_tokens_mistral': 12435, 'n_tokens_neox': 11684, 'n_words': 3225}