@charset "UTF-8";
@use "sass:math";
@use "sass:map";
@use "sass:list";

// ==========================================================================
// 1. Konfigurasjon
// ==========================================================================

// Angir globale CSS custom properties for maksimale container-bredder.
@layer jokul.components {
    :root {
        --container-m: 43.75rem;
        --container-l: 60rem;
        --container-xl: 75rem;
        --container-2xl: 90rem;
        --container-full: 100%;
    }
}

$jokul-breakpoints: (
    "small": 0,
    "medium": 680px,
    "large": 1200px,
    "xl": 1600px,
);
$jokul-semantic-spacing: (
    "none",
    "2xs",
    "xs",
    "s",
    "m",
    "l",
    "xl",
    "2xl",
);
$jokul-static-spacing: (
    "0",
    "2",
    "4",
    "8",
    "12",
    "16",
    "20",
    "24",
    "28",
    "32",
    "40",
    "48",
    "56",
    "64",
    "72",
    "80",
    "104",
    "168",
);
$jokul-spacing: list.join($jokul-semantic-spacing, $jokul-static-spacing, comma);

// Map for å generere klasser for uniforme (jevnt fordelte) kolonner.
// Nøkkelen (key) representerer antall elementer, og verdien (value) er hvor mange
// av de 12 grid-kolonnene hvert element skal oppta.
$uniform-layouts: (
    "0": "auto",
    // Automatisk bredde basert på innhold
    "1": 12,
    // 1 element i full bredde
    "2": 6,
    // 2 elementer, 50% bredde hver
    "3": 4,
    // 3 elementer, 33.3% bredde hver
    "4": 3,
    // 4 elementer, 25% bredde hver
    "6": 2,
    // 6 elementer, 16.6% bredde hver
);

// Map for å generere asymmetriske layout-klasser (f.eks. .s-2\.10).
// Nøkkelen (key) er klassens suffiks, og verdien (value) angir bredden i antall
// grid-kolonner for elementer på oddetallsplassering (1, 3, 5, ...).
// Bredden for partallselementer beregnes automatisk (12 - verdi).
$asymmetric-layouts: (
    "2\\.10": 2,
    "10\\.2": 10,
    "3\\.9": 3,
    "9\\.3": 9,
    "4\\.8": 4,
    "8\\.4": 8,
    "5\\.7": 5,
    "7\\.5": 7,
);

// Sass-map for å generere generiske hjelpeklasser (utility classes).
// Hver nøkkel på toppnivå er en CSS-egenskap, og de nøstede map-ene
// definerer klassenavn og tilhørende verdi.
$utility-classes: (
    "display": (inline-flex,
    ),
    "flex-wrap": (wrap-reverse,
        nowrap,
    ),
    "flex-direction": (column,
        column-reverse,
        row-reverse,
    ),
    "text-align": (left,
        center,
        right,
    ),
    "align-items": (start,
        center,
        end,
        baseline,
        stretch,
    ),
    "align-content": (start,
        center,
        end,
        stretch,
        baseline,
        space-around,
        space-between,
        space-evenly,
    ),
    "justify-content": (start,
        center,
        end,
        space-around,
        space-between,
        space-evenly,
    ),
);

// Map som definerer maksimale bredder for sentrerte containere (`.center-*`).
// Brukes til å generere responsive breddebegrensninger.
$containers: (
    "small": var(--container-m),
    "medium": var(--container-l),
    "large": var(--container-xl),
    "xl": var(--container-2xl),
);

// ==========================================================================
// 2. Verktøy (Mixins)
// ==========================================================================

/// Mixin som genererer hjelpeklasser for de forskjellige egenskapene et
/// flex-element kan ha. For eksempel vil man for `align-items`-egenskapen
/// få generert ut hjelpeklasser som `.align-items-end`.
/// @output Hjelpeklasser for de vanligste flex-egenskapene
@mixin generate-utility-classes() {
    @each $property, $values in $utility-classes {
        @each $value in $values {
            .#{$property}-#{$value} {
                #{$property}: $value;
            }
        }
    }
}

// Mixin for å generere responsive layout-klasser basert på $asymmetric-layouts og $uniform-layouts.
@mixin generate-layout-classes($breakpoint) {

    // --- Asymmetriske layouts ---
    // Genererer klasser for layouts der oddetalls- og partalls-elementer har ulik bredde.
    @each $layout, $odd-child-columns in $asymmetric-layouts {
        $even-child-columns: 12 - $odd-child-columns;

        .screen-#{$breakpoint}-#{$layout} {
            > :where(:nth-child(odd)) {
                --jkl-flex-layout: #{$odd-child-columns};
            }

            > :where(:nth-child(even)) {
                --jkl-flex-layout: #{$even-child-columns};
            }
        }
    }

    // --- Uniforme layouts ---
    // Genererer klasser for layouts der alle elementer har lik bredde.
    @each $layout, $value in $uniform-layouts {
        .screen-#{$breakpoint}-#{$layout} > * {
            --jkl-flex-layout: #{$value};
        }
    }
}


// Mixin for å generere klasser for `row-gap` og `column-gap`.
@mixin generate-gap-classes($breakpoint) {
    @each $spacing in $jokul-spacing {
        .screen-#{$breakpoint}-row-gap-#{$spacing} {
            row-gap: var(--jkl-spacing-#{$spacing});
        }

        .screen-#{$breakpoint}-col-gap-#{$spacing} {
            column-gap: var(--jkl-spacing-#{$spacing});

            // Setter en custom property for å kunne kalkulere nøyaktig kolonnebredde
            // i `flex-basis`, justert for `column-gap`.
            & > * {
                --jkl-flex-gap: var(--jkl-spacing-#{$spacing});
            }
        }
    }
}

// ==========================================================================
// 3. Kjernestiler
// ==========================================================================

@layer jokul.components {

    // Basisstil for alle flex-containere.
    :is(.jkl-flex) {
        box-sizing: border-box;
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
    }

    // Sørger for at direkte barn av .fill-elementer fyller tilgjengelig plass.
    // :where brukes for å holde spesifisiteten lav.
    :where(.fill > *) {
        flex-grow: 1;
    }

    // Definerer standardoppførsel for alle direkte elementer av en `.flex`-container.
    :where(.jkl-flex > *) {
        --jkl-flex-gap: 0px; // Standard gap er null.
        --jkl-flex-layout: auto; // Standard layout er automatisk bredde.

        box-sizing: border-box;

        // Kalkulerer `flex-basis` for å lage et grid-system som tar hensyn til `gap`.
        // Formelen fordeler bredden basert på antall kolonner definert av `--jkl-flex-layout`.
        flex-basis: calc((100% - (12 / var(--jkl-flex-layout) - 1) * var(--jkl-flex-gap)) / 12 * var(--jkl-flex-layout));

        // Sørger for at elementene kan krympe, for å unngå at de flyter ut av containeren.
        min-width: calc(var(--jkl-flex-layout) * 0px);
        min-height: calc(var(--jkl-flex-layout) * 0px);
    }

    // Hindrer at elementer krymper når `flex-wrap: nowrap` er satt.
    :where(.wrap-nowrap > *) {
        flex-shrink: calc(var(--jkl-flex-layout) * 0);
    }
}

// ==========================================================================
// 4. CSS-generering
// ==========================================================================

@layer jokul.components {
    @include generate-utility-classes;

    // Stiler for sentrerte containere.
    :is(.center-m, .center-l, .center-xl, .center-2xl) {
        box-sizing: border-box;
        margin-inline: auto;
        width: calc(100% - var(--jkl-unit-50));
    }

    // Genererer responsive `max-width` for hver container-størrelse.
    @each $size, $width in $containers {
        @media (width >=#{map.get($jokul-breakpoints, $size)}) {
            .center-#{$size} {
                max-width: $width;
            }
        }
    }

    // Itererer gjennom alle definerte breakpoints for å generere responsive layout- og gap-klasser.
    @each $breakpoint, $width in $jokul-breakpoints {
        @if $breakpoint =="small" {
            @include generate-layout-classes($breakpoint);
            @include generate-gap-classes($breakpoint);
        }

        @else {
            @media (width >=#{$width}) {
                @include generate-layout-classes($breakpoint);
                @include generate-gap-classes($breakpoint);
            }
        }
    }
}
