angkit007 commited on
Commit
03e0f64
·
1 Parent(s): 7f40688
Files changed (1) hide show
  1. app.py +180 -64
app.py CHANGED
@@ -15,9 +15,6 @@ import spaces
15
  from sklearn.feature_extraction.text import TfidfVectorizer
16
  from sklearn.metrics.pairwise import cosine_similarity
17
 
18
- # ---------------------------------------------------------------------------
19
- # Resume content — the single source of truth the retrieval engine indexes.
20
- # ---------------------------------------------------------------------------
21
  CORPUS = [
22
  {"tag": "Experience · Flexday AI", "text": "Built and pitched INFERA, an AI-powered agentic solution that maps sales projects to real-world opportunities, winning 1st place at the Flexday AI Hackathon."},
23
  {"tag": "Experience · Flexday AI", "text": "Optimized a semantic search system using LLM and embedding based techniques, improving retrieval performance by 50 percent and enhancing user experience."},
@@ -45,7 +42,6 @@ _doc_matrix = _vectorizer.fit_transform(_texts)
45
 
46
 
47
  def retrieve(query: str, top_k: int = 3):
48
- """Rank resume chunks against a query using TF-IDF cosine similarity."""
49
  if not query or not query.strip():
50
  return []
51
  q_vec = _vectorizer.transform([query])
@@ -88,9 +84,6 @@ EXAMPLE_QUERIES = [
88
  "What certifications do you have?",
89
  ]
90
 
91
- # ---------------------------------------------------------------------------
92
- # Leaderboard-style tables — sortable, scannable, MTEB-inspired.
93
- # ---------------------------------------------------------------------------
94
  SKILLS_DF = pd.DataFrame([
95
  {"Category": "AI/ML & GenAI", "Skills": "LLMs, Generative AI, Agentic AI, Prompt Engineering, Semantic Search, Classification, Regression, Decision Trees, SMOTE, OCR/NLP"},
96
  {"Category": "Programming", "Skills": "Python, JavaScript, Node.js"},
@@ -121,18 +114,44 @@ EDUCATION_DF = pd.DataFrame([
121
  {"Degree": "B.Tech, Computer Science & Engineering", "Institution": "KIET Group of Institutions", "Years": "2012–2016", "Highlight": "First Division"},
122
  ])
123
 
124
- # ---------------------------------------------------------------------------
125
- # Styling — dark "console" theme matching the static-site edition
126
- # ---------------------------------------------------------------------------
127
  CUSTOM_CSS = """
 
 
128
  :root {
129
  --amber: #f5b841;
 
130
  --teal: #4fd1c5;
 
 
 
 
 
 
131
  }
 
132
  .gradio-container {
133
- background: radial-gradient(ellipse 1200px 800px at 20% -10%, #1a2130 0%, #12151c 55%) !important;
 
 
 
 
134
  font-family: 'Inter', sans-serif !important;
 
135
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  @keyframes revealUp {
137
  from { opacity: 0; transform: translateY(22px); }
138
  to { opacity: 1; transform: translateY(0); }
@@ -146,75 +165,155 @@ CUSTOM_CSS = """
146
  #hero-headline { animation-delay: 0.28s; }
147
  #hero-bio { animation-delay: 0.40s; }
148
  #hero-contact { animation-delay: 0.52s; }
 
149
  #hero-name {
150
  font-family: 'Space Grotesk', sans-serif !important;
151
  font-weight: 700 !important;
152
- font-size: 58px !important;
153
- letter-spacing: -0.02em !important;
154
  line-height: 1.05 !important;
155
- margin-bottom: 4px !important;
156
- background: linear-gradient(180deg, #ffffff 0%, #c9d2e3 100%);
157
  -webkit-background-clip: text;
158
  background-clip: text;
159
  -webkit-text-fill-color: transparent;
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  }
161
- #hero-headline { color: var(--amber) !important; font-weight: 600 !important; font-size: 19px !important; margin-top: 6px !important; }
162
  .status-badge {
163
  display: inline-flex; align-items: center; gap: 8px;
164
- font-family: monospace; font-size: 12px; letter-spacing: 0.1em;
165
- color: #9aa3b5; text-transform: uppercase; margin-bottom: 10px;
166
  }
167
  .dot {
168
- width: 8px; height: 8px; border-radius: 50%; background: var(--amber);
 
 
169
  display: inline-block; animation: pulse 2.2s infinite;
170
  }
171
  @keyframes pulse {
172
- 0% { box-shadow: 0 0 0 0 rgba(245,184,65,.55); }
173
- 70% { box-shadow: 0 0 0 9px rgba(245,184,65,0); }
174
- 100% { box-shadow: 0 0 0 0 rgba(245,184,65,0); }
 
 
 
 
 
 
175
  }
 
 
176
  .section-label {
177
- font-family: monospace !important; color: var(--amber) !important;
178
- letter-spacing: 0.1em !important; text-transform: uppercase; font-size: 13px !important;
 
179
  }
180
- #hero-contact a {
181
- color: #9aa3b5; text-decoration: none; border-bottom: 1px solid transparent;
182
- transition: color .18s ease, border-color .18s ease;
 
 
 
 
 
 
 
183
  }
184
- #hero-contact a:hover { color: var(--teal) !important; border-color: var(--teal); }
 
 
 
 
 
 
185
  .gradio-container button {
186
- transition: transform .15s ease, border-color .15s ease, box-shadow .15s ease !important;
 
 
 
 
 
 
 
 
187
  }
188
- .gradio-container button:hover {
189
- transform: translateY(-2px);
190
  }
 
191
  .tabs > .tab-nav {
192
- border-bottom: 1px solid #2a3040 !important;
193
- gap: 4px !important;
 
 
 
 
 
 
194
  }
195
  .tabs > .tab-nav button {
196
- font-family: monospace !important;
197
- font-size: 13px !important;
198
- color: #9aa3b5 !important;
199
  border: none !important;
200
  background: transparent !important;
201
- padding: 10px 16px !important;
 
 
202
  }
203
  .tabs > .tab-nav button.selected {
204
- color: var(--amber) !important;
205
- border-bottom: 2px solid var(--amber) !important;
206
- font-weight: 600 !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
  }
208
- table {
209
- font-size: 13.5px !important;
 
 
 
 
 
 
 
 
210
  }
211
- thead th {
212
- font-family: monospace !important;
 
213
  text-transform: uppercase !important;
214
- font-size: 11px !important;
215
- letter-spacing: 0.06em !important;
216
  color: var(--amber) !important;
 
217
  }
 
 
218
  """
219
 
220
  with gr.Blocks(title="Angkit Sarma — Living CV") as demo:
@@ -223,32 +322,41 @@ with gr.Blocks(title="Angkit Sarma — Living CV") as demo:
223
  """
224
  <div class="status-badge"><span class="dot"></span> resume · live · self-querying</div>
225
  <div id="hero-name">Angkit Sarma</div>
226
- <div id="hero-headline">AI/ML Engineer — Agentic Systems &amp; LLM Applications</div>
227
- <p id="hero-bio" style="color:#9aa3b5; max-width:680px; margin-top:14px;">
228
  4+ years building and shipping ML and generative AI systems — from a 50%-faster semantic
229
  search pipeline to <b style="color:#eef0f4">INFERA</b>, an agentic AI tool that won 1st place
230
  at the Flexday AI Hackathon. Ask the panel below anything about my experience — it's a live
231
  TF-IDF retrieval engine running over this résumé's own content.
232
  </p>
233
- <p id="hero-contact" style="font-family:monospace; font-size:13px;">
234
- +91 9990797061 &nbsp;·&nbsp; angkit93@gmail.com &nbsp;·&nbsp;
 
235
  <a href="https://www.linkedin.com/in/angkit-s-81b7131b0/" target="_blank">LinkedIn</a>
236
- &nbsp;·&nbsp;
237
  <a href="https://github.com/angkit-hash" target="_blank">GitHub</a>
238
- &nbsp;·&nbsp; Hyderabad, India
239
  </p>
240
  """
241
  )
242
 
243
- gr.HTML('<p class="section-label">// ask the cv</p>')
244
- chatbot = gr.Chatbot(label=None, height=320, show_label=False)
245
- with gr.Row():
246
- query_box = gr.Textbox(placeholder="e.g. What's your experience with LLMs?", scale=5, show_label=False, container=False)
247
- ask_btn = gr.Button("Ask", variant="primary", scale=1)
 
 
 
 
 
 
 
 
 
248
 
249
- with gr.Row():
250
- for q in EXAMPLE_QUERIES:
251
- gr.Button(q, size="sm").click(fn=ask_the_cv, inputs=[gr.State(q), chatbot], outputs=[chatbot, query_box])
252
 
253
  ask_btn.click(fn=ask_the_cv, inputs=[query_box, chatbot], outputs=[chatbot, query_box])
254
  query_box.submit(fn=ask_the_cv, inputs=[query_box, chatbot], outputs=[chatbot, query_box])
@@ -267,6 +375,8 @@ with gr.Blocks(title="Angkit Sarma — Living CV") as demo:
267
  gr.Dataframe(
268
  value=IMPACT_DF, interactive=False, wrap=True,
269
  column_widths=["55%", "25%", "20%"],
 
 
270
  )
271
 
272
  with gr.Tab("Experience"):
@@ -298,14 +408,14 @@ with gr.Blocks(title="Angkit Sarma — Living CV") as demo:
298
 
299
  with gr.Tab("Projects"):
300
  with gr.Row():
301
- with gr.Column():
302
  gr.Markdown("**INFERA** — Agentic AI Sales-Opportunity Mapper\n\n*LLMs · AI Agents · Python*\n\nAn AI agent that analyzes sales pipeline data and autonomously maps projects to real-world business opportunities.\n\n🏆 1st Place — Flexday AI Hackathon")
303
- with gr.Column():
304
  gr.Markdown("**Analytica** — End-to-End ML Analytics Platform\n\n*React · Python · Azure · SQL*\n\nFull-stack analytics tool surfacing ML model performance metrics and usage statistics.")
305
- with gr.Column():
306
  gr.Markdown("**Predictive Allocation** — ML Deployment Pipeline\n\n*Python · Azure SQL · Azure Blob · DevOps*\n\nRe-engineered end-to-end training/deployment pipeline; hardened security with Snyk and Wiz.")
307
  gr.HTML(
308
- '<p style="font-family:monospace; font-size:13px; margin-top:10px;">'
309
  '<a href="https://github.com/angkit-hash" target="_blank" style="color:#4fd1c5; text-decoration:none; border-bottom:1px solid #4fd1c5;">'
310
  '→ View source &amp; more projects on GitHub</a></p>'
311
  )
@@ -314,6 +424,8 @@ with gr.Blocks(title="Angkit Sarma — Living CV") as demo:
314
  gr.Dataframe(
315
  value=SKILLS_DF, interactive=False, wrap=True,
316
  column_widths=["25%", "75%"],
 
 
317
  )
318
 
319
  with gr.Tab("Certifications & Education"):
@@ -321,11 +433,15 @@ with gr.Blocks(title="Angkit Sarma — Living CV") as demo:
321
  gr.Dataframe(
322
  value=CERTS_DF, interactive=False, wrap=True,
323
  column_widths=["55%", "45%"],
 
 
324
  )
325
  gr.HTML('<p class="section-label" style="margin-top:22px;">Education</p>')
326
  gr.Dataframe(
327
  value=EDUCATION_DF, interactive=False, wrap=True,
328
  column_widths=["30%", "28%", "14%", "28%"],
 
 
329
  )
330
 
331
  if __name__ == "__main__":
 
15
  from sklearn.feature_extraction.text import TfidfVectorizer
16
  from sklearn.metrics.pairwise import cosine_similarity
17
 
 
 
 
18
  CORPUS = [
19
  {"tag": "Experience · Flexday AI", "text": "Built and pitched INFERA, an AI-powered agentic solution that maps sales projects to real-world opportunities, winning 1st place at the Flexday AI Hackathon."},
20
  {"tag": "Experience · Flexday AI", "text": "Optimized a semantic search system using LLM and embedding based techniques, improving retrieval performance by 50 percent and enhancing user experience."},
 
42
 
43
 
44
  def retrieve(query: str, top_k: int = 3):
 
45
  if not query or not query.strip():
46
  return []
47
  q_vec = _vectorizer.transform([query])
 
84
  "What certifications do you have?",
85
  ]
86
 
 
 
 
87
  SKILLS_DF = pd.DataFrame([
88
  {"Category": "AI/ML & GenAI", "Skills": "LLMs, Generative AI, Agentic AI, Prompt Engineering, Semantic Search, Classification, Regression, Decision Trees, SMOTE, OCR/NLP"},
89
  {"Category": "Programming", "Skills": "Python, JavaScript, Node.js"},
 
114
  {"Degree": "B.Tech, Computer Science & Engineering", "Institution": "KIET Group of Institutions", "Years": "2012–2016", "Highlight": "First Division"},
115
  ])
116
 
 
 
 
117
  CUSTOM_CSS = """
118
+ @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500;600;700&display=swap');
119
+
120
  :root {
121
  --amber: #f5b841;
122
+ --amber-deep: #f97316;
123
  --teal: #4fd1c5;
124
+ --bg-0: #0d0f16;
125
+ --bg-1: #12151f;
126
+ --card: rgba(255,255,255,0.035);
127
+ --card-border: rgba(255,255,255,0.09);
128
+ --text-dim: #9aa3b5;
129
+ --text-faint: #6b7280;
130
  }
131
+
132
  .gradio-container {
133
+ background:
134
+ radial-gradient(ellipse 900px 500px at 15% -8%, rgba(245,184,65,0.10) 0%, transparent 60%),
135
+ radial-gradient(ellipse 700px 600px at 100% 10%, rgba(79,209,197,0.08) 0%, transparent 55%),
136
+ radial-gradient(ellipse 1400px 900px at 50% 0%, #171b28 0%, var(--bg-0) 60%) !important;
137
+ background-attachment: fixed !important;
138
  font-family: 'Inter', sans-serif !important;
139
+ position: relative;
140
  }
141
+ .gradio-container::before {
142
+ content: "";
143
+ position: fixed; inset: 0; pointer-events: none; z-index: 0;
144
+ background-image:
145
+ linear-gradient(rgba(255,255,255,0.025) 1px, transparent 1px),
146
+ linear-gradient(90deg, rgba(255,255,255,0.025) 1px, transparent 1px);
147
+ background-size: 48px 48px;
148
+ mask-image: radial-gradient(ellipse 900px 600px at 20% 0%, black 0%, transparent 70%);
149
+ }
150
+ ::-webkit-scrollbar { width: 10px; height: 10px; }
151
+ ::-webkit-scrollbar-track { background: var(--bg-0); }
152
+ ::-webkit-scrollbar-thumb { background: #2a3040; border-radius: 8px; }
153
+ ::-webkit-scrollbar-thumb:hover { background: var(--amber-deep); }
154
+
155
  @keyframes revealUp {
156
  from { opacity: 0; transform: translateY(22px); }
157
  to { opacity: 1; transform: translateY(0); }
 
165
  #hero-headline { animation-delay: 0.28s; }
166
  #hero-bio { animation-delay: 0.40s; }
167
  #hero-contact { animation-delay: 0.52s; }
168
+
169
  #hero-name {
170
  font-family: 'Space Grotesk', sans-serif !important;
171
  font-weight: 700 !important;
172
+ font-size: 60px !important;
173
+ letter-spacing: -0.025em !important;
174
  line-height: 1.05 !important;
175
+ margin-bottom: 6px !important;
176
+ background: linear-gradient(180deg, #ffffff 0%, #b9c3d9 100%);
177
  -webkit-background-clip: text;
178
  background-clip: text;
179
  -webkit-text-fill-color: transparent;
180
+ filter: drop-shadow(0 2px 24px rgba(245,184,65,0.08));
181
+ }
182
+ #hero-headline {
183
+ display: inline-block;
184
+ color: var(--amber) !important;
185
+ font-family: 'Space Grotesk', sans-serif !important;
186
+ font-weight: 600 !important;
187
+ font-size: 18px !important;
188
+ margin-top: 8px !important;
189
+ padding: 6px 16px !important;
190
+ background: rgba(245,184,65,0.08);
191
+ border: 1px solid rgba(245,184,65,0.25);
192
+ border-radius: 999px;
193
  }
 
194
  .status-badge {
195
  display: inline-flex; align-items: center; gap: 8px;
196
+ font-family: 'JetBrains Mono', monospace; font-size: 12px; letter-spacing: 0.12em;
197
+ color: var(--text-dim); text-transform: uppercase; margin-bottom: 14px;
198
  }
199
  .dot {
200
+ width: 8px; height: 8px; border-radius: 50%;
201
+ background: var(--amber);
202
+ box-shadow: 0 0 12px 2px rgba(245,184,65,0.7);
203
  display: inline-block; animation: pulse 2.2s infinite;
204
  }
205
  @keyframes pulse {
206
+ 0% { box-shadow: 0 0 0 0 rgba(245,184,65,.55), 0 0 12px 2px rgba(245,184,65,0.7); }
207
+ 70% { box-shadow: 0 0 0 9px rgba(245,184,65,0), 0 0 12px 2px rgba(245,184,65,0.7); }
208
+ 100% { box-shadow: 0 0 0 0 rgba(245,184,65,0), 0 0 12px 2px rgba(245,184,65,0.7); }
209
+ }
210
+ #hero-contact a {
211
+ color: var(--text-dim); text-decoration: none;
212
+ padding: 4px 12px; border-radius: 999px;
213
+ border: 1px solid var(--card-border); background: var(--card);
214
+ transition: all .18s ease;
215
  }
216
+ #hero-contact a:hover { color: #0d0f16 !important; background: var(--teal); border-color: var(--teal); }
217
+
218
  .section-label {
219
+ font-family: 'JetBrains Mono', monospace !important; color: var(--amber) !important;
220
+ letter-spacing: 0.12em !important; text-transform: uppercase; font-size: 12.5px !important;
221
+ font-weight: 600 !important;
222
  }
223
+
224
+ .ask-card {
225
+ background: var(--card) !important;
226
+ border: 1px solid var(--card-border) !important;
227
+ border-radius: 18px !important;
228
+ backdrop-filter: blur(18px);
229
+ box-shadow: 0 20px 60px -20px rgba(0,0,0,0.6), inset 0 1px 0 rgba(255,255,255,0.04) !important;
230
+ padding: 22px !important;
231
+ position: relative;
232
+ z-index: 1;
233
  }
234
+ .ask-titlebar {
235
+ display: flex; align-items: center; gap: 8px; margin-bottom: 14px;
236
+ font-family: 'JetBrains Mono', monospace; font-size: 11.5px; color: var(--text-faint);
237
+ letter-spacing: 0.08em;
238
+ }
239
+ .ask-titlebar .tl-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
240
+
241
  .gradio-container button {
242
+ transition: transform .16s ease, border-color .16s ease, box-shadow .16s ease, background .16s ease !important;
243
+ }
244
+ .gradio-container button:hover { transform: translateY(-2px); }
245
+ button.primary, button[class*="primary"] {
246
+ background: linear-gradient(135deg, var(--amber) 0%, var(--amber-deep) 100%) !important;
247
+ border: none !important;
248
+ box-shadow: 0 8px 24px -8px rgba(245,184,65,0.55) !important;
249
+ color: #1a1305 !important;
250
+ font-weight: 700 !important;
251
  }
252
+ button.primary:hover, button[class*="primary"]:hover {
253
+ box-shadow: 0 12px 32px -8px rgba(245,184,65,0.75) !important;
254
  }
255
+
256
  .tabs > .tab-nav {
257
+ border-bottom: none !important;
258
+ background: var(--card);
259
+ border: 1px solid var(--card-border);
260
+ border-radius: 999px !important;
261
+ padding: 5px !important;
262
+ display: inline-flex !important;
263
+ gap: 2px !important;
264
+ margin-bottom: 18px;
265
  }
266
  .tabs > .tab-nav button {
267
+ font-family: 'JetBrains Mono', monospace !important;
268
+ font-size: 12.5px !important;
269
+ color: var(--text-dim) !important;
270
  border: none !important;
271
  background: transparent !important;
272
+ border-radius: 999px !important;
273
+ padding: 9px 18px !important;
274
+ margin: 0 !important;
275
  }
276
  .tabs > .tab-nav button.selected {
277
+ background: linear-gradient(135deg, var(--amber) 0%, var(--amber-deep) 100%) !important;
278
+ color: #1a1305 !important;
279
+ font-weight: 700 !important;
280
+ box-shadow: 0 6px 18px -6px rgba(245,184,65,0.6);
281
+ }
282
+
283
+ .proj-card {
284
+ background: var(--card) !important;
285
+ border: 1px solid var(--card-border) !important;
286
+ border-radius: 14px !important;
287
+ padding: 18px !important;
288
+ transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease !important;
289
+ }
290
+ .proj-card:hover {
291
+ transform: translateY(-4px);
292
+ border-color: rgba(245,184,65,0.4) !important;
293
+ box-shadow: 0 16px 40px -16px rgba(245,184,65,0.25) !important;
294
  }
295
+
296
+ .gr-accordion, [class*="accordion"] {
297
+ border-radius: 14px !important;
298
+ }
299
+
300
+ .cv-table {
301
+ border-radius: 14px !important;
302
+ overflow: hidden !important;
303
+ border: 1px solid var(--card-border) !important;
304
+ box-shadow: 0 12px 32px -18px rgba(0,0,0,0.6);
305
  }
306
+ .cv-table table { font-size: 13.5px !important; }
307
+ .cv-table thead th {
308
+ font-family: 'JetBrains Mono', monospace !important;
309
  text-transform: uppercase !important;
310
+ font-size: 10.5px !important;
311
+ letter-spacing: 0.08em !important;
312
  color: var(--amber) !important;
313
+ background: rgba(245,184,65,0.06) !important;
314
  }
315
+ .cv-table tbody tr:nth-child(even) { background: rgba(255,255,255,0.02) !important; }
316
+ .cv-table tbody tr:hover { background: rgba(245,184,65,0.05) !important; }
317
  """
318
 
319
  with gr.Blocks(title="Angkit Sarma — Living CV") as demo:
 
322
  """
323
  <div class="status-badge"><span class="dot"></span> resume · live · self-querying</div>
324
  <div id="hero-name">Angkit Sarma</div>
325
+ <div><span id="hero-headline">AI/ML Engineer — Agentic Systems &amp; LLM Applications</span></div>
326
+ <p id="hero-bio" style="color:#9aa3b5; max-width:680px; margin-top:16px; line-height:1.6;">
327
  4+ years building and shipping ML and generative AI systems — from a 50%-faster semantic
328
  search pipeline to <b style="color:#eef0f4">INFERA</b>, an agentic AI tool that won 1st place
329
  at the Flexday AI Hackathon. Ask the panel below anything about my experience — it's a live
330
  TF-IDF retrieval engine running over this résumé's own content.
331
  </p>
332
+ <p id="hero-contact" style="font-family:'JetBrains Mono',monospace; font-size:12.5px; margin-top:16px; display:flex; flex-wrap:wrap; gap:8px; align-items:center;">
333
+ <a href="tel:+919990797061">+91 9990797061</a>
334
+ <a href="mailto:angkit93@gmail.com">angkit93@gmail.com</a>
335
  <a href="https://www.linkedin.com/in/angkit-s-81b7131b0/" target="_blank">LinkedIn</a>
 
336
  <a href="https://github.com/angkit-hash" target="_blank">GitHub</a>
337
+ <a href="#" style="pointer-events:none;">Hyderabad, India</a>
338
  </p>
339
  """
340
  )
341
 
342
+ gr.HTML('<p class="section-label" style="margin-top:8px;">// ask the cv</p>')
343
+ with gr.Group(elem_classes=["ask-card"]):
344
+ gr.HTML(
345
+ '<div class="ask-titlebar">'
346
+ '<span class="tl-dot" style="background:#ff5f57;"></span>'
347
+ '<span class="tl-dot" style="background:#febc2e;"></span>'
348
+ '<span class="tl-dot" style="background:#28c840;"></span>'
349
+ '&nbsp;&nbsp;ask_the_cv.py — live TF-IDF retrieval, runs in this Space'
350
+ '</div>'
351
+ )
352
+ chatbot = gr.Chatbot(label=None, height=320, show_label=False)
353
+ with gr.Row():
354
+ query_box = gr.Textbox(placeholder="e.g. What's your experience with LLMs?", scale=5, show_label=False, container=False)
355
+ ask_btn = gr.Button("Ask", variant="primary", scale=1)
356
 
357
+ with gr.Row():
358
+ for q in EXAMPLE_QUERIES:
359
+ gr.Button(q, size="sm").click(fn=ask_the_cv, inputs=[gr.State(q), chatbot], outputs=[chatbot, query_box])
360
 
361
  ask_btn.click(fn=ask_the_cv, inputs=[query_box, chatbot], outputs=[chatbot, query_box])
362
  query_box.submit(fn=ask_the_cv, inputs=[query_box, chatbot], outputs=[chatbot, query_box])
 
375
  gr.Dataframe(
376
  value=IMPACT_DF, interactive=False, wrap=True,
377
  column_widths=["55%", "25%", "20%"],
378
+ row_count=(len(IMPACT_DF), "fixed"),
379
+ elem_classes=["cv-table"],
380
  )
381
 
382
  with gr.Tab("Experience"):
 
408
 
409
  with gr.Tab("Projects"):
410
  with gr.Row():
411
+ with gr.Column(elem_classes=["proj-card"]):
412
  gr.Markdown("**INFERA** — Agentic AI Sales-Opportunity Mapper\n\n*LLMs · AI Agents · Python*\n\nAn AI agent that analyzes sales pipeline data and autonomously maps projects to real-world business opportunities.\n\n🏆 1st Place — Flexday AI Hackathon")
413
+ with gr.Column(elem_classes=["proj-card"]):
414
  gr.Markdown("**Analytica** — End-to-End ML Analytics Platform\n\n*React · Python · Azure · SQL*\n\nFull-stack analytics tool surfacing ML model performance metrics and usage statistics.")
415
+ with gr.Column(elem_classes=["proj-card"]):
416
  gr.Markdown("**Predictive Allocation** — ML Deployment Pipeline\n\n*Python · Azure SQL · Azure Blob · DevOps*\n\nRe-engineered end-to-end training/deployment pipeline; hardened security with Snyk and Wiz.")
417
  gr.HTML(
418
+ '<p style="font-family:\'JetBrains Mono\',monospace; font-size:13px; margin-top:14px;">'
419
  '<a href="https://github.com/angkit-hash" target="_blank" style="color:#4fd1c5; text-decoration:none; border-bottom:1px solid #4fd1c5;">'
420
  '→ View source &amp; more projects on GitHub</a></p>'
421
  )
 
424
  gr.Dataframe(
425
  value=SKILLS_DF, interactive=False, wrap=True,
426
  column_widths=["25%", "75%"],
427
+ row_count=(len(SKILLS_DF), "fixed"),
428
+ elem_classes=["cv-table"],
429
  )
430
 
431
  with gr.Tab("Certifications & Education"):
 
433
  gr.Dataframe(
434
  value=CERTS_DF, interactive=False, wrap=True,
435
  column_widths=["55%", "45%"],
436
+ row_count=(len(CERTS_DF), "fixed"),
437
+ elem_classes=["cv-table"],
438
  )
439
  gr.HTML('<p class="section-label" style="margin-top:22px;">Education</p>')
440
  gr.Dataframe(
441
  value=EDUCATION_DF, interactive=False, wrap=True,
442
  column_widths=["30%", "28%", "14%", "28%"],
443
+ row_count=(len(EDUCATION_DF), "fixed"),
444
+ elem_classes=["cv-table"],
445
  )
446
 
447
  if __name__ == "__main__":