ysharma HF Staff commited on
Commit
d15c9e2
Β·
verified Β·
1 Parent(s): 528a001

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +922 -0
app.py ADDED
@@ -0,0 +1,922 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Build Small β€” Gradio + Hugging Face Hackathon
3
+ Org README Space.
4
+
5
+ This Space renders the hackathon landing page using gr.HTML().
6
+ Custom CSS strips Gradio's default container so the design renders edge-to-edge.
7
+ """
8
+
9
+ import gradio as gr
10
+
11
+
12
+ HEAD_HTML = """
13
+ <link rel="preconnect" href="https://fonts.googleapis.com">
14
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
15
+ <link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght,SOFT@9..144,300..900,0..100&family=EB+Garamond:ital,wght@0,400;0,500;0,600;1,400&family=Caveat:wght@500;700&display=swap" rel="stylesheet">
16
+ """
17
+
18
+ # Override Gradio's default container so the landing page renders edge-to-edge
19
+ CUSTOM_CSS = """
20
+ .gradio-container {
21
+ max-width: 100% !important;
22
+ padding: 0 !important;
23
+ margin: 0 !important;
24
+ background: #F2EAD8 !important;
25
+ }
26
+ .gradio-container > .main, .gradio-container > .wrap, .main, .wrap {
27
+ padding: 0 !important;
28
+ margin: 0 !important;
29
+ max-width: 100% !important;
30
+ }
31
+ .app, .container, .contain {
32
+ padding: 0 !important;
33
+ margin: 0 !important;
34
+ max-width: 100% !important;
35
+ }
36
+ footer { display: none !important; }
37
+ .show-api { display: none !important; }
38
+ .built-with { display: none !important; }
39
+ body { background: #F2EAD8 !important; }
40
+ """
41
+
42
+ LANDING_HTML = r"""
43
+ <style>
44
+ :root {
45
+ --paper: #F2EAD8;
46
+ --paper-deep: #E8DEC6;
47
+ --ink: #1E1A12;
48
+ --ink-soft: #4A3F2E;
49
+ --moss: #3D5A3A;
50
+ --moss-deep: #2A3F28;
51
+ --ember: #B8501E;
52
+ --ember-soft: #D67A3F;
53
+ --gold: #B98C2C;
54
+ --sage: #8FA689;
55
+ --twilight: #2C3338;
56
+ --rule: rgba(30, 26, 18, 0.18);
57
+ }
58
+
59
+ /* Scoped reset for the landing wrapper only */
60
+ .build-small * { box-sizing: border-box; margin: 0; padding: 0; }
61
+ .build-small {
62
+ background: var(--paper);
63
+ color: var(--ink);
64
+ font-family: 'EB Garamond', Georgia, serif;
65
+ font-size: 19px;
66
+ line-height: 1.55;
67
+ overflow-x: hidden;
68
+ background-image:
69
+ radial-gradient(circle at 20% 10%, rgba(184,80,30,0.04) 0%, transparent 40%),
70
+ radial-gradient(circle at 80% 90%, rgba(61,90,58,0.05) 0%, transparent 45%),
71
+ url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.12 0 0 0 0 0.10 0 0 0 0 0.07 0 0 0 0.08 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
72
+ width: 100%;
73
+ min-height: 100vh;
74
+ }
75
+ .build-small .display { font-family: 'Fraunces', 'Times New Roman', serif; font-variation-settings: "SOFT" 100, "opsz" 144; }
76
+ .build-small .hand { font-family: 'Caveat', cursive; }
77
+
78
+ /* ========= NAV ========= */
79
+ .build-small nav {
80
+ position: sticky; top: 0; z-index: 50;
81
+ backdrop-filter: blur(8px);
82
+ background: rgba(242, 234, 216, 0.85);
83
+ border-bottom: 1px solid var(--rule);
84
+ }
85
+ .build-small nav .inner {
86
+ max-width: 1200px; margin: 0 auto;
87
+ padding: 18px 32px;
88
+ display: flex; justify-content: space-between; align-items: center;
89
+ gap: 24px;
90
+ }
91
+ .build-small .brand {
92
+ font-family: 'Fraunces', serif;
93
+ font-weight: 600;
94
+ font-size: 18px;
95
+ letter-spacing: 0.02em;
96
+ font-variation-settings: "SOFT" 100;
97
+ }
98
+ .build-small .brand .sm { color: var(--ember); font-style: italic; }
99
+ .build-small nav ul {
100
+ display: flex; gap: 28px; list-style: none;
101
+ font-family: 'EB Garamond', serif;
102
+ font-size: 16px;
103
+ }
104
+ .build-small nav a { color: var(--ink-soft); text-decoration: none; transition: color 0.2s; }
105
+ .build-small nav a:hover { color: var(--ember); }
106
+ .build-small .register-btn {
107
+ background: var(--ink);
108
+ color: var(--paper);
109
+ padding: 10px 22px;
110
+ border-radius: 999px;
111
+ font-family: 'Fraunces', serif;
112
+ font-size: 14px;
113
+ font-weight: 500;
114
+ letter-spacing: 0.04em;
115
+ text-transform: uppercase;
116
+ transition: transform 0.2s, background 0.2s;
117
+ text-decoration: none;
118
+ }
119
+ .build-small .register-btn:hover { background: var(--ember); color: var(--paper); transform: translateY(-1px); }
120
+
121
+ /* ========= HERO ========= */
122
+ .build-small .hero {
123
+ max-width: 1200px;
124
+ margin: 0 auto;
125
+ padding: 80px 32px 60px;
126
+ position: relative;
127
+ text-align: center;
128
+ }
129
+ .build-small .hero .kicker {
130
+ font-family: 'Caveat', cursive;
131
+ font-size: 26px;
132
+ color: var(--ember);
133
+ margin-bottom: 12px;
134
+ transform: rotate(-1.5deg);
135
+ display: inline-block;
136
+ }
137
+ .build-small .hero h1 {
138
+ font-family: 'Fraunces', serif;
139
+ font-variation-settings: "SOFT" 100, "opsz" 144, "wght" 600;
140
+ font-size: clamp(64px, 12vw, 168px);
141
+ line-height: 0.92;
142
+ letter-spacing: -0.03em;
143
+ color: var(--ink);
144
+ margin: 8px 0 24px;
145
+ }
146
+ .build-small .hero h1 em {
147
+ font-style: italic;
148
+ color: var(--ember);
149
+ font-variation-settings: "SOFT" 100, "opsz" 144, "wght" 500;
150
+ }
151
+ .build-small .hero .lede {
152
+ font-size: 22px;
153
+ line-height: 1.5;
154
+ color: var(--ink-soft);
155
+ max-width: 640px;
156
+ margin: 0 auto 36px;
157
+ }
158
+ .build-small .hero .meta-row {
159
+ display: inline-flex;
160
+ gap: 32px;
161
+ align-items: center;
162
+ padding: 14px 28px;
163
+ border: 1px solid var(--rule);
164
+ border-radius: 999px;
165
+ background: rgba(255,255,255,0.4);
166
+ font-size: 15px;
167
+ color: var(--ink-soft);
168
+ flex-wrap: wrap;
169
+ justify-content: center;
170
+ }
171
+ .build-small .hero .meta-row .dot { color: var(--ember); }
172
+ .build-small .hero .meta-row strong { color: var(--ink); font-weight: 500; }
173
+
174
+ .build-small .scribble {
175
+ display: block;
176
+ margin: 0 auto;
177
+ width: 120px;
178
+ color: var(--ember);
179
+ opacity: 0.6;
180
+ }
181
+
182
+ /* ========= INTRO ========= */
183
+ .build-small .intro {
184
+ max-width: 720px;
185
+ margin: 80px auto;
186
+ padding: 0 32px;
187
+ text-align: center;
188
+ }
189
+ .build-small .intro h2 {
190
+ font-family: 'Fraunces', serif;
191
+ font-variation-settings: "SOFT" 80;
192
+ font-size: 38px;
193
+ font-weight: 400;
194
+ font-style: italic;
195
+ color: var(--moss-deep);
196
+ margin-bottom: 24px;
197
+ line-height: 1.2;
198
+ }
199
+ .build-small .intro p {
200
+ font-size: 19px;
201
+ color: var(--ink-soft);
202
+ margin-bottom: 18px;
203
+ }
204
+ .build-small .intro p strong { color: var(--ink); font-weight: 600; }
205
+
206
+ /* ========= TRACKS ========= */
207
+ .build-small .tracks {
208
+ max-width: 1280px;
209
+ margin: 100px auto 80px;
210
+ padding: 0 32px;
211
+ }
212
+ .build-small .section-label {
213
+ text-align: center;
214
+ font-family: 'Caveat', cursive;
215
+ font-size: 28px;
216
+ color: var(--ember);
217
+ margin-bottom: 8px;
218
+ transform: rotate(-1deg);
219
+ }
220
+ .build-small .section-title {
221
+ text-align: center;
222
+ font-family: 'Fraunces', serif;
223
+ font-variation-settings: "SOFT" 100;
224
+ font-size: 56px;
225
+ font-weight: 400;
226
+ line-height: 1;
227
+ margin-bottom: 60px;
228
+ color: var(--ink);
229
+ }
230
+
231
+ .build-small .track-grid {
232
+ display: grid;
233
+ grid-template-columns: 1fr 1fr;
234
+ gap: 0;
235
+ border-top: 1px solid var(--rule);
236
+ border-bottom: 1px solid var(--rule);
237
+ }
238
+ .build-small .track {
239
+ padding: 56px 48px;
240
+ position: relative;
241
+ }
242
+ .build-small .track:first-child { border-right: 1px solid var(--rule); }
243
+ .build-small .track .chapter {
244
+ font-family: 'Caveat', cursive;
245
+ font-size: 22px;
246
+ color: var(--ember);
247
+ margin-bottom: 12px;
248
+ }
249
+ .build-small .track .illustration {
250
+ height: 140px;
251
+ display: flex;
252
+ align-items: center;
253
+ justify-content: center;
254
+ margin-bottom: 24px;
255
+ }
256
+ .build-small .track h3 {
257
+ font-family: 'Fraunces', serif;
258
+ font-variation-settings: "SOFT" 100, "wght" 500;
259
+ font-size: 42px;
260
+ line-height: 1.05;
261
+ margin-bottom: 18px;
262
+ }
263
+ .build-small .track-1 h3 { color: var(--moss-deep); }
264
+ .build-small .track-2 h3 { color: var(--ember); font-style: italic; }
265
+ .build-small .track .subtitle {
266
+ font-family: 'EB Garamond', serif;
267
+ font-style: italic;
268
+ font-size: 19px;
269
+ color: var(--ink-soft);
270
+ margin-bottom: 28px;
271
+ }
272
+ .build-small .track .body { color: var(--ink-soft); margin-bottom: 28px; }
273
+ .build-small .track .judging {
274
+ border-top: 1px dashed var(--rule);
275
+ padding-top: 24px;
276
+ }
277
+ .build-small .track .judging-label {
278
+ font-family: 'Fraunces', serif;
279
+ font-size: 13px;
280
+ text-transform: uppercase;
281
+ letter-spacing: 0.18em;
282
+ color: var(--ink-soft);
283
+ margin-bottom: 12px;
284
+ }
285
+ .build-small .track .judging ul { list-style: none; }
286
+ .build-small .track .judging li {
287
+ padding: 8px 0;
288
+ font-size: 17px;
289
+ color: var(--ink);
290
+ display: flex;
291
+ gap: 12px;
292
+ }
293
+ .build-small .track .judging li::before {
294
+ content: "✦";
295
+ color: var(--ember);
296
+ flex-shrink: 0;
297
+ }
298
+ .build-small .track-1 .judging li::before { color: var(--moss); }
299
+
300
+ /* ========= RULES ========= */
301
+ .build-small .rules {
302
+ max-width: 1080px;
303
+ margin: 100px auto;
304
+ padding: 0 32px;
305
+ }
306
+ .build-small .rules-grid {
307
+ display: grid;
308
+ grid-template-columns: repeat(3, 1fr);
309
+ gap: 0;
310
+ }
311
+ .build-small .rule-card {
312
+ padding: 36px 28px;
313
+ text-align: center;
314
+ border-right: 1px solid var(--rule);
315
+ }
316
+ .build-small .rule-card:last-child { border-right: none; }
317
+ .build-small .rule-card .icon {
318
+ font-family: 'Fraunces', serif;
319
+ font-size: 38px;
320
+ color: var(--ember);
321
+ margin-bottom: 12px;
322
+ font-variation-settings: "SOFT" 100;
323
+ font-style: italic;
324
+ }
325
+ .build-small .rule-card h4 {
326
+ font-family: 'Fraunces', serif;
327
+ font-size: 20px;
328
+ font-weight: 500;
329
+ margin-bottom: 8px;
330
+ font-variation-settings: "SOFT" 100;
331
+ }
332
+ .build-small .rule-card p {
333
+ font-size: 16px;
334
+ color: var(--ink-soft);
335
+ line-height: 1.5;
336
+ }
337
+ .build-small .rule-card .pending {
338
+ display: inline-block;
339
+ margin-top: 8px;
340
+ font-family: 'Caveat', cursive;
341
+ font-size: 15px;
342
+ color: var(--ember);
343
+ }
344
+
345
+ /* ========= HOW IT WORKS (new section, from README) ========= */
346
+ .build-small .how-it-works {
347
+ max-width: 1080px;
348
+ margin: 100px auto;
349
+ padding: 0 32px;
350
+ }
351
+ .build-small .steps {
352
+ display: grid;
353
+ grid-template-columns: repeat(4, 1fr);
354
+ gap: 24px;
355
+ margin-top: 16px;
356
+ }
357
+ .build-small .step {
358
+ padding: 32px 24px;
359
+ border: 1px solid var(--rule);
360
+ border-radius: 4px;
361
+ background: rgba(255,255,255,0.35);
362
+ position: relative;
363
+ }
364
+ .build-small .step .num {
365
+ font-family: 'Fraunces', serif;
366
+ font-style: italic;
367
+ font-variation-settings: "SOFT" 100;
368
+ font-size: 48px;
369
+ color: var(--ember);
370
+ line-height: 1;
371
+ margin-bottom: 14px;
372
+ }
373
+ .build-small .step h4 {
374
+ font-family: 'Fraunces', serif;
375
+ font-size: 22px;
376
+ font-weight: 500;
377
+ font-variation-settings: "SOFT" 80;
378
+ margin-bottom: 8px;
379
+ color: var(--ink);
380
+ }
381
+ .build-small .step p {
382
+ font-size: 16px;
383
+ color: var(--ink-soft);
384
+ line-height: 1.5;
385
+ }
386
+ .build-small .step p strong { color: var(--ink); font-weight: 600; }
387
+
388
+ /* ========= BONUS QUESTS ========= */
389
+ .build-small .bonus {
390
+ background: var(--paper-deep);
391
+ padding: 100px 32px;
392
+ border-top: 1px solid var(--rule);
393
+ border-bottom: 1px solid var(--rule);
394
+ position: relative;
395
+ overflow: hidden;
396
+ }
397
+ .build-small .bonus::before {
398
+ content: "";
399
+ position: absolute;
400
+ inset: 0;
401
+ background-image:
402
+ url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.10 0 0 0 0 0.08 0 0 0 0 0.05 0 0 0 0.10 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
403
+ pointer-events: none;
404
+ opacity: 0.5;
405
+ }
406
+ .build-small .bonus-inner {
407
+ max-width: 1080px;
408
+ margin: 0 auto;
409
+ position: relative;
410
+ }
411
+ .build-small .bonus .intro-text {
412
+ text-align: center;
413
+ max-width: 580px;
414
+ margin: 0 auto 50px;
415
+ color: var(--ink-soft);
416
+ font-size: 18px;
417
+ }
418
+ .build-small .bonus-grid {
419
+ display: grid;
420
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
421
+ gap: 16px;
422
+ }
423
+ .build-small .badge {
424
+ background: var(--paper);
425
+ border: 1px solid var(--rule);
426
+ padding: 24px 20px;
427
+ border-radius: 4px;
428
+ transition: transform 0.2s, box-shadow 0.2s;
429
+ position: relative;
430
+ }
431
+ .build-small .badge:hover {
432
+ transform: translateY(-3px) rotate(-0.5deg);
433
+ box-shadow: 0 12px 30px rgba(30,26,18,0.10);
434
+ }
435
+ .build-small .badge .name {
436
+ font-family: 'Fraunces', serif;
437
+ font-size: 20px;
438
+ font-weight: 500;
439
+ color: var(--ember);
440
+ margin-bottom: 6px;
441
+ font-variation-settings: "SOFT" 100;
442
+ font-style: italic;
443
+ }
444
+ .build-small .badge .desc {
445
+ font-size: 15px;
446
+ color: var(--ink-soft);
447
+ line-height: 1.45;
448
+ }
449
+ .build-small .badge.tentative::after {
450
+ content: "tentative";
451
+ position: absolute;
452
+ top: 10px;
453
+ right: 12px;
454
+ font-family: 'Caveat', cursive;
455
+ font-size: 13px;
456
+ color: var(--ember-soft);
457
+ transform: rotate(8deg);
458
+ }
459
+
460
+ /* ========= TIMELINE ========= */
461
+ .build-small .timeline-section {
462
+ max-width: 900px;
463
+ margin: 100px auto;
464
+ padding: 0 32px;
465
+ }
466
+ .build-small .timeline {
467
+ position: relative;
468
+ padding-left: 28px;
469
+ border-left: 2px dashed var(--rule);
470
+ }
471
+ .build-small .milestone {
472
+ margin-bottom: 36px;
473
+ position: relative;
474
+ }
475
+ .build-small .milestone::before {
476
+ content: "";
477
+ position: absolute;
478
+ left: -36px;
479
+ top: 8px;
480
+ width: 14px;
481
+ height: 14px;
482
+ border-radius: 50%;
483
+ background: var(--ember);
484
+ border: 3px solid var(--paper);
485
+ box-shadow: 0 0 0 1px var(--ember);
486
+ }
487
+ .build-small .milestone .date {
488
+ font-family: 'Caveat', cursive;
489
+ font-size: 22px;
490
+ color: var(--ember);
491
+ margin-bottom: 4px;
492
+ }
493
+ .build-small .milestone .title {
494
+ font-family: 'Fraunces', serif;
495
+ font-size: 22px;
496
+ font-weight: 500;
497
+ margin-bottom: 4px;
498
+ font-variation-settings: "SOFT" 80;
499
+ }
500
+ .build-small .milestone .desc {
501
+ color: var(--ink-soft);
502
+ font-size: 17px;
503
+ }
504
+
505
+ /* ========= SUBMIT BLOCK ========= */
506
+ .build-small .submit {
507
+ max-width: 1080px;
508
+ margin: 100px auto;
509
+ padding: 0 32px;
510
+ }
511
+ .build-small .submit-card {
512
+ background: var(--twilight);
513
+ color: var(--paper);
514
+ padding: 80px 60px;
515
+ border-radius: 8px;
516
+ text-align: center;
517
+ position: relative;
518
+ overflow: hidden;
519
+ }
520
+ .build-small .submit-card::before {
521
+ content: "";
522
+ position: absolute;
523
+ inset: 0;
524
+ background: radial-gradient(circle at 30% 20%, rgba(184,80,30,0.25), transparent 60%),
525
+ radial-gradient(circle at 80% 90%, rgba(143,166,137,0.18), transparent 55%);
526
+ }
527
+ .build-small .submit-card > * { position: relative; }
528
+ .build-small .submit-card .scribble-light { color: var(--ember-soft); opacity: 0.8; }
529
+ .build-small .submit-card h2 {
530
+ font-family: 'Fraunces', serif;
531
+ font-variation-settings: "SOFT" 100, "opsz" 144;
532
+ font-size: 64px;
533
+ font-weight: 500;
534
+ line-height: 1;
535
+ margin: 24px 0 20px;
536
+ }
537
+ .build-small .submit-card h2 em { color: var(--ember-soft); font-style: italic; }
538
+ .build-small .submit-card p {
539
+ color: rgba(242, 234, 216, 0.8);
540
+ font-size: 19px;
541
+ max-width: 540px;
542
+ margin: 0 auto 36px;
543
+ }
544
+ .build-small .submit-btn {
545
+ display: inline-block;
546
+ background: var(--paper);
547
+ color: var(--ink);
548
+ padding: 18px 40px;
549
+ border-radius: 999px;
550
+ font-family: 'Fraunces', serif;
551
+ font-size: 16px;
552
+ font-weight: 500;
553
+ letter-spacing: 0.05em;
554
+ text-transform: uppercase;
555
+ text-decoration: none;
556
+ transition: background 0.2s, transform 0.2s;
557
+ }
558
+ .build-small .submit-btn:hover { background: var(--ember-soft); color: var(--paper); transform: translateY(-2px); }
559
+
560
+ /* ========= SPONSORS ========= */
561
+ .build-small .sponsors {
562
+ max-width: 1080px;
563
+ margin: 0 auto 100px;
564
+ padding: 0 32px;
565
+ text-align: center;
566
+ }
567
+ .build-small .sponsors h3 {
568
+ font-family: 'Fraunces', serif;
569
+ font-size: 14px;
570
+ font-weight: 500;
571
+ text-transform: uppercase;
572
+ letter-spacing: 0.25em;
573
+ color: var(--ink-soft);
574
+ margin-bottom: 32px;
575
+ }
576
+ .build-small .sponsor-row {
577
+ display: flex;
578
+ justify-content: center;
579
+ align-items: center;
580
+ gap: 60px;
581
+ flex-wrap: wrap;
582
+ opacity: 0.7;
583
+ }
584
+ .build-small .sponsor-placeholder {
585
+ font-family: 'Fraunces', serif;
586
+ font-style: italic;
587
+ color: var(--ink-soft);
588
+ font-size: 18px;
589
+ border: 1px dashed var(--rule);
590
+ padding: 16px 32px;
591
+ border-radius: 4px;
592
+ }
593
+
594
+ /* ========= FOOTER ========= */
595
+ .build-small .page-footer {
596
+ border-top: 1px solid var(--rule);
597
+ padding: 40px 32px;
598
+ text-align: center;
599
+ color: var(--ink-soft);
600
+ font-size: 15px;
601
+ }
602
+ .build-small .page-footer a { color: var(--ember); text-decoration: none; }
603
+
604
+ /* ========= RESPONSIVE ========= */
605
+ @media (max-width: 760px) {
606
+ .build-small .track-grid { grid-template-columns: 1fr; }
607
+ .build-small .track:first-child { border-right: none; border-bottom: 1px solid var(--rule); }
608
+ .build-small .rules-grid { grid-template-columns: 1fr; }
609
+ .build-small .rule-card { border-right: none; border-bottom: 1px solid var(--rule); }
610
+ .build-small .rule-card:last-child { border-bottom: none; }
611
+ .build-small .steps { grid-template-columns: 1fr 1fr; }
612
+ .build-small nav ul { display: none; }
613
+ .build-small .submit-card { padding: 56px 28px; }
614
+ .build-small .submit-card h2 { font-size: 44px; }
615
+ .build-small .hero { padding: 56px 24px 40px; }
616
+ .build-small .section-title { font-size: 40px; }
617
+ .build-small .track { padding: 40px 28px; }
618
+ }
619
+ @media (max-width: 480px) {
620
+ .build-small .steps { grid-template-columns: 1fr; }
621
+ }
622
+
623
+ /* ========= ANIMATION ========= */
624
+ @keyframes build-small-rise {
625
+ from { opacity: 0; transform: translateY(20px); }
626
+ to { opacity: 1; transform: translateY(0); }
627
+ }
628
+ .build-small .hero .kicker, .build-small .hero h1, .build-small .hero .lede, .build-small .hero .meta-row {
629
+ animation: build-small-rise 0.8s ease-out backwards;
630
+ }
631
+ .build-small .hero .kicker { animation-delay: 0.05s; }
632
+ .build-small .hero h1 { animation-delay: 0.18s; }
633
+ .build-small .hero .lede { animation-delay: 0.4s; }
634
+ .build-small .hero .meta-row { animation-delay: 0.55s; }
635
+ </style>
636
+
637
+ <div class="build-small">
638
+
639
+ <nav>
640
+ <div class="inner">
641
+ <div class="brand">Build <span class="sm">Small</span></div>
642
+ <ul>
643
+ <li><a href="#tracks">Tracks</a></li>
644
+ <li><a href="#rules">Rules</a></li>
645
+ <li><a href="#how">How it works</a></li>
646
+ <li><a href="#bonus">Extra Credit</a></li>
647
+ <li><a href="#timeline">Timeline</a></li>
648
+ </ul>
649
+ <a href="#register" class="register-btn">Register</a>
650
+ </div>
651
+ </nav>
652
+
653
+ <!-- ============================ HERO ============================ -->
654
+ <section class="hero">
655
+ <div class="kicker">~ a hackathon for small things ~</div>
656
+ <h1>Build <em>Small.</em></h1>
657
+ <p class="lede">A two-week hackathon for tiny weights, big ideas, and the things you can build close to home β€” hosted by Gradio &amp; Hugging Face.</p>
658
+
659
+ <div class="meta-row">
660
+ <span><strong>Two tracks</strong></span>
661
+ <span class="dot">✦</span>
662
+ <span><strong>Models ≀ 22GB</strong></span>
663
+ <span class="dot">✦</span>
664
+ <span><strong>Built on Gradio</strong></span>
665
+ <span class="dot">✦</span>
666
+ <span><strong>Open to everyone</strong></span>
667
+ </div>
668
+ </section>
669
+
670
+ <!-- ============================ INTRO ============================ -->
671
+ <section class="intro">
672
+ <svg class="scribble" viewBox="0 0 120 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round">
673
+ <path d="M2 12 Q15 2, 30 12 T60 12 T90 12 T118 12" />
674
+ </svg>
675
+ <h2 style="margin-top: 32px;">The internet is full of giant models doing giant things. This isn't that.</h2>
676
+ <p>For two weeks, we want to see what you can do with <strong>small models</strong>, <strong>tight constraints</strong>, and <strong>care for the people right around you</strong>. Build for one neighbor. Build something that runs on the laptop you already own. Build something a child could love.</p>
677
+ <p style="margin-top: 24px;">Pick a track, ship a Gradio app, and tell us a story.</p>
678
+ </section>
679
+
680
+ <!-- ============================ TRACKS ============================ -->
681
+ <section class="tracks" id="tracks">
682
+ <div class="section-label">~ choose your path ~</div>
683
+ <h2 class="section-title">Two Tracks.</h2>
684
+
685
+ <div class="track-grid">
686
+ <!-- TRACK 1 -->
687
+ <div class="track track-1">
688
+ <div class="chapter">Chapter One</div>
689
+ <div class="illustration">
690
+ <svg width="180" height="120" viewBox="0 0 180 120" fill="none" stroke="#3D5A3A" stroke-width="1.4" stroke-linecap="round">
691
+ <path d="M0 95 Q90 88, 180 95" />
692
+ <path d="M50 95 L50 65 L75 50 L100 65 L100 95 Z" />
693
+ <path d="M68 95 L68 80 L82 80 L82 95" />
694
+ <circle cx="62" cy="72" r="2.5" />
695
+ <circle cx="88" cy="72" r="2.5" />
696
+ <path d="M85 50 L85 42" />
697
+ <path d="M84 38 Q86 36, 88 38 Q86 40, 88 42" stroke-dasharray="2 2" opacity="0.6" />
698
+ <path d="M135 95 L135 75" />
699
+ <circle cx="135" cy="68" r="14" />
700
+ <path d="M10 95 L10 86 M18 95 L18 86 M26 95 L26 86 M34 95 L34 86 M42 95 L42 86" />
701
+ <path d="M8 88 L44 88" />
702
+ <circle cx="155" cy="22" r="8" />
703
+ <path d="M155 8 L155 4 M155 36 L155 40 M141 22 L137 22 M169 22 L173 22 M145 12 L142 9 M165 12 L168 9" />
704
+ </svg>
705
+ </div>
706
+ <h3>Backyard AI</h3>
707
+ <p class="subtitle">Solve a real problem for someone you actually know.</p>
708
+ <p class="body">Pick a person β€” a neighbor, a parent, a small business owner on your street β€” and build something that makes their day measurably better. Walk over. Watch them use it. The closer the problem, the better the project.</p>
709
+ <div class="judging">
710
+ <div class="judging-label">Judging Criteria</div>
711
+ <ul>
712
+ <li>The problem is specific and real (not invented for the demo)</li>
713
+ <li>The person it was built for actually used it</li>
714
+ <li>Honest fit between problem, solution, and the small-model constraint</li>
715
+ <li>Polish and craft of the Gradio app</li>
716
+ </ul>
717
+ </div>
718
+ </div>
719
+
720
+ <!-- TRACK 2 -->
721
+ <div class="track track-2">
722
+ <div class="chapter">Chapter Two</div>
723
+ <div class="illustration">
724
+ <svg width="180" height="120" viewBox="0 0 180 120" fill="none" stroke="#B8501E" stroke-width="1.4" stroke-linecap="round">
725
+ <path d="M0 100 Q90 92, 180 100" />
726
+ <path d="M30 100 Q60 80, 90 90 T160 70" stroke-dasharray="3 3" opacity="0.6" />
727
+ <path d="M48 100 L48 95 Q43 95, 43 90 Q43 85, 53 85 Q63 85, 63 90 Q63 95, 58 95 L58 100" />
728
+ <circle cx="48" cy="89" r="0.8" fill="#B8501E" />
729
+ <circle cx="55" cy="87" r="0.8" fill="#B8501E" />
730
+ <path d="M22 100 L22 96 Q19 96, 19 93 Q19 90, 25 90 Q31 90, 31 93 Q31 96, 28 96 L28 100" />
731
+ <path d="M85 100 L85 70" />
732
+ <path d="M78 75 L85 70 L92 75 M75 80 L85 75 L95 80 M73 86 L85 80 L97 86" />
733
+ <path d="M125 100 L125 65" />
734
+ <path d="M117 70 L125 65 L133 70 M114 76 L125 70 L136 76 M111 83 L125 76 L139 83" />
735
+ <path d="M155 25 L155 19 L159 22 L153 22 L157 19 Z" />
736
+ <circle cx="148" cy="35" r="1" fill="#B8501E" />
737
+ <circle cx="170" cy="40" r="1" fill="#B8501E" />
738
+ </svg>
739
+ </div>
740
+ <h3>An Adventure in Thousand Token Wood</h3>
741
+ <p class="subtitle">Build something delightful that wouldn't exist without AI.</p>
742
+ <p class="body">Wander somewhere weirder. A toy, a tiny game, a strange interactive story, an art experiment that surprises you. The AI should be doing the fun thing β€” not just helping you build it. Strange is good. Joyful is the bar.</p>
743
+ <div class="judging">
744
+ <div class="judging-label">Judging Criteria</div>
745
+ <ul>
746
+ <li>Genuinely delightful β€” would you show a friend?</li>
747
+ <li>The AI is load-bearing for the experience</li>
748
+ <li>Originality of concept (we've seen the chatbot)</li>
749
+ <li>Polish and craft of the Gradio app</li>
750
+ </ul>
751
+ </div>
752
+ </div>
753
+ </div>
754
+ </section>
755
+
756
+ <!-- ============================ RULES ============================ -->
757
+ <section class="rules" id="rules">
758
+ <div class="section-label">~ rules of the land ~</div>
759
+ <h2 class="section-title">The Constraints.</h2>
760
+
761
+ <div class="rules-grid">
762
+ <div class="rule-card">
763
+ <div class="icon">β‘ </div>
764
+ <h4>Small Models Only</h4>
765
+ <p>Any model that fits inside <strong>22 GB</strong> of memory.</p>
766
+ <span class="pending">↳ pending team sign-off</span>
767
+ </div>
768
+ <div class="rule-card">
769
+ <div class="icon">β‘‘</div>
770
+ <h4>Built on Gradio</h4>
771
+ <p>Your app must be a Gradio app, hosted as a Hugging Face Space.</p>
772
+ </div>
773
+ <div class="rule-card">
774
+ <div class="icon">β‘’</div>
775
+ <h4>Show, Don't Tell</h4>
776
+ <p>A short demo video and a social-media post about your project are part of the submission.</p>
777
+ </div>
778
+ </div>
779
+ </section>
780
+
781
+ <!-- ============================ HOW IT WORKS ============================ -->
782
+ <section class="how-it-works" id="how">
783
+ <div class="section-label">~ getting started ~</div>
784
+ <h2 class="section-title">How It Works.</h2>
785
+
786
+ <div class="steps">
787
+ <div class="step">
788
+ <div class="num">1</div>
789
+ <h4>Register</h4>
790
+ <p>Join this Hugging Face org. That's your ticket in β€” no application, no waitlist.</p>
791
+ </div>
792
+ <div class="step">
793
+ <div class="num">2</div>
794
+ <h4>Find Your People</h4>
795
+ <p>Hop into the Gradio Discord channel. Office hours, AMAs, and teammates live there.</p>
796
+ </div>
797
+ <div class="step">
798
+ <div class="num">3</div>
799
+ <h4>Build &amp; Ship</h4>
800
+ <p>Build your Gradio app and host it as a Space under this org during the hack window.</p>
801
+ </div>
802
+ <div class="step">
803
+ <div class="num">4</div>
804
+ <h4>Submit</h4>
805
+ <p>Drop your <strong>Space link</strong>, a short <strong>demo video</strong>, and a <strong>social post</strong> by the deadline.</p>
806
+ </div>
807
+ </div>
808
+ </section>
809
+
810
+ <!-- ============================ BONUS ============================ -->
811
+ <section class="bonus" id="bonus">
812
+ <div class="bonus-inner">
813
+ <div class="section-label">~ extra credit ~</div>
814
+ <h2 class="section-title">Bonus Quests.</h2>
815
+ <p class="intro-text">None of these are required. Each one bumps you up the leaderboard. Stack them like badges on a scout sash.</p>
816
+
817
+ <div class="bonus-grid">
818
+ <div class="badge">
819
+ <div class="name">Off the Grid</div>
820
+ <div class="desc">No cloud APIs. The whole thing runs on the model in front of you.</div>
821
+ </div>
822
+ <div class="badge">
823
+ <div class="name">Well-Tuned</div>
824
+ <div class="desc">Your app uses a fine-tuned model you've published on Hugging Face.</div>
825
+ </div>
826
+ <div class="badge">
827
+ <div class="name">Off-Brand</div>
828
+ <div class="desc">A custom frontend that pushes past the default Gradio look.</div>
829
+ </div>
830
+ <div class="badge">
831
+ <div class="name">Llama ChamPion</div>
832
+ <div class="desc">Your model runs through the llama.cpp runtime.</div>
833
+ </div>
834
+ <div class="badge">
835
+ <div class="name">Sharing is Caring</div>
836
+ <div class="desc">You shared your agent trace on the Hub.</div>
837
+ </div>
838
+ <div class="badge tentative">
839
+ <div class="name">Field Notes</div>
840
+ <div class="desc">You wrote a blog post or report about what you built and what you learned.</div>
841
+ </div>
842
+ </div>
843
+ </div>
844
+ </section>
845
+
846
+ <!-- ============================ TIMELINE ============================ -->
847
+ <section class="timeline-section" id="timeline">
848
+ <div class="section-label">~ when ~</div>
849
+ <h2 class="section-title">Timeline.</h2>
850
+
851
+ <div class="timeline">
852
+ <div class="milestone">
853
+ <div class="date">Week of [date TBD]</div>
854
+ <div class="title">Registration opens</div>
855
+ <div class="desc">Sign up on the Hugging Face org, join the Discord channel, start sketching ideas.</div>
856
+ </div>
857
+ <div class="milestone">
858
+ <div class="date">[date TBD]</div>
859
+ <div class="title">Hack window begins</div>
860
+ <div class="desc">Two weeks to build, ship, and demo.</div>
861
+ </div>
862
+ <div class="milestone">
863
+ <div class="date">Mid-window</div>
864
+ <div class="title">Live AMA + office hours</div>
865
+ <div class="desc">Drop in to ask the Gradio team anything about your build.</div>
866
+ </div>
867
+ <div class="milestone">
868
+ <div class="date">[date TBD]</div>
869
+ <div class="title">Submissions close</div>
870
+ <div class="desc">Demo video, public Space, and social post β€” locked in.</div>
871
+ </div>
872
+ <div class="milestone">
873
+ <div class="date">[date TBD]</div>
874
+ <div class="title">Winners announced</div>
875
+ <div class="desc">Per track, plus the leaderboard for bonus quests stacked.</div>
876
+ </div>
877
+ </div>
878
+ </section>
879
+
880
+ <!-- ============================ SUBMIT ============================ -->
881
+ <section class="submit" id="register">
882
+ <div class="submit-card">
883
+ <svg class="scribble scribble-light" viewBox="0 0 120 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round">
884
+ <path d="M2 12 Q15 2, 30 12 T60 12 T90 12 T118 12" />
885
+ </svg>
886
+ <h2>Build something <em>small.</em></h2>
887
+ <p>Two weeks. Two tracks. The model on your laptop. The neighbor next door. Let's make some little things.</p>
888
+ <a href="#" class="submit-btn">Register on Hugging Face β†’</a>
889
+ </div>
890
+ </section>
891
+
892
+ <!-- ============================ SPONSORS ============================ -->
893
+ <section class="sponsors">
894
+ <h3>Hosted by Β· Sponsored by</h3>
895
+ <div class="sponsor-row">
896
+ <div class="sponsor-placeholder">Gradio</div>
897
+ <div class="sponsor-placeholder">Hugging Face</div>
898
+ <div class="sponsor-placeholder">[ Sponsor TBD ]</div>
899
+ <div class="sponsor-placeholder">[ Sponsor TBD ]</div>
900
+ </div>
901
+ </section>
902
+
903
+ <div class="page-footer">
904
+ <p>Made with care by the Gradio team β€” questions? <a href="#">Find us on Discord</a></p>
905
+ </div>
906
+
907
+ </div>
908
+ """
909
+
910
+
911
+ with gr.Blocks(
912
+ title="Build Small β€” A Gradio + Hugging Face Hackathon",
913
+ ) as demo:
914
+ gr.HTML(LANDING_HTML)
915
+
916
+
917
+ if __name__ == "__main__":
918
+ demo.launch(
919
+ css=CUSTOM_CSS,
920
+ head=HEAD_HTML,
921
+ theme=gr.themes.Base(),
922
+ )