-- Kanso Mist WezTerm Colors
local config = {
    force_reverse_video_cursor = true,
    colors =

---@class PaletteColors
local palette = {

    -- Zen Bg Shades
    zenBg0 = "#090E13",
    zenBg1 = "#1C1E25",
    zenBg2 = "#22262D",
    zenBg3 = "#393B44",

    -- Ink Bg Shades
    inkBg0 = "#14171d",
    inkBg1 = "#1f1f26",
    inkBg2 = "#22262D",
    inkBg3 = "#393B44",
    inkBg4 = "#4b4e57",

    -- Mist Bg Shades
    mistBg0 = "#22262D",
    mistBg1 = "#2a2c35",
    mistBg2 = "#393B44",
    mistBg3 = "#5C6066",

    -- Popup and Floats
    altBlue1 = "#223249",
    altBlue2 = "#2D4F67",

    -- Diff and Git
    diffGreen = "#2B3328",
    diffYellow = "#49443C",
    diffRed = "#43242B",
    diffBlue = "#252535",
    gitGreen = "#76946A",
    gitRed = "#C34043",
    gitYellow = "#DCA561",

    -- Main Colors
    red = "#C34043",
    red2 = "#E46876",
    red3 = "#c4746e",
    yellow = "#DCA561",
    yellow2 = "#E6C384",
    yellow3 = "#c4b28a",
    green = "#98BB6C",
    green2 = "#87a987",
    green3 = "#8a9a7b",
    green4 = "#6A9589",
    green5 = "#7AA89F",
    blue = "#7FB4CA",
    blue2 = "#658594",
    blue3 = "#8ba4b0",
    blue4 = "#8ea4a2",
    violet = "#938AA9",
    violet2 = "#8992a7",
    violet3 = "#949fb5",
    pink = "#a292a3",
    orange = "#b6927b",
    orange2 = "#b98d7b",
    aqua = "#8ea4a2",

    -- Contrast variants (20% more saturation)
    redContrast = "#C93134",
    red2Contrast = "#ED5965",
    red3Contrast = "#CA675F",
    yellowContrast = "#E59F49",
    yellow2Contrast = "#EDC272",
    yellow3Contrast = "#CAAC7A",
    greenContrast = "#8FC055",
    green2Contrast = "#7CAF7C",
    green3Contrast = "#7F9F6E",
    green4Contrast = "#5B9A82",
    green5Contrast = "#6BAE97",
    blueContrast = "#6EBBD4",
    blue2Contrast = "#568B8F",
    blue3Contrast = "#7EAABA",
    blue4Contrast = "#81AAA9",
    violetContrast = "#8A88B0",
    violet2Contrast = "#7E91AF",
    violet3Contrast = "#8A9FBE",
    pinkContrast = "#A08AA2",
    orangeContrast = "#BC8A6C",
    orange2Contrast = "#BF856B",
    aquaContrast = "#81AAA9",

    -- Fg and Comments
    fg = "#C5C9C7",
    fg2 = "#f2f1ef",
    gray = "#717C7C",
    gray2 = "#A4A7A4",
    gray3 = "#909398",
    gray4 = "#75797f",
    gray5 = "#5C6066",

    -- Light theme colors (pearl prefix)
    pearlBlack0 = "#22262D",
    pearlBlack1 = "#545464",
    pearlBlack2 = "#43436c",
    pearlGray = "#e2e1df",
    pearlGray2 = "#5C6068",
    pearlGray3 = "#6D6D69",
    pearlGray4 = "#9F9F99",

    pearlWhite0 = "#f2f1ef",
    pearlWhite1 = "#e2e1df",
    pearlWhite2 = "#dddddb",
    pearlWhite3 = "#cacac7",
    pearlViolet1 = "#a09cac",
    pearlViolet2 = "#766b90",
    pearlViolet3 = "#c9cbd1",
    pearlViolet4 = "#624c83",
    pearlBlue1 = "#c7d7e0",
    pearlBlue2 = "#b5cbd2",
    pearlBlue3 = "#9fb5c9",
    pearlBlue4 = "#4d699b",
    pearlBlue5 = "#5d57a3",
    pearlGreen = "#6f894e",
    pearlGreen2 = "#6e915f",
    pearlGreen3 = "#b7d0ae",
    pearlPink = "#b35b79",
    pearlOrange = "#cc6d00",
    pearlOrange2 = "#e98a00",
    pearlYellow = "#77713f",
    pearlYellow2 = "#836f4a",
    pearlYellow3 = "#de9800",
    pearlYellow4 = "#f9d791",
    pearlRed = "#c84053",
    pearlRed2 = "#d7474b",
    pearlRed3 = "#e82424",
    pearlRed4 = "#d9a594",
    pearlAqua = "#597b75",
    pearlAqua2 = "#5e857a",
    pearlTeal1 = "#4e8ca2",
    pearlTeal2 = "#6693bf",
    pearlTeal3 = "#5a7785",
    pearlCyan = "#d7e3d8",

    -- Pearl contrast variants (40% more saturation)
    pearlGreenContrast = "#5E8F2F",
    pearlGreen2Contrast = "#5B9945",
    pearlGreen3Contrast = "#A8DA9B",
    pearlPinkContrast = "#C04062",
    pearlOrangeContrast = "#E05700",
    pearlOrange2Contrast = "#FF7700",
    pearlYellowContrast = "#656720",
    pearlYellow2Contrast = "#72612B",
    pearlYellow3Contrast = "#F28C00",
    pearlYellow4Contrast = "#FFD56D",
    pearlRedContrast = "#D72436",
    pearlRed2Contrast = "#E42D2C",
    pearlRed3Contrast = "#F50000",
    pearlRed4Contrast = "#E4977B",
    pearlAquaContrast = "#3E8366",
    pearlAqua2Contrast = "#428F6A",
    pearlTeal1Contrast = "#2E96B0",
    pearlTeal2Contrast = "#469FD3",
    pearlTeal3Contrast = "#3D8077",
    pearlBlue4Contrast = "#2A73B1",
    pearlBlue5Contrast = "#3E56B8",
    pearlViolet4Contrast = "#44418F",
}

local M = {}
--- Generate colors table:
--- * opts:
---   - colors: Table of personalized colors and/or overrides of existing ones.
---     Defaults to KansoConfig.colors.
---   - theme: Use selected theme. Defaults to KansoConfig.theme
---     according to the value of 'background' option.
---@param opts? { colors?: table, theme?: string, foreground?: "default"|"contrast" }
---@return { theme: ThemeColors, palette: PaletteColors}
function M.setup(opts)
    opts = opts or {}
    local override_colors = opts.colors or require("kanso").config.colors
    local theme = opts.theme or require("kanso")._CURRENT_THEME -- WARN: this fails if called before kanso.load()

    if not theme then
        error(
            "kanso.colors.setup(): Unable to infer `theme`. Either specify a theme or call this function after ':colorscheme kanso'"
        )
    end

    -- Add to and/or override palette_colors
    local updated_palette_colors = vim.tbl_extend("force", palette, override_colors.palette or {})

    -- Generate the theme according to the updated palette colors
    local kanso_config = require("kanso").config
    local bg_mode = vim.o.background
    local foreground = opts.foreground
        or (type(kanso_config.foreground) == "table" and kanso_config.foreground[bg_mode])
        or kanso_config.foreground
        or "default"
    ---@cast foreground "default"|"contrast"
    local theme_colors = require("kanso.themes")[theme](updated_palette_colors, foreground)

    -- Add to and/or override theme_colors
    local theme_overrides =
        vim.tbl_deep_extend("force", override_colors.theme["all"] or {}, override_colors.theme[theme] or {})
    local updated_theme_colors = vim.tbl_deep_extend("force", theme_colors, theme_overrides)
    -- return palette_colors AND theme_colors

    return {
        theme = updated_theme_colors,
        palette = updated_palette_colors,
    }
end

return M

--[[
Lua implementation of HSLuv and HPLuv color spaces
Homepage: http://www.hsluv.org/

Copyright (C) 2019 Alexei Boronine

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]

local hsluv = {}

local hexChars = "0123456789abcdef"

local distance_line_from_origin = function(line)
    return math.abs(line.intercept) / math.sqrt((line.slope ^ 2) + 1)
end

local length_of_ray_until_intersect = function(theta, line)
    return line.intercept / (math.sin(theta) - line.slope * math.cos(theta))
end

hsluv.get_bounds = function(l)
    local result = {}
    local sub2
    local sub1 = ((l + 16) ^ 3) / 1560896
    if sub1 > hsluv.epsilon then
        sub2 = sub1
    else
        sub2 = l / hsluv.kappa
    end

    for i = 1, 3 do
        local m1 = hsluv.m[i][1]
        local m2 = hsluv.m[i][2]
        local m3 = hsluv.m[i][3]

        for t = 0, 1 do
            local top1 = (284517 * m1 - 94839 * m3) * sub2
            local top2 = (838422 * m3 + 769860 * m2 + 731718 * m1) * l * sub2 - 769860 * t * l
            local bottom = (632260 * m3 - 126452 * m2) * sub2 + 126452 * t
            table.insert(result, {
                slope = top1 / bottom,
                intercept = top2 / bottom,
            })
        end
    end
    return result
end

hsluv.max_safe_chroma_for_l = function(l)
    local bounds = hsluv.get_bounds(l)
    local min = 1.7976931348623157e+308

    for i = 1, 6 do
        local length = distance_line_from_origin(bounds[i])
        if length >= 0 then
            min = math.min(min, length)
        end
    end
    return min
end

hsluv.max_safe_chroma_for_lh = function(l, h)
    local hrad = h / 360 * math.pi * 2
    local bounds = hsluv.get_bounds(l)
    local min = 1.7976931348623157e+308

    for i = 1, 6 do
        local bound = bounds[i]
        local length = length_of_ray_until_intersect(hrad, bound)
        if length >= 0 then
            min = math.min(min, length)
        end
    end
    return min
end

hsluv.dot_product = function(a, b)
    local sum = 0
    for i = 1, 3 do
        sum = sum + a[i] * b[i]
    end
    return sum
end

hsluv.from_linear = function(c)
    if c <= 0.0031308 then
        return 12.92 * c
    else
        return 1.055 * (c ^ 0.416666666666666685) - 0.055
    end
end

hsluv.to_linear = function(c)
    if c > 0.04045 then
        return ((c + 0.055) / 1.055) ^ 2.4
    else
        return c / 12.92
    end
end

hsluv.xyz_to_rgb = function(tuple)
    return {
        hsluv.from_linear(hsluv.dot_product(hsluv.m[1], tuple)),
        hsluv.from_linear(hsluv.dot_product(hsluv.m[2], tuple)),
        hsluv.from_linear(hsluv.dot_product(hsluv.m[3], tuple)),
    }
end

hsluv.rgb_to_xyz = function(tuple)
    local rgbl = {
        hsluv.to_linear(tuple[1]),
        hsluv.to_linear(tuple[2]),
        hsluv.to_linear(tuple[3]),
    }
    return {
        hsluv.dot_product(hsluv.minv[1], rgbl),
        hsluv.dot_product(hsluv.minv[2], rgbl),
        hsluv.dot_product(hsluv.minv[3], rgbl),
    }
end

hsluv.y_to_l = function(Y)
    if Y <= hsluv.epsilon then
        return Y / hsluv.refY * hsluv.kappa
    else
        return 116 * ((Y / hsluv.refY) ^ 0.333333333333333315) - 16
    end
end

hsluv.l_to_y = function(L)
    if L <= 8 then
        return hsluv.refY * L / hsluv.kappa
    else
        return hsluv.refY * (((L + 16) / 116) ^ 3)
    end
end

hsluv.xyz_to_luv = function(tuple)
    local X = tuple[1]
    local Y = tuple[2]
    local divider = X + 15 * Y + 3 * tuple[3]
    local varU = 4 * X
    local varV = 9 * Y
    if divider ~= 0 then
        varU = varU / divider
        varV = varV / divider
    else
        varU = 0
        varV = 0
    end
    local L = hsluv.y_to_l(Y)
    if L == 0 then
        return { 0, 0, 0 }
    end
    return { L, 13 * L * (varU - hsluv.refU), 13 * L * (varV - hsluv.refV) }
end

hsluv.luv_to_xyz = function(tuple)
    local L = tuple[1]
    local U = tuple[2]
    local V = tuple[3]
    if L == 0 then
        return { 0, 0, 0 }
    end
    local varU = U / (13 * L) + hsluv.refU
    local varV = V / (13 * L) + hsluv.refV
    local Y = hsluv.l_to_y(L)
    local X = 0 - (9 * Y * varU) / (((varU - 4) * varV) - varU * varV)
    return { X, Y, (9 * Y - 15 * varV * Y - varV * X) / (3 * varV) }
end

hsluv.luv_to_lch = function(tuple)
    local L = tuple[1]
    local U = tuple[2]
    local V = tuple[3]
    local C = math.sqrt(U * U + V * V)
    local H
    if C < 0.00000001 then
        H = 0
    else
        H = math.atan2(V, U) * 180.0 / 3.1415926535897932
        if H < 0 then
            H = 360 + H
        end
    end
    return { L, C, H }
end

hsluv.lch_to_luv = function(tuple)
    local L = tuple[1]
    local C = tuple[2]
    local Hrad = tuple[3] / 360.0 * 2 * math.pi
    return { L, math.cos(Hrad) * C, math.sin(Hrad) * C }
end

hsluv.hsluv_to_lch = function(tuple)
    local H = tuple[1]
    local S = tuple[2]
    local L = tuple[3]
    if L > 99.9999999 then
        return { 100, 0, H }
    end
    if L < 0.00000001 then
        return { 0, 0, H }
    end
    return { L, hsluv.max_safe_chroma_for_lh(L, H) / 100 * S, H }
end

hsluv.lch_to_hsluv = function(tuple)
    local L = tuple[1]
    local C = tuple[2]
    local H = tuple[3]
    local max_chroma = hsluv.max_safe_chroma_for_lh(L, H)
    if L > 99.9999999 then
        return { H, 0, 100 }
    end
    if L < 0.00000001 then
        return { H, 0, 0 }
    end

    return { H, C / max_chroma * 100, L }
end

hsluv.hpluv_to_lch = function(tuple)
    local H = tuple[1]
    local S = tuple[2]
    local L = tuple[3]
    if L > 99.9999999 then
        return { 100, 0, H }
    end
    if L < 0.00000001 then
        return { 0, 0, H }
    end
    return { L, hsluv.max_safe_chroma_for_l(L) / 100 * S, H }
end

hsluv.lch_to_hpluv = function(tuple)
    local L = tuple[1]
    local C = tuple[2]
    local H = tuple[3]
    if L > 99.9999999 then
        return { H, 0, 100 }
    end
    if L < 0.00000001 then
        return { H, 0, 0 }
    end
    return { H, C / hsluv.max_safe_chroma_for_l(L) * 100, L }
end

hsluv.rgb_to_hex = function(tuple)
    local h = "#"
    for i = 1, 3 do
        local c = math.floor(tuple[i] * 255 + 0.5)
        local digit2 = math.fmod(c, 16)
        local x = (c - digit2) / 16
        local digit1 = math.floor(x)
        h = h .. string.sub(hexChars, digit1 + 1, digit1 + 1)
        h = h .. string.sub(hexChars, digit2 + 1, digit2 + 1)
    end
    return h
end

hsluv.hex_to_rgb = function(hex)
    hex = string.lower(hex)
    local ret = {}
    for i = 0, 2 do
        local char1 = string.sub(hex, i * 2 + 2, i * 2 + 2)
        local char2 = string.sub(hex, i * 2 + 3, i * 2 + 3)
        local digit1 = string.find(hexChars, char1) - 1
        local digit2 = string.find(hexChars, char2) - 1
        ret[i + 1] = (digit1 * 16 + digit2) / 255.0
    end
    return ret
end

hsluv.lch_to_rgb = function(tuple)
    return hsluv.xyz_to_rgb(hsluv.luv_to_xyz(hsluv.lch_to_luv(tuple)))
end

hsluv.rgb_to_lch = function(tuple)
    return hsluv.luv_to_lch(hsluv.xyz_to_luv(hsluv.rgb_to_xyz(tuple)))
end

hsluv.hsluv_to_rgb = function(tuple)
    return hsluv.lch_to_rgb(hsluv.hsluv_to_lch(tuple))
end

hsluv.rgb_to_hsluv = function(tuple)
    return hsluv.lch_to_hsluv(hsluv.rgb_to_lch(tuple))
end

hsluv.hpluv_to_rgb = function(tuple)
    return hsluv.lch_to_rgb(hsluv.hpluv_to_lch(tuple))
end

hsluv.rgb_to_hpluv = function(tuple)
    return hsluv.lch_to_hpluv(hsluv.rgb_to_lch(tuple))
end

hsluv.hsluv_to_hex = function(tuple)
    return hsluv.rgb_to_hex(hsluv.hsluv_to_rgb(tuple))
end

hsluv.hpluv_to_hex = function(tuple)
    return hsluv.rgb_to_hex(hsluv.hpluv_to_rgb(tuple))
end

hsluv.hex_to_hsluv = function(s)
    return hsluv.rgb_to_hsluv(hsluv.hex_to_rgb(s))
end

hsluv.hex_to_hpluv = function(s)
    return hsluv.rgb_to_hpluv(hsluv.hex_to_rgb(s))
end

hsluv.m = {
    { 3.240969941904521, -1.537383177570093, -0.498610760293 },
    { -0.96924363628087, 1.87596750150772, 0.041555057407175 },
    { 0.055630079696993, -0.20397695888897, 1.056971514242878 },
}
hsluv.minv = {
    { 0.41239079926595, 0.35758433938387, 0.18048078840183 },
    { 0.21263900587151, 0.71516867876775, 0.072192315360733 },
    { 0.019330818715591, 0.11919477979462, 0.95053215224966 },
}
hsluv.refY = 1.0
hsluv.refU = 0.19783000664283
hsluv.refV = 0.46831999493879
hsluv.kappa = 903.2962962
hsluv.epsilon = 0.0088564516

return hsluv

local M = {}

---@param colors KansoColors
---@param config? KansoConfig
function M.setup(colors, config)
    config = config or require("kanso").config
    local theme = colors.theme

    return {
        -- Neovcs
        -- NeovcsBranch = {},
        -- NeovcsRemote = {},
        -- NeovcsDiffDelete = { fg = theme.vcs.removed, bg = theme.diff.delete },
        -- NeovcsDiffAdd = { fg = theme.vcs.added, bg = theme.diff.add },
        -- NeovcsHunkHeader = { fg = theme.syn.identifier },
        -- NeovcsDiffContextHighlight = { bg = theme.diff.change },

        -- vcsSigns
        -- vcsSignsAdd = { link = "diffAdded" },
        -- vcsSignsChange = { link = "diffChanged" },
        -- vcsSignsDelete = { link = "diffDeleted" },
        -- vcsSignsDeleteLn = { bg = theme.diff.delete },

        -- Gitsigns
        GitSignsAdd = { fg = theme.vcs.added, bg = theme.ui.none },
        GitSignsChange = { fg = theme.vcs.changed, bg = theme.ui.none },
        GitSignsDelete = { fg = theme.vcs.removed, bg = theme.ui.none },
        GitSignsChangedelete = { fg = theme.vcs.removed, bg = theme.ui.none },
        GitSignsTopdelete = { fg = theme.vcs.removed, bg = theme.ui.none },
        GitSignsUntracked = { fg = theme.vcs.untracked, bg = theme.ui.none },

        -- Neogit
        NeogitDiffContextHighlight = { bg = theme.diff.change }, --[[  guibg=#333333 guifg=#b2b2b2 ]]
        NeogitHunkHeader = { fg = theme.syn.fun }, --[[  guifg=#cccccc guibg=#404040 ]]
        NeogitHunkHeaderHighlight = { fg = theme.syn.constant, bg = theme.diff.change }, --[[ guifg=#cccccc guibg=#4d4d4d ]]
        NeogitDiffAddHighlight = { bg = theme.diff.add },
        NeogitDiffDeleteHighlight = { bg = theme.diff.delete },
        -- TreeSitter Extensions
        TreesitterContext = { link = "Folded" },
        TreesitterContextLineNumber = { fg = theme.ui.special, bg = theme.ui.none },
        -- Telescope
        TelescopeBorder = { fg = theme.ui.float.fg_border, bg = config.transparent and theme.ui.none or theme.ui.bg },
        TelescopeTitle = { fg = theme.ui.special },
        TelescopeSelection = { link = "CursorLine" },
        TelescopeSelectionCaret = { link = "CursorLineNr" },
        TelescopeResultsClass = { link = "Structure" },
        TelescopeResultsStruct = { link = "Structure" },
        TelescopeResultsField = { link = "@field" },
        TelescopeResultsMethod = { link = "Function" },
        TelescopeResultsVariable = { link = "@variable" },
        -- NvimTree
        NvimTreeNormal = { link = "Normal" },
        NvimTreeNormalNC = { link = "NvimTreeNormal" },
        NvimTreeRootFolder = { fg = theme.syn.identifier, bold = config.bold },
        NvimTreeGitDirty = { fg = theme.vcs.changed },
        NvimTreeGitNew = { fg = theme.vcs.added },
        NvimTreeGitDeleted = { fg = theme.vcs.removed },
        NvimTreeGitStaged = { fg = theme.vcs.added },
        NvimTreeSpecialFile = { fg = theme.syn.special1 },
        -- NvimTreeIndentMarker           = {},
        NvimTreeImageFile = { fg = theme.syn.special2 },
        NvimTreeSymlink = { link = "Type" },
        NvimTreeFolderName = { link = "Directory" },
        NvimTreeExecFile = { fg = theme.syn.string, bold = config.bold },
        NvimTreeOpenedFile = { fg = theme.syn.special1, italic = config.italics },
        NvimTreeWinSeparator = { link = "WinSeparator" },
        NvimTreeWindowPicker = {
            bg = config.transparent and theme.ui.none or theme.ui.bg_m1,
            fg = theme.syn.special1,
            bold = config.bold,
        },
        -- NeoTree
        NeoTreeTabInactive = { fg = theme.ui.special, bg = config.transparent and theme.ui.none or theme.ui.bg },
        NeoTreeTabActive = {
            fg = theme.ui.fg_dim,
            bg = config.transparent and theme.ui.none or theme.ui.bg_p1,
            bold = config.bold,
        },
        NeoTreeTabSeparatorInactive = {
            fg = theme.ui.special,
            bg = config.transparent and theme.ui.none or theme.ui.bg,
        },
        NeoTreeTabSeparatorActive = {
            fg = theme.ui.fg_dim,
            bg = config.transparent and theme.ui.none or theme.ui.bg_p1,
        },
        NeoTreeRootName = { fg = theme.syn.identifier, bold = config.bold },
        NeoTreeModified = { link = "String" },
        NeoTreeNormal = { link = "Normal" },
        NeoTreeNormalNC = { link = "Normal" },
        NeoTreeTitleBar = { link = "Title" },
        NeoTreeDimText = { fg = theme.ui.fg_dim },
        NeoTreeGitModified = { fg = theme.vcs.changed },
        NeoTreeGitAdded = { fg = theme.vcs.added },
        NeoTreeGitDeleted = { fg = theme.vcs.removed },
        NeoTreeGitStaged = { fg = theme.vcs.added },
        NeoTreeGitConflict = { fg = theme.diag.error },
        NeoTreeGitUntracked = { link = "NeoTreeGitModified", default = true },
        NeoTreeGitUnstaged = { link = "NeoTreeGitModified", default = true },
        NeoTreeIndentMarker = { link = "NonText" },
        -- WindowPicker
        -- NvimWindowSwitch = { bg = theme.ui.bg_m3, fg = theme.diag.warning },
        -- NvimWindowSwitchNC = { link = "NvimWindowSwitch" },
        -- Dashboard
        DashboardShortCut = { fg = theme.syn.special1 },
        DashboardHeader = { fg = theme.vcs.removed },
        DashboardCenter = { fg = theme.syn.identifier },
        DashboardFooter = { fg = theme.syn.comment },
        DashboardDesc = { fg = theme.syn.identifier },
        DashboardKey = { fg = theme.syn.special1 },
        DashboardIcon = { fg = theme.ui.special },
        -- Notify
        NotifyBackground = { bg = config.transparent and theme.ui.none or theme.ui.bg },
        NotifyERRORBorder = { link = "DiagnosticError" },
        NotifyWARNBorder = { link = "DiagnosticWarn" },
        NotifyINFOBorder = { link = "DiagnosticInfo" },
        NotifyHINTBorder = { link = "DiagnosticHint" },
        NotifyDEBUGBorder = { link = "Debug" },
        NotifyTRACEBorder = { link = "Comment" },
        NotifyERRORIcon = { link = "DiagnosticError" },
        NotifyWARNIcon = { link = "DiagnosticWarn" },
        NotifyINFOIcon = { link = "DiagnosticInfo" },
        NotifyHINTIcon = { link = "DiagnosticHint" },
        NotifyDEBUGIcon = { link = "Debug" },
        NotifyTRACEIcon = { link = "Comment" },
        NotifyERRORTitle = { link = "DiagnosticError" },
        NotifyWARNTitle = { link = "DiagnosticWarn" },
        NotifyINFOTitle = { link = "DiagnosticInfo" },
        NotifyHINTTitle = { link = "DiagnosticHint" },
        NotifyDEBUGTitle = { link = "Debug" },
        NotifyTRACETitle = { link = "Comment" },
        -- Dap-UI
        -- DapUIVariable = { link = "Normal" },
        DapUIScope = { link = "Special" }, -- guifg=#00F1F5"
        DapUIType = { link = "Type" }, -- guifg=#D484FF"
        -- DapUIValue = { link = "Normal" },
        DapUIModifiedValue = { fg = theme.syn.special1, bold = config.bold }, -- guifg=#00F1F5 gui=bold"
        DapUIDecoration = { fg = theme.ui.float.fg_border }, -- guifg=#00F1F5"
        DapUIThread = { fg = theme.syn.identifier }, --guifg=#A9FF68"
        DapUIStoppedThread = { fg = theme.syn.special1 }, --guifg=#00f1f5"
        -- DapUIFrameName = { link = "Normal"},
        DapUISource = { fg = theme.syn.special2 }, -- guifg=#D484FF"
        DapUILineNumber = { fg = theme.syn.special1 }, -- guifg=#00f1f5"
        DapUIFloatBorder = { fg = theme.ui.float.fg_border }, -- guifg=#00F1F5"
        DapUIWatchesEmpty = { fg = theme.diag.error }, -- guifg=#F70067"
        DapUIWatchesValue = { fg = theme.syn.identifier }, -- guifg=#A9FF68"
        DapUIWatchesError = { fg = theme.diag.error }, --guifg=#F70067"
        DapUIBreakpointsPath = { link = "Directory" }, --guifg=#00F1F5"
        DapUIBreakpointsInfo = { fg = theme.diag.info }, --guifg=#A9FF68"
        DapUIBreakpointsCurrentLine = { fg = theme.syn.identifier, bold = config.bold }, --guifg=#A9FF68 gui=bold"
        -- DapUIBreakpointsLine = {}, -- DapUILineNumber"
        DapUIBreakpointsDisabledLine = { link = "Comment" }, --guifg=#424242"
        -- DapUICurrentFrameName = {}, -- DapUIBreakpointsCurrentLine"
        DapUIStepOver = { fg = theme.syn.special1 }, --guifg=#00f1f5"
        DapUIStepInto = { fg = theme.syn.special1 }, --guifg=#00f1f5"
        DapUIStepBack = { fg = theme.syn.special1 }, --guifg=#00f1f5"
        DapUIStepOut = { fg = theme.syn.special1 }, --guifg=#00f1f5"
        DapUIStop = { fg = theme.diag.error }, --guifg=#F70067"
        DapUIPlayPause = { fg = theme.syn.string }, --guifg=#A9FF68"
        DapUIRestart = { fg = theme.syn.string }, --guifg=#A9FF68"
        DapUIUnavailable = { fg = theme.syn.comment }, --guifg=#424242"
        -- Floaterm
        FloatermBorder = { fg = theme.ui.float.fg_border, bg = config.transparent and theme.ui.none or theme.ui.bg },
        -- NeoVim                         = {},
        healthError = { fg = theme.diag.error },
        healthSuccess = { fg = theme.diag.ok },
        healthWarning = { fg = theme.diag.warning },
        -- Cmp
        CmpDocumentation = { link = "NormalFloat" },
        CmpDocumentationBorder = { link = "FloatBorder" },
        CmpCompletion = { link = "Pmenu" },
        CmpCompletionSel = { link = "PmenuSel" },
        CmpCompletionBorder = { fg = theme.ui.bg_search, bg = theme.ui.pmenu.bg },
        CmpCompletionThumb = { link = "PmenuThumb" },
        CmpCompletionSbar = { link = "PmenuSbar" },
        CmpItemAbbr = { fg = theme.ui.pmenu.fg },
        CmpItemAbbrDeprecated = { fg = theme.syn.comment, strikethrough = true },
        CmpItemAbbrMatch = { fg = theme.syn.fun },
        CmpItemAbbrMatchFuzzy = { link = "CmpItemAbbrMatch" },
        CmpItemKindDefault = { fg = theme.ui.fg_dim },
        CmpItemMenu = { fg = theme.ui.fg_dim },
        CmpGhostText = { fg = theme.syn.comment },

        CmpItemKindText = { fg = theme.ui.fg },
        CmpItemKindMethod = { link = "@function.method" },
        CmpItemKindFunction = { link = "Function" },
        CmpItemKindConstructor = { link = "@constructor" },
        CmpItemKindField = { link = "@variable.member" },
        CmpItemKindVariable = { fg = theme.ui.fg_dim },
        CmpItemKindClass = { link = "Type" },
        CmpItemKindInterface = { link = "Type" },
        CmpItemKindModule = { link = "@module" },
        CmpItemKindProperty = { link = "@property" },
        CmpItemKindUnit = { link = "Number" },
        CmpItemKindValue = { link = "String" },
        CmpItemKindEnum = { link = "Type" },
        CmpItemKindKeyword = { link = "Keyword" },
        CmpItemKindSnippet = { link = "Special" },
        CmpItemKindColor = { link = "Special" },
        CmpItemKindFile = { link = "Directory" },
        CmpItemKindReference = { link = "Special" },
        CmpItemKindFolder = { link = "Directory" },
        CmpItemKindEnumMember = { link = "Constant" },
        CmpItemKindConstant = { link = "Constant" },
        CmpItemKindStruct = { link = "Type" },
        CmpItemKindEvent = { link = "Type" },
        CmpItemKindOperator = { link = "Operator" },
        CmpItemKindTypeParameter = { link = "Type" },
        CmpItemKindCopilot = { link = "String" },

        -- blink.cmp
        BlinkCmpMenu = { link = "Pmenu" },
        BlinkCmpMenuSelection = { link = "PmenuSel" },
        BlinkCmpMenuBorder = { fg = theme.ui.bg_search, bg = theme.ui.pmenu.bg },
        BlinkCmpScrollBarThumb = { link = "PmenuThumb" },
        BlinkCmpScrollBarGutter = { link = "PmenuSbar" },
        BlinkCmpLabel = { fg = theme.ui.pmenu.fg },
        BlinkCmpLabelMatch = { fg = theme.syn.fun },
        BlinkCmpLabelDetails = { fg = theme.syn.comment },
        BlinkCmpLabelDeprecated = { fg = theme.syn.comment, strikethrough = true },
        BlinkCmpGhostText = { fg = theme.syn.comment },
        BlinkCmpDoc = { link = "NormalFloat" },
        BlinkCmpDocBorder = { link = "FloatBorder" },
        BlinkCmpDocCursorLine = { link = "Visual" },
        BlinkCmpSignatureHelp = { link = "NormalFloat" },
        BlinkCmpSignatureHelpBorder = { link = "FloatBorder" },
        BlinkCmpSignatureHelpActiveParameter = { link = "LspSignatureActiveParameter" },

        BlinkCmpKind = { fg = theme.ui.fg_dim },
        BlinkCmpKindText = { fg = theme.ui.fg },
        BlinkCmpKindMethod = { link = "@function.method" },
        BlinkCmpKindFunction = { link = "Function" },
        BlinkCmpKindConstructor = { link = "@constructor" },
        BlinkCmpKindField = { link = "@variable.member" },
        BlinkCmpKindVariable = { fg = theme.ui.fg_dim },
        BlinkCmpKindClass = { link = "Type" },
        BlinkCmpKindInterface = { link = "Type" },
        BlinkCmpKindModule = { link = "@module" },
        BlinkCmpKindProperty = { link = "@property" },
        BlinkCmpKindUnit = { link = "Number" },
        BlinkCmpKindValue = { link = "String" },
        BlinkCmpKindEnum = { link = "Type" },
        BlinkCmpKindKeyword = { link = "Keyword" },
        BlinkCmpKindSnippet = { link = "Special" },
        BlinkCmpKindColor = { link = "Special" },
        BlinkCmpKindFile = { link = "Directory" },
        BlinkCmpKindReference = { link = "Special" },
        BlinkCmpKindFolder = { link = "Directory" },
        BlinkCmpKindEnumMember = { link = "Constant" },
        BlinkCmpKindConstant = { link = "Constant" },
        BlinkCmpKindStruct = { link = "Type" },
        BlinkCmpKindEvent = { link = "Type" },
        BlinkCmpKindOperator = { link = "Operator" },
        BlinkCmpKindTypeParameter = { link = "Type" },
        BlinkCmpKindCopilot = { link = "String" },

        -- IndentBlankline
        IndentBlanklineChar = { fg = theme.ui.indent_line, nocombine = true },
        IndentBlanklineSpaceChar = { fg = theme.ui.indent_line, nocombine = true },
        IndentBlanklineSpaceCharBlankline = { fg = theme.ui.indent_line, nocombine = true },
        IndentBlanklineContextChar = { fg = theme.ui.active_indent_line, nocombine = true },
        IndentBlanklineContextStart = { sp = theme.ui.active_indent_line, underline = true, nocombine = true },
        IblIndent = { fg = theme.ui.indent_line, nocombine = true },
        IblWhitespace = { fg = theme.ui.indent_line, nocombine = true },
        IblScope = { fg = theme.ui.active_indent_line, nocombine = true },
        -- Other indent plugins
        IndentLine = { fg = theme.ui.indent_line, nocombine = true },
        Indent = { fg = theme.ui.indent_line, nocombine = true },
        IndentGuide = { fg = theme.ui.indent_line, nocombine = true },
        IndentGuidesOdd = { fg = theme.ui.indent_line, nocombine = true },
        IndentGuidesEven = { fg = theme.ui.indent_line, nocombine = true },
        -- Lazy
        LazyProgressTodo = { fg = theme.ui.nontext },

        -- Trouble
        TroubleIndent = { fg = theme.ui.whitespace },
        TroublePos = { fg = theme.ui.special },

        -- Nvim-Navic
        NavicIconsFile = { link = "Directory" },
        NavicIconsModule = { link = "@module" },
        NavicIconsNamespace = { link = "@module" },
        NavicIconsPackage = { link = "@module" },
        NavicIconsClass = { link = "Type" },
        NavicIconsMethod = { link = "@function.method" },
        NavicIconsProperty = { link = "@property" },
        NavicIconsField = { link = "@variable.member" },
        NavicIconsConstructor = { link = "@constructor" },
        NavicIconsEnum = { link = "Type" },
        NavicIconsInterface = { link = "Type" },
        NavicIconsFunction = { link = "Function" },
        NavicIconsVariable = { link = "@variable" },
        NavicIconsConstant = { link = "Constant" },
        NavicIconsString = { link = "String" },
        NavicIconsNumber = { link = "Number" },
        NavicIconsBoolean = { link = "Boolean" },
        NavicIconsArray = { link = "Type" },
        NavicIconsObject = { link = "Type" },
        NavicIconsKey = { link = "Identifier" },
        NavicIconsNull = { link = "Type" },
        NavicIconsEnumMember = { link = "Constant" },
        NavicIconsStruct = { link = "Structure" },
        NavicIconsEvent = { link = "Structure" },
        NavicIconsOperator = { link = "Operator" },
        NavicIconsTypeParameter = { link = "Type" },
        NavicText = { fg = theme.ui.fg },
        NavicSeparator = { fg = theme.ui.fg },

        -- Aerial icons
        AerialFileIcon = { link = "Directory" },
        AerialModuleIcon = { link = "@module" },
        AerialNamespaceIcon = { link = "@module" },
        AerialPackageIcon = { link = "@module" },
        AerialClassIcon = { link = "Type" },
        AerialMethodIcon = { link = "@function.method" },
        AerialPropertyIcon = { link = "@property" },
        AerialFieldIcon = { link = "@variable.member" },
        AerialConstructorIcon = { link = "@constructor" },
        AerialEnumIcon = { link = "Type" },
        AerialInterfaceIcon = { link = "Type" },
        AerialFunctionIcon = { link = "Function" },
        AerialVariableIcon = { link = "@variable" },
        AerialConstantIcon = { link = "Constant" },
        AerialStringIcon = { link = "String" },
        AerialNumberIcon = { link = "Number" },
        AerialBooleanIcon = { link = "Boolean" },
        AerialArrayIcon = { link = "Type" },
        AerialObjectIcon = { link = "Type" },
        AerialKeyIcon = { link = "Identifier" },
        AerialNullIcon = { link = "Type" },
        AerialEnumMemberIcon = { link = "Constant" },
        AerialStructIcon = { link = "Structure" },
        AerialEventIcon = { link = "Structure" },
        AerialOperatorIcon = { link = "Operator" },
        AerialTypeParameterIcon = { link = "Type" },

        -- Mini
        MiniAnimateCursor = { reverse = true, nocombine = true },
        MiniAnimateNormalFloat = { link = "NormalFloat" },

        MiniClueBorder = { link = "FloatBorder" },
        MiniClueDescGroup = { link = "DiagnosticFloatingWarn" },
        MiniClueDescSingle = { link = "NormalFloat" },
        MiniClueNextKey = { link = "DiagnosticFloatingHint" },
        MiniClueNextKeyWithPostkeys = { link = "DiagnosticFloatingError" },
        MiniClueSeparator = { link = "DiagnosticFloatingInfo" },
        MiniClueTitle = { link = "FloatTitle" },

        MiniCompletionActiveParameter = { underline = true },

        MiniCursorword = { underline = true },
        MiniCursorwordCurrent = { underline = true },

        MiniDepsChangeAdded = { link = "diffAdded" },
        MiniDepsChangeRemoved = { link = "diffRemoved" },
        MiniDepsHint = { fg = theme.diag.hint },
        MiniDepsInfo = { fg = theme.diag.info },
        MiniDepsMsgBreaking = { fg = theme.diag.warning },
        MiniDepsPlaceholder = { link = "Comment" },
        MiniDepsTitle = { link = "Title" },
        MiniDepsTitleError = { link = "DiffDelete" },
        MiniDepsTitleSame = { link = "DiffText" },
        MiniDepsTitleUpdate = { link = "DiffAdd" },

        MiniDiffSignAdd = { fg = theme.vcs.added, bg = theme.ui.none },
        MiniDiffSignChange = { fg = theme.vcs.changed, bg = theme.ui.none },
        MiniDiffSignDelete = { fg = theme.vcs.removed, bg = theme.ui.none },
        MiniDiffOverAdd = { link = "DiffAdd" },
        MiniDiffOverChange = { link = "DiffText" },
        MiniDiffOverContext = { link = "DiffChange" },
        MiniDiffOverDelete = { link = "DiffDelete" },

        MiniFilesBorder = { link = "FloatBorder" },
        MiniFilesBorderModified = { link = "DiagnosticFloatingWarn" },
        MiniFilesCursorLine = { link = "CursorLine" },
        MiniFilesDirectory = { link = "Directory" },
        MiniFilesFile = { fg = theme.ui.fg },
        MiniFilesNormal = { link = "NormalFloat" },
        MiniFilesTitle = {
            fg = theme.ui.special,
            bg = config.transparent and theme.ui.none or theme.ui.float.bg_border,
            bold = config.bold,
        },
        MiniFilesTitleFocused = {
            fg = theme.ui.fg,
            bg = config.transparent and theme.ui.none or theme.ui.float.bg_border,
            bold = config.bold,
        },

        MiniHipatternsFixme = { fg = theme.ui.bg, bg = theme.diag.error, bold = config.bold },
        MiniHipatternsHack = { fg = theme.ui.bg, bg = theme.diag.warning, bold = config.bold },
        MiniHipatternsNote = { fg = theme.ui.bg, bg = theme.diag.info, bold = config.bold },
        MiniHipatternsTodo = { fg = theme.ui.bg, bg = theme.diag.hint, bold = config.bold },

        MiniIconsAzure = { fg = theme.syn.special1 },
        MiniIconsBlue = { fg = theme.syn.fun },
        MiniIconsCyan = { fg = theme.syn.type },
        MiniIconsGreen = { fg = theme.syn.string },
        MiniIconsGrey = { fg = theme.ui.fg },
        MiniIconsOrange = { fg = theme.syn.constant },
        MiniIconsPurple = { fg = theme.syn.keyword },
        MiniIconsRed = { fg = theme.syn.special3 },
        MiniIconsYellow = { fg = theme.syn.identifier },

        MiniIndentscopeSymbol = { fg = theme.syn.special1 },
        MiniIndentscopePrefix = { nocombine = true }, -- Make it invisible

        MiniJump = { link = "SpellRare" },

        MiniJump2dDim = { link = "Comment" },
        MiniJump2dSpot = { fg = theme.syn.constant, bold = config.bold, nocombine = true },
        MiniJump2dSpotAhead = { fg = theme.diag.hint, bg = theme.ui.bg_dim, nocombine = true },
        MiniJump2dSpotUnique = { fg = theme.syn.special1, bold = config.bold, nocombine = true },

        MiniMapNormal = { link = "NormalFloat" },
        MiniMapSymbolCount = { link = "Special" },
        MiniMapSymbolLine = { link = "Title" },
        MiniMapSymbolView = { link = "Delimiter" },

        MiniNotifyBorder = { link = "FloatBorder" },
        MiniNotifyNormal = { link = "NormalFloat" },
        MiniNotifyTitle = { link = "FloatTitle" },

        MiniOperatorsExchangeFrom = { link = "IncSearch" },

        MiniPickBorder = { link = "FloatBorder" },
        MiniPickBorderBusy = { link = "DiagnosticFloatingWarn" },
        MiniPickBorderText = { link = "FloatTitle" },
        MiniPickIconDirectory = { link = "Directory" },
        MiniPickIconFile = { link = "MiniPickNormal" },
        MiniPickHeader = { link = "DiagnosticFloatingHint" },
        MiniPickMatchCurrent = { link = "CursorLine" },
        MiniPickMatchMarked = { link = "Visual" },
        MiniPickMatchRanges = { link = "DiagnosticFloatingHint" },
        MiniPickNormal = { link = "NormalFloat" },
        MiniPickPreviewLine = { link = "CursorLine" },
        MiniPickPreviewRegion = { link = "IncSearch" },
        MiniPickPrompt = { fg = theme.syn.fun, bg = config.transparent and theme.ui.none or theme.ui.float.bg_border },

        MiniStarterCurrent = { nocombine = true },
        MiniStarterFooter = { fg = theme.syn.deprecated },
        MiniStarterHeader = { link = "Title" },
        MiniStarterInactive = { link = "Comment" },
        MiniStarterItem = { link = "Normal" },
        MiniStarterItemBullet = { link = "Delimiter" },
        MiniStarterItemPrefix = { fg = theme.diag.warning },
        MiniStarterSection = { fg = theme.diag.ok },
        MiniStarterQuery = { fg = theme.diag.info },

        MiniStatuslineDevinfo = { fg = theme.ui.fg_dim, bg = config.transparent and theme.ui.none or theme.ui.bg_p1 },
        MiniStatuslineFileinfo = { fg = theme.ui.fg_dim, bg = config.transparent and theme.ui.none or theme.ui.bg_p1 },
        MiniStatuslineFilename = { fg = theme.ui.fg_dim, bg = config.transparent and theme.ui.none or theme.ui.bg_dim },
        MiniStatuslineInactive = { link = "StatusLineNC" },
        MiniStatuslineModeCommand = { fg = theme.ui.bg, bg = theme.syn.operator, bold = config.bold },
        MiniStatuslineModeInsert = { fg = theme.ui.bg, bg = theme.diag.ok, bold = config.bold },
        MiniStatuslineModeNormal = { fg = theme.ui.bg_m3, bg = theme.syn.fun, bold = config.bold },
        MiniStatuslineModeOther = { fg = theme.ui.bg, bg = theme.syn.type, bold = config.bold },
        MiniStatuslineModeReplace = { fg = theme.ui.bg, bg = theme.syn.constant, bold = config.bold },
        MiniStatuslineModeVisual = { fg = theme.ui.bg, bg = theme.syn.keyword, bold = config.bold },

        MiniSurround = { link = "IncSearch" },

        MiniTablineCurrent = {
            fg = theme.ui.fg_dim,
            bg = config.transparent and theme.ui.none or theme.ui.bg_p1,
            bold = config.bold,
        },
        MiniTablineFill = { link = "TabLineFill" },
        MiniTablineHidden = { fg = theme.ui.special, bg = theme.ui.bg_m3 },
        MiniTablineModifiedCurrent = { fg = theme.ui.bg_p1, bg = theme.ui.fg_dim, bold = config.bold },
        MiniTablineModifiedHidden = { fg = theme.ui.bg_m3, bg = theme.ui.special },
        MiniTablineModifiedVisible = { fg = theme.ui.bg_m3, bg = theme.ui.special, bold = config.bold },
        MiniTablineTabpagesection = { fg = theme.ui.fg, bg = theme.ui.bg_search, bold = config.bold },
        MiniTablineVisible = { fg = theme.ui.special, bg = theme.ui.bg_m3, bold = config.bold },

        MiniTestEmphasis = { bold = config.bold },
        MiniTestFail = { fg = theme.diag.error, bold = config.bold },
        MiniTestPass = { fg = theme.diag.ok, bold = config.bold },

        MiniTrailspace = { bg = theme.vcs.removed },

        NeotestAdapterName = { fg = theme.syn.special3 },
        NeotestDir = { fg = theme.syn.fun },
        NeotestExpandMarker = { fg = theme.syn.punct, bold = config.bold },
        NeotestFailed = { fg = theme.diag.error },
        NeotestFile = { fg = theme.syn.fun },
        NeotestFocused = { bold = config.bold, underline = true },
        NeotestIndent = { fg = theme.ui.special, bold = config.bold },
        NeotestMarked = { fg = theme.diag.warning, italic = config.italics },
        NeotestNamespace = { fg = theme.syn.fun },
        NeotestPassed = { fg = theme.diag.ok },
        NeotestRunning = { fg = theme.vcs.changed },
        NeotestWinSelect = { fg = theme.diag.hint },
        NeotestSkipped = { fg = theme.syn.special1 },
        NeotestTarget = { fg = theme.syn.special3 },
        NeotestTest = { fg = theme.ui.float.fg },
        NeotestUnknown = { fg = theme.syn.deprecated },
        NeotestWatching = { fg = theme.vcs.changed },

        SnacksPicker = { bg = config.transparent and theme.ui.none or theme.ui.bg },
        SnacksPickerTitle = { fg = theme.ui.fg, bg = config.transparent and theme.ui.none or theme.ui.bg },
        SnacksPickerBorder = { fg = theme.ui.none, bg = theme.ui.none },
        SnacksPickerNormal = { fg = theme.ui.fg, bg = config.transparent and theme.ui.none or theme.ui.bg },
        SnacksPickerMatch = { fg = theme.ui.fg },
        SnacksPickerCursor = { fg = theme.ui.bg, bg = theme.ui.bg },
        SnacksPickerPrompt = { fg = theme.ui.fg },
        SnacksPickerDim = { fg = theme.ui.fg_dim },
        SnacksInputIcon = { fg = theme.ui.fg, bg = config.transparent and theme.ui.none or theme.ui.bg },
        SnacksIndent = { fg = theme.ui.indent_line, nocombine = true },
        SnacksIndentChunk = { fg = theme.ui.active_indent_line, nocombine = true },
        SnacksIndentScope = { fg = theme.ui.active_indent_line, nocombine = true },
        SnacksPickerListCursorLine = { fg = theme.ui.fg, bg = theme.ui.bg_p2 },
        SnacksPickerInputBorder = { fg = theme.ui.none, bg = theme.ui.none },
        SnacksPickerInputTitle = { fg = theme.ui.fg, bg = config.transparent and theme.ui.none or theme.ui.bg },
        SnacksPickerBoxTitle = { fg = theme.ui.fg, bg = config.transparent and theme.ui.none or theme.ui.bg },
        SnacksPickerSelected = { fg = theme.ui.bg },
        SnacksPickerPickWinCurrent = {
            fg = theme.ui.fg,
            bg = config.transparent and theme.ui.none or theme.ui.bg,
            bold = config.bold,
        },
        SnacksPickerPickWin = {
            fg = theme.ui.fg,
            bg = config.transparent and theme.ui.none or theme.ui.bg_search,
            bold = config.bold,
        },

        BufferLineBackground = { fg = theme.ui.none, bg = theme.ui.none },
        BufferLineBuffer = { fg = theme.ui.none, bg = theme.ui.none },
        BufferLineBufferSelected = { bg = theme.ui.none, fg = theme.ui.fg },
        BufferLineBufferVisible = { bg = theme.ui.none },
        BufferLineCloseButton = { bg = theme.ui.none },
        BufferLineCloseButtonSelected = { bg = theme.ui.none },
        BufferLineCloseButtonVisible = { bg = theme.ui.none },
        BufferLineDuplicate = { bg = theme.ui.none },
        BufferLineDuplicateSelected = { bg = theme.ui.none },
        BufferLineDuplicateVisible = { bg = theme.ui.none },
        BufferLineError = { bg = theme.ui.none, sp = theme.ui.none },
        BufferLineErrorDiagnostic = { bg = theme.ui.none, sp = theme.ui.none },
        BufferLineErrorDiagnosticSelected = { bg = theme.ui.none, sp = theme.ui.none },
        BufferLineErrorDiagnosticVisible = { bg = theme.ui.none },
        BufferLineErrorSelected = { bg = theme.ui.none, sp = theme.ui.none },
        BufferLineErrorVisible = { bg = theme.ui.none },
        BufferLineFill = { bg = theme.ui.none },
        BufferLineHint = { sp = theme.ui.none, bg = theme.ui.none },
        BufferLineHintDiagnostic = { sp = theme.ui.none, bg = theme.ui.none },
        BufferLineHintDiagnosticSelected = { bg = theme.ui.none, sp = theme.ui.none },
        BufferLineHintDiagnosticVisible = { bg = theme.ui.none },
        BufferLineHintSelected = { bg = theme.ui.none, sp = theme.ui.none },
        BufferLineHintVisible = { bg = theme.ui.none },
        BufferLineInfo = { sp = theme.ui.none, bg = theme.ui.none },
        BufferLineInfoDiagnostic = { sp = theme.ui.none, bg = theme.ui.none },
        BufferLineInfoDiagnosticSelected = { sp = theme.ui.none, bg = theme.ui.none },
        BufferLineInfoDiagnosticVisible = { bg = theme.ui.none },
        BufferLineInfoSelected = { bg = theme.ui.none, sp = theme.ui.none },
        BufferLineInfoVisible = { bg = theme.ui.none },
        BufferLineIndicatorSelected = { bg = theme.ui.none },
        BufferLineModified = { bg = theme.ui.none },
        BufferLineModifiedSelected = { bg = theme.ui.none },
        BufferLineModifiedVisible = { bg = theme.ui.none },
        BufferLineNumbers = { bg = theme.ui.none },
        BufferLineNumbersSelected = { bg = theme.ui.none },
        BufferLineNumbersVisible = { bg = theme.ui.none },
        BufferLineOffsetSeparator = { bg = theme.ui.none },
        BufferLineSeparator = { bg = theme.ui.none },
        BufferLineSeparatorSelected = { bg = theme.ui.none },
        BufferLineSeparatorVisible = { bg = theme.ui.none },
        BufferLineTab = { bg = theme.ui.none },
        BufferLinePick = { bg = theme.ui.none },
        BufferLinePickSelected = { bg = theme.ui.none },
        BufferLineDevIconLua = { bg = theme.ui.none },
        BufferLineDevIconLuaSelected = { bg = theme.ui.none },
        BufferLineDevIconLuaVisible = { bg = theme.ui.none },
        BufferLineDevIconLuaInactive = { bg = theme.ui.none },
        BufferLinePickVisible = { bg = theme.ui.none },
        BufferLineIndicatorVisible = { bg = theme.ui.none },
        BufferLineTabClose = { bg = theme.ui.none },
        BufferLineTabSelected = { bg = theme.ui.none },
        BufferLineTabSeparator = { bg = theme.ui.none },
        BufferLineTabSeparatorSelected = { bg = theme.ui.none },
        BufferLineTruncMarker = { bg = theme.ui.none },
        BufferLineWarning = { bg = theme.ui.none },
        BufferLineWarningDiagnostic = { bg = theme.ui.none },
        BufferLineWarningDiagnosticSelected = { bg = theme.ui.none },
        BufferLineWarningDiagnosticVisible = { bg = theme.ui.none },
        BufferLineWarningSelected = { bg = theme.ui.none },
        BufferLineWarningVisible = { bg = theme.ui.none },
    }
end

return M

--TODO:
--PreProc needs its own color
--parameter and field should be different
---@class SyntaxElements
---@field string ColorSpec
---@field variable ColorSpec
---@field number ColorSpec
---@field constant ColorSpec
---@field identifier ColorSpec
---@field parameter ColorSpec
---@field fun ColorSpec
---@field statement ColorSpec
---@field keyword ColorSpec
---@field operator ColorSpec
---@field preproc ColorSpec
---@field type ColorSpec
---@field regex ColorSpec
---@field deprecated ColorSpec
---@field comment ColorSpec
---@field punct ColorSpec
---@field special1 ColorSpec
---@field special2 ColorSpec
---@field special3 ColorSpec

---@class DiagnosticsElements
---@field error ColorSpec
---@field ok ColorSpec
---@field warning ColorSpec
---@field info ColorSpec
---@field hint ColorSpec
--
---@class DiffElements
---@field add ColorSpec
---@field delete ColorSpec
---@field change ColorSpec
---@field text ColorSpec

---@class VCSElements
---@field added ColorSpec
---@field removed ColorSpec
---@field changed ColorSpec
---@field untracked ColorSpec

---@class UiElements
---@field none ColorSpec
---@field fg ColorSpec Default foreground
---@field fg_dim ColorSpec Dimmed foreground
---@field fg_reverse ColorSpec
---@field bg_dim ColorSpec Dimmed background
---@field bg_m3 ColorSpec
---@field bg_m2 ColorSpec
---@field bg_m1 ColorSpec
---@field bg ColorSpec Default background
---@field bg_p1 ColorSpec Lighter background ColorColumn, Folded, Gutter
---@field bg_p2 ColorSpec Lighter background Cursor{Line,Column}, TabLineSel (Selected Items)
---@field bg_gutter ColorSpec {Sign,Fold}Column, LineNr
---@field special ColorSpec SpecialKey
---@field indent_line ColorSpec IndentLine
---@field active_indent_line ColorSpec IndentLine
---@field nontext ColorSpec LineNr, NonText
---@field whitespace ColorSpec Whitespace
---@field bg_search ColorSpec
---@field bg_visual ColorSpec
---@field cursor_line_nr_foreground ColorSpec
---@field cursor_line_nr_active_foreground ColorSpec
---@field cursor_bg ColorSpec
---@field cursor_fg ColorSpec
---@field pmenu MenuElements
---@field float FloatElements

---@class FloatElements
---@field fg ColorSpec
---@field bg ColorSpec
---@field fg_border ColorSpec
---@field bg_border ColorSpec

---@class MenuElements
---@field bg ColorSpec
---@field fg ColorSpec
---@field fg_sel ColorSpec
---@field bg_sel ColorSpec
---@field bg_sbar ColorSpec
---@field bg_thumb ColorSpec

---@class ThemeColors
---@field syn SyntaxElements
---@field diag DiagnosticsElements
---@field vcs VCSElements
---@field diff DiffElements
---@field ui UiElements
---@field term ColorSpec[]

return {
    ---@param palette PaletteColors
    ---@param foreground? "default"|"contrast"
    ---@return ThemeColors
    zen = function(palette, foreground)
        return {
            ui = {
                none = "NONE",
                fg = palette.fg,
                fg_dim = palette.gray2,
                fg_reverse = palette.altBlue1,

                bg_dim = palette.zenBg0,

                bg_m3 = palette.zenBg0,
                bg_m2 = palette.zenBg0,
                bg_m1 = palette.zenBg0,
                bg = palette.zenBg0,
                bg_p1 = palette.zenBg1,
                bg_p2 = palette.zenBg2,

                special = palette.gray5,
                indent_line = palette.inkBg2,
                active_indent_line = palette.inkBg3,
                whitespace = palette.inkBg3,
                nontext = palette.gray5,

                bg_visual = palette.inkBg3,
                bg_search = palette.altBlue2,

                cursor_line_nr_foreground = palette.gray5,
                cursor_line_nr_active_foreground = palette.fg2,
                cursor_bg = palette.fg2,
                cursor_fg = palette.zenBg0,

                pmenu = {
                    fg = palette.fg2,
                    fg_sel = "NONE",
                    bg = palette.zenBg0,
                    bg_sel = palette.inkBg3,
                    bg_thumb = palette.inkBg3,
                    bg_sbar = palette.zenBg0,
                },

                float = {
                    fg = palette.gray2,
                    bg = palette.zenBg0,
                    fg_border = palette.zenBg2,
                    bg_border = palette.zenBg0,
                },
            },
            syn = {
                string = foreground == "contrast" and palette.green3Contrast or palette.green3,
                variable = "NONE",
                number = foreground == "contrast" and palette.pinkContrast or palette.pink,
                constant = foreground == "contrast" and palette.orangeContrast or palette.orange,
                identifier = foreground == "contrast" and palette.violet2Contrast or palette.violet2,
                parameter = palette.gray3,
                fun = foreground == "contrast" and palette.blue3Contrast or palette.blue3,
                statement = foreground == "contrast" and palette.violet2Contrast or palette.violet2,
                keyword = foreground == "contrast" and palette.violet2Contrast or palette.violet2,
                operator = palette.gray3,
                preproc = palette.gray3,
                type = foreground == "contrast" and palette.aquaContrast or palette.aqua,
                regex = foreground == "contrast" and palette.red3Contrast or palette.red3,
                deprecated = palette.gray,
                punct = palette.gray3,
                comment = palette.gray4,
                special1 = foreground == "contrast" and palette.yellow3Contrast or palette.yellow3,
                special2 = foreground == "contrast" and palette.violet2Contrast or palette.violet2,
                special3 = foreground == "contrast" and palette.violet2Contrast or palette.violet2,
            },
            diag = {
                error = palette.red,
                ok = palette.green,
                warning = palette.yellow,
                info = palette.blue2,
                hint = palette.green4,
            },
            diff = {
                add = palette.diffGreen,
                delete = palette.diffRed,
                change = palette.diffBlue,
                text = palette.diffYellow,
            },
            vcs = {
                added = palette.gitGreen,
                removed = palette.gitRed,
                changed = palette.gitYellow,
                untracked = palette.gray4,
            },
            term = {
                palette.zenBg0, -- black
                palette.red3, -- red
                palette.green3, -- green
                palette.yellow3, -- yellow
                palette.blue3, -- blue
                palette.pink, -- magenta
                palette.fg, -- cyan
                palette.gray2, -- white
                palette.gray3, -- bright black
                palette.red2, -- bright red
                palette.green2, -- bright green
                palette.yellow2, -- bright yellow
                palette.blue, -- bright blue
                palette.violet, -- bright magenta
                palette.green5, -- bright cyan
                palette.fg, -- bright white
                palette.orange, -- extended color 1
                palette.orange2, -- extended color 2
            },
        }
    end,
    ---@param palette PaletteColors
    ---@param foreground? "default"|"contrast"
    ---@return ThemeColors
    ink = function(palette, foreground)
        return {
            ui = {
                none = "NONE",
                fg = palette.fg,
                fg_dim = palette.gray2,
                fg_reverse = palette.altBlue1,

                bg_dim = palette.inkBg0,

                bg_m3 = palette.inkBg0,
                bg_m2 = palette.inkBg0,
                bg_m1 = palette.inkBg0,
                bg = palette.inkBg0,
                bg_p1 = palette.inkBg1,
                bg_p2 = palette.inkBg2,

                special = palette.gray5,
                indent_line = palette.inkBg2,
                active_indent_line = palette.inkBg3,
                whitespace = palette.inkBg4,
                nontext = palette.gray5,

                bg_visual = palette.inkBg3,
                bg_search = palette.altBlue2,

                cursor_line_nr_foreground = palette.gray5,
                cursor_line_nr_active_foreground = palette.fg2,
                cursor_bg = palette.fg2,
                cursor_fg = palette.inkBg0,

                pmenu = {
                    fg = palette.fg2,
                    fg_sel = "NONE",
                    bg = palette.inkBg0,
                    bg_sel = palette.inkBg3,
                    bg_thumb = palette.inkBg3,
                    bg_sbar = palette.inkBg0,
                },

                float = {
                    fg = palette.gray2,
                    bg = palette.inkBg0,
                    fg_border = palette.inkBg2,
                    bg_border = palette.inkBg0,
                },
            },
            syn = {
                string = foreground == "contrast" and palette.green3Contrast or palette.green3,
                variable = "NONE",
                number = foreground == "contrast" and palette.pinkContrast or palette.pink,
                constant = foreground == "contrast" and palette.orangeContrast or palette.orange,
                identifier = foreground == "contrast" and palette.violet2Contrast or palette.violet2,
                parameter = palette.gray3,
                fun = foreground == "contrast" and palette.blue3Contrast or palette.blue3,
                statement = foreground == "contrast" and palette.violet2Contrast or palette.violet2,
                keyword = foreground == "contrast" and palette.violet2Contrast or palette.violet2,
                operator = palette.gray3,
                preproc = palette.gray3,
                type = foreground == "contrast" and palette.aquaContrast or palette.aqua,
                regex = foreground == "contrast" and palette.red3Contrast or palette.red3,
                deprecated = palette.gray,
                punct = palette.gray3,
                comment = palette.gray4,
                special1 = foreground == "contrast" and palette.yellow3Contrast or palette.yellow3,
                special2 = foreground == "contrast" and palette.violet2Contrast or palette.violet2,
                special3 = foreground == "contrast" and palette.violet2Contrast or palette.violet2,
            },
            diag = {
                error = palette.red,
                ok = palette.green,
                warning = palette.yellow,
                info = palette.blue2,
                hint = palette.green4,
            },
            diff = {
                add = palette.diffGreen,
                delete = palette.diffRed,
                change = palette.diffBlue,
                text = palette.diffYellow,
            },
            vcs = {
                added = palette.gitGreen,
                removed = palette.gitRed,
                changed = palette.gitYellow,
                untracked = palette.gray4,
            },
            term = {
                palette.inkBg0, -- black
                palette.red3, -- red
                palette.green3, -- green
                palette.yellow3, -- yellow
                palette.blue3, -- blue
                palette.pink, -- magenta
                palette.fg, -- cyan
                palette.gray2, -- white
                palette.gray3, -- bright black
                palette.red2, -- bright red
                palette.green2, -- bright green
                palette.yellow2, -- bright yellow
                palette.blue, -- bright blue
                palette.violet, -- bright magenta
                palette.green5, -- bright cyan
                palette.fg, -- bright white
                palette.orange, -- extended color 1
                palette.orange2, -- extended color 2
            },
        }
    end,
    ---@param palette PaletteColors
    ---@param foreground? "default"|"contrast"
    ---@return ThemeColors
    pearl = function(palette, foreground)
        return {
            ui = {
                none = "NONE",
                fg = palette.pearlBlack0,
                fg_dim = palette.pearlBlack1,
                fg_reverse = palette.pearlGray,

                bg_dim = palette.pearlWhite0,

                bg_m3 = palette.pearlWhite0,
                bg_m2 = palette.pearlWhite0,
                bg_m1 = palette.pearlWhite0,
                bg = palette.pearlWhite0,
                bg_p1 = palette.pearlWhite1,
                bg_p2 = palette.pearlWhite1,

                nontext = palette.pearlViolet1,
                whitespace = palette.pearlWhite3,
                special = palette.pearlViolet2,
                indent_line = palette.pearlWhite2,
                active_indent_line = palette.pearlWhite2,

                bg_visual = palette.pearlWhite2,
                bg_search = palette.pearlBlue2,

                cursor_line_nr_foreground = palette.pearlGray4,
                cursor_line_nr_active_foreground = palette.inkBg2,
                cursor_bg = palette.fg2,
                cursor_fg = palette.inkBg2,

                pmenu = {
                    fg = palette.pearlBlack2,
                    fg_sel = "NONE", -- This is important to make highlights pass-through
                    bg = palette.pearlWhite0,
                    bg_sel = palette.pearlWhite2,
                    bg_thumb = palette.pearlWhite2,
                    bg_sbar = palette.pearlWhite0,
                },
                float = {
                    fg = palette.pearlBlack2,
                    bg = palette.pearlWhite0,
                    fg_border = palette.pearlWhite2,
                    bg_border = palette.pearlWhite0,
                },
            },
            syn = {
                string = foreground == "contrast" and palette.pearlGreenContrast or palette.pearlGreen,
                variable = "NONE",
                number = foreground == "contrast" and palette.pearlPinkContrast or palette.pearlPink,
                constant = foreground == "contrast" and palette.pearlOrangeContrast or palette.pearlOrange,
                identifier = foreground == "contrast" and palette.pearlViolet4Contrast or palette.pearlViolet4,
                parameter = foreground == "contrast" and palette.pearlBlue5Contrast or palette.pearlBlue5,
                fun = foreground == "contrast" and palette.pearlBlue4Contrast or palette.pearlBlue4,
                statement = foreground == "contrast" and palette.pearlViolet4Contrast or palette.pearlViolet4,
                keyword = foreground == "contrast" and palette.pearlViolet4Contrast or palette.pearlViolet4,
                operator = palette.pearlGray3,
                preproc = palette.pearlGray2,
                type = foreground == "contrast" and palette.pearlAquaContrast or palette.pearlAqua,
                regex = foreground == "contrast" and palette.pearlYellow2Contrast or palette.pearlYellow2,
                deprecated = palette.pearlGray3,
                comment = palette.pearlGray3,
                punct = palette.pearlGray3,
                special1 = foreground == "contrast" and palette.pearlYellow2Contrast or palette.pearlYellow2,
                special2 = foreground == "contrast" and palette.pearlViolet4Contrast or palette.pearlViolet4,
                special3 = foreground == "contrast" and palette.pearlViolet4Contrast or palette.pearlViolet4,
            },
            vcs = {
                added = palette.pearlGreen2,
                removed = palette.pearlRed2,
                changed = palette.pearlYellow3,
                untracked = palette.pearlGray4,
            },
            diff = {
                add = palette.pearlGreen3,
                delete = palette.pearlRed4,
                change = palette.pearlCyan,
                text = palette.pearlYellow4,
            },
            diag = {
                error = palette.pearlRed3,
                ok = palette.pearlGreen,
                warning = palette.pearlOrange2,
                info = palette.pearlTeal3,
                hint = palette.pearlAqua2,
            },
            term = {
                palette.inkBg2, -- black
                palette.pearlRed, -- red
                palette.pearlGreen, -- green
                palette.pearlYellow, -- yellow
                palette.pearlBlue4, -- blue
                palette.pearlPink, -- magenta
                palette.pearlAqua, -- cyan
                palette.pearlBlack0, -- white
                palette.pearlGray3, -- bright black
                palette.pearlRed2, -- bright red
                palette.pearlGreen2, -- bright green
                palette.pearlYellow2, -- bright yellow
                palette.pearlTeal2, -- bright blue
                palette.pearlViolet4, -- bright magenta
                palette.pearlAqua2, -- bright cyan
                palette.pearlBlack2, -- bright white
                palette.pearlOrange2, -- extended color 1
                palette.pearlRed3, -- extended color 2
            },
        }
    end,
    ---@param palette PaletteColors
    ---@param foreground? "default"|"contrast"
    ---@return ThemeColors
    mist = function(palette, foreground)
        return {
            ui = {
                none = "NONE",
                fg = palette.fg,
                fg_dim = palette.gray2,
                fg_reverse = palette.altBlue1,

                bg_dim = palette.mistBg0,

                bg_m3 = palette.mistBg0,
                bg_m2 = palette.mistBg0,
                bg_m1 = palette.mistBg0,
                bg = palette.mistBg0,
                bg_p1 = palette.mistBg2,
                bg_p2 = palette.mistBg2,

                special = palette.gray5,
                indent_line = palette.gray5,
                active_indent_line = palette.gray5,
                whitespace = palette.mistBg3,
                nontext = palette.gray5,

                bg_visual = palette.mistBg2,
                bg_search = palette.altBlue2,

                cursor_line_nr_foreground = palette.gray4,
                cursor_line_nr_active_foreground = palette.fg2,
                cursor_bg = palette.fg2,
                cursor_fg = palette.mistBg0,

                pmenu = {
                    fg = palette.fg2,
                    fg_sel = "NONE",
                    bg = palette.mistBg0,
                    bg_sel = palette.mistBg2,
                    bg_thumb = palette.mistBg2,
                    bg_sbar = palette.mistBg0,
                },

                float = {
                    fg = palette.gray2,
                    bg = palette.mistBg0,
                    fg_border = palette.mistBg2,
                    bg_border = palette.mistBg0,
                },
            },
            syn = {
                string = foreground == "contrast" and palette.green3Contrast or palette.green3,
                variable = "NONE",
                number = foreground == "contrast" and palette.pinkContrast or palette.pink,
                constant = foreground == "contrast" and palette.orangeContrast or palette.orange,
                identifier = foreground == "contrast" and palette.violet2Contrast or palette.violet2,
                parameter = palette.gray3,
                fun = foreground == "contrast" and palette.blue3Contrast or palette.blue3,
                statement = foreground == "contrast" and palette.violet2Contrast or palette.violet2,
                keyword = foreground == "contrast" and palette.violet2Contrast or palette.violet2,
                operator = palette.gray3,
                preproc = palette.gray3,
                type = foreground == "contrast" and palette.aquaContrast or palette.aqua,
                regex = foreground == "contrast" and palette.red3Contrast or palette.red3,
                deprecated = palette.gray,
                punct = palette.gray3,
                comment = palette.gray4,
                special1 = foreground == "contrast" and palette.yellow3Contrast or palette.yellow3,
                special2 = foreground == "contrast" and palette.violet2Contrast or palette.violet2,
                special3 = foreground == "contrast" and palette.violet2Contrast or palette.violet2,
            },
            diag = {
                error = palette.red,
                ok = palette.green,
                warning = palette.yellow,
                info = palette.blue2,
                hint = palette.green4,
            },
            diff = {
                add = palette.diffGreen,
                delete = palette.diffRed,
                change = palette.diffBlue,
                text = palette.diffYellow,
            },
            vcs = {
                added = palette.gitGreen,
                removed = palette.gitRed,
                changed = palette.gitYellow,
                untracked = palette.gray4,
            },
            term = {
                palette.mistBg0, -- black
                palette.red3, -- red
                palette.green3, -- green
                palette.yellow3, -- yellow
                palette.blue3, -- blue
                palette.pink, -- magenta
                palette.fg, -- cyan
                palette.gray2, -- white
                palette.gray3, -- bright black
                palette.red2, -- bright red
                palette.green2, -- bright green
                palette.yellow2, -- bright yellow
                palette.blue, -- bright blue
                palette.violet, -- bright magenta
                palette.green5, -- bright cyan
                palette.fg, -- bright white
                palette.orange, -- extended color 1
                palette.orange2, -- extended color 2
            },
        }
    end,
}

local M = {}
local PATH_SEP = vim.uv.os_uname().version:match("Windows") and "\\" or "/"

local get_compiled_path = function(theme)
    return table.concat({ vim.fn.stdpath("state"), "kanso", theme .. "_compiled.lua" }, PATH_SEP)
end

---@return string theme
function M.get_theme_from_bg_opt()
    local config = require("kanso").config
    return config.background[vim.o.background] or config.theme
end

---@param theme string
---@param highlights table
---@param termcolors table
function M.compile(theme, highlights, termcolors)
    vim.uv.fs_mkdir(vim.fn.stdpath("state") .. PATH_SEP .. "kanso", 448)

    local fname = get_compiled_path(theme)
    local file, err = io.open(fname, "wb")
    if not file or err then
        vim.notify("Kanso: Error writing " .. fname .. ":\n" .. err, vim.log.levels.ERROR)
        return
    end

    local lines = {
        "require'kanso'.compiled = string.dump(function()",
        "local g = vim.g",
        "local nvim_set_hl = vim.api.nvim_set_hl",
    }
    local inspect = vim.inspect
    for hl, spec in pairs(highlights) do
        if next(spec) then
            table.insert(lines, ('nvim_set_hl(0, "%s", %s)'):format(hl, inspect(spec):gsub("%s", "")))
        end
        for i, tcolor in ipairs(termcolors) do
            table.insert(lines, ('g["terminal_color_%d"] = "%s"'):format(i - 1, tcolor))
        end
    end
    table.insert(lines, "end)")

    local blob = table.concat(lines, "\n")
    assert(loadstring(blob, "=(compile)"))()
    file:write(require("kanso").compiled)
    file:close()
end

---@param theme string
---@return boolean status
function M.load_compiled(theme)
    local f = loadfile(get_compiled_path(theme))
    if f then
        f()
        return true
    end
    return false
end

return M

local M = {}

---@param colors KansoColors
---@param config? KansoConfig
function M.setup(colors, config)
    config = config or require("kanso").config
    local theme = colors.theme
    return {
        -- @variable                       various variable names
        ["@variable"] = { fg = theme.ui.fg },
        -- @variable.builtin (Special)     built-in variable names (e.g. `this`, `self`)
        ["@variable.builtin"] = { fg = theme.syn.special2, italic = config.italics },
        -- @variable.parameter             parameters of a function
        ["@variable.parameter"] = { fg = theme.syn.parameter },
        -- @variable.parameter.builtin     special parameters (e.g. `_`, `it`)
        -- @variable.member                object and struct fields
        ["@variable.member"] = { fg = theme.syn.identifier },
        --
        -- @constant (Constant)              constant identifiers
        -- @constant.builtin       built-in constant values
        -- @constant.macro         constants defined by the preprocessor
        --
        -- @module (Structure)      modules or namespaces
        -- @module.builtin         built-in modules or namespaces
        -- @label                  `GOTO` and other labels (e.g. `label:` in C), including heredoc labels
        --
        -- @string                 string literals
        -- @string.documentation   string documenting code (e.g. Python docstrings)
        -- @string.regexp          regular expressions
        ["@string.regexp"] = { fg = theme.syn.regex },
        -- @string.escape          escape sequences
        ["@string.escape"] = { fg = theme.syn.regex },
        -- @string.special         other special strings (e.g. dates)
        -- @string.special.symbol  symbols or atoms
        ["@string.special.symbol"] = { fg = theme.syn.identifier },
        -- @string.special.path    filenames
        -- @string.special.url (Underlined)     URIs (e.g. hyperlinks)
        ["@string.special.url"] = { fg = theme.syn.special1, undercurl = true },
        -- @character              character literals
        -- @character.special      special characters (e.g. wildcards)
        --
        -- @boolean                boolean literals
        -- @number                 numeric literals
        -- @number.float           floating-point number literals
        --
        -- @type                   type or class definitions and annotations
        -- @type.builtin           built-in types
        -- @type.definition        identifiers in type definitions (e.g. `typedef <type> <identifier>` in C)
        --
        -- @attribute              attribute annotations (e.g. Python decorators, Rust lifetimes)
        ["@attribute"] = { link = "Constant" },
        -- @attribute.builtin      builtin annotations (e.g. `@property` in Python)
        -- @property               the key in key/value pairs
        --
        -- @function               function definitions
        -- @function.builtin       built-in functions
        -- @function.call          function calls
        -- @function.macro         preprocessor macros
        --
        -- @function.method        method definitions
        -- @function.method.call   method calls
        --
        -- @constructor            constructor calls and definitions
        ["@constructor"] = { fg = theme.syn.special1 },
        ["@constructor.lua"] = { fg = theme.syn.keyword },
        -- @operator               symbolic operators (e.g. `+`, `*`)
        ["@operator"] = { link = "Operator" },
        --
        -- @keyword                keywords not fitting into specific categories
        -- @keyword.coroutine      keywords related to coroutines (e.g. `go` in Go, `async/await` in Python)
        -- @keyword.function       keywords that define a function (e.g. `func` in Go, `def` in Python)
        -- @keyword.operator       operators that are English words (e.g. `and`, `or`)
        ["@keyword.operator"] = { fg = theme.syn.operator },
        -- @keyword.import         keywords for including modules (e.g. `import`, `from` in Python)
        ["@keyword.import"] = { link = "PreProc" },
        -- @keyword.type           keywords defining composite types (e.g. `struct`, `enum`)
        -- @keyword.modifier       keywords defining type modifiers (e.g. `const`, `static`, `public`)
        -- @keyword.repeat         keywords related to loops (e.g. `for`, `while`)
        -- @keyword.return         keywords like `return` and `yield`
        ["@keyword.return"] = vim.tbl_extend(
            "force",
            { fg = theme.syn.special3 },
            not config.italics and {} or config.keywordStyle
        ),
        -- @keyword.debug          keywords related to debugging
        -- @keyword.exception      keywords related to exceptions (e.g. `throw`, `catch`)
        ["@keyword.exception"] = vim.tbl_extend("force", { fg = theme.syn.special3 }, config.statementStyle),

        ["@keyword.luap"] = { link = "@string.regex" },
        --
        -- @keyword.conditional         keywords related to conditionals (e.g. `if`, `else`)
        -- @keyword.conditional.ternary ternary operator (e.g. `?`, `:`)
        --
        -- @keyword.directive           various preprocessor directives and shebangs
        -- @keyword.directive.define    preprocessor definition directives
        --
        -- @punctuation.delimiter  delimiters (e.g. `;`, `.`, `,`)
        ["@punctuation.delimiter"] = { fg = theme.syn.punct },
        -- @punctuation.bracket    brackets (e.g. `()`, `{}`, `[]`)
        ["@punctuation.bracket"] = { fg = theme.syn.punct },
        -- @punctuation.special    special symbols (e.g. `{}` in string interpolation)
        ["@punctuation.special"] = { fg = theme.syn.special1 },
        --
        -- @comment                line and block comments
        -- @comment.documentation  comments documenting code
        --
        -- @comment.error          error-type comments (e.g. `ERROR`, `FIXME`, `DEPRECATED`)
        ["@comment.error"] = { fg = theme.ui.fg, bg = theme.diag.error, bold = config.bold },
        -- @comment.warning        warning-type comments (e.g. `WARNING`, `FIX`, `HACK`)
        ["@comment.warning"] = { fg = theme.ui.fg_reverse, bg = theme.diag.warning, bold = config.bold },
        -- @comment.todo           todo-type comments (e.g. `TODO`, `WIP`)
        -- @comment.note           note-type comments (e.g. `NOTE`, `INFO`, `XXX`)
        ["@comment.note"] = { fg = theme.ui.fg_reverse, bg = theme.diag.hint, bold = config.bold },
        --
        -- @markup.strong          bold text
        ["@markup.strong"] = { bold = config.bold },
        -- @markup.italic          italic text
        ["@markup.italic"] = { italic = true },
        -- @markup.strikethrough   struck-through text
        ["@markup.strikethrough"] = { strikethrough = true },
        -- @markup.underline       underlined text (only for literal underline markup!)
        ["@markup.underline"] = { underline = true },
        --
        -- @markup.heading         headings, titles (including markers)
        ["@markup.heading"] = { link = "Function" },
        -- @markup.heading.1       top-level heading
        -- @markup.heading.2       section heading
        -- @markup.heading.3       subsection heading
        -- @markup.heading.4       and so on
        -- @markup.heading.5       and so forth
        -- @markup.heading.6       six levels ought to be enough for anybody
        --
        -- @markup.quote           block quotes
        ["@markup.quote"] = { link = "@variable.parameter" },
        -- @markup.math            math environments (e.g. `$ ... $` in LaTeX)
        ["@markup.math"] = { link = "Constant" },
        -- @markup.environment     environments (e.g. in LaTeX)
        ["@markup.environment"] = { link = "Keyword" },
        --
        -- @markup.link            text references, footnotes, citations, etc.
        -- @markup.link.label      link, reference descriptions
        -- @markup.link.url        URL-style links
        ["@markup.link.url"] = { link = "@string.special.url" },
        -- @markup.raw             literal or verbatim text (e.g. inline code)
        ["@markup.raw"] = { link = "String" },
        -- @markup.raw.block       literal or verbatim text as a stand-alone block
        --
        -- @markup.list            list markers
        -- @markup.list.checked    checked todo-style list markers
        -- @markup.list.unchecked  unchecked todo-style list markers
        --
        -- @diff.plus              added text (for diff files)
        ["@diff.plus"] = { fg = theme.vcs.added },
        -- @diff.minus             deleted text (for diff files)
        ["@diff.minus"] = { fg = theme.vcs.removed },
        -- @diff.delta             changed text (for diff files)
        ["@diff.delta"] = { fg = theme.vcs.changed },
        --
        -- @tag                    XML-style tag names (e.g. in XML, HTML, etc.)
        -- @tag.builtin            XML-style tag names (e.g. HTML5 tags)
        -- @tag.attribute          XML-style tag attributes
        ["@tag.attribute"] = { fg = theme.syn.identifier },
        -- @tag.delimiter          XML-style tag delimiters
        ["@tag.delimiter"] = { fg = theme.syn.punct },
    }
end

return M
--vim: fdm=marker

local M = {}

---@alias ColorSpec string RGB Hex string
---@alias ColorTable table<string, ColorSpec>
---@alias KansoColorsSpec { palette: ColorTable, theme: ColorTable }
---@alias KansoColors { palette: PaletteColors, theme: ThemeColors }

--- default config
---@class KansoConfig
M.config = {
    bold = true,
    italics = true,
    undercurl = true,
    commentStyle = { italic = true },
    functionStyle = {},
    keywordStyle = { italic = true },
    statementStyle = {},
    typeStyle = {},
    transparent = false,
    dimInactive = false,
    terminalColors = true,
    colors = { theme = { zen = {}, pearl = {}, ink = {}, all = {} }, palette = {} },
    ---@type fun(colors: KansoColorsSpec): table<string, table>
    overrides = function()
        return {}
    end,
    ---@type { dark: string, light: string }
    background = { dark = "ink", light = "pearl" },
    theme = "ink",
    ---@type { dark: "default"|"contrast", light: "default"|"contrast" }|"default"|"contrast"
    foreground = "default",
    compile = false,
}

local function check_config(_)
    local err
    return not err
end

--- update global configuration with user settings
---@param config? KansoConfig user configuration
function M.setup(config)
    if check_config(config) then
        M.config = vim.tbl_deep_extend("force", M.config, config or {})
    else
        vim.notify("Kanso: Errors found while loading user config. Using default config.", vim.log.levels.ERROR)
    end
end

--- load the colorscheme
---@param theme? string
function M.load(theme)
    local utils = require("kanso.utils")

    theme = theme or M.config.background[vim.o.background] or M.config.theme
    M._CURRENT_THEME = theme

    if vim.g.colors_name then
        vim.cmd("hi clear")
    end

    vim.g.colors_name = "kanso"
    vim.o.termguicolors = true

    -- Setup autocommand to reload theme when background changes
    if not M._autocmd_created then
        M._autocmd_created = true
        vim.api.nvim_create_autocmd("OptionSet", {
            pattern = "background",
            callback = function()
                if vim.g.colors_name == "kanso" then
                    -- Clear cached modules to force reload
                    package.loaded["kanso.colors"] = nil
                    package.loaded["kanso.themes"] = nil
                    M.load()
                end
            end,
        })
    end

    if M.config.compile then
        if utils.load_compiled(theme) then
            return
        end

        M.compile()
        utils.load_compiled(theme)
    else
        local foreground_setting = type(M.config.foreground) == "table" and M.config.foreground[vim.o.background]
            or M.config.foreground
        ---@cast foreground_setting "default"|"contrast"
        local colors =
            require("kanso.colors").setup({ theme = theme, colors = M.config.colors, foreground = foreground_setting })
        local highlights = require("kanso.highlights").setup(colors, M.config)
        require("kanso.highlights").highlight(highlights, M.config.terminalColors and colors.theme.term or {})
    end
end

function M.compile()
    for theme, _ in pairs(require("kanso.themes")) do
        -- Compile both foreground variants if foreground is a table
        if type(M.config.foreground) == "table" then
            -- Compile for dark mode
            local colors_dark = require("kanso.colors").setup({
                theme = theme,
                colors = M.config.colors,
                foreground = M.config.foreground.dark,
            })
            local highlights_dark = require("kanso.highlights").setup(colors_dark, M.config)
            require("kanso.utils").compile(
                theme .. "_dark_" .. M.config.foreground.dark,
                highlights_dark,
                M.config.terminalColors and colors_dark.theme.term or {}
            )

            -- Compile for light mode
            local colors_light = require("kanso.colors").setup({
                theme = theme,
                colors = M.config.colors,
                foreground = M.config.foreground.light,
            })
            local highlights_light = require("kanso.highlights").setup(colors_light, M.config)
            require("kanso.utils").compile(
                theme .. "_light_" .. M.config.foreground.light,
                highlights_light,
                M.config.terminalColors and colors_light.theme.term or {}
            )
        else
            -- Fallback for backward compatibility
            local foreground_str = M.config.foreground
            ---@cast foreground_str "default"|"contrast"
            local colors = require("kanso.colors").setup({
                theme = theme,
                colors = M.config.colors,
                foreground = foreground_str,
            })
            local highlights = require("kanso.highlights").setup(colors, M.config)
            require("kanso.utils").compile(theme, highlights, M.config.terminalColors and colors.theme.term or {})
        end
    end
end

vim.api.nvim_create_user_command("KansoCompile", function()
    for mod, _ in pairs(package.loaded) do
        if mod:match("^kanso%.") then
            package.loaded[mod] = nil
        end
    end
    M.compile()
    vim.notify("Kanso: compiled successfully!", vim.log.levels.INFO)
    M.load(M._CURRENT_THEME)
    vim.api.nvim_exec_autocmds("ColorScheme", { modeline = false })
end, {})

return M

-- local c = require("kanso.color")
local M = {}

---@param colors KansoColors
---@param config? KansoConfig
function M.setup(colors, config)
    local theme = colors.theme
    config = config or require("kanso").config

    return {
        -- ColorColumn	Used for the columns set with 'colorcolumn'.
        ColorColumn = { bg = theme.ui.bg_p1 },
        -- Conceal		Placeholder characters substituted for concealed text (see 'conceallevel').
        Conceal = { fg = theme.ui.special, bold = config.bold },
        -- CurSearch	Used for highlighting a search pattern under the cursor (see 'hlsearch').
        CurSearch = { fg = theme.ui.fg, bg = theme.ui.bg_search, bold = config.bold },
        -- Cursor		Character under the cursor.
        Cursor = { fg = theme.ui.cursor_fg, bg = theme.ui.cursor_bg },
        -- lCursor		Character under the cursor when |language-mapping| is used (see 'guicursor').
        lCursor = { link = "Cursor" },
        -- CursorIM	Like Cursor, but used when in IME mode.
        CursorIM = { link = "Cursor" },
        -- CursorColumn	Screen-column at the cursor, when 'cursorcolumn' is set.
        CursorColumn = { link = "CursorLine" },
        -- CursorLine	Screen-line at the cursor, when 'cursorline' is set. Low-priority if foreground (ctermfg OR guifg) is not set.
        CursorLine = { bg = theme.ui.bg_p2 },
        -- Directory	Directory names (and other special names in listings).
        Directory = { fg = theme.syn.fun },
        -- DiffAdd		Diff mode: Added line. |diff.txt|
        DiffAdd = { bg = theme.diff.add },
        -- DiffChange	Diff mode: Changed line. |diff.txt|
        DiffChange = { bg = theme.diff.change },
        -- DiffDelete	Diff mode: Deleted line. |diff.txt|
        DiffDelete = { fg = theme.vcs.removed, bg = theme.diff.delete },
        -- DiffText	Diff mode: Changed text within a changed line. |diff.txt|
        DiffText = { bg = theme.diff.text },
        -- EndOfBuffer	Filler lines (~) after the end of the buffer. By default, this is highlighted like |hl-NonText|.
        EndOfBuffer = { fg = theme.ui.bg },
        -- TermCursor	Cursor in a focused terminal.
        -- TermCursorNC	Cursor in an unfocused terminal.
        -- ErrorMsg	Error messages on the command line.
        ErrorMsg = { fg = theme.diag.error },
        -- WinSeparator	Separators between window splits.
        WinSeparator = { fg = theme.ui.bg_m3, bg = config.dimInactive and theme.ui.bg_dim or theme.ui.none },
        VertSplit = { link = "WinSeparator" },
        -- Folded		Line used for closed folds.
        Folded = { fg = theme.ui.special, bg = theme.ui.bg_p1 },
        -- FoldColumn	'foldcolumn'
        FoldColumn = { fg = theme.ui.nontext, bg = theme.ui.none },
        -- SignColumn	Column where |signs| are displayed.
        SignColumn = { fg = theme.ui.special, bg = theme.ui.none },
        -- IncSearch	'incsearch' highlighting; also used for the text replaced with ":s///c".
        IncSearch = { fg = theme.ui.fg_reverse, bg = theme.diag.warning },
        -- Substitute	|:substitute| replacement text highlighting.
        Substitute = { fg = theme.ui.fg, bg = theme.vcs.removed },
        -- LineNr		Line number for ":number" and ":#" commands, and when 'number' or 'relativenumber' option is set.
        LineNr = { fg = theme.ui.cursor_line_nr_foreground, bg = theme.ui.none },
        -- LineNrAbove	Line number for when the 'relativenumber' option is set, above the cursor line.
        -- LineNrBelow	Line number for when the 'relativenumber' option is set, below the cursor line.
        -- CursorLineNr	Like LineNr when 'cursorline' is set and 'cursorlineopt' contains "number" or is "both", for the cursor line.
        CursorLineNr = { fg = theme.ui.cursor_line_nr_active_foreground, bg = theme.ui.none },
        -- CursorLineFold	Like FoldColumn when 'cursorline' is set for the cursor line.
        -- CursorLineSign	Like SignColumn when 'cursorline' is set for the cursor line.
        -- MatchParen	Character under the cursor or just before it, if it is a paired bracket, and its match. |pi_paren.txt|
        MatchParen = { fg = theme.diag.warning, bold = config.bold },
        -- ModeMsg		'showmode' message (e.g., "-- INSERT --").
        ModeMsg = { fg = theme.diag.warning, bold = config.bold },
        -- MsgArea		Area for messages and cmdline.
        MsgArea = vim.o.cmdheight == 0 and { link = "StatusLine" } or { fg = theme.ui.fg_dim },
        -- MsgSeparator	Separator for scrolled messages |msgsep|.
        MsgSeparator = { bg = vim.o.cmdheight == 0 and theme.ui.bg or theme.ui.bg_m3 },
        -- MoreMsg		|more-prompt|
        MoreMsg = { fg = theme.diag.info },
        -- NonText		'@' at the end of the window, characters from 'showbreak' and other characters that do not really exist in the text (e.g., ">" displayed when a double-wide character doesn't fit at the end of the line). See also |hl-EndOfBuffer|.
        NonText = { fg = theme.ui.nontext },
        -- Normal		Normal text.
        Normal = { fg = theme.ui.fg, bg = config.transparent and theme.ui.none or theme.ui.bg },
        -- NormalFloat	Normal text in floating windows.
        NormalFloat = { fg = theme.ui.float.fg, bg = config.transparent and theme.ui.none or theme.ui.float.bg },
        -- FloatBorder	Border of floating windows.
        FloatBorder = {
            fg = theme.ui.float.fg_border,
            bg = config.transparent and theme.ui.none or theme.ui.float.bg_border,
        },
        -- FloatTitle	Title of floating windows.
        FloatTitle = {
            fg = theme.ui.special,
            bg = config.transparent and theme.ui.none or theme.ui.float.bg_border,
            bold = config.bold,
        },
        -- FloatFooter	Footer of floating windows.
        FloatFooter = { fg = theme.ui.nontext, bg = config.transparent and theme.ui.none or theme.ui.float.bg_border },
        -- NormalNC	Normal text in non-current windows.
        NormalNC = config.dimInactive and { fg = theme.ui.fg_dim, bg = theme.ui.bg_dim } or { link = "Normal" },
        -- Pmenu		Popup menu: Normal item.
        Pmenu = { fg = theme.ui.pmenu.fg, bg = config.transparent and theme.ui.none or theme.ui.pmenu.bg },
        -- PmenuSel	Popup menu: Selected item.
        PmenuSel = { fg = theme.ui.pmenu.fg_sel, bg = theme.ui.pmenu.bg_sel },
        -- PmenuKind	Popup menu: Normal item "kind".
        PmenuKind = { fg = theme.ui.fg_dim, bg = config.transparent and theme.ui.none or theme.ui.pmenu.bg },
        -- PmenuKindSel	Popup menu: Selected item "kind".
        PmenuKindSel = { fg = theme.ui.fg_dim, bg = theme.ui.pmenu.bg_sel },
        -- PmenuExtra	Popup menu: Normal item "extra text".
        PmenuExtra = { fg = theme.ui.special, bg = theme.ui.pmenu.bg },
        -- PmenuExtraSel	Popup menu: Selected item "extra text".
        PmenuExtraSel = { fg = theme.ui.special, bg = theme.ui.pmenu.bg_sel },
        -- PmenuSbar	Popup menu: Scrollbar.
        PmenuSbar = { bg = config.transparent and theme.ui.none or theme.ui.pmenu.bg_sbar },
        -- PmenuThumb	Popup menu: Thumb of the scrollbar.
        PmenuThumb = { bg = theme.ui.pmenu.bg_thumb },
        -- Question	|hit-enter| prompt and yes/no questions.
        Question = { link = "MoreMsg" },
        -- QuickFixLine	Current |quickfix| item in the quickfix window. Combined with |hl-CursorLine| when the cursor is there.
        QuickFixLine = { bg = config.transparent and theme.ui.none or theme.ui.bg_p1 },
        -- Search		Last search pattern highlighting (see 'hlsearch'). Also used for similar items that need to stand out.
        Search = { fg = theme.ui.fg, bg = theme.ui.bg_search },
        -- SpecialKey	Unprintable characters: Text displayed differently from what it really is. But not 'listchars' whitespace. |hl-Whitespace|
        SpecialKey = { fg = theme.ui.special },
        -- SpellBad	Word that is not recognized by the spellchecker. |spell| Combined with the highlighting used otherwise.
        SpellBad = { undercurl = config.undercurl, underline = not config.undercurl, sp = theme.diag.error },
        -- SpellCap	Word that should start with a capital. |spell| Combined with the highlighting used otherwise.
        SpellCap = { undercurl = config.undercurl, underline = not config.undercurl, sp = theme.diag.warning },
        -- SpellLocal	Word that is recognized by the spellchecker as one that is used in another region. |spell| Combined with the highlighting used otherwise.
        SpellLocal = { undercurl = config.undercurl, underline = not config.undercurl, sp = theme.diag.warning },
        -- SpellRare	Word that is recognized by the spellchecker as one that is hardly ever used. |spell| Combined with the highlighting used otherwise.
        SpellRare = { undercurl = config.undercurl, underline = not config.undercurl, sp = theme.diag.warning },
        -- StatusLine	Status line of current window.
        StatusLine = { fg = theme.ui.fg_dim, bg = theme.ui.none },
        -- StatusLineNC	Status lines of not-current windows. Note: If this is equal to "StatusLine", Vim will use "^^^" in the status line of the current window.
        StatusLineNC = { fg = theme.ui.nontext, bg = theme.ui.none },
        -- TabLine		Tab pages line, not active tab page label.
        TabLine = { bg = theme.ui.none, fg = theme.ui.special },
        -- TabLineFill	Tab pages line, where there are no labels.
        TabLineFill = { bg = theme.ui.none },
        -- TabLineSel	Tab pages line, active tab page label.
        TabLineSel = {
            fg = theme.ui.fg_dim,
            bg = not config.transparent and theme.ui.bg_p1 or theme.ui.none,
            bold = config.bold,
        },
        -- Title		Titles for output from ":set all", ":autocmd" etc.
        Title = { fg = theme.syn.fun, bold = config.bold },
        -- Visual		Visual mode selection.
        Visual = { bg = theme.ui.bg_visual },
        -- VisualNOS	Visual mode selection when vim is "Not Owning the Selection".
        VisualNOS = { link = "Visual" },
        -- WarningMsg	Warning messages.
        WarningMsg = { fg = theme.diag.warning },
        -- Whitespace	"nbsp", "space", "tab", "multispace", "lead" and "trail" in 'listchars'.
        Whitespace = { fg = theme.ui.whitespace },
        -- WildMenu	Current match in 'wildmenu' completion.
        WildMenu = { link = "Pmenu" },
        -- WinBar		Window bar of current window.
        WinBar = { fg = theme.ui.fg_dim, bg = theme.ui.none },
        -- WinBarNC	Window bar of not-current windows.
        WinBarNC = { fg = theme.ui.fg_dim, bg = config.dimInactive and theme.ui.bg_dim or theme.ui.none },

        -- SignColumnSB = { link = "SignColumn" },
        -- NormalSB = { link = "Normal" },

        debugPC = { bg = theme.diff.delete },
        debugBreakpoint = { fg = theme.syn.special1, bg = theme.ui.none },

        LspReferenceText = { bg = theme.ui.bg_p2 },
        LspReferenceRead = { link = "LspReferenceText" },
        LspReferenceWrite = { bg = theme.ui.bg_p2, underline = true },
        -- LspInlayHint = { link = "NonText"},

        DiagnosticError = { fg = theme.diag.error },
        DiagnosticWarn = { fg = theme.diag.warning },
        DiagnosticInfo = { fg = theme.diag.info },
        DiagnosticHint = { fg = theme.diag.hint },
        DiagnosticOk = { fg = theme.diag.ok },

        DiagnosticFloatingError = { fg = theme.diag.error },
        DiagnosticFloatingWarn = { fg = theme.diag.warning },
        DiagnosticFloatingInfo = { fg = theme.diag.info },
        DiagnosticFloatingHint = { fg = theme.diag.hint },
        DiagnosticFloatingOk = { fg = theme.diag.ok },

        DiagnosticSignError = { fg = theme.diag.error, bg = theme.ui.none },
        DiagnosticSignWarn = { fg = theme.diag.warning, bg = theme.ui.none },
        DiagnosticSignInfo = { fg = theme.diag.info, bg = theme.ui.none },
        DiagnosticSignHint = { fg = theme.diag.hint, bg = theme.ui.none },

        DiagnosticVirtualTextError = { link = "DiagnosticError" },
        DiagnosticVirtualTextWarn = { link = "DiagnosticWarn" },
        DiagnosticVirtualTextInfo = { link = "DiagnosticInfo" },
        DiagnosticVirtualTextHint = { link = "DiagnosticHint" },

        DiagnosticUnderlineError = {
            undercurl = config.undercurl,
            underline = not config.undercurl,
            sp = theme.diag.error,
        },
        DiagnosticUnderlineWarn = {
            undercurl = config.undercurl,
            underline = not config.undercurl,
            sp = theme.diag.warning,
        },
        DiagnosticUnderlineInfo = {
            undercurl = config.undercurl,
            underline = not config.undercurl,
            sp = theme.diag.info,
        },
        DiagnosticUnderlineHint = {
            undercurl = config.undercurl,
            underline = not config.undercurl,
            sp = theme.diag.hint,
        },

        LspSignatureActiveParameter = { fg = theme.diag.warning },
        LspCodeLens = { fg = theme.syn.comment },

        -- vcs
        diffAdded = { fg = theme.vcs.added },
        diffRemoved = { fg = theme.vcs.removed },
        diffDeleted = { fg = theme.vcs.removed },
        diffChanged = { fg = theme.vcs.changed },
        diffOldFile = { fg = theme.vcs.removed },
        diffNewFile = { fg = theme.vcs.added },
        -- diffFile = { fg = c.steelGray },
        -- diffLine = { fg = c.steelGray },
        -- diffIndexLine = { link = 'Identifier' },
    }
end

return M

-- local c = require("kanso.color")
local M = {}

---@param colors KansoColors
---@param config? KansoConfig
function M.setup(colors, config)
    local theme = colors.theme
    config = config or require("kanso").config

    return {
        -- *Comment	any comment
        Comment = vim.tbl_extend("force", { fg = theme.syn.comment }, not config.italics and {} or config.commentStyle),

        -- *Constant	any constant
        Constant = { fg = theme.syn.constant },
        --  String		a string constant: "this is a string"
        String = { fg = theme.syn.string },
        --  Character	a character constant: 'c', '\n'
        Character = { link = "String" },
        --  Number		a number constant: 234, 0xff
        Number = { fg = theme.syn.number },
        --  Boolean	a boolean constant: TRUE, false
        Boolean = { fg = theme.syn.constant },
        --  Float		a floating point constant: 2.3e10
        Float = { link = "Number" },

        -- *Identifier	any variable name
        Identifier = { fg = theme.syn.identifier },
        --  Function	function name (also: methods for classes)
        Function = vim.tbl_extend("force", { fg = theme.syn.fun }, config.functionStyle),

        -- *Statement	any statement
        Statement = vim.tbl_extend("force", { fg = theme.syn.statement }, config.statementStyle),
        --  Conditional	if, then, else, endif, switch, etc.
        --  Repeat		for, do, while, etc.
        --  Label		case, default, etc.
        --  Operator	"sizeof", "+", "*", etc.
        Operator = { fg = theme.syn.operator },
        --  Keyword	any other keyword
        Keyword = vim.tbl_extend("force", { fg = theme.syn.keyword }, not config.italics and {} or config.keywordStyle),
        --  Exception	try, catch, throw
        Exception = { fg = theme.syn.special2 },

        -- *PreProc	generic Preprocessor
        PreProc = { fg = theme.syn.preproc },
        --  Include	preprocessor #include
        --  Define		preprocessor #define
        --  Macro		same as Define
        --  PreCondit	preprocessor #if, #else, #endif, etc.

        -- *Type		int, long, char, etc.
        Type = vim.tbl_extend("force", { fg = theme.syn.type }, config.typeStyle),
        --  StorageClass	static, register, volatile, etc.
        --  Structure	struct, union, enum, etc.
        --  Typedef	A typedef

        -- *Special	any special symbol
        Special = { fg = theme.syn.special1 },
        --  SpecialChar	special character in a constant
        --  Tag		you can use CTRL-] on this
        --  Delimiter	character that needs attention
        Delimiter = { fg = theme.syn.punct },
        --  SpecialComment	special things inside a comment
        --  Debug		debugging statements

        -- *Underlined	text that stands out, HTML links
        Underlined = { fg = theme.syn.special1, underline = true },
        Bold = { bold = config.bold },
        Italic = { italic = config.italics },

        -- *Ignore		left blank, hidden  |hl-Ignore|
        Ignore = { link = "NonText" },

        -- *Error		any erroneous construct
        Error = { fg = theme.diag.error },

        -- *Todo		anything that needs extra attention; mostly the keywords TODO FIXME WARNING and XXX
        Todo = { fg = theme.ui.fg_reverse, bg = theme.diag.info, bold = config.bold },

        qfLineNr = { link = "lineNr" },
        qfFileName = { link = "Directory" },

        -- htmlH1 = {},
        -- htmlH2 = {},

        -- mkdHeading = {},
        -- mkdCode = {},
        -- mkdCodeDelimiter = {},
        -- mkdCodeStart = {},
        -- mkdCodeEnd = {},
        -- mkdLink = {},

        -- markdownHeadingDelimiter = {},
        markdownCode = { fg = theme.syn.string },
        markdownCodeBlock = { fg = theme.syn.string },
        markdownEscape = { fg = theme.ui.none },
        -- markdownH1 = {},
        -- markdownH2 = {},
        -- markdownLinkText = {},
    }
end

return M

local hsluv = require("kanso.lib.hsluv")

---@class HSLuvColor
local Color = {}
local Color_mt = {
    __index = Color,
    __tostring = function(self)
        return self:to_hex()
    end,
}

local function none_to_hex()
    return "NONE"
end

---Create a new HSLuv color object from a RGB hex string
---@param hex string Hex color
---@return HSLuvColor
function Color.new(hex)
    if hex:lower() == "none" then
        return setmetatable({ H = 0, S = 0, L = 0, to_hex = none_to_hex }, Color_mt)
    end
    local H, S, L = unpack(hsluv.hex_to_hsluv(hex))
    return setmetatable({ H = H, S = S, L = L }, Color_mt)
end

function Color:to_rgb()
    return hsluv.hsluv_to_rgb({ self.H, self.S, self.L })
end

function Color:to_hex()
    return hsluv.hsluv_to_hex({ self.H, self.S, self.L })
end

local function blendRGB(a, b, r)
    local c = {}
    for i = 1, 3 do
        c[i] = math.sqrt((1 - r) * math.pow(a[i], 2) + r * math.pow(b[i], 2))
    end
    return c
end

--- Blend Color with another color (hex)
---@param b string Hex color
---@param r number Blend ratio [0, 1]
---@return HSLuvColor
function Color:blend(b, r)
    if b:lower() == "none" then
        return self
    end
    local c = blendRGB(self:to_rgb(), hsluv.hex_to_rgb(b), r)
    self.H, self.S, self.L = unpack(hsluv.rgb_to_hsluv(c))
    return self
end

---@param r number Brighten ratio [-1, 1]
---@param bg? string background color, if light, r = -r
---@return HSLuvColor
function Color:brighten(r, bg)
    if bg and bg:lower() == "none" then
        return self
    end
    local bg_lightness = bg and hsluv.hex_to_hsluv(bg)[3] or 0
    r = bg_lightness > 50 and -r or r

    local lspace = r > 0 and 100 - self.L or self.L
    self.L = self.L + lspace * r
    return self
end

---@param r number Saturate ratio [-1, 1]
---@return HSLuvColor
function Color:saturate(r)
    local lspace = r > 0 and 100 - self.S or self.S
    self.S = self.S + lspace * r
    return self
end

local M = {}
return setmetatable(M, {
    __call = function(_, ...)
        return Color.new(...)
    end,
})

local M = {}

---@param highlights table
---@param termcolors table
function M.highlight(highlights, termcolors)
    for hl, spec in pairs(highlights) do
        vim.api.nvim_set_hl(0, hl, spec)
    end
    for i, tcolor in ipairs(termcolors) do
        vim.g["terminal_color_" .. i - 1] = tcolor
    end
end

---@param colors KansoColors
---@param config? KansoConfig
function M.setup(colors, config)
    config = config or require("kanso").config

    local highlights = {}
    for _, highlight in ipairs({ "editor", "syntax", "treesitter", "lsp", "plugins" }) do
        local mod = require("kanso.highlights." .. highlight)
        for hl, spec in pairs(mod.setup(colors, config)) do
            highlights[hl] = spec
        end
    end

    for hl, spec in pairs(config.overrides(colors)) do
        if highlights[hl] and next(spec) then
            highlights[hl].link = nil
        end
        highlights[hl] = vim.tbl_extend("force", highlights[hl] or {}, spec)
    end

    return highlights
end

return M

local M = {}
---@param colors KansoColors
---@param config? KansoConfig
function M.setup(colors, config)
    config = config or require("kanso").config
    local theme = colors.theme
    return {
        -- ["@lsp.type.class"] = { link = "Structure" },
        -- ["@lsp.type.decorator"] = { link = "Function" },
        -- ["@lsp.type.enum"] = { link = "Structure" },
        -- ["@lsp.type.enumMember"] = { link = "Constant" },
        -- ["@lsp.type.function"] = { link = "Function" },
        -- ["@lsp.type.interface"] = { link = "Structure" },
        ["@lsp.type.macro"] = { link = "Macro" },
        ["@lsp.type.method"] = { link = "@function.method" }, -- Function
        ["@lsp.type.namespace"] = { link = "@module" }, -- Structure
        ["@lsp.type.parameter"] = { link = "@variable.parameter" }, -- Identifier
        -- ["@lsp.type.property"] = { link = "Identifier" },
        -- ["@lsp.type.struct"] = { link = "Structure" },
        -- ["@lsp.type.type"] = { link = "Type" },
        -- ["@lsp.type.typeParameter"] = { link = "TypeDef" },
        ["@lsp.type.variable"] = { fg = "none" }, -- Identifier
        ["@lsp.type.comment"] = { link = "Comment" }, -- Comment

        ["@lsp.type.const"] = { link = "Constant" },
        ["@lsp.type.comparison"] = { link = "Operator" },
        ["@lsp.type.bitwise"] = { link = "Operator" },
        ["@lsp.type.punctuation"] = { link = "Delimiter" },

        ["@lsp.type.selfParameter"] = { link = "@variable.builtin" },
        -- ["@lsp.type.builtinConstant"] = { link = "@constant.builtin" },
        ["@lsp.type.builtinConstant"] = { link = "@constant.builtin" },
        ["@lsp.type.magicFunction"] = { link = "@function.builtin" },

        ["@lsp.mod.readonly"] = { link = "Constant" },
        ["@lsp.mod.typeHint"] = { link = "Type" },
        -- ["@lsp.mod.defaultLibrary"] = { link = "Special" },
        -- ["@lsp.mod.builtin"] = { link = "Special" },

        ["@lsp.typemod.operator.controlFlow"] = { link = "@keyword.exception" }, -- rust ? operator
        ["@lsp.type.lifetime"] = { link = "Operator" },
        ["@lsp.typemod.keyword.documentation"] = { link = "Special" },
        ["@lsp.type.decorator.rust"] = { link = "PreProc" },

        ["@lsp.typemod.variable.global"] = { link = "Constant" },
        ["@lsp.typemod.variable.static"] = { link = "Constant" },
        ["@lsp.typemod.variable.defaultLibrary"] = { link = "Special" },

        ["@lsp.typemod.function.builtin"] = { link = "@function.builtin" },
        ["@lsp.typemod.function.defaultLibrary"] = { link = "@function.builtin" },
        ["@lsp.typemod.method.defaultLibrary"] = { link = "@function.builtin" },

        ["@lsp.typemod.variable.injected"] = { link = "@variable" },

        ["@lsp.typemod.function.readonly"] = { fg = theme.syn.fun, bold = config.bold },
    }
end

return M
--vim: fdm=marker

local theme = require("kanso.colors").setup().theme

local kanso = {}

kanso.normal = {
    a = { bg = theme.ui.fg, fg = theme.ui.bg },
    b = { bg = theme.ui.none, fg = theme.ui.fg },
    c = { bg = theme.ui.none, fg = theme.ui.fg },
}

kanso.insert = {
    a = { bg = theme.diag.ok, fg = theme.ui.bg },
    b = { bg = theme.ui.none, fg = theme.diag.ok },
}

kanso.command = {
    a = { bg = theme.syn.operator, fg = theme.ui.bg },
    b = { bg = theme.ui.none, fg = theme.syn.operator },
}

kanso.visual = {
    a = { bg = theme.syn.keyword, fg = theme.ui.bg },
    b = { bg = theme.ui.none, fg = theme.syn.keyword },
}

kanso.replace = {
    a = { bg = theme.syn.constant, fg = theme.ui.bg },
    b = { bg = theme.ui.none, fg = theme.syn.constant },
}

kanso.inactive = {
    a = { bg = theme.ui.none, fg = theme.ui.fg_dim },
    b = { bg = theme.ui.none, fg = theme.ui.fg_dim },
    c = { bg = theme.ui.none, fg = theme.ui.fg_dim },
}

if vim.g.kanso_lualine_bold then
    for _, mode in pairs(kanso) do
        mode.a.gui = "bold"
    end
end

return kanso

This code segment functions to: Define color scheme configurations for a terminal interface by specifying hexadecimal values for text elements, cursor appearance, background shading, and extended ANSI palette variations.

```lua
[TASK_BEGIN]
{
    foreground = "#4d6962",
    background = "#f4f0e6",

    cursor_bg = "#7c8377",
    cursor_fg = "#f4f0e6",
    cursor_border = "#7c8377",

    selection_fg = "#f4f0e6",
    selection_bg = "#7c8377",

    ansi = {
        "#3d4843",   -- black (dark)
        "#ab5d52",   -- red
        "#6e915d",   -- green
        "#b7a15f",   -- yellow
        "#6c8c95",   -- blue
        "#9b859d",   -- magenta
        "#5d9098",   -- cyan
        "#c6c3b5"    -- white (light)
    },

    bright_ansi = {
        "#5c6c66",   -- bright black
        "#c96759",   -- bright red
        "#87b26a",   -- bright green
        "#d5b875",   -- bright yellow
        "#7fa8b3",   -- bright blue
        "#b49eb6",   -- bright magenta
        "#76adb6",   -- bright cyan
        "#e0ded1"    -- bright white
    }
}
[TASK_END]
```