feat: complete release preparation, 10+ ad mediation, CI/CD, and docker deployment
Some checks failed
CI Pipeline / Code Quality & Typecheck (push) Waiting to run
CI Pipeline / Test Suite (macos-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (ubuntu-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (windows-latest) (push) Blocked by required conditions
CI Pipeline / Build Validation (admin) (push) Blocked by required conditions
CI Pipeline / Build Validation (desktop) (push) Blocked by required conditions
Deploy Landing Page / deploy (push) Blocked by required conditions
Deploy Landing Page / build (push) Waiting to run
Release & Packaging Pipeline / Build & Publish Admin Docker Image (push) Failing after 8s
Release & Code Signing CA Pipeline / build-and-sign-windows (push) Failing after 1m51s
Build macOS / Build & Package (macOS) (push) Failing after 4s
Build macOS / Build & Package (macOS)-1 (push) Failing after 5s
Release & Code Signing CA Pipeline / build-and-sign-macos (push) Failing after 3s
Release & Packaging Pipeline / Package macOS Desktop App (push) Failing after 4s
Release & Packaging Pipeline / Package Windows Desktop App (push) Failing after 2m28s
Release & Packaging Pipeline / Publish Official GitHub Release (push) Has been skipped

This commit is contained in:
Yun Chan 2026-08-20 11:12:05 +09:00
parent 5cd1de6859
commit 708e20f747
406 changed files with 42464 additions and 6199 deletions

View file

@ -1,114 +1,204 @@
// apps/admin/src/lib/console-theme.ts
// D3RO Console 디자인 토큰 — 터미널/콘솔 스타일
// D3RO Voice Admin CRM — "Midnight Glass v2" Design Tokens & UI Helpers
// Fully aligned with @d3ro/ui/theme SSOT & High-End Awwwards/Linear aesthetic
import { d3roFontSans, d3roFontMono } from '@d3ro/ui/theme'
export const C = {
// backgrounds
base: '#000000',
panel: '#09090b',
panelHover: '#121214',
base: '#070b16',
app: '#0a0e1c',
card: '#111a30',
cardHover: '#152039',
elevated: '#1a2540',
input: '#0d1526',
sidebar: '#0b101f',
inset: '#0a111f',
chassis: '#111a30',
// borders
border: '#1f1f22',
borderHl: '#27272a',
border: 'rgba(148, 180, 255, 0.08)',
borderHl: 'rgba(148, 180, 255, 0.16)',
borderStrong: 'rgba(148, 180, 255, 0.24)',
// text
dim: '#71717a',
text: '#a1a1aa',
bright: '#ffffff',
// accent
accent: '#ff5c28',
// semantic
green: '#22c55e',
green400: '#4ade80',
orange: '#f97316',
orange400: '#fb923c',
dim: '#67789e',
text: '#93a4c8',
bright: '#eef2fb',
muted: '#3c4763',
// accents & gradients
accent: '#3b82f6',
accentLight: '#60a5fa',
accentDark: '#1d4ed8',
cyan: '#06b6d4',
cyanLight: '#22d3ee',
purple: '#8b5cf6',
purple400: '#a78bfa',
green: '#10b981',
green400: '#34d399',
orange: '#f59e0b',
orange400: '#fbbf24',
red: '#ef4444',
red400: '#f87171',
blue: '#3b82f6',
blue400: '#60a5fa',
purple: '#a855f7',
purple400: '#c084fc',
} as const
export const FONT = '"JetBrains Mono", ui-monospace, monospace'
export const FONT_SANS = d3roFontSans
export const FONT_MONO = d3roFontMono
/** 공통 패널 스타일 */
/** High-End Double-Bezel Glass Panel Style */
export const panelSx = {
bgcolor: C.panel,
border: `1px solid ${C.border}`,
borderRadius: '16px',
position: 'relative' as const,
bgcolor: 'rgba(17, 26, 48, 0.65)',
backdropFilter: 'blur(24px)',
border: `1px solid ${C.border}`,
borderRadius: '20px',
overflow: 'hidden',
'&:hover': { borderColor: C.borderHl },
transition: 'border-color 0.2s',
boxShadow: '0 16px 40px rgba(3, 7, 18, 0.5), inset 0 1px 0 rgba(148, 180, 255, 0.08)',
transition: 'border-color 0.25s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.25s ease, transform 0.25s ease',
'&:hover': {
borderColor: C.borderHl,
boxShadow: '0 20px 48px rgba(3, 7, 18, 0.6), inset 0 1px 0 rgba(148, 180, 255, 0.15)',
},
}
/** 테이블 공통 스타일 */
/** Inner Glass Core Style (Double-Bezel nested architecture) */
export const innerCoreSx = {
position: 'relative' as const,
borderRadius: '14px',
bgcolor: 'rgba(13, 21, 38, 0.75)',
backdropFilter: 'blur(16px)',
border: `1px solid ${C.border}`,
p: 2.5,
boxShadow: 'inset 0 2px 6px rgba(3, 7, 18, 0.5)',
}
/** Interactive Table Style */
export const tableSx = {
width: '100%',
borderCollapse: 'collapse' as const,
fontFamily: FONT,
fontSize: '12px',
borderCollapse: 'separate' as const,
borderSpacing: '0 6px',
fontFamily: FONT_SANS,
fontSize: '13px',
'& th': {
px: 2,
pb: 1.5,
fontWeight: 400,
fontWeight: 600,
fontSize: '11px',
textTransform: 'uppercase' as const,
letterSpacing: '0.1em',
letterSpacing: '0.08em',
color: C.dim,
textAlign: 'left' as const,
borderBottom: `1px solid ${C.borderHl}`,
},
'& td': {
py: 1.5,
px: 2,
py: 1.75,
textAlign: 'left' as const,
color: C.text,
borderBottom: `1px solid ${C.border}50`,
bgcolor: 'rgba(17, 26, 48, 0.45)',
borderTop: `1px solid ${C.border}`,
borderBottom: `1px solid ${C.border}`,
transition: 'all 0.15s cubic-bezier(0.16, 1, 0.3, 1)',
'&:first-of-type': {
borderLeft: `1px solid ${C.border}`,
borderTopLeftRadius: '10px',
borderBottomLeftRadius: '10px',
},
'&:last-of-type': {
borderRight: `1px solid ${C.border}`,
borderTopRightRadius: '10px',
borderBottomRightRadius: '10px',
},
},
'& tr:hover td': {
bgcolor: `${C.borderHl}33`,
bgcolor: 'rgba(26, 38, 68, 0.75)',
borderColor: C.borderHl,
color: C.bright,
},
}
/** 필터 버튼 스타일 */
/** Filter Pill Button Style */
export const filterBtnSx = (active: boolean) => ({
px: 1.5,
py: 0.5,
borderRadius: '4px',
fontFamily: FONT,
fontSize: '10px',
fontWeight: 500,
letterSpacing: '0.1em',
textTransform: 'uppercase' as const,
px: 2,
py: 0.75,
borderRadius: '999px',
fontFamily: FONT_SANS,
fontSize: '11px',
fontWeight: 600,
letterSpacing: '0.04em',
textTransform: 'none' as const,
cursor: 'pointer',
border: `1px solid ${active ? C.borderHl : 'transparent'}`,
bgcolor: active ? C.borderHl : 'transparent',
color: active ? C.bright : C.text,
border: `1px solid ${active ? 'rgba(59, 130, 246, 0.4)' : C.border}`,
bgcolor: active ? 'rgba(59, 130, 246, 0.16)' : 'rgba(17, 26, 48, 0.5)',
color: active ? C.bright : C.dim,
boxShadow: active ? '0 0 16px rgba(59, 130, 246, 0.25)' : 'none',
backdropFilter: 'blur(12px)',
'&:hover': {
bgcolor: C.panelHover,
borderColor: C.border,
bgcolor: active ? 'rgba(59, 130, 246, 0.22)' : 'rgba(26, 38, 68, 0.8)',
borderColor: active ? C.accentLight : C.borderHl,
color: C.bright,
transform: 'translateY(-1px)',
},
transition: 'all 0.15s',
'&:active': {
transform: 'translateY(0) scale(0.98)',
},
transition: 'all 0.15s cubic-bezier(0.16, 1, 0.3, 1)',
})
/** 상태 뱃지 스타일 */
export function statusBadgeSx(variant: 'green' | 'red' | 'orange' | 'blue' | 'purple') {
/** Semantic Status Badge Style */
export function statusBadgeSx(variant: 'green' | 'red' | 'orange' | 'blue' | 'purple' | 'cyan') {
const colorMap = {
green: { bg: 'rgba(34, 197, 94, 0.1)', fg: C.green400, border: 'rgba(34, 197, 94, 0.2)' },
red: { bg: 'rgba(239, 68, 68, 0.1)', fg: C.red400, border: 'rgba(239, 68, 68, 0.2)' },
orange: { bg: 'rgba(249, 115, 22, 0.1)', fg: C.orange400, border: 'rgba(249, 115, 22, 0.2)' },
blue: { bg: 'rgba(59, 130, 246, 0.1)', fg: C.blue400, border: 'rgba(59, 130, 246, 0.2)' },
purple: { bg: 'rgba(168, 85, 247, 0.1)', fg: C.purple400, border: 'rgba(168, 85, 247, 0.2)' },
green: { bg: 'rgba(16, 185, 129, 0.12)', fg: C.green400, border: 'rgba(16, 185, 129, 0.3)', glow: '0 0 12px rgba(16, 185, 129, 0.2)' },
red: { bg: 'rgba(239, 68, 68, 0.12)', fg: C.red400, border: 'rgba(239, 68, 68, 0.3)', glow: '0 0 12px rgba(239, 68, 68, 0.2)' },
orange: { bg: 'rgba(245, 158, 11, 0.12)', fg: C.orange400, border: 'rgba(245, 158, 11, 0.3)', glow: '0 0 12px rgba(245, 158, 11, 0.2)' },
blue: { bg: 'rgba(59, 130, 246, 0.12)', fg: C.accentLight, border: 'rgba(59, 130, 246, 0.3)', glow: '0 0 12px rgba(59, 130, 246, 0.2)' },
purple: { bg: 'rgba(139, 92, 246, 0.12)', fg: C.purple400, border: 'rgba(139, 92, 246, 0.3)', glow: '0 0 12px rgba(139, 92, 246, 0.2)' },
cyan: { bg: 'rgba(6, 182, 212, 0.12)', fg: C.cyanLight, border: 'rgba(6, 182, 212, 0.3)', glow: '0 0 12px rgba(6, 182, 212, 0.2)' },
}
const c = colorMap[variant]
return {
display: 'inline-block',
px: 1,
py: 0.25,
borderRadius: '4px',
fontSize: '10px',
fontFamily: FONT,
fontWeight: 500,
letterSpacing: '0.05em',
display: 'inline-flex',
alignItems: 'center',
gap: 0.75,
px: 1.25,
py: 0.4,
borderRadius: '999px',
fontSize: '11px',
fontFamily: FONT_SANS,
fontWeight: 600,
letterSpacing: '0.04em',
bgcolor: c.bg,
color: c.fg,
border: `1px solid ${c.border}`,
boxShadow: c.glow,
backdropFilter: 'blur(8px)',
}
}
/** Primary Action Button Style with Gradient & Glow */
export const primaryButtonSx = {
background: 'linear-gradient(135deg, #1d4ed8 0%, #3b82f6 55%, #60a5fa 100%)',
color: '#ffffff',
fontFamily: FONT_SANS,
fontSize: '13px',
fontWeight: 600,
borderRadius: '10px',
px: 2.5,
py: 1,
boxShadow: '0 0 0 1px rgba(59,130,246,0.35), 0 8px 24px rgba(37,99,235,0.35)',
textTransform: 'none' as const,
transition: 'all 0.2s cubic-bezier(0.16, 1, 0.3, 1)',
'&:hover': {
filter: 'brightness(1.12)',
boxShadow: '0 0 0 1px rgba(96,165,250,0.5), 0 12px 32px rgba(59,130,246,0.5)',
transform: 'translateY(-1px)',
},
'&:active': {
transform: 'translateY(0) scale(0.98)',
},
}
// Backward compatibility alias for FONT
export const FONT = FONT_MONO