local Color = {} Color.__index = Color function Color.new(hex) local self = setmetatable({}, Color) hex = hex:gsub("^#", "") self.r = tonumber(hex:sub(1, 2), 16) self.g = tonumber(hex:sub(3, 4), 16) self.b = tonumber(hex:sub(5, 6), 16) return self end function Color:to_css() return string.format("#%02x%02x%02x", self.r, self.g, self.b) end function Color:blend(other, factor) other = type(other) == "string" and Color.new(other) or other return Color.new( string.format( "#%02x%02x%02x", math.floor(self.r + (other.r - self.r) * factor + 0.5), math.floor(self.g + (other.g - self.g) * factor + 0.5), math.floor(self.b + (other.b - self.b) * factor + 0.5) ) ) end function Color:darken(amount) return self:blend("#000000", amount) end function Color:lighten(amount) return self:blend("#ffffff", amount) end function Color:saturate(factor) local gray = math.floor(0.299 * self.r + 0.587 * self.g + 0.114 * self.b + 0.5) local gray_color = Color.new(string.format("#%02x%02x%02x", gray, gray, gray)) return self:blend(gray_color, 1 - factor) end return setmetatable(Color, { __call = function(_, hex) return Color.new(hex) end, })