$screens: (
    base: 0px,
    xs: 390px,
    sm: 600px,
    md: 768px,
    lg: 1024px,
    xl: 1280px,
    2xl: 1536px,
);

$layoutProperties: (
    position,
    overflow,
    overflow-x,
    overflow-y,
    top,
    right,
    bottom,
    left,
    margin,
    margin-x,
    margin-y,
    margin-left,
    margin-right,
    margin-top,
    margin-bottom,
    padding,
    padding-x,
    padding-y,
    padding-left,
    padding-right,
    padding-top,
    padding-bottom,
    width,
    min-width,
    max-width,
    height,
    min-height,
    max-height
);

@mixin responsive-properties($additional-properties: ()) {
    @each $property in $additional-properties {
        --#{$property}-computed: var(/* Value defined by the component, e.g. --display */ --#{$property});
    }

    $previous-breakpoint: null;

    @each $breakpoint, $min-width in $screens {
        @if $breakpoint == base {
            @include __properties($breakpoint, $previous-breakpoint, $additional-properties);
        } @else {
            @media (min-width: $min-width) {
                @include __properties($breakpoint, $previous-breakpoint, $additional-properties);
            }
        }

        $previous-breakpoint: $breakpoint;
    }
}

@mixin __properties($breakpoint, $previous-breakpoint, $additional-properties: ()) {
    & {
        @each $property in $additional-properties {
            @if ($previous-breakpoint == null) {
                --#{$breakpoint}-#{$property}-computed: var(
                    /* Value defined by the component, e.g. --xs-display */ --#{$breakpoint}-#{$property},
                    var(--#{$property}-computed)
                );
            } @else {
                --#{$breakpoint}-#{$property}-computed: var(
                    --#{$breakpoint}-#{$property},
                    var(--#{$previous-breakpoint}-#{$property}-computed)
                );
            }
        }

        @if (index($additional-properties, 'position')) {
            position: var(--#{$breakpoint}-position-computed);
        }

        @if (index($additional-properties, 'overflow')) {
            overflow: var(--#{$breakpoint}-overflow-computed);
        }
        @if (index($additional-properties, 'overflow-x')) {
            overflow-x: var(--#{$breakpoint}-overflow-x-computed);
        }
        @if (index($additional-properties, 'overflow-y')) {
            overflow-y: var(--#{$breakpoint}-overflow-y-computed);
        }

        @if (index($additional-properties, 'top')) {
            top: var(--#{$breakpoint}-top-computed);
        }
        @if (index($additional-properties, 'right')) {
            right: var(--#{$breakpoint}-right-computed);
        }
        @if (index($additional-properties, 'bottom')) {
            bottom: var(--#{$breakpoint}-bottom-computed);
        }
        @if (index($additional-properties, 'left')) {
            left: var(--#{$breakpoint}-left-computed);
        }

        @if (index($additional-properties, 'margin')) {
            margin: var(--#{$breakpoint}-margin-computed);
        }
        @if (index($additional-properties, 'margin-left')) {
            margin-left: var(
                --#{$breakpoint}-margin-left-computed,
                var(--#{$breakpoint}-margin-x-computed, var(--#{$breakpoint}-margin-computed))
            );
        }
        @if (index($additional-properties, 'margin-right')) {
            margin-right: var(
                --#{$breakpoint}-margin-right-computed,
                var(--#{$breakpoint}-margin-x-computed, var(--#{$breakpoint}-margin-computed))
            );
        }
        @if (index($additional-properties, 'margin-top')) {
            margin-top: var(
                --#{$breakpoint}-margin-top-computed,
                var(--#{$breakpoint}-margin-y-computed, var(--#{$breakpoint}-margin-computed))
            );
        }
        @if (index($additional-properties, 'margin-bottom')) {
            margin-bottom: var(
                --#{$breakpoint}-margin-bottom-computed,
                var(--#{$breakpoint}-margin-y-computed, var(--#{$breakpoint}-margin-computed))
            );
        }

        @if (index($additional-properties, 'padding')) {
            padding: var(--#{$breakpoint}-padding-computed);
        }
        @if (index($additional-properties, 'padding-left')) {
            padding-left: var(
                --#{$breakpoint}-padding-left-computed,
                var(--#{$breakpoint}-padding-x-computed, var(--#{$breakpoint}-padding-computed))
            );
        }
        @if (index($additional-properties, 'padding-right')) {
            padding-right: var(
                --#{$breakpoint}-padding-right-computed,
                var(--#{$breakpoint}-padding-x-computed, var(--#{$breakpoint}-padding-computed))
            );
        }
        @if (index($additional-properties, 'padding-top')) {
            padding-top: var(
                --#{$breakpoint}-padding-top-computed,
                var(--#{$breakpoint}-padding-y-computed, var(--#{$breakpoint}-padding-computed))
            );
        }
        @if (index($additional-properties, 'padding-bottom')) {
            padding-bottom: var(
                --#{$breakpoint}-padding-bottom-computed,
                var(--#{$breakpoint}-padding-y-computed, var(--#{$breakpoint}-padding-computed))
            );
        }

        @if index($additional-properties, 'width') {
            width: var(--#{$breakpoint}-width-computed);
        }
        @if index($additional-properties, 'min-width') {
            min-width: var(--#{$breakpoint}-min-width-computed);
        }
        @if index($additional-properties, 'max-width') {
            max-width: var(--#{$breakpoint}-max-width-computed);
        }

        @if index($additional-properties, 'height') {
            height: var(--#{$breakpoint}-height-computed);
        }
        @if index($additional-properties, 'min-height') {
            min-height: var(--#{$breakpoint}-min-height-computed);
        }
        @if index($additional-properties, 'max-height') {
            max-height: var(--#{$breakpoint}-max-height-computed);
        }

        @if index($additional-properties, 'display') {
            display: var(--#{$breakpoint}-display-computed);
        }
        @if index($additional-properties, 'flex-direction') {
            flex-direction: var(--#{$breakpoint}-flex-direction-computed);
        }
        @if index($additional-properties, 'align-items') {
            align-items: var(--#{$breakpoint}-align-items-computed);
        }
        @if index($additional-properties, 'justify-content') {
            justify-content: var(--#{$breakpoint}-justify-content-computed);
        }
        @if index($additional-properties, 'flex-wrap') {
            flex-wrap: var(--#{$breakpoint}-flex-wrap-computed);
        }
        @if index($additional-properties, 'gap') {
            gap: var(--#{$breakpoint}-gap-computed);
        }
        @if index($additional-properties, 'gap-x') {
            column-gap: var(--#{$breakpoint}-gap-x-computed, var(--#{$breakpoint}-gap-computed));
        }
        @if index($additional-properties, 'gap-y') {
            row-gap: var(--#{$breakpoint}-gap-y-computed, var(--#{$breakpoint}-gap-computed));
        }

        @if index($additional-properties, 'grid-template-rows') {
            grid-template-rows: var(--#{$breakpoint}-grid-template-rows-computed);
        }
        @if index($additional-properties, 'grid-template-columns') {
            grid-template-columns: var(--#{$breakpoint}-grid-template-columns-computed);
        }
        @if index($additional-properties, 'grid-auto-flow') {
            grid-auto-flow: var(--#{$breakpoint}-grid-auto-flow-computed);
        }
        @if index($additional-properties, 'justify-items') {
            justify-items: var(--#{$breakpoint}-justify-items-computed);
        }
    }
}

/**
 * Apply default values for a property for all breakpoints if the value isn't a list or set the default value per breakpoint if you pass a list.
 */
@mixin responsive-default-value($property, $value) {
    @if type-of($value) == map {
        @each $breakpoint, $_value in $screens {
            $value-at-breakpoint: map-get($value, $breakpoint);

            @if ($value-at-breakpoint == null) {
                @error 'Value for "#{$property}" at breakpoint "#{$breakpoint}" is not defined.';
            }

            & {
                --#{$breakpoint}-#{$property}: $value-at-breakpoint;
            }

            @if $breakpoint == base {
                --#{$property}: $value-at-breakpoint;
            }
        }
    } @else {
        & {
            --#{$property}: #{$value};
        }

        @each $breakpoint, $min-width in $screens {
            & {
                --#{$breakpoint}-#{$property}: var(--#{$breakpoint}-#{$property}, #{$value});
            }
        }
    }
}
