diff --git a/frontend/src/components/StrategyEvaluationPage.tsx b/frontend/src/components/StrategyEvaluationPage.tsx index 5b42793..1c79fc6 100644 --- a/frontend/src/components/StrategyEvaluationPage.tsx +++ b/frontend/src/components/StrategyEvaluationPage.tsx @@ -811,6 +811,7 @@ export default function StrategyEvaluationPage({ theme = 'dark' }: Props) { contextSummary={aiVerifySummary} verifyContext={aiVerifyContext} result={aiVerifyResult} + theme={theme} onRetry={() => { void runAiVerify(); }} /> diff --git a/frontend/src/components/strategyEvaluation/StrategyEvaluationAiVerifyModal.tsx b/frontend/src/components/strategyEvaluation/StrategyEvaluationAiVerifyModal.tsx index d754f5c..d71b9f2 100644 --- a/frontend/src/components/strategyEvaluation/StrategyEvaluationAiVerifyModal.tsx +++ b/frontend/src/components/strategyEvaluation/StrategyEvaluationAiVerifyModal.tsx @@ -10,6 +10,8 @@ import type { import { buildAiVerifyFixPoints } from '../../utils/strategyEvaluationAiVerify'; import type { StrategyEvaluationAiVerifyResponse } from '../../utils/strategyEvaluationAiVerify'; +import type { Theme } from '../../types'; + interface Props { open: boolean; onClose: () => void; @@ -19,6 +21,7 @@ interface Props { verifyContext: StrategyEvaluationAiVerifyContext | null; result: StrategyEvaluationAiVerifyResponse | null; onRetry?: () => void; + theme?: Theme; } function renderAnalysisMarkdown(text: string): React.ReactNode { @@ -227,6 +230,7 @@ const StrategyEvaluationAiVerifyModal: React.FC = ({ verifyContext, result, onRetry, + theme = 'dark', }) => { const bodyRef = useRef(null); @@ -260,20 +264,20 @@ const StrategyEvaluationAiVerifyModal: React.FC = ({ const content = (
e.stopPropagation()} > -
-
-

+
+
+

AI 전략평가 검증

{contextSummary && ( @@ -282,7 +286,7 @@ const StrategyEvaluationAiVerifyModal: React.FC = ({
-
+
{loading && (
diff --git a/frontend/src/styles/strategyEvaluation.css b/frontend/src/styles/strategyEvaluation.css index f70b77d..a97d7a2 100644 --- a/frontend/src/styles/strategyEvaluation.css +++ b/frontend/src/styles/strategyEvaluation.css @@ -418,7 +418,7 @@ height: 14px; } -/* ── AI 검증 모달 ─────────────────────────────────────────────── */ +/* ── AI 검증 모달 (body portal — 앱 테마·app-popup-shell 연동) ─────────────── */ .seval-ai-verify-overlay { position: fixed; inset: 0; @@ -427,18 +427,42 @@ align-items: center; justify-content: center; padding: 24px; - background: rgba(0, 0, 0, 0.55); } .seval-ai-verify-modal { + /* body 포털 — .se-page 테마 토큰 미상속 보정 */ + --se-bg: var(--bg); + --se-bg-elevated: var(--bg2); + --se-bg-muted: var(--bg3); + --se-text: var(--text); + --se-text-muted: var(--text2); + --se-text-dim: var(--text3); + --se-border: var(--border); + --se-accent: var(--accent); + --se-accent-hover: var(--accent-h); + --se-gold: #e6c200; + --se-input-bg: color-mix(in srgb, var(--bg3) 88%, transparent); + --se-panel-bg: var(--bg2); + --btd-gold: var(--se-gold, #e6c200); + --app-popup-accent: color-mix(in srgb, var(--btd-gold, #e6c200) 40%, var(--accent, #3f7ef5)); + + position: relative; width: min(720px, 100%); max-height: min(88vh, 820px); display: flex; flex-direction: column; - border-radius: 12px; - border: 1px solid var(--se-border); - background: var(--se-panel-bg, #1a1d24); - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.45); + color: var(--text, #c0caf5); + font-size: 13px; +} + +.seval-ai-verify-modal.se-page--light { + --se-gold: #f57f17; + --btd-gold: var(--se-gold); +} + +.seval-ai-verify-modal.se-page--blue { + --se-gold: #ffd54f; + --btd-gold: var(--se-gold); } .seval-ai-verify-head { @@ -446,38 +470,41 @@ align-items: flex-start; justify-content: space-between; gap: 12px; - padding: 16px 18px 12px; - border-bottom: 1px solid var(--se-border); + padding: 12px 16px; + flex-shrink: 0; + cursor: default; + border-bottom: 1px solid var(--border, rgba(122, 162, 247, 0.12)); + background: linear-gradient( + 180deg, + color-mix(in srgb, var(--app-popup-accent, var(--accent, #3f7ef5)) 16%, transparent) 0%, + color-mix(in srgb, var(--app-popup-accent, var(--accent, #3f7ef5)) 5%, transparent) 28px, + var(--bg3, #1f2335) 100% + ); } .seval-ai-verify-title { margin: 0; - font-size: 1.05rem; - font-weight: 600; - color: var(--se-text); + font-size: 14px; + font-weight: 700; + color: var(--text, #c0caf5); + letter-spacing: 0.02em; } .seval-ai-verify-summary { margin: 6px 0 0; font-size: 0.78rem; - color: var(--se-text-muted); + color: var(--text2, #9aa5ce); line-height: 1.45; } .seval-ai-verify-close { - border: none; - background: transparent; - color: var(--se-text-muted); - font-size: 1.5rem; - line-height: 1; - cursor: pointer; - padding: 0 4px; + font-size: 16px; } .seval-ai-verify-body { flex: 1; overflow: auto; - padding: 16px 18px; + padding: 14px 16px 16px; min-height: 200px; } @@ -488,7 +515,11 @@ gap: 10px; padding: 32px 12px; text-align: center; - color: var(--se-text-muted); + color: var(--text, #c0caf5); +} + +.seval-ai-verify-loading p { + margin: 0; } .seval-ai-verify-spinner { @@ -498,13 +529,14 @@ .seval-ai-verify-loading-hint { font-size: 0.78rem; - opacity: 0.85; + color: var(--text2, #9aa5ce); } .seval-ai-verify-error { padding: 12px; border-radius: 8px; - background: color-mix(in srgb, #ef5350 12%, transparent); + background: color-mix(in srgb, #ef5350 14%, var(--bg2, #1e222d)); + border: 1px solid color-mix(in srgb, #ef5350 35%, var(--border, transparent)); color: #ffb4ab; } @@ -512,9 +544,9 @@ margin-top: 12px; padding: 6px 14px; border-radius: 6px; - border: 1px solid var(--se-border); - background: var(--se-input-bg); - color: var(--se-text); + border: 1px solid var(--border, var(--se-border)); + background: var(--bg3, var(--se-input-bg)); + color: var(--text, var(--se-text)); cursor: pointer; } @@ -522,7 +554,7 @@ display: flex; gap: 12px; font-size: 0.75rem; - color: var(--se-text-muted); + color: var(--text2, var(--se-text-muted)); margin-bottom: 12px; } @@ -530,7 +562,7 @@ margin: 16px 0 8px; font-size: 0.92rem; font-weight: 600; - color: var(--btd-gold, var(--se-gold)); + color: var(--btd-gold, var(--se-gold, #e6c200)); } .seval-ai-verify-h3:first-child { @@ -541,7 +573,7 @@ margin: 0 0 8px; font-size: 0.84rem; line-height: 1.55; - color: var(--se-text); + color: var(--text, var(--se-text)); } .seval-ai-verify-list { @@ -549,7 +581,7 @@ padding-left: 1.2rem; font-size: 0.84rem; line-height: 1.5; - color: var(--se-text); + color: var(--text, var(--se-text)); } .seval-ai-verify-foot { @@ -557,14 +589,15 @@ align-items: center; justify-content: space-between; gap: 12px; - padding: 12px 18px 16px; - border-top: 1px solid var(--se-border); + padding: 12px 16px 14px; + border-top: 1px solid var(--border, var(--se-border)); + background: color-mix(in srgb, var(--bg3, #1f2335) 65%, var(--bg2, #1e222d)); } .seval-ai-verify-footnote { margin: 0; font-size: 0.72rem; - color: var(--se-text-muted); + color: var(--text2, var(--se-text-muted)); line-height: 1.4; } @@ -572,10 +605,16 @@ flex-shrink: 0; padding: 6px 16px; border-radius: 6px; - border: 1px solid var(--se-border); - background: var(--se-input-bg); - color: var(--se-text); + border: 1px solid var(--border, var(--se-border)); + background: var(--bg3, var(--se-input-bg)); + color: var(--text, var(--se-text)); cursor: pointer; + transition: background 0.15s, border-color 0.15s; +} + +.seval-ai-verify-close-btn:hover { + background: color-mix(in srgb, var(--accent, #3f7ef5) 12%, var(--bg3, #1f2335)); + border-color: color-mix(in srgb, var(--accent, #3f7ef5) 35%, var(--border)); } /* ── AI 검증 수정 포인트 (Cursor) ── */ @@ -636,10 +675,10 @@ } .seval-ai-verify-fixpoint { - border: 1px solid var(--se-border); + border: 1px solid var(--border, var(--se-border)); border-radius: 8px; overflow: hidden; - background: color-mix(in srgb, var(--se-input-bg) 80%, transparent); + background: color-mix(in srgb, var(--bg2, var(--se-input-bg)) 92%, var(--bg, #1a1b26)); } .seval-ai-verify-fixpoint-toggle { @@ -650,7 +689,7 @@ padding: 10px 12px; border: none; background: transparent; - color: var(--se-text); + color: var(--text, var(--se-text)); text-align: left; cursor: pointer; font-size: 0.82rem; @@ -705,12 +744,12 @@ margin: 0; padding: 8px 10px; border-radius: 6px; - border: 1px solid var(--se-border); - background: var(--se-panel-bg, #14161a); + border: 1px solid var(--border, var(--se-border)); + background: color-mix(in srgb, var(--bg, #1a1b26) 55%, var(--bg2, #24283b)); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.72rem; line-height: 1.5; - color: var(--se-text); + color: var(--text, var(--se-text)); white-space: pre-wrap; word-break: break-word; max-height: 220px; @@ -719,7 +758,7 @@ .seval-ai-verify-ta4j { margin-top: 16px; - border: 1px solid var(--se-border); + border: 1px solid var(--border, var(--se-border)); border-radius: 8px; overflow: hidden; } @@ -731,8 +770,8 @@ width: 100%; padding: 10px 12px; border: none; - background: color-mix(in srgb, var(--se-input-bg) 90%, transparent); - color: var(--se-text); + background: color-mix(in srgb, var(--bg3, var(--se-input-bg)) 88%, transparent); + color: var(--text, var(--se-text)); font-size: 0.82rem; font-weight: 500; cursor: pointer; @@ -748,7 +787,7 @@ flex-wrap: wrap; gap: 10px 16px; font-size: 0.78rem; - color: var(--se-text-muted); + color: var(--text2, var(--se-text-muted)); margin-bottom: 8px; } @@ -756,7 +795,7 @@ margin: 0 0 8px; font-size: 0.78rem; line-height: 1.45; - color: var(--se-text); + color: var(--text, var(--se-text)); } .seval-ai-verify-ta4j-err {