Ron Au commited on
Commit
8f246ac
1 Parent(s): 4c519fd

WIP: New UI

Browse files
app.py CHANGED
@@ -2,13 +2,11 @@ from time import time
2
  from statistics import mean
3
  from flask import Flask, jsonify, render_template, request
4
 
5
- from modules.details import load_lists, rand_details
6
  from modules.inference import generate_image
7
 
8
  app = Flask(__name__)
9
 
10
- TEMPLATES_AUTO_RELOAD = True
11
-
12
 
13
  @app.route('/')
14
  def index():
@@ -61,7 +59,8 @@ def poll_task():
61
  if task["status"] == "pending":
62
  pending_tasks.append(task["task_id"])
63
  elif task["status"] == "completed":
64
- completed_durations.append(task["completed_at"] - task["created_at"])
 
65
 
66
  try:
67
  place_in_queue = pending_tasks.index(task_id) + 1
@@ -69,7 +68,8 @@ def poll_task():
69
  place_in_queue = 0
70
 
71
  if (len(completed_durations)):
72
- eta = sum(completed_durations) / len(completed_durations) * (place_in_queue or 1)
 
73
  else:
74
  eta = 40 * (place_in_queue or 1)
75
 
2
  from statistics import mean
3
  from flask import Flask, jsonify, render_template, request
4
 
5
+ from modules.details import rand_details
6
  from modules.inference import generate_image
7
 
8
  app = Flask(__name__)
9
 
 
 
10
 
11
  @app.route('/')
12
  def index():
59
  if task["status"] == "pending":
60
  pending_tasks.append(task["task_id"])
61
  elif task["status"] == "completed":
62
+ completed_durations.append(
63
+ task["completed_at"] - task["created_at"])
64
 
65
  try:
66
  place_in_queue = pending_tasks.index(task_id) + 1
68
  place_in_queue = 0
69
 
70
  if (len(completed_durations)):
71
+ eta = sum(completed_durations) / \
72
+ len(completed_durations) * (place_in_queue or 1)
73
  else:
74
  eta = 40 * (place_in_queue or 1)
75
 
static/blacky.png ADDED
static/bluey.png ADDED
static/huggingface-logo.svg ADDED
static/huggingface-pokemon-logo-1200.png ADDED
static/index.js CHANGED
@@ -105,8 +105,8 @@ const cardHTML = (details) => {
105
  >Illus. Max Woolf</a
106
  ></span
107
  >
108
- <span><a href="">2022 Hugging Face</a></span>
109
- <span>${rarity}</span>
110
  </div>
111
  </div>`;
112
  };
@@ -211,64 +211,93 @@ const rotateCard = () => {
211
  const rotateX = (containerMouseEvent.clientY - rect.y - rect.height / 2) * RANGE;
212
  const rotateY = -(containerMouseEvent.clientX - rect.x - rect.width / 2) * RANGE;
213
 
214
- card.style.setProperty('--rotate-x', rotateX + 'deg');
215
- card.style.setProperty('--rotate-y', rotateY + 'deg');
 
 
216
  }
217
  };
218
  };
219
 
220
- const cardRotationInitiator = (renderSection) => {
221
- let currentCard;
222
 
223
- return () => {
224
- let handleMouseMove;
225
 
226
- if (currentCard) {
227
- handleMouseMove = rotateCard().bind(null, currentCard);
228
- renderSection.removeEventListener('mousemove', handleMouseMove, true);
229
- }
230
 
231
- const newCard = document.querySelector('.pokecard');
 
232
 
233
- currentCard = newCard;
 
 
234
 
235
- handleMouseMove = rotateCard().bind(null, newCard);
236
- renderSection.addEventListener('mousemove', handleMouseMove, true);
237
- };
238
  };
239
 
240
  let generating = false;
241
 
242
- generateButton.addEventListener('click', async () => {
 
 
 
 
 
243
  if (generating) {
244
  return;
245
  }
246
 
247
- const renderSection = document.querySelector('section.render');
248
- const durationDisplay = document.querySelector('.duration');
249
- const initialiseCardRotation = cardRotationInitiator(renderSection);
250
-
251
  try {
 
 
 
 
 
 
 
 
252
  generating = true;
253
 
 
 
254
  const details = await generateDetails();
255
- const task = await createTask(details.energy_type);
256
 
257
- const timer = durationTimer(durationDisplay);
258
- const timerCleanup = timer().cleanup;
259
 
260
- const longPromises = [queueTask(task.task_id), longPollTask(task)];
261
- const completedTask = await Promise.any(longPromises);
 
262
 
263
- generating = false;
264
- timerCleanup(completedTask);
 
265
 
266
- renderSection.innerHTML = cardHTML(details);
267
- const picture = document.querySelector('img.picture');
268
- picture.src = completedTask.value;
269
- initialiseCardRotation();
 
 
 
 
 
270
  } catch (err) {
271
  generating = false;
272
  console.error(err);
273
  }
274
- });
 
 
 
 
 
 
 
 
 
 
 
105
  >Illus. Max Woolf</a
106
  ></span
107
  >
108
+ <span><a href="https://huggingface.co/spaces/launch">${new Date().getFullYear()} Hugging Face</a></span>
109
+ <span title="Rarity">${rarity}</span>
110
  </div>
111
  </div>`;
112
  };
211
  const rotateX = (containerMouseEvent.clientY - rect.y - rect.height / 2) * RANGE;
212
  const rotateY = -(containerMouseEvent.clientX - rect.x - rect.width / 2) * RANGE;
213
 
214
+ console.log(performance.now() - previousTime);
215
+
216
+ card.style.setProperty('--card-rx', rotateX + 'deg');
217
+ card.style.setProperty('--card-ry', rotateY + 'deg');
218
  }
219
  };
220
  };
221
 
222
+ const initialiseCardRotation = (scene) => {
223
+ const card = document.querySelector('.pokecard');
224
 
225
+ const mousemoveHandler = rotateCard().bind(null, card);
 
226
 
227
+ scene.addEventListener('mousemove', mousemoveHandler, true);
 
 
 
228
 
229
+ return mousemoveHandler;
230
+ };
231
 
232
+ const setScene = (scene, mode, state) => {
233
+ const booster = scene.querySelector('.booster');
234
+ const cardSlot = scene.querySelector('.cardSlot');
235
 
236
+ scene.dataset.mode = mode;
237
+ scene.dataset.state = state;
 
238
  };
239
 
240
  let generating = false;
241
 
242
+ const booster = document.querySelector('.booster');
243
+ const newGenerationButton = document.querySelector('button.generate-new');
244
+
245
+ let mousemoveHandlerForPreviousCard;
246
+
247
+ const generate = async () => {
248
  if (generating) {
249
  return;
250
  }
251
 
 
 
 
 
252
  try {
253
+ const scene = document.querySelector('.scene');
254
+ const cardSlot = scene.querySelector('.card-slot');
255
+ const durationDisplay = document.querySelector('.duration');
256
+
257
+ cardSlot.innerHTML = '';
258
+ // const oldCard = cardSlot.querySelector('.pokecard');
259
+ scene.removeEventListener('mousemove', mousemoveHandlerForPreviousCard, true);
260
+
261
  generating = true;
262
 
263
+ setScene(scene, 'booster', 'generating');
264
+
265
  const details = await generateDetails();
266
+ // const task = await createTask(details.energy_type);
267
 
268
+ // const timer = durationTimer(durationDisplay);
269
+ // const timerCleanup = timer().cleanup;
270
 
271
+ // const longPromises = [queueTask(task.task_id), longPollTask(task)];
272
+ // const completedTask = await Promise.any(longPromises);
273
+ await new Promise((resolve) => setTimeout(resolve, 3_000));
274
 
275
+ setScene(scene, 'booster', 'completed');
276
+
277
+ await new Promise((resolve) => setTimeout(resolve, 1_000));
278
 
279
+ generating = false;
280
+ // timerCleanup(completedTask);
281
+
282
+ // scene.innerHTML = cardHTML(details);
283
+ cardSlot.innerHTML = cardHTML(details);
284
+ // const picture = document.querySelector('img.picture');
285
+ // picture.src = completedTask.value;
286
+ mousemoveHandlerForPreviousCard = initialiseCardRotation(scene);
287
+ setScene(scene, 'card', 'completed');
288
  } catch (err) {
289
  generating = false;
290
  console.error(err);
291
  }
292
+ };
293
+
294
+ booster.addEventListener('click', generate);
295
+ newGenerationButton.addEventListener('click', generate);
296
+
297
+ // generateButton.addEventListener('click', async () => {
298
+
299
+ // booster.addEventListener('click', () => {
300
+
301
+ // })
302
+ // booster.style.display = 'none';
303
+ // generateButton.click();
static/style.css CHANGED
@@ -3,6 +3,14 @@
3
  --card-s: 95%;
4
  --card-l: 58%;
5
  --card-color: hsl(var(--card-h) var(--card-s) var(--card-l));
 
 
 
 
 
 
 
 
6
  }
7
 
8
  html,
@@ -10,27 +18,276 @@ body {
10
  overflow: scroll;
11
  }
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  body {
14
- display: grid;
15
- place-items: center;
16
  height: 100vh;
17
  font-family: 'Gill Sans', 'Gill Sans Mt', 'sans-serif';
18
  background-color: whitesmoke;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
20
 
21
  .duration {
 
 
22
  text-align: right;
 
 
 
 
23
  }
24
 
25
  button {
 
26
  padding: 0.5rem 1rem;
27
- margin: 1rem;
 
 
 
 
 
 
 
 
 
 
28
  }
29
 
30
- section.render {
 
 
 
 
 
 
 
 
 
 
31
  perspective: 100rem;
32
  margin: 0.5rem;
33
  height: 40rem;
 
 
 
 
 
 
 
 
34
  }
35
 
36
  .grass {
@@ -138,6 +395,11 @@ section.render {
138
  filter: contrast(0.75) grayscale(1) sepia(1) saturate(10) hue-rotate(300deg) drop-shadow(0 0 0.1rem pink);
139
  }
140
 
 
 
 
 
 
141
  .pokecard,
142
  .pokecard * {
143
  box-sizing: border-box;
@@ -147,9 +409,10 @@ section.render {
147
  --color: hsl(var(--h) var(--s) var(--l));
148
  --lighter: hsl(var(--h) var(--s) calc(var(--l) + 10%));
149
  --lightest: hsl(var(--h) var(--s) calc(var(--l) + 30%));
150
- --rotate-x: 0deg;
151
- --rotate-y: 0deg;
152
- --rotate-z: 0deg;
 
153
  display: flex;
154
  flex-direction: column;
155
  width: 25rem;
@@ -169,7 +432,7 @@ section.render {
169
  );
170
  transform-origin: center;
171
  transform-style: preserve-3d;
172
- transform: rotateX(var(--rotate-x)) rotateY(var(--rotate-y)) translate3d(10px, 10px, 10px);
173
  transition: transform 0.5s ease-out;
174
  }
175
 
@@ -364,7 +627,361 @@ hr {
364
  margin: auto 0;
365
  }
366
 
367
- a {
368
  text-decoration: none;
369
- color: black !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
370
  }
3
  --card-s: 95%;
4
  --card-l: 58%;
5
  --card-color: hsl(var(--card-h) var(--card-s) var(--card-l));
6
+ --card-width: 25rem;
7
+ --card-aspect: 63 / 88;
8
+ --theme-primary: hsl(158 100% 33%);
9
+ --theme-secondary: hsl(165 67% 48%);
10
+ --theme-ternary: hsl(112 46% 75%);
11
+ --theme-highlight: hsl(111 95% 92%);
12
+ --theme-white: hsl(0 100% 100%);
13
+ --theme-subtext: hsl(0 0% 30%);
14
  }
15
 
16
  html,
18
  overflow: scroll;
19
  }
20
 
21
+ * {
22
+ outline-style: none;
23
+ outline-width: 0.15rem;
24
+ outline-color: var(--theme-primary);
25
+ transition: outline-offset 0.25s ease-out;
26
+ }
27
+
28
+ *:focus-visible:not(input) {
29
+ outline-style: dashed;
30
+ outline-offset: 0.25em;
31
+ /* border-radius: 0.375em; */
32
+ }
33
+
34
+ .info h1::selection {
35
+ text-fill-color: white;
36
+ -webkit-text-fill-color: white;
37
+ -moz-text-fill-color: white;
38
+ }
39
+
40
+ *::selection {
41
+ background-color: gold;
42
+ }
43
+
44
  body {
 
 
45
  height: 100vh;
46
  font-family: 'Gill Sans', 'Gill Sans Mt', 'sans-serif';
47
  background-color: whitesmoke;
48
+ background-image: linear-gradient(300deg, var(--theme-highlight), var(--theme-white));
49
+ }
50
+
51
+ main {
52
+ display: grid;
53
+ grid-template-columns: repeat(auto-fit, minmax(25rem, 1fr));
54
+ place-items: center;
55
+ gap: 1.5rem 0;
56
+ margin: 0 auto;
57
+ max-width: 80rem;
58
+ padding: 3rem;
59
+ }
60
+
61
+ section {
62
+ /* display: flex;
63
+ flex-direction: column; */
64
+ display: grid;
65
+ place-items: center;
66
+ box-sizing: border-box;
67
+ width: 100%;
68
+ /* border: 2px dashed dodgerblue; */
69
+ }
70
+
71
+ .info {
72
+ max-width: 35rem;
73
+ height: min-content;
74
+ }
75
+
76
+ .output {
77
+ height: min-content;
78
+ }
79
+
80
+ .poke-trio {
81
+ display: flex;
82
+ flex-direction: row;
83
+ justify-content: space-between;
84
+ height: 5rem;
85
+ position: relative;
86
+ }
87
+
88
+ .poke-trio > img {
89
+ position: relative;
90
+ user-select: none;
91
+ }
92
+
93
+ .poke-trio > img::after {
94
+ content: '';
95
+ position: absolute;
96
+ top: 0;
97
+ /* bottom: 0; */
98
+ left: 0;
99
+ /* left: 50%; */
100
+ /* width: 100%; */
101
+ /* height: 15%; */
102
+ width: 3rem;
103
+ height: 3rem;
104
+ /* background-color: hsl(0 0% 25% / 0.5); */
105
+ background-color: blue;
106
+ /* border-radius: 50%; */
107
+ border: 2px solid red;
108
+ }
109
+
110
+ .info h1 {
111
+ /* min-width: 25rem; */
112
+ /* background-size: 100%; */
113
+ background-image: linear-gradient(0deg, var(--theme-primary), var(--theme-secondary));
114
+ background-clip: text;
115
+ text-fill-color: transparent;
116
+ -webkit-background-clip: text;
117
+ -moz-background-clip: text;
118
+ -webkit-text-fill-color: transparent;
119
+ -moz-text-fill-color: transparent;
120
+ font-size: 4.5rem;
121
+ font-weight: bold;
122
+ text-align: center;
123
+ margin: 0.5rem auto 3rem;
124
+ /* text-align: left; */
125
+ /* margin: auto; */
126
+ /* padding-bottom: 1rem; */
127
+ transition: font-size 0.5s ease;
128
+ }
129
+
130
+ @media (max-width: 1280px) {
131
+ .info h1 {
132
+ font-size: 3rem;
133
+ }
134
+ }
135
+
136
+ /* @media (min-width: 600px) and (max-width: 1280px) { */
137
+ @media (max-width: 1280px) {
138
+ /* .scene[data-mode='card'] {
139
+ --scale: 0.8;
140
+ } */
141
+ .card-slot > .pokecard {
142
+ --card-scale: 0.8;
143
+ }
144
+ }
145
+
146
+ /* .info hr {
147
+ width: 100%;
148
+ border-width: 1px;
149
+ margin: 1rem;
150
+ } */
151
+
152
+ .info label {
153
+ width: 100%;
154
+ font-weight: 700;
155
+ font-size: 1.25rem;
156
+ text-align: center;
157
+ }
158
+
159
+ .info input {
160
+ box-sizing: border-box;
161
+ display: block;
162
+ width: 80%;
163
+ padding: 0.5rem 1rem;
164
+ margin: 0.5rem auto;
165
+ /* border-radius: 0.375rem;
166
+ border: hsl(0 0% 70%);
167
+ box-shadow: 0 0 0.1rem var(--theme-primary); */
168
+ border-radius: 1rem;
169
+ border: 0.2rem solid hsl(0 0% 70%);
170
+ /* box-shadow: 0 0 0.1rem var(--theme-primary); */
171
+ box-shadow: 0 0 0.25rem hsl(165.1 64.7% 48.8% / 60%);
172
+ /* box-shadow: 0 0 0.25rem hsl(165.1 64.7% 48.8% / 60%); */
173
+ font-size: 1.25rem;
174
+ text-align: center;
175
+ outline-color: white;
176
+ /* transition: outline-color 0.5s ease-in; */
177
+ transition: border-color 0.25s ease-in;
178
+ /* outline: none; */
179
+ }
180
+
181
+ input:focus {
182
+ border-color: transparent;
183
+ /* border-color: var(--theme-primary); */
184
+ outline-style: solid;
185
+ outline-color: var(--theme-primary);
186
+ }
187
+
188
+ .info input::placeholder {
189
+ text-align: center;
190
+ }
191
+
192
+ .info p {
193
+ width: 80%;
194
+ margin: 3rem auto 0;
195
+ line-height: 1.5rem;
196
+ text-align: justify;
197
+ color: var(--theme-subtext);
198
+ }
199
+
200
+ .info a:is(:hover, :focus, :active, :visited) {
201
+ color: inherit;
202
+ }
203
+
204
+ /* Output Section */
205
+
206
+ .output .actions {
207
+ display: flex;
208
+ flex-direction: row;
209
+ justify-content: center;
210
+ align-items: center;
211
+ gap: 1rem;
212
+ width: 100%;
213
+ margin: 1rem auto 2.5rem;
214
+ }
215
+
216
+ @media (max-width: 500px) {
217
+ main {
218
+ padding: 3rem 0;
219
+ /* background-color: hotpink !important; */
220
+ }
221
+
222
+ .output .actions {
223
+ display: flex;
224
+ flex-wrap: wrap;
225
+ width: 90vw;
226
+ }
227
+
228
+ /* .output .actions > button {
229
+ width: max-content;
230
+ width: 40rem;
231
+ whitespace: nowrap;
232
+ } */
233
+
234
+ /* .info h1 {
235
+ font-size: 3rem;
236
+ } */
237
+
238
+ /* .scene {
239
+ transform: scale(0.8);
240
+ } */
241
  }
242
 
243
  .duration {
244
+ color: var(--theme-subtext);
245
+ margin-left: auto;
246
  text-align: right;
247
+ width: max-content;
248
+ background-color: var(--theme-highlight);
249
+ padding: 0.5rem 1rem;
250
+ border-radius: 1rem;
251
  }
252
 
253
  button {
254
+ whitespace: nowrap;
255
  padding: 0.5rem 1rem;
256
+ border: none;
257
+ border-radius: 1rem;
258
+ /* margin: 1rem; */
259
+ background-image: linear-gradient(-90deg, var(--theme-ternary), var(--theme-secondary));
260
+ /* color: var(--theme-white); */
261
+ color: white;
262
+ font-weight: bold;
263
+ box-shadow: 0 0.2rem 0.375rem hsl(158 100% 33% / 60%);
264
+ transition: transform 0.1s ease-out, box-shadow 0.1s, outline-offset 0.25s ease-out;
265
+ cursor: pointer;
266
+ user-select: none;
267
  }
268
 
269
+ button:active {
270
+ transform: translateY(0.1rem);
271
+ box-shadow: none;
272
+ }
273
+
274
+ /* button:focus-visible: {
275
+ outline-offset: 1em !important;
276
+ } */
277
+
278
+ .scene {
279
+ --scale: 0.9;
280
  perspective: 100rem;
281
  margin: 0.5rem;
282
  height: 40rem;
283
+ /* height: 100%; */
284
+
285
+ /* transform: scale(2); */
286
+ box-sizing: border-box;
287
+ /* border: 2px dashed gold; */
288
+ transform-origin: top;
289
+ transform: scale(var(--scale));
290
+ transition: transform 0.5s ease-out;
291
  }
292
 
293
  .grass {
395
  filter: contrast(0.75) grayscale(1) sepia(1) saturate(10) hue-rotate(300deg) drop-shadow(0 0 0.1rem pink);
396
  }
397
 
398
+ .card-slot {
399
+ perspective: 100rem;
400
+ transition: transform 0.5s ease-out;
401
+ }
402
+
403
  .pokecard,
404
  .pokecard * {
405
  box-sizing: border-box;
409
  --color: hsl(var(--h) var(--s) var(--l));
410
  --lighter: hsl(var(--h) var(--s) calc(var(--l) + 10%));
411
  --lightest: hsl(var(--h) var(--s) calc(var(--l) + 30%));
412
+ --card-rx: 0deg;
413
+ --card-ry: 0deg;
414
+ --card-rz: 0deg;
415
+ --card-scale: 1;
416
  display: flex;
417
  flex-direction: column;
418
  width: 25rem;
432
  );
433
  transform-origin: center;
434
  transform-style: preserve-3d;
435
+ transform: rotateX(var(--card-rx)) rotateY(var(--card-ry)) scale(var(--card-scale));
436
  transition: transform 0.5s ease-out;
437
  }
438
 
627
  margin: auto 0;
628
  }
629
 
630
+ .pokecard a {
631
  text-decoration: none;
632
+ color: inherit !important;
633
+ }
634
+
635
+ /* Booster Pack */
636
+
637
+ .booster {
638
+ display: none;
639
+ --booster-rx: 0deg;
640
+ --booster-ry: 0deg;
641
+ /* --booster-ry: 65deg; */
642
+ --booster-rz: -5deg;
643
+ /* --booster-rz: 0deg; */
644
+ --booster-scale: 0.7;
645
+ /* --width: 18.9rem;
646
+ --height: 27.2rem; */
647
+ --width: var(--card-width);
648
+ --height: calc(var(--card-width) / 66 * 88);
649
+ --depth: 0.5rem;
650
+ --bg: hsl(227, 54%, 21%);
651
+ /* --foil: */
652
+ /* width: var(--width);
653
+ height: var(--height); */
654
+ width: var(--width);
655
+ height: var(--height);
656
+ position: relative;
657
+ transform-style: preserve-3d;
658
+ transform: rotateX(var(--booster-rx)) rotateY(var(--booster-ry)) rotateZ(var(--booster-rz))
659
+ scale(var(--booster-scale));
660
+ transition: transform 0.5s ease-in-out;
661
+ cursor: pointer;
662
+ }
663
+
664
+ .booster > div {
665
+ position: absolute;
666
+ display: grid;
667
+ place-items: center;
668
+ font-size: 5rem;
669
+ transform-origin: center;
670
+ user-select: none;
671
+ }
672
+
673
+ .face:is(.front, .back, .left, .right) {
674
+ height: var(--height);
675
+ background-color: var(--bg);
676
+ }
677
+
678
+ .face:is(.front, .back, .top, .bottom) {
679
+ width: var(--width);
680
+ }
681
+ .left,
682
+ .right {
683
+ width: var(--depth);
684
+ }
685
+
686
+ .face:is(.top, .bottom) {
687
+ height: var(--depth);
688
+ }
689
+
690
+ .foil {
691
+ width: var(--width);
692
+ background-image: linear-gradient(
693
+ 90deg,
694
+ hsl(0 0% 80%) 0%,
695
+ hsl(0 0% 84%) 10%,
696
+ hsl(0 0% 88%) 20%,
697
+ hsl(0 0% 92%) 30%,
698
+ hsl(0 0% 96%) 40%,
699
+ hsl(0 0% 100%) 50%,
700
+ hsl(0 0% 96%) 60%,
701
+ hsl(0 0% 92%) 70%,
702
+ hsl(0 0% 88%) 80%,
703
+ hsl(0 0% 84%) 90%,
704
+ hsl(0 0% 80%) 100%
705
+ );
706
+ }
707
+ .foil.top.flat {
708
+ transform-origin: bottom;
709
+ transform: translate3d(0, -30px, 0px) rotateX(0deg);
710
+ height: 20px;
711
+ }
712
+ .foil.top.flat::after,
713
+ .foil.bottom.flat::after {
714
+ content: '';
715
+ position: absolute;
716
+ width: var(--width);
717
+ height: 20px;
718
+ background: radial-gradient(#ffffff 0%, transparent 50%);
719
+ background-size: 1% 100%;
720
+ }
721
+ .foil.top.front {
722
+ transform-origin: bottom;
723
+ transform: translate3d(0, -11.4px, 3.8px) rotateX(20.5deg);
724
+ height: 11px;
725
+ }
726
+ .foil.top.back {
727
+ transform-origin: bottom;
728
+ transform: translate3d(0, -11.4px, -4px) rotateX(339deg);
729
+ height: 11px;
730
+ }
731
+ .face.front {
732
+ transform: rotateY(0deg) translate3d(0, 0, calc(var(--depth) / 2));
733
+ }
734
+ .face.left {
735
+ transform: rotateY(90deg) translate3d(0, 0, calc(var(--width) - calc(var(--depth) / 2)));
736
+ }
737
+ .face.back {
738
+ transform: rotateY(180deg) translate3d(0, 0, calc(var(--depth) / 2)) rotateZ(180deg);
739
+ }
740
+ .face.right {
741
+ transform: rotateY(-90deg) translate3d(0, 0, calc(var(--depth) / 2));
742
+ }
743
+ .face.top {
744
+ transform: rotateX(90deg) translate3d(0, 0, calc(var(--depth) / 2));
745
+ }
746
+ .face.bottom {
747
+ transform: rotateX(-90deg) translate3d(0, 0, calc(var(--height) - calc(var(--depth) / 2)));
748
+ }
749
+ .foil.bottom.flat {
750
+ transform-origin: top;
751
+ transform: translate3d(0, calc(var(--height) + 10px), 0px) rotateX(0deg);
752
+ height: 20px;
753
+ }
754
+ .foil.bottom.front {
755
+ transform-origin: top;
756
+ transform: translate3d(0, var(--height), 3.8px) rotateX(-19.5deg);
757
+ height: 11px;
758
+ }
759
+ .foil.bottom.back {
760
+ transform-origin: top;
761
+ transform: translate3d(0, var(--height), -3.8px) rotateX(19.5deg);
762
+ height: 11px;
763
+ }
764
+
765
+ .foil.back.flat {
766
+ transform-origin: bottom;
767
+ transform: translate3d(calc(var(--width) / 2 - 25px), 0px, calc(var(--depth) * -0.50001)) rotateX(0deg);
768
+ width: 30px;
769
+ height: var(--height);
770
+ transform-style: preserve-3d;
771
+ background-image: linear-gradient(
772
+ 90deg,
773
+ hsl(0 0% 0%) 0%,
774
+ hsl(0 0% 10%) 20%,
775
+ hsl(0 0% 40%) 30%,
776
+ hsl(0 0% 60%) 40%,
777
+ hsl(0 0% 86%) 50%,
778
+ hsl(0 0% 90%) 60%,
779
+ hsl(0 0% 85%) 80%,
780
+ hsl(0 0% 90%) 90%,
781
+ hsl(0 0% 70%) 100%
782
+ );
783
+ }
784
+ .foil.back.flap {
785
+ transform-origin: center;
786
+ transform: translate3d(calc(var(--width) / 2 - 25.5px), 0, -8px) rotateY(15deg);
787
+ width: 30px;
788
+ height: var(--height);
789
+ transform-style: preserve-3d;
790
+ background-image: linear-gradient(
791
+ 90deg,
792
+ hsl(0 0% 70%) 0%,
793
+ hsl(0 0% 74%) 10%,
794
+ hsl(0 0% 78%) 20%,
795
+ hsl(0 0% 82%) 30%,
796
+ hsl(0 0% 86%) 40%,
797
+ hsl(0 0% 90%) 50%,
798
+ hsl(0 0% 86%) 60%,
799
+ hsl(0 0% 82%) 70%,
800
+ hsl(0 0% 78%) 80%,
801
+ hsl(0 0% 74%) 90%,
802
+ hsl(0 0% 70%) 100%
803
+ );
804
+ }
805
+
806
+ .foil.back.flap::after {
807
+ content: '';
808
+ position: absolute;
809
+ width: 30px;
810
+ height: var(--height);
811
+ background: radial-gradient(#ffffff 0%, transparent 50%);
812
+ background-size: 100% 0.75%;
813
+ }
814
+
815
+ .gradient-bg {
816
+ background-image: linear-gradient(
817
+ 225deg,
818
+ hsl(270deg 100% 7%) 0%,
819
+ hsl(246deg 77% 15%) 14%,
820
+ hsl(223deg 59% 24%) 29%,
821
+ hsl(199deg 44% 35%) 43%,
822
+ hsl(175deg 32% 48%) 57%,
823
+ hsl(151deg 36% 62%) 71%,
824
+ hsl(128deg 45% 78%) 86%,
825
+ hsl(104deg 100% 95%) 100%
826
+ );
827
+ }
828
+
829
+ .face.front {
830
+ display: flex;
831
+ flex-direction: column;
832
+ justify-content: space-evenly;
833
+ gap: 0.5rem;
834
+ box-sizing: border-box;
835
+ padding: 1rem;
836
+ }
837
+
838
+ .face.front,
839
+ .face.back {
840
+ background-image: url("data:image/svg+xml;utf8,<svg id='patternId' width='100%' height='100%' style='opacity: 0.1' xmlns='http://www.w3.org/2000/svg'><defs><pattern id='a' patternUnits='userSpaceOnUse' width='100' height='100' patternTransform='scale(3) rotate(45)'><rect x='0' y='0' width='100%' height='100%' fill='hsla(0, 0%, 0%, 0)'/><path d='M4.43 0c.17.58.34 1.12.52 1.58.29.76.59 1.51.9 2.25 1.59 3.68 4.3 5.96 8.1 7.2 2.69.88 6.77 1.47 10.1 1.58.14 0-.38-1.66-.93-3.38-.77-2.4-.74-4.74-1.27-7.16-.16-.7-.4-1.4-.7-2.07h-3.37c.19.24.37.49.54.74 1.25 1.83 1.73 4.07 2.07 6.2.17 1.08.33 2.67 1 3.45-.61-.28-3.5-1.2-3.97-1.4-2.94-1.2-5.53-1.08-7.84-3.6C8.21 3.9 7.56 1.96 6.87 0zm22.6 0a30.74 30.74 0 001.89 3.75c.09-1.1.54-2.51.94-3.75zm8.85 0c-3.4 5.03-5.04 11.1-.88 16.5 1.77 2.16 3.52 4.33 5.14 6.6 1.45 2.02 2.6 4.46 4.36 6.23.04.05 2.12-3.78 2.27-4.14.69-1.58 1.25-3.22 1.98-4.79 1.57-3.4 3.8-6.5 5.32-9.89v-.02c1.32-2.95 1.3-6.26 1.2-9.43 0-.25 0-.6-.03-1.06h-2.3a22.37 22.37 0 01.7 4.7 9.7 9.7 0 01-.57 3.33 15.35 15.35 0 01-1.74 3.47c-2.83 4.33-5.16 8.5-7.83 12.67-.33-.71-.58-1.42-.87-2.13l-.07-.15c-.1-.25-.2-.5-.32-.74l-.08-.17a10.11 10.11 0 00-.96-1.5l-.06-.08a12.18 12.18 0 00-.68-.79l-.39-.41a19.1 19.1 0 01-1.13-1.28 9.06 9.06 0 01-.67-.98 18.88 18.88 0 01-1.65-3.29c-.35-.96-.62-1.95-.76-2.96-.11-.8-.15-1.62-.1-2.45.18-2.9 1.5-5.18 3.22-7.24zm26.83 0a23.38 23.38 0 01-.85 3.63c-.46 1.47-1.2 2.97-1.2 4.54 1.79-2.23 4.86-2.88 7.38-3.93 2.63-1.1 5.25-2.37 7.42-4.24zM16.08 18.25c-.28 0-.55 0-.83.02-1.61-.05-3.17.34-4.75.73-1.11.28.44 1.06 2.67 4.17 2.31 3.24 3.84 8.76 8.33 9.66 3.01.6 6.15-.06 9.15-.45.47-.06 6.11-1.02 6.23-.6-.06-.23-.4-.58-1-1.08a22.05 22.05 0 01-4.18-4.47 17.1 17.1 0 00-4.7-4.81 19.07 19.07 0 00-10.92-3.17zm67.25 8.58a45.04 45.04 0 01-6.41 8c-2.57 2.46-5.57 4.03-8.59 5.84-3.22 1.93-4.9 6.23-4.16 9.83 1 5.33 2.16 10.17 2.38 15.35.04.9.45 3.98 1.37 4.98.56-.96 1.91-3.21 2.55-4.1a86.54 86.54 0 018.08-9.4c1.94-2.01 4.3-3.98 5.73-6.41a7.71 7.71 0 001.12-3.62c.27-6.8.6-13.97-2.07-20.47zm-1.16 7.5c-.25 4.67-.59 9.63-1.83 14.22a18.17 18.17 0 01-2.05 5.12c-2.46 3.83-6.12 6.5-9.29 9.83.25-1.92-.33-3.67-.48-5.58-.2-2.76-1.26-5.32-1.55-8.03-.1-.86-.04-1.73.3-2.57 1.16-2.92 4.3-5.4 6.7-7.32 1.52-1.23 7.03-3.83 8.2-5.67zM36.6 39.5c-4.17-.04-7.9 1.7-12.1 2.34-3.65.82-8.63.16-11.9 2.12-1.91 1.14-2.89 3.37-4.2 5.1-1.86 3.1-6 5.72-8.4 8.83v6.22c4.92-2.43 10.42-2.03 15.9-2.13 4.62-.08 10.32-.37 13.46-4.3 1.48-1.86 1.27-4.84 2.03-7.03.88-2.54 2.26-4.87 3.55-7.22.21-.4 1.4-3.25 2.06-3.92l-.4-.01zm-3.68 3.34c-2.77 3.2-5.32 7.08-8.25 12.17a9.54 9.54 0 01-4.7 4.3c-2.12.83-4.84.35-7.06.34a37.4 37.4 0 00-6.3.41c-1.33.22-3.2.37-5.2 1.53.13-.54 1.06-2.06 1.31-2.57 1.26-2.55 3.92-4.68 5.72-6.6 1.98-2.11 4.23-3.97 6.96-5.01 2.27-.87 4.66-1.37 7.04-1.88 2.33-.5 8.9-2.6 10.48-2.69zM100 57.88c-1.56 2.02-2.39 4.25-1.33 6.95.44-.27.88-.51 1.33-.73zM32.75 62.5c-1.75 2-4.07 5.92-5.85 8.13-2.37 2.95-5.05 6.05-5.27 9.84-.17 2.92.85 5.76 1.72 8.5 1.18 3.7 2.15 7.47 3.67 11.03h2.84c.16-.51.32-1 .43-1.4 1.23-4.34 3.72-8.16 6.38-11.77 2.56-3.47 2-8.6.5-12.42-.56-1.4-1.37-2.57-2.18-3.83-.93-1.44-1.26-3.1-1.8-4.7-.21-.66-.44-2.13-.44-3.38zM9.75 81C7.33 82.58 3.1 82.39.22 82.64l-.22.02v6.5c.5.08 1 .15 1.5.17 3.82.18 7.19-5.15 8.25-8.33zm38.58.17a34.68 34.68 0 01-7.05 12.75c-1.15 1.25-2.5 2.4-3.58 3.67-.64.77-1.25 1.58-1.82 2.41h3.1c1.5-1.8 3.32-3.42 4.93-5.12 1.78-1.88 2.79-4.1 3.74-6.38.13-.33.6-1.83.93-2.92 1.4 2.9 2.3 6.78 3.12 9.87.4 1.52.87 3.02 1.25 4.55h2.29c-.12-2.43-.87-8.03-6.9-18.83zm51.67 1.5c-2.4.22-4.95.7-6.92 2.18-.83.62-3.08 3.82-3.41 5.32 1.43-.92 3.08-1.9 4.81-1.94 1.88-.04 3.68.6 5.52.93zm-15.83 1.16a95.53 95.53 0 01-7.97 3.32c-4.2 1.53-9.96 2.46-12.32 6.78-.8 1.46-.94 3.3-1.05 4.94-.03.38-.07.76-.12 1.13h12.75l.39-.35c1.74-1.6 2.91-3.86 4.04-5.92a37.51 37.51 0 004.28-9.9zm-80.7 8.28c-.9 0-1.74.14-2.47.56 1.45 2.27 2.41 4.8 3.36 7.33h2.5a16.57 16.57 0 00-2.03-4.33c1.34 0 2.5 0 3.77-.13.25-.03.5-.04.75-.05 3.43-.06 6.36 1.85 8.43 4.51h3.37a14.48 14.48 0 00-1.76-2.91c-2.43-3.13-5.9-4.06-9.69-4.4-1.97.1-4.24-.58-6.23-.58z' stroke-width='1' stroke='none' fill='hsla(174, 100%, 29%, 1)'/><path d='M38.98 0c-1.72 2.06-3.04 4.34-3.22 7.24-.2 3.3 1.02 6.52 2.85 9.22.86 1.27 2.07 2.21 2.93 3.47.96 1.4 1.3 2.82 1.96 4.24 2.67-4.17 5-8.34 7.83-12.67 1.43-2.19 2.43-4.64 2.3-7.3a22.37 22.37 0 00-.68-4.2zm19.68 0a27.2 27.2 0 01-.12 4.26c-.4 2.95-.95 5.94-.37 8.9 3-.83 4.66-3.66 7.37-4.78C70.23 6.44 74.71 3.82 78.1 0h-2.64c-2.17 1.87-4.8 3.14-7.42 4.24-2.52 1.05-5.59 1.7-7.37 3.93 0-1.57.73-3.07 1.19-4.54.37-1.2.67-2.4.85-3.63zM97.4 6.96c-.03 0-.05.01-.07.04C93.17 15.33 84 23.17 86.9 33.34c1.12 3.97 4.3 6.5 6.73 9.65 2.08 2.7 3.07 5.46 4.42 8.5l1.96-2.86v-4.48c-.48.8-.98 1.56-1.5 2.24-.44-3.45-3.5-7.39-6.17-10.72-1.86-2.23-2.13-5.54-2.15-8.33-.03-6.4 4.9-10.22 7.65-15.5 1 1.1.7 3.71 1.12 5 .38 1.2.71 2.39 1.05 3.58v-9.45l-.12-.42c-.1-.34-2.06-3.54-2.48-3.59zm-97.4 4v9.46c.37 1.3.77 2.61 1.28 3.89 1.12 2.73 3.07 5.38 3.24 8.41.05.94-.1 1.92-.52 2.95a67.51 67.51 0 01-4 8.48v4.48c2.65-3.97 4.22-7 5.88-11.48.62-1.67 1.35-3.51 1.37-5.35.03-2.32-1.44-4.3-2.29-6.25-1.04-2.4-2.47-4.61-3.42-7.05C.58 16.05.68 13.46 0 10.97zm65.04 3.85l-.04.02c-1.35 1.36-3.08 2.3-4.58 3.47-2.34 1.84-3.93 4.46-6.06 6.51-1.37 1.32-2.7 2.75-2.34 4.8.88 4.88 2.09 9.82 5.31 13.72a16.93 16.93 0 011.57-4.14c1.43-2.49 4-3.85 5.97-5.83 2.48-2.48 3.29-5.9 2.8-9.36-.65-3.23-2.16-9.2-2.63-9.19zM91 59.33a36.8 36.8 0 01-3.61 1.65c-1.49.6-3 1.1-4.45 1.8-3.36 1.59-6.83 3.78-8.2 7.36-.7 1.8-1.12 3.58-2.05 5.32-.94 1.76-2.02 3.47-2.69 5.37 1.83-1 5.84-2.2 7.54-2.74 1.7-.54 3.5-.83 5.06-1.76a10.69 10.69 0 004.15-4.89c1.21-2.75.9-5.94 2.24-8.65.68-1.12 1.51-2.29 2.01-3.46zm-68 5.34a40.93 40.93 0 01-7.83 1.66c-3.61.4-7.25.17-10.86.65-1.47.12-2.92.5-4.31 1.1v1.95a16.41 16.41 0 019.19-2.3c2.7.11 5.14.77 7.81.44-.67.66-1.18 1.4-1.49 1.75-1.47 1.7-3 3.43-5.01 4.52a18.8 18.8 0 01-8.72 2.1c-.2.01-.9-.03-1.78-.08v1.6c.83 0 1.66-.02 2.48-.07 3.02-.15 5.92-.56 8.64-1.98a27.4 27.4 0 006.95-5.28 45.84 45.84 0 003.24-3.78c.21-.27 1.1-1.53 1.69-2.28zm77 3.4c-4.42 1.87-8.17 5.82-9.5 10.26 0 0 2.86-.12 3.24-.15 2.02-.14 4.15-.1 6.26-.12v-1.6l-1.57-.08a20.72 20.72 0 00-4.08.13l-.22.05c.37-.98.94-1.78 1.2-2.15a15.34 15.34 0 014.67-4.38zM87.17 80c-1.09.42-4.75 1.51-5.28 1.7-3.44 1.3-6.79 2.81-10.24 4.06-2.6.94-5.22 1.46-7.65 2.85-3.6 2.04-5.33 5.33-5.36 9.41 0 .66 0 1.32.02 1.98h4.05c.05-.37.1-.75.12-1.13.1-1.64.25-3.48 1.05-4.94 2.36-4.32 8.12-5.25 12.32-6.78 2.7-.98 5.36-2.1 7.97-3.32-1 3.5-2.34 6.84-4.28 9.9-1.13 2.06-2.3 4.31-4.04 5.92l-.39.35h2.64c3.1-3.5 5.56-7.71 7.1-12.13A45.45 45.45 0 0087.16 80zm-38.59 5.58c-.33 1.09-.8 2.6-.93 2.92-.95 2.28-1.96 4.5-3.74 6.38-1.61 1.7-3.42 3.32-4.93 5.12h13.97c-.38-1.53-.84-3.03-1.25-4.55-.82-3.1-1.73-6.97-3.12-9.87z' stroke-width='1' stroke='none' fill='hsla(0, 0%, 22%, 1)'/><path d='M80.57 0c-.35.33-.7.66-1.03 1-3.65 3.67-6.35 8.32-6.71 13.57-.16 2.3.06 4.61.3 6.9.24 2.2.98 6.53 1.54 9.7 2.79-2.7 4.55-6.26 7.41-8.86 1.52-1.38 3.2-2.55 4.62-4.04a24.4 24.4 0 003.64-5.12c.77-1.4 1.62-2.83 2.12-4.36l.09-.28c.47-1.61.53-3.3.85-4.94.25-1.24.74-2.42 1.25-3.57h-3.31c-.37.74-.66 1.52-.84 2.32-.34 1.5-.32 3.08-.52 4.6a16.5 16.5 0 01-1.07 4.13 16.93 16.93 0 01-4.28 5.91c-1.57 1.48-3.33 2.74-4.8 4.32-1.46 1.59-2.51 3.49-4 5.05 0-2.63-.43-5.23-.26-7.86.17-2.65.38-5.3.8-7.93.35-2.1.95-4.22 2.4-5.85C80.3 3 82.39 1.8 84.37.68l1.2-.68zm17.26 11.84c-2.74 5.28-7.68 9.1-7.65 15.5.02 2.8.3 6.1 2.15 8.33C95 39 98.06 42.94 98.5 46.39c.52-.68 1.02-1.44 1.5-2.24V20.42c-.34-1.2-.67-2.39-1.05-3.57-.43-1.3-.12-3.9-1.12-5.01zm-89.68 2.4c-1.48-.02-2.94.17-4.32.76 1.88 2.89 4.27 5.44 5.43 8.74 1.07 3.04 1.37 6.31 2.8 9.23 1.54 3.16 4.84 5.14 8.22 5.8 3.66.7 6.91-1.03 10.32-2.05 3.37-1 6.4-2.89 9.82-3.64.86-.19-1.66-3.3-2.9-4.49-.38-.37-.7-.66-.82-.82-1.4-1.7-2.5-3.62-3.44-5.6-1.16-2.47-2.55-4.82-5.31-5.65-4.04-1.22-8.26-1.2-12.43-1.5-2.37-.18-4.9-.76-7.37-.78zm7.93 4.01c4.09-.01 7.75 1.04 10.93 3.17a17.1 17.1 0 014.7 4.81c1.15 1.7 2.6 3.15 4.17 4.47.6.5.94.85 1 1.08-.12-.42-5.76.54-6.23.6-3 .4-6.14 1.06-9.15.45-4.5-.9-6.02-6.42-8.33-9.66-2.23-3.11-3.78-3.9-2.67-4.17a17.51 17.51 0 015.58-.75zM0 20.42v23.73a67.51 67.51 0 004-8.48c.42-1.03.57-2 .52-2.95-.17-3.03-2.12-5.68-3.24-8.41A37.8 37.8 0 010 20.42zm82.17 13.91c-1.17 1.84-6.68 4.44-8.2 5.67-2.4 1.92-5.54 4.4-6.7 7.32-.34.84-.4 1.7-.3 2.57.29 2.71 1.34 5.27 1.55 8.03.15 1.91.73 3.66.48 5.58 3.17-3.33 6.83-6 9.3-9.83.99-1.55 1.56-3.35 2.04-5.12 1.24-4.6 1.58-9.55 1.83-14.22zM44 39.83c-4 5-5.33 13.34-5.67 20-.24 4.96 1.97 10.36 6.54 12.83 1.95 1.05 4.16 1.49 6.19 2.35 1.9.8 3.68 1.8 5.47 2.8 5.22 2.94 6.28 4.63 6.47 4.19 1.33-3.08 1.02-6.82.92-10.02-.05-1.52-.08-3.04-.09-4.56.33-4.86-.2-10.61-4.67-13.53-2.05-1.57-4.7-1.71-6.98-2.75C47.5 49 47 43.5 44 39.84zm-11.08 3c-1.59.09-8.15 2.19-10.48 2.7-2.38.5-4.77 1-7.04 1.87-2.73 1.04-4.98 2.9-6.96 5-1.8 1.93-4.46 4.06-5.72 6.61-.25.5-1.18 2.03-1.3 2.57 2-1.16 3.86-1.31 5.18-1.53a37.4 37.4 0 016.31-.41c2.22.01 4.94.5 7.07-.34a9.54 9.54 0 004.69-4.3c2.94-5.1 5.48-8.96 8.25-12.17zm10.39 2.59c1.52 4.08 4.97 8.29 7.26 9.87 2.13 1.47 4.69 2.17 6.65 3.94 1.75 1.58 2.22 3.48 2.61 5.73.26 1.44 1.19 9.1 1.11 11.32-.55-.84-4.6-2.7-5.12-3.01-3.13-1.8-7.19-2.57-9.88-5.03-3.55-3.25-3.92-8.85-3.75-13.35.08-2.17.71-6.94 1.12-9.47zm53.02 45.75c-.83 1-1.66 1.83-2.66 2.16-1.81.6-3.57 1.32-5.35 2.01A22.3 22.3 0 0083 97.98c-.84.62-1.65 1.3-2.42 2.02h5c2.27-1.29 5.6-3.14 8.37-3.89-.25.39-1.44 1.84-1.69 2.24a18.8 18.8 0 00-.91 1.65h3.3l.17-.36c.91-2.03 2.43-4.4 2.21-6.7a3.21 3.21 0 00-.69-1.77z' stroke-width='1' stroke='none' fill='hsla(199, 59%, 53%, 1)'/><path d='M6.87 0c.69 1.95 1.34 3.9 2.71 5.4 2.31 2.5 4.9 2.4 7.84 3.6.46.19 3.36 1.11 3.97 1.39-.67-.78-.83-2.37-1-3.45-.34-2.13-.82-4.37-2.07-6.2-.17-.25-.35-.5-.54-.74zm17.09 0C25.5 2.97 27.27 5.84 29 8.67c.25-.92.84-2.54 1.07-3.08.76-1.84 1.33-3.73 1.98-5.59h-2.2c-.4 1.24-.84 2.66-.93 3.75A30.74 30.74 0 0127.02 0zm61.6 0l-1.2.68c-1.98 1.1-4.06 2.3-5.58 4.01-1.46 1.63-2.06 3.74-2.4 5.85a83.57 83.57 0 00-.81 7.93c-.17 2.63.26 5.23.26 7.86 1.49-1.56 2.54-3.46 4-5.05 1.47-1.58 3.23-2.84 4.8-4.32 1.8-1.7 3.33-3.6 4.28-5.91.54-1.33.89-2.7 1.07-4.13.2-1.52.18-3.1.52-4.6.18-.8.47-1.58.84-2.32zm-19.4 10.17c-.41.75-2.77 2.88-3.1 3.19a27.62 27.62 0 01-3.93 3.01c-5.3 3.3-11.46 7.8-9.96 14.96 1.5 6.67 3 14.34 9.66 17.5.2-.94.47-1.85.81-2.72a18.7 18.7 0 013.68-5.84c1.56-1.66 3.54-2.83 5.2-4.38 2.46-2.32 1.92-5.43 1.62-8.48-.5-5.02-1.74-9.9-3.02-14.75-.29-.85-.6-1.68-.95-2.5zm-1.12 4.64c.47 0 1.98 5.96 2.63 9.19.49 3.46-.32 6.88-2.8 9.36-1.97 1.98-4.54 3.34-5.97 5.83-.3.53-1.4 2.9-1.57 4.14-3.22-3.9-4.43-8.84-5.3-13.71-.38-2.06.96-3.5 2.33-4.8 2.13-2.06 3.72-4.68 6.06-6.52 1.5-1.18 3.23-2.11 4.58-3.47a.06.06 0 01.04-.02zm-21.73 30.6c-.4 2.54-1.04 7.31-1.12 9.48-.17 4.5.2 10.1 3.75 13.35 2.7 2.46 6.75 3.22 9.88 5.03.52.3 4.57 2.17 5.12 3 .08-2.2-.85-9.87-1.1-11.31-.4-2.25-.87-4.15-2.62-5.73-1.96-1.77-4.52-2.47-6.65-3.94-2.3-1.58-5.74-5.79-7.26-9.87zm-8.48 9.26c-1 2.27-2.31 4.31-3.8 6.21-2.14 2.73-4.73 5.82-7.46 7.97-2.33 2.34-4.7 4.1-5.3 7.54-.75 4.3.7 9.01 1.63 13.1.85 3.7 2.32 7.18 4.06 10.51h3.06c-1.52-3.56-2.49-7.33-3.67-11.04-.87-2.73-1.9-5.57-1.72-8.49.22-3.8 2.9-6.9 5.27-9.84 1.78-2.2 4.1-6.13 5.85-8.13 0 1.25.23 2.72.45 3.38.53 1.6.86 3.26 1.79 4.7.8 1.26 1.62 2.44 2.17 3.83 1.51 3.81 2.07 8.95-.5 12.42-2.65 3.6-5.14 7.43-6.37 11.77-.11.4-.27.89-.43 1.4h2.2c.8-2.31 1.73-4.56 3.32-6.56 2.92-3.7 8.14-7.56 7.12-12.94-1.07-5.6-4.96-10.04-6.68-15.4-.74-2.3-.9-4.75-.97-7.15a68.51 68.51 0 01-.02-3.28zm61.67.5c-2.67 1.58-6.63 2.6-8.93 3.04-3.7.72-8.12 2.56-11.32 5.24a14.57 14.57 0 00-2.65 2.85c-2.63 3.79-3.12 8.75-5.16 12.86-1.02 2.05-2.19 4-3.6 5.84 5.59-1.86 10.9-4.63 16.59-6.2 2.07-.57 4.59-.72 6.22-2.28 1.9-1.81 1.8-4.99 2.44-7.36.87-3.2 2.3-6.2 3.83-9.12.85-1.63 1.74-3.24 2.58-4.87zM91 59.33c-.5 1.17-1.33 2.34-2 3.46-1.34 2.7-1.04 5.9-2.25 8.65a10.69 10.69 0 01-4.15 4.9c-1.55.92-3.35 1.2-5.06 1.75-1.7.54-5.7 1.74-7.54 2.74.67-1.9 1.75-3.6 2.7-5.37.92-1.74 1.35-3.51 2.04-5.32 1.37-3.58 4.84-5.77 8.2-7.37 1.45-.69 2.96-1.19 4.45-1.79A36.8 36.8 0 0091 59.33zM8.68 67.72c-3.1-.04-6.1.76-8.68 2.31v6.43c.88.05 1.57.1 1.78.09a18.8 18.8 0 008.72-2.11c2-1.09 3.54-2.81 5.01-4.52.3-.35.82-1.09 1.49-1.75-2.67.33-5.11-.33-7.81-.44l-.51-.01zM100 70.03a15.34 15.34 0 00-4.67 4.38c-.26.37-.83 1.17-1.2 2.15 1.11-.33 3.96-.2 5.87-.1zm-85.06 7.25a42.2 42.2 0 00-4.37 1.17C8.7 79.2 6.81 80 4.81 80.44c-1.59.34-3.2.5-4.81.68v1.54l.22-.02c2.88-.25 7.11-.06 9.53-1.64-1.06 3.18-4.43 8.5-8.25 8.33-.5-.02-1-.09-1.5-.17v.99c1.44-.04 2.9-.07 4.33-.15 1.82-.1 3.38-1.42 4.17-3 .8-1.61 1.64-3.24 2.54-4.8 1.04-1.77 2.38-3.2 3.9-4.92zM100 81.12c-2.07.23-4.14.47-6.15 1.12-5.18 1.6-5.85 7.6-8.18 11.76 3.83-3.5 9.16-4 13.96-3.84l.37-.01v-1c-1.84-.32-3.64-.96-5.52-.92-1.73.04-3.38 1.02-4.81 1.94.33-1.5 2.58-4.7 3.4-5.32 1.98-1.47 4.53-1.96 6.93-2.19zM9.35 95.5a35.79 35.79 0 01-4.52.18c.95 1.3 1.5 2.81 2.04 4.33h10.91c-2.07-2.66-5-4.57-8.43-4.5zm84.6.62c-2.77.75-6.11 2.6-8.39 3.89h5.78c.27-.57.58-1.12.91-1.65.25-.4 1.44-1.85 1.7-2.24z' stroke-width='1' stroke='none' fill='hsla(199, 100%, 62%, 1)'/></pattern></defs><rect width='800%' height='800%' transform='translate(0,0)' fill='url(%23a)'/></svg>");
841
+ background-position: center;
842
+ background-size: var(--width);
843
+ }
844
+
845
+ .face.right,
846
+ .face.left {
847
+ background-image: linear-gradient(
848
+ 0deg,
849
+ hsl(151deg 36% 62%) 0%,
850
+ hsl(175deg 32% 48%) 14%,
851
+ hsl(199deg 44% 35%) 29%,
852
+ hsl(223deg 59% 24%) 57%,
853
+ hsl(246deg 77% 15%) 86%,
854
+ hsl(270deg 100% 7%) 100%
855
+ );
856
+ }
857
+
858
+ img.title {
859
+ width: 100%;
860
+ filter: drop-shadow(0 0.25rem 0.1rem hsl(220 100% 10% / 0.75));
861
+ }
862
+ img.hf-logo {
863
+ width: 90%;
864
+ }
865
+
866
+ .triangle.top.right {
867
+ width: calc(var(--depth) * 10);
868
+ aspect-ratio: 1 / 1.35;
869
+ transform: rotateY(90deg) translate3d(0.1px, -59.1px, -39.5px) scale(0.1);
870
+ clip-path: polygon(0% 100%, 50% 0%, 100% 100%);
871
+ }
872
+ .triangle.top.left {
873
+ width: calc(var(--depth) * 10);
874
+ aspect-ratio: 1 / 1.35;
875
+ transform: rotateY(90deg) translate3d(0.1px, -59.1px, calc(var(--width) - 41.5px)) scale(0.1);
876
+ clip-path: polygon(0% 100%, 50% 0%, 100% 100%);
877
+ }
878
+ .triangle.bottom.left {
879
+ width: calc(var(--depth) * 10);
880
+ aspect-ratio: 1 / 1.35;
881
+ background-color: hotpink !important;
882
+ transform: rotateY(90deg) translate3d(0.1px, calc(var(--height) - 49px), calc(var(--width) - 41.5px)) scale(0.1);
883
+ clip-path: polygon(0% 0%, 50% 100%, 100% 0%);
884
+ }
885
+ .triangle.bottom.right {
886
+ width: calc(var(--depth) * 10);
887
+ aspect-ratio: 1 / 1.35;
888
+ transform: rotateY(90deg) translate3d(0px, calc(var(--height) - 49px), -39.5px) scale(0.1);
889
+ clip-path: polygon(0% 0%, 50% 100%, 100% 0%);
890
+ }
891
+
892
+ /* Animation */
893
+
894
+ /* transform: rotateX(var(--booster-rx)) rotateY(var(--booster-ry)) rotateZ(var(--booster-rz)) scale(var(--booster-scale)); */
895
+
896
+ @keyframes spin-x {
897
+ from {
898
+ /* transform: scale(0.9) rotate(0turn); */
899
+ transform: scale(var(--scale)) rotate(0turn);
900
+ }
901
+ to {
902
+ /* transform: scale(0.9) rotate(1turn); */
903
+ transform: scale(var(--scale)) rotate(1turn);
904
+ }
905
+ }
906
+
907
+ @keyframes spin-y {
908
+ 0% {
909
+ /* transform: rotateZ(0turn) rotateY(0turn); */
910
+ transform: rotateX(var(--booster-rx)) rotateY(0deg) rotateZ(0deg) scale(var(--booster-scale));
911
+ }
912
+ /* 80% {
913
+ transform: rotateX(var(--booster-rx)) rotateY(360deg) rotateZ(0deg) scale(var(--booster-scale));
914
+ } */
915
+ 100% {
916
+ transform: rotateX(var(--booster-rx)) rotateY(360deg) rotateZ(0deg) scale(var(--booster-scale));
917
+ }
918
+ }
919
+
920
+ @keyframes bounce {
921
+ 0% {
922
+ transform: rotateX(var(--booster-rx)) rotateY(var(--booster-ry)) rotateZ(var(--booster-rz))
923
+ scale(var(--booster-scale)) translateY(0%);
924
+ }
925
+ 30% {
926
+ transform: rotateX(var(--booster-rx)) rotateY(var(--booster-ry)) rotateZ(var(--booster-rz))
927
+ scale(var(--booster-scale)) translateY(-2%);
928
+ }
929
+ 50% {
930
+ transform: rotateX(var(--booster-rx)) rotateY(var(--booster-ry)) rotateZ(var(--booster-rz))
931
+ scale(var(--booster-scale)) translateY(1%);
932
+ }
933
+ 70% {
934
+ transform: rotateX(var(--booster-rx)) rotateY(var(--booster-ry)) rotateZ(var(--booster-rz))
935
+ scale(var(--booster-scale)) translateY(-1%);
936
+ }
937
+ 100% {
938
+ transform: rotateX(var(--booster-rx)) rotateY(var(--booster-ry)) rotateZ(var(--booster-rz))
939
+ scale(var(--booster-scale)) translateY(0%);
940
+ }
941
+ }
942
+
943
+ @keyframes shrink {
944
+ from {
945
+ transform: rotateZ(-45deg) scale(var(--booster-scale));
946
+ opacity: 1;
947
+ }
948
+ to {
949
+ transform: rotateZ(-270deg) scale(0);
950
+ opacity: 0;
951
+ }
952
+ }
953
+
954
+ [data-mode='booster']:is([data-state='ready'], [data-state='generating'], [data-state='completed']) .booster {
955
+ display: block;
956
+ }
957
+
958
+ [data-state='ready'] .booster {
959
+ animation: 5s bounce infinite ease-out;
960
+ }
961
+
962
+ [data-state='generating'].scene {
963
+ animation: 15s spin-x infinite linear;
964
+ height: auto;
965
+ transform-origin: center;
966
+ }
967
+ [data-state='generating'] .booster {
968
+ animation: 3s spin-y infinite linear;
969
+ transform-origin: center;
970
+ cursor: default;
971
+ }
972
+
973
+ [data-mode='booster'][data-state='completed'] .booster {
974
+ animation: 0.5s shrink ease-out forwards;
975
+ }
976
+
977
+ [data-mode='booster'][data-state='completed'] .card-slot {
978
+ transform: scale(0);
979
+ }
980
+
981
+ [data-mode='card'][data-state='completed'] .booster {
982
+ --booster-scale: 0;
983
+ }
984
+
985
+ [data-mode='card'][data-state='completed'] .card-slot {
986
+ transform: scale(1);
987
  }
static/whitey.png ADDED
templates/index.html CHANGED
@@ -14,9 +14,66 @@
14
  </script>
15
  </head>
16
  <body>
17
- <h1>This Pokémon Does Not Exist</h1>
18
- <div class="duration"><span class="elapsed">0.0</span>s (ETA: <span class="eta">40</span>s)</div>
19
- <button class="generate">Generate Pokémon Card with AI</button>
20
- <section class="render"></section>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  </body>
22
  </html>
14
  </script>
15
  </head>
16
  <body>
17
+ <main>
18
+ <section class="info">
19
+ <div class="poke-trio">
20
+ <img src="static/whitey.png" alt="AI generated creature" width="80" height="80">
21
+ <img src="static/blacky.png" alt="AI generated creature" width="80" height="80">
22
+ <img src="static/bluey.png" alt="AI generated creature" width="80" height="80">
23
+ </div>
24
+ <h1>This Pokémon<br />Does Not Exist</h1>
25
+ <label>
26
+ Enter your trainer name
27
+ <input type="text" placeholder="Ash" />
28
+ </label>
29
+ <p>
30
+ Each illustration is <strong>generated with AI</strong> using a <a href="https://rudalle.ru/en/">ruDALL-E</a>
31
+ model <a href="https://huggingface.co/minimaxir/ai-generated-pokemon-rudalle"
32
+ >fine-tuned by Max Woolf.</a> More than
33
+ <a href="https://huggingface.co/models">30,000 such models</a> are hosted on Hugging Face for immediate use.</a
34
+ >
35
+ </p>
36
+ </section>
37
+ <section class="output">
38
+ <div class="actions">
39
+ <button class="share">Share</button>
40
+ <button class="save">Save</button>
41
+ <button class="trainer-name" data-include>Trainer Name</button>
42
+ <button class="generate-new">New Pokémon</button>
43
+ </div>
44
+ <div class="duration"><span class="elapsed">0.0</span>s (ETA: <span class="eta">40</span>s)</div>
45
+ <div class="scene" data-mode="booster" data-state="ready">
46
+ <div class="booster">
47
+ <div class="foil triangle top left"></div>
48
+ <div class="foil triangle top right"></div>
49
+ <div class="foil top flat"></div>
50
+ <div class="foil top front"></div>
51
+ <div class="foil top back"></div>
52
+ <div class="face front">
53
+ <img
54
+ class="title"
55
+ src="static/huggingface-pokemon-logo-1200.png"
56
+ alt="The words 'Hugging Face' in the style of the Pokémon logo"
57
+ draggable="false"
58
+ />
59
+ <img class="hf-logo" src="static/huggingface-logo.svg" alt="Hugging Face emoji logo" draggable="false" />
60
+ </div>
61
+ <div class="face back"></div>
62
+ <div class="foil back flat"></div>
63
+ <div class="foil back flap"></div>
64
+ <div class="face top foil"></div>
65
+ <div class="face bottom foil"></div>
66
+ <div class="face left"></div>
67
+ <div class="face right"></div>
68
+ <div class="foil bottom front"></div>
69
+ <div class="foil bottom back"></div>
70
+ <div class="foil triangle bottom left"></div>
71
+ <div class="foil triangle bottom right"></div>
72
+ <div class="foil bottom flat"></div>
73
+ </div>
74
+ <div class="card-slot"></div>
75
+ </div>
76
+ </section>
77
+ </main>
78
  </body>
79
  </html>