-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.html
More file actions
538 lines (489 loc) · 26.7 KB
/
Copy pathindex.html
File metadata and controls
538 lines (489 loc) · 26.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Primary Meta Tags -->
<title>Beercap Mosaic Generator — Transform Images into Beercap Art</title>
<meta name="title" content="Beercap Mosaic Generator — Transform Images into Beercap Art">
<meta name="description"
content="Free online tool to convert any image into a beercap mosaic. Upload your beercap collection, choose a target image, and get step-by-step assembly instructions. Works offline, no signup required.">
<meta name="keywords"
content="beercap mosaic, bottle cap art, beer cap craft, image to mosaic, mosaic generator, DIY art, beercap art, craft project, pixel art, color matching">
<meta name="author" content="Beercap Mosaic Generator">
<meta name="robots" content="index, follow">
<meta name="language" content="English">
<!-- Theme Color -->
<meta name="theme-color" content="#1a1a1a">
<meta name="msapplication-TileColor" content="#ff8a00">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://beercap-mosaic.com/">
<meta property="og:title" content="Beercap Mosaic Generator — Transform Images into Beercap Art">
<meta property="og:description"
content="Free online tool to convert any image into a beercap mosaic. Upload your beercap collection, choose a target image, and get step-by-step assembly instructions.">
<meta property="og:image" content="https://beercap-mosaic.com/og-image.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:site_name" content="Beercap Mosaic Generator">
<meta property="og:locale" content="en_US">
<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:url" content="https://beercap-mosaic.com/">
<meta name="twitter:title" content="Beercap Mosaic Generator — Transform Images into Beercap Art">
<meta name="twitter:description"
content="Free online tool to convert any image into a beercap mosaic. Upload your beercap collection and get step-by-step assembly instructions.">
<meta name="twitter:image" content="https://beercap-mosaic.com/og-image.png">
<!-- Canonical URL -->
<link rel="canonical" href="https://beercap-mosaic.com/">
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Space+Grotesk:wght@400;500;600;700&display=swap"
rel="stylesheet">
<!-- Styles -->
<link rel="stylesheet" href="css/styles.css">
<!-- Favicon -->
<link rel="icon"
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🍺</text></svg>">
<link rel="icon" href="beer-cap-32.png" type="image/png" sizes="32x32">
<link rel="icon" href="beer-cap-64.png" type="image/png" sizes="64x64">
<link rel="icon" href="beer-cap-128.png" type="image/png" sizes="128x128">
<link rel="icon" href="beer-cap-256.png" type="image/png" sizes="256x256">
<link rel="icon" href="beer-cap-512.png" type="image/png" sizes="512x512">
<!-- Structured Data / JSON-LD -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebApplication",
"name": "Beercap Mosaic Generator",
"description": "Free online tool to convert any image into a beercap mosaic with step-by-step assembly instructions.",
"url": "https://beercap-mosaic.com/",
"applicationCategory": "DesignApplication",
"operatingSystem": "Any",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD"
},
"featureList": [
"Image to mosaic conversion",
"Beercap library management",
"Color matching algorithm",
"Hexagonal and square layouts",
"Export to PNG and CSV",
"Works offline"
],
"screenshot": "https://beercap-mosaic.com/screenshot.png",
"softwareVersion": "1.0.0",
"author": {
"@type": "Organization",
"name": "Beercap Mosaic Generator"
}
}
</script>
<!-- Adsense -->
<meta name="google-adsense-account" content="ca-pub-5650792980026546">
</head>
<body>
<div class="app-container">
<!-- Header -->
<header class="app-header">
<h1 class="app-title">Beercap Mosaic</h1>
<p class="app-subtitle">Transform images into beercap art instructions</p>
<button id="go-to-app-btn" class="btn btn-primary go-to-app-btn">
<span class="btn-icon">🚀</span>
Start Creating
</button>
</header>
<!-- Landing Hero Section -->
<section id="hero" class="hero-section">
<div class="hero-content">
<h2 class="hero-title">Create Stunning Mosaic Art from Your Beercap Collection</h2>
<p class="hero-desc">Turn your physical collection into a digital masterpiece and get step-by-step
instructions to build it in real life.</p>
<div class="hero-badges">
<span class="hero-badge">✅ Works Offline</span>
<span class="hero-badge">⚡ WASM Powered</span>
<span class="hero-badge">📦 Global Optimization</span>
</div>
<div class="hero-image-container">
<img src="screenshot.png" alt="Beercap Mosaic Generator Interface" class="hero-screenshot">
</div>
</div>
</section>
<!-- Documentation / How It Works -->
<section id="documentation" class="documentation-section">
<div class="doc-container">
<h2 class="section-title">How It Works</h2>
<div class="process-flow-container">
<div class="process-flow">
<div class="process-step">
<div class="process-icon">🍺</div>
<div class="process-label">Your Beercaps</div>
</div>
<div class="process-arrow">→</div>
<div class="process-step">
<div class="process-icon">🖼️</div>
<div class="process-label">Target Image</div>
</div>
<div class="process-arrow">→</div>
<div class="process-step">
<div class="process-icon">🎨</div>
<div class="process-label">Mosaic Grid</div>
</div>
</div>
</div>
<div class="doc-grid">
<div class="doc-card">
<h3 class="doc-card-title"><span class="step-number">1</span> Build Your Beercap Library</h3>
<p>Upload photos of each unique beercap. The app automatically extracts the dominant color using
center-weighted sampling. Set the quantity you have available for each type.</p>
<div class="doc-sub-feature">
<strong>📷 Smart Scanner:</strong> Photograph many caps at once; the scanner auto-detects, clusters, and
counts duplicates for you.
</div>
</div>
<div class="doc-card">
<h3 class="doc-card-title"><span class="step-number">2</span> Upload Target Image</h3>
<p>Choose the image you want to recreate. The app calculates the optimal grid size based on your total
available caps and the image's aspect ratio.</p>
<p class="doc-tip">💡 Tip: High-contrast images with ~500 caps yield the best results!</p>
</div>
<div class="doc-card">
<h3 class="doc-card-title"><span class="step-number">3</span> Generate Optimized Mosaic</h3>
<p>Our <strong>Hungarian Algorithm</strong> (compiled to WebAssembly) finds the globally optimal
assignment of caps to grid positions.</p>
<p class="doc-note">Unlike "greedy" algorithms, global optimization ensures the best overall color match
across the entire mosaic.</p>
</div>
<div class="doc-card">
<h3 class="doc-card-title"><span class="step-number">4</span> Build Your Art</h3>
<p>Follow the reference grid with letter codes (A, B, C...) to assemble your mosaic. Export as PNG or CSV
for a printable reference.</p>
</div>
</div>
<div class="tips-section">
<h3 class="tips-title">Best Practices for Great Mosaics</h3>
<div class="tips-grid">
<div class="tip-card">
<span class="tip-icon">📸</span>
<strong>Photo Quality</strong>
<p>Good lighting and neutral backgrounds make color extraction more accurate.</p>
</div>
<div class="tip-card">
<span class="tip-icon">📐</span>
<strong>Grid Layout</strong>
<p>Choose <strong>Hexagonal</strong> for a natural, tightly-packed honeycomb look.</p>
</div>
<div class="tip-card">
<span class="tip-icon">🎨</span>
<strong>Color Variety</strong>
<p>A diverse palette of caps allows for more detailed transitions and shading.</p>
</div>
</div>
</div>
</div>
</section>
<!-- Application Section -->
<div id="app-section" class="app-section">
<h2 class="section-title">Mosaic Generator</h2>
<main class="main-grid">
<!-- Beercap Library Panel -->
<section class="panel">
<div class="panel-header">
<h2 class="panel-title">
Beercap Library
<button class="help-icon" data-popover="library-help" aria-label="Help">?</button>
</h2>
<div class="popover" id="library-help">
<div class="popover-content">
<h4>📦 Building Your Library</h4>
<p><strong>Add manually:</strong> Upload individual beercap photos. Colors are auto-extracted from the
center.</p>
<p><strong>Scan multiple:</strong> Photograph many caps at once on a contrasting surface. The scanner
auto-detects and groups duplicates.</p>
<p class="popover-tip">💡 More color variety = better mosaics!</p>
</div>
</div>
<div class="library-actions">
<span class="stats-badge">
Total: <strong id="total-caps">0</strong> caps
</span>
<button id="add-beercap-btn" class="btn btn-primary btn-sm">+ Add</button>
<button id="scan-beercaps-btn" class="btn btn-secondary btn-sm">📷 Scan</button>
<button id="clear-library-btn" class="btn btn-danger btn-sm">Clear</button>
</div>
</div>
<div class="panel-content">
<div id="beercap-list" class="beercap-list">
<div class="empty-library">
<p>No beercaps added yet.</p>
<p>Click "Add Beercap" to start building your library.</p>
</div>
</div>
</div>
</section>
<!-- Target Image Panel -->
<section class="panel">
<div class="panel-header">
<h2 class="panel-title">
Target Image
<button class="help-icon" data-popover="target-help" aria-label="Help">?</button>
</h2>
<div class="popover" id="target-help">
<div class="popover-content">
<h4>🖼️ Choose Your Image</h4>
<p>Upload the image you want to recreate as a beercap mosaic.</p>
<p>The app calculates the optimal grid size based on your available caps and the image's aspect ratio.
</p>
<p class="popover-tip">💡 ~500 caps creates recognizable images. High contrast images work best!</p>
</div>
</div>
</div>
<div class="panel-content">
<div id="target-upload-area" class="upload-area">
<input type="file" id="target-image-input" accept="image/*">
<div id="target-image-placeholder" class="upload-placeholder">
<div class="upload-icon">🖼️</div>
<p class="upload-text">Click or drag image here</p>
<p class="upload-hint">Supports JPG, PNG, GIF, WebP</p>
</div>
<img id="target-image-preview" class="target-preview hidden" alt="Target image preview">
</div>
<div id="grid-info" class="grid-info">
Upload an image and add beercaps to see grid dimensions
</div>
<div class="layout-toggle">
<span class="layout-label">Layout:</span>
<div class="toggle-group">
<input type="radio" id="layout-square" name="layout" value="square">
<label for="layout-square" class="toggle-option">Square</label>
<input type="radio" id="layout-hex" name="layout" value="hex" checked>
<label for="layout-hex" class="toggle-option">Hexagonal</label>
</div>
<button class="help-icon" data-popover="layout-help" aria-label="Help">?</button>
<div class="popover" id="layout-help">
<div class="popover-content">
<h4>📐 Grid Layouts</h4>
<p><strong>Square:</strong> Traditional grid pattern, easier to build.</p>
<p><strong>Hexagonal:</strong> Offset rows create a more natural, tightly-packed honeycomb look.</p>
</div>
</div>
</div>
<div class="generate-section">
<div class="generate-row">
<button id="generate-btn" class="btn btn-primary btn-generate" disabled>
Generate Mosaic
</button>
<button class="help-icon help-icon-lg" data-popover="algo-help" aria-label="Algorithm help">?</button>
<div class="popover popover-above-wide" id="algo-help">
<div class="popover-content">
<h4>🧠 The Algorithm</h4>
<p>Uses the <strong>Hungarian Algorithm</strong> for global optimization — not just picking the
best cap for each spot, but finding the best overall arrangement.</p>
<p>This means a cell might get a slightly worse match so that another cell can get a much better
one, improving total quality.</p>
<h4 class="popover-section-title">⚡ Performance Status</h4>
<p>The green bar below shows your engine status:</p>
<ul class="popover-list">
<li><strong>🚀 WASM X threads</strong> — Fastest! Multi-threaded WebAssembly using all your CPU
cores.</li>
<li><strong>⚡ WASM (single-threaded)</strong> — Fast. WASM but without multi-threading.</li>
<li><strong>🐢 JavaScript Fallback</strong> — Slowest. WASM failed to load.</li>
</ul>
</div>
</div>
</div>
<div id="wasm-status" class="wasm-status loading">
<span class="wasm-icon">⏳</span>
<span class="wasm-text">Loading WASM...</span>
</div>
</div>
</main>
</div>
<!-- Output Section -->
<section id="output-section" class="output-section hidden">
<div class="output-header">
<div class="tabs">
<button class="tab-btn active" data-tab="visual">Visual Preview</button>
<button class="tab-btn" data-tab="reference">Reference Grid</button>
<button class="tab-btn" data-tab="stats">Statistics</button>
</div>
<div class="export-buttons">
<button id="download-png-btn" class="btn btn-secondary btn-sm" disabled>
📥 Download PNG
</button>
<button id="download-csv-btn" class="btn btn-secondary btn-sm" disabled>
📊 Export CSV
</button>
</div>
</div>
<div class="tab-content">
<!-- Visual Preview Tab -->
<div id="visual-panel" class="tab-panel active">
<div class="canvas-container">
<canvas id="visual-canvas"></canvas>
</div>
</div>
<!-- Reference Grid Tab -->
<div id="reference-panel" class="tab-panel">
<div class="reference-container">
<div id="reference-grid"></div>
</div>
<div class="legend-section">
<h4 class="legend-title">Legend</h4>
<div id="legend-container" class="legend-container"></div>
</div>
</div>
<!-- Stats Tab -->
<div id="stats-panel" class="tab-panel">
<div id="stats-content"></div>
</div>
</div>
</section>
</div>
<!-- Add Beercap Modal -->
<div id="beercap-modal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h3 id="modal-title" class="modal-title">Add Beercap</h3>
<button id="modal-close" class="modal-close">×</button>
</div>
<form id="beercap-form">
<div class="modal-body">
<div class="form-group">
<label for="beercap-name" class="form-label">Name</label>
<input type="text" id="beercap-name" class="form-input" placeholder="e.g., Heineken, Corona..." required>
</div>
<div class="form-group">
<label for="beercap-quantity" class="form-label">Quantity Available</label>
<input type="number" id="beercap-quantity" class="form-input" min="0" value="1" required>
</div>
<div class="form-group">
<span class="form-label">Beercap Image</span>
<div class="file-input-wrapper">
<input type="file" id="beercap-image" accept="image/*" required>
<label for="beercap-image" class="file-input-label">
📷 Click to upload beercap image
</label>
</div>
<div class="beercap-preview-container">
<div id="beercap-preview"></div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" id="modal-cancel" class="btn btn-secondary">Cancel</button>
<button type="submit" class="btn btn-primary">Add Beercap</button>
</div>
</form>
</div>
</div>
<!-- Progress Modal -->
<div id="progress-modal" class="modal progress-modal">
<div class="modal-content progress-modal-content">
<div class="progress-modal-icon">⚙️</div>
<h3 class="progress-modal-title">Generating Mosaic</h3>
<div class="progress-bar-container">
<div class="progress-bar">
<div id="progress-fill" class="progress-fill"></div>
</div>
</div>
<div id="progress-text" class="progress-text">Initializing...</div>
<div id="progress-percent" class="progress-percent">0%</div>
</div>
</div>
<!-- Scan Beercaps Modal -->
<div id="scan-modal" class="modal scan-modal">
<div class="modal-content scan-modal-content">
<div class="modal-header">
<h3 class="modal-title">Scan Beercaps</h3>
<button id="scan-modal-close" class="modal-close">×</button>
</div>
<div class="scan-body">
<!-- Input selection -->
<div class="scan-input-toggle">
<button id="scan-photo-btn" class="scan-toggle-btn active">
<span>📷</span> Upload Photo
</button>
<button id="scan-camera-btn" class="scan-toggle-btn">
<span>🎥</span> Use Camera
</button>
</div>
<!-- Photo upload area -->
<div id="scan-photo-area" class="scan-area">
<input type="file" id="scan-photo-input" accept="image/*" hidden>
<label for="scan-photo-input" class="scan-upload-label">
<div class="scan-upload-icon">🖼️</div>
<p>Click to upload a photo of your beercaps</p>
<p class="scan-hint">Spread caps on a contrasting background for best results</p>
</label>
</div>
<!-- Camera area -->
<div id="scan-camera-area" class="scan-area hidden">
<video id="scan-video" autoplay playsinline></video>
<button id="scan-capture-btn" class="btn btn-primary">📸 Capture</button>
</div>
<!-- Preview with detections -->
<div id="scan-preview-area" class="scan-area hidden">
<canvas id="scan-canvas"></canvas>
<div class="scan-detection-info">
<span id="scan-circle-count">0</span> caps detected
</div>
</div>
<!-- Detection progress -->
<div id="scan-progress" class="scan-progress hidden">
<div class="progress-bar">
<div id="scan-progress-fill" class="progress-fill"></div>
</div>
<div id="scan-progress-text" class="progress-text">Analyzing...</div>
</div>
<!-- Clustered results -->
<div id="scan-results" class="scan-results hidden">
<div id="scan-new-section" class="scan-section hidden">
<h4 class="scan-section-title new">🆕 New Caps (<span id="scan-new-count">0</span>)</h4>
<div id="scan-new-clusters" class="scan-clusters"></div>
</div>
<div id="scan-existing-section" class="scan-section hidden">
<h4 class="scan-section-title existing">📦 Matches Existing (<span id="scan-existing-count">0</span>)</h4>
<div id="scan-existing-clusters" class="scan-clusters"></div>
</div>
<div id="scan-empty-message" class="scan-hint hidden">No beercaps detected. Try a photo with better lighting
and contrast.</div>
</div>
</div>
<div class="modal-footer">
<button id="scan-reset-btn" class="btn btn-secondary">Reset</button>
<button id="scan-add-btn" class="btn btn-primary" disabled>Add All to Library</button>
</div>
</div>
</div>
<!-- Footer -->
<footer class="app-footer">
<div class="footer-content">
<span class="footer-text">Made with 🍺 for beercap collectors</span>
<div class="footer-links">
<a href="https://github.com/martijnenco/Image2Beercaps/issues" target="_blank" rel="noopener noreferrer"
class="feedback-btn">
<svg class="github-icon" viewBox="0 0 24 24" fill="currentColor" width="18" height="18">
<path
d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
</svg>
Feedback & Ideas
</a>
<a href="https://buymeacoffee.com/martijnenco" target="_blank" rel="noopener noreferrer" class="sponsor-btn">
<svg class="coffee-icon" viewBox="0 0 24 24" fill="currentColor" width="18" height="18">
<path
d="M20.216 6.415l-.132-.666c-.119-.598-.388-1.163-1.001-1.379-.197-.069-.42-.098-.57-.241-.152-.143-.196-.366-.231-.572-.065-.378-.125-.756-.192-1.133-.057-.325-.102-.69-.25-.987-.195-.4-.597-.634-.996-.788a5.723 5.723 0 00-.626-.194c-1-.263-2.05-.36-3.077-.416a25.834 25.834 0 00-3.7.062c-.915.083-1.88.184-2.75.5-.318.116-.646.256-.888.501-.297.302-.393.77-.177 1.146.154.267.415.456.692.58.36.162.737.284 1.123.366 1.075.238 2.189.331 3.287.37 1.218.05 2.437.01 3.65-.118.299-.033.598-.073.896-.119.352-.054.578-.513.474-.834-.124-.383-.457-.531-.834-.473-.466.074-.96.108-1.382.146-1.177.08-2.358.082-3.536.006a22.228 22.228 0 01-1.157-.107c-.086-.01-.18-.025-.258-.036-.243-.036-.484-.08-.724-.13-.111-.027-.111-.185 0-.212h.005c.277-.06.557-.108.838-.147h.002c.131-.009.263-.032.394-.048a25.076 25.076 0 013.426-.12c.674.019 1.347.067 2.017.144l.228.031c.267.04.533.088.798.145.392.085.895.113 1.07.542.055.137.08.288.111.431l.319 1.484a.237.237 0 01-.199.284h-.003c-.037.006-.075.01-.112.015a36.704 36.704 0 01-4.743.295 37.059 37.059 0 01-4.699-.304c-.14-.017-.293-.042-.417-.06-.326-.048-.649-.108-.973-.161-.393-.065-.768-.032-1.123.161-.29.16-.527.404-.675.701-.154.316-.199.66-.267 1-.069.34-.176.707-.135 1.056.087.753.613 1.365 1.37 1.502a39.69 39.69 0 0011.343.376.483.483 0 01.535.53l-.071.697-1.018 9.907c-.041.41-.047.832-.125 1.237-.122.637-.553 1.028-1.182 1.171-.577.131-1.165.2-1.756.205-.656.004-1.31-.025-1.966-.022-.699.004-1.556-.06-2.095-.58-.475-.458-.54-1.174-.605-1.793l-.731-7.013-.322-3.094c-.037-.351-.286-.695-.678-.678-.336.015-.718.3-.678.679l.228 2.185.949 9.112c.147 1.344 1.174 2.068 2.446 2.272.742.12 1.503.144 2.257.156.966.016 1.942.053 2.892-.122 1.408-.258 2.465-1.198 2.616-2.657.34-3.332.683-6.663 1.024-9.995l.215-2.087a.484.484 0 01.39-.426c.402-.078.787-.212 1.074-.518.455-.488.546-1.124.385-1.766zm-1.478.772c-.145.137-.363.201-.578.233-2.416.359-4.866.54-7.308.46-1.748-.06-3.477-.254-5.207-.498-.17-.024-.353-.055-.47-.18-.22-.236-.111-.71-.054-.995.052-.26.152-.609.463-.646.484-.057 1.046.148 1.526.22.577.088 1.156.159 1.737.212 2.48.226 5.002.19 7.472-.14.45-.06.899-.13 1.345-.21.399-.072.84-.206 1.08.206.166.281.188.657.162.974a.544.544 0 01-.169.364z" />
</svg>
Buy me a coffee
</a>
</div>
</div>
</footer>
<!-- Main application script -->
<script type="module" src="js/app.js"></script>
</body>
</html>