@use "sass:map";
@use "config" as *;
@use "functions" as *;
@use "theme" as *;

// add:
// - double check css grid helpers
//
// update:
// - focus-ring if needed

// Shadow opacity acts as a midpoint: double the standard opacity scale so
// .shadow-opacity-50 → 1 (== the default shadow) and .shadow-opacity-100 → 2
// (twice as strong). The shadow expressions read a clean var(--shadow-opacity, 1).
$shadow-opacities: () !default;
@each $key, $value in $util-opacity {
  $shadow-opacities: map.set($shadow-opacities, $key, $value * 2);
}

$utilities: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$utilities: map.merge(
  (
    // scss-docs-start utils-vertical-align
    "align": (
      property: vertical-align,
      class: align,
      values: baseline top middle bottom text-bottom text-top
    ),
    // scss-docs-end utils-vertical-align
    // scss-docs-start utils-aspect-ratio
    "aspect-ratio-attr": (
      selector: "attr-includes",
      class: "ratio-",
      property: aspect-ratio,
      values: var(--ratio),
    ),
    "aspect-ratio": (
      property: --ratio,
      class: ratio,
      values: $aspect-ratios
    ),
    // scss-docs-end utils-aspect-ratio
    // scss-docs-start utils-float
    "float": (
      property: float,
      responsive: true,
      values: (
        start: inline-start,
        end: inline-end,
        none: none,
      )
    ),
    // scss-docs-end utils-float
    // Object Fit utilities
    // scss-docs-start utils-object-fit
    "object-fit": (
      responsive: true,
      property: object-fit,
      values: (
        contain: contain,
        cover: cover,
        fill: fill,
        scale: scale-down,
        none: none,
      )
    ),
    // scss-docs-end utils-object-fit
    // Opacity utilities
    // scss-docs-start utils-opacity
    "opacity": (
      property: opacity,
      values: (
        0: 0,
        25: .25,
        50: .5,
        75: .75,
        100: 1,
      )
    ),
    // scss-docs-end utils-opacity
    // scss-docs-start utils-overflow
    "overflow": (
      property: overflow,
      values: auto hidden visible scroll,
    ),
    "overflow-x": (
      property: overflow-x,
      values: auto hidden visible scroll,
    ),
    "overflow-y": (
      property: overflow-y,
      values: auto hidden visible scroll,
    ),
    // scss-docs-end utils-overflow
    // scss-docs-start utils-container
    "container": (
      property: container-type,
      class: contains,
      values: (
        "inline": inline-size,
        "size": size,
      )
    ),
    // scss-docs-end utils-container
    // scss-docs-start utils-display
    "display": (
      responsive: true,
      property: display,
      class: d,
      values: inline inline-block block grid inline-grid table table-row table-cell flex inline-flex contents flow-root none
    ),
    // scss-docs-end utils-display
    // scss-docs-start utils-shadow
    "shadow": (
      property: box-shadow,
      class: shadow,
      // Pull the literal layered expressions straight from the shared $shadows
      // map (single source of truth in scss/_config.scss, also consumed by
      // scss/_root.scss). Emitting the literal—rather than var(--box-shadow-*)—
      // keeps the nested var(--sc, var(--shadow-color)) / var(--so, 1)
      // unresolved so they resolve on the element, letting .shadow-{color} and
      // .shadow-opacity-* take effect. `inset` isn't a utility, so it's excluded.
      values: map.merge(map.remove($shadows, inset), (none: none))
    ),
    // scss-docs-end utils-shadow
    // scss-docs-start utils-shadow-color
    "shadow-color": (
      // --sc is a local override composed into the $shadows expressions
      // (scss/_config.scss) as var(--sc, var(--shadow-color)); like --bc for
      // border-color, it's non-inheriting so .shadow-primary doesn't tint
      // nested .shadow-* descendants, which instead fall back to the
      // cascading global --shadow-color token (scss/_root.scss).
      property: --sc,
      class: shadow,
      values: map-merge-multiple(
        theme-color-refs("base"),
        (
          "current": currentcolor,
          "black": var(--black),
          "white": var(--white),
        )
      )
    ),
    // scss-docs-end utils-shadow-color
    // scss-docs-start utils-shadow-opacity
    "shadow-opacity": (
      // --so is a local override composed into the $shadows expressions
      // (scss/_config.scss) as var(--so, 1); same rationale as --sc above,
      // it's non-inheriting so it doesn't leak to nested .shadow-* descendants.
      property: --so,
      class: shadow-opacity,
      values: $shadow-opacities
    ),
    // scss-docs-end utils-shadow-opacity
    // scss-docs-start utils-position
    "position": (
      property: position,
      values: static relative absolute fixed sticky
    ),
    "top": (
      property: top,
      values: $position-values
    ),
    "bottom": (
      property: bottom,
      values: $position-values
    ),
    "start": (
      property: inset-inline-start,
      class: start,
      values: $position-values
    ),
    "end": (
      property: inset-inline-end,
      class: end,
      values: $position-values
    ),
    "translate-middle": (
      property: transform,
      class: translate-middle,
      values: (
        null: translate(-50%, -50%),
        x: translateX(-50%),
        y: translateY(-50%),
      )
    ),
    // scss-docs-end utils-position
    // scss-docs-start utils-borders
    "border": (
      property: border,
      values: (
        null: var(--border-width) var(--border-style) var(--border-color),
        0: 0,
      )
    ),
    "border-top": (
      class: border-top,
      property: border-block-start,
      values: (
        null: var(--border-width) var(--border-style) var(--border-color),
        0: 0,
      )
    ),
    "border-end": (
      property: border-inline-end,
      class: border-end,
      values: (
        null: var(--border-width) var(--border-style) var(--border-color),
        0: 0,
      )
    ),
    "border-bottom": (
      property: border-block-end,
      class: border-bottom,
      values: (
        null: var(--border-width) var(--border-style) var(--border-color),
        0: 0,
      )
    ),
    "border-start": (
      property: border-inline-start,
      class: border-start,
      values: (
        null: var(--border-width) var(--border-style) var(--border-color),
        0: 0,
      )
    ),
    "border-y": (
      class: border-y,
      property: border-block,
      values: (
        null: var(--border-width) var(--border-style) var(--border-color),
        0: 0,
      )
    ),
    "border-x": (
      class: border-x,
      property: border-inline,
      values: (
        null: var(--border-width) var(--border-style) var(--border-color),
        0: 0,
      )
    ),
    // scss-docs-end utils-borders
    // scss-docs-start utils-border-color
    "border-color": (
      property: (
        "--bc": null,
        "border-color": var(--bc)
      ),
      class: border,
      values: map.merge(theme-color-refs("bg"), theme-token-refs($theme-borders, "border")),
    ),
    "border-color-subtle": (
      property: (
        "--bc": null,
        "border-color": var(--bc)
      ),
      class: border-subtle,
      values: theme-color-refs("border"),
    ),
    "border-width": (
      property: border-width,
      class: border,
      values: map.merge($border-widths, (keyline: var(--border-width-keyline)))
    ),
    "border-opacity": (
      class: border,
      property: border-color,
      values: theme-opacity-values(--bc)
    ),
    // scss-docs-end utils-border-color
    // Sizing utilities
    // scss-docs-start utils-width
    "width": (
      property: width,
      class: w,
      values: map.merge(
        $sizes,
        (
          25: 25%,
          50: 50%,
          75: 75%,
          100: 100%,
          auto: auto,
          min: min-content,
          max: max-content,
          fit: fit-content,
        )
      )
    ),
    "max-width": (
      property: max-width,
      class: max-w,
      values: (100: 100%)
    ),
    "min-width": (
      property: min-width,
      class: min-w,
      values: (
        0: 0,
        100: 100%
      )
    ),
    "viewport-width": (
      property: width,
      class: vw,
      values: (100: 100vw)
    ),
    "min-viewport-width": (
      property: min-width,
      class: min-vw,
      values: (100: 100vw)
    ),
    "dynamic-viewport-width": (
      property: width,
      class: dvw,
      values: (100: 100dvw)
    ),
    "min-dynamic-viewport-width": (
      property: min-width,
      class: min-dvw,
      values: (100: 100dvw)
    ),
    // scss-docs-end utils-width
    // scss-docs-start utils-height
    "height": (
      property: height,
      class: h,
      values: (
        25: 25%,
        50: 50%,
        75: 75%,
        100: 100%,
        auto: auto,
        min: min-content,
        max: max-content,
        fit: fit-content,
      )
    ),
    "max-height": (
      property: max-height,
      class: max-h,
      values: (100: 100%)
    ),
    "min-height": (
      property: min-height,
      class: min-h,
      values: (
        0: 0,
        100: 100%,
      ),
    ),
    "viewport-height": (
      property: height,
      class: vh,
      values: (100: 100vh)
    ),
    "min-viewport-height": (
      property: min-height,
      class: min-vh,
      values: (100: 100vh)
    ),
    "dynamic-viewport-height": (
      property: height,
      class: dvh,
      values: (100: 100dvh)
    ),
    "min-dynamic-viewport-height": (
      property: min-height,
      class: min-dvh,
      values: (100: 100dvh)
    ),
    // scss-docs-end utils-height
    // Flex utilities
    // scss-docs-start utils-flex
    "flex": (
      responsive: true,
      property: flex,
      values: (fill: 1 1 auto)
    ),
    "flex-direction": (
      responsive: true,
      property: flex-direction,
      class: flex,
      values: row column row-reverse column-reverse
    ),
    "flex-grow": (
      responsive: true,
      property: flex-grow,
      class: flex,
      values: (
        grow-0: 0,
        grow-1: 1,
      )
    ),
    "flex-shrink": (
      responsive: true,
      property: flex-shrink,
      class: flex,
      values: (
        shrink-0: 0,
        shrink-1: 1,
      )
    ),
    "flex-wrap": (
      responsive: true,
      property: flex-wrap,
      class: flex,
      values: wrap nowrap wrap-reverse
    ),
    // scss-docs-end utils-flex
    // scss-docs-start utils-justify-content
    "justify-content": (
      responsive: true,
      property: justify-content,
      values: (
        start: flex-start,
        end: flex-end,
        center: center,
        between: space-between,
        around: space-around,
        evenly: space-evenly,
      )
    ),
    // scss-docs-end utils-justify-content
    // scss-docs-start utils-justify-items
    "justify-items": (
      responsive: true,
      property: justify-items,
      values: (
        start: start,
        end: end,
        center: center,
        stretch: stretch,
      )
    ),
    // scss-docs-end utils-justify-items
    "justify-self": (
      responsive: true,
      property: justify-self,
      values: (
        start: start,
        end: end,
        center: center,
      )
    ),
    // scss-docs-start utils-align-items
    "align-items": (
      responsive: true,
      property: align-items,
      values: (
        start: flex-start,
        end: flex-end,
        center: center,
        baseline: baseline,
        stretch: stretch,
      )
    ),
    // scss-docs-end utils-align-items
    // scss-docs-start utils-align-content
    "align-content": (
      responsive: true,
      property: align-content,
      values: (
        start: flex-start,
        end: flex-end,
        center: center,
        between: space-between,
        around: space-around,
        stretch: stretch,
      )
    ),
    // scss-docs-end utils-align-content
    // scss-docs-start utils-align-self
    "align-self": (
      responsive: true,
      property: align-self,
      values: (
        auto: auto,
        start: flex-start,
        end: flex-end,
        center: center,
        baseline: baseline,
        stretch: stretch,
      )
    ),
    // scss-docs-end utils-align-self
    // scss-docs-start utils-place-items
    "place-items": (
      responsive: true,
      property: place-items,
      values: (
        start: start,
        end: end,
        center: center,
        stretch: stretch,
      )
    ),
    // scss-docs-end utils-place-items
    // scss-docs-start utils-grid
    "grid-column-counts": (
      responsive: true,
      property: grid-template-columns,
      class: grid-cols,
      values: (
        "1": 1fr,
        "2": repeat(2, 1fr),
        "3": repeat(3, 1fr),
        "4": repeat(4, 1fr),
        "6": repeat(6, 1fr),
        subgrid: subgrid,
      )
    ),
    "grid-columns": (
      responsive: true,
      property: grid-column,
      class: grid-cols,
      values: (
        fill: #{"1 / -1"},
      )
    ),
    "grid-auto-flow": (
      responsive: true,
      property: grid-auto-flow,
      class: grid-auto-flow,
      values: row column dense
    ),
    // scss-docs-end utils-grid
    "order": (
      responsive: true,
      property: order,
      values: (
        first: -1,
        0: 0,
        1: 1,
        2: 2,
        3: 3,
        4: 4,
        5: 5,
        last: 6,
      ),
    ),
    // Margin utilities
    // scss-docs-start utils-margin
    "margin": (
      responsive: true,
      property: margin,
      class: m,
      values: map.merge($spacers, (auto: auto))
    ),
    "margin-x": (
      responsive: true,
      property: margin-inline,
      class: mx,
      values: map.merge($spacers, (auto: auto))
    ),
    "margin-y": (
      responsive: true,
      property: margin-block,
      class: my,
      values: map.merge($spacers, (auto: auto))
    ),
    "margin-top": (
      responsive: true,
      property: margin-block-start,
      class: mt,
      values: map.merge($spacers, (auto: auto))
    ),
    "margin-end": (
      responsive: true,
      property: margin-inline-end,
      class: me,
      values: map-merge-multiple($spacers, $negative-spacers, (auto: auto))
    ),
    "margin-bottom": (
      responsive: true,
      property: margin-block-end,
      class: mb,
      values: map.merge($spacers, (auto: auto))
    ),
    "margin-start": (
      responsive: true,
      property: margin-inline-start,
      class: ms,
      values: map-merge-multiple($spacers, $negative-spacers, (auto: auto))
    ),
    // scss-docs-end utils-margin
    // Padding utilities
    // scss-docs-start utils-padding
    "padding": (
      responsive: true,
      property: padding,
      class: p,
      values: $spacers
    ),
    "padding-x": (
      responsive: true,
      property: padding-inline,
      class: px,
      values: $spacers
    ),
    "padding-y": (
      responsive: true,
      property: padding-block,
      class: py,
      values: $spacers
    ),
    "padding-top": (
      responsive: true,
      property: padding-block-start,
      class: pt,
      values: $spacers
    ),
    "padding-end": (
      responsive: true,
      property: padding-inline-end,
      class: pe,
      values: $spacers
    ),
    "padding-bottom": (
      responsive: true,
      property: padding-block-end,
      class: pb,
      values: $spacers
    ),
    "padding-start": (
      responsive: true,
      property: padding-inline-start,
      class: ps,
      values: $spacers
    ),
    // scss-docs-end utils-padding
    // Gap utility
    // scss-docs-start utils-gap
    "gap": (
      responsive: true,
      property: gap,
      class: gap,
      values: $spacers
    ),
    "row-gap": (
      responsive: true,
      property: row-gap,
      class: row-gap,
      values: $spacers
    ),
    "column-gap": (
      responsive: true,
      property: column-gap,
      class: column-gap,
      values: $spacers
    ),
    // scss-docs-end utils-gap
    // scss-docs-start utils-space
    "space-x": (
      responsive: true,
      property: margin-inline-end,
      class: space-x,
      child-selector: "> :not(:last-child)",
      values: $spacers
    ),
    "space-y": (
      responsive: true,
      property: margin-block-end,
      class: space-y,
      child-selector: "> :not(:last-child)",
      values: $spacers
    ),
    // scss-docs-end utils-space
    // scss-docs-start utils-divide
    "divide-x": (
      responsive: true,
      property: border-inline-start,
      class: divide-x,
      child-selector: "> :not(:first-child)",
      values: (
        null: var(--border-width) var(--border-style) var(--border-color),
        0: 0,
      )
    ),
    "divide-y": (
      responsive: true,
      property: border-block-start,
      class: divide-y,
      child-selector: "> :not(:first-child)",
      values: (
        null: var(--border-width) var(--border-style) var(--border-color),
        0: 0,
      )
    ),
    // scss-docs-end utils-divide
    // Text
    // scss-docs-start utils-font-family
    "font-family": (
      property: font-family,
      class: font,
      values: (
        "monospace": var(--font-mono),
        "body": var(--body-font-family),
      )
    ),
    // scss-docs-end utils-font-family
    // scss-docs-start utils-font-size
    "font-size": (
      property: font-size,
      class: fs,
      values: map-get-nested($font-sizes, "font-size")
    ),
    "text-size": (
      property: (
        "font-size": 1rem,
        "line-height": 1.5
      ),
      class: text,
      values: $font-sizes
    ),
    // scss-docs-end utils-font-size
    // scss-docs-start utils-font-style
    "font-style": (
      property: font-style,
      class: fst,
      values: italic normal
    ),
    // scss-docs-end utils-font-style
    // scss-docs-start utils-font-weight
    "font-weight": (
      property: font-weight,
      class: fw,
      values: $font-weights
    ),
    // scss-docs-end utils-font-weight
    // scss-docs-start utils-line-height
    "line-height": (
      property: line-height,
      class: lh,
      values: (
        1: 1,
        sm: var(--line-height-sm),
        md: var(--line-height-md),
        lg: var(--line-height-lg),
      )
    ),
    // scss-docs-end utils-line-height
    // scss-docs-start utils-text-align
    "text-align": (
      responsive: true,
      property: text-align,
      class: text,
      values: (
        start: start,
        end: end,
        center: center,
      )
    ),
    // scss-docs-end utils-text-align
    "text-decoration": (
      property: text-decoration,
      values: none underline line-through
    ),
    // scss-docs-start utils-text-transform
    "text-transform": (
      property: text-transform,
      class: text,
      values: lowercase uppercase capitalize
    ),
    // scss-docs-end utils-text-transform
    // scss-docs-start utils-text-wrap
    "text-wrap": (
      property: text-wrap,
      class: text,
      values: wrap nowrap balance pretty,
    ),
    // scss-docs-end utils-text-wrap
    // scss-docs-start utils-text-break
    "word-wrap": (
      property: word-wrap word-break,
      class: text,
      values: (break: break-word),
    ),
    // scss-docs-end utils-text-break
    // scss-docs-start utils-color
    "fg": (
      property: (
        "--fg": null,
        "color": var(--fg)
      ),
      class: fg,
      values: map.merge(
        map.merge(theme-color-refs("fg"), theme-token-refs($theme-fgs, "fg")),
        (reset: inherit)
      ),
    ),
    "fg-emphasis": (
      property: (
        "--fg": null,
        "color": var(--fg)
      ),
      class: fg-emphasis,
      values: theme-color-refs("fg-emphasis"),
    ),
    "fg-contrast": (
      property: (
        "--fg": null,
        "color": var(--fg)
      ),
      class: fg-contrast,
      values: theme-color-refs("contrast"),
    ),
    "fg-opacity": (
      class: fg,
      property: color,
      values: theme-opacity-values(--fg)
    ),
    // scss-docs-end utils-color
    // scss-docs-start utils-links
    "link-opacity": (
      property: color,
      // css-var: true,
      class: link,
      state: hover,
      values: theme-opacity-values(--link-color)
    ),
    // scss-docs-end utils-links
    // scss-docs-start utils-underline
    "underline-offset": (
      property: text-underline-offset,
      class: underline-offset,
      state: hover,
      values: (
        1: .125em,
        2: .25em,
        3: .375em,
      )
    ),
    "underline-color": (
      property: (
        "--underline-color": null,
        "text-decoration-color": var(--underline-color)
      ),
      class: underline,
      values: theme-color-values("fg"),
    ),
    "underline-opacity": (
      property: text-decoration-color,
      class: underline,
      state: hover,
      values: theme-opacity-values(--underline-color, currentcolor)
    ),
    "underline-thickness": (
      property: text-decoration-thickness,
      class: underline-thickness,
      state: hover,
      values: (
        1: 1px,
        2: 2px,
        3: 3px,
        4: 4px,
        5: 5px,
      )
    ),
    // scss-docs-end utils-underline
    // scss-docs-start utils-bg-color
    "bg-color": (
      property: (
        "--bg": null,
        "background-color": var(--bg)
      ),
      class: bg,
      values: map.merge(theme-color-refs("bg"), theme-token-refs($theme-bgs, "bg")),
    ),
    "bg-color-subtle": (
      property: (
        "--bg": null,
        "background-color": var(--bg)
      ),
      class: bg-subtle,
      values: theme-color-refs("bg-subtle"),
    ),
    "bg-color-muted": (
      property: (
        "--bg": null,
        "background-color": var(--bg)
      ),
      class: bg-muted,
      values: theme-color-refs("bg-muted"),
    ),
    "bg-opacity": (
      class: bg,
      property: background-color,
      values: theme-opacity-values(--bg)
    ),
    // scss-docs-end utils-bg-color
    // scss-docs-start utils-theme
    // Theme style utilities - pair with .theme-{color} to apply coordinated bg + text colors
    "theme-contrast": (
      property: (
        "background-color": var(--theme-bg),
        "color": var(--theme-contrast)
      ),
      class: theme-contrast,
      values: (null: null)
    ),
    "theme-subtle": (
      property: (
        "background-color": var(--theme-bg-subtle),
        "color": var(--theme-fg)
      ),
      class: theme-subtle,
      values: (null: null)
    ),
    "theme-muted": (
      property: (
        "background-color": var(--theme-bg-muted),
        "color": var(--theme-fg-emphasis)
      ),
      class: theme-muted,
      values: (null: null)
    ),
    "theme-border": (
      property: border,
      class: theme-border,
      values: (null: var(--border-width) solid var(--theme-border))
    ),
    // scss-docs-end utils-theme
    "gradient": (
      property: background-image,
      class: bg,
      values: (gradient: var(--gradient))
    ),
    // scss-docs-start utils-color-scheme
    "color-scheme": (
      property: color-scheme,
      class: color-scheme,
      values: (
        light: light,
        dark: dark,
        auto: light dark,
      )
    ),
    // scss-docs-end utils-color-scheme
    // scss-docs-start utils-user-select
    "user-select": (
      property: user-select,
      values: all auto text none
    ),
    // scss-docs-end utils-user-select
    // scss-docs-start utils-pointer-events
    "pointer-events": (
      property: pointer-events,
      class: pe,
      values: none auto,
    ),
    // scss-docs-end utils-pointer-events
    // scss-docs-start utils-border-radius
    "border-radius": (
      property: (
        "--rounded-size": null,
        "border-radius": var(--rounded-size)
      ),
      class: rounded,
      values: map.merge(
        $radii,
        (
          null: map.get($radii, 5),
          circle: 50%,
          pill: var(--radius-pill)
        )
      )
    ),
    "rounded-size": (
      property: --rounded-size,
      class: rounded-size,
      values: map.merge(
        $radii,
        (
          null: map.get($radii, 5),
          circle: 50%,
          pill: var(--radius-pill)
        )
      )
    ),
    "rounded-top": (
      property: border-start-start-radius border-start-end-radius,
      class: rounded-top,
      values: map.merge(
        $radii,
        (
          null: var(--rounded-size, var(--radius-5)),
          circle: 50%,
          pill: var(--radius-pill)
        )
      )
    ),
    "rounded-end": (
      property: border-start-end-radius border-end-end-radius,
      class: rounded-end,
      values: map.merge(
        $radii,
        (
          null: var(--rounded-size, var(--radius-5)),
          circle: 50%,
          pill: var(--radius-pill)
        )
      )
    ),
    "rounded-bottom": (
      property: border-end-start-radius border-end-end-radius,
      class: rounded-bottom,
      values: map.merge(
        $radii,
        (
          null: var(--rounded-size, var(--radius-5)),
          circle: 50%,
          pill: var(--radius-pill)
        )
      )
    ),
    "rounded-start": (
      property: border-start-start-radius border-end-start-radius,
      class: rounded-start,
      values: map.merge(
        $radii,
        (
          null: var(--rounded-size, var(--radius-5)),
          circle: 50%,
          pill: var(--radius-pill)
        )
      )
    ),
    // scss-docs-end utils-border-radius
    // scss-docs-start utils-visibility
    "visibility": (
      property: visibility,
      class: null,
      values: (
        visible: visible,
        invisible: hidden,
      )
    ),
    // scss-docs-end utils-visibility
    // scss-docs-start utils-zindex
    "z-index": (
      property: z-index,
      class: z,
      values: $zindex-levels,
    ),
    // scss-docs-end utils-zindex
    // scss-docs-start utils-transition
    "transition": (
      property: transition,
      class: transition,
      values: (
        none: none,
      )
    ),
    // scss-docs-end utils-transition
    // scss-docs-start utils-animation
    "animation": (
      property: animation,
      class: animation,
      values: (
        none: none,
        shake: animation-shake .82s cubic-bezier(.36, .07, .19, .97) both,
        pop: animation-pop .3s cubic-bezier(.34, 1.56, .64, 1) both,
      )
    ),
    // scss-docs-end utils-animation
  ),
  $utilities
);
