andito HF Staff commited on
Commit
61d52ba
·
verified ·
1 Parent(s): 876683b

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. README.md +2 -0
  2. index.html +103 -57
README.md CHANGED
@@ -15,6 +15,8 @@ Rate any Hugging Face profile out of 99 as an Ultimate-Team-style player card, s
15
 
16
  Fully static: everything runs client-side against the public Hub API (`huggingface.co/api`). No token, no backend, nothing stored.
17
 
 
 
18
  ## Stat mapping
19
 
20
  | Card stat | Hub meaning |
 
15
 
16
  Fully static: everything runs client-side against the public Hub API (`huggingface.co/api`). No token, no backend, nothing stored.
17
 
18
+ Card layout geometry ported from [gitfut](https://github.com/Younesfdj/gitfut) (MIT, © Younesfdj); card artwork recreated from scratch in CSS/SVG.
19
+
20
  ## Stat mapping
21
 
22
  | Card stat | Hub meaning |
index.html CHANGED
@@ -9,7 +9,7 @@
9
  <meta property="og:description" content="Turn your Hugging Face stats into a transfer-market player card. Get drafted.">
10
  <link rel="preconnect" href="https://fonts.googleapis.com">
11
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
12
- <link href="https://fonts.googleapis.com/css2?family=Saira+Condensed:wght@500;600;700;800&family=Space+Grotesk:wght@400;500;700&display=swap" rel="stylesheet">
13
  <script src="https://cdnjs.cloudflare.com/ajax/libs/html-to-image/1.11.11/html-to-image.min.js"></script>
14
  <style>
15
  :root{
@@ -21,7 +21,7 @@
21
  --hf-orange:#FF9D00;
22
  --line:#242c40;
23
  --card-w:320px;
24
- --card-h:500px;
25
  --fan-scale:.58;
26
  }
27
  *{box-sizing:border-box;margin:0;padding:0}
@@ -57,21 +57,45 @@
57
  .status.err{color:#ff8484}
58
  .status.busy{color:var(--ink-dim)}
59
 
60
- /* ---------- the card ---------- */
 
 
 
61
  .fut{
 
 
 
 
 
62
  position:relative;width:var(--card-w);height:var(--card-h);
63
- clip-path:path("M160 0 L288 30 Q320 38 320 72 L320 372 Q320 412 284 428 L160 500 L36 428 Q0 412 0 372 L0 72 Q0 38 32 30 Z");
64
- color:#241a05;
 
65
  font-family:'Saira Condensed',sans-serif;
66
  transform-origin:center;
 
67
  }
68
- .fut-bg{position:absolute;inset:0}
69
- .fut.tier-silver .fut-bg{background:linear-gradient(160deg,#e7eaf1 0%,#b9c0cd 34%,#8f97a8 60%,#cfd4de 100%)}
70
- .fut.tier-silver{color:#232733}
71
- .fut.tier-gold .fut-bg{background:linear-gradient(160deg,#f4dd8f 0%,#e2bb5e 36%,#b8863a 64%,#e9cc76 100%)}
72
- .fut.tier-legend .fut-bg{background:linear-gradient(160deg,#ffe680 0%,#ffd21e 30%,#f0a13d 55%,#ffdf5e 78%,#ffef9e 100%)}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  .fut.tier-legend .fut-bg::after{
74
- content:"";position:absolute;inset:0;mix-blend-mode:soft-light;opacity:.9;
75
  background:linear-gradient(115deg,transparent 30%,rgba(255,0,200,.55) 44%,rgba(0,229,255,.55) 52%,transparent 66%);
76
  background-size:300% 300%;
77
  }
@@ -79,26 +103,42 @@
79
  .fut.tier-legend .fut-bg::after{animation:holo 4.5s ease-in-out infinite alternate}
80
  @keyframes holo{from{background-position:0% 50%}to{background-position:100% 50%}}
81
  }
82
- .fut-inner{position:absolute;inset:0;padding:26px 30px 0}
83
-
84
- .fut-top{position:absolute;top:56px;left:32px;display:flex;flex-direction:column;align-items:center;gap:2px;width:72px}
85
- .fut-rating{font-size:3.4rem;font-weight:800;line-height:.9}
86
- .fut-pos{font-size:1.15rem;font-weight:700;letter-spacing:.05em;border-bottom:2px solid currentColor;padding-bottom:3px;margin-bottom:5px}
87
- .fut-domain{font-size:1.5rem;line-height:1.2}
88
- .fut-club{width:30px;height:30px;border-radius:50%;object-fit:cover;margin-top:6px;border:2px solid rgba(0,0,0,.25);background:#fff;display:none}
89
-
90
- .fut-avatar{position:absolute;top:44px;right:26px;width:186px;height:186px;border-radius:14px;object-fit:cover;background:rgba(0,0,0,.12)}
91
- .fut-avatar.letter{display:flex;align-items:center;justify-content:center;font-size:5rem;font-weight:800}
92
-
93
- .fut-name{position:absolute;top:246px;left:0;right:0;text-align:center;font-size:1.9rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;padding:0 16px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
94
- .fut-rule{position:absolute;top:292px;left:56px;right:56px;height:2px;background:currentColor;opacity:.45}
95
-
96
- .fut-stats{position:absolute;top:304px;left:44px;right:44px;display:grid;grid-template-columns:1fr 1fr;column-gap:34px;row-gap:5px}
97
- .fut-stat{display:flex;align-items:baseline;gap:8px;font-size:1.35rem}
98
- .fut-stat b{font-weight:800;min-width:2ch;text-align:right}
99
- .fut-stat span{font-weight:600;letter-spacing:.06em;font-size:1.05rem;opacity:.85}
100
-
101
- .fut-foot{position:absolute;top:436px;left:0;right:0;text-align:center;font-weight:600;letter-spacing:.18em;font-size:.72rem;opacity:.7}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
103
  /* ---------- stage: fan of collected cards / scouted card ---------- */
104
  .stage{display:flex;flex-direction:column;align-items:center;gap:16px;min-height:calc(var(--card-h) + 60px);justify-content:center}
@@ -126,7 +166,8 @@
126
 
127
  .card-holder{display:flex;flex-direction:column;align-items:center;gap:16px}
128
  .card-holder[hidden]{display:none}
129
- .card-holder .fut{filter:drop-shadow(0 18px 40px rgba(0,0,0,.55))}
 
130
  @media (prefers-reduced-motion:no-preference){
131
  .card-holder .fut.deal{animation:walkout 1.05s cubic-bezier(.16,1,.3,1) both}
132
  /* THE WALKOUT: card rises out of darkness into the spotlight */
@@ -217,26 +258,21 @@
217
  <template id="card-tpl">
218
  <div class="fut">
219
  <div class="fut-bg"></div>
220
- <div class="fut-inner">
221
- <div class="fut-top">
222
- <div class="fut-rating"></div>
223
- <div class="fut-pos"></div>
224
- <div class="fut-domain"></div>
225
- <img class="fut-club" alt="">
226
- </div>
227
- <div class="fut-avatar letter"></div>
228
- <div class="fut-name"></div>
229
- <div class="fut-rule"></div>
230
- <div class="fut-stats">
231
- <div class="fut-stat"><b class="s-PAC"></b><span>PAC</span></div>
232
- <div class="fut-stat"><b class="s-DRI"></b><span>DRI</span></div>
233
- <div class="fut-stat"><b class="s-SHO"></b><span>SHO</span></div>
234
- <div class="fut-stat"><b class="s-DEF"></b><span>DEF</span></div>
235
- <div class="fut-stat"><b class="s-PAS"></b><span>PAS</span></div>
236
- <div class="fut-stat"><b class="s-PHY"></b><span>PHY</span></div>
237
- </div>
238
- <div class="fut-foot">HUGFUT · HF.CO</div>
239
- </div>
240
  </div>
241
  </template>
242
 
@@ -275,19 +311,29 @@ const ANGLE = 7, SPREAD_CLOSED = 88, SPREAD_OPEN = 124;
275
 
276
  function makeCard(){ return document.getElementById("card-tpl").content.firstElementChild.cloneNode(true); }
277
 
 
 
278
  function fillCard(el, d){
279
  el.className = "fut tier-" + d.tier;
280
- el.querySelector(".fut-rating").textContent = d.rating;
281
  el.querySelector(".fut-pos").textContent = d.pos;
282
  el.querySelector(".fut-domain").textContent = d.domain;
283
  el.querySelector(".fut-name").textContent = d.name.toUpperCase();
284
  for (const k of ["PAC","SHO","PAS","DRI","DEF","PHY"])
285
- el.querySelector(".s-"+k).textContent = d.stats[k];
286
  const av = el.querySelector(".fut-avatar");
287
- if (d.avatar){ av.className = "fut-avatar"; av.style.background = `center/cover url(${d.avatar})`; av.textContent = ""; }
288
- else { av.className = "fut-avatar letter"; av.style.background = ""; av.textContent = d.name[0].toUpperCase(); }
289
  const club = el.querySelector(".fut-club");
290
  if (d.club){ club.src = d.club; club.style.display = "block"; } else club.style.display = "none";
 
 
 
 
 
 
 
 
291
  }
292
 
293
  /* ---------- fan of collected cards ---------- */
@@ -402,7 +448,7 @@ function domainEmoji(models){
402
  return "🤗";
403
  }
404
 
405
- function tier(overall){ return overall >= 89 ? "legend" : overall >= 75 ? "gold" : "silver"; }
406
 
407
  async function scout(user){
408
  user = user.trim().replace(/^@/,"");
 
9
  <meta property="og:description" content="Turn your Hugging Face stats into a transfer-market player card. Get drafted.">
10
  <link rel="preconnect" href="https://fonts.googleapis.com">
11
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
12
+ <link href="https://fonts.googleapis.com/css2?family=Saira+Condensed:wght@500;600;700;800&family=Space+Grotesk:wght@400;500;700&display=swap" rel="stylesheet" crossorigin="anonymous">
13
  <script src="https://cdnjs.cloudflare.com/ajax/libs/html-to-image/1.11.11/html-to-image.min.js"></script>
14
  <style>
15
  :root{
 
21
  --hf-orange:#FF9D00;
22
  --line:#242c40;
23
  --card-w:320px;
24
+ --card-h:486px;
25
  --fan-scale:.58;
26
  }
27
  *{box-sizing:border-box;margin:0;padding:0}
 
57
  .status.err{color:#ff8484}
58
  .status.busy{color:var(--ink-dim)}
59
 
60
+ /* ---------- the card ----------
61
+ Layout numbers ported from gitfut's PlayerCard (MIT). Art recreated in
62
+ CSS: traced FUT-style silhouette, brushed texture, gloss break, tier
63
+ palettes, feathered avatar. Card is a size container so cqw = % width. */
64
  .fut{
65
+ --ink-card:#46390c;
66
+ --glow:rgba(225,185,80,.55);
67
+ --av-halo:rgba(243,214,121,.45);
68
+ --av-tint:radial-gradient(ellipse 72% 76% at 52% 40%, transparent 46%, rgba(243,214,121,.24) 78%, rgba(156,118,33,.44));
69
+ --grad:linear-gradient(180deg,#f2e19c 0%,#e7d281 22%,#d9c262 45%,#d2ba5c 53.5%,#fce487 54%,#f3da7d 80%,#dfc261 100%);
70
  position:relative;width:var(--card-w);height:var(--card-h);
71
+ container-type:inline-size;
72
+ clip-path:path("M160 11 C 128 12, 96 18, 71 24 C 46 30, 24 48, 15 70 C 12.5 77, 12 82, 12 89 L 12 408 C 12 415, 18 421, 30 427 C 52 437, 80 446, 108 454 C 126 460, 144 469, 160 478 C 176 469, 194 460, 212 454 C 240 446, 268 437, 290 427 C 302 421, 308 415, 308 408 L 308 89 C 308 82, 307.5 77, 305 70 C 296 48, 274 30, 249 24 C 224 18, 192 12, 160 11 Z");
73
+ color:var(--ink-card);
74
  font-family:'Saira Condensed',sans-serif;
75
  transform-origin:center;
76
+ user-select:none;-webkit-user-select:none;
77
  }
78
+ .fut.tier-bronze{--ink-card:#3a2717;--glow:rgba(190,120,60,.45);--av-halo:rgba(214,163,110,.4);
79
+ --av-tint:radial-gradient(ellipse 72% 76% at 52% 40%, transparent 46%, rgba(106,69,39,.26) 78%, rgba(50,31,14,.44));
80
+ --grad:linear-gradient(180deg,#f1ca98 0%,#e8b877 22%,#dda863 45%,#d49e5c 53.5%,#f2c993 54%,#e2b986 80%,#c59661 100%)}
81
+ .fut.tier-silver{--ink-card:#303536;--glow:rgba(170,188,210,.5);--av-halo:rgba(220,228,238,.4);
82
+ --av-tint:radial-gradient(ellipse 72% 76% at 52% 40%, transparent 46%, rgba(170,188,210,.22) 78%, rgba(70,78,90,.42));
83
+ --grad:linear-gradient(180deg,#c4cacf 0%,#aeb4b9 22%,#9da2a6 45%,#969b9f 53.5%,#c2c9ce 54%,#afb5b9 80%,#8e9497 100%)}
84
+ .fut.tier-legend{--ink-card:#625217;--glow:rgba(243,213,128,.5);--av-halo:rgba(243,214,136,.5);
85
+ --av-tint:radial-gradient(ellipse 72% 76% at 52% 40%, transparent 46%, rgba(243,214,121,.24) 78%, rgba(120,90,30,.46));
86
+ --grad:linear-gradient(180deg,#fcfaf4 0%,#f9f7f0 22%,#f4f1e8 45%,#efebe0 53.5%,#fffef9 54%,#eeebe2 80%,#d2cdc1 100%)}
87
+
88
+ .fut-bg{position:absolute;inset:0;background:
89
+ linear-gradient(180deg,rgba(255,255,255,.30),rgba(255,255,255,0) 9%),
90
+ linear-gradient(180deg,transparent 53%,rgba(255,255,255,.55) 53.6%,rgba(255,255,255,0) 55.6%),
91
+ var(--grad);}
92
+ /* brushed-metal streaks, only on the upper finish */
93
+ .fut-bg::before{content:"";position:absolute;inset:0;opacity:.45;mix-blend-mode:overlay;
94
+ background:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='280' height='280'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.012 0.85' numOctaves='2' seed='7' stitchTiles='stitch'/><feColorMatrix type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0.9 0.9 0.9 0 0'/></filter><rect width='280' height='280' filter='url(%23n)'/></svg>");
95
+ -webkit-mask-image:linear-gradient(180deg,#000 53.5%,transparent 54%);
96
+ mask-image:linear-gradient(180deg,#000 53.5%,transparent 54%);}
97
  .fut.tier-legend .fut-bg::after{
98
+ content:"";position:absolute;inset:0;mix-blend-mode:soft-light;opacity:.6;
99
  background:linear-gradient(115deg,transparent 30%,rgba(255,0,200,.55) 44%,rgba(0,229,255,.55) 52%,transparent 66%);
100
  background-size:300% 300%;
101
  }
 
103
  .fut.tier-legend .fut-bg::after{animation:holo 4.5s ease-in-out infinite alternate}
104
  @keyframes holo{from{background-position:0% 50%}to{background-position:100% 50%}}
105
  }
106
+ /* ghost watermark in the brushed band */
107
+ .fut-mark{position:absolute;left:-4cqw;top:29.5%;font-size:22cqw;font-weight:800;line-height:1;letter-spacing:-.02em;white-space:nowrap;color:var(--ink-card);opacity:.10;transform:skewX(-8deg)}
108
+
109
+ .fut-avatar{position:absolute;left:27cqw;top:13cqw;width:68cqw;height:70cqw;
110
+ background-size:cover;background-position:center 20%;
111
+ -webkit-mask-image:radial-gradient(ellipse 66% 88% at 52% 40%, #000 56%, transparent 80%), linear-gradient(220deg, #000 70%, transparent 100%), linear-gradient(180deg, transparent 1%, #000 22%);
112
+ mask-image:radial-gradient(ellipse 66% 88% at 52% 40%, #000 56%, transparent 80%), linear-gradient(220deg, #000 70%, transparent 100%), linear-gradient(180deg, transparent 1%, #000 22%);
113
+ -webkit-mask-composite:source-in;mask-composite:intersect;
114
+ filter:drop-shadow(0 3cqw 6cqw rgba(0,0,0,.5)) drop-shadow(0 0 5cqw var(--av-halo));}
115
+ .fut-avatar::after{content:"";position:absolute;inset:0;background:var(--av-tint)}
116
+ .fut-avatar.letter{display:flex;align-items:center;justify-content:center;font-size:30cqw;font-weight:800;background:rgba(0,0,0,.10)}
117
+
118
+ .fut-rating{position:absolute;left:16.3%;top:9.76%;font-size:22.2cqw;font-weight:600;line-height:1}
119
+ .fut-pos{position:absolute;left:25%;top:23.78%;transform:translateX(-50%);font-size:9.3cqw;font-weight:600;letter-spacing:.02em;line-height:1}
120
+ .fut-domain{position:absolute;left:25%;top:33.4%;transform:translateX(-50%);font-size:8.2cqw;line-height:1}
121
+ .fut-club{position:absolute;left:19.06%;top:42.25%;width:11.875%;aspect-ratio:1;border-radius:50%;object-fit:cover;display:none;background:#fff;border:.4cqw solid rgba(0,0,0,.18)}
122
+
123
+ .fut-name{position:absolute;left:50%;top:53.66%;transform:translateX(-50%);font-size:13cqw;font-weight:700;line-height:1;white-space:nowrap;text-transform:uppercase}
124
+
125
+ .fut-line{position:absolute;height:.35cqw;background:var(--ink-card);opacity:.5}
126
+ .fut-line.l1{left:19.44%;top:31.1%;width:10.19%}
127
+ .fut-line.l2{left:19.44%;top:40.85%;width:10.19%}
128
+ .fut-line.l3{left:16.67%;top:64.02%;width:66.67%}
129
+ .fut-line.l4{left:44.44%;top:89.63%;width:11.11%}
130
+ .fut-vline{position:absolute;left:50%;top:66.46%;width:.35cqw;height:20.12%;background:var(--ink-card);opacity:.5}
131
+
132
+ .fut-stat-v{position:absolute;font-size:10.2cqw;font-weight:700;line-height:1}
133
+ .fut-stat-l{position:absolute;font-size:9.3cqw;font-weight:600;letter-spacing:.02em;line-height:1}
134
+ .v-PAC{left:21.3%;top:64.63%} .lab-PAC{left:32.41%;top:65.24%}
135
+ .v-DRI{left:56.48%;top:64.63%} .lab-DRI{left:67.59%;top:65.24%}
136
+ .v-SHO{left:21.3%;top:72.2%} .lab-SHO{left:32.41%;top:72.8%}
137
+ .v-DEF{left:56.48%;top:72.2%} .lab-DEF{left:67.59%;top:72.8%}
138
+ .v-PAS{left:21.3%;top:79.76%} .lab-PAS{left:32.41%;top:80.37%}
139
+ .v-PHY{left:56.48%;top:79.76%} .lab-PHY{left:67.59%;top:80.37%}
140
+
141
+ .fut-foot{position:absolute;left:50%;top:91.2%;transform:translateX(-50%);font-size:4.1cqw;font-weight:700;letter-spacing:.1em;line-height:1;opacity:.6;white-space:nowrap}
142
 
143
  /* ---------- stage: fan of collected cards / scouted card ---------- */
144
  .stage{display:flex;flex-direction:column;align-items:center;gap:16px;min-height:calc(var(--card-h) + 60px);justify-content:center}
 
166
 
167
  .card-holder{display:flex;flex-direction:column;align-items:center;gap:16px}
168
  .card-holder[hidden]{display:none}
169
+ .card-holder .fut{filter:drop-shadow(0 18px 40px rgba(0,0,0,.55)) drop-shadow(0 0 20px var(--glow))}
170
+ .fan-slot .fut{filter:drop-shadow(0 0 14px var(--glow))}
171
  @media (prefers-reduced-motion:no-preference){
172
  .card-holder .fut.deal{animation:walkout 1.05s cubic-bezier(.16,1,.3,1) both}
173
  /* THE WALKOUT: card rises out of darkness into the spotlight */
 
258
  <template id="card-tpl">
259
  <div class="fut">
260
  <div class="fut-bg"></div>
261
+ <div class="fut-mark">HUGFUT</div>
262
+ <div class="fut-avatar letter"></div>
263
+ <div class="fut-rating"></div>
264
+ <div class="fut-pos"></div>
265
+ <div class="fut-domain"></div>
266
+ <img class="fut-club" alt="">
267
+ <div class="fut-line l1"></div><div class="fut-line l2"></div><div class="fut-line l3"></div><div class="fut-line l4"></div><div class="fut-vline"></div>
268
+ <div class="fut-name"></div>
269
+ <span class="fut-stat-v v-PAC"></span><span class="fut-stat-l lab-PAC">PAC</span>
270
+ <span class="fut-stat-v v-DRI"></span><span class="fut-stat-l lab-DRI">DRI</span>
271
+ <span class="fut-stat-v v-SHO"></span><span class="fut-stat-l lab-SHO">SHO</span>
272
+ <span class="fut-stat-v v-DEF"></span><span class="fut-stat-l lab-DEF">DEF</span>
273
+ <span class="fut-stat-v v-PAS"></span><span class="fut-stat-l lab-PAS">PAS</span>
274
+ <span class="fut-stat-v v-PHY"></span><span class="fut-stat-l lab-PHY">PHY</span>
275
+ <div class="fut-foot">HUGFUT · HF.CO</div>
 
 
 
 
 
276
  </div>
277
  </template>
278
 
 
311
 
312
  function makeCard(){ return document.getElementById("card-tpl").content.firstElementChild.cloneNode(true); }
313
 
314
+ const pad2 = n => String(Math.round(n)).padStart(2, "0");
315
+
316
  function fillCard(el, d){
317
  el.className = "fut tier-" + d.tier;
318
+ el.querySelector(".fut-rating").textContent = pad2(d.rating);
319
  el.querySelector(".fut-pos").textContent = d.pos;
320
  el.querySelector(".fut-domain").textContent = d.domain;
321
  el.querySelector(".fut-name").textContent = d.name.toUpperCase();
322
  for (const k of ["PAC","SHO","PAS","DRI","DEF","PHY"])
323
+ el.querySelector(".v-"+k).textContent = pad2(d.stats[k]);
324
  const av = el.querySelector(".fut-avatar");
325
+ if (d.avatar){ av.className = "fut-avatar"; av.style.backgroundImage = `url(${d.avatar})`; av.textContent = ""; }
326
+ else { av.className = "fut-avatar letter"; av.style.backgroundImage = ""; av.textContent = d.name[0].toUpperCase(); }
327
  const club = el.querySelector(".fut-club");
328
  if (d.club){ club.src = d.club; club.style.display = "block"; } else club.style.display = "none";
329
+ /* shrink long names to fit the shield */
330
+ const nameEl = el.querySelector(".fut-name");
331
+ nameEl.style.fontSize = "";
332
+ requestAnimationFrame(() => {
333
+ const max = el.clientWidth * .84;
334
+ if (nameEl.scrollWidth > max)
335
+ nameEl.style.fontSize = (parseFloat(getComputedStyle(nameEl).fontSize) * max / nameEl.scrollWidth) + "px";
336
+ });
337
  }
338
 
339
  /* ---------- fan of collected cards ---------- */
 
448
  return "🤗";
449
  }
450
 
451
+ function tier(overall){ return overall >= 89 ? "legend" : overall >= 75 ? "gold" : overall >= 65 ? "silver" : "bronze"; }
452
 
453
  async function scout(user){
454
  user = user.trim().replace(/^@/,"");