@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,83 @@
1
+ import type { Ingredient } from '../domain/Ingredient';
2
+
3
+ export const INGREDIENTS_DB: Ingredient[] = [
4
+ { id: 'gin_std', name: 'Ginebra (London Dry)', type: 'spirit', abv: 40, sugar: 0, acid: 0, bitterness: 2, complexity: 5, color: '#e0f2fe' },
5
+ { id: 'gin_old_tom', name: 'Ginebra Old Tom', type: 'spirit', abv: 40, sugar: 2.0, acid: 0, bitterness: 1, complexity: 6, color: '#e0f2fe' },
6
+ { id: 'gin_plymouth', name: 'Ginebra Plymouth', type: 'spirit', abv: 41.2, sugar: 0, acid: 0, bitterness: 1, complexity: 5, color: '#e0f2fe' },
7
+ { id: 'vodka_std', name: 'Vodka', type: 'spirit', abv: 40, sugar: 0, acid: 0, bitterness: 0, complexity: 0, color: '#ffffff' },
8
+ { id: 'rum_white', name: 'Ron Blanco (Ligero)', type: 'spirit', abv: 40, sugar: 0, acid: 0, bitterness: 0, complexity: 2, color: '#ffffff' },
9
+ { id: 'rum_aged', name: 'Ron Añejo (5+ años)', type: 'spirit', abv: 40, sugar: 0.5, acid: 0, bitterness: 1, complexity: 7, color: '#d97706' },
10
+ { id: 'rum_overproof', name: 'Ron Overproof (69%)', type: 'spirit', abv: 69, sugar: 0, acid: 0, bitterness: 2, complexity: 4, color: '#fef3c7' },
11
+ { id: 'rum_agricole', name: 'Rhum Agricole Blanc', type: 'spirit', abv: 50, sugar: 0, acid: 0, bitterness: 1, complexity: 8, color: '#ffffff' },
12
+ { id: 'tequila_blanco', name: 'Tequila Blanco', type: 'spirit', abv: 40, sugar: 0, acid: 0, bitterness: 1, complexity: 5, color: '#ffffff' },
13
+ { id: 'tequila_reposado', name: 'Tequila Reposado', type: 'spirit', abv: 40, sugar: 0.3, acid: 0, bitterness: 1, complexity: 6, color: '#fcd34d' },
14
+ { id: 'mezcal', name: 'Mezcal Espadín', type: 'spirit', abv: 45, sugar: 0, acid: 0, bitterness: 2, complexity: 9, color: '#ffffff' },
15
+ { id: 'whiskey_bourbon', name: 'Bourbon Whiskey', type: 'spirit', abv: 45, sugar: 0, acid: 0, bitterness: 2, complexity: 7, color: '#b45309' },
16
+ { id: 'rye_whiskey', name: 'Rye Whiskey', type: 'spirit', abv: 50, sugar: 0, acid: 0, bitterness: 3, complexity: 7, color: '#b45309' },
17
+ { id: 'scotch_blended', name: 'Scotch Blended', type: 'spirit', abv: 40, sugar: 0, acid: 0, bitterness: 2, complexity: 6, color: '#d97706' },
18
+ { id: 'scotch_islay', name: 'Islay Scotch (Ahumado)', type: 'spirit', abv: 43, sugar: 0, acid: 0, bitterness: 4, complexity: 10, color: '#fcd34d' },
19
+ { id: 'brandy_cognac', name: 'Cognac VSOP', type: 'spirit', abv: 40, sugar: 0.8, acid: 0, bitterness: 1, complexity: 8, color: '#92400e' },
20
+ { id: 'pisco_quebranta', name: 'Pisco Quebranta', type: 'spirit', abv: 40, sugar: 1, acid: 0, bitterness: 1, complexity: 6, color: '#ffffff' },
21
+ { id: 'cachaca', name: 'Cachaça', type: 'spirit', abv: 40, sugar: 1, acid: 0, bitterness: 1, complexity: 6, color: '#ffffff' },
22
+ { id: 'absinthe', name: 'Absenta', type: 'spirit', abv: 60, sugar: 0, acid: 0, bitterness: 5, complexity: 9, color: '#bef264' },
23
+ { id: 'juice_lime', name: 'Zumo de Lima (Fresco)', type: 'citrus', abv: 0, sugar: 1.5, acid: 6.0, bitterness: 1, complexity: 2, color: '#d9f99d' },
24
+ { id: 'juice_lemon', name: 'Zumo de Limón', type: 'citrus', abv: 0, sugar: 2.0, acid: 6.0, bitterness: 0.5, complexity: 1, color: '#fef08a' },
25
+ { id: 'juice_grapefruit', name: 'Zumo de Pomelo', type: 'citrus', abv: 0, sugar: 7.0, acid: 2.0, bitterness: 3, complexity: 3, color: '#fecaca' },
26
+ { id: 'juice_orange', name: 'Zumo de Naranja', type: 'citrus', abv: 0, sugar: 9.0, acid: 0.8, bitterness: 0, complexity: 2, color: '#fdba74' },
27
+ { id: 'juice_yuzu', name: 'Zumo de Yuzu', type: 'citrus', abv: 0, sugar: 1.5, acid: 4.5, bitterness: 2, complexity: 6, color: '#fef08a' },
28
+ { id: 'juice_pineapple', name: 'Zumo de Piña', type: 'citrus', abv: 0, sugar: 10.0, acid: 0.8, bitterness: 0, complexity: 3, color: '#fde047' },
29
+ { id: 'acid_solution_citric', name: 'Solución Ácido Cítrico (6%)', type: 'citrus', abv: 0, sugar: 0, acid: 6.0, bitterness: 0, complexity: 0, color: '#ffffff' },
30
+ { id: 'acid_solution_malic', name: 'Solución Ácido Málico (20%)', type: 'citrus', abv: 0, sugar: 0, acid: 20.0, bitterness: 1, complexity: 0, color: '#ffffff' },
31
+ { id: 'syrup_simple_11', name: 'Jarabe Simple (1:1)', type: 'syrup', abv: 0, sugar: 61.5, acid: 0, bitterness: 0, complexity: 0, color: '#ffffff' },
32
+ { id: 'syrup_rich_21', name: 'Jarabe Rico (2:1)', type: 'syrup', abv: 0, sugar: 80.0, acid: 0, bitterness: 0, complexity: 0, color: '#ffffff' },
33
+ { id: 'syrup_honey', name: 'Jarabe de Miel (3:1)', type: 'syrup', abv: 0, sugar: 75.0, acid: 0.1, bitterness: 0, complexity: 4, color: '#fcd34d' },
34
+ { id: 'syrup_agave', name: 'Sirope de Agave', type: 'syrup', abv: 0, sugar: 70.0, acid: 0, bitterness: 0, complexity: 3, color: '#fde047' },
35
+ { id: 'syrup_demerara', name: 'Sirope Demerara', type: 'syrup', abv: 0, sugar: 65.0, acid: 0, bitterness: 1, complexity: 3, color: '#d97706' },
36
+ { id: 'syrup_grenadine', name: 'Granadina (Real)', type: 'syrup', abv: 0, sugar: 65.0, acid: 0.5, bitterness: 0, complexity: 2, color: '#dc2626' },
37
+ { id: 'syrup_orgeat', name: 'Orgeat (Almendra)', type: 'syrup', abv: 0, sugar: 60.0, acid: 0, bitterness: 0, complexity: 5, color: '#f1f5f9' },
38
+ { id: 'syrup_falernum', name: 'Falernum (Sin Alcohol)', type: 'syrup', abv: 0, sugar: 50.0, acid: 0.2, bitterness: 2, complexity: 7, color: '#fef3c7' },
39
+ { id: 'syrup_ginger', name: 'Sirope de Jengibre', type: 'syrup', abv: 0, sugar: 60.0, acid: 0.1, bitterness: 2, complexity: 3, color: '#fef9c3' },
40
+ { id: 'syrup_passion', name: 'Sirope de Maracuyá', type: 'syrup', abv: 0, sugar: 60.0, acid: 2.0, bitterness: 0, complexity: 4, color: '#fbbf24' },
41
+ { id: 'cordial_lime', name: 'Cordial de Lima (Rose\'s)', type: 'syrup', abv: 0, sugar: 50.0, acid: 2.5, bitterness: 1, complexity: 1, color: '#d9f99d' },
42
+ { id: 'maple_syrup', name: 'Sirope de Arce (Grado A)', type: 'syrup', abv: 0, sugar: 66.0, acid: 0, bitterness: 1, complexity: 5, color: '#92400e' },
43
+ { id: 'liq_cointreau', name: 'Cointreau / Triple Sec', type: 'liqueur', abv: 40, sugar: 25.0, acid: 0, bitterness: 1, complexity: 3, color: '#ffffff' },
44
+ { id: 'liq_curacao', name: 'Dry Curaçao (Pierre Ferrand)', type: 'liqueur', abv: 40, sugar: 20.0, acid: 0, bitterness: 2, complexity: 6, color: '#fbbf24' },
45
+ { id: 'liq_blue_curacao', name: 'Blue Curaçao', type: 'liqueur', abv: 20, sugar: 30.0, acid: 0, bitterness: 1, complexity: 2, color: '#2563eb' },
46
+ { id: 'liq_maraschino', name: 'Licor Maraschino', type: 'liqueur', abv: 32, sugar: 35.0, acid: 0, bitterness: 0, complexity: 5, color: '#ffffff' },
47
+ { id: 'liq_campari', name: 'Campari', type: 'bitter', abv: 25, sugar: 24.0, acid: 0, bitterness: 9, complexity: 8, color: '#dc2626' },
48
+ { id: 'liq_aperol', name: 'Aperol', type: 'bitter', abv: 11, sugar: 25.0, acid: 0, bitterness: 6, complexity: 5, color: '#f97316' },
49
+ { id: 'liq_cynar', name: 'Cynar', type: 'bitter', abv: 16.5, sugar: 20.0, acid: 0, bitterness: 8, complexity: 8, color: '#3f2c22' },
50
+ { id: 'liq_fernet', name: 'Fernet Branca', type: 'bitter', abv: 39, sugar: 8.0, acid: 0, bitterness: 10, complexity: 9, color: '#1a1006' },
51
+ { id: 'vermouth_sweet', name: 'Vermut Rojo (Dulce)', type: 'liqueur', abv: 16, sugar: 16.0, acid: 0.4, bitterness: 3, complexity: 6, color: '#7f1d1d' },
52
+ { id: 'vermouth_dry', name: 'Vermut Dry (Seco)', type: 'liqueur', abv: 18, sugar: 3.0, acid: 0.5, bitterness: 2, complexity: 5, color: '#fefce8' },
53
+ { id: 'vermouth_bianco', name: 'Vermut Bianco', type: 'liqueur', abv: 16, sugar: 14.0, acid: 0.4, bitterness: 2, complexity: 5, color: '#fefce8' },
54
+ { id: 'sherry_fino', name: 'Jerez Fino/Manzanilla', type: 'liqueur', abv: 15, sugar: 0, acid: 0.4, bitterness: 1, complexity: 7, color: '#fefce8' },
55
+ { id: 'sherry_px', name: 'Jerez Pedro Ximénez', type: 'liqueur', abv: 17, sugar: 40.0, acid: 0.4, bitterness: 0, complexity: 9, color: '#3f2c22' },
56
+ { id: 'chartreuse_green', name: 'Chartreuse Verde', type: 'liqueur', abv: 55, sugar: 25.0, acid: 0, bitterness: 4, complexity: 10, color: '#84cc16' },
57
+ { id: 'chartreuse_yellow', name: 'Chartreuse Amarillo', type: 'liqueur', abv: 40, sugar: 28.0, acid: 0, bitterness: 2, complexity: 9, color: '#facc15' },
58
+ { id: 'liq_coffee', name: 'Licor de Café (Kahlúa)', type: 'liqueur', abv: 20, sugar: 40.0, acid: 0.1, bitterness: 3, complexity: 4, color: '#3f2c21' },
59
+ { id: 'liq_amaretto', name: 'Amaretto', type: 'liqueur', abv: 28, sugar: 30.0, acid: 0, bitterness: 1, complexity: 3, color: '#d97706' },
60
+ { id: 'liq_stgermain', name: 'St. Germain (Sauco)', type: 'liqueur', abv: 20, sugar: 25.0, acid: 0, bitterness: 0, complexity: 5, color: '#fef9c3' },
61
+ { id: 'liq_benedictine', name: 'Bénédictine', type: 'liqueur', abv: 40, sugar: 32.0, acid: 0, bitterness: 1, complexity: 8, color: '#b45309' },
62
+ { id: 'liq_baileys', name: 'Crema Irlandesa (Baileys)', type: 'liqueur', abv: 17, sugar: 20.0, acid: 0, bitterness: 0, complexity: 3, color: '#d6d3d1' },
63
+ { id: 'mix_soda', name: 'Agua con Gas / Soda', type: 'mixer', abv: 0, sugar: 0, acid: 0, bitterness: 0, complexity: 0, color: '#ffffff' },
64
+ { id: 'mix_tonic', name: 'Tónica', type: 'mixer', abv: 0, sugar: 9.0, acid: 0.5, bitterness: 4, complexity: 2, color: '#ffffff' },
65
+ { id: 'mix_cola', name: 'Cola', type: 'mixer', abv: 0, sugar: 10.6, acid: 0.1, bitterness: 1, complexity: 3, color: '#3f2c22' },
66
+ { id: 'mix_gingerbeer', name: 'Ginger Beer', type: 'mixer', abv: 0, sugar: 12.0, acid: 0.1, bitterness: 3, complexity: 3, color: '#fef08a' },
67
+ { id: 'mix_gingerale', name: 'Ginger Ale', type: 'mixer', abv: 0, sugar: 9.0, acid: 0.1, bitterness: 1, complexity: 1, color: '#fefce8' },
68
+ { id: 'mix_coconut_water', name: 'Agua de Coco', type: 'mixer', abv: 0, sugar: 4.0, acid: 0, bitterness: 0, complexity: 2, color: '#ffffff' },
69
+ { id: 'mix_coffee', name: 'Café Espresso', type: 'mixer', abv: 0, sugar: 0, acid: 1.0, bitterness: 6, complexity: 6, color: '#1a1006' },
70
+ { id: 'mix_cream', name: 'Nata Líquida', type: 'mixer', abv: 0, sugar: 3.0, acid: 0, bitterness: 0, complexity: 1, color: '#ffffff' },
71
+ { id: 'egg_white', name: 'Clara de Huevo', type: 'mixer', abv: 0, sugar: 0, acid: 0, bitterness: 0, complexity: 0, color: '#ffffff' },
72
+ { id: 'bitter_angostura', name: 'Angostura Bitters', type: 'bitter', abv: 44.7, sugar: 0, acid: 0, bitterness: 10, complexity: 10, color: '#7f1d1d' },
73
+ { id: 'bitter_orange', name: 'Orange Bitters', type: 'bitter', abv: 39, sugar: 5.0, acid: 0, bitterness: 8, complexity: 8, color: '#f97316' },
74
+ { id: 'bitter_peychaud', name: 'Peychaud\'s Bitters', type: 'bitter', abv: 35, sugar: 10.0, acid: 0, bitterness: 7, complexity: 8, color: '#ef4444' },
75
+ ];
76
+
77
+ export function getAllIngredients(): Ingredient[] {
78
+ return [...INGREDIENTS_DB].sort((a, b) => a.name.localeCompare(b.name));
79
+ }
80
+
81
+ export function getIngredientById(id: string): Ingredient | undefined {
82
+ return INGREDIENTS_DB.find((i) => i.id === id);
83
+ }
@@ -0,0 +1,122 @@
1
+ export interface PresetRecipe {
2
+ id: string;
3
+ name: string;
4
+ icon: string;
5
+ ingredients: { id: string; vol: number }[];
6
+ description?: string;
7
+ }
8
+
9
+ export const COCKTAIL_PRESETS: PresetRecipe[] = [
10
+ {
11
+ id: "daiquiri",
12
+ name: "Daiquiri Clásico",
13
+ icon: "mdi:glass-cocktail",
14
+ description: "El estándar de oro del equilibrio Sour.",
15
+ ingredients: [
16
+ { id: "rum_white", vol: 60 },
17
+ { id: "juice_lime", vol: 30 },
18
+ { id: "syrup_simple_11", vol: 22.5 },
19
+ ],
20
+ },
21
+ {
22
+ id: "margarita_tommys",
23
+ name: "Tommy's Margarita",
24
+ icon: "mdi:glass-cocktail",
25
+ description: "Versión moderna resaltando el agave.",
26
+ ingredients: [
27
+ { id: "tequila_blanco", vol: 60 },
28
+ { id: "juice_lime", vol: 30 },
29
+ { id: "syrup_agave", vol: 15 },
30
+ ],
31
+ },
32
+ {
33
+ id: "whiskey_sour",
34
+ name: "Whiskey Sour",
35
+ icon: "mdi:glass-cocktail",
36
+ description: "Cuerpo, acidez y carácter.",
37
+ ingredients: [
38
+ { id: "whiskey_bourbon", vol: 60 },
39
+ { id: "juice_lemon", vol: 30 },
40
+ { id: "syrup_simple_11", vol: 22.5 },
41
+ ],
42
+ },
43
+ {
44
+ id: "gimlet",
45
+ name: "Gimlet (Fresco)",
46
+ icon: "mdi:glass-cocktail",
47
+ description: "Gin y lima, afilado y refrescante.",
48
+ ingredients: [
49
+ { id: "gin_std", vol: 60 },
50
+ { id: "juice_lime", vol: 30 },
51
+ { id: "syrup_simple_11", vol: 22.5 },
52
+ ],
53
+ },
54
+ {
55
+ id: "negroni",
56
+ name: "Negroni",
57
+ icon: "mdi:glass-cocktail",
58
+ description: "El rey del aperitivo. Amargo y dulce.",
59
+ ingredients: [
60
+ { id: "gin_std", vol: 30 },
61
+ { id: "vermouth_sweet", vol: 30 },
62
+ { id: "liq_campari", vol: 30 },
63
+ ],
64
+ },
65
+ {
66
+ id: "mai_tai",
67
+ name: "Mai Tai Tradicional",
68
+ icon: "mdi:palm-tree",
69
+ description: "Complejidad tropical tiki.",
70
+ ingredients: [
71
+ { id: "rum_aged", vol: 60 },
72
+ { id: "juice_lime", vol: 30 },
73
+ { id: "liq_curacao", vol: 15 },
74
+ { id: "syrup_orgeat", vol: 7.5 },
75
+ { id: "syrup_rich_21", vol: 7.5 },
76
+ ],
77
+ },
78
+ {
79
+ id: "pisco_sour",
80
+ name: "Pisco Sour",
81
+ icon: "mdi:glass-cocktail",
82
+ description: "El clásico peruano.",
83
+ ingredients: [
84
+ { id: "pisco_quebranta", vol: 60 },
85
+ { id: "juice_lime", vol: 30 },
86
+ { id: "syrup_simple_11", vol: 22.5 },
87
+ ],
88
+ },
89
+ {
90
+ id: "tom_collins",
91
+ name: "Tom Collins",
92
+ icon: "mdi:glass-cocktail",
93
+ description: "Limonada de adultos.",
94
+ ingredients: [
95
+ { id: "gin_std", vol: 60 },
96
+ { id: "juice_lemon", vol: 30 },
97
+ { id: "syrup_simple_11", vol: 15 },
98
+ { id: "mix_soda", vol: 60 },
99
+ ],
100
+ },
101
+ {
102
+ id: "old_fashioned",
103
+ name: "Old Fashioned",
104
+ icon: "mdi:glass-cocktail",
105
+ description: "El cóctel original.",
106
+ ingredients: [
107
+ { id: "whiskey_bourbon", vol: 60 },
108
+ { id: "syrup_simple_11", vol: 7.5 },
109
+ ],
110
+ },
111
+ {
112
+ id: "boulevardier",
113
+ name: "Boulevardier",
114
+ icon: "mdi:glass-cocktail",
115
+ description: "El primo rico del Negroni.",
116
+ ingredients: [
117
+ { id: "whiskey_bourbon", vol: 45 },
118
+ { id: "vermouth_sweet", vol: 30 },
119
+ { id: "liq_campari", vol: 30 },
120
+ ],
121
+ },
122
+ ];
@@ -0,0 +1,29 @@
1
+ export interface Ingredient {
2
+ id: string;
3
+ name: string;
4
+ type: 'spirit' | 'citrus' | 'syrup' | 'liqueur' | 'bitter' | 'mixer' | 'other';
5
+ abv: number;
6
+ sugar: number;
7
+ acid: number;
8
+ bitterness?: number;
9
+ complexity?: number;
10
+ color?: string;
11
+ }
12
+
13
+ export interface CocktailComponent {
14
+ ingredient: Ingredient;
15
+ volumeMl: number;
16
+ }
17
+
18
+ export interface CocktailStats {
19
+ totalVolumeMl: number;
20
+ finalAbv: number;
21
+ totalSugarGrams: number;
22
+ totalAcidGrams: number;
23
+ sugarConcentration: number;
24
+ acidConcentration: number;
25
+ balanceRatio: number;
26
+ bitternessIndex: number;
27
+ complexityIndex: number;
28
+ finalColor: string;
29
+ }
@@ -0,0 +1,193 @@
1
+ import type { WithContext, SoftwareApplication } from 'schema-dts';
2
+ import type { CocktailBalancerUI, CocktailBalancerLocaleContent } from '../index';
3
+
4
+ const slug = 'cocktail-balancer';
5
+ const title = 'Cocktail Balancer - The Sour Law';
6
+ const description = 'Calculate the perfect balance between sweet and sour for your cocktails. Master the golden ratio of mixology.';
7
+
8
+ const ui: CocktailBalancerUI = {
9
+ title: 'Cocktail Balancer',
10
+ presetsBtn: 'Recipes',
11
+ saveBtn: 'Save',
12
+ resetBtn: 'Reset',
13
+ emptyStateTitle: 'Your Workbench is Empty',
14
+ emptyStateDescription: 'Add ingredients to analyze your cocktail balance in real-time.',
15
+ addBtn: 'Add Ingredient',
16
+ addMoreBtn: 'Add Another Ingredient',
17
+ flavorProfileTitle: 'Flavor Profile',
18
+ volLabel: 'Volume',
19
+ sugarLabel: 'Sugar',
20
+ colorLabel: 'Color',
21
+ sourLawTitle: 'Sour Law',
22
+ acidDryLabel: 'Acid (Dry)',
23
+ balanceLabel: 'Balance',
24
+ sweetLabel: 'Sweet',
25
+ aiSuggestionTitle: 'AI Suggestion',
26
+ addIngredientTitle: 'Add Ingredient',
27
+ searchPlaceholder: 'Search rum, lime, syrup...',
28
+ presetsTitle: 'Recipes & Presets',
29
+ savedSectionTitle: 'My Saved',
30
+ classicsSectionTitle: 'Classics',
31
+ confirmDeleteTitle: 'Delete everything?',
32
+ confirmDeleteText: 'This will remove all ingredients from your workbench. This action cannot be undone.',
33
+ cancelBtn: 'Cancel',
34
+ deleteBtn: 'Delete',
35
+ verdictSpiritSeco: 'Spirituous / Dry',
36
+ verdictSoloDulce: 'Sweet Only (Old Fashioned)',
37
+ verdictMuyAcido: 'Too Acidic / Bone Dry',
38
+ verdictAcido: 'Acidic / Tart',
39
+ verdictEquilibrado: 'Balanced (Sour)',
40
+ verdictDulce: 'Sweet / Commercial',
41
+ verdictEmpalagoso: 'Cloying',
42
+ fixAddBitters: 'Missing Bitterness',
43
+ fixAddSugar: 'Too Acidic',
44
+ fixAddAcid: 'Too Sweet'
45
+ };
46
+
47
+ const faqTitle = 'Frequently Asked Questions';
48
+ const bibliographyTitle = 'Bibliography & Sources';
49
+
50
+ const faq: CocktailBalancerLocaleContent['faq'] = [
51
+ {
52
+ question: "What is the 'Sour Law'?",
53
+ answer: "It is the golden ratio of mixology that balances three elements: the strong base (spirit), the sour (citrus), and the sweet (syrups). A classic recipe usually follows the 2:1:1 ratio (Strong:Sour:Sweet), although this varies depending on strength and density.",
54
+ },
55
+ {
56
+ question: "How does dilution affect cocktail balance?",
57
+ answer: "Ice doesn't just cool; it adds water (dilution) which opens up the spirit's aromas and softens the peaks of acidity and sweetness. A balanced cocktail in the shaker can become unbalanced if left too long with ice in the glass.",
58
+ },
59
+ {
60
+ question: "Why don't my home cocktails taste like those in a bar?",
61
+ answer: "It's usually due to the lack of balance between sugar and the pH of the citrus. Lemons vary in acidity by season. Our calculator helps you adjust the exact amount of syrup based on the volume of juice used.",
62
+ },
63
+ ];
64
+
65
+ const howTo: CocktailBalancerLocaleContent['howTo'] = [
66
+ {
67
+ name: "Select the alcoholic base",
68
+ text: "Choose the main spirit (Gin, Rum, Whiskey) from our database to know its body and alcohol contribution.",
69
+ },
70
+ {
71
+ name: "Enter the acidic agent",
72
+ text: "Add the volume of lemon, lime, or grapefruit juice. The calculator will analyze the pH impact on the mix.",
73
+ },
74
+ {
75
+ name: "Adjust the sweet component",
76
+ text: "Enter the type of syrup (simple, 2:1, agave) and watch the balance indicator move in real-time.",
77
+ },
78
+ ];
79
+
80
+ const bibliography: CocktailBalancerLocaleContent['bibliography'] = [
81
+ {
82
+ name: "Liquid Intelligence: The Art and Science of the Perfect Cocktail",
83
+ url: "http://www.cookingissues.com/index.html%3Fp=4587.html",
84
+ },
85
+ {
86
+ name: "The Bar Book: Elements of Cocktail Technique - Jeffrey Morgenthaler",
87
+ url: "https://jeffreymorgenthaler.com/the-bar-book/",
88
+ },
89
+ {
90
+ name: "Cocktail Balance - Difford's Guide",
91
+ url: "https://www.diffordsguide.com/encyclopedia/1066/cocktails/cocktail-balance",
92
+ },
93
+ ];
94
+
95
+ const seo: CocktailBalancerLocaleContent['seo'] = [
96
+ {
97
+ type: 'title',
98
+ text: 'Molecular Engineering & Liquid Balance',
99
+ level: 2
100
+ },
101
+ {
102
+ type: 'paragraph',
103
+ html: 'Welcome to the digital laboratory where intuition meets mathematics. This tool is not a simple recipe book; it is an <strong>advanced physical-chemical simulator</strong> designed to deconstruct and analyze the molecular structure of your cocktails in real-time. Every drop of citrus, every measure of spirit, every gram of syrup interacts according to immutable chemical laws that determine whether your drink will be a masterpiece or a disappointing failure.'
104
+ },
105
+ {
106
+ type: 'stats',
107
+ items: [
108
+ { label: 'Lime', value: '~6% Acid', icon: 'mdi:fruit-citrus' },
109
+ { label: 'Lemon', value: '~6% Acid', icon: 'mdi:fruit-citrus' },
110
+ { label: 'Grapefruit', value: '~1-2% Acid', icon: 'mdi:fruit-citrus' }
111
+ ],
112
+ columns: 3
113
+ },
114
+ {
115
+ type: 'card',
116
+ title: 'The Science of Acid',
117
+ icon: 'mdi:fruit-citrus',
118
+ html: 'Acidity is not just a flavor; it is the structural backbone of any balanced cocktail. Without the correct acidity, a drink becomes flat, one-dimensional, and forgettable. Our algorithm distinguishes the titratable acidity of a Persian lime versus a Eureka lemon, accounting for seasonal variations in citrus pH that can shift your recipe by an entire balance point on the palate.'
119
+ },
120
+ {
121
+ type: 'card',
122
+ title: 'Brix Control (Sweetness)',
123
+ icon: 'mdi:spoon-sugar',
124
+ html: 'The body and texture of your cocktail depends entirely on dissolved sugar. A Simple Syrup (1:1) behaves very differently from a Rich Syrup (2:1), honey, or agave nectar. Each sweetener has a different Brix degree and viscosity that affects how the drink coats the tongue. Our calculator computes the exact grams of dissolved sugar to predict final mouthfeel and sweetness perception.'
125
+ },
126
+ {
127
+ type: 'card',
128
+ title: 'Thermodynamics and Dilution',
129
+ icon: 'mdi:water-percent',
130
+ html: 'A shaken cocktail dilutes by 25-40% depending on the ice temperature, shaking technique, and duration. This water addition is not a flaw; it is an essential ingredient that opens aromas and softens the alcohol edge. Our calculator estimates the Final ABV after dilution, so you can engineer drinks with precisely the intended strength and flavour balance.'
131
+ },
132
+ {
133
+ type: 'title',
134
+ text: 'Beyond the Basic Ratio',
135
+ level: 2
136
+ },
137
+ {
138
+ type: 'paragraph',
139
+ html: 'Many bartenders learn the classic 2:1:1 rule (2 parts spirit, 1 part sour, 1 part sweet) and treat it as universal truth. However, <strong>chemistry is far more nuanced</strong>. A lemon from Sicily contains different acidity than a lime from Mexico. A triple sec like Cointreau behaves radically differently from a blue Curaçao. The same recipe can taste perfectly balanced one week and brutally acidic the next, simply due to seasonal fruit variation.'
140
+ },
141
+ {
142
+ type: 'paragraph',
143
+ html: 'This balancer breaks through those simplistic barriers. By entering your specific ingredients, you consult a living database that dynamically adjusts acidity and sweetness vectors to offer a precise sensory map of your creation. Stop guessing and start engineering your cocktails with the same scientific rigour that bartenders at world-class establishments use every single service.'
144
+ },
145
+ {
146
+ type: 'summary',
147
+ title: 'Who is this tool for?',
148
+ items: [
149
+ 'Professional Bartenders: Standardize recipes and create signature menus with reproducible consistency.',
150
+ 'Home Enthusiasts: Stop guessing and start understanding why your cocktails succeed or fail.',
151
+ 'Beverage Developers: Rapidly prototype new flavour concepts before expensive production runs.'
152
+ ]
153
+ },
154
+ {
155
+ type: 'diagnostic',
156
+ title: 'The Golden Zone',
157
+ icon: 'mdi:star',
158
+ variant: 'success',
159
+ badge: 'Goal',
160
+ html: 'This is the ultimate objective: a controlled pH where sugar neutralizes the aggression of acid without masking the essential oils and aromatic compounds of the base spirit. This precise balance is where immortal classics live — the Daiquiri, the Margarita, the Sidecar — drinks that have survived decades because they obey the fundamental laws of flavour chemistry.'
161
+ },
162
+ {
163
+ type: 'tip',
164
+ title: 'Expert Tip: Always Use Fresh Citrus',
165
+ html: 'Always squeeze citrus at the last moment. Lemon and lime juice oxidizes quickly, losing live acidity within 20-30 minutes of juicing. A cocktail made with truly fresh juice will always have a brightness and vibrancy on the palate that no bottled product can replicate. Use fruit at room temperature to maximize juice yield.'
166
+ }
167
+ ];
168
+
169
+ const schemas: CocktailBalancerLocaleContent['schemas'] = [
170
+ {
171
+ '@context': 'https://schema.org',
172
+ '@type': 'SoftwareApplication',
173
+ name: title,
174
+ description: description,
175
+ applicationCategory: 'UtilityApplication',
176
+ operatingSystem: 'Web',
177
+ offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
178
+ } as WithContext<SoftwareApplication>,
179
+ ];
180
+
181
+ export const content: CocktailBalancerLocaleContent = {
182
+ slug,
183
+ title,
184
+ description,
185
+ ui,
186
+ seo,
187
+ faqTitle,
188
+ faq,
189
+ bibliographyTitle,
190
+ bibliography,
191
+ howTo,
192
+ schemas,
193
+ };
@@ -0,0 +1,193 @@
1
+ import type { WithContext, SoftwareApplication } from 'schema-dts';
2
+ import type { CocktailBalancerUI, CocktailBalancerLocaleContent } from '../index';
3
+
4
+ const slug = 'equilibrador-cocteles';
5
+ const title = 'Equilibrador de Cócteles - La Ley del Sour';
6
+ const description = 'Calcula el equilibrio perfecto entre dulce y ácido para tus cócteles. Domina la proporción áurea de la mixología.';
7
+
8
+ const ui: CocktailBalancerUI = {
9
+ title: 'Cocktail Balancer',
10
+ presetsBtn: 'Recetas',
11
+ saveBtn: 'Guardar',
12
+ resetBtn: 'Reset',
13
+ emptyStateTitle: 'Tu Mesa de Trabajo está Vacía',
14
+ emptyStateDescription: 'Añade ingredientes para analizar el equilibrio de tu cóctel en tiempo real.',
15
+ addBtn: 'Añadir Ingrediente',
16
+ addMoreBtn: 'Añadir Otro Ingrediente',
17
+ flavorProfileTitle: 'Perfil de Sabor',
18
+ volLabel: 'Volumen',
19
+ sugarLabel: 'Azúcar',
20
+ colorLabel: 'Color',
21
+ sourLawTitle: 'Ley del Sour',
22
+ acidDryLabel: 'Ácido (Dry)',
23
+ balanceLabel: 'Equilibrio',
24
+ sweetLabel: 'Dulce (Sweet)',
25
+ aiSuggestionTitle: 'Sugerencia de la IA',
26
+ addIngredientTitle: 'Añadir Ingrediente',
27
+ searchPlaceholder: 'Buscar ron, lima, sirope...',
28
+ presetsTitle: 'Recetas & Presets',
29
+ savedSectionTitle: 'Mis Guardadas',
30
+ classicsSectionTitle: 'Clásicos',
31
+ confirmDeleteTitle: '¿Borrar todo?',
32
+ confirmDeleteText: 'Esta acción eliminará todos los ingredientes de tu mesa de trabajo. No se puede deshacer.',
33
+ cancelBtn: 'Cancelar',
34
+ deleteBtn: 'Borrar',
35
+ verdictSpiritSeco: 'Espirituoso / Seco',
36
+ verdictSoloDulce: 'Solo Dulce (Old Fashioned)',
37
+ verdictMuyAcido: 'Muy Ácido / Bone Dry',
38
+ verdictAcido: 'Ácido / Tart',
39
+ verdictEquilibrado: 'Equilibrado (Sour)',
40
+ verdictDulce: 'Dulce / Comercial',
41
+ verdictEmpalagoso: 'Empalagoso',
42
+ fixAddBitters: 'Falta Amargor',
43
+ fixAddSugar: 'Muy Ácido',
44
+ fixAddAcid: 'Muy Dulce'
45
+ };
46
+
47
+ const faqTitle = 'Preguntas Frecuentes';
48
+ const bibliographyTitle = 'Bibliografía y Fuentes';
49
+
50
+ const faq: CocktailBalancerLocaleContent['faq'] = [
51
+ {
52
+ question: "¿Qué es la 'Ley del Sour'?",
53
+ answer: "Es la proporción áurea de la coctelería que equilibra tres elementos: la base fuerte (destilado), lo ácido (cítricos) y lo dulce (siropes). Una receta clásica suele seguir el ratio 2:1:1 (Fuerte:Ácido:Dulce), aunque este varía según la graduación y densidad.",
54
+ },
55
+ {
56
+ question: "¿Cómo afecta la dilución al equilibrio del cóctel?",
57
+ answer: "El hielo no solo enfría; aporta agua (dilución) que abre los aromas del destilado y suaviza los picos de acidez y dulzor. Un cóctel equilibrado en la coctelera puede descompensarse si se deja demasiado tiempo con hielo en el vaso.",
58
+ },
59
+ {
60
+ question: "¿Por qué mis cócteles caseros no saben igual que los de un bar?",
61
+ answer: "Suele ser por la falta de equilibrio entre el azúcar y el pH del cítrico. Los limones varían en acidez según la temporada. Nuestra calculadora te ayuda a ajustar la cantidad de sirope exacta según el volumen de zumo usado.",
62
+ },
63
+ ];
64
+
65
+ const howTo: CocktailBalancerLocaleContent['howTo'] = [
66
+ {
67
+ name: "Seleccionar la base alcohólica",
68
+ text: "Elige el destilado principal (Gin, Ron, Whisky) de nuestra base de datos para conocer su aporte de cuerpo y alcohol.",
69
+ },
70
+ {
71
+ name: "Introducir el agente ácido",
72
+ text: "Añade el volumen de zumo de limón, lima o pomelo. La calculadora analizará el impacto del pH en la mezcla.",
73
+ },
74
+ {
75
+ name: "Ajustar el componente dulce",
76
+ text: "Introduce el tipo de sirope (simple, 2:1, agave) y observa cómo se desplaza el indicador de equilibrio en tiempo real.",
77
+ },
78
+ ];
79
+
80
+ const bibliography: CocktailBalancerLocaleContent['bibliography'] = [
81
+ {
82
+ name: "Liquid Intelligence: The Art and Science of the Perfect Cocktail",
83
+ url: "http://www.cookingissues.com/index.html%3Fp=4587.html",
84
+ },
85
+ {
86
+ name: "The Bar Book: Elements of Cocktail Technique - Jeffrey Morgenthaler",
87
+ url: "https://jeffreymorgenthaler.com/the-bar-book/",
88
+ },
89
+ {
90
+ name: "Cocktail Balance - Difford's Guide",
91
+ url: "https://www.diffordsguide.com/encyclopedia/1066/cocktails/cocktail-balance",
92
+ },
93
+ ];
94
+
95
+ const seo: CocktailBalancerLocaleContent['seo'] = [
96
+ {
97
+ type: 'title',
98
+ text: 'Ingeniería Molecular & Equilibrio Líquido',
99
+ level: 2
100
+ },
101
+ {
102
+ type: 'paragraph',
103
+ html: 'Bienvenido al laboratorio digital donde la intuición se encuentra con la matemática. Esta herramienta no es un simple recetario; es un <strong>simulador físico-químico avanzado</strong> diseñado para deconstruir y analizar la estructura molecular de tus cócteles en tiempo real, garantizando la perfección en cada copa.'
104
+ },
105
+ {
106
+ type: 'stats',
107
+ items: [
108
+ { label: 'Lima', value: '~6% Ácido', icon: 'mdi:fruit-citrus' },
109
+ { label: 'Limón', value: '~6% Ácido', icon: 'mdi:fruit-citrus' },
110
+ { label: 'Pomelo', value: '~1-2% Ácido', icon: 'mdi:fruit-citrus' }
111
+ ],
112
+ columns: 3
113
+ },
114
+ {
115
+ type: 'card',
116
+ title: 'La Ciencia del Ácido',
117
+ icon: 'mdi:fruit-citrus',
118
+ html: 'La acidez no es solo sabor; es estructura. Un cóctel sin la acidez correcta es plano y aburrido. Nuestro algoritmo distingue la potencia titulerable de una lima persa frente a un limón eureka o una naranja dulce.'
119
+ },
120
+ {
121
+ type: 'card',
122
+ title: 'Control de Brix (Dulzura)',
123
+ icon: 'mdi:spoon-sugar',
124
+ html: 'El "cuerpo" de tu bebida depende del azúcar. No es lo mismo usar un Jarabe Simple (1:1) que un Rich Syrup (2:1) o miel. Calculamos los gramos exactos de azúcar disuelta para predecir la textura final.'
125
+ },
126
+ {
127
+ type: 'card',
128
+ title: 'Termodinámica y Dilución',
129
+ icon: 'mdi:water-percent',
130
+ html: 'Un cóctel agitado se diluye entre un 25-40% dependiendo del hielo y la técnica. Nuestra calculadora estima el ABV Final antes de que agites la coctelera, permitiéndote diseñar bebidas con la potencia exacta deseada.'
131
+ },
132
+ {
133
+ type: 'title',
134
+ text: 'Más allá de la "Regla de Tres"',
135
+ level: 2
136
+ },
137
+ {
138
+ type: 'paragraph',
139
+ html: 'Muchos bartenders aprenden fórmulas básicas como la regla 2:1:1 (2 partes de alcohol, 1 de acido, 1 de dulce). Sin embargo, <strong>la química es caprichosa</strong>. Un limón de Sicilia no tiene la misma acidez que una lima de Brasil. Un licor de naranja como el Cointreau se comporta radicalmente distinto a un Curaçao.'
140
+ },
141
+ {
142
+ type: 'paragraph',
143
+ html: 'Este equilibrador rompe esas barreras simplistas. Al introducir ingredientes en nuestro sistema, estás consultando una base de datos viva que ajusta los vectores de acidez y dulzor para ofrecerte un mapa sensorial preciso de tu creación antes de gastar una sola gota de licor caro.'
144
+ },
145
+ {
146
+ type: 'summary',
147
+ title: '¿Para quién es esta herramienta?',
148
+ items: [
149
+ 'Bartenders Profesionales: Para estandarizar recetas y crear menús de autor.',
150
+ 'Entusiastas del Hogar: Para dejar de adivinar y empezar a entender los fallos.',
151
+ 'Desarrolladores de Bebidas: Para prototipar rápidamente conceptos de sabor.'
152
+ ]
153
+ },
154
+ {
155
+ type: 'diagnostic',
156
+ title: 'La Zona Dorada',
157
+ icon: 'mdi:star',
158
+ variant: 'success',
159
+ badge: 'Objetivo',
160
+ html: 'Este es el objetivo final: un pH controlado donde el azúcar neutraliza la agresión del ácido sin enmascarar los aceites esenciales y los compuestos aromáticos del alcohol base. Aquí viven los clásicos inmortales: el Daiquiri, la Margarita, el Sidecar. Bebidas que han sobrevivido décadas porque obedecen las leyes fundamentales de la química del sabor.'
161
+ },
162
+ {
163
+ type: 'tip',
164
+ title: 'Consejo Experto: Usa Siempre Cítricos Frescos',
165
+ html: 'Exprime siempre los cítricos en el último momento. El zumo de limón y lima se oxida rápidamente, perdiendo su acidez viva en 20-30 minutos tras la extracción. Un cóctel elaborado con zumo verdaderamente fresco siempre tendrá una brillantez y vivacidad en el paladar que ningún producto embotellado puede replicar. Usa fruta a temperatura ambiente para maximizar el rendimiento del zumo.'
166
+ }
167
+ ];
168
+
169
+ const schemas: CocktailBalancerLocaleContent['schemas'] = [
170
+ {
171
+ '@context': 'https://schema.org',
172
+ '@type': 'SoftwareApplication',
173
+ name: title,
174
+ description: description,
175
+ applicationCategory: 'UtilityApplication',
176
+ operatingSystem: 'Web',
177
+ offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
178
+ } as WithContext<SoftwareApplication>,
179
+ ];
180
+
181
+ export const content: CocktailBalancerLocaleContent = {
182
+ slug,
183
+ title,
184
+ description,
185
+ ui,
186
+ seo,
187
+ faqTitle,
188
+ faq,
189
+ bibliographyTitle,
190
+ bibliography,
191
+ howTo,
192
+ schemas,
193
+ };