import SwiftUI #if canImport(UIKit) import UIKit #elseif canImport(AppKit) import AppKit #endif private enum AIPalette { #if canImport(UIKit) private static func dynamicColor(light: UIColor, dark: UIColor) -> Color { Color( UIColor { traits in traits.userInterfaceStyle == .dark ? dark : light }) } private static func rgba( _ red: CGFloat, _ green: CGFloat, _ blue: CGFloat, _ alpha: CGFloat ) -> UIColor { UIColor(red: red / 255, green: green / 255, blue: blue / 255, alpha: alpha) } private static func color(light: UIColor, dark: UIColor) -> Color { dynamicColor(light: light, dark: dark) } // 中性石墨灰阶:所有中性色严格 R=G=B,既不冷到读出蓝,也不暖到读出米色;主色让位给 // 黑/白,颜色只用来表达状态。原先 B 比 R 高 3~10 级,浅色下大面积文字与描边会蒙一层冷调。 static let canvas = color(light: rgba(245, 245, 245, 1), dark: rgba(10, 10, 10, 1)) static let surface = color(light: rgba(255, 255, 255, 1), dark: rgba(21, 21, 21, 1)) static let surfaceRaised = color(light: rgba(255, 255, 255, 1), dark: rgba(29, 29, 29, 1)) static let control = color(light: rgba(239, 239, 239, 1), dark: rgba(39, 39, 39, 1)) static let tile = color(light: rgba(247, 247, 247, 1), dark: rgba(255, 255, 255, 0.055)) static let tileLine = color(light: rgba(232, 232, 232, 1), dark: rgba(255, 255, 255, 0.09)) static let chrome = color(light: rgba(252, 252, 252, 0.92), dark: rgba(13, 13, 13, 0.88)) static let ink = color(light: rgba(18, 18, 18, 1), dark: rgba(242, 242, 242, 1)) static let muted = color(light: rgba(92, 92, 92, 1), dark: rgba(164, 164, 164, 1)) static let faint = color(light: rgba(130, 130, 130, 1), dark: rgba(118, 118, 118, 1)) static let line = color(light: rgba(226, 226, 226, 1), dark: rgba(255, 255, 255, 0.11)) static let brand = color(light: rgba(18, 18, 18, 1), dark: rgba(9, 9, 9, 1)) static let primary = color(light: rgba(23, 23, 23, 1), dark: rgba(240, 240, 240, 1)) static let onPrimary = color(light: rgba(255, 255, 255, 1), dark: rgba(13, 13, 13, 1)) static let danger = color(light: rgba(193, 46, 40, 1), dark: rgba(247, 113, 105, 1)) static let onDanger = color(light: rgba(255, 255, 255, 1), dark: rgba(24, 8, 7, 1)) static let warning = color(light: rgba(170, 92, 15, 1), dark: rgba(233, 166, 60, 1)) static let success = color(light: rgba(16, 122, 86, 1), dark: rgba(66, 199, 132, 1)) static let segmentTrack = color(light: rgba(235, 235, 235, 1), dark: rgba(28, 28, 28, 1)) static let segmentSelected = color(light: rgba(255, 255, 255, 1), dark: rgba(58, 58, 58, 1)) static let cardShadow = color(light: rgba(18, 18, 18, 0.06), dark: rgba(0, 0, 0, 0.60)) #elseif canImport(AppKit) static let canvas = Color(red: 0.961, green: 0.961, blue: 0.961) static let surface = Color.white static let control = Color(red: 0.937, green: 0.937, blue: 0.937) static let ink = Color(red: 0.071, green: 0.071, blue: 0.071) static let muted = Color(red: 0.361, green: 0.361, blue: 0.361) static let line = Color(red: 0.886, green: 0.886, blue: 0.886) static let brand = Color(red: 0.071, green: 0.071, blue: 0.071) static let surfaceRaised = Color.white static let chrome = Color.white.opacity(0.86) static let onPrimary = Color.white static let onDanger = Color.white static let primary = Color(red: 0.090, green: 0.090, blue: 0.090) static let danger = Color(red: 0.757, green: 0.180, blue: 0.157) static let warning = Color(red: 0.667, green: 0.361, blue: 0.059) static let success = Color(red: 0.063, green: 0.478, blue: 0.337) static let tile = Color(red: 0.969, green: 0.969, blue: 0.969) static let tileLine = Color(red: 0.910, green: 0.910, blue: 0.910) static let faint = Color(red: 0.510, green: 0.510, blue: 0.510) static let segmentTrack = Color(red: 0.922, green: 0.922, blue: 0.922) static let segmentSelected = Color.white static let cardShadow = Color(red: 0.071, green: 0.071, blue: 0.071).opacity(0.06) #else private static func color(_ red: CGFloat, _ green: CGFloat, _ blue: CGFloat) -> Color { Color(red: red / 255, green: green / 255, blue: blue / 255) } static let canvas = color(245, 245, 245) static let surface = color(255, 255, 255) static let control = color(239, 239, 239) static let ink = color(18, 18, 18) static let muted = color(92, 92, 92) static let line = color(226, 226, 226) static let brand = color(18, 18, 18) static let surfaceRaised = color(255, 255, 255) static let chrome = color(255, 255, 255, 0.82) static let onPrimary = color(255, 255, 255) static let onDanger = color(255, 255, 255) static let primary = color(23, 23, 23) static let danger = color(190, 65, 57) static let warning = color(170, 111, 23) static let success = color(50, 150, 101) static let tile = color(247, 247, 247) static let tileLine = color(232, 232, 232) static let faint = color(130, 130, 130) static let segmentTrack = color(235, 235, 235) static let segmentSelected = color(255, 255, 255) static let cardShadow = color(18, 18, 18) #endif } public enum AITheme { public static let canvas = AIPalette.canvas public static let surface = AIPalette.surface public static let surfaceRaised = AIPalette.surfaceRaised public static let control = AIPalette.control public static let tile = AIPalette.tile public static let tileLine = AIPalette.tileLine public static let chrome = AIPalette.chrome public static let ink = AIPalette.ink public static let muted = AIPalette.muted public static let faint = AIPalette.faint public static let line = AIPalette.line public static let brand = AIPalette.brand public static let primary = AIPalette.primary public static let onPrimary = AIPalette.onPrimary public static let danger = AIPalette.danger public static let onDanger = AIPalette.onDanger public static let warning = AIPalette.warning public static let success = AIPalette.success public static let segmentTrack = AIPalette.segmentTrack public static let segmentSelected = AIPalette.segmentSelected public static let cardShadow = AIPalette.cardShadow public static let buttonHeight: CGFloat = 48 // 停用态主按钮保留一层主色淡底,避免和次级按钮长得一模一样,层级读不出来。 public static let disabledFillOpacity: Double = 0.14 public static let disabledStrokeOpacity: Double = 0.22 public static let compactButtonHeight: CGFloat = 44 public static let largeButtonHeight: CGFloat = 56 public static let toolbarButtonHeight: CGFloat = 44 // 导航栏只给约 38pt 高度,44pt 的方块会被上下裁切,所以工具栏图标按钮单独取 34。 public static let iconButtonSize: CGFloat = 34 public static let iconButtonRadius: CGFloat = 11 public static let buttonRadius: CGFloat = 16 public static let cardRadius: CGFloat = 22 public static let inputRadius: CGFloat = 16 public static let inputHeight: CGFloat = 52 public static let segmentedControlHeight: CGFloat = 44 public static let tileRadius: CGFloat = 14 public static let chipHeight: CGFloat = 34 public static let compactControlHeight: CGFloat = 44 public static let compactButtonMinWidth: CGFloat = 72 public static let regularButtonMinWidth: CGFloat = 88 public static let toolbarButtonMinWidth: CGFloat = 96 public static let toolbarButtonWidth: CGFloat = 104 public static let footerSecondaryButtonWidth: CGFloat = 104 public static let listActionButtonWidth: CGFloat = 84 }