dev-yuje commited on
Commit
e302529
·
1 Parent(s): e7d3bfe

fix: delete temporary css fix files and consolidate to ui_templates

Browse files
fix_css.py DELETED
@@ -1,185 +0,0 @@
1
- with open('app.py', 'r', encoding='utf-8') as f:
2
- content = f.read()
3
-
4
- start_marker = 'FINAL_CSS = CUSTOM_CSS + """'
5
- end_marker = '"""\n\nlaunch_kwargs = {'
6
-
7
- start_idx = content.find(start_marker)
8
- end_idx = content.find(end_marker)
9
-
10
- if start_idx != -1 and end_idx != -1:
11
- before = content[:start_idx + len(start_marker)]
12
- after = content[end_idx:]
13
-
14
- new_css = '''
15
- /* ── 전체 화면 너비 대폭 확대 ── */
16
- .gradio-container {
17
- max-width: 1400px !important;
18
- width: 95% !important;
19
- margin: 0 auto !important;
20
- }
21
-
22
- /* ── 챗봇 컨테이너 짤림 원천 봉쇄 ── */
23
- div[data-testid="chatbot"], .chatbot-container, .chatbot {
24
- border: none !important;
25
- overflow: visible !important;
26
- }
27
-
28
- /* ── 챗봇 내부 Placeholder(소개글 영역) 위쪽 짤림 영구 방어 ── */
29
- .placeholder, [class*="placeholder"] {
30
- display: flex !important;
31
- flex-direction: column !important;
32
- align-items: center !important;
33
- justify-content: flex-start !important; /* 위쪽 짤림 방지 */
34
- padding-top: 5% !important; /* 위에서 살짝 내림 */
35
- height: 50% !important;
36
- flex-grow: 0 !important;
37
- overflow: visible !important;
38
- margin: 0 auto !important;
39
- }
40
-
41
- /* ── 소개글(Prose) 쿨톤 회색 웰컴 카드 ── */
42
- .placeholder .prose {
43
- background: #f8fafc !important; /* 대시보드 카드와 동일한 색상 */
44
- border: 1px solid #e2e8f0 !important;
45
- border-radius: 12px !important;
46
- padding: 16px 24px !important; /* 높이 세이브 */
47
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05) !important;
48
- max-width: 700px !important;
49
- margin: 0 auto 12px auto !important;
50
- display: block !important;
51
- height: auto !important;
52
- }
53
- .placeholder h3, [class*="placeholder"] h3 {
54
- color: #334155 !important;
55
- font-weight: 800 !important;
56
- margin-top: 0 !important;
57
- margin-bottom: 12px !important;
58
- }
59
- .placeholder .prose ul {
60
- list-style-type: none !important;
61
- padding-left: 0 !important;
62
- margin-bottom: 12px !important;
63
- }
64
- .placeholder .prose li {
65
- margin-bottom: 4px !important;
66
- color: #475569 !important;
67
- font-size: 14px !important;
68
- line-height: 1.5 !important;
69
- }
70
- .placeholder .prose p:last-child {
71
- font-weight: 700 !important;
72
- color: #4c1d95 !important;
73
- background: #f3e8ff !important;
74
- padding: 8px 16px !important;
75
- border-radius: 8px !important;
76
- display: inline-block !important;
77
- margin-bottom: 0 !important;
78
- }
79
-
80
- /* ── 예시 질문 컨테이너 (그리드 배치) ── */
81
- [class*="examples"], .gr-samples-wrapper, .examples-container {
82
- display: grid !important;
83
- grid-template-columns: repeat(2, 1fr) !important;
84
- gap: 12px !important;
85
- width: 100% !important;
86
- max-width: 900px !important; /* 잘림 방지 */
87
- margin: 0 auto 40px auto !important;
88
- background: transparent !important;
89
- border: none !important;
90
- }
91
-
92
- /* 개별 버튼 디자인 (연보라색 테마 & 강력한 중앙 정렬) */
93
- .examples-container button, div[data-testid="chatbot"] button.example, button.example, .example-btn {
94
- border-radius: 8px !important;
95
- padding: 16px !important;
96
- text-align: center !important; /* 텍스트 가운데 정렬 */
97
- font-size: 14px !important;
98
- font-weight: 600 !important;
99
- color: #4c1d95 !important;
100
- background: #f5f3ff !important; /* 진짜 연보라색 배경 */
101
- background-color: #f5f3ff !important; /* 덮어쓰기 철벽 방어 */
102
- border: 1px solid #e9d5ff !important;
103
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) !important;
104
- transition: all 0.2s ease-in-out !important;
105
- display: flex !important;
106
- align-items: center !important;
107
- justify-content: center !important; /* 완벽 중앙 배치 */
108
- min-height: 80px !important;
109
- width: 100% !important;
110
- white-space: normal !important; /* 두줄 허용하되 900px 덕분에 보통 한 줄로 나옴 */
111
- }
112
-
113
- .examples-container button:hover, div[data-testid="chatbot"] button.example:hover, button.example:hover, .example-btn:hover {
114
- border-color: #a855f7 !important;
115
- background: #f3e8ff !important;
116
- background-color: #f3e8ff !important;
117
- transform: translateY(-2px) !important;
118
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.08) !important;
119
- color: #7c3aed !important;
120
- }
121
-
122
- /* ── 메시지 말풍선 정리 ── */
123
- .message.user, [data-testid="user"] .message {
124
- background-color: #111827 !important;
125
- border-radius: 12px 12px 0 12px !important;
126
- padding: 7px 13px !important;
127
- margin: 2px 0 !important;
128
- border: none !important;
129
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.08) !important;
130
- min-height: unset !important;
131
- }
132
- [data-testid="user"] > div, .bubble-wrap [data-testid="user"], .message-wrap.user > div, .message-row.user {
133
- background: transparent !important;
134
- background-color: transparent !important;
135
- border: none !important;
136
- }
137
- [data-testid="user"] .message *, .message.user * {
138
- color: #ffffff !important;
139
- line-height: 1.4 !important;
140
- margin: 0 !important;
141
- }
142
- [data-testid="bot"] .message, [data-testid="bot"] > div, .message-wrap.bot > div, .message.bot, .message-row.bot .message {
143
- background-color: #ffffff !important;
144
- color: #1f2937 !important;
145
- border: 1px solid #e5e7eb !important;
146
- border-radius: 12px 12px 12px 0 !important;
147
- padding: 16px 20px !important;
148
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05) !important;
149
- }
150
-
151
- /* ── 피드백 및 전송 버튼 ── */
152
- .message-buttons, button[aria-label="Good response"], button[aria-label="Bad response"], .like-dislike-area { display: none !important; }
153
- button[class*="submit-btn"], #submit-btn, button[id*="submit"], button.submit-button {
154
- background: linear-gradient(135deg, #1e3a5f 0%, #7c3aed 100%) !important;
155
- color: white !important;
156
- border-radius: 8px !important;
157
- font-weight: bold !important;
158
- border: none !important;
159
- display: block !important;
160
- opacity: 1 !important;
161
- visibility: visible !important;
162
- }
163
-
164
- /* ── 메인 레이아웃 사이드바 균형 최적화 ── */
165
- .sidebar-container {
166
- border: 1px solid #e2e8f0 !important;
167
- border-radius: 12px !important;
168
- padding: 24px 20px !important;
169
- background: #ffffff !important;
170
- height: 700px !important;
171
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.04) !important;
172
- display: flex !important;
173
- flex-direction: column !important;
174
- }
175
- .news-feed-container {
176
- flex-grow: 1 !important;
177
- max-height: 250px !important;
178
- overflow-y: auto !important;
179
- }
180
- '''
181
- with open('app.py', 'w', encoding='utf-8') as f:
182
- f.write(before + '\n' + new_css + '\n' + after)
183
- print('CSS Update Success')
184
- else:
185
- print('Markers not found')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fix_css2.py DELETED
@@ -1,245 +0,0 @@
1
- import sys
2
-
3
- with open('app.py', 'r', encoding='utf-8') as f:
4
- lines = f.readlines()
5
-
6
- # 157번째 라인부터 문제가 생김 (res_comp = session.run(...))
7
- # 156번째 라인은 '# 상위 5개 회사 키워드 리스트업 추가' 임
8
- cut_idx = -1
9
- for i, line in enumerate(lines):
10
- if '# 상위 5개 회사 키워드 리스트업 추가' in line:
11
- cut_idx = i
12
- break
13
-
14
- if cut_idx == -1:
15
- print("Cannot find cut index!")
16
- sys.exit(1)
17
-
18
- # 그 아래로 launch_kwargs = { 가 있는 라인을 찾음
19
- end_idx = -1
20
- for i in range(cut_idx, len(lines)):
21
- if 'launch_kwargs = {' in line or 'launch_kwargs =' in lines[i]:
22
- end_idx = i
23
- break
24
-
25
- if end_idx == -1:
26
- print("Cannot find end index!")
27
- sys.exit(1)
28
-
29
- before_lines = lines[:cut_idx + 1]
30
- after_lines = lines[end_idx:]
31
-
32
- correct_middle = ''' res_comp = session.run(
33
- "MATCH (c:AICompany) "
34
- "OPTIONAL MATCH (a:Article)-[:MENTIONS]->(c) "
35
- "RETURN c.name as name, count(a) as cnt "
36
- "ORDER BY cnt DESC LIMIT 5"
37
- )
38
- stats["companies_list"] = [{"name": row["name"]} for row in res_comp]
39
-
40
- res_art = session.run(
41
- "MATCH (a:Article) "
42
- "RETURN a.title as title, a.published_date as date, a.url as url "
43
- "ORDER BY a.published_date DESC LIMIT 4"
44
- )
45
- stats["recent_articles"] = [
46
- {"title": r["title"], "date": r["date"], "url": r["url"]}
47
- for r in res_art
48
- ]
49
- except Exception as e:
50
- print(f"⚠️ [통계 조회 실패] {e}")
51
- return stats
52
-
53
-
54
- # ──────────────────────────────────────────
55
- # 5. Gradio UI 구성
56
- # ──────────────────────────────────────────
57
-
58
- theme_obj = gr.themes.Soft(primary_hue="indigo", secondary_hue="slate")
59
-
60
- CHATBOT_DESCRIPTION = """
61
- ### 🌌 국내 AI 뉴스 기사를 기반으로 구축된 지식 그래프(GraphRAG)에 질문하세요.
62
-
63
- - 📰 **기업별 AI 트렌드** — 삼성, 카카오, 네이버 등 주요 기업의 최신 AI 동향
64
- - 🔬 **기술 키워드 분석** — LLM, 생성형 AI, 파운데이션 모델 등 핵심 기술 정리
65
- - 🔗 **실제 뉴스 출처 제공** — 답변마다 근거 기사 링크 포함
66
-
67
- 👇 **아래 예시 질문 버튼을 클릭하거나 직접 입력해 보세요.**
68
- """
69
-
70
- FINAL_CSS = CUSTOM_CSS + """
71
- /* ── 전체 화면 너비 대폭 확대 ── */
72
- .gradio-container {
73
- max-width: 1400px !important;
74
- width: 95% !important;
75
- margin: 0 auto !important;
76
- }
77
-
78
- /* ── 챗봇 컨테이너 테두리 및 짤림(Overflow) 방지 ── */
79
- div[data-testid="chatbot"], .chatbot-container, .chatbot {
80
- border: none !important;
81
- overflow: visible !important;
82
- }
83
-
84
- /* ── 챗봇 내부 Placeholder(소개글 영역) 위쪽 짤림 영구 방어 ── */
85
- .placeholder, [class*="placeholder"] {
86
- display: flex !important;
87
- flex-direction: column !important;
88
- align-items: center !important;
89
- justify-content: flex-start !important; /* 위쪽 짤림 방지 */
90
- padding-top: 5% !important; /* 위에서 살짝 내림 */
91
- height: 50% !important;
92
- flex-grow: 0 !important;
93
- overflow: visible !important;
94
- margin: 0 auto !important;
95
- }
96
-
97
- /* ── 소개글(Prose) 아이보리/쿨톤 회색 웰컴 카드 ── */
98
- .placeholder .prose {
99
- background: #f8fafc !important; /* 대시보드 카드와 동일한 색상 */
100
- border: 1px solid #e2e8f0 !important;
101
- border-radius: 12px !important;
102
- padding: 16px 24px !important; /* 높이 세이브 */
103
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05) !important;
104
- max-width: 700px !important;
105
- margin: 0 auto 12px auto !important;
106
- display: block !important;
107
- height: auto !important;
108
- }
109
- .placeholder h3, [class*="placeholder"] h3 {
110
- color: #334155 !important;
111
- font-weight: 800 !important;
112
- margin-top: 0 !important;
113
- margin-bottom: 12px !important;
114
- }
115
- .placeholder .prose ul {
116
- list-style-type: none !important;
117
- padding-left: 0 !important;
118
- margin-bottom: 12px !important;
119
- }
120
- .placeholder .prose li {
121
- margin-bottom: 4px !important;
122
- color: #475569 !important;
123
- font-size: 14px !important;
124
- line-height: 1.5 !important;
125
- }
126
- .placeholder .prose p:last-child {
127
- font-weight: 700 !important;
128
- color: #4c1d95 !important;
129
- background: #f3e8ff !important;
130
- padding: 8px 16px !important;
131
- border-radius: 8px !important;
132
- display: inline-block !important;
133
- margin-bottom: 0 !important;
134
- }
135
-
136
- /* ── 예시 질문 컨테이너 (그리드 배치) ── */
137
- [class*="examples"], .gr-samples-wrapper, .examples-container {
138
- display: grid !important;
139
- grid-template-columns: repeat(2, 1fr) !important;
140
- gap: 12px !important;
141
- width: 100% !important;
142
- max-width: 900px !important; /* 잘림 방지 */
143
- margin: 0 auto 40px auto !important;
144
- background: transparent !important;
145
- border: none !important;
146
- }
147
-
148
- /* 개별 버튼 디자인 (연보라색 테마 & 강력한 중앙 정렬) */
149
- .examples-container button, div[data-testid="chatbot"] button.example, button.example, .example-btn {
150
- border-radius: 8px !important;
151
- padding: 16px !important;
152
- text-align: center !important; /* 텍스트 가운데 정렬 */
153
- font-size: 14px !important;
154
- font-weight: 600 !important;
155
- color: #4c1d95 !important;
156
- background: #f5f3ff !important; /* 진짜 연보라색 배경 */
157
- background-color: #f5f3ff !important; /* 덮어쓰기 철벽 방어 */
158
- border: 1px solid #e9d5ff !important;
159
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) !important;
160
- transition: all 0.2s ease-in-out !important;
161
- display: flex !important;
162
- align-items: center !important;
163
- justify-content: center !important; /* 완벽 중앙 배치 */
164
- min-height: 80px !important;
165
- width: 100% !important;
166
- white-space: normal !important; /* 두줄 허용하되 900px 덕분에 보통 한 줄로 나옴 */
167
- }
168
-
169
- .examples-container button:hover, div[data-testid="chatbot"] button.example:hover, button.example:hover, .example-btn:hover {
170
- border-color: #a855f7 !important;
171
- background: #f3e8ff !important;
172
- background-color: #f3e8ff !important;
173
- transform: translateY(-2px) !important;
174
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.08) !important;
175
- color: #7c3aed !important;
176
- }
177
-
178
- /* ── 메시지 말풍선 정리 ── */
179
- .message.user, [data-testid="user"] .message {
180
- background-color: #111827 !important;
181
- border-radius: 12px 12px 0 12px !important;
182
- padding: 7px 13px !important;
183
- margin: 2px 0 !important;
184
- border: none !important;
185
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.08) !important;
186
- min-height: unset !important;
187
- }
188
- [data-testid="user"] > div, .bubble-wrap [data-testid="user"], .message-wrap.user > div, .message-row.user {
189
- background: transparent !important;
190
- background-color: transparent !important;
191
- border: none !important;
192
- }
193
- [data-testid="user"] .message *, .message.user * {
194
- color: #ffffff !important;
195
- line-height: 1.4 !important;
196
- margin: 0 !important;
197
- }
198
- [data-testid="bot"] .message, [data-testid="bot"] > div, .message-wrap.bot > div, .message.bot, .message-row.bot .message {
199
- background-color: #ffffff !important;
200
- color: #1f2937 !important;
201
- border: 1px solid #e5e7eb !important;
202
- border-radius: 12px 12px 12px 0 !important;
203
- padding: 16px 20px !important;
204
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05) !important;
205
- }
206
-
207
- /* ── 피드백 및 전송 버튼 ── */
208
- .message-buttons, button[aria-label="Good response"], button[aria-label="Bad response"], .like-dislike-area { display: none !important; }
209
- button[class*="submit-btn"], #submit-btn, button[id*="submit"], button.submit-button {
210
- background: linear-gradient(135deg, #1e3a5f 0%, #7c3aed 100%) !important;
211
- color: white !important;
212
- border-radius: 8px !important;
213
- font-weight: bold !important;
214
- border: none !important;
215
- display: block !important;
216
- opacity: 1 !important;
217
- visibility: visible !important;
218
- }
219
-
220
- /* ── 메인 레이아웃 사이드바 균형 최적화 ── */
221
- .sidebar-container {
222
- border: 1px solid #e2e8f0 !important;
223
- border-radius: 12px !important;
224
- padding: 24px 20px !important;
225
- background: #ffffff !important;
226
- height: 700px !important;
227
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.04) !important;
228
- display: flex !important;
229
- flex-direction: column !important;
230
- }
231
- .news-feed-container {
232
- flex-grow: 1 !important;
233
- max-height: 250px !important;
234
- overflow-y: auto !important;
235
- }
236
- """
237
-
238
- '''
239
-
240
- final_content = "".join(before_lines) + "\n" + correct_middle + "\n" + "".join(after_lines)
241
-
242
- with open('app.py', 'w', encoding='utf-8') as f:
243
- f.write(final_content)
244
-
245
- print("APP.PY PERFECTLY RECOVERED AND UPDATED!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fix_css3.py DELETED
@@ -1,203 +0,0 @@
1
- import sys
2
-
3
- with open('app.py', 'r', encoding='utf-8') as f:
4
- lines = f.readlines()
5
-
6
- start_idx = -1
7
- for i, line in enumerate(lines):
8
- if 'FINAL_CSS = CUSTOM_CSS + """' in line:
9
- start_idx = i
10
- break
11
-
12
- if start_idx == -1:
13
- print('Cannot find FINAL_CSS')
14
- sys.exit(1)
15
-
16
- clean_css = '''FINAL_CSS = CUSTOM_CSS + """
17
- /* ── 전체 화면 너비 확대 ── */
18
- .gradio-container {
19
- max-width: 1400px !important;
20
- width: 95% !important;
21
- margin: 0 auto !important;
22
- }
23
-
24
- /* ── 챗봇 컨테이너 테두리 제거 ── */
25
- div[data-testid="chatbot"], .chatbot-container, .chatbot {
26
- border: none !important;
27
- overflow: visible !important;
28
- }
29
-
30
- /* ── 챗봇 내부 Placeholder(소개글 영역) 상단 짤림 영구 차단 ── */
31
- .placeholder, [class*="placeholder"] {
32
- display: flex !important;
33
- flex-direction: column !important;
34
- align-items: center !important;
35
- justify-content: flex-start !important; /* 항상 위에서부터 뿌림 */
36
- padding-top: 40px !important; /* 상단 여백 넉넉히 주어 짤림 절대 불가 */
37
- height: 100% !important; /* 전체 높이 사용 */
38
- min-height: 400px !important;
39
- flex-grow: 1 !important;
40
- overflow: visible !important;
41
- margin: 0 auto !important;
42
- }
43
-
44
- /* ── 소개글(Prose) 웰컴 보드 (위쪽 절반) ── */
45
- .placeholder .prose {
46
- background: #f8fafc !important; /* 쿨톤 회색 */
47
- border: 1px solid #e2e8f0 !important;
48
- border-bottom: none !important; /* 아래쪽 경계선 제거로 결합 준비 */
49
- border-radius: 12px 12px 0 0 !important; /* 아래쪽 모서리 직각으로 펴서 결합 준비 */
50
- padding: 24px 24px 10px 24px !important;
51
- max-width: 800px !important; /* 800px 고정너비 */
52
- width: 100% !important;
53
- margin: 0 auto !important;
54
- display: block !important;
55
- position: relative !important;
56
- z-index: 2 !important; /* 아래쪽 컨테이너 위로 살짝 덮게 함 */
57
- }
58
- .placeholder h3, [class*="placeholder"] h3 {
59
- color: #334155 !important;
60
- font-weight: 800 !important;
61
- margin-top: 0 !important;
62
- margin-bottom: 12px !important;
63
- }
64
- .placeholder .prose ul {
65
- list-style-type: none !important;
66
- padding-left: 0 !important;
67
- margin-bottom: 12px !important;
68
- }
69
- .placeholder .prose li {
70
- margin-bottom: 4px !important;
71
- color: #475569 !important;
72
- font-size: 14px !important;
73
- line-height: 1.5 !important;
74
- }
75
- .placeholder .prose p:last-child {
76
- font-weight: 700 !important;
77
- color: #4c1d95 !important;
78
- background: #f3e8ff !important;
79
- padding: 8px 16px !important;
80
- border-radius: 8px !important;
81
- display: inline-block !important;
82
- margin-bottom: 0 !important;
83
- }
84
-
85
- /* ── 예시 질문 컨테이너 (아래쪽 절반: 보드 병합 완료) ── */
86
- [class*="examples"], .gr-samples-wrapper, .examples-container {
87
- display: grid !important;
88
- grid-template-columns: repeat(2, 1fr) !important;
89
- gap: 12px !important;
90
- width: 100% !important;
91
- max-width: 800px !important; /* 소개글과 800px 너비 일치 */
92
-
93
- /* 🌟 핵심: 위쪽 보드와 완벽 결합을 위한 마이너스 마진 🌟 */
94
- margin: -32px auto 40px auto !important; /* 32px 갭 제거 (Gradio 기본 갭) */
95
-
96
- background: #f8fafc !important; /* 소개글과 동일한 회색 배경 */
97
- border: 1px solid #e2e8f0 !important;
98
- border-top: none !important; /* 위쪽 경계선 제거 */
99
- border-radius: 0 0 12px 12px !important; /* 위쪽 모서리 직각으로 펴서 결합 완료 */
100
- padding: 10px 24px 24px 24px !important;
101
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05) !important;
102
- position: relative !important;
103
- z-index: 1 !important; /* 위쪽 컨테이너 밑으로 겹치게 하여 흰줄 완전 소멸 */
104
- }
105
-
106
- /* 개별 버튼 디자인 (연보라색 테마 & 강력한 중앙 정렬) */
107
- .examples-container button, div[data-testid="chatbot"] button.example, button.example, .example-btn {
108
- border-radius: 8px !important;
109
- padding: 16px !important;
110
- text-align: center !important; /* 텍스트 가운데 정렬 */
111
- font-size: 14px !important;
112
- font-weight: 600 !important;
113
- color: #4c1d95 !important;
114
- background: #f5f3ff !important; /* 진짜 연보라색 배경 */
115
- background-color: #f5f3ff !important; /* 덮어쓰기 철벽 방어 */
116
- border: 1px solid #e9d5ff !important;
117
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) !important;
118
- transition: all 0.2s ease-in-out !important;
119
- display: flex !important;
120
- align-items: center !important;
121
- justify-content: center !important; /* 완벽 중앙 배치 */
122
- min-height: 80px !important;
123
- width: 100% !important;
124
- white-space: normal !important;
125
- }
126
-
127
- .examples-container button:hover, div[data-testid="chatbot"] button.example:hover, button.example:hover, .example-btn:hover {
128
- border-color: #a855f7 !important;
129
- background: #f3e8ff !important;
130
- background-color: #f3e8ff !important;
131
- transform: translateY(-2px) !important;
132
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.08) !important;
133
- color: #7c3aed !important;
134
- }
135
-
136
- /* ── 메시지 말풍선 정리 ── */
137
- .message.user, [data-testid="user"] .message {
138
- background-color: #111827 !important;
139
- border-radius: 12px 12px 0 12px !important;
140
- padding: 7px 13px !important;
141
- margin: 2px 0 !important;
142
- border: none !important;
143
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.08) !important;
144
- min-height: unset !important;
145
- }
146
- [data-testid="user"] > div, .bubble-wrap [data-testid="user"], .message-wrap.user > div, .message-row.user {
147
- background: transparent !important;
148
- background-color: transparent !important;
149
- border: none !important;
150
- }
151
- [data-testid="user"] .message *, .message.user * {
152
- color: #ffffff !important;
153
- line-height: 1.4 !important;
154
- margin: 0 !important;
155
- }
156
- [data-testid="bot"] .message, [data-testid="bot"] > div, .message-wrap.bot > div, .message.bot, .message-row.bot .message {
157
- background-color: #ffffff !important;
158
- color: #1f2937 !important;
159
- border: 1px solid #e5e7eb !important;
160
- border-radius: 12px 12px 12px 0 !important;
161
- padding: 16px 20px !important;
162
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05) !important;
163
- }
164
-
165
- /* ── 피드백 및 전송 버튼 ── */
166
- .message-buttons, button[aria-label="Good response"], button[aria-label="Bad response"], .like-dislike-area { display: none !important; }
167
- button[class*="submit-btn"], #submit-btn, button[id*="submit"], button.submit-button {
168
- background: linear-gradient(135deg, #1e3a5f 0%, #7c3aed 100%) !important;
169
- color: white !important;
170
- border-radius: 8px !important;
171
- font-weight: bold !important;
172
- border: none !important;
173
- display: block !important;
174
- opacity: 1 !important;
175
- visibility: visible !important;
176
- }
177
-
178
- /* ── 메인 레이아웃 사이드바 균형 최적화 ── */
179
- .sidebar-container {
180
- border: 1px solid #e2e8f0 !important;
181
- border-radius: 12px !important;
182
- padding: 24px 20px !important;
183
- background: #ffffff !important;
184
- height: 700px !important;
185
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.04) !important;
186
- display: flex !important;
187
- flex-direction: column !important;
188
- }
189
- .news-feed-container {
190
- flex-grow: 1 !important;
191
- max-height: 250px !important;
192
- overflow-y: auto !important;
193
- }
194
- """
195
- '''
196
-
197
- before_lines = lines[:start_idx]
198
- final_content = ''.join(before_lines) + clean_css
199
-
200
- with open('app.py', 'w', encoding='utf-8') as f:
201
- f.write(final_content)
202
-
203
- print('Clean CSS recovery done!')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/graphBuilder/scrapping/finScrapping.py CHANGED
@@ -14,7 +14,7 @@ categories = {
14
  "경제": "https://news.naver.com/section/101",
15
  "IT/과학": "https://news.naver.com/section/105",
16
  }
17
- NUM_ARTICLES_PER_CATEGORY = 300
18
 
19
  # AI 핀테크 키워드 (FinNode 프로젝트 전용)
20
  FINTECH_AI_KEYWORDS = [
@@ -43,7 +43,7 @@ def get_article_links(driver, category_url, num_articles):
43
  print(f" [LINK] 로드 완료 (title: {driver.title})")
44
 
45
  print(" [LINK] 더 많은 기사를 불러오기 위해 스크롤 및 '기사 더보기' 버튼을 클릭합니다...")
46
- for _ in range(15): # 최대 15회 스크롤/클릭 시도
47
  driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
48
  time.sleep(1.0)
49
  try:
 
14
  "경제": "https://news.naver.com/section/101",
15
  "IT/과학": "https://news.naver.com/section/105",
16
  }
17
+ NUM_ARTICLES_PER_CATEGORY = 1500
18
 
19
  # AI 핀테크 키워드 (FinNode 프로젝트 전용)
20
  FINTECH_AI_KEYWORDS = [
 
43
  print(f" [LINK] 로드 완료 (title: {driver.title})")
44
 
45
  print(" [LINK] 더 많은 기사를 불러오기 위해 스크롤 및 '기사 더보기' 버튼을 클릭합니다...")
46
+ for _ in range(150): # 최대 150회 스크롤/클릭 시도
47
  driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
48
  time.sleep(1.0)
49
  try:
src/utils/ui_templates.py CHANGED
@@ -15,12 +15,17 @@ CUSTOM_CSS: str = """
15
  /* ── Google Fonts 로드 ── */
16
  @import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;600;700;800&family=JetBrains+Mono:wght@400;500&family=Inter:wght@400;600&display=swap');
17
 
18
- /* ── 전체 배경 / 기본 폰트 ── */
19
  body, .gradio-container {
20
  background-color: #F6F5FA !important;
21
  font-family: 'Sora', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;
22
  color: #1e3a5f !important;
23
  }
 
 
 
 
 
24
 
25
  /* ── Ambient glow ── */
26
  .ambient-glow {
@@ -37,8 +42,12 @@ body, .gradio-container {
37
  .sidebar-container {
38
  border: 1px solid #e2e8f0 !important;
39
  border-radius: 12px !important;
40
- padding: 20px 18px !important;
41
  background: #ffffff !important;
 
 
 
 
42
  }
43
 
44
  /* ── 구분선 ── */
@@ -128,13 +137,13 @@ body, .gradio-container {
128
  }
129
  .keyword-badge {
130
  display: inline-block;
131
- background: transparent !important; /* 배경색 없음 */
132
- border: 1px solid #ddd6fe !important; /* 아주 연한 보라 테두리 */
133
  border-radius: 9999px !important;
134
  padding: 4px 12px !important;
135
  font-size: 11px !important;
136
  font-weight: 600 !important;
137
- color: #8b5cf6 !important; /* 기업(진한 보라)보다 연하고 밝은 보라 텍스트 */
138
  }
139
  .keyword-badge-first {
140
  background: transparent !important;
@@ -151,13 +160,13 @@ body, .gradio-container {
151
  }
152
  .company-badge {
153
  display: inline-block;
154
- background: transparent !important; /* 배경색 없음 */
155
- border: 1px solid #ddd6fe !important; /* 아주 연한 보라 테두리 */
156
  border-radius: 9999px !important;
157
  padding: 4px 12px !important;
158
  font-size: 11px !important;
159
  font-weight: 600 !important;
160
- color: #8b5cf6 !important; /* 주요 기술 키워드와 동일한 색상 */
161
  }
162
  .company-badge-first {
163
  background: transparent !important;
@@ -167,8 +176,9 @@ body, .gradio-container {
167
 
168
  /* ── 최신 뉴스 피드 ── */
169
  .news-feed-container {
170
- max-height: 260px;
171
- overflow-y: auto;
 
172
  }
173
  .news-feed-container::-webkit-scrollbar { width: 3px; }
174
  .news-feed-container::-webkit-scrollbar-track { background: transparent; }
@@ -212,45 +222,117 @@ body, .gradio-container {
212
  margin-top: 4px;
213
  }
214
 
215
- /* ── 예시 질문 버튼 (2x2 그드) ── */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  [class*="examples"], .gr-samples-wrapper, .examples-container {
217
  display: grid !important;
218
  grid-template-columns: repeat(2, 1fr) !important;
219
- gap: 8px !important;
220
- margin-top: 12px !important;
221
- margin-bottom: 8px !important;
222
- background: transparent !important;
223
- border: none !important;
 
 
 
 
 
 
 
224
  }
225
- [class*="examples"] button {
226
- text-align: left !important;
227
- padding: 11px 13px !important;
228
- background: rgba(255,255,255,0.70) !important;
229
- border: 1px solid rgba(124,58,237,0.09) !important;
230
- border-radius: 9px !important;
231
- font-size: 12px !important;
232
  font-weight: 600 !important;
233
- color: #1e3a5f !important;
234
- line-height: 1.4 !important;
235
- box-shadow: none !important;
236
- transition: all 0.16s ease !important;
237
- white-space: normal !important;
238
- height: auto !important;
239
- min-height: 46px !important;
240
- cursor: pointer !important;
 
 
 
 
241
  }
242
- [class*="examples"] button:hover {
243
- background: rgba(255,255,255,0.97) !important;
244
- border-color: rgba(124,58,237,0.20) !important;
245
- color: #1e3a5f !important;
246
- box-shadow: 0 2px 8px rgba(124,58,237,0.06) !important;
247
- transform: translateY(-1px) !important;
 
 
248
  }
249
 
250
  /* ── 전송 버튼: 너비 넓고 높이 입력창에 맞춤 ── */
251
- button[class*="submit-btn"],
252
- [data-testid="submit-button"],
253
- #submit-btn {
254
  background: linear-gradient(135deg, #1e3a5f 0%, #7c3aed 100%) !important;
255
  color: white !important;
256
  font-weight: 700 !important;
@@ -268,6 +350,8 @@ button[class*="submit-btn"],
268
  align-items: center !important;
269
  justify-content: center !important;
270
  box-sizing: border-box !important;
 
 
271
  }
272
  button[class*="submit-btn"]:hover,
273
  [data-testid="submit-button"]:hover {
@@ -307,13 +391,6 @@ div:has(> [data-testid="submit-button"]),
307
  align-items: center !important;
308
  }
309
 
310
- /* ── 챗봇 컨테이너 ── */
311
- div[data-testid="chatbot"] {
312
- background: transparent !important;
313
- border: 1px solid rgba(30,58,95,0.08) !important;
314
- border-radius: 12px !important;
315
- }
316
-
317
  /* ── 챗봇 탭/라벨 숨김 ── */
318
  .chatbot > div:first-child, [class*="chatbot"] > div:first-child,
319
  .chatbot-label, div[class*="chatbot"] .label,
@@ -330,24 +407,36 @@ label.svelte-1ipelgc, span.svelte-1ipelgc {
330
  min-height: auto !important;
331
  }
332
 
333
- /* ── 사용자 버블 ── */
334
- .message.user {
335
- background: rgba(30,58,95,0.06) !important;
336
- border: 1px solid rgba(30,58,95,0.14) !important;
337
- border-radius: 12px !important;
 
 
 
 
338
  }
339
- .message.user p, .message.user span,
340
- .message.user li, .message.user div {
341
- color: #1e3a5f !important;
342
- font-weight: 600 !important;
 
 
 
 
 
343
  background: transparent !important;
344
  }
345
 
346
- /* ── 봇 버블 ── */
347
- .message.bot {
348
- background: rgba(255,255,255,0.65) !important;
349
- border: 1px solid rgba(30,58,95,0.08) !important;
350
- border-radius: 12px !important;
 
 
 
351
  }
352
  .message.bot p, .message.bot span,
353
  .message.bot li, .message.bot div {
@@ -407,7 +496,7 @@ button.secondary:hover, button.variant-secondary:hover {
407
  border-color: rgba(124,58,237,0.24) !important;
408
  }
409
 
410
- /* ── 메인 레이아웃 컬럼 높이 동기화 (챗봇 내부 깨짐 방지) ── */
411
  #main-row { align-items: stretch !important; }
412
  #main-row > div[class*="column"] {
413
  display: flex !important;
 
15
  /* ── Google Fonts 로드 ── */
16
  @import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;600;700;800&family=JetBrains+Mono:wght@400;500&family=Inter:wght@400;600&display=swap');
17
 
18
+ /* ── 전체 배경 / 기본 폰트 / 화면 너비 확대 ── */
19
  body, .gradio-container {
20
  background-color: #F6F5FA !important;
21
  font-family: 'Sora', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;
22
  color: #1e3a5f !important;
23
  }
24
+ .gradio-container {
25
+ max-width: 1400px !important;
26
+ width: 95% !important;
27
+ margin: 0 auto !important;
28
+ }
29
 
30
  /* ── Ambient glow ── */
31
  .ambient-glow {
 
42
  .sidebar-container {
43
  border: 1px solid #e2e8f0 !important;
44
  border-radius: 12px !important;
45
+ padding: 24px 20px !important;
46
  background: #ffffff !important;
47
+ height: 700px !important;
48
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.04) !important;
49
+ display: flex !important;
50
+ flex-direction: column !important;
51
  }
52
 
53
  /* ── 구분선 ── */
 
137
  }
138
  .keyword-badge {
139
  display: inline-block;
140
+ background: transparent !important;
141
+ border: 1px solid #ddd6fe !important;
142
  border-radius: 9999px !important;
143
  padding: 4px 12px !important;
144
  font-size: 11px !important;
145
  font-weight: 600 !important;
146
+ color: #8b5cf6 !important;
147
  }
148
  .keyword-badge-first {
149
  background: transparent !important;
 
160
  }
161
  .company-badge {
162
  display: inline-block;
163
+ background: transparent !important;
164
+ border: 1px solid #ddd6fe !important;
165
  border-radius: 9999px !important;
166
  padding: 4px 12px !important;
167
  font-size: 11px !important;
168
  font-weight: 600 !important;
169
+ color: #8b5cf6 !important;
170
  }
171
  .company-badge-first {
172
  background: transparent !important;
 
176
 
177
  /* ── 최신 뉴스 피드 ── */
178
  .news-feed-container {
179
+ flex-grow: 1 !important;
180
+ max-height: 250px !important;
181
+ overflow-y: auto !important;
182
  }
183
  .news-feed-container::-webkit-scrollbar { width: 3px; }
184
  .news-feed-container::-webkit-scrollbar-track { background: transparent; }
 
222
  margin-top: 4px;
223
  }
224
 
225
+ /* ── 챗봇 컨테이너 테두제거 ── */
226
+ div[data-testid="chatbot"], .chatbot-container, .chatbot {
227
+ border: none !important;
228
+ overflow: visible !important;
229
+ }
230
+
231
+ /* ── 챗봇 내부 Placeholder(소개글 영역) 상단 짤림 영구 차단 ── */
232
+ .placeholder, [class*="placeholder"] {
233
+ display: flex !important;
234
+ flex-direction: column !important;
235
+ align-items: center !important;
236
+ justify-content: flex-start !important;
237
+ padding-top: 40px !important;
238
+ height: 100% !important;
239
+ min-height: 400px !important;
240
+ flex-grow: 1 !important;
241
+ overflow: visible !important;
242
+ margin: 0 auto !important;
243
+ }
244
+
245
+ /* ── 소개글(Prose) 웰컴 보드 (위쪽 절반) ── */
246
+ .placeholder .prose {
247
+ background: #f8fafc !important;
248
+ border: 1px solid #e2e8f0 !important;
249
+ border-bottom: none !important;
250
+ border-radius: 12px 12px 0 0 !important;
251
+ padding: 24px 24px 10px 24px !important;
252
+ max-width: 800px !important;
253
+ width: 100% !important;
254
+ margin: 0 auto !important;
255
+ display: block !important;
256
+ position: relative !important;
257
+ z-index: 2 !important;
258
+ }
259
+ .placeholder h3, [class*="placeholder"] h3 {
260
+ color: #334155 !important;
261
+ font-weight: 800 !important;
262
+ margin-top: 0 !important;
263
+ margin-bottom: 12px !important;
264
+ }
265
+ .placeholder .prose ul {
266
+ list-style-type: none !important;
267
+ padding-left: 0 !important;
268
+ margin-bottom: 12px !important;
269
+ }
270
+ .placeholder .prose li {
271
+ margin-bottom: 4px !important;
272
+ color: #475569 !important;
273
+ font-size: 14px !important;
274
+ line-height: 1.5 !important;
275
+ }
276
+ .placeholder .prose p:last-child {
277
+ font-weight: 700 !important;
278
+ color: #4c1d95 !important;
279
+ background: #f3e8ff !important;
280
+ padding: 8px 16px !important;
281
+ border-radius: 8px !important;
282
+ display: inline-block !important;
283
+ margin-bottom: 0 !important;
284
+ }
285
+
286
+ /* ── 예시 질문 컨테이너 (아래쪽 절반: 보드 병합 완료) ── */
287
  [class*="examples"], .gr-samples-wrapper, .examples-container {
288
  display: grid !important;
289
  grid-template-columns: repeat(2, 1fr) !important;
290
+ gap: 12px !important;
291
+ width: 100% !important;
292
+ max-width: 800px !important;
293
+ margin: -32px auto 40px auto !important;
294
+ background: #f8fafc !important;
295
+ border: 1px solid #e2e8f0 !important;
296
+ border-top: none !important;
297
+ border-radius: 0 0 12px 12px !important;
298
+ padding: 10px 24px 24px 24px !important;
299
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05) !important;
300
+ position: relative !important;
301
+ z-index: 1 !important;
302
  }
303
+
304
+ /* 개별 버튼 디자인 (연보라색 테마 & 강력한 중앙 정렬) */
305
+ .examples-container button, div[data-testid="chatbot"] button.example, button.example, .example-btn {
306
+ border-radius: 8px !important;
307
+ padding: 16px !important;
308
+ text-align: center !important;
309
+ font-size: 14px !important;
310
  font-weight: 600 !important;
311
+ color: #4c1d95 !important;
312
+ background: #f5f3ff !important;
313
+ background-color: #f5f3ff !important;
314
+ border: 1px solid #e9d5ff !important;
315
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) !important;
316
+ transition: all 0.2s ease-in-out !important;
317
+ display: flex !important;
318
+ align-items: center !important;
319
+ justify-content: center !important;
320
+ min-height: 80px !important;
321
+ width: 100% !important;
322
+ white-space: normal !important;
323
  }
324
+
325
+ .examples-container button:hover, div[data-testid="chatbot"] button.example:hover, button.example:hover, .example-btn:hover {
326
+ border-color: #a855f7 !important;
327
+ background: #f3e8ff !important;
328
+ background-color: #f3e8ff !important;
329
+ transform: translateY(-2px) !important;
330
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.08) !important;
331
+ color: #7c3aed !important;
332
  }
333
 
334
  /* ── 전송 버튼: 너비 넓고 높이 입력창에 맞춤 ── */
335
+ button[class*="submit-btn"], #submit-btn, button[id*="submit"], button.submit-button {
 
 
336
  background: linear-gradient(135deg, #1e3a5f 0%, #7c3aed 100%) !important;
337
  color: white !important;
338
  font-weight: 700 !important;
 
350
  align-items: center !important;
351
  justify-content: center !important;
352
  box-sizing: border-box !important;
353
+ opacity: 1 !important;
354
+ visibility: visible !important;
355
  }
356
  button[class*="submit-btn"]:hover,
357
  [data-testid="submit-button"]:hover {
 
391
  align-items: center !important;
392
  }
393
 
 
 
 
 
 
 
 
394
  /* ── 챗봇 탭/라벨 숨김 ── */
395
  .chatbot > div:first-child, [class*="chatbot"] > div:first-child,
396
  .chatbot-label, div[class*="chatbot"] .label,
 
407
  min-height: auto !important;
408
  }
409
 
410
+ /* ── 사용자 버블 (다크그레이 프리미엄 테마) ── */
411
+ .message.user, [data-testid="user"] .message {
412
+ background-color: #111827 !important;
413
+ border-radius: 12px 12px 0 12px !important;
414
+ padding: 7px 13px !important;
415
+ margin: 2px 0 !important;
416
+ border: none !important;
417
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.08) !important;
418
+ min-height: unset !important;
419
  }
420
+ [data-testid="user"] > div, .bubble-wrap [data-testid="user"], .message-wrap.user > div, .message-row.user {
421
+ background: transparent !important;
422
+ background-color: transparent !important;
423
+ border: none !important;
424
+ }
425
+ [data-testid="user"] .message *, .message.user * {
426
+ color: #ffffff !important;
427
+ line-height: 1.4 !important;
428
+ margin: 0 !important;
429
  background: transparent !important;
430
  }
431
 
432
+ /* ── 봇 버블 (화이트 & 그레이 경계선 테마) ── */
433
+ .message.bot, [data-testid="bot"] .message, [data-testid="bot"] > div, .message-wrap.bot > div, .message.bot, .message-row.bot .message {
434
+ background-color: #ffffff !important;
435
+ color: #1f2937 !important;
436
+ border: 1px solid #e5e7eb !important;
437
+ border-radius: 12px 12px 12px 0 !important;
438
+ padding: 16px 20px !important;
439
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05) !important;
440
  }
441
  .message.bot p, .message.bot span,
442
  .message.bot li, .message.bot div {
 
496
  border-color: rgba(124,58,237,0.24) !important;
497
  }
498
 
499
+ /* ── 메인 레이아웃 컬럼 높이 동기화 ── */
500
  #main-row { align-items: stretch !important; }
501
  #main-row > div[class*="column"] {
502
  display: flex !important;