Home / Function/ createUtilities() — tailwindcss Function Reference

createUtilities() — tailwindcss Function Reference

Architecture documentation for the createUtilities() function in utilities.ts from the tailwindcss codebase.

Entity Profile

Dependency Diagram

graph TD
  ba6df4b8_e7cd_66be_ac5e_1d70e8699df2["createUtilities()"]
  cebe77e1_f0f2_aeee_417e_2192f5790344["buildDesignSystem()"]
  cebe77e1_f0f2_aeee_417e_2192f5790344 -->|calls| ba6df4b8_e7cd_66be_ac5e_1d70e8699df2
  style ba6df4b8_e7cd_66be_ac5e_1d70e8699df2 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

packages/tailwindcss/src/utilities.ts lines 291–5929

export function createUtilities(theme: Theme) {
  let utilities = new Utilities()

  /**
   * Register list of suggestions for a class
   */
  function suggest(classRoot: string, defns: () => SuggestionDefinition[]) {
    function* resolve(themeKeys: ThemeKey[]) {
      for (let value of theme.keysInNamespaces(themeKeys)) {
        yield value.replace(LEGACY_NUMERIC_KEY, (_, a, b) => {
          return `${a}.${b}`
        })
      }
    }

    let suggestedFractions = [
      '1/2',
      '1/3',
      '2/3',
      '1/4',
      '2/4',
      '3/4',
      '1/5',
      '2/5',
      '3/5',
      '4/5',
      '1/6',
      '2/6',
      '3/6',
      '4/6',
      '5/6',
      '1/12',
      '2/12',
      '3/12',
      '4/12',
      '5/12',
      '6/12',
      '7/12',
      '8/12',
      '9/12',
      '10/12',
      '11/12',
    ]

    utilities.suggest(classRoot, () => {
      let groups: SuggestionGroup[] = []

      for (let defn of defns()) {
        if (typeof defn === 'string') {
          groups.push({ values: [defn], modifiers: [] })
          continue
        }

        let values: (string | null)[] = [
          ...(defn.values ?? []),
          ...resolve(defn.valueThemeKeys ?? []),
        ]

        let modifiers = [...(defn.modifiers ?? []), ...resolve(defn.modifierThemeKeys ?? [])]

        if (defn.supportsFractions) {
          values.push(...suggestedFractions)
        }

        if (defn.hasDefaultValue) {
          values.unshift(null)
        }

        groups.push({ supportsNegative: defn.supportsNegative, values, modifiers })
      }

      return groups
    })
  }

  /**
   * Register a static utility class like `justify-center`.
   */
  function staticUtility(className: string, declarations: ([string, string] | (() => AstNode))[]) {
    utilities.static(className, () => {
      return declarations.map((node) => {
        return typeof node === 'function' ? node() : decl(node[0], node[1])
      })
    })
  }

  type UtilityDescription = {
    supportsNegative?: boolean
    supportsFractions?: boolean
    themeKeys?: ThemeKey[]
    defaultValue?: string | null
    staticValues?: Record<string, AstNode[]>
    handleBareValue?: (value: NamedUtilityValue) => string | null
    handleNegativeBareValue?: (value: NamedUtilityValue) => string | null
    handle: (value: string, dataType: string | null) => AstNode[] | undefined
  }

  /**
   * Register a functional utility class like `max-w-*` that maps to tokens in the
   * user's theme.
   */
  function functionalUtility(classRoot: string, desc: UtilityDescription) {
    function handleFunctionalUtility({ negative }: { negative: boolean }) {
      return (candidate: Extract<Candidate, { kind: 'functional' }>) => {
        let value: string | null = null
        let dataType: string | null = null

        if (!candidate.value) {
          if (candidate.modifier) return

          // If the candidate has no value segment (like `rounded`), use the
          // `defaultValue` (for candidates like `grow` that have no theme
          // values) or a bare theme value (like `--radius` for `rounded`). No
          // utility will ever support both of these.
          value =
            desc.defaultValue !== undefined
              ? desc.defaultValue
              : theme.resolve(null, desc.themeKeys ?? [])
        } else if (candidate.value.kind === 'arbitrary') {
          if (candidate.modifier) return
          value = candidate.value.value
          dataType = candidate.value.dataType
        } else {
          value = theme.resolve(
            candidate.value.fraction ?? candidate.value.value,
            desc.themeKeys ?? [],
          )

          // Automatically handle things like `w-1/2` without requiring `1/2` to
          // exist as a theme value.
          if (value === null && desc.supportsFractions && candidate.value.fraction) {
            let [lhs, rhs] = segment(candidate.value.fraction, '/')
            if (!isPositiveInteger(lhs) || !isPositiveInteger(rhs)) return
            value = `calc(${lhs} / ${rhs} * 100%)`
          }

          // If there is still no value but the utility supports bare values,
          // then use the bare candidate value as the value.
          if (value === null && negative && desc.handleNegativeBareValue) {
            value = desc.handleNegativeBareValue(candidate.value)
            if (!value?.includes('/') && candidate.modifier) return
            if (value !== null) return desc.handle(value, null)
          }

          if (value === null && desc.handleBareValue) {
            value = desc.handleBareValue(candidate.value)
            if (!value?.includes('/') && candidate.modifier) return
          }

          if (value === null && !negative && desc.staticValues && !candidate.modifier) {
            let fallback = desc.staticValues[candidate.value.value]
            if (fallback) return fallback.map(cloneAstNode)
          }
        }

        // If there is no value, don't generate any rules.
        if (value === null) return

        // Negate the value if the candidate has a negative prefix.
        return desc.handle(negative ? `calc(${value} * -1)` : value, dataType)
      }
    }

    if (desc.supportsNegative) {
      utilities.functional(`-${classRoot}`, handleFunctionalUtility({ negative: true }))
    }
    utilities.functional(classRoot, handleFunctionalUtility({ negative: false }))

    suggest(classRoot, () => [
      {
        supportsNegative: desc.supportsNegative,
        valueThemeKeys: desc.themeKeys ?? [],
        hasDefaultValue: desc.defaultValue !== undefined && desc.defaultValue !== null,
        supportsFractions: desc.supportsFractions,
      },
    ])

    // Also suggest any staticValues automatically so callers don't need to
    // manually add suggestion groups for e.g. `auto`, `none`, `full`, etc.
    if (desc.staticValues && Object.keys(desc.staticValues).length > 0) {
      let values = Object.keys(desc.staticValues)
      suggest(classRoot, () => [{ values }])
    }
  }

  type ColorUtilityDescription = {
    themeKeys: ThemeKey[]
    handle: (value: string) => AstNode[] | undefined
  }

  /**
   * Register a functional utility class that represents a color.
   * Such utilities gain automatic support for color opacity modifiers.
   */
  function colorUtility(classRoot: string, desc: ColorUtilityDescription) {
    utilities.functional(classRoot, (candidate) => {
      // Color utilities have to have a value, like the `red-500` in
      // `bg-red-500`, otherwise they would be static utilities.
      if (!candidate.value) return

      // Find the actual CSS value that the candidate value maps to.
      let value: string | null = null

      if (candidate.value.kind === 'arbitrary') {
        value = candidate.value.value

        // Apply an opacity modifier to the value if appropriate.
        value = asColor(value, candidate.modifier, theme)
      } else {
        value = resolveThemeColor(candidate, theme, desc.themeKeys)
      }

      // If the candidate value (like the `red-500` in `bg-red-500`) doesn't
      // resolve to an actual value, don't generate any rules.
      if (value === null) return

      return desc.handle(value)
    })

    suggest(classRoot, () => [
      {
        values: ['current', 'inherit', 'transparent'],
        valueThemeKeys: desc.themeKeys,
        modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
      },
    ])
  }

  function spacingUtility(
    name: string,
    themeKeys: ThemeKey[],
    handle: (value: string) => AstNode[] | undefined,
    {
      supportsNegative = false,
      supportsFractions = false,
      staticValues,
    }: {
      supportsNegative?: boolean
      supportsFractions?: boolean
      staticValues?: Record<string, AstNode[]>
    } = {},
  ) {
    if (supportsNegative) {
      utilities.static(`-${name}-px`, () => handle('-1px'))
    }
    utilities.static(`${name}-px`, () => handle('1px'))
    functionalUtility(name, {
      themeKeys,
      supportsFractions,
      supportsNegative,
      defaultValue: null,
      handleBareValue: ({ value }) => {
        let multiplier = theme.resolve(null, ['--spacing'])
        if (!multiplier) return null
        if (!isValidSpacingMultiplier(value)) return null

        return `calc(${multiplier} * ${value})`
      },
      handleNegativeBareValue: ({ value }) => {
        let multiplier = theme.resolve(null, ['--spacing'])
        if (!multiplier) return null
        if (!isValidSpacingMultiplier(value)) return null

        return `calc(${multiplier} * -${value})`
      },
      handle,
      staticValues,
    })

    suggest(name, () => [
      {
        values: theme.get(['--spacing']) ? DEFAULT_SPACING_SUGGESTIONS : [],
        supportsNegative,
        supportsFractions,
        valueThemeKeys: themeKeys,
      },
    ])
  }

  /**
   * ----------------
   * Utility matchers
   * ----------------
   */

  staticUtility('sr-only', [
    ['position', 'absolute'],
    ['width', '1px'],
    ['height', '1px'],
    ['padding', '0'],
    ['margin', '-1px'],
    ['overflow', 'hidden'],
    ['clip-path', 'inset(50%)'],
    ['white-space', 'nowrap'],
    ['border-width', '0'],
  ])
  staticUtility('not-sr-only', [
    ['position', 'static'],
    ['width', 'auto'],
    ['height', 'auto'],
    ['padding', '0'],
    ['margin', '0'],
    ['overflow', 'visible'],
    ['clip-path', 'none'],
    ['white-space', 'normal'],
  ])

  /**
   * @css `pointer-events`
   */
  staticUtility('pointer-events-none', [['pointer-events', 'none']])
  staticUtility('pointer-events-auto', [['pointer-events', 'auto']])

  /**
   * @css `visibility`
   */
  staticUtility('visible', [['visibility', 'visible']])
  staticUtility('invisible', [['visibility', 'hidden']])
  staticUtility('collapse', [['visibility', 'collapse']])

  /**
   * @css `position`
   */
  staticUtility('static', [['position', 'static']])
  staticUtility('fixed', [['position', 'fixed']])
  staticUtility('absolute', [['position', 'absolute']])
  staticUtility('relative', [['position', 'relative']])
  staticUtility('sticky', [['position', 'sticky']])

  /**
   * @css `inset`
   */
  for (let [name, property] of [
    ['inset', 'inset'],
    ['inset-x', 'inset-inline'],
    ['inset-y', 'inset-block'],
    ['inset-s', 'inset-inline-start'],
    ['inset-e', 'inset-inline-end'],
    ['inset-bs', 'inset-block-start'],
    ['inset-be', 'inset-block-end'],
    ['top', 'top'],
    ['right', 'right'],
    ['bottom', 'bottom'],
    ['left', 'left'],
  ] as const) {
    staticUtility(`${name}-auto`, [[property, 'auto']])
    staticUtility(`${name}-full`, [[property, '100%']])
    staticUtility(`-${name}-full`, [[property, '-100%']])
    spacingUtility(name, ['--inset', '--spacing'], (value) => [decl(property, value)], {
      supportsNegative: true,
      supportsFractions: true,
    })
  }

  /**
   * @css `isolation`
   */
  staticUtility('isolate', [['isolation', 'isolate']])
  staticUtility('isolation-auto', [['isolation', 'auto']])

  /**
   * @css `z-index`
   */
  functionalUtility('z', {
    supportsNegative: true,
    handleBareValue: ({ value }) => {
      if (!isPositiveInteger(value)) return null
      return value
    },
    themeKeys: ['--z-index'],
    handle: (value) => [decl('z-index', value)],
    staticValues: {
      auto: [decl('z-index', 'auto')],
    },
  })

  suggest('z', () => [
    {
      supportsNegative: true,
      values: ['0', '10', '20', '30', '40', '50'],
      valueThemeKeys: ['--z-index'],
    },
  ])

  /**
   * @css `order`
   */
  functionalUtility('order', {
    supportsNegative: true,
    handleBareValue: ({ value }) => {
      if (!isPositiveInteger(value)) return null
      return value
    },
    themeKeys: ['--order'],
    handle: (value) => [decl('order', value)],
    staticValues: {
      first: [decl('order', '-9999')],
      last: [decl('order', '9999')],
    },
  })

  suggest('order', () => [
    {
      supportsNegative: true,
      values: Array.from({ length: 12 }, (_, i) => `${i + 1}`),
      valueThemeKeys: ['--order'],
    },
  ])

  /**
   * @css `grid-column`
   */
  functionalUtility('col', {
    supportsNegative: true,
    handleBareValue: ({ value }) => {
      if (!isPositiveInteger(value)) return null
      return value
    },
    themeKeys: ['--grid-column'],
    handle: (value) => [decl('grid-column', value)],
    staticValues: {
      auto: [decl('grid-column', 'auto')],
    },
  })

  functionalUtility('col-span', {
    handleBareValue: ({ value }) => {
      if (!isPositiveInteger(value)) return null
      return value
    },
    handle: (value) => [decl('grid-column', `span ${value} / span ${value}`)],
    staticValues: {
      full: [decl('grid-column', '1 / -1')],
    },
  })

  /**
   * @css `grid-column-start`
   */
  functionalUtility('col-start', {
    supportsNegative: true,
    handleBareValue: ({ value }) => {
      if (!isPositiveInteger(value)) return null
      return value
    },
    themeKeys: ['--grid-column-start'],
    handle: (value) => [decl('grid-column-start', value)],
    staticValues: {
      auto: [decl('grid-column-start', 'auto')],
    },
  })

  /**
   * @css `grid-column-end`
   */
  functionalUtility('col-end', {
    supportsNegative: true,
    handleBareValue: ({ value }) => {
      if (!isPositiveInteger(value)) return null
      return value
    },
    themeKeys: ['--grid-column-end'],
    handle: (value) => [decl('grid-column-end', value)],
    staticValues: {
      auto: [decl('grid-column-end', 'auto')],
    },
  })

  suggest('col-span', () => [
    {
      values: Array.from({ length: 12 }, (_, i) => `${i + 1}`),
      valueThemeKeys: [],
    },
  ])

  suggest('col-start', () => [
    {
      supportsNegative: true,
      values: Array.from({ length: 13 }, (_, i) => `${i + 1}`),
      valueThemeKeys: ['--grid-column-start'],
    },
  ])

  suggest('col-end', () => [
    {
      supportsNegative: true,
      values: Array.from({ length: 13 }, (_, i) => `${i + 1}`),
      valueThemeKeys: ['--grid-column-end'],
    },
  ])

  /**
   * @css `grid-row`
   */
  functionalUtility('row', {
    supportsNegative: true,
    handleBareValue: ({ value }) => {
      if (!isPositiveInteger(value)) return null
      return value
    },
    themeKeys: ['--grid-row'],
    handle: (value) => [decl('grid-row', value)],
    staticValues: {
      auto: [decl('grid-row', 'auto')],
    },
  })

  functionalUtility('row-span', {
    themeKeys: [],
    handleBareValue: ({ value }) => {
      if (!isPositiveInteger(value)) return null
      return value
    },
    handle: (value) => [decl('grid-row', `span ${value} / span ${value}`)],
    staticValues: {
      full: [decl('grid-row', '1 / -1')],
    },
  })

  /**
   * @css `grid-row-start`
   */
  functionalUtility('row-start', {
    supportsNegative: true,
    handleBareValue: ({ value }) => {
      if (!isPositiveInteger(value)) return null
      return value
    },
    themeKeys: ['--grid-row-start'],
    handle: (value) => [decl('grid-row-start', value)],
    staticValues: {
      auto: [decl('grid-row-start', 'auto')],
    },
  })

  /**
   * @css `grid-row-end`
   */
  functionalUtility('row-end', {
    supportsNegative: true,
    handleBareValue: ({ value }) => {
      if (!isPositiveInteger(value)) return null
      return value
    },
    themeKeys: ['--grid-row-end'],
    handle: (value) => [decl('grid-row-end', value)],
    staticValues: {
      auto: [decl('grid-row-end', 'auto')],
    },
  })

  suggest('row-span', () => [
    {
      values: Array.from({ length: 12 }, (_, i) => `${i + 1}`),
      valueThemeKeys: [],
    },
  ])

  suggest('row-start', () => [
    {
      supportsNegative: true,
      values: Array.from({ length: 13 }, (_, i) => `${i + 1}`),
      valueThemeKeys: ['--grid-row-start'],
    },
  ])

  suggest('row-end', () => [
    {
      supportsNegative: true,
      values: Array.from({ length: 13 }, (_, i) => `${i + 1}`),
      valueThemeKeys: ['--grid-row-end'],
    },
  ])

  /**
   * @css `float`
   */
  staticUtility('float-start', [['float', 'inline-start']])
  staticUtility('float-end', [['float', 'inline-end']])
  staticUtility('float-right', [['float', 'right']])
  staticUtility('float-left', [['float', 'left']])
  staticUtility('float-none', [['float', 'none']])

  /**
   * @css `clear`
   */
  staticUtility('clear-start', [['clear', 'inline-start']])
  staticUtility('clear-end', [['clear', 'inline-end']])
  staticUtility('clear-right', [['clear', 'right']])
  staticUtility('clear-left', [['clear', 'left']])
  staticUtility('clear-both', [['clear', 'both']])
  staticUtility('clear-none', [['clear', 'none']])

  /**
   * @css `margin`
   */
  for (let [namespace, property] of [
    ['m', 'margin'],
    ['mx', 'margin-inline'],
    ['my', 'margin-block'],
    ['ms', 'margin-inline-start'],
    ['me', 'margin-inline-end'],
    ['mbs', 'margin-block-start'],
    ['mbe', 'margin-block-end'],
    ['mt', 'margin-top'],
    ['mr', 'margin-right'],
    ['mb', 'margin-bottom'],
    ['ml', 'margin-left'],
  ] as const) {
    staticUtility(`${namespace}-auto`, [[property, 'auto']])
    spacingUtility(namespace, ['--margin', '--spacing'], (value) => [decl(property, value)], {
      supportsNegative: true,
    })
  }

  /**
   * @css `box-sizing`
   */
  staticUtility('box-border', [['box-sizing', 'border-box']])
  staticUtility('box-content', [['box-sizing', 'content-box']])

  /**
   * @css `line-clamp`
   */
  functionalUtility('line-clamp', {
    themeKeys: ['--line-clamp'],
    handleBareValue: ({ value }) => {
      if (!isPositiveInteger(value)) return null
      return value
    },
    handle: (value) => [
      decl('overflow', 'hidden'),
      decl('display', '-webkit-box'),
      decl('-webkit-box-orient', 'vertical'),
      decl('-webkit-line-clamp', value),
    ],
    staticValues: {
      none: [
        decl('overflow', 'visible'),
        decl('display', 'block'),
        decl('-webkit-box-orient', 'horizontal'),
        decl('-webkit-line-clamp', 'unset'),
      ],
    },
  })

  suggest('line-clamp', () => [
    {
      values: ['1', '2', '3', '4', '5', '6'],
      valueThemeKeys: ['--line-clamp'],
    },
  ])

  /**
   * @css `display`
   */
  staticUtility('block', [['display', 'block']])
  staticUtility('inline-block', [['display', 'inline-block']])
  staticUtility('inline', [['display', 'inline']])
  staticUtility('hidden', [['display', 'none']])
  // flex is registered below
  staticUtility('inline-flex', [['display', 'inline-flex']])
  staticUtility('table', [['display', 'table']])
  staticUtility('inline-table', [['display', 'inline-table']])
  staticUtility('table-caption', [['display', 'table-caption']])
  staticUtility('table-cell', [['display', 'table-cell']])
  staticUtility('table-column', [['display', 'table-column']])
  staticUtility('table-column-group', [['display', 'table-column-group']])
  staticUtility('table-footer-group', [['display', 'table-footer-group']])
  staticUtility('table-header-group', [['display', 'table-header-group']])
  staticUtility('table-row-group', [['display', 'table-row-group']])
  staticUtility('table-row', [['display', 'table-row']])
  staticUtility('flow-root', [['display', 'flow-root']])
  staticUtility('flex', [['display', 'flex']])
  staticUtility('grid', [['display', 'grid']])
  staticUtility('inline-grid', [['display', 'inline-grid']])
  staticUtility('contents', [['display', 'contents']])
  staticUtility('list-item', [['display', 'list-item']])

  /**
   * @css `field-sizing`
   */
  staticUtility('field-sizing-content', [['field-sizing', 'content']])
  staticUtility('field-sizing-fixed', [['field-sizing', 'fixed']])

  /**
   * @css `aspect-ratio`
   */
  functionalUtility('aspect', {
    themeKeys: ['--aspect'],
    handleBareValue: ({ fraction }) => {
      if (fraction === null) return null
      let [lhs, rhs] = segment(fraction, '/')
      if (!isPositiveInteger(lhs) || !isPositiveInteger(rhs)) return null
      return fraction
    },
    handle: (value) => [decl('aspect-ratio', value)],
    staticValues: {
      auto: [decl('aspect-ratio', 'auto')],
      square: [decl('aspect-ratio', '1 / 1')],
    },
  })

  /**
   * @css `size`
   * @css `width`
   * @css `min-width`
   * @css `max-width`
   * @css `height`
   * @css `min-height`
   * @css `max-height`
   */
  for (let [key, value] of [
    ['full', '100%'],
    ['svw', '100svw'],
    ['lvw', '100lvw'],
    ['dvw', '100dvw'],
    ['svh', '100svh'],
    ['lvh', '100lvh'],
    ['dvh', '100dvh'],
    ['min', 'min-content'],
    ['max', 'max-content'],
    ['fit', 'fit-content'],
  ]) {
    staticUtility(`size-${key}`, [
      ['--tw-sort', 'size'],
      ['width', value],
      ['height', value],
    ])
    staticUtility(`w-${key}`, [['width', value]])
    staticUtility(`h-${key}`, [['height', value]])
    staticUtility(`min-w-${key}`, [['min-width', value]])
    staticUtility(`min-h-${key}`, [['min-height', value]])
    staticUtility(`max-w-${key}`, [['max-width', value]])
    staticUtility(`max-h-${key}`, [['max-height', value]])
  }

  staticUtility(`size-auto`, [
    ['--tw-sort', 'size'],
    ['width', 'auto'],
    ['height', 'auto'],
  ])
  staticUtility(`w-auto`, [['width', 'auto']])
  staticUtility(`h-auto`, [['height', 'auto']])
  staticUtility(`min-w-auto`, [['min-width', 'auto']])
  staticUtility(`min-h-auto`, [['min-height', 'auto']])

  staticUtility(`h-lh`, [['height', '1lh']])
  staticUtility(`min-h-lh`, [['min-height', '1lh']])
  staticUtility(`max-h-lh`, [['max-height', '1lh']])

  staticUtility(`w-screen`, [['width', '100vw']])
  staticUtility(`min-w-screen`, [['min-width', '100vw']])
  staticUtility(`max-w-screen`, [['max-width', '100vw']])
  staticUtility(`h-screen`, [['height', '100vh']])
  staticUtility(`min-h-screen`, [['min-height', '100vh']])
  staticUtility(`max-h-screen`, [['max-height', '100vh']])

  staticUtility(`max-w-none`, [['max-width', 'none']])
  staticUtility(`max-h-none`, [['max-height', 'none']])

  spacingUtility(
    'size',
    ['--size', '--spacing'],
    (value) => [decl('--tw-sort', 'size'), decl('width', value), decl('height', value)],
    {
      supportsFractions: true,
    },
  )

  for (let [name, namespaces, property] of [
    ['w', ['--width', '--spacing', '--container'], 'width'],
    ['min-w', ['--min-width', '--spacing', '--container'], 'min-width'],
    ['max-w', ['--max-width', '--spacing', '--container'], 'max-width'],
    ['h', ['--height', '--spacing'], 'height'],
    ['min-h', ['--min-height', '--height', '--spacing'], 'min-height'],
    ['max-h', ['--max-height', '--height', '--spacing'], 'max-height'],
  ] as [string, ThemeKey[], string][]) {
    spacingUtility(name, namespaces, (value) => [decl(property, value)], {
      supportsFractions: true,
    })
  }

  /**
   * @css `inline-size`
   * @css `min-inline-size`
   * @css `max-inline-size`
   * @css `block-size`
   * @css `min-block-size`
   * @css `max-block-size`
   */
  for (let [key, value] of [
    ['full', '100%'],
    ['min', 'min-content'],
    ['max', 'max-content'],
    ['fit', 'fit-content'],
  ]) {
    staticUtility(`inline-${key}`, [['inline-size', value]])
    staticUtility(`block-${key}`, [['block-size', value]])
    staticUtility(`min-inline-${key}`, [['min-inline-size', value]])
    staticUtility(`min-block-${key}`, [['min-block-size', value]])
    staticUtility(`max-inline-${key}`, [['max-inline-size', value]])
    staticUtility(`max-block-${key}`, [['max-block-size', value]])
  }

  // inline-size viewport units (like width)
  for (let [key, value] of [
    ['svw', '100svw'],
    ['lvw', '100lvw'],
    ['dvw', '100dvw'],
  ]) {
    staticUtility(`inline-${key}`, [['inline-size', value]])
    staticUtility(`min-inline-${key}`, [['min-inline-size', value]])
    staticUtility(`max-inline-${key}`, [['max-inline-size', value]])
  }

  // block-size viewport units (like height)
  for (let [key, value] of [
    ['svh', '100svh'],
    ['lvh', '100lvh'],
    ['dvh', '100dvh'],
  ]) {
    staticUtility(`block-${key}`, [['block-size', value]])
    staticUtility(`min-block-${key}`, [['min-block-size', value]])
    staticUtility(`max-block-${key}`, [['max-block-size', value]])
  }

  staticUtility(`inline-auto`, [['inline-size', 'auto']])
  staticUtility(`block-auto`, [['block-size', 'auto']])
  staticUtility(`min-inline-auto`, [['min-inline-size', 'auto']])
  staticUtility(`min-block-auto`, [['min-block-size', 'auto']])

  staticUtility(`block-lh`, [['block-size', '1lh']])
  staticUtility(`min-block-lh`, [['min-block-size', '1lh']])
  staticUtility(`max-block-lh`, [['max-block-size', '1lh']])

  staticUtility(`inline-screen`, [['inline-size', '100vw']])
  staticUtility(`min-inline-screen`, [['min-inline-size', '100vw']])
  staticUtility(`max-inline-screen`, [['max-inline-size', '100vw']])
  staticUtility(`block-screen`, [['block-size', '100vh']])
  staticUtility(`min-block-screen`, [['min-block-size', '100vh']])
  staticUtility(`max-block-screen`, [['max-block-size', '100vh']])

  staticUtility(`max-inline-none`, [['max-inline-size', 'none']])
  staticUtility(`max-block-none`, [['max-block-size', 'none']])

  for (let [name, namespaces, property] of [
    ['inline', ['--spacing', '--container'], 'inline-size'],
    ['min-inline', ['--spacing', '--container'], 'min-inline-size'],
    ['max-inline', ['--spacing', '--container'], 'max-inline-size'],
    ['block', ['--spacing'], 'block-size'],
    ['min-block', ['--spacing'], 'min-block-size'],
    ['max-block', ['--spacing'], 'max-block-size'],
  ] as [string, ThemeKey[], string][]) {
    spacingUtility(name, namespaces, (value) => [decl(property, value)], {
      supportsFractions: true,
    })
  }

  utilities.static('container', () => {
    let breakpoints = [...theme.namespace('--breakpoint').values()]
    breakpoints.sort((a, z) => compareBreakpoints(a, z, 'asc'))

    let decls: AstNode[] = [decl('--tw-sort', '--tw-container-component'), decl('width', '100%')]
    for (let breakpoint of breakpoints) {
      decls.push(atRule('@media', `(width >= ${breakpoint})`, [decl('max-width', breakpoint)]))
    }

    return decls
  })

  /**
   * @css `flex`
   */
  staticUtility('flex-auto', [['flex', 'auto']])
  staticUtility('flex-initial', [['flex', '0 auto']])
  staticUtility('flex-none', [['flex', 'none']])

  // The `flex` utility generates `display: flex` but utilities like `flex-1`
  // generate `flex: 1`. Our `functionalUtility` helper can't handle two properties
  // using the same namespace, so we handle this one manually.
  utilities.functional('flex', (candidate) => {
    if (!candidate.value) return

    if (candidate.value.kind === 'arbitrary') {
      if (candidate.modifier) return
      return [decl('flex', candidate.value.value)]
    }

    if (candidate.value.fraction) {
      let [lhs, rhs] = segment(candidate.value.fraction, '/')
      if (!isPositiveInteger(lhs) || !isPositiveInteger(rhs)) return
      return [decl('flex', `calc(${candidate.value.fraction} * 100%)`)]
    }

    if (isPositiveInteger(candidate.value.value)) {
      if (candidate.modifier) return
      return [decl('flex', candidate.value.value)]
    }
  })

  suggest('flex', () => [
    { supportsFractions: true },
    { values: Array.from({ length: 12 }, (_, i) => `${i + 1}`) },
  ])

  /**
   * @css `flex-shrink`
   */
  functionalUtility('shrink', {
    defaultValue: '1',
    handleBareValue: ({ value }) => {
      if (!isPositiveInteger(value)) return null
      return value
    },
    handle: (value) => [decl('flex-shrink', value)],
  })

  /**
   * @css `flex-grow`
   */
  functionalUtility('grow', {
    defaultValue: '1',
    handleBareValue: ({ value }) => {
      if (!isPositiveInteger(value)) return null
      return value
    },
    handle: (value) => [decl('flex-grow', value)],
  })

  suggest('shrink', () => [
    {
      values: ['0'],
      valueThemeKeys: [],
      hasDefaultValue: true,
    },
  ])

  suggest('grow', () => [
    {
      values: ['0'],
      valueThemeKeys: [],
      hasDefaultValue: true,
    },
  ])

  /**
   * @css `flex-basis`
   */
  staticUtility('basis-auto', [['flex-basis', 'auto']])
  staticUtility('basis-full', [['flex-basis', '100%']])
  spacingUtility(
    'basis',
    ['--flex-basis', '--spacing', '--container'],
    (value) => [decl('flex-basis', value)],
    {
      supportsFractions: true,
    },
  )

  /**
   * @css `table-layout`
   */
  staticUtility('table-auto', [['table-layout', 'auto']])
  staticUtility('table-fixed', [['table-layout', 'fixed']])

  /**
   * @css `caption-side`
   */
  staticUtility('caption-top', [['caption-side', 'top']])
  staticUtility('caption-bottom', [['caption-side', 'bottom']])

  /**
   * @css `border-collapse`
   */
  staticUtility('border-collapse', [['border-collapse', 'collapse']])
  staticUtility('border-separate', [['border-collapse', 'separate']])

  let borderSpacingProperties = () =>
    atRoot([
      property('--tw-border-spacing-x', '0', '<length>'),
      property('--tw-border-spacing-y', '0', '<length>'),
    ])

  /**
   * @css `border-spacing`
   */
  spacingUtility('border-spacing', ['--border-spacing', '--spacing'], (value) => [
    borderSpacingProperties(),
    decl('--tw-border-spacing-x', value),
    decl('--tw-border-spacing-y', value),
    decl('border-spacing', 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)'),
  ])

  spacingUtility('border-spacing-x', ['--border-spacing', '--spacing'], (value) => [
    borderSpacingProperties(),
    decl('--tw-border-spacing-x', value),
    decl('border-spacing', 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)'),
  ])

  spacingUtility('border-spacing-y', ['--border-spacing', '--spacing'], (value) => [
    borderSpacingProperties(),
    decl('--tw-border-spacing-y', value),
    decl('border-spacing', 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)'),
  ])

  /**
   * @css `transform-origin`
   */
  functionalUtility('origin', {
    themeKeys: ['--transform-origin'],
    handle: (value) => [decl('transform-origin', value)],
    staticValues: {
      center: [decl('transform-origin', 'center')],
      top: [decl('transform-origin', 'top')],
      'top-right': [decl('transform-origin', '100% 0')],
      right: [decl('transform-origin', '100%')],
      'bottom-right': [decl('transform-origin', '100% 100%')],
      bottom: [decl('transform-origin', 'bottom')],
      'bottom-left': [decl('transform-origin', '0 100%')],
      left: [decl('transform-origin', '0')],
      'top-left': [decl('transform-origin', '0 0')],
    },
  })

  functionalUtility('perspective-origin', {
    themeKeys: ['--perspective-origin'],
    handle: (value) => [decl('perspective-origin', value)],
    staticValues: {
      center: [decl('perspective-origin', 'center')],
      top: [decl('perspective-origin', 'top')],
      'top-right': [decl('perspective-origin', '100% 0')],
      right: [decl('perspective-origin', '100%')],
      'bottom-right': [decl('perspective-origin', '100% 100%')],
      bottom: [decl('perspective-origin', 'bottom')],
      'bottom-left': [decl('perspective-origin', '0 100%')],
      left: [decl('perspective-origin', '0')],
      'top-left': [decl('perspective-origin', '0 0')],
    },
  })

  /**
   * @css `perspective`
   */
  functionalUtility('perspective', {
    themeKeys: ['--perspective'],
    handle: (value) => [decl('perspective', value)],
    staticValues: {
      none: [decl('perspective', 'none')],
    },
  })

  let translateProperties = () =>
    atRoot([
      property('--tw-translate-x', '0'),
      property('--tw-translate-y', '0'),
      property('--tw-translate-z', '0'),
    ])

  /**
   * @css `translate`
   */
  staticUtility('translate-none', [['translate', 'none']])
  staticUtility('-translate-full', [
    translateProperties,
    ['--tw-translate-x', '-100%'],
    ['--tw-translate-y', '-100%'],
    ['translate', 'var(--tw-translate-x) var(--tw-translate-y)'],
  ])
  staticUtility('translate-full', [
    translateProperties,
    ['--tw-translate-x', '100%'],
    ['--tw-translate-y', '100%'],
    ['translate', 'var(--tw-translate-x) var(--tw-translate-y)'],
  ])

  spacingUtility(
    'translate',
    ['--translate', '--spacing'],
    (value) => [
      translateProperties(),
      decl('--tw-translate-x', value),
      decl('--tw-translate-y', value),
      decl('translate', 'var(--tw-translate-x) var(--tw-translate-y)'),
    ],
    { supportsNegative: true, supportsFractions: true },
  )

  for (let axis of ['x', 'y']) {
    staticUtility(`-translate-${axis}-full`, [
      translateProperties,
      [`--tw-translate-${axis}`, '-100%'],
      ['translate', `var(--tw-translate-x) var(--tw-translate-y)`],
    ])
    staticUtility(`translate-${axis}-full`, [
      translateProperties,
      [`--tw-translate-${axis}`, '100%'],
      ['translate', `var(--tw-translate-x) var(--tw-translate-y)`],
    ])
    spacingUtility(
      `translate-${axis}`,
      ['--translate', '--spacing'],
      (value) => [
        translateProperties(),
        decl(`--tw-translate-${axis}`, value),
        decl('translate', `var(--tw-translate-x) var(--tw-translate-y)`),
      ],
      {
        supportsNegative: true,
        supportsFractions: true,
      },
    )
  }

  spacingUtility(
    `translate-z`,
    ['--translate', '--spacing'],
    (value) => [
      translateProperties(),
      decl(`--tw-translate-z`, value),
      decl('translate', 'var(--tw-translate-x) var(--tw-translate-y) var(--tw-translate-z)'),
    ],
    {
      supportsNegative: true,
    },
  )

  staticUtility('translate-3d', [
    translateProperties,
    ['translate', 'var(--tw-translate-x) var(--tw-translate-y) var(--tw-translate-z)'],
  ])

  let scaleProperties = () =>
    atRoot([
      property('--tw-scale-x', '1'),
      property('--tw-scale-y', '1'),
      property('--tw-scale-z', '1'),
    ])

  /**
   * @css `scale`
   */
  staticUtility('scale-none', [['scale', 'none']])
  function handleScale({ negative }: { negative: boolean }) {
    return (candidate: Extract<Candidate, { kind: 'functional' }>) => {
      if (!candidate.value || candidate.modifier) return

      let value
      if (candidate.value.kind === 'arbitrary') {
        value = candidate.value.value
        value = negative ? `calc(${value} * -1)` : value
        return [decl('scale', value)]
      } else {
        value = theme.resolve(candidate.value.value, ['--scale'])
        if (!value && isPositiveInteger(candidate.value.value)) {
          value = `${candidate.value.value}%`
        }
        if (!value) return
      }
      value = negative ? `calc(${value} * -1)` : value
      return [
        scaleProperties(),
        decl('--tw-scale-x', value),
        decl('--tw-scale-y', value),
        decl('--tw-scale-z', value),
        decl('scale', `var(--tw-scale-x) var(--tw-scale-y)`),
      ]
    }
  }
  utilities.functional('-scale', handleScale({ negative: true }))
  utilities.functional('scale', handleScale({ negative: false }))

  suggest('scale', () => [
    {
      supportsNegative: true,
      values: ['0', '50', '75', '90', '95', '100', '105', '110', '125', '150', '200'],
      valueThemeKeys: ['--scale'],
    },
  ])

  for (let axis of ['x', 'y', 'z']) {
    /**
     * @css `scale`
     */
    functionalUtility(`scale-${axis}`, {
      supportsNegative: true,
      themeKeys: ['--scale'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}%`
      },
      handle: (value) => [
        scaleProperties(),
        decl(`--tw-scale-${axis}`, value),
        decl(
          'scale',
          `var(--tw-scale-x) var(--tw-scale-y)${axis === 'z' ? ' var(--tw-scale-z)' : ''}`,
        ),
      ],
    })

    suggest(`scale-${axis}`, () => [
      {
        supportsNegative: true,
        values: ['0', '50', '75', '90', '95', '100', '105', '110', '125', '150', '200'],
        valueThemeKeys: ['--scale'],
      },
    ])
  }

  /**
   * @css `scale`
   */
  staticUtility('scale-3d', [
    scaleProperties,
    ['scale', 'var(--tw-scale-x) var(--tw-scale-y) var(--tw-scale-z)'],
  ])

  /**
   * @css `rotate`
   *
   * `rotate-45` => `rotate: 45deg`
   * `rotate-[x_45deg]` => `rotate: x 45deg`
   * `rotate-[1_2_3_45deg]` => `rotate: 1 2 3 45deg`
   */
  staticUtility('rotate-none', [['rotate', 'none']])

  function handleRotate({ negative }: { negative: boolean }) {
    return (candidate: Extract<Candidate, { kind: 'functional' }>) => {
      if (!candidate.value || candidate.modifier) return

      let value
      if (candidate.value.kind === 'arbitrary') {
        value = candidate.value.value
        let type = candidate.value.dataType ?? inferDataType(value, ['angle', 'vector'])
        if (type === 'vector') {
          return [decl('rotate', `${value} var(--tw-rotate)`)]
        } else if (type !== 'angle') {
          return [decl('rotate', negative ? `calc(${value} * -1)` : value)]
        }
      } else {
        value = theme.resolve(candidate.value.value, ['--rotate'])
        if (!value && isPositiveInteger(candidate.value.value)) {
          value = `${candidate.value.value}deg`
        }
        if (!value) return
      }
      return [decl('rotate', negative ? `calc(${value} * -1)` : value)]
    }
  }

  utilities.functional('-rotate', handleRotate({ negative: true }))
  utilities.functional('rotate', handleRotate({ negative: false }))

  suggest('rotate', () => [
    {
      supportsNegative: true,
      values: ['0', '1', '2', '3', '6', '12', '45', '90', '180'],
      valueThemeKeys: ['--rotate'],
    },
  ])

  {
    let transformValue = [
      'var(--tw-rotate-x,)',
      'var(--tw-rotate-y,)',
      'var(--tw-rotate-z,)',
      'var(--tw-skew-x,)',
      'var(--tw-skew-y,)',
    ].join(' ')

    let transformProperties = () =>
      atRoot([
        property('--tw-rotate-x'),
        property('--tw-rotate-y'),
        property('--tw-rotate-z'),
        property('--tw-skew-x'),
        property('--tw-skew-y'),
      ])

    for (let axis of ['x', 'y', 'z']) {
      functionalUtility(`rotate-${axis}`, {
        supportsNegative: true,
        themeKeys: ['--rotate'],
        handleBareValue: ({ value }) => {
          if (!isPositiveInteger(value)) return null
          return `${value}deg`
        },
        handle: (value) => [
          transformProperties(),
          decl(`--tw-rotate-${axis}`, `rotate${axis.toUpperCase()}(${value})`),
          decl('transform', transformValue),
        ],
      })

      suggest(`rotate-${axis}`, () => [
        {
          supportsNegative: true,
          values: ['0', '1', '2', '3', '6', '12', '45', '90', '180'],
          valueThemeKeys: ['--rotate'],
        },
      ])
    }

    /**
     * @css `transform`
     * @css `skew()`
     */
    functionalUtility('skew', {
      supportsNegative: true,
      themeKeys: ['--skew'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}deg`
      },
      handle: (value) => [
        transformProperties(),
        decl('--tw-skew-x', `skewX(${value})`),
        decl('--tw-skew-y', `skewY(${value})`),
        decl('transform', transformValue),
      ],
    })

    /**
     * @css `transform`
     * @css `skew()`
     */
    functionalUtility('skew-x', {
      supportsNegative: true,
      themeKeys: ['--skew'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}deg`
      },
      handle: (value) => [
        transformProperties(),
        decl('--tw-skew-x', `skewX(${value})`),
        decl('transform', transformValue),
      ],
    })

    /**
     * @css `transform`
     * @css `skew()`
     */
    functionalUtility('skew-y', {
      supportsNegative: true,
      themeKeys: ['--skew'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}deg`
      },
      handle: (value) => [
        transformProperties(),
        decl('--tw-skew-y', `skewY(${value})`),
        decl('transform', transformValue),
      ],
    })

    suggest('skew', () => [
      {
        supportsNegative: true,
        values: ['0', '1', '2', '3', '6', '12'],
        valueThemeKeys: ['--skew'],
      },
    ])

    suggest('skew-x', () => [
      {
        supportsNegative: true,
        values: ['0', '1', '2', '3', '6', '12'],
        valueThemeKeys: ['--skew'],
      },
    ])

    suggest('skew-y', () => [
      {
        supportsNegative: true,
        values: ['0', '1', '2', '3', '6', '12'],
        valueThemeKeys: ['--skew'],
      },
    ])

    /**
     * @css `transform`
     */
    utilities.functional('transform', (candidate) => {
      if (candidate.modifier) return

      let value: string | null = null
      if (!candidate.value) {
        value = transformValue
      } else if (candidate.value.kind === 'arbitrary') {
        value = candidate.value.value
      }

      if (value === null) return

      return [transformProperties(), decl('transform', value)]
    })
    suggest('transform', () => [
      {
        hasDefaultValue: true,
      },
    ])

    staticUtility('transform-cpu', [['transform', transformValue]])
    staticUtility('transform-gpu', [['transform', `translateZ(0) ${transformValue}`]])
    staticUtility('transform-none', [['transform', 'none']])
  }

  /**
   * @css `transform-style`
   */
  staticUtility('transform-flat', [['transform-style', 'flat']])
  staticUtility('transform-3d', [['transform-style', 'preserve-3d']])

  /**
   * @css `transform-box`
   */
  staticUtility('transform-content', [['transform-box', 'content-box']])
  staticUtility('transform-border', [['transform-box', 'border-box']])
  staticUtility('transform-fill', [['transform-box', 'fill-box']])
  staticUtility('transform-stroke', [['transform-box', 'stroke-box']])
  staticUtility('transform-view', [['transform-box', 'view-box']])

  /**
   * @css `backface-visibility`
   */
  staticUtility('backface-visible', [['backface-visibility', 'visible']])
  staticUtility('backface-hidden', [['backface-visibility', 'hidden']])

  /**
   * @css `cursor`
   */
  for (let value of [
    'auto',
    'default',
    'pointer',
    'wait',
    'text',
    'move',
    'help',
    'not-allowed',
    'none',
    'context-menu',
    'progress',
    'cell',
    'crosshair',
    'vertical-text',
    'alias',
    'copy',
    'no-drop',
    'grab',
    'grabbing',
    'all-scroll',
    'col-resize',
    'row-resize',
    'n-resize',
    'e-resize',
    's-resize',
    'w-resize',
    'ne-resize',
    'nw-resize',
    'se-resize',
    'sw-resize',
    'ew-resize',
    'ns-resize',
    'nesw-resize',
    'nwse-resize',
    'zoom-in',
    'zoom-out',
  ]) {
    staticUtility(`cursor-${value}`, [['cursor', value]])
  }

  functionalUtility('cursor', {
    themeKeys: ['--cursor'],
    handle: (value) => [decl('cursor', value)],
  })

  /**
   * @css `touch-action`
   */
  for (let value of ['auto', 'none', 'manipulation']) {
    staticUtility(`touch-${value}`, [['touch-action', value]])
  }

  let touchProperties = () =>
    atRoot([property('--tw-pan-x'), property('--tw-pan-y'), property('--tw-pinch-zoom')])

  for (let value of ['x', 'left', 'right']) {
    staticUtility(`touch-pan-${value}`, [
      touchProperties,
      ['--tw-pan-x', `pan-${value}`],
      ['touch-action', 'var(--tw-pan-x,) var(--tw-pan-y,) var(--tw-pinch-zoom,)'],
    ])
  }

  for (let value of ['y', 'up', 'down']) {
    staticUtility(`touch-pan-${value}`, [
      touchProperties,
      ['--tw-pan-y', `pan-${value}`],
      ['touch-action', 'var(--tw-pan-x,) var(--tw-pan-y,) var(--tw-pinch-zoom,)'],
    ])
  }

  staticUtility('touch-pinch-zoom', [
    touchProperties,
    ['--tw-pinch-zoom', `pinch-zoom`],
    ['touch-action', 'var(--tw-pan-x,) var(--tw-pan-y,) var(--tw-pinch-zoom,)'],
  ])

  /**
   * @css `user-select`
   */
  for (let value of ['none', 'text', 'all', 'auto']) {
    staticUtility(`select-${value}`, [
      ['-webkit-user-select', value],
      ['user-select', value],
    ])
  }

  /**
   * @css `resize`
   */
  staticUtility('resize-none', [['resize', 'none']])
  staticUtility('resize-x', [['resize', 'horizontal']])
  staticUtility('resize-y', [['resize', 'vertical']])
  staticUtility('resize', [['resize', 'both']])

  /**
   * @css `scroll-snap-type`
   */
  staticUtility('snap-none', [['scroll-snap-type', 'none']])

  let snapProperties = () => atRoot([property('--tw-scroll-snap-strictness', 'proximity', '*')])

  for (let value of ['x', 'y', 'both']) {
    staticUtility(`snap-${value}`, [
      snapProperties,
      ['scroll-snap-type', `${value} var(--tw-scroll-snap-strictness)`],
    ])
  }

  staticUtility('snap-mandatory', [snapProperties, ['--tw-scroll-snap-strictness', 'mandatory']])

  staticUtility('snap-proximity', [snapProperties, ['--tw-scroll-snap-strictness', 'proximity']])

  staticUtility('snap-align-none', [['scroll-snap-align', 'none']])
  staticUtility('snap-start', [['scroll-snap-align', 'start']])
  staticUtility('snap-end', [['scroll-snap-align', 'end']])
  staticUtility('snap-center', [['scroll-snap-align', 'center']])

  staticUtility('snap-normal', [['scroll-snap-stop', 'normal']])
  staticUtility('snap-always', [['scroll-snap-stop', 'always']])

  /**
   * @css `scroll-margin`
   */
  for (let [namespace, property] of [
    ['scroll-m', 'scroll-margin'],
    ['scroll-mx', 'scroll-margin-inline'],
    ['scroll-my', 'scroll-margin-block'],
    ['scroll-ms', 'scroll-margin-inline-start'],
    ['scroll-me', 'scroll-margin-inline-end'],
    ['scroll-mbs', 'scroll-margin-block-start'],
    ['scroll-mbe', 'scroll-margin-block-end'],
    ['scroll-mt', 'scroll-margin-top'],
    ['scroll-mr', 'scroll-margin-right'],
    ['scroll-mb', 'scroll-margin-bottom'],
    ['scroll-ml', 'scroll-margin-left'],
  ] as const) {
    spacingUtility(
      namespace,
      ['--scroll-margin', '--spacing'],
      (value) => [decl(property, value)],
      {
        supportsNegative: true,
      },
    )
  }

  /**
   * @css `scroll-padding`
   */
  for (let [namespace, property] of [
    ['scroll-p', 'scroll-padding'],
    ['scroll-px', 'scroll-padding-inline'],
    ['scroll-py', 'scroll-padding-block'],
    ['scroll-ps', 'scroll-padding-inline-start'],
    ['scroll-pe', 'scroll-padding-inline-end'],
    ['scroll-pbs', 'scroll-padding-block-start'],
    ['scroll-pbe', 'scroll-padding-block-end'],
    ['scroll-pt', 'scroll-padding-top'],
    ['scroll-pr', 'scroll-padding-right'],
    ['scroll-pb', 'scroll-padding-bottom'],
    ['scroll-pl', 'scroll-padding-left'],
  ] as const) {
    spacingUtility(namespace, ['--scroll-padding', '--spacing'], (value) => [decl(property, value)])
  }

  staticUtility('list-inside', [['list-style-position', 'inside']])
  staticUtility('list-outside', [['list-style-position', 'outside']])

  functionalUtility('list', {
    themeKeys: ['--list-style-type'],
    handle: (value) => [decl('list-style-type', value)],
    staticValues: {
      none: [decl('list-style-type', 'none')],
      disc: [decl('list-style-type', 'disc')],
      decimal: [decl('list-style-type', 'decimal')],
    },
  })

  // list-image-*

  functionalUtility('list-image', {
    themeKeys: ['--list-style-image'],
    handle: (value) => [decl('list-style-image', value)],
    staticValues: {
      none: [decl('list-style-image', 'none')],
    },
  })

  staticUtility('appearance-none', [['appearance', 'none']])
  staticUtility('appearance-auto', [['appearance', 'auto']])

  staticUtility('scheme-normal', [['color-scheme', 'normal']])
  staticUtility('scheme-dark', [['color-scheme', 'dark']])
  staticUtility('scheme-light', [['color-scheme', 'light']])
  staticUtility('scheme-light-dark', [['color-scheme', 'light dark']])
  staticUtility('scheme-only-dark', [['color-scheme', 'only dark']])
  staticUtility('scheme-only-light', [['color-scheme', 'only light']])

  functionalUtility('columns', {
    themeKeys: ['--columns', '--container'],
    handleBareValue: ({ value }) => {
      if (!isPositiveInteger(value)) return null
      return value
    },
    handle: (value) => [decl('columns', value)],
    staticValues: {
      auto: [decl('columns', 'auto')],
    },
  })

  suggest('columns', () => [
    {
      values: Array.from({ length: 12 }, (_, i) => `${i + 1}`),
      valueThemeKeys: ['--columns', '--container'],
    },
  ])

  for (let value of ['auto', 'avoid', 'all', 'avoid-page', 'page', 'left', 'right', 'column']) {
    staticUtility(`break-before-${value}`, [['break-before', value]])
  }

  for (let value of ['auto', 'avoid', 'avoid-page', 'avoid-column']) {
    staticUtility(`break-inside-${value}`, [['break-inside', value]])
  }

  for (let value of ['auto', 'avoid', 'all', 'avoid-page', 'page', 'left', 'right', 'column']) {
    staticUtility(`break-after-${value}`, [['break-after', value]])
  }

  staticUtility('grid-flow-row', [['grid-auto-flow', 'row']])
  staticUtility('grid-flow-col', [['grid-auto-flow', 'column']])
  staticUtility('grid-flow-dense', [['grid-auto-flow', 'dense']])
  staticUtility('grid-flow-row-dense', [['grid-auto-flow', 'row dense']])
  staticUtility('grid-flow-col-dense', [['grid-auto-flow', 'column dense']])

  functionalUtility('auto-cols', {
    themeKeys: ['--grid-auto-columns'],
    handle: (value) => [decl('grid-auto-columns', value)],
    staticValues: {
      auto: [decl('grid-auto-columns', 'auto')],
      min: [decl('grid-auto-columns', 'min-content')],
      max: [decl('grid-auto-columns', 'max-content')],
      fr: [decl('grid-auto-columns', 'minmax(0, 1fr)')],
    },
  })

  functionalUtility('auto-rows', {
    themeKeys: ['--grid-auto-rows'],
    handle: (value) => [decl('grid-auto-rows', value)],
    staticValues: {
      auto: [decl('grid-auto-rows', 'auto')],
      min: [decl('grid-auto-rows', 'min-content')],
      max: [decl('grid-auto-rows', 'max-content')],
      fr: [decl('grid-auto-rows', 'minmax(0, 1fr)')],
    },
  })

  functionalUtility('grid-cols', {
    themeKeys: ['--grid-template-columns'],
    handleBareValue: ({ value }) => {
      if (!isStrictPositiveInteger(value)) return null
      return `repeat(${value}, minmax(0, 1fr))`
    },
    handle: (value) => [decl('grid-template-columns', value)],
    staticValues: {
      none: [decl('grid-template-columns', 'none')],
      subgrid: [decl('grid-template-columns', 'subgrid')],
    },
  })

  functionalUtility('grid-rows', {
    themeKeys: ['--grid-template-rows'],
    handleBareValue: ({ value }) => {
      if (!isStrictPositiveInteger(value)) return null
      return `repeat(${value}, minmax(0, 1fr))`
    },
    handle: (value) => [decl('grid-template-rows', value)],
    staticValues: {
      none: [decl('grid-template-rows', 'none')],
      subgrid: [decl('grid-template-rows', 'subgrid')],
    },
  })

  suggest('grid-cols', () => [
    {
      values: Array.from({ length: 12 }, (_, i) => `${i + 1}`),
      valueThemeKeys: ['--grid-template-columns'],
    },
  ])

  suggest('grid-rows', () => [
    {
      values: Array.from({ length: 12 }, (_, i) => `${i + 1}`),
      valueThemeKeys: ['--grid-template-rows'],
    },
  ])

  staticUtility('flex-row', [['flex-direction', 'row']])
  staticUtility('flex-row-reverse', [['flex-direction', 'row-reverse']])
  staticUtility('flex-col', [['flex-direction', 'column']])
  staticUtility('flex-col-reverse', [['flex-direction', 'column-reverse']])

  staticUtility('flex-wrap', [['flex-wrap', 'wrap']])
  staticUtility('flex-nowrap', [['flex-wrap', 'nowrap']])
  staticUtility('flex-wrap-reverse', [['flex-wrap', 'wrap-reverse']])

  staticUtility('place-content-center', [['place-content', 'center']])
  staticUtility('place-content-start', [['place-content', 'start']])
  staticUtility('place-content-end', [['place-content', 'end']])
  staticUtility('place-content-center-safe', [['place-content', 'safe center']])
  staticUtility('place-content-end-safe', [['place-content', 'safe end']])
  staticUtility('place-content-between', [['place-content', 'space-between']])
  staticUtility('place-content-around', [['place-content', 'space-around']])
  staticUtility('place-content-evenly', [['place-content', 'space-evenly']])
  staticUtility('place-content-baseline', [['place-content', 'baseline']])
  staticUtility('place-content-stretch', [['place-content', 'stretch']])

  staticUtility('place-items-center', [['place-items', 'center']])
  staticUtility('place-items-start', [['place-items', 'start']])
  staticUtility('place-items-end', [['place-items', 'end']])
  staticUtility('place-items-center-safe', [['place-items', 'safe center']])
  staticUtility('place-items-end-safe', [['place-items', 'safe end']])
  staticUtility('place-items-baseline', [['place-items', 'baseline']])
  staticUtility('place-items-stretch', [['place-items', 'stretch']])

  staticUtility('content-normal', [['align-content', 'normal']])
  staticUtility('content-center', [['align-content', 'center']])
  staticUtility('content-start', [['align-content', 'flex-start']])
  staticUtility('content-end', [['align-content', 'flex-end']])
  staticUtility('content-center-safe', [['align-content', 'safe center']])
  staticUtility('content-end-safe', [['align-content', 'safe flex-end']])
  staticUtility('content-between', [['align-content', 'space-between']])
  staticUtility('content-around', [['align-content', 'space-around']])
  staticUtility('content-evenly', [['align-content', 'space-evenly']])
  staticUtility('content-baseline', [['align-content', 'baseline']])
  staticUtility('content-stretch', [['align-content', 'stretch']])

  staticUtility('items-center', [['align-items', 'center']])
  staticUtility('items-start', [['align-items', 'flex-start']])
  staticUtility('items-end', [['align-items', 'flex-end']])
  staticUtility('items-center-safe', [['align-items', 'safe center']])
  staticUtility('items-end-safe', [['align-items', 'safe flex-end']])
  staticUtility('items-baseline', [['align-items', 'baseline']])
  staticUtility('items-baseline-last', [['align-items', 'last baseline']])
  staticUtility('items-stretch', [['align-items', 'stretch']])

  staticUtility('justify-normal', [['justify-content', 'normal']])
  staticUtility('justify-center', [['justify-content', 'center']])
  staticUtility('justify-start', [['justify-content', 'flex-start']])
  staticUtility('justify-end', [['justify-content', 'flex-end']])
  staticUtility('justify-center-safe', [['justify-content', 'safe center']])
  staticUtility('justify-end-safe', [['justify-content', 'safe flex-end']])
  staticUtility('justify-between', [['justify-content', 'space-between']])
  staticUtility('justify-around', [['justify-content', 'space-around']])
  staticUtility('justify-evenly', [['justify-content', 'space-evenly']])
  staticUtility('justify-baseline', [['justify-content', 'baseline']])
  staticUtility('justify-stretch', [['justify-content', 'stretch']])

  staticUtility('justify-items-normal', [['justify-items', 'normal']])
  staticUtility('justify-items-center', [['justify-items', 'center']])
  staticUtility('justify-items-start', [['justify-items', 'start']])
  staticUtility('justify-items-end', [['justify-items', 'end']])
  staticUtility('justify-items-center-safe', [['justify-items', 'safe center']])
  staticUtility('justify-items-end-safe', [['justify-items', 'safe end']])
  staticUtility('justify-items-stretch', [['justify-items', 'stretch']])

  spacingUtility('gap', ['--gap', '--spacing'], (value) => [decl('gap', value)])
  spacingUtility('gap-x', ['--gap', '--spacing'], (value) => [decl('column-gap', value)])
  spacingUtility('gap-y', ['--gap', '--spacing'], (value) => [decl('row-gap', value)])

  spacingUtility(
    'space-x',
    ['--space', '--spacing'],
    (value) => [
      atRoot([property('--tw-space-x-reverse', '0')]),

      styleRule(':where(& > :not(:last-child))', [
        decl('--tw-sort', 'row-gap'),
        decl('--tw-space-x-reverse', '0'),
        decl('margin-inline-start', `calc(${value} * var(--tw-space-x-reverse))`),
        decl('margin-inline-end', `calc(${value} * calc(1 - var(--tw-space-x-reverse)))`),
      ]),
    ],
    { supportsNegative: true },
  )

  spacingUtility(
    'space-y',
    ['--space', '--spacing'],
    (value) => [
      atRoot([property('--tw-space-y-reverse', '0')]),
      styleRule(':where(& > :not(:last-child))', [
        decl('--tw-sort', 'column-gap'),
        decl('--tw-space-y-reverse', '0'),
        decl('margin-block-start', `calc(${value} * var(--tw-space-y-reverse))`),
        decl('margin-block-end', `calc(${value} * calc(1 - var(--tw-space-y-reverse)))`),
      ]),
    ],
    { supportsNegative: true },
  )

  staticUtility('space-x-reverse', [
    () => atRoot([property('--tw-space-x-reverse', '0')]),
    () =>
      styleRule(':where(& > :not(:last-child))', [
        decl('--tw-sort', 'row-gap'),
        decl('--tw-space-x-reverse', '1'),
      ]),
  ])

  staticUtility('space-y-reverse', [
    () => atRoot([property('--tw-space-y-reverse', '0')]),
    () =>
      styleRule(':where(& > :not(:last-child))', [
        decl('--tw-sort', 'column-gap'),
        decl('--tw-space-y-reverse', '1'),
      ]),
  ])

  staticUtility('accent-auto', [['accent-color', 'auto']])
  colorUtility('accent', {
    themeKeys: ['--accent-color', '--color'],
    handle: (value) => [decl('accent-color', value)],
  })

  colorUtility('caret', {
    themeKeys: ['--caret-color', '--color'],
    handle: (value) => [decl('caret-color', value)],
  })

  colorUtility('divide', {
    themeKeys: ['--divide-color', '--border-color', '--color'],
    handle: (value) => [
      styleRule(':where(& > :not(:last-child))', [
        decl('--tw-sort', 'divide-color'),
        decl('border-color', value),
      ]),
    ],
  })

  staticUtility('place-self-auto', [['place-self', 'auto']])
  staticUtility('place-self-start', [['place-self', 'start']])
  staticUtility('place-self-end', [['place-self', 'end']])
  staticUtility('place-self-center', [['place-self', 'center']])
  staticUtility('place-self-end-safe', [['place-self', 'safe end']])
  staticUtility('place-self-center-safe', [['place-self', 'safe center']])
  staticUtility('place-self-stretch', [['place-self', 'stretch']])

  staticUtility('self-auto', [['align-self', 'auto']])
  staticUtility('self-start', [['align-self', 'flex-start']])
  staticUtility('self-end', [['align-self', 'flex-end']])
  staticUtility('self-center', [['align-self', 'center']])
  staticUtility('self-end-safe', [['align-self', 'safe flex-end']])
  staticUtility('self-center-safe', [['align-self', 'safe center']])
  staticUtility('self-stretch', [['align-self', 'stretch']])
  staticUtility('self-baseline', [['align-self', 'baseline']])
  staticUtility('self-baseline-last', [['align-self', 'last baseline']])

  staticUtility('justify-self-auto', [['justify-self', 'auto']])
  staticUtility('justify-self-start', [['justify-self', 'flex-start']])
  staticUtility('justify-self-end', [['justify-self', 'flex-end']])
  staticUtility('justify-self-center', [['justify-self', 'center']])
  staticUtility('justify-self-end-safe', [['justify-self', 'safe flex-end']])
  staticUtility('justify-self-center-safe', [['justify-self', 'safe center']])
  staticUtility('justify-self-stretch', [['justify-self', 'stretch']])

  for (let value of ['auto', 'hidden', 'clip', 'visible', 'scroll']) {
    staticUtility(`overflow-${value}`, [['overflow', value]])
    staticUtility(`overflow-x-${value}`, [['overflow-x', value]])
    staticUtility(`overflow-y-${value}`, [['overflow-y', value]])
  }

  for (let value of ['auto', 'contain', 'none']) {
    staticUtility(`overscroll-${value}`, [['overscroll-behavior', value]])
    staticUtility(`overscroll-x-${value}`, [['overscroll-behavior-x', value]])
    staticUtility(`overscroll-y-${value}`, [['overscroll-behavior-y', value]])
  }

  staticUtility('scroll-auto', [['scroll-behavior', 'auto']])
  staticUtility('scroll-smooth', [['scroll-behavior', 'smooth']])

  staticUtility('truncate', [
    ['overflow', 'hidden'],
    ['text-overflow', 'ellipsis'],
    ['white-space', 'nowrap'],
  ])

  staticUtility('text-ellipsis', [['text-overflow', 'ellipsis']])
  staticUtility('text-clip', [['text-overflow', 'clip']])

  staticUtility('hyphens-none', [
    ['-webkit-hyphens', 'none'],
    ['hyphens', 'none'],
  ])
  staticUtility('hyphens-manual', [
    ['-webkit-hyphens', 'manual'],
    ['hyphens', 'manual'],
  ])
  staticUtility('hyphens-auto', [
    ['-webkit-hyphens', 'auto'],
    ['hyphens', 'auto'],
  ])

  staticUtility('whitespace-normal', [['white-space', 'normal']])
  staticUtility('whitespace-nowrap', [['white-space', 'nowrap']])
  staticUtility('whitespace-pre', [['white-space', 'pre']])
  staticUtility('whitespace-pre-line', [['white-space', 'pre-line']])
  staticUtility('whitespace-pre-wrap', [['white-space', 'pre-wrap']])
  staticUtility('whitespace-break-spaces', [['white-space', 'break-spaces']])

  staticUtility('text-wrap', [['text-wrap', 'wrap']])
  staticUtility('text-nowrap', [['text-wrap', 'nowrap']])
  staticUtility('text-balance', [['text-wrap', 'balance']])
  staticUtility('text-pretty', [['text-wrap', 'pretty']])
  staticUtility('break-normal', [
    ['overflow-wrap', 'normal'],
    ['word-break', 'normal'],
  ])
  staticUtility('break-all', [['word-break', 'break-all']])
  staticUtility('break-keep', [['word-break', 'keep-all']])

  staticUtility('wrap-anywhere', [['overflow-wrap', 'anywhere']])
  staticUtility('wrap-break-word', [['overflow-wrap', 'break-word']])
  staticUtility('wrap-normal', [['overflow-wrap', 'normal']])

  {
    // border-radius
    for (let [root, properties] of [
      ['rounded', ['border-radius']],
      ['rounded-s', ['border-start-start-radius', 'border-end-start-radius']],
      ['rounded-e', ['border-start-end-radius', 'border-end-end-radius']],
      ['rounded-t', ['border-top-left-radius', 'border-top-right-radius']],
      ['rounded-r', ['border-top-right-radius', 'border-bottom-right-radius']],
      ['rounded-b', ['border-bottom-right-radius', 'border-bottom-left-radius']],
      ['rounded-l', ['border-top-left-radius', 'border-bottom-left-radius']],
      ['rounded-ss', ['border-start-start-radius']],
      ['rounded-se', ['border-start-end-radius']],
      ['rounded-ee', ['border-end-end-radius']],
      ['rounded-es', ['border-end-start-radius']],
      ['rounded-tl', ['border-top-left-radius']],
      ['rounded-tr', ['border-top-right-radius']],
      ['rounded-br', ['border-bottom-right-radius']],
      ['rounded-bl', ['border-bottom-left-radius']],
    ] as const) {
      functionalUtility(root, {
        themeKeys: ['--radius'],
        handle: (value) => properties.map((property) => decl(property, value)),
        staticValues: {
          none: properties.map((property) => decl(property, '0')),
          full: properties.map((property) => decl(property, 'calc(infinity * 1px)')),
        },
      })
    }
  }

  staticUtility('border-solid', [
    ['--tw-border-style', 'solid'],
    ['border-style', 'solid'],
  ])
  staticUtility('border-dashed', [
    ['--tw-border-style', 'dashed'],
    ['border-style', 'dashed'],
  ])
  staticUtility('border-dotted', [
    ['--tw-border-style', 'dotted'],
    ['border-style', 'dotted'],
  ])
  staticUtility('border-double', [
    ['--tw-border-style', 'double'],
    ['border-style', 'double'],
  ])
  staticUtility('border-hidden', [
    ['--tw-border-style', 'hidden'],
    ['border-style', 'hidden'],
  ])
  staticUtility('border-none', [
    ['--tw-border-style', 'none'],
    ['border-style', 'none'],
  ])

  {
    // border-* (color)
    type BorderDescription = {
      width: (value: string) => AstNode[] | undefined
      color: (value: string) => AstNode[] | undefined
    }

    let borderProperties = () => {
      return atRoot([property('--tw-border-style', 'solid')])
    }

    function borderSideUtility(classRoot: string, desc: BorderDescription) {
      utilities.functional(classRoot, (candidate) => {
        if (!candidate.value) {
          if (candidate.modifier) return
          let value = theme.get(['--default-border-width']) ?? '1px'
          let decls = desc.width(value)
          if (!decls) return
          return [borderProperties(), ...decls]
        }

        if (candidate.value.kind === 'arbitrary') {
          let value: string | null = candidate.value.value
          let type =
            candidate.value.dataType ?? inferDataType(value, ['color', 'line-width', 'length'])

          switch (type) {
            case 'line-width':
            case 'length': {
              if (candidate.modifier) return
              let decls = desc.width(value)
              if (!decls) return
              return [borderProperties(), ...decls]
            }
            default: {
              value = asColor(value, candidate.modifier, theme)
              if (value === null) return

              return desc.color(value)
            }
          }
        }

        // `border-color` property
        {
          let value = resolveThemeColor(candidate, theme, ['--border-color', '--color'])
          if (value) {
            return desc.color(value)
          }
        }

        // `border-width` property
        {
          if (candidate.modifier) return
          let value = theme.resolve(candidate.value.value, ['--border-width'])
          if (value) {
            let decls = desc.width(value)
            if (!decls) return
            return [borderProperties(), ...decls]
          }

          if (isPositiveInteger(candidate.value.value)) {
            let decls = desc.width(`${candidate.value.value}px`)
            if (!decls) return
            return [borderProperties(), ...decls]
          }
        }
      })

      suggest(classRoot, () => [
        {
          values: ['current', 'inherit', 'transparent'],
          valueThemeKeys: ['--border-color', '--color'],
          modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
          hasDefaultValue: true,
        },
        {
          values: ['0', '2', '4', '8'],
          valueThemeKeys: ['--border-width'],
        },
      ])
    }

    borderSideUtility('border', {
      width: (value) => [
        decl('border-style', 'var(--tw-border-style)'),
        decl('border-width', value),
      ],
      color: (value) => [decl('border-color', value)],
    })

    borderSideUtility('border-x', {
      width: (value) => [
        decl('border-inline-style', 'var(--tw-border-style)'),
        decl('border-inline-width', value),
      ],
      color: (value) => [decl('border-inline-color', value)],
    })

    borderSideUtility('border-y', {
      width: (value) => [
        decl('border-block-style', 'var(--tw-border-style)'),
        decl('border-block-width', value),
      ],
      color: (value) => [decl('border-block-color', value)],
    })

    borderSideUtility('border-s', {
      width: (value) => [
        decl('border-inline-start-style', 'var(--tw-border-style)'),
        decl('border-inline-start-width', value),
      ],
      color: (value) => [decl('border-inline-start-color', value)],
    })

    borderSideUtility('border-e', {
      width: (value) => [
        decl('border-inline-end-style', 'var(--tw-border-style)'),
        decl('border-inline-end-width', value),
      ],
      color: (value) => [decl('border-inline-end-color', value)],
    })

    borderSideUtility('border-bs', {
      width: (value) => [
        decl('border-block-start-style', 'var(--tw-border-style)'),
        decl('border-block-start-width', value),
      ],
      color: (value) => [decl('border-block-start-color', value)],
    })

    borderSideUtility('border-be', {
      width: (value) => [
        decl('border-block-end-style', 'var(--tw-border-style)'),
        decl('border-block-end-width', value),
      ],
      color: (value) => [decl('border-block-end-color', value)],
    })

    borderSideUtility('border-t', {
      width: (value) => [
        decl('border-top-style', 'var(--tw-border-style)'),
        decl('border-top-width', value),
      ],
      color: (value) => [decl('border-top-color', value)],
    })

    borderSideUtility('border-r', {
      width: (value) => [
        decl('border-right-style', 'var(--tw-border-style)'),
        decl('border-right-width', value),
      ],
      color: (value) => [decl('border-right-color', value)],
    })

    borderSideUtility('border-b', {
      width: (value) => [
        decl('border-bottom-style', 'var(--tw-border-style)'),
        decl('border-bottom-width', value),
      ],
      color: (value) => [decl('border-bottom-color', value)],
    })

    borderSideUtility('border-l', {
      width: (value) => [
        decl('border-left-style', 'var(--tw-border-style)'),
        decl('border-left-width', value),
      ],
      color: (value) => [decl('border-left-color', value)],
    })

    functionalUtility('divide-x', {
      defaultValue: theme.get(['--default-border-width']) ?? '1px',
      themeKeys: ['--divide-width', '--border-width'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}px`
      },
      handle: (value) => [
        atRoot([property('--tw-divide-x-reverse', '0')]),

        styleRule(':where(& > :not(:last-child))', [
          decl('--tw-sort', 'divide-x-width'),
          borderProperties(),
          decl('--tw-divide-x-reverse', '0'),
          decl('border-inline-style', 'var(--tw-border-style)'),
          decl('border-inline-start-width', `calc(${value} * var(--tw-divide-x-reverse))`),
          decl('border-inline-end-width', `calc(${value} * calc(1 - var(--tw-divide-x-reverse)))`),
        ]),
      ],
    })

    functionalUtility('divide-y', {
      defaultValue: theme.get(['--default-border-width']) ?? '1px',
      themeKeys: ['--divide-width', '--border-width'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}px`
      },
      handle: (value) => [
        atRoot([property('--tw-divide-y-reverse', '0')]),

        styleRule(':where(& > :not(:last-child))', [
          decl('--tw-sort', 'divide-y-width'),
          borderProperties(),
          decl('--tw-divide-y-reverse', '0'),
          decl('border-bottom-style', 'var(--tw-border-style)'),
          decl('border-top-style', 'var(--tw-border-style)'),
          decl('border-top-width', `calc(${value} * var(--tw-divide-y-reverse))`),
          decl('border-bottom-width', `calc(${value} * calc(1 - var(--tw-divide-y-reverse)))`),
        ]),
      ],
    })

    suggest('divide-x', () => [
      {
        values: ['0', '2', '4', '8'],
        valueThemeKeys: ['--divide-width', '--border-width'],
        hasDefaultValue: true,
      },
    ])

    suggest('divide-y', () => [
      {
        values: ['0', '2', '4', '8'],
        valueThemeKeys: ['--divide-width', '--border-width'],
        hasDefaultValue: true,
      },
    ])

    staticUtility('divide-x-reverse', [
      () => atRoot([property('--tw-divide-x-reverse', '0')]),
      () => styleRule(':where(& > :not(:last-child))', [decl('--tw-divide-x-reverse', '1')]),
    ])

    staticUtility('divide-y-reverse', [
      () => atRoot([property('--tw-divide-y-reverse', '0')]),
      () => styleRule(':where(& > :not(:last-child))', [decl('--tw-divide-y-reverse', '1')]),
    ])

    for (let value of ['solid', 'dashed', 'dotted', 'double', 'none']) {
      staticUtility(`divide-${value}`, [
        () =>
          styleRule(':where(& > :not(:last-child))', [
            decl('--tw-sort', 'divide-style'),
            decl('--tw-border-style', value),
            decl('border-style', value),
          ]),
      ])
    }
  }

  staticUtility('bg-auto', [['background-size', 'auto']])
  staticUtility('bg-cover', [['background-size', 'cover']])
  staticUtility('bg-contain', [['background-size', 'contain']])
  functionalUtility('bg-size', {
    handle(value) {
      if (!value) return
      return [decl('background-size', value)]
    },
  })

  staticUtility('bg-fixed', [['background-attachment', 'fixed']])
  staticUtility('bg-local', [['background-attachment', 'local']])
  staticUtility('bg-scroll', [['background-attachment', 'scroll']])

  staticUtility('bg-top', [['background-position', 'top']])
  staticUtility('bg-top-left', [['background-position', 'left top']])
  staticUtility('bg-top-right', [['background-position', 'right top']])
  staticUtility('bg-bottom', [['background-position', 'bottom']])
  staticUtility('bg-bottom-left', [['background-position', 'left bottom']])
  staticUtility('bg-bottom-right', [['background-position', 'right bottom']])
  staticUtility('bg-left', [['background-position', 'left']])
  staticUtility('bg-right', [['background-position', 'right']])
  staticUtility('bg-center', [['background-position', 'center']])
  functionalUtility('bg-position', {
    handle(value) {
      if (!value) return
      return [decl('background-position', value)]
    },
  })

  staticUtility('bg-repeat', [['background-repeat', 'repeat']])
  staticUtility('bg-no-repeat', [['background-repeat', 'no-repeat']])
  staticUtility('bg-repeat-x', [['background-repeat', 'repeat-x']])
  staticUtility('bg-repeat-y', [['background-repeat', 'repeat-y']])
  staticUtility('bg-repeat-round', [['background-repeat', 'round']])
  staticUtility('bg-repeat-space', [['background-repeat', 'space']])

  staticUtility('bg-none', [['background-image', 'none']])

  {
    let suggestedModifiers = [
      'oklab',
      'oklch',
      'srgb',
      'hsl',
      'longer',
      'shorter',
      'increasing',
      'decreasing',
    ]

    let linearGradientDirections = new Map([
      ['to-t', 'to top'],
      ['to-tr', 'to top right'],
      ['to-r', 'to right'],
      ['to-br', 'to bottom right'],
      ['to-b', 'to bottom'],
      ['to-bl', 'to bottom left'],
      ['to-l', 'to left'],
      ['to-tl', 'to top left'],
    ])

    function resolveInterpolationModifier(modifier: CandidateModifier | null) {
      let interpolationMethod = 'in oklab'

      if (modifier?.kind === 'named') {
        switch (modifier.value) {
          case 'longer':
          case 'shorter':
          case 'increasing':
          case 'decreasing':
            interpolationMethod = `in oklch ${modifier.value} hue`
            break
          default:
            interpolationMethod = `in ${modifier.value}`
        }
      } else if (modifier?.kind === 'arbitrary') {
        interpolationMethod = modifier.value
      }

      return interpolationMethod
    }

    function handleBgLinear({ negative }: { negative: boolean }) {
      return (candidate: Extract<Candidate, { kind: 'functional' }>) => {
        if (!candidate.value) return

        if (candidate.value.kind === 'arbitrary') {
          if (candidate.modifier) return

          let value = candidate.value.value
          let type = candidate.value.dataType ?? inferDataType(value, ['angle'])

          switch (type) {
            case 'angle': {
              value = negative ? `calc(${value} * -1)` : `${value}`

              return [
                decl('--tw-gradient-position', value),
                decl('background-image', `linear-gradient(var(--tw-gradient-stops,${value}))`),
              ]
            }
            default: {
              if (negative) return

              return [
                decl('--tw-gradient-position', value),
                decl('background-image', `linear-gradient(var(--tw-gradient-stops,${value}))`),
              ]
            }
          }
        }

        let value = candidate.value.value

        if (!negative && linearGradientDirections.has(value)) {
          value = linearGradientDirections.get(value)!
        } else if (isPositiveInteger(value)) {
          value = negative ? `calc(${value}deg * -1)` : `${value}deg`
        } else {
          return
        }

        let interpolationMethod = resolveInterpolationModifier(candidate.modifier)

        return [
          decl('--tw-gradient-position', `${value}`),
          rule('@supports (background-image: linear-gradient(in lab, red, red))', [
            decl('--tw-gradient-position', `${value} ${interpolationMethod}`),
          ]),
          decl('background-image', `linear-gradient(var(--tw-gradient-stops))`),
        ]
      }
    }

    utilities.functional('-bg-linear', handleBgLinear({ negative: true }))
    utilities.functional('bg-linear', handleBgLinear({ negative: false }))

    suggest('bg-linear', () => [
      {
        values: [...linearGradientDirections.keys()],
        modifiers: suggestedModifiers,
      },
      {
        values: ['0', '30', '60', '90', '120', '150', '180', '210', '240', '270', '300', '330'],
        supportsNegative: true,
        modifiers: suggestedModifiers,
      },
    ])

    function handleBgConic({ negative }: { negative: boolean }) {
      return (candidate: Extract<Candidate, { kind: 'functional' }>) => {
        if (candidate.value?.kind === 'arbitrary') {
          if (candidate.modifier) return
          let value = candidate.value.value
          return [
            decl('--tw-gradient-position', value),
            decl('background-image', `conic-gradient(var(--tw-gradient-stops,${value}))`),
          ]
        }

        let interpolationMethod = resolveInterpolationModifier(candidate.modifier)

        if (!candidate.value) {
          return [
            decl('--tw-gradient-position', interpolationMethod),
            decl('background-image', `conic-gradient(var(--tw-gradient-stops))`),
          ]
        }

        let value = candidate.value.value

        if (!isPositiveInteger(value)) return

        value = negative ? `calc(${value}deg * -1)` : `${value}deg`

        return [
          decl('--tw-gradient-position', `from ${value} ${interpolationMethod}`),
          decl('background-image', `conic-gradient(var(--tw-gradient-stops))`),
        ]
      }
    }

    utilities.functional('-bg-conic', handleBgConic({ negative: true }))
    utilities.functional('bg-conic', handleBgConic({ negative: false }))

    suggest('bg-conic', () => [
      {
        hasDefaultValue: true,
        modifiers: suggestedModifiers,
      },
      {
        values: ['0', '30', '60', '90', '120', '150', '180', '210', '240', '270', '300', '330'],
        supportsNegative: true,
        modifiers: suggestedModifiers,
      },
    ])

    utilities.functional('bg-radial', (candidate) => {
      if (!candidate.value) {
        let interpolationMethod = resolveInterpolationModifier(candidate.modifier)
        return [
          decl('--tw-gradient-position', interpolationMethod),
          decl('background-image', `radial-gradient(var(--tw-gradient-stops))`),
        ]
      }

      if (candidate.value.kind === 'arbitrary') {
        if (candidate.modifier) return
        let value = candidate.value.value
        return [
          decl('--tw-gradient-position', value),
          decl('background-image', `radial-gradient(var(--tw-gradient-stops,${value}))`),
        ]
      }
    })

    suggest('bg-radial', () => [
      {
        hasDefaultValue: true,
        modifiers: suggestedModifiers,
      },
    ])
  }

  utilities.functional('bg', (candidate) => {
    if (!candidate.value) return

    // Arbitrary values
    if (candidate.value.kind === 'arbitrary') {
      let value: string | null = candidate.value.value
      let type =
        candidate.value.dataType ??
        inferDataType(value, [
          'image',
          'color',
          'percentage',
          'position',
          'bg-size',
          'length',
          'url',
        ])

      switch (type) {
        case 'percentage':
        case 'position': {
          if (candidate.modifier) return
          return [decl('background-position', value)]
        }
        case 'bg-size':
        case 'length':
        case 'size': {
          if (candidate.modifier) return
          return [decl('background-size', value)]
        }
        case 'image':
        case 'url': {
          if (candidate.modifier) return
          return [decl('background-image', value)]
        }
        default: {
          value = asColor(value, candidate.modifier, theme)
          if (value === null) return

          return [decl('background-color', value)]
        }
      }
    }

    // `background-color` property
    {
      let value = resolveThemeColor(candidate, theme, ['--background-color', '--color'])
      if (value) {
        return [decl('background-color', value)]
      }
    }

    // `background-image` property
    {
      if (candidate.modifier) return
      let value = theme.resolve(candidate.value.value, ['--background-image'])
      if (value) {
        return [decl('background-image', value)]
      }
    }
  })

  suggest('bg', () => [
    {
      values: ['current', 'inherit', 'transparent'],
      valueThemeKeys: ['--background-color', '--color'],
      modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
    },
    {
      values: [],
      valueThemeKeys: ['--background-image'],
    },
  ])

  let gradientStopProperties = () => {
    return atRoot([
      property('--tw-gradient-position'),
      property('--tw-gradient-from', '#0000', '<color>'),
      property('--tw-gradient-via', '#0000', '<color>'),
      property('--tw-gradient-to', '#0000', '<color>'),
      property('--tw-gradient-stops'),
      property('--tw-gradient-via-stops'),
      property('--tw-gradient-from-position', '0%', '<length-percentage>'),
      property('--tw-gradient-via-position', '50%', '<length-percentage>'),
      property('--tw-gradient-to-position', '100%', '<length-percentage>'),
    ])
  }

  type GradientStopDescription = {
    color: (value: string) => AstNode[] | undefined
    position: (value: string) => AstNode[] | undefined
  }

  function gradientStopUtility(classRoot: string, desc: GradientStopDescription) {
    utilities.functional(classRoot, (candidate) => {
      if (!candidate.value) return

      // Arbitrary values
      if (candidate.value.kind === 'arbitrary') {
        let value: string | null = candidate.value.value
        let type =
          candidate.value.dataType ?? inferDataType(value, ['color', 'length', 'percentage'])

        switch (type) {
          case 'length':
          case 'percentage': {
            if (candidate.modifier) return
            return desc.position(value)
          }
          default: {
            value = asColor(value, candidate.modifier, theme)
            if (value === null) return

            return desc.color(value)
          }
        }
      }

      // Known values: Color Stops
      {
        let value = resolveThemeColor(candidate, theme, ['--background-color', '--color'])
        if (value) {
          return desc.color(value)
        }
      }

      // Known values: Positions
      {
        if (candidate.modifier) return
        let value = theme.resolve(candidate.value.value, ['--gradient-color-stop-positions'])
        if (value) {
          return desc.position(value)
        } else if (
          candidate.value.value[candidate.value.value.length - 1] === '%' &&
          isPositiveInteger(candidate.value.value.slice(0, -1))
        ) {
          return desc.position(candidate.value.value)
        }
      }
    })

    suggest(classRoot, () => [
      {
        values: ['current', 'inherit', 'transparent'],
        valueThemeKeys: ['--background-color', '--color'],
        modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
      },
      {
        values: Array.from({ length: 21 }, (_, index) => `${index * 5}%`),
        valueThemeKeys: ['--gradient-color-stop-positions'],
      },
    ])
  }

  gradientStopUtility('from', {
    color: (value) => [
      gradientStopProperties(),
      decl('--tw-sort', '--tw-gradient-from'),
      decl('--tw-gradient-from', value),
      decl(
        '--tw-gradient-stops',
        'var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))',
      ),
    ],
    position: (value) => [gradientStopProperties(), decl('--tw-gradient-from-position', value)],
  })
  staticUtility('via-none', [['--tw-gradient-via-stops', 'initial']])
  gradientStopUtility('via', {
    color: (value) => [
      gradientStopProperties(),
      decl('--tw-sort', '--tw-gradient-via'),
      decl('--tw-gradient-via', value),
      decl(
        '--tw-gradient-via-stops',
        'var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position)',
      ),
      decl('--tw-gradient-stops', 'var(--tw-gradient-via-stops)'),
    ],
    position: (value) => [gradientStopProperties(), decl('--tw-gradient-via-position', value)],
  })
  gradientStopUtility('to', {
    color: (value) => [
      gradientStopProperties(),
      decl('--tw-sort', '--tw-gradient-to'),
      decl('--tw-gradient-to', value),
      decl(
        '--tw-gradient-stops',
        'var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))',
      ),
    ],
    position: (value) => [gradientStopProperties(), decl('--tw-gradient-to-position', value)],
  })

  /**
   * @css `mask-image`
   */

  staticUtility('mask-none', [['mask-image', 'none']])

  utilities.functional('mask', (candidate) => {
    if (!candidate.value) return
    if (candidate.modifier) return
    if (candidate.value.kind !== 'arbitrary') return

    // Arbitrary values
    let value: string | null = candidate.value.value
    let type =
      candidate.value.dataType ??
      inferDataType(value, ['image', 'percentage', 'position', 'bg-size', 'length', 'url'])

    switch (type) {
      case 'percentage':
      case 'position': {
        if (candidate.modifier) return
        return [decl('mask-position', value)]
      }
      case 'bg-size':
      case 'length':
      case 'size': {
        return [decl('mask-size', value)]
      }
      case 'image':
      case 'url':
      default: {
        return [decl('mask-image', value)]
      }
    }
  })

  /**
   * @css `mask-composite`
   */

  staticUtility('mask-add', [['mask-composite', 'add']])
  staticUtility('mask-subtract', [['mask-composite', 'subtract']])
  staticUtility('mask-intersect', [['mask-composite', 'intersect']])
  staticUtility('mask-exclude', [['mask-composite', 'exclude']])

  /**
   * @css `mask-mode`
   *
   * Sets the "mode" of the mask given by mask-image
   */

  staticUtility('mask-alpha', [['mask-mode', 'alpha']])
  staticUtility('mask-luminance', [['mask-mode', 'luminance']])
  staticUtility('mask-match', [['mask-mode', 'match-source']])

  /**
   * @css `mask-type`
   *
   * Sets the "mode" of the current `<mask>` element
   * Is overridden by `mask-mode` if used
   */
  staticUtility('mask-type-alpha', [['mask-type', 'alpha']])
  staticUtility('mask-type-luminance', [['mask-type', 'luminance']])

  /**
   * @css `mask-size`
   */

  staticUtility('mask-auto', [['mask-size', 'auto']])
  staticUtility('mask-cover', [['mask-size', 'cover']])
  staticUtility('mask-contain', [['mask-size', 'contain']])
  functionalUtility('mask-size', {
    handle(value) {
      if (!value) return
      return [decl('mask-size', value)]
    },
  })

  /**
   * @css `mask-position`
   */

  staticUtility('mask-top', [['mask-position', 'top']])
  staticUtility('mask-top-left', [['mask-position', 'left top']])
  staticUtility('mask-top-right', [['mask-position', 'right top']])
  staticUtility('mask-bottom', [['mask-position', 'bottom']])
  staticUtility('mask-bottom-left', [['mask-position', 'left bottom']])
  staticUtility('mask-bottom-right', [['mask-position', 'right bottom']])
  staticUtility('mask-left', [['mask-position', 'left']])
  staticUtility('mask-right', [['mask-position', 'right']])
  staticUtility('mask-center', [['mask-position', 'center']])
  functionalUtility('mask-position', {
    handle(value) {
      if (!value) return
      return [decl('mask-position', value)]
    },
  })

  /**
   * @css `mask-repeat`
   */

  staticUtility('mask-repeat', [['mask-repeat', 'repeat']])
  staticUtility('mask-no-repeat', [['mask-repeat', 'no-repeat']])
  staticUtility('mask-repeat-x', [['mask-repeat', 'repeat-x']])
  staticUtility('mask-repeat-y', [['mask-repeat', 'repeat-y']])
  staticUtility('mask-repeat-round', [['mask-repeat', 'round']])
  staticUtility('mask-repeat-space', [['mask-repeat', 'space']])

  /**
   * @css `mask-clip`
   */

  staticUtility('mask-clip-border', [['mask-clip', 'border-box']])
  staticUtility('mask-clip-padding', [['mask-clip', 'padding-box']])
  staticUtility('mask-clip-content', [['mask-clip', 'content-box']])
  staticUtility('mask-clip-fill', [['mask-clip', 'fill-box']])
  staticUtility('mask-clip-stroke', [['mask-clip', 'stroke-box']])
  staticUtility('mask-clip-view', [['mask-clip', 'view-box']])
  staticUtility('mask-no-clip', [['mask-clip', 'no-clip']])

  /**
   * @css `mask-origin`
   */

  staticUtility('mask-origin-border', [['mask-origin', 'border-box']])
  staticUtility('mask-origin-padding', [['mask-origin', 'padding-box']])
  staticUtility('mask-origin-content', [['mask-origin', 'content-box']])
  staticUtility('mask-origin-fill', [['mask-origin', 'fill-box']])
  staticUtility('mask-origin-stroke', [['mask-origin', 'stroke-box']])
  staticUtility('mask-origin-view', [['mask-origin', 'view-box']])

  /**
   * @css `mask-image` gradients
   */

  let maskPropertiesGradient = () =>
    atRoot([
      property('--tw-mask-linear', 'linear-gradient(#fff, #fff)'),
      property('--tw-mask-radial', 'linear-gradient(#fff, #fff)'),
      property('--tw-mask-conic', 'linear-gradient(#fff, #fff)'),
    ])

  type MaskStopDescription = {
    color: (value: string) => AstNode[] | undefined
    position: (value: string) => AstNode[] | undefined
  }

  function maskStopUtility(classRoot: string, desc: MaskStopDescription) {
    utilities.functional(classRoot, (candidate) => {
      if (!candidate.value) return

      // Arbitrary values
      if (candidate.value.kind === 'arbitrary') {
        let value: string | null = candidate.value.value
        let type =
          candidate.value.dataType ?? inferDataType(value, ['length', 'percentage', 'color'])

        switch (type) {
          case 'color': {
            value = asColor(value, candidate.modifier, theme)
            if (value === null) return

            return desc.color(value)
          }
          case 'percentage': {
            if (candidate.modifier) return
            if (!isPositiveInteger(value.slice(0, -1))) return

            return desc.position(value)
          }
          default: {
            if (candidate.modifier) return

            return desc.position(value)
          }
        }
      }

      // Known values: Color Stops
      {
        let value = resolveThemeColor(candidate, theme, ['--background-color', '--color'])
        if (value) {
          return desc.color(value)
        }
      }

      // Known values: Positions
      {
        if (candidate.modifier) return

        let type = inferDataType(candidate.value.value, ['number', 'percentage'])
        if (!type) return

        switch (type) {
          case 'number': {
            let multiplier = theme.resolve(null, ['--spacing'])
            if (!multiplier) return
            if (!isValidSpacingMultiplier(candidate.value.value)) return

            return desc.position(`calc(${multiplier} * ${candidate.value.value})`)
          }

          case 'percentage': {
            if (!isPositiveInteger(candidate.value.value.slice(0, -1))) return
            return desc.position(candidate.value.value)
          }

          default: {
            return
          }
        }
      }
    })

    suggest(classRoot, () => [
      {
        values: ['current', 'inherit', 'transparent'],
        valueThemeKeys: ['--background-color', '--color'],
        modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
      },
      {
        values: Array.from({ length: 21 }, (_, index) => `${index * 5}%`),
        valueThemeKeys: ['--gradient-color-stop-positions'],
      },
    ])

    suggest(classRoot, () => [
      // Percentages
      {
        values: Array.from({ length: 21 }, (_, index) => `${index * 5}%`),
      },

      // Spacing Scale
      {
        values: theme.get(['--spacing']) ? DEFAULT_SPACING_SUGGESTIONS : [],
      },

      // Colors
      {
        values: ['current', 'inherit', 'transparent'],
        valueThemeKeys: ['--background-color', '--color'],
        modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
      },
    ])
  }

  /**
   * Edge masks
   */

  let maskPropertiesEdge = () =>
    atRoot([
      property('--tw-mask-left', 'linear-gradient(#fff, #fff)'),
      property('--tw-mask-right', 'linear-gradient(#fff, #fff)'),
      property('--tw-mask-bottom', 'linear-gradient(#fff, #fff)'),
      property('--tw-mask-top', 'linear-gradient(#fff, #fff)'),
    ])

  type MaskEdge = 'top' | 'right' | 'bottom' | 'left'
  type MaskStop = 'from' | 'to'

  function maskEdgeUtility(name: string, stop: MaskStop, edges: Record<MaskEdge, boolean>) {
    maskStopUtility(name, {
      color(value) {
        let nodes: AstNode[] = [
          // Common @property declarations
          maskPropertiesGradient(),
          maskPropertiesEdge(),

          // Common properties to all edge utilities
          decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
          decl('mask-composite', 'intersect'),
          decl(
            '--tw-mask-linear',
            'var(--tw-mask-left), var(--tw-mask-right), var(--tw-mask-bottom), var(--tw-mask-top)',
          ),
        ]

        for (let edge of ['top', 'right', 'bottom', 'left'] as const) {
          if (!edges[edge]) continue

          nodes.push(
            decl(
              `--tw-mask-${edge}`,
              `linear-gradient(to ${edge}, var(--tw-mask-${edge}-from-color) var(--tw-mask-${edge}-from-position), var(--tw-mask-${edge}-to-color) var(--tw-mask-${edge}-to-position))`,
            ),
          )

          nodes.push(
            atRoot([
              property(`--tw-mask-${edge}-from-position`, '0%'),
              property(`--tw-mask-${edge}-to-position`, '100%'),
              property(`--tw-mask-${edge}-from-color`, 'black'),
              property(`--tw-mask-${edge}-to-color`, 'transparent'),
            ]),
          )

          nodes.push(decl(`--tw-mask-${edge}-${stop}-color`, value))
        }

        return nodes
      },
      position(value) {
        let nodes: AstNode[] = [
          // Common @property declarations
          maskPropertiesGradient(),
          maskPropertiesEdge(),

          // Common properties to all edge utilities
          decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
          decl('mask-composite', 'intersect'),
          decl(
            '--tw-mask-linear',
            'var(--tw-mask-left), var(--tw-mask-right), var(--tw-mask-bottom), var(--tw-mask-top)',
          ),
        ]

        for (let edge of ['top', 'right', 'bottom', 'left'] as const) {
          if (!edges[edge]) continue

          nodes.push(
            decl(
              `--tw-mask-${edge}`,
              `linear-gradient(to ${edge}, var(--tw-mask-${edge}-from-color) var(--tw-mask-${edge}-from-position), var(--tw-mask-${edge}-to-color) var(--tw-mask-${edge}-to-position))`,
            ),
          )

          nodes.push(
            atRoot([
              property(`--tw-mask-${edge}-from-position`, '0%'),
              property(`--tw-mask-${edge}-to-position`, '100%'),
              property(`--tw-mask-${edge}-from-color`, 'black'),
              property(`--tw-mask-${edge}-to-color`, 'transparent'),
            ]),
          )

          nodes.push(decl(`--tw-mask-${edge}-${stop}-position`, value))
        }

        return nodes
      },
    })
  }

  maskEdgeUtility('mask-x-from', 'from', { top: false, right: true, bottom: false, left: true })
  maskEdgeUtility('mask-x-to', 'to', { top: false, right: true, bottom: false, left: true })
  maskEdgeUtility('mask-y-from', 'from', { top: true, right: false, bottom: true, left: false })
  maskEdgeUtility('mask-y-to', 'to', { top: true, right: false, bottom: true, left: false })
  maskEdgeUtility('mask-t-from', 'from', { top: true, right: false, bottom: false, left: false })
  maskEdgeUtility('mask-t-to', 'to', { top: true, right: false, bottom: false, left: false })
  maskEdgeUtility('mask-r-from', 'from', { top: false, right: true, bottom: false, left: false })
  maskEdgeUtility('mask-r-to', 'to', { top: false, right: true, bottom: false, left: false })
  maskEdgeUtility('mask-b-from', 'from', { top: false, right: false, bottom: true, left: false })
  maskEdgeUtility('mask-b-to', 'to', { top: false, right: false, bottom: true, left: false })
  maskEdgeUtility('mask-l-from', 'from', { top: false, right: false, bottom: false, left: true })
  maskEdgeUtility('mask-l-to', 'to', { top: false, right: false, bottom: false, left: true })

  /**
   *  Linear Masks
   */

  let maskPropertiesLinear = () =>
    atRoot([
      property('--tw-mask-linear-position', '0deg'),
      property('--tw-mask-linear-from-position', '0%'),
      property('--tw-mask-linear-to-position', '100%'),
      property('--tw-mask-linear-from-color', 'black'),
      property('--tw-mask-linear-to-color', 'transparent'),
    ])

  functionalUtility('mask-linear', {
    defaultValue: null,
    supportsNegative: true,
    supportsFractions: false,
    handleBareValue(value) {
      if (!isPositiveInteger(value.value)) return null
      return `calc(1deg * ${value.value})`
    },
    handleNegativeBareValue(value) {
      if (!isPositiveInteger(value.value)) return null
      return `calc(1deg * -${value.value})`
    },
    handle: (value) => [
      maskPropertiesGradient(),
      maskPropertiesLinear(),
      decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
      decl('mask-composite', 'intersect'),
      decl(
        '--tw-mask-linear',
        `linear-gradient(var(--tw-mask-linear-stops, var(--tw-mask-linear-position)))`,
      ),
      decl('--tw-mask-linear-position', value),
    ],
  })

  suggest('mask-linear', () => [
    {
      supportsNegative: true,
      values: ['0', '1', '2', '3', '6', '12', '45', '90', '180'],
    },
  ])

  maskStopUtility('mask-linear-from', {
    color: (value) => [
      maskPropertiesGradient(),
      maskPropertiesLinear(),
      decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
      decl('mask-composite', 'intersect'),
      decl(
        '--tw-mask-linear-stops',
        'var(--tw-mask-linear-position), var(--tw-mask-linear-from-color) var(--tw-mask-linear-from-position), var(--tw-mask-linear-to-color) var(--tw-mask-linear-to-position)',
      ),
      decl('--tw-mask-linear', 'linear-gradient(var(--tw-mask-linear-stops))'),
      decl('--tw-mask-linear-from-color', value),
    ],
    position: (value) => [
      maskPropertiesGradient(),
      maskPropertiesLinear(),
      decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
      decl('mask-composite', 'intersect'),
      decl(
        '--tw-mask-linear-stops',
        'var(--tw-mask-linear-position), var(--tw-mask-linear-from-color) var(--tw-mask-linear-from-position), var(--tw-mask-linear-to-color) var(--tw-mask-linear-to-position)',
      ),
      decl('--tw-mask-linear', 'linear-gradient(var(--tw-mask-linear-stops))'),
      decl('--tw-mask-linear-from-position', value),
    ],
  })

  maskStopUtility('mask-linear-to', {
    color: (value) => [
      maskPropertiesGradient(),
      maskPropertiesLinear(),
      decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
      decl('mask-composite', 'intersect'),
      decl(
        '--tw-mask-linear-stops',
        'var(--tw-mask-linear-position), var(--tw-mask-linear-from-color) var(--tw-mask-linear-from-position), var(--tw-mask-linear-to-color) var(--tw-mask-linear-to-position)',
      ),
      decl('--tw-mask-linear', 'linear-gradient(var(--tw-mask-linear-stops))'),
      decl('--tw-mask-linear-to-color', value),
    ],
    position: (value) => [
      maskPropertiesGradient(),
      maskPropertiesLinear(),
      decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
      decl('mask-composite', 'intersect'),
      decl(
        '--tw-mask-linear-stops',
        'var(--tw-mask-linear-position), var(--tw-mask-linear-from-color) var(--tw-mask-linear-from-position), var(--tw-mask-linear-to-color) var(--tw-mask-linear-to-position)',
      ),
      decl('--tw-mask-linear', 'linear-gradient(var(--tw-mask-linear-stops))'),
      decl('--tw-mask-linear-to-position', value),
    ],
  })

  /**
   * Radial masks
   */

  let maskPropertiesRadial = () =>
    atRoot([
      property('--tw-mask-radial-from-position', '0%'),
      property('--tw-mask-radial-to-position', '100%'),
      property('--tw-mask-radial-from-color', 'black'),
      property('--tw-mask-radial-to-color', 'transparent'),
      property('--tw-mask-radial-shape', 'ellipse'),
      property('--tw-mask-radial-size', 'farthest-corner'),
      property('--tw-mask-radial-position', 'center'),
    ])

  staticUtility('mask-circle', [['--tw-mask-radial-shape', 'circle']])
  staticUtility('mask-ellipse', [['--tw-mask-radial-shape', 'ellipse']])
  staticUtility('mask-radial-closest-side', [['--tw-mask-radial-size', 'closest-side']])
  staticUtility('mask-radial-farthest-side', [['--tw-mask-radial-size', 'farthest-side']])
  staticUtility('mask-radial-closest-corner', [['--tw-mask-radial-size', 'closest-corner']])
  staticUtility('mask-radial-farthest-corner', [['--tw-mask-radial-size', 'farthest-corner']])
  staticUtility('mask-radial-at-top', [['--tw-mask-radial-position', 'top']])
  staticUtility('mask-radial-at-top-left', [['--tw-mask-radial-position', 'top left']])
  staticUtility('mask-radial-at-top-right', [['--tw-mask-radial-position', 'top right']])
  staticUtility('mask-radial-at-bottom', [['--tw-mask-radial-position', 'bottom']])
  staticUtility('mask-radial-at-bottom-left', [['--tw-mask-radial-position', 'bottom left']])
  staticUtility('mask-radial-at-bottom-right', [['--tw-mask-radial-position', 'bottom right']])
  staticUtility('mask-radial-at-left', [['--tw-mask-radial-position', 'left']])
  staticUtility('mask-radial-at-right', [['--tw-mask-radial-position', 'right']])
  staticUtility('mask-radial-at-center', [['--tw-mask-radial-position', 'center']])
  functionalUtility('mask-radial-at', {
    defaultValue: null,
    supportsNegative: false,
    supportsFractions: false,
    handle: (value) => [decl('--tw-mask-radial-position', value)],
  })

  /*
      This can be used to set just the size in conjunction with `mask-radial-from-*` et al,
      or can set the whole gradient if it's the only utility you use.

      For example:
      `mask-radial-[40px_80px] mask-radial-from-50%`
      `mask-radial-[96px_at_top,black_40%,transparent_80%,black_90%]`

      This will produce nonsense though and break, which is fine:
      `mask-radial-[96px_at_top,black_40%,transparent_80%,black_90%]  mask-radial-from-50%`
    */
  functionalUtility('mask-radial', {
    defaultValue: null,
    supportsNegative: false,
    supportsFractions: false,
    handle: (value) => [
      maskPropertiesGradient(),
      maskPropertiesRadial(),
      decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
      decl('mask-composite', 'intersect'),
      decl(
        '--tw-mask-radial',
        'radial-gradient(var(--tw-mask-radial-stops, var(--tw-mask-radial-size)))',
      ),
      decl('--tw-mask-radial-size', value),
    ],
  })

  maskStopUtility('mask-radial-from', {
    color: (value) => [
      maskPropertiesGradient(),
      maskPropertiesRadial(),
      decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
      decl('mask-composite', 'intersect'),
      decl(
        '--tw-mask-radial-stops',
        'var(--tw-mask-radial-shape) var(--tw-mask-radial-size) at var(--tw-mask-radial-position), var(--tw-mask-radial-from-color) var(--tw-mask-radial-from-position), var(--tw-mask-radial-to-color) var(--tw-mask-radial-to-position)',
      ),
      decl('--tw-mask-radial', 'radial-gradient(var(--tw-mask-radial-stops))'),
      decl('--tw-mask-radial-from-color', value),
    ],
    position: (value) => [
      maskPropertiesGradient(),
      maskPropertiesRadial(),
      decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
      decl('mask-composite', 'intersect'),
      decl(
        '--tw-mask-radial-stops',
        'var(--tw-mask-radial-shape) var(--tw-mask-radial-size) at var(--tw-mask-radial-position), var(--tw-mask-radial-from-color) var(--tw-mask-radial-from-position), var(--tw-mask-radial-to-color) var(--tw-mask-radial-to-position)',
      ),
      decl('--tw-mask-radial', 'radial-gradient(var(--tw-mask-radial-stops))'),
      decl('--tw-mask-radial-from-position', value),
    ],
  })

  maskStopUtility('mask-radial-to', {
    color: (value) => [
      maskPropertiesGradient(),
      maskPropertiesRadial(),
      decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
      decl('mask-composite', 'intersect'),
      decl(
        '--tw-mask-radial-stops',
        'var(--tw-mask-radial-shape) var(--tw-mask-radial-size) at var(--tw-mask-radial-position), var(--tw-mask-radial-from-color) var(--tw-mask-radial-from-position), var(--tw-mask-radial-to-color) var(--tw-mask-radial-to-position)',
      ),
      decl('--tw-mask-radial', 'radial-gradient(var(--tw-mask-radial-stops))'),
      decl('--tw-mask-radial-to-color', value),
    ],
    position: (value) => [
      maskPropertiesGradient(),
      maskPropertiesRadial(),
      decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
      decl('mask-composite', 'intersect'),
      decl(
        '--tw-mask-radial-stops',
        'var(--tw-mask-radial-shape) var(--tw-mask-radial-size) at var(--tw-mask-radial-position), var(--tw-mask-radial-from-color) var(--tw-mask-radial-from-position), var(--tw-mask-radial-to-color) var(--tw-mask-radial-to-position)',
      ),
      decl('--tw-mask-radial', 'radial-gradient(var(--tw-mask-radial-stops))'),
      decl('--tw-mask-radial-to-position', value),
    ],
  })

  /**
   * Conic masks
   */

  let maskPropertiesConic = () =>
    atRoot([
      property('--tw-mask-conic-position', '0deg'),
      property('--tw-mask-conic-from-position', '0%'),
      property('--tw-mask-conic-to-position', '100%'),
      property('--tw-mask-conic-from-color', 'black'),
      property('--tw-mask-conic-to-color', 'transparent'),
    ])

  functionalUtility('mask-conic', {
    defaultValue: null,
    supportsNegative: true,
    supportsFractions: false,
    handleBareValue(value) {
      if (!isPositiveInteger(value.value)) return null
      return `calc(1deg * ${value.value})`
    },
    handleNegativeBareValue(value) {
      if (!isPositiveInteger(value.value)) return null
      return `calc(1deg * -${value.value})`
    },
    handle: (value) => [
      maskPropertiesGradient(),
      maskPropertiesConic(),
      decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
      decl('mask-composite', 'intersect'),
      decl(
        '--tw-mask-conic',
        'conic-gradient(var(--tw-mask-conic-stops, var(--tw-mask-conic-position)))',
      ),
      decl('--tw-mask-conic-position', value),
    ],
  })

  suggest('mask-conic', () => [
    {
      supportsNegative: true,
      values: ['0', '1', '2', '3', '6', '12', '45', '90', '180'],
    },
  ])

  maskStopUtility('mask-conic-from', {
    color: (value) => [
      maskPropertiesGradient(),
      maskPropertiesConic(),
      decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
      decl('mask-composite', 'intersect'),
      decl(
        '--tw-mask-conic-stops',
        'from var(--tw-mask-conic-position), var(--tw-mask-conic-from-color) var(--tw-mask-conic-from-position), var(--tw-mask-conic-to-color) var(--tw-mask-conic-to-position)',
      ),
      decl('--tw-mask-conic', 'conic-gradient(var(--tw-mask-conic-stops))'),
      decl('--tw-mask-conic-from-color', value),
    ],
    position: (value) => [
      maskPropertiesGradient(),
      maskPropertiesConic(),
      decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
      decl('mask-composite', 'intersect'),
      decl(
        '--tw-mask-conic-stops',
        'from var(--tw-mask-conic-position), var(--tw-mask-conic-from-color) var(--tw-mask-conic-from-position), var(--tw-mask-conic-to-color) var(--tw-mask-conic-to-position)',
      ),
      decl('--tw-mask-conic', 'conic-gradient(var(--tw-mask-conic-stops))'),
      decl('--tw-mask-conic-from-position', value),
    ],
  })

  maskStopUtility('mask-conic-to', {
    color: (value) => [
      maskPropertiesGradient(),
      maskPropertiesConic(),
      decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
      decl('mask-composite', 'intersect'),
      decl(
        '--tw-mask-conic-stops',
        'from var(--tw-mask-conic-position), var(--tw-mask-conic-from-color) var(--tw-mask-conic-from-position), var(--tw-mask-conic-to-color) var(--tw-mask-conic-to-position)',
      ),
      decl('--tw-mask-conic', 'conic-gradient(var(--tw-mask-conic-stops))'),
      decl('--tw-mask-conic-to-color', value),
    ],
    position: (value) => [
      maskPropertiesGradient(),
      maskPropertiesConic(),
      decl('mask-image', 'var(--tw-mask-linear), var(--tw-mask-radial), var(--tw-mask-conic)'),
      decl('mask-composite', 'intersect'),
      decl(
        '--tw-mask-conic-stops',
        'from var(--tw-mask-conic-position), var(--tw-mask-conic-from-color) var(--tw-mask-conic-from-position), var(--tw-mask-conic-to-color) var(--tw-mask-conic-to-position)',
      ),
      decl('--tw-mask-conic', 'conic-gradient(var(--tw-mask-conic-stops))'),
      decl('--tw-mask-conic-to-position', value),
    ],
  })

  /**
   * @css `box-decoration-break`
   */
  staticUtility('box-decoration-slice', [
    ['-webkit-box-decoration-break', 'slice'],
    ['box-decoration-break', 'slice'],
  ])
  staticUtility('box-decoration-clone', [
    ['-webkit-box-decoration-break', 'clone'],
    ['box-decoration-break', 'clone'],
  ])

  /**
   * @css `background-clip`
   */
  staticUtility('bg-clip-text', [['background-clip', 'text']])
  staticUtility('bg-clip-border', [['background-clip', 'border-box']])
  staticUtility('bg-clip-padding', [['background-clip', 'padding-box']])
  staticUtility('bg-clip-content', [['background-clip', 'content-box']])

  staticUtility('bg-origin-border', [['background-origin', 'border-box']])
  staticUtility('bg-origin-padding', [['background-origin', 'padding-box']])
  staticUtility('bg-origin-content', [['background-origin', 'content-box']])

  for (let value of [
    'normal',
    'multiply',
    'screen',
    'overlay',
    'darken',
    'lighten',
    'color-dodge',
    'color-burn',
    'hard-light',
    'soft-light',
    'difference',
    'exclusion',
    'hue',
    'saturation',
    'color',
    'luminosity',
  ]) {
    staticUtility(`bg-blend-${value}`, [['background-blend-mode', value]])
    staticUtility(`mix-blend-${value}`, [['mix-blend-mode', value]])
  }

  staticUtility('mix-blend-plus-darker', [['mix-blend-mode', 'plus-darker']])
  staticUtility('mix-blend-plus-lighter', [['mix-blend-mode', 'plus-lighter']])

  staticUtility('fill-none', [['fill', 'none']])
  utilities.functional('fill', (candidate) => {
    if (!candidate.value) return

    if (candidate.value.kind === 'arbitrary') {
      let value = asColor(candidate.value.value, candidate.modifier, theme)
      if (value === null) return
      return [decl('fill', value)]
    }

    let value = resolveThemeColor(candidate, theme, ['--fill', '--color'])
    if (value) {
      return [decl('fill', value)]
    }
  })

  suggest('fill', () => [
    {
      values: ['current', 'inherit', 'transparent'],
      valueThemeKeys: ['--fill', '--color'],
      modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
    },
  ])

  staticUtility('stroke-none', [['stroke', 'none']])
  utilities.functional('stroke', (candidate) => {
    if (!candidate.value) return

    if (candidate.value.kind === 'arbitrary') {
      let value: string | null = candidate.value.value
      let type =
        candidate.value.dataType ??
        inferDataType(value, ['color', 'number', 'length', 'percentage'])

      switch (type) {
        case 'number':
        case 'length':
        case 'percentage': {
          if (candidate.modifier) return
          return [decl('stroke-width', value)]
        }
        default: {
          value = asColor(candidate.value.value, candidate.modifier, theme)
          if (value === null) return

          return [decl('stroke', value)]
        }
      }
    }

    {
      let value = resolveThemeColor(candidate, theme, ['--stroke', '--color'])
      if (value) {
        return [decl('stroke', value)]
      }
    }

    {
      let value = theme.resolve(candidate.value.value, ['--stroke-width'])
      if (value) {
        return [decl('stroke-width', value)]
      } else if (isPositiveInteger(candidate.value.value)) {
        return [decl('stroke-width', candidate.value.value)]
      }
    }
  })

  suggest('stroke', () => [
    {
      values: ['current', 'inherit', 'transparent'],
      valueThemeKeys: ['--stroke', '--color'],
      modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
    },
    {
      values: ['0', '1', '2', '3'],
      valueThemeKeys: ['--stroke-width'],
    },
  ])

  staticUtility('object-contain', [['object-fit', 'contain']])
  staticUtility('object-cover', [['object-fit', 'cover']])
  staticUtility('object-fill', [['object-fit', 'fill']])
  staticUtility('object-none', [['object-fit', 'none']])
  staticUtility('object-scale-down', [['object-fit', 'scale-down']])

  functionalUtility('object', {
    themeKeys: ['--object-position'],
    handle: (value) => [decl('object-position', value)],
    staticValues: {
      top: [decl('object-position', 'top')],
      'top-left': [decl('object-position', 'left top')],
      'top-right': [decl('object-position', 'right top')],
      bottom: [decl('object-position', 'bottom')],
      'bottom-left': [decl('object-position', 'left bottom')],
      'bottom-right': [decl('object-position', 'right bottom')],
      left: [decl('object-position', 'left')],
      right: [decl('object-position', 'right')],
      center: [decl('object-position', 'center')],
    },
  })

  for (let [name, property] of [
    ['p', 'padding'],
    ['px', 'padding-inline'],
    ['py', 'padding-block'],
    ['ps', 'padding-inline-start'],
    ['pe', 'padding-inline-end'],
    ['pbs', 'padding-block-start'],
    ['pbe', 'padding-block-end'],
    ['pt', 'padding-top'],
    ['pr', 'padding-right'],
    ['pb', 'padding-bottom'],
    ['pl', 'padding-left'],
  ] as const) {
    spacingUtility(name, ['--padding', '--spacing'], (value) => [decl(property, value)])
  }

  staticUtility('text-left', [['text-align', 'left']])
  staticUtility('text-center', [['text-align', 'center']])
  staticUtility('text-right', [['text-align', 'right']])
  staticUtility('text-justify', [['text-align', 'justify']])
  staticUtility('text-start', [['text-align', 'start']])
  staticUtility('text-end', [['text-align', 'end']])

  spacingUtility(
    'indent',
    ['--text-indent', '--spacing'],
    (value) => [decl('text-indent', value)],
    {
      supportsNegative: true,
    },
  )

  staticUtility('align-baseline', [['vertical-align', 'baseline']])
  staticUtility('align-top', [['vertical-align', 'top']])
  staticUtility('align-middle', [['vertical-align', 'middle']])
  staticUtility('align-bottom', [['vertical-align', 'bottom']])
  staticUtility('align-text-top', [['vertical-align', 'text-top']])
  staticUtility('align-text-bottom', [['vertical-align', 'text-bottom']])
  staticUtility('align-sub', [['vertical-align', 'sub']])
  staticUtility('align-super', [['vertical-align', 'super']])

  functionalUtility('align', {
    themeKeys: [],
    handle: (value) => [decl('vertical-align', value)],
  })

  utilities.functional('font', (candidate) => {
    if (!candidate.value || candidate.modifier) return

    if (candidate.value.kind === 'arbitrary') {
      let value = candidate.value.value
      let type =
        candidate.value.dataType ?? inferDataType(value, ['number', 'generic-name', 'family-name'])

      switch (type) {
        case 'generic-name':
        case 'family-name': {
          return [decl('font-family', value)]
        }
        default: {
          return [
            atRoot([property('--tw-font-weight')]),
            decl('--tw-font-weight', value),
            decl('font-weight', value),
          ]
        }
      }
    }

    {
      let value = theme.resolveWith(
        candidate.value.value,
        ['--font'],
        ['--font-feature-settings', '--font-variation-settings'],
      )
      if (value) {
        let [families, options = {}] = value

        return [
          decl('font-family', families),
          decl('font-feature-settings', options['--font-feature-settings']),
          decl('font-variation-settings', options['--font-variation-settings']),
        ]
      }
    }

    {
      let value = theme.resolve(candidate.value.value, ['--font-weight'])
      if (value) {
        return [
          atRoot([property('--tw-font-weight')]),
          decl('--tw-font-weight', value),
          decl('font-weight', value),
        ]
      }
    }
  })

  suggest('font', () => [
    {
      values: [],
      valueThemeKeys: ['--font'],
    },
    {
      values: [],
      valueThemeKeys: ['--font-weight'],
    },
  ])

  /**
   * @css `font-feature-settings`
   */
  functionalUtility('font-features', {
    themeKeys: [],
    handle: (value) => [decl('font-feature-settings', value)],
  })

  staticUtility('uppercase', [['text-transform', 'uppercase']])
  staticUtility('lowercase', [['text-transform', 'lowercase']])
  staticUtility('capitalize', [['text-transform', 'capitalize']])
  staticUtility('normal-case', [['text-transform', 'none']])

  staticUtility('italic', [['font-style', 'italic']])
  staticUtility('not-italic', [['font-style', 'normal']])
  staticUtility('underline', [['text-decoration-line', 'underline']])
  staticUtility('overline', [['text-decoration-line', 'overline']])
  staticUtility('line-through', [['text-decoration-line', 'line-through']])
  staticUtility('no-underline', [['text-decoration-line', 'none']])

  staticUtility('font-stretch-normal', [['font-stretch', 'normal']])
  staticUtility('font-stretch-ultra-condensed', [['font-stretch', 'ultra-condensed']])
  staticUtility('font-stretch-extra-condensed', [['font-stretch', 'extra-condensed']])
  staticUtility('font-stretch-condensed', [['font-stretch', 'condensed']])
  staticUtility('font-stretch-semi-condensed', [['font-stretch', 'semi-condensed']])
  staticUtility('font-stretch-semi-expanded', [['font-stretch', 'semi-expanded']])
  staticUtility('font-stretch-expanded', [['font-stretch', 'expanded']])
  staticUtility('font-stretch-extra-expanded', [['font-stretch', 'extra-expanded']])
  staticUtility('font-stretch-ultra-expanded', [['font-stretch', 'ultra-expanded']])
  functionalUtility('font-stretch', {
    handleBareValue: ({ value }) => {
      if (!value.endsWith('%')) return null
      let num = Number(value.slice(0, -1))
      if (!isPositiveInteger(num)) return null
      // Only 50-200% (inclusive) are valid:
      // https://developer.mozilla.org/en-US/docs/Web/CSS/font-stretch#percentage
      if (Number.isNaN(num) || num < 50 || num > 200) return null
      return value
    },
    handle: (value) => [decl('font-stretch', value)],
  })
  suggest('font-stretch', () => [
    {
      values: ['50%', '75%', '90%', '95%', '100%', '105%', '110%', '125%', '150%', '200%'],
    },
  ])

  colorUtility('placeholder', {
    themeKeys: ['--background-color', '--color'],
    handle: (value) => [
      styleRule('&::placeholder', [decl('--tw-sort', 'placeholder-color'), decl('color', value)]),
    ],
  })

  /**
   * @css `text-decoration-style`
   */
  staticUtility('decoration-solid', [['text-decoration-style', 'solid']])
  staticUtility('decoration-double', [['text-decoration-style', 'double']])
  staticUtility('decoration-dotted', [['text-decoration-style', 'dotted']])
  staticUtility('decoration-dashed', [['text-decoration-style', 'dashed']])
  staticUtility('decoration-wavy', [['text-decoration-style', 'wavy']])

  /**
   * @css `text-decoration-thickness`
   */
  staticUtility('decoration-auto', [['text-decoration-thickness', 'auto']])
  staticUtility('decoration-from-font', [['text-decoration-thickness', 'from-font']])

  utilities.functional('decoration', (candidate) => {
    if (!candidate.value) return

    if (candidate.value.kind === 'arbitrary') {
      let value: string | null = candidate.value.value
      let type = candidate.value.dataType ?? inferDataType(value, ['color', 'length', 'percentage'])

      switch (type) {
        case 'length':
        case 'percentage': {
          if (candidate.modifier) return
          return [decl('text-decoration-thickness', value)]
        }
        default: {
          value = asColor(value, candidate.modifier, theme)
          if (value === null) return

          return [decl('text-decoration-color', value)]
        }
      }
    }

    // `text-decoration-thickness` property
    {
      let value = theme.resolve(candidate.value.value, ['--text-decoration-thickness'])
      if (value) {
        if (candidate.modifier) return
        return [decl('text-decoration-thickness', value)]
      }

      if (isPositiveInteger(candidate.value.value)) {
        if (candidate.modifier) return
        return [decl('text-decoration-thickness', `${candidate.value.value}px`)]
      }
    }

    // `text-decoration-color` property
    {
      let value = resolveThemeColor(candidate, theme, ['--text-decoration-color', '--color'])
      if (value) {
        return [decl('text-decoration-color', value)]
      }
    }
  })

  suggest('decoration', () => [
    {
      values: ['current', 'inherit', 'transparent'],
      valueThemeKeys: ['--text-decoration-color', '--color'],
      modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
    },
    {
      values: ['0', '1', '2'],
      valueThemeKeys: ['--text-decoration-thickness'],
    },
  ])

  functionalUtility('animate', {
    themeKeys: ['--animate'],
    handle: (value) => [decl('animation', value)],
    staticValues: {
      none: [decl('animation', 'none')],
    },
  })

  {
    let cssFilterValue = [
      'var(--tw-blur,)',
      'var(--tw-brightness,)',
      'var(--tw-contrast,)',
      'var(--tw-grayscale,)',
      'var(--tw-hue-rotate,)',
      'var(--tw-invert,)',
      'var(--tw-saturate,)',
      'var(--tw-sepia,)',
      'var(--tw-drop-shadow,)',
    ].join(' ')

    let cssBackdropFilterValue = [
      'var(--tw-backdrop-blur,)',
      'var(--tw-backdrop-brightness,)',
      'var(--tw-backdrop-contrast,)',
      'var(--tw-backdrop-grayscale,)',
      'var(--tw-backdrop-hue-rotate,)',
      'var(--tw-backdrop-invert,)',
      'var(--tw-backdrop-opacity,)',
      'var(--tw-backdrop-saturate,)',
      'var(--tw-backdrop-sepia,)',
    ].join(' ')

    let filterProperties = () => {
      return atRoot([
        property('--tw-blur'),
        property('--tw-brightness'),
        property('--tw-contrast'),
        property('--tw-grayscale'),
        property('--tw-hue-rotate'),
        property('--tw-invert'),
        property('--tw-opacity'),
        property('--tw-saturate'),
        property('--tw-sepia'),
        property('--tw-drop-shadow'),
        property('--tw-drop-shadow-color'),
        property('--tw-drop-shadow-alpha', '100%', '<percentage>'),
        property('--tw-drop-shadow-size'),
      ])
    }

    let backdropFilterProperties = () => {
      return atRoot([
        property('--tw-backdrop-blur'),
        property('--tw-backdrop-brightness'),
        property('--tw-backdrop-contrast'),
        property('--tw-backdrop-grayscale'),
        property('--tw-backdrop-hue-rotate'),
        property('--tw-backdrop-invert'),
        property('--tw-backdrop-opacity'),
        property('--tw-backdrop-saturate'),
        property('--tw-backdrop-sepia'),
      ])
    }

    utilities.functional('filter', (candidate) => {
      if (candidate.modifier) return

      if (candidate.value === null) {
        return [filterProperties(), decl('filter', cssFilterValue)]
      }

      if (candidate.value.kind === 'arbitrary') {
        return [decl('filter', candidate.value.value)]
      }

      switch (candidate.value.value) {
        case 'none':
          return [decl('filter', 'none')]
      }
    })

    utilities.functional('backdrop-filter', (candidate) => {
      if (candidate.modifier) return

      if (candidate.value === null) {
        return [
          backdropFilterProperties(),
          decl('-webkit-backdrop-filter', cssBackdropFilterValue),
          decl('backdrop-filter', cssBackdropFilterValue),
        ]
      }

      if (candidate.value.kind === 'arbitrary') {
        return [
          decl('-webkit-backdrop-filter', candidate.value.value),
          decl('backdrop-filter', candidate.value.value),
        ]
      }

      switch (candidate.value.value) {
        case 'none':
          return [decl('-webkit-backdrop-filter', 'none'), decl('backdrop-filter', 'none')]
      }
    })

    functionalUtility('blur', {
      themeKeys: ['--blur'],
      handle: (value) => [
        filterProperties(),
        decl('--tw-blur', `blur(${value})`),
        decl('filter', cssFilterValue),
      ],
      staticValues: {
        none: [filterProperties(), decl('--tw-blur', ' '), decl('filter', cssFilterValue)],
      },
    })

    functionalUtility('backdrop-blur', {
      themeKeys: ['--backdrop-blur', '--blur'],
      handle: (value) => [
        backdropFilterProperties(),
        decl('--tw-backdrop-blur', `blur(${value})`),
        decl('-webkit-backdrop-filter', cssBackdropFilterValue),
        decl('backdrop-filter', cssBackdropFilterValue),
      ],
      staticValues: {
        none: [
          backdropFilterProperties(),
          decl('--tw-backdrop-blur', ' '),
          decl('-webkit-backdrop-filter', cssBackdropFilterValue),
          decl('backdrop-filter', cssBackdropFilterValue),
        ],
      },
    })

    functionalUtility('brightness', {
      themeKeys: ['--brightness'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}%`
      },
      handle: (value) => [
        filterProperties(),
        decl('--tw-brightness', `brightness(${value})`),
        decl('filter', cssFilterValue),
      ],
    })

    functionalUtility('backdrop-brightness', {
      themeKeys: ['--backdrop-brightness', '--brightness'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}%`
      },
      handle: (value) => [
        backdropFilterProperties(),
        decl('--tw-backdrop-brightness', `brightness(${value})`),
        decl('-webkit-backdrop-filter', cssBackdropFilterValue),
        decl('backdrop-filter', cssBackdropFilterValue),
      ],
    })

    suggest('brightness', () => [
      {
        values: ['0', '50', '75', '90', '95', '100', '105', '110', '125', '150', '200'],
        valueThemeKeys: ['--brightness'],
      },
    ])

    suggest('backdrop-brightness', () => [
      {
        values: ['0', '50', '75', '90', '95', '100', '105', '110', '125', '150', '200'],
        valueThemeKeys: ['--backdrop-brightness', '--brightness'],
      },
    ])

    functionalUtility('contrast', {
      themeKeys: ['--contrast'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}%`
      },
      handle: (value) => [
        filterProperties(),
        decl('--tw-contrast', `contrast(${value})`),
        decl('filter', cssFilterValue),
      ],
    })

    functionalUtility('backdrop-contrast', {
      themeKeys: ['--backdrop-contrast', '--contrast'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}%`
      },
      handle: (value) => [
        backdropFilterProperties(),
        decl('--tw-backdrop-contrast', `contrast(${value})`),
        decl('-webkit-backdrop-filter', cssBackdropFilterValue),
        decl('backdrop-filter', cssBackdropFilterValue),
      ],
    })

    suggest('contrast', () => [
      {
        values: ['0', '50', '75', '100', '125', '150', '200'],
        valueThemeKeys: ['--contrast'],
      },
    ])

    suggest('backdrop-contrast', () => [
      {
        values: ['0', '50', '75', '100', '125', '150', '200'],
        valueThemeKeys: ['--backdrop-contrast', '--contrast'],
      },
    ])

    functionalUtility('grayscale', {
      themeKeys: ['--grayscale'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}%`
      },
      defaultValue: '100%',
      handle: (value) => [
        filterProperties(),
        decl('--tw-grayscale', `grayscale(${value})`),
        decl('filter', cssFilterValue),
      ],
    })

    functionalUtility('backdrop-grayscale', {
      themeKeys: ['--backdrop-grayscale', '--grayscale'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}%`
      },
      defaultValue: '100%',
      handle: (value) => [
        backdropFilterProperties(),
        decl('--tw-backdrop-grayscale', `grayscale(${value})`),
        decl('-webkit-backdrop-filter', cssBackdropFilterValue),
        decl('backdrop-filter', cssBackdropFilterValue),
      ],
    })

    suggest('grayscale', () => [
      {
        values: ['0', '25', '50', '75', '100'],
        valueThemeKeys: ['--grayscale'],
        hasDefaultValue: true,
      },
    ])

    suggest('backdrop-grayscale', () => [
      {
        values: ['0', '25', '50', '75', '100'],
        valueThemeKeys: ['--backdrop-grayscale', '--grayscale'],
        hasDefaultValue: true,
      },
    ])

    functionalUtility('hue-rotate', {
      supportsNegative: true,
      themeKeys: ['--hue-rotate'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}deg`
      },
      handle: (value) => [
        filterProperties(),
        decl('--tw-hue-rotate', `hue-rotate(${value})`),
        decl('filter', cssFilterValue),
      ],
    })

    functionalUtility('backdrop-hue-rotate', {
      supportsNegative: true,
      themeKeys: ['--backdrop-hue-rotate', '--hue-rotate'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}deg`
      },
      handle: (value) => [
        backdropFilterProperties(),
        decl('--tw-backdrop-hue-rotate', `hue-rotate(${value})`),
        decl('-webkit-backdrop-filter', cssBackdropFilterValue),
        decl('backdrop-filter', cssBackdropFilterValue),
      ],
    })

    suggest('hue-rotate', () => [
      {
        values: ['0', '15', '30', '60', '90', '180'],
        valueThemeKeys: ['--hue-rotate'],
      },
    ])

    suggest('backdrop-hue-rotate', () => [
      {
        values: ['0', '15', '30', '60', '90', '180'],
        valueThemeKeys: ['--backdrop-hue-rotate', '--hue-rotate'],
      },
    ])

    functionalUtility('invert', {
      themeKeys: ['--invert'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}%`
      },
      defaultValue: '100%',
      handle: (value) => [
        filterProperties(),
        decl('--tw-invert', `invert(${value})`),
        decl('filter', cssFilterValue),
      ],
    })

    functionalUtility('backdrop-invert', {
      themeKeys: ['--backdrop-invert', '--invert'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}%`
      },
      defaultValue: '100%',
      handle: (value) => [
        backdropFilterProperties(),
        decl('--tw-backdrop-invert', `invert(${value})`),
        decl('-webkit-backdrop-filter', cssBackdropFilterValue),
        decl('backdrop-filter', cssBackdropFilterValue),
      ],
    })

    suggest('invert', () => [
      {
        values: ['0', '25', '50', '75', '100'],
        valueThemeKeys: ['--invert'],
        hasDefaultValue: true,
      },
    ])

    suggest('backdrop-invert', () => [
      {
        values: ['0', '25', '50', '75', '100'],
        valueThemeKeys: ['--backdrop-invert', '--invert'],
        hasDefaultValue: true,
      },
    ])

    functionalUtility('saturate', {
      themeKeys: ['--saturate'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}%`
      },
      handle: (value) => [
        filterProperties(),
        decl('--tw-saturate', `saturate(${value})`),
        decl('filter', cssFilterValue),
      ],
    })

    functionalUtility('backdrop-saturate', {
      themeKeys: ['--backdrop-saturate', '--saturate'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}%`
      },
      handle: (value) => [
        backdropFilterProperties(),
        decl('--tw-backdrop-saturate', `saturate(${value})`),
        decl('-webkit-backdrop-filter', cssBackdropFilterValue),
        decl('backdrop-filter', cssBackdropFilterValue),
      ],
    })

    suggest('saturate', () => [
      {
        values: ['0', '50', '100', '150', '200'],
        valueThemeKeys: ['--saturate'],
      },
    ])

    suggest('backdrop-saturate', () => [
      {
        values: ['0', '50', '100', '150', '200'],
        valueThemeKeys: ['--backdrop-saturate', '--saturate'],
      },
    ])

    functionalUtility('sepia', {
      themeKeys: ['--sepia'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}%`
      },
      defaultValue: '100%',
      handle: (value) => [
        filterProperties(),
        decl('--tw-sepia', `sepia(${value})`),
        decl('filter', cssFilterValue),
      ],
    })

    functionalUtility('backdrop-sepia', {
      themeKeys: ['--backdrop-sepia', '--sepia'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}%`
      },
      defaultValue: '100%',
      handle: (value) => [
        backdropFilterProperties(),
        decl('--tw-backdrop-sepia', `sepia(${value})`),
        decl('-webkit-backdrop-filter', cssBackdropFilterValue),
        decl('backdrop-filter', cssBackdropFilterValue),
      ],
    })

    suggest('sepia', () => [
      {
        values: ['0', '50', '100'],
        valueThemeKeys: ['--sepia'],
        hasDefaultValue: true,
      },
    ])

    suggest('backdrop-sepia', () => [
      {
        values: ['0', '50', '100'],
        valueThemeKeys: ['--backdrop-sepia', '--sepia'],
        hasDefaultValue: true,
      },
    ])

    staticUtility('drop-shadow-none', [
      filterProperties,
      ['--tw-drop-shadow', ' '],
      ['filter', cssFilterValue],
    ])

    utilities.functional('drop-shadow', (candidate) => {
      let alpha: string | undefined

      if (candidate.modifier) {
        if (candidate.modifier.kind === 'arbitrary') {
          alpha = candidate.modifier.value
        } else {
          if (isPositiveInteger(candidate.modifier.value)) {
            alpha = `${candidate.modifier.value}%`
          }
        }
      }

      if (!candidate.value) {
        let value = theme.get(['--drop-shadow'])
        let resolved = theme.resolve(null, ['--drop-shadow'])
        if (value === null || resolved === null) return

        return [
          filterProperties(),
          decl('--tw-drop-shadow-alpha', alpha),
          ...alphaReplacedDropShadowProperties(
            '--tw-drop-shadow-size',
            value,
            alpha,
            (color) => `var(--tw-drop-shadow-color, ${color})`,
          ),
          decl(
            '--tw-drop-shadow',
            segment(resolved, ',')
              .map((value) => `drop-shadow(${value})`)
              .join(' '),
          ),
          decl('filter', cssFilterValue),
        ]
      }

      if (candidate.value.kind === 'arbitrary') {
        let value: string | null = candidate.value.value
        let type = candidate.value.dataType ?? inferDataType(value, ['color'])

        switch (type) {
          case 'color': {
            value = asColor(value, candidate.modifier, theme)
            if (value === null) return
            return [
              filterProperties(),
              decl('--tw-drop-shadow-color', withAlpha(value, 'var(--tw-drop-shadow-alpha)')),
              decl('--tw-drop-shadow', `var(--tw-drop-shadow-size)`),
            ]
          }
          default: {
            if (candidate.modifier && !alpha) return

            return [
              filterProperties(),
              decl('--tw-drop-shadow-alpha', alpha),
              ...alphaReplacedDropShadowProperties(
                '--tw-drop-shadow-size',
                value,
                alpha,
                (color) => `var(--tw-drop-shadow-color, ${color})`,
              ),
              decl('--tw-drop-shadow', `var(--tw-drop-shadow-size)`),
              decl('filter', cssFilterValue),
            ]
          }
        }
      }

      // Shadow size
      {
        let value = theme.get([`--drop-shadow-${candidate.value.value}`])
        let resolved = theme.resolve(candidate.value.value, ['--drop-shadow'])
        if (value && resolved) {
          if (candidate.modifier && !alpha) return

          if (alpha) {
            return [
              filterProperties(),
              decl('--tw-drop-shadow-alpha', alpha),
              ...alphaReplacedDropShadowProperties(
                '--tw-drop-shadow-size',
                value,
                alpha,
                (color) => `var(--tw-drop-shadow-color, ${color})`,
              ),
              decl('--tw-drop-shadow', `var(--tw-drop-shadow-size)`),
              decl('filter', cssFilterValue),
            ]
          }

          return [
            filterProperties(),
            decl('--tw-drop-shadow-alpha', alpha),
            ...alphaReplacedDropShadowProperties(
              '--tw-drop-shadow-size',
              value,
              alpha,
              (color) => `var(--tw-drop-shadow-color, ${color})`,
            ),
            decl(
              '--tw-drop-shadow',
              segment(resolved, ',')
                .map((value) => `drop-shadow(${value})`)
                .join(' '),
            ),
            decl('filter', cssFilterValue),
          ]
        }
      }

      // Shadow color
      {
        let value = resolveThemeColor(candidate, theme, ['--drop-shadow-color', '--color'])
        if (value) {
          if (value === 'inherit') {
            return [
              filterProperties(),
              decl('--tw-drop-shadow-color', 'inherit'),
              decl('--tw-drop-shadow', `var(--tw-drop-shadow-size)`),
            ]
          }

          return [
            filterProperties(),
            decl('--tw-drop-shadow-color', withAlpha(value, 'var(--tw-drop-shadow-alpha)')),
            decl('--tw-drop-shadow', `var(--tw-drop-shadow-size)`),
          ]
        }
      }
    })

    suggest('drop-shadow', () => [
      {
        values: ['current', 'inherit', 'transparent'],
        valueThemeKeys: ['--drop-shadow-color', '--color'],
        modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
      },
      {
        valueThemeKeys: ['--drop-shadow'],
      },
    ])

    functionalUtility('backdrop-opacity', {
      themeKeys: ['--backdrop-opacity', '--opacity'],
      handleBareValue: ({ value }) => {
        if (!isValidOpacityValue(value)) return null
        return `${value}%`
      },
      handle: (value) => [
        backdropFilterProperties(),
        decl('--tw-backdrop-opacity', `opacity(${value})`),
        decl('-webkit-backdrop-filter', cssBackdropFilterValue),
        decl('backdrop-filter', cssBackdropFilterValue),
      ],
    })

    suggest('backdrop-opacity', () => [
      {
        values: Array.from({ length: 21 }, (_, i) => `${i * 5}`),
        valueThemeKeys: ['--backdrop-opacity', '--opacity'],
      },
    ])
  }

  {
    let defaultTimingFunction = `var(--tw-ease, ${theme.resolve(null, ['--default-transition-timing-function']) ?? 'ease'})`
    let defaultDuration = `var(--tw-duration, ${theme.resolve(null, ['--default-transition-duration']) ?? '0s'})`

    functionalUtility('transition', {
      defaultValue:
        'color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events',
      themeKeys: ['--transition-property'],
      handle: (value) => [
        decl('transition-property', value),
        decl('transition-timing-function', defaultTimingFunction),
        decl('transition-duration', defaultDuration),
      ],
      staticValues: {
        none: [decl('transition-property', 'none')],
        all: [
          decl('transition-property', 'all'),
          decl('transition-timing-function', defaultTimingFunction),
          decl('transition-duration', defaultDuration),
        ],
        colors: [
          decl(
            'transition-property',
            'color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to',
          ),
          decl('transition-timing-function', defaultTimingFunction),
          decl('transition-duration', defaultDuration),
        ],
        opacity: [
          decl('transition-property', 'opacity'),
          decl('transition-timing-function', defaultTimingFunction),
          decl('transition-duration', defaultDuration),
        ],
        shadow: [
          decl('transition-property', 'box-shadow'),
          decl('transition-timing-function', defaultTimingFunction),
          decl('transition-duration', defaultDuration),
        ],
        transform: [
          decl('transition-property', 'transform, translate, scale, rotate'),
          decl('transition-timing-function', defaultTimingFunction),
          decl('transition-duration', defaultDuration),
        ],
      },
    })

    staticUtility('transition-discrete', [['transition-behavior', 'allow-discrete']])
    staticUtility('transition-normal', [['transition-behavior', 'normal']])

    functionalUtility('delay', {
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}ms`
      },
      themeKeys: ['--transition-delay'],
      handle: (value) => [decl('transition-delay', value)],
    })

    {
      let transitionDurationProperty = () => {
        return atRoot([property('--tw-duration')])
      }

      staticUtility('duration-initial', [transitionDurationProperty, ['--tw-duration', 'initial']])

      utilities.functional('duration', (candidate) => {
        // This utility doesn't support modifiers.
        if (candidate.modifier) return

        // This utility doesn't support `DEFAULT` values.
        if (!candidate.value) return

        // Find the actual CSS value that the candidate value maps to.
        let value: string | null = null

        if (candidate.value.kind === 'arbitrary') {
          value = candidate.value.value
        } else {
          value = theme.resolve(candidate.value.fraction ?? candidate.value.value, [
            '--transition-duration',
          ])

          if (value === null && isPositiveInteger(candidate.value.value)) {
            value = `${candidate.value.value}ms`
          }
        }

        // If the candidate value (like the `sm` in `max-w-sm`) doesn't resolve to
        // an actual value, don't generate any rules.
        if (value === null) return

        return [
          transitionDurationProperty(),
          decl('--tw-duration', value),
          decl('transition-duration', value),
        ]
      })
    }

    suggest('delay', () => [
      {
        values: ['75', '100', '150', '200', '300', '500', '700', '1000'],
        valueThemeKeys: ['--transition-delay'],
      },
    ])

    suggest('duration', () => [
      {
        values: ['75', '100', '150', '200', '300', '500', '700', '1000'],
        valueThemeKeys: ['--transition-duration'],
      },
    ])
  }

  {
    let transitionTimingFunctionProperty = () => {
      return atRoot([property('--tw-ease')])
    }

    functionalUtility('ease', {
      themeKeys: ['--ease'],
      handle: (value) => [
        transitionTimingFunctionProperty(),
        decl('--tw-ease', value),
        decl('transition-timing-function', value),
      ],
      staticValues: {
        initial: [transitionTimingFunctionProperty(), decl('--tw-ease', 'initial')],
        linear: [
          transitionTimingFunctionProperty(),
          decl('--tw-ease', 'linear'),
          decl('transition-timing-function', 'linear'),
        ],
      },
    })
  }

  staticUtility('will-change-auto', [['will-change', 'auto']])
  staticUtility('will-change-scroll', [['will-change', 'scroll-position']])
  staticUtility('will-change-contents', [['will-change', 'contents']])
  staticUtility('will-change-transform', [['will-change', 'transform']])
  functionalUtility('will-change', {
    themeKeys: [],
    handle: (value) => [decl('will-change', value)],
  })

  staticUtility('content-none', [
    ['--tw-content', 'none'],
    ['content', 'none'],
  ])
  functionalUtility('content', {
    // BC: We only read from the `--content` theme key for compatibility reasons. It's recommended
    // to use the utility with arbitrary values instead.
    themeKeys: ['--content'],
    handle: (value) => [
      atRoot([property('--tw-content', '""')]),
      decl('--tw-content', value),
      decl('content', 'var(--tw-content)'),
    ],
  })

  {
    let cssContainValue =
      'var(--tw-contain-size,) var(--tw-contain-layout,) var(--tw-contain-paint,) var(--tw-contain-style,)'
    let cssContainProperties = () => {
      return atRoot([
        property('--tw-contain-size'),
        property('--tw-contain-layout'),
        property('--tw-contain-paint'),
        property('--tw-contain-style'),
      ])
    }

    staticUtility('contain-none', [['contain', 'none']])
    staticUtility('contain-content', [['contain', 'content']])
    staticUtility('contain-strict', [['contain', 'strict']])

    staticUtility('contain-size', [
      cssContainProperties,
      ['--tw-contain-size', 'size'],
      ['contain', cssContainValue],
    ])

    staticUtility('contain-inline-size', [
      cssContainProperties,
      ['--tw-contain-size', 'inline-size'],
      ['contain', cssContainValue],
    ])

    staticUtility('contain-layout', [
      cssContainProperties,
      ['--tw-contain-layout', 'layout'],
      ['contain', cssContainValue],
    ])

    staticUtility('contain-paint', [
      cssContainProperties,
      ['--tw-contain-paint', 'paint'],
      ['contain', cssContainValue],
    ])

    staticUtility('contain-style', [
      cssContainProperties,
      ['--tw-contain-style', 'style'],
      ['contain', cssContainValue],
    ])

    functionalUtility('contain', {
      themeKeys: [],
      handle: (value) => [decl('contain', value)],
    })
  }

  staticUtility('forced-color-adjust-none', [['forced-color-adjust', 'none']])
  staticUtility('forced-color-adjust-auto', [['forced-color-adjust', 'auto']])

  spacingUtility(
    'leading',
    ['--leading', '--spacing'],
    (value) => [
      atRoot([property('--tw-leading')]),
      decl('--tw-leading', value),
      decl('line-height', value),
    ],
    {
      staticValues: {
        none: [
          atRoot([property('--tw-leading')]),
          decl('--tw-leading', '1'),
          decl('line-height', '1'),
        ],
      },
    },
  )

  functionalUtility('tracking', {
    supportsNegative: true,
    themeKeys: ['--tracking'],
    handle: (value) => [
      atRoot([property('--tw-tracking')]),
      decl('--tw-tracking', value),
      decl('letter-spacing', value),
    ],
  })

  staticUtility('antialiased', [
    ['-webkit-font-smoothing', 'antialiased'],
    ['-moz-osx-font-smoothing', 'grayscale'],
  ])

  staticUtility('subpixel-antialiased', [
    ['-webkit-font-smoothing', 'auto'],
    ['-moz-osx-font-smoothing', 'auto'],
  ])

  {
    let cssFontVariantNumericValue =
      'var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)'
    let fontVariantNumericProperties = () => {
      return atRoot([
        property('--tw-ordinal'),
        property('--tw-slashed-zero'),
        property('--tw-numeric-figure'),
        property('--tw-numeric-spacing'),
        property('--tw-numeric-fraction'),
      ])
    }

    staticUtility('normal-nums', [['font-variant-numeric', 'normal']])

    staticUtility('ordinal', [
      fontVariantNumericProperties,
      ['--tw-ordinal', 'ordinal'],
      ['font-variant-numeric', cssFontVariantNumericValue],
    ])

    staticUtility('slashed-zero', [
      fontVariantNumericProperties,
      ['--tw-slashed-zero', 'slashed-zero'],
      ['font-variant-numeric', cssFontVariantNumericValue],
    ])

    staticUtility('lining-nums', [
      fontVariantNumericProperties,
      ['--tw-numeric-figure', 'lining-nums'],
      ['font-variant-numeric', cssFontVariantNumericValue],
    ])

    staticUtility('oldstyle-nums', [
      fontVariantNumericProperties,
      ['--tw-numeric-figure', 'oldstyle-nums'],
      ['font-variant-numeric', cssFontVariantNumericValue],
    ])

    staticUtility('proportional-nums', [
      fontVariantNumericProperties,
      ['--tw-numeric-spacing', 'proportional-nums'],
      ['font-variant-numeric', cssFontVariantNumericValue],
    ])

    staticUtility('tabular-nums', [
      fontVariantNumericProperties,
      ['--tw-numeric-spacing', 'tabular-nums'],
      ['font-variant-numeric', cssFontVariantNumericValue],
    ])

    staticUtility('diagonal-fractions', [
      fontVariantNumericProperties,
      ['--tw-numeric-fraction', 'diagonal-fractions'],
      ['font-variant-numeric', cssFontVariantNumericValue],
    ])

    staticUtility('stacked-fractions', [
      fontVariantNumericProperties,
      ['--tw-numeric-fraction', 'stacked-fractions'],
      ['font-variant-numeric', cssFontVariantNumericValue],
    ])
  }

  {
    let outlineProperties = () => {
      return atRoot([property('--tw-outline-style', 'solid')])
    }

    utilities.static('outline-hidden', () => {
      return [
        decl('--tw-outline-style', 'none'),
        decl('outline-style', 'none'),
        atRule('@media', '(forced-colors: active)', [
          decl('outline', '2px solid transparent'),
          decl('outline-offset', '2px'),
        ]),
      ]
    })

    /**
     * @css `outline-style`
     */
    staticUtility('outline-none', [
      ['--tw-outline-style', 'none'],
      ['outline-style', 'none'],
    ])
    staticUtility('outline-solid', [
      ['--tw-outline-style', 'solid'],
      ['outline-style', 'solid'],
    ])
    staticUtility('outline-dashed', [
      ['--tw-outline-style', 'dashed'],
      ['outline-style', 'dashed'],
    ])
    staticUtility('outline-dotted', [
      ['--tw-outline-style', 'dotted'],
      ['outline-style', 'dotted'],
    ])
    staticUtility('outline-double', [
      ['--tw-outline-style', 'double'],
      ['outline-style', 'double'],
    ])

    utilities.functional('outline', (candidate) => {
      if (candidate.value === null) {
        if (candidate.modifier) return
        let value = theme.get(['--default-outline-width']) ?? '1px'
        return [
          outlineProperties(),
          decl('outline-style', 'var(--tw-outline-style)'),
          decl('outline-width', value),
        ]
      }

      if (candidate.value.kind === 'arbitrary') {
        let value: string | null = candidate.value.value
        let type =
          candidate.value.dataType ??
          inferDataType(value, ['color', 'length', 'number', 'percentage'])

        switch (type) {
          case 'length':
          case 'number':
          case 'percentage': {
            if (candidate.modifier) return
            return [
              outlineProperties(),
              decl('outline-style', 'var(--tw-outline-style)'),
              decl('outline-width', value),
            ]
          }
          default: {
            value = asColor(value, candidate.modifier, theme)
            if (value === null) return

            return [decl('outline-color', value)]
          }
        }
      }

      // `outline-color` property
      {
        let value = resolveThemeColor(candidate, theme, ['--outline-color', '--color'])
        if (value) {
          return [decl('outline-color', value)]
        }
      }

      // `outline-width` property
      {
        if (candidate.modifier) return
        let value = theme.resolve(candidate.value.value, ['--outline-width'])
        if (value) {
          return [
            outlineProperties(),
            decl('outline-style', 'var(--tw-outline-style)'),
            decl('outline-width', value),
          ]
        } else if (isPositiveInteger(candidate.value.value)) {
          return [
            outlineProperties(),
            decl('outline-style', 'var(--tw-outline-style)'),
            decl('outline-width', `${candidate.value.value}px`),
          ]
        }
      }
    })

    suggest('outline', () => [
      {
        values: ['current', 'inherit', 'transparent'],
        valueThemeKeys: ['--outline-color', '--color'],
        modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
        hasDefaultValue: true,
      },
      {
        values: ['0', '1', '2', '4', '8'],
        valueThemeKeys: ['--outline-width'],
      },
    ])

    functionalUtility('outline-offset', {
      supportsNegative: true,
      themeKeys: ['--outline-offset'],
      handleBareValue: ({ value }) => {
        if (!isPositiveInteger(value)) return null
        return `${value}px`
      },
      handle: (value) => [decl('outline-offset', value)],
    })

    suggest('outline-offset', () => [
      {
        supportsNegative: true,
        values: ['0', '1', '2', '4', '8'],
        valueThemeKeys: ['--outline-offset'],
      },
    ])
  }

  functionalUtility('opacity', {
    themeKeys: ['--opacity'],
    handleBareValue: ({ value }) => {
      if (!isValidOpacityValue(value)) return null
      return `${value}%`
    },
    handle: (value) => [decl('opacity', value)],
  })

  suggest('opacity', () => [
    {
      values: Array.from({ length: 21 }, (_, i) => `${i * 5}`),
      valueThemeKeys: ['--opacity'],
    },
  ])

  functionalUtility('underline-offset', {
    supportsNegative: true,
    themeKeys: ['--text-underline-offset'],
    handleBareValue: ({ value }) => {
      if (!isPositiveInteger(value)) return null
      return `${value}px`
    },
    handle: (value) => [decl('text-underline-offset', value)],
    staticValues: {
      auto: [decl('text-underline-offset', 'auto')],
    },
  })

  suggest('underline-offset', () => [
    {
      supportsNegative: true,
      values: ['0', '1', '2', '4', '8'],
      valueThemeKeys: ['--text-underline-offset'],
    },
  ])

  utilities.functional('text', (candidate) => {
    if (!candidate.value) return

    if (candidate.value.kind === 'arbitrary') {
      let value: string | null = candidate.value.value
      let type =
        candidate.value.dataType ??
        inferDataType(value, ['color', 'length', 'percentage', 'absolute-size', 'relative-size'])

      switch (type) {
        case 'size':
        case 'length':
        case 'percentage':
        case 'absolute-size':
        case 'relative-size': {
          if (candidate.modifier) {
            let modifier =
              candidate.modifier.kind === 'arbitrary'
                ? candidate.modifier.value
                : theme.resolve(candidate.modifier.value, ['--leading'])

            if (!modifier && isValidSpacingMultiplier(candidate.modifier.value)) {
              let multiplier = theme.resolve(null, ['--spacing'])
              if (!multiplier) return null
              modifier = `calc(${multiplier} * ${candidate.modifier.value})`
            }

            // Shorthand for `leading-none`
            if (!modifier && candidate.modifier.value === 'none') {
              modifier = '1'
            }

            if (modifier) {
              return [decl('font-size', value), decl('line-height', modifier)]
            }

            return null
          }

          return [decl('font-size', value)]
        }
        default: {
          value = asColor(value, candidate.modifier, theme)
          if (value === null) return

          return [decl('color', value)]
        }
      }
    }

    // `color` property
    {
      let value = resolveThemeColor(candidate, theme, ['--text-color', '--color'])
      if (value) {
        return [decl('color', value)]
      }
    }

    // `font-size` property
    {
      let value = theme.resolveWith(
        candidate.value.value,
        ['--text'],
        ['--line-height', '--letter-spacing', '--font-weight'],
      )
      if (value) {
        let [fontSize, options = {}] = Array.isArray(value) ? value : [value]

        if (candidate.modifier) {
          let modifier =
            candidate.modifier.kind === 'arbitrary'
              ? candidate.modifier.value
              : theme.resolve(candidate.modifier.value, ['--leading'])

          if (!modifier && isValidSpacingMultiplier(candidate.modifier.value)) {
            let multiplier = theme.resolve(null, ['--spacing'])
            if (!multiplier) return null
            modifier = `calc(${multiplier} * ${candidate.modifier.value})`
          }

          // Shorthand for `leading-none`
          if (!modifier && candidate.modifier.value === 'none') {
            modifier = '1'
          }

          if (!modifier) {
            return null
          }

          let declarations = [decl('font-size', fontSize)]
          modifier && declarations.push(decl('line-height', modifier))
          return declarations
        }

        if (typeof options === 'string') {
          return [decl('font-size', fontSize), decl('line-height', options)]
        }

        return [
          decl('font-size', fontSize),
          decl(
            'line-height',
            options['--line-height'] ? `var(--tw-leading, ${options['--line-height']})` : undefined,
          ),
          decl(
            'letter-spacing',
            options['--letter-spacing']
              ? `var(--tw-tracking, ${options['--letter-spacing']})`
              : undefined,
          ),
          decl(
            'font-weight',
            options['--font-weight']
              ? `var(--tw-font-weight, ${options['--font-weight']})`
              : undefined,
          ),
        ]
      }
    }
  })

  suggest('text', () => [
    {
      values: ['current', 'inherit', 'transparent'],
      valueThemeKeys: ['--text-color', '--color'],
      modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
    },
    {
      values: [],
      valueThemeKeys: ['--text'],
      modifiers: [],
      modifierThemeKeys: ['--leading'],
    },
  ])

  let textShadowProperties = () => {
    return atRoot([
      property('--tw-text-shadow-color'),
      property('--tw-text-shadow-alpha', '100%', '<percentage>'),
    ])
  }

  staticUtility('text-shadow-initial', [
    textShadowProperties,
    ['--tw-text-shadow-color', 'initial'],
  ])

  utilities.functional('text-shadow', (candidate) => {
    let alpha: string | undefined

    if (candidate.modifier) {
      if (candidate.modifier.kind === 'arbitrary') {
        alpha = candidate.modifier.value
      } else {
        if (isPositiveInteger(candidate.modifier.value)) {
          alpha = `${candidate.modifier.value}%`
        }
      }
    }

    if (!candidate.value) {
      let value = theme.get(['--text-shadow'])
      if (value === null) return

      return [
        textShadowProperties(),
        decl('--tw-text-shadow-alpha', alpha),
        ...alphaReplacedShadowProperties(
          'text-shadow',
          value,
          alpha,
          (color) => `var(--tw-text-shadow-color, ${color})`,
        ),
      ]
    }

    if (candidate.value.kind === 'arbitrary') {
      let value: string | null = candidate.value.value
      let type = candidate.value.dataType ?? inferDataType(value, ['color'])

      switch (type) {
        case 'color': {
          value = asColor(value, candidate.modifier, theme)
          if (value === null) return
          return [
            textShadowProperties(),
            decl('--tw-text-shadow-color', withAlpha(value, 'var(--tw-text-shadow-alpha)')),
          ]
        }
        default: {
          return [
            textShadowProperties(),
            decl('--tw-text-shadow-alpha', alpha),
            ...alphaReplacedShadowProperties(
              'text-shadow',
              value,
              alpha,
              (color) => `var(--tw-text-shadow-color, ${color})`,
            ),
          ]
        }
      }
    }

    switch (candidate.value.value) {
      case 'none':
        if (candidate.modifier) return
        return [textShadowProperties(), decl('text-shadow', 'none')]

      case 'inherit':
        if (candidate.modifier) return
        return [textShadowProperties(), decl('--tw-text-shadow-color', 'inherit')]
    }

    // Shadow size
    {
      let value = theme.get([`--text-shadow-${candidate.value.value}`])
      if (value) {
        return [
          textShadowProperties(),
          decl('--tw-text-shadow-alpha', alpha),
          ...alphaReplacedShadowProperties(
            'text-shadow',
            value,
            alpha,
            (color) => `var(--tw-text-shadow-color, ${color})`,
          ),
        ]
      }
    }

    // Shadow color
    {
      let value = resolveThemeColor(candidate, theme, ['--text-shadow-color', '--color'])
      if (value) {
        return [
          textShadowProperties(),
          decl('--tw-text-shadow-color', withAlpha(value, 'var(--tw-text-shadow-alpha)')),
        ]
      }
    }
  })

  suggest('text-shadow', () => [
    {
      values: ['current', 'inherit', 'transparent'],
      valueThemeKeys: ['--text-shadow-color', '--color'],
      modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
    },
    {
      values: ['none'],
    },
    {
      valueThemeKeys: ['--text-shadow'],
      modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
      hasDefaultValue: theme.get(['--text-shadow']) !== null,
    },
  ])

  {
    let cssBoxShadowValue = [
      'var(--tw-inset-shadow)',
      'var(--tw-inset-ring-shadow)',
      'var(--tw-ring-offset-shadow)',
      'var(--tw-ring-shadow)',
      'var(--tw-shadow)',
    ].join(', ')
    let nullShadow = '0 0 #0000'

    let boxShadowProperties = () => {
      return atRoot([
        property('--tw-shadow', nullShadow),
        property('--tw-shadow-color'),
        property('--tw-shadow-alpha', '100%', '<percentage>'),
        property('--tw-inset-shadow', nullShadow),
        property('--tw-inset-shadow-color'),
        property('--tw-inset-shadow-alpha', '100%', '<percentage>'),
        property('--tw-ring-color'),
        property('--tw-ring-shadow', nullShadow),
        property('--tw-inset-ring-color'),
        property('--tw-inset-ring-shadow', nullShadow),

        // Legacy
        property('--tw-ring-inset'),
        property('--tw-ring-offset-width', '0px', '<length>'),
        property('--tw-ring-offset-color', '#fff'),
        property('--tw-ring-offset-shadow', nullShadow),
      ])
    }

    staticUtility('shadow-initial', [boxShadowProperties, ['--tw-shadow-color', 'initial']])

    utilities.functional('shadow', (candidate) => {
      let alpha: string | undefined

      if (candidate.modifier) {
        if (candidate.modifier.kind === 'arbitrary') {
          alpha = candidate.modifier.value
        } else {
          if (isPositiveInteger(candidate.modifier.value)) {
            alpha = `${candidate.modifier.value}%`
          }
        }
      }

      if (!candidate.value) {
        let value = theme.get(['--shadow'])
        if (value === null) return

        return [
          boxShadowProperties(),
          decl('--tw-shadow-alpha', alpha),
          ...alphaReplacedShadowProperties(
            '--tw-shadow',
            value,
            alpha,
            (color) => `var(--tw-shadow-color, ${color})`,
          ),
          decl('box-shadow', cssBoxShadowValue),
        ]
      }

      if (candidate.value.kind === 'arbitrary') {
        let value: string | null = candidate.value.value
        let type = candidate.value.dataType ?? inferDataType(value, ['color'])

        switch (type) {
          case 'color': {
            value = asColor(value, candidate.modifier, theme)
            if (value === null) return

            return [
              boxShadowProperties(),
              decl('--tw-shadow-color', withAlpha(value, 'var(--tw-shadow-alpha)')),
            ]
          }
          default: {
            return [
              boxShadowProperties(),
              decl('--tw-shadow-alpha', alpha),
              ...alphaReplacedShadowProperties(
                '--tw-shadow',
                value,
                alpha,
                (color) => `var(--tw-shadow-color, ${color})`,
              ),
              decl('box-shadow', cssBoxShadowValue),
            ]
          }
        }
      }

      switch (candidate.value.value) {
        case 'none':
          if (candidate.modifier) return
          return [
            boxShadowProperties(),
            decl('--tw-shadow', nullShadow),
            decl('box-shadow', cssBoxShadowValue),
          ]

        case 'inherit':
          if (candidate.modifier) return
          return [boxShadowProperties(), decl('--tw-shadow-color', 'inherit')]
      }

      // Shadow size
      {
        let value = theme.get([`--shadow-${candidate.value.value}`])
        if (value) {
          return [
            boxShadowProperties(),
            decl('--tw-shadow-alpha', alpha),
            ...alphaReplacedShadowProperties(
              '--tw-shadow',
              value,
              alpha,
              (color) => `var(--tw-shadow-color, ${color})`,
            ),
            decl('box-shadow', cssBoxShadowValue),
          ]
        }
      }

      // Shadow color
      {
        let value = resolveThemeColor(candidate, theme, ['--box-shadow-color', '--color'])
        if (value) {
          return [
            boxShadowProperties(),
            decl('--tw-shadow-color', withAlpha(value, 'var(--tw-shadow-alpha)')),
          ]
        }
      }
    })

    suggest('shadow', () => [
      {
        values: ['current', 'inherit', 'transparent'],
        valueThemeKeys: ['--box-shadow-color', '--color'],
        modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
      },
      {
        values: ['none'],
      },
      {
        valueThemeKeys: ['--shadow'],
        modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
        hasDefaultValue: theme.get(['--shadow']) !== null,
      },
    ])

    staticUtility('inset-shadow-initial', [
      boxShadowProperties,
      ['--tw-inset-shadow-color', 'initial'],
    ])

    utilities.functional('inset-shadow', (candidate) => {
      let alpha: string | undefined

      if (candidate.modifier) {
        if (candidate.modifier.kind === 'arbitrary') {
          alpha = candidate.modifier.value
        } else {
          if (isPositiveInteger(candidate.modifier.value)) {
            alpha = `${candidate.modifier.value}%`
          }
        }
      }

      if (!candidate.value) {
        let value = theme.get(['--inset-shadow'])
        if (value === null) return

        return [
          boxShadowProperties(),
          decl('--tw-inset-shadow-alpha', alpha),
          ...alphaReplacedShadowProperties(
            '--tw-inset-shadow',
            value,
            alpha,
            (color) => `var(--tw-inset-shadow-color, ${color})`,
          ),
          decl('box-shadow', cssBoxShadowValue),
        ]
      }

      if (candidate.value.kind === 'arbitrary') {
        let value: string | null = candidate.value.value
        let type = candidate.value.dataType ?? inferDataType(value, ['color'])

        switch (type) {
          case 'color': {
            value = asColor(value, candidate.modifier, theme)
            if (value === null) return

            return [
              boxShadowProperties(),
              decl('--tw-inset-shadow-color', withAlpha(value, 'var(--tw-inset-shadow-alpha)')),
            ]
          }
          default: {
            return [
              boxShadowProperties(),
              decl('--tw-inset-shadow-alpha', alpha),
              ...alphaReplacedShadowProperties(
                '--tw-inset-shadow',
                value,
                alpha,
                (color) => `var(--tw-inset-shadow-color, ${color})`,
                'inset',
              ),
              decl('box-shadow', cssBoxShadowValue),
            ]
          }
        }
      }

      switch (candidate.value.value) {
        case 'none':
          if (candidate.modifier) return
          return [
            boxShadowProperties(),
            decl('--tw-inset-shadow', nullShadow),
            decl('box-shadow', cssBoxShadowValue),
          ]

        case 'inherit':
          if (candidate.modifier) return
          return [boxShadowProperties(), decl('--tw-inset-shadow-color', 'inherit')]
      }

      // Shadow size
      {
        let value = theme.get([`--inset-shadow-${candidate.value.value}`])

        if (value) {
          return [
            boxShadowProperties(),
            decl('--tw-inset-shadow-alpha', alpha),
            ...alphaReplacedShadowProperties(
              '--tw-inset-shadow',
              value,
              alpha,
              (color) => `var(--tw-inset-shadow-color, ${color})`,
            ),
            decl('box-shadow', cssBoxShadowValue),
          ]
        }
      }

      // Shadow color
      {
        let value = resolveThemeColor(candidate, theme, ['--box-shadow-color', '--color'])
        if (value) {
          return [
            boxShadowProperties(),
            decl('--tw-inset-shadow-color', withAlpha(value, 'var(--tw-inset-shadow-alpha)')),
          ]
        }
      }
    })

    suggest('inset-shadow', () => [
      {
        values: ['current', 'inherit', 'transparent'],
        valueThemeKeys: ['--box-shadow-color', '--color'],
        modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
      },
      {
        values: ['none'],
      },
      {
        valueThemeKeys: ['--inset-shadow'],
        modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
        hasDefaultValue: theme.get(['--inset-shadow']) !== null,
      },
    ])

    staticUtility('ring-inset', [boxShadowProperties, ['--tw-ring-inset', 'inset']])

    let defaultRingColor = theme.get(['--default-ring-color']) ?? 'currentcolor'
    function ringShadowValue(value: string) {
      return `var(--tw-ring-inset,) 0 0 0 calc(${value} + var(--tw-ring-offset-width)) var(--tw-ring-color, ${defaultRingColor})`
    }
    utilities.functional('ring', (candidate) => {
      if (!candidate.value) {
        if (candidate.modifier) return
        let value = theme.get(['--default-ring-width']) ?? '1px'
        return [
          boxShadowProperties(),
          decl('--tw-ring-shadow', ringShadowValue(value)),
          decl('box-shadow', cssBoxShadowValue),
        ]
      }

      if (candidate.value.kind === 'arbitrary') {
        let value: string | null = candidate.value.value
        let type = candidate.value.dataType ?? inferDataType(value, ['color', 'length'])

        switch (type) {
          case 'length': {
            if (candidate.modifier) return
            return [
              boxShadowProperties(),
              decl('--tw-ring-shadow', ringShadowValue(value)),
              decl('box-shadow', cssBoxShadowValue),
            ]
          }
          default: {
            value = asColor(value, candidate.modifier, theme)
            if (value === null) return

            return [decl('--tw-ring-color', value)]
          }
        }
      }

      // Ring color
      {
        let value = resolveThemeColor(candidate, theme, ['--ring-color', '--color'])
        if (value) {
          return [decl('--tw-ring-color', value)]
        }
      }

      // Ring width
      {
        if (candidate.modifier) return
        let value = theme.resolve(candidate.value.value, ['--ring-width'])
        if (value === null && isPositiveInteger(candidate.value.value)) {
          value = `${candidate.value.value}px`
        }
        if (value) {
          return [
            boxShadowProperties(),
            decl('--tw-ring-shadow', ringShadowValue(value)),
            decl('box-shadow', cssBoxShadowValue),
          ]
        }
      }
    })

    suggest('ring', () => [
      {
        values: ['current', 'inherit', 'transparent'],
        valueThemeKeys: ['--ring-color', '--color'],
        modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
      },
      {
        values: ['0', '1', '2', '4', '8'],
        valueThemeKeys: ['--ring-width'],
        hasDefaultValue: true,
      },
    ])

    function insetRingShadowValue(value: string) {
      return `inset 0 0 0 ${value} var(--tw-inset-ring-color, currentcolor)`
    }
    utilities.functional('inset-ring', (candidate) => {
      if (!candidate.value) {
        if (candidate.modifier) return
        return [
          boxShadowProperties(),
          decl('--tw-inset-ring-shadow', insetRingShadowValue('1px')),
          decl('box-shadow', cssBoxShadowValue),
        ]
      }

      if (candidate.value.kind === 'arbitrary') {
        let value: string | null = candidate.value.value
        let type = candidate.value.dataType ?? inferDataType(value, ['color', 'length'])

        switch (type) {
          case 'length': {
            if (candidate.modifier) return
            return [
              boxShadowProperties(),
              decl('--tw-inset-ring-shadow', insetRingShadowValue(value)),
              decl('box-shadow', cssBoxShadowValue),
            ]
          }
          default: {
            value = asColor(value, candidate.modifier, theme)
            if (value === null) return

            return [decl('--tw-inset-ring-color', value)]
          }
        }
      }

      // Ring color
      {
        let value = resolveThemeColor(candidate, theme, ['--ring-color', '--color'])
        if (value) {
          return [decl('--tw-inset-ring-color', value)]
        }
      }

      // Ring width
      {
        if (candidate.modifier) return
        let value = theme.resolve(candidate.value.value, ['--ring-width'])
        if (value === null && isPositiveInteger(candidate.value.value)) {
          value = `${candidate.value.value}px`
        }
        if (value) {
          return [
            boxShadowProperties(),
            decl('--tw-inset-ring-shadow', insetRingShadowValue(value)),
            decl('box-shadow', cssBoxShadowValue),
          ]
        }
      }
    })

    suggest('inset-ring', () => [
      {
        values: ['current', 'inherit', 'transparent'],
        valueThemeKeys: ['--ring-color', '--color'],
        modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
      },
      {
        values: ['0', '1', '2', '4', '8'],
        valueThemeKeys: ['--ring-width'],
        hasDefaultValue: true,
      },
    ])

    let ringOffsetShadowValue =
      'var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)'
    utilities.functional('ring-offset', (candidate) => {
      if (!candidate.value) return

      if (candidate.value.kind === 'arbitrary') {
        let value: string | null = candidate.value.value
        let type = candidate.value.dataType ?? inferDataType(value, ['color', 'length'])

        switch (type) {
          case 'length': {
            if (candidate.modifier) return
            return [
              decl('--tw-ring-offset-width', value),
              decl('--tw-ring-offset-shadow', ringOffsetShadowValue),
            ]
          }
          default: {
            value = asColor(value, candidate.modifier, theme)
            if (value === null) return

            return [decl('--tw-ring-offset-color', value)]
          }
        }
      }

      // `--tw-ring-offset-width` property
      {
        let value = theme.resolve(candidate.value.value, ['--ring-offset-width'])
        if (value) {
          if (candidate.modifier) return
          return [
            decl('--tw-ring-offset-width', value),
            decl('--tw-ring-offset-shadow', ringOffsetShadowValue),
          ]
        } else if (isPositiveInteger(candidate.value.value)) {
          if (candidate.modifier) return
          return [
            decl('--tw-ring-offset-width', `${candidate.value.value}px`),
            decl('--tw-ring-offset-shadow', ringOffsetShadowValue),
          ]
        }
      }

      // `--tw-ring-offset-color` property
      {
        let value = resolveThemeColor(candidate, theme, ['--ring-offset-color', '--color'])
        if (value) {
          return [decl('--tw-ring-offset-color', value)]
        }
      }
    })
  }

  suggest('ring-offset', () => [
    {
      values: ['current', 'inherit', 'transparent'],
      valueThemeKeys: ['--ring-offset-color', '--color'],
      modifiers: Array.from({ length: 21 }, (_, index) => `${index * 5}`),
    },
    {
      values: ['0', '1', '2', '4', '8'],
      valueThemeKeys: ['--ring-offset-width'],
    },
  ])

  utilities.functional('@container', (candidate) => {
    let value: string | null = null
    if (candidate.value === null) {
      value = 'inline-size'
    } else if (candidate.value.kind === 'arbitrary') {
      value = candidate.value.value
    } else if (candidate.value.kind === 'named' && candidate.value.value === 'normal') {
      value = 'normal'
    } else if (
      enableContainerSizeUtility &&
      candidate.value.kind === 'named' &&
      candidate.value.value === 'size'
    ) {
      value = 'size'
    }

    if (value === null) return

    if (candidate.modifier) {
      return [decl('container-type', value), decl('container-name', candidate.modifier.value)]
    }

    return [decl('container-type', value)]
  })

  suggest('@container', () => [
    {
      values: ['normal'],
      valueThemeKeys: [],
      hasDefaultValue: true,
    },
  ])

  return utilities
}

Subdomains

Frequently Asked Questions

What does createUtilities() do?
createUtilities() is a function in the tailwindcss codebase.
What calls createUtilities()?
createUtilities() is called by 1 function(s): buildDesignSystem.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free