style(frontend): ABAP_OPENCODE 디자인 시스템으로 맞춤 + 화면 재구성

DESIGN_SYSTEM.md 의 Dark Workspace 토큰을 shadcn 토큰으로 이식(다크 기본, radius 8px,
success/warning/shadow-float), 시스템 산세리프, PwC 로고(LogoMark). 목록·새 대화·대화·
로그인 화면을 가운데 760px 열로 통일하고, 떠 있던 테마·로그아웃 상자는 상단 바로,
말풍선은 다크 토큰(AI 답변은 상자 없이), ABAP 흰 에디터 룩은 라이트 모드에서만.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-16 21:24:17 +09:00
co-authored by Claude Fable 5.1
parent 506fbf601d
commit 9c6b28782d
32 changed files with 490 additions and 353 deletions
+102 -61
View File
@@ -15,12 +15,14 @@
/* shadcn/ui 토큰 → Tailwind 색상·반경 매핑 */
@theme inline {
/* ABAP_OPENCODE DESIGN_SYSTEM.md 와 같은 시스템 산세리프. 메타 라벨(font-mono 클래스)도 같은 서체 —
그쪽 UI 가 10~11px 산세리프 메타를 쓰기 때문. 코드블럭은 CodeBlock 이 자체 monospace 지정. */
--font-sans:
"Geist Variable", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
Arial, "Noto Sans KR", sans-serif;
-apple-system, "Segoe UI", "Inter", Roboto, "Noto Sans KR", "Apple SD Gothic Neo", sans-serif;
--font-mono:
"Geist Variable", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
Arial, "Noto Sans KR", sans-serif;
-apple-system, "Segoe UI", "Inter", Roboto, "Noto Sans KR", "Apple SD Gothic Neo", sans-serif;
--color-success: var(--success);
--color-warning: var(--warning);
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
@@ -55,76 +57,80 @@
}
/* ────────────────────────────────────────────────────────────────────────────
팔레트 시스템 — palettes.ts 의 DEFAULT_THEME(=clean-blue) 폴백.
런타임 CSS는 main.tsx 가 ALL_THEMES_CSS 를 <style> 로 주입.
index.html 인라인 스크립트가 첫 페인트 전 [data-theme]/.dark 박음 → FOUC 없음.
의미색(destructive, chart-1..5)은 모든 팔레트 공통이므로 :root 에만 둠.
팔레트 — 기본은 ABAP_OPENCODE 의 "Dark Workspace" 테마(DESIGN_SYSTEM.md §1/§7)를
shadcn 토큰으로 옮긴 것. 계층(사이드바 < 패널 < 캔버스 < 카드)으로 깊이를 내고,
카드엔 항상 border, 악센트는 블루(선택·포커스)/그린(상태)/오렌지(경고) 셋만.
palettes.ts 의 DEFAULT_THEME(=clean-blue, 이름 "워크스페이스") 가 라이트 값을 덮고,
.dark 는 여기 값이 그대로 쓰임. index.html 이 첫 페인트 전 [data-theme]/.dark 박음.
──────────────────────────────────────────────────────────────────────────── */
:root {
/* 클린 블루 기본 — derive.ts의 고정 토큰과 동일 */
--background: #ffffff;
--foreground: #242c39;
--card: #f7f9fc;
--card-foreground: #242c39;
/* 라이트 — 회색 층 → 흰 카드 */
--background: #fafbfc; /* canvas */
--foreground: #1a1d22; /* text-hi */
--card: #ffffff;
--card-foreground: #1a1d22;
--popover: #ffffff;
--popover-foreground: #242c39;
--primary: #034ea2;
--popover-foreground: #1a1d22;
--primary: #3563e9; /* blue (흰 배경 대비용으로 진하게) */
--primary-foreground: #ffffff;
--secondary: #f0f3f8;
--secondary-foreground: #242c39;
--muted: #f7f9fc;
--muted-foreground: #606d7f;
--accent: #edf3fc;
--accent-foreground: #034ea2;
--secondary: #eff1f4; /* chip */
--secondary-foreground: #1a1d22;
--muted: #f2f3f5; /* sidebar */
--muted-foreground: #494f59; /* text-md */
--accent: #e4e8ef; /* sel-bg */
--accent-foreground: #1a1d22;
--destructive: oklch(0.577 0.245 27.325);
--destructive-foreground: oklch(0.985 0 0);
--border: #e1e6ee;
--input: #bbc7d8;
--ring: #034ea2;
--radius: 0.625rem;
--success: #22a85c; /* green — 상태·진행 */
--warning: #d07e44; /* orange — 보조·경고 */
--border: #e1e3e8;
--input: #e1e3e8;
--ring: #3563e9;
--radius: 0.5rem; /* 카드 8px, 소형 6px */
--shadow-float: 0 4px 14px rgba(23, 26, 31, 0.08), 0 1px 3px rgba(23, 26, 31, 0.06);
/* 사이드바 */
--sidebar: #f7f9fc;
--sidebar-foreground: #242c39;
--sidebar-primary: #034ea2;
--sidebar: #f2f3f5;
--sidebar-foreground: #1a1d22;
--sidebar-primary: #3563e9;
--sidebar-primary-foreground: #ffffff;
--sidebar-accent: #edf3fc;
--sidebar-accent-foreground: #034ea2;
--sidebar-border: #e1e6ee;
--sidebar-ring: #034ea2;
--sidebar-accent: #e9ebef;
--sidebar-accent-foreground: #1a1d22;
--sidebar-border: #e9ebef;
--sidebar-ring: #3563e9;
}
/*
* 다크모드 — themeStore (light/dark/system) 가 .dark 클래스 토글.
* 24 팔레트는 라이트 톤 기준이라 다크는 grayscale 베이스로 통일.
*/
/* 다크(기본 모드) — 어두운 층 → 밝은 카드. themeStore 가 .dark 토글. */
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--popover: oklch(0.205 0 0);
--popover-foreground: oklch(0.985 0 0);
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--background: #15171c; /* canvas */
--foreground: #e8eaed; /* text-hi (순백 금지) */
--card: #1a1d22;
--card-foreground: #e8eaed;
--popover: #1b1e24; /* float */
--popover-foreground: #e8eaed;
--primary: #4c7dff;
--primary-foreground: #ffffff;
--secondary: #1d2127; /* chip */
--secondary-foreground: #c9cdd3;
--muted: #191c21; /* item */
--muted-foreground: #9aa0a8; /* text-md */
--accent: #22262c; /* hover */
--accent-foreground: #e8eaed;
--destructive: oklch(0.704 0.191 22.216);
--destructive-foreground: oklch(0.985 0 0);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.556 0 0);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.556 0 0);
--success: #35c96e;
--warning: #e0915a;
--border: #24272d;
--input: #24272d;
--ring: #4c7dff;
--shadow-float: 0 6px 18px rgba(0, 0, 0, 0.45);
--sidebar: #0c0d0f;
--sidebar-foreground: #c9cdd3;
--sidebar-primary: #4c7dff;
--sidebar-primary-foreground: #ffffff;
--sidebar-accent: #20242c; /* sel-bg */
--sidebar-accent-foreground: #e8eaed;
--sidebar-border: #1e2126;
--sidebar-ring: #4c7dff;
}
@layer base {
@@ -140,6 +146,41 @@
"rlig" 1,
"calt" 1;
}
/* 스크롤바·선택·캐럿 — ABAP_OPENCODE 와 같은 얇은 오버레이 스타일 */
* {
scrollbar-width: thin;
scrollbar-color: var(--border) transparent;
}
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: var(--border);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--accent);
}
::selection {
background: color-mix(in srgb, var(--primary) 28%, transparent);
}
:root {
caret-color: var(--primary);
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
}
/* 시머 텍스트 — "생각하는 중…" 등 대기 문구에 밝은 띠가 좌→우로 쓸고 지나감.