@import "tailwindcss"; /* 색상 토큰 출처: edupay-app lib/ui/core/tokens/app_colors.dart (Figma: FOX PAY 1차 제작시안, node 91:10205). 다크 값은 edupay-app에 대응 다크 시안이 없어 "임의 도출 — 정식 다크 시안 확정 시 교체". 메커니즘: `color-scheme` + `light-dark()`(Chrome 123+/Safari 17.5+/Firefox 120+ 지원, 미지원 브라우저는 값이 무효화되므로 사내 어드민 한정 트레이드오프로 채택 — design 계획 §4.1/§5.3, 2026-07-28 게이트 승인). 각 시맨틱 토큰이 `light-dark(라이트값, 다크값)`으로 라이트/다크 값을 한 선언에 함께 보유해 드리프트를 구조적으로 차단한다. 수동 전환은 아래 `:root[data-theme]`가 `color-scheme`만 덮어써 처리하므로 값 자체는 이 블록 한 곳에만 존재한다 (Next.js 16 번들 문서 preventing-flash-before-hydration.md §Themes 패턴). */ :root { color-scheme: light dark; /* Brand */ --primary: light-dark(#502ef5, #877aec); --primary-container: light-dark(#6d5ce7, #502ef5); --on-primary: light-dark(#ffffff, #ffffff); --on-primary-container: light-dark(#e2e0fb, #e2e0fb); --secondary: light-dark(#877aec, #9b92ff); /* Surface / background (원 토큰: surface / gray0) */ --background: light-dark(#ffffff, #14161b); --surface: light-dark(#ffffff, #1e2128); --surface-muted: light-dark(#f5f7fa, #2c3038); /* Foreground / text (원 토큰: onSurface 계열) */ --foreground: light-dark(#2c3038, #f5f7fa); --foreground-muted: light-dark(#565d6b, #bbc4d8); --foreground-subtle: light-dark(#6b7486, #8790a3); /* Border (원 토큰: outline 계열) */ --border: light-dark(#dae0ed, #424752); --border-subtle: light-dark(#e1e6f1, #343943); /* Status */ --danger: light-dark(#ec2e2f, #ff5c5d); --success: light-dark(#21b770, #3acb93); --warning: light-dark(#ffb020, #ffc24d); /* Overlay */ --scrim: light-dark(rgb(0 0 0 / 0.6), rgb(0 0 0 / 0.7)); } /* 수동 테마 선택 — 가 `color-scheme`만 덮어써 위 light-dark() 값이 해당 분기로 고정된다(값 자체는 여기서 재정의하지 않음). data-theme 속성이 없거나 "system"이면 :root의 `color-scheme: light dark`가 유지되어 OS `prefers-color-scheme`를 그대로 따른다(feature 전달 사양). */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } @theme inline { --color-primary: var(--primary); --color-primary-container: var(--primary-container); --color-on-primary: var(--on-primary); --color-on-primary-container: var(--on-primary-container); --color-secondary: var(--secondary); --color-background: var(--background); --color-surface: var(--surface); --color-surface-muted: var(--surface-muted); --color-foreground: var(--foreground); --color-foreground-muted: var(--foreground-muted); --color-foreground-subtle: var(--foreground-subtle); --color-border: var(--border); --color-border-subtle: var(--border-subtle); --color-danger: var(--danger); --color-success: var(--success); --color-warning: var(--warning); --color-scrim: var(--scrim); /* WantedSans 연결 전에도 안전한 폴백(feature 레인이 app/layout.tsx에서 next/font/local로 --font-wanted-sans를 정의). */ --font-sans: var(--font-wanted-sans, system-ui), system-ui, "Apple SD Gothic Neo", sans-serif; --font-mono: var(--font-geist-mono); /* 타이포 토큰 출처: edupay-app lib/ui/core/tokens/app_typography.dart (Figma: FOX PAY 1차 제작시안, node 112:11439). voucher/numeric 등 앱 전용 스타일은 어드민 무관으로 미이식. */ --text-display-lg: 3rem; --text-display-lg--line-height: 1.5; --text-display-lg--font-weight: 700; --text-display-md: 2.25rem; --text-display-md--line-height: 1.5; --text-display-md--letter-spacing: -0.72px; --text-display-md--font-weight: 700; --text-display-sm: 2rem; --text-display-sm--line-height: 1.5; --text-display-sm--letter-spacing: -0.64px; --text-display-sm--font-weight: 700; --text-headline-lg: 1.5rem; --text-headline-lg--line-height: 1.5; --text-headline-lg--letter-spacing: -0.72px; --text-headline-lg--font-weight: 700; --text-headline-md: 1.25rem; --text-headline-md--line-height: 1.5; --text-headline-md--letter-spacing: -0.6px; --text-headline-md--font-weight: 700; --text-headline-sm: 1.125rem; --text-headline-sm--line-height: 1.3; --text-headline-sm--letter-spacing: -0.54px; --text-headline-sm--font-weight: 700; --text-title-lg: 1.125rem; --text-title-lg--line-height: 1.5; --text-title-lg--font-weight: 700; --text-title-md: 1rem; --text-title-md--line-height: 1.5; --text-title-md--font-weight: 700; --text-title-sm: 0.875rem; --text-title-sm--line-height: 1.5; --text-title-sm--letter-spacing: -0.42px; --text-title-sm--font-weight: 700; --text-body-lg: 1rem; --text-body-lg--line-height: 1.5; --text-body-lg--letter-spacing: -0.48px; --text-body-lg--font-weight: 400; --text-body-md: 0.875rem; --text-body-md--line-height: 1.5; --text-body-md--font-weight: 400; --text-body-sm: 0.75rem; --text-body-sm--line-height: 1.5; --text-body-sm--font-weight: 400; --text-label-lg: 1rem; --text-label-lg--line-height: 1.4; --text-label-lg--letter-spacing: -0.48px; --text-label-lg--font-weight: 700; --text-label-md: 0.875rem; --text-label-md--letter-spacing: -0.28px; --text-label-md--font-weight: 400; --text-label-sm: 0.75rem; --text-label-sm--font-weight: 400; /* radius 토큰 출처: edupay-app lib/ui/core/tokens/app_radius.dart. Tailwind 기본 스케일과 다른 값으로 의도적 재정의(앱 일체화, §8-4 승인). pill(999)은 기본 rounded-full로 충족, card(50)은 앱 전용 미이식. */ --radius-xs: 0.25rem; --radius-sm: 0.5rem; --radius-md: 0.75rem; --radius-lg: 1rem; --radius-xl: 1.25rem; --radius-2xl: 1.5rem; /* 그림자 토큰 출처: edupay-app lib/ui/core/tokens/app_shadows.dart — 어드민 유효분만 이식(voucher inner·stacked 등 미이식). */ --shadow-card: 0 5.16px 5.16px rgb(93 100 119 / 0.12); --shadow-list-card: 0 8px 16px rgb(93 100 119 / 0.12); --shadow-dialog: 0 8px 16px rgb(0 0 0 / 0.1); --shadow-popup: 2.16px 6.32px 6px rgb(177 178 180 / 0.24); --shadow-toast: 0 10px 12px rgb(0 0 0 / 0.2); --shadow-subtle: 0 2px 4px rgb(0 0 0 / 0.08); /* 애니메이션 토큰(신규 네임스페이스 — §4.2 승인). 오버레이·다이얼로그·토스트· 스플래시 전환에 사용. --ease-*는 Tailwind 기본값 사용, duration은 값에 내장(트랜지션 duration 표준은 bare 유틸 duration-200 사용). */ --animate-fade-in: fade-in 200ms var(--ease-out); --animate-fade-out: fade-out 200ms var(--ease-in); --animate-dialog-in: dialog-in 200ms var(--ease-out); --animate-toast-in: toast-in 300ms var(--ease-out); } @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } } /* 스플래시 등 풀스크린 오버레이 퇴장용 — fade-in의 역방향 키프레임. */ @keyframes fade-out { from { opacity: 1; } to { opacity: 0; } } @keyframes dialog-in { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } @keyframes toast-in { from { opacity: 0; transform: translateY(0.5rem); } to { opacity: 1; transform: translateY(0); } } /* 레이아웃 전환(View Transitions API, feature 레인 A안) — feature가 전환 루트 요소에 .layout-transition 클래스를 부여하면 view-transition-class로 매핑되어 아래 ::view-transition-old/new 규칙이 부드러운 크로스페이드를 적용한다. (CSS View Transitions Level 2, view-transition-class 프로퍼티 사용) */ .layout-transition { view-transition-class: layout-transition; } ::view-transition-old(.layout-transition) { animation: var(--animate-fade-out); } ::view-transition-new(.layout-transition) { animation: var(--animate-fade-in); } @media (prefers-reduced-motion: reduce) { ::view-transition-group(.layout-transition), ::view-transition-old(.layout-transition), ::view-transition-new(.layout-transition) { animation: none; } } /* 간격 토큰 매핑 (변경 없음) — edupay-app lib/ui/core/tokens/app_spacing.dart의 4/8 grid(4·8·12·16·20·24·32·40)는 Tailwind 기본 --spacing: 0.25rem 스케일과 정확히 일치한다: xs→p-1, sm→p-2, md→p-3, lg→p-4, xl→p-5, xxl→p-6, xxxl→p-8, xxxxl→p-10. */ body { background: var(--background); color: var(--foreground); }