// // Theme.swift // Haru_Danim // // 컬러 팔레트 (CLAUDE.md §5.2) // import SwiftUI import UIKit extension Color { /// "#RRGGBB" 형식의 hex 문자열로 생성 init(hex: String) { let cleaned = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) var value: UInt64 = 0 Scanner(string: cleaned).scanHexInt64(&value) let r = Double((value >> 16) & 0xFF) / 255 let g = Double((value >> 8) & 0xFF) / 255 let b = Double(value & 0xFF) / 255 self.init(red: r, green: g, blue: b) } /// 라이트/다크 모드에 따라 달라지는 동적 색 init(light: Color, dark: Color) { self.init(uiColor: UIColor { traits in traits.userInterfaceStyle == .dark ? UIColor(dark) : UIColor(light) }) } /// "#RRGGBB" hex 문자열로 변환. /// 와이드 컬러(P3)에서 getRed 성분이 0...1 밖으로 나올 수 있어 클램프한다 — /// 음수/1 초과 값이 %02X 포맷을 거치면 자릿수가 깨진 hex("#FFFFFFE6…")가 저장된다. var hexString: String { let ui = UIColor(self) var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0 ui.getRed(&r, green: &g, blue: &b, alpha: &a) func component(_ value: CGFloat) -> Int { Int(round(min(max(value, 0), 1) * 255)) } return String(format: "#%02X%02X%02X", component(r), component(g), component(b)) } } enum AppTheme { /// Primary Green: 라이트 딥 모스 그린 / 다크 세이지 민트 static let green = Color(light: Color(hex: "#2F6B4F"), dark: Color(hex: "#7FBF9E")) /// Accent Yellow: 라이트 머스터드 골드 / 다크 소프트 앰버 static let yellow = Color(light: Color(hex: "#D9A621"), dark: Color(hex: "#E8C558")) /// Background: 라이트 웜 화이트 / 다크 그린 틴트 블랙 static let background = Color(light: Color(hex: "#FAFAF6"), dark: Color(hex: "#111512")) /// 카드 등 한 단계 떠 있는 표면 static let surface = Color(light: .white, dark: Color(hex: "#1B211D")) /// 꼬리표 색 프리셋 (라이트/다크 공용으로 무난한 톤) static let tagPresets: [String] = [ "#2F6B4F", "#D9A621", "#4A7A9D", "#9D5B4A", "#7A5C9D", "#4F8A8B", "#C06C84", "#6B705C", "#B5651D", "#3D5A80", "#8D6B94", "#588157", ] }