import { hexToRgba } from '@toss/utils'; import { mapValues } from 'es-toolkit'; import type { BrandOriginalKey, BrandAlphaKey, BrandAccentKey } from './service-domain'; import { alphas } from './alphas'; import type { AlphasKey } from './types'; export { alphas }; /** * 원시(primitive) 색상 SSOT. * * 정본 = color-variables.json의 `primitive` 블록 (Figma export, 2026-07-29 전수 대조 — 무변경). * gray-cool 100(밝음)→1600(어두움) 선형 스케일 · rainbow 9색 · achromatic. * 중립 alpha(alpha-white/black/gray)는 아래 seed × `alphas` 스텝으로 생성하고, * 브랜드 램프는 도메인 스코프라 `service-domain.ts`에 분리한다. */ const primitiveBase = { 'lp-pri-achromatic-white': '#ffffff', 'lp-pri-achromatic-black': '#000000', 'lp-pri-gray-cool-100': '#fafafb', 'lp-pri-gray-cool-200': '#f1f1f2', 'lp-pri-gray-cool-300': '#e8e8e9', 'lp-pri-gray-cool-400': '#d2d2d4', 'lp-pri-gray-cool-500': '#bdbdc0', 'lp-pri-gray-cool-600': '#a9a9ab', 'lp-pri-gray-cool-700': '#959597', 'lp-pri-gray-cool-800': '#818184', 'lp-pri-gray-cool-900': '#6e6e71', 'lp-pri-gray-cool-1000': '#5c5c5f', 'lp-pri-gray-cool-1100': '#4a4a4d', 'lp-pri-gray-cool-1200': '#39393b', 'lp-pri-gray-cool-1300': '#2b2b2d', 'lp-pri-gray-cool-1400': '#1e1e1f', 'lp-pri-gray-cool-1500': '#121213', 'lp-pri-gray-cool-1600': '#060606', 'lp-pri-rainbow-red-100': '#fff0ee', 'lp-pri-rainbow-red-200': '#ffdbd6', 'lp-pri-rainbow-red-300': '#ffbbb2', 'lp-pri-rainbow-red-400': '#ff9a8e', 'lp-pri-rainbow-red-500': '#ff796e', 'lp-pri-rainbow-red-600': '#ff5048', 'lp-pri-rainbow-red-700': '#fa001d', 'lp-pri-rainbow-red-800': '#dd0018', 'lp-pri-rainbow-red-900': '#c10014', 'lp-pri-rainbow-red-1000': '#a6000f', 'lp-pri-rainbow-red-1100': '#8b000b', 'lp-pri-rainbow-red-1200': '#6a1413', 'lp-pri-rainbow-red-1300': '#4f1411', 'lp-pri-rainbow-red-1400': '#37100d', 'lp-pri-rainbow-orange-100': '#fff2e7', 'lp-pri-rainbow-orange-200': '#ffdec3', 'lp-pri-rainbow-orange-300': '#ffc08c', 'lp-pri-rainbow-orange-400': '#ffa04c', 'lp-pri-rainbow-orange-500': '#f58800', 'lp-pri-rainbow-orange-600': '#dd7a00', 'lp-pri-rainbow-orange-700': '#c56c00', 'lp-pri-rainbow-orange-800': '#ae5e00', 'lp-pri-rainbow-orange-900': '#985200', 'lp-pri-rainbow-orange-1000': '#824500', 'lp-pri-rainbow-orange-1100': '#6d3900', 'lp-pri-rainbow-orange-1200': '#542f0e', 'lp-pri-rainbow-orange-1300': '#3e240f', 'lp-pri-rainbow-orange-1400': '#2b1a0c', 'lp-pri-rainbow-yellow-100': '#fff8d9', 'lp-pri-rainbow-yellow-200': '#fff2bc', 'lp-pri-rainbow-yellow-300': '#ffe88d', 'lp-pri-rainbow-yellow-400': '#ffd739', 'lp-pri-rainbow-yellow-500': '#ffcc00', 'lp-pri-rainbow-yellow-600': '#cca400', 'lp-pri-rainbow-yellow-700': '#b69000', 'lp-pri-rainbow-yellow-800': '#a47a00', 'lp-pri-rainbow-yellow-900': '#926500', 'lp-pri-rainbow-yellow-1000': '#785500', 'lp-pri-rainbow-yellow-1100': '#5e4700', 'lp-pri-rainbow-yellow-1200': '#463800', 'lp-pri-rainbow-yellow-1300': '#352b00', 'lp-pri-rainbow-yellow-1400': '#231e0c', 'lp-pri-rainbow-lime-green-100': '#f5ffda', 'lp-pri-rainbow-lime-green-200': '#eaffb6', 'lp-pri-rainbow-lime-green-300': '#c9ff31', 'lp-pri-rainbow-lime-green-400': '#b3e900', 'lp-pri-rainbow-lime-green-500': '#a0d200', 'lp-pri-rainbow-lime-green-600': '#8ebc00', 'lp-pri-rainbow-lime-green-700': '#7ea600', 'lp-pri-rainbow-lime-green-800': '#6d9000', 'lp-pri-rainbow-lime-green-900': '#5d7b00', 'lp-pri-rainbow-lime-green-1000': '#4d6700', 'lp-pri-rainbow-lime-green-1100': '#394d00', 'lp-pri-rainbow-lime-green-1200': '#2f4000', 'lp-pri-rainbow-lime-green-1300': '#233100', 'lp-pri-rainbow-lime-green-1400': '#1a220c', 'lp-pri-rainbow-green-100': '#eaf9ea', 'lp-pri-rainbow-green-200': '#c6f3c8', 'lp-pri-rainbow-green-300': '#94e798', 'lp-pri-rainbow-green-400': '#55d964', 'lp-pri-rainbow-green-500': '#4dc45b', 'lp-pri-rainbow-green-600': '#44b151', 'lp-pri-rainbow-green-700': '#3c9d47', 'lp-pri-rainbow-green-800': '#348b3e', 'lp-pri-rainbow-green-900': '#2c7835', 'lp-pri-rainbow-green-1000': '#24672c', 'lp-pri-rainbow-green-1100': '#1d5523', 'lp-pri-rainbow-green-1200': '#1e4320', 'lp-pri-rainbow-green-1300': '#18321a', 'lp-pri-rainbow-green-1400': '#122313', 'lp-pri-rainbow-mint-100': '#e1fbfa', 'lp-pri-rainbow-mint-200': '#bcf1f0', 'lp-pri-rainbow-mint-300': '#7fe3e2', 'lp-pri-rainbow-mint-400': '#00d4d4', 'lp-pri-rainbow-mint-500': '#00c0c1', 'lp-pri-rainbow-mint-600': '#00acac', 'lp-pri-rainbow-mint-700': '#009a9a', 'lp-pri-rainbow-mint-800': '#008787', 'lp-pri-rainbow-mint-900': '#007676', 'lp-pri-rainbow-mint-1000': '#006464', 'lp-pri-rainbow-mint-1100': '#005353', 'lp-pri-rainbow-mint-1200': '#124242', 'lp-pri-rainbow-mint-1300': '#113131', 'lp-pri-rainbow-mint-1400': '#0e2222', 'lp-pri-rainbow-cyan-100': '#eaf6ff', 'lp-pri-rainbow-cyan-200': '#cde9ff', 'lp-pri-rainbow-cyan-300': '#a0d6ff', 'lp-pri-rainbow-cyan-400': '#70c2ff', 'lp-pri-rainbow-cyan-500': '#39b1ff', 'lp-pri-rainbow-cyan-600': '#00a0f0', 'lp-pri-rainbow-cyan-700': '#008ed7', 'lp-pri-rainbow-cyan-800': '#007dbe', 'lp-pri-rainbow-cyan-900': '#006ca6', 'lp-pri-rainbow-cyan-1000': '#005c8e', 'lp-pri-rainbow-cyan-1100': '#094771', 'lp-pri-rainbow-cyan-1200': '#042941', 'lp-pri-rainbow-cyan-1300': '#102e43', 'lp-pri-rainbow-cyan-1400': '#0d202f', 'lp-pri-rainbow-purple-100': '#faf1ff', 'lp-pri-rainbow-purple-200': '#f2dcff', 'lp-pri-rainbow-purple-300': '#e7bcff', 'lp-pri-rainbow-purple-400': '#db9bff', 'lp-pri-rainbow-purple-500': '#d17dff', 'lp-pri-rainbow-purple-600': '#c85aff', 'lp-pri-rainbow-purple-700': '#bf26ff', 'lp-pri-rainbow-purple-800': '#ac00e9', 'lp-pri-rainbow-purple-900': '#9600cb', 'lp-pri-rainbow-purple-1000': '#8000af', 'lp-pri-rainbow-purple-1100': '#6b0093', 'lp-pri-rainbow-purple-1200': '#53156e', 'lp-pri-rainbow-purple-1300': '#3d1551', 'lp-pri-rainbow-purple-1400': '#2b1138', 'lp-pri-rainbow-pink-100': '#ffeff2', 'lp-pri-rainbow-pink-200': '#ffd9df', 'lp-pri-rainbow-pink-300': '#ffb7c4', 'lp-pri-rainbow-pink-400': '#ff95aa', 'lp-pri-rainbow-pink-500': '#ff7394', 'lp-pri-rainbow-pink-600': '#ff457d', 'lp-pri-rainbow-pink-700': '#f4006a', 'lp-pri-rainbow-pink-800': '#d8005d', 'lp-pri-rainbow-pink-900': '#bd0051', 'lp-pri-rainbow-pink-1000': '#a20043', 'lp-pri-rainbow-pink-1100': '#880037', 'lp-pri-rainbow-pink-1200': '#68142e', 'lp-pri-rainbow-pink-1300': '#4d1323', 'lp-pri-rainbow-pink-1400': '#361019', }; /** * 중립 alpha 원시색 seed. alpha 값은 seed × `alphas` 스텝으로 생성한다 * (Figma가 내보낸 rgba 문자열을 하드코딩하지 않음). */ export type AlphaSeedKey = 'lp-pri-alpha-white' | 'lp-pri-alpha-black' | 'lp-pri-alpha-gray'; const alphaSeeds: { name: AlphaSeedKey; value: string }[] = [ { name: 'lp-pri-alpha-white', value: '#ffffff' }, { name: 'lp-pri-alpha-black', value: '#000000' }, { name: 'lp-pri-alpha-gray', value: '#949497' }, ]; export type PrimitiveKey = | keyof typeof primitiveBase | AlphasKey | BrandOriginalKey | BrandAlphaKey | BrandAccentKey; /** * 시맨틱 토큰 맵. 값은 `[light, dark]` 튜플(primitive 키 참조). * * 정본 = color-variables.json의 `system` 블록. **시맨틱 이름은 리포 기존 이름을 유지**하고 * (예: `positive-strong`, `link`, `accent-label-yellow`, `label-neutral-base`), 내부 참조 값만 * SSOT에 맞춰 교체한다. * SSOT가 다른 이름(status-/utility-/label-accent-/label- 계열)을 쓰는 25개 토큰은 이름을 * 유지하며 값만 매칭했다. SSOT에서 빠진 리포 전용 6개(caution, surface-neutral-high 계열, * brandinverse-fill-static-low 계열)는 이름을 유지하되 참조를 가장 가까운 새 primitive로 * remap했다. SSOT 신규 4개(disabled 계열)는 추가했다. */ const system = { 'surface-neutral-lowest': ['lp-pri-achromatic-white', 'lp-pri-gray-cool-1400'], 'surface-neutral-lowest-hover': ['lp-pri-gray-cool-100', 'lp-pri-gray-cool-1200'], 'surface-neutral-low': ['lp-pri-gray-cool-100', 'lp-pri-gray-cool-1300'], // SSOT 재동기화 (dark 1200→1300) 'surface-neutral-low-hover': ['lp-pri-gray-cool-200', 'lp-pri-gray-cool-1100'], 'surface-neutral-mid': ['lp-pri-gray-cool-200', 'lp-pri-gray-cool-1100'], 'surface-neutral-mid-hover': ['lp-pri-gray-cool-300', 'lp-pri-gray-cool-1200'], 'surface-neutral-high': ['lp-pri-gray-cool-300', 'lp-pri-gray-cool-1200'], // not in JSON SSOT — kept, refs remapped to nearest primitive 'surface-neutral-high-hover': ['lp-pri-gray-cool-400', 'lp-pri-gray-cool-1100'], // not in JSON SSOT — kept, refs remapped to nearest primitive 'surface-neutral-highest': ['lp-pri-gray-cool-300', 'lp-pri-gray-cool-1100'], // not in JSON SSOT — kept, refs remapped to nearest primitive 'surface-neutral-static-lowest': ['lp-pri-achromatic-white', 'lp-pri-achromatic-white'], 'surface-neutral-static-lowest-hover': ['lp-pri-gray-cool-100', 'lp-pri-gray-cool-100'], 'surface-neutral-variation-lowest': ['lp-pri-achromatic-white', 'lp-pri-gray-cool-1200'], 'control-fill-neutral-lowest': ['lp-pri-alpha-gray-0', 'lp-pri-alpha-gray-0'], 'control-fill-neutral-lowest-hover': ['lp-pri-gray-cool-100', 'lp-pri-gray-cool-1300'], 'control-fill-neutral-low': ['lp-pri-gray-cool-100', 'lp-pri-gray-cool-1400'], 'control-fill-neutral-low-hover': ['lp-pri-gray-cool-200', 'lp-pri-gray-cool-1300'], 'control-fill-neutral-mid': ['lp-pri-gray-cool-200', 'lp-pri-gray-cool-1300'], // SSOT 재동기화 (light 100→200) 'control-fill-neutral-mid-hover': ['lp-pri-gray-cool-300', 'lp-pri-gray-cool-1200'], // SSOT 재동기화 (light 200→300) 'control-fill-neutral-high': ['lp-pri-gray-cool-300', 'lp-pri-gray-cool-1200'], 'control-fill-neutral-high-hover': ['lp-pri-gray-cool-400', 'lp-pri-gray-cool-1100'], 'control-fill-neutral-highest': ['lp-pri-gray-cool-700', 'lp-pri-gray-cool-1200'], 'label-neutral-base': ['lp-pri-gray-cool-1400', 'lp-pri-achromatic-white'], // repo name kept; value from JSON 'label-base' 'label-neutral-secondary': ['lp-pri-gray-cool-800', 'lp-pri-gray-cool-600'], // repo name kept; value from JSON 'label-secondary' 'label-neutral-tertiary': ['lp-pri-gray-cool-500', 'lp-pri-gray-cool-1000'], // repo name kept; value from JSON 'label-tertiary' 'label-neutral-quaternary': ['lp-pri-gray-cool-400', 'lp-pri-gray-cool-1100'], // repo name kept; value from JSON 'label-quaternary' 'label-neutral-static': ['lp-pri-gray-cool-1400', 'lp-pri-gray-cool-1400'], 'label-neutral-static-secondary': ['lp-pri-gray-cool-800', 'lp-pri-gray-cool-800'], 'border-neutral-alpha-strong': ['lp-pri-alpha-gray-48', 'lp-pri-alpha-gray-48'], 'border-neutral-alpha-normal': ['lp-pri-alpha-gray-24', 'lp-pri-alpha-gray-24'], 'border-neutral-alpha-subtle': ['lp-pri-alpha-gray-12', 'lp-pri-alpha-gray-12'], 'border-neutral-alpha-hint': ['lp-pri-alpha-gray-12', 'lp-pri-alpha-gray-12'], 'border-neutral-strong': ['lp-pri-gray-cool-1400', 'lp-pri-achromatic-white'], 'border-neutral-normal': ['lp-pri-gray-cool-600', 'lp-pri-gray-cool-900'], 'border-neutral-subtle': ['lp-pri-gray-cool-300', 'lp-pri-gray-cool-1100'], // PRI-568 QA (light 400→300) 'surface-inverse-lowest': ['lp-pri-gray-cool-1400', 'lp-pri-achromatic-white'], 'surface-inverse-lowest-hover': ['lp-pri-gray-cool-1200', 'lp-pri-gray-cool-100'], 'surface-inverse-low': ['lp-pri-gray-cool-1200', 'lp-pri-gray-cool-100'], 'surface-inverse-low-hover': ['lp-pri-gray-cool-1100', 'lp-pri-gray-cool-200'], 'surface-inverse-mid': ['lp-pri-gray-cool-1100', 'lp-pri-gray-cool-200'], 'surface-inverse-mid-hover': ['lp-pri-gray-cool-1200', 'lp-pri-gray-cool-300'], 'surface-inverse-high': ['lp-pri-gray-cool-1100', 'lp-pri-gray-cool-300'], 'surface-inverse-high-hover': ['lp-pri-gray-cool-1000', 'lp-pri-gray-cool-400'], 'surface-inverse-static-high': ['lp-pri-gray-cool-1200', 'lp-pri-gray-cool-1200'], // SSOT 재동기화 (light 1100→1200, dark 200→1200; 핸드오프의 dark 1100 정정) 'surface-inverse-static-high-hover': ['lp-pri-gray-cool-1300', 'lp-pri-gray-cool-1100'], // PRI-568 QA (hover 확정) 'surface-inverse-highest': ['lp-pri-gray-cool-1000', 'lp-pri-gray-cool-500'], 'label-on-inverse-base': ['lp-pri-achromatic-white', 'lp-pri-gray-cool-1400'], 'label-on-inverse-secondary': ['lp-pri-gray-cool-600', 'lp-pri-gray-cool-800'], 'label-on-inverse-tertiary': ['lp-pri-gray-cool-1000', 'lp-pri-gray-cool-500'], 'label-on-inverse-quaternary': ['lp-pri-gray-cool-1100', 'lp-pri-gray-cool-400'], 'label-on-inverse-static-base': ['lp-pri-achromatic-white', 'lp-pri-achromatic-white'], 'label-on-inverse-static-secondary': ['lp-pri-gray-cool-600', 'lp-pri-gray-cool-600'], 'border-on-inverse-alpha-strong': ['lp-pri-alpha-gray-64', 'lp-pri-alpha-gray-64'], 'border-on-inverse-alpha-normal': ['lp-pri-alpha-gray-32', 'lp-pri-alpha-gray-32'], 'border-on-inverse-alpha-subtle': ['lp-pri-alpha-gray-24', 'lp-pri-alpha-gray-24'], 'border-on-inverse-alpha-hint': ['lp-pri-alpha-gray-12', 'lp-pri-alpha-gray-12'], 'border-on-inverse-strong': ['lp-pri-achromatic-white', 'lp-pri-gray-cool-1400'], 'border-on-inverse-normal': ['lp-pri-gray-cool-900', 'lp-pri-gray-cool-600'], 'border-on-inverse-subtle': ['lp-pri-gray-cool-1100', 'lp-pri-gray-cool-400'], 'control-fill-brand': ['lp-pri-brand-original-900', 'lp-pri-brand-original-800'], // SSOT 재동기화 (dark 700→800) 'control-fill-brand-hover': ['lp-pri-brand-original-1000', 'lp-pri-brand-original-600'], 'control-fill-brand-strong': ['lp-pri-brand-original-1000', 'lp-pri-brand-original-500'], // SSOT 재동기화 (500·100→1000·500) 'control-fill-brand-strongest': ['lp-pri-brand-original-1300', 'lp-pri-brand-original-300'], // NEW — 브랜드 최강 컨트롤 필 (기존 control-fill 악센트 베이스 대체) 'control-fill-brand-faint': ['lp-pri-brand-original-100', 'lp-pri-brand-original-1300'], // SSOT 재동기화 (dark 1200→1300) 'control-fill-brand-faint-hover': ['lp-pri-brand-original-200', 'lp-pri-brand-original-1300'], 'label-brand-base': ['lp-pri-brand-original-800', 'lp-pri-brand-original-700'], // PRI-568 QA (900·600→800·700) — 1.6.0의 light accent-1300 전환은 롤백 'label-brand-secondary': ['lp-pri-brand-original-900', 'lp-pri-brand-original-800'], // PRI-568 QA (병합 확정) 'label-brand-strongest': ['lp-pri-brand-original-1300', 'lp-pri-brand-original-300'], // NEW — control-fill-brand-strongest와 동일 단계, label 계열 최강 강조용 'border-brand-subtle': ['lp-pri-brand-original-300', 'lp-pri-brand-original-1000'], // NEW — 브랜드 옅은 보더 (SSOT: dark 1000, 핸드오프의 100 정정) 'border-brand-normal': ['lp-pri-brand-original-800', 'lp-pri-brand-original-800'], // PRI-568 QA (alpha→solid original) 'border-brand-strong': ['lp-pri-brand-original-1100', 'lp-pri-brand-original-600'], // PRI-568 QA (light 800→1100, SSOT 정정) 'label-on-brand': ['lp-pri-achromatic-white', 'lp-pri-achromatic-white'], 'brandinverse-fill-static-low': ['lp-pri-brand-original-1200', 'lp-pri-brand-original-1200'], // not in JSON SSOT — kept, refs remapped to nearest primitive 'brandinverse-fill-static-low-hover': [ 'lp-pri-brand-original-1100', 'lp-pri-brand-original-1100', ], // not in JSON SSOT — kept, refs remapped to nearest primitive 'accent-label-base': ['lp-pri-brand-accent-1300', 'lp-pri-rainbow-orange-100'], // repo name kept; JSON 'label-accent-base' SSOT 재동기화 (accent-300·900→accent-1300·rainbow-orange-100) 'accent-label-yellow': ['lp-pri-rainbow-yellow-500', 'lp-pri-rainbow-yellow-400'], // repo name kept; value from JSON 'label-accent-yellow' 'accent-label-mint': ['lp-pri-rainbow-mint-600', 'lp-pri-rainbow-mint-500'], // repo name kept; value from JSON 'label-accent-mint' 'accent-label-cyan': ['lp-pri-rainbow-cyan-600', 'lp-pri-rainbow-cyan-500'], // repo name kept; value from JSON 'label-accent-cyan' 'accent-label-purple': ['lp-pri-rainbow-purple-800', 'lp-pri-rainbow-purple-500'], // repo name kept; value from JSON 'label-accent-purple' 'accent-label-pink': ['lp-pri-rainbow-pink-600', 'lp-pri-rainbow-pink-500'], // repo name kept; value from JSON 'label-accent-pink' 'accent-control-fill-base': ['lp-pri-brand-accent-100', 'lp-pri-brand-accent-900'], // repo name kept; JSON 'control-fill-accent-base' SSOT 재동기화 (rainbow-yellow-800·1000→accent-100·900) 'positive-strong': ['lp-pri-rainbow-green-500', 'lp-pri-rainbow-green-600'], // repo name kept; PRI-568 QA (light 700→500) 'negative-strong': ['lp-pri-rainbow-red-700', 'lp-pri-rainbow-red-700'], // repo name kept; PRI-568 QA (light 800→700) 'negative-strong-hover': ['lp-pri-rainbow-red-800', 'lp-pri-rainbow-red-600'], // repo name kept; PRI-568 QA (light 900→800) caution: ['lp-pri-rainbow-orange-500', 'lp-pri-rainbow-orange-400'], // not in JSON SSOT — kept, refs remapped to nearest primitive 'caution-strong': ['lp-pri-rainbow-orange-500', 'lp-pri-rainbow-orange-500'], // repo name kept; PRI-568 QA (dark 400→500) 'caution-base': ['lp-pri-rainbow-orange-700', 'lp-pri-rainbow-orange-500'], // repo name kept; PRI-568 QA (light 800→700) 'caution-faint': ['lp-pri-rainbow-orange-100', 'lp-pri-rainbow-orange-1200'], // repo name kept; PRI-568 QA (dark 1100→1200) highlight: ['lp-pri-rainbow-lime-green-100', 'lp-pri-rainbow-lime-green-1200'], // repo name kept; SSOT 재동기화 (200·1100→100·1200) 'control-fill-selected': ['lp-pri-alpha-black-8', 'lp-pri-alpha-white-12'], 'control-fill-drag': ['lp-pri-alpha-black-12', 'lp-pri-alpha-white-16'], 'positive-faint': ['lp-pri-rainbow-green-100', 'lp-pri-rainbow-green-1200'], // repo name kept; PRI-568 QA (dark 1100→1200) 'negative-faint': ['lp-pri-rainbow-red-100', 'lp-pri-rainbow-red-1200'], // repo name kept; PRI-568 QA (dark 1300→1200) 'positive-base': ['lp-pri-rainbow-green-800', 'lp-pri-rainbow-green-600'], // repo name kept; PRI-568 QA (dark 500→600) 'negative-base': ['lp-pri-rainbow-red-800', 'lp-pri-rainbow-red-800'], // repo name kept; PRI-568 QA (light 600→800) link: ['lp-pri-rainbow-cyan-800', 'lp-pri-rainbow-cyan-500'], // repo name kept; value from JSON 'utility-link' 'overlay-dim': ['lp-pri-alpha-black-48', 'lp-pri-alpha-black-48'], 'background-default': ['lp-pri-achromatic-white', 'lp-pri-gray-cool-1400'], 'background-subtle': ['lp-pri-gray-cool-100', 'lp-pri-gray-cool-1300'], 'control-fill-neutral-opaque-lowest': ['lp-pri-achromatic-white', 'lp-pri-gray-cool-1400'], 'control-fill-neutral-opaque-lowest-hover': ['lp-pri-gray-cool-100', 'lp-pri-gray-cool-1200'], 'control-fill-neutral-opaque-low': ['lp-pri-gray-cool-100', 'lp-pri-gray-cool-1200'], 'control-fill-neutral-opaque-low-hover': ['lp-pri-gray-cool-200', 'lp-pri-gray-cool-1100'], 'control-fill-neutral-opaque-static-lowest': [ 'lp-pri-achromatic-white', 'lp-pri-achromatic-white', ], 'control-fill-neutral-lowest-pressed': ['lp-pri-gray-cool-200', 'lp-pri-gray-cool-1200'], 'control-fill-neutral-low-pressed': ['lp-pri-gray-cool-300', 'lp-pri-gray-cool-1200'], 'control-fill-neutral-mid-pressed': ['lp-pri-gray-cool-400', 'lp-pri-gray-cool-1100'], // SSOT 재동기화 (light 300→400) 'control-fill-neutral-high-pressed': ['lp-pri-gray-cool-500', 'lp-pri-gray-cool-1000'], 'control-fill-brand-pressed': ['lp-pri-brand-original-1100', 'lp-pri-brand-original-500'], 'control-fill-brand-faint-pressed': ['lp-pri-brand-original-300', 'lp-pri-brand-original-1400'], 'surface-neutral-lowest-pressed': ['lp-pri-gray-cool-100', 'lp-pri-gray-cool-1200'], 'surface-neutral-low-pressed': ['lp-pri-gray-cool-300', 'lp-pri-gray-cool-1100'], 'surface-neutral-mid-pressed': ['lp-pri-gray-cool-400', 'lp-pri-gray-cool-1300'], 'surface-neutral-static-lowest-pressed': ['lp-pri-gray-cool-100', 'lp-pri-gray-cool-100'], 'surface-inverse-lowest-pressed': ['lp-pri-gray-cool-1200', 'lp-pri-gray-cool-100'], 'surface-inverse-low-pressed': ['lp-pri-gray-cool-1100', 'lp-pri-gray-cool-300'], 'surface-inverse-mid-pressed': ['lp-pri-gray-cool-1300', 'lp-pri-gray-cool-400'], 'surface-inverse-high-pressed': ['lp-pri-gray-cool-1000', 'lp-pri-gray-cool-500'], 'negative-strong-pressed': ['lp-pri-rainbow-red-900', 'lp-pri-rainbow-red-500'], // repo name kept; PRI-568 QA (light 1000→900) focus: ['lp-pri-rainbow-cyan-600', 'lp-pri-rainbow-cyan-600'], // repo name kept; value from JSON 'utility-focus' disabled: ['lp-pri-alpha-gray-24', 'lp-pri-alpha-gray-24'], // NEW from JSON SSOT 'label-disabled': ['lp-pri-gray-cool-500', 'lp-pri-gray-cool-1000'], // NEW from JSON SSOT 'control-fill-disabled': ['lp-pri-gray-cool-200', 'lp-pri-gray-cool-1300'], // NEW from JSON SSOT 'surface-disabled': ['lp-pri-alpha-gray-6', 'lp-pri-alpha-gray-8'], // NEW from JSON SSOT 'border-disabled': ['lp-pri-gray-cool-400', 'lp-pri-gray-cool-1100'], // NEW from JSON SSOT } satisfies Record; export type SystemKeys = keyof typeof system; export const color: { primitive: typeof primitiveBase & Partial>; system: { dark: Partial>; light: Partial>; }; } = { primitive: primitiveBase, system: { dark: {}, light: {}, }, }; const generateAlpha = () => { alphaSeeds.forEach(({ name, value }) => { alphas.forEach((alpha) => { color.primitive[`${name}-${alpha}` as AlphasKey] = hexToRgba(value.slice(1), alpha / 100); }); }); }; generateAlpha(); color.system.light = mapValues(system, ([light]) => light); color.system.dark = mapValues(system, ([, dark]) => dark);