@jjlmoya/utils-alcohol 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/package.json +60 -0
  2. package/src/category/i18n/en.ts +19 -0
  3. package/src/category/i18n/es.ts +28 -0
  4. package/src/category/i18n/fr.ts +19 -0
  5. package/src/category/index.ts +12 -0
  6. package/src/category/seo.astro +15 -0
  7. package/src/components/PreviewNavSidebar.astro +116 -0
  8. package/src/components/PreviewToolbar.astro +143 -0
  9. package/src/data.ts +11 -0
  10. package/src/env.d.ts +5 -0
  11. package/src/index.ts +19 -0
  12. package/src/layouts/PreviewLayout.astro +117 -0
  13. package/src/pages/[locale]/[slug].astro +155 -0
  14. package/src/pages/[locale].astro +271 -0
  15. package/src/pages/index.astro +4 -0
  16. package/src/tests/content_mandatory.test.ts +32 -0
  17. package/src/tests/faq_count.test.ts +17 -0
  18. package/src/tests/mocks/astro_mock.js +2 -0
  19. package/src/tests/seo_length.test.ts +39 -0
  20. package/src/tests/tool_validation.test.ts +17 -0
  21. package/src/tool/alcoholClearance/component.astro +219 -0
  22. package/src/tool/alcoholClearance/component.css +369 -0
  23. package/src/tool/alcoholClearance/i18n/en.ts +172 -0
  24. package/src/tool/alcoholClearance/i18n/es.ts +181 -0
  25. package/src/tool/alcoholClearance/i18n/fr.ts +163 -0
  26. package/src/tool/alcoholClearance/index.ts +50 -0
  27. package/src/tool/alcoholClearance/logic.ts +59 -0
  28. package/src/tool/beerCooler/component.astro +236 -0
  29. package/src/tool/beerCooler/component.css +381 -0
  30. package/src/tool/beerCooler/i18n/en.ts +168 -0
  31. package/src/tool/beerCooler/i18n/es.ts +181 -0
  32. package/src/tool/beerCooler/i18n/fr.ts +168 -0
  33. package/src/tool/beerCooler/index.ts +49 -0
  34. package/src/tool/beerCooler/logic.ts +34 -0
  35. package/src/tool/carbonationCalculator/component.astro +225 -0
  36. package/src/tool/carbonationCalculator/component.css +483 -0
  37. package/src/tool/carbonationCalculator/i18n/en.ts +175 -0
  38. package/src/tool/carbonationCalculator/i18n/es.ts +179 -0
  39. package/src/tool/carbonationCalculator/i18n/fr.ts +175 -0
  40. package/src/tool/carbonationCalculator/index.ts +48 -0
  41. package/src/tool/carbonationCalculator/logic.ts +40 -0
  42. package/src/tool/cocktailBalancer/bibliography.astro +14 -0
  43. package/src/tool/cocktailBalancer/component.astro +396 -0
  44. package/src/tool/cocktailBalancer/component.css +1218 -0
  45. package/src/tool/cocktailBalancer/data/IngredientRepository.ts +83 -0
  46. package/src/tool/cocktailBalancer/data/Presets.ts +122 -0
  47. package/src/tool/cocktailBalancer/domain/Ingredient.ts +29 -0
  48. package/src/tool/cocktailBalancer/i18n/en.ts +193 -0
  49. package/src/tool/cocktailBalancer/i18n/es.ts +193 -0
  50. package/src/tool/cocktailBalancer/i18n/fr.ts +193 -0
  51. package/src/tool/cocktailBalancer/index.ts +68 -0
  52. package/src/tool/cocktailBalancer/logic.ts +118 -0
  53. package/src/tool/cocktailBalancer/seo.astro +53 -0
  54. package/src/tool/partyKeg/component.astro +269 -0
  55. package/src/tool/partyKeg/component.css +660 -0
  56. package/src/tool/partyKeg/i18n/en.ts +162 -0
  57. package/src/tool/partyKeg/i18n/es.ts +166 -0
  58. package/src/tool/partyKeg/i18n/fr.ts +162 -0
  59. package/src/tool/partyKeg/index.ts +46 -0
  60. package/src/tool/partyKeg/logic.ts +36 -0
  61. package/src/tools.ts +14 -0
  62. package/src/types.ts +72 -0
@@ -0,0 +1,660 @@
1
+ .party-app {
2
+ width: 100%;
3
+ max-width: 72rem;
4
+ margin: 0 auto;
5
+ padding: 0.25rem;
6
+ user-select: none;
7
+ color: #1e293b;
8
+ }
9
+
10
+ .party-card {
11
+ position: relative;
12
+ border-radius: 1.5rem;
13
+ overflow: hidden;
14
+ background: rgba(255,255,255,0.9);
15
+ backdrop-filter: blur(12px);
16
+ border: 1px solid rgba(255,255,255,0.4);
17
+ box-shadow: 0 10px 30px rgba(0,0,0,0.1);
18
+ }
19
+
20
+ .theme-dark .party-card {
21
+ background: rgba(15,23,42,0.9);
22
+ border-color: rgba(255,255,255,0.1);
23
+ }
24
+
25
+ .party-deco {
26
+ position: absolute;
27
+ width: 24rem;
28
+ height: 24rem;
29
+ border-radius: 50%;
30
+ pointer-events: none;
31
+ filter: blur(3rem);
32
+ }
33
+
34
+ .party-deco-top {
35
+ top: 0;
36
+ right: 0;
37
+ transform: translate(50%, -50%);
38
+ background: rgba(251,191,36,0.3);
39
+ }
40
+
41
+ .party-deco-bottom {
42
+ bottom: 0;
43
+ left: 0;
44
+ transform: translate(-50%, 50%);
45
+ background: rgba(34,211,238,0.3);
46
+ }
47
+
48
+ .party-grid {
49
+ display: grid;
50
+ position: relative;
51
+ z-index: 1;
52
+ }
53
+
54
+ @media (min-width: 1280px) {
55
+ .party-grid {
56
+ grid-template-columns: 5fr 7fr;
57
+ }
58
+ }
59
+
60
+ .party-inputs {
61
+ padding: 2rem 2.5rem;
62
+ display: flex;
63
+ flex-direction: column;
64
+ gap: 2.5rem;
65
+ background: rgba(255,255,255,0.4);
66
+ }
67
+
68
+ @media (min-width: 1280px) {
69
+ .party-inputs {
70
+ border-right: 1px solid #e2e8f0;
71
+ }
72
+ }
73
+
74
+ .theme-dark .party-inputs {
75
+ background: rgba(255,255,255,0.03);
76
+ border-color: #1e293b;
77
+ }
78
+
79
+ .calc-header {
80
+ display: flex;
81
+ align-items: center;
82
+ gap: 0.75rem;
83
+ }
84
+
85
+ .calc-header-icon {
86
+ width: 2.5rem;
87
+ height: 2.5rem;
88
+ border-radius: 50%;
89
+ flex-shrink: 0;
90
+ background: linear-gradient(to bottom right, #fbbf24, #f97316);
91
+ display: flex;
92
+ align-items: center;
93
+ justify-content: center;
94
+ box-shadow: 0 4px 12px rgba(251,191,36,0.3);
95
+ color: #fff;
96
+ }
97
+
98
+ .calc-header-icon-svg {
99
+ width: 1.5rem;
100
+ height: 1.5rem;
101
+ }
102
+
103
+ .calc-title {
104
+ font-weight: 700;
105
+ font-size: 1.25rem;
106
+ margin: 0;
107
+ line-height: 1;
108
+ color: #1e293b;
109
+ }
110
+
111
+ .theme-dark .calc-title {
112
+ color: #f1f5f9;
113
+ }
114
+
115
+ .calc-subtitle {
116
+ color: #64748b;
117
+ font-size: 0.75rem;
118
+ text-transform: uppercase;
119
+ letter-spacing: 0.05em;
120
+ margin: 0.25rem 0 0;
121
+ }
122
+
123
+ .slider-section {
124
+ display: flex;
125
+ flex-direction: column;
126
+ gap: 1rem;
127
+ }
128
+
129
+ .slider-header {
130
+ display: flex;
131
+ justify-content: space-between;
132
+ align-items: flex-end;
133
+ }
134
+
135
+ .slider-lbl {
136
+ color: #475569;
137
+ font-size: 0.875rem;
138
+ font-weight: 700;
139
+ text-transform: uppercase;
140
+ letter-spacing: 0.05em;
141
+ }
142
+
143
+ .slider-val {
144
+ font-size: 1.875rem;
145
+ font-weight: 300;
146
+ color: #0f172a;
147
+ letter-spacing: -0.05em;
148
+ }
149
+
150
+ .theme-dark .slider-val {
151
+ color: #f1f5f9;
152
+ }
153
+
154
+ .slider-val-unit {
155
+ display: flex;
156
+ align-items: baseline;
157
+ gap: 0.25rem;
158
+ }
159
+
160
+ .slider-unit {
161
+ font-size: 0.875rem;
162
+ color: #64748b;
163
+ font-weight: 700;
164
+ text-transform: uppercase;
165
+ }
166
+
167
+ .custom-slider-wrap {
168
+ position: relative;
169
+ height: 3rem;
170
+ background: #f1f5f9;
171
+ border-radius: 0.75rem;
172
+ border: 1px solid #e2e8f0;
173
+ box-shadow: inset 0 2px 4px rgba(0,0,0,0.05);
174
+ display: flex;
175
+ align-items: center;
176
+ padding: 0 0.5rem;
177
+ cursor: pointer;
178
+ }
179
+
180
+ .theme-dark .custom-slider-wrap {
181
+ background: #1e293b;
182
+ border-color: #334155;
183
+ }
184
+
185
+ .custom-range {
186
+ position: absolute;
187
+ inset: 0;
188
+ width: 100%;
189
+ height: 100%;
190
+ opacity: 0;
191
+ z-index: 3;
192
+ cursor: pointer;
193
+ margin: 0;
194
+ }
195
+
196
+ .slider-track-fill {
197
+ position: absolute;
198
+ left: 0.5rem;
199
+ top: 0.5rem;
200
+ bottom: 0.5rem;
201
+ border-radius: 0.5rem;
202
+ z-index: 1;
203
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
204
+ transition: width 0.1s;
205
+ }
206
+
207
+ .slider-fill-amber {
208
+ background: linear-gradient(to right, #fbbf24, #f97316);
209
+ }
210
+
211
+ .slider-fill-blue {
212
+ background: linear-gradient(to right, #60a5fa, #6366f1);
213
+ }
214
+
215
+ .slider-fill-temp {
216
+ background: linear-gradient(to right, #22d3ee, #2dd4bf, #fb7185);
217
+ }
218
+
219
+ .slider-thumb {
220
+ position: absolute;
221
+ height: 2rem;
222
+ width: 4px;
223
+ background: #fff;
224
+ border-radius: 9999px;
225
+ box-shadow: 0 2px 8px rgba(0,0,0,0.15);
226
+ border: 1px solid rgba(0,0,0,0.05);
227
+ z-index: 2;
228
+ pointer-events: none;
229
+ transform: translateX(-2px);
230
+ transition: left 0.1s;
231
+ }
232
+
233
+ .vibe-section {
234
+ display: flex;
235
+ flex-direction: column;
236
+ gap: 1rem;
237
+ }
238
+
239
+ .vibe-buttons {
240
+ display: grid;
241
+ grid-template-columns: repeat(3, 1fr);
242
+ gap: 0.5rem;
243
+ }
244
+
245
+ .vibe-btn {
246
+ position: relative;
247
+ padding: 0.75rem;
248
+ border-radius: 0.75rem;
249
+ border: 1px solid #e2e8f0;
250
+ background: #fff;
251
+ cursor: pointer;
252
+ overflow: hidden;
253
+ box-shadow: 0 1px 3px rgba(0,0,0,0.05);
254
+ transition: all 0.2s;
255
+ }
256
+
257
+ .theme-dark .vibe-btn {
258
+ border-color: #334155;
259
+ background: #0f172a;
260
+ }
261
+
262
+ .vibe-btn:hover {
263
+ background: #f8fafc;
264
+ }
265
+
266
+ .vibe-bg {
267
+ position: absolute;
268
+ inset: 0;
269
+ opacity: 0;
270
+ transition: opacity 0.2s;
271
+ }
272
+
273
+ .vibe-bg-green {
274
+ background: rgba(16,185,129,0.1);
275
+ }
276
+
277
+ .vibe-bg-amber {
278
+ background: rgba(245,158,11,0.1);
279
+ }
280
+
281
+ .vibe-bg-rose {
282
+ background: rgba(244,63,94,0.1);
283
+ }
284
+
285
+ .vibe-content {
286
+ position: relative;
287
+ z-index: 1;
288
+ display: flex;
289
+ flex-direction: column;
290
+ align-items: center;
291
+ gap: 0.5rem;
292
+ }
293
+
294
+ .vibe-icon {
295
+ width: 1.5rem;
296
+ height: 1.5rem;
297
+ color: #94a3b8;
298
+ transition: color 0.2s;
299
+ }
300
+
301
+ .vibe-label {
302
+ font-size: 0.75rem;
303
+ font-weight: 700;
304
+ color: #64748b;
305
+ transition: color 0.2s;
306
+ }
307
+
308
+ .vibe-bar {
309
+ position: absolute;
310
+ bottom: 0;
311
+ left: 0;
312
+ width: 100%;
313
+ height: 4px;
314
+ transform: scaleX(0);
315
+ transition: transform 0.2s;
316
+ }
317
+
318
+ .vibe-bar-green {
319
+ background: #10b981;
320
+ }
321
+
322
+ .vibe-bar-amber {
323
+ background: #f59e0b;
324
+ }
325
+
326
+ .vibe-bar-rose {
327
+ background: #f43f5e;
328
+ }
329
+
330
+ .vibe-btn.active .vibe-bg {
331
+ opacity: 1;
332
+ }
333
+
334
+ .vibe-btn.active .active-bar {
335
+ transform: scaleX(1);
336
+ }
337
+
338
+ .vibe-btn[data-mult="1"].active .icon-col {
339
+ color: #10b981;
340
+ }
341
+
342
+ .vibe-btn[data-mult="1.5"].active .icon-col {
343
+ color: #f59e0b;
344
+ }
345
+
346
+ .vibe-btn[data-mult="2.5"].active .icon-col {
347
+ color: #f43f5e;
348
+ }
349
+
350
+ .temp-section {
351
+ display: flex;
352
+ flex-direction: column;
353
+ gap: 1rem;
354
+ padding-top: 1rem;
355
+ border-top: 1px solid #e2e8f0;
356
+ }
357
+
358
+ .theme-dark .temp-section {
359
+ border-color: #334155;
360
+ }
361
+
362
+ .temp-lbl {
363
+ display: flex;
364
+ align-items: center;
365
+ gap: 0.5rem;
366
+ }
367
+
368
+ .temp-icon {
369
+ color: #94a3b8;
370
+ width: 1.25rem;
371
+ height: 1.25rem;
372
+ }
373
+
374
+ .party-results {
375
+ background: #f8fafc;
376
+ display: flex;
377
+ flex-direction: column;
378
+ position: relative;
379
+ }
380
+
381
+ .theme-dark .party-results {
382
+ background: rgba(0,0,0,0.2);
383
+ }
384
+
385
+ .stats-header {
386
+ display: grid;
387
+ grid-template-columns: 1fr 1fr;
388
+ border-bottom: 1px solid #e2e8f0;
389
+ background: rgba(255,255,255,0.4);
390
+ backdrop-filter: blur(4px);
391
+ }
392
+
393
+ .theme-dark .stats-header {
394
+ border-color: #1e293b;
395
+ background: rgba(255,255,255,0.03);
396
+ }
397
+
398
+ .stat-block {
399
+ padding: 2rem;
400
+ position: relative;
401
+ overflow: hidden;
402
+ }
403
+
404
+ .stat-block-left {
405
+ border-right: 1px solid #e2e8f0;
406
+ }
407
+
408
+ .theme-dark .stat-block-left {
409
+ border-color: #1e293b;
410
+ }
411
+
412
+ .stat-deco-icon {
413
+ position: absolute;
414
+ top: 0;
415
+ right: 0;
416
+ padding: 1rem;
417
+ opacity: 0.05;
418
+ }
419
+
420
+ .stat-block:hover .stat-deco-icon {
421
+ opacity: 0.1;
422
+ transition: opacity 0.2s;
423
+ }
424
+
425
+ .stat-deco-svg {
426
+ width: 6rem;
427
+ height: 6rem;
428
+ color: #0f172a;
429
+ transform: rotate(12deg);
430
+ }
431
+
432
+ .stat-block-right .stat-deco-svg {
433
+ transform: rotate(-12deg);
434
+ }
435
+
436
+ .stat-label {
437
+ font-size: 0.75rem;
438
+ font-weight: 700;
439
+ text-transform: uppercase;
440
+ letter-spacing: 0.1em;
441
+ color: #94a3b8;
442
+ display: block;
443
+ margin-bottom: 0.5rem;
444
+ }
445
+
446
+ .stat-value-row {
447
+ display: flex;
448
+ align-items: baseline;
449
+ gap: 0.5rem;
450
+ }
451
+
452
+ .stat-number {
453
+ font-size: 3rem;
454
+ font-weight: 300;
455
+ color: #0f172a;
456
+ letter-spacing: -0.05em;
457
+ }
458
+
459
+ .theme-dark .stat-number {
460
+ color: #f1f5f9;
461
+ }
462
+
463
+ .stat-unit {
464
+ font-size: 1.125rem;
465
+ color: #64748b;
466
+ font-weight: 700;
467
+ }
468
+
469
+ .stat-sub {
470
+ margin: 1rem 0 0;
471
+ font-size: 0.875rem;
472
+ font-weight: 500;
473
+ }
474
+
475
+ .stat-sub-amber {
476
+ color: #d97706;
477
+ }
478
+
479
+ .stat-sub-cyan {
480
+ color: #0891b2;
481
+ }
482
+
483
+ .visual-stage-wrap {
484
+ flex: 1;
485
+ min-height: 400px;
486
+ padding: 2rem;
487
+ position: relative;
488
+ overflow: hidden;
489
+ display: flex;
490
+ flex-direction: column;
491
+ justify-content: flex-end;
492
+ background: linear-gradient(to top, rgba(203,213,225,0.5) 0%, rgba(248,250,252,0) 100%);
493
+ }
494
+
495
+ .theme-dark .visual-stage-wrap {
496
+ background: linear-gradient(to top, rgba(15,23,42,0.5) 0%, transparent 100%);
497
+ }
498
+
499
+ .visual-stage-header {
500
+ position: absolute;
501
+ top: 1.5rem;
502
+ left: 2rem;
503
+ right: 2rem;
504
+ display: flex;
505
+ justify-content: space-between;
506
+ }
507
+
508
+ .visual-title {
509
+ font-size: 0.75rem;
510
+ color: #94a3b8;
511
+ font-weight: 700;
512
+ text-transform: uppercase;
513
+ letter-spacing: 0.1em;
514
+ }
515
+
516
+ .ice-hint {
517
+ font-size: 0.75rem;
518
+ color: #64748b;
519
+ }
520
+
521
+ .visual-stage {
522
+ display: flex;
523
+ justify-content: center;
524
+ align-items: flex-end;
525
+ gap: 3rem;
526
+ width: 100%;
527
+ }
528
+
529
+ .stage-baseline {
530
+ position: absolute;
531
+ bottom: 0;
532
+ left: 0;
533
+ right: 0;
534
+ height: 1px;
535
+ background: #cbd5e1;
536
+ }
537
+
538
+ .theme-dark .stage-baseline {
539
+ background: #334155;
540
+ }
541
+
542
+ @keyframes drop-in {
543
+ 0% {
544
+ transform: translateY(-50px);
545
+ opacity: 0;
546
+ }
547
+
548
+ 100% {
549
+ transform: translateY(0);
550
+ opacity: 1;
551
+ }
552
+ }
553
+
554
+ .animate-drop {
555
+ animation: drop-in 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
556
+ }
557
+
558
+ .visual-container {
559
+ display: flex;
560
+ align-items: flex-end;
561
+ justify-content: center;
562
+ width: 100%;
563
+ height: 100%;
564
+ gap: 2rem;
565
+ }
566
+
567
+ @media (min-width: 1024px) {
568
+ .visual-container {
569
+ gap: 4rem;
570
+ }
571
+ }
572
+
573
+ .keg-stack {
574
+ display: flex;
575
+ flex-direction: column-reverse;
576
+ align-items: center;
577
+ justify-content: flex-start;
578
+ height: 100%;
579
+ margin-bottom: -2rem;
580
+ min-width: 80px;
581
+ }
582
+
583
+ .keg-item {
584
+ position: relative;
585
+ transition: transform 0.3s;
586
+ transform-origin: bottom;
587
+ cursor: default;
588
+ }
589
+
590
+ .keg-item:hover {
591
+ transform: scale(1.05);
592
+ }
593
+
594
+ .keg-plus {
595
+ text-align: center;
596
+ font-weight: 900;
597
+ font-size: 1.25rem;
598
+ color: #b45309;
599
+ margin-bottom: 1rem;
600
+ background: rgba(251,191,36,0.8);
601
+ backdrop-filter: blur(4px);
602
+ border-radius: 9999px;
603
+ width: 3.5rem;
604
+ height: 3.5rem;
605
+ display: flex;
606
+ align-items: center;
607
+ justify-content: center;
608
+ border: 2px solid #fde68a;
609
+ box-shadow: 0 4px 20px rgba(0,0,0,0.1);
610
+ z-index: 50;
611
+ animation: bounce 1s infinite;
612
+ }
613
+
614
+ @keyframes bounce {
615
+ 0%, 100% {
616
+ transform: translateY(0);
617
+ }
618
+
619
+ 50% {
620
+ transform: translateY(-4px);
621
+ }
622
+ }
623
+
624
+ .ice-pile {
625
+ display: flex;
626
+ flex-wrap: wrap;
627
+ align-content: flex-end;
628
+ justify-content: center;
629
+ width: 15rem;
630
+ margin-left: -1.25rem;
631
+ padding: 1rem;
632
+ position: relative;
633
+ }
634
+
635
+ .ice-bag {
636
+ transition: transform 0.3s;
637
+ cursor: pointer;
638
+ }
639
+
640
+ .ice-bag:hover {
641
+ transform: scale(1.1);
642
+ z-index: 50;
643
+ }
644
+
645
+ .bags-plus {
646
+ position: absolute;
647
+ top: -3rem;
648
+ left: 50%;
649
+ transform: translateX(-50%);
650
+ z-index: 100;
651
+ font-weight: 900;
652
+ font-size: 1.25rem;
653
+ color: #0e7490;
654
+ background: rgba(236,254,255,0.9);
655
+ padding: 0.5rem 1rem;
656
+ border-radius: 9999px;
657
+ border: 2px solid #a5f3fc;
658
+ box-shadow: 0 4px 20px rgba(6,182,212,0.3);
659
+ animation: bounce 1s infinite;
660
+ }